From 94ac6cccbf29191b00425d29fef1719099add76e Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 31 May 2026 05:04:10 -0700 Subject: [PATCH] Fix worktree path comparison after base-path rebase --- src/main/ipc/worktree-logic.test.ts | 10 ++++++++++ src/main/ipc/worktree-logic.ts | 18 ++++++++++++++++-- src/main/ipc/worktrees.test.ts | 6 +++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/main/ipc/worktree-logic.test.ts b/src/main/ipc/worktree-logic.test.ts index 16f73eb9c..14c33599f 100644 --- a/src/main/ipc/worktree-logic.test.ts +++ b/src/main/ipc/worktree-logic.test.ts @@ -266,6 +266,16 @@ describe('areWorktreePathsEqual', () => { it('keeps POSIX path comparison case-sensitive', () => { expect(areWorktreePathsEqual('/tmp/Worktree', '/tmp/worktree', 'linux')).toBe(false) }) + + it('treats macOS /private/tmp git paths as matching /tmp workspace paths', () => { + expect( + areWorktreePathsEqual( + '/private/tmp/orca-proof/worktrees/repo/feature', + '/tmp/orca-proof/worktrees/repo/feature', + 'darwin' + ) + ).toBe(true) + }) }) describe('shouldSetDisplayName', () => { diff --git a/src/main/ipc/worktree-logic.ts b/src/main/ipc/worktree-logic.ts index ae8926c15..13e603828 100644 --- a/src/main/ipc/worktree-logic.ts +++ b/src/main/ipc/worktree-logic.ts @@ -190,8 +190,8 @@ export function areWorktreePathsEqual( // create spuriously fails until the next full reload repopulates state. return left.toLowerCase() === right.toLowerCase() } - const left = posix.normalize(posix.resolve(leftPath)) - const right = posix.normalize(posix.resolve(rightPath)) + const left = normalizePosixWorktreePathForComparison(leftPath, platform) + const right = normalizePosixWorktreePathForComparison(rightPath, platform) return left === right } @@ -201,6 +201,20 @@ function looksLikeWindowsPath(pathValue: string): boolean { ) } +function normalizePosixWorktreePathForComparison( + pathValue: string, + platform: NodeJS.Platform +): string { + const normalized = posix.normalize(posix.resolve(pathValue)) + if (platform !== 'darwin') { + return normalized + } + if (normalized === '/private/tmp') { + return '/tmp' + } + return normalized.startsWith('/private/tmp/') ? normalized.slice('/private'.length) : normalized +} + function getRuntimePathOps( repoPath: string, workspaceDir: string diff --git a/src/main/ipc/worktrees.test.ts b/src/main/ipc/worktrees.test.ts index 9e3e8accd..114eaaf54 100644 --- a/src/main/ipc/worktrees.test.ts +++ b/src/main/ipc/worktrees.test.ts @@ -1763,7 +1763,7 @@ describe('registerWorktreeHandlers', () => { } const fsProvider = { stat: vi.fn().mockImplementation(async (pathValue: string) => { - if (pathValue === '/remote/repo/../fix-title') { + if (pathValue === '/remote/fix-title') { return { size: 0, type: 'directory', mtime: 0 } } const error = new Error('missing') as Error & { code: string } @@ -1792,11 +1792,11 @@ describe('registerWorktreeHandlers', () => { expect(provider.addWorktree).toHaveBeenCalledWith( '/remote/repo', 'feature/fix', - '/remote/repo/../fix-title-2', + '/remote/fix-title-2', { checkoutExistingBranch: true } ) expect(mux.request).toHaveBeenCalledWith('session.registerRoot', { - rootPath: '/remote/repo/../fix-title-2' + rootPath: '/remote/fix-title-2' }) })