feat(FN-4606): complete Step 4 — enhance worktree root lookup

Ref: Runfusion/Fusion#321
Fusion-Task-Id: FN-4606
Fusion-Task-Lineage: 94b23f37-944e-4bcd-bfa1-67d0a8c0a267
This commit is contained in:
Fusion
2026-05-15 08:35:57 -07:00
committed by gsxdsm
parent 457b4cddf5
commit c51646fc66
2 changed files with 37 additions and 8 deletions

View File

@@ -88,6 +88,20 @@ describe("getProjectRootFromWorktree", () => {
expect(getProjectRootFromWorktree("C:\\repo\\.worktrees\\fn-001")).toBe("C:\\repo");
expect(getProjectRootFromWorktree("C:\\repo\\.worktrees\\fn-001\\src\\file.ts")).toBe("C:\\repo");
});
it("supports configured candidate worktrees dir paths", () => {
expect(
getProjectRootFromWorktree("/tmp/.fn-worktrees/repo/fn-001/src", {
worktreesDirCandidates: ["/tmp/.fn-worktrees/repo"],
}),
).toBe("/tmp/.fn-worktrees");
expect(
getProjectRootFromWorktree("/tmp/repo.worktrees/fn-001", {
worktreesDirCandidates: ["/tmp/repo.worktrees"],
}),
).toBe("/tmp");
});
});
// Initialize mocks before first test

View File

@@ -1242,15 +1242,30 @@ async function registerExtensionProviders(cwd: string, modelRegistry: ModelRegis
* `/project/.worktrees/fn-001/src/file.ts` → `/project`
* `/project` → null (not a worktree)
*/
export function getProjectRootFromWorktree(cwd: string): string | null {
// Match paths like:
// /project/.worktrees/task-id
// /project/.worktrees/task-id/src/file.ts
// C:\project\.worktrees\task-id
const match = cwd.match(/^(.+?)[\\/]\.worktrees[\\/][^\\/]+(?:[\\/]|$)/);
if (match) {
return match[1]!;
export function getProjectRootFromWorktree(
cwd: string,
opts?: { worktreesDirCandidates?: string[] },
): string | null {
const legacyMatch = cwd.match(/^(.+?)[\\/]\.worktrees[\\/][^\\/]+(?:[\\/]|$)/);
if (legacyMatch) {
return legacyMatch[1]!;
}
for (const candidate of opts?.worktreesDirCandidates ?? []) {
const normalizedCandidate = resolve(candidate);
const normalizedCwd = resolve(cwd);
const rel = relative(normalizedCandidate, normalizedCwd);
if (rel !== "" && !rel.startsWith("..") && !isAbsolute(rel)) {
const firstSegment = rel.split(/[\\/]/).filter(Boolean)[0];
if (firstSegment) {
const parent = normalizedCandidate.split(/[\\/]/).slice(0, -1).join("/");
if (parent) {
return parent;
}
}
}
}
return null;
}