Unify scoped development with ordinary Workspace authoring commands

This commit is contained in:
Timothy J. Aveni
2026-10-12 13:09:47 -07:00
parent ecf97173b4
commit bbf9056dfa
3 changed files with 32 additions and 3 deletions
@@ -16,8 +16,11 @@ export async function prepareDevelopmentSources(options: {
directory: string;
cacheDirectory: string;
locations?: Record<string, string>;
workspaceId?: string;
}) {
const source = workspaceSourcePin(options.source);
if (options.workspaceId !== undefined && !/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/.test(options.workspaceId))
throw Error("Development source binding requires a Workspace UUID");
const destination = path.resolve(options.directory);
const cache = path.resolve(options.cacheDirectory);
if (cache === destination || cache.startsWith(destination + path.sep))
@@ -43,7 +46,8 @@ export async function prepareDevelopmentSources(options: {
const parent = path.dirname(destination);
await mkdir(parent, { recursive: true });
const staging = await mkdtemp(path.join(parent, ".development-sources-"));
const workspaceId = randomUUID();
// This local association does not create or grant access to a hosted Graph.
const workspaceId = options.workspaceId ?? randomUUID();
try {
const resources = [];
for (const entry of closure.resources) {
+6 -2
View File
@@ -73,7 +73,7 @@ const main = async () => {
"--dir",
...(args[1] !== "restore" ? ["--locations"] : []),
...(args[1] === "checkout" ? ["--repository-prefix"] : []),
...(args[1] === "develop" ? ["--cache"] : []),
...(args[1] === "develop" ? ["--cache", "--workspace-id"] : []),
...(args[1] === "backup" ? ["--output"] : []),
].includes(args[i]) ||
!args[i + 1] ||
@@ -100,7 +100,11 @@ const main = async () => {
if (args[1] === "develop") {
if (!flags.get("--cache")) throw Error("source develop requires --cache DIRECTORY");
const { prepareDevelopmentSources } = await import("./development-sources.js");
result = await prepareDevelopmentSources({ ...options, cacheDirectory: path.resolve(flags.get("--cache")!) });
result = await prepareDevelopmentSources({
...options,
cacheDirectory: path.resolve(flags.get("--cache")!),
...(flags.has("--workspace-id") ? { workspaceId: flags.get("--workspace-id")! } : {}),
});
} else if (args[1] === "backup") {
if (!flags.get("--output")) throw Error("source backup requires --output DIRECTORY");
const { backupWorkspaceSources } = await import("./source-backup.js");
+21
View File
@@ -172,6 +172,27 @@ test("exact source closure recovers through explicitly selected bundles, preserv
directory: path.join(temporary, "b"),
});
assert.notEqual(a.workspaceId, b.workspaceId);
const assigned = "f8f2f8a3-328c-45a2-847a-31869ad28ce7";
const c = await prepareDevelopmentSources({
source: root,
cacheDirectory: directory,
directory: path.join(temporary, "assigned"),
workspaceId: assigned,
});
assert.equal(c.workspaceId, assigned);
assert.equal(
JSON.parse(await readFile(path.join(c.directory, ".quixos/resource-graph.json"), "utf8")).workspaceId,
assigned,
);
await assert.rejects(
prepareDevelopmentSources({
source: root,
cacheDirectory: directory,
directory: path.join(temporary, "invalid"),
workspaceId: "not-a-workspace",
}),
/Workspace UUID/,
);
const aRoot = path.join(a.directory, "root"),
bRoot = path.join(b.directory, "root");
assert.equal((await exec("git", ["remote", "get-url", "origin"], { cwd: aRoot })).stdout.trim(), root.repository);