feat(FN-4884): complete Step 2-3 fast-path and coverage
Fusion-Task-Id: FN-4884 Fusion-Task-Lineage: b906ade4-a9f1-4f2e-b684-4ebf49c3e7e6
This commit is contained in:
committed by
gsxdsm
parent
83ed893382
commit
030a27b40d
@@ -207,6 +207,47 @@ describe("branch contamination recovery classification", () => {
|
||||
expect(range).toBe("0");
|
||||
});
|
||||
|
||||
it("reanchors without checkout -B when detached worktree is already at base on bound branch", async () => {
|
||||
const { repoDir, baseSha } = await setupRepo();
|
||||
const secondaryWorktree = path.join(repoDir, "../feature-secondary");
|
||||
await run(`git worktree add --detach ${JSON.stringify(secondaryWorktree)} ${baseSha}`, repoDir);
|
||||
dirs.push(secondaryWorktree);
|
||||
|
||||
await expect(
|
||||
run(`git checkout -B feature ${baseSha}`, secondaryWorktree),
|
||||
).rejects.toThrow(/already used by worktree/i);
|
||||
|
||||
const result = await reanchorBranchToBase({
|
||||
repoDir,
|
||||
worktreePath: secondaryWorktree,
|
||||
branchName: "feature",
|
||||
baseSha,
|
||||
taskId: "FN-4884",
|
||||
});
|
||||
|
||||
const headSha = await run("git rev-parse HEAD", secondaryWorktree);
|
||||
expect(result.previousTipSha).toBe(baseSha);
|
||||
expect(result.newTipSha).toBe(baseSha);
|
||||
expect(headSha).toBe(baseSha);
|
||||
});
|
||||
|
||||
it("treats already-bound branch-at-base as a no-op fast-path", async () => {
|
||||
const { repoDir, baseSha } = await setupRepo();
|
||||
|
||||
const result = await reanchorBranchToBase({
|
||||
repoDir,
|
||||
worktreePath: repoDir,
|
||||
branchName: "feature",
|
||||
baseSha,
|
||||
taskId: "FN-4884",
|
||||
});
|
||||
|
||||
const currentBranch = await run("git symbolic-ref --quiet --short HEAD", repoDir);
|
||||
expect(result.previousTipSha).toBe(baseSha);
|
||||
expect(result.newTipSha).toBe(baseSha);
|
||||
expect(currentBranch).toBe("feature");
|
||||
});
|
||||
|
||||
it("auto-recovers by dropping already-upstream foreign commits and preserving remaining branch work", async () => {
|
||||
const { repoDir, baseSha } = await setupRepo();
|
||||
await writeFile(path.join(repoDir, "foreign.txt"), "", "utf-8");
|
||||
|
||||
@@ -558,6 +558,29 @@ export async function reanchorBranchToBase(
|
||||
timeout: GIT_TIMEOUT_MS,
|
||||
maxBuffer: GIT_MAX_BUFFER,
|
||||
});
|
||||
|
||||
const worktreeHeadSha = await revParse(worktreePath, "HEAD");
|
||||
const branchTipSha = previousTipSha;
|
||||
const worktreeHeadBranch = await runGit(worktreePath, "git symbolic-ref --quiet --short HEAD").catch(() => "");
|
||||
|
||||
if (worktreeHeadSha === baseSha && branchTipSha === baseSha) {
|
||||
if (worktreeHeadBranch !== branchName) {
|
||||
try {
|
||||
await runGit(worktreePath, `git checkout ${quoteShellArg(branchName)}`);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
if (!message.includes("already used by worktree")) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
await assertCleanBranchAtBase(repoDir, branchName, baseSha, taskId);
|
||||
return {
|
||||
previousTipSha,
|
||||
newTipSha: previousTipSha,
|
||||
};
|
||||
}
|
||||
|
||||
await runGit(worktreePath, `git checkout --detach ${quoteShellArg(baseSha)}`);
|
||||
await runGit(worktreePath, `git checkout -B ${quoteShellArg(branchName)} ${quoteShellArg(baseSha)}`);
|
||||
await assertCleanBranchAtBase(repoDir, branchName, baseSha, taskId);
|
||||
|
||||
Reference in New Issue
Block a user