@gitkraken/core-gitlens 0.15.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/dist/git/models/branch.d.ts +7 -0
  3. package/dist/git/models/branch.js +1 -0
  4. package/dist/git/models/branch.js.map +1 -1
  5. package/dist/git/models/graph.d.ts +2 -0
  6. package/dist/git/models/graph.js.map +1 -1
  7. package/dist/git/models/reference.d.ts +4 -0
  8. package/dist/git/providers/provider.d.ts +3 -1
  9. package/dist/git/providers/revision.d.ts +2 -1
  10. package/dist/git/run.types.d.ts +3 -2
  11. package/dist/git/utils/branch.utils.d.ts +15 -3
  12. package/dist/git/utils/branch.utils.js +34 -8
  13. package/dist/git/utils/branch.utils.js.map +1 -1
  14. package/dist/git/utils/reference.utils.d.ts +2 -0
  15. package/dist/git/utils/reference.utils.js.map +1 -1
  16. package/dist/git/watching/worktreeSummary.d.ts +7 -4
  17. package/dist/git/watching/worktreeSummary.js +22 -3
  18. package/dist/git/watching/worktreeSummary.js.map +1 -1
  19. package/dist/git-cli/cliGitProvider.d.ts +6 -0
  20. package/dist/git-cli/cliGitProvider.js +48 -2
  21. package/dist/git-cli/cliGitProvider.js.map +1 -1
  22. package/dist/git-cli/exec/git.d.ts +1 -0
  23. package/dist/git-cli/exec/git.js +8 -10
  24. package/dist/git-cli/exec/git.js.map +1 -1
  25. package/dist/git-cli/exec/indexLock.d.ts +9 -1
  26. package/dist/git-cli/exec/indexLock.js +19 -5
  27. package/dist/git-cli/exec/indexLock.js.map +1 -1
  28. package/dist/git-cli/parsers/logParser.d.ts +4 -0
  29. package/dist/git-cli/parsers/logParser.js +12 -2
  30. package/dist/git-cli/parsers/logParser.js.map +1 -1
  31. package/dist/git-cli/parsers/refParser.js +4 -2
  32. package/dist/git-cli/parsers/refParser.js.map +1 -1
  33. package/dist/git-cli/providers/branchRemote.d.ts +13 -1
  34. package/dist/git-cli/providers/branchRemote.js +41 -12
  35. package/dist/git-cli/providers/branchRemote.js.map +1 -1
  36. package/dist/git-cli/providers/branches.js +55 -21
  37. package/dist/git-cli/providers/branches.js.map +1 -1
  38. package/dist/git-cli/providers/graph.js +53 -32
  39. package/dist/git-cli/providers/graph.js.map +1 -1
  40. package/dist/git-cli/providers/operations.js +22 -4
  41. package/dist/git-cli/providers/operations.js.map +1 -1
  42. package/dist/git-cli/providers/revision.d.ts +8 -1
  43. package/dist/git-cli/providers/revision.js +22 -8
  44. package/dist/git-cli/providers/revision.js.map +1 -1
  45. package/dist/git-cli/providers/stash.js +3 -3
  46. package/dist/git-cli/providers/stash.js.map +1 -1
  47. package/dist/git-cli/providers/worktrees.js +3 -3
  48. package/dist/git-cli/providers/worktrees.js.map +1 -1
  49. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","names":["resolvePath","isAbsolute","dirname"],"sources":["../../../../git-cli/src/exec/git.ts"],"sourcesContent":["import type { SpawnOptions } from 'child_process';\nimport { spawn } from 'child_process';\nimport { resolve as resolvePath } from 'path';\nimport * as process from 'process';\nimport type {\n\tBranchErrorReason,\n\tCheckoutErrorReason,\n\tCherryPickErrorReason,\n\tCommitErrorReason,\n\tFetchErrorReason,\n\tGitCommandError,\n\tGitSearchErrorReason,\n\tGitWarningKey,\n\tMergeErrorReason,\n\tPausedOperationAbortErrorReason,\n\tPausedOperationContinueErrorReason,\n\tPullErrorReason,\n\tPushErrorReason,\n\tRebaseErrorReason,\n\tReferenceUpdateErrorReason,\n\tResetErrorReason,\n\tRevertErrorReason,\n\tShowErrorReason,\n\tSigningErrorReason,\n\tStashApplyErrorReason,\n\tStashPushErrorReason,\n\tTagErrorReason,\n\tWorktreeCreateErrorReason,\n\tWorktreeDeleteErrorReason,\n} from '@gitlens/git/errors.js';\nimport { getGitWarning, GitWarnings, WorkspaceUntrustedError } from '@gitlens/git/errors.js';\nimport type { GitHealthSlownessCategory } from '@gitlens/git/gitHealth.js';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\nimport type { SigningFormat } from '@gitlens/git/models/signature.js';\nimport type { GitRunCancellation } from '@gitlens/git/run.types.js';\nimport { CancellationError, getAbortSignalId, isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { getScopedCounter } from '@gitlens/utils/counter.js';\nimport { getDurationMilliseconds, hrtime } from '@gitlens/utils/hrtime.js';\nimport { chunkByStringLength } from '@gitlens/utils/iterable.js';\nimport type { LogChannel } from '@gitlens/utils/logger.js';\nimport { Logger } from '@gitlens/utils/logger.js';\nimport { formatLoggableScopeBlock } from '@gitlens/utils/logger.scoped.js';\nimport { arePathsEqual, dirname, isAbsolute, isDescendant, joinPaths, normalizePath } from '@gitlens/utils/path.js';\nimport { defer } from '@gitlens/utils/promise.js';\nimport type { Mutable } from '@gitlens/utils/types.js';\nimport { compare, fromString } from '@gitlens/utils/version.js';\nimport { getChangesForCommand, leadingCommand } from './commandClassifier.js';\nimport { EventLoopMonitor } from './eventLoopMonitor.js';\nimport { CancelledRunError, RunError } from './exec.errors.js';\nimport type { RunOptions, RunResult } from './exec.js';\nimport { endStdin, fsExists, runSpawn } from './exec.js';\nimport type { GitCommandPriority, GitResult, GitRunOptions, GitSpawnOptions } from './exec.types.js';\nimport type { FilteredGitFeatures, GitFeatureOrPrefix, GitFeatures } from './features.js';\nimport { gitFeaturesByVersion } from './features.js';\nimport type { GitQueueConfig } from './gitQueue.js';\nimport { getPrimaryGitCommand, GitQueue, inferGitCommandPriority } from './gitQueue.js';\nimport {\n\tisConfigCommand,\n\tisIndexWriteCommand,\n\tKeyedSequencer,\n\tretryWhileConfigLocked,\n\tretryWhileIndexLocked,\n} from './indexLock.js';\nimport type { GitLocation } from './locator.js';\n\nexport const slowCallWarningThreshold = 2000;\nexport type GitFeatureUnsupportedMessage = (requiredVersion: string, installedVersion: string) => string;\n/** Below this, a queue-wait annotation isn't worth adding to the log line. */\nconst queueWaitAnnotationThreshold = 100;\n/** Below this, a measured event-loop stall isn't worth annotating — see {@link EventLoopMonitor}. */\nconst eventLoopDelayAnnotationThreshold = 500;\nexport const maxGitCliLength = 30000;\n\n/**\n * Splits `paths` into `:(literal)` pathspec batches that each fit the command-line length limit after `prefix`, so a\n * folder named like a glob (`[id]/`) doesn't match its siblings.\n */\nexport function batchLiteralPathspecs(\n\tpaths: readonly string[],\n\tprefix: readonly string[],\n): Iterable<readonly string[]> {\n\t// Reserve the prefix and a per-arg overhead (separator + possible quoting), so neither a run of long paths nor\n\t// many short ones can push a batch past the OS limit\n\tconst perArgOverhead = 3;\n\tconst prefixLength = [...prefix, '--'].reduce((sum, arg) => sum + arg.length + perArgOverhead, 0);\n\treturn chunkByStringLength(\n\t\tpaths.map(p => `:(literal)${p}`),\n\t\tmaxGitCliLength - prefixLength,\n\t\tperArgOverhead,\n\t);\n}\n\nexport const gitConfigsBranch = ['-c', 'color.branch=false'] as const;\nexport const gitConfigsDiff = ['-c', 'color.diff=false', '-c', 'diff.mnemonicPrefix=false'] as const;\nexport const gitConfigsLog = ['-c', 'log.showSignature=false'] as const;\nexport const gitConfigsLogWithFiles = ['-c', 'log.showSignature=false', '-c', 'diff.renameLimit=0'] as const;\nexport const gitConfigsLogWithSignatures = ['-c', 'log.showSignature=true'] as const;\nexport const gitConfigsPull = ['-c', 'merge.autoStash=true', '-c', 'rebase.autoStash=true'] as const;\nexport const gitConfigsStatus = ['-c', 'color.status=false'] as const;\n\nexport const GitErrors = {\n\talreadyCheckedOut: /already checked out/i,\n\talreadyExists: /already exists/i,\n\tambiguousArgument: /fatal:\\s*ambiguous argument ['\"](.+?)['\"]: unknown revision or path not in the working tree/i,\n\tbadObject: /fatal:\\s*bad object (.*?)/i,\n\tbadRevision: /bad revision '(.*?)'/i,\n\tbranchAlreadyExists: /fatal:\\s*A branch named '.+?' already exists/i,\n\tnotFullyMerged: /error:\\s*The branch '.+?' is not fully merged/i,\n\tcantLockRef: /cannot lock ref|unable to update local ref/i,\n\tchangesWouldBeOverwritten:\n\t\t/Your local changes to the following files would be overwritten|Your local changes would be overwritten|overwritten by checkout/i,\n\tcherryPickAborted: /cherry-pick.*aborted/i,\n\tcherryPickInProgress: /cherry-pick is already in progress|You have not concluded your cherry-pick/i,\n\tcommitChangesFirst: /Please, commit your changes before you can/i,\n\tconflict: /^CONFLICT \\([^)]+\\): \\b/m,\n\tdetachedHead: /You are in 'detached HEAD' state/i,\n\tentryNotUpToDate: /error:\\s*Entry ['\"].+['\"] not uptodate\\. Cannot merge\\./i,\n\tfailedToDeleteDirectoryNotEmpty: /failed to delete '(.*?)': Directory not empty/i,\n\tgpgNotFound: /gpg:?\\s*(?:command\\s+)?not found|'gpg' is not recognized as|cannot run gpg:/i,\n\tgpgSignFailed: /^error:\\s*gpg failed to sign the data/im,\n\tinvalidName: /fatal:\\s*'.+?' is not a valid branch name/i,\n\tinvalidLineCount: /file .+? has only (\\d+) lines/i,\n\tinvalidObjectName: /invalid object name: (.*)\\s/i,\n\tinvalidObjectNameList: /could not open object name list: (.*)\\s/i,\n\t// Regcomp failure reasons from `-G`/pathspec regex compilation (search); matched without a known\n\t// prefix as a fallback when the reason appears in an unrecognized stderr shape\n\tinvalidSearchPattern:\n\t\t/Unmatched \\( or \\\\\\(|Unmatched \\[|Unmatched \\) or \\\\\\)|Invalid content of \\\\\\{\\\\\\}|Invalid preceding regular expression|Invalid regular expression|Trailing backslash|invalid regex/i,\n\tinvalidTagName: /invalid tag name/i,\n\tmainWorkingTree: /is a main working tree/i,\n\tmergeAborted: /merge.*aborted/i,\n\tmergeInProgress: /^fatal:\\s*You have not concluded your merge/i,\n\tnoFastForward: /\\(non-fast-forward\\)/i,\n\tnoMergeBase: /no merge base/i,\n\tnoRemoteReference: /unable to delete '.+?': remote ref does not exist/i,\n\tnoRemoteRepositorySpecified: /No remote repository specified\\./i,\n\tnoUpstream: /^fatal:\\s*The current branch .* has no upstream branch/i,\n\t// `git pull` (not `push`) on a branch with no upstream — distinct wording from `noUpstream` above\n\tnoTrackingInformation: /There is no tracking information for the current branch/i,\n\tnotAValidObjectName: /Not a valid object name/i,\n\tnotPossibleToFastForward: /Not possible to fast-forward/i,\n\tnotAWorkingTree: /'(.*?)' is not a working tree/i,\n\tnoUserNameConfigured: /Please tell me who you are\\./i,\n\tnothingToCommit: /nothing(?: added)? to commit|no changes added to commit/i,\n\tnoPausedOperation:\n\t\t/no merge (?:in progress|to abort)|no cherry-pick(?: or revert)? in progress|no rebase in progress/i,\n\tpermissionDenied: /Permission.*denied/i,\n\tpreviousOperationEmpty: /The previous (?:cherry-pick|revert) is now empty/i,\n\tproblemWithEditor: /there was a problem with the editor/i,\n\tpushRejected: /^error:\\s*failed to push some refs to\\b/m,\n\tpushRejectedRefDoesNotExists: /error:\\s*unable to delete '(.*?)': remote ref does not exist/m,\n\trebaseAborted: /Nothing to do|rebase.*aborted/i,\n\trebaseInProgress: /It seems that there is already a rebase-(?:merge|apply) directory/i,\n\trebaseMissingTodo: /error:\\s*could not read file .*\\/git-rebase-todo': No such file or directory/,\n\trebaseMultipleBranches: /cannot rebase onto multiple branches/i,\n\trevertAborted: /revert.*aborted/i,\n\trevertInProgress: /^(error: )?(revert|cherry-pick) is already in progress/i,\n\trefAlreadyExists: /cannot lock ref '.*?': reference already exists/i,\n\trefBadName: /refusing to update ref with bad name/i,\n\trefLocked: /fatal:\\s*cannot lock ref ['\"].+['\"]: unable to create file/i,\n\trefNonexistentObject: /trying to write ref '.*?' with nonexistent object/i,\n\trefNotAValidSha: /not a valid (?:old )?SHA1/i,\n\trefUnableToResolve: /cannot lock ref '.*?': unable to resolve reference/i,\n\trefValueMismatch: /cannot lock ref '.*?': is at [0-9a-f]+ but expected/i,\n\tremoteAhead: /rejected because the remote contains work/i,\n\tremoteConnectionFailed: /Could not read from remote repository/i,\n\tremoteRejected: /rejected because the remote contains work/i,\n\tsigningKeyNotAvailable: /secret key not available|no secret key|no signing key/i,\n\tsshNotFound: /ssh-keygen[^\\n]*(?:not found|No such file or directory|is not recognized)/i,\n\tstashConflictingStagedAndUnstagedLines: /Cannot remove worktree changes/i,\n\tstashNothingToSave: /No local changes to save/i,\n\tstashSavedWorkingDirAndIndexState: /Saved working directory and index state/i,\n\ttagAlreadyExists: /tag .* already exists/i,\n\ttagConflict: /! \\[rejected\\].*\\(would clobber existing tag\\)/m,\n\ttagNotFound: /tag .* not found/i,\n\tuncommittedChanges: /contains modified or untracked files/i,\n\tunmergedChanges: /error:\\s*you need to resolve your current index first/i,\n\tunmergedFiles: /is not possible because you have unmerged files|You have unmerged files/i,\n\tunresolvedConflicts:\n\t\t/You must edit all merge conflicts|Resolve all conflicts|^CONFLICT \\(|^Automatic merge failed|could not apply .*/im,\n\tunsafeRepository:\n\t\t/(?:^fatal:\\s*detected dubious ownership in repository at '([^']+)'|unsafe repository \\('([^']+)' is owned by someone else\\))[\\s\\S]*(git config --global --add safe\\.directory [^\\n•]+)/m,\n\tunstagedChanges: /You have unstaged changes/i,\n\t// Matches both variants: with a lock reason (`..., lock reason: <reason>`) and without (`...;`)\n\tworktreeLocked: /fatal:\\s*cannot remove a locked working tree/i,\n\t// Only matches the variant where Git reports a lock reason; the reason is free text, so capture the whole line\n\tworktreeLockedReason: /cannot remove a locked working tree,[ \\t]*lock reason:[ \\t]*(.*)/i,\n} as const;\n\n// `GitWarnings` moved to `@gitlens/git/errors.js` so the shared run contract can name its keys; re-exported\n// here because it's long-established as part of this module's surface.\nexport { GitWarnings };\nexport type { GitWarningKey } from '@gitlens/git/errors.js';\n\nexport class GitError extends Error {\n\treadonly cmd: string | undefined;\n\treadonly exitCode: number | string | undefined;\n\treadonly stdout: string | undefined;\n\treadonly stderr: string | undefined;\n\n\tconstructor(readonly original: Error) {\n\t\tlet message: string;\n\t\tlet stdout: string | undefined;\n\t\tlet stderr: string | undefined;\n\t\tlet cmd: string | undefined;\n\t\tlet exitCode: number | string | undefined;\n\n\t\tif (original instanceof RunError) {\n\t\t\tstdout = original.stdout;\n\t\t\tstderr = original.stderr;\n\t\t\tmessage = stderr || stdout || original.message;\n\t\t\tcmd = original.cmd;\n\t\t\texitCode = original.code;\n\t\t} else {\n\t\t\tmessage = original.message;\n\t\t}\n\n\t\tsuper(message);\n\n\t\tthis.stdout = stdout;\n\t\tthis.stderr = stderr;\n\t\tthis.cmd = cmd;\n\t\tthis.exitCode = exitCode;\n\n\t\tError.captureStackTrace?.(this, new.target);\n\t}\n}\n\nexport type PushForceOptions = { withLease: true; ifIncludes?: boolean } | { withLease: false; ifIncludes?: never };\n\ntype GitCommand =\n\t| 'branch'\n\t| 'checkout'\n\t| 'cherry-pick'\n\t| 'commit'\n\t| 'fetch'\n\t| 'merge'\n\t| 'paused-operation-abort'\n\t| 'paused-operation-continue'\n\t| 'pull'\n\t| 'push'\n\t| 'rebase'\n\t| 'reset'\n\t| 'revert'\n\t| 'show'\n\t| 'stash-apply'\n\t| 'stash-push'\n\t| 'tag'\n\t| 'update-ref'\n\t| 'update-ref-delete'\n\t| 'worktree-create'\n\t| 'worktree-delete';\n\ntype GitCommandToReasonMap = {\n\tbranch: BranchErrorReason;\n\tcheckout: CheckoutErrorReason;\n\t'cherry-pick': CherryPickErrorReason;\n\tcommit: CommitErrorReason;\n\tfetch: FetchErrorReason;\n\tmerge: MergeErrorReason;\n\t'paused-operation-abort': PausedOperationAbortErrorReason;\n\t'paused-operation-continue': PausedOperationContinueErrorReason;\n\tpull: PullErrorReason;\n\tpush: PushErrorReason;\n\trebase: RebaseErrorReason;\n\treset: ResetErrorReason;\n\trevert: RevertErrorReason;\n\tshow: ShowErrorReason;\n\t'stash-apply': StashApplyErrorReason;\n\t'stash-push': StashPushErrorReason;\n\ttag: TagErrorReason;\n\t'update-ref': ReferenceUpdateErrorReason;\n\t'update-ref-delete': ReferenceUpdateErrorReason;\n\t'worktree-create': WorktreeCreateErrorReason;\n\t'worktree-delete': WorktreeDeleteErrorReason;\n};\n\nconst errorToReasonMap = new Map<GitCommand, [RegExp, GitCommandToReasonMap[GitCommand]][]>([\n\t[\n\t\t'branch',\n\t\t[\n\t\t\t[GitErrors.branchAlreadyExists, 'alreadyExists'],\n\t\t\t[GitErrors.invalidName, 'invalidName'],\n\t\t\t[GitErrors.notFullyMerged, 'notFullyMerged'],\n\t\t\t[GitErrors.noRemoteReference, 'noRemoteReference'],\n\t\t],\n\t],\n\t[\n\t\t'checkout',\n\t\t[\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t\t[GitErrors.ambiguousArgument, 'pathspecNotFound'],\n\t\t\t[GitErrors.notAValidObjectName, 'invalidRef'],\n\t\t],\n\t],\n\t[\n\t\t'cherry-pick',\n\t\t[\n\t\t\t[GitErrors.cherryPickAborted, 'aborted'],\n\t\t\t[GitErrors.cherryPickInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.conflict, 'conflicts'],\n\t\t\t[GitErrors.previousOperationEmpty, 'emptyCommit'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'commit',\n\t\t[\n\t\t\t[GitErrors.nothingToCommit, 'nothingToCommit'],\n\t\t\t[GitErrors.unmergedFiles, 'conflicts'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.noUserNameConfigured, 'noUserNameConfigured'],\n\t\t],\n\t],\n\t[\n\t\t'fetch',\n\t\t[\n\t\t\t[GitErrors.noFastForward, 'noFastForward'],\n\t\t\t[GitErrors.noRemoteRepositorySpecified, 'noRemote'],\n\t\t\t[GitErrors.remoteConnectionFailed, 'remoteConnectionFailed'],\n\t\t],\n\t],\n\t[\n\t\t'merge',\n\t\t[\n\t\t\t[GitErrors.mergeAborted, 'aborted'],\n\t\t\t[GitErrors.mergeInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t['paused-operation-abort', [[GitErrors.noPausedOperation, 'nothingToAbort']]],\n\t[\n\t\t'paused-operation-continue',\n\t\t[\n\t\t\t// Kept FIRST: an editor failure's stderr can also carry broader messages (\"could not\n\t\t\t// commit staged changes\", …) that later patterns would otherwise claim\n\t\t\t[GitErrors.problemWithEditor, 'messageEditFailed'],\n\t\t\t[GitErrors.previousOperationEmpty, 'emptyCommit'],\n\t\t\t[GitErrors.noPausedOperation, 'nothingToContinue'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.unmergedFiles, 'unmergedFiles'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.unstagedChanges, 'unstagedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t\t// A single (non-sequencer) revert resolved to a no-op never gets git's \"previous revert is now\n\t\t\t// empty\" message — its `--continue` falls through to the commit, which reports having nothing to\n\t\t\t// commit. Mid-paused-op that means the step became empty, so it earns the same choice.\n\t\t\t//\n\t\t\t// Kept LAST because the pattern is deliberately broad: it also matches \"no changes added to\n\t\t\t// commit\" and \"nothing added to commit\", which appear alongside the more specific unmerged /\n\t\t\t// conflict / unstaged messages. Matching first would shadow those. It isn't narrowed to the\n\t\t\t// \"working tree clean\" variant because an empty step with untracked files present instead reports\n\t\t\t// \"nothing added to commit but untracked files present\".\n\t\t\t[GitErrors.nothingToCommit, 'emptyCommit'],\n\t\t],\n\t],\n\t[\n\t\t'pull',\n\t\t[\n\t\t\t[GitErrors.conflict, 'conflict'],\n\t\t\t[GitErrors.noUserNameConfigured, 'gitIdentity'],\n\t\t\t[GitErrors.remoteConnectionFailed, 'remoteConnectionFailed'],\n\t\t\t[GitErrors.unstagedChanges, 'unstagedChanges'],\n\t\t\t[GitErrors.unmergedFiles, 'unmergedFiles'],\n\t\t\t[GitErrors.commitChangesFirst, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t\t[GitErrors.cantLockRef, 'refLocked'],\n\t\t\t[GitErrors.rebaseMultipleBranches, 'rebaseMultipleBranches'],\n\t\t\t[GitErrors.tagConflict, 'tagConflict'],\n\t\t\t[GitErrors.notPossibleToFastForward, 'noFastForward'],\n\t\t\t[GitErrors.noTrackingInformation, 'noUpstream'],\n\t\t],\n\t],\n\t[\n\t\t'push',\n\t\t[\n\t\t\t[GitErrors.remoteAhead, 'remoteAhead'],\n\t\t\t[GitWarnings.tipBehind, 'tipBehind'],\n\t\t\t// Kept BEFORE the generic push rejection: a failed `push -d` of a missing ref reports both\n\t\t\t// \"unable to delete '<ref>': remote ref does not exist\" and \"failed to push some refs to ...\",\n\t\t\t// and the specific reason is the actionable one.\n\t\t\t[GitErrors.pushRejectedRefDoesNotExists, 'rejectedRefDoesNotExist'],\n\t\t\t[GitErrors.pushRejected, 'rejected'],\n\t\t\t[GitErrors.permissionDenied, 'permissionDenied'],\n\t\t\t[GitErrors.remoteConnectionFailed, 'remoteConnectionFailed'],\n\t\t\t[GitErrors.noUpstream, 'noUpstream'],\n\t\t],\n\t],\n\t[\n\t\t'rebase',\n\t\t[\n\t\t\t[GitErrors.rebaseAborted, 'aborted'],\n\t\t\t[GitErrors.rebaseMissingTodo, 'aborted'],\n\t\t\t[GitErrors.rebaseInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'reset',\n\t\t[\n\t\t\t[GitErrors.ambiguousArgument, 'ambiguousArgument'],\n\t\t\t[GitErrors.detachedHead, 'detachedHead'],\n\t\t\t[GitErrors.refLocked, 'refLocked'],\n\t\t\t[GitErrors.entryNotUpToDate, 'notUpToDate'],\n\t\t\t[GitErrors.permissionDenied, 'permissionDenied'],\n\t\t\t[GitErrors.unmergedChanges, 'unmergedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'revert',\n\t\t[\n\t\t\t[GitErrors.revertAborted, 'aborted'],\n\t\t\t[GitErrors.revertInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'show',\n\t\t[\n\t\t\t[GitErrors.badObject, 'invalidObject'],\n\t\t\t[GitErrors.badRevision, 'invalidRevision'],\n\t\t\t[GitErrors.notAValidObjectName, 'invalidRevision'],\n\t\t\t[GitWarnings.notFound, 'notFound'],\n\t\t\t[GitWarnings.foundButNotInRevision, 'notInRevision'],\n\t\t],\n\t],\n\t['stash-apply', [[GitErrors.changesWouldBeOverwritten, 'uncommittedChanges']]],\n\t[\n\t\t'stash-push',\n\t\t[\n\t\t\t[GitErrors.stashConflictingStagedAndUnstagedLines, 'conflictingStagedAndUnstagedLines'],\n\t\t\t[GitErrors.stashNothingToSave, 'nothingToSave'],\n\t\t\t[GitErrors.stashSavedWorkingDirAndIndexState, 'conflictingStagedAndUnstagedLines'],\n\t\t],\n\t],\n\t[\n\t\t'tag',\n\t\t[\n\t\t\t[GitErrors.tagAlreadyExists, 'alreadyExists'],\n\t\t\t[GitErrors.invalidTagName, 'invalidName'],\n\t\t\t[GitErrors.tagNotFound, 'notFound'],\n\t\t\t[GitErrors.permissionDenied, 'permissionDenied'],\n\t\t\t[GitErrors.remoteRejected, 'remoteRejected'],\n\t\t\t[GitErrors.tagConflict, 'tagConflict'],\n\t\t],\n\t],\n\t[\n\t\t'update-ref',\n\t\t[\n\t\t\t// Every entry below also matches the broad `cantLockRef` catch-all that closes the list, so\n\t\t\t// order is load-bearing — the specific shapes must be claimed first.\n\t\t\t[GitErrors.refBadName, 'invalidRef'],\n\t\t\t[GitErrors.refNonexistentObject, 'invalidObject'],\n\t\t\t[GitErrors.refNotAValidSha, 'invalidObject'],\n\t\t\t[GitErrors.refValueMismatch, 'conflict'],\n\t\t\t[GitErrors.refAlreadyExists, 'conflict'],\n\t\t\t// A ref that vanished under a compare-and-swap lost the same race as one that moved, so an\n\t\t\t// update reports both as a conflict — the caller's response (re-read, retry) is identical.\n\t\t\t[GitErrors.refUnableToResolve, 'conflict'],\n\t\t\t// Directory/file collisions and any other lock refusal\n\t\t\t[GitErrors.cantLockRef, 'conflict'],\n\t\t],\n\t],\n\t[\n\t\t'update-ref-delete',\n\t\t[\n\t\t\t[GitErrors.refBadName, 'invalidRef'],\n\t\t\t[GitErrors.refNotAValidSha, 'invalidObject'],\n\t\t\t// Kept BEFORE the generic lock failures, and split from the update table above: a deleter\n\t\t\t// that finds its target already gone has reached the state it wanted, while one that finds\n\t\t\t// the target moved has not. Collapsing both into `conflict` would force every caller to\n\t\t\t// re-read just to tell an idempotent no-op from a real race.\n\t\t\t[GitErrors.refUnableToResolve, 'notFound'],\n\t\t\t[GitErrors.refValueMismatch, 'conflict'],\n\t\t\t[GitErrors.cantLockRef, 'conflict'],\n\t\t],\n\t],\n\t[\n\t\t'worktree-create',\n\t\t[\n\t\t\t[GitErrors.alreadyCheckedOut, 'alreadyCheckedOut'],\n\t\t\t[GitErrors.alreadyExists, 'alreadyExists'],\n\t\t],\n\t],\n\t[\n\t\t'worktree-delete',\n\t\t[\n\t\t\t// Must come first -- a locked worktree's lock reason is free text that can otherwise match the errors below\n\t\t\t[GitErrors.worktreeLocked, 'locked'],\n\t\t\t[GitErrors.mainWorkingTree, 'defaultWorkingTree'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.failedToDeleteDirectoryNotEmpty, 'directoryNotEmpty'],\n\t\t],\n\t],\n]);\n\nexport function getGitCommandError<T extends GitCommand, TReturn extends GitCommandError<any>>(\n\tcommand: T,\n\tex: GitError,\n\tcreator: (reason: GitCommandToReasonMap[T] | undefined) => TReturn,\n): TReturn {\n\tconst msg: string = ex?.toString() ?? '';\n\n\tconst errorsToReasons = errorToReasonMap.get(command) as [RegExp, GitCommandToReasonMap[T]][] | undefined;\n\tif (errorsToReasons != null) {\n\t\tfor (const [error, reason] of errorsToReasons) {\n\t\t\tif (error.test(msg) || (ex.stderr && error.test(ex.stderr)) || (ex.stdout && error.test(ex.stdout))) {\n\t\t\t\treturn creator(reason);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn creator(undefined);\n}\n\nfunction extractSigningErrorText(ex: unknown): string {\n\tif (ex == null) return '';\n\tif (ex instanceof GitError) return ex.stderr || ex.stdout || ex.message || '';\n\tif (ex instanceof Error) return ex.message || '';\n\tif (typeof ex === 'string') return ex;\n\tif (typeof ex === 'number' || typeof ex === 'boolean' || typeof ex === 'bigint') return String(ex);\n\tif (typeof ex === 'object' && 'message' in ex && typeof ex.message === 'string') return ex.message;\n\treturn '';\n}\n\n/**\n * Classifies a Git error as a signing-related failure using the {@link GitErrors}\n * signing regexes. Returns the matched {@link SigningErrorReason}, or `undefined`\n * when the error is not a recognized signing failure.\n *\n * Precedence is significant: `passphraseFailed` (gpg sign failure) is checked\n * before `noKey`, matching the ordering used historically in patch.ts — a\n * combined stderr like \"error: gpg failed to sign … gpg: No secret key\"\n * resolves to `passphraseFailed`, the outer cause.\n */\nexport function classifySigningError(ex: unknown): SigningErrorReason | undefined {\n\tconst text = extractSigningErrorText(ex);\n\tif (!text) return undefined;\n\tif (GitErrors.gpgSignFailed.test(text)) return 'passphraseFailed';\n\tif (GitErrors.signingKeyNotAvailable.test(text)) return 'noKey';\n\tif (GitErrors.gpgNotFound.test(text)) return 'gpgNotFound';\n\tif (GitErrors.sshNotFound.test(text)) return 'sshNotFound';\n\treturn undefined;\n}\n\n/**\n * Infers the {@link SigningFormat} from stderr hints (e.g., mentions of\n * `ssh-keygen` or `gpg.ssh.*` config keys). Returns `undefined` when no hints\n * are present so callers can supply their own default (typically `'gpg'`).\n *\n * Used as a fallback when `config.getSigningConfig` is unavailable or rejects\n * on the error path.\n */\nexport function inferSigningFormatFromError(ex: unknown): SigningFormat | undefined {\n\tconst text = extractSigningErrorText(ex);\n\tif (!text) return undefined;\n\tif (/\\bssh-keygen\\b|gpg\\.ssh\\.(?:program|allowedsignersfile)/i.test(text)) return 'ssh';\n\tif (/\\bgpg\\b/i.test(text)) return 'gpg';\n\treturn undefined;\n}\n\nexport interface SearchErrorClassification {\n\treason: GitSearchErrorReason;\n\tdetail?: string;\n}\n\n/**\n * Classifies a graph search failure from its stderr into an {@link GitSearchErrorReason}, with the\n * offending pattern/ref text (when git reports one) as `detail`. Returns `undefined` when the error\n * isn't a `GitError` with stderr, or the stderr doesn't match a recognized shape.\n */\nexport function classifySearchError(ex: unknown): SearchErrorClassification | undefined {\n\tif (!(ex instanceof GitError) || !ex.stderr) return undefined;\n\n\tconst stderr = ex.stderr;\n\n\t// `-G<pattern>`/pathspec regex compile failures report one of two shapes:\n\t// fatal: command line, '<pattern>': <regcomp reason>\n\t// fatal: invalid regex: <regcomp reason>\n\t// The pattern itself may contain \"': \", so anchor on the known prefixes and let the greedy `.*`\n\t// resolve to the LAST matching delimiter rather than splitting on the first occurrence.\n\tconst patternDetail =\n\t\t/^fatal:\\s*command line,\\s*'.*':\\s*(.+)$/im.exec(stderr)?.[1] ??\n\t\t/^fatal:\\s*invalid regex:\\s*(.+)$/im.exec(stderr)?.[1];\n\tif (patternDetail != null) return { reason: 'invalidPattern', detail: patternDetail.trim() };\n\n\tif (GitErrors.invalidSearchPattern.test(stderr)) return { reason: 'invalidPattern' };\n\n\tconst ambiguous = GitErrors.ambiguousArgument.exec(stderr);\n\tif (ambiguous != null) return { reason: 'invalidRef', detail: ambiguous[1] };\n\n\tconst badRevision = GitErrors.badRevision.exec(stderr);\n\tif (badRevision != null) return { reason: 'invalidRef', detail: badRevision[1] };\n\n\tif (/unknown revision/i.test(stderr)) return { reason: 'invalidRef' };\n\n\treturn undefined;\n}\n\nexport interface GitOptions {\n\t/** Custom environment variables to add to every git command */\n\tenv?: Record<string, string | undefined>;\n\t/** Dynamic environment provider called for each command (e.g., host-discovered SCM credentials) */\n\tgetEnvironment?: () => Record<string, string | undefined> | undefined;\n\t/** Git command timeout in milliseconds, for runs that don't set their own. Defaults to 60000. Set to 0 to disable. */\n\tgitTimeout?: number;\n\t/** Returns whether the workspace is currently trusted. Defaults to true when not provided. Called on every exec/stream. */\n\tisTrusted?: () => boolean;\n\t/** Queue configuration (max concurrent processes, etc.) */\n\tqueue?: GitQueueConfig;\n\t/** Decodes non-UTF-8 git output. Required when repositories use non-UTF-8 encodings. */\n\tdecode?: (data: Uint8Array, options?: { readonly encoding: string }) => string | Promise<string>;\n\t/** Hooks for observing git execution events */\n\thooks?: GitHooks;\n\t/** Optional dedicated logger for git command logging */\n\tlogger?: LogChannel;\n}\n\nexport interface GitHooks {\n\t/** Called when a git command is aborted (timeout or cancellation) */\n\tonAborted?(info: {\n\t\toperation: string;\n\t\treason: 'timeout' | 'cancellation' | 'unknown';\n\t\tduration: number;\n\t\ttimeout: number;\n\t}): void;\n\t/** Called when a queued command waited longer than 1s before executing */\n\tonSlowQueue?(info: {\n\t\tpriority: GitCommandPriority;\n\t\twaitTime: number;\n\t\tactive: number;\n\t\tqueued: Record<GitCommandPriority, number>;\n\t\tmaxConcurrent: number;\n\t}): void;\n\t/**\n\t * Called once per git command that ran slowly (over the slow-call threshold). Fired only for the\n\t * command that actually executed, never for a deduplicated rider that merely awaited it, so a single\n\t * slow subprocess counts once. `operation` is the primary git subcommand (e.g. `status`, `rev-list`).\n\t */\n\tonSlowCommand?(info: {\n\t\toperation: string | undefined;\n\t\tcwd: string | undefined;\n\t\tduration: number;\n\t\t/** Measured event-loop stall overlapping the command; omitted (or 0) when none was observed. */\n\t\teventLoopDelay?: number;\n\t\t/** Caller-declared operation family, see `GitRunOptions.slownessCategory`. */\n\t\tslownessCategory?: GitHealthSlownessCategory;\n\t}): void;\n}\n\n/**\n * Keys dropped from the INHERITED `process.env` before it seeds the base git environment. git hands these\n * to anything it launches (a hook, `rebase -x`, an editor invoked as `GIT_EDITOR`) to describe the command\n * it is running; a host started that way would otherwise run every command against THAT repository with\n * THAT command's settings, whatever `cwd` we pass. None is worth keeping when set deliberately either: a\n * `GIT_DIR` would point every repository the host opens at one. `options.env`, `options.getEnvironment()`\n * and a per-call `env` are merged in afterwards, so any of them can still set these keys (e.g. a temporary\n * `GIT_INDEX_FILE` for a call).\n */\nconst inheritedEnvKeysToDrop: ReadonlySet<string> = new Set([\n\t// The parent's repository location — must come from our own cwd\n\t'GIT_DIR',\n\t'GIT_WORK_TREE',\n\t'GIT_INDEX_FILE',\n\t'GIT_COMMON_DIR',\n\t'GIT_OBJECT_DIRECTORY',\n\t'GIT_ALTERNATE_OBJECT_DIRECTORIES',\n\t'GIT_NAMESPACE',\n\t// What git tells a child about the command it's running: its `-c` overrides, its helpers' location, the\n\t// subdirectory it ran from, and the label for its reflog entries\n\t'GIT_CONFIG_PARAMETERS',\n\t'GIT_EXEC_PATH',\n\t'GIT_PREFIX',\n\t'GIT_REFLOG_ACTION',\n]);\n\n/**\n * Dropped only when git launched the host, which it always marks by exporting `GIT_EXEC_PATH`: an editor\n * opened for `commit --amend` gets that commit's author and date, while an identity set deliberately (e.g.\n * by direnv) must still reach our commits.\n */\nconst inheritedIdentityKeysToDrop: ReadonlySet<string> = new Set([\n\t'GIT_AUTHOR_NAME',\n\t'GIT_AUTHOR_EMAIL',\n\t'GIT_AUTHOR_DATE',\n\t'GIT_COMMITTER_NAME',\n\t'GIT_COMMITTER_EMAIL',\n\t'GIT_COMMITTER_DATE',\n]);\n\n/** `process.env` with {@link inheritedEnvKeysToDrop} removed, and {@link inheritedIdentityKeysToDrop} when git launched us. */\nfunction getInheritedEnv(): Record<string, string | undefined> {\n\tconst launchedByGit = process.env.GIT_EXEC_PATH != null;\n\treturn Object.fromEntries(\n\t\tObject.entries(process.env).filter(\n\t\t\t([key]) => !inheritedEnvKeysToDrop.has(key) && !(launchedByGit && inheritedIdentityKeysToDrop.has(key)),\n\t\t),\n\t);\n}\n\nconst emptyArray: readonly never[] = Object.freeze([]);\nconst emptyObj = Object.freeze({});\nconst trailingNewlineRegex = /[\\r|\\n]+$/;\nconst unsharedRunCounter = getScopedCounter();\nconst uniqueCounterForStream = getScopedCounter();\n\ntype ExitCodeOnlyGitCommandOptions = GitRunOptions & { exitCodeOnly: true };\n\nexport class Git {\n\t/** Map of running git commands — avoids running duplicate overlapping commands */\n\tprivate readonly pendingCommands = new Map<\n\t\tstring,\n\t\t{ readonly cwd: string | undefined; readonly promise: Promise<RunResult<string | Buffer>> }\n\t>();\n\t/** Queue for throttling background git operations */\n\tprivate readonly _queue: GitQueue;\n\t/** Orders the index-writing runs of each checkout, so they don't race for its `index.lock` */\n\tprivate readonly _indexWrites = new KeyedSequencer();\n\t/** The spawn behind every non-streaming run — a field only so tests can substitute it */\n\tprivate readonly _runSpawn: typeof runSpawn = runSpawn;\n\t/** Detects event-loop stalls while at least one git command is in flight */\n\tprivate readonly _eventLoopMonitor = new EventLoopMonitor();\n\t/** Count of git commands currently in flight, across both the exec and streaming paths */\n\tprivate _activeCommandCount = 0;\n\n\t/** Cached base environment: process.env (minus {@link inheritedEnvKeysToDrop}) + static options.env + GCM/LC_ALL vars */\n\tprivate _baseEnv: Record<string, string | undefined> | undefined;\n\t/** Cached full environment: base + dynamic getEnvironment() result */\n\tprivate _fullEnv: Record<string, string | undefined> | undefined;\n\t/** Last dynamic env reference, used to detect when getEnvironment() returns a new object */\n\tprivate _lastDynamicEnv: Record<string, string | undefined> | undefined | null;\n\n\t/** Bound via {@link bindChangeNotifier}; announces a `notify`-flagged run's changes. No-op until bound. */\n\tprivate _changeNotifier:\n\t\t| ((\n\t\t\t\trepoPaths: readonly string[],\n\t\t\t\tchanges: readonly RepositoryChange[],\n\t\t\t\tsharedPaths?: readonly string[],\n\t\t ) => void)\n\t\t| undefined;\n\n\tconstructor(\n\t\tprivate readonly _locator: () => Promise<GitLocation>,\n\t\treadonly options: GitOptions = {},\n\t) {\n\t\tthis._queue = new GitQueue(options.queue, { onSlowQueue: options.hooks?.onSlowQueue });\n\t}\n\n\t/**\n\t * Binds the callback a `notify`-flagged {@link run} calls once it settles. `CliGitProvider` wires this\n\t * to its own `notifyChanged` from its constructor — including when it's handed a pre-built `Git` via\n\t * `options.git`, so a host-supplied instance gets bound too. With nothing bound, `notify` is a no-op.\n\t * `repoPaths` holds more than one path only for a `-C`-scoped shared-state verb: the `-C` target, then the\n\t * caller's own `cwd`. `sharedPaths` names the paths that were not run in but share the repository, which\n\t * hear only the part of `changes` every worktree sees (the caller's `cwd`, when the verb also changed\n\t * something local to the `-C` target).\n\t */\n\tbindChangeNotifier(\n\t\tfn: (\n\t\t\trepoPaths: readonly string[],\n\t\t\tchanges: readonly RepositoryChange[],\n\t\t\tsharedPaths?: readonly string[],\n\t\t) => void,\n\t): void {\n\t\tthis._changeNotifier = fn;\n\t}\n\n\t/**\n\t * Returns the base environment for git commands. Cached to avoid spreading\n\t * process.env (30-100+ keys) on every call. Includes static options.env and\n\t * GCM/LC_ALL vars but NOT dynamic getEnvironment() or per-call env overrides.\n\t */\n\tprivate getBaseEnv(): Record<string, string | undefined> {\n\t\treturn (this._baseEnv ??= {\n\t\t\t...getInheritedEnv(),\n\t\t\t...(this.options.env ?? emptyObj),\n\t\t\tGCM_INTERACTIVE: 'NEVER',\n\t\t\tGCM_PRESERVE_CREDS: 'TRUE',\n\t\t\tLC_ALL: 'C',\n\t\t});\n\t}\n\n\t/**\n\t * Returns the full environment (base + dynamic). Cached and invalidated\n\t * when getEnvironment() returns a different object reference.\n\t */\n\tprivate getFullEnv(): Record<string, string | undefined> {\n\t\tconst dynamicEnv = this.options.getEnvironment?.() ?? undefined;\n\t\tif (this._fullEnv != null && dynamicEnv === this._lastDynamicEnv) return this._fullEnv;\n\n\t\tthis._lastDynamicEnv = dynamicEnv;\n\t\tthis._fullEnv = dynamicEnv != null ? { ...this.getBaseEnv(), ...dynamicEnv } : this.getBaseEnv();\n\t\treturn this._fullEnv;\n\t}\n\n\t/**\n\t * Builds the environment for a git command. Returns the cached full env\n\t * directly when there are no per-call overrides (the common case).\n\t * Only allocates a new object when per-call env overrides are provided.\n\t */\n\tprivate buildEnv(perCallEnv: Record<string, string | undefined> | undefined): Record<string, string | undefined> {\n\t\tif (perCallEnv == null) return this.getFullEnv();\n\n\t\treturn { ...this.getFullEnv(), ...perCallEnv };\n\t}\n\n\tdispose(): void {\n\t\tthis._queue.dispose();\n\t\tthis._eventLoopMonitor.dispose();\n\t}\n\n\t/**\n\t * Drops in-flight commands so a later identical call spawns its own run instead of joining one that\n\t * started before a change. With `repoPaths`, drops only runs whose `cwd` is one of them or inside one;\n\t * without, drops every run.\n\t */\n\tclearPendingCommands(repoPaths?: readonly string[]): void {\n\t\tif (repoPaths == null) {\n\t\t\tthis.pendingCommands.clear();\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const [key, { cwd }] of this.pendingCommands) {\n\t\t\tif (cwd == null) continue;\n\n\t\t\tif (repoPaths.some(p => arePathsEqual(cwd, p) || isDescendant(cwd, p))) {\n\t\t\t\tthis.pendingCommands.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Marks one more git command as in flight; starts the event-loop monitor on the first. */\n\tprivate beginActiveCommand(): void {\n\t\tthis._activeCommandCount++;\n\t\tif (this._activeCommandCount === 1) {\n\t\t\tthis._eventLoopMonitor.start();\n\t\t}\n\t}\n\n\t/** Marks a git command as finished; stops the event-loop monitor once none remain. */\n\tprivate endActiveCommand(): void {\n\t\tthis._activeCommandCount--;\n\t\tif (this._activeCommandCount === 0) {\n\t\t\tthis._eventLoopMonitor.stop();\n\t\t}\n\t}\n\n\t/** Formats the shared \"event loop blocked\" log annotation; undefined below {@link eventLoopDelayAnnotationThreshold}. */\n\tprivate formatEventLoopDelayAnnotation(sinceEpochMs: number): string | undefined {\n\t\tconst delay = this._eventLoopMonitor.maxDelaySince(sinceEpochMs);\n\t\treturn delay >= eventLoopDelayAnnotationThreshold ? `event loop blocked ~${delay}ms` : undefined;\n\t}\n\n\tprivate _gitLocation: GitLocation | undefined;\n\tprivate _gitLocationPromise: Promise<GitLocation> | undefined;\n\n\tprivate async getLocation(): Promise<GitLocation> {\n\t\tif (this._gitLocation == null) {\n\t\t\tthis._gitLocationPromise ??= this._locator();\n\t\t\tthis._gitLocation = await this._gitLocationPromise;\n\t\t}\n\t\treturn this._gitLocation;\n\t}\n\n\tasync path(): Promise<string> {\n\t\treturn (await this.getLocation()).path;\n\t}\n\n\tasync version(): Promise<string> {\n\t\treturn (await this.getLocation()).version;\n\t}\n\n\tsupports(feature: GitFeatures): boolean | Promise<boolean> {\n\t\tconst version = gitFeaturesByVersion.get(feature);\n\t\tif (version == null) return true;\n\n\t\treturn this._gitLocation != null\n\t\t\t? compare(fromString(this._gitLocation.version), fromString(version)) !== -1\n\t\t\t: this.version().then(v => compare(fromString(v), fromString(version)) !== -1);\n\t}\n\n\tsupported<T extends GitFeatureOrPrefix>(feature: T): FilteredGitFeatures<T>[] | Promise<FilteredGitFeatures<T>[]> {\n\t\tfunction supportedCore(gitVersion: string): FilteredGitFeatures<T>[] {\n\t\t\treturn [...gitFeaturesByVersion]\n\t\t\t\t.filter(([f, v]) => f.startsWith(feature) && compare(fromString(gitVersion), v) !== -1)\n\t\t\t\t.map(([f]) => f as FilteredGitFeatures<T>);\n\t\t}\n\n\t\tif (this._gitLocation == null) {\n\t\t\treturn this.version().then(v => supportedCore(v));\n\t\t}\n\t\treturn supportedCore(this._gitLocation.version);\n\t}\n\n\tasync ensureSupports(feature: GitFeatures, prefix: string, suffix: string): Promise<void>;\n\tasync ensureSupports(feature: GitFeatures, message: GitFeatureUnsupportedMessage): Promise<void>;\n\tasync ensureSupports(\n\t\tfeature: GitFeatures,\n\t\tprefixOrMessage: string | GitFeatureUnsupportedMessage,\n\t\tsuffix?: string,\n\t): Promise<void> {\n\t\tconst version = gitFeaturesByVersion.get(feature);\n\t\tif (version == null) return;\n\n\t\tconst gitVersion = await this.version();\n\t\tif (compare(fromString(gitVersion), fromString(version)) !== -1) return;\n\n\t\tconst message =\n\t\t\ttypeof prefixOrMessage === 'function'\n\t\t\t\t? prefixOrMessage(version, gitVersion)\n\t\t\t\t: `${prefixOrMessage} requires a newer version of Git (>= ${version}) than is currently installed (${gitVersion}).${suffix}`;\n\t\tthrow new Error(message);\n\t}\n\n\tasync run(\n\t\toptions: ExitCodeOnlyGitCommandOptions,\n\t\t...args: readonly (string | undefined)[]\n\t): Promise<GitResult<unknown>>;\n\tasync run<T extends string | Buffer = string>(\n\t\toptions: GitRunOptions,\n\t\t...args: readonly (string | undefined)[]\n\t): Promise<GitResult<T>>;\n\tasync run<T extends string | Buffer = string>(\n\t\toptions: GitRunOptions,\n\t\t...args: readonly (string | undefined)[]\n\t): Promise<GitResult<T | unknown>> {\n\t\tif (this.options.isTrusted?.() === false) throw new WorkspaceUntrustedError();\n\n\t\tconst runArgs = args.filter(a => a != null);\n\n\t\t// `notify` announces once the run settles (success, failure or cancellation), which the bare\n\t\t// `return <promise>` paths below don't wait for; callers without it never take this branch.\n\t\tif (options.notify != null) {\n\t\t\ttry {\n\t\t\t\treturn await this.run<T>({ ...options, notify: undefined }, ...args);\n\t\t\t} finally {\n\t\t\t\tthis.applyNotify(options, runArgs);\n\t\t\t}\n\t\t}\n\n\t\tconst gitCommand = `git ${runArgs.join(' ')}`;\n\n\t\t// If cache is provided, use it to cache the full result\n\t\tif (options.caching != null) {\n\t\t\tconst cachePath = options.caching.commonPath ?? options.cwd!;\n\t\t\t// Drop the cached (or in-flight) entry first so `getOrCreate` below always creates a fresh\n\t\t\t// entry with its own `AbortAggregate` — the underlying spawn can then never join an in-flight\n\t\t\t// run that started before this caller's own write.\n\t\t\tif (options.caching.force) {\n\t\t\t\toptions.caching.cache.delete(cachePath, gitCommand);\n\t\t\t}\n\n\t\t\treturn options.caching.cache.getOrCreate(\n\t\t\t\tcachePath,\n\t\t\t\tgitCommand,\n\t\t\t\tasync (cacheable, signal) => {\n\t\t\t\t\t// Bind the shared spawn to the aggregate `signal` (fires only when ALL current callers\n\t\t\t\t\t// abort), not this-caller's `options.cancellation` — otherwise a superseded caller's\n\t\t\t\t\t// abort would kill the shared command and reject concurrent riders that never cancelled.\n\t\t\t\t\tconst result = await this.runCore<T>(\n\t\t\t\t\t\t{ ...options, caching: undefined, cancellation: signal ?? options.cancellation },\n\t\t\t\t\t\trunArgs,\n\t\t\t\t\t\tgitCommand,\n\t\t\t\t\t);\n\t\t\t\t\t// Never cache a result that isn't a genuine command outcome. Under `errors: 'ignore'` a\n\t\t\t\t\t// cancelled/aborted run RESOLVES an empty result, which — left cached — would be served as a\n\t\t\t\t\t// real empty result for the full TTL (e.g. a valid merge-base read back as \"none\").\n\t\t\t\t\t// Invalidate on anything that isn't a clean exit, or whenever the aggregate signal aborted,\n\t\t\t\t\t// so the entry self-evicts instead of poisoning later callers.\n\t\t\t\t\t//\n\t\t\t\t\t// `status !== 'exited'` is what catches the case a bare `exitCode` check cannot. A swallowed\n\t\t\t\t\t// `GitWarnings` match used to report `exitCode: 0` UNCONDITIONALLY — the old code read it off\n\t\t\t\t\t// a `result` that is only ever assigned on the non-throwing path, so it was always the `?? 0`\n\t\t\t\t\t// fallback — which meant `exitCode !== 0` could never fire and every swallowed failure was\n\t\t\t\t\t// cached. A `warned` result now carries git's real code, so it's the status, not the code,\n\t\t\t\t\t// that has to do the work here. The `exitCode !== 0` half is kept as-is — a non-zero exit is\n\t\t\t\t\t// a real answer and arguably cacheable, but it isn't cached today and this isn't the change\n\t\t\t\t\t// to start.\n\t\t\t\t\tif (result.completion.status !== 'exited' || result.exitCode !== 0 || signal?.aborted) {\n\t\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\t// Forward this caller's cancellation so `getOrCreate` races each caller's own wait — an\n\t\t\t\t// aborting caller rejects only itself, leaving the shared work (and its riders) intact.\n\t\t\t\t{ ...options.caching.options, cancellation: options.cancellation },\n\t\t\t);\n\t\t}\n\n\t\treturn this.runCore<T>(options, runArgs, gitCommand);\n\t}\n\n\t/**\n\t * Applies `options.notify` once a {@link run} has settled — a no-op unless both `notify` and a\n\t * {@link bindChangeNotifier bound} notifier are present, so an unflagged caller pays nothing.\n\t */\n\tprivate applyNotify(options: GitRunOptions, args: readonly string[]): void {\n\t\tconst notify = options.notify;\n\t\tif (notify == null || this._changeNotifier == null || options.cwd == null) return;\n\n\t\tif (notify !== 'infer') {\n\t\t\t// The caller decided exactly what changed; still resolve WHERE it changed the same way `infer`\n\t\t\t// does, since the caller may have passed its own `-C` in the argv.\n\t\t\tthis._changeNotifier([this.resolveNotifyPath(options.cwd, leadingCommand(args).pathOverride)], notify);\n\t\t\treturn;\n\t\t}\n\n\t\tconst command = getChangesForCommand(args);\n\t\tif (command == null) return; // read-only or object-store-only — nothing to announce\n\n\t\tconst ranIn = this.resolveNotifyPath(options.cwd, command.pathOverride);\n\n\t\t// A `-C`-scoped write also changes what the caller's own `cwd` sees when both share a `.git`: a branch,\n\t\t// tag or stash it wrote. The target may be a worktree the cache never registered, so its eviction can't be\n\t\t// trusted to reach `cwd`; announce the shared kinds there too, and only those. A write it can't classify\n\t\t// (`[]`) resets both, since what it shares is unknown.\n\t\tconst cwd = normalizePath(options.cwd);\n\t\tif (\n\t\t\tcommand.pathOverride != null &&\n\t\t\tcwd !== ranIn &&\n\t\t\t(command.sharedChanges.length || !command.changes.length)\n\t\t) {\n\t\t\tif (command.sharedChanges.length === command.changes.length) {\n\t\t\t\tthis._changeNotifier([ranIn, cwd], command.changes);\n\t\t\t} else {\n\t\t\t\tthis._changeNotifier([ranIn], command.changes, [cwd]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis._changeNotifier([ranIn], command.changes);\n\t}\n\n\tprivate resolveNotifyPath(cwd: string, pathOverride: string | undefined): string {\n\t\treturn normalizePath(pathOverride != null ? resolvePath(cwd, pathOverride) : cwd);\n\t}\n\n\tprivate async runCore<T extends string | Buffer>(\n\t\toptions: GitRunOptions,\n\t\targs: string[],\n\t\tgitCommand: string,\n\t): Promise<GitResult<T | unknown>> {\n\t\tconst start = hrtime();\n\t\tconst startEpochMs = Date.now();\n\n\t\tgitCommand = `[${options.cwd}] ${gitCommand}`;\n\t\tconst {\n\t\t\tbeforeIndexLockRetry,\n\t\t\tcancellation,\n\t\t\tconfigs,\n\t\t\tcorrelationKey,\n\t\t\terrors: errorHandling,\n\t\t\tencoding,\n\t\t\texpectedExitCodes,\n\t\t\trunLocally: _,\n\t\t\tselfMaintenance,\n\t\t\tslownessCategory,\n\t\t\t...opts\n\t\t} = options;\n\n\t\t// A run's own timeout holds even when the default is disabled (0), so an unrequested background run stays capped\n\t\tconst runTimeout = opts.timeout ?? this.options.gitTimeout ?? 60000;\n\t\tconst runOpts: Mutable<RunOptions> = {\n\t\t\t...opts,\n\t\t\ttimeout: runTimeout === 0 ? undefined : runTimeout,\n\t\t\tencoding: (encoding ?? 'utf8') === 'utf8' ? 'utf8' : 'buffer',\n\t\t\tdecode: this.options.decode,\n\t\t\tenv: this.buildEnv(options.env),\n\t\t\tquiet: errorHandling === 'ignore',\n\t\t};\n\n\t\t// A run fed its own stdin or per-call env is never shared: the same argv can answer differently for\n\t\t// each (a temporary index through `GIT_INDEX_FILE`, config injected through `GIT_CONFIG_*`). Nor is one\n\t\t// carrying a retry hook, since the check it makes is that caller's own.\n\t\tconst unshared =\n\t\t\toptions?.stdin != null ||\n\t\t\t(options?.env != null && Object.keys(options.env).length > 0) ||\n\t\t\tbeforeIndexLockRetry != null;\n\t\tconst cacheKey = `${correlationKey !== undefined ? `${correlationKey}:` : ''}${\n\t\t\tunshared ? `${unsharedRunCounter.next()}:` : ''\n\t\t}${cancellation != null ? `${getAbortSignalId(cancellation)}:` : ''}${gitCommand}`;\n\n\t\t// When the subprocess actually started — `start` includes GitQueue wait, which is congestion rather\n\t\t// than anything the repository did. Stays undefined for a dedup rider or a command aborted while queued.\n\t\tlet execStart: ReturnType<typeof hrtime> | undefined;\n\t\t// What the caller's retry hook threw. It is the caller's own failure, so it must reach them as thrown\n\t\t// rather than be classified like a git failure below.\n\t\tlet hookFailure: { error: unknown } | undefined;\n\t\tlet waiting;\n\t\tlet promise = this.pendingCommands.get(cacheKey)?.promise;\n\t\tif (promise == null) {\n\t\t\twaiting = false;\n\n\t\t\t// Create a deferred promise and store it immediately to prevent duplicate commands\n\t\t\t// Note: cancellation tokens are not part of the dedup key — calls with different AbortSignals will not be deduplicated\n\t\t\tconst deferred = defer<RunResult<string | Buffer>>();\n\t\t\tpromise = deferred.promise;\n\t\t\tthis.pendingCommands.set(cacheKey, { cwd: options.cwd, promise: promise });\n\n\t\t\t// A write to the index takes `index.lock` and fails at once if another process holds it, so these\n\t\t\t// runs queue behind one another per checkout and retry briefly when something outside still beats\n\t\t\t// them to it. A temporary index (`GIT_INDEX_FILE`) has a lock of its own, so it never joins the order.\n\t\t\tconst writesIndex = isIndexWriteCommand(args);\n\t\t\tconst checkoutKey =\n\t\t\t\twritesIndex && options.cwd != null && runOpts.env?.GIT_INDEX_FILE == null\n\t\t\t\t\t? this.resolveNotifyPath(options.cwd, leadingCommand(args).pathOverride)\n\t\t\t\t\t: undefined;\n\n\t\t\t// Fixes https://github.com/gitkraken/vscode-gitlens/issues/73 & https://github.com/gitkraken/vscode-gitlens/issues/161\n\t\t\t// See https://stackoverflow.com/questions/4144417/how-to-handle-asian-characters-in-file-names-in-git-on-os-x\n\t\t\targs.unshift('-c', 'core.quotepath=false', '-c', 'color.ui=false', ...(configs ?? emptyArray));\n\n\t\t\tif (process.platform === 'win32') {\n\t\t\t\targs.unshift('-c', 'core.longpaths=true');\n\t\t\t}\n\n\t\t\tif (cancellation != null) {\n\t\t\t\trunOpts.cancellation = cancellation;\n\t\t\t}\n\n\t\t\t// Determine command priority:\n\t\t\t// Priority resolution:\n\t\t\t// 1. Explicit priority from options (highest precedence)\n\t\t\t// 2. Inferred from command type (only downgrades expensive commands to Background)\n\t\t\tconst priority = options.priority ?? inferGitCommandPriority(args);\n\n\t\t\t// Execute through the queue (interactive/normal run immediately, background is throttled)\n\t\t\tconst gitPath = await this.path();\n\t\t\tconst spawnQueued = () =>\n\t\t\t\tthis._queue.run(\n\t\t\t\t\tpriority,\n\t\t\t\t\t() => {\n\t\t\t\t\t\texecStart = hrtime();\n\t\t\t\t\t\treturn this._runSpawn<T>(gitPath, args, encoding ?? 'utf8', runOpts);\n\t\t\t\t\t},\n\t\t\t\t\tcancellation,\n\t\t\t\t);\n\t\t\t// The retry wraps the spawn itself, before any `errors` mode turns a failure into a result or a\n\t\t\t// throw, because only the raw `RunError` carries the stderr that says the lock was held. It re-queues\n\t\t\t// each attempt, so waiting between them doesn't hold a queue slot.\n\t\t\t// A config write likewise fails at once on a held `<file>.lock`. Reads never produce that failure, so\n\t\t\t// the retry costs them nothing, and one wrap covers both `errors` modes.\n\t\t\tconst beforeRetry =\n\t\t\t\tbeforeIndexLockRetry != null\n\t\t\t\t\t? async (lockError: Error) => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait beforeIndexLockRetry(lockError);\n\t\t\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t\t\t// The lock error thrown back only declines the retry, leaving the lock failure as the result\n\t\t\t\t\t\t\t\tif (ex !== lockError) {\n\t\t\t\t\t\t\t\t\thookFailure = { error: ex };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthrow ex;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined;\n\t\t\tconst spawnWithRetry = writesIndex\n\t\t\t\t? () => retryWhileIndexLocked(spawnQueued, cancellation, beforeRetry)\n\t\t\t\t: isConfigCommand(args)\n\t\t\t\t\t? () => retryWhileConfigLocked(spawnQueued, cancellation)\n\t\t\t\t\t: spawnQueued;\n\t\t\tvoid (\n\t\t\t\tcheckoutKey != null\n\t\t\t\t\t? this._indexWrites.run(checkoutKey, cancellation, spawnWithRetry)\n\t\t\t\t\t: spawnWithRetry()\n\t\t\t)\n\t\t\t\t.then(deferred.fulfill, (e: unknown) => deferred.cancel(e instanceof Error ? e : new Error(String(e))))\n\t\t\t\t.finally(() => {\n\t\t\t\t\t// A clear may have dropped this run and a later identical call registered its own under the key\n\t\t\t\t\tif (this.pendingCommands.get(cacheKey)?.promise === deferred.promise) {\n\t\t\t\t\t\tthis.pendingCommands.delete(cacheKey);\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch(() => {});\n\t\t} else {\n\t\t\twaiting = true;\n\t\t\tLogger.trace(`${formatLoggableScopeBlock('GIT')} ${gitCommand} \\u00b7 awaiting existing call...`);\n\t\t}\n\n\t\t// Placed HERE, not at the top of the method — every path from this point flows through the\n\t\t// `finally` below, so the active count can't leak if setup (e.g. locating git) throws.\n\t\tthis.beginActiveCommand();\n\n\t\tlet exception: Error | undefined;\n\t\tlet result;\n\t\ttry {\n\t\t\tresult = await promise;\n\t\t\t// A normal `runSpawn` only resolves on a clean exit — `code !== 0 || signal` rejects — but the\n\t\t\t// `exitCodeOnly` overload resolves unconditionally, INCLUDING for a signalled run (no code, partial\n\t\t\t// or absent stdout). Coercing that to `0` would report a killed command as a clean success, so\n\t\t\t// classify it as the failure it is.\n\t\t\tif (result.exitCode == null) {\n\t\t\t\t// SIGTERM groups with cancellations here exactly as it does on the reject path — `failed`/`signal`\n\t\t\t\t// is for every OTHER signal. Only `exitCodeOnly` reaches this: a native spawn `timeout` fires\n\t\t\t\t// `close(null, 'SIGTERM')` with no `error` event, so it resolves instead of rejecting (a caller\n\t\t\t\t// abort never does — `'error'` rejects first). Throwing hands it to the catch below, which owns\n\t\t\t\t// the ABORTED log and the `onAborted` hook — neither of which a branch here would fire.\n\t\t\t\tif (result.signal === 'SIGTERM') {\n\t\t\t\t\tthrow new CancelledRunError(\n\t\t\t\t\t\tgitCommand,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tresult.signal,\n\t\t\t\t\t\tresult.killed ? 'timeout' : 'unknown',\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tstdout: result.stdout,\n\t\t\t\t\tstderr: result.stderr,\n\t\t\t\t\tcompletion: {\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\treason: result.signal != null ? 'signal' : 'unstarted',\n\t\t\t\t\t\terror: new Error(\n\t\t\t\t\t\t\t`Command terminated without an exit code${result.signal != null ? ` (${result.signal})` : ''}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tstdout: result.stdout,\n\t\t\t\tstderr: result.stderr,\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\tcompletion: { status: 'exited', code: result.exitCode },\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (hookFailure != null) {\n\t\t\t\texception =\n\t\t\t\t\thookFailure.error instanceof Error ? hookFailure.error : new Error(String(hookFailure.error));\n\t\t\t\tthrow hookFailure.error;\n\t\t\t}\n\n\t\t\tif (expectedExitCodes?.length && ex instanceof RunError && !(ex instanceof CancelledRunError)) {\n\t\t\t\tconst code = toExitCode(ex.code);\n\t\t\t\tif (code != null && expectedExitCodes.includes(code)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstdout: ex.stdout,\n\t\t\t\t\t\tstderr: ex.stderr,\n\t\t\t\t\t\texitCode: code,\n\t\t\t\t\t\tcompletion: { status: 'exited', code: code },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet cancellationReason: GitRunCancellation = 'unknown';\n\t\t\tif (ex instanceof CancelledRunError) {\n\t\t\t\tconst duration = getDurationMilliseconds(start);\n\t\t\t\tconst timeout = runOpts.timeout ?? 0;\n\t\t\t\tcancellationReason =\n\t\t\t\t\tex.reason !== 'unknown' ? ex.reason : cancellation?.aborted ? 'aborted' : 'unknown';\n\t\t\t\tconst reason = cancellationReason === 'aborted' ? 'cancellation' : cancellationReason;\n\n\t\t\t\t// A stalled event loop can leave a command looking timed out when it merely never got its exit\n\t\t\t\t// event delivered in time \\u2014 surface the same signal here so it isn't misread as a real timeout.\n\t\t\t\tconst loopDelayAnnotation = this.formatEventLoopDelayAnnotation(startEpochMs);\n\t\t\t\tconst loopDelayText = loopDelayAnnotation != null ? ` \\u00b7 ${loopDelayAnnotation}` : '';\n\n\t\t\t\tLogger.warn(\n\t\t\t\t\t`${formatLoggableScopeBlock('GIT')} ${gitCommand} \\u00b7 ABORTED after ${duration}ms (${reason})${loopDelayText}`,\n\t\t\t\t);\n\t\t\t\tthis.options.hooks?.onAborted?.({\n\t\t\t\t\toperation: gitCommand,\n\t\t\t\t\treason: reason,\n\t\t\t\t\tduration: duration,\n\t\t\t\t\ttimeout: timeout,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (errorHandling === 'ignore') {\n\t\t\t\tif (ex instanceof RunError) {\n\t\t\t\t\tconst code = toExitCode(ex.code);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstdout: ex.stdout,\n\t\t\t\t\t\tstderr: ex.stderr,\n\t\t\t\t\t\t...(code != null ? { exitCode: code } : {}),\n\t\t\t\t\t\tcompletion:\n\t\t\t\t\t\t\tex instanceof CancelledRunError\n\t\t\t\t\t\t\t\t? { status: 'cancelled', reason: cancellationReason, error: ex }\n\t\t\t\t\t\t\t\t: code != null\n\t\t\t\t\t\t\t\t\t? { status: 'exited', code: code }\n\t\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\t\t\t\t\t\t// A signal means it ran and was killed (partial `stdout` may exist);\n\t\t\t\t\t\t\t\t\t\t\t// no signal and no numeric code means it never got that far.\n\t\t\t\t\t\t\t\t\t\t\treason: ex.signal != null ? 'signal' : 'unstarted',\n\t\t\t\t\t\t\t\t\t\t\terror: ex,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// No cancellation branch here: `CancelledRunError extends RunError`, so reaching this at all\n\t\t\t\t// proves `ex` is neither.\n\t\t\t\treturn {\n\t\t\t\t\tstdout: '',\n\t\t\t\t\tstderr: undefined,\n\t\t\t\t\tcompletion: {\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\t// No `RunError` means no process was ever spawned — a queue rejection or a\n\t\t\t\t\t\t// failure before `spawn` returned. (Not an untrusted workspace: `run` refuses\n\t\t\t\t\t\t// those up front, so they never reach this catch.)\n\t\t\t\t\t\treason: 'unstarted',\n\t\t\t\t\t\terror: ex instanceof Error ? ex : new Error(String(ex)),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// The queue refuses an already-aborted signal, or drops a command aborted while it waited, by\n\t\t\t// rejecting with the signal's own reason; that never reached a spawn, so it isn't a `RunError`,\n\t\t\t// and wrapping it as a `GitError` would make a cancellation read as the command failing.\n\t\t\tif (ex instanceof CancelledRunError) {\n\t\t\t\texception = new CancellationError(ex, cancellationReason);\n\t\t\t} else if (!(ex instanceof RunError) && cancellation?.aborted) {\n\t\t\t\texception = new CancellationError(ex instanceof Error ? ex : undefined, 'aborted');\n\t\t\t} else {\n\t\t\t\texception = new GitError(ex);\n\t\t\t}\n\t\t\tif (errorHandling === 'throw') throw exception;\n\n\t\t\t// Rethrows unless the message matches a `GitWarnings` pattern, in which case it logs and returns the\n\t\t\t// key that matched. Capture the error first — `exception` is cleared to keep it out of the `finally`\n\t\t\t// log, but the result still needs to carry it.\n\t\t\tconst swallowed = exception;\n\t\t\tconst warning = defaultExceptionHandler(exception, options.cwd, start);\n\t\t\texception = undefined;\n\t\t\t// The command did NOT produce this empty stdout — a warning was swallowed. Say so, or the caller\n\t\t\t// can't tell a genuinely empty answer (`noCommits`) from a read that never happened\n\t\t\t// (`notARepository`).\n\t\t\t//\n\t\t\t// The process DID exit though (a warning is only ever swallowed for a non-zero exit), so report the\n\t\t\t// code.\n\t\t\tconst code = toExitCode(swallowed instanceof GitError ? swallowed.exitCode : undefined);\n\n\t\t\t// No `stderr`: it belongs to the error here. The top-level field is the channel for runs that\n\t\t\t// completed WITHOUT one (`exited` carries no error, so a successful command's stderr has nowhere\n\t\t\t// else to go) — a swallowed warning always has a `GitError`, and it carries the stderr. Reading\n\t\t\t// `result?.stderr` would be dead anyway: `result` is only assigned on the non-throwing path.\n\t\t\treturn {\n\t\t\t\tstdout: '',\n\t\t\t\t...(code != null ? { exitCode: code } : {}),\n\t\t\t\tcompletion: { status: 'warned', warning: warning, error: swallowed },\n\t\t\t};\n\t\t} finally {\n\t\t\tthis.logGitCommandComplete(\n\t\t\t\tgitCommand,\n\t\t\t\texception,\n\t\t\t\tgetDurationMilliseconds(start),\n\t\t\t\t// 0 when the subprocess never started — there is no execution time to attribute. Also 0 for\n\t\t\t\t// GitLens's own maintenance work, which is slow by design and must not read as repo slowness.\n\t\t\t\texecStart == null || selfMaintenance ? 0 : getDurationMilliseconds(execStart),\n\t\t\t\twaiting,\n\t\t\t\toptions.cwd,\n\t\t\t\targs,\n\t\t\t\tslownessCategory,\n\t\t\t\tstartEpochMs,\n\t\t\t);\n\t\t\tthis.endActiveCommand();\n\t\t}\n\t}\n\n\tasync *stream(options: GitSpawnOptions, ...args: readonly (string | undefined)[]): AsyncGenerator<string> {\n\t\tif (this.options.isTrusted?.() === false) throw new WorkspaceUntrustedError();\n\n\t\tconst start = hrtime();\n\t\tconst startEpochMs = Date.now();\n\t\tconst streamId = uniqueCounterForStream.next();\n\n\t\tconst { configs, stdin, stdinEncoding, cancellation, encoding, slownessCategory, ...opts } = options;\n\t\tconst runArgs = args.filter(a => a != null);\n\n\t\tconst spawnOpts: SpawnOptions = {\n\t\t\t// Unless provided, ignore stdin and leave default streams for stdout and stderr\n\t\t\tstdio: [stdin ? 'pipe' : 'ignore', null, null],\n\t\t\t...opts,\n\t\t\tsignal: cancellation,\n\t\t\tenv: this.buildEnv(options.env),\n\t\t};\n\n\t\tconst gitCommand = `(spawn) [${spawnOpts.cwd as string}] git ${runArgs.join(' ')}`;\n\n\t\t// Fixes https://github.com/gitkraken/vscode-gitlens/issues/73 & https://github.com/gitkraken/vscode-gitlens/issues/161\n\t\t// See https://stackoverflow.com/questions/4144417/how-to-handle-asian-characters-in-file-names-in-git-on-os-x\n\t\trunArgs.unshift('-c', 'core.quotepath=false', '-c', 'color.ui=false', ...(configs ?? emptyArray));\n\n\t\tif (process.platform === 'win32') {\n\t\t\trunArgs.unshift('-c', 'core.longpaths=true');\n\t\t}\n\n\t\tconst command = await this.path();\n\t\tconst proc = spawn(command, runArgs, spawnOpts);\n\n\t\tif (stdin) {\n\t\t\tendStdin(proc.stdin, stdin, stdinEncoding);\n\t\t}\n\n\t\tlet exception: Error | undefined;\n\n\t\tconst promise = new Promise<void>((resolve, reject) => {\n\t\t\tconst stderrChunks: string[] = [];\n\t\t\tif (proc.stderr) {\n\t\t\t\tproc.stderr?.setEncoding('utf8');\n\t\t\t\tproc.stderr.on('data', chunk => stderrChunks.push(chunk));\n\t\t\t}\n\n\t\t\tproc.once('error', ex => {\n\t\t\t\tif (ex?.name === 'AbortError') return;\n\n\t\t\t\texception = new GitError(ex);\n\t\t\t});\n\t\t\tproc.once('close', (code, signal) => {\n\t\t\t\tif (code === 0) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (signal === 'SIGTERM') {\n\t\t\t\t\t// If the caller aborted, just resolve\n\t\t\t\t\tif (cancellation?.aborted) {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew CancelledRunError(proc.spawnargs.join(' '), true, code ?? undefined, signal, 'unknown'),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If the caller didn't read the complete stream, just resolve\n\t\t\t\tif (\n\t\t\t\t\tsignal === 'SIGPIPE' ||\n\t\t\t\t\tcode === 141 /* SIGPIPE */ ||\n\t\t\t\t\t(code === 128 && stderrChunks.some(c => c.includes('Connection reset by peer')))\n\t\t\t\t) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst stderr = stderrChunks.join('').trim();\n\t\t\t\treject(\n\t\t\t\t\tnew GitError(\n\t\t\t\t\t\tnew RunError(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmessage: `Error (${code}): ${stderr || 'Unknown'}`,\n\t\t\t\t\t\t\t\tcmd: proc.spawnargs.join(' '),\n\t\t\t\t\t\t\t\tkilled: proc.killed,\n\t\t\t\t\t\t\t\tcode: proc.exitCode,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\tstderr,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\n\t\tlet cleanedUp = false;\n\t\tconst cleanup = () => {\n\t\t\tif (cleanedUp) return;\n\n\t\t\tcleanedUp = true;\n\n\t\t\ttry {\n\t\t\t\tproc.removeAllListeners();\n\t\t\t} catch {}\n\t\t\t// Streaming spawns directly, with no GitQueue wait to exclude. It isn't pure subprocess time\n\t\t\t// either — the generator applies backpressure, so a slow consumer stalls the pipe and inflates\n\t\t\t// this — but there's no separate signal to measure here.\n\t\t\tconst duration = getDurationMilliseconds(start);\n\t\t\tthis.logGitCommandComplete(\n\t\t\t\tgitCommand,\n\t\t\t\texception,\n\t\t\t\tduration,\n\t\t\t\tduration,\n\t\t\t\tfalse,\n\t\t\t\tspawnOpts.cwd as string | undefined,\n\t\t\t\trunArgs,\n\t\t\t\tslownessCategory,\n\t\t\t\tstartEpochMs,\n\t\t\t\tstreamId,\n\t\t\t);\n\t\t\tthis.endActiveCommand();\n\t\t};\n\n\t\t// Placed HERE, not at the top of the method — every path from this point reaches `cleanup()`\n\t\t// (the `finally` below, or the generator-close return), so the active count can't leak if\n\t\t// setup (e.g. locating git) throws.\n\t\tthis.beginActiveCommand();\n\n\t\ttry {\n\t\t\tthis.logGitCommandStart(gitCommand, streamId);\n\n\t\t\ttry {\n\t\t\t\tif (proc.stdout) {\n\t\t\t\t\tconst enc = encoding ?? 'utf8';\n\t\t\t\t\tif (enc === 'utf8' || enc === 'binary' || enc === 'buffer') {\n\t\t\t\t\t\tproc.stdout.setEncoding(enc === 'buffer' ? 'utf8' : enc);\n\t\t\t\t\t\tfor await (const chunk of proc.stdout) {\n\t\t\t\t\t\t\tyield chunk;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Non-UTF-8 encoding: collect raw buffers and decode at the end.\n\t\t\t\t\t\t// Streaming decode is unsafe because chunk boundaries can split\n\t\t\t\t\t\t// multi-byte sequences in the source encoding.\n\t\t\t\t\t\tconst decode = this.options.decode;\n\t\t\t\t\t\tif (decode == null) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Non-UTF-8 encoding '${enc}' requested for stream but no decode function configured`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst buffers: Buffer[] = [];\n\t\t\t\t\t\tfor await (const chunk of proc.stdout) {\n\t\t\t\t\t\t\tbuffers.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield await decode(Buffer.concat(buffers), { encoding: enc });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\t// This await MUST be in this inner finally block to ensure the child process close event completes\n\t\t\t\t// before we call removeAllListeners() in the outer finally. When consumers break early from the\n\t\t\t\t// async generator (e.g., reading only the first chunk), the git process receives SIGPIPE and triggers\n\t\t\t\t// the close handler asynchronously. Without awaiting here, removeAllListeners() would execute before\n\t\t\t\t// the close handler finishes, causing a race condition and potential resource leaks.\n\t\t\t\tawait promise;\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\texception = ex;\n\t\t\tthrow ex;\n\t\t} finally {\n\t\t\tcleanup();\n\t\t}\n\n\t\t// Ensure cleanup happens immediately when the generator is explicitly closed (e.g., via break or return)\n\t\t// This is called by JavaScript when the generator is abandoned, ensuring logGitCommand is called\n\t\t// synchronously rather than waiting for garbage collection.\n\t\t// oxlint-disable-next-line typescript/no-meaningless-void-operator\n\t\treturn void cleanup();\n\t}\n\n\t/**\n\t * Resolves the git dir (and common dir, for a linked worktree) of `cwd`.\n\t *\n\t * Resolves `undefined` when `cwd` is not in a repository: git reported so, or `cwd` doesn't exist. Any\n\t * other failure (unsafe ownership, a timeout or cancellation, a missing git binary) rejects.\n\t */\n\tasync rev_parse__git_dir(cwd: string): Promise<{ path: string; commonPath?: string } | undefined> {\n\t\tlet result;\n\t\ttry {\n\t\t\tresult = await this.run({ cwd: cwd, errors: 'throw' }, 'rev-parse', '--git-dir', '--git-common-dir');\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof GitError && GitWarnings.notARepository.test(ex.stderr ?? '')) return undefined;\n\t\t\t// A missing `cwd` fails the spawn itself (ENOENT) before git can say anything about it\n\t\t\tif (!(await fsExists(cwd))) return undefined;\n\t\t\tthrow ex;\n\t\t}\n\t\tif (!result.stdout) return undefined;\n\n\t\t// Keep trailing spaces which are part of the directory name\n\t\tlet [dotGitPath, commonDotGitPath] = result.stdout.split('\\n').map(r => r.trimStart());\n\n\t\t// Make sure to normalize: https://github.com/git-for-windows/git/issues/2478\n\n\t\tif (!isAbsolute(dotGitPath)) {\n\t\t\tdotGitPath = joinPaths(cwd, dotGitPath);\n\t\t}\n\t\tdotGitPath = normalizePath(dotGitPath);\n\n\t\tif (commonDotGitPath) {\n\t\t\tif (!isAbsolute(commonDotGitPath)) {\n\t\t\t\tcommonDotGitPath = joinPaths(cwd, commonDotGitPath);\n\t\t\t}\n\t\t\tcommonDotGitPath = normalizePath(commonDotGitPath);\n\n\t\t\treturn { path: dotGitPath, commonPath: commonDotGitPath !== dotGitPath ? commonDotGitPath : undefined };\n\t\t}\n\n\t\treturn { path: dotGitPath };\n\t}\n\n\tasync rev_parse__show_toplevel(cwd: string): Promise<[safe: true, repoPath: string] | [safe: false] | []> {\n\t\tlet result;\n\n\t\tif (this.options.isTrusted?.() === false) {\n\t\t\t// Check if the folder is a bare clone: if it has a file named HEAD && `rev-parse --show-cdup` is empty\n\t\t\tif (await fsExists(joinPaths(cwd, 'HEAD'))) {\n\t\t\t\ttry {\n\t\t\t\t\tresult = await this.run(\n\t\t\t\t\t\t{ cwd: cwd, errors: 'throw', configs: ['-C', cwd] },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--show-cdup',\n\t\t\t\t\t);\n\t\t\t\t\tif (!result.stdout.trim()) {\n\t\t\t\t\t\tLogger.warn(`Skipping (untrusted workspace); bare clone repository detected in '${cwd}'`);\n\t\t\t\t\t\treturn emptyArray as [];\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// If this throws, we should be good to open the repo (e.g. HEAD doesn't exist)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tresult = await this.run({ cwd: cwd, errors: 'throw' }, 'rev-parse', '--show-toplevel');\n\t\t\t// Make sure to normalize: https://github.com/git-for-windows/git/issues/2478\n\t\t\t// Keep trailing spaces which are part of the directory name\n\t\t\treturn !result.stdout\n\t\t\t\t? (emptyArray as [])\n\t\t\t\t: [true, normalizePath(result.stdout.trimStart().replace(trailingNewlineRegex, ''))];\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof WorkspaceUntrustedError) return emptyArray as [];\n\t\t\tif (!(ex instanceof GitError)) throw ex;\n\n\t\t\tconst unsafeMatch = GitErrors.unsafeRepository.exec(ex.stderr ?? '');\n\t\t\tif (unsafeMatch != null) {\n\t\t\t\tLogger.warn(\n\t\t\t\t\t`Skipping; unsafe repository detected in '${unsafeMatch[1] || unsafeMatch[2]}'; run '${\n\t\t\t\t\t\tunsafeMatch[3]\n\t\t\t\t\t}' to allow it`,\n\t\t\t\t);\n\t\t\t\treturn [false];\n\t\t\t}\n\n\t\t\tconst inDotGit = GitWarnings.mustRunInWorkTree.test(ex.stderr ?? '');\n\t\t\t// Check if we are in a bare clone\n\t\t\tif (inDotGit && this.options.isTrusted?.() !== false) {\n\t\t\t\tresult = await this.run({ cwd: cwd, errors: 'ignore' }, 'rev-parse', '--is-bare-repository');\n\t\t\t\tif (result.stdout.trim() === 'true') {\n\t\t\t\t\tconst result = await this.rev_parse__git_dir(cwd).catch(() => undefined);\n\t\t\t\t\tconst repoPath = result?.commonPath ?? result?.path;\n\t\t\t\t\tif (repoPath?.length) return [true, repoPath];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (inDotGit || (ex.original as NodeJS.ErrnoException)?.code === 'ENOENT') {\n\t\t\t\t// If the `cwd` doesn't exist, walk backward to see if any parent folder exists\n\t\t\t\tlet exists = inDotGit ? false : await fsExists(cwd);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tconst parent = dirname(cwd);\n\t\t\t\t\t\tif (parent === cwd || parent.length === 0) return emptyArray as [];\n\n\t\t\t\t\t\tcwd = parent;\n\t\t\t\t\t\texists = await fsExists(cwd);\n\t\t\t\t\t} while (!exists);\n\n\t\t\t\t\treturn this.rev_parse__show_toplevel(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn emptyArray as [];\n\t\t}\n\t}\n\n\tprivate logGitCommandStart(command: string, id: number): void {\n\t\tLogger.info(`${formatLoggableScopeBlock(`GIT:\\u2192${id}`)} ${command} \\u00b7 starting...`);\n\t\tthis.options.logger?.info(`${formatLoggableScopeBlock(`\\u2192${id}`, '')} ${command} \\u2022 starting...`);\n\t}\n\n\tprivate logGitCommandComplete(\n\t\tcommand: string,\n\t\tex: Error | undefined,\n\t\tduration: number,\n\t\t/** Subprocess-only duration (excludes GitQueue wait); 0 when it never ran. */\n\t\texecDuration: number,\n\t\twaiting: boolean,\n\t\tcwd: string | undefined,\n\t\targs: readonly (string | undefined)[] | undefined,\n\t\tslownessCategory: GitHealthSlownessCategory | undefined,\n\t\tstartEpochMs: number,\n\t\tid?: number,\n\t): void {\n\t\tconst slow = duration > slowCallWarningThreshold;\n\n\t\tconst annotations: string[] = [];\n\t\tif (slow) {\n\t\t\tannotations.push('slow');\n\t\t}\n\n\t\tif (waiting) {\n\t\t\tannotations.push('waiting');\n\t\t} else if (execDuration > 0) {\n\t\t\t// Dedup riders (`waiting`) and never-started commands (`execDuration === 0`) have no queue\n\t\t\t// wait of their own to report.\n\t\t\tconst queued = duration - execDuration;\n\t\t\tif (queued >= queueWaitAnnotationThreshold) {\n\t\t\t\tannotations.push(`queued ${queued}ms`);\n\t\t\t}\n\t\t}\n\n\t\t// `hrtime` spans don't correlate with the monitor's wall-clock ring, so the lookup needs the\n\t\t// command's own start time — only worth measuring once the command is already slow. Whole-call\n\t\t// window on purpose: the annotation explains the TOTAL duration this log line reports.\n\t\tif (slow) {\n\t\t\tconst loopDelayAnnotation = this.formatEventLoopDelayAnnotation(startEpochMs);\n\t\t\tif (loopDelayAnnotation != null) {\n\t\t\t\tannotations.push(loopDelayAnnotation);\n\t\t\t}\n\t\t}\n\n\t\tconst status = annotations.length > 0 ? ` (${annotations.join(', ')})` : '';\n\n\t\t// The health signal is gated on the SUBPROCESS time, not the total: time spent queued behind other\n\t\t// git work is congestion, not repository slowness, and counting it would let a busy queue (including\n\t\t// our own background maintenance holding slots) manufacture the evidence that recommends more\n\t\t// maintenance. Logging keeps the total — the wait is exactly what you want to see when diagnosing.\n\t\t//\n\t\t// A deduplicated rider (`waiting`) shares the executed command's duration, so counting it too\n\t\t// would double-count a single slow subprocess — fire only for the command that actually ran.\n\t\t// Guarded: this runs inside the command's `finally`, so a hook throw would otherwise replace\n\t\t// the command's real result/error for the caller.\n\t\tif (execDuration > slowCallWarningThreshold && !waiting) {\n\t\t\t// Scoped to the SUBPROCESS window, matching the hook's `duration`: `duration - execDuration`\n\t\t\t// is the queue wait, and a stall while queued is congestion, not the command's own signal\n\t\t\t// (same reasoning as the `execDuration` gate above). The subprocess ends at log time, so it\n\t\t\t// started `duration - execDuration` after the call did.\n\t\t\tconst execEventLoopDelay = this._eventLoopMonitor.maxDelaySince(startEpochMs + (duration - execDuration));\n\t\t\ttry {\n\t\t\t\tthis.options.hooks?.onSlowCommand?.({\n\t\t\t\t\toperation: args != null ? getPrimaryGitCommand(args) : undefined,\n\t\t\t\t\tcwd: cwd,\n\t\t\t\t\tduration: execDuration,\n\t\t\t\t\teventLoopDelay: execEventLoopDelay,\n\t\t\t\t\tslownessCategory: slownessCategory,\n\t\t\t\t});\n\t\t\t} catch {}\n\t\t}\n\n\t\tif (ex != null) {\n\t\t\tLogger.error(\n\t\t\t\tundefined,\n\t\t\t\t`${formatLoggableScopeBlock(id ? `GIT:\\u2190${id}` : 'GIT')} ${command} \\u00b7 ${\n\t\t\t\t\tisCancellationError(ex)\n\t\t\t\t\t\t? 'cancelled'\n\t\t\t\t\t\t: (ex.message || String(ex) || '')\n\t\t\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t\t\t.replace(/fatal:\\s*/g, '')\n\t\t\t\t\t\t\t\t.replace(/\\r?\\n|\\r/g, ' \\u00b7 ')\n\t\t\t\t} [${duration}ms]${status}`,\n\t\t\t);\n\t\t} else if (slow) {\n\t\t\tLogger.warn(\n\t\t\t\t`${formatLoggableScopeBlock(id ? `GIT:\\u2190${id}` : 'GIT', `*${duration}ms`)} ${command} [*${duration}ms]${status}`,\n\t\t\t);\n\t\t} else {\n\t\t\tLogger.info(\n\t\t\t\t`${formatLoggableScopeBlock(id ? `GIT:\\u2190${id}` : 'GIT', `${duration}ms`)} ${command} [${duration}ms]${status}`,\n\t\t\t);\n\t\t}\n\n\t\tconst logMessage = `${formatLoggableScopeBlock(\n\t\t\t`${id ? `\\u2190${id}` : ''}${slow ? '*' : ''}`,\n\t\t\t`${duration}ms`,\n\t\t)} ${command}${status}`;\n\t\tif (ex != null) {\n\t\t\tthis.options.logger?.error(`${logMessage} \\u2022 FAILED\\n${String(ex)}`);\n\t\t} else {\n\t\t\tthis.options.logger?.info(`${logMessage} \\u2022 completed`);\n\t\t}\n\t}\n}\n\n/**\n * The exit code in a run error's `code`, or `undefined` when the process never exited normally: a numeric string\n * is a real exit code, but an errno (`'ENOENT'`) means the spawn itself failed, and `undefined` means it was killed.\n */\nfunction toExitCode(code: number | string | undefined): number | undefined {\n\tconst exitCode = typeof code === 'number' ? code : code != null ? parseInt(code, 10) : NaN;\n\treturn Number.isInteger(exitCode) ? exitCode : undefined;\n}\n\n/**\n * Swallows an error whose message matches a known-benign {@link GitWarnings} pattern, returning WHICH one\n * matched so the caller can record it — the distinction matters, since `noCommits` is a real answer while\n * `notARepository` is a failed read. Rethrows anything else.\n */\nexport function defaultExceptionHandler(\n\tex: Error,\n\tcwd: string | undefined,\n\tstart?: [number, number],\n): GitWarningKey | undefined {\n\tif (isCancellationError(ex)) throw ex;\n\n\tconst msg = ex.message || ex.toString();\n\tif (msg) {\n\t\tconst warning = getGitWarning(ex);\n\t\tif (warning != null) {\n\t\t\tconst duration = start !== undefined ? ` [${getDurationMilliseconds(start)}ms]` : '';\n\t\t\tLogger.warn(\n\t\t\t\t`[${cwd}] Git ${msg\n\t\t\t\t\t.trim()\n\t\t\t\t\t.replace(/fatal:\\s*/g, '')\n\t\t\t\t\t.replace(/\\r?\\n|\\r/g, ' \\u00b7 ')}${duration}`,\n\t\t\t);\n\t\t\treturn warning;\n\t\t}\n\n\t\tconst match = GitErrors.badRevision.exec(msg);\n\t\tif (match != null) {\n\t\t\tconst [, ref] = match;\n\n\t\t\t// Since looking up a ref with ^3 (e.g. looking for untracked files in a stash) can error on some versions of git just ignore it\n\t\t\t// Swallowed, but it matched no `GitWarnings` entry — `undefined` records \"unclassified\", which\n\t\t\t// callers must treat as \"not a real answer\" exactly like any warning they don't whitelist.\n\t\t\tif (ref?.endsWith('^3')) return undefined;\n\t\t}\n\t}\n\n\tthrow ex;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"git.js","names":["resolvePath","isAbsolute","dirname"],"sources":["../../../../git-cli/src/exec/git.ts"],"sourcesContent":["import type { SpawnOptions } from 'child_process';\nimport { spawn } from 'child_process';\nimport { resolve as resolvePath } from 'path';\nimport * as process from 'process';\nimport type {\n\tBranchErrorReason,\n\tCheckoutErrorReason,\n\tCherryPickErrorReason,\n\tCommitErrorReason,\n\tFetchErrorReason,\n\tGitCommandError,\n\tGitSearchErrorReason,\n\tGitWarningKey,\n\tMergeErrorReason,\n\tPausedOperationAbortErrorReason,\n\tPausedOperationContinueErrorReason,\n\tPullErrorReason,\n\tPushErrorReason,\n\tRebaseErrorReason,\n\tReferenceUpdateErrorReason,\n\tResetErrorReason,\n\tRevertErrorReason,\n\tShowErrorReason,\n\tSigningErrorReason,\n\tStashApplyErrorReason,\n\tStashPushErrorReason,\n\tTagErrorReason,\n\tWorktreeCreateErrorReason,\n\tWorktreeDeleteErrorReason,\n} from '@gitlens/git/errors.js';\nimport { getGitWarning, GitWarnings, WorkspaceUntrustedError } from '@gitlens/git/errors.js';\nimport type { GitHealthSlownessCategory } from '@gitlens/git/gitHealth.js';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\nimport type { SigningFormat } from '@gitlens/git/models/signature.js';\nimport type { GitRunCancellation } from '@gitlens/git/run.types.js';\nimport { CancellationError, getAbortSignalId, isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { getScopedCounter } from '@gitlens/utils/counter.js';\nimport { getDurationMilliseconds, hrtime } from '@gitlens/utils/hrtime.js';\nimport { chunkByStringLength } from '@gitlens/utils/iterable.js';\nimport type { LogChannel } from '@gitlens/utils/logger.js';\nimport { Logger } from '@gitlens/utils/logger.js';\nimport { formatLoggableScopeBlock } from '@gitlens/utils/logger.scoped.js';\nimport { arePathsEqual, dirname, isAbsolute, isDescendant, joinPaths, normalizePath } from '@gitlens/utils/path.js';\nimport { defer } from '@gitlens/utils/promise.js';\nimport type { Mutable } from '@gitlens/utils/types.js';\nimport { compare, fromString } from '@gitlens/utils/version.js';\nimport { getChangesForCommand, leadingCommand } from './commandClassifier.js';\nimport { EventLoopMonitor } from './eventLoopMonitor.js';\nimport { CancelledRunError, RunError } from './exec.errors.js';\nimport type { RunOptions, RunResult } from './exec.js';\nimport { endStdin, fsExists, runSpawn } from './exec.js';\nimport type { GitCommandPriority, GitResult, GitRunOptions, GitSpawnOptions } from './exec.types.js';\nimport type { FilteredGitFeatures, GitFeatureOrPrefix, GitFeatures } from './features.js';\nimport { gitFeaturesByVersion } from './features.js';\nimport type { GitQueueConfig } from './gitQueue.js';\nimport { getPrimaryGitCommand, GitQueue, inferGitCommandPriority } from './gitQueue.js';\nimport {\n\tisConfigCommand,\n\tisIndexWriteCommand,\n\tKeyedSequencer,\n\tretryWhileConfigLocked,\n\tretryWhileIndexLocked,\n\ttoExitCode,\n} from './indexLock.js';\nimport type { GitLocation } from './locator.js';\n\nexport const slowCallWarningThreshold = 2000;\nexport type GitFeatureUnsupportedMessage = (requiredVersion: string, installedVersion: string) => string;\n/** Below this, a queue-wait annotation isn't worth adding to the log line. */\nconst queueWaitAnnotationThreshold = 100;\n/** Below this, a measured event-loop stall isn't worth annotating — see {@link EventLoopMonitor}. */\nconst eventLoopDelayAnnotationThreshold = 500;\nexport const maxGitCliLength = 30000;\n\n/** Rejections from a host's `beforeIndexLockRetry` — typed writes rethrow these as thrown instead of mapping them to their own error. */\nconst runHookFailures = new WeakSet<object>();\n\nexport function isRunHookFailure(ex: unknown): boolean {\n\treturn typeof ex === 'object' && ex != null && runHookFailures.has(ex);\n}\n\n/**\n * Splits `paths` into `:(literal)` pathspec batches that each fit the command-line length limit after `prefix`, so a\n * folder named like a glob (`[id]/`) doesn't match its siblings.\n */\nexport function batchLiteralPathspecs(\n\tpaths: readonly string[],\n\tprefix: readonly string[],\n): Iterable<readonly string[]> {\n\t// Reserve the prefix and a per-arg overhead (separator + possible quoting), so neither a run of long paths nor\n\t// many short ones can push a batch past the OS limit\n\tconst perArgOverhead = 3;\n\tconst prefixLength = [...prefix, '--'].reduce((sum, arg) => sum + arg.length + perArgOverhead, 0);\n\treturn chunkByStringLength(\n\t\tpaths.map(p => `:(literal)${p}`),\n\t\tmaxGitCliLength - prefixLength,\n\t\tperArgOverhead,\n\t);\n}\n\nexport const gitConfigsBranch = ['-c', 'color.branch=false'] as const;\nexport const gitConfigsDiff = ['-c', 'color.diff=false', '-c', 'diff.mnemonicPrefix=false'] as const;\nexport const gitConfigsLog = ['-c', 'log.showSignature=false'] as const;\nexport const gitConfigsLogWithFiles = ['-c', 'log.showSignature=false', '-c', 'diff.renameLimit=0'] as const;\nexport const gitConfigsLogWithSignatures = ['-c', 'log.showSignature=true'] as const;\nexport const gitConfigsPull = ['-c', 'merge.autoStash=true', '-c', 'rebase.autoStash=true'] as const;\nexport const gitConfigsStatus = ['-c', 'color.status=false'] as const;\n\nexport const GitErrors = {\n\talreadyCheckedOut: /already checked out/i,\n\talreadyExists: /already exists/i,\n\tambiguousArgument: /fatal:\\s*ambiguous argument ['\"](.+?)['\"]: unknown revision or path not in the working tree/i,\n\tbadObject: /fatal:\\s*bad object (.*?)/i,\n\tbadRevision: /bad revision '(.*?)'/i,\n\tbranchAlreadyExists: /fatal:\\s*A branch named '.+?' already exists/i,\n\tnotFullyMerged: /error:\\s*The branch '.+?' is not fully merged/i,\n\tcantLockRef: /cannot lock ref|unable to update local ref/i,\n\tchangesWouldBeOverwritten:\n\t\t/Your local changes to the following files would be overwritten|Your local changes would be overwritten|overwritten by checkout/i,\n\tcherryPickAborted: /cherry-pick.*aborted/i,\n\tcherryPickInProgress: /cherry-pick is already in progress|You have not concluded your cherry-pick/i,\n\tcommitChangesFirst: /Please, commit your changes before you can/i,\n\tconflict: /^CONFLICT \\([^)]+\\): \\b/m,\n\tdetachedHead: /You are in 'detached HEAD' state/i,\n\tentryNotUpToDate: /error:\\s*Entry ['\"].+['\"] not uptodate\\. Cannot merge\\./i,\n\tfailedToDeleteDirectoryNotEmpty: /failed to delete '(.*?)': Directory not empty/i,\n\tgpgNotFound: /gpg:?\\s*(?:command\\s+)?not found|'gpg' is not recognized as|cannot run gpg:/i,\n\tgpgSignFailed: /^error:\\s*gpg failed to sign the data/im,\n\tinvalidName: /fatal:\\s*'.+?' is not a valid branch name/i,\n\tinvalidLineCount: /file .+? has only (\\d+) lines/i,\n\tinvalidObjectName: /invalid object name: (.*)\\s/i,\n\tinvalidObjectNameList: /could not open object name list: (.*)\\s/i,\n\t// Regcomp failure reasons from `-G`/pathspec regex compilation (search); matched without a known\n\t// prefix as a fallback when the reason appears in an unrecognized stderr shape\n\tinvalidSearchPattern:\n\t\t/Unmatched \\( or \\\\\\(|Unmatched \\[|Unmatched \\) or \\\\\\)|Invalid content of \\\\\\{\\\\\\}|Invalid preceding regular expression|Invalid regular expression|Trailing backslash|invalid regex/i,\n\tinvalidTagName: /invalid tag name/i,\n\tmainWorkingTree: /is a main working tree/i,\n\tmergeAborted: /merge.*aborted/i,\n\tmergeInProgress: /^fatal:\\s*You have not concluded your merge/i,\n\tnoFastForward: /\\(non-fast-forward\\)/i,\n\tnoMergeBase: /no merge base/i,\n\tnoRemoteReference: /unable to delete '.+?': remote ref does not exist/i,\n\tnoRemoteRepositorySpecified: /No remote repository specified\\./i,\n\tnoUpstream: /^fatal:\\s*The current branch .* has no upstream branch/i,\n\t// `git pull` (not `push`) on a branch with no upstream — distinct wording from `noUpstream` above\n\tnoTrackingInformation: /There is no tracking information for the current branch/i,\n\tnotAValidObjectName: /Not a valid object name/i,\n\tnotPossibleToFastForward: /Not possible to fast-forward/i,\n\tnotAWorkingTree: /'(.*?)' is not a working tree/i,\n\tnoUserNameConfigured: /Please tell me who you are\\./i,\n\tnothingToCommit: /nothing(?: added)? to commit|no changes added to commit/i,\n\tnoPausedOperation:\n\t\t/no merge (?:in progress|to abort)|no cherry-pick(?: or revert)? in progress|no rebase in progress/i,\n\tpermissionDenied: /Permission.*denied/i,\n\tpreviousOperationEmpty: /The previous (?:cherry-pick|revert) is now empty/i,\n\tproblemWithEditor: /there was a problem with the editor/i,\n\tpushRejected: /^error:\\s*failed to push some refs to\\b/m,\n\tpushRejectedRefDoesNotExists: /error:\\s*unable to delete '(.*?)': remote ref does not exist/m,\n\trebaseAborted: /Nothing to do|rebase.*aborted/i,\n\trebaseInProgress: /It seems that there is already a rebase-(?:merge|apply) directory/i,\n\trebaseMissingTodo: /error:\\s*could not read file .*\\/git-rebase-todo': No such file or directory/,\n\trebaseMultipleBranches: /cannot rebase onto multiple branches/i,\n\trevertAborted: /revert.*aborted/i,\n\trevertInProgress: /^(error: )?(revert|cherry-pick) is already in progress/i,\n\trefAlreadyExists: /cannot lock ref '.*?': reference already exists/i,\n\trefBadName: /refusing to update ref with bad name/i,\n\trefLocked: /fatal:\\s*cannot lock ref ['\"].+['\"]: unable to create file/i,\n\trefNonexistentObject: /trying to write ref '.*?' with nonexistent object/i,\n\trefNotAValidSha: /not a valid (?:old )?SHA1/i,\n\trefUnableToResolve: /cannot lock ref '.*?': unable to resolve reference/i,\n\trefValueMismatch: /cannot lock ref '.*?': is at [0-9a-f]+ but expected/i,\n\tremoteAhead: /rejected because the remote contains work/i,\n\tremoteConnectionFailed: /Could not read from remote repository/i,\n\tremoteRejected: /rejected because the remote contains work/i,\n\tsigningKeyNotAvailable: /secret key not available|no secret key|no signing key/i,\n\tsshNotFound: /ssh-keygen[^\\n]*(?:not found|No such file or directory|is not recognized)/i,\n\tstashConflictingStagedAndUnstagedLines: /Cannot remove worktree changes/i,\n\tstashNothingToSave: /No local changes to save/i,\n\tstashSavedWorkingDirAndIndexState: /Saved working directory and index state/i,\n\ttagAlreadyExists: /tag .* already exists/i,\n\ttagConflict: /! \\[rejected\\].*\\(would clobber existing tag\\)/m,\n\ttagNotFound: /tag .* not found/i,\n\tuncommittedChanges: /contains modified or untracked files/i,\n\tunmergedChanges: /error:\\s*you need to resolve your current index first/i,\n\tunmergedFiles: /is not possible because you have unmerged files|You have unmerged files/i,\n\tunresolvedConflicts:\n\t\t/You must edit all merge conflicts|Resolve all conflicts|^CONFLICT \\(|^Automatic merge failed|could not apply .*/im,\n\tunsafeRepository:\n\t\t/(?:^fatal:\\s*detected dubious ownership in repository at '([^']+)'|unsafe repository \\('([^']+)' is owned by someone else\\))[\\s\\S]*(git config --global --add safe\\.directory [^\\n•]+)/m,\n\tunstagedChanges: /You have unstaged changes/i,\n\t// Matches both variants: with a lock reason (`..., lock reason: <reason>`) and without (`...;`)\n\tworktreeLocked: /fatal:\\s*cannot remove a locked working tree/i,\n\t// Only matches the variant where Git reports a lock reason; the reason is free text, so capture the whole line\n\tworktreeLockedReason: /cannot remove a locked working tree,[ \\t]*lock reason:[ \\t]*(.*)/i,\n} as const;\n\n// `GitWarnings` moved to `@gitlens/git/errors.js` so the shared run contract can name its keys; re-exported\n// here because it's long-established as part of this module's surface.\nexport { GitWarnings };\nexport type { GitWarningKey } from '@gitlens/git/errors.js';\n\nexport class GitError extends Error {\n\treadonly cmd: string | undefined;\n\treadonly exitCode: number | string | undefined;\n\treadonly stdout: string | undefined;\n\treadonly stderr: string | undefined;\n\n\tconstructor(readonly original: Error) {\n\t\tlet message: string;\n\t\tlet stdout: string | undefined;\n\t\tlet stderr: string | undefined;\n\t\tlet cmd: string | undefined;\n\t\tlet exitCode: number | string | undefined;\n\n\t\tif (original instanceof RunError) {\n\t\t\tstdout = original.stdout;\n\t\t\tstderr = original.stderr;\n\t\t\tmessage = stderr || stdout || original.message;\n\t\t\tcmd = original.cmd;\n\t\t\texitCode = original.code;\n\t\t} else {\n\t\t\tmessage = original.message;\n\t\t}\n\n\t\tsuper(message);\n\n\t\tthis.stdout = stdout;\n\t\tthis.stderr = stderr;\n\t\tthis.cmd = cmd;\n\t\tthis.exitCode = exitCode;\n\n\t\tError.captureStackTrace?.(this, new.target);\n\t}\n}\n\nexport type PushForceOptions = { withLease: true; ifIncludes?: boolean } | { withLease: false; ifIncludes?: never };\n\ntype GitCommand =\n\t| 'branch'\n\t| 'checkout'\n\t| 'cherry-pick'\n\t| 'commit'\n\t| 'fetch'\n\t| 'merge'\n\t| 'paused-operation-abort'\n\t| 'paused-operation-continue'\n\t| 'pull'\n\t| 'push'\n\t| 'rebase'\n\t| 'reset'\n\t| 'revert'\n\t| 'show'\n\t| 'stash-apply'\n\t| 'stash-push'\n\t| 'tag'\n\t| 'update-ref'\n\t| 'update-ref-delete'\n\t| 'worktree-create'\n\t| 'worktree-delete';\n\ntype GitCommandToReasonMap = {\n\tbranch: BranchErrorReason;\n\tcheckout: CheckoutErrorReason;\n\t'cherry-pick': CherryPickErrorReason;\n\tcommit: CommitErrorReason;\n\tfetch: FetchErrorReason;\n\tmerge: MergeErrorReason;\n\t'paused-operation-abort': PausedOperationAbortErrorReason;\n\t'paused-operation-continue': PausedOperationContinueErrorReason;\n\tpull: PullErrorReason;\n\tpush: PushErrorReason;\n\trebase: RebaseErrorReason;\n\treset: ResetErrorReason;\n\trevert: RevertErrorReason;\n\tshow: ShowErrorReason;\n\t'stash-apply': StashApplyErrorReason;\n\t'stash-push': StashPushErrorReason;\n\ttag: TagErrorReason;\n\t'update-ref': ReferenceUpdateErrorReason;\n\t'update-ref-delete': ReferenceUpdateErrorReason;\n\t'worktree-create': WorktreeCreateErrorReason;\n\t'worktree-delete': WorktreeDeleteErrorReason;\n};\n\nconst errorToReasonMap = new Map<GitCommand, [RegExp, GitCommandToReasonMap[GitCommand]][]>([\n\t[\n\t\t'branch',\n\t\t[\n\t\t\t[GitErrors.branchAlreadyExists, 'alreadyExists'],\n\t\t\t[GitErrors.invalidName, 'invalidName'],\n\t\t\t[GitErrors.notFullyMerged, 'notFullyMerged'],\n\t\t\t[GitErrors.noRemoteReference, 'noRemoteReference'],\n\t\t],\n\t],\n\t[\n\t\t'checkout',\n\t\t[\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t\t[GitErrors.ambiguousArgument, 'pathspecNotFound'],\n\t\t\t[GitErrors.notAValidObjectName, 'invalidRef'],\n\t\t],\n\t],\n\t[\n\t\t'cherry-pick',\n\t\t[\n\t\t\t[GitErrors.cherryPickAborted, 'aborted'],\n\t\t\t[GitErrors.cherryPickInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.conflict, 'conflicts'],\n\t\t\t[GitErrors.previousOperationEmpty, 'emptyCommit'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'commit',\n\t\t[\n\t\t\t[GitErrors.nothingToCommit, 'nothingToCommit'],\n\t\t\t[GitErrors.unmergedFiles, 'conflicts'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.noUserNameConfigured, 'noUserNameConfigured'],\n\t\t],\n\t],\n\t[\n\t\t'fetch',\n\t\t[\n\t\t\t[GitErrors.noFastForward, 'noFastForward'],\n\t\t\t[GitErrors.noRemoteRepositorySpecified, 'noRemote'],\n\t\t\t[GitErrors.remoteConnectionFailed, 'remoteConnectionFailed'],\n\t\t],\n\t],\n\t[\n\t\t'merge',\n\t\t[\n\t\t\t[GitErrors.mergeAborted, 'aborted'],\n\t\t\t[GitErrors.mergeInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t['paused-operation-abort', [[GitErrors.noPausedOperation, 'nothingToAbort']]],\n\t[\n\t\t'paused-operation-continue',\n\t\t[\n\t\t\t// Kept FIRST: an editor failure's stderr can also carry broader messages (\"could not\n\t\t\t// commit staged changes\", …) that later patterns would otherwise claim\n\t\t\t[GitErrors.problemWithEditor, 'messageEditFailed'],\n\t\t\t[GitErrors.previousOperationEmpty, 'emptyCommit'],\n\t\t\t[GitErrors.noPausedOperation, 'nothingToContinue'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.unmergedFiles, 'unmergedFiles'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.unstagedChanges, 'unstagedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t\t// A single (non-sequencer) revert resolved to a no-op never gets git's \"previous revert is now\n\t\t\t// empty\" message — its `--continue` falls through to the commit, which reports having nothing to\n\t\t\t// commit. Mid-paused-op that means the step became empty, so it earns the same choice.\n\t\t\t//\n\t\t\t// Kept LAST because the pattern is deliberately broad: it also matches \"no changes added to\n\t\t\t// commit\" and \"nothing added to commit\", which appear alongside the more specific unmerged /\n\t\t\t// conflict / unstaged messages. Matching first would shadow those. It isn't narrowed to the\n\t\t\t// \"working tree clean\" variant because an empty step with untracked files present instead reports\n\t\t\t// \"nothing added to commit but untracked files present\".\n\t\t\t[GitErrors.nothingToCommit, 'emptyCommit'],\n\t\t],\n\t],\n\t[\n\t\t'pull',\n\t\t[\n\t\t\t[GitErrors.conflict, 'conflict'],\n\t\t\t[GitErrors.noUserNameConfigured, 'gitIdentity'],\n\t\t\t[GitErrors.remoteConnectionFailed, 'remoteConnectionFailed'],\n\t\t\t[GitErrors.unstagedChanges, 'unstagedChanges'],\n\t\t\t[GitErrors.unmergedFiles, 'unmergedFiles'],\n\t\t\t[GitErrors.commitChangesFirst, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t\t[GitErrors.cantLockRef, 'refLocked'],\n\t\t\t[GitErrors.rebaseMultipleBranches, 'rebaseMultipleBranches'],\n\t\t\t[GitErrors.tagConflict, 'tagConflict'],\n\t\t\t[GitErrors.notPossibleToFastForward, 'noFastForward'],\n\t\t\t[GitErrors.noTrackingInformation, 'noUpstream'],\n\t\t],\n\t],\n\t[\n\t\t'push',\n\t\t[\n\t\t\t[GitErrors.remoteAhead, 'remoteAhead'],\n\t\t\t[GitWarnings.tipBehind, 'tipBehind'],\n\t\t\t// Kept BEFORE the generic push rejection: a failed `push -d` of a missing ref reports both\n\t\t\t// \"unable to delete '<ref>': remote ref does not exist\" and \"failed to push some refs to ...\",\n\t\t\t// and the specific reason is the actionable one.\n\t\t\t[GitErrors.pushRejectedRefDoesNotExists, 'rejectedRefDoesNotExist'],\n\t\t\t[GitErrors.pushRejected, 'rejected'],\n\t\t\t[GitErrors.permissionDenied, 'permissionDenied'],\n\t\t\t[GitErrors.remoteConnectionFailed, 'remoteConnectionFailed'],\n\t\t\t[GitErrors.noUpstream, 'noUpstream'],\n\t\t],\n\t],\n\t[\n\t\t'rebase',\n\t\t[\n\t\t\t[GitErrors.rebaseAborted, 'aborted'],\n\t\t\t[GitErrors.rebaseMissingTodo, 'aborted'],\n\t\t\t[GitErrors.rebaseInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'reset',\n\t\t[\n\t\t\t[GitErrors.ambiguousArgument, 'ambiguousArgument'],\n\t\t\t[GitErrors.detachedHead, 'detachedHead'],\n\t\t\t[GitErrors.refLocked, 'refLocked'],\n\t\t\t[GitErrors.entryNotUpToDate, 'notUpToDate'],\n\t\t\t[GitErrors.permissionDenied, 'permissionDenied'],\n\t\t\t[GitErrors.unmergedChanges, 'unmergedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'revert',\n\t\t[\n\t\t\t[GitErrors.revertAborted, 'aborted'],\n\t\t\t[GitErrors.revertInProgress, 'alreadyInProgress'],\n\t\t\t[GitErrors.unresolvedConflicts, 'conflicts'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.changesWouldBeOverwritten, 'wouldOverwriteChanges'],\n\t\t],\n\t],\n\t[\n\t\t'show',\n\t\t[\n\t\t\t[GitErrors.badObject, 'invalidObject'],\n\t\t\t[GitErrors.badRevision, 'invalidRevision'],\n\t\t\t[GitErrors.notAValidObjectName, 'invalidRevision'],\n\t\t\t[GitWarnings.notFound, 'notFound'],\n\t\t\t[GitWarnings.foundButNotInRevision, 'notInRevision'],\n\t\t],\n\t],\n\t['stash-apply', [[GitErrors.changesWouldBeOverwritten, 'uncommittedChanges']]],\n\t[\n\t\t'stash-push',\n\t\t[\n\t\t\t[GitErrors.stashConflictingStagedAndUnstagedLines, 'conflictingStagedAndUnstagedLines'],\n\t\t\t[GitErrors.stashNothingToSave, 'nothingToSave'],\n\t\t\t[GitErrors.stashSavedWorkingDirAndIndexState, 'conflictingStagedAndUnstagedLines'],\n\t\t],\n\t],\n\t[\n\t\t'tag',\n\t\t[\n\t\t\t[GitErrors.tagAlreadyExists, 'alreadyExists'],\n\t\t\t[GitErrors.invalidTagName, 'invalidName'],\n\t\t\t[GitErrors.tagNotFound, 'notFound'],\n\t\t\t[GitErrors.permissionDenied, 'permissionDenied'],\n\t\t\t[GitErrors.remoteRejected, 'remoteRejected'],\n\t\t\t[GitErrors.tagConflict, 'tagConflict'],\n\t\t],\n\t],\n\t[\n\t\t'update-ref',\n\t\t[\n\t\t\t// Every entry below also matches the broad `cantLockRef` catch-all that closes the list, so\n\t\t\t// order is load-bearing — the specific shapes must be claimed first.\n\t\t\t[GitErrors.refBadName, 'invalidRef'],\n\t\t\t[GitErrors.refNonexistentObject, 'invalidObject'],\n\t\t\t[GitErrors.refNotAValidSha, 'invalidObject'],\n\t\t\t[GitErrors.refValueMismatch, 'conflict'],\n\t\t\t[GitErrors.refAlreadyExists, 'conflict'],\n\t\t\t// A ref that vanished under a compare-and-swap lost the same race as one that moved, so an\n\t\t\t// update reports both as a conflict — the caller's response (re-read, retry) is identical.\n\t\t\t[GitErrors.refUnableToResolve, 'conflict'],\n\t\t\t// Directory/file collisions and any other lock refusal\n\t\t\t[GitErrors.cantLockRef, 'conflict'],\n\t\t],\n\t],\n\t[\n\t\t'update-ref-delete',\n\t\t[\n\t\t\t[GitErrors.refBadName, 'invalidRef'],\n\t\t\t[GitErrors.refNotAValidSha, 'invalidObject'],\n\t\t\t// Kept BEFORE the generic lock failures, and split from the update table above: a deleter\n\t\t\t// that finds its target already gone has reached the state it wanted, while one that finds\n\t\t\t// the target moved has not. Collapsing both into `conflict` would force every caller to\n\t\t\t// re-read just to tell an idempotent no-op from a real race.\n\t\t\t[GitErrors.refUnableToResolve, 'notFound'],\n\t\t\t[GitErrors.refValueMismatch, 'conflict'],\n\t\t\t[GitErrors.cantLockRef, 'conflict'],\n\t\t],\n\t],\n\t[\n\t\t'worktree-create',\n\t\t[\n\t\t\t[GitErrors.alreadyCheckedOut, 'alreadyCheckedOut'],\n\t\t\t[GitErrors.alreadyExists, 'alreadyExists'],\n\t\t],\n\t],\n\t[\n\t\t'worktree-delete',\n\t\t[\n\t\t\t// Must come first -- a locked worktree's lock reason is free text that can otherwise match the errors below\n\t\t\t[GitErrors.worktreeLocked, 'locked'],\n\t\t\t[GitErrors.mainWorkingTree, 'defaultWorkingTree'],\n\t\t\t[GitErrors.uncommittedChanges, 'uncommittedChanges'],\n\t\t\t[GitErrors.failedToDeleteDirectoryNotEmpty, 'directoryNotEmpty'],\n\t\t],\n\t],\n]);\n\nexport function getGitCommandError<T extends GitCommand, TReturn extends GitCommandError<any>>(\n\tcommand: T,\n\tex: GitError,\n\tcreator: (reason: GitCommandToReasonMap[T] | undefined) => TReturn,\n): TReturn {\n\tconst msg: string = ex?.toString() ?? '';\n\n\tconst errorsToReasons = errorToReasonMap.get(command) as [RegExp, GitCommandToReasonMap[T]][] | undefined;\n\tif (errorsToReasons != null) {\n\t\tfor (const [error, reason] of errorsToReasons) {\n\t\t\tif (error.test(msg) || (ex.stderr && error.test(ex.stderr)) || (ex.stdout && error.test(ex.stdout))) {\n\t\t\t\treturn creator(reason);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn creator(undefined);\n}\n\nfunction extractSigningErrorText(ex: unknown): string {\n\tif (ex == null) return '';\n\tif (ex instanceof GitError) return ex.stderr || ex.stdout || ex.message || '';\n\tif (ex instanceof Error) return ex.message || '';\n\tif (typeof ex === 'string') return ex;\n\tif (typeof ex === 'number' || typeof ex === 'boolean' || typeof ex === 'bigint') return String(ex);\n\tif (typeof ex === 'object' && 'message' in ex && typeof ex.message === 'string') return ex.message;\n\treturn '';\n}\n\n/**\n * Classifies a Git error as a signing-related failure using the {@link GitErrors}\n * signing regexes. Returns the matched {@link SigningErrorReason}, or `undefined`\n * when the error is not a recognized signing failure.\n *\n * Precedence is significant: `passphraseFailed` (gpg sign failure) is checked\n * before `noKey`, matching the ordering used historically in patch.ts — a\n * combined stderr like \"error: gpg failed to sign … gpg: No secret key\"\n * resolves to `passphraseFailed`, the outer cause.\n */\nexport function classifySigningError(ex: unknown): SigningErrorReason | undefined {\n\tconst text = extractSigningErrorText(ex);\n\tif (!text) return undefined;\n\tif (GitErrors.gpgSignFailed.test(text)) return 'passphraseFailed';\n\tif (GitErrors.signingKeyNotAvailable.test(text)) return 'noKey';\n\tif (GitErrors.gpgNotFound.test(text)) return 'gpgNotFound';\n\tif (GitErrors.sshNotFound.test(text)) return 'sshNotFound';\n\treturn undefined;\n}\n\n/**\n * Infers the {@link SigningFormat} from stderr hints (e.g., mentions of\n * `ssh-keygen` or `gpg.ssh.*` config keys). Returns `undefined` when no hints\n * are present so callers can supply their own default (typically `'gpg'`).\n *\n * Used as a fallback when `config.getSigningConfig` is unavailable or rejects\n * on the error path.\n */\nexport function inferSigningFormatFromError(ex: unknown): SigningFormat | undefined {\n\tconst text = extractSigningErrorText(ex);\n\tif (!text) return undefined;\n\tif (/\\bssh-keygen\\b|gpg\\.ssh\\.(?:program|allowedsignersfile)/i.test(text)) return 'ssh';\n\tif (/\\bgpg\\b/i.test(text)) return 'gpg';\n\treturn undefined;\n}\n\nexport interface SearchErrorClassification {\n\treason: GitSearchErrorReason;\n\tdetail?: string;\n}\n\n/**\n * Classifies a graph search failure from its stderr into an {@link GitSearchErrorReason}, with the\n * offending pattern/ref text (when git reports one) as `detail`. Returns `undefined` when the error\n * isn't a `GitError` with stderr, or the stderr doesn't match a recognized shape.\n */\nexport function classifySearchError(ex: unknown): SearchErrorClassification | undefined {\n\tif (!(ex instanceof GitError) || !ex.stderr) return undefined;\n\n\tconst stderr = ex.stderr;\n\n\t// `-G<pattern>`/pathspec regex compile failures report one of two shapes:\n\t// fatal: command line, '<pattern>': <regcomp reason>\n\t// fatal: invalid regex: <regcomp reason>\n\t// The pattern itself may contain \"': \", so anchor on the known prefixes and let the greedy `.*`\n\t// resolve to the LAST matching delimiter rather than splitting on the first occurrence.\n\tconst patternDetail =\n\t\t/^fatal:\\s*command line,\\s*'.*':\\s*(.+)$/im.exec(stderr)?.[1] ??\n\t\t/^fatal:\\s*invalid regex:\\s*(.+)$/im.exec(stderr)?.[1];\n\tif (patternDetail != null) return { reason: 'invalidPattern', detail: patternDetail.trim() };\n\n\tif (GitErrors.invalidSearchPattern.test(stderr)) return { reason: 'invalidPattern' };\n\n\tconst ambiguous = GitErrors.ambiguousArgument.exec(stderr);\n\tif (ambiguous != null) return { reason: 'invalidRef', detail: ambiguous[1] };\n\n\tconst badRevision = GitErrors.badRevision.exec(stderr);\n\tif (badRevision != null) return { reason: 'invalidRef', detail: badRevision[1] };\n\n\tif (/unknown revision/i.test(stderr)) return { reason: 'invalidRef' };\n\n\treturn undefined;\n}\n\nexport interface GitOptions {\n\t/** Custom environment variables to add to every git command */\n\tenv?: Record<string, string | undefined>;\n\t/** Dynamic environment provider called for each command (e.g., host-discovered SCM credentials) */\n\tgetEnvironment?: () => Record<string, string | undefined> | undefined;\n\t/** Git command timeout in milliseconds, for runs that don't set their own. Defaults to 60000. Set to 0 to disable. */\n\tgitTimeout?: number;\n\t/** Returns whether the workspace is currently trusted. Defaults to true when not provided. Called on every exec/stream. */\n\tisTrusted?: () => boolean;\n\t/** Queue configuration (max concurrent processes, etc.) */\n\tqueue?: GitQueueConfig;\n\t/** Decodes non-UTF-8 git output. Required when repositories use non-UTF-8 encodings. */\n\tdecode?: (data: Uint8Array, options?: { readonly encoding: string }) => string | Promise<string>;\n\t/** Hooks for observing git execution events */\n\thooks?: GitHooks;\n\t/** Optional dedicated logger for git command logging */\n\tlogger?: LogChannel;\n}\n\nexport interface GitHooks {\n\t/** Called when a git command is aborted (timeout or cancellation) */\n\tonAborted?(info: {\n\t\toperation: string;\n\t\treason: 'timeout' | 'cancellation' | 'unknown';\n\t\tduration: number;\n\t\ttimeout: number;\n\t}): void;\n\t/** Called when a queued command waited longer than 1s before executing */\n\tonSlowQueue?(info: {\n\t\tpriority: GitCommandPriority;\n\t\twaitTime: number;\n\t\tactive: number;\n\t\tqueued: Record<GitCommandPriority, number>;\n\t\tmaxConcurrent: number;\n\t}): void;\n\t/**\n\t * Called once per git command that ran slowly (over the slow-call threshold). Fired only for the\n\t * command that actually executed, never for a deduplicated rider that merely awaited it, so a single\n\t * slow subprocess counts once. `operation` is the primary git subcommand (e.g. `status`, `rev-list`).\n\t */\n\tonSlowCommand?(info: {\n\t\toperation: string | undefined;\n\t\tcwd: string | undefined;\n\t\tduration: number;\n\t\t/** Measured event-loop stall overlapping the command; omitted (or 0) when none was observed. */\n\t\teventLoopDelay?: number;\n\t\t/** Caller-declared operation family, see `GitRunOptions.slownessCategory`. */\n\t\tslownessCategory?: GitHealthSlownessCategory;\n\t}): void;\n}\n\n/**\n * Keys dropped from the INHERITED `process.env` before it seeds the base git environment. git hands these\n * to anything it launches (a hook, `rebase -x`, an editor invoked as `GIT_EDITOR`) to describe the command\n * it is running; a host started that way would otherwise run every command against THAT repository with\n * THAT command's settings, whatever `cwd` we pass. None is worth keeping when set deliberately either: a\n * `GIT_DIR` would point every repository the host opens at one. `options.env`, `options.getEnvironment()`\n * and a per-call `env` are merged in afterwards, so any of them can still set these keys (e.g. a temporary\n * `GIT_INDEX_FILE` for a call).\n */\nconst inheritedEnvKeysToDrop: ReadonlySet<string> = new Set([\n\t// The parent's repository location — must come from our own cwd\n\t'GIT_DIR',\n\t'GIT_WORK_TREE',\n\t'GIT_INDEX_FILE',\n\t'GIT_COMMON_DIR',\n\t'GIT_OBJECT_DIRECTORY',\n\t'GIT_ALTERNATE_OBJECT_DIRECTORIES',\n\t'GIT_NAMESPACE',\n\t// What git tells a child about the command it's running: its `-c` overrides, its helpers' location, the\n\t// subdirectory it ran from, and the label for its reflog entries\n\t'GIT_CONFIG_PARAMETERS',\n\t'GIT_EXEC_PATH',\n\t'GIT_PREFIX',\n\t'GIT_REFLOG_ACTION',\n]);\n\n/**\n * Dropped only when git launched the host, which it always marks by exporting `GIT_EXEC_PATH`: an editor\n * opened for `commit --amend` gets that commit's author and date, while an identity set deliberately (e.g.\n * by direnv) must still reach our commits.\n */\nconst inheritedIdentityKeysToDrop: ReadonlySet<string> = new Set([\n\t'GIT_AUTHOR_NAME',\n\t'GIT_AUTHOR_EMAIL',\n\t'GIT_AUTHOR_DATE',\n\t'GIT_COMMITTER_NAME',\n\t'GIT_COMMITTER_EMAIL',\n\t'GIT_COMMITTER_DATE',\n]);\n\n/** `process.env` with {@link inheritedEnvKeysToDrop} removed, and {@link inheritedIdentityKeysToDrop} when git launched us. */\nfunction getInheritedEnv(): Record<string, string | undefined> {\n\tconst launchedByGit = process.env.GIT_EXEC_PATH != null;\n\treturn Object.fromEntries(\n\t\tObject.entries(process.env).filter(\n\t\t\t([key]) => !inheritedEnvKeysToDrop.has(key) && !(launchedByGit && inheritedIdentityKeysToDrop.has(key)),\n\t\t),\n\t);\n}\n\nconst emptyArray: readonly never[] = Object.freeze([]);\nconst emptyObj = Object.freeze({});\nconst trailingNewlineRegex = /[\\r|\\n]+$/;\nconst unsharedRunCounter = getScopedCounter();\nconst uniqueCounterForStream = getScopedCounter();\n\ntype ExitCodeOnlyGitCommandOptions = GitRunOptions & { exitCodeOnly: true };\n\nexport class Git {\n\t/** Map of running git commands — avoids running duplicate overlapping commands */\n\tprivate readonly pendingCommands = new Map<\n\t\tstring,\n\t\t{ readonly cwd: string | undefined; readonly promise: Promise<RunResult<string | Buffer>> }\n\t>();\n\t/** Queue for throttling background git operations */\n\tprivate readonly _queue: GitQueue;\n\t/** Orders the index-writing runs of each checkout, so they don't race for its `index.lock` */\n\tprivate readonly _indexWrites = new KeyedSequencer();\n\t/** The spawn behind every non-streaming run — a field only so tests can substitute it */\n\tprivate readonly _runSpawn: typeof runSpawn = runSpawn;\n\t/** Detects event-loop stalls while at least one git command is in flight */\n\tprivate readonly _eventLoopMonitor = new EventLoopMonitor();\n\t/** Count of git commands currently in flight, across both the exec and streaming paths */\n\tprivate _activeCommandCount = 0;\n\n\t/** Cached base environment: process.env (minus {@link inheritedEnvKeysToDrop}) + static options.env + GCM/LC_ALL vars */\n\tprivate _baseEnv: Record<string, string | undefined> | undefined;\n\t/** Cached full environment: base + dynamic getEnvironment() result */\n\tprivate _fullEnv: Record<string, string | undefined> | undefined;\n\t/** Last dynamic env reference, used to detect when getEnvironment() returns a new object */\n\tprivate _lastDynamicEnv: Record<string, string | undefined> | undefined | null;\n\n\t/** Bound via {@link bindChangeNotifier}; announces a `notify`-flagged run's changes. No-op until bound. */\n\tprivate _changeNotifier:\n\t\t| ((\n\t\t\t\trepoPaths: readonly string[],\n\t\t\t\tchanges: readonly RepositoryChange[],\n\t\t\t\tsharedPaths?: readonly string[],\n\t\t ) => void)\n\t\t| undefined;\n\n\tconstructor(\n\t\tprivate readonly _locator: () => Promise<GitLocation>,\n\t\treadonly options: GitOptions = {},\n\t) {\n\t\tthis._queue = new GitQueue(options.queue, { onSlowQueue: options.hooks?.onSlowQueue });\n\t}\n\n\t/**\n\t * Binds the callback a `notify`-flagged {@link run} calls once it settles. `CliGitProvider` wires this\n\t * to its own `notifyChanged` from its constructor — including when it's handed a pre-built `Git` via\n\t * `options.git`, so a host-supplied instance gets bound too. With nothing bound, `notify` is a no-op.\n\t * `repoPaths` holds more than one path only for a `-C`-scoped shared-state verb: the `-C` target, then the\n\t * caller's own `cwd`. `sharedPaths` names the paths that were not run in but share the repository, which\n\t * hear only the part of `changes` every worktree sees (the caller's `cwd`, when the verb also changed\n\t * something local to the `-C` target).\n\t */\n\tbindChangeNotifier(\n\t\tfn: (\n\t\t\trepoPaths: readonly string[],\n\t\t\tchanges: readonly RepositoryChange[],\n\t\t\tsharedPaths?: readonly string[],\n\t\t) => void,\n\t): void {\n\t\tthis._changeNotifier = fn;\n\t}\n\n\t/**\n\t * Returns the base environment for git commands. Cached to avoid spreading\n\t * process.env (30-100+ keys) on every call. Includes static options.env and\n\t * GCM/LC_ALL vars but NOT dynamic getEnvironment() or per-call env overrides.\n\t */\n\tprivate getBaseEnv(): Record<string, string | undefined> {\n\t\treturn (this._baseEnv ??= {\n\t\t\t...getInheritedEnv(),\n\t\t\t...(this.options.env ?? emptyObj),\n\t\t\tGCM_INTERACTIVE: 'NEVER',\n\t\t\tGCM_PRESERVE_CREDS: 'TRUE',\n\t\t\tLC_ALL: 'C',\n\t\t});\n\t}\n\n\t/**\n\t * Returns the full environment (base + dynamic). Cached and invalidated\n\t * when getEnvironment() returns a different object reference.\n\t */\n\tprivate getFullEnv(): Record<string, string | undefined> {\n\t\tconst dynamicEnv = this.options.getEnvironment?.() ?? undefined;\n\t\tif (this._fullEnv != null && dynamicEnv === this._lastDynamicEnv) return this._fullEnv;\n\n\t\tthis._lastDynamicEnv = dynamicEnv;\n\t\tthis._fullEnv = dynamicEnv != null ? { ...this.getBaseEnv(), ...dynamicEnv } : this.getBaseEnv();\n\t\treturn this._fullEnv;\n\t}\n\n\t/**\n\t * Builds the environment for a git command. Returns the cached full env\n\t * directly when there are no per-call overrides (the common case).\n\t * Only allocates a new object when per-call env overrides are provided.\n\t */\n\tprivate buildEnv(perCallEnv: Record<string, string | undefined> | undefined): Record<string, string | undefined> {\n\t\tif (perCallEnv == null) return this.getFullEnv();\n\n\t\treturn { ...this.getFullEnv(), ...perCallEnv };\n\t}\n\n\tdispose(): void {\n\t\tthis._queue.dispose();\n\t\tthis._eventLoopMonitor.dispose();\n\t}\n\n\t/**\n\t * Drops in-flight commands so a later identical call spawns its own run instead of joining one that\n\t * started before a change. With `repoPaths`, drops only runs whose `cwd` is one of them or inside one;\n\t * without, drops every run.\n\t */\n\tclearPendingCommands(repoPaths?: readonly string[]): void {\n\t\tif (repoPaths == null) {\n\t\t\tthis.pendingCommands.clear();\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const [key, { cwd }] of this.pendingCommands) {\n\t\t\tif (cwd == null) continue;\n\n\t\t\tif (repoPaths.some(p => arePathsEqual(cwd, p) || isDescendant(cwd, p))) {\n\t\t\t\tthis.pendingCommands.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Marks one more git command as in flight; starts the event-loop monitor on the first. */\n\tprivate beginActiveCommand(): void {\n\t\tthis._activeCommandCount++;\n\t\tif (this._activeCommandCount === 1) {\n\t\t\tthis._eventLoopMonitor.start();\n\t\t}\n\t}\n\n\t/** Marks a git command as finished; stops the event-loop monitor once none remain. */\n\tprivate endActiveCommand(): void {\n\t\tthis._activeCommandCount--;\n\t\tif (this._activeCommandCount === 0) {\n\t\t\tthis._eventLoopMonitor.stop();\n\t\t}\n\t}\n\n\t/** Formats the shared \"event loop blocked\" log annotation; undefined below {@link eventLoopDelayAnnotationThreshold}. */\n\tprivate formatEventLoopDelayAnnotation(sinceEpochMs: number): string | undefined {\n\t\tconst delay = this._eventLoopMonitor.maxDelaySince(sinceEpochMs);\n\t\treturn delay >= eventLoopDelayAnnotationThreshold ? `event loop blocked ~${delay}ms` : undefined;\n\t}\n\n\tprivate _gitLocation: GitLocation | undefined;\n\tprivate _gitLocationPromise: Promise<GitLocation> | undefined;\n\n\tprivate async getLocation(): Promise<GitLocation> {\n\t\tif (this._gitLocation == null) {\n\t\t\tthis._gitLocationPromise ??= this._locator();\n\t\t\tthis._gitLocation = await this._gitLocationPromise;\n\t\t}\n\t\treturn this._gitLocation;\n\t}\n\n\tasync path(): Promise<string> {\n\t\treturn (await this.getLocation()).path;\n\t}\n\n\tasync version(): Promise<string> {\n\t\treturn (await this.getLocation()).version;\n\t}\n\n\tsupports(feature: GitFeatures): boolean | Promise<boolean> {\n\t\tconst version = gitFeaturesByVersion.get(feature);\n\t\tif (version == null) return true;\n\n\t\treturn this._gitLocation != null\n\t\t\t? compare(fromString(this._gitLocation.version), fromString(version)) !== -1\n\t\t\t: this.version().then(v => compare(fromString(v), fromString(version)) !== -1);\n\t}\n\n\tsupported<T extends GitFeatureOrPrefix>(feature: T): FilteredGitFeatures<T>[] | Promise<FilteredGitFeatures<T>[]> {\n\t\tfunction supportedCore(gitVersion: string): FilteredGitFeatures<T>[] {\n\t\t\treturn [...gitFeaturesByVersion]\n\t\t\t\t.filter(([f, v]) => f.startsWith(feature) && compare(fromString(gitVersion), v) !== -1)\n\t\t\t\t.map(([f]) => f as FilteredGitFeatures<T>);\n\t\t}\n\n\t\tif (this._gitLocation == null) {\n\t\t\treturn this.version().then(v => supportedCore(v));\n\t\t}\n\t\treturn supportedCore(this._gitLocation.version);\n\t}\n\n\tasync ensureSupports(feature: GitFeatures, prefix: string, suffix: string): Promise<void>;\n\tasync ensureSupports(feature: GitFeatures, message: GitFeatureUnsupportedMessage): Promise<void>;\n\tasync ensureSupports(\n\t\tfeature: GitFeatures,\n\t\tprefixOrMessage: string | GitFeatureUnsupportedMessage,\n\t\tsuffix?: string,\n\t): Promise<void> {\n\t\tconst version = gitFeaturesByVersion.get(feature);\n\t\tif (version == null) return;\n\n\t\tconst gitVersion = await this.version();\n\t\tif (compare(fromString(gitVersion), fromString(version)) !== -1) return;\n\n\t\tconst message =\n\t\t\ttypeof prefixOrMessage === 'function'\n\t\t\t\t? prefixOrMessage(version, gitVersion)\n\t\t\t\t: `${prefixOrMessage} requires a newer version of Git (>= ${version}) than is currently installed (${gitVersion}).${suffix}`;\n\t\tthrow new Error(message);\n\t}\n\n\tasync run(\n\t\toptions: ExitCodeOnlyGitCommandOptions,\n\t\t...args: readonly (string | undefined)[]\n\t): Promise<GitResult<unknown>>;\n\tasync run<T extends string | Buffer = string>(\n\t\toptions: GitRunOptions,\n\t\t...args: readonly (string | undefined)[]\n\t): Promise<GitResult<T>>;\n\tasync run<T extends string | Buffer = string>(\n\t\toptions: GitRunOptions,\n\t\t...args: readonly (string | undefined)[]\n\t): Promise<GitResult<T | unknown>> {\n\t\tif (this.options.isTrusted?.() === false) throw new WorkspaceUntrustedError();\n\n\t\tconst runArgs = args.filter(a => a != null);\n\n\t\t// `notify` announces once the run settles (success, failure or cancellation), which the bare\n\t\t// `return <promise>` paths below don't wait for; callers without it never take this branch.\n\t\tif (options.notify != null) {\n\t\t\ttry {\n\t\t\t\treturn await this.run<T>({ ...options, notify: undefined }, ...args);\n\t\t\t} finally {\n\t\t\t\tthis.applyNotify(options, runArgs);\n\t\t\t}\n\t\t}\n\n\t\tconst gitCommand = `git ${runArgs.join(' ')}`;\n\n\t\t// If cache is provided, use it to cache the full result\n\t\tif (options.caching != null) {\n\t\t\tconst cachePath = options.caching.commonPath ?? options.cwd!;\n\t\t\t// Drop the cached (or in-flight) entry first so `getOrCreate` below always creates a fresh\n\t\t\t// entry with its own `AbortAggregate` — the underlying spawn can then never join an in-flight\n\t\t\t// run that started before this caller's own write.\n\t\t\tif (options.caching.force) {\n\t\t\t\toptions.caching.cache.delete(cachePath, gitCommand);\n\t\t\t}\n\n\t\t\treturn options.caching.cache.getOrCreate(\n\t\t\t\tcachePath,\n\t\t\t\tgitCommand,\n\t\t\t\tasync (cacheable, signal) => {\n\t\t\t\t\t// Bind the shared spawn to the aggregate `signal` (fires only when ALL current callers\n\t\t\t\t\t// abort), not this-caller's `options.cancellation` — otherwise a superseded caller's\n\t\t\t\t\t// abort would kill the shared command and reject concurrent riders that never cancelled.\n\t\t\t\t\tconst result = await this.runCore<T>(\n\t\t\t\t\t\t{ ...options, caching: undefined, cancellation: signal ?? options.cancellation },\n\t\t\t\t\t\trunArgs,\n\t\t\t\t\t\tgitCommand,\n\t\t\t\t\t);\n\t\t\t\t\t// Never cache a result that isn't a genuine command outcome. Under `errors: 'ignore'` a\n\t\t\t\t\t// cancelled/aborted run RESOLVES an empty result, which — left cached — would be served as a\n\t\t\t\t\t// real empty result for the full TTL (e.g. a valid merge-base read back as \"none\").\n\t\t\t\t\t// Invalidate on anything that isn't a clean exit, or whenever the aggregate signal aborted,\n\t\t\t\t\t// so the entry self-evicts instead of poisoning later callers.\n\t\t\t\t\t//\n\t\t\t\t\t// `status !== 'exited'` is what catches the case a bare `exitCode` check cannot. A swallowed\n\t\t\t\t\t// `GitWarnings` match used to report `exitCode: 0` UNCONDITIONALLY — the old code read it off\n\t\t\t\t\t// a `result` that is only ever assigned on the non-throwing path, so it was always the `?? 0`\n\t\t\t\t\t// fallback — which meant `exitCode !== 0` could never fire and every swallowed failure was\n\t\t\t\t\t// cached. A `warned` result now carries git's real code, so it's the status, not the code,\n\t\t\t\t\t// that has to do the work here. The `exitCode !== 0` half is kept as-is — a non-zero exit is\n\t\t\t\t\t// a real answer and arguably cacheable, but it isn't cached today and this isn't the change\n\t\t\t\t\t// to start.\n\t\t\t\t\tif (result.completion.status !== 'exited' || result.exitCode !== 0 || signal?.aborted) {\n\t\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\t// Forward this caller's cancellation so `getOrCreate` races each caller's own wait — an\n\t\t\t\t// aborting caller rejects only itself, leaving the shared work (and its riders) intact.\n\t\t\t\t{ ...options.caching.options, cancellation: options.cancellation },\n\t\t\t);\n\t\t}\n\n\t\treturn this.runCore<T>(options, runArgs, gitCommand);\n\t}\n\n\t/**\n\t * Applies `options.notify` once a {@link run} has settled — a no-op unless both `notify` and a\n\t * {@link bindChangeNotifier bound} notifier are present, so an unflagged caller pays nothing.\n\t */\n\tprivate applyNotify(options: GitRunOptions, args: readonly string[]): void {\n\t\tconst notify = options.notify;\n\t\tif (notify == null || this._changeNotifier == null || options.cwd == null) return;\n\n\t\tif (notify !== 'infer') {\n\t\t\t// The caller decided exactly what changed; still resolve WHERE it changed the same way `infer`\n\t\t\t// does, since the caller may have passed its own `-C` in the argv.\n\t\t\tthis._changeNotifier([this.resolveNotifyPath(options.cwd, leadingCommand(args).pathOverride)], notify);\n\t\t\treturn;\n\t\t}\n\n\t\tconst command = getChangesForCommand(args);\n\t\tif (command == null) return; // read-only or object-store-only — nothing to announce\n\n\t\tconst ranIn = this.resolveNotifyPath(options.cwd, command.pathOverride);\n\n\t\t// A `-C`-scoped write also changes what the caller's own `cwd` sees when both share a `.git`: a branch,\n\t\t// tag or stash it wrote. The target may be a worktree the cache never registered, so its eviction can't be\n\t\t// trusted to reach `cwd`; announce the shared kinds there too, and only those. A write it can't classify\n\t\t// (`[]`) resets both, since what it shares is unknown.\n\t\tconst cwd = normalizePath(options.cwd);\n\t\tif (\n\t\t\tcommand.pathOverride != null &&\n\t\t\tcwd !== ranIn &&\n\t\t\t(command.sharedChanges.length || !command.changes.length)\n\t\t) {\n\t\t\tif (command.sharedChanges.length === command.changes.length) {\n\t\t\t\tthis._changeNotifier([ranIn, cwd], command.changes);\n\t\t\t} else {\n\t\t\t\tthis._changeNotifier([ranIn], command.changes, [cwd]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis._changeNotifier([ranIn], command.changes);\n\t}\n\n\tprivate resolveNotifyPath(cwd: string, pathOverride: string | undefined): string {\n\t\treturn normalizePath(pathOverride != null ? resolvePath(cwd, pathOverride) : cwd);\n\t}\n\n\tprivate async runCore<T extends string | Buffer>(\n\t\toptions: GitRunOptions,\n\t\targs: string[],\n\t\tgitCommand: string,\n\t): Promise<GitResult<T | unknown>> {\n\t\tconst start = hrtime();\n\t\tconst startEpochMs = Date.now();\n\n\t\tgitCommand = `[${options.cwd}] ${gitCommand}`;\n\t\tconst {\n\t\t\tbeforeIndexLockRetry,\n\t\t\tcancellation,\n\t\t\tconfigs,\n\t\t\tcorrelationKey,\n\t\t\terrors: errorHandling,\n\t\t\tencoding,\n\t\t\texpectedExitCodes,\n\t\t\trunLocally: _,\n\t\t\tselfMaintenance,\n\t\t\tslownessCategory,\n\t\t\t...opts\n\t\t} = options;\n\n\t\t// A run's own timeout holds even when the default is disabled (0), so an unrequested background run stays capped\n\t\tconst runTimeout = opts.timeout ?? this.options.gitTimeout ?? 60000;\n\t\tconst runOpts: Mutable<RunOptions> = {\n\t\t\t...opts,\n\t\t\ttimeout: runTimeout === 0 ? undefined : runTimeout,\n\t\t\tencoding: (encoding ?? 'utf8') === 'utf8' ? 'utf8' : 'buffer',\n\t\t\tdecode: this.options.decode,\n\t\t\tenv: this.buildEnv(options.env),\n\t\t\tquiet: errorHandling === 'ignore',\n\t\t};\n\n\t\t// A run fed its own stdin or per-call env is never shared: the same argv can answer differently for\n\t\t// each (a temporary index through `GIT_INDEX_FILE`, config injected through `GIT_CONFIG_*`). Nor is one\n\t\t// carrying a retry hook, since the check it makes is that caller's own.\n\t\tconst unshared =\n\t\t\toptions?.stdin != null ||\n\t\t\t(options?.env != null && Object.keys(options.env).length > 0) ||\n\t\t\tbeforeIndexLockRetry != null;\n\t\tconst cacheKey = `${correlationKey !== undefined ? `${correlationKey}:` : ''}${\n\t\t\tunshared ? `${unsharedRunCounter.next()}:` : ''\n\t\t}${cancellation != null ? `${getAbortSignalId(cancellation)}:` : ''}${gitCommand}`;\n\n\t\t// When the subprocess actually started — `start` includes GitQueue wait, which is congestion rather\n\t\t// than anything the repository did. Stays undefined for a dedup rider or a command aborted while queued.\n\t\tlet execStart: ReturnType<typeof hrtime> | undefined;\n\t\t// What the caller's retry hook threw. It is the caller's own failure, so it must reach them as thrown\n\t\t// rather than be classified like a git failure below.\n\t\tlet hookFailure: { error: unknown } | undefined;\n\t\tlet waiting;\n\t\tlet promise = this.pendingCommands.get(cacheKey)?.promise;\n\t\tif (promise == null) {\n\t\t\twaiting = false;\n\n\t\t\t// Create a deferred promise and store it immediately to prevent duplicate commands\n\t\t\t// Note: cancellation tokens are not part of the dedup key — calls with different AbortSignals will not be deduplicated\n\t\t\tconst deferred = defer<RunResult<string | Buffer>>();\n\t\t\tpromise = deferred.promise;\n\t\t\tthis.pendingCommands.set(cacheKey, { cwd: options.cwd, promise: promise });\n\n\t\t\t// A write to the index takes `index.lock` and fails at once if another process holds it, so these\n\t\t\t// runs queue behind one another per checkout and retry briefly when something outside still beats\n\t\t\t// them to it. A temporary index (`GIT_INDEX_FILE`) has a lock of its own, so it never joins the order.\n\t\t\tconst writesIndex = isIndexWriteCommand(args);\n\t\t\tconst checkoutKey =\n\t\t\t\twritesIndex && options.cwd != null && runOpts.env?.GIT_INDEX_FILE == null\n\t\t\t\t\t? this.resolveNotifyPath(options.cwd, leadingCommand(args).pathOverride)\n\t\t\t\t\t: undefined;\n\n\t\t\t// Fixes https://github.com/gitkraken/vscode-gitlens/issues/73 & https://github.com/gitkraken/vscode-gitlens/issues/161\n\t\t\t// See https://stackoverflow.com/questions/4144417/how-to-handle-asian-characters-in-file-names-in-git-on-os-x\n\t\t\targs.unshift('-c', 'core.quotepath=false', '-c', 'color.ui=false', ...(configs ?? emptyArray));\n\n\t\t\tif (process.platform === 'win32') {\n\t\t\t\targs.unshift('-c', 'core.longpaths=true');\n\t\t\t}\n\n\t\t\tif (cancellation != null) {\n\t\t\t\trunOpts.cancellation = cancellation;\n\t\t\t}\n\n\t\t\t// Determine command priority:\n\t\t\t// Priority resolution:\n\t\t\t// 1. Explicit priority from options (highest precedence)\n\t\t\t// 2. Inferred from command type (only downgrades expensive commands to Background)\n\t\t\tconst priority = options.priority ?? inferGitCommandPriority(args);\n\n\t\t\t// Execute through the queue (interactive/normal run immediately, background is throttled)\n\t\t\tconst gitPath = await this.path();\n\t\t\tconst spawnQueued = () =>\n\t\t\t\tthis._queue.run(\n\t\t\t\t\tpriority,\n\t\t\t\t\t() => {\n\t\t\t\t\t\texecStart = hrtime();\n\t\t\t\t\t\treturn this._runSpawn<T>(gitPath, args, encoding ?? 'utf8', runOpts);\n\t\t\t\t\t},\n\t\t\t\t\tcancellation,\n\t\t\t\t);\n\t\t\t// The retry wraps the spawn itself, before any `errors` mode turns a failure into a result or a\n\t\t\t// throw, because only the raw `RunError` carries the stderr that says the lock was held. It re-queues\n\t\t\t// each attempt, so waiting between them doesn't hold a queue slot.\n\t\t\t// A config write likewise fails at once on a held `<file>.lock`. Reads never produce that failure, so\n\t\t\t// the retry costs them nothing, and one wrap covers both `errors` modes.\n\t\t\tconst beforeRetry =\n\t\t\t\tbeforeIndexLockRetry != null\n\t\t\t\t\t? async (lockError: Error) => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait beforeIndexLockRetry(lockError);\n\t\t\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t\t\t// The lock error thrown back only declines the retry, leaving the lock failure as the result\n\t\t\t\t\t\t\t\tif (ex !== lockError) {\n\t\t\t\t\t\t\t\t\thookFailure = { error: ex };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthrow ex;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined;\n\t\t\tconst spawnWithRetry = writesIndex\n\t\t\t\t? () => retryWhileIndexLocked(spawnQueued, cancellation, beforeRetry)\n\t\t\t\t: isConfigCommand(args)\n\t\t\t\t\t? () => retryWhileConfigLocked(spawnQueued, cancellation)\n\t\t\t\t\t: spawnQueued;\n\t\t\tvoid (\n\t\t\t\tcheckoutKey != null\n\t\t\t\t\t? this._indexWrites.run(checkoutKey, cancellation, spawnWithRetry)\n\t\t\t\t\t: spawnWithRetry()\n\t\t\t)\n\t\t\t\t.then(deferred.fulfill, (e: unknown) => deferred.cancel(e instanceof Error ? e : new Error(String(e))))\n\t\t\t\t.finally(() => {\n\t\t\t\t\t// A clear may have dropped this run and a later identical call registered its own under the key\n\t\t\t\t\tif (this.pendingCommands.get(cacheKey)?.promise === deferred.promise) {\n\t\t\t\t\t\tthis.pendingCommands.delete(cacheKey);\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch(() => {});\n\t\t} else {\n\t\t\twaiting = true;\n\t\t\tLogger.trace(`${formatLoggableScopeBlock('GIT')} ${gitCommand} \\u00b7 awaiting existing call...`);\n\t\t}\n\n\t\t// Placed HERE, not at the top of the method — every path from this point flows through the\n\t\t// `finally` below, so the active count can't leak if setup (e.g. locating git) throws.\n\t\tthis.beginActiveCommand();\n\n\t\tlet exception: Error | undefined;\n\t\tlet result;\n\t\ttry {\n\t\t\tresult = await promise;\n\t\t\t// A normal `runSpawn` only resolves on a clean exit — `code !== 0 || signal` rejects — but the\n\t\t\t// `exitCodeOnly` overload resolves unconditionally, INCLUDING for a signalled run (no code, partial\n\t\t\t// or absent stdout). Coercing that to `0` would report a killed command as a clean success, so\n\t\t\t// classify it as the failure it is.\n\t\t\tif (result.exitCode == null) {\n\t\t\t\t// SIGTERM groups with cancellations here exactly as it does on the reject path — `failed`/`signal`\n\t\t\t\t// is for every OTHER signal. Only `exitCodeOnly` reaches this: a native spawn `timeout` fires\n\t\t\t\t// `close(null, 'SIGTERM')` with no `error` event, so it resolves instead of rejecting (a caller\n\t\t\t\t// abort never does — `'error'` rejects first). Throwing hands it to the catch below, which owns\n\t\t\t\t// the ABORTED log and the `onAborted` hook — neither of which a branch here would fire.\n\t\t\t\tif (result.signal === 'SIGTERM') {\n\t\t\t\t\tthrow new CancelledRunError(\n\t\t\t\t\t\tgitCommand,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tresult.signal,\n\t\t\t\t\t\tresult.killed ? 'timeout' : 'unknown',\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tstdout: result.stdout,\n\t\t\t\t\tstderr: result.stderr,\n\t\t\t\t\tcompletion: {\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\treason: result.signal != null ? 'signal' : 'unstarted',\n\t\t\t\t\t\terror: new Error(\n\t\t\t\t\t\t\t`Command terminated without an exit code${result.signal != null ? ` (${result.signal})` : ''}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tstdout: result.stdout,\n\t\t\t\tstderr: result.stderr,\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\tcompletion: { status: 'exited', code: result.exitCode },\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (hookFailure != null) {\n\t\t\t\texception =\n\t\t\t\t\thookFailure.error instanceof Error ? hookFailure.error : new Error(String(hookFailure.error));\n\t\t\t\tif (typeof hookFailure.error === 'object' && hookFailure.error != null) {\n\t\t\t\t\trunHookFailures.add(hookFailure.error);\n\t\t\t\t}\n\n\t\t\t\tthrow hookFailure.error;\n\t\t\t}\n\n\t\t\tif (expectedExitCodes?.length && ex instanceof RunError && !(ex instanceof CancelledRunError)) {\n\t\t\t\tconst code = toExitCode(ex.code);\n\t\t\t\tif (code != null && expectedExitCodes.includes(code)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstdout: ex.stdout,\n\t\t\t\t\t\tstderr: ex.stderr,\n\t\t\t\t\t\texitCode: code,\n\t\t\t\t\t\tcompletion: { status: 'exited', code: code },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet cancellationReason: GitRunCancellation = 'unknown';\n\t\t\tif (ex instanceof CancelledRunError) {\n\t\t\t\tconst duration = getDurationMilliseconds(start);\n\t\t\t\tconst timeout = runOpts.timeout ?? 0;\n\t\t\t\tcancellationReason =\n\t\t\t\t\tex.reason !== 'unknown' ? ex.reason : cancellation?.aborted ? 'aborted' : 'unknown';\n\t\t\t\tconst reason = cancellationReason === 'aborted' ? 'cancellation' : cancellationReason;\n\n\t\t\t\t// A stalled event loop can leave a command looking timed out when it merely never got its exit\n\t\t\t\t// event delivered in time \\u2014 surface the same signal here so it isn't misread as a real timeout.\n\t\t\t\tconst loopDelayAnnotation = this.formatEventLoopDelayAnnotation(startEpochMs);\n\t\t\t\tconst loopDelayText = loopDelayAnnotation != null ? ` \\u00b7 ${loopDelayAnnotation}` : '';\n\n\t\t\t\tLogger.warn(\n\t\t\t\t\t`${formatLoggableScopeBlock('GIT')} ${gitCommand} \\u00b7 ABORTED after ${duration}ms (${reason})${loopDelayText}`,\n\t\t\t\t);\n\t\t\t\tthis.options.hooks?.onAborted?.({\n\t\t\t\t\toperation: gitCommand,\n\t\t\t\t\treason: reason,\n\t\t\t\t\tduration: duration,\n\t\t\t\t\ttimeout: timeout,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (errorHandling === 'ignore') {\n\t\t\t\tif (ex instanceof RunError) {\n\t\t\t\t\tconst code = toExitCode(ex.code);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstdout: ex.stdout,\n\t\t\t\t\t\tstderr: ex.stderr,\n\t\t\t\t\t\t...(code != null ? { exitCode: code } : {}),\n\t\t\t\t\t\tcompletion:\n\t\t\t\t\t\t\tex instanceof CancelledRunError\n\t\t\t\t\t\t\t\t? { status: 'cancelled', reason: cancellationReason, error: ex }\n\t\t\t\t\t\t\t\t: code != null\n\t\t\t\t\t\t\t\t\t? { status: 'exited', code: code }\n\t\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\t\t\t\t\t\t// A signal means it ran and was killed (partial `stdout` may exist);\n\t\t\t\t\t\t\t\t\t\t\t// no signal and no numeric code means it never got that far.\n\t\t\t\t\t\t\t\t\t\t\treason: ex.signal != null ? 'signal' : 'unstarted',\n\t\t\t\t\t\t\t\t\t\t\terror: ex,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// No cancellation branch here: `CancelledRunError extends RunError`, so reaching this at all\n\t\t\t\t// proves `ex` is neither.\n\t\t\t\treturn {\n\t\t\t\t\tstdout: '',\n\t\t\t\t\tstderr: undefined,\n\t\t\t\t\tcompletion: {\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\t// No `RunError` means no process was ever spawned — a queue rejection or a\n\t\t\t\t\t\t// failure before `spawn` returned. (Not an untrusted workspace: `run` refuses\n\t\t\t\t\t\t// those up front, so they never reach this catch.)\n\t\t\t\t\t\treason: 'unstarted',\n\t\t\t\t\t\terror: ex instanceof Error ? ex : new Error(String(ex)),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// The queue refuses an already-aborted signal, or drops a command aborted while it waited, by\n\t\t\t// rejecting with the signal's own reason; that never reached a spawn, so it isn't a `RunError`,\n\t\t\t// and wrapping it as a `GitError` would make a cancellation read as the command failing.\n\t\t\tif (ex instanceof CancelledRunError) {\n\t\t\t\texception = new CancellationError(ex, cancellationReason);\n\t\t\t} else if (!(ex instanceof RunError) && cancellation?.aborted) {\n\t\t\t\texception = new CancellationError(ex instanceof Error ? ex : undefined, 'aborted');\n\t\t\t} else {\n\t\t\t\texception = new GitError(ex);\n\t\t\t}\n\t\t\tif (errorHandling === 'throw') throw exception;\n\n\t\t\t// Rethrows unless the message matches a `GitWarnings` pattern, in which case it logs and returns the\n\t\t\t// key that matched. Capture the error first — `exception` is cleared to keep it out of the `finally`\n\t\t\t// log, but the result still needs to carry it.\n\t\t\tconst swallowed = exception;\n\t\t\tconst warning = defaultExceptionHandler(exception, options.cwd, start);\n\t\t\texception = undefined;\n\t\t\t// The command did NOT produce this empty stdout — a warning was swallowed. Say so, or the caller\n\t\t\t// can't tell a genuinely empty answer (`noCommits`) from a read that never happened\n\t\t\t// (`notARepository`).\n\t\t\t//\n\t\t\t// The process DID exit though (a warning is only ever swallowed for a non-zero exit), so report the\n\t\t\t// code.\n\t\t\tconst code = toExitCode(swallowed instanceof GitError ? swallowed.exitCode : undefined);\n\n\t\t\t// No `stderr`: it belongs to the error here. The top-level field is the channel for runs that\n\t\t\t// completed WITHOUT one (`exited` carries no error, so a successful command's stderr has nowhere\n\t\t\t// else to go) — a swallowed warning always has a `GitError`, and it carries the stderr. Reading\n\t\t\t// `result?.stderr` would be dead anyway: `result` is only assigned on the non-throwing path.\n\t\t\treturn {\n\t\t\t\tstdout: '',\n\t\t\t\t...(code != null ? { exitCode: code } : {}),\n\t\t\t\tcompletion: { status: 'warned', warning: warning, error: swallowed },\n\t\t\t};\n\t\t} finally {\n\t\t\tthis.logGitCommandComplete(\n\t\t\t\tgitCommand,\n\t\t\t\texception,\n\t\t\t\tgetDurationMilliseconds(start),\n\t\t\t\t// 0 when the subprocess never started — there is no execution time to attribute. Also 0 for\n\t\t\t\t// GitLens's own maintenance work, which is slow by design and must not read as repo slowness.\n\t\t\t\texecStart == null || selfMaintenance ? 0 : getDurationMilliseconds(execStart),\n\t\t\t\twaiting,\n\t\t\t\toptions.cwd,\n\t\t\t\targs,\n\t\t\t\tslownessCategory,\n\t\t\t\tstartEpochMs,\n\t\t\t);\n\t\t\tthis.endActiveCommand();\n\t\t}\n\t}\n\n\tasync *stream(options: GitSpawnOptions, ...args: readonly (string | undefined)[]): AsyncGenerator<string> {\n\t\tif (this.options.isTrusted?.() === false) throw new WorkspaceUntrustedError();\n\n\t\tconst start = hrtime();\n\t\tconst startEpochMs = Date.now();\n\t\tconst streamId = uniqueCounterForStream.next();\n\n\t\tconst { configs, stdin, stdinEncoding, cancellation, encoding, slownessCategory, ...opts } = options;\n\t\tconst runArgs = args.filter(a => a != null);\n\n\t\tconst spawnOpts: SpawnOptions = {\n\t\t\t// Unless provided, ignore stdin and leave default streams for stdout and stderr\n\t\t\tstdio: [stdin ? 'pipe' : 'ignore', null, null],\n\t\t\t...opts,\n\t\t\tsignal: cancellation,\n\t\t\tenv: this.buildEnv(options.env),\n\t\t};\n\n\t\tconst gitCommand = `(spawn) [${spawnOpts.cwd as string}] git ${runArgs.join(' ')}`;\n\n\t\t// Fixes https://github.com/gitkraken/vscode-gitlens/issues/73 & https://github.com/gitkraken/vscode-gitlens/issues/161\n\t\t// See https://stackoverflow.com/questions/4144417/how-to-handle-asian-characters-in-file-names-in-git-on-os-x\n\t\trunArgs.unshift('-c', 'core.quotepath=false', '-c', 'color.ui=false', ...(configs ?? emptyArray));\n\n\t\tif (process.platform === 'win32') {\n\t\t\trunArgs.unshift('-c', 'core.longpaths=true');\n\t\t}\n\n\t\tconst command = await this.path();\n\t\tconst proc = spawn(command, runArgs, spawnOpts);\n\n\t\tif (stdin) {\n\t\t\tendStdin(proc.stdin, stdin, stdinEncoding);\n\t\t}\n\n\t\tlet exception: Error | undefined;\n\n\t\tconst promise = new Promise<void>((resolve, reject) => {\n\t\t\tconst stderrChunks: string[] = [];\n\t\t\tif (proc.stderr) {\n\t\t\t\tproc.stderr?.setEncoding('utf8');\n\t\t\t\tproc.stderr.on('data', chunk => stderrChunks.push(chunk));\n\t\t\t}\n\n\t\t\tproc.once('error', ex => {\n\t\t\t\tif (ex?.name === 'AbortError') return;\n\n\t\t\t\texception = new GitError(ex);\n\t\t\t});\n\t\t\tproc.once('close', (code, signal) => {\n\t\t\t\tif (code === 0) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (signal === 'SIGTERM') {\n\t\t\t\t\t// If the caller aborted, just resolve\n\t\t\t\t\tif (cancellation?.aborted) {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew CancelledRunError(proc.spawnargs.join(' '), true, code ?? undefined, signal, 'unknown'),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If the caller didn't read the complete stream, just resolve\n\t\t\t\tif (\n\t\t\t\t\tsignal === 'SIGPIPE' ||\n\t\t\t\t\tcode === 141 /* SIGPIPE */ ||\n\t\t\t\t\t(code === 128 && stderrChunks.some(c => c.includes('Connection reset by peer')))\n\t\t\t\t) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst stderr = stderrChunks.join('').trim();\n\t\t\t\treject(\n\t\t\t\t\tnew GitError(\n\t\t\t\t\t\tnew RunError(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmessage: `Error (${code}): ${stderr || 'Unknown'}`,\n\t\t\t\t\t\t\t\tcmd: proc.spawnargs.join(' '),\n\t\t\t\t\t\t\t\tkilled: proc.killed,\n\t\t\t\t\t\t\t\tcode: proc.exitCode,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\tstderr,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\n\t\tlet cleanedUp = false;\n\t\tconst cleanup = () => {\n\t\t\tif (cleanedUp) return;\n\n\t\t\tcleanedUp = true;\n\n\t\t\ttry {\n\t\t\t\tproc.removeAllListeners();\n\t\t\t} catch {}\n\t\t\t// Streaming spawns directly, with no GitQueue wait to exclude. It isn't pure subprocess time\n\t\t\t// either — the generator applies backpressure, so a slow consumer stalls the pipe and inflates\n\t\t\t// this — but there's no separate signal to measure here.\n\t\t\tconst duration = getDurationMilliseconds(start);\n\t\t\tthis.logGitCommandComplete(\n\t\t\t\tgitCommand,\n\t\t\t\texception,\n\t\t\t\tduration,\n\t\t\t\tduration,\n\t\t\t\tfalse,\n\t\t\t\tspawnOpts.cwd as string | undefined,\n\t\t\t\trunArgs,\n\t\t\t\tslownessCategory,\n\t\t\t\tstartEpochMs,\n\t\t\t\tstreamId,\n\t\t\t);\n\t\t\tthis.endActiveCommand();\n\t\t};\n\n\t\t// Placed HERE, not at the top of the method — every path from this point reaches `cleanup()`\n\t\t// (the `finally` below, or the generator-close return), so the active count can't leak if\n\t\t// setup (e.g. locating git) throws.\n\t\tthis.beginActiveCommand();\n\n\t\ttry {\n\t\t\tthis.logGitCommandStart(gitCommand, streamId);\n\n\t\t\ttry {\n\t\t\t\tif (proc.stdout) {\n\t\t\t\t\tconst enc = encoding ?? 'utf8';\n\t\t\t\t\tif (enc === 'utf8' || enc === 'binary' || enc === 'buffer') {\n\t\t\t\t\t\tproc.stdout.setEncoding(enc === 'buffer' ? 'utf8' : enc);\n\t\t\t\t\t\tfor await (const chunk of proc.stdout) {\n\t\t\t\t\t\t\tyield chunk;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Non-UTF-8 encoding: collect raw buffers and decode at the end.\n\t\t\t\t\t\t// Streaming decode is unsafe because chunk boundaries can split\n\t\t\t\t\t\t// multi-byte sequences in the source encoding.\n\t\t\t\t\t\tconst decode = this.options.decode;\n\t\t\t\t\t\tif (decode == null) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Non-UTF-8 encoding '${enc}' requested for stream but no decode function configured`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst buffers: Buffer[] = [];\n\t\t\t\t\t\tfor await (const chunk of proc.stdout) {\n\t\t\t\t\t\t\tbuffers.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield await decode(Buffer.concat(buffers), { encoding: enc });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\t// This await MUST be in this inner finally block to ensure the child process close event completes\n\t\t\t\t// before we call removeAllListeners() in the outer finally. When consumers break early from the\n\t\t\t\t// async generator (e.g., reading only the first chunk), the git process receives SIGPIPE and triggers\n\t\t\t\t// the close handler asynchronously. Without awaiting here, removeAllListeners() would execute before\n\t\t\t\t// the close handler finishes, causing a race condition and potential resource leaks.\n\t\t\t\tawait promise;\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\texception = ex;\n\t\t\tthrow ex;\n\t\t} finally {\n\t\t\tcleanup();\n\t\t}\n\n\t\t// Ensure cleanup happens immediately when the generator is explicitly closed (e.g., via break or return)\n\t\t// This is called by JavaScript when the generator is abandoned, ensuring logGitCommand is called\n\t\t// synchronously rather than waiting for garbage collection.\n\t\t// oxlint-disable-next-line typescript/no-meaningless-void-operator\n\t\treturn void cleanup();\n\t}\n\n\t/**\n\t * Resolves the git dir (and common dir, for a linked worktree) of `cwd`.\n\t *\n\t * Resolves `undefined` when `cwd` is not in a repository: git reported so, or `cwd` doesn't exist. Any\n\t * other failure (unsafe ownership, a timeout or cancellation, a missing git binary) rejects.\n\t */\n\tasync rev_parse__git_dir(cwd: string): Promise<{ path: string; commonPath?: string } | undefined> {\n\t\tlet result;\n\t\ttry {\n\t\t\tresult = await this.run({ cwd: cwd, errors: 'throw' }, 'rev-parse', '--git-dir', '--git-common-dir');\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof GitError && GitWarnings.notARepository.test(ex.stderr ?? '')) return undefined;\n\t\t\t// A missing `cwd` fails the spawn itself (ENOENT) before git can say anything about it\n\t\t\tif (!(await fsExists(cwd))) return undefined;\n\t\t\tthrow ex;\n\t\t}\n\t\tif (!result.stdout) return undefined;\n\n\t\t// Keep trailing spaces which are part of the directory name\n\t\tlet [dotGitPath, commonDotGitPath] = result.stdout.split('\\n').map(r => r.trimStart());\n\n\t\t// Make sure to normalize: https://github.com/git-for-windows/git/issues/2478\n\n\t\tif (!isAbsolute(dotGitPath)) {\n\t\t\tdotGitPath = joinPaths(cwd, dotGitPath);\n\t\t}\n\t\tdotGitPath = normalizePath(dotGitPath);\n\n\t\tif (commonDotGitPath) {\n\t\t\tif (!isAbsolute(commonDotGitPath)) {\n\t\t\t\tcommonDotGitPath = joinPaths(cwd, commonDotGitPath);\n\t\t\t}\n\t\t\tcommonDotGitPath = normalizePath(commonDotGitPath);\n\n\t\t\treturn { path: dotGitPath, commonPath: commonDotGitPath !== dotGitPath ? commonDotGitPath : undefined };\n\t\t}\n\n\t\treturn { path: dotGitPath };\n\t}\n\n\tasync rev_parse__show_toplevel(cwd: string): Promise<[safe: true, repoPath: string] | [safe: false] | []> {\n\t\tlet result;\n\n\t\tif (this.options.isTrusted?.() === false) {\n\t\t\t// Check if the folder is a bare clone: if it has a file named HEAD && `rev-parse --show-cdup` is empty\n\t\t\tif (await fsExists(joinPaths(cwd, 'HEAD'))) {\n\t\t\t\ttry {\n\t\t\t\t\tresult = await this.run(\n\t\t\t\t\t\t{ cwd: cwd, errors: 'throw', configs: ['-C', cwd] },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--show-cdup',\n\t\t\t\t\t);\n\t\t\t\t\tif (!result.stdout.trim()) {\n\t\t\t\t\t\tLogger.warn(`Skipping (untrusted workspace); bare clone repository detected in '${cwd}'`);\n\t\t\t\t\t\treturn emptyArray as [];\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// If this throws, we should be good to open the repo (e.g. HEAD doesn't exist)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tresult = await this.run({ cwd: cwd, errors: 'throw' }, 'rev-parse', '--show-toplevel');\n\t\t\t// Make sure to normalize: https://github.com/git-for-windows/git/issues/2478\n\t\t\t// Keep trailing spaces which are part of the directory name\n\t\t\treturn !result.stdout\n\t\t\t\t? (emptyArray as [])\n\t\t\t\t: [true, normalizePath(result.stdout.trimStart().replace(trailingNewlineRegex, ''))];\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof WorkspaceUntrustedError) return emptyArray as [];\n\t\t\tif (!(ex instanceof GitError)) throw ex;\n\n\t\t\tconst unsafeMatch = GitErrors.unsafeRepository.exec(ex.stderr ?? '');\n\t\t\tif (unsafeMatch != null) {\n\t\t\t\tLogger.warn(\n\t\t\t\t\t`Skipping; unsafe repository detected in '${unsafeMatch[1] || unsafeMatch[2]}'; run '${\n\t\t\t\t\t\tunsafeMatch[3]\n\t\t\t\t\t}' to allow it`,\n\t\t\t\t);\n\t\t\t\treturn [false];\n\t\t\t}\n\n\t\t\tconst inDotGit = GitWarnings.mustRunInWorkTree.test(ex.stderr ?? '');\n\t\t\t// Check if we are in a bare clone\n\t\t\tif (inDotGit && this.options.isTrusted?.() !== false) {\n\t\t\t\tresult = await this.run({ cwd: cwd, errors: 'ignore' }, 'rev-parse', '--is-bare-repository');\n\t\t\t\tif (result.stdout.trim() === 'true') {\n\t\t\t\t\tconst result = await this.rev_parse__git_dir(cwd).catch(() => undefined);\n\t\t\t\t\tconst repoPath = result?.commonPath ?? result?.path;\n\t\t\t\t\tif (repoPath?.length) return [true, repoPath];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (inDotGit || (ex.original as NodeJS.ErrnoException)?.code === 'ENOENT') {\n\t\t\t\t// If the `cwd` doesn't exist, walk backward to see if any parent folder exists\n\t\t\t\tlet exists = inDotGit ? false : await fsExists(cwd);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tconst parent = dirname(cwd);\n\t\t\t\t\t\tif (parent === cwd || parent.length === 0) return emptyArray as [];\n\n\t\t\t\t\t\tcwd = parent;\n\t\t\t\t\t\texists = await fsExists(cwd);\n\t\t\t\t\t} while (!exists);\n\n\t\t\t\t\treturn this.rev_parse__show_toplevel(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn emptyArray as [];\n\t\t}\n\t}\n\n\tprivate logGitCommandStart(command: string, id: number): void {\n\t\tLogger.info(`${formatLoggableScopeBlock(`GIT:\\u2192${id}`)} ${command} \\u00b7 starting...`);\n\t\tthis.options.logger?.info(`${formatLoggableScopeBlock(`\\u2192${id}`, '')} ${command} \\u2022 starting...`);\n\t}\n\n\tprivate logGitCommandComplete(\n\t\tcommand: string,\n\t\tex: Error | undefined,\n\t\tduration: number,\n\t\t/** Subprocess-only duration (excludes GitQueue wait); 0 when it never ran. */\n\t\texecDuration: number,\n\t\twaiting: boolean,\n\t\tcwd: string | undefined,\n\t\targs: readonly (string | undefined)[] | undefined,\n\t\tslownessCategory: GitHealthSlownessCategory | undefined,\n\t\tstartEpochMs: number,\n\t\tid?: number,\n\t): void {\n\t\tconst slow = duration > slowCallWarningThreshold;\n\n\t\tconst annotations: string[] = [];\n\t\tif (slow) {\n\t\t\tannotations.push('slow');\n\t\t}\n\n\t\tif (waiting) {\n\t\t\tannotations.push('waiting');\n\t\t} else if (execDuration > 0) {\n\t\t\t// Dedup riders (`waiting`) and never-started commands (`execDuration === 0`) have no queue\n\t\t\t// wait of their own to report.\n\t\t\tconst queued = duration - execDuration;\n\t\t\tif (queued >= queueWaitAnnotationThreshold) {\n\t\t\t\tannotations.push(`queued ${queued}ms`);\n\t\t\t}\n\t\t}\n\n\t\t// `hrtime` spans don't correlate with the monitor's wall-clock ring, so the lookup needs the\n\t\t// command's own start time — only worth measuring once the command is already slow. Whole-call\n\t\t// window on purpose: the annotation explains the TOTAL duration this log line reports.\n\t\tif (slow) {\n\t\t\tconst loopDelayAnnotation = this.formatEventLoopDelayAnnotation(startEpochMs);\n\t\t\tif (loopDelayAnnotation != null) {\n\t\t\t\tannotations.push(loopDelayAnnotation);\n\t\t\t}\n\t\t}\n\n\t\tconst status = annotations.length > 0 ? ` (${annotations.join(', ')})` : '';\n\n\t\t// The health signal is gated on the SUBPROCESS time, not the total: time spent queued behind other\n\t\t// git work is congestion, not repository slowness, and counting it would let a busy queue (including\n\t\t// our own background maintenance holding slots) manufacture the evidence that recommends more\n\t\t// maintenance. Logging keeps the total — the wait is exactly what you want to see when diagnosing.\n\t\t//\n\t\t// A deduplicated rider (`waiting`) shares the executed command's duration, so counting it too\n\t\t// would double-count a single slow subprocess — fire only for the command that actually ran.\n\t\t// Guarded: this runs inside the command's `finally`, so a hook throw would otherwise replace\n\t\t// the command's real result/error for the caller.\n\t\tif (execDuration > slowCallWarningThreshold && !waiting) {\n\t\t\t// Scoped to the SUBPROCESS window, matching the hook's `duration`: `duration - execDuration`\n\t\t\t// is the queue wait, and a stall while queued is congestion, not the command's own signal\n\t\t\t// (same reasoning as the `execDuration` gate above). The subprocess ends at log time, so it\n\t\t\t// started `duration - execDuration` after the call did.\n\t\t\tconst execEventLoopDelay = this._eventLoopMonitor.maxDelaySince(startEpochMs + (duration - execDuration));\n\t\t\ttry {\n\t\t\t\tthis.options.hooks?.onSlowCommand?.({\n\t\t\t\t\toperation: args != null ? getPrimaryGitCommand(args) : undefined,\n\t\t\t\t\tcwd: cwd,\n\t\t\t\t\tduration: execDuration,\n\t\t\t\t\teventLoopDelay: execEventLoopDelay,\n\t\t\t\t\tslownessCategory: slownessCategory,\n\t\t\t\t});\n\t\t\t} catch {}\n\t\t}\n\n\t\tif (ex != null) {\n\t\t\tLogger.error(\n\t\t\t\tundefined,\n\t\t\t\t`${formatLoggableScopeBlock(id ? `GIT:\\u2190${id}` : 'GIT')} ${command} \\u00b7 ${\n\t\t\t\t\tisCancellationError(ex)\n\t\t\t\t\t\t? 'cancelled'\n\t\t\t\t\t\t: (ex.message || String(ex) || '')\n\t\t\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t\t\t.replace(/fatal:\\s*/g, '')\n\t\t\t\t\t\t\t\t.replace(/\\r?\\n|\\r/g, ' \\u00b7 ')\n\t\t\t\t} [${duration}ms]${status}`,\n\t\t\t);\n\t\t} else if (slow) {\n\t\t\tLogger.warn(\n\t\t\t\t`${formatLoggableScopeBlock(id ? `GIT:\\u2190${id}` : 'GIT', `*${duration}ms`)} ${command} [*${duration}ms]${status}`,\n\t\t\t);\n\t\t} else {\n\t\t\tLogger.info(\n\t\t\t\t`${formatLoggableScopeBlock(id ? `GIT:\\u2190${id}` : 'GIT', `${duration}ms`)} ${command} [${duration}ms]${status}`,\n\t\t\t);\n\t\t}\n\n\t\tconst logMessage = `${formatLoggableScopeBlock(\n\t\t\t`${id ? `\\u2190${id}` : ''}${slow ? '*' : ''}`,\n\t\t\t`${duration}ms`,\n\t\t)} ${command}${status}`;\n\t\tif (ex != null) {\n\t\t\tthis.options.logger?.error(`${logMessage} \\u2022 FAILED\\n${String(ex)}`);\n\t\t} else {\n\t\t\tthis.options.logger?.info(`${logMessage} \\u2022 completed`);\n\t\t}\n\t}\n}\n\n/**\n * Swallows an error whose message matches a known-benign {@link GitWarnings} pattern, returning WHICH one\n * matched so the caller can record it — the distinction matters, since `noCommits` is a real answer while\n * `notARepository` is a failed read. Rethrows anything else.\n */\nexport function defaultExceptionHandler(\n\tex: Error,\n\tcwd: string | undefined,\n\tstart?: [number, number],\n): GitWarningKey | undefined {\n\tif (isCancellationError(ex)) throw ex;\n\n\tconst msg = ex.message || ex.toString();\n\tif (msg) {\n\t\tconst warning = getGitWarning(ex);\n\t\tif (warning != null) {\n\t\t\tconst duration = start !== undefined ? ` [${getDurationMilliseconds(start)}ms]` : '';\n\t\t\tLogger.warn(\n\t\t\t\t`[${cwd}] Git ${msg\n\t\t\t\t\t.trim()\n\t\t\t\t\t.replace(/fatal:\\s*/g, '')\n\t\t\t\t\t.replace(/\\r?\\n|\\r/g, ' \\u00b7 ')}${duration}`,\n\t\t\t);\n\t\t\treturn warning;\n\t\t}\n\n\t\tconst match = GitErrors.badRevision.exec(msg);\n\t\tif (match != null) {\n\t\t\tconst [, ref] = match;\n\n\t\t\t// Since looking up a ref with ^3 (e.g. looking for untracked files in a stash) can error on some versions of git just ignore it\n\t\t\t// Swallowed, but it matched no `GitWarnings` entry — `undefined` records \"unclassified\", which\n\t\t\t// callers must treat as \"not a real answer\" exactly like any warning they don't whitelist.\n\t\t\tif (ref?.endsWith('^3')) return undefined;\n\t\t}\n\t}\n\n\tthrow ex;\n}\n"],"mappings":"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"}
@@ -1,4 +1,9 @@
1
1
  //#region ../git-cli/src/exec/indexLock.d.ts
2
+ /**
3
+ * The exit code in a run error's `code`, or `undefined` when the process never exited normally: a numeric string
4
+ * is a real exit code, but an errno (`'ENOENT'`) means the spawn itself failed, and `undefined` means it was killed.
5
+ */
6
+ export declare function toExitCode(code: number | string | undefined): number | undefined;
2
7
  /** How long to wait before each retry of a run that found `index.lock` held; its length is the retry count. */
3
8
  export declare const indexLockRetryDelays: readonly number[];
4
9
  /**
@@ -6,7 +11,10 @@ export declare const indexLockRetryDelays: readonly number[];
6
11
  * which implies `--index`, and never with `--check`).
7
12
  */
8
13
  export declare function isIndexWriteCommand(args: readonly string[]): boolean;
9
- /** Whether a run failed because another process held `index.lock`. */
14
+ /**
15
+ * Whether a run failed because another process held `index.lock`. The exit code must be 128 too: a hook that
16
+ * prints the same line from its own git command and fails makes the run exit 1, after the hook's work is done.
17
+ */
10
18
  export declare function isIndexLockHeldError(ex: unknown): boolean;
11
19
  /**
12
20
  * Whether the argv is `git config`. Only that verb: others that write config (`branch -m`, `remote add`) can
@@ -28,13 +28,24 @@ const applyIndexOptions = /* @__PURE__ */ new Set([
28
28
  "-3"
29
29
  ]);
30
30
  /**
31
- * Matches git's `fatal: Unable to create '<path>/index.lock': File exists.` — the wording varies a little by version.
31
+ * Matches git's `fatal: Unable to create '<path>/index.lock': File exists.` — the wording varies a little by version,
32
+ * but git always `die()`s (`fatal:`) on it.
32
33
  * Anchored to the start of stderr: git takes the lock before doing anything else, so its own failure is the first
33
34
  * thing it prints past any `warning:`/`hint:` lines from parsing its arguments (`checkout` warns of an ambiguous
34
35
  * refname first). The same line after other output came from something the run started, such as a hook running its
35
36
  * own git command, after the run had already done its work — retrying would run it all again.
36
37
  */
37
- const indexLockHeldRegex = /^(?:\s*(?:warning|hint): [^\r\n]*\r?\n)*\s*(?:fatal|error): Unable to create '[^\r\n]*index\.lock': File exists/i;
38
+ const indexLockHeldRegex = /^(?:\s*(?:warning|hint): [^\r\n]*\r?\n)*\s*fatal: Unable to create '[^\r\n]*index\.lock': File exists/i;
39
+ /**
40
+ * The exit code in a run error's `code`, or `undefined` when the process never exited normally: a numeric string
41
+ * is a real exit code, but an errno (`'ENOENT'`) means the spawn itself failed, and `undefined` means it was killed.
42
+ */
43
+ function toExitCode(code) {
44
+ const exitCode = typeof code === "number" ? code : code != null ? parseInt(code, 10) : NaN;
45
+ return Number.isInteger(exitCode) ? exitCode : void 0;
46
+ }
47
+ /** Git's exit code when it `die()`s, as it does on a held `index.lock`. */
48
+ const gitFatalExitCode = 128;
38
49
  /** How long to wait before each retry of a run that found `index.lock` held; its length is the retry count. */
39
50
  const indexLockRetryDelays = [
40
51
  100,
@@ -50,9 +61,12 @@ function isIndexWriteCommand(args) {
50
61
  if (verb === "apply") return !rest.includes("--check") && rest.some((a) => applyIndexOptions.has(a));
51
62
  return indexWritingVerbs.has(verb);
52
63
  }
53
- /** Whether a run failed because another process held `index.lock`. */
64
+ /**
65
+ * Whether a run failed because another process held `index.lock`. The exit code must be 128 too: a hook that
66
+ * prints the same line from its own git command and fails makes the run exit 1, after the hook's work is done.
67
+ */
54
68
  function isIndexLockHeldError(ex) {
55
- return ex instanceof RunError && !(ex instanceof CancelledRunError) && indexLockHeldRegex.test(ex.stderr);
69
+ return ex instanceof RunError && !(ex instanceof CancelledRunError) && toExitCode(ex.code) === gitFatalExitCode && indexLockHeldRegex.test(ex.stderr);
56
70
  }
57
71
  /** Resolves after `ms`, or rejects as soon as `signal` aborts. */
58
72
  async function delay(ms, signal) {
@@ -155,6 +169,6 @@ function waitFor(promise, signal) {
155
169
  });
156
170
  }
157
171
  //#endregion
158
- export { KeyedSequencer, indexLockRetryDelays, isConfigCommand, isConfigLockHeldError, isIndexLockHeldError, isIndexWriteCommand, retryWhileConfigLocked, retryWhileIndexLocked };
172
+ export { KeyedSequencer, indexLockRetryDelays, isConfigCommand, isConfigLockHeldError, isIndexLockHeldError, isIndexWriteCommand, retryWhileConfigLocked, retryWhileIndexLocked, toExitCode };
159
173
 
160
174
  //# sourceMappingURL=indexLock.js.map