import test from "node:test"; import assert from "node:assert/strict"; import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { execFile as callback } from "node:child_process"; import { promisify } from "node:util"; import { createGitCapabilityResolver } from "../src/capability-language/git-resolver.js"; const execFile = promisify(callback); test("dependency resolution is reusable across processes, concurrent and rejects modified checkouts", async (context) => { const temporary = await mkdtemp(path.join(os.tmpdir(), "qx-resolver-test-")); context.after(() => rm(temporary, { recursive: true, force: true })); const origin = path.join(temporary, "origin"); await mkdir(origin); const git = (...args: string[]) => execFile("git", ["-C", origin, ...args]); await git("init"); await writeFile(path.join(origin, "interface.qx"), "contract"); await git("add", "."); await git("-c", "user.name=Test", "-c", "user.email=test@example.test", "commit", "-m", "contract"); const commit = (await git("rev-parse", "HEAD")).stdout.trim(); await git("tag", `quixos-reachability/${commit}`); const source = { resolver: "git" as const, repository: origin, commit }; const options = { checkoutRoot: path.join(temporary, "cache") }; const a = await createGitCapabilityResolver(options); const b = await createGitCapabilityResolver(options); const [first, second] = await Promise.all([a(source, "interface"), b(source, "interface")]); assert.equal(first.directory, second.directory); const c = await createGitCapabilityResolver(options); assert.equal((await c(source, "interface")).directory, first.directory); await writeFile(path.join(first.directory, "interface.qx"), "changed"); const d = await createGitCapabilityResolver(options); await assert.rejects(d(source, "interface"), /modified/); // A failed request is not memoized forever; repair can be observed on retry. await writeFile(path.join(first.directory, "interface.qx"), "contract"); assert.equal((await d(source, "interface")).directory, first.directory); });