From 033f33bc079b6c7b01d8d0b9ea3e040d6b802264 Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Wed, 2 Sep 2026 11:13:57 -0700 Subject: [PATCH] Improve git worktree operation lock robustness - Refactor async path resolution to be explicit and reliable - Add test guard ensuring release function is available before use --- src/main/git/status-read-coalescing.test.ts | 1 + src/shared/git-worktree-operation-lock.ts | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/git/status-read-coalescing.test.ts b/src/main/git/status-read-coalescing.test.ts index e0170f8d6a5..fae95130915 100644 --- a/src/main/git/status-read-coalescing.test.ts +++ b/src/main/git/status-read-coalescing.test.ts @@ -364,6 +364,7 @@ describe('getStatus', () => { const mutation = stageFile('/repo', 'src/file.ts') const duringMutation = getStatus('/repo', { signal: new AbortController().signal }) await vi.waitFor(() => expect(statusCommandCalls).toBe(2)) + await vi.waitFor(() => expect(releaseMutation).toBeTypeOf('function')) releaseMutation() await mutation const afterMutation = getStatus('/repo', { signal: new AbortController().signal }) diff --git a/src/shared/git-worktree-operation-lock.ts b/src/shared/git-worktree-operation-lock.ts index f60fa782569..acaefa19bf8 100644 --- a/src/shared/git-worktree-operation-lock.ts +++ b/src/shared/git-worktree-operation-lock.ts @@ -8,9 +8,11 @@ export async function runWithGitWorktreeOperationLock( signal: AbortSignal | undefined, run: () => Promise ): Promise { - // Async so a hung filesystem cannot freeze the main-process event loop; the - // extra yield is harmless because reads never take this lock and the lane - // chain serializes mutations whatever order they acquire it in. - const key = await realpath(worktreePath).catch(() => resolve(worktreePath)) + const fallbackKey = resolve(worktreePath) + // Async so a hung filesystem cannot freeze the main-process event loop. + const key = await Promise.resolve() + .then(() => realpath(worktreePath)) + .then((canonicalPath) => canonicalPath ?? fallbackKey) + .catch(() => fallbackKey) return runWithGitOperationLock(key, signal, run) }