diff --git a/src/main/git/command-runner/git-exec-admission-lifetime.test.ts b/src/main/git/command-runner/git-exec-admission-lifetime.test.ts index bba29a4adaa..e603bb3398d 100644 --- a/src/main/git/command-runner/git-exec-admission-lifetime.test.ts +++ b/src/main/git/command-runner/git-exec-admission-lifetime.test.ts @@ -1,6 +1,7 @@ import { EventEmitter } from 'node:events' import type { ChildProcess } from 'node:child_process' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type * as GitFetchHeadLockModule from '../../../shared/git-fetch-head-lock' const { execFileMock, @@ -28,6 +29,22 @@ vi.mock('../../../shared/child-process/process-tree-termination', () => ({ signalProcessTree: signalProcessTreeMock, forceTerminateProcessTree: forceTerminateProcessTreeMock })) +// Why: the real FETCH_HEAD key derivation walks the filesystem (realpath/stat/readFile), so +// concurrent same-repo callers join the lock lane in libuv threadpool completion order rather +// than call order. Keep the real FIFO lock and drop only the key walk, which owns its coverage +// in `src/shared/git-fetch-head-lock.test.ts`. +vi.mock('../../../shared/git-fetch-head-lock', async (importOriginal) => { + const actual = await importOriginal() + const { runWithGitOperationLock } = await import('../../../shared/git-operation-lock') + return { + ...actual, + runWithGitFetchHeadLock: ( + worktreePath: string, + signal: AbortSignal | undefined, + run: () => Promise + ): Promise => runWithGitOperationLock(worktreePath, signal, run) + } +}) import { gitExecFileAsync, gitExecFileAsyncBuffer } from './git-exec-file' import { execFileCapture } from './exec-file-capture'