@gitkraken/core-gitlens 0.9.1 → 0.9.2

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 CHANGED
@@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.9.2] - 2026-09-30
10
+
11
+ ### Added
12
+
13
+ - Adds `errors: 'throw'` to `diff.getDiff`, `getParsedDiff`, `getDiffStatus` and `getChangedFilesCount`, so a failed diff rejects instead of resolving `undefined`: with a `GitError` carrying git's `stderr` when git ran and failed (an unresolvable revision, a path that is no longer a repository, a permission denial), or with the error that kept it from starting (a deleted working directory, a missing git binary). Without it they resolve `undefined` as before (git, git-cli)
14
+
15
+ ### Fixed
16
+
17
+ - Fixes a typed `ops.fetch`, `pull` or `push` that rejects announcing nothing, so reads kept serving what they cached before a run that had already stored some refs or stopped on a conflict, until a file watcher caught up. They announce their changes as a finished run does; a fetch that ran no git command still announces nothing (git-cli)
18
+ - Fixes `diff.getDiff` and `getParsedDiff` failing to diff from `HEAD` in a repository with no commits yet, where HEAD names nothing. It diffs against the empty tree, and `GitDiff.from` reports that tree's id (git-cli)
19
+
9
20
  ## [0.9.1] - 2026-09-29
10
21
 
11
22
  ### Added
@@ -457,7 +468,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
457
468
 
458
469
  - Initial release. Bundles `@gitlens/utils`, `@gitlens/git`, `@gitlens/git-cli`, `@gitlens/ai`, and `@gitlens/git-github` into a single core npm package with subpath exports.
459
470
 
460
- [unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.9.1...HEAD
471
+ [unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.9.2...HEAD
472
+ [0.9.2]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.9.1...gitkraken:releases/core/v0.9.2
461
473
  [0.9.1]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.9.0...gitkraken:releases/core/v0.9.1
462
474
  [0.9.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.8.0...gitkraken:releases/core/v0.9.0
463
475
  [0.8.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.7.2...gitkraken:releases/core/v0.8.0
@@ -3,6 +3,7 @@ import { DiffRange, RevisionUri } from "./types.js";
3
3
  import { GitRevisionRange, GitRevisionRangeNotation } from "../models/revision.js";
4
4
  import { GitDiff, GitDiffFiles, GitDiffFilter, GitDiffShortStat, ParsedGitDiff, ParsedGitDiffHunks } from "../models/diff.js";
5
5
  import { GitFile } from "../models/file.js";
6
+ import { GitErrorHandling } from "../run.types.js";
6
7
  import { DisposableTemporaryGitIndex } from "./staging.js";
7
8
  //#region ../git/src/providers/diff.d.ts
8
9
  export interface NextComparisonUrisResult {
@@ -21,12 +22,18 @@ export interface GitDiffSubProvider {
21
22
  getChangedFilesCount(repoPath: string, to?: string, from?: string, options?: {
22
23
  uris?: (string | Uri)[];
23
24
  includeUntracked?: boolean;
25
+ errors?: GitErrorHandling;
24
26
  }, cancellation?: AbortSignal): Promise<GitDiffShortStat | undefined>;
25
27
  getDiff?(repoPath: string, to: string, from?: string, options?: {
26
28
  context?: number;
27
29
  index?: DisposableTemporaryGitIndex;
28
30
  notation?: GitRevisionRangeNotation;
29
31
  uris?: (string | Uri)[];
32
+ /**
33
+ * `'throw'` rejects with the failure (a `GitError` carrying git's `stderr` when git ran) rather than
34
+ * resolving `undefined`, which is the default for every failure
35
+ */
36
+ errors?: GitErrorHandling;
30
37
  }, cancellation?: AbortSignal): Promise<GitDiff | undefined>;
31
38
  /**
32
39
  * Runs `git diff` and returns the fully parsed structure (files with hunks together) in a
@@ -39,6 +46,7 @@ export interface GitDiffSubProvider {
39
46
  context?: number;
40
47
  notation?: GitRevisionRangeNotation;
41
48
  uris?: (string | Uri)[];
49
+ errors?: GitErrorHandling;
42
50
  }, cancellation?: AbortSignal): Promise<ParsedGitDiff | undefined>;
43
51
  getDiffFiles?(repoPath: string, contents: string, cancellation?: AbortSignal): Promise<GitDiffFiles | undefined>;
44
52
  getDiffStatus(repoPath: string, ref1OrRange: string | GitRevisionRange, ref2?: string, options?: {
@@ -47,6 +55,7 @@ export interface GitDiffSubProvider {
47
55
  path?: string;
48
56
  renameLimit?: number;
49
57
  similarityThreshold?: number;
58
+ errors?: GitErrorHandling;
50
59
  }): Promise<GitFile[] | undefined>;
51
60
  getDiffTool?(repoPath?: string): Promise<string | undefined>;
52
61
  getNextComparisonUris(repoPath: string, pathOrUri: string | Uri, rev: string | undefined, skip?: number, options?: {
@@ -4,7 +4,7 @@ import { GitRevisionRange, GitRevisionRangeNotation } from "../../git/models/rev
4
4
  import { GitDiff, GitDiffFiles, GitDiffFilter, GitDiffShortStat, ParsedGitDiff, ParsedGitDiffHunks } from "../../git/models/diff.js";
5
5
  import { GitFile } from "../../git/models/file.js";
6
6
  import { GitServiceContext } from "../../git/context.js";
7
- import { GitResult } from "../../git/run.types.js";
7
+ import { GitErrorHandling, GitResult } from "../../git/run.types.js";
8
8
  import { Cache } from "../../git/cache.js";
9
9
  import { DisposableTemporaryGitIndex } from "../../git/providers/staging.js";
10
10
  import { GitDiffSubProvider, NextComparisonUrisResult, PreviousComparisonUrisResult, PreviousRangeComparisonUrisResult } from "../../git/providers/diff.js";
@@ -22,17 +22,22 @@ export declare class DiffGitSubProvider implements GitDiffSubProvider {
22
22
  getChangedFilesCount(repoPath: string, to?: string, from?: string, options?: {
23
23
  uris?: (string | Uri)[];
24
24
  includeUntracked?: boolean;
25
+ errors?: GitErrorHandling;
25
26
  }, _cancellation?: AbortSignal): Promise<GitDiffShortStat | undefined>;
26
27
  getDiff(repoPath: string, to: string, from?: string, options?: {
27
28
  context?: number;
28
29
  index?: DisposableTemporaryGitIndex;
29
30
  notation?: GitRevisionRangeNotation;
30
31
  uris?: (string | Uri)[];
32
+ errors?: GitErrorHandling;
31
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;
32
36
  getParsedDiff(repoPath: string, to: string, from?: string, options?: {
33
37
  context?: number;
34
38
  notation?: GitRevisionRangeNotation;
35
39
  uris?: (string | Uri)[];
40
+ errors?: GitErrorHandling;
36
41
  }, cancellation?: AbortSignal): Promise<ParsedGitDiff | undefined>;
37
42
  getDiffFiles(repoPath: string, contents: string, _cancellation?: AbortSignal): Promise<GitDiffFiles | undefined>;
38
43
  getDiffStatus(repoPath: string, ref1OrRange: string | GitRevisionRange, ref2?: string, options?: {
@@ -41,6 +46,7 @@ export declare class DiffGitSubProvider implements GitDiffSubProvider {
41
46
  path?: string;
42
47
  renameLimit?: number;
43
48
  similarityThreshold?: number;
49
+ errors?: GitErrorHandling;
44
50
  }): Promise<GitFile[] | undefined>;
45
51
  getDiffTool(repoPath?: string): Promise<string | undefined>;
46
52
  getNextComparisonUris(repoPath: string, pathOrUri: string | Uri, rev: string | undefined, skip?: number, options?: {
@@ -34,7 +34,8 @@ var DiffGitSubProvider = class {
34
34
  try {
35
35
  const result = await this.git.run({
36
36
  cwd: repoPath,
37
- configs: gitConfigsDiff
37
+ configs: gitConfigsDiff,
38
+ errors: options?.errors === "throw" ? "throw" : void 0
38
39
  }, "diff", "--shortstat", "--no-ext-diff", ...args, "--", ...options?.uris?.map((p) => this.provider.getRelativePath(p, repoPath)) ?? []);
39
40
  const stat = result.stdout ? parseGitDiffShortStat(result.stdout) : void 0;
40
41
  if (options?.includeUntracked && !options.uris?.length && isWorkingTreeComparison(to, from)) {
@@ -48,7 +49,7 @@ var DiffGitSubProvider = class {
48
49
  return stat;
49
50
  } catch (ex) {
50
51
  const msg = ex?.toString() ?? "";
51
- if (GitErrors.noMergeBase.test(msg) || GitErrors.badRevision.test(msg)) return;
52
+ if (options?.errors !== "throw" && (GitErrors.noMergeBase.test(msg) || GitErrors.badRevision.test(msg))) return;
52
53
  scope?.error(ex);
53
54
  throw ex;
54
55
  }
@@ -67,6 +68,7 @@ var DiffGitSubProvider = class {
67
68
  };
68
69
  }
69
70
  }
71
+ const hasFrom = from != null;
70
72
  from = prepareToFromDiffArgs(to, from, args, options?.notation);
71
73
  let paths;
72
74
  if (options?.uris) {
@@ -82,7 +84,16 @@ var DiffGitSubProvider = class {
82
84
  env: options?.index?.env
83
85
  }, "diff", ...args, args.includes("--") ? void 0 : "--");
84
86
  } catch (ex) {
87
+ if (isHead(from) && await this.isUnbornHeadFailure(repoPath, ex)) {
88
+ const emptyTree = await this.provider.revision.getEmptyTreeSha(repoPath);
89
+ const retried = await this.getDiff(repoPath, !hasFrom && isHead(to) ? "" : to, emptyTree, options, _cancellation);
90
+ return retried != null ? {
91
+ ...retried,
92
+ to
93
+ } : void 0;
94
+ }
85
95
  scope?.error(ex);
96
+ if (options?.errors === "throw") throw ex;
86
97
  return;
87
98
  }
88
99
  return {
@@ -92,6 +103,12 @@ var DiffGitSubProvider = class {
92
103
  notation: options?.notation
93
104
  };
94
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
+ }
95
112
  async getParsedDiff(repoPath, to, from, options, cancellation) {
96
113
  const diff = await this.getDiff(repoPath, to, from, options, cancellation);
97
114
  if (!diff?.contents) return void 0;
@@ -116,7 +133,8 @@ var DiffGitSubProvider = class {
116
133
  ] : gitConfigsDiff;
117
134
  const result = await this.git.run({
118
135
  cwd: repoPath,
119
- configs
136
+ configs,
137
+ errors: options?.errors === "throw" ? "throw" : void 0
120
138
  }, "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);
121
139
  const files = result.stdout ? parseGitDiffNumStatFiles(result.stdout, repoPath) ?? [] : [];
122
140
  if (options?.includeUntracked && ref2 == null && typeof ref1OrRange === "string" && !isRevisionRange(ref1OrRange) && !isUncommittedStaged(ref1OrRange) && filtersAllowUntracked(options.filters) && !isNonExactPathspec(options.path)) {
@@ -131,7 +149,8 @@ var DiffGitSubProvider = class {
131
149
  }
132
150
  }
133
151
  return files.length ? files : void 0;
134
- } catch (_ex) {
152
+ } catch (ex) {
153
+ if (options?.errors === "throw") throw ex;
135
154
  return;
136
155
  }
137
156
  }
@@ -591,9 +610,12 @@ function isWorkingTreeComparison(to, from) {
591
610
  if (isRevisionRange(to) || isUncommittedStaged(to)) return false;
592
611
  if (isUncommitted(to)) return true;
593
612
  if (to === "") return from == null || !isUncommittedStaged(from);
594
- if (to.toUpperCase() === "HEAD" && from == null) return true;
613
+ if (isHead(to) && from == null) return true;
595
614
  return false;
596
615
  }
616
+ function isHead(ref) {
617
+ return ref?.toUpperCase() === "HEAD";
618
+ }
597
619
  function prepareToFromDiffArgs(to, from, args, notation) {
598
620
  if (to === "0000000000000000000000000000000000000000") {
599
621
  if (from != null) args.push(from);
@@ -603,7 +625,7 @@ function prepareToFromDiffArgs(to, from, args, notation) {
603
625
  if (from != null) args.push(from);
604
626
  else from = "HEAD";
605
627
  } else if (from == null) {
606
- if (to === "" || to.toUpperCase() === "HEAD") {
628
+ if (to === "" || isHead(to)) {
607
629
  from = "HEAD";
608
630
  args.push(from);
609
631
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","names":[],"sources":["../../../../git-cli/src/providers/diff.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type {\n\tGitDiff,\n\tGitDiffFiles,\n\tGitDiffFilter,\n\tGitDiffShortStat,\n\tParsedGitDiff,\n\tParsedGitDiffHunks,\n} from '@gitlens/git/models/diff.js';\nimport type { GitFile } from '@gitlens/git/models/file.js';\nimport type { GitRevisionRange, GitRevisionRangeNotation } from '@gitlens/git/models/revision.js';\nimport { deletedOrMissing, uncommitted, uncommittedStaged } from '@gitlens/git/models/revision.js';\nimport {\n\tparseGitApplyFiles,\n\tparseGitDiff,\n\tparseGitDiffNumStatFiles,\n\tparseGitDiffShortStat,\n\tparseGitFileDiff,\n} from '@gitlens/git/parsers/diffParser.js';\nimport type {\n\tGitDiffSubProvider,\n\tNextComparisonUrisResult,\n\tPreviousComparisonUrisResult,\n\tPreviousRangeComparisonUrisResult,\n} from '@gitlens/git/providers/diff.js';\nimport type { DisposableTemporaryGitIndex } from '@gitlens/git/providers/staging.js';\nimport type { DiffRange, RevisionUri } from '@gitlens/git/providers/types.js';\nimport {\n\tgetRevisionRangeParts,\n\tisRevisionRange,\n\tisUncommitted,\n\tisUncommittedStaged,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { encodeGitLensRevisionUriAuthority } from '@gitlens/git/utils/uriAuthority.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { fnv1aHash } from '@gitlens/utils/hash.js';\nimport { first } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fromUri, toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { GitResult } from '../exec/exec.types.js';\nimport type { Git } from '../exec/git.js';\nimport { gitConfigsDiff, gitConfigsLog, GitError, GitErrors } from '../exec/git.js';\nimport type { LogParsedFile } from '../parsers/logParser.js';\nimport { getShaAndFileRangeLogParser, getShaAndFileSummaryLogParser } from '../parsers/logParser.js';\n\nexport class DiffGitSubProvider implements GitDiffSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync getChangedFilesCount(\n\t\trepoPath: string,\n\t\tto?: string,\n\t\tfrom?: string,\n\t\toptions?: { uris?: (string | Uri)[]; includeUntracked?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiffShortStat | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args: string[] = [];\n\t\tif (to != null) {\n\t\t\t// Handle revision ranges specially if there is no `from`, otherwise `prepareToFromDiffArgs` will duplicate the range\n\t\t\tif (isRevisionRange(to) && from == null) {\n\t\t\t\targs.push(to);\n\t\t\t} else {\n\t\t\t\tprepareToFromDiffArgs(to, from, args);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsDiff },\n\t\t\t\t'diff',\n\t\t\t\t'--shortstat',\n\t\t\t\t'--no-ext-diff',\n\t\t\t\t...args,\n\t\t\t\t'--',\n\t\t\t\t...(options?.uris?.map(p => this.provider.getRelativePath(p, repoPath)) ?? []),\n\t\t\t);\n\n\t\t\tconst stat = result.stdout ? parseGitDiffShortStat(result.stdout) : undefined;\n\n\t\t\t// Merge in untracked files when the comparison involves the working tree.\n\t\t\t// Skip when a pathspec filter is active — mixing a path-filtered diff count with an\n\t\t\t// unfiltered untracked count would silently produce wrong totals.\n\t\t\tif (options?.includeUntracked && !options.uris?.length && isWorkingTreeComparison(to, from)) {\n\t\t\t\tconst untracked = (await this.provider.status?.getUntrackedFiles?.(repoPath)) ?? [];\n\t\t\t\tif (untracked.length) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfiles: (stat?.files ?? 0) + untracked.length,\n\t\t\t\t\t\tadditions: stat?.additions ?? 0,\n\t\t\t\t\t\tdeletions: stat?.deletions ?? 0,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn stat;\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif (GitErrors.noMergeBase.test(msg) || GitErrors.badRevision.test(msg)) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getDiff(\n\t\trepoPath: string,\n\t\tto: string,\n\t\tfrom?: string,\n\t\toptions?: {\n\t\t\tcontext?: number;\n\t\t\tindex?: DisposableTemporaryGitIndex;\n\t\t\tnotation?: GitRevisionRangeNotation;\n\t\t\turis?: (string | Uri)[];\n\t\t},\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiff | undefined> {\n\t\tconst scope = getScopedLogger();\n\t\tconst args = [`-U${options?.context ?? 3}`];\n\n\t\tif (to != null && isRevisionRange(to)) {\n\t\t\tconst parts = getRevisionRangeParts(to);\n\t\t\tif (parts != null) {\n\t\t\t\tto = parts.right ?? '';\n\t\t\t\tfrom = parts.left;\n\t\t\t\toptions = { ...options, notation: parts.notation };\n\t\t\t}\n\t\t}\n\n\t\tfrom = prepareToFromDiffArgs(to, from, args, options?.notation);\n\n\t\tlet paths: Set<string> | undefined;\n\t\tif (options?.uris) {\n\t\t\tpaths = new Set<string>(options.uris.map(p => this.provider.getRelativePath(p, repoPath)));\n\t\t\targs.push('--', ...paths);\n\t\t}\n\n\t\tlet result;\n\t\ttry {\n\t\t\tresult = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsDiff, errors: 'throw', env: options?.index?.env },\n\t\t\t\t'diff',\n\t\t\t\t...args,\n\t\t\t\targs.includes('--') ? undefined : '--',\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst diff: GitDiff = { contents: result.stdout, from: from, to: to, notation: options?.notation };\n\t\treturn diff;\n\t}\n\n\t@debug()\n\tasync getParsedDiff(\n\t\trepoPath: string,\n\t\tto: string,\n\t\tfrom?: string,\n\t\toptions?: {\n\t\t\tcontext?: number;\n\t\t\tnotation?: GitRevisionRangeNotation;\n\t\t\turis?: (string | Uri)[];\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<ParsedGitDiff | undefined> {\n\t\tconst diff = await this.getDiff(repoPath, to, from, options, cancellation);\n\t\tif (!diff?.contents) return undefined;\n\n\t\treturn parseGitDiff(diff.contents);\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync getDiffFiles(\n\t\trepoPath: string,\n\t\tcontents: string,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiffFiles | undefined> {\n\t\tconst result = await this.git.run(\n\t\t\t{ cwd: repoPath, configs: gitConfigsLog, stdin: contents },\n\t\t\t'apply',\n\t\t\t'--numstat',\n\t\t\t'--summary',\n\t\t\t'-z',\n\t\t\t'-',\n\t\t);\n\t\tif (!result.stdout) return undefined;\n\n\t\tconst files = parseGitApplyFiles(result.stdout, repoPath);\n\t\treturn {\n\t\t\tfiles: files,\n\t\t};\n\t}\n\n\t@debug()\n\tasync getDiffStatus(\n\t\trepoPath: string,\n\t\tref1OrRange: string | GitRevisionRange,\n\t\tref2?: string,\n\t\toptions?: {\n\t\t\tfilters?: GitDiffFilter[];\n\t\t\tincludeUntracked?: boolean;\n\t\t\tpath?: string;\n\t\t\trenameLimit?: number;\n\t\t\tsimilarityThreshold?: number;\n\t\t},\n\t): Promise<GitFile[] | undefined> {\n\t\ttry {\n\t\t\tconst similarityThreshold =\n\t\t\t\toptions?.similarityThreshold ?? this.context.config?.commits.similarityThreshold;\n\t\t\tconst configs =\n\t\t\t\toptions?.renameLimit != null\n\t\t\t\t\t? [...gitConfigsDiff, '-c', `diff.renameLimit=${options.renameLimit}`]\n\t\t\t\t\t: gitConfigsDiff;\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: configs },\n\t\t\t\t'diff',\n\t\t\t\t'--numstat',\n\t\t\t\t'--summary',\n\t\t\t\t`-M${similarityThreshold == null ? '' : `${similarityThreshold}%`}`,\n\t\t\t\t'--no-ext-diff',\n\t\t\t\t'-z',\n\t\t\t\toptions?.filters?.length ? `--diff-filter=${options.filters.join('')}` : undefined,\n\t\t\t\tref1OrRange ? ref1OrRange : undefined,\n\t\t\t\tref2 ? ref2 : undefined,\n\t\t\t\t'--',\n\t\t\t\toptions?.path ? options.path : undefined,\n\t\t\t);\n\n\t\t\tconst files = result.stdout ? (parseGitDiffNumStatFiles(result.stdout, repoPath) ?? []) : [];\n\n\t\t\t// Merge in untracked files when the comparison involves the working tree.\n\t\t\t// Skip when `filters` excludes additions (untracked entries are semantically 'A'/added),\n\t\t\t// or when `path` is a non-exact pathspec we can't reliably match against the untracked list.\n\t\t\tif (\n\t\t\t\toptions?.includeUntracked &&\n\t\t\t\tref2 == null &&\n\t\t\t\ttypeof ref1OrRange === 'string' &&\n\t\t\t\t!isRevisionRange(ref1OrRange) &&\n\t\t\t\t!isUncommittedStaged(ref1OrRange) &&\n\t\t\t\tfiltersAllowUntracked(options.filters) &&\n\t\t\t\t!isNonExactPathspec(options.path)\n\t\t\t) {\n\t\t\t\tconst untracked = (await this.provider.status?.getUntrackedFiles?.(repoPath)) ?? [];\n\t\t\t\tif (untracked.length) {\n\t\t\t\t\tconst seen = new Set(files.map(f => f.path));\n\t\t\t\t\tfor (const file of untracked) {\n\t\t\t\t\t\tif (seen.has(file.path)) continue;\n\t\t\t\t\t\tif (options.path && options.path !== file.path) continue;\n\n\t\t\t\t\t\tfiles.push(file);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn files.length ? files : undefined;\n\t\t} catch (_ex) {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getDiffTool(repoPath?: string): Promise<string | undefined> {\n\t\treturn (\n\t\t\t(await this.provider.config.getConfig?.(repoPath, 'diff.guitool', { runGitLocally: true })) ??\n\t\t\tthis.provider.config.getConfig?.(repoPath, 'diff.tool', { runGitLocally: true })\n\t\t);\n\t}\n\n\t@debug()\n\tasync getNextComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\toptions?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<NextComparisonUrisResult | undefined> {\n\t\t// If we have no revision there is no next commit\n\t\tif (!rev) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\tif (isUncommittedStaged(rev)) {\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, relativePath, rev),\n\t\t\t\tnext: createRevisionUri(this.provider, repoPath, relativePath, undefined),\n\t\t\t};\n\t\t} else if (isUncommitted(rev)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parser = getShaAndFileSummaryLogParser();\n\t\t\tconst args = ['log', ...parser.arguments];\n\n\t\t\tconst ordering = options?.ordering ?? this.context.config?.commits.ordering;\n\t\t\tif (ordering) {\n\t\t\t\targs.push(`--${ordering}-order`);\n\t\t\t}\n\n\t\t\targs.push(\n\t\t\t\t// Use reverse to get the next commits (oldest to newest instead of newest to oldest)\n\t\t\t\t'--reverse',\n\t\t\t);\n\n\t\t\tif (rev !== deletedOrMissing) {\n\t\t\t\targs.push(\n\t\t\t\t\t// Ancestry path to ensure we only follow the path from the given revision to HEAD\n\t\t\t\t\t'--ancestry-path',\n\t\t\t\t\t// Range from the given revision to HEAD\n\t\t\t\t\t`${rev}..HEAD`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Follow file history and specify the file path\n\t\t\targs.push('--follow', '--', relativePath);\n\n\t\t\t// Unbounded --follow walk over file history can be slow on long histories — queue as background\n\t\t\t// so it doesn't compete with interactive work.\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsLog, priority: 'background' },\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tlet currentSha;\n\t\t\tlet currentPath;\n\n\t\t\tif (skip === 0) {\n\t\t\t\tcurrentSha = rev;\n\t\t\t\tcurrentPath = relativePath;\n\t\t\t} else {\n\t\t\t\tskip--;\n\t\t\t}\n\n\t\t\tlet nextSha;\n\t\t\tlet nextPath;\n\n\t\t\tlet file;\n\t\t\tfor (const commit of parser.parse(result.stdout)) {\n\t\t\t\tconst path = relativePath;\n\t\t\t\tfile = commit.files.find(f => f.path === path || f.originalPath === path);\n\t\t\t\t// Keep track of the file changing paths\n\t\t\t\tif (file?.path && file.path !== relativePath) {\n\t\t\t\t\trelativePath = file.path;\n\t\t\t\t}\n\n\t\t\t\tif (skip > 0) {\n\t\t\t\t\tskip--;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (currentSha == null) {\n\t\t\t\t\tcurrentSha = commit.sha;\n\t\t\t\t\tcurrentPath = file?.path ?? relativePath;\n\t\t\t\t} else if (nextSha == null) {\n\t\t\t\t\t// if (commit.sha === rev) continue;\n\n\t\t\t\t\tnextSha = commit.sha;\n\t\t\t\t\tnextPath = file?.path ?? relativePath;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentSha == null || currentPath == null) {\n\t\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, relativePath);\n\t\t\t\tif (status != null) {\n\t\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\t\tcurrentSha = uncommittedStaged;\n\t\t\t\t\t\tcurrentPath = status.originalPath ?? status.path;\n\t\t\t\t\t\tnextSha = '';\n\t\t\t\t\t\tnextPath = status.path;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (nextSha == null || nextPath == null) {\n\t\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, relativePath);\n\t\t\t\tif (status != null) {\n\t\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\t\tnextSha = uncommittedStaged;\n\t\t\t\t\t\tnextPath = status.originalPath ?? status.path;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnextSha = '';\n\t\t\t\t\t\tnextPath = status.path;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnextSha = '';\n\t\t\t\t\tnextPath = relativePath;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha || undefined),\n\t\t\t\tnext: createRevisionUri(\n\t\t\t\t\tthis.provider,\n\t\t\t\t\trepoPath,\n\t\t\t\t\tnextPath ?? currentPath,\n\t\t\t\t\t(nextSha ?? deletedOrMissing) || undefined,\n\t\t\t\t),\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getPreviousComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\tunsaved?: boolean,\n\t\toptions?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousComparisonUrisResult | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tif (rev === uncommitted) {\n\t\t\trev = undefined;\n\t\t}\n\n\t\t/* Rules:\n\t\t * Starting from working tree (rev is empty or undefined):\n\t\t * 1. Check file status:\n\t\t * 1.1. If file has both staged and working (or unsaved) changes:\n\t\t * - If skip=0: diff working with staged\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.2. If file has only staged changes:\n\t\t * - If skip=0: diff working with HEAD\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.3. If file has only working changes:\n\t\t * - If skip=0: diff working with HEAD\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.4. If file has no changes (or no status found):\n\t\t * - If skip=0: diff working with HEAD~1\n\t\t * - If skip>0: skip through revs starting at HEAD~1\n\t\t *\n\t\t * Starting from staged (rev is uncommittedStaged):\n\t\t * 1. Check file status:\n\t\t * 1.1. If status exists:\n\t\t * - If skip=0: diff staged with HEAD\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.2. If status doesn't exist:\n\t\t * - If skip=0: diff HEAD with HEAD~1\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * Starting from a commit (rev is a SHA):\n\t\t * - If skip=0: diff SHA with SHA^\n\t\t * - If skip>0: skip through revs starting at SHA\n\t\t */\n\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\t\tlet skipPrev = 0;\n\n\t\tlet revs: [string, string][] = [];\n\t\tif (!rev) {\n\t\t\trevs = [['', relativePath]];\n\n\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, pathOrUri);\n\t\t\tif (status != null) {\n\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\trevs.push([uncommittedStaged, status.originalPath ?? status.path]);\n\t\t\t\t}\n\n\t\t\t\trevs.push(['HEAD', status.originalPath ?? status.path]);\n\t\t\t\tif (status.workingTreeStatus == null && !unsaved) {\n\t\t\t\t\tif (skip === 0 || status.indexStatus == null) {\n\t\t\t\t\t\t// Skip over the HEAD commit to get a diff, because working and HEAD are the same\n\t\t\t\t\t\tskipPrev++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trevs.push(['HEAD', relativePath]);\n\t\t\t\tif (!unsaved) {\n\t\t\t\t\t// Skip over the HEAD commit to get a diff, because working and HEAD are the same\n\t\t\t\t\tskipPrev++;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (isUncommittedStaged(rev)) {\n\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, pathOrUri);\n\t\t\tif (status != null) {\n\t\t\t\trevs = [\n\t\t\t\t\t[uncommittedStaged, status.originalPath ?? status.path],\n\t\t\t\t\t['HEAD', status.originalPath ?? status.path],\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\t// Even though we supposedly started at staged, there is no staged version\n\t\t\t\trevs = [['HEAD', relativePath]];\n\t\t\t\tif (skip > 0) {\n\t\t\t\t\tskip--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet currentSha;\n\t\tlet currentPath;\n\n\t\tif (revs.length) {\n\t\t\tskip++;\n\t\t\twhile (revs.length && skip > 0) {\n\t\t\t\tskip--;\n\t\t\t\t[rev, relativePath] = revs.shift()!;\n\t\t\t}\n\n\t\t\tif (rev !== 'HEAD') {\n\t\t\t\tcurrentSha = rev;\n\t\t\t\tcurrentPath = relativePath;\n\n\t\t\t\tskipPrev++;\n\t\t\t\twhile (revs.length && skipPrev > 0) {\n\t\t\t\t\tskipPrev--;\n\t\t\t\t\t[rev, relativePath] = revs.shift()!;\n\t\t\t\t}\n\n\t\t\t\tif (skipPrev > 0) {\n\t\t\t\t\tskip += skipPrev;\n\t\t\t\t}\n\n\t\t\t\tif (rev !== 'HEAD' && skip === 0) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha),\n\t\t\t\t\t\tprevious: createRevisionUri(this.provider, repoPath, relativePath, rev),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst parser = getShaAndFileSummaryLogParser();\n\t\t\tconst args = ['log', ...parser.arguments, `-n${skip + 2}`]; // Don't use --skip as it doesn't work with --follow\n\n\t\t\tconst ordering = options?.ordering ?? this.context.config?.commits.ordering;\n\t\t\tif (ordering) {\n\t\t\t\targs.push(`--${ordering}-order`);\n\t\t\t}\n\n\t\t\targs.push('--follow', rev!, '--', relativePath);\n\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\tconfigs: gitConfigsLog,\n\t\t\t\t\tcaching: { cache: this.cache.gitResults, options: { accessTTL: 5 * 60 * 1000 } },\n\t\t\t\t},\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tlet previousSha;\n\t\t\tlet previousPath;\n\t\t\tlet file;\n\n\t\t\tfor (const commit of parser.parse(result.stdout)) {\n\t\t\t\tconst path = relativePath;\n\t\t\t\tfile = commit.files.find(f => f.path === path || f.originalPath === path);\n\t\t\t\t// Keep track of the file changing paths\n\t\t\t\tif (file?.originalPath && file.originalPath !== relativePath) {\n\t\t\t\t\trelativePath = file.originalPath;\n\t\t\t\t}\n\n\t\t\t\tif (skip > 0) {\n\t\t\t\t\tskip--;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (currentSha == null) {\n\t\t\t\t\tcurrentSha = commit.sha;\n\t\t\t\t\tcurrentPath = file?.path ?? relativePath;\n\t\t\t\t} else if (previousSha == null) {\n\t\t\t\t\tif (commit.sha === rev) continue;\n\n\t\t\t\t\tpreviousSha = commit.sha;\n\t\t\t\t\tpreviousPath = file?.path ?? relativePath;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentSha == null || currentPath == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha || undefined),\n\t\t\t\tprevious: createRevisionUri(\n\t\t\t\t\tthis.provider,\n\t\t\t\t\trepoPath,\n\t\t\t\t\tpreviousPath ?? currentPath,\n\t\t\t\t\tpreviousSha ?? deletedOrMissing,\n\t\t\t\t),\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getPreviousComparisonUrisForRange(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\trange: DiffRange,\n\t\toptions?: { ordering?: 'date' | 'author-date' | 'topo' | null; skipFirstRev?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousRangeComparisonUrisResult | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tif (rev === uncommitted) {\n\t\t\trev = undefined;\n\t\t}\n\n\t\tlet currentSha;\n\t\tlet currentPath;\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\t\tconst skipFirstRev = options?.skipFirstRev ?? true;\n\n\t\t// If we are at the working tree (i.e. no ref), we need to dig deeper to figure out where to go\n\t\tif (!rev) {\n\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, pathOrUri);\n\t\t\tif (status != null) {\n\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\tif (status.workingTreeStatus != null && !skipFirstRev) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, relativePath, undefined),\n\t\t\t\t\t\t\tprevious: createRevisionUri(this.provider, repoPath, relativePath, uncommittedStaged),\n\t\t\t\t\t\t\trange: range,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrentSha = uncommittedStaged;\n\t\t\t\t\tcurrentPath = status.originalPath ?? status.path;\n\t\t\t\t\tif (status.originalPath != null) {\n\t\t\t\t\t\trelativePath = status.originalPath;\n\t\t\t\t\t}\n\t\t\t\t\trev = uncommittedStaged;\n\t\t\t\t} else if (status.workingTreeStatus != null && !skipFirstRev) {\n\t\t\t\t\tcurrentSha = '';\n\t\t\t\t\tcurrentPath = relativePath;\n\t\t\t\t\trev = '';\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (!skipFirstRev) {\n\t\t\tcurrentSha = rev;\n\t\t\tcurrentPath = relativePath;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parser = getShaAndFileRangeLogParser();\n\t\t\tconst args = ['log', ...parser.arguments, '-n2']; // Don't use --skip as it doesn't work with --follow\n\n\t\t\tconst ordering = options?.ordering ?? this.context.config?.commits.ordering;\n\t\t\tif (ordering) {\n\t\t\t\targs.push(`--${ordering}-order`);\n\t\t\t}\n\n\t\t\tif (rev && !isUncommittedStaged(rev)) {\n\t\t\t\targs.push(rev);\n\t\t\t}\n\n\t\t\targs.push(`-L${range.startLine},${range.endLine}:${relativePath}`);\n\n\t\t\tlet result: GitResult;\n\t\t\ttry {\n\t\t\t\tresult = await this.git.run({ cwd: repoPath, configs: gitConfigsLog }, ...args);\n\t\t\t} catch (ex) {\n\t\t\t\tif (rev && !isUncommittedStaged(rev)) throw ex;\n\n\t\t\t\t// If the line count is invalid reset to a valid range\n\t\t\t\tconst match = GitErrors.invalidLineCount.exec(ex?.toString() ?? '');\n\t\t\t\tif (match == null) throw ex;\n\n\t\t\t\tconst line = parseInt(match[1], 10);\n\t\t\t\tif (isNaN(line)) throw ex;\n\n\t\t\t\tconst index = args.findIndex(a => a.startsWith('-L'));\n\t\t\t\tif (index === -1) throw ex;\n\n\t\t\t\trange = {\n\t\t\t\t\tstartLine: Math.min(range.startLine, line),\n\t\t\t\t\tstartCharacter: range.startCharacter,\n\t\t\t\t\tendLine: Math.min(range.endLine, line),\n\t\t\t\t\tendCharacter: range.endCharacter,\n\t\t\t\t\tactive: range.active,\n\t\t\t\t};\n\n\t\t\t\targs.splice(index, 1, `-L${range.startLine},${range.endLine}:${relativePath}`);\n\t\t\t\tresult = await this.git.run({ cwd: repoPath, configs: gitConfigsLog }, ...args);\n\t\t\t}\n\n\t\t\tlet currentRange;\n\t\t\tlet previousSha;\n\t\t\tlet previousPath;\n\t\t\tlet file;\n\n\t\t\tfor (const commit of parser.parse(result.stdout)) {\n\t\t\t\tconst path = relativePath;\n\t\t\t\tfile = commit.files.find(f => f.path === path || f.originalPath === path);\n\t\t\t\t// If we couldn't find the file, but there is only one file in the commit, use that one and assume the filename changed\n\t\t\t\tif (file == null && commit.files.length === 1) {\n\t\t\t\t\tfile = commit.files[0];\n\t\t\t\t\trelativePath = file.path;\n\t\t\t\t}\n\t\t\t\t// Keep track of the file changing paths\n\t\t\t\tif (file?.originalPath && file.originalPath !== relativePath) {\n\t\t\t\t\trelativePath = file.originalPath;\n\t\t\t\t}\n\n\t\t\t\tif (currentSha == null) {\n\t\t\t\t\tcurrentSha = commit.sha;\n\t\t\t\t\tcurrentPath = file?.path ?? relativePath;\n\t\t\t\t\tcurrentRange =\n\t\t\t\t\t\tfile?.range != null ? { ...file.range, startCharacter: 1, endCharacter: 1 } : undefined;\n\t\t\t\t} else if (previousSha == null) {\n\t\t\t\t\tif (commit.sha === rev) continue;\n\n\t\t\t\t\tpreviousSha = commit.sha;\n\t\t\t\t\tpreviousPath = file?.path ?? relativePath;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentSha == null || currentPath == null) return undefined;\n\n\t\t\t// If we have no previous SHA but have a real current SHA, resolve the parent commit.\n\t\t\t// This handles the case where a line is newly added — the line has no prior history,\n\t\t\t// but the file likely existed at the parent commit\n\t\t\tif (previousSha == null && currentSha) {\n\t\t\t\tpreviousSha =\n\t\t\t\t\t(await this.provider.refs.validateReference(repoPath, `${currentSha}^`)) ?? deletedOrMissing;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha || undefined),\n\t\t\t\tprevious: createRevisionUri(\n\t\t\t\t\tthis.provider,\n\t\t\t\t\trepoPath,\n\t\t\t\t\tpreviousPath ?? currentPath,\n\t\t\t\t\tpreviousSha ?? deletedOrMissing,\n\t\t\t\t),\n\t\t\t\trange: currentRange ?? range,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t/** Returns raw diff output for a file between two revisions. */\n\tasync diff(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref1?: string,\n\t\tref2?: string,\n\t\toptions?: {\n\t\t\tencoding?: string;\n\t\t\tfilters?: GitDiffFilter[];\n\t\t\tlinesOfContext?: number;\n\t\t\trenames?: boolean;\n\t\t\tsimilarityThreshold?: number | null;\n\t\t},\n\t): Promise<GitResult> {\n\t\tconst params = ['diff', '--no-ext-diff', '--minimal'];\n\n\t\tif (options?.linesOfContext != null) {\n\t\t\tparams.push(`-U${options.linesOfContext}`);\n\t\t}\n\n\t\tif (options?.renames) {\n\t\t\tparams.push(`-M${options.similarityThreshold == null ? '' : `${options.similarityThreshold}%`}`);\n\t\t}\n\n\t\tif (options?.filters != null && options.filters.length !== 0) {\n\t\t\tparams.push(`--diff-filter=${options.filters.join('')}`);\n\t\t}\n\n\t\tif (ref1) {\n\t\t\t// <sha>^3 signals an untracked file in a stash and if we are trying to find its parent, use the empty tree\n\t\t\tif (ref1.endsWith('^3^')) {\n\t\t\t\tref1 = await this.provider.revision.getEmptyTreeSha(repoPath);\n\t\t\t}\n\t\t\tparams.push(isUncommittedStaged(ref1) ? '--staged' : ref1);\n\t\t}\n\t\tif (ref2) {\n\t\t\tparams.push(isUncommittedStaged(ref2) ? '--staged' : ref2);\n\t\t}\n\n\t\ttry {\n\t\t\treturn await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsDiff, encoding: options?.encoding },\n\t\t\t\t...params,\n\t\t\t\t'--',\n\t\t\t\tfileName,\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tconst match = GitErrors.badRevision.exec(ex.message);\n\t\t\tif (match !== null) {\n\t\t\t\tconst [, ref] = match;\n\n\t\t\t\t// If the bad ref is trying to find a parent ref, assume we hit to the last commit, so try again using the empty tree\n\t\t\t\tif (ref === ref1 && ref?.endsWith('^')) {\n\t\t\t\t\treturn this.diff(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tfileName,\n\t\t\t\t\t\tawait this.provider.revision.getEmptyTreeSha(repoPath),\n\t\t\t\t\t\tref2,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t/** Returns raw diff output comparing a file's revision with given contents via stdin. */\n\tasync diffContents(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref: string,\n\t\tcontents: string,\n\t\toptions?: { encoding?: string; filters?: GitDiffFilter[]; similarityThreshold?: number | null },\n\t): Promise<string> {\n\t\tconst params = [\n\t\t\t'diff',\n\t\t\t`-M${options?.similarityThreshold == null ? '' : `${options.similarityThreshold}%`}`,\n\t\t\t'--no-ext-diff',\n\t\t\t'-U0',\n\t\t\t'--minimal',\n\t\t];\n\n\t\tif (options?.filters != null && options.filters.length !== 0) {\n\t\t\tparams.push(`--diff-filter=${options.filters.join('')}`);\n\t\t}\n\n\t\tparams.push('--no-index');\n\n\t\ttry {\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\tconfigs: gitConfigsDiff,\n\t\t\t\t\tencoding: options?.encoding,\n\t\t\t\t\tstdin: contents,\n\t\t\t\t},\n\t\t\t\t...params,\n\t\t\t\t'--',\n\t\t\t\tfileName,\n\t\t\t\t// Pipe the contents to stdin\n\t\t\t\t'-',\n\t\t\t);\n\t\t\treturn result.stdout;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof GitError && ex.stdout) {\n\t\t\t\treturn ex.stdout;\n\t\t\t}\n\n\t\t\tconst match = GitErrors.badRevision.exec(ex.message);\n\t\t\tif (match !== null) {\n\t\t\t\tconst [, matchedRef] = match;\n\n\t\t\t\t// If the bad ref is trying to find a parent ref, assume we hit to the last commit, so try again using the empty tree\n\t\t\t\tif (matchedRef === ref && matchedRef?.endsWith('^')) {\n\t\t\t\t\treturn this.diffContents(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tfileName,\n\t\t\t\t\t\tawait this.provider.revision.getEmptyTreeSha(repoPath),\n\t\t\t\t\t\tcontents,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t/** Returns parsed diff hunks for a file between two revisions. */\n\t@debug()\n\tgetDiffForFile(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref1: string | undefined,\n\t\tref2?: string,\n\t\toptions?: { encoding?: string },\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\tconst cacheKey = `${normalizePath(fileName)}:${ref1 ?? ''}:${ref2 ?? ''}`;\n\t\treturn this.cache.diff.getOrCreate(\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\t() => this.getDiffForFileCore(repoPath, fileName, ref1, ref2, options),\n\t\t\t{ errorTTL: 1000 * 60 },\n\t\t);\n\t}\n\n\tprivate async getDiffForFileCore(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref1: string | undefined,\n\t\tref2: string | undefined,\n\t\toptions: { encoding?: string } | undefined,\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\t// Include renames (R) and copies (C) so content diffs on renamed files still surface;\n\t\t// --diff-filter runs after `-M` rename detection, so 'M' alone would drop valid rename diffs.\n\t\tconst result = await this.diff(repoPath, fileName, ref1, ref2, {\n\t\t\tencoding: options?.encoding,\n\t\t\tfilters: ['M', 'R', 'C'],\n\t\t\tlinesOfContext: 0,\n\t\t\trenames: true,\n\t\t\tsimilarityThreshold: this.context.config?.commits.similarityThreshold,\n\t\t});\n\t\treturn parseGitFileDiff(result.stdout);\n\t}\n\n\t/** Returns parsed diff hunks comparing a file's revision with given contents via stdin. */\n\t@debug()\n\tgetDiffForFileContents(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref: string,\n\t\tcontents: string,\n\t\toptions?: { encoding?: string },\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\tconst cacheKey = `${normalizePath(fileName)}:${ref}:~${fnv1aHash(contents)}`;\n\t\treturn this.cache.diff.getOrCreate(\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\t() => this.getDiffForFileContentsCore(repoPath, fileName, ref, contents, options),\n\t\t\t{ errorTTL: 1000 * 60 },\n\t\t);\n\t}\n\n\tprivate async getDiffForFileContentsCore(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref: string,\n\t\tcontents: string,\n\t\toptions: { encoding?: string } | undefined,\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\tconst data = await this.diffContents(repoPath, fileName, ref, contents, {\n\t\t\tencoding: options?.encoding,\n\t\t\tfilters: ['M', 'R', 'C'],\n\t\t\tsimilarityThreshold: this.context.config?.commits.similarityThreshold,\n\t\t});\n\t\treturn parseGitFileDiff(data);\n\t}\n\n\t/** Finds the most recent commit where the given path was copied, renamed, or deleted. */\n\t@debug()\n\tasync findPathStatusChanged(\n\t\trepoPath: string,\n\t\tpathspec: string,\n\t\trev: string | undefined,\n\t\toptions?: { filters?: GitDiffFilter[]; ordering?: 'date' | 'author-date' | 'topo' | null },\n\t): Promise<{ sha: string; file: LogParsedFile | undefined } | undefined> {\n\t\treturn findPathStatusChanged(this.git, repoPath, pathspec, rev, options);\n\t}\n\n\t@debug()\n\tasync openDiffTool(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\toptions?: { ref1?: string; ref2?: string; staged?: boolean; tool?: string },\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\t\tconst [relativePath, root] = splitPath(toFsPath(pathOrUri), repoPath);\n\n\t\ttry {\n\t\t\tlet tool = options?.tool;\n\t\t\tif (!tool) {\n\t\t\t\tconst scope = getScopedLogger();\n\n\t\t\t\ttool = await this.getDiffTool(root);\n\t\t\t\tif (tool == null) throw new Error('No diff tool found');\n\n\t\t\t\tscope?.debug(`Using tool=${tool}`);\n\t\t\t}\n\n\t\t\tawait this.git.run(\n\t\t\t\t{ cwd: root },\n\t\t\t\t'difftool',\n\t\t\t\t'--no-prompt',\n\t\t\t\t`--tool=${tool}`,\n\t\t\t\toptions?.staged ? '--staged' : undefined,\n\t\t\t\toptions?.ref1 ? options.ref1 : undefined,\n\t\t\t\toptions?.ref2 ? options.ref2 : undefined,\n\t\t\t\t'--',\n\t\t\t\trelativePath,\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif ((ex instanceof Error && ex.message === 'No diff tool found') || /Unknown .+? tool/.test(msg)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tl10n.t(\n\t\t\t\t\t\t'Unable to open changes because the specified diff tool cannot be found or no Git diff tool is configured',\n\t\t\t\t\t),\n\t\t\t\t\t{ cause: ex },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync openDirectoryCompare(repoPath: string, ref1: string, ref2?: string, tool?: string): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tif (!tool) {\n\t\t\t\tconst scope = getScopedLogger();\n\n\t\t\t\ttool = await this.getDiffTool(repoPath);\n\t\t\t\tif (tool == null) throw new Error('No diff tool found');\n\n\t\t\t\tscope?.debug(`Using tool=${tool}`);\n\t\t\t}\n\n\t\t\tawait this.git.run({ cwd: repoPath }, 'difftool', '--dir-diff', `--tool=${tool}`, ref1, ref2);\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif ((ex instanceof Error && ex.message === 'No diff tool found') || /Unknown .+? tool/.test(msg)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tl10n.t(\n\t\t\t\t\t\t'Unable to open directory compare because the specified diff tool cannot be found or no Git diff tool is configured',\n\t\t\t\t\t),\n\t\t\t\t\t{ cause: ex },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n}\n// Returns true when no --diff-filter is active or when it includes additions ('A' or '*').\n// Untracked files are semantically \"added\" — if a caller restricts filters to e.g. ['M'],\n// honor that and omit untracked.\nfunction filtersAllowUntracked(filters: GitDiffFilter[] | undefined): boolean {\n\tif (!filters?.length) return true;\n\treturn filters.includes('A') || filters.includes('*');\n}\n\n// Returns true when the path is a git pathspec we can't match with simple equality\n// (directory prefix, glob, or magic pathspec). In that case, skip the untracked merge\n// rather than risk excluding legitimate matches or including wrong ones.\nfunction isNonExactPathspec(path: string | undefined): boolean {\n\tif (!path) return false;\n\treturn path.endsWith('/') || /[*?[\\]]|^:/.test(path);\n}\n\n// Returns true when the `git diff` invocation shape includes the working tree\n// (i.e. `git diff`, `git diff HEAD`, or `git diff <ref>` with no `from`), and\n// therefore untracked files are a meaningful addition to the result.\nfunction isWorkingTreeComparison(to: string | undefined, from: string | undefined): boolean {\n\tif (to == null) return true;\n\tif (isRevisionRange(to) || isUncommittedStaged(to)) return false;\n\n\t// `to === uncommitted` always targets the working tree (`prepareToFromDiffArgs` sets\n\t// `from = 'HEAD'` when omitted, or diffs against the caller-supplied `from`).\n\tif (isUncommitted(to)) return true;\n\n\t// `git diff <from>` — `to === ''` means the caller explicitly asked for working tree vs `from`\n\tif (to === '') return from == null || !isUncommittedStaged(from);\n\n\t// `getChangedFilesCount` uses `prepareToFromDiffArgs`, which translates `to` (with no `from`)\n\t// to `${to}^ ${to}` UNLESS `to` is HEAD or empty.\n\tif (to.toUpperCase() === 'HEAD' && from == null) return true;\n\treturn false;\n}\n\nfunction prepareToFromDiffArgs(\n\tto: string,\n\tfrom: string | undefined,\n\targs: string[],\n\tnotation?: GitRevisionRangeNotation,\n): string {\n\tif (to === uncommitted) {\n\t\tif (from != null) {\n\t\t\targs.push(from);\n\t\t} else {\n\t\t\t// Get only unstaged changes\n\t\t\tfrom = 'HEAD';\n\t\t}\n\t} else if (to === uncommittedStaged) {\n\t\targs.push('--staged');\n\t\tif (from != null) {\n\t\t\targs.push(from);\n\t\t} else {\n\t\t\t// Get only staged changes\n\t\t\tfrom = 'HEAD';\n\t\t}\n\t} else if (from == null) {\n\t\tif (to === '' || to.toUpperCase() === 'HEAD') {\n\t\t\tfrom = 'HEAD';\n\t\t\targs.push(from);\n\t\t} else {\n\t\t\tfrom = `${to}^`;\n\t\t\targs.push(from, to);\n\t\t}\n\t} else if (to === '') {\n\t\targs.push(from);\n\t} else if (notation != null) {\n\t\targs.push(`${from}${notation}${to}`);\n\t} else {\n\t\targs.push(from, to);\n\t}\n\treturn from;\n}\n\nfunction createRevisionUri(\n\tprovider: CliGitProviderInternal,\n\trepoPath: string,\n\trelativePath: string,\n\tsha: string | undefined,\n): RevisionUri {\n\treturn {\n\t\turi: sha\n\t\t\t? fromUri({\n\t\t\t\t\tscheme: 'gitlens',\n\t\t\t\t\tauthority: encodeGitLensRevisionUriAuthority({ ref: sha, repoPath: repoPath }),\n\t\t\t\t\tpath: provider.getAbsoluteUri(relativePath, repoPath).path,\n\t\t\t\t})\n\t\t\t: provider.getAbsoluteUri(relativePath, repoPath),\n\t\tpath: relativePath,\n\t\tsha: sha,\n\t\trepoPath: repoPath,\n\t};\n}\n\nexport async function findPathStatusChanged(\n\tgit: Git,\n\trepoPath: string,\n\tpathspec: string,\n\trev: string | undefined,\n\toptions?: { filters?: GitDiffFilter[]; ordering?: 'date' | 'author-date' | 'topo' | null },\n): Promise<{ sha: string; file: LogParsedFile | undefined } | undefined> {\n\tconst parser = getShaAndFileSummaryLogParser();\n\n\tconst ordering = options?.ordering;\n\n\tconst result = await git.run(\n\t\t{ cwd: repoPath, configs: gitConfigsLog },\n\t\t'log',\n\t\t...parser.arguments,\n\t\tordering ? `--${ordering}-order` : undefined,\n\t\t'--no-walk',\n\t\t`--diff-filter=${options?.filters?.length ? options.filters.join('') : 'RCD'}`,\n\t\trev,\n\t\t// Note: --no-walk constrains to the exact commit (no ancestor search). Pathspec is omitted\n\t\t// because git suppresses rename detection with pathspecs (shows D instead of R, losing the destination path).\n\t\t'--',\n\t);\n\n\tconst commit = first(parser.parse(result.stdout));\n\tif (commit == null) return undefined;\n\n\tconst file = commit.files.find(f => f.path === pathspec || f.originalPath === pathspec);\n\treturn { sha: commit.sha, file: file };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"diff.js","names":[],"sources":["../../../../git-cli/src/providers/diff.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type {\n\tGitDiff,\n\tGitDiffFiles,\n\tGitDiffFilter,\n\tGitDiffShortStat,\n\tParsedGitDiff,\n\tParsedGitDiffHunks,\n} from '@gitlens/git/models/diff.js';\nimport type { GitFile } from '@gitlens/git/models/file.js';\nimport type { GitRevisionRange, GitRevisionRangeNotation } from '@gitlens/git/models/revision.js';\nimport { deletedOrMissing, uncommitted, uncommittedStaged } from '@gitlens/git/models/revision.js';\nimport {\n\tparseGitApplyFiles,\n\tparseGitDiff,\n\tparseGitDiffNumStatFiles,\n\tparseGitDiffShortStat,\n\tparseGitFileDiff,\n} from '@gitlens/git/parsers/diffParser.js';\nimport type {\n\tGitDiffSubProvider,\n\tNextComparisonUrisResult,\n\tPreviousComparisonUrisResult,\n\tPreviousRangeComparisonUrisResult,\n} from '@gitlens/git/providers/diff.js';\nimport type { DisposableTemporaryGitIndex } from '@gitlens/git/providers/staging.js';\nimport type { DiffRange, RevisionUri } from '@gitlens/git/providers/types.js';\nimport type { GitErrorHandling } from '@gitlens/git/run.types.js';\nimport {\n\tgetRevisionRangeParts,\n\tisRevisionRange,\n\tisUncommitted,\n\tisUncommittedStaged,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { encodeGitLensRevisionUriAuthority } from '@gitlens/git/utils/uriAuthority.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { fnv1aHash } from '@gitlens/utils/hash.js';\nimport { first } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fromUri, toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { GitResult } from '../exec/exec.types.js';\nimport type { Git } from '../exec/git.js';\nimport { gitConfigsDiff, gitConfigsLog, GitError, GitErrors } from '../exec/git.js';\nimport type { LogParsedFile } from '../parsers/logParser.js';\nimport { getShaAndFileRangeLogParser, getShaAndFileSummaryLogParser } from '../parsers/logParser.js';\n\nexport class DiffGitSubProvider implements GitDiffSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync getChangedFilesCount(\n\t\trepoPath: string,\n\t\tto?: string,\n\t\tfrom?: string,\n\t\toptions?: { uris?: (string | Uri)[]; includeUntracked?: boolean; errors?: GitErrorHandling },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiffShortStat | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args: string[] = [];\n\t\tif (to != null) {\n\t\t\t// Handle revision ranges specially if there is no `from`, otherwise `prepareToFromDiffArgs` will duplicate the range\n\t\t\tif (isRevisionRange(to) && from == null) {\n\t\t\t\targs.push(to);\n\t\t\t} else {\n\t\t\t\tprepareToFromDiffArgs(to, from, args);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// A default run swallows a failure matching a git warning (not a repository, say) into empty output\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsDiff, errors: options?.errors === 'throw' ? 'throw' : undefined },\n\t\t\t\t'diff',\n\t\t\t\t'--shortstat',\n\t\t\t\t'--no-ext-diff',\n\t\t\t\t...args,\n\t\t\t\t'--',\n\t\t\t\t...(options?.uris?.map(p => this.provider.getRelativePath(p, repoPath)) ?? []),\n\t\t\t);\n\n\t\t\tconst stat = result.stdout ? parseGitDiffShortStat(result.stdout) : undefined;\n\n\t\t\t// Merge in untracked files when the comparison involves the working tree.\n\t\t\t// Skip when a pathspec filter is active — mixing a path-filtered diff count with an\n\t\t\t// unfiltered untracked count would silently produce wrong totals.\n\t\t\tif (options?.includeUntracked && !options.uris?.length && isWorkingTreeComparison(to, from)) {\n\t\t\t\tconst untracked = (await this.provider.status?.getUntrackedFiles?.(repoPath)) ?? [];\n\t\t\t\tif (untracked.length) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfiles: (stat?.files ?? 0) + untracked.length,\n\t\t\t\t\t\tadditions: stat?.additions ?? 0,\n\t\t\t\t\t\tdeletions: stat?.deletions ?? 0,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn stat;\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif (options?.errors !== 'throw' && (GitErrors.noMergeBase.test(msg) || GitErrors.badRevision.test(msg))) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getDiff(\n\t\trepoPath: string,\n\t\tto: string,\n\t\tfrom?: string,\n\t\toptions?: {\n\t\t\tcontext?: number;\n\t\t\tindex?: DisposableTemporaryGitIndex;\n\t\t\tnotation?: GitRevisionRangeNotation;\n\t\t\turis?: (string | Uri)[];\n\t\t\terrors?: GitErrorHandling;\n\t\t},\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiff | undefined> {\n\t\tconst scope = getScopedLogger();\n\t\tconst args = [`-U${options?.context ?? 3}`];\n\n\t\tif (to != null && isRevisionRange(to)) {\n\t\t\tconst parts = getRevisionRangeParts(to);\n\t\t\tif (parts != null) {\n\t\t\t\tto = parts.right ?? '';\n\t\t\t\tfrom = parts.left;\n\t\t\t\toptions = { ...options, notation: parts.notation };\n\t\t\t}\n\t\t}\n\n\t\tconst hasFrom = from != null;\n\t\tfrom = prepareToFromDiffArgs(to, from, args, options?.notation);\n\n\t\tlet paths: Set<string> | undefined;\n\t\tif (options?.uris) {\n\t\t\tpaths = new Set<string>(options.uris.map(p => this.provider.getRelativePath(p, repoPath)));\n\t\t\targs.push('--', ...paths);\n\t\t}\n\n\t\tlet result;\n\t\ttry {\n\t\t\tresult = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsDiff, errors: 'throw', env: options?.index?.env },\n\t\t\t\t'diff',\n\t\t\t\t...args,\n\t\t\t\targs.includes('--') ? undefined : '--',\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\t// Before its first commit HEAD names nothing, so a diff from it fails; the empty tree is what it is against\n\t\t\tif (isHead(from) && (await this.isUnbornHeadFailure(repoPath, ex))) {\n\t\t\t\tconst emptyTree = await this.provider.revision.getEmptyTreeSha(repoPath);\n\t\t\t\t// With no `from`, a `to` of HEAD means the working tree against HEAD, so it is the empty tree alone\n\t\t\t\tconst retried = await this.getDiff(\n\t\t\t\t\trepoPath,\n\t\t\t\t\t!hasFrom && isHead(to) ? '' : to,\n\t\t\t\t\temptyTree,\n\t\t\t\t\toptions,\n\t\t\t\t\t_cancellation,\n\t\t\t\t);\n\t\t\t\treturn retried != null ? { ...retried, to: to } : undefined;\n\t\t\t}\n\n\t\t\tscope?.error(ex);\n\t\t\tif (options?.errors === 'throw') throw ex;\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst diff: GitDiff = { contents: result.stdout, from: from, to: to, notation: options?.notation };\n\t\treturn diff;\n\t}\n\n\t/** Whether `ex` is git failing to resolve `HEAD` because the repository has no commit yet */\n\tprivate async isUnbornHeadFailure(repoPath: string, ex: unknown): Promise<boolean> {\n\t\tconst ref = GitErrors.badRevision.exec(String(ex))?.[1];\n\t\tif (!isHead(ref)) return false;\n\n\t\treturn (await this.provider.refs.validateReference(repoPath, 'HEAD', { force: true })) == null;\n\t}\n\n\t@debug()\n\tasync getParsedDiff(\n\t\trepoPath: string,\n\t\tto: string,\n\t\tfrom?: string,\n\t\toptions?: {\n\t\t\tcontext?: number;\n\t\t\tnotation?: GitRevisionRangeNotation;\n\t\t\turis?: (string | Uri)[];\n\t\t\terrors?: GitErrorHandling;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<ParsedGitDiff | undefined> {\n\t\tconst diff = await this.getDiff(repoPath, to, from, options, cancellation);\n\t\tif (!diff?.contents) return undefined;\n\n\t\treturn parseGitDiff(diff.contents);\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync getDiffFiles(\n\t\trepoPath: string,\n\t\tcontents: string,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiffFiles | undefined> {\n\t\tconst result = await this.git.run(\n\t\t\t{ cwd: repoPath, configs: gitConfigsLog, stdin: contents },\n\t\t\t'apply',\n\t\t\t'--numstat',\n\t\t\t'--summary',\n\t\t\t'-z',\n\t\t\t'-',\n\t\t);\n\t\tif (!result.stdout) return undefined;\n\n\t\tconst files = parseGitApplyFiles(result.stdout, repoPath);\n\t\treturn {\n\t\t\tfiles: files,\n\t\t};\n\t}\n\n\t@debug()\n\tasync getDiffStatus(\n\t\trepoPath: string,\n\t\tref1OrRange: string | GitRevisionRange,\n\t\tref2?: string,\n\t\toptions?: {\n\t\t\tfilters?: GitDiffFilter[];\n\t\t\tincludeUntracked?: boolean;\n\t\t\tpath?: string;\n\t\t\trenameLimit?: number;\n\t\t\tsimilarityThreshold?: number;\n\t\t\terrors?: GitErrorHandling;\n\t\t},\n\t): Promise<GitFile[] | undefined> {\n\t\ttry {\n\t\t\tconst similarityThreshold =\n\t\t\t\toptions?.similarityThreshold ?? this.context.config?.commits.similarityThreshold;\n\t\t\tconst configs =\n\t\t\t\toptions?.renameLimit != null\n\t\t\t\t\t? [...gitConfigsDiff, '-c', `diff.renameLimit=${options.renameLimit}`]\n\t\t\t\t\t: gitConfigsDiff;\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: configs, errors: options?.errors === 'throw' ? 'throw' : undefined },\n\t\t\t\t'diff',\n\t\t\t\t'--numstat',\n\t\t\t\t'--summary',\n\t\t\t\t`-M${similarityThreshold == null ? '' : `${similarityThreshold}%`}`,\n\t\t\t\t'--no-ext-diff',\n\t\t\t\t'-z',\n\t\t\t\toptions?.filters?.length ? `--diff-filter=${options.filters.join('')}` : undefined,\n\t\t\t\tref1OrRange ? ref1OrRange : undefined,\n\t\t\t\tref2 ? ref2 : undefined,\n\t\t\t\t'--',\n\t\t\t\toptions?.path ? options.path : undefined,\n\t\t\t);\n\n\t\t\tconst files = result.stdout ? (parseGitDiffNumStatFiles(result.stdout, repoPath) ?? []) : [];\n\n\t\t\t// Merge in untracked files when the comparison involves the working tree.\n\t\t\t// Skip when `filters` excludes additions (untracked entries are semantically 'A'/added),\n\t\t\t// or when `path` is a non-exact pathspec we can't reliably match against the untracked list.\n\t\t\tif (\n\t\t\t\toptions?.includeUntracked &&\n\t\t\t\tref2 == null &&\n\t\t\t\ttypeof ref1OrRange === 'string' &&\n\t\t\t\t!isRevisionRange(ref1OrRange) &&\n\t\t\t\t!isUncommittedStaged(ref1OrRange) &&\n\t\t\t\tfiltersAllowUntracked(options.filters) &&\n\t\t\t\t!isNonExactPathspec(options.path)\n\t\t\t) {\n\t\t\t\tconst untracked = (await this.provider.status?.getUntrackedFiles?.(repoPath)) ?? [];\n\t\t\t\tif (untracked.length) {\n\t\t\t\t\tconst seen = new Set(files.map(f => f.path));\n\t\t\t\t\tfor (const file of untracked) {\n\t\t\t\t\t\tif (seen.has(file.path)) continue;\n\t\t\t\t\t\tif (options.path && options.path !== file.path) continue;\n\n\t\t\t\t\t\tfiles.push(file);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn files.length ? files : undefined;\n\t\t} catch (ex) {\n\t\t\tif (options?.errors === 'throw') throw ex;\n\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getDiffTool(repoPath?: string): Promise<string | undefined> {\n\t\treturn (\n\t\t\t(await this.provider.config.getConfig?.(repoPath, 'diff.guitool', { runGitLocally: true })) ??\n\t\t\tthis.provider.config.getConfig?.(repoPath, 'diff.tool', { runGitLocally: true })\n\t\t);\n\t}\n\n\t@debug()\n\tasync getNextComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\toptions?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<NextComparisonUrisResult | undefined> {\n\t\t// If we have no revision there is no next commit\n\t\tif (!rev) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\tif (isUncommittedStaged(rev)) {\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, relativePath, rev),\n\t\t\t\tnext: createRevisionUri(this.provider, repoPath, relativePath, undefined),\n\t\t\t};\n\t\t} else if (isUncommitted(rev)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parser = getShaAndFileSummaryLogParser();\n\t\t\tconst args = ['log', ...parser.arguments];\n\n\t\t\tconst ordering = options?.ordering ?? this.context.config?.commits.ordering;\n\t\t\tif (ordering) {\n\t\t\t\targs.push(`--${ordering}-order`);\n\t\t\t}\n\n\t\t\targs.push(\n\t\t\t\t// Use reverse to get the next commits (oldest to newest instead of newest to oldest)\n\t\t\t\t'--reverse',\n\t\t\t);\n\n\t\t\tif (rev !== deletedOrMissing) {\n\t\t\t\targs.push(\n\t\t\t\t\t// Ancestry path to ensure we only follow the path from the given revision to HEAD\n\t\t\t\t\t'--ancestry-path',\n\t\t\t\t\t// Range from the given revision to HEAD\n\t\t\t\t\t`${rev}..HEAD`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Follow file history and specify the file path\n\t\t\targs.push('--follow', '--', relativePath);\n\n\t\t\t// Unbounded --follow walk over file history can be slow on long histories — queue as background\n\t\t\t// so it doesn't compete with interactive work.\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsLog, priority: 'background' },\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tlet currentSha;\n\t\t\tlet currentPath;\n\n\t\t\tif (skip === 0) {\n\t\t\t\tcurrentSha = rev;\n\t\t\t\tcurrentPath = relativePath;\n\t\t\t} else {\n\t\t\t\tskip--;\n\t\t\t}\n\n\t\t\tlet nextSha;\n\t\t\tlet nextPath;\n\n\t\t\tlet file;\n\t\t\tfor (const commit of parser.parse(result.stdout)) {\n\t\t\t\tconst path = relativePath;\n\t\t\t\tfile = commit.files.find(f => f.path === path || f.originalPath === path);\n\t\t\t\t// Keep track of the file changing paths\n\t\t\t\tif (file?.path && file.path !== relativePath) {\n\t\t\t\t\trelativePath = file.path;\n\t\t\t\t}\n\n\t\t\t\tif (skip > 0) {\n\t\t\t\t\tskip--;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (currentSha == null) {\n\t\t\t\t\tcurrentSha = commit.sha;\n\t\t\t\t\tcurrentPath = file?.path ?? relativePath;\n\t\t\t\t} else if (nextSha == null) {\n\t\t\t\t\t// if (commit.sha === rev) continue;\n\n\t\t\t\t\tnextSha = commit.sha;\n\t\t\t\t\tnextPath = file?.path ?? relativePath;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentSha == null || currentPath == null) {\n\t\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, relativePath);\n\t\t\t\tif (status != null) {\n\t\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\t\tcurrentSha = uncommittedStaged;\n\t\t\t\t\t\tcurrentPath = status.originalPath ?? status.path;\n\t\t\t\t\t\tnextSha = '';\n\t\t\t\t\t\tnextPath = status.path;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (nextSha == null || nextPath == null) {\n\t\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, relativePath);\n\t\t\t\tif (status != null) {\n\t\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\t\tnextSha = uncommittedStaged;\n\t\t\t\t\t\tnextPath = status.originalPath ?? status.path;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnextSha = '';\n\t\t\t\t\t\tnextPath = status.path;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnextSha = '';\n\t\t\t\t\tnextPath = relativePath;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha || undefined),\n\t\t\t\tnext: createRevisionUri(\n\t\t\t\t\tthis.provider,\n\t\t\t\t\trepoPath,\n\t\t\t\t\tnextPath ?? currentPath,\n\t\t\t\t\t(nextSha ?? deletedOrMissing) || undefined,\n\t\t\t\t),\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getPreviousComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\tunsaved?: boolean,\n\t\toptions?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousComparisonUrisResult | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tif (rev === uncommitted) {\n\t\t\trev = undefined;\n\t\t}\n\n\t\t/* Rules:\n\t\t * Starting from working tree (rev is empty or undefined):\n\t\t * 1. Check file status:\n\t\t * 1.1. If file has both staged and working (or unsaved) changes:\n\t\t * - If skip=0: diff working with staged\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.2. If file has only staged changes:\n\t\t * - If skip=0: diff working with HEAD\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.3. If file has only working changes:\n\t\t * - If skip=0: diff working with HEAD\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.4. If file has no changes (or no status found):\n\t\t * - If skip=0: diff working with HEAD~1\n\t\t * - If skip>0: skip through revs starting at HEAD~1\n\t\t *\n\t\t * Starting from staged (rev is uncommittedStaged):\n\t\t * 1. Check file status:\n\t\t * 1.1. If status exists:\n\t\t * - If skip=0: diff staged with HEAD\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * 1.2. If status doesn't exist:\n\t\t * - If skip=0: diff HEAD with HEAD~1\n\t\t * - If skip>0: skip through revs starting at HEAD\n\t\t *\n\t\t * Starting from a commit (rev is a SHA):\n\t\t * - If skip=0: diff SHA with SHA^\n\t\t * - If skip>0: skip through revs starting at SHA\n\t\t */\n\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\t\tlet skipPrev = 0;\n\n\t\tlet revs: [string, string][] = [];\n\t\tif (!rev) {\n\t\t\trevs = [['', relativePath]];\n\n\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, pathOrUri);\n\t\t\tif (status != null) {\n\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\trevs.push([uncommittedStaged, status.originalPath ?? status.path]);\n\t\t\t\t}\n\n\t\t\t\trevs.push(['HEAD', status.originalPath ?? status.path]);\n\t\t\t\tif (status.workingTreeStatus == null && !unsaved) {\n\t\t\t\t\tif (skip === 0 || status.indexStatus == null) {\n\t\t\t\t\t\t// Skip over the HEAD commit to get a diff, because working and HEAD are the same\n\t\t\t\t\t\tskipPrev++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trevs.push(['HEAD', relativePath]);\n\t\t\t\tif (!unsaved) {\n\t\t\t\t\t// Skip over the HEAD commit to get a diff, because working and HEAD are the same\n\t\t\t\t\tskipPrev++;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (isUncommittedStaged(rev)) {\n\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, pathOrUri);\n\t\t\tif (status != null) {\n\t\t\t\trevs = [\n\t\t\t\t\t[uncommittedStaged, status.originalPath ?? status.path],\n\t\t\t\t\t['HEAD', status.originalPath ?? status.path],\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\t// Even though we supposedly started at staged, there is no staged version\n\t\t\t\trevs = [['HEAD', relativePath]];\n\t\t\t\tif (skip > 0) {\n\t\t\t\t\tskip--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet currentSha;\n\t\tlet currentPath;\n\n\t\tif (revs.length) {\n\t\t\tskip++;\n\t\t\twhile (revs.length && skip > 0) {\n\t\t\t\tskip--;\n\t\t\t\t[rev, relativePath] = revs.shift()!;\n\t\t\t}\n\n\t\t\tif (rev !== 'HEAD') {\n\t\t\t\tcurrentSha = rev;\n\t\t\t\tcurrentPath = relativePath;\n\n\t\t\t\tskipPrev++;\n\t\t\t\twhile (revs.length && skipPrev > 0) {\n\t\t\t\t\tskipPrev--;\n\t\t\t\t\t[rev, relativePath] = revs.shift()!;\n\t\t\t\t}\n\n\t\t\t\tif (skipPrev > 0) {\n\t\t\t\t\tskip += skipPrev;\n\t\t\t\t}\n\n\t\t\t\tif (rev !== 'HEAD' && skip === 0) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha),\n\t\t\t\t\t\tprevious: createRevisionUri(this.provider, repoPath, relativePath, rev),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst parser = getShaAndFileSummaryLogParser();\n\t\t\tconst args = ['log', ...parser.arguments, `-n${skip + 2}`]; // Don't use --skip as it doesn't work with --follow\n\n\t\t\tconst ordering = options?.ordering ?? this.context.config?.commits.ordering;\n\t\t\tif (ordering) {\n\t\t\t\targs.push(`--${ordering}-order`);\n\t\t\t}\n\n\t\t\targs.push('--follow', rev!, '--', relativePath);\n\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\tconfigs: gitConfigsLog,\n\t\t\t\t\tcaching: { cache: this.cache.gitResults, options: { accessTTL: 5 * 60 * 1000 } },\n\t\t\t\t},\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tlet previousSha;\n\t\t\tlet previousPath;\n\t\t\tlet file;\n\n\t\t\tfor (const commit of parser.parse(result.stdout)) {\n\t\t\t\tconst path = relativePath;\n\t\t\t\tfile = commit.files.find(f => f.path === path || f.originalPath === path);\n\t\t\t\t// Keep track of the file changing paths\n\t\t\t\tif (file?.originalPath && file.originalPath !== relativePath) {\n\t\t\t\t\trelativePath = file.originalPath;\n\t\t\t\t}\n\n\t\t\t\tif (skip > 0) {\n\t\t\t\t\tskip--;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (currentSha == null) {\n\t\t\t\t\tcurrentSha = commit.sha;\n\t\t\t\t\tcurrentPath = file?.path ?? relativePath;\n\t\t\t\t} else if (previousSha == null) {\n\t\t\t\t\tif (commit.sha === rev) continue;\n\n\t\t\t\t\tpreviousSha = commit.sha;\n\t\t\t\t\tpreviousPath = file?.path ?? relativePath;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentSha == null || currentPath == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha || undefined),\n\t\t\t\tprevious: createRevisionUri(\n\t\t\t\t\tthis.provider,\n\t\t\t\t\trepoPath,\n\t\t\t\t\tpreviousPath ?? currentPath,\n\t\t\t\t\tpreviousSha ?? deletedOrMissing,\n\t\t\t\t),\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getPreviousComparisonUrisForRange(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\trange: DiffRange,\n\t\toptions?: { ordering?: 'date' | 'author-date' | 'topo' | null; skipFirstRev?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousRangeComparisonUrisResult | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tif (rev === uncommitted) {\n\t\t\trev = undefined;\n\t\t}\n\n\t\tlet currentSha;\n\t\tlet currentPath;\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\t\tconst skipFirstRev = options?.skipFirstRev ?? true;\n\n\t\t// If we are at the working tree (i.e. no ref), we need to dig deeper to figure out where to go\n\t\tif (!rev) {\n\t\t\tconst status = await this.provider.status?.getStatusForFile?.(repoPath, pathOrUri);\n\t\t\tif (status != null) {\n\t\t\t\tif (status.indexStatus != null) {\n\t\t\t\t\tif (status.workingTreeStatus != null && !skipFirstRev) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, relativePath, undefined),\n\t\t\t\t\t\t\tprevious: createRevisionUri(this.provider, repoPath, relativePath, uncommittedStaged),\n\t\t\t\t\t\t\trange: range,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrentSha = uncommittedStaged;\n\t\t\t\t\tcurrentPath = status.originalPath ?? status.path;\n\t\t\t\t\tif (status.originalPath != null) {\n\t\t\t\t\t\trelativePath = status.originalPath;\n\t\t\t\t\t}\n\t\t\t\t\trev = uncommittedStaged;\n\t\t\t\t} else if (status.workingTreeStatus != null && !skipFirstRev) {\n\t\t\t\t\tcurrentSha = '';\n\t\t\t\t\tcurrentPath = relativePath;\n\t\t\t\t\trev = '';\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (!skipFirstRev) {\n\t\t\tcurrentSha = rev;\n\t\t\tcurrentPath = relativePath;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parser = getShaAndFileRangeLogParser();\n\t\t\tconst args = ['log', ...parser.arguments, '-n2']; // Don't use --skip as it doesn't work with --follow\n\n\t\t\tconst ordering = options?.ordering ?? this.context.config?.commits.ordering;\n\t\t\tif (ordering) {\n\t\t\t\targs.push(`--${ordering}-order`);\n\t\t\t}\n\n\t\t\tif (rev && !isUncommittedStaged(rev)) {\n\t\t\t\targs.push(rev);\n\t\t\t}\n\n\t\t\targs.push(`-L${range.startLine},${range.endLine}:${relativePath}`);\n\n\t\t\tlet result: GitResult;\n\t\t\ttry {\n\t\t\t\tresult = await this.git.run({ cwd: repoPath, configs: gitConfigsLog }, ...args);\n\t\t\t} catch (ex) {\n\t\t\t\tif (rev && !isUncommittedStaged(rev)) throw ex;\n\n\t\t\t\t// If the line count is invalid reset to a valid range\n\t\t\t\tconst match = GitErrors.invalidLineCount.exec(ex?.toString() ?? '');\n\t\t\t\tif (match == null) throw ex;\n\n\t\t\t\tconst line = parseInt(match[1], 10);\n\t\t\t\tif (isNaN(line)) throw ex;\n\n\t\t\t\tconst index = args.findIndex(a => a.startsWith('-L'));\n\t\t\t\tif (index === -1) throw ex;\n\n\t\t\t\trange = {\n\t\t\t\t\tstartLine: Math.min(range.startLine, line),\n\t\t\t\t\tstartCharacter: range.startCharacter,\n\t\t\t\t\tendLine: Math.min(range.endLine, line),\n\t\t\t\t\tendCharacter: range.endCharacter,\n\t\t\t\t\tactive: range.active,\n\t\t\t\t};\n\n\t\t\t\targs.splice(index, 1, `-L${range.startLine},${range.endLine}:${relativePath}`);\n\t\t\t\tresult = await this.git.run({ cwd: repoPath, configs: gitConfigsLog }, ...args);\n\t\t\t}\n\n\t\t\tlet currentRange;\n\t\t\tlet previousSha;\n\t\t\tlet previousPath;\n\t\t\tlet file;\n\n\t\t\tfor (const commit of parser.parse(result.stdout)) {\n\t\t\t\tconst path = relativePath;\n\t\t\t\tfile = commit.files.find(f => f.path === path || f.originalPath === path);\n\t\t\t\t// If we couldn't find the file, but there is only one file in the commit, use that one and assume the filename changed\n\t\t\t\tif (file == null && commit.files.length === 1) {\n\t\t\t\t\tfile = commit.files[0];\n\t\t\t\t\trelativePath = file.path;\n\t\t\t\t}\n\t\t\t\t// Keep track of the file changing paths\n\t\t\t\tif (file?.originalPath && file.originalPath !== relativePath) {\n\t\t\t\t\trelativePath = file.originalPath;\n\t\t\t\t}\n\n\t\t\t\tif (currentSha == null) {\n\t\t\t\t\tcurrentSha = commit.sha;\n\t\t\t\t\tcurrentPath = file?.path ?? relativePath;\n\t\t\t\t\tcurrentRange =\n\t\t\t\t\t\tfile?.range != null ? { ...file.range, startCharacter: 1, endCharacter: 1 } : undefined;\n\t\t\t\t} else if (previousSha == null) {\n\t\t\t\t\tif (commit.sha === rev) continue;\n\n\t\t\t\t\tpreviousSha = commit.sha;\n\t\t\t\t\tpreviousPath = file?.path ?? relativePath;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentSha == null || currentPath == null) return undefined;\n\n\t\t\t// If we have no previous SHA but have a real current SHA, resolve the parent commit.\n\t\t\t// This handles the case where a line is newly added — the line has no prior history,\n\t\t\t// but the file likely existed at the parent commit\n\t\t\tif (previousSha == null && currentSha) {\n\t\t\t\tpreviousSha =\n\t\t\t\t\t(await this.provider.refs.validateReference(repoPath, `${currentSha}^`)) ?? deletedOrMissing;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(this.provider, repoPath, currentPath, currentSha || undefined),\n\t\t\t\tprevious: createRevisionUri(\n\t\t\t\t\tthis.provider,\n\t\t\t\t\trepoPath,\n\t\t\t\t\tpreviousPath ?? currentPath,\n\t\t\t\t\tpreviousSha ?? deletedOrMissing,\n\t\t\t\t),\n\t\t\t\trange: currentRange ?? range,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t/** Returns raw diff output for a file between two revisions. */\n\tasync diff(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref1?: string,\n\t\tref2?: string,\n\t\toptions?: {\n\t\t\tencoding?: string;\n\t\t\tfilters?: GitDiffFilter[];\n\t\t\tlinesOfContext?: number;\n\t\t\trenames?: boolean;\n\t\t\tsimilarityThreshold?: number | null;\n\t\t},\n\t): Promise<GitResult> {\n\t\tconst params = ['diff', '--no-ext-diff', '--minimal'];\n\n\t\tif (options?.linesOfContext != null) {\n\t\t\tparams.push(`-U${options.linesOfContext}`);\n\t\t}\n\n\t\tif (options?.renames) {\n\t\t\tparams.push(`-M${options.similarityThreshold == null ? '' : `${options.similarityThreshold}%`}`);\n\t\t}\n\n\t\tif (options?.filters != null && options.filters.length !== 0) {\n\t\t\tparams.push(`--diff-filter=${options.filters.join('')}`);\n\t\t}\n\n\t\tif (ref1) {\n\t\t\t// <sha>^3 signals an untracked file in a stash and if we are trying to find its parent, use the empty tree\n\t\t\tif (ref1.endsWith('^3^')) {\n\t\t\t\tref1 = await this.provider.revision.getEmptyTreeSha(repoPath);\n\t\t\t}\n\t\t\tparams.push(isUncommittedStaged(ref1) ? '--staged' : ref1);\n\t\t}\n\t\tif (ref2) {\n\t\t\tparams.push(isUncommittedStaged(ref2) ? '--staged' : ref2);\n\t\t}\n\n\t\ttry {\n\t\t\treturn await this.git.run(\n\t\t\t\t{ cwd: repoPath, configs: gitConfigsDiff, encoding: options?.encoding },\n\t\t\t\t...params,\n\t\t\t\t'--',\n\t\t\t\tfileName,\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tconst match = GitErrors.badRevision.exec(ex.message);\n\t\t\tif (match !== null) {\n\t\t\t\tconst [, ref] = match;\n\n\t\t\t\t// If the bad ref is trying to find a parent ref, assume we hit to the last commit, so try again using the empty tree\n\t\t\t\tif (ref === ref1 && ref?.endsWith('^')) {\n\t\t\t\t\treturn this.diff(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tfileName,\n\t\t\t\t\t\tawait this.provider.revision.getEmptyTreeSha(repoPath),\n\t\t\t\t\t\tref2,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t/** Returns raw diff output comparing a file's revision with given contents via stdin. */\n\tasync diffContents(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref: string,\n\t\tcontents: string,\n\t\toptions?: { encoding?: string; filters?: GitDiffFilter[]; similarityThreshold?: number | null },\n\t): Promise<string> {\n\t\tconst params = [\n\t\t\t'diff',\n\t\t\t`-M${options?.similarityThreshold == null ? '' : `${options.similarityThreshold}%`}`,\n\t\t\t'--no-ext-diff',\n\t\t\t'-U0',\n\t\t\t'--minimal',\n\t\t];\n\n\t\tif (options?.filters != null && options.filters.length !== 0) {\n\t\t\tparams.push(`--diff-filter=${options.filters.join('')}`);\n\t\t}\n\n\t\tparams.push('--no-index');\n\n\t\ttry {\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\tconfigs: gitConfigsDiff,\n\t\t\t\t\tencoding: options?.encoding,\n\t\t\t\t\tstdin: contents,\n\t\t\t\t},\n\t\t\t\t...params,\n\t\t\t\t'--',\n\t\t\t\tfileName,\n\t\t\t\t// Pipe the contents to stdin\n\t\t\t\t'-',\n\t\t\t);\n\t\t\treturn result.stdout;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof GitError && ex.stdout) {\n\t\t\t\treturn ex.stdout;\n\t\t\t}\n\n\t\t\tconst match = GitErrors.badRevision.exec(ex.message);\n\t\t\tif (match !== null) {\n\t\t\t\tconst [, matchedRef] = match;\n\n\t\t\t\t// If the bad ref is trying to find a parent ref, assume we hit to the last commit, so try again using the empty tree\n\t\t\t\tif (matchedRef === ref && matchedRef?.endsWith('^')) {\n\t\t\t\t\treturn this.diffContents(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tfileName,\n\t\t\t\t\t\tawait this.provider.revision.getEmptyTreeSha(repoPath),\n\t\t\t\t\t\tcontents,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t/** Returns parsed diff hunks for a file between two revisions. */\n\t@debug()\n\tgetDiffForFile(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref1: string | undefined,\n\t\tref2?: string,\n\t\toptions?: { encoding?: string },\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\tconst cacheKey = `${normalizePath(fileName)}:${ref1 ?? ''}:${ref2 ?? ''}`;\n\t\treturn this.cache.diff.getOrCreate(\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\t() => this.getDiffForFileCore(repoPath, fileName, ref1, ref2, options),\n\t\t\t{ errorTTL: 1000 * 60 },\n\t\t);\n\t}\n\n\tprivate async getDiffForFileCore(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref1: string | undefined,\n\t\tref2: string | undefined,\n\t\toptions: { encoding?: string } | undefined,\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\t// Include renames (R) and copies (C) so content diffs on renamed files still surface;\n\t\t// --diff-filter runs after `-M` rename detection, so 'M' alone would drop valid rename diffs.\n\t\tconst result = await this.diff(repoPath, fileName, ref1, ref2, {\n\t\t\tencoding: options?.encoding,\n\t\t\tfilters: ['M', 'R', 'C'],\n\t\t\tlinesOfContext: 0,\n\t\t\trenames: true,\n\t\t\tsimilarityThreshold: this.context.config?.commits.similarityThreshold,\n\t\t});\n\t\treturn parseGitFileDiff(result.stdout);\n\t}\n\n\t/** Returns parsed diff hunks comparing a file's revision with given contents via stdin. */\n\t@debug()\n\tgetDiffForFileContents(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref: string,\n\t\tcontents: string,\n\t\toptions?: { encoding?: string },\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\tconst cacheKey = `${normalizePath(fileName)}:${ref}:~${fnv1aHash(contents)}`;\n\t\treturn this.cache.diff.getOrCreate(\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\t() => this.getDiffForFileContentsCore(repoPath, fileName, ref, contents, options),\n\t\t\t{ errorTTL: 1000 * 60 },\n\t\t);\n\t}\n\n\tprivate async getDiffForFileContentsCore(\n\t\trepoPath: string,\n\t\tfileName: string,\n\t\tref: string,\n\t\tcontents: string,\n\t\toptions: { encoding?: string } | undefined,\n\t): Promise<ParsedGitDiffHunks | undefined> {\n\t\tconst data = await this.diffContents(repoPath, fileName, ref, contents, {\n\t\t\tencoding: options?.encoding,\n\t\t\tfilters: ['M', 'R', 'C'],\n\t\t\tsimilarityThreshold: this.context.config?.commits.similarityThreshold,\n\t\t});\n\t\treturn parseGitFileDiff(data);\n\t}\n\n\t/** Finds the most recent commit where the given path was copied, renamed, or deleted. */\n\t@debug()\n\tasync findPathStatusChanged(\n\t\trepoPath: string,\n\t\tpathspec: string,\n\t\trev: string | undefined,\n\t\toptions?: { filters?: GitDiffFilter[]; ordering?: 'date' | 'author-date' | 'topo' | null },\n\t): Promise<{ sha: string; file: LogParsedFile | undefined } | undefined> {\n\t\treturn findPathStatusChanged(this.git, repoPath, pathspec, rev, options);\n\t}\n\n\t@debug()\n\tasync openDiffTool(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\toptions?: { ref1?: string; ref2?: string; staged?: boolean; tool?: string },\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\t\tconst [relativePath, root] = splitPath(toFsPath(pathOrUri), repoPath);\n\n\t\ttry {\n\t\t\tlet tool = options?.tool;\n\t\t\tif (!tool) {\n\t\t\t\tconst scope = getScopedLogger();\n\n\t\t\t\ttool = await this.getDiffTool(root);\n\t\t\t\tif (tool == null) throw new Error('No diff tool found');\n\n\t\t\t\tscope?.debug(`Using tool=${tool}`);\n\t\t\t}\n\n\t\t\tawait this.git.run(\n\t\t\t\t{ cwd: root },\n\t\t\t\t'difftool',\n\t\t\t\t'--no-prompt',\n\t\t\t\t`--tool=${tool}`,\n\t\t\t\toptions?.staged ? '--staged' : undefined,\n\t\t\t\toptions?.ref1 ? options.ref1 : undefined,\n\t\t\t\toptions?.ref2 ? options.ref2 : undefined,\n\t\t\t\t'--',\n\t\t\t\trelativePath,\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif ((ex instanceof Error && ex.message === 'No diff tool found') || /Unknown .+? tool/.test(msg)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tl10n.t(\n\t\t\t\t\t\t'Unable to open changes because the specified diff tool cannot be found or no Git diff tool is configured',\n\t\t\t\t\t),\n\t\t\t\t\t{ cause: ex },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync openDirectoryCompare(repoPath: string, ref1: string, ref2?: string, tool?: string): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tif (!tool) {\n\t\t\t\tconst scope = getScopedLogger();\n\n\t\t\t\ttool = await this.getDiffTool(repoPath);\n\t\t\t\tif (tool == null) throw new Error('No diff tool found');\n\n\t\t\t\tscope?.debug(`Using tool=${tool}`);\n\t\t\t}\n\n\t\t\tawait this.git.run({ cwd: repoPath }, 'difftool', '--dir-diff', `--tool=${tool}`, ref1, ref2);\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif ((ex instanceof Error && ex.message === 'No diff tool found') || /Unknown .+? tool/.test(msg)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tl10n.t(\n\t\t\t\t\t\t'Unable to open directory compare because the specified diff tool cannot be found or no Git diff tool is configured',\n\t\t\t\t\t),\n\t\t\t\t\t{ cause: ex },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n}\n// Returns true when no --diff-filter is active or when it includes additions ('A' or '*').\n// Untracked files are semantically \"added\" — if a caller restricts filters to e.g. ['M'],\n// honor that and omit untracked.\nfunction filtersAllowUntracked(filters: GitDiffFilter[] | undefined): boolean {\n\tif (!filters?.length) return true;\n\treturn filters.includes('A') || filters.includes('*');\n}\n\n// Returns true when the path is a git pathspec we can't match with simple equality\n// (directory prefix, glob, or magic pathspec). In that case, skip the untracked merge\n// rather than risk excluding legitimate matches or including wrong ones.\nfunction isNonExactPathspec(path: string | undefined): boolean {\n\tif (!path) return false;\n\treturn path.endsWith('/') || /[*?[\\]]|^:/.test(path);\n}\n\n// Returns true when the `git diff` invocation shape includes the working tree\n// (i.e. `git diff`, `git diff HEAD`, or `git diff <ref>` with no `from`), and\n// therefore untracked files are a meaningful addition to the result.\nfunction isWorkingTreeComparison(to: string | undefined, from: string | undefined): boolean {\n\tif (to == null) return true;\n\tif (isRevisionRange(to) || isUncommittedStaged(to)) return false;\n\n\t// `to === uncommitted` always targets the working tree (`prepareToFromDiffArgs` sets\n\t// `from = 'HEAD'` when omitted, or diffs against the caller-supplied `from`).\n\tif (isUncommitted(to)) return true;\n\n\t// `git diff <from>` — `to === ''` means the caller explicitly asked for working tree vs `from`\n\tif (to === '') return from == null || !isUncommittedStaged(from);\n\n\t// `getChangedFilesCount` uses `prepareToFromDiffArgs`, which translates `to` (with no `from`)\n\t// to `${to}^ ${to}` UNLESS `to` is HEAD or empty.\n\tif (isHead(to) && from == null) return true;\n\treturn false;\n}\n\nfunction isHead(ref: string | undefined): boolean {\n\treturn ref?.toUpperCase() === 'HEAD';\n}\n\nfunction prepareToFromDiffArgs(\n\tto: string,\n\tfrom: string | undefined,\n\targs: string[],\n\tnotation?: GitRevisionRangeNotation,\n): string {\n\tif (to === uncommitted) {\n\t\tif (from != null) {\n\t\t\targs.push(from);\n\t\t} else {\n\t\t\t// Get only unstaged changes\n\t\t\tfrom = 'HEAD';\n\t\t}\n\t} else if (to === uncommittedStaged) {\n\t\targs.push('--staged');\n\t\tif (from != null) {\n\t\t\targs.push(from);\n\t\t} else {\n\t\t\t// Get only staged changes\n\t\t\tfrom = 'HEAD';\n\t\t}\n\t} else if (from == null) {\n\t\tif (to === '' || isHead(to)) {\n\t\t\tfrom = 'HEAD';\n\t\t\targs.push(from);\n\t\t} else {\n\t\t\tfrom = `${to}^`;\n\t\t\targs.push(from, to);\n\t\t}\n\t} else if (to === '') {\n\t\targs.push(from);\n\t} else if (notation != null) {\n\t\targs.push(`${from}${notation}${to}`);\n\t} else {\n\t\targs.push(from, to);\n\t}\n\treturn from;\n}\n\nfunction createRevisionUri(\n\tprovider: CliGitProviderInternal,\n\trepoPath: string,\n\trelativePath: string,\n\tsha: string | undefined,\n): RevisionUri {\n\treturn {\n\t\turi: sha\n\t\t\t? fromUri({\n\t\t\t\t\tscheme: 'gitlens',\n\t\t\t\t\tauthority: encodeGitLensRevisionUriAuthority({ ref: sha, repoPath: repoPath }),\n\t\t\t\t\tpath: provider.getAbsoluteUri(relativePath, repoPath).path,\n\t\t\t\t})\n\t\t\t: provider.getAbsoluteUri(relativePath, repoPath),\n\t\tpath: relativePath,\n\t\tsha: sha,\n\t\trepoPath: repoPath,\n\t};\n}\n\nexport async function findPathStatusChanged(\n\tgit: Git,\n\trepoPath: string,\n\tpathspec: string,\n\trev: string | undefined,\n\toptions?: { filters?: GitDiffFilter[]; ordering?: 'date' | 'author-date' | 'topo' | null },\n): Promise<{ sha: string; file: LogParsedFile | undefined } | undefined> {\n\tconst parser = getShaAndFileSummaryLogParser();\n\n\tconst ordering = options?.ordering;\n\n\tconst result = await git.run(\n\t\t{ cwd: repoPath, configs: gitConfigsLog },\n\t\t'log',\n\t\t...parser.arguments,\n\t\tordering ? `--${ordering}-order` : undefined,\n\t\t'--no-walk',\n\t\t`--diff-filter=${options?.filters?.length ? options.filters.join('') : 'RCD'}`,\n\t\trev,\n\t\t// Note: --no-walk constrains to the exact commit (no ancestor search). Pathspec is omitted\n\t\t// because git suppresses rename detection with pathspecs (shows D instead of R, losing the destination path).\n\t\t'--',\n\t);\n\n\tconst commit = first(parser.parse(result.stdout));\n\tif (commit == null) return undefined;\n\n\tconst file = commit.files.find(f => f.path === pathspec || f.originalPath === pathspec);\n\treturn { sha: commit.sha, file: file };\n}\n"],"mappings":"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"}
@@ -62,6 +62,7 @@ export declare class OperationsGitSubProvider implements GitOperationsSubProvide
62
62
  tags?: boolean;
63
63
  source?: unknown;
64
64
  }, runOptions?: GitOperationRunOptions): Promise<void>;
65
+ private announcePull;
65
66
  private pullCore;
66
67
  push(repoPath: string, options?: {
67
68
  reference?: GitReference;
@@ -147,10 +147,12 @@ var OperationsGitSubProvider = class {
147
147
  async fetch(repoPath, options, runOptions) {
148
148
  const scope = getScopedLogger();
149
149
  const { branch, ...opts } = options ?? {};
150
+ let ran = false;
150
151
  try {
151
152
  if (isBranchReference(branch)) {
152
153
  const [branchName, remoteName] = getBranchNameAndRemote(branch);
153
154
  if (remoteName == null) return;
155
+ ran = true;
154
156
  await this.fetchCore(repoPath, {
155
157
  branch: branchName,
156
158
  remote: remoteName,
@@ -158,12 +160,18 @@ var OperationsGitSubProvider = class {
158
160
  pull: options?.pull,
159
161
  preserveFetchHead: options?.preserveFetchHead
160
162
  }, runOptions);
161
- } else await this.fetchCore(repoPath, opts, runOptions);
162
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "tags");
163
- this.context.hooks?.repository?.onChanged?.(repoPath, this.getFetchChanges(branch, options));
163
+ } else {
164
+ ran = true;
165
+ await this.fetchCore(repoPath, opts, runOptions);
166
+ }
164
167
  } catch (ex) {
165
168
  scope?.error(ex);
166
169
  throw ex;
170
+ } finally {
171
+ if (ran) {
172
+ this.context.hooks?.cache?.onReset?.(repoPath, "branches", "tags");
173
+ this.context.hooks?.repository?.onChanged?.(repoPath, this.getFetchChanges(branch, options));
174
+ }
167
175
  }
168
176
  }
169
177
  /** `remotes`, plus `heads`/`tags` for any local branch or tag the fetch writes — a `pull` fetch writes `<upstream>:<branch>` */
@@ -256,12 +264,17 @@ var OperationsGitSubProvider = class {
256
264
  }
257
265
  async pull(repoPath, options, runOptions) {
258
266
  const scope = getScopedLogger();
267
+ let announce;
259
268
  try {
260
269
  if (isBranchReference(options?.branch)) {
261
270
  const branch = options.branch;
262
271
  const worktree = await this.provider.worktrees?.getWorktree(repoPath, (wt) => wt.branch?.name === branch.name);
263
272
  if (worktree != null) {
264
273
  const worktreePath = normalizePath(worktree.uri.fsPath);
274
+ announce = () => {
275
+ this.announcePull(repoPath);
276
+ if (worktreePath !== normalizePath(repoPath)) this.announcePull(worktreePath);
277
+ };
265
278
  this.context.hooks?.operations?.onRebaseCapableOperation?.(worktreePath, "pull", "started");
266
279
  try {
267
280
  await this.pullCore(worktreePath, {
@@ -273,13 +286,6 @@ var OperationsGitSubProvider = class {
273
286
  } finally {
274
287
  this.context.hooks?.operations?.onRebaseCapableOperation?.(worktreePath, "pull", "ended");
275
288
  }
276
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status", "tags");
277
- this.context.hooks?.repository?.onChanged?.(repoPath, [
278
- "head",
279
- "heads",
280
- "remotes",
281
- "index"
282
- ]);
283
289
  } else if (options?.fastForward === "only") {
284
290
  const [branchName, remoteName] = getBranchNameAndRemote(branch);
285
291
  const upstream = getBranchTrackingWithoutRemote(branch);
@@ -294,6 +300,10 @@ var OperationsGitSubProvider = class {
294
300
  ]
295
301
  }
296
302
  });
303
+ announce = () => {
304
+ this.context.hooks?.cache?.onReset?.(repoPath, "branches", "tags");
305
+ this.context.hooks?.repository?.onChanged?.(repoPath, ["heads", "remotes"]);
306
+ };
297
307
  try {
298
308
  await this.fetchCore(repoPath, {
299
309
  branch: branchName,
@@ -309,11 +319,10 @@ var OperationsGitSubProvider = class {
309
319
  }, ex.original);
310
320
  throw ex;
311
321
  }
312
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "tags");
313
- this.context.hooks?.repository?.onChanged?.(repoPath, ["heads", "remotes"]);
314
322
  } else await this.fetch(repoPath, { branch }, runOptions);
315
323
  return;
316
324
  }
325
+ announce = () => this.announcePull(repoPath);
317
326
  this.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, "pull", "started");
318
327
  try {
319
328
  await this.pullCore(repoPath, {
@@ -325,18 +334,22 @@ var OperationsGitSubProvider = class {
325
334
  } finally {
326
335
  this.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, "pull", "ended");
327
336
  }
328
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status", "tags");
329
- this.context.hooks?.repository?.onChanged?.(repoPath, [
330
- "head",
331
- "heads",
332
- "remotes",
333
- "index"
334
- ]);
335
337
  } catch (ex) {
336
338
  scope?.error(ex);
337
339
  throw ex;
340
+ } finally {
341
+ announce?.();
338
342
  }
339
343
  }
344
+ announcePull(repoPath) {
345
+ this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status", "tags");
346
+ this.context.hooks?.repository?.onChanged?.(repoPath, [
347
+ "head",
348
+ "heads",
349
+ "remotes",
350
+ "index"
351
+ ]);
352
+ }
340
353
  async pullCore(repoPath, options, runOptions) {
341
354
  const params = ["pull"];
342
355
  if (options.tags) params.push("--tags");
@@ -410,15 +423,16 @@ var OperationsGitSubProvider = class {
410
423
  } catch (ex) {
411
424
  scope?.error(ex, "Unable to set upstream tracking after publish");
412
425
  }
426
+ } catch (ex) {
427
+ scope?.error(ex);
428
+ throw ex;
429
+ } finally {
413
430
  this.context.hooks?.cache?.onReset?.(repoPath, "branches");
414
431
  this.context.hooks?.repository?.onChanged?.(repoPath, options?.publish != null ? [
415
432
  "config",
416
433
  "heads",
417
434
  "remotes"
418
435
  ] : ["remotes"]);
419
- } catch (ex) {
420
- scope?.error(ex);
421
- throw ex;
422
436
  }
423
437
  }
424
438
  async pushCore(repoPath, options, runOptions) {
@@ -1 +1 @@
1
- {"version":3,"file":"operations.js","names":[],"sources":["../../../../git-cli/src/providers/operations.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitConflictCommand, GitServiceContext } from '@gitlens/git/context.js';\nimport {\n\tCheckoutError,\n\tCherryPickError,\n\tCommitError,\n\tFetchError,\n\tMergeError,\n\tPullError,\n\tPushError,\n\tRebaseError,\n\tResetError,\n\tRevertError,\n\tSigningError,\n} from '@gitlens/git/errors.js';\nimport type { GitBranchReference, GitReference } from '@gitlens/git/models/reference.js';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\nimport type { SigningFormat } from '@gitlens/git/models/signature.js';\nimport type { GitConflictFile } from '@gitlens/git/models/staging.js';\nimport type {\n\tGitOperationResult,\n\tGitOperationRunOptions,\n\tGitOperationsSubProvider,\n} from '@gitlens/git/providers/operations.js';\nimport { getBranchNameAndRemote, getBranchTrackingWithoutRemote } from '@gitlens/git/utils/branch.utils.js';\nimport { isBranchReference } from '@gitlens/git/utils/reference.utils.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { sequentialize } from '@gitlens/utils/decorators/sequentialize.js';\nimport { chunkByStringLength } from '@gitlens/utils/iterable.js';\nimport { Logger } from '@gitlens/utils/logger.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git, PushForceOptions } from '../exec/git.js';\nimport {\n\tclassifySigningError,\n\tgetGitCommandError,\n\tgitConfigsPull,\n\tGitErrors,\n\tinferSigningFormatFromError,\n\tmaxGitCliLength,\n} from '../exec/git.js';\n\nexport class OperationsGitSubProvider implements GitOperationsSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync checkout(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { createBranch?: string; noTracking?: boolean },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst params = ['checkout'];\n\t\tif (options?.createBranch) {\n\t\t\tparams.push('-b', options.createBranch);\n\t\t\tif (options.noTracking) {\n\t\t\t\tparams.push('--no-track');\n\t\t\t}\n\t\t\tparams.push(ref, '--');\n\t\t} else {\n\t\t\tparams.push(ref, '--');\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t\tif (options?.createBranch) {\n\t\t\t\t// Evict the cached base only — see `createBranch` on why the persisted keys stay.\n\t\t\t\tthis.cache.deleteBaseBranchName(repoPath, options.createBranch);\n\t\t\t}\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'checkout',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CheckoutError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', ref: ref, gitCommand: { repoPath: repoPath, args: params } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync cherryPick(\n\t\trepoPath: string,\n\t\trevs: string[],\n\t\toptions?: { edit?: boolean; noCommit?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['cherry-pick'];\n\t\tif (options?.edit) {\n\t\t\targs.push('-e');\n\t\t}\n\t\tif (options?.noCommit) {\n\t\t\targs.push('-n');\n\t\t}\n\n\t\tif (revs.length > 1) {\n\t\t\t// Sort commits in topological order (oldest ancestor first) so cherry-pick applies them correctly.\n\t\t\t// This is a local read-only pre-flight, not the user-initiated op — don't subject it to caller env/timeout.\n\t\t\tconst revsSet = new Set(revs);\n\t\t\tconst result = await this.git.run({ cwd: repoPath }, 'rev-list', '--topo-order', '--reverse', ...revs);\n\n\t\t\tconst ordered: string[] = [];\n\t\t\tfor (const sha of result.stdout.trim().split('\\n')) {\n\t\t\t\tif (sha && revsSet.has(sha)) {\n\t\t\t\t\tordered.push(sha);\n\t\t\t\t\tif (ordered.length === revs.length) break; // Early exit once we have all\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (ordered.length === revs.length) {\n\t\t\t\trevs = ordered;\n\t\t\t}\n\t\t\t// If we didn't get all commits (shouldn't happen), keep original order\n\t\t}\n\n\t\targs.push(...revs);\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...args);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'cherry-pick',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CherryPickError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', revs: revs, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (CherryPickError.is(mapped, 'conflicts')) {\n\t\t\t\treturn this.createConflictResult(repoPath, 'cherry-pick');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync commit(\n\t\trepoPath: string,\n\t\tmessage: string,\n\t\toptions?: {\n\t\t\tall?: boolean;\n\t\t\tallowEmpty?: boolean;\n\t\t\tamend?: boolean;\n\t\t\tauthor?: string;\n\t\t\tdate?: string;\n\t\t\tsignoff?: boolean;\n\t\t\tsource?: unknown;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst params = ['commit'];\n\t\tif (options?.all) {\n\t\t\tparams.push('--all');\n\t\t}\n\t\tif (options?.allowEmpty) {\n\t\t\tparams.push('--allow-empty');\n\t\t}\n\t\tif (options?.amend) {\n\t\t\tparams.push('--amend');\n\t\t}\n\t\tif (options?.signoff) {\n\t\t\tparams.push('--signoff');\n\t\t}\n\t\tif (options?.author) {\n\t\t\tparams.push(`--author=${options.author}`);\n\t\t}\n\t\tif (options?.date) {\n\t\t\tparams.push(`--date=${options.date}`);\n\t\t}\n\t\t// Host-level override (e.g. VS Code's `git.enableCommitSigning`) — request signing explicitly\n\t\t// via `-S`. Implicit repo-config signing (`commit.gpgsign=true`) needs no flag, and `-S`\n\t\t// alongside it is harmless, so the override can only enable signing, never force it off.\n\t\tconst sign = this.context.config?.signing?.enabled === true;\n\t\tif (sign) {\n\t\t\tparams.push('-S');\n\t\t}\n\t\t// Read commit message from stdin via -F - to avoid shell escaping issues\n\t\tparams.push('-F', '-');\n\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t{ cwd: repoPath, stdin: message, stdinEncoding: 'utf8', errors: 'throw', ...runOptions },\n\t\t\t\t...params,\n\t\t\t);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\tif (sign) {\n\t\t\t\t// `-S` was passed and the commit succeeded, so signing is confirmed — fire the\n\t\t\t\t// explicit-sign hook (same contract as the patch provider's `commit-tree -S` path).\n\t\t\t\tlet format: SigningFormat | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tformat = (await this.provider.config.getSigningConfig?.(repoPath))?.format;\n\t\t\t\t} catch {}\n\t\t\t\tthis.context.hooks?.commits?.onSigned?.(format ?? 'gpg', options?.source);\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, params, ex, options?.source);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'commit',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CommitError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync fetch(\n\t\trepoPath: string,\n\t\toptions?:\n\t\t\t| {\n\t\t\t\t\tall?: boolean;\n\t\t\t\t\tbranch?: GitBranchReference;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: boolean;\n\t\t\t\t\tremote?: string;\n\t\t\t\t\trefspecs?: undefined;\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tall?: undefined;\n\t\t\t\t\tbranch?: undefined;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: undefined;\n\t\t\t\t\tremote: string;\n\t\t\t\t\trefspecs: readonly string[];\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst { branch, ...opts } = options ?? {};\n\t\ttry {\n\t\t\tif (isBranchReference(branch)) {\n\t\t\t\tconst [branchName, remoteName] = getBranchNameAndRemote(branch);\n\t\t\t\tif (remoteName == null) return;\n\n\t\t\t\tawait this.fetchCore(\n\t\t\t\t\trepoPath,\n\t\t\t\t\t{\n\t\t\t\t\t\tbranch: branchName,\n\t\t\t\t\t\tremote: remoteName,\n\t\t\t\t\t\tupstream: getBranchTrackingWithoutRemote(branch)!,\n\t\t\t\t\t\tpull: options?.pull,\n\t\t\t\t\t\tpreserveFetchHead: options?.preserveFetchHead,\n\t\t\t\t\t},\n\t\t\t\t\trunOptions,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait this.fetchCore(repoPath, opts, runOptions);\n\t\t\t}\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'tags');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, this.getFetchChanges(branch, options));\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t/** `remotes`, plus `heads`/`tags` for any local branch or tag the fetch writes — a `pull` fetch writes `<upstream>:<branch>` */\n\tprivate getFetchChanges(\n\t\tbranch: GitBranchReference | undefined,\n\t\toptions: { pull?: boolean; refspecs?: readonly string[] } | undefined,\n\t): RepositoryChange[] {\n\t\tif (isBranchReference(branch)) {\n\t\t\treturn options?.pull ? ['heads', 'remotes'] : ['remotes'];\n\t\t}\n\t\tif (!options?.refspecs?.length) return ['remotes'];\n\n\t\tconst changes: RepositoryChange[] = ['remotes'];\n\t\tfor (const refspec of options.refspecs) {\n\t\t\tconst stripped = refspec.startsWith('+') ? refspec.slice(1) : refspec;\n\t\t\tconst colonIndex = stripped.indexOf(':');\n\t\t\tif (colonIndex === -1) continue;\n\n\t\t\t// Qualified as git's fetch does: an empty destination stores nothing, `heads/`/`tags/`/`remotes/`\n\t\t\t// get `refs/`, and any other unqualified name is a local branch\n\t\t\tlet destination = stripped.slice(colonIndex + 1);\n\t\t\tif (!destination) continue;\n\n\t\t\tif (!destination.startsWith('refs/')) {\n\t\t\t\tdestination = /^(?:heads|tags|remotes)\\//.test(destination)\n\t\t\t\t\t? `refs/${destination}`\n\t\t\t\t\t: `refs/heads/${destination}`;\n\t\t\t}\n\n\t\t\tif (destination.startsWith('refs/tags/')) {\n\t\t\t\tif (!changes.includes('tags')) {\n\t\t\t\t\tchanges.push('tags');\n\t\t\t\t}\n\t\t\t} else if (destination.startsWith('refs/heads/')) {\n\t\t\t\tif (!changes.includes('heads')) {\n\t\t\t\t\tchanges.push('heads');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn changes;\n\t}\n\n\tprivate async fetchCore(\n\t\trepoPath: string,\n\t\toptions:\n\t\t\t| {\n\t\t\t\t\tall?: boolean;\n\t\t\t\t\tbranch?: undefined;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: boolean;\n\t\t\t\t\tremote?: string;\n\t\t\t\t\trefspecs?: undefined;\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tall?: undefined;\n\t\t\t\t\tbranch: string;\n\t\t\t\t\tprune?: undefined;\n\t\t\t\t\tpull?: boolean;\n\t\t\t\t\tremote: string;\n\t\t\t\t\tupstream: string;\n\t\t\t\t\t/**\n\t\t\t\t\t * `-u` (`--update-head-ok`, the default) lets a `pull` fetch move a branch even where it is\n\t\t\t\t\t * checked out; `false` keeps git's own refusal as a guard against a stale worktree lookup.\n\t\t\t\t\t */\n\t\t\t\t\tupdateHeadOk?: boolean;\n\t\t\t\t\trefspecs?: undefined;\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tall?: undefined;\n\t\t\t\t\tbranch?: undefined;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: undefined;\n\t\t\t\t\tremote: string;\n\t\t\t\t\trefspecs: readonly string[];\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['fetch'];\n\n\t\tif (options.prune) {\n\t\t\tparams.push('--prune');\n\t\t}\n\n\t\tif (options.preserveFetchHead && (await this.git.supports('git:fetch:no-write-fetch-head'))) {\n\t\t\tparams.push('--no-write-fetch-head');\n\t\t}\n\n\t\tif (options.branch && options.remote) {\n\t\t\tif (options.upstream && options.pull) {\n\t\t\t\tif (options.updateHeadOk !== false) {\n\t\t\t\t\tparams.push('-u');\n\t\t\t\t}\n\t\t\t\tparams.push(options.remote, `${options.upstream}:${options.branch}`);\n\t\t\t} else {\n\t\t\t\tparams.push(options.remote, options.upstream || options.branch);\n\t\t\t}\n\t\t} else if (options.refspecs?.length) {\n\t\t\tparams.push(options.remote, ...options.refspecs);\n\t\t} else if (options.remote) {\n\t\t\tparams.push(options.remote);\n\t\t} else if (options.all) {\n\t\t\tparams.push('--all');\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'fetch',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew FetchError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\tbranch: options?.branch,\n\t\t\t\t\t\t\tremote: options?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync merge(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { fastForward?: boolean | 'only'; noCommit?: boolean; squash?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['merge'];\n\n\t\tif (options?.fastForward === 'only') {\n\t\t\targs.push('--ff-only');\n\t\t} else if (options?.fastForward === true) {\n\t\t\targs.push('--ff');\n\t\t} else if (options?.fastForward === false) {\n\t\t\targs.push('--no-ff');\n\t\t}\n\t\tif (options?.squash) {\n\t\t\targs.push('--squash');\n\t\t}\n\t\tif (options?.noCommit) {\n\t\t\targs.push('--no-commit');\n\t\t}\n\n\t\targs.push(ref);\n\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t// Avoid a timeout since merges can take a long time (set to 0 to disable)\n\t\t\t\t{ cwd: repoPath, errors: 'throw', timeout: 0, ...runOptions },\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'merge',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew MergeError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', ref: ref, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (MergeError.is(mapped, 'conflicts')) {\n\t\t\t\treturn this.createConflictResult(repoPath, 'merge');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync pull(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tbranch?: GitBranchReference;\n\t\t\tfastForward?: 'only';\n\t\t\trebase?: boolean;\n\t\t\ttags?: boolean;\n\t\t\tsource?: unknown;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tif (isBranchReference(options?.branch)) {\n\t\t\t\tconst branch = options.branch;\n\t\t\t\t// Find the worktree where this branch is checked out (if any)\n\t\t\t\tconst worktree = await this.provider.worktrees?.getWorktree(\n\t\t\t\t\trepoPath,\n\t\t\t\t\twt => wt.branch?.name === branch.name,\n\t\t\t\t);\n\t\t\t\tif (worktree != null) {\n\t\t\t\t\t// Branch is checked out in a worktree — run git pull in that worktree's directory\n\t\t\t\t\t// Any rebase state (e.g. from `pull.rebase=true`) appears under the worktree path\n\t\t\t\t\tconst worktreePath = normalizePath(worktree.uri.fsPath);\n\t\t\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(worktreePath, 'pull', 'started');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.pullCore(\n\t\t\t\t\t\t\tworktreePath,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfastForward: options?.fastForward,\n\t\t\t\t\t\t\t\trebase: options?.rebase,\n\t\t\t\t\t\t\t\ttags: options?.tags,\n\t\t\t\t\t\t\t\tsource: options?.source,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trunOptions,\n\t\t\t\t\t\t);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(worktreePath, 'pull', 'ended');\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status', 'tags');\n\t\t\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'remotes', 'index']);\n\t\t\t\t} else if (options?.fastForward === 'only') {\n\t\t\t\t\t// Not checked out anywhere, so there is no working tree to merge into — but a fast-forward\n\t\t\t\t\t// needs none: fetching `<upstream>:<branch>` advances the local branch, and git refuses that\n\t\t\t\t\t// non-forced refspec unless it fast-forwards. A plain fetch would leave the branch unmoved\n\t\t\t\t\t// and report success.\n\t\t\t\t\t// Fetched without `-u`: the worktree lookup above is cached and can miss a worktree added\n\t\t\t\t\t// outside core, and then git's own refusal is what keeps a checked-out branch from moving.\n\t\t\t\t\tconst [branchName, remoteName] = getBranchNameAndRemote(branch);\n\t\t\t\t\tconst upstream = getBranchTrackingWithoutRemote(branch);\n\t\t\t\t\tif (remoteName == null || upstream == null) {\n\t\t\t\t\t\tthrow new PullError({\n\t\t\t\t\t\t\treason: 'noUpstream',\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: ['pull', '--ff-only', branch.name] },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.fetchCore(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbranch: branchName,\n\t\t\t\t\t\t\t\tremote: remoteName,\n\t\t\t\t\t\t\t\tupstream: upstream,\n\t\t\t\t\t\t\t\tpull: true,\n\t\t\t\t\t\t\t\tupdateHeadOk: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trunOptions,\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\tif (FetchError.is(ex, 'noFastForward')) {\n\t\t\t\t\t\t\tthrow new PullError(\n\t\t\t\t\t\t\t\t{ reason: 'noFastForward', gitCommand: ex.details.gitCommand },\n\t\t\t\t\t\t\t\tex.original,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow ex;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'tags');\n\t\t\t\t\t// A `pull` fetch writes `<upstream>:<branch>`, moving the local branch too — same\n\t\t\t\t\t// hooks `fetch()` fires for a pull fetch with a branch reference.\n\t\t\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['heads', 'remotes']);\n\t\t\t\t} else {\n\t\t\t\t\t// Branch is not checked out anywhere — can only fetch (no working tree to merge into)\n\t\t\t\t\tawait this.fetch(repoPath, { branch: branch }, runOptions);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'pull', 'started');\n\t\t\ttry {\n\t\t\t\tawait this.pullCore(\n\t\t\t\t\trepoPath,\n\t\t\t\t\t{\n\t\t\t\t\t\tfastForward: options?.fastForward,\n\t\t\t\t\t\trebase: options?.rebase,\n\t\t\t\t\t\ttags: options?.tags,\n\t\t\t\t\t\tsource: options?.source,\n\t\t\t\t\t},\n\t\t\t\t\trunOptions,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'pull', 'ended');\n\t\t\t}\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status', 'tags');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'remotes', 'index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate async pullCore(\n\t\trepoPath: string,\n\t\toptions: { fastForward?: 'only'; rebase?: boolean; tags?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['pull'];\n\n\t\tif (options.tags) {\n\t\t\tparams.push('--tags');\n\t\t}\n\n\t\tif (options.rebase) {\n\t\t\tparams.push('-r');\n\t\t}\n\n\t\tif (options.fastForward === 'only') {\n\t\t\tparams.push('--ff-only');\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, configs: gitConfigsPull, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tawait this.throwIfSigningError(repoPath, params, ex, options.source);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'pull',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PullError({ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } }, ex),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync push(\n\t\trepoPath: string,\n\t\toptions?: { reference?: GitReference; force?: boolean; publish?: { remote: string } },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tlet branchName: string;\n\t\tlet remoteName: string | undefined;\n\t\tlet upstreamName: string | undefined;\n\t\tlet setUpstream:\n\t\t\t| {\n\t\t\t\t\tbranch: string;\n\t\t\t\t\tremote: string;\n\t\t\t\t\tremoteBranch: string;\n\t\t\t }\n\t\t\t| undefined;\n\n\t\tif (isBranchReference(options?.reference)) {\n\t\t\tif (options.publish != null) {\n\t\t\t\tbranchName = options.reference.name;\n\t\t\t\tremoteName = options.publish.remote;\n\t\t\t} else {\n\t\t\t\t[branchName, remoteName] = getBranchNameAndRemote(options.reference);\n\t\t\t}\n\t\t\tupstreamName = getBranchTrackingWithoutRemote(options.reference);\n\t\t} else {\n\t\t\tconst branch = await this.provider.branches.getBranch(repoPath);\n\t\t\tif (branch == null) return;\n\n\t\t\tif (options?.reference != null) {\n\t\t\t\tbranchName = `${options.reference.ref}:${\n\t\t\t\t\toptions?.publish != null ? 'refs/heads/' : ''\n\t\t\t\t}${branch.nameWithoutRemote}`;\n\t\t\t} else {\n\t\t\t\tconst tracking = options?.publish == null ? branch.trackingWithoutRemote : undefined;\n\t\t\t\tbranchName =\n\t\t\t\t\ttracking != null && tracking !== branch.nameWithoutRemote\n\t\t\t\t\t\t? `${branch.name}:${tracking}`\n\t\t\t\t\t\t: branch.name;\n\t\t\t}\n\t\t\tremoteName = branch.remoteName ?? options?.publish?.remote;\n\t\t\tupstreamName = options?.reference == null && options?.publish != null ? branch.name : undefined;\n\n\t\t\t// Git can't setup upstream tracking when publishing a new branch to a specific commit, so we'll need to do it after the push\n\t\t\tif (options?.publish?.remote != null && options?.reference != null) {\n\t\t\t\tsetUpstream = {\n\t\t\t\t\tbranch: branch.nameWithoutRemote,\n\t\t\t\t\tremote: remoteName!,\n\t\t\t\t\tremoteBranch: branch.nameWithoutRemote,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (options?.publish == null && remoteName == null && upstreamName == null) {\n\t\t\tthrow new PushError({ reason: 'other' });\n\t\t}\n\n\t\tlet forceOpts: PushForceOptions | undefined;\n\t\tif (options?.force) {\n\t\t\t// Honor the host's force-push preferences (e.g. VS Code's `git.useForcePushWithLease` /\n\t\t\t// `git.useForcePushIfIncludes`); fall back to the safer `--force-with-lease` behavior.\n\t\t\tconst useForceWithLease = this.context.config?.push?.useForceWithLease ?? true;\n\t\t\tforceOpts = useForceWithLease\n\t\t\t\t? { withLease: true, ifIncludes: this.context.config?.push?.useForceIfIncludes ?? true }\n\t\t\t\t: { withLease: false };\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.pushCore(\n\t\t\t\trepoPath,\n\t\t\t\t{\n\t\t\t\t\tbranch: branchName,\n\t\t\t\t\tremote: remoteName,\n\t\t\t\t\tupstream: upstreamName,\n\t\t\t\t\tforce: forceOpts,\n\t\t\t\t\tpublish: options?.publish != null,\n\t\t\t\t},\n\t\t\t\trunOptions,\n\t\t\t);\n\n\t\t\t// Since Git can't setup upstream tracking when publishing a new branch to a specific commit, do it now.\n\t\t\t// Soft-fail: the push already succeeded, so don't let a local upstream-tracking failure (cancellation\n\t\t\t// arriving mid-spawn, transient git error) suppress the post-push hook fan-out below.\n\t\t\tif (setUpstream != null) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, ...runOptions },\n\t\t\t\t\t\t'branch',\n\t\t\t\t\t\t'--set-upstream-to',\n\t\t\t\t\t\t`${setUpstream.remote}/${setUpstream.remoteBranch}`,\n\t\t\t\t\t\tsetUpstream.branch,\n\t\t\t\t\t);\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tscope?.error(ex, 'Unable to set upstream tracking after publish');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(\n\t\t\t\trepoPath,\n\t\t\t\toptions?.publish != null ? ['config', 'heads', 'remotes'] : ['remotes'],\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate async pushCore(\n\t\trepoPath: string,\n\t\toptions: {\n\t\t\tbranch?: string;\n\t\t\tforce?: PushForceOptions;\n\t\t\tpublish?: boolean;\n\t\t\tremote?: string;\n\t\t\tupstream?: string;\n\t\t\tdelete?: { remote: string; branch: string };\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['push'];\n\n\t\tif (options.force != null) {\n\t\t\tif (options.force.withLease) {\n\t\t\t\tparams.push('--force-with-lease');\n\t\t\t\tif (options.force.ifIncludes) {\n\t\t\t\t\tif (await this.git.supports('git:push:force-if-includes')) {\n\t\t\t\t\t\tparams.push('--force-if-includes');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams.push('--force');\n\t\t\t}\n\t\t}\n\n\t\tif (options.branch && options.remote) {\n\t\t\tif (options.upstream) {\n\t\t\t\tparams.push('-u', options.remote, `${options.branch}:${options.upstream}`);\n\t\t\t} else if (options.publish) {\n\t\t\t\tparams.push('--set-upstream', options.remote, options.branch);\n\t\t\t} else {\n\t\t\t\tparams.push(options.remote, options.branch);\n\t\t\t}\n\t\t} else if (options.remote) {\n\t\t\tparams.push(options.remote);\n\t\t} else if (options.delete) {\n\t\t\tparams.push(options.delete.remote, `:${options.delete.branch}`);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tconst error = getGitCommandError(\n\t\t\t\t'push',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (options?.force?.withLease && error.details.reason === 'rejected') {\n\t\t\t\tif (ex.stderr && /! \\[rejected\\].*\\(stale info\\)/m.test(ex.stderr)) {\n\t\t\t\t\tthrow new PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: 'rejectedWithLease',\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\toptions.force.ifIncludes &&\n\t\t\t\t\tex.stderr &&\n\t\t\t\t\t/! \\[rejected\\].*\\(remote ref updated since checkout\\)/m.test(ex.stderr)\n\t\t\t\t) {\n\t\t\t\t\tthrow new PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: 'rejectedWithLeaseIfIncludes',\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (ex.stderr && GitErrors.pushRejectedRefDoesNotExists.test(ex.stderr)) {\n\t\t\t\t\tthrow new PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: 'rejectedRefDoesNotExist',\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync rebase(\n\t\trepoPath: string,\n\t\tupstream: string,\n\t\toptions?: {\n\t\t\tautoStash?: boolean;\n\t\t\tbranch?: string;\n\t\t\teditor?: string;\n\t\t\tinteractive?: boolean;\n\t\t\tprogrammaticEditor?: boolean;\n\t\t\tautosquash?: boolean;\n\t\t\tmessageEditor?: string;\n\t\t\tonto?: string;\n\t\t\tupdateRefs?: boolean;\n\t\t\tsource?: unknown;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['rebase'];\n\t\tconst configs: string[] = [];\n\n\t\tif (options?.autoStash !== false) {\n\t\t\targs.push('--autostash');\n\t\t}\n\n\t\tif (options?.interactive) {\n\t\t\targs.push('--interactive');\n\n\t\t\tif (options.editor) {\n\t\t\t\tconfigs.push('-c', `sequence.editor=${options.editor}`);\n\t\t\t}\n\n\t\t\t// A script-based sequence editor rewrites the todo by command word + SHA, so git must emit a\n\t\t\t// plain, natural-order todo regardless of the user's rebase config: `rebase.autosquash` would\n\t\t\t// reorder commits and rewrite `pick`→`fixup`, and `rebase.abbreviateCommands` would emit `p`.\n\t\t\tif (options.programmaticEditor) {\n\t\t\t\tconfigs.push('-c', 'rebase.autosquash=false', '-c', 'rebase.abbreviateCommands=false');\n\t\t\t}\n\t\t}\n\n\t\tif (options?.autosquash != null) {\n\t\t\tif (options.autosquash && options.programmaticEditor) {\n\t\t\t\tthrow new Error(l10n.t('rebase: autosquash cannot be combined with programmaticEditor'));\n\t\t\t}\n\n\t\t\t// `--no-autosquash` is passed explicitly when `false` — omitting the flag would let a\n\t\t\t// `rebase.autosquash=true` git config fold fixups anyway.\n\t\t\targs.push(options.autosquash ? '--autosquash' : '--no-autosquash');\n\t\t}\n\n\t\t// Drive per-commit message editing (the combined message a `squash` produces, or a `reword`).\n\t\t// `GIT_EDITOR` (not `core.editor`) is what git's interactive-rebase backend honors for the `reword`\n\t\t// amend step, so set it on the environment; also set `core.editor` config as a fallback.\n\t\tlet env = runOptions?.env;\n\t\tif (options?.messageEditor) {\n\t\t\tconfigs.push('-c', `core.editor=${options.messageEditor}`);\n\t\t\tenv = { ...env, GIT_EDITOR: options.messageEditor };\n\t\t}\n\n\t\tif (options?.updateRefs === true) {\n\t\t\targs.push('--update-refs');\n\t\t} else if (options?.updateRefs === false) {\n\t\t\targs.push('--no-update-refs');\n\t\t}\n\n\t\tif (options?.onto) {\n\t\t\targs.push('--onto', options.onto);\n\t\t}\n\n\t\targs.push(upstream);\n\n\t\tif (options?.branch) {\n\t\t\targs.push(options.branch);\n\t\t}\n\n\t\t// Fired before the process runs — `git rebase` exits 0 when stopping at `edit`/`break`,\n\t\t// so the result can't be used to detect that a rebase started\n\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'rebase', 'started');\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t// Avoid a timeout since rebases can take a long time (set to 0 to disable)\n\t\t\t\t{ cwd: repoPath, errors: 'throw', configs: configs, timeout: 0, ...runOptions, env: env },\n\t\t\t\t...args,\n\t\t\t);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'rebase',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew RebaseError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\tupstream: upstream,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (RebaseError.is(mapped, 'conflicts')) {\n\t\t\t\treturn await this.createConflictResult(repoPath, 'rebase');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t} finally {\n\t\t\t// The command exited (success, pause, or failure) — any rebase it left behind is on disk now\n\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'rebase', 'ended');\n\t\t}\n\t}\n\n\t@debug()\n\tasync reset(\n\t\trepoPath: string,\n\t\trev: string,\n\t\toptions?: { mode?: 'hard' | 'keep' | 'merge' | 'mixed' | 'soft' },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tawait this.resetCore(repoPath, rev, options?.mode, runOptions);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate async resetCore(\n\t\trepoPath: string,\n\t\trev: string,\n\t\tmode?: 'hard' | 'keep' | 'merge' | 'mixed' | 'soft',\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['reset', '-q'];\n\t\tif (mode) {\n\t\t\tparams.push(`--${mode}`);\n\t\t}\n\t\tparams.push(rev, '--');\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'reset',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew ResetError({ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } }, ex),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync restore(\n\t\trepoPath: string,\n\t\tpath: string | string[],\n\t\toptions?: { ref?: string; side?: 'ours' | 'theirs' },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst paths = Array.isArray(path) ? path : [path];\n\t\tif (!paths.length) return;\n\n\t\tconst scope = getScopedLogger();\n\t\tconst normalized = paths.map(p => splitPath(p, repoPath, true)[0]);\n\n\t\t// `side` and `ref` are mutually exclusive in git (--ours/--theirs apply during conflict\n\t\t// resolution and take no source ref); side takes precedence if both are somehow supplied.\n\t\t// Use a truthy check on `ref` so an empty string falls through to index-restore rather than\n\t\t// producing a malformed `git checkout '' -- …`. Implemented via `checkout` rather than\n\t\t// `git restore` for compatibility with the minimum supported git (2.7.2); `git restore`\n\t\t// only landed in 2.23.\n\t\tconst selector = options?.side != null ? `--${options.side}` : options?.ref || undefined;\n\t\tconst prefix = selector != null ? ['checkout', selector, '--'] : ['checkout', '--'];\n\n\t\ttry {\n\t\t\tif (await this.git.supports('git:checkout:pathspec-from-file')) {\n\t\t\t\t// Git ≥ 2.26: stream all pathspecs via stdin (NUL-separated) in a single invocation —\n\t\t\t\t// no CLI-length limit (so no batching), and robust for paths with spaces/newlines.\n\t\t\t\t// Pathspecs come from the file rather than argv, so `--` isn't used.\n\t\t\t\tconst args = ['checkout'];\n\t\t\t\tif (selector != null) {\n\t\t\t\t\targs.push(selector);\n\t\t\t\t}\n\t\t\t\targs.push('--pathspec-from-file=-', '--pathspec-file-nul');\n\t\t\t\tawait this.git.run(\n\t\t\t\t\t{ cwd: repoPath, errors: 'throw', ...runOptions, stdin: normalized.join('\\0') },\n\t\t\t\t\t...args,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Older git: pass pathspecs as args, one git invocation per chunk (collapsing N\n\t\t\t\t// path-mode checkouts into ⌈N / chunk⌉ spawns). Reserve the command prefix length and\n\t\t\t\t// a per-arg overhead (separator + possible quoting) so the assembled command line\n\t\t\t\t// can't exceed the OS limit even with many short paths.\n\t\t\t\tconst perArgOverhead = 3;\n\t\t\t\tconst prefixLength = prefix.reduce((sum, arg) => sum + arg.length + perArgOverhead, 0);\n\t\t\t\tfor (const batch of chunkByStringLength(normalized, maxGitCliLength - prefixLength, perArgOverhead)) {\n\t\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...prefix, ...batch);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'checkout',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CheckoutError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\tref: options?.side ?? options?.ref,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: [...prefix, ...normalized] },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync revert(\n\t\trepoPath: string,\n\t\trefs: string[],\n\t\toptions?: { editMessage?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['revert'];\n\n\t\tif (options?.editMessage === true) {\n\t\t\targs.push('--edit');\n\t\t} else if (options?.editMessage === false) {\n\t\t\targs.push('--no-edit');\n\t\t}\n\n\t\targs.push(...refs);\n\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t// Avoid a timeout since reverts can take a long time (set to 0 to disable)\n\t\t\t\t{ cwd: repoPath, errors: 'throw', timeout: 0, ...runOptions },\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'revert',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew RevertError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', refs: refs, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (RevertError.is(mapped, 'conflicts')) {\n\t\t\t\treturn this.createConflictResult(repoPath, 'revert');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t}\n\t}\n\n\t/**\n\t * Classifies `ex` as a signing failure; if so, fires the `commits.onSigningFailed`\n\t * hook and throws a typed {@link SigningError}. Callers should invoke this first\n\t * in their catch blocks, before falling through to command-specific error mapping\n\t * via {@link getGitCommandError}.\n\t *\n\t * `SigningFormat` is read opportunistically from `config.getSigningConfig`, with\n\t * {@link inferSigningFormatFromError} as a stderr-based fallback and `'gpg'` as\n\t * the final default.\n\t */\n\tprivate async throwIfSigningError(\n\t\trepoPath: string,\n\t\targs: readonly (string | undefined)[],\n\t\tex: unknown,\n\t\tsource?: unknown,\n\t): Promise<void> {\n\t\tconst reason = classifySigningError(ex);\n\t\tif (reason == null) return;\n\n\t\tlet format: SigningFormat | undefined;\n\t\ttry {\n\t\t\tformat = (await this.provider.config.getSigningConfig?.(repoPath))?.format;\n\t\t} catch {\n\t\t\t// Fall through — config read failed; use stderr-inferred format or gpg default\n\t\t}\n\t\tformat ??= inferSigningFormatFromError(ex) ?? 'gpg';\n\n\t\tthis.context.hooks?.commits?.onSigningFailed?.(reason, format, source);\n\t\tthrow new SigningError(\n\t\t\t{ reason: reason, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\tex instanceof Error ? ex : undefined,\n\t\t);\n\t}\n\n\tprivate async createConflictResult(repoPath: string, command: GitConflictCommand): Promise<GitOperationResult> {\n\t\tlet conflicts: GitConflictFile[] | undefined;\n\t\ttry {\n\t\t\tconflicts = await this.provider.status.getConflictingFiles(repoPath);\n\t\t} catch (ex) {\n\t\t\t// Don't let a secondary status-read failure mask the original conflict signal\n\t\t\tLogger.warn(`Unable to read conflicting files after ${command}: ${ex}`);\n\t\t}\n\t\t// A conflicted op mutates the working tree, index, and paused-op state — invalidate caches\n\t\t// and fire repository-change the same way the success path does, so downstream views refresh.\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\tthis.context.hooks?.operations?.onConflicted?.(command, conflicts);\n\t\treturn { conflicted: true, conflicts: conflicts };\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;AA4CA,IAAa,2BAAb,MAA0E;CAEvD;CACA;CACA;CACA;CAJlB,YACC,SACA,KACA,OACA,UACC;EAJgB,KAAA,UAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACf;CAEH,MACM,SACL,UACA,KACA,SACA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,SAAS,CAAC,UAAU;EAC1B,IAAI,SAAS,cAAc;GAC1B,OAAO,KAAK,MAAM,QAAQ,YAAY;GACtC,IAAI,QAAQ,YACX,OAAO,KAAK,YAAY;GAEzB,OAAO,KAAK,KAAK,IAAI;EACtB,OACC,OAAO,KAAK,KAAK,IAAI;EAGtB,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;IAAS,GAAG;GAAW,GAAG,GAAG,MAAM;GAC/E,IAAI,SAAS,cAEZ,KAAK,MAAM,qBAAqB,UAAU,QAAQ,YAAY;GAE/D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;GAAO,CAAC;EACjF,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,mBACL,YACA,KACA,WACC,IAAI,cACH;IAAE,QAAQ,UAAU;IAAc;IAAK,YAAY;KAAY;KAAU,MAAM;IAAO;GAAE,GACxF,EACD,CACF;EACD;CACD;CAEA,MAEM,WACL,UACA,MACA,SACA,YAC8B;EAC9B,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,OAAO,CAAC,aAAa;EAC3B,IAAI,SAAS,MACZ,KAAK,KAAK,IAAI;EAEf,IAAI,SAAS,UACZ,KAAK,KAAK,IAAI;EAGf,IAAI,KAAK,SAAS,GAAG;GAGpB,MAAM,UAAU,IAAI,IAAI,IAAI;GAC5B,MAAM,SAAS,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,YAAY,gBAAgB,aAAa,GAAG,IAAI;GAErG,MAAM,UAAoB,CAAC;GAC3B,KAAK,MAAM,OAAO,OAAO,OAAO,KAAK,CAAC,CAAC,MAAM,IAAI,GAChD,IAAI,OAAO,QAAQ,IAAI,GAAG,GAAG;IAC5B,QAAQ,KAAK,GAAG;IAChB,IAAI,QAAQ,WAAW,KAAK,QAAQ;GACrC;GAGD,IAAI,QAAQ,WAAW,KAAK,QAC3B,OAAO;EAGT;EAEA,KAAK,KAAK,GAAG,IAAI;EAEjB,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;IAAS,GAAG;GAAW,GAAG,GAAG,IAAI;GAC7E,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;GAAO,CAAC;GAChF,OAAO,EAAE,YAAY,MAAM;EAC5B,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,KAAK,oBAAoB,UAAU,MAAM,IAAI,SAAS,MAAM;GAClE,MAAM,SAAS,mBACd,eACA,KACA,WACC,IAAI,gBACH;IAAE,QAAQ,UAAU;IAAe;IAAM,YAAY;KAAY;KAAgB;IAAK;GAAE,GACxF,EACD,CACF;GACA,IAAI,gBAAgB,GAAG,QAAQ,WAAW,GACzC,OAAO,KAAK,qBAAqB,UAAU,aAAa;GAEzD,MAAM;EACP;CACD;CAEA,MAEM,OACL,UACA,SACA,SASA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,SAAS,CAAC,QAAQ;EACxB,IAAI,SAAS,KACZ,OAAO,KAAK,OAAO;EAEpB,IAAI,SAAS,YACZ,OAAO,KAAK,eAAe;EAE5B,IAAI,SAAS,OACZ,OAAO,KAAK,SAAS;EAEtB,IAAI,SAAS,SACZ,OAAO,KAAK,WAAW;EAExB,IAAI,SAAS,QACZ,OAAO,KAAK,YAAY,QAAQ,QAAQ;EAEzC,IAAI,SAAS,MACZ,OAAO,KAAK,UAAU,QAAQ,MAAM;EAKrC,MAAM,OAAO,KAAK,QAAQ,QAAQ,SAAS,YAAY;EACvD,IAAI,MACH,OAAO,KAAK,IAAI;EAGjB,OAAO,KAAK,MAAM,GAAG;EAErB,IAAI;GACH,MAAM,KAAK,IAAI,IACd;IAAE,KAAK;IAAU,OAAO;IAAS,eAAe;IAAQ,QAAQ;IAAS,GAAG;GAAW,GACvF,GAAG,MACJ;GACA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;GAAO,CAAC;GAChF,IAAI,MAAM;IAGT,IAAI;IACJ,IAAI;KACH,UAAU,MAAM,KAAK,SAAS,OAAO,mBAAmB,QAAQ,EAAA,EAAI;IACrE,QAAQ,CAAC;IACT,KAAK,QAAQ,OAAO,SAAS,WAAW,UAAU,OAAO,SAAS,MAAM;GACzE;EACD,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,KAAK,oBAAoB,UAAU,QAAQ,IAAI,SAAS,MAAM;GACpE,MAAM,mBACL,UACA,KACA,WACC,IAAI,YACH;IAAE,QAAQ,UAAU;IAAS,YAAY;KAAY;KAAU,MAAM;IAAO;GAAE,GAC9E,EACD,CACF;EACD;CACD;CAEA,MAEM,MACL,UACA,SAmBA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,EAAE,QAAQ,GAAG,SAAS,WAAW,CAAC;EACxC,IAAI;GACH,IAAI,kBAAkB,MAAM,GAAG;IAC9B,MAAM,CAAC,YAAY,cAAc,uBAAuB,MAAM;IAC9D,IAAI,cAAc,MAAM;IAExB,MAAM,KAAK,UACV,UACA;KACC,QAAQ;KACR,QAAQ;KACR,UAAU,+BAA+B,MAAM;KAC/C,MAAM,SAAS;KACf,mBAAmB,SAAS;IAC7B,GACA,UACD;GACD,OACC,MAAM,KAAK,UAAU,UAAU,MAAM,UAAU;GAGhD,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,MAAM;GACjE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,KAAK,gBAAgB,QAAQ,OAAO,CAAC;EAC5F,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM;EACP;CACD;;CAGA,gBACC,QACA,SACqB;EACrB,IAAI,kBAAkB,MAAM,GAC3B,OAAO,SAAS,OAAO,CAAC,SAAS,SAAS,IAAI,CAAC,SAAS;EAEzD,IAAI,CAAC,SAAS,UAAU,QAAQ,OAAO,CAAC,SAAS;EAEjD,MAAM,UAA8B,CAAC,SAAS;EAC9C,KAAK,MAAM,WAAW,QAAQ,UAAU;GACvC,MAAM,WAAW,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;GAC9D,MAAM,aAAa,SAAS,QAAQ,GAAG;GACvC,IAAI,eAAe,IAAI;GAIvB,IAAI,cAAc,SAAS,MAAM,aAAa,CAAC;GAC/C,IAAI,CAAC,aAAa;GAElB,IAAI,CAAC,YAAY,WAAW,OAAO,GAClC,cAAc,4BAA4B,KAAK,WAAW,IACvD,QAAQ,gBACR,cAAc;GAGlB,IAAI,YAAY,WAAW,YAAY,GAClC;QAAA,CAAC,QAAQ,SAAS,MAAM,GAC3B,QAAQ,KAAK,MAAM;GAAA,OAEd,IAAI,YAAY,WAAW,aAAa,GAC1C;QAAA,CAAC,QAAQ,SAAS,OAAO,GAC5B,QAAQ,KAAK,OAAO;GAAA;EAGvB;EACA,OAAO;CACR;CAEA,MAAc,UACb,UACA,SAkCA,YACgB;EAChB,MAAM,SAAS,CAAC,OAAO;EAEvB,IAAI,QAAQ,OACX,OAAO,KAAK,SAAS;EAGtB,IAAI,QAAQ,qBAAsB,MAAM,KAAK,IAAI,SAAS,+BAA+B,GACxF,OAAO,KAAK,uBAAuB;EAGpC,IAAI,QAAQ,UAAU,QAAQ,QAAQ;GACrC,IAAI,QAAQ,YAAY,QAAQ,MAAM;IACrC,IAAI,QAAQ,iBAAiB,OAC5B,OAAO,KAAK,IAAI;IAEjB,OAAO,KAAK,QAAQ,QAAQ,GAAG,QAAQ,SAAS,GAAG,QAAQ,QAAQ;GACpE,OACC,OAAO,KAAK,QAAQ,QAAQ,QAAQ,YAAY,QAAQ,MAAM;EAEhE,OAAO,IAAI,QAAQ,UAAU,QAC5B,OAAO,KAAK,QAAQ,QAAQ,GAAG,QAAQ,QAAQ;OACzC,IAAI,QAAQ,QAClB,OAAO,KAAK,QAAQ,MAAM;OACpB,IAAI,QAAQ,KAClB,OAAO,KAAK,OAAO;EAGpB,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;IAAS,GAAG;GAAW,GAAG,GAAG,MAAM;EAChF,SAAS,IAAI;GACZ,MAAM,mBACL,SACA,KACA,WACC,IAAI,WACH;IACC,QAAQ,UAAU;IAClB,QAAQ,SAAS;IACjB,QAAQ,SAAS;IACjB,YAAY;KAAY;KAAU,MAAM;IAAO;GAChD,GACA,EACD,CACF;EACD;CACD;CAEA,MAEM,MACL,UACA,KACA,SACA,YAC8B;EAC9B,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,OAAO,CAAC,OAAO;EAErB,IAAI,SAAS,gBAAgB,QAC5B,KAAK,KAAK,WAAW;OACf,IAAI,SAAS,gBAAgB,MACnC,KAAK,KAAK,MAAM;OACV,IAAI,SAAS,gBAAgB,OACnC,KAAK,KAAK,SAAS;EAEpB,IAAI,SAAS,QACZ,KAAK,KAAK,UAAU;EAErB,IAAI,SAAS,UACZ,KAAK,KAAK,aAAa;EAGxB,KAAK,KAAK,GAAG;EAEb,IAAI;GACH,MAAM,KAAK,IAAI,IAEd;IAAE,KAAK;IAAU,QAAQ;IAAS,SAAS;IAAG,GAAG;GAAW,GAC5D,GAAG,IACJ;GAEA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;GAAO,CAAC;GAChF,OAAO,EAAE,YAAY,MAAM;EAC5B,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,KAAK,oBAAoB,UAAU,MAAM,IAAI,SAAS,MAAM;GAClE,MAAM,SAAS,mBACd,SACA,KACA,WACC,IAAI,WACH;IAAE,QAAQ,UAAU;IAAc;IAAK,YAAY;KAAY;KAAgB;IAAK;GAAE,GACtF,EACD,CACF;GACA,IAAI,WAAW,GAAG,QAAQ,WAAW,GACpC,OAAO,KAAK,qBAAqB,UAAU,OAAO;GAEnD,MAAM;EACP;CACD;CAEA,MAEM,KACL,UACA,SAOA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,IAAI;GACH,IAAI,kBAAkB,SAAS,MAAM,GAAG;IACvC,MAAM,SAAS,QAAQ;IAEvB,MAAM,WAAW,MAAM,KAAK,SAAS,WAAW,YAC/C,WACA,OAAM,GAAG,QAAQ,SAAS,OAAO,IAClC;IACA,IAAI,YAAY,MAAM;KAGrB,MAAM,eAAe,cAAc,SAAS,IAAI,MAAM;KACtD,KAAK,QAAQ,OAAO,YAAY,2BAA2B,cAAc,QAAQ,SAAS;KAC1F,IAAI;MACH,MAAM,KAAK,SACV,cACA;OACC,aAAa,SAAS;OACtB,QAAQ,SAAS;OACjB,MAAM,SAAS;OACf,QAAQ,SAAS;MAClB,GACA,UACD;KACD,UAAU;MACT,KAAK,QAAQ,OAAO,YAAY,2BAA2B,cAAc,QAAQ,OAAO;KACzF;KAEA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,UAAU,MAAM;KAC3E,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;MAAC;MAAQ;MAAS;MAAW;KAAO,CAAC;IAC5F,OAAO,IAAI,SAAS,gBAAgB,QAAQ;KAO3C,MAAM,CAAC,YAAY,cAAc,uBAAuB,MAAM;KAC9D,MAAM,WAAW,+BAA+B,MAAM;KACtD,IAAI,cAAc,QAAQ,YAAY,MACrC,MAAM,IAAI,UAAU;MACnB,QAAQ;MACR,YAAY;OAAY;OAAU,MAAM;QAAC;QAAQ;QAAa,OAAO;OAAI;MAAE;KAC5E,CAAC;KAGF,IAAI;MACH,MAAM,KAAK,UACV,UACA;OACC,QAAQ;OACR,QAAQ;OACE;OACV,MAAM;OACN,cAAc;MACf,GACA,UACD;KACD,SAAS,IAAI;MACZ,IAAI,WAAW,GAAG,IAAI,eAAe,GACpC,MAAM,IAAI,UACT;OAAE,QAAQ;OAAiB,YAAY,GAAG,QAAQ;MAAW,GAC7D,GAAG,QACJ;MAED,MAAM;KACP;KAEA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,MAAM;KAGjE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,SAAS,SAAS,CAAC;IAC3E,OAEC,MAAM,KAAK,MAAM,UAAU,EAAU,OAAO,GAAG,UAAU;IAE1D;GACD;GAEA,KAAK,QAAQ,OAAO,YAAY,2BAA2B,UAAU,QAAQ,SAAS;GACtF,IAAI;IACH,MAAM,KAAK,SACV,UACA;KACC,aAAa,SAAS;KACtB,QAAQ,SAAS;KACjB,MAAM,SAAS;KACf,QAAQ,SAAS;IAClB,GACA,UACD;GACD,UAAU;IACT,KAAK,QAAQ,OAAO,YAAY,2BAA2B,UAAU,QAAQ,OAAO;GACrF;GAEA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,UAAU,MAAM;GAC3E,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;IAAW;GAAO,CAAC;EAC5F,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM;EACP;CACD;CAEA,MAAc,SACb,UACA,SACA,YACgB;EAChB,MAAM,SAAS,CAAC,MAAM;EAEtB,IAAI,QAAQ,MACX,OAAO,KAAK,QAAQ;EAGrB,IAAI,QAAQ,QACX,OAAO,KAAK,IAAI;EAGjB,IAAI,QAAQ,gBAAgB,QAC3B,OAAO,KAAK,WAAW;EAGxB,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,SAAS;IAAgB,QAAQ;IAAS,GAAG;GAAW,GAAG,GAAG,MAAM;EACzG,SAAS,IAAI;GACZ,MAAM,KAAK,oBAAoB,UAAU,QAAQ,IAAI,QAAQ,MAAM;GACnE,MAAM,mBACL,QACA,KACA,WACC,IAAI,UAAU;IAAE,QAAQ,UAAU;IAAS,YAAY;KAAY;KAAU,MAAM;IAAO;GAAE,GAAG,EAAE,CACnG;EACD;CACD;CAEA,MAEM,KACL,UACA,SACA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EAQJ,IAAI,kBAAkB,SAAS,SAAS,GAAG;GAC1C,IAAI,QAAQ,WAAW,MAAM;IAC5B,aAAa,QAAQ,UAAU;IAC/B,aAAa,QAAQ,QAAQ;GAC9B,OACC,CAAC,YAAY,cAAc,uBAAuB,QAAQ,SAAS;GAEpE,eAAe,+BAA+B,QAAQ,SAAS;EAChE,OAAO;GACN,MAAM,SAAS,MAAM,KAAK,SAAS,SAAS,UAAU,QAAQ;GAC9D,IAAI,UAAU,MAAM;GAEpB,IAAI,SAAS,aAAa,MACzB,aAAa,GAAG,QAAQ,UAAU,IAAI,GACrC,SAAS,WAAW,OAAO,gBAAgB,KACzC,OAAO;QACJ;IACN,MAAM,WAAW,SAAS,WAAW,OAAO,OAAO,wBAAwB,KAAA;IAC3E,aACC,YAAY,QAAQ,aAAa,OAAO,oBACrC,GAAG,OAAO,KAAK,GAAG,aAClB,OAAO;GACZ;GACA,aAAa,OAAO,cAAc,SAAS,SAAS;GACpD,eAAe,SAAS,aAAa,QAAQ,SAAS,WAAW,OAAO,OAAO,OAAO,KAAA;GAGtF,IAAI,SAAS,SAAS,UAAU,QAAQ,SAAS,aAAa,MAC7D,cAAc;IACb,QAAQ,OAAO;IACf,QAAQ;IACR,cAAc,OAAO;GACtB;EAEF;EAEA,IAAI,SAAS,WAAW,QAAQ,cAAc,QAAQ,gBAAgB,MACrE,MAAM,IAAI,UAAU,EAAE,QAAQ,QAAQ,CAAC;EAGxC,IAAI;EACJ,IAAI,SAAS,OAIZ,YAD0B,KAAK,QAAQ,QAAQ,MAAM,qBAAqB,OAEvE;GAAE,WAAW;GAAM,YAAY,KAAK,QAAQ,QAAQ,MAAM,sBAAsB;EAAK,IACrF,EAAE,WAAW,MAAM;EAGvB,IAAI;GACH,MAAM,KAAK,SACV,UACA;IACC,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,OAAO;IACP,SAAS,SAAS,WAAW;GAC9B,GACA,UACD;GAKA,IAAI,eAAe,MAClB,IAAI;IACH,MAAM,KAAK,IAAI,IACd;KAAE,KAAK;KAAU,GAAG;IAAW,GAC/B,UACA,qBACA,GAAG,YAAY,OAAO,GAAG,YAAY,gBACrC,YAAY,MACb;GACD,SAAS,IAAI;IACZ,OAAO,MAAM,IAAI,+CAA+C;GACjE;GAGD,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,UAAU;GACzD,KAAK,QAAQ,OAAO,YAAY,YAC/B,UACA,SAAS,WAAW,OAAO;IAAC;IAAU;IAAS;GAAS,IAAI,CAAC,SAAS,CACvE;EACD,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM;EACP;CACD;CAEA,MAAc,SACb,UACA,SAQA,YACgB;EAChB,MAAM,SAAS,CAAC,MAAM;EAEtB,IAAI,QAAQ,SAAS,MAAM;GAC1B,IAAI,QAAQ,MAAM,WAAW;IAC5B,OAAO,KAAK,oBAAoB;IAChC,IAAI,QAAQ,MAAM,YACb;SAAA,MAAM,KAAK,IAAI,SAAS,4BAA4B,GACvD,OAAO,KAAK,qBAAqB;IAAA;GAGpC,OACC,OAAO,KAAK,SAAS;EAEvB;EAEA,IAAI,QAAQ,UAAU,QAAQ,QAAQ;GACrC,IAAI,QAAQ,UACX,OAAO,KAAK,MAAM,QAAQ,QAAQ,GAAG,QAAQ,OAAO,GAAG,QAAQ,UAAU;QACnE,IAAI,QAAQ,SAClB,OAAO,KAAK,kBAAkB,QAAQ,QAAQ,QAAQ,MAAM;QAE5D,OAAO,KAAK,QAAQ,QAAQ,QAAQ,MAAM;EAE5C,OAAO,IAAI,QAAQ,QAClB,OAAO,KAAK,QAAQ,MAAM;OACpB,IAAI,QAAQ,QAClB,OAAO,KAAK,QAAQ,OAAO,QAAQ,IAAI,QAAQ,OAAO,QAAQ;EAG/D,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;IAAS,GAAG;GAAW,GAAG,GAAG,MAAM;EAChF,SAAS,IAAI;GACZ,MAAM,QAAQ,mBACb,QACA,KACA,WACC,IAAI,UACH;IACS;IACR,QAAQ,SAAS,UAAU,SAAS,QAAQ;IAC5C,QAAQ,SAAS,UAAU,SAAS,QAAQ;IAC5C,YAAY;KAAY;KAAU,MAAM;IAAO;GAChD,GACA,EACD,CACF;GAEA,IAAI,SAAS,OAAO,aAAa,MAAM,QAAQ,WAAW,YAAY;IACrE,IAAI,GAAG,UAAU,kCAAkC,KAAK,GAAG,MAAM,GAChE,MAAM,IAAI,UACT;KACC,QAAQ;KACR,QAAQ,SAAS,UAAU,SAAS,QAAQ;KAC5C,QAAQ,SAAS,UAAU,SAAS,QAAQ;KAC5C,YAAY;MAAY;MAAU,MAAM;KAAO;IAChD,GACA,EACD;IAED,IACC,QAAQ,MAAM,cACd,GAAG,UACH,yDAAyD,KAAK,GAAG,MAAM,GAEvE,MAAM,IAAI,UACT;KACC,QAAQ;KACR,QAAQ,SAAS,UAAU,SAAS,QAAQ;KAC5C,QAAQ,SAAS,UAAU,SAAS,QAAQ;KAC5C,YAAY;MAAY;MAAU,MAAM;KAAO;IAChD,GACA,EACD;IAED,IAAI,GAAG,UAAU,UAAU,6BAA6B,KAAK,GAAG,MAAM,GACrE,MAAM,IAAI,UACT;KACC,QAAQ;KACR,QAAQ,SAAS,UAAU,SAAS,QAAQ;KAC5C,QAAQ,SAAS,UAAU,SAAS,QAAQ;KAC5C,YAAY;MAAY;MAAU,MAAM;KAAO;IAChD,GACA,EACD;GAEF;GACA,MAAM;EACP;CACD;CAEA,MAEM,OACL,UACA,UACA,SAYA,YAC8B;EAC9B,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,OAAO,CAAC,QAAQ;EACtB,MAAM,UAAoB,CAAC;EAE3B,IAAI,SAAS,cAAc,OAC1B,KAAK,KAAK,aAAa;EAGxB,IAAI,SAAS,aAAa;GACzB,KAAK,KAAK,eAAe;GAEzB,IAAI,QAAQ,QACX,QAAQ,KAAK,MAAM,mBAAmB,QAAQ,QAAQ;GAMvD,IAAI,QAAQ,oBACX,QAAQ,KAAK,MAAM,2BAA2B,MAAM,iCAAiC;EAEvF;EAEA,IAAI,SAAS,cAAc,MAAM;GAChC,IAAI,QAAQ,cAAc,QAAQ,oBACjC,MAAM,IAAI,MAAM,KAAK,EAAE,+DAA+D,CAAC;GAKxF,KAAK,KAAK,QAAQ,aAAa,iBAAiB,iBAAiB;EAClE;EAKA,IAAI,MAAM,YAAY;EACtB,IAAI,SAAS,eAAe;GAC3B,QAAQ,KAAK,MAAM,eAAe,QAAQ,eAAe;GACzD,MAAM;IAAE,GAAG;IAAK,YAAY,QAAQ;GAAc;EACnD;EAEA,IAAI,SAAS,eAAe,MAC3B,KAAK,KAAK,eAAe;OACnB,IAAI,SAAS,eAAe,OAClC,KAAK,KAAK,kBAAkB;EAG7B,IAAI,SAAS,MACZ,KAAK,KAAK,UAAU,QAAQ,IAAI;EAGjC,KAAK,KAAK,QAAQ;EAElB,IAAI,SAAS,QACZ,KAAK,KAAK,QAAQ,MAAM;EAKzB,KAAK,QAAQ,OAAO,YAAY,2BAA2B,UAAU,UAAU,SAAS;EACxF,IAAI;GACH,MAAM,KAAK,IAAI,IAEd;IAAE,KAAK;IAAU,QAAQ;IAAkB;IAAS,SAAS;IAAG,GAAG;IAAiB;GAAI,GACxF,GAAG,IACJ;GACA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;GAAO,CAAC;GAChF,OAAO,EAAE,YAAY,MAAM;EAC5B,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,KAAK,oBAAoB,UAAU,MAAM,IAAI,SAAS,MAAM;GAClE,MAAM,SAAS,mBACd,UACA,KACA,WACC,IAAI,YACH;IACC,QAAQ,UAAU;IACR;IACV,YAAY;KAAY;KAAgB;IAAK;GAC9C,GACA,EACD,CACF;GACA,IAAI,YAAY,GAAG,QAAQ,WAAW,GACrC,OAAO,MAAM,KAAK,qBAAqB,UAAU,QAAQ;GAE1D,MAAM;EACP,UAAU;GAET,KAAK,QAAQ,OAAO,YAAY,2BAA2B,UAAU,UAAU,OAAO;EACvF;CACD;CAEA,MACM,MACL,UACA,KACA,SACA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,IAAI;GACH,MAAM,KAAK,UAAU,UAAU,KAAK,SAAS,MAAM,UAAU;GAC7D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;GAAO,CAAC;EACjF,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM;EACP;CACD;CAEA,MAAc,UACb,UACA,KACA,MACA,YACgB;EAChB,MAAM,SAAS,CAAC,SAAS,IAAI;EAC7B,IAAI,MACH,OAAO,KAAK,KAAK,MAAM;EAExB,OAAO,KAAK,KAAK,IAAI;EAErB,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;IAAS,GAAG;GAAW,GAAG,GAAG,MAAM;EAChF,SAAS,IAAI;GACZ,MAAM,mBACL,SACA,KACA,WACC,IAAI,WAAW;IAAE,QAAQ,UAAU;IAAS,YAAY;KAAY;KAAU,MAAM;IAAO;GAAE,GAAG,EAAE,CACpG;EACD;CACD;CAEA,MAEM,QACL,UACA,MACA,SACA,YACgB;EAChB,MAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;EAChD,IAAI,CAAC,MAAM,QAAQ;EAEnB,MAAM,QAAQ,gBAAgB;EAC9B,MAAM,aAAa,MAAM,KAAI,MAAK,UAAU,GAAG,UAAU,IAAI,CAAC,CAAC,EAAE;EAQjE,MAAM,WAAW,SAAS,QAAQ,OAAO,KAAK,QAAQ,SAAS,SAAS,OAAO,KAAA;EAC/E,MAAM,SAAS,YAAY,OAAO;GAAC;GAAY;GAAU;EAAI,IAAI,CAAC,YAAY,IAAI;EAElF,IAAI;GACH,IAAI,MAAM,KAAK,IAAI,SAAS,iCAAiC,GAAG;IAI/D,MAAM,OAAO,CAAC,UAAU;IACxB,IAAI,YAAY,MACf,KAAK,KAAK,QAAQ;IAEnB,KAAK,KAAK,0BAA0B,qBAAqB;IACzD,MAAM,KAAK,IAAI,IACd;KAAE,KAAK;KAAU,QAAQ;KAAS,GAAG;KAAY,OAAO,WAAW,KAAK,IAAI;IAAE,GAC9E,GAAG,IACJ;GACD,OAAO;IAKN,MAAM,iBAAiB;IACvB,MAAM,eAAe,OAAO,QAAQ,KAAK,QAAQ,MAAM,IAAI,SAAS,gBAAgB,CAAC;IACrF,KAAK,MAAM,SAAS,oBAAoB,YAAY,kBAAkB,cAAc,cAAc,GACjG,MAAM,KAAK,IAAI,IAAI;KAAE,KAAK;KAAU,QAAQ;KAAS,GAAG;IAAW,GAAG,GAAG,QAAQ,GAAG,KAAK;GAE3F;GACA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,QAAQ;GACvD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;EAChE,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,mBACL,YACA,KACA,WACC,IAAI,cACH;IACC,QAAQ,UAAU;IAClB,KAAK,SAAS,QAAQ,SAAS;IAC/B,YAAY;KAAY;KAAU,MAAM,CAAC,GAAG,QAAQ,GAAG,UAAU;IAAE;GACpE,GACA,EACD,CACF;EACD;CACD;CAEA,MAEM,OACL,UACA,MACA,SACA,YAC8B;EAC9B,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,OAAO,CAAC,QAAQ;EAEtB,IAAI,SAAS,gBAAgB,MAC5B,KAAK,KAAK,QAAQ;OACZ,IAAI,SAAS,gBAAgB,OACnC,KAAK,KAAK,WAAW;EAGtB,KAAK,KAAK,GAAG,IAAI;EAEjB,IAAI;GACH,MAAM,KAAK,IAAI,IAEd;IAAE,KAAK;IAAU,QAAQ;IAAS,SAAS;IAAG,GAAG;GAAW,GAC5D,GAAG,IACJ;GAEA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;IAAC;IAAQ;IAAS;GAAO,CAAC;GAChF,OAAO,EAAE,YAAY,MAAM;EAC5B,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,KAAK,oBAAoB,UAAU,MAAM,IAAI,SAAS,MAAM;GAElE,MAAM,SAAS,mBACd,UACA,KACA,WACC,IAAI,YACH;IAAE,QAAQ,UAAU;IAAe;IAAM,YAAY;KAAY;KAAgB;IAAK;GAAE,GACxF,EACD,CACF;GACA,IAAI,YAAY,GAAG,QAAQ,WAAW,GACrC,OAAO,KAAK,qBAAqB,UAAU,QAAQ;GAEpD,MAAM;EACP;CACD;;;;;;;;;;;CAYA,MAAc,oBACb,UACA,MACA,IACA,QACgB;EAChB,MAAM,SAAS,qBAAqB,EAAE;EACtC,IAAI,UAAU,MAAM;EAEpB,IAAI;EACJ,IAAI;GACH,UAAU,MAAM,KAAK,SAAS,OAAO,mBAAmB,QAAQ,EAAA,EAAI;EACrE,QAAQ,CAER;EACA,WAAW,4BAA4B,EAAE,KAAK;EAE9C,KAAK,QAAQ,OAAO,SAAS,kBAAkB,QAAQ,QAAQ,MAAM;EACrE,MAAM,IAAI,aACT;GAAU;GAAQ,YAAY;IAAY;IAAgB;GAAK;EAAE,GACjE,cAAc,QAAQ,KAAK,KAAA,CAC5B;CACD;CAEA,MAAc,qBAAqB,UAAkB,SAA0D;EAC9G,IAAI;EACJ,IAAI;GACH,YAAY,MAAM,KAAK,SAAS,OAAO,oBAAoB,QAAQ;EACpE,SAAS,IAAI;GAEZ,QAAO,KAAK,0CAA0C,QAAQ,IAAI,IAAI;EACvE;EAGA,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;EACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU;GAAC;GAAQ;GAAS;EAAO,CAAC;EAChF,KAAK,QAAQ,OAAO,YAAY,eAAe,SAAS,SAAS;EACjE,OAAO;GAAE,YAAY;GAAiB;EAAU;CACjD;AACD;AAvlCE,WAAA,CAAA,MAAM,CAAA,GAAA,yBAAA,WAAA,YAAA,IAAA;AA0CN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,cAAA,IAAA;AA+DN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,UAAA,IAAA;AA6EN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,SAAA,IAAA;AAoLN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,SAAA,IAAA;AAwDN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,QAAA,IAAA;AAqJN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,QAAA,IAAA;AAoNN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,UAAA,IAAA;AAmHN,WAAA,CAAA,MAAM,CAAA,GAAA,yBAAA,WAAA,SAAA,IAAA;AA2CN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,WAAA,IAAA;AAmEN,WAAA,CAAA,cAAc,EAAE,cAAa,OAAM,GAAG,CAAC,GACvC,MAAM,CAAA,GAAA,yBAAA,WAAA,UAAA,IAAA"}
1
+ {"version":3,"file":"operations.js","names":[],"sources":["../../../../git-cli/src/providers/operations.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitConflictCommand, GitServiceContext } from '@gitlens/git/context.js';\nimport {\n\tCheckoutError,\n\tCherryPickError,\n\tCommitError,\n\tFetchError,\n\tMergeError,\n\tPullError,\n\tPushError,\n\tRebaseError,\n\tResetError,\n\tRevertError,\n\tSigningError,\n} from '@gitlens/git/errors.js';\nimport type { GitBranchReference, GitReference } from '@gitlens/git/models/reference.js';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\nimport type { SigningFormat } from '@gitlens/git/models/signature.js';\nimport type { GitConflictFile } from '@gitlens/git/models/staging.js';\nimport type {\n\tGitOperationResult,\n\tGitOperationRunOptions,\n\tGitOperationsSubProvider,\n} from '@gitlens/git/providers/operations.js';\nimport { getBranchNameAndRemote, getBranchTrackingWithoutRemote } from '@gitlens/git/utils/branch.utils.js';\nimport { isBranchReference } from '@gitlens/git/utils/reference.utils.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { sequentialize } from '@gitlens/utils/decorators/sequentialize.js';\nimport { chunkByStringLength } from '@gitlens/utils/iterable.js';\nimport { Logger } from '@gitlens/utils/logger.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git, PushForceOptions } from '../exec/git.js';\nimport {\n\tclassifySigningError,\n\tgetGitCommandError,\n\tgitConfigsPull,\n\tGitErrors,\n\tinferSigningFormatFromError,\n\tmaxGitCliLength,\n} from '../exec/git.js';\n\nexport class OperationsGitSubProvider implements GitOperationsSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync checkout(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { createBranch?: string; noTracking?: boolean },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst params = ['checkout'];\n\t\tif (options?.createBranch) {\n\t\t\tparams.push('-b', options.createBranch);\n\t\t\tif (options.noTracking) {\n\t\t\t\tparams.push('--no-track');\n\t\t\t}\n\t\t\tparams.push(ref, '--');\n\t\t} else {\n\t\t\tparams.push(ref, '--');\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t\tif (options?.createBranch) {\n\t\t\t\t// Evict the cached base only — see `createBranch` on why the persisted keys stay.\n\t\t\t\tthis.cache.deleteBaseBranchName(repoPath, options.createBranch);\n\t\t\t}\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'checkout',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CheckoutError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', ref: ref, gitCommand: { repoPath: repoPath, args: params } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync cherryPick(\n\t\trepoPath: string,\n\t\trevs: string[],\n\t\toptions?: { edit?: boolean; noCommit?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['cherry-pick'];\n\t\tif (options?.edit) {\n\t\t\targs.push('-e');\n\t\t}\n\t\tif (options?.noCommit) {\n\t\t\targs.push('-n');\n\t\t}\n\n\t\tif (revs.length > 1) {\n\t\t\t// Sort commits in topological order (oldest ancestor first) so cherry-pick applies them correctly.\n\t\t\t// This is a local read-only pre-flight, not the user-initiated op — don't subject it to caller env/timeout.\n\t\t\tconst revsSet = new Set(revs);\n\t\t\tconst result = await this.git.run({ cwd: repoPath }, 'rev-list', '--topo-order', '--reverse', ...revs);\n\n\t\t\tconst ordered: string[] = [];\n\t\t\tfor (const sha of result.stdout.trim().split('\\n')) {\n\t\t\t\tif (sha && revsSet.has(sha)) {\n\t\t\t\t\tordered.push(sha);\n\t\t\t\t\tif (ordered.length === revs.length) break; // Early exit once we have all\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (ordered.length === revs.length) {\n\t\t\t\trevs = ordered;\n\t\t\t}\n\t\t\t// If we didn't get all commits (shouldn't happen), keep original order\n\t\t}\n\n\t\targs.push(...revs);\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...args);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'cherry-pick',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CherryPickError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', revs: revs, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (CherryPickError.is(mapped, 'conflicts')) {\n\t\t\t\treturn this.createConflictResult(repoPath, 'cherry-pick');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync commit(\n\t\trepoPath: string,\n\t\tmessage: string,\n\t\toptions?: {\n\t\t\tall?: boolean;\n\t\t\tallowEmpty?: boolean;\n\t\t\tamend?: boolean;\n\t\t\tauthor?: string;\n\t\t\tdate?: string;\n\t\t\tsignoff?: boolean;\n\t\t\tsource?: unknown;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst params = ['commit'];\n\t\tif (options?.all) {\n\t\t\tparams.push('--all');\n\t\t}\n\t\tif (options?.allowEmpty) {\n\t\t\tparams.push('--allow-empty');\n\t\t}\n\t\tif (options?.amend) {\n\t\t\tparams.push('--amend');\n\t\t}\n\t\tif (options?.signoff) {\n\t\t\tparams.push('--signoff');\n\t\t}\n\t\tif (options?.author) {\n\t\t\tparams.push(`--author=${options.author}`);\n\t\t}\n\t\tif (options?.date) {\n\t\t\tparams.push(`--date=${options.date}`);\n\t\t}\n\t\t// Host-level override (e.g. VS Code's `git.enableCommitSigning`) — request signing explicitly\n\t\t// via `-S`. Implicit repo-config signing (`commit.gpgsign=true`) needs no flag, and `-S`\n\t\t// alongside it is harmless, so the override can only enable signing, never force it off.\n\t\tconst sign = this.context.config?.signing?.enabled === true;\n\t\tif (sign) {\n\t\t\tparams.push('-S');\n\t\t}\n\t\t// Read commit message from stdin via -F - to avoid shell escaping issues\n\t\tparams.push('-F', '-');\n\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t{ cwd: repoPath, stdin: message, stdinEncoding: 'utf8', errors: 'throw', ...runOptions },\n\t\t\t\t...params,\n\t\t\t);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\tif (sign) {\n\t\t\t\t// `-S` was passed and the commit succeeded, so signing is confirmed — fire the\n\t\t\t\t// explicit-sign hook (same contract as the patch provider's `commit-tree -S` path).\n\t\t\t\tlet format: SigningFormat | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tformat = (await this.provider.config.getSigningConfig?.(repoPath))?.format;\n\t\t\t\t} catch {}\n\t\t\t\tthis.context.hooks?.commits?.onSigned?.(format ?? 'gpg', options?.source);\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, params, ex, options?.source);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'commit',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CommitError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync fetch(\n\t\trepoPath: string,\n\t\toptions?:\n\t\t\t| {\n\t\t\t\t\tall?: boolean;\n\t\t\t\t\tbranch?: GitBranchReference;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: boolean;\n\t\t\t\t\tremote?: string;\n\t\t\t\t\trefspecs?: undefined;\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tall?: undefined;\n\t\t\t\t\tbranch?: undefined;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: undefined;\n\t\t\t\t\tremote: string;\n\t\t\t\t\trefspecs: readonly string[];\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst { branch, ...opts } = options ?? {};\n\t\tlet ran = false;\n\t\ttry {\n\t\t\tif (isBranchReference(branch)) {\n\t\t\t\tconst [branchName, remoteName] = getBranchNameAndRemote(branch);\n\t\t\t\tif (remoteName == null) return;\n\n\t\t\t\tran = true;\n\t\t\t\tawait this.fetchCore(\n\t\t\t\t\trepoPath,\n\t\t\t\t\t{\n\t\t\t\t\t\tbranch: branchName,\n\t\t\t\t\t\tremote: remoteName,\n\t\t\t\t\t\tupstream: getBranchTrackingWithoutRemote(branch)!,\n\t\t\t\t\t\tpull: options?.pull,\n\t\t\t\t\t\tpreserveFetchHead: options?.preserveFetchHead,\n\t\t\t\t\t},\n\t\t\t\t\trunOptions,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tran = true;\n\t\t\t\tawait this.fetchCore(repoPath, opts, runOptions);\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t} finally {\n\t\t\t// A rejected fetch may have stored some of its refs before it failed\n\t\t\tif (ran) {\n\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'tags');\n\t\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, this.getFetchChanges(branch, options));\n\t\t\t}\n\t\t}\n\t}\n\n\t/** `remotes`, plus `heads`/`tags` for any local branch or tag the fetch writes — a `pull` fetch writes `<upstream>:<branch>` */\n\tprivate getFetchChanges(\n\t\tbranch: GitBranchReference | undefined,\n\t\toptions: { pull?: boolean; refspecs?: readonly string[] } | undefined,\n\t): RepositoryChange[] {\n\t\tif (isBranchReference(branch)) {\n\t\t\treturn options?.pull ? ['heads', 'remotes'] : ['remotes'];\n\t\t}\n\t\tif (!options?.refspecs?.length) return ['remotes'];\n\n\t\tconst changes: RepositoryChange[] = ['remotes'];\n\t\tfor (const refspec of options.refspecs) {\n\t\t\tconst stripped = refspec.startsWith('+') ? refspec.slice(1) : refspec;\n\t\t\tconst colonIndex = stripped.indexOf(':');\n\t\t\tif (colonIndex === -1) continue;\n\n\t\t\t// Qualified as git's fetch does: an empty destination stores nothing, `heads/`/`tags/`/`remotes/`\n\t\t\t// get `refs/`, and any other unqualified name is a local branch\n\t\t\tlet destination = stripped.slice(colonIndex + 1);\n\t\t\tif (!destination) continue;\n\n\t\t\tif (!destination.startsWith('refs/')) {\n\t\t\t\tdestination = /^(?:heads|tags|remotes)\\//.test(destination)\n\t\t\t\t\t? `refs/${destination}`\n\t\t\t\t\t: `refs/heads/${destination}`;\n\t\t\t}\n\n\t\t\tif (destination.startsWith('refs/tags/')) {\n\t\t\t\tif (!changes.includes('tags')) {\n\t\t\t\t\tchanges.push('tags');\n\t\t\t\t}\n\t\t\t} else if (destination.startsWith('refs/heads/')) {\n\t\t\t\tif (!changes.includes('heads')) {\n\t\t\t\t\tchanges.push('heads');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn changes;\n\t}\n\n\tprivate async fetchCore(\n\t\trepoPath: string,\n\t\toptions:\n\t\t\t| {\n\t\t\t\t\tall?: boolean;\n\t\t\t\t\tbranch?: undefined;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: boolean;\n\t\t\t\t\tremote?: string;\n\t\t\t\t\trefspecs?: undefined;\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tall?: undefined;\n\t\t\t\t\tbranch: string;\n\t\t\t\t\tprune?: undefined;\n\t\t\t\t\tpull?: boolean;\n\t\t\t\t\tremote: string;\n\t\t\t\t\tupstream: string;\n\t\t\t\t\t/**\n\t\t\t\t\t * `-u` (`--update-head-ok`, the default) lets a `pull` fetch move a branch even where it is\n\t\t\t\t\t * checked out; `false` keeps git's own refusal as a guard against a stale worktree lookup.\n\t\t\t\t\t */\n\t\t\t\t\tupdateHeadOk?: boolean;\n\t\t\t\t\trefspecs?: undefined;\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tall?: undefined;\n\t\t\t\t\tbranch?: undefined;\n\t\t\t\t\tprune?: boolean;\n\t\t\t\t\tpull?: undefined;\n\t\t\t\t\tremote: string;\n\t\t\t\t\trefspecs: readonly string[];\n\t\t\t\t\tpreserveFetchHead?: boolean;\n\t\t\t },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['fetch'];\n\n\t\tif (options.prune) {\n\t\t\tparams.push('--prune');\n\t\t}\n\n\t\tif (options.preserveFetchHead && (await this.git.supports('git:fetch:no-write-fetch-head'))) {\n\t\t\tparams.push('--no-write-fetch-head');\n\t\t}\n\n\t\tif (options.branch && options.remote) {\n\t\t\tif (options.upstream && options.pull) {\n\t\t\t\tif (options.updateHeadOk !== false) {\n\t\t\t\t\tparams.push('-u');\n\t\t\t\t}\n\t\t\t\tparams.push(options.remote, `${options.upstream}:${options.branch}`);\n\t\t\t} else {\n\t\t\t\tparams.push(options.remote, options.upstream || options.branch);\n\t\t\t}\n\t\t} else if (options.refspecs?.length) {\n\t\t\tparams.push(options.remote, ...options.refspecs);\n\t\t} else if (options.remote) {\n\t\t\tparams.push(options.remote);\n\t\t} else if (options.all) {\n\t\t\tparams.push('--all');\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'fetch',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew FetchError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\tbranch: options?.branch,\n\t\t\t\t\t\t\tremote: options?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync merge(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { fastForward?: boolean | 'only'; noCommit?: boolean; squash?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['merge'];\n\n\t\tif (options?.fastForward === 'only') {\n\t\t\targs.push('--ff-only');\n\t\t} else if (options?.fastForward === true) {\n\t\t\targs.push('--ff');\n\t\t} else if (options?.fastForward === false) {\n\t\t\targs.push('--no-ff');\n\t\t}\n\t\tif (options?.squash) {\n\t\t\targs.push('--squash');\n\t\t}\n\t\tif (options?.noCommit) {\n\t\t\targs.push('--no-commit');\n\t\t}\n\n\t\targs.push(ref);\n\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t// Avoid a timeout since merges can take a long time (set to 0 to disable)\n\t\t\t\t{ cwd: repoPath, errors: 'throw', timeout: 0, ...runOptions },\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'merge',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew MergeError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', ref: ref, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (MergeError.is(mapped, 'conflicts')) {\n\t\t\t\treturn this.createConflictResult(repoPath, 'merge');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync pull(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tbranch?: GitBranchReference;\n\t\t\tfastForward?: 'only';\n\t\t\trebase?: boolean;\n\t\t\ttags?: boolean;\n\t\t\tsource?: unknown;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Set once a git command is about to run, so a pull that fails partway (a merge or rebase stopping on a\n\t\t// conflict, a fetch that stored some refs) announces what it changed the way a finished one does\n\t\tlet announce: (() => void) | undefined;\n\t\ttry {\n\t\t\tif (isBranchReference(options?.branch)) {\n\t\t\t\tconst branch = options.branch;\n\t\t\t\t// Find the worktree where this branch is checked out (if any)\n\t\t\t\tconst worktree = await this.provider.worktrees?.getWorktree(\n\t\t\t\t\trepoPath,\n\t\t\t\t\twt => wt.branch?.name === branch.name,\n\t\t\t\t);\n\t\t\t\tif (worktree != null) {\n\t\t\t\t\t// Branch is checked out in a worktree — run git pull in that worktree's directory\n\t\t\t\t\t// Any rebase state (e.g. from `pull.rebase=true`) appears under the worktree path\n\t\t\t\t\tconst worktreePath = normalizePath(worktree.uri.fsPath);\n\t\t\t\t\t// Its HEAD, index and any paused merge or rebase belong to that worktree, not to `repoPath`\n\t\t\t\t\tannounce = () => {\n\t\t\t\t\t\tthis.announcePull(repoPath);\n\t\t\t\t\t\tif (worktreePath !== normalizePath(repoPath)) {\n\t\t\t\t\t\t\tthis.announcePull(worktreePath);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(worktreePath, 'pull', 'started');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.pullCore(\n\t\t\t\t\t\t\tworktreePath,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfastForward: options?.fastForward,\n\t\t\t\t\t\t\t\trebase: options?.rebase,\n\t\t\t\t\t\t\t\ttags: options?.tags,\n\t\t\t\t\t\t\t\tsource: options?.source,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trunOptions,\n\t\t\t\t\t\t);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(worktreePath, 'pull', 'ended');\n\t\t\t\t\t}\n\t\t\t\t} else if (options?.fastForward === 'only') {\n\t\t\t\t\t// Not checked out anywhere, so there is no working tree to merge into — but a fast-forward\n\t\t\t\t\t// needs none: fetching `<upstream>:<branch>` advances the local branch, and git refuses that\n\t\t\t\t\t// non-forced refspec unless it fast-forwards. A plain fetch would leave the branch unmoved\n\t\t\t\t\t// and report success.\n\t\t\t\t\t// Fetched without `-u`: the worktree lookup above is cached and can miss a worktree added\n\t\t\t\t\t// outside core, and then git's own refusal is what keeps a checked-out branch from moving.\n\t\t\t\t\tconst [branchName, remoteName] = getBranchNameAndRemote(branch);\n\t\t\t\t\tconst upstream = getBranchTrackingWithoutRemote(branch);\n\t\t\t\t\tif (remoteName == null || upstream == null) {\n\t\t\t\t\t\tthrow new PullError({\n\t\t\t\t\t\t\treason: 'noUpstream',\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: ['pull', '--ff-only', branch.name] },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// A `pull` fetch writes `<upstream>:<branch>`, moving the local branch too — same\n\t\t\t\t\t// hooks `fetch()` fires for a pull fetch with a branch reference.\n\t\t\t\t\tannounce = () => {\n\t\t\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'tags');\n\t\t\t\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['heads', 'remotes']);\n\t\t\t\t\t};\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.fetchCore(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbranch: branchName,\n\t\t\t\t\t\t\t\tremote: remoteName,\n\t\t\t\t\t\t\t\tupstream: upstream,\n\t\t\t\t\t\t\t\tpull: true,\n\t\t\t\t\t\t\t\tupdateHeadOk: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trunOptions,\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\tif (FetchError.is(ex, 'noFastForward')) {\n\t\t\t\t\t\t\tthrow new PullError(\n\t\t\t\t\t\t\t\t{ reason: 'noFastForward', gitCommand: ex.details.gitCommand },\n\t\t\t\t\t\t\t\tex.original,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow ex;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Branch is not checked out anywhere — can only fetch (no working tree to merge into)\n\t\t\t\t\tawait this.fetch(repoPath, { branch: branch }, runOptions);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tannounce = () => this.announcePull(repoPath);\n\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'pull', 'started');\n\t\t\ttry {\n\t\t\t\tawait this.pullCore(\n\t\t\t\t\trepoPath,\n\t\t\t\t\t{\n\t\t\t\t\t\tfastForward: options?.fastForward,\n\t\t\t\t\t\trebase: options?.rebase,\n\t\t\t\t\t\ttags: options?.tags,\n\t\t\t\t\t\tsource: options?.source,\n\t\t\t\t\t},\n\t\t\t\t\trunOptions,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'pull', 'ended');\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t} finally {\n\t\t\tannounce?.();\n\t\t}\n\t}\n\n\tprivate announcePull(repoPath: string): void {\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status', 'tags');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'remotes', 'index']);\n\t}\n\n\tprivate async pullCore(\n\t\trepoPath: string,\n\t\toptions: { fastForward?: 'only'; rebase?: boolean; tags?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['pull'];\n\n\t\tif (options.tags) {\n\t\t\tparams.push('--tags');\n\t\t}\n\n\t\tif (options.rebase) {\n\t\t\tparams.push('-r');\n\t\t}\n\n\t\tif (options.fastForward === 'only') {\n\t\t\tparams.push('--ff-only');\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, configs: gitConfigsPull, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tawait this.throwIfSigningError(repoPath, params, ex, options.source);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'pull',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PullError({ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } }, ex),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync push(\n\t\trepoPath: string,\n\t\toptions?: { reference?: GitReference; force?: boolean; publish?: { remote: string } },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tlet branchName: string;\n\t\tlet remoteName: string | undefined;\n\t\tlet upstreamName: string | undefined;\n\t\tlet setUpstream:\n\t\t\t| {\n\t\t\t\t\tbranch: string;\n\t\t\t\t\tremote: string;\n\t\t\t\t\tremoteBranch: string;\n\t\t\t }\n\t\t\t| undefined;\n\n\t\tif (isBranchReference(options?.reference)) {\n\t\t\tif (options.publish != null) {\n\t\t\t\tbranchName = options.reference.name;\n\t\t\t\tremoteName = options.publish.remote;\n\t\t\t} else {\n\t\t\t\t[branchName, remoteName] = getBranchNameAndRemote(options.reference);\n\t\t\t}\n\t\t\tupstreamName = getBranchTrackingWithoutRemote(options.reference);\n\t\t} else {\n\t\t\tconst branch = await this.provider.branches.getBranch(repoPath);\n\t\t\tif (branch == null) return;\n\n\t\t\tif (options?.reference != null) {\n\t\t\t\tbranchName = `${options.reference.ref}:${\n\t\t\t\t\toptions?.publish != null ? 'refs/heads/' : ''\n\t\t\t\t}${branch.nameWithoutRemote}`;\n\t\t\t} else {\n\t\t\t\tconst tracking = options?.publish == null ? branch.trackingWithoutRemote : undefined;\n\t\t\t\tbranchName =\n\t\t\t\t\ttracking != null && tracking !== branch.nameWithoutRemote\n\t\t\t\t\t\t? `${branch.name}:${tracking}`\n\t\t\t\t\t\t: branch.name;\n\t\t\t}\n\t\t\tremoteName = branch.remoteName ?? options?.publish?.remote;\n\t\t\tupstreamName = options?.reference == null && options?.publish != null ? branch.name : undefined;\n\n\t\t\t// Git can't setup upstream tracking when publishing a new branch to a specific commit, so we'll need to do it after the push\n\t\t\tif (options?.publish?.remote != null && options?.reference != null) {\n\t\t\t\tsetUpstream = {\n\t\t\t\t\tbranch: branch.nameWithoutRemote,\n\t\t\t\t\tremote: remoteName!,\n\t\t\t\t\tremoteBranch: branch.nameWithoutRemote,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (options?.publish == null && remoteName == null && upstreamName == null) {\n\t\t\tthrow new PushError({ reason: 'other' });\n\t\t}\n\n\t\tlet forceOpts: PushForceOptions | undefined;\n\t\tif (options?.force) {\n\t\t\t// Honor the host's force-push preferences (e.g. VS Code's `git.useForcePushWithLease` /\n\t\t\t// `git.useForcePushIfIncludes`); fall back to the safer `--force-with-lease` behavior.\n\t\t\tconst useForceWithLease = this.context.config?.push?.useForceWithLease ?? true;\n\t\t\tforceOpts = useForceWithLease\n\t\t\t\t? { withLease: true, ifIncludes: this.context.config?.push?.useForceIfIncludes ?? true }\n\t\t\t\t: { withLease: false };\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.pushCore(\n\t\t\t\trepoPath,\n\t\t\t\t{\n\t\t\t\t\tbranch: branchName,\n\t\t\t\t\tremote: remoteName,\n\t\t\t\t\tupstream: upstreamName,\n\t\t\t\t\tforce: forceOpts,\n\t\t\t\t\tpublish: options?.publish != null,\n\t\t\t\t},\n\t\t\t\trunOptions,\n\t\t\t);\n\n\t\t\t// Since Git can't setup upstream tracking when publishing a new branch to a specific commit, do it now.\n\t\t\t// Soft-fail: the push already succeeded, so don't let a local upstream-tracking failure (cancellation\n\t\t\t// arriving mid-spawn, transient git error) suppress the post-push hook fan-out below.\n\t\t\tif (setUpstream != null) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, ...runOptions },\n\t\t\t\t\t\t'branch',\n\t\t\t\t\t\t'--set-upstream-to',\n\t\t\t\t\t\t`${setUpstream.remote}/${setUpstream.remoteBranch}`,\n\t\t\t\t\t\tsetUpstream.branch,\n\t\t\t\t\t);\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tscope?.error(ex, 'Unable to set upstream tracking after publish');\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t} finally {\n\t\t\t// A rejected push may have updated some of its remote-tracking refs before it failed\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(\n\t\t\t\trepoPath,\n\t\t\t\toptions?.publish != null ? ['config', 'heads', 'remotes'] : ['remotes'],\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async pushCore(\n\t\trepoPath: string,\n\t\toptions: {\n\t\t\tbranch?: string;\n\t\t\tforce?: PushForceOptions;\n\t\t\tpublish?: boolean;\n\t\t\tremote?: string;\n\t\t\tupstream?: string;\n\t\t\tdelete?: { remote: string; branch: string };\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['push'];\n\n\t\tif (options.force != null) {\n\t\t\tif (options.force.withLease) {\n\t\t\t\tparams.push('--force-with-lease');\n\t\t\t\tif (options.force.ifIncludes) {\n\t\t\t\t\tif (await this.git.supports('git:push:force-if-includes')) {\n\t\t\t\t\t\tparams.push('--force-if-includes');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams.push('--force');\n\t\t\t}\n\t\t}\n\n\t\tif (options.branch && options.remote) {\n\t\t\tif (options.upstream) {\n\t\t\t\tparams.push('-u', options.remote, `${options.branch}:${options.upstream}`);\n\t\t\t} else if (options.publish) {\n\t\t\t\tparams.push('--set-upstream', options.remote, options.branch);\n\t\t\t} else {\n\t\t\t\tparams.push(options.remote, options.branch);\n\t\t\t}\n\t\t} else if (options.remote) {\n\t\t\tparams.push(options.remote);\n\t\t} else if (options.delete) {\n\t\t\tparams.push(options.delete.remote, `:${options.delete.branch}`);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tconst error = getGitCommandError(\n\t\t\t\t'push',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (options?.force?.withLease && error.details.reason === 'rejected') {\n\t\t\t\tif (ex.stderr && /! \\[rejected\\].*\\(stale info\\)/m.test(ex.stderr)) {\n\t\t\t\t\tthrow new PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: 'rejectedWithLease',\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\toptions.force.ifIncludes &&\n\t\t\t\t\tex.stderr &&\n\t\t\t\t\t/! \\[rejected\\].*\\(remote ref updated since checkout\\)/m.test(ex.stderr)\n\t\t\t\t) {\n\t\t\t\t\tthrow new PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: 'rejectedWithLeaseIfIncludes',\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (ex.stderr && GitErrors.pushRejectedRefDoesNotExists.test(ex.stderr)) {\n\t\t\t\t\tthrow new PushError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: 'rejectedRefDoesNotExist',\n\t\t\t\t\t\t\tbranch: options?.branch || options?.delete?.branch,\n\t\t\t\t\t\t\tremote: options?.remote || options?.delete?.remote,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync rebase(\n\t\trepoPath: string,\n\t\tupstream: string,\n\t\toptions?: {\n\t\t\tautoStash?: boolean;\n\t\t\tbranch?: string;\n\t\t\teditor?: string;\n\t\t\tinteractive?: boolean;\n\t\t\tprogrammaticEditor?: boolean;\n\t\t\tautosquash?: boolean;\n\t\t\tmessageEditor?: string;\n\t\t\tonto?: string;\n\t\t\tupdateRefs?: boolean;\n\t\t\tsource?: unknown;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['rebase'];\n\t\tconst configs: string[] = [];\n\n\t\tif (options?.autoStash !== false) {\n\t\t\targs.push('--autostash');\n\t\t}\n\n\t\tif (options?.interactive) {\n\t\t\targs.push('--interactive');\n\n\t\t\tif (options.editor) {\n\t\t\t\tconfigs.push('-c', `sequence.editor=${options.editor}`);\n\t\t\t}\n\n\t\t\t// A script-based sequence editor rewrites the todo by command word + SHA, so git must emit a\n\t\t\t// plain, natural-order todo regardless of the user's rebase config: `rebase.autosquash` would\n\t\t\t// reorder commits and rewrite `pick`→`fixup`, and `rebase.abbreviateCommands` would emit `p`.\n\t\t\tif (options.programmaticEditor) {\n\t\t\t\tconfigs.push('-c', 'rebase.autosquash=false', '-c', 'rebase.abbreviateCommands=false');\n\t\t\t}\n\t\t}\n\n\t\tif (options?.autosquash != null) {\n\t\t\tif (options.autosquash && options.programmaticEditor) {\n\t\t\t\tthrow new Error(l10n.t('rebase: autosquash cannot be combined with programmaticEditor'));\n\t\t\t}\n\n\t\t\t// `--no-autosquash` is passed explicitly when `false` — omitting the flag would let a\n\t\t\t// `rebase.autosquash=true` git config fold fixups anyway.\n\t\t\targs.push(options.autosquash ? '--autosquash' : '--no-autosquash');\n\t\t}\n\n\t\t// Drive per-commit message editing (the combined message a `squash` produces, or a `reword`).\n\t\t// `GIT_EDITOR` (not `core.editor`) is what git's interactive-rebase backend honors for the `reword`\n\t\t// amend step, so set it on the environment; also set `core.editor` config as a fallback.\n\t\tlet env = runOptions?.env;\n\t\tif (options?.messageEditor) {\n\t\t\tconfigs.push('-c', `core.editor=${options.messageEditor}`);\n\t\t\tenv = { ...env, GIT_EDITOR: options.messageEditor };\n\t\t}\n\n\t\tif (options?.updateRefs === true) {\n\t\t\targs.push('--update-refs');\n\t\t} else if (options?.updateRefs === false) {\n\t\t\targs.push('--no-update-refs');\n\t\t}\n\n\t\tif (options?.onto) {\n\t\t\targs.push('--onto', options.onto);\n\t\t}\n\n\t\targs.push(upstream);\n\n\t\tif (options?.branch) {\n\t\t\targs.push(options.branch);\n\t\t}\n\n\t\t// Fired before the process runs — `git rebase` exits 0 when stopping at `edit`/`break`,\n\t\t// so the result can't be used to detect that a rebase started\n\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'rebase', 'started');\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t// Avoid a timeout since rebases can take a long time (set to 0 to disable)\n\t\t\t\t{ cwd: repoPath, errors: 'throw', configs: configs, timeout: 0, ...runOptions, env: env },\n\t\t\t\t...args,\n\t\t\t);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'rebase',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew RebaseError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\tupstream: upstream,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (RebaseError.is(mapped, 'conflicts')) {\n\t\t\t\treturn await this.createConflictResult(repoPath, 'rebase');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t} finally {\n\t\t\t// The command exited (success, pause, or failure) — any rebase it left behind is on disk now\n\t\t\tthis.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, 'rebase', 'ended');\n\t\t}\n\t}\n\n\t@debug()\n\tasync reset(\n\t\trepoPath: string,\n\t\trev: string,\n\t\toptions?: { mode?: 'hard' | 'keep' | 'merge' | 'mixed' | 'soft' },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tawait this.resetCore(repoPath, rev, options?.mode, runOptions);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate async resetCore(\n\t\trepoPath: string,\n\t\trev: string,\n\t\tmode?: 'hard' | 'keep' | 'merge' | 'mixed' | 'soft',\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['reset', '-q'];\n\t\tif (mode) {\n\t\t\tparams.push(`--${mode}`);\n\t\t}\n\t\tparams.push(rev, '--');\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);\n\t\t} catch (ex) {\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'reset',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew ResetError({ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } }, ex),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync restore(\n\t\trepoPath: string,\n\t\tpath: string | string[],\n\t\toptions?: { ref?: string; side?: 'ours' | 'theirs' },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst paths = Array.isArray(path) ? path : [path];\n\t\tif (!paths.length) return;\n\n\t\tconst scope = getScopedLogger();\n\t\tconst normalized = paths.map(p => splitPath(p, repoPath, true)[0]);\n\n\t\t// `side` and `ref` are mutually exclusive in git (--ours/--theirs apply during conflict\n\t\t// resolution and take no source ref); side takes precedence if both are somehow supplied.\n\t\t// Use a truthy check on `ref` so an empty string falls through to index-restore rather than\n\t\t// producing a malformed `git checkout '' -- …`. Implemented via `checkout` rather than\n\t\t// `git restore` for compatibility with the minimum supported git (2.7.2); `git restore`\n\t\t// only landed in 2.23.\n\t\tconst selector = options?.side != null ? `--${options.side}` : options?.ref || undefined;\n\t\tconst prefix = selector != null ? ['checkout', selector, '--'] : ['checkout', '--'];\n\n\t\ttry {\n\t\t\tif (await this.git.supports('git:checkout:pathspec-from-file')) {\n\t\t\t\t// Git ≥ 2.26: stream all pathspecs via stdin (NUL-separated) in a single invocation —\n\t\t\t\t// no CLI-length limit (so no batching), and robust for paths with spaces/newlines.\n\t\t\t\t// Pathspecs come from the file rather than argv, so `--` isn't used.\n\t\t\t\tconst args = ['checkout'];\n\t\t\t\tif (selector != null) {\n\t\t\t\t\targs.push(selector);\n\t\t\t\t}\n\t\t\t\targs.push('--pathspec-from-file=-', '--pathspec-file-nul');\n\t\t\t\tawait this.git.run(\n\t\t\t\t\t{ cwd: repoPath, errors: 'throw', ...runOptions, stdin: normalized.join('\\0') },\n\t\t\t\t\t...args,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Older git: pass pathspecs as args, one git invocation per chunk (collapsing N\n\t\t\t\t// path-mode checkouts into ⌈N / chunk⌉ spawns). Reserve the command prefix length and\n\t\t\t\t// a per-arg overhead (separator + possible quoting) so the assembled command line\n\t\t\t\t// can't exceed the OS limit even with many short paths.\n\t\t\t\tconst perArgOverhead = 3;\n\t\t\t\tconst prefixLength = prefix.reduce((sum, arg) => sum + arg.length + perArgOverhead, 0);\n\t\t\t\tfor (const batch of chunkByStringLength(normalized, maxGitCliLength - prefixLength, perArgOverhead)) {\n\t\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...prefix, ...batch);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'checkout',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew CheckoutError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\tref: options?.side ?? options?.ref,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: [...prefix, ...normalized] },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@sequentialize({ getQueueKey: rp => rp })\n\t@debug()\n\tasync revert(\n\t\trepoPath: string,\n\t\trefs: string[],\n\t\toptions?: { editMessage?: boolean; source?: unknown },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitOperationResult> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['revert'];\n\n\t\tif (options?.editMessage === true) {\n\t\t\targs.push('--edit');\n\t\t} else if (options?.editMessage === false) {\n\t\t\targs.push('--no-edit');\n\t\t}\n\n\t\targs.push(...refs);\n\n\t\ttry {\n\t\t\tawait this.git.run(\n\t\t\t\t// Avoid a timeout since reverts can take a long time (set to 0 to disable)\n\t\t\t\t{ cwd: repoPath, errors: 'throw', timeout: 0, ...runOptions },\n\t\t\t\t...args,\n\t\t\t);\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tawait this.throwIfSigningError(repoPath, args, ex, options?.source);\n\n\t\t\tconst mapped = getGitCommandError(\n\t\t\t\t'revert',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew RevertError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', refs: refs, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as Error,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (RevertError.is(mapped, 'conflicts')) {\n\t\t\t\treturn this.createConflictResult(repoPath, 'revert');\n\t\t\t}\n\t\t\tthrow mapped;\n\t\t}\n\t}\n\n\t/**\n\t * Classifies `ex` as a signing failure; if so, fires the `commits.onSigningFailed`\n\t * hook and throws a typed {@link SigningError}. Callers should invoke this first\n\t * in their catch blocks, before falling through to command-specific error mapping\n\t * via {@link getGitCommandError}.\n\t *\n\t * `SigningFormat` is read opportunistically from `config.getSigningConfig`, with\n\t * {@link inferSigningFormatFromError} as a stderr-based fallback and `'gpg'` as\n\t * the final default.\n\t */\n\tprivate async throwIfSigningError(\n\t\trepoPath: string,\n\t\targs: readonly (string | undefined)[],\n\t\tex: unknown,\n\t\tsource?: unknown,\n\t): Promise<void> {\n\t\tconst reason = classifySigningError(ex);\n\t\tif (reason == null) return;\n\n\t\tlet format: SigningFormat | undefined;\n\t\ttry {\n\t\t\tformat = (await this.provider.config.getSigningConfig?.(repoPath))?.format;\n\t\t} catch {\n\t\t\t// Fall through — config read failed; use stderr-inferred format or gpg default\n\t\t}\n\t\tformat ??= inferSigningFormatFromError(ex) ?? 'gpg';\n\n\t\tthis.context.hooks?.commits?.onSigningFailed?.(reason, format, source);\n\t\tthrow new SigningError(\n\t\t\t{ reason: reason, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\tex instanceof Error ? ex : undefined,\n\t\t);\n\t}\n\n\tprivate async createConflictResult(repoPath: string, command: GitConflictCommand): Promise<GitOperationResult> {\n\t\tlet conflicts: GitConflictFile[] | undefined;\n\t\ttry {\n\t\t\tconflicts = await this.provider.status.getConflictingFiles(repoPath);\n\t\t} catch (ex) {\n\t\t\t// Don't let a secondary status-read failure mask the original conflict signal\n\t\t\tLogger.warn(`Unable to read conflicting files after ${command}: ${ex}`);\n\t\t}\n\t\t// A conflicted op mutates the working tree, index, and paused-op state — invalidate caches\n\t\t// and fire repository-change the same way the success path does, so downstream views refresh.\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\tthis.context.hooks?.operations?.onConflicted?.(command, conflicts);\n\t\treturn { conflicted: true, conflicts: conflicts };\n\t}\n}\n"],"mappings":"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"}
@@ -3,6 +3,7 @@ import { DiffRange } from "../../../../git/providers/types.js";
3
3
  import { GitRevisionRange } from "../../../../git/models/revision.js";
4
4
  import { GitDiffFilter, GitDiffShortStat } from "../../../../git/models/diff.js";
5
5
  import { GitFile } from "../../../../git/models/file.js";
6
+ import { GitErrorHandling } from "../../../../git/run.types.js";
6
7
  import { Cache } from "../../../../git/cache.js";
7
8
  import { GitDiffSubProvider, NextComparisonUrisResult, PreviousComparisonUrisResult, PreviousRangeComparisonUrisResult } from "../../../../git/providers/diff.js";
8
9
  import { GitHubGitProviderInternal } from "../githubProvider.js";
@@ -15,12 +16,13 @@ export declare class DiffGitSubProvider implements GitDiffSubProvider {
15
16
  uris?: (string | Uri)[];
16
17
  includeUntracked?: boolean;
17
18
  }, _cancellation?: AbortSignal): Promise<GitDiffShortStat | undefined>;
18
- getDiffStatus(repoPath: string, ref1OrRange: string | GitRevisionRange, ref2?: string, _options?: {
19
+ getDiffStatus(repoPath: string, ref1OrRange: string | GitRevisionRange, ref2?: string, options?: {
19
20
  filters?: GitDiffFilter[];
20
21
  includeUntracked?: boolean;
21
22
  path?: string;
22
23
  renameLimit?: number;
23
24
  similarityThreshold?: number;
25
+ errors?: GitErrorHandling;
24
26
  }): Promise<GitFile[] | undefined>;
25
27
  getNextComparisonUris(repoPath: string, pathOrUri: string | Uri, rev: string | undefined, skip?: number, _options?: {
26
28
  ordering?: 'date' | 'author-date' | 'topo' | null;
@@ -54,7 +54,7 @@ var DiffGitSubProvider = class {
54
54
  files: changedFiles
55
55
  };
56
56
  }
57
- async getDiffStatus(repoPath, ref1OrRange, ref2, _options) {
57
+ async getDiffStatus(repoPath, ref1OrRange, ref2, options) {
58
58
  if (repoPath == null) return void 0;
59
59
  const scope = getScopedLogger();
60
60
  const { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);
@@ -95,6 +95,7 @@ var DiffGitSubProvider = class {
95
95
  } catch (ex) {
96
96
  scope?.error(ex);
97
97
  debugger;
98
+ if (options?.errors === "throw") throw ex;
98
99
  return;
99
100
  }
100
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/diff.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitDiffFilter, GitDiffShortStat } from '@gitlens/git/models/diff.js';\nimport type { GitFile } from '@gitlens/git/models/file.js';\nimport { GitFileIndexStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitRevisionRange } from '@gitlens/git/models/revision.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type {\n\tGitDiffSubProvider,\n\tNextComparisonUrisResult,\n\tPreviousComparisonUrisResult,\n\tPreviousRangeComparisonUrisResult,\n} from '@gitlens/git/providers/diff.js';\nimport type { DiffRange, RevisionUri } from '@gitlens/git/providers/types.js';\nimport { getChangedFilesCount } from '@gitlens/git/utils/commit.utils.js';\nimport {\n\tcreateRevisionRange,\n\tgetRevisionRangeParts,\n\tisRevisionRange,\n\tstripOrigin,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { encodeGitLensRevisionUriAuthority } from '@gitlens/git/utils/uriAuthority.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { union } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fromUri } from '@gitlens/utils/uri.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport { fromCommitFileStatus } from '../../models.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nconst slash = 47;\n\nfunction createRevisionUri(repoPath: string, relativePath: string, sha: string | undefined): RevisionUri {\n\t// For virtual repos, the path is the relative path prefixed with /\n\tlet uriPath = relativePath.replace(/\\\\/g, '/');\n\tif (uriPath.charCodeAt(0) !== slash) {\n\t\turiPath = `/${uriPath}`;\n\t}\n\treturn {\n\t\turi: fromUri({\n\t\t\tscheme: 'gitlens',\n\t\t\tauthority: encodeGitLensRevisionUriAuthority({ ref: sha, repoPath: repoPath }),\n\t\t\tpath: uriPath,\n\t\t}),\n\t\tpath: relativePath,\n\t\tsha: sha,\n\t\trepoPath: repoPath,\n\t};\n}\n\nexport class DiffGitSubProvider implements GitDiffSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync getChangedFilesCount(\n\t\trepoPath: string,\n\t\tto?: string,\n\t\tfrom?: string,\n\t\t_options?: { uris?: (string | Uri)[]; includeUntracked?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiffShortStat | undefined> {\n\t\t// Virtual GitHub repos have no working tree, so no working changes can exist.\n\t\t// Without any refs, return empty stats rather than undefined to avoid \"uncertain state\" callers.\n\t\tif (!to && !from) return { additions: 0, deletions: 0, files: 0 };\n\n\t\t// If only `from` is provided, compare against HEAD\n\t\tif (!to) {\n\t\t\tto = 'HEAD';\n\t\t}\n\n\t\tconst commit = await this.provider.commits.getCommit(repoPath, to);\n\t\tif (commit?.stats == null) return undefined;\n\n\t\tconst { stats } = commit;\n\n\t\tconst changedFiles = getChangedFilesCount(stats.files);\n\t\treturn { additions: stats.additions, deletions: stats.deletions, files: changedFiles };\n\t}\n\n\t@debug()\n\tasync getDiffStatus(\n\t\trepoPath: string,\n\t\tref1OrRange: string | GitRevisionRange,\n\t\tref2?: string,\n\t\t_options?: {\n\t\t\tfilters?: GitDiffFilter[];\n\t\t\tincludeUntracked?: boolean;\n\t\t\tpath?: string;\n\t\t\trenameLimit?: number;\n\t\t\tsimilarityThreshold?: number;\n\t\t},\n\t): Promise<GitFile[] | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\tlet range: GitRevisionRange;\n\t\tif (isRevisionRange(ref1OrRange)) {\n\t\t\trange = ref1OrRange;\n\n\t\t\tif (!isRevisionRange(ref1OrRange, 'qualified')) {\n\t\t\t\tconst parts = getRevisionRangeParts(ref1OrRange);\n\t\t\t\trange = createRevisionRange(parts?.left || 'HEAD', parts?.right || 'HEAD', parts?.notation ?? '...');\n\t\t\t}\n\t\t} else {\n\t\t\trange = createRevisionRange(ref1OrRange || 'HEAD', ref2 || 'HEAD', '...');\n\t\t}\n\n\t\tlet range2: GitRevisionRange | undefined;\n\t\t// GitHub doesn't support the `..` range notation, so we will need to do some extra work\n\t\tif (isRevisionRange(range, 'qualified-double-dot')) {\n\t\t\tconst parts = getRevisionRangeParts(range)!;\n\n\t\t\trange = createRevisionRange(parts.left, parts.right, '...');\n\t\t\trange2 = createRevisionRange(parts.right, parts.left, '...');\n\t\t}\n\n\t\ttry {\n\t\t\tconst token = toTokenInfo(this.provider.authenticationProviderId, session);\n\n\t\t\tlet files;\n\t\t\tif (range2) {\n\t\t\t\t// GitHub doesn't support `..`, so issue both `...` comparisons in parallel and union the results.\n\t\t\t\tconst [result1, result2] = await Promise.allSettled([\n\t\t\t\t\tgithub.getComparison(token, metadata.repo.owner, metadata.repo.name, stripOrigin(range)),\n\t\t\t\t\tgithub.getComparison(token, metadata.repo.owner, metadata.repo.name, stripOrigin(range2)),\n\t\t\t\t]);\n\n\t\t\t\tconst files1 = getSettledValue(result1)?.files;\n\t\t\t\tconst files2 = getSettledValue(result2)?.files;\n\n\t\t\t\tfiles = [...new Set(union(files1, files2))];\n\t\t\t} else {\n\t\t\t\tconst result = await github.getComparison(\n\t\t\t\t\ttoken,\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tstripOrigin(range),\n\t\t\t\t);\n\t\t\t\tfiles = result?.files;\n\t\t\t}\n\n\t\t\treturn files?.map(f => ({\n\t\t\t\tpath: f.filename ?? '',\n\t\t\t\toriginalPath: f.previous_filename,\n\t\t\t\tstatus: fromCommitFileStatus(f.status) ?? GitFileIndexStatus.Modified,\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tstats: { additions: f.additions, deletions: f.deletions, changes: f.changes },\n\t\t\t}));\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getNextComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\t_options?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<NextComparisonUrisResult | undefined> {\n\t\t// If we have no revision there is no next commit\n\t\tif (!rev) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst path = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\ttry {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return undefined;\n\n\t\t\tconst { metadata, github, session } = context;\n\t\t\tconst revision = (await metadata.getRevision()).revision;\n\n\t\t\tif (rev === 'HEAD') {\n\t\t\t\trev = revision;\n\t\t\t}\n\n\t\t\tconst refs = await github.getNextCommitRefs(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\trevision,\n\t\t\t\tpath,\n\t\t\t\tstripOrigin(rev),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tcurrent:\n\t\t\t\t\tskip === 0\n\t\t\t\t\t\t? createRevisionUri(repoPath, path, rev)\n\t\t\t\t\t\t: createRevisionUri(repoPath, path, refs[skip - 1]),\n\t\t\t\tnext: refs[skip] != null ? createRevisionUri(repoPath, path, refs[skip]) : undefined,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getPreviousComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\t_unsaved?: boolean,\n\t\t_options?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousComparisonUrisResult | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst path = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\ttry {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return undefined;\n\n\t\t\tconst { metadata, github, session } = context;\n\n\t\t\tconst offset = rev != null ? 1 : 0;\n\n\t\t\tconst result = await github.getCommitRefs(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\tstripOrigin(!rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev),\n\t\t\t\t{\n\t\t\t\t\tpath: path,\n\t\t\t\t\tfirst: offset + skip + 1,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (result == null) return undefined;\n\n\t\t\t// If we are at a commit, diff commit with previous\n\t\t\tconst currentSha = skip === 0 ? rev : (result.values[offset + skip - 1]?.oid ?? deletedOrMissing);\n\n\t\t\tif (currentSha === deletedOrMissing) return undefined;\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(repoPath, path, currentSha),\n\t\t\t\tprevious: createRevisionUri(repoPath, path, result.values[offset + skip]?.oid ?? deletedOrMissing),\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\t// oxlint-disable-next-line typescript/require-await\n\tasync getPreviousComparisonUrisForRange(\n\t\t_repoPath: string,\n\t\t_path: string | Uri,\n\t\t_rev: string | undefined,\n\t\t_range: DiffRange,\n\t\t_options?: { ordering?: 'date' | 'author-date' | 'topo' | null; skipFirstRev?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousRangeComparisonUrisResult | undefined> {\n\t\t// This method requires `getBlameForLine` which depends on VS Code-specific\n\t\t// blame infrastructure. It will be overridden in the extension wrapper.\n\t\treturn undefined;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"diff.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/diff.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitDiffFilter, GitDiffShortStat } from '@gitlens/git/models/diff.js';\nimport type { GitFile } from '@gitlens/git/models/file.js';\nimport { GitFileIndexStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitRevisionRange } from '@gitlens/git/models/revision.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type {\n\tGitDiffSubProvider,\n\tNextComparisonUrisResult,\n\tPreviousComparisonUrisResult,\n\tPreviousRangeComparisonUrisResult,\n} from '@gitlens/git/providers/diff.js';\nimport type { DiffRange, RevisionUri } from '@gitlens/git/providers/types.js';\nimport type { GitErrorHandling } from '@gitlens/git/run.types.js';\nimport { getChangedFilesCount } from '@gitlens/git/utils/commit.utils.js';\nimport {\n\tcreateRevisionRange,\n\tgetRevisionRangeParts,\n\tisRevisionRange,\n\tstripOrigin,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { encodeGitLensRevisionUriAuthority } from '@gitlens/git/utils/uriAuthority.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { union } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fromUri } from '@gitlens/utils/uri.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport { fromCommitFileStatus } from '../../models.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nconst slash = 47;\n\nfunction createRevisionUri(repoPath: string, relativePath: string, sha: string | undefined): RevisionUri {\n\t// For virtual repos, the path is the relative path prefixed with /\n\tlet uriPath = relativePath.replace(/\\\\/g, '/');\n\tif (uriPath.charCodeAt(0) !== slash) {\n\t\turiPath = `/${uriPath}`;\n\t}\n\treturn {\n\t\turi: fromUri({\n\t\t\tscheme: 'gitlens',\n\t\t\tauthority: encodeGitLensRevisionUriAuthority({ ref: sha, repoPath: repoPath }),\n\t\t\tpath: uriPath,\n\t\t}),\n\t\tpath: relativePath,\n\t\tsha: sha,\n\t\trepoPath: repoPath,\n\t};\n}\n\nexport class DiffGitSubProvider implements GitDiffSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync getChangedFilesCount(\n\t\trepoPath: string,\n\t\tto?: string,\n\t\tfrom?: string,\n\t\t_options?: { uris?: (string | Uri)[]; includeUntracked?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitDiffShortStat | undefined> {\n\t\t// Virtual GitHub repos have no working tree, so no working changes can exist.\n\t\t// Without any refs, return empty stats rather than undefined to avoid \"uncertain state\" callers.\n\t\tif (!to && !from) return { additions: 0, deletions: 0, files: 0 };\n\n\t\t// If only `from` is provided, compare against HEAD\n\t\tif (!to) {\n\t\t\tto = 'HEAD';\n\t\t}\n\n\t\tconst commit = await this.provider.commits.getCommit(repoPath, to);\n\t\tif (commit?.stats == null) return undefined;\n\n\t\tconst { stats } = commit;\n\n\t\tconst changedFiles = getChangedFilesCount(stats.files);\n\t\treturn { additions: stats.additions, deletions: stats.deletions, files: changedFiles };\n\t}\n\n\t@debug()\n\tasync getDiffStatus(\n\t\trepoPath: string,\n\t\tref1OrRange: string | GitRevisionRange,\n\t\tref2?: string,\n\t\toptions?: {\n\t\t\tfilters?: GitDiffFilter[];\n\t\t\tincludeUntracked?: boolean;\n\t\t\tpath?: string;\n\t\t\trenameLimit?: number;\n\t\t\tsimilarityThreshold?: number;\n\t\t\terrors?: GitErrorHandling;\n\t\t},\n\t): Promise<GitFile[] | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\tlet range: GitRevisionRange;\n\t\tif (isRevisionRange(ref1OrRange)) {\n\t\t\trange = ref1OrRange;\n\n\t\t\tif (!isRevisionRange(ref1OrRange, 'qualified')) {\n\t\t\t\tconst parts = getRevisionRangeParts(ref1OrRange);\n\t\t\t\trange = createRevisionRange(parts?.left || 'HEAD', parts?.right || 'HEAD', parts?.notation ?? '...');\n\t\t\t}\n\t\t} else {\n\t\t\trange = createRevisionRange(ref1OrRange || 'HEAD', ref2 || 'HEAD', '...');\n\t\t}\n\n\t\tlet range2: GitRevisionRange | undefined;\n\t\t// GitHub doesn't support the `..` range notation, so we will need to do some extra work\n\t\tif (isRevisionRange(range, 'qualified-double-dot')) {\n\t\t\tconst parts = getRevisionRangeParts(range)!;\n\n\t\t\trange = createRevisionRange(parts.left, parts.right, '...');\n\t\t\trange2 = createRevisionRange(parts.right, parts.left, '...');\n\t\t}\n\n\t\ttry {\n\t\t\tconst token = toTokenInfo(this.provider.authenticationProviderId, session);\n\n\t\t\tlet files;\n\t\t\tif (range2) {\n\t\t\t\t// GitHub doesn't support `..`, so issue both `...` comparisons in parallel and union the results.\n\t\t\t\tconst [result1, result2] = await Promise.allSettled([\n\t\t\t\t\tgithub.getComparison(token, metadata.repo.owner, metadata.repo.name, stripOrigin(range)),\n\t\t\t\t\tgithub.getComparison(token, metadata.repo.owner, metadata.repo.name, stripOrigin(range2)),\n\t\t\t\t]);\n\n\t\t\t\tconst files1 = getSettledValue(result1)?.files;\n\t\t\t\tconst files2 = getSettledValue(result2)?.files;\n\n\t\t\t\tfiles = [...new Set(union(files1, files2))];\n\t\t\t} else {\n\t\t\t\tconst result = await github.getComparison(\n\t\t\t\t\ttoken,\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tstripOrigin(range),\n\t\t\t\t);\n\t\t\t\tfiles = result?.files;\n\t\t\t}\n\n\t\t\treturn files?.map(f => ({\n\t\t\t\tpath: f.filename ?? '',\n\t\t\t\toriginalPath: f.previous_filename,\n\t\t\t\tstatus: fromCommitFileStatus(f.status) ?? GitFileIndexStatus.Modified,\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tstats: { additions: f.additions, deletions: f.deletions, changes: f.changes },\n\t\t\t}));\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\tif (options?.errors === 'throw') throw ex;\n\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getNextComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\t_options?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<NextComparisonUrisResult | undefined> {\n\t\t// If we have no revision there is no next commit\n\t\tif (!rev) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst path = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\ttry {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return undefined;\n\n\t\t\tconst { metadata, github, session } = context;\n\t\t\tconst revision = (await metadata.getRevision()).revision;\n\n\t\t\tif (rev === 'HEAD') {\n\t\t\t\trev = revision;\n\t\t\t}\n\n\t\t\tconst refs = await github.getNextCommitRefs(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\trevision,\n\t\t\t\tpath,\n\t\t\t\tstripOrigin(rev),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tcurrent:\n\t\t\t\t\tskip === 0\n\t\t\t\t\t\t? createRevisionUri(repoPath, path, rev)\n\t\t\t\t\t\t: createRevisionUri(repoPath, path, refs[skip - 1]),\n\t\t\t\tnext: refs[skip] != null ? createRevisionUri(repoPath, path, refs[skip]) : undefined,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getPreviousComparisonUris(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev: string | undefined,\n\t\tskip: number = 0,\n\t\t_unsaved?: boolean,\n\t\t_options?: { ordering?: 'date' | 'author-date' | 'topo' | null },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousComparisonUrisResult | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst path = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\ttry {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return undefined;\n\n\t\t\tconst { metadata, github, session } = context;\n\n\t\t\tconst offset = rev != null ? 1 : 0;\n\n\t\t\tconst result = await github.getCommitRefs(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\tstripOrigin(!rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev),\n\t\t\t\t{\n\t\t\t\t\tpath: path,\n\t\t\t\t\tfirst: offset + skip + 1,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (result == null) return undefined;\n\n\t\t\t// If we are at a commit, diff commit with previous\n\t\t\tconst currentSha = skip === 0 ? rev : (result.values[offset + skip - 1]?.oid ?? deletedOrMissing);\n\n\t\t\tif (currentSha === deletedOrMissing) return undefined;\n\n\t\t\treturn {\n\t\t\t\tcurrent: createRevisionUri(repoPath, path, currentSha),\n\t\t\t\tprevious: createRevisionUri(repoPath, path, result.values[offset + skip]?.oid ?? deletedOrMissing),\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\t// oxlint-disable-next-line typescript/require-await\n\tasync getPreviousComparisonUrisForRange(\n\t\t_repoPath: string,\n\t\t_path: string | Uri,\n\t\t_rev: string | undefined,\n\t\t_range: DiffRange,\n\t\t_options?: { ordering?: 'date' | 'author-date' | 'topo' | null; skipFirstRev?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<PreviousRangeComparisonUrisResult | undefined> {\n\t\t// This method requires `getBlameForLine` which depends on VS Code-specific\n\t\t// blame infrastructure. It will be overridden in the extension wrapper.\n\t\treturn undefined;\n\t}\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gitkraken/core-gitlens",
3
3
  "description": "GitLens core — shared Git / AI / GitHub primitives for internal GitKraken consumption",
4
- "version": "0.9.1",
4
+ "version": "0.9.2",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": {
7
7
  "name": "GitKraken",