@gitkraken/core-gitlens 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.md +57 -1
  2. package/dist/git/cache.d.ts +84 -29
  3. package/dist/git/cache.js +188 -54
  4. package/dist/git/cache.js.map +1 -1
  5. package/dist/git/features.d.ts +1 -1
  6. package/dist/git/features.js +4 -0
  7. package/dist/git/features.js.map +1 -1
  8. package/dist/git/models/branch.d.ts +15 -2
  9. package/dist/git/models/branch.js +27 -5
  10. package/dist/git/models/branch.js.map +1 -1
  11. package/dist/git/models/status.js +1 -1
  12. package/dist/git/models/worktree.d.ts +4 -1
  13. package/dist/git/models/worktree.js +4 -2
  14. package/dist/git/models/worktree.js.map +1 -1
  15. package/dist/git/providers/branches.d.ts +73 -8
  16. package/dist/git/providers/pausedOperations.d.ts +6 -0
  17. package/dist/git/providers/provider.d.ts +34 -2
  18. package/dist/git/providers/status.d.ts +8 -2
  19. package/dist/git/remotes/azure-devops.js +61 -53
  20. package/dist/git/remotes/azure-devops.js.map +1 -1
  21. package/dist/git/service.d.ts +8 -5
  22. package/dist/git/service.js +16 -8
  23. package/dist/git/service.js.map +1 -1
  24. package/dist/git/utils/branch.utils.d.ts +8 -1
  25. package/dist/git/utils/branch.utils.js +30 -1
  26. package/dist/git/utils/branch.utils.js.map +1 -1
  27. package/dist/git/watching/changeEvent.d.ts +13 -2
  28. package/dist/git/watching/changeEvent.js +17 -3
  29. package/dist/git/watching/changeEvent.js.map +1 -1
  30. package/dist/git/watching/gitDirPoller.d.ts +111 -0
  31. package/dist/git/watching/gitDirPoller.js +266 -0
  32. package/dist/git/watching/gitDirPoller.js.map +1 -0
  33. package/dist/git/watching/provider.d.ts +16 -0
  34. package/dist/git/watching/watchGroup.d.ts +40 -4
  35. package/dist/git/watching/watchGroup.js +143 -17
  36. package/dist/git/watching/watchGroup.js.map +1 -1
  37. package/dist/git/watching/watchService.d.ts +70 -1
  38. package/dist/git/watching/watchService.js +158 -13
  39. package/dist/git/watching/watchService.js.map +1 -1
  40. package/dist/git/watching/watchSession.d.ts +44 -0
  41. package/dist/git/watching/watchSession.js +91 -6
  42. package/dist/git/watching/watchSession.js.map +1 -1
  43. package/dist/git/watching/watcherPatterns.d.ts +21 -0
  44. package/dist/git/watching/watcherPatterns.js +67 -1
  45. package/dist/git/watching/watcherPatterns.js.map +1 -1
  46. package/dist/git/watching/worktreeSummary.d.ts +34 -7
  47. package/dist/git/watching/worktreeSummary.js +39 -12
  48. package/dist/git/watching/worktreeSummary.js.map +1 -1
  49. package/dist/git-cli/cliGitProvider.d.ts +34 -2
  50. package/dist/git-cli/cliGitProvider.js +119 -17
  51. package/dist/git-cli/cliGitProvider.js.map +1 -1
  52. package/dist/git-cli/exec/commandClassifier.d.ts +15 -0
  53. package/dist/git-cli/exec/commandClassifier.js +48 -2
  54. package/dist/git-cli/exec/commandClassifier.js.map +1 -1
  55. package/dist/git-cli/exec/git.d.ts +15 -3
  56. package/dist/git-cli/exec/git.js +38 -17
  57. package/dist/git-cli/exec/git.js.map +1 -1
  58. package/dist/git-cli/exec/gitQueue.d.ts +2 -0
  59. package/dist/git-cli/exec/gitQueue.js +2 -1
  60. package/dist/git-cli/exec/gitQueue.js.map +1 -1
  61. package/dist/git-cli/exec/indexLock.d.ts +38 -0
  62. package/dist/git-cli/exec/indexLock.js +150 -0
  63. package/dist/git-cli/exec/indexLock.js.map +1 -0
  64. package/dist/git-cli/parsers/worktreeParser.js +42 -2
  65. package/dist/git-cli/parsers/worktreeParser.js.map +1 -1
  66. package/dist/git-cli/providers/branches.d.ts +109 -10
  67. package/dist/git-cli/providers/branches.js +624 -131
  68. package/dist/git-cli/providers/branches.js.map +1 -1
  69. package/dist/git-cli/providers/config.d.ts +9 -5
  70. package/dist/git-cli/providers/config.js +60 -27
  71. package/dist/git-cli/providers/config.js.map +1 -1
  72. package/dist/git-cli/providers/operations.d.ts +17 -0
  73. package/dist/git-cli/providers/operations.js +153 -96
  74. package/dist/git-cli/providers/operations.js.map +1 -1
  75. package/dist/git-cli/providers/pausedOperations.d.ts +8 -0
  76. package/dist/git-cli/providers/pausedOperations.js +60 -40
  77. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  78. package/dist/git-cli/providers/refs.js +11 -8
  79. package/dist/git-cli/providers/refs.js.map +1 -1
  80. package/dist/git-cli/providers/remotes.js +19 -10
  81. package/dist/git-cli/providers/remotes.js.map +1 -1
  82. package/dist/git-cli/providers/staging.js +40 -15
  83. package/dist/git-cli/providers/staging.js.map +1 -1
  84. package/dist/git-cli/providers/stash.d.ts +2 -0
  85. package/dist/git-cli/providers/stash.js +33 -18
  86. package/dist/git-cli/providers/stash.js.map +1 -1
  87. package/dist/git-cli/providers/status.d.ts +3 -1
  88. package/dist/git-cli/providers/status.js +38 -20
  89. package/dist/git-cli/providers/status.js.map +1 -1
  90. package/dist/git-cli/providers/tags.js +6 -4
  91. package/dist/git-cli/providers/tags.js.map +1 -1
  92. package/dist/git-cli/providers/worktrees.d.ts +1 -0
  93. package/dist/git-cli/providers/worktrees.js +60 -31
  94. package/dist/git-cli/providers/worktrees.js.map +1 -1
  95. package/dist/git-cli/service.d.ts +6 -0
  96. package/dist/git-cli/service.js +5 -2
  97. package/dist/git-cli/service.js.map +1 -1
  98. package/dist/ipc/discovery.js +1 -1
  99. package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
  100. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  101. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
  102. package/dist/plus/git-github/providers/github/status.d.ts +3 -1
  103. package/dist/plus/git-github/providers/github/status.js +1 -1
  104. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  105. package/dist/plus/integrations/collectionMetadata.d.ts +13 -2
  106. package/dist/plus/integrations/collectionMetadata.js +14 -2
  107. package/dist/plus/integrations/collectionMetadata.js.map +1 -1
  108. package/dist/plus/integrations/index.d.ts +2 -2
  109. package/dist/plus/integrations/index.js.map +1 -1
  110. package/dist/plus/integrations/integrationService.d.ts +1 -0
  111. package/dist/plus/integrations/integrationService.js +1 -1
  112. package/dist/plus/integrations/integrationService.js.map +1 -1
  113. package/dist/plus/integrations/manager.d.ts +1 -0
  114. package/dist/plus/integrations/models/gitHostIntegration.d.ts +41 -5
  115. package/dist/plus/integrations/models/gitHostIntegration.js +106 -29
  116. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  117. package/dist/plus/integrations/models/issueReads.d.ts +17 -4
  118. package/dist/plus/integrations/providers/apiClients.d.ts +2 -0
  119. package/dist/plus/integrations/providers/apiClients.js +7 -1
  120. package/dist/plus/integrations/providers/apiClients.js.map +1 -1
  121. package/dist/plus/integrations/providers/azure/azure.d.ts +5 -4
  122. package/dist/plus/integrations/providers/azure/azure.js +37 -77
  123. package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
  124. package/dist/plus/integrations/providers/azure/azure.utils.js +20 -17
  125. package/dist/plus/integrations/providers/azure/azure.utils.js.map +1 -1
  126. package/dist/plus/integrations/providers/azure/models.d.ts +2 -2
  127. package/dist/plus/integrations/providers/azure/models.js +4 -4
  128. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  129. package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +18 -14
  130. package/dist/plus/integrations/providers/azure/workItemStateCategories.js +69 -17
  131. package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -1
  132. package/dist/plus/integrations/providers/azureDevOps.d.ts +44 -0
  133. package/dist/plus/integrations/providers/azureDevOps.js +108 -17
  134. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
  135. package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +45 -1
  136. package/dist/plus/integrations/providers/azureDevOpsServer.js +121 -6
  137. package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
  138. package/dist/plus/integrations/providers/jira-server.js +18 -14
  139. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  140. package/dist/plus/integrations/providers/jira.js +18 -14
  141. package/dist/plus/integrations/providers/jira.js.map +1 -1
  142. package/dist/plus/integrations/providers/models.d.ts +1 -2
  143. package/dist/plus/integrations/providers/models.js +9 -2
  144. package/dist/plus/integrations/providers/models.js.map +1 -1
  145. package/dist/plus/integrations/providers/providersApi.d.ts +7 -17
  146. package/dist/plus/integrations/providers/providersApi.js +85 -78
  147. package/dist/plus/integrations/providers/providersApi.js.map +1 -1
  148. package/dist/plus/integrations/providers/utils/jiraIssueDrains.d.ts +22 -0
  149. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js +69 -9
  150. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js.map +1 -1
  151. package/dist/plus/integrations/providers/utils/providerPaging.js +8 -2
  152. package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
  153. package/dist/plus/integrations/reads/filters.d.ts +3 -3
  154. package/dist/plus/integrations/reads/filters.js.map +1 -1
  155. package/dist/plus/integrations/reads/issueBatch.d.ts +2 -1
  156. package/dist/plus/integrations/reads/issueBatch.js +1 -1
  157. package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
  158. package/dist/plus/integrations/reads/issueTracker.js +23 -14
  159. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  160. package/dist/plus/integrations/reads/issues.d.ts +2 -1
  161. package/dist/plus/integrations/reads/issues.js +18 -3
  162. package/dist/plus/integrations/reads/issues.js.map +1 -1
  163. package/dist/plus/integrations/reads/pullRequestBatch.js +1 -1
  164. package/dist/plus/integrations/reads/resolveRepository.js +12 -3
  165. package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
  166. package/dist/plus/integrations/reads/warnings.d.ts +11 -4
  167. package/dist/plus/integrations/reads/warnings.js +15 -5
  168. package/dist/plus/integrations/reads/warnings.js.map +1 -1
  169. package/dist/plus/integrations/results.d.ts +36 -2
  170. package/dist/plus/integrations/results.js +33 -13
  171. package/dist/plus/integrations/results.js.map +1 -1
  172. package/dist/utils/env/node/exec.js +2 -2
  173. package/dist/utils/promiseCache.d.ts +10 -0
  174. package/dist/utils/promiseCache.js +17 -2
  175. package/dist/utils/promiseCache.js.map +1 -1
  176. package/docs/integrations.md +52 -20
  177. package/package.json +2 -2
@@ -3,11 +3,13 @@ import { Logger as _logger } from "../../utils/logger.js";
3
3
  import { getScopedLogger } from "../../utils/logger.scoped.js";
4
4
  import { debug } from "../../utils/decorators/log.js";
5
5
  import { normalizePath, splitPath } from "../../utils/path.js";
6
+ import { getBranchNameAndRemote, getBranchTrackingWithoutRemote } from "../../git/utils/branch.utils.js";
6
7
  import { isBranchReference } from "../../git/utils/reference.utils.js";
7
8
  import __decorate from "../../_virtual/@oxc-project+runtime/helpers/esm/decorate.js";
8
9
  import { CheckoutError, CherryPickError, CommitError, FetchError, MergeError, PullError, PushError, RebaseError, ResetError, RevertError, SigningError } from "../../git/errors.js";
10
+ import { mayWriteTracking } from "../exec/commandClassifier.js";
9
11
  import { GitErrors, classifySigningError, getGitCommandError, gitConfigsPull, inferSigningFormatFromError, maxGitCliLength } from "../exec/git.js";
10
- import { getBranchNameAndRemote, getBranchTrackingWithoutRemote } from "../../git/utils/branch.utils.js";
12
+ import { parseGitBoolean } from "./config.js";
11
13
  import { sequentialize } from "../../utils/decorators/sequentialize.js";
12
14
  import * as l10n from "@vscode/l10n";
13
15
  //#region ../git-cli/src/providers/operations.ts
@@ -16,6 +18,8 @@ var OperationsGitSubProvider = class {
16
18
  git;
17
19
  cache;
18
20
  provider;
21
+ /** The `commonPath\0remote` pairs {@link followRemoteHeads} has handled */
22
+ followedRemoteHeads = /* @__PURE__ */ new Set();
19
23
  constructor(context, git, cache, provider) {
20
24
  this.context = context;
21
25
  this.git = git;
@@ -37,12 +41,6 @@ var OperationsGitSubProvider = class {
37
41
  ...runOptions
38
42
  }, ...params);
39
43
  if (options?.createBranch) this.cache.deleteBaseBranchName(repoPath, options.createBranch);
40
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
41
- this.context.hooks?.repository?.onChanged?.(repoPath, [
42
- "head",
43
- "heads",
44
- "index"
45
- ]);
46
44
  } catch (ex) {
47
45
  scope?.error(ex);
48
46
  throw getGitCommandError("checkout", ex, (reason) => new CheckoutError({
@@ -53,6 +51,8 @@ var OperationsGitSubProvider = class {
53
51
  args: params
54
52
  }
55
53
  }, ex));
54
+ } finally {
55
+ this.announceHeadChanged(repoPath, Boolean(options?.createBranch) && mayWriteTracking(ref, options?.noTracking));
56
56
  }
57
57
  }
58
58
  async cherryPick(repoPath, revs, options, runOptions) {
@@ -72,17 +72,15 @@ var OperationsGitSubProvider = class {
72
72
  }
73
73
  args.push(...revs);
74
74
  try {
75
- await this.git.run({
76
- cwd: repoPath,
77
- errors: "throw",
78
- ...runOptions
79
- }, ...args);
80
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
81
- this.context.hooks?.repository?.onChanged?.(repoPath, [
82
- "head",
83
- "heads",
84
- "index"
85
- ]);
75
+ try {
76
+ await this.git.run({
77
+ cwd: repoPath,
78
+ errors: "throw",
79
+ ...runOptions
80
+ }, ...args);
81
+ } finally {
82
+ this.announceHeadChanged(repoPath);
83
+ }
86
84
  return { conflicted: false };
87
85
  } catch (ex) {
88
86
  scope?.error(ex);
@@ -112,19 +110,17 @@ var OperationsGitSubProvider = class {
112
110
  if (sign) params.push("-S");
113
111
  params.push("-F", "-");
114
112
  try {
115
- await this.git.run({
116
- cwd: repoPath,
117
- stdin: message,
118
- stdinEncoding: "utf8",
119
- errors: "throw",
120
- ...runOptions
121
- }, ...params);
122
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
123
- this.context.hooks?.repository?.onChanged?.(repoPath, [
124
- "head",
125
- "heads",
126
- "index"
127
- ]);
113
+ try {
114
+ await this.git.run({
115
+ cwd: repoPath,
116
+ stdin: message,
117
+ stdinEncoding: "utf8",
118
+ errors: "throw",
119
+ ...runOptions
120
+ }, ...params);
121
+ } finally {
122
+ this.announceHeadChanged(repoPath);
123
+ }
128
124
  if (sign) {
129
125
  let format;
130
126
  try {
@@ -148,6 +144,7 @@ var OperationsGitSubProvider = class {
148
144
  const scope = getScopedLogger();
149
145
  const { branch, ...opts } = options ?? {};
150
146
  let ran = false;
147
+ let fetched;
151
148
  try {
152
149
  if (isBranchReference(branch)) {
153
150
  const [branchName, remoteName] = getBranchNameAndRemote(branch);
@@ -163,6 +160,7 @@ var OperationsGitSubProvider = class {
163
160
  } else {
164
161
  ran = true;
165
162
  await this.fetchCore(repoPath, opts, runOptions);
163
+ if (!opts.refspecs?.length) fetched = opts.remote != null ? { remote: opts.remote } : opts.all ? "all" : "default";
166
164
  }
167
165
  } catch (ex) {
168
166
  scope?.error(ex);
@@ -172,8 +170,46 @@ var OperationsGitSubProvider = class {
172
170
  this.context.hooks?.cache?.onReset?.(repoPath, "branches", "tags");
173
171
  this.context.hooks?.repository?.onChanged?.(repoPath, this.getFetchChanges(branch, options));
174
172
  }
173
+ if (fetched != null) this.followRemoteHeads(repoPath, fetched);
175
174
  }
176
175
  }
176
+ /**
177
+ * Writes the missing `refs/remotes/<remote>/HEAD` (the default branch the base reads) of each remote a fetch just
178
+ * read with its configured refspecs, once per remote, on git < 2.48 — newer git's fetch creates it itself. A bare
179
+ * fetch/pull reads every remote when `fetch.all` is set (git 2.44+), else its default remote. Right after the
180
+ * fetch, so the credentials it used are still cached. Never awaited; never rejects, failures not retried.
181
+ */
182
+ async followRemoteHeads(repoPath, fetched) {
183
+ try {
184
+ if (await this.git.supports("git:fetch:follow-remote-head")) return;
185
+ const commonPath = this.cache.getCommonPath(repoPath);
186
+ const pending = (names) => names.filter((r) => !this.followedRemoteHeads.has(`${commonPath}\0${r}`));
187
+ const config = await this.provider.config.getConfigRegex(repoPath, "^(fetch\\.all|remote\\..+\\.skipfetchall|branch\\..+\\.remote)$");
188
+ if (fetched === "default" && parseGitBoolean(config.get("fetch.all")) && await this.git.supports("git:fetch:all-config")) fetched = "all";
189
+ let remotes;
190
+ if (fetched === "all") remotes = pending((await this.provider.remotes.getRemotes(repoPath)).map((r) => r.name).filter((r) => !parseGitBoolean(config.get(`remote.${r}.skipfetchall`))));
191
+ else if (fetched === "default") {
192
+ const remote = await this.getDefaultFetchRemote(repoPath, config);
193
+ remotes = pending(remote != null ? [remote] : []);
194
+ } else remotes = pending([fetched.remote]);
195
+ if (!remotes.length) return;
196
+ for (const remote of remotes) this.followedRemoteHeads.add(`${commonPath}\0${remote}`);
197
+ for (const remote of remotes) try {
198
+ await this.provider.branches.setRemoteHeadIfMissing(repoPath, remote);
199
+ } catch {}
200
+ } catch {}
201
+ }
202
+ /**
203
+ * The remote a bare `fetch`/`pull` reads: the current branch's `branch.<name>.remote` (none for `.`, the local
204
+ * repository), else the sole remote, else `origin`
205
+ */
206
+ async getDefaultFetchRemote(repoPath, config) {
207
+ const current = await this.provider.branches.getBranch(repoPath);
208
+ const configured = current != null ? config.get(`branch.${current.name}.remote`) : void 0;
209
+ if (configured) return configured === "." ? void 0 : configured;
210
+ const remotes = await this.provider.remotes.getRemotes(repoPath);
211
+ return remotes.length === 1 ? remotes[0].name : "origin";
212
+ }
177
213
  /** `remotes`, plus `heads`/`tags` for any local branch or tag the fetch writes — a `pull` fetch writes `<upstream>:<branch>` */
178
214
  getFetchChanges(branch, options) {
179
215
  if (isBranchReference(branch)) return options?.pull ? ["heads", "remotes"] : ["remotes"];
@@ -234,18 +270,16 @@ var OperationsGitSubProvider = class {
234
270
  if (options?.noCommit) args.push("--no-commit");
235
271
  args.push(ref);
236
272
  try {
237
- await this.git.run({
238
- cwd: repoPath,
239
- errors: "throw",
240
- timeout: 0,
241
- ...runOptions
242
- }, ...args);
243
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
244
- this.context.hooks?.repository?.onChanged?.(repoPath, [
245
- "head",
246
- "heads",
247
- "index"
248
- ]);
273
+ try {
274
+ await this.git.run({
275
+ cwd: repoPath,
276
+ errors: "throw",
277
+ timeout: 0,
278
+ ...runOptions
279
+ }, ...args);
280
+ } finally {
281
+ this.announceHeadChanged(repoPath);
282
+ }
249
283
  return { conflicted: false };
250
284
  } catch (ex) {
251
285
  scope?.error(ex);
@@ -265,6 +299,7 @@ var OperationsGitSubProvider = class {
265
299
  async pull(repoPath, options, runOptions) {
266
300
  const scope = getScopedLogger();
267
301
  let announce;
302
+ let fetched;
268
303
  try {
269
304
  if (isBranchReference(options?.branch)) {
270
305
  const branch = options.branch;
@@ -283,6 +318,10 @@ var OperationsGitSubProvider = class {
283
318
  tags: options?.tags,
284
319
  source: options?.source
285
320
  }, runOptions);
321
+ fetched = {
322
+ repoPath: worktreePath,
323
+ remotes: "default"
324
+ };
286
325
  } finally {
287
326
  this.context.hooks?.operations?.onRebaseCapableOperation?.(worktreePath, "pull", "ended");
288
327
  }
@@ -331,6 +370,10 @@ var OperationsGitSubProvider = class {
331
370
  tags: options?.tags,
332
371
  source: options?.source
333
372
  }, runOptions);
373
+ fetched = {
374
+ repoPath,
375
+ remotes: "default"
376
+ };
334
377
  } finally {
335
378
  this.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, "pull", "ended");
336
379
  }
@@ -339,6 +382,7 @@ var OperationsGitSubProvider = class {
339
382
  throw ex;
340
383
  } finally {
341
384
  announce?.();
385
+ if (fetched != null) this.followRemoteHeads(fetched.repoPath, fetched.remotes);
342
386
  }
343
387
  }
344
388
  announcePull(repoPath) {
@@ -378,6 +422,7 @@ var OperationsGitSubProvider = class {
378
422
  let branchName;
379
423
  let remoteName;
380
424
  let upstreamName;
425
+ let trackUpstream = options?.publish != null;
381
426
  let setUpstream;
382
427
  if (isBranchReference(options?.reference)) {
383
428
  if (options.publish != null) {
@@ -385,6 +430,7 @@ var OperationsGitSubProvider = class {
385
430
  remoteName = options.publish.remote;
386
431
  } else [branchName, remoteName] = getBranchNameAndRemote(options.reference);
387
432
  upstreamName = getBranchTrackingWithoutRemote(options.reference);
433
+ trackUpstream ||= options.reference.upstream?.missing === true;
388
434
  } else {
389
435
  const branch = await this.provider.branches.getBranch(repoPath);
390
436
  if (branch == null) return;
@@ -413,7 +459,7 @@ var OperationsGitSubProvider = class {
413
459
  remote: remoteName,
414
460
  upstream: upstreamName,
415
461
  force: forceOpts,
416
- publish: options?.publish != null
462
+ setUpstream: trackUpstream
417
463
  }, runOptions);
418
464
  if (setUpstream != null) try {
419
465
  await this.git.run({
@@ -428,11 +474,11 @@ var OperationsGitSubProvider = class {
428
474
  throw ex;
429
475
  } finally {
430
476
  this.context.hooks?.cache?.onReset?.(repoPath, "branches");
431
- this.context.hooks?.repository?.onChanged?.(repoPath, options?.publish != null ? [
432
- "config",
433
- "heads",
434
- "remotes"
435
- ] : ["remotes"]);
477
+ const changes = [];
478
+ if (trackUpstream || setUpstream != null) changes.push("config");
479
+ if (options?.publish != null) changes.push("heads");
480
+ changes.push("remotes");
481
+ this.context.hooks?.repository?.onChanged?.(repoPath, changes);
436
482
  }
437
483
  }
438
484
  async pushCore(repoPath, options, runOptions) {
@@ -446,8 +492,10 @@ var OperationsGitSubProvider = class {
446
492
  } else params.push("--force");
447
493
  }
448
494
  if (options.branch && options.remote) {
449
- if (options.upstream) params.push("-u", options.remote, `${options.branch}:${options.upstream}`);
450
- else if (options.publish) params.push("--set-upstream", options.remote, options.branch);
495
+ if (options.upstream) {
496
+ if (options.setUpstream) params.push("-u");
497
+ params.push(options.remote, `${options.branch}:${options.upstream}`);
498
+ } else if (options.setUpstream) params.push("--set-upstream", options.remote, options.branch);
451
499
  else params.push(options.remote, options.branch);
452
500
  } else if (options.remote) params.push(options.remote);
453
501
  else if (options.delete) params.push(options.delete.remote, `:${options.delete.branch}`);
@@ -528,20 +576,18 @@ var OperationsGitSubProvider = class {
528
576
  if (options?.branch) args.push(options.branch);
529
577
  this.context.hooks?.operations?.onRebaseCapableOperation?.(repoPath, "rebase", "started");
530
578
  try {
531
- await this.git.run({
532
- cwd: repoPath,
533
- errors: "throw",
534
- configs,
535
- timeout: 0,
536
- ...runOptions,
537
- env
538
- }, ...args);
539
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
540
- this.context.hooks?.repository?.onChanged?.(repoPath, [
541
- "head",
542
- "heads",
543
- "index"
544
- ]);
579
+ try {
580
+ await this.git.run({
581
+ cwd: repoPath,
582
+ errors: "throw",
583
+ configs,
584
+ timeout: 0,
585
+ ...runOptions,
586
+ env
587
+ }, ...args);
588
+ } finally {
589
+ this.announceHeadChanged(repoPath);
590
+ }
545
591
  return { conflicted: false };
546
592
  } catch (ex) {
547
593
  scope?.error(ex);
@@ -564,15 +610,11 @@ var OperationsGitSubProvider = class {
564
610
  const scope = getScopedLogger();
565
611
  try {
566
612
  await this.resetCore(repoPath, rev, options?.mode, runOptions);
567
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
568
- this.context.hooks?.repository?.onChanged?.(repoPath, [
569
- "head",
570
- "heads",
571
- "index"
572
- ]);
573
613
  } catch (ex) {
574
614
  scope?.error(ex);
575
615
  throw ex;
616
+ } finally {
617
+ this.announceHeadChanged(repoPath);
576
618
  }
577
619
  }
578
620
  async resetCore(repoPath, rev, mode, runOptions) {
@@ -606,11 +648,13 @@ var OperationsGitSubProvider = class {
606
648
  selector,
607
649
  "--"
608
650
  ] : ["checkout", "--"];
651
+ let ran = false;
609
652
  try {
610
653
  if (await this.git.supports("git:checkout:pathspec-from-file")) {
611
654
  const args = ["checkout"];
612
655
  if (selector != null) args.push(selector);
613
656
  args.push("--pathspec-from-file=-", "--pathspec-file-nul");
657
+ ran = true;
614
658
  await this.git.run({
615
659
  cwd: repoPath,
616
660
  errors: "throw",
@@ -620,14 +664,15 @@ var OperationsGitSubProvider = class {
620
664
  } else {
621
665
  const perArgOverhead = 3;
622
666
  const prefixLength = prefix.reduce((sum, arg) => sum + arg.length + perArgOverhead, 0);
623
- for (const batch of chunkByStringLength(normalized, maxGitCliLength - prefixLength, perArgOverhead)) await this.git.run({
624
- cwd: repoPath,
625
- errors: "throw",
626
- ...runOptions
627
- }, ...prefix, ...batch);
667
+ for (const batch of chunkByStringLength(normalized, maxGitCliLength - prefixLength, perArgOverhead)) {
668
+ ran = true;
669
+ await this.git.run({
670
+ cwd: repoPath,
671
+ errors: "throw",
672
+ ...runOptions
673
+ }, ...prefix, ...batch);
674
+ }
628
675
  }
629
- this.context.hooks?.cache?.onReset?.(repoPath, "status");
630
- this.context.hooks?.repository?.onChanged?.(repoPath, ["index"]);
631
676
  } catch (ex) {
632
677
  scope?.error(ex);
633
678
  throw getGitCommandError("checkout", ex, (reason) => new CheckoutError({
@@ -638,6 +683,11 @@ var OperationsGitSubProvider = class {
638
683
  args: [...prefix, ...normalized]
639
684
  }
640
685
  }, ex));
686
+ } finally {
687
+ if (ran) {
688
+ this.context.hooks?.cache?.onReset?.(repoPath, "status");
689
+ this.context.hooks?.repository?.onChanged?.(repoPath, ["index"]);
690
+ }
641
691
  }
642
692
  }
643
693
  async revert(repoPath, refs, options, runOptions) {
@@ -647,18 +697,16 @@ var OperationsGitSubProvider = class {
647
697
  else if (options?.editMessage === false) args.push("--no-edit");
648
698
  args.push(...refs);
649
699
  try {
650
- await this.git.run({
651
- cwd: repoPath,
652
- errors: "throw",
653
- timeout: 0,
654
- ...runOptions
655
- }, ...args);
656
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
657
- this.context.hooks?.repository?.onChanged?.(repoPath, [
658
- "head",
659
- "heads",
660
- "index"
661
- ]);
700
+ try {
701
+ await this.git.run({
702
+ cwd: repoPath,
703
+ errors: "throw",
704
+ timeout: 0,
705
+ ...runOptions
706
+ }, ...args);
707
+ } finally {
708
+ this.announceHeadChanged(repoPath);
709
+ }
662
710
  return { conflicted: false };
663
711
  } catch (ex) {
664
712
  scope?.error(ex);
@@ -702,6 +750,21 @@ var OperationsGitSubProvider = class {
702
750
  }
703
751
  }, ex instanceof Error ? ex : void 0);
704
752
  }
753
+ /** Called once git has run, success or not — a rejected write can still have moved HEAD or left state behind */
754
+ announceHeadChanged(repoPath, wroteTracking) {
755
+ this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
756
+ this.context.hooks?.repository?.onChanged?.(repoPath, wroteTracking ? [
757
+ "config",
758
+ "head",
759
+ "heads",
760
+ "index"
761
+ ] : [
762
+ "head",
763
+ "heads",
764
+ "index"
765
+ ]);
766
+ }
767
+ /** The caller has already announced the change — the conflict is what the failed run left behind */
705
768
  async createConflictResult(repoPath, command) {
706
769
  let conflicts;
707
770
  try {
@@ -709,12 +772,6 @@ var OperationsGitSubProvider = class {
709
772
  } catch (ex) {
710
773
  _logger.warn(`Unable to read conflicting files after ${command}: ${ex}`);
711
774
  }
712
- this.context.hooks?.cache?.onReset?.(repoPath, "branches", "status");
713
- this.context.hooks?.repository?.onChanged?.(repoPath, [
714
- "head",
715
- "heads",
716
- "index"
717
- ]);
718
775
  this.context.hooks?.operations?.onConflicted?.(command, conflicts);
719
776
  return {
720
777
  conflicted: true,