feat(FN-5063): merge fusion/fn-5063
This commit is contained in:
@@ -74,5 +74,5 @@ describe("pre-commit identity guard (real git)", () => {
|
||||
} finally {
|
||||
rmSync(rootDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
}, 30_000);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import { mkdtemp, realpath, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { NativeWorktreeBackend } from "../../worktree-backend.js";
|
||||
import { WorktreePool } from "../../worktree-pool.js";
|
||||
import { git, hasGit } from "./_helpers.js";
|
||||
|
||||
describe.skipIf(!hasGit)("reliability interactions: worktree stale registration recovery", () => {
|
||||
const roots: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(roots.map((root) => rm(root, { recursive: true, force: true })));
|
||||
roots.length = 0;
|
||||
});
|
||||
|
||||
async function setupRepo() {
|
||||
const root = await mkdtemp(join(tmpdir(), "fusion-stale-registration-"));
|
||||
roots.push(root);
|
||||
git(root, "git init -b main");
|
||||
git(root, 'git config user.email "test@example.com"');
|
||||
git(root, 'git config user.name "Test User"');
|
||||
await writeFile(join(root, "README.md"), "# repo\n", "utf-8");
|
||||
git(root, "git add README.md");
|
||||
git(root, 'git commit -m "init"');
|
||||
return root;
|
||||
}
|
||||
|
||||
it("recovers missing-but-registered worktree via prune and retries add", async () => {
|
||||
const root = await setupRepo();
|
||||
const worktreePath = join(root, ".worktrees", "fn-test-1");
|
||||
const backendAuditEvents: string[] = [];
|
||||
|
||||
git(root, `git worktree add -b feature ${JSON.stringify(worktreePath)}`);
|
||||
await rm(worktreePath, { recursive: true, force: true });
|
||||
|
||||
const backend = new NativeWorktreeBackend({
|
||||
audit: {
|
||||
git: async (event) => {
|
||||
backendAuditEvents.push(event.type);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const result = await backend.create({
|
||||
rootDir: root,
|
||||
taskId: "FN-TEST-1",
|
||||
worktreePath,
|
||||
branch: "fusion/fn-test-1",
|
||||
startPoint: "main",
|
||||
});
|
||||
|
||||
expect(result).toEqual({ path: worktreePath, branch: "fusion/fn-test-1" });
|
||||
expect(backendAuditEvents).toContain("worktree:stale-registration-detected");
|
||||
expect(backendAuditEvents).toContain("worktree:stale-registration-recovered");
|
||||
|
||||
const porcelain = git(root, "git worktree list --porcelain");
|
||||
const resolvedWorktreePath = await realpath(worktreePath);
|
||||
expect(porcelain).toContain(`worktree ${resolvedWorktreePath}`);
|
||||
});
|
||||
|
||||
it("recovered path composes with FN-4954 pool acquire/release contract", async () => {
|
||||
const root = await setupRepo();
|
||||
const worktreePath = join(root, ".worktrees", "fn-test-2");
|
||||
|
||||
git(root, `git worktree add -b feature ${JSON.stringify(worktreePath)}`);
|
||||
await rm(worktreePath, { recursive: true, force: true });
|
||||
|
||||
const backend = new NativeWorktreeBackend();
|
||||
await backend.create({
|
||||
rootDir: root,
|
||||
taskId: "FN-TEST-2",
|
||||
worktreePath,
|
||||
branch: "fusion/fn-test-2",
|
||||
startPoint: "main",
|
||||
});
|
||||
|
||||
const pool = new WorktreePool();
|
||||
pool.release(worktreePath, "FN-TEST-2");
|
||||
const acquired = pool.acquire("FN-TEST-3");
|
||||
|
||||
expect(acquired).toBe(worktreePath);
|
||||
expect(pool.getLeasedPaths().get(worktreePath)).toBe("FN-TEST-3");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user