feat(FN-2944): merge fusion/fn-2944
- test(FN-2944): cover already checked out worktree conflict recovery - fix(FN-2944): recognize git already checked out worktree conflict - fix(engine): auto-recover from squash-merge orphan rebase failures Fusion-Task-Id: FN-2944
This commit is contained in:
@@ -966,6 +966,56 @@ describe("TaskExecutor worktree recovery", () => {
|
||||
expect(worktreeAddCalls).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("extractWorktreeConflictInfo classifies already checked out errors as already-used", () => {
|
||||
const store = createMockStore();
|
||||
const executor = new TaskExecutor(store, "/tmp/test");
|
||||
|
||||
const error: any = new Error(
|
||||
"fatal: 'fusion/fn-050' is already checked out at '/tmp/test/.worktrees/green-sage'",
|
||||
);
|
||||
error.stderr = Buffer.from(
|
||||
"fatal: 'fusion/fn-050' is already checked out at '/tmp/test/.worktrees/green-sage'",
|
||||
);
|
||||
|
||||
const conflictInfo = (executor as any).extractWorktreeConflictInfo(error);
|
||||
expect(conflictInfo).toMatchObject({
|
||||
type: "already-used",
|
||||
path: "/tmp/test/.worktrees/green-sage",
|
||||
});
|
||||
});
|
||||
|
||||
it("recovers from already checked out worktree conflict and retries", async () => {
|
||||
const store = createMockStore();
|
||||
let callCount = 0;
|
||||
|
||||
mockedExecSync.mockImplementation((cmd: string | string[]) => {
|
||||
const command = typeof cmd === "string" ? cmd : cmd[0];
|
||||
if (command.includes("git worktree add") && callCount++ === 0) {
|
||||
const error: any = new Error(
|
||||
"fatal: 'fusion/fn-050' is already checked out at '/tmp/test/.worktrees/green-sage'",
|
||||
);
|
||||
error.stderr = Buffer.from(
|
||||
"fatal: 'fusion/fn-050' is already checked out at '/tmp/test/.worktrees/green-sage'",
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
return Buffer.from("");
|
||||
});
|
||||
|
||||
const executor = new TaskExecutor(store, "/tmp/test");
|
||||
await executor.execute(makeTask());
|
||||
|
||||
expect(store.logEntry).toHaveBeenCalledWith(
|
||||
"FN-050",
|
||||
expect.stringContaining("Cleaned up conflicting worktree, retrying"),
|
||||
"/tmp/test/.worktrees/swift-falcon",
|
||||
);
|
||||
expect(store.updateTask).toHaveBeenCalledWith(
|
||||
"FN-050",
|
||||
expect.objectContaining({ worktree: expect.any(String) }),
|
||||
);
|
||||
});
|
||||
|
||||
it("recovers from worktree conflict and retries", async () => {
|
||||
const store = createMockStore();
|
||||
let callCount = 0;
|
||||
|
||||
@@ -10,3 +10,11 @@ import { join } from "node:path";
|
||||
|
||||
const tempHome = mkdtempSync(join(tmpdir(), "fn-test-home-"));
|
||||
process.env.HOME = tempHome;
|
||||
process.env.USERPROFILE = tempHome;
|
||||
if (process.platform === "win32") {
|
||||
const match = tempHome.match(/^([A-Za-z]:)(.*)$/);
|
||||
if (match) {
|
||||
process.env.HOMEDRIVE = match[1];
|
||||
process.env.HOMEPATH = match[2] || "\\";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user