@gitkraken/core-gitlens 0.15.7 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/dist/git/cache.d.ts +13 -0
  3. package/dist/git/cache.js +45 -8
  4. package/dist/git/cache.js.map +1 -1
  5. package/dist/git/features.d.ts +1 -1
  6. package/dist/git/features.js +1 -0
  7. package/dist/git/features.js.map +1 -1
  8. package/dist/git/providers/branches.d.ts +29 -0
  9. package/dist/git/run.types.d.ts +3 -0
  10. package/dist/git/service.d.ts +4 -2
  11. package/dist/git/service.js +6 -4
  12. package/dist/git/service.js.map +1 -1
  13. package/dist/git/watching/classifyChange.js +3 -0
  14. package/dist/git/watching/classifyChange.js.map +1 -1
  15. package/dist/git/watching/watchSession.d.ts +2 -0
  16. package/dist/git/watching/watchSession.js +9 -1
  17. package/dist/git/watching/watchSession.js.map +1 -1
  18. package/dist/git/watching/worktreeSummary.d.ts +19 -4
  19. package/dist/git/watching/worktreeSummary.js +121 -36
  20. package/dist/git/watching/worktreeSummary.js.map +1 -1
  21. package/dist/git-cli/cliGitProvider.d.ts +1 -1
  22. package/dist/git-cli/cliGitProvider.js +8 -5
  23. package/dist/git-cli/cliGitProvider.js.map +1 -1
  24. package/dist/git-cli/exec/commandClassifier.d.ts +18 -3
  25. package/dist/git-cli/exec/commandClassifier.js +562 -16
  26. package/dist/git-cli/exec/commandClassifier.js.map +1 -1
  27. package/dist/git-cli/exec/exec.d.ts +2 -2
  28. package/dist/git-cli/exec/git.d.ts +31 -4
  29. package/dist/git-cli/exec/git.js +105 -43
  30. package/dist/git-cli/exec/git.js.map +1 -1
  31. package/dist/git-cli/exec/headState.d.ts +32 -0
  32. package/dist/git-cli/exec/headState.js +78 -0
  33. package/dist/git-cli/exec/headState.js.map +1 -0
  34. package/dist/git-cli/providers/branches.d.ts +50 -0
  35. package/dist/git-cli/providers/branches.js +294 -25
  36. package/dist/git-cli/providers/branches.js.map +1 -1
  37. package/dist/git-cli/providers/config.js +3 -2
  38. package/dist/git-cli/providers/config.js.map +1 -1
  39. package/dist/git-cli/providers/operations.d.ts +6 -7
  40. package/dist/git-cli/providers/operations.js +46 -64
  41. package/dist/git-cli/providers/operations.js.map +1 -1
  42. package/dist/git-cli/providers/refs.d.ts +4 -1
  43. package/dist/git-cli/providers/refs.js +13 -9
  44. package/dist/git-cli/providers/refs.js.map +1 -1
  45. package/dist/git-cli/providers/revision.js +1 -1
  46. package/dist/git-cli/providers/stash.js +1 -1
  47. package/dist/git-cli/providers/worktrees.js +23 -6
  48. package/dist/git-cli/providers/worktrees.js.map +1 -1
  49. package/dist/git-cli/service.d.ts +3 -0
  50. package/dist/git-cli/service.js +1 -0
  51. package/dist/git-cli/service.js.map +1 -1
  52. package/dist/utils/env/node/exec.d.ts +38 -1
  53. package/dist/utils/env/node/exec.js +14 -6
  54. package/dist/utils/env/node/exec.js.map +1 -1
  55. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"commandClassifier.js","names":[],"sources":["../../../../git-cli/src/exec/commandClassifier.ts"],"sourcesContent":["import { isAbsolute, join } from 'node:path';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\n\n/**\n * Verbs that never move a ref, the index or the working tree, so a raw run needs no notification.\n * Anything not listed is treated as a mutation: a needless notification costs a full cache eviction, a\n * missed one serves stale state. Object-writing plumbing (`hash-object -w`, `mktree`, `commit-tree`,\n * `write-tree`) is listed too: it only adds loose objects nothing cached observes.\n */\nconst readOnlyVerbs = new Set([\n\t'annotate',\n\t'archive',\n\t'blame',\n\t'cat-file',\n\t'check-attr',\n\t'check-ignore',\n\t'check-mailmap',\n\t'check-ref-format',\n\t'cherry',\n\t'commit-tree',\n\t'count-objects',\n\t'describe',\n\t'diff',\n\t'diff-files',\n\t'diff-index',\n\t'diff-tree',\n\t'for-each-ref',\n\t'fsck',\n\t'grep',\n\t'hash-object',\n\t'help',\n\t'log',\n\t'ls-files',\n\t// Asks a remote what it has; nothing local moves.\n\t'ls-remote',\n\t'ls-tree',\n\t'merge-base',\n\t'merge-tree',\n\t'mktree',\n\t'name-rev',\n\t'patch-id',\n\t'range-diff',\n\t'rev-list',\n\t'rev-parse',\n\t'shortlog',\n\t'show',\n\t'show-branch',\n\t'show-ref',\n\t'status',\n\t'var',\n\t'verify-commit',\n\t'verify-pack',\n\t'verify-tag',\n\t'version',\n\t'whatchanged',\n\t'write-tree',\n]);\n\nconst reflogWriteSubcommands: ReadonlySet<string> = new Set(['expire', 'delete', 'drop']);\n\n/**\n * Sub-commands of otherwise-mutating verbs that only list. `''` is the bare verb, which lists for `branch`,\n * `tag`, `remote` and `notes`; `branch -v` and every `tag` filter imply git's own list mode.\n */\nconst readOnlySubcommands: Readonly<Record<string, ReadonlySet<string>>> = {\n\tbranch: new Set([\n\t\t'',\n\t\t'-l',\n\t\t'--list',\n\t\t'--show-current',\n\t\t'-a',\n\t\t'-r',\n\t\t'-v',\n\t\t'-vv',\n\t\t'--verbose',\n\t\t'--contains',\n\t\t'--no-contains',\n\t\t'--merged',\n\t\t'--no-merged',\n\t\t'--points-at',\n\t]),\n\tconfig: new Set(['get', 'list']),\n\tnotes: new Set(['', 'list', 'show', 'get-ref']),\n\tstash: new Set(['list', 'show']),\n\ttag: new Set([\n\t\t'',\n\t\t'-l',\n\t\t'--list',\n\t\t'-n',\n\t\t'-v',\n\t\t'--verify',\n\t\t'--contains',\n\t\t'--no-contains',\n\t\t'--merged',\n\t\t'--no-merged',\n\t\t'--points-at',\n\t]),\n\tworktree: new Set(['list']),\n\tremote: new Set(['', '-v', 'get-url', 'show']),\n};\n\n/**\n * Options that make an argv write whatever else it contains, checked across the whole argv rather than\n * only its first token: `branch -r -d origin/x` leads with a listing flag and still deletes.\n */\nconst writeOptions: Readonly<Record<string, readonly string[]>> = {\n\tbranch: [\n\t\t'-d',\n\t\t'-D',\n\t\t'--delete',\n\t\t'-m',\n\t\t'-M',\n\t\t'--move',\n\t\t'-c',\n\t\t'-C',\n\t\t'--copy',\n\t\t'-f',\n\t\t'--force',\n\t\t'-t',\n\t\t'--track',\n\t\t'--no-track',\n\t\t'-u',\n\t\t'--set-upstream-to',\n\t\t'--unset-upstream',\n\t\t'--edit-description',\n\t],\n\tconfig: [\n\t\t'--add',\n\t\t'--replace-all',\n\t\t'--unset',\n\t\t'--unset-all',\n\t\t'--rename-section',\n\t\t'--remove-section',\n\t\t'-e',\n\t\t'--edit',\n\t],\n};\n\nconst configReadOptions = new Set([\n\t'--get',\n\t'--get-all',\n\t'--get-regexp',\n\t'--get-urlmatch',\n\t'--get-color',\n\t'--get-colorbool',\n\t'--list',\n\t'-l',\n]);\n\nfunction hasWriteOption(verb: string, rest: readonly string[]): boolean {\n\tconst options = writeOptions[verb];\n\tif (options == null) return false;\n\treturn hasOption(rest, options);\n}\n\nfunction hasOption(rest: readonly string[], options: readonly string[]): boolean {\n\treturn rest.some(arg => options.some(opt => arg === opt || arg.startsWith(`${opt}=`)));\n}\n\n/**\n * `config <key>` with nothing after the key is git's own read form, as is any `--get*`/`--list`. `config edit`\n * (git 2.46's subcommand form of `--edit`) also has a single non-flag argument but writes.\n */\nfunction isConfigRead(rest: readonly string[]): boolean {\n\tif (rest[0] === 'edit') return false;\n\tif (rest.some(arg => configReadOptions.has(arg))) return true;\n\n\treturn rest.filter(arg => !arg.startsWith('-')).length === 1;\n}\n\n/** Global options whose value is the next argument, so the verb scan must skip both. */\nconst globalOptionsWithValue = new Set([\n\t'-c',\n\t'--config-env',\n\t'--exec-path',\n\t'--git-dir',\n\t'--namespace',\n\t'--super-prefix',\n\t'--work-tree',\n]);\n\nexport interface LeadingCommand {\n\tverb: string;\n\treadOnly: boolean;\n\t/** The first token after the verb, unresolved — used for subcommand-shaped decisions (`worktree add`). */\n\tsubcommand?: string;\n\t/** Every token after the verb */\n\trest: readonly string[];\n\t/** The `-C <path>` target when the caller re-scopes the command to another working tree. */\n\tpathOverride?: string;\n}\n\n/**\n * Skips the global options (`-c key=val`, `-C path`) git accepts before the verb to find it, and notes a\n * `-C` re-scope so notification targets that tree.\n */\nexport function leadingCommand(args: readonly string[]): LeadingCommand {\n\tlet pathOverride: string | undefined;\n\tlet i = 0;\n\twhile (i < args.length) {\n\t\tconst arg = args[i];\n\t\tif (arg === '-C') {\n\t\t\t// git applies each `-C` relative to the one before it\n\t\t\tconst path = args[i + 1];\n\t\t\tif (path != null) {\n\t\t\t\tpathOverride = pathOverride == null || isAbsolute(path) ? path : join(pathOverride, path);\n\t\t\t}\n\t\t\ti += 2;\n\n\t\t\tcontinue;\n\t\t}\n\t\tif (globalOptionsWithValue.has(arg)) {\n\t\t\ti += 2;\n\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith('-')) {\n\t\t\ti += 1;\n\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\tconst verb = args[i] ?? '';\n\tconst rest = args.slice(i + 1);\n\tconst readOnly =\n\t\t!hasWriteOption(verb, rest) &&\n\t\t(readOnlyVerbs.has(verb) ||\n\t\t\t(readOnlySubcommands[verb]?.has(rest[0] ?? '') ?? false) ||\n\t\t\t(verb === 'config' && isConfigRead(rest)) ||\n\t\t\t// Every `reflog` form reads (bare, `<ref>`, `show`, `list`, `exists`) except the three that rewrite\n\t\t\t// it. Base-branch detection answers \"none\" unless a branch's reflog has exactly one creation entry,\n\t\t\t// so a rewrite can make a cached \"none\" derivable; no change kind names a reflog, so it resets all.\n\t\t\t(verb === 'reflog' && !reflogWriteSubcommands.has(rest[0] ?? '')) ||\n\t\t\t// A bare `symbolic-ref <name>` reads; a second non-flag argument, or a delete, writes.\n\t\t\t(verb === 'symbolic-ref' &&\n\t\t\t\t!rest.includes('-d') &&\n\t\t\t\t!rest.includes('--delete') &&\n\t\t\t\trest.filter(a => !a.startsWith('-')).length < 2));\n\n\treturn { verb: verb, readOnly: readOnly, subcommand: rest[0], rest: rest, pathOverride: pathOverride };\n}\n\n/**\n * The change kinds every worktree sharing a `.git` sees: its refs, stash, worktree list and config. The rest a\n * classified verb announces — HEAD, the index, a paused operation, FETCH_HEAD — belong to the one tree the\n * command ran in, so a `-C`-scoped write tells the caller's own `cwd` only this subset of what it changed.\n */\nexport const worktreeSharedChanges: ReadonlySet<RepositoryChange> = new Set([\n\t'heads',\n\t'tags',\n\t'stash',\n\t'remotes',\n\t'worktrees',\n\t'config',\n]);\n\n/**\n * Verbs whose effect is confined to the object store that nothing cached observes — repacking or pruning\n * `.git/objects` changes no cached read (branches, refs, status, worktrees, …). `init` and `clone` create a\n * repository rather than mutate a registered one, so there is nothing yet registered to notify.\n */\nconst objectOnlyVerbs = new Set([\n\t'gc',\n\t'repack',\n\t'prune',\n\t'maintenance',\n\t'commit-graph',\n\t'multi-pack-index',\n\t'init',\n\t'clone',\n]);\n\n/**\n * The {@link RepositoryChange} kinds each mutating verb announces. A worktree subcommand other than a\n * listing is handled separately (see {@link getChangesForCommand}), and any verb absent from both this\n * table and {@link objectOnlyVerbs} announces `[]` — the conservative default for an unclassified\n * mutation: the caller still learns something changed, just not what. An entry covers at least what the\n * verb's typed mutator announces; `update-ref` and `symbolic-ref` name every kind their target ref could be.\n * The kinds decide which caches the announcement resets, so a verb that can start or end a paused operation\n * names `pausedOp`: `commit` concludes a merge, cherry-pick or revert, `reset` aborts one, and `am` runs in\n * `rebase-apply`.\n */\nconst changesByVerb: Readonly<Record<string, readonly RepositoryChange[]>> = {\n\tcommit: ['head', 'heads', 'index', 'pausedOp'],\n\tam: ['head', 'heads', 'index', 'pausedOp'],\n\tbisect: ['head', 'index'],\n\tcheckout: ['head', 'heads', 'index'],\n\tswitch: ['head', 'heads', 'index'],\n\treset: ['head', 'heads', 'index', 'pausedOp'],\n\tmerge: ['head', 'heads', 'index', 'pausedOp', 'merge'],\n\trebase: ['head', 'heads', 'index', 'pausedOp', 'rebase'],\n\t'cherry-pick': ['head', 'heads', 'index', 'pausedOp', 'cherryPick'],\n\trevert: ['head', 'heads', 'index', 'pausedOp', 'revert'],\n\tpull: ['head', 'heads', 'index', 'remotes', 'tags', 'lastFetched', 'pausedOp', 'merge', 'rebase'],\n\tadd: ['index'],\n\trm: ['index'],\n\tmv: ['index'],\n\trestore: ['index'],\n\tapply: ['index'],\n\t'read-tree': ['index'],\n\t'update-index': ['index'],\n\tclean: ['index'],\n\tstash: ['stash', 'index'],\n\t'update-ref': ['head', 'heads', 'remotes', 'tags', 'stash'],\n\tbranch: ['heads', 'remotes', 'tags'],\n\t'symbolic-ref': ['head', 'heads', 'remotes', 'tags'],\n\t'pack-refs': ['heads', 'remotes', 'tags'],\n\ttag: ['tags'],\n\t// A refspec can write a local branch (`fetch origin main:main`), which only the typed fetch parses for\n\tfetch: ['heads', 'remotes', 'tags', 'lastFetched'],\n\tpush: ['remotes'],\n\tremote: ['remotes', 'config'],\n\tconfig: ['config', 'heads', 'remotes'],\n\tnotes: ['heads'],\n};\n\n/**\n * `branch` options that write `.git/config`: a rename, copy or delete moves or drops the branch's section, and the\n * rest set or clear its upstream or description. A plain create (or `-f`) writes tracking only from a remote-tracking\n * start point, which the `.git/config` watcher reports.\n */\nconst branchConfigOptions: readonly string[] = [\n\t'-d',\n\t'-D',\n\t'--delete',\n\t'-m',\n\t'-M',\n\t'--move',\n\t'-c',\n\t'-C',\n\t'--copy',\n\t'-t',\n\t'--track',\n\t'-u',\n\t'--set-upstream-to',\n\t'--unset-upstream',\n\t'--edit-description',\n];\nconst branchConfigChanges: readonly RepositoryChange[] = ['config', 'heads', 'remotes', 'tags'];\n\n/**\n * Whether creating a branch from `startPoint` may write its tracking to `.git/config`, as git's default\n * `branch.autoSetupMerge=true` does from a remote-tracking start point. Only a name holding a `/` can be one, so a\n * local name with a `/` counts too. The `.git/config` watcher reports what this misses, such as\n * `branch.autoSetupMerge=always`.\n */\nexport function mayWriteTracking(startPoint: string | undefined, noTracking: boolean | undefined): boolean {\n\tif (noTracking || !startPoint) return false;\n\tif (startPoint.startsWith('refs/')) return startPoint.startsWith('refs/remotes/');\n\n\treturn startPoint.includes('/');\n}\n\nconst worktreeChanges: readonly RepositoryChange[] = ['worktrees', 'heads'];\nconst emptyChanges: readonly RepositoryChange[] = [];\n\nexport interface CommandChanges {\n\tchanges: readonly RepositoryChange[];\n\t/** The `-C <path>` target when the caller re-scoped the command to another working tree. */\n\tpathOverride?: string;\n\t/** The subset of {@link changes} every worktree sharing the same `.git` sees, not just the tree the command ran in. */\n\tsharedChanges: readonly RepositoryChange[];\n}\n\n/**\n * Classifies a raw git argv for the notification `git.run`'s `notify: 'infer'` applies after the run\n * settles. Returns `undefined` for a read-only or object-only command — nothing to announce — otherwise\n * the {@link RepositoryChange} kinds the verb announces, the `-C` re-scope target (if any), and which of\n * those kinds every worktree sees.\n */\nexport function getChangesForCommand(args: readonly string[]): CommandChanges | undefined {\n\tconst command = leadingCommand(args);\n\tif (command.readOnly || objectOnlyVerbs.has(command.verb)) return undefined;\n\n\t// `worktree list` is read-only (filtered out above); every other subcommand adds, removes or\n\t// relocks a checkout, which is both a worktree-list change and, for `add`, a brand-new HEAD.\n\tlet changes: readonly RepositoryChange[];\n\tif (command.verb === 'worktree') {\n\t\tchanges = worktreeChanges;\n\t} else if (command.verb === 'branch' && hasOption(command.rest, branchConfigOptions)) {\n\t\tchanges = branchConfigChanges;\n\t} else {\n\t\tchanges = changesByVerb[command.verb] ?? emptyChanges;\n\t}\n\treturn {\n\t\tchanges: changes,\n\t\tpathOverride: command.pathOverride,\n\t\tsharedChanges: changes.filter(c => worktreeSharedChanges.has(c)),\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"commandClassifier.js","names":[],"sources":["../../../../git-cli/src/exec/commandClassifier.ts"],"sourcesContent":["import { isAbsolute, join } from 'node:path';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\nimport { getRefChangeKind } from '@gitlens/git/watching/changeEvent.js';\n\n/**\n * Verbs that never move a ref, the index or the working tree, so a raw run needs no notification.\n * Anything not listed is treated as a mutation: a needless notification costs a full cache eviction, a\n * missed one serves stale state. Object-writing plumbing (`hash-object -w`, `mktree`, `commit-tree`,\n * `write-tree`) is listed too: it only adds loose objects nothing cached observes.\n */\nconst readOnlyVerbs = new Set([\n\t'annotate',\n\t'archive',\n\t'blame',\n\t'cat-file',\n\t'check-attr',\n\t'check-ignore',\n\t'check-mailmap',\n\t'check-ref-format',\n\t'cherry',\n\t'commit-tree',\n\t'count-objects',\n\t'describe',\n\t'diff',\n\t'diff-files',\n\t'diff-index',\n\t'diff-tree',\n\t'for-each-ref',\n\t'fsck',\n\t'grep',\n\t'hash-object',\n\t'help',\n\t'log',\n\t'ls-files',\n\t// Asks a remote what it has; nothing local moves.\n\t'ls-remote',\n\t'ls-tree',\n\t'merge-base',\n\t'merge-tree',\n\t'mktree',\n\t'name-rev',\n\t'patch-id',\n\t'range-diff',\n\t'rev-list',\n\t'rev-parse',\n\t'shortlog',\n\t'show',\n\t'show-branch',\n\t'show-ref',\n\t'status',\n\t'var',\n\t'verify-commit',\n\t'verify-pack',\n\t'verify-tag',\n\t'version',\n\t'whatchanged',\n\t'write-tree',\n]);\n\nconst reflogWriteSubcommands: ReadonlySet<string> = new Set(['expire', 'delete', 'drop']);\n\n/**\n * Sub-commands of otherwise-mutating verbs that only list. `''` is the bare verb, which lists for `branch`,\n * `tag`, `remote` and `notes`; `branch -v` and every `tag` filter imply git's own list mode.\n */\nconst readOnlySubcommands: Readonly<Record<string, ReadonlySet<string>>> = {\n\tbranch: new Set([\n\t\t'',\n\t\t'-l',\n\t\t'--list',\n\t\t'--show-current',\n\t\t'-a',\n\t\t'-r',\n\t\t'-v',\n\t\t'-vv',\n\t\t'--verbose',\n\t\t'--contains',\n\t\t'--no-contains',\n\t\t'--merged',\n\t\t'--no-merged',\n\t\t'--points-at',\n\t]),\n\tconfig: new Set(['get', 'list']),\n\tnotes: new Set(['', 'list', 'show', 'get-ref']),\n\t// `stash create` writes a commit object and prints it; no ref moves\n\tstash: new Set(['list', 'show', 'create']),\n\ttag: new Set([\n\t\t'',\n\t\t'-l',\n\t\t'--list',\n\t\t'-n',\n\t\t'-v',\n\t\t'--verify',\n\t\t'--contains',\n\t\t'--no-contains',\n\t\t'--merged',\n\t\t'--no-merged',\n\t\t'--points-at',\n\t]),\n\tworktree: new Set(['list']),\n\tremote: new Set(['', '-v', 'get-url', 'show']),\n};\n\n/**\n * Options that make an argv write whatever else it contains, checked across the whole argv rather than\n * only its first token: `branch -r -d origin/x` leads with a listing flag and still deletes.\n */\nconst writeOptions: Readonly<Record<string, readonly string[]>> = {\n\tbranch: [\n\t\t'-d',\n\t\t'-D',\n\t\t'--delete',\n\t\t'-m',\n\t\t'-M',\n\t\t'--move',\n\t\t'-c',\n\t\t'-C',\n\t\t'--copy',\n\t\t'-f',\n\t\t'--force',\n\t\t'-t',\n\t\t'--track',\n\t\t'--no-track',\n\t\t'-u',\n\t\t'--set-upstream-to',\n\t\t'--unset-upstream',\n\t\t'--edit-description',\n\t],\n\tconfig: [\n\t\t'--add',\n\t\t'--replace-all',\n\t\t'--unset',\n\t\t'--unset-all',\n\t\t'--rename-section',\n\t\t'--remove-section',\n\t\t'-e',\n\t\t'--edit',\n\t],\n};\n\nconst configReadOptions = new Set([\n\t'--get',\n\t'--get-all',\n\t'--get-regexp',\n\t'--get-urlmatch',\n\t'--get-color',\n\t'--get-colorbool',\n\t'--list',\n\t'-l',\n]);\n\nfunction hasWriteOption(verb: string, rest: readonly string[]): boolean {\n\tconst options = writeOptions[verb];\n\tif (options == null) return false;\n\treturn hasOption(rest, options);\n}\n\nfunction hasOption(rest: readonly string[], options: readonly string[]): boolean {\n\treturn rest.some(arg => options.some(opt => arg === opt || arg.startsWith(`${opt}=`)));\n}\n\n/**\n * `config <key>` with nothing after the key is git's own read form, as is any `--get*`/`--list`. `config edit`\n * (git 2.46's subcommand form of `--edit`) also has a single non-flag argument but writes.\n */\nfunction isConfigRead(rest: readonly string[]): boolean {\n\tif (rest[0] === 'edit') return false;\n\tif (rest.some(arg => configReadOptions.has(arg))) return true;\n\n\treturn rest.filter(arg => !arg.startsWith('-')).length === 1;\n}\n\n/** Global options whose value is the next argument, so the verb scan must skip both. */\nconst globalOptionsWithValue = new Set([\n\t'-c',\n\t'--config-env',\n\t'--exec-path',\n\t'--git-dir',\n\t'--namespace',\n\t'--super-prefix',\n\t'--work-tree',\n]);\n\nexport interface LeadingCommand {\n\tverb: string;\n\treadOnly: boolean;\n\t/** The first token after the verb, unresolved — used for subcommand-shaped decisions (`worktree add`). */\n\tsubcommand?: string;\n\t/** Every token after the verb */\n\trest: readonly string[];\n\t/** The `-C <path>` target when the caller re-scopes the command to another working tree. */\n\tpathOverride?: string;\n\t/** Each `-c <key>[=<value>]` given before the verb, in order */\n\tconfigs?: readonly string[];\n}\n\n/**\n * Skips the global options (`-c key=val`, `-C path`) git accepts before the verb to find it, and notes a\n * `-C` re-scope so notification targets that tree.\n */\nexport function leadingCommand(args: readonly string[]): LeadingCommand {\n\tlet pathOverride: string | undefined;\n\tlet configs: string[] | undefined;\n\tlet i = 0;\n\twhile (i < args.length) {\n\t\tconst arg = args[i];\n\t\tif (arg === '-C') {\n\t\t\t// git applies each `-C` relative to the one before it\n\t\t\tconst path = args[i + 1];\n\t\t\tif (path != null) {\n\t\t\t\tpathOverride = pathOverride == null || isAbsolute(path) ? path : join(pathOverride, path);\n\t\t\t}\n\t\t\ti += 2;\n\n\t\t\tcontinue;\n\t\t}\n\t\tif (globalOptionsWithValue.has(arg)) {\n\t\t\tif (arg === '-c' && args[i + 1] != null) {\n\t\t\t\t(configs ??= []).push(args[i + 1]);\n\t\t\t}\n\t\t\ti += 2;\n\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith('-')) {\n\t\t\ti += 1;\n\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\tconst verb = args[i] ?? '';\n\tconst rest = args.slice(i + 1);\n\tconst readOnly =\n\t\t!hasWriteOption(verb, rest) &&\n\t\t(readOnlyVerbs.has(verb) ||\n\t\t\t(readOnlySubcommands[verb]?.has(rest[0] ?? '') ?? false) ||\n\t\t\t(verb === 'config' && isConfigRead(rest)) ||\n\t\t\t// Every `reflog` form reads (bare, `<ref>`, `show`, `list`, `exists`) except the three that rewrite\n\t\t\t// it. Base-branch detection answers \"none\" unless a branch's reflog has exactly one creation entry,\n\t\t\t// so a rewrite can make a cached \"none\" derivable; no change kind names a reflog, so it resets all.\n\t\t\t(verb === 'reflog' && !reflogWriteSubcommands.has(rest[0] ?? '')) ||\n\t\t\t// A bare `symbolic-ref <name>` reads; a second non-flag argument, or a delete, writes.\n\t\t\t(verb === 'symbolic-ref' &&\n\t\t\t\t!rest.includes('-d') &&\n\t\t\t\t!rest.includes('--delete') &&\n\t\t\t\trest.filter(a => !a.startsWith('-')).length < 2));\n\n\treturn {\n\t\tverb: verb,\n\t\treadOnly: readOnly,\n\t\tsubcommand: rest[0],\n\t\trest: rest,\n\t\tpathOverride: pathOverride,\n\t\tconfigs: configs,\n\t};\n}\n\n/**\n * The change kinds every worktree sharing a `.git` sees: its refs, stash, worktree list and config. The rest a\n * classified verb announces — HEAD, the index, a paused operation, FETCH_HEAD — belong to the one tree the\n * command ran in, so a `-C`-scoped write tells the caller's own `cwd` only this subset of what it changed.\n */\nexport const worktreeSharedChanges: ReadonlySet<RepositoryChange> = new Set([\n\t'heads',\n\t'tags',\n\t'stash',\n\t'remotes',\n\t'worktrees',\n\t'config',\n]);\n\n/**\n * Verbs whose effect is confined to the object store that nothing cached observes — repacking or pruning\n * `.git/objects` changes no cached read (branches, refs, status, worktrees, …). `init` and `clone` create a\n * repository rather than mutate a registered one, so there is nothing yet registered to notify.\n */\nconst objectOnlyVerbs = new Set([\n\t'gc',\n\t'repack',\n\t'prune',\n\t'maintenance',\n\t'commit-graph',\n\t'multi-pack-index',\n\t'init',\n\t'clone',\n]);\n\n/**\n * The {@link RepositoryChange} kinds each mutating verb announces. A worktree subcommand other than a\n * listing is handled separately (see {@link getChangesForCommand}), and any verb absent from both this\n * table and {@link objectOnlyVerbs} announces `[]` — the conservative default for an unclassified\n * mutation: the caller still learns something changed, just not what. An entry covers at least what the\n * verb's typed mutator announces; `update-ref` and `symbolic-ref` name every kind their target ref could be.\n * {@link getNamedChanges} narrows the forms whose argv proves what moved, which can announce less: the typed\n * checkout announces `heads` for any target, but a `--detach` or full-SHA checkout moves only this tree's HEAD,\n * no shared ref.\n * The kinds decide which caches the announcement resets, so a verb that can start or end a paused operation\n * names `pausedOp`: `commit` concludes a merge, cherry-pick or revert, `reset` aborts one, and `am` runs in\n * `rebase-apply`.\n */\nconst changesByVerb: Readonly<Record<string, readonly RepositoryChange[]>> = {\n\tcommit: ['head', 'heads', 'index', 'pausedOp'],\n\tam: ['head', 'heads', 'index', 'pausedOp'],\n\tbisect: ['head', 'index'],\n\tcheckout: ['head', 'heads', 'index'],\n\tswitch: ['head', 'heads', 'index'],\n\treset: ['head', 'heads', 'index', 'pausedOp'],\n\tmerge: ['head', 'heads', 'index', 'pausedOp', 'merge'],\n\trebase: ['head', 'heads', 'index', 'pausedOp', 'rebase'],\n\t'cherry-pick': ['head', 'heads', 'index', 'pausedOp', 'cherryPick'],\n\trevert: ['head', 'heads', 'index', 'pausedOp', 'revert'],\n\tpull: ['head', 'heads', 'index', 'remotes', 'tags', 'lastFetched', 'pausedOp', 'merge', 'rebase'],\n\tadd: ['index'],\n\trm: ['index'],\n\tmv: ['index'],\n\trestore: ['index'],\n\tapply: ['index'],\n\t'read-tree': ['index'],\n\t'update-index': ['index'],\n\tclean: ['index'],\n\tstash: ['stash', 'index'],\n\t'update-ref': ['head', 'heads', 'remotes', 'tags', 'stash'],\n\tbranch: ['heads', 'remotes'],\n\t'symbolic-ref': ['head', 'heads', 'remotes', 'tags'],\n\t'pack-refs': ['heads', 'remotes', 'tags'],\n\ttag: ['tags'],\n\t// A refspec can write a local branch (`fetch origin main:main`), which only the typed fetch parses for\n\tfetch: ['heads', 'remotes', 'tags', 'lastFetched'],\n\tpush: ['remotes'],\n\tremote: ['remotes', 'config'],\n\tconfig: ['config', 'heads', 'remotes'],\n\tnotes: ['heads'],\n};\n\n/**\n * `branch` options that write `.git/config`: a rename, copy or delete moves or drops the branch's section, and the\n * rest set or clear its upstream or description. A plain create (or `-f`) writes tracking only from a remote-tracking\n * start point, which the `.git/config` watcher reports.\n */\nconst branchConfigOptions: readonly string[] = [\n\t'-d',\n\t'-D',\n\t'--delete',\n\t'-m',\n\t'-M',\n\t'--move',\n\t'-c',\n\t'-C',\n\t'--copy',\n\t'-t',\n\t'--track',\n\t'-u',\n\t'--set-upstream-to',\n\t'--unset-upstream',\n\t'--edit-description',\n];\nconst branchConfigChanges: readonly RepositoryChange[] = ['config', 'heads', 'remotes'];\n\n/**\n * Whether creating a branch from `startPoint` may write its tracking to `.git/config`, as git's default\n * `branch.autoSetupMerge=true` does from a remote-tracking start point. Only a name holding a `/` can be one, so a\n * local name with a `/` counts too. The `.git/config` watcher reports what this misses, such as\n * `branch.autoSetupMerge=always`.\n */\nexport function mayWriteTracking(startPoint: string | undefined, noTracking: boolean | undefined): boolean {\n\tif (noTracking || !startPoint) return false;\n\tif (startPoint.startsWith('refs/')) return startPoint.startsWith('refs/remotes/');\n\n\treturn startPoint.includes('/');\n}\n\nconst worktreeChanges: readonly RepositoryChange[] = ['worktrees', 'heads'];\nconst emptyChanges: readonly RepositoryChange[] = [];\n\nexport interface CommandChanges {\n\tchanges: readonly RepositoryChange[];\n\t/** The `-C <path>` target when the caller re-scoped the command to another working tree. */\n\tpathOverride?: string;\n\t/** The subset of {@link changes} every worktree sharing the same `.git` sees, not just the tree the command ran in. */\n\tsharedChanges: readonly RepositoryChange[];\n\t/**\n\t * The full ref names the command creates, moves or deletes, when its argv proves them. A ref kind in\n\t * {@link changes} with a name of its kind here is fully described by those names, as `repository.onChanged`'s\n\t * `refs` are; a ref kind with none stays unnamed.\n\t */\n\trefs?: readonly string[];\n\t/** The command's `config` change touches only the `branch.<name>` sections of the local branches {@link refs} names */\n\tconfigConfinedToRefs?: boolean;\n\t/**\n\t * The command moves only the branch HEAD is on, or no branch when HEAD is detached, so `git.run` reads HEAD\n\t * before and after the run to name it.\n\t */\n\tmovesHeadBranch?: boolean;\n}\n\ntype NamedChanges = Omit<CommandChanges, 'pathOverride' | 'sharedChanges'>;\n\nconst configHeadsChanges: readonly RepositoryChange[] = ['config', 'heads'];\nconst headsChanges: readonly RepositoryChange[] = ['heads'];\nconst remotesChanges: readonly RepositoryChange[] = ['remotes'];\nconst tagsChanges: readonly RepositoryChange[] = ['tags'];\nconst stashChanges: readonly RepositoryChange[] = ['stash'];\nconst stashIndexChanges: readonly RepositoryChange[] = ['stash', 'index'];\nconst stashBranchChanges: readonly RepositoryChange[] = ['head', 'heads', 'index', 'stash'];\nconst indexChanges: readonly RepositoryChange[] = ['index'];\nconst headHeadsChanges: readonly RepositoryChange[] = ['head', 'heads'];\nconst headIndexChanges: readonly RepositoryChange[] = ['head', 'index'];\nconst checkoutChanges: readonly RepositoryChange[] = ['head', 'heads', 'index'];\nconst checkoutTrackingChanges: readonly RepositoryChange[] = ['config', 'head', 'heads', 'index'];\nconst worktreeOnlyChanges: readonly RepositoryChange[] = ['worktrees'];\nconst worktreeTrackingChanges: readonly RepositoryChange[] = ['config', 'worktrees', 'heads'];\n\nconst stashRefs: readonly string[] = ['refs/stash'];\n\n/** A full object name, which `checkout` and `worktree add` never DWIM into a new branch */\nconst fullShaRegex = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i;\n\n/**\n * Whether a branch name in argv is the branch it names. Git expands `@{-<n>}` (and `@`) wherever it takes a branch\n * name, `branch -d @{-1}` deleting the previous branch, and no ref name can hold `@{` or be `@`\n */\nfunction isLiteralBranchName(name: string): boolean {\n\treturn name !== '@' && !name.includes('@{');\n}\n\ninterface ParsedArgs {\n\t/** Each option in argv order, with its value when it takes one */\n\toptions: readonly (readonly [name: string, value: string | undefined])[];\n\t/** The non-option arguments, including those after `--` */\n\tpositionals: readonly string[];\n\t/** Where `--` fell in {@link positionals}, for the verbs that take pathspecs after it */\n\tdashDash?: number;\n}\n\n/**\n * Splits a verb's arguments by its own option table, since one letter means different things to different verbs\n * (`-m` moves, merges or sets a message). An option outside the table returns `undefined` rather than a guess at\n * whether it takes a value. A valued option accepts `--opt=<v>`, `--opt <v>`, `-o <v>` and `-o<v>`.\n */\nfunction parseArgs(\n\targs: readonly string[],\n\tflags: ReadonlySet<string>,\n\tvalued: ReadonlySet<string>,\n): ParsedArgs | undefined {\n\tconst options: [string, string | undefined][] = [];\n\tconst positionals: string[] = [];\n\tlet dashDash: number | undefined;\n\tlet optionsEnded = false;\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\t// Still a pathspec separator after `--end-of-options`, as `checkout` and `reset` read it\n\t\tif (arg === '--' && dashDash == null) {\n\t\t\tdashDash = positionals.length;\n\t\t\toptionsEnded = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (optionsEnded || arg === '-' || !arg.startsWith('-')) {\n\t\t\tpositionals.push(arg);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === '--end-of-options') {\n\t\t\toptionsEnded = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (flags.has(arg)) {\n\t\t\toptions.push([arg, undefined]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (valued.has(arg)) {\n\t\t\tconst value = args[i + 1];\n\t\t\tif (value == null) return undefined;\n\n\t\t\toptions.push([arg, value]);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst long = arg.startsWith('--');\n\t\tconst name = long ? arg.split('=', 1)[0] : arg.slice(0, 2);\n\t\tif (name === arg || !valued.has(name)) return undefined;\n\n\t\toptions.push([name, arg.slice(long ? name.length + 1 : name.length)]);\n\t}\n\treturn { options: options, positionals: positionals, dashDash: dashDash };\n}\n\nfunction hasParsedOption(parsed: ParsedArgs, ...names: string[]): boolean {\n\treturn parsed.options.some(([option]) => names.includes(option));\n}\n\nconst updateRefFlags: ReadonlySet<string> = new Set(['-d', '--delete', '--no-deref', '--create-reflog']);\nconst updateRefValued: ReadonlySet<string> = new Set(['-m', '--message']);\n\n/**\n * `update-ref` moves the one ref it names, or the ref a symbolic one points to without `--no-deref`, so `HEAD` and a\n * remote's `HEAD` stay unnamed. `null` means a ref outside the namespaces core reads, which the typed\n * `updateReference` doesn't announce either. `git log --all` (graph, search, contributors) does walk such a ref when\n * it points at a commit, and argv can't tell that from a blob ref, so a row it adds or drops can stay stale until the\n * next heads change: the trade the typed write makes not to refresh every worktree on each bookkeeping write. A packed\n * ref's delete rewrites `packed-refs`, which the watcher still reports.\n */\nfunction getUpdateRefChanges(args: readonly string[]): NamedChanges | null | undefined {\n\tconst parsed = parseArgs(args, updateRefFlags, updateRefValued);\n\tif (parsed == null) return undefined;\n\n\tconst [ref] = parsed.positionals;\n\tif (!ref) return undefined;\n\tif (ref === 'HEAD') return { changes: headHeadsChanges };\n\tif (!ref.startsWith('refs/')) return undefined;\n\tif (ref.endsWith('/HEAD') && !hasParsedOption(parsed, '--no-deref')) return undefined;\n\n\tconst kind = getRefChangeKind(ref);\n\tif (kind != null) return { changes: [kind], refs: [ref] };\n\t// The watcher reports `refs/replace` as heads, and `notes` announces heads too\n\tif (ref.startsWith('refs/replace/') || ref.startsWith('refs/notes/')) return { changes: headsChanges };\n\n\treturn null;\n}\n\nconst branchFlags: ReadonlySet<string> = new Set([\n\t'-f',\n\t'--force',\n\t'--no-track',\n\t'-d',\n\t'-D',\n\t'--delete',\n\t'-m',\n\t'-M',\n\t'--move',\n\t'-c',\n\t'-C',\n\t'--copy',\n\t'-r',\n\t'--remotes',\n\t'-q',\n\t'--quiet',\n\t'--create-reflog',\n]);\nconst noValuedOptions: ReadonlySet<string> = new Set();\n\n/**\n * The create, delete, rename and copy forms of `branch` name every branch they write. A delete removes a local\n * branch's `branch.<name>` section and a rename or copy moves it; a create writes it only for tracking.\n */\nfunction getBranchChanges(args: readonly string[]): NamedChanges | undefined {\n\tconst parsed = parseArgs(args, branchFlags, noValuedOptions);\n\tif (parsed == null) return undefined;\n\n\tlet mode: 'delete' | 'move' | undefined;\n\tlet remote = false;\n\tlet noTrack = false;\n\tfor (const [option] of parsed.options) {\n\t\tswitch (option) {\n\t\t\tcase '-d':\n\t\t\tcase '-D':\n\t\t\tcase '--delete':\n\t\t\t\tif (mode === 'move') return undefined;\n\n\t\t\t\tmode = 'delete';\n\t\t\t\tbreak;\n\t\t\tcase '-m':\n\t\t\tcase '-M':\n\t\t\tcase '--move':\n\t\t\tcase '-c':\n\t\t\tcase '-C':\n\t\t\tcase '--copy':\n\t\t\t\tif (mode === 'delete') return undefined;\n\n\t\t\t\tmode = 'move';\n\t\t\t\tbreak;\n\t\t\tcase '-r':\n\t\t\tcase '--remotes':\n\t\t\t\tremote = true;\n\t\t\t\tbreak;\n\t\t\tcase '--no-track':\n\t\t\t\tnoTrack = true;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst names = parsed.positionals;\n\tif (mode === 'delete') {\n\t\tif (!names.length || !names.every(isLiteralBranchName)) return undefined;\n\t\tif (remote) return { changes: remotesChanges, refs: names.map(n => `refs/remotes/${n}`) };\n\n\t\treturn { changes: configHeadsChanges, refs: names.map(n => `refs/heads/${n}`), configConfinedToRefs: true };\n\t}\n\tif (remote) return undefined;\n\n\tif (mode === 'move') {\n\t\t// With one name, git renames or copies the current branch, which argv doesn't name\n\t\tif (names.length !== 2 || !names.every(isLiteralBranchName)) return undefined;\n\n\t\treturn { changes: configHeadsChanges, refs: names.map(n => `refs/heads/${n}`), configConfinedToRefs: true };\n\t}\n\n\tif ((names.length !== 1 && names.length !== 2) || !isLiteralBranchName(names[0])) return undefined;\n\n\tconst refs = [`refs/heads/${names[0]}`];\n\tif (mayWriteTracking(names[1], noTrack)) {\n\t\treturn { changes: configHeadsChanges, refs: refs, configConfinedToRefs: true };\n\t}\n\treturn { changes: headsChanges, refs: refs };\n}\n\nconst tagFlags: ReadonlySet<string> = new Set([\n\t'-f',\n\t'--force',\n\t'-d',\n\t'--delete',\n\t'-a',\n\t'--annotate',\n\t'-s',\n\t'--sign',\n\t'--no-sign',\n\t'-e',\n\t'--edit',\n\t'--create-reflog',\n]);\nconst tagValued: ReadonlySet<string> = new Set(['-m', '--message', '-F', '--file', '-u', '--local-user', '--cleanup']);\n\nfunction getTagChanges(args: readonly string[]): NamedChanges | undefined {\n\tconst parsed = parseArgs(args, tagFlags, tagValued);\n\tif (parsed == null) return undefined;\n\n\tconst names = parsed.positionals;\n\tif (hasParsedOption(parsed, '-d', '--delete')) {\n\t\tif (!names.length) return undefined;\n\n\t\treturn { changes: tagsChanges, refs: names.map(n => `refs/tags/${n}`) };\n\t}\n\tif (names.length !== 1 && names.length !== 2) return undefined;\n\n\treturn { changes: tagsChanges, refs: [`refs/tags/${names[0]}`] };\n}\n\n/** The `worktree` subcommands other than `add` and `list`; none writes a branch */\nconst worktreeEditSubcommands: ReadonlySet<string> = new Set(['remove', 'prune', 'lock', 'unlock', 'move', 'repair']);\nconst worktreeAddFlags: ReadonlySet<string> = new Set([\n\t'-f',\n\t'--force',\n\t'-d',\n\t'--detach',\n\t'--checkout',\n\t'--no-checkout',\n\t'--lock',\n\t'-q',\n\t'--quiet',\n\t'--track',\n\t'--no-track',\n\t'--guess-remote',\n\t'--no-guess-remote',\n\t'--orphan',\n]);\nconst worktreeAddValued: ReadonlySet<string> = new Set(['-b', '-B', '--reason']);\n\n/**\n * `worktree add` is the only subcommand that can create a branch: the `-b`/`-B` one it names or, without either, one\n * git DWIMs from a short commit-ish (or from the path, given none), which argv can't name. A detached or full-SHA add\n * creates none.\n */\nfunction getWorktreeChanges(args: readonly string[]): NamedChanges | undefined {\n\tconst [subcommand, ...rest] = args;\n\tif (subcommand != null && worktreeEditSubcommands.has(subcommand)) return { changes: worktreeOnlyChanges };\n\tif (subcommand !== 'add') return undefined;\n\n\tconst parsed = parseArgs(rest, worktreeAddFlags, worktreeAddValued);\n\tif (parsed == null) return undefined;\n\n\tlet branch: string | undefined;\n\tlet detach = false;\n\tlet orphan = false;\n\tlet track: boolean | undefined;\n\tfor (const [option, value] of parsed.options) {\n\t\tswitch (option) {\n\t\t\tcase '-b':\n\t\t\tcase '-B':\n\t\t\t\tbranch = value;\n\t\t\t\tbreak;\n\t\t\tcase '-d':\n\t\t\tcase '--detach':\n\t\t\t\tdetach = true;\n\t\t\t\tbreak;\n\t\t\tcase '--orphan':\n\t\t\t\torphan = true;\n\t\t\t\tbreak;\n\t\t\tcase '--track':\n\t\t\t\ttrack = true;\n\t\t\t\tbreak;\n\t\t\tcase '--no-track':\n\t\t\t\ttrack = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst [path, commitish, ...extra] = parsed.positionals;\n\tif (orphan || path == null || extra.length) return undefined;\n\n\tif (branch) {\n\t\tif (!isLiteralBranchName(branch)) return undefined;\n\n\t\tconst refs = [`refs/heads/${branch}`];\n\t\t// An explicit `--track` writes tracking from a local start point too. Git may also write\n\t\t// `extensions.relativeWorktrees` (under `worktree.useRelativePaths`), which nothing a worktree shows reads, so\n\t\t// the change is still claimed confined: unlike the typed add, a raw run can't evict the config cache unannounced\n\t\tif (track === true || mayWriteTracking(commitish, track === false)) {\n\t\t\treturn { changes: worktreeTrackingChanges, refs: refs, configConfinedToRefs: true };\n\t\t}\n\t\treturn { changes: worktreeChanges, refs: refs };\n\t}\n\tif (detach || (commitish != null && fullShaRegex.test(commitish))) return { changes: worktreeOnlyChanges };\n\n\treturn undefined;\n}\n\nconst checkoutFlags: ReadonlySet<string> = new Set([\n\t'-q',\n\t'--quiet',\n\t'-f',\n\t'--force',\n\t'--detach',\n\t'--no-track',\n\t'-m',\n\t'--merge',\n\t'--progress',\n\t'--no-progress',\n\t'--ignore-other-worktrees',\n\t'--overwrite-ignore',\n\t'--no-overwrite-ignore',\n\t'--recurse-submodules',\n\t'--no-recurse-submodules',\n]);\nconst checkoutValued: ReadonlySet<string> = new Set(['-b', '-B']);\nconst switchFlags: ReadonlySet<string> = new Set([...checkoutFlags, '-d', '--discard-changes']);\nconst switchValued: ReadonlySet<string> = new Set(['-c', '-C', '--create', '--force-create']);\n\n/**\n * `checkout`/`switch` moves no existing branch, so the only shared ref it writes is one it creates: the `-b`/`-c` one\n * it names, or the one git DWIMs from a remote branch named like its lone argument. A detached or full-SHA checkout\n * creates none, and a pathspec checkout writes only the index and working tree.\n */\nfunction getCheckoutChanges(verb: 'checkout' | 'switch', args: readonly string[]): NamedChanges | undefined {\n\tconst parsed =\n\t\tverb === 'switch' ? parseArgs(args, switchFlags, switchValued) : parseArgs(args, checkoutFlags, checkoutValued);\n\tif (parsed == null) return undefined;\n\n\tlet branch: string | undefined;\n\tlet detach = false;\n\tlet noTrack = false;\n\tfor (const [option, value] of parsed.options) {\n\t\tif (value != null) {\n\t\t\tbranch = value;\n\t\t} else if (option === '-d' || option === '--detach') {\n\t\t\tdetach = true;\n\t\t} else if (option === '--no-track') {\n\t\t\tnoTrack = true;\n\t\t}\n\t}\n\n\tconst { positionals, dashDash } = parsed;\n\tconst revs = dashDash == null ? positionals : positionals.slice(0, dashDash);\n\tconst hasPaths = dashDash != null && dashDash < positionals.length;\n\tif (branch != null) {\n\t\tif (hasPaths || revs.length > 1 || !isLiteralBranchName(branch)) return undefined;\n\n\t\tconst refs = [`refs/heads/${branch}`];\n\t\tif (mayWriteTracking(revs[0], noTrack)) {\n\t\t\treturn { changes: checkoutTrackingChanges, refs: refs, configConfinedToRefs: true };\n\t\t}\n\t\treturn { changes: checkoutChanges, refs: refs };\n\t}\n\tif (hasPaths) return verb === 'checkout' ? { changes: indexChanges } : undefined;\n\tif (revs.length > 1) return undefined;\n\tif (detach) return { changes: headIndexChanges };\n\n\tconst [rev] = revs;\n\tif (rev == null || rev === '-' || rev.startsWith('@{-')) return undefined;\n\tif (fullShaRegex.test(rev)) return { changes: headIndexChanges };\n\n\t// A path, an existing ref, or a branch git DWIMs from a remote branch, tracking it from its own config section\n\treturn { changes: checkoutTrackingChanges, refs: [`refs/heads/${rev}`], configConfinedToRefs: true };\n}\n\n/**\n * A stash write moves only `refs/stash` (or its reflog, the rest of the list), save `branch`, which also creates the\n * branch it names from a commit and checks it out; `apply` moves no ref\n */\nfunction getStashChanges(subcommand: string | undefined, rest: readonly string[]): NamedChanges | undefined {\n\tswitch (subcommand) {\n\t\tcase 'branch': {\n\t\t\tconst name = rest[1];\n\t\t\tif (!name || name.startsWith('-') || !isLiteralBranchName(name)) return undefined;\n\n\t\t\treturn { changes: stashBranchChanges, refs: [`refs/heads/${name}`, ...stashRefs] };\n\t\t}\n\t\tcase undefined:\n\t\tcase 'push':\n\t\tcase 'save':\n\t\tcase 'pop':\n\t\t\treturn { changes: stashIndexChanges, refs: stashRefs };\n\t\tcase 'drop':\n\t\tcase 'clear':\n\t\tcase 'store':\n\t\t\treturn { changes: stashChanges, refs: stashRefs };\n\t\tcase 'apply':\n\t\t\treturn { changes: indexChanges };\n\t\tdefault:\n\t\t\t// A bare `stash` with options is a push\n\t\t\treturn subcommand.startsWith('-') ? { changes: stashIndexChanges, refs: stashRefs } : undefined;\n\t}\n}\n\n/** A `reset` given paths, or `-p`, restores index entries and moves no ref */\nfunction isPathspecReset(args: readonly string[]): boolean {\n\tconst dashDash = args.indexOf('--');\n\tif (dashDash >= 0 && dashDash < args.length - 1) return true;\n\n\treturn args.some(\n\t\targ =>\n\t\t\targ === '-p' ||\n\t\t\targ === '--patch' ||\n\t\t\targ === '--pathspec-from-file' ||\n\t\t\targ.startsWith('--pathspec-from-file='),\n\t);\n}\n\nconst falseConfigValues: ReadonlySet<string> = new Set(['false', 'no', 'off', '0', '']);\n\n/**\n * The `rebase` options that take the refs it writes out of argv's hands: the update-refs list was fixed when the\n * rebase started, whatever this argv says, an interactive or `--exec` todo list can write any ref, and `--update-refs`\n * spelled any other way than in full turns update-refs on\n */\nconst unprovableRebaseOptions: readonly string[] = [\n\t'--continue',\n\t'--skip',\n\t'--edit-todo',\n\t'--interactive',\n\t'--exec',\n\t'--update-refs',\n];\n\n/**\n * Whether `arg` is one of {@link unprovableRebaseOptions}, `-i` or `-x`, however git lets it be written: any unique\n * prefix of a long option, before any `=<value>` (`--cont`, `--update-ref`, `--exe=make`), and short ones bundled\n * (`-ri`, `-xmake`)\n */\nfunction isUnprovableRebaseOption(arg: string): boolean {\n\tif (arg.startsWith('--')) {\n\t\tconst name = arg.split('=', 1)[0];\n\t\treturn name.length > 2 && unprovableRebaseOptions.some(o => o.startsWith(name));\n\t}\n\treturn arg.length > 1 && arg.startsWith('-') && /[ix]/.test(arg.slice(1));\n}\n\n/**\n * Whether a `rebase` moves only the branch being rebased. Update-refs would rewrite every branch in the rebased range,\n * so it must be provably off: the last of `--update-refs`/`--no-update-refs`, else the last `-c rebase.updateRefs`\n * before the verb. An interactive or `--exec` rebase can write any ref from its todo list. Git writes the listed refs\n * only when the rebase finishes, so an abort or quit moves none.\n */\nfunction isHeadBranchRebase(command: LeadingCommand): boolean {\n\tlet off: boolean | undefined;\n\tfor (const arg of command.rest) {\n\t\tif (arg === '--' || arg === '--end-of-options') break;\n\n\t\tif (arg === '--abort' || arg === '--quit') return true;\n\n\t\tif (arg === '--no-update-refs') {\n\t\t\toff = true;\n\t\t} else if (arg === '--update-refs') {\n\t\t\toff = false;\n\t\t} else if (isUnprovableRebaseOption(arg)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (off != null) return off;\n\n\tfor (const config of command.configs ?? []) {\n\t\tconst separator = config.indexOf('=');\n\t\tconst key = separator < 0 ? config : config.slice(0, separator);\n\t\tif (key.toLowerCase() !== 'rebase.updaterefs') continue;\n\n\t\t// A bare `-c key` is git's `true`\n\t\toff = separator >= 0 && falseConfigValues.has(config.slice(separator + 1).toLowerCase());\n\t}\n\treturn off ?? false;\n}\n\n/** Verbs that move only the branch HEAD is on, or none from a detached HEAD */\nconst headBranchVerbs: ReadonlySet<string> = new Set(['commit', 'merge', 'cherry-pick', 'revert', 'am']);\n\n/**\n * What argv proves more precisely than {@link changesByVerb}: the refs a write moved, or fewer kinds. `undefined`\n * keeps the verb's table entry; `null` means the write moved nothing cached.\n */\nfunction getNamedChanges(command: LeadingCommand): NamedChanges | null | undefined {\n\tswitch (command.verb) {\n\t\tcase 'update-ref':\n\t\t\treturn getUpdateRefChanges(command.rest);\n\t\tcase 'branch':\n\t\t\treturn getBranchChanges(command.rest);\n\t\tcase 'tag':\n\t\t\treturn getTagChanges(command.rest);\n\t\tcase 'worktree':\n\t\t\treturn getWorktreeChanges(command.rest);\n\t\tcase 'checkout':\n\t\tcase 'switch':\n\t\t\treturn getCheckoutChanges(command.verb, command.rest);\n\t\tcase 'stash':\n\t\t\treturn getStashChanges(command.subcommand, command.rest);\n\t\tcase 'reset':\n\t\t\tif (isPathspecReset(command.rest)) return { changes: indexChanges };\n\n\t\t\treturn { changes: changesByVerb.reset, movesHeadBranch: true };\n\t\tcase 'rebase':\n\t\t\tif (!isHeadBranchRebase(command)) return undefined;\n\n\t\t\treturn { changes: changesByVerb.rebase, movesHeadBranch: true };\n\t\tdefault:\n\t\t\tif (!headBranchVerbs.has(command.verb)) return undefined;\n\n\t\t\treturn { changes: changesByVerb[command.verb], movesHeadBranch: true };\n\t}\n}\n\n/**\n * Classifies a raw git argv for the notification `git.run`'s `notify: 'infer'` applies after the run\n * settles. Returns `undefined` for a command with nothing to announce — read-only, object-only, or a write to a\n * ref nothing cached reads — otherwise the {@link RepositoryChange} kinds it announces, the refs it names when argv\n * proves them, the `-C` re-scope target (if any), and which of those kinds every worktree sees.\n */\nexport function getChangesForCommand(args: readonly string[]): CommandChanges | undefined {\n\tconst command = leadingCommand(args);\n\tif (command.readOnly || objectOnlyVerbs.has(command.verb)) return undefined;\n\n\tconst named = getNamedChanges(command);\n\tif (named === null) return undefined;\n\n\tlet changes = named?.changes;\n\tif (changes == null) {\n\t\tif (command.verb === 'worktree') {\n\t\t\tchanges = worktreeChanges;\n\t\t} else if (command.verb === 'branch' && hasOption(command.rest, branchConfigOptions)) {\n\t\t\tchanges = branchConfigChanges;\n\t\t} else {\n\t\t\tchanges = changesByVerb[command.verb] ?? emptyChanges;\n\t\t}\n\t}\n\treturn {\n\t\t...named,\n\t\tchanges: changes,\n\t\tpathOverride: command.pathOverride,\n\t\tsharedChanges: changes.filter(c => worktreeSharedChanges.has(c)),\n\t};\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { CancelledRunError, RunError, RunExitResult, RunOptions, RunResult, endStdin, findExecutable, fsExists, getWindowsShortPath, run, runSpawn } from "../../utils/env/node/exec.js";
1
+ import { CancelledRunError, ProcessSpawnOptions, ProcessSpawner, RunError, RunExitResult, RunOptions, RunResult, SpawnedProcess, endStdin, findExecutable, fsExists, getWindowsShortPath, run, runSpawn } from "../../utils/env/node/exec.js";
2
2
  import { isWindows } from "../../utils/env/node/platform.js";
3
- export { CancelledRunError, RunError, type RunExitResult, type RunOptions, type RunResult, endStdin, findExecutable, fsExists, getWindowsShortPath, isWindows, run, runSpawn };
3
+ export { CancelledRunError, type ProcessSpawnOptions, type ProcessSpawner, RunError, type RunExitResult, type RunOptions, type RunResult, type SpawnedProcess, endStdin, findExecutable, fsExists, getWindowsShortPath, isWindows, run, runSpawn };
@@ -5,8 +5,11 @@ import { GitHealthSlownessCategory } from "../../git/gitHealth.js";
5
5
  import { GitCommandPriority, GitResult, GitRunOptions, GitSpawnOptions } from "../../git/run.types.js";
6
6
  import { FilteredGitFeatures, GitFeatureOrPrefix, GitFeatures } from "../../git/features.js";
7
7
  import { LogChannel } from "../../utils/logger.js";
8
+ import { ProcessSpawner } from "../../utils/env/node/exec.js";
9
+ import "./exec.js";
8
10
  import "./exec.types.js";
9
11
  import { GitQueueConfig } from "./gitQueue.js";
12
+ import { HeadState } from "./headState.js";
10
13
  import { GitLocation } from "./locator.js";
11
14
  //#region ../git-cli/src/exec/git.d.ts
12
15
  export declare const slowCallWarningThreshold = 2000;
@@ -192,6 +195,8 @@ export interface GitOptions {
192
195
  hooks?: GitHooks;
193
196
  /** Optional dedicated logger for git command logging */
194
197
  logger?: LogChannel;
198
+ /** Launches the git process of every run and stream (not the locator's); defaults to Node's `spawn`. Set it to start git from a helper process when the host's own is too large to fork cheaply. */
199
+ spawn?: ProcessSpawner;
195
200
  }
196
201
  export interface GitHooks {
197
202
  /** Called when a git command is aborted (timeout or cancellation) */
@@ -227,6 +232,11 @@ export interface GitHooks {
227
232
  type ExitCodeOnlyGitCommandOptions = GitRunOptions & {
228
233
  exitCodeOnly: true;
229
234
  };
235
+ /** The refs a `notify`-flagged run proved it moved, as {@link Git.bindChangeNotifier} passes them on */
236
+ export type NamedRefs = {
237
+ readonly refs: readonly string[];
238
+ readonly configConfinedToRefs?: boolean;
239
+ };
230
240
  export declare class Git {
231
241
  private readonly _locator;
232
242
  readonly options: GitOptions;
@@ -250,6 +260,10 @@ export declare class Git {
250
260
  private _lastDynamicEnv;
251
261
  /** Bound via {@link bindChangeNotifier}; announces a `notify`-flagged run's changes. No-op until bound. */
252
262
  private _changeNotifier;
263
+ /** Bound via {@link bindHeadReader}; reads HEAD around a `notify: 'infer'` run that moves only HEAD's branch */
264
+ private _headReader;
265
+ /** The classifier behind `notify: 'infer'` — a field only so tests can substitute it */
266
+ private readonly _classify;
253
267
  constructor(_locator: () => Promise<GitLocation>, options?: GitOptions);
254
268
  /**
255
269
  * Binds the callback a `notify`-flagged {@link run} calls once it settles. `CliGitProvider` wires this
@@ -258,9 +272,17 @@ export declare class Git {
258
272
  * `repoPaths` holds more than one path only for a `-C`-scoped shared-state verb: the `-C` target, then the
259
273
  * caller's own `cwd`. `sharedPaths` names the paths that were not run in but share the repository, which
260
274
  * hear only the part of `changes` every worktree sees (the caller's `cwd`, when the verb also changed
261
- * something local to the `-C` target).
275
+ * something local to the `-C` target). `named.refs`, given only when the run proved them, are the full ref
276
+ * names it moved, as `repository.onChanged`'s `refs` are: `repoPaths` hear all of them, `sharedPaths` those of
277
+ * the kinds they hear. `named.configConfinedToRefs` confines a `config` change to those branches' sections.
278
+ */
279
+ bindChangeNotifier(fn: (repoPaths: readonly string[], changes: readonly RepositoryChange[], sharedPaths?: readonly string[], named?: NamedRefs) => void): void;
280
+ /**
281
+ * Binds the reader a `notify: 'infer'` {@link run} of a verb that moves only HEAD's branch (a commit, a reset)
282
+ * calls on the tree it runs in, before and after the run, to name that branch. It must not run git, and resolves
283
+ * `undefined` when HEAD can't be read. With nothing bound, such a run announces its branch move unnamed.
262
284
  */
263
- bindChangeNotifier(fn: (repoPaths: readonly string[], changes: readonly RepositoryChange[], sharedPaths?: readonly string[]) => void): void;
285
+ bindHeadReader(fn: (path: string) => Promise<HeadState>): void;
264
286
  /**
265
287
  * Returns the base environment for git commands. Cached to avoid spreading
266
288
  * process.env (30-100+ keys) on every call. Includes static options.env and
@@ -303,10 +325,15 @@ export declare class Git {
303
325
  run(options: ExitCodeOnlyGitCommandOptions, ...args: readonly (string | undefined)[]): Promise<GitResult<unknown>>;
304
326
  run<T extends string | Buffer = string>(options: GitRunOptions, ...args: readonly (string | undefined)[]): Promise<GitResult<T>>;
305
327
  /**
306
- * Applies `options.notify` once a {@link run} has settled — a no-op unless both `notify` and a
307
- * {@link bindChangeNotifier bound} notifier are present, so an unflagged caller pays nothing.
328
+ * Works out, before a `notify`-flagged {@link run} spawns, what it announces once it settles — `undefined` unless
329
+ * both `notify` and a {@link bindChangeNotifier bound} notifier are present, so an unflagged caller pays nothing.
330
+ * A verb that moves only HEAD's branch reads HEAD here, since the run may move it.
308
331
  */
332
+ private prepareNotify;
333
+ /** Announces what {@link prepareNotify} worked out, once the run has settled */
309
334
  private applyNotify;
335
+ /** HEAD of `path` through the {@link bindHeadReader bound} reader, or `undefined` when it can't be read */
336
+ private readHead;
310
337
  private resolveNotifyPath;
311
338
  private runCore;
312
339
  stream(options: GitSpawnOptions, ...args: readonly (string | undefined)[]): AsyncGenerator<string>;
@@ -13,6 +13,7 @@ import { CancelledRunError, RunError, endStdin, fsExists, runSpawn } from "../..
13
13
  import { compare, fromString } from "../../utils/version.js";
14
14
  import { EventLoopMonitor } from "./eventLoopMonitor.js";
15
15
  import { GitQueue, getPrimaryGitCommand, inferGitCommandPriority } from "./gitQueue.js";
16
+ import { getMovedHead } from "./headState.js";
16
17
  import { KeyedSequencer, isConfigCommand, isIndexWriteCommand, retryWhileConfigLocked, retryWhileIndexLocked, toExitCode } from "./indexLock.js";
17
18
  import { resolve } from "path";
18
19
  import { spawn } from "child_process";
@@ -450,6 +451,10 @@ var Git = class {
450
451
  _lastDynamicEnv;
451
452
  /** Bound via {@link bindChangeNotifier}; announces a `notify`-flagged run's changes. No-op until bound. */
452
453
  _changeNotifier;
454
+ /** Bound via {@link bindHeadReader}; reads HEAD around a `notify: 'infer'` run that moves only HEAD's branch */
455
+ _headReader;
456
+ /** The classifier behind `notify: 'infer'` — a field only so tests can substitute it */
457
+ _classify = getChangesForCommand;
453
458
  constructor(_locator, options = {}) {
454
459
  this._locator = _locator;
455
460
  this.options = options;
@@ -462,12 +467,22 @@ var Git = class {
462
467
  * `repoPaths` holds more than one path only for a `-C`-scoped shared-state verb: the `-C` target, then the
463
468
  * caller's own `cwd`. `sharedPaths` names the paths that were not run in but share the repository, which
464
469
  * hear only the part of `changes` every worktree sees (the caller's `cwd`, when the verb also changed
465
- * something local to the `-C` target).
470
+ * something local to the `-C` target). `named.refs`, given only when the run proved them, are the full ref
471
+ * names it moved, as `repository.onChanged`'s `refs` are: `repoPaths` hear all of them, `sharedPaths` those of
472
+ * the kinds they hear. `named.configConfinedToRefs` confines a `config` change to those branches' sections.
466
473
  */
467
474
  bindChangeNotifier(fn) {
468
475
  this._changeNotifier = fn;
469
476
  }
470
477
  /**
478
+ * Binds the reader a `notify: 'infer'` {@link run} of a verb that moves only HEAD's branch (a commit, a reset)
479
+ * calls on the tree it runs in, before and after the run, to name that branch. It must not run git, and resolves
480
+ * `undefined` when HEAD can't be read. With nothing bound, such a run announces its branch move unnamed.
481
+ */
482
+ bindHeadReader(fn) {
483
+ this._headReader = fn;
484
+ }
485
+ /**
471
486
  * Returns the base environment for git commands. Cached to avoid spreading
472
487
  * process.env (30-100+ keys) on every call. Includes static options.env and
473
488
  * GCM/LC_ALL vars but NOT dynamic getEnvironment() or per-call env overrides.
@@ -579,13 +594,16 @@ var Git = class {
579
594
  async run(options, ...args) {
580
595
  if (this.options.isTrusted?.() === false) throw new WorkspaceUntrustedError();
581
596
  const runArgs = args.filter((a) => a != null);
582
- if (options.notify != null) try {
583
- return await this.run({
584
- ...options,
585
- notify: void 0
586
- }, ...args);
587
- } finally {
588
- this.applyNotify(options, runArgs);
597
+ if (options.notify != null) {
598
+ const pending = await this.prepareNotify(options, runArgs);
599
+ try {
600
+ return await this.run({
601
+ ...options,
602
+ notify: void 0
603
+ }, ...args);
604
+ } finally {
605
+ if (pending != null) await this.applyNotify(pending);
606
+ }
589
607
  }
590
608
  const gitCommand = `git ${runArgs.join(" ")}`;
591
609
  if (options.caching != null) {
@@ -607,26 +625,69 @@ var Git = class {
607
625
  return this.runCore(options, runArgs, gitCommand);
608
626
  }
609
627
  /**
610
- * Applies `options.notify` once a {@link run} has settled — a no-op unless both `notify` and a
611
- * {@link bindChangeNotifier bound} notifier are present, so an unflagged caller pays nothing.
628
+ * Works out, before a `notify`-flagged {@link run} spawns, what it announces once it settles — `undefined` unless
629
+ * both `notify` and a {@link bindChangeNotifier bound} notifier are present, so an unflagged caller pays nothing.
630
+ * A verb that moves only HEAD's branch reads HEAD here, since the run may move it.
612
631
  */
613
- applyNotify(options, args) {
632
+ async prepareNotify(options, args) {
614
633
  const notify = options.notify;
615
- if (notify == null || this._changeNotifier == null || options.cwd == null) return;
616
- if (notify !== "infer") {
617
- this._changeNotifier([this.resolveNotifyPath(options.cwd, leadingCommand(args).pathOverride)], notify);
634
+ if (notify == null || this._changeNotifier == null || options.cwd == null) return void 0;
635
+ const argv = options.configs?.length ? [...options.configs, ...args] : args;
636
+ if (notify !== "infer") return {
637
+ cwd: options.cwd,
638
+ pathOverride: leadingCommand(argv).pathOverride,
639
+ changes: notify
640
+ };
641
+ const command = this._classify(argv);
642
+ if (command == null) return void 0;
643
+ const headBefore = command.movesHeadBranch && this._headReader != null ? await this.readHead(this.resolveNotifyPath(options.cwd, command.pathOverride)) : void 0;
644
+ return {
645
+ cwd: options.cwd,
646
+ command,
647
+ headBefore
648
+ };
649
+ }
650
+ /** Announces what {@link prepareNotify} worked out, once the run has settled */
651
+ async applyNotify(pending) {
652
+ if (!("command" in pending)) {
653
+ this._changeNotifier?.([this.resolveNotifyPath(pending.cwd, pending.pathOverride)], pending.changes);
654
+ return;
655
+ }
656
+ const command = pending.command;
657
+ const ranIn = this.resolveNotifyPath(pending.cwd, command.pathOverride);
658
+ let changes = command.changes;
659
+ let sharedChanges = command.sharedChanges;
660
+ const refs = [...command.refs ?? []];
661
+ if (command.movesHeadBranch && this._headReader != null) {
662
+ const moved = getMovedHead(pending.headBefore, await this.readHead(ranIn));
663
+ if (moved === "detached") {
664
+ changes = changes.filter((c) => c !== "heads");
665
+ sharedChanges = sharedChanges.filter((c) => c !== "heads");
666
+ if (!changes.length) return;
667
+ } else if (moved != null && changes.includes("heads") && !refs.includes(moved.branch)) refs.push(moved.branch);
668
+ }
669
+ const notifier = this._changeNotifier;
670
+ if (notifier == null) return;
671
+ let named;
672
+ if (refs.length) named = command.configConfinedToRefs ? {
673
+ refs,
674
+ configConfinedToRefs: true
675
+ } : { refs };
676
+ const cwd = normalizePath(pending.cwd);
677
+ if (command.pathOverride != null && cwd !== ranIn && (sharedChanges.length || !changes.length)) {
678
+ if (sharedChanges.length === changes.length) notifier([ranIn, cwd], changes, void 0, named);
679
+ else notifier([ranIn], changes, [cwd], named);
618
680
  return;
619
681
  }
620
- const command = getChangesForCommand(args);
621
- if (command == null) return;
622
- const ranIn = this.resolveNotifyPath(options.cwd, command.pathOverride);
623
- const cwd = normalizePath(options.cwd);
624
- if (command.pathOverride != null && cwd !== ranIn && (command.sharedChanges.length || !command.changes.length)) {
625
- if (command.sharedChanges.length === command.changes.length) this._changeNotifier([ranIn, cwd], command.changes);
626
- else this._changeNotifier([ranIn], command.changes, [cwd]);
682
+ notifier([ranIn], changes, void 0, named);
683
+ }
684
+ /** HEAD of `path` through the {@link bindHeadReader bound} reader, or `undefined` when it can't be read */
685
+ async readHead(path) {
686
+ try {
687
+ return await this._headReader?.(path);
688
+ } catch {
627
689
  return;
628
690
  }
629
- this._changeNotifier([ranIn], command.changes);
630
691
  }
631
692
  resolveNotifyPath(cwd, pathOverride) {
632
693
  return normalizePath(pathOverride != null ? resolve(cwd, pathOverride) : cwd);
@@ -643,7 +704,8 @@ var Git = class {
643
704
  encoding: (encoding ?? "utf8") === "utf8" ? "utf8" : "buffer",
644
705
  decode: this.options.decode,
645
706
  env: this.buildEnv(options.env),
646
- quiet: errorHandling === "ignore"
707
+ quiet: errorHandling === "ignore",
708
+ spawn: this.options.spawn
647
709
  };
648
710
  const unshared = options?.stdin != null || options?.env != null && Object.keys(options.env).length > 0 || beforeIndexLockRetry != null;
649
711
  const cacheKey = `${correlationKey !== void 0 ? `${correlationKey}:` : ""}${unshared ? `${unsharedRunCounter.next()}:` : ""}${cancellation != null ? `${getAbortSignalId(cancellation)}:` : ""}${gitCommand}`;
@@ -804,7 +866,7 @@ var Git = class {
804
866
  const start = hrtime();
805
867
  const startEpochMs = Date.now();
806
868
  const streamId = uniqueCounterForStream.next();
807
- const { configs, stdin, stdinEncoding, cancellation, encoding, slownessCategory, ...opts } = options;
869
+ const { configs, stdin, stdinEncoding, cancellation, encoding, slownessCategory, cwd, timeout } = options;
808
870
  const runArgs = args.filter((a) => a != null);
809
871
  const spawnOpts = {
810
872
  stdio: [
@@ -812,15 +874,16 @@ var Git = class {
812
874
  null,
813
875
  null
814
876
  ],
815
- ...opts,
816
- signal: cancellation,
817
- env: this.buildEnv(options.env)
877
+ cwd,
878
+ env: this.buildEnv(options.env),
879
+ timeout: timeout === 0 ? void 0 : timeout,
880
+ signal: cancellation
818
881
  };
819
- const gitCommand = `(spawn) [${spawnOpts.cwd}] git ${runArgs.join(" ")}`;
882
+ const gitCommand = `(spawn) [${cwd}] git ${runArgs.join(" ")}`;
820
883
  runArgs.unshift("-c", "core.quotepath=false", "-c", "color.ui=false", ...configs ?? emptyArray);
821
884
  if (process.platform === "win32") runArgs.unshift("-c", "core.longpaths=true");
822
885
  const command = await this.path();
823
- const proc = spawn(command, runArgs, spawnOpts);
886
+ const proc = (this.options.spawn ?? spawn)(command, runArgs, spawnOpts);
824
887
  if (stdin) endStdin(proc.stdin, stdin, stdinEncoding);
825
888
  let exception;
826
889
  const promise = new Promise((resolve, reject) => {
@@ -840,7 +903,7 @@ var Git = class {
840
903
  }
841
904
  if (signal === "SIGTERM") {
842
905
  if (cancellation?.aborted) resolve();
843
- else reject(new CancelledRunError(proc.spawnargs.join(" "), true, code ?? void 0, signal, "unknown"));
906
+ else reject(new CancelledRunError(proc.spawnargs.join(" "), true, code ?? void 0, signal, proc.killed ? "timeout" : "unknown"));
844
907
  return;
845
908
  }
846
909
  if (signal === "SIGPIPE" || code === 141 || code === 128 && stderrChunks.some((c) => c.includes("Connection reset by peer"))) {
@@ -864,25 +927,24 @@ var Git = class {
864
927
  proc.removeAllListeners();
865
928
  } catch {}
866
929
  const duration = getDurationMilliseconds(start);
867
- this.logGitCommandComplete(gitCommand, exception, duration, duration, false, spawnOpts.cwd, runArgs, slownessCategory, startEpochMs, streamId);
930
+ this.logGitCommandComplete(gitCommand, exception, duration, duration, false, cwd, runArgs, slownessCategory, startEpochMs, streamId);
868
931
  this.endActiveCommand();
869
932
  };
870
933
  this.beginActiveCommand();
871
934
  try {
872
935
  this.logGitCommandStart(gitCommand, streamId);
873
936
  try {
874
- if (proc.stdout) {
875
- const enc = encoding ?? "utf8";
876
- if (enc === "utf8" || enc === "binary" || enc === "buffer") {
877
- proc.stdout.setEncoding(enc === "buffer" ? "utf8" : enc);
878
- for await (const chunk of proc.stdout) yield chunk;
879
- } else {
880
- const decode = this.options.decode;
881
- if (decode == null) throw new Error(`Non-UTF-8 encoding '${enc}' requested for stream but no decode function configured`);
882
- const buffers = [];
883
- for await (const chunk of proc.stdout) buffers.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
884
- yield await decode(Buffer.concat(buffers), { encoding: enc });
885
- }
937
+ if (proc.stdout == null) throw new Error(`'${command}' was spawned without a stdout pipe`);
938
+ const enc = encoding ?? "utf8";
939
+ if (enc === "utf8" || enc === "binary" || enc === "buffer") {
940
+ proc.stdout.setEncoding(enc === "buffer" ? "utf8" : enc);
941
+ for await (const chunk of proc.stdout) yield chunk;
942
+ } else {
943
+ const decode = this.options.decode;
944
+ if (decode == null) throw new Error(`Non-UTF-8 encoding '${enc}' requested for stream but no decode function configured`);
945
+ const buffers = [];
946
+ for await (const chunk of proc.stdout) buffers.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
947
+ yield await decode(Buffer.concat(buffers), { encoding: enc });
886
948
  }
887
949
  } finally {
888
950
  await promise;