@gitkraken/core-gitlens 0.9.9 → 0.10.0
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.
- package/CHANGELOG.md +18 -1
- package/dist/git/errors.d.ts +7 -0
- package/dist/git/errors.js +14 -1
- package/dist/git/errors.js.map +1 -1
- package/dist/git/providers/status.d.ts +6 -1
- package/dist/git/run.types.d.ts +9 -4
- package/dist/git-cli/exec/git.js +36 -16
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/providers/diff.d.ts +5 -2
- package/dist/git-cli/providers/diff.js +21 -9
- package/dist/git-cli/providers/diff.js.map +1 -1
- package/dist/git-cli/providers/patch.js +5 -7
- package/dist/git-cli/providers/patch.js.map +1 -1
- package/dist/git-cli/providers/status.d.ts +0 -1
- package/dist/git-cli/providers/status.js +119 -142
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/plus/git-github/providers/github/status.d.ts +0 -1
- package/dist/plus/git-github/providers/github/status.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +1 -0
- package/dist/plus/integrations/reads/drains.d.ts +1 -0
- package/dist/utils/cancellation.d.ts +4 -1
- package/dist/utils/cancellation.js +4 -2
- package/dist/utils/cancellation.js.map +1 -1
- package/dist/utils/env/node/exec.d.ts +5 -1
- package/dist/utils/env/node/exec.js +8 -5
- package/dist/utils/env/node/exec.js.map +1 -1
- 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 { 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 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 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\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. 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/** 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: ((repoPaths: readonly string[], changes: readonly RepositoryChange[]) => void) | 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`.\n\t */\n\tbindChangeNotifier(fn: (repoPaths: readonly string[], changes: readonly RepositoryChange[]) => void): 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);\n\t\t\t\tthis._changeNotifier([cwd], command.sharedChanges);\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\tcancellation,\n\t\t\tconfigs,\n\t\t\tcorrelationKey,\n\t\t\terrors: errorHandling,\n\t\t\tencoding,\n\t\t\trunLocally: _,\n\t\t\tselfMaintenance,\n\t\t\tslownessCategory,\n\t\t\t...opts\n\t\t} = options;\n\n\t\tconst defaultTimeout = this.options.gitTimeout ?? 60000;\n\t\tconst runOpts: Mutable<RunOptions> = {\n\t\t\t...opts,\n\t\t\ttimeout: opts.timeout === 0 || defaultTimeout === 0 ? undefined : (opts.timeout ?? defaultTimeout),\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_*`).\n\t\tconst unshared = options?.stdin != null || (options?.env != null && Object.keys(options.env).length > 0);\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\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// 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\tvoid this._queue\n\t\t\t\t.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 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\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 is how BOTH a timeout kill and a caller abort terminate, so it has to group with\n\t\t\t\t// cancellations here exactly as it does on the reject path — `failed`/`signal` is for every\n\t\t\t\t// 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.\n\t\t\t\t// Throwing hands it to the catch below, which owns the timeout-vs-abort heuristic, the ABORTED\n\t\t\t\t// log, and the `onAborted` hook — none of which a branch here would fire.\n\t\t\t\tif (result.signal === 'SIGTERM') {\n\t\t\t\t\tthrow new CancelledRunError(gitCommand, true, undefined, result.signal);\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\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\tconst reason =\n\t\t\t\t\ttimeout > 0 && duration >= timeout - 100\n\t\t\t\t\t\t? 'timeout'\n\t\t\t\t\t\t: cancellation?.aborted\n\t\t\t\t\t\t\t? 'cancellation'\n\t\t\t\t\t\t\t: 'unknown';\n\t\t\t\t// Also surfaced on the result, but DIAGNOSTIC ONLY — a timeout kill and a caller abort are both\n\t\t\t\t// SIGTERM, so this duration heuristic can be wrong near the boundary. Never gate behavior on it.\n\t\t\t\tcancellationReason = reason === 'cancellation' ? 'aborted' : reason;\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\t// `code` is `string | number | undefined`: a numeric string is a real exit code, but an errno\n\t\t\t\t\t// (`'ENOENT'`) means the spawn itself failed, and `undefined` means the process never exited\n\t\t\t\t\t// normally. Only the numeric case is an exit; the rest previously became `0` or `NaN`.\n\t\t\t\t\tconst code = typeof ex.code === 'number' ? ex.code : ex.code != null ? parseInt(ex.code, 10) : NaN;\n\t\t\t\t\tconst exited = Number.isInteger(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...(exited ? { 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: exited\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 || (!(ex instanceof RunError) && cancellation?.aborted)) {\n\t\t\t\texception = new CancellationError(ex instanceof Error ? ex : undefined);\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. `GitError.exitCode` is `number | string | undefined` — same normalization as the\n\t\t\t// `errors: 'ignore'` path above, since only the numeric case is a real exit.\n\t\t\tconst rawCode = swallowed instanceof GitError ? swallowed.exitCode : undefined;\n\t\t\tconst code = typeof rawCode === 'number' ? rawCode : rawCode != null ? parseInt(rawCode, 10) : NaN;\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...(Number.isInteger(code) ? { 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(new CancelledRunError(proc.spawnargs.join(' '), true, code ?? undefined, signal));\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\tasync rev_parse__git_dir(cwd: string): Promise<{ path: string; commonPath?: string } | undefined> {\n\t\tconst result = await this.run({ cwd: cwd, errors: 'ignore' }, 'rev-parse', '--git-dir', '--git-common-dir');\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);\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\tfor (const [key, warning] of Object.entries(GitWarnings) as [GitWarningKey, RegExp][]) {\n\t\t\tif (warning.test(msg)) {\n\t\t\t\tconst duration = start !== undefined ? ` [${getDurationMilliseconds(start)}ms]` : '';\n\t\t\t\tLogger.warn(\n\t\t\t\t\t`[${cwd}] Git ${msg\n\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t.replace(/fatal:\\s*/g, '')\n\t\t\t\t\t\t.replace(/\\r?\\n|\\r/g, ' \\u00b7 ')}${duration}`,\n\t\t\t\t);\n\t\t\t\treturn key;\n\t\t\t}\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 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 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\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. 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/** 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: ((repoPaths: readonly string[], changes: readonly RepositoryChange[]) => void) | 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`.\n\t */\n\tbindChangeNotifier(fn: (repoPaths: readonly string[], changes: readonly RepositoryChange[]) => void): 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);\n\t\t\t\tthis._changeNotifier([cwd], command.sharedChanges);\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\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\tconst defaultTimeout = this.options.gitTimeout ?? 60000;\n\t\tconst runOpts: Mutable<RunOptions> = {\n\t\t\t...opts,\n\t\t\ttimeout: opts.timeout === 0 || defaultTimeout === 0 ? undefined : (opts.timeout ?? defaultTimeout),\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_*`).\n\t\tconst unshared = options?.stdin != null || (options?.env != null && Object.keys(options.env).length > 0);\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\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// 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\tvoid this._queue\n\t\t\t\t.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 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\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 (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\tasync rev_parse__git_dir(cwd: string): Promise<{ path: string; commonPath?: string } | undefined> {\n\t\tconst result = await this.run({ cwd: cwd, errors: 'ignore' }, 'rev-parse', '--git-dir', '--git-common-dir');\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);\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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"}
|
|
@@ -31,8 +31,6 @@ export declare class DiffGitSubProvider implements GitDiffSubProvider {
|
|
|
31
31
|
uris?: (string | Uri)[];
|
|
32
32
|
errors?: GitErrorHandling;
|
|
33
33
|
}, _cancellation?: AbortSignal): Promise<GitDiff | undefined>;
|
|
34
|
-
/** Whether `ex` is git failing to resolve `HEAD` because the repository has no commit yet */
|
|
35
|
-
private isUnbornHeadFailure;
|
|
36
34
|
getParsedDiff(repoPath: string, to: string, from?: string, options?: {
|
|
37
35
|
context?: number;
|
|
38
36
|
notation?: GitRevisionRangeNotation;
|
|
@@ -48,6 +46,11 @@ export declare class DiffGitSubProvider implements GitDiffSubProvider {
|
|
|
48
46
|
similarityThreshold?: number;
|
|
49
47
|
errors?: GitErrorHandling;
|
|
50
48
|
}): Promise<GitFile[] | undefined>;
|
|
49
|
+
/**
|
|
50
|
+
* The untracked files a working-tree diff folds in; outside `errors: 'throw'`, a failed listing adds nothing. The diff
|
|
51
|
+
* reads take no cancellation, so a `CancellationError` here is a timeout and degrades like any other failure.
|
|
52
|
+
*/
|
|
53
|
+
private getUntrackedFilesForDiff;
|
|
51
54
|
getDiffTool(repoPath?: string): Promise<string | undefined>;
|
|
52
55
|
getNextComparisonUris(repoPath: string, pathOrUri: string | Uri, rev: string | undefined, skip?: number, options?: {
|
|
53
56
|
ordering?: 'date' | 'author-date' | 'topo' | null;
|
|
@@ -39,7 +39,7 @@ var DiffGitSubProvider = class {
|
|
|
39
39
|
}, "diff", "--shortstat", "--no-ext-diff", ...args, "--", ...options?.uris?.map((p) => this.provider.getRelativePath(p, repoPath)) ?? []);
|
|
40
40
|
const stat = result.stdout ? parseGitDiffShortStat(result.stdout) : void 0;
|
|
41
41
|
if (options?.includeUntracked && !options.uris?.length && isWorkingTreeComparison(to, from)) {
|
|
42
|
-
const untracked = await this.
|
|
42
|
+
const untracked = await this.getUntrackedFilesForDiff(repoPath, options.errors);
|
|
43
43
|
if (untracked.length) return {
|
|
44
44
|
files: (stat?.files ?? 0) + untracked.length,
|
|
45
45
|
additions: stat?.additions ?? 0,
|
|
@@ -84,7 +84,7 @@ var DiffGitSubProvider = class {
|
|
|
84
84
|
env: options?.index?.env
|
|
85
85
|
}, "diff", ...args, args.includes("--") ? void 0 : "--");
|
|
86
86
|
} catch (ex) {
|
|
87
|
-
if (isHead(from) && await this.
|
|
87
|
+
if (isHead(from) && await isUnbornHeadFailure(this.provider, repoPath, ex)) {
|
|
88
88
|
const emptyTree = await this.provider.revision.getEmptyTreeSha(repoPath);
|
|
89
89
|
const retried = await this.getDiff(repoPath, !hasFrom && isHead(to) ? "" : to, emptyTree, options, _cancellation);
|
|
90
90
|
return retried != null ? {
|
|
@@ -103,12 +103,6 @@ var DiffGitSubProvider = class {
|
|
|
103
103
|
notation: options?.notation
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
|
-
/** Whether `ex` is git failing to resolve `HEAD` because the repository has no commit yet */
|
|
107
|
-
async isUnbornHeadFailure(repoPath, ex) {
|
|
108
|
-
const ref = GitErrors.badRevision.exec(String(ex))?.[1];
|
|
109
|
-
if (!isHead(ref)) return false;
|
|
110
|
-
return await this.provider.refs.validateReference(repoPath, "HEAD", { force: true }) == null;
|
|
111
|
-
}
|
|
112
106
|
async getParsedDiff(repoPath, to, from, options, cancellation) {
|
|
113
107
|
const diff = await this.getDiff(repoPath, to, from, options, cancellation);
|
|
114
108
|
if (!diff?.contents) return void 0;
|
|
@@ -138,7 +132,7 @@ var DiffGitSubProvider = class {
|
|
|
138
132
|
}, "diff", "--numstat", "--summary", `-M${similarityThreshold == null ? "" : `${similarityThreshold}%`}`, "--no-ext-diff", "-z", options?.filters?.length ? `--diff-filter=${options.filters.join("")}` : void 0, ref1OrRange ? ref1OrRange : void 0, ref2 ? ref2 : void 0, "--", options?.path ? options.path : void 0);
|
|
139
133
|
const files = result.stdout ? parseGitDiffNumStatFiles(result.stdout, repoPath) ?? [] : [];
|
|
140
134
|
if (options?.includeUntracked && ref2 == null && typeof ref1OrRange === "string" && !isRevisionRange(ref1OrRange) && !isUncommittedStaged(ref1OrRange) && filtersAllowUntracked(options.filters) && !isNonExactPathspec(options.path)) {
|
|
141
|
-
const untracked = await this.
|
|
135
|
+
const untracked = await this.getUntrackedFilesForDiff(repoPath, options.errors);
|
|
142
136
|
if (untracked.length) {
|
|
143
137
|
const seen = new Set(files.map((f) => f.path));
|
|
144
138
|
for (const file of untracked) {
|
|
@@ -154,6 +148,18 @@ var DiffGitSubProvider = class {
|
|
|
154
148
|
return;
|
|
155
149
|
}
|
|
156
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* The untracked files a working-tree diff folds in; outside `errors: 'throw'`, a failed listing adds nothing. The diff
|
|
153
|
+
* reads take no cancellation, so a `CancellationError` here is a timeout and degrades like any other failure.
|
|
154
|
+
*/
|
|
155
|
+
async getUntrackedFilesForDiff(repoPath, errors) {
|
|
156
|
+
try {
|
|
157
|
+
return await this.provider.status?.getUntrackedFiles?.(repoPath) ?? [];
|
|
158
|
+
} catch (ex) {
|
|
159
|
+
if (errors === "throw") throw ex;
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
157
163
|
async getDiffTool(repoPath) {
|
|
158
164
|
return await this.provider.config.getConfig?.(repoPath, "diff.guitool", { runGitLocally: true }) ?? this.provider.config.getConfig?.(repoPath, "diff.tool", { runGitLocally: true });
|
|
159
165
|
}
|
|
@@ -616,6 +622,12 @@ function isWorkingTreeComparison(to, from) {
|
|
|
616
622
|
function isHead(ref) {
|
|
617
623
|
return ref?.toUpperCase() === "HEAD";
|
|
618
624
|
}
|
|
625
|
+
/** Whether `ex` is git failing to resolve `HEAD` because the repository has no commit yet */
|
|
626
|
+
async function isUnbornHeadFailure(provider, repoPath, ex) {
|
|
627
|
+
const ref = GitErrors.badRevision.exec(String(ex))?.[1];
|
|
628
|
+
if (!isHead(ref)) return false;
|
|
629
|
+
return await provider.refs.validateReference(repoPath, "HEAD", { force: true }) == null;
|
|
630
|
+
}
|
|
619
631
|
function prepareToFromDiffArgs(to, from, args, notation) {
|
|
620
632
|
if (to === "0000000000000000000000000000000000000000") {
|
|
621
633
|
if (from != null) args.push(from);
|