Skip to content

Instantly share code, notes, and snippets.

@Anaminus
Created December 20, 2022 01:43
Show Gist options
  • Save Anaminus/135999033fa01a3b1491b0d0e54b6f68 to your computer and use it in GitHub Desktop.
Save Anaminus/135999033fa01a3b1491b0d0e54b6f68 to your computer and use it in GitHub Desktop.
Wrangle package-structured projects to be more DataModel-friendly via Rojo
--[[
NOTICE: Requires unreleased version of rbxmk
https://github.com/Anaminus/rbxmk
Usage:
local Build = rbxmk.runFile("Build.rbxmk.lua"))
Build.package:
Build.package("pkg", {
server = "src/server",
client = "src/client",
shared = "src/shared",
})
Unpacks "packages" of modules. The first argument is a path to a directory
containing packages. The second argument is a map of package component names
to destination paths.
Each directory under the packages directory is a package. A file under a
package is a component if its stem name matches a specified component name.
In the destination, a "pointer" file is created to point back to the package
component. For example:
src/server/package.project.json => pkg/package/server.lua
Build.ref:
Build.ref("data, "src/data")
Creates a project file from the second argument that points back to the
first argument. For example:
src/data.project.json:
{
"name": "data",
"tree": {
"$path": "../data"
}
}
Build.clean:
Build.clean("src")
Remove any files and directories from the first argument that haven't been
touched by the library.
]]
local export = {}
local touchedFiles = {}
local function touch(file)
touchedFiles[file] = true
end
local function clean(dir)
local t = {}
for touched in pairs(touchedFiles) do
local touchedFile = ""
for _, element in ipairs({path.explode(touched)}) do
touchedFile = path.join(touchedFile, element)
t[touchedFile] = true
end
end
for _, file in ipairs(fs.dir(dir)) do
local fullPath = path.join(dir, file.Name)
if t[fullPath] then
if file.IsDir then
clean(fullPath)
end
else
fs.remove(fullPath, true)
print("remove", fullPath)
end
end
end
export.clean = clean
local function ref(target, project)
local dir, name = path.split(project, "dir", "stem")
project = path.join(dir, name .. ".project.json")
local relPath = path.rel(dir, target)
if relPath == nil then
error(string.format("cannot make target %q relative to base %q", target, dir))
end
if fs.stat(project) then
print("write", project)
else
print("create", project)
end
fs.mkdir(dir, true)
touch(project)
fs.write(project, {name=name, tree={["$path"]=relPath}}, {Format="json", Indent=""})
end
export.ref = ref
function export.package(packagesDir, components)
local packageNames = {}
local packages = fs.dir(packagesDir)
for _, file in ipairs(packages) do
if file.IsDir then
packageNames[file.Name] = true
end
end
-- Generate references.
local toWrite = {}
for _, package in ipairs(packages) do
if package.IsDir then
local packageDir = path.join(packagesDir, package.Name)
for _, file in ipairs(fs.dir(packageDir)) do
local component = path.split(file.Name, "stem")
local basePath = components[component]
if basePath then
local target = path.join(packageDir, file.Name)
local project = path.join(basePath, package.Name)
table.insert(toWrite, {target=target, project=project})
end
end
end
end
table.sort(toWrite, function(a,b) return a.project < b.project end)
-- Apply changes.
for _, file in ipairs(toWrite) do
ref(file.target, file.project)
end
end
return export
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment