@gitkraken/core-gitlens 0.9.8 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/dist/git/errors.d.ts +7 -0
  3. package/dist/git/errors.js +14 -1
  4. package/dist/git/errors.js.map +1 -1
  5. package/dist/git/providers/status.d.ts +6 -1
  6. package/dist/git/run.types.d.ts +9 -4
  7. package/dist/git-cli/exec/git.js +36 -16
  8. package/dist/git-cli/exec/git.js.map +1 -1
  9. package/dist/git-cli/providers/diff.d.ts +5 -2
  10. package/dist/git-cli/providers/diff.js +21 -9
  11. package/dist/git-cli/providers/diff.js.map +1 -1
  12. package/dist/git-cli/providers/patch.js +5 -7
  13. package/dist/git-cli/providers/patch.js.map +1 -1
  14. package/dist/git-cli/providers/status.d.ts +0 -1
  15. package/dist/git-cli/providers/status.js +119 -142
  16. package/dist/git-cli/providers/status.js.map +1 -1
  17. package/dist/plus/git-github/providers/github/status.d.ts +0 -1
  18. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  19. package/dist/plus/integrations/collectionMetadata.d.ts +7 -0
  20. package/dist/plus/integrations/collectionMetadata.js +11 -1
  21. package/dist/plus/integrations/collectionMetadata.js.map +1 -1
  22. package/dist/plus/integrations/models/issueReads.d.ts +5 -0
  23. package/dist/plus/integrations/models/issuesIntegration.d.ts +37 -1
  24. package/dist/plus/integrations/models/issuesIntegration.js +118 -2
  25. package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
  26. package/dist/plus/integrations/providers/jira-server.d.ts +8 -1
  27. package/dist/plus/integrations/providers/jira-server.js +90 -138
  28. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  29. package/dist/plus/integrations/providers/jira.d.ts +11 -1
  30. package/dist/plus/integrations/providers/jira.js +88 -122
  31. package/dist/plus/integrations/providers/jira.js.map +1 -1
  32. package/dist/plus/integrations/providers/linear.d.ts +22 -1
  33. package/dist/plus/integrations/providers/linear.js +84 -35
  34. package/dist/plus/integrations/providers/linear.js.map +1 -1
  35. package/dist/plus/integrations/providers/models.d.ts +5 -9
  36. package/dist/plus/integrations/providers/models.js.map +1 -1
  37. package/dist/plus/integrations/providers/providersApi.d.ts +24 -3
  38. package/dist/plus/integrations/providers/providersApi.js +56 -4
  39. package/dist/plus/integrations/providers/providersApi.js.map +1 -1
  40. package/dist/plus/integrations/providers/utils/jiraIssueDrains.d.ts +86 -0
  41. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js +139 -0
  42. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js.map +1 -0
  43. package/dist/plus/integrations/reads/issueTracker.js +20 -9
  44. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  45. package/dist/utils/cancellation.d.ts +4 -1
  46. package/dist/utils/cancellation.js +4 -2
  47. package/dist/utils/cancellation.js.map +1 -1
  48. package/dist/utils/env/node/exec.d.ts +5 -1
  49. package/dist/utils/env/node/exec.js +8 -5
  50. package/dist/utils/env/node/exec.js.map +1 -1
  51. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { isCancellationError, raceWithTimeout } from "../../utils/cancellation.js";
1
+ import { raceWithTimeout } from "../../utils/cancellation.js";
2
2
  import { iterateByDelimiter } from "../../utils/string.js";
3
3
  import { getScopedLogger } from "../../utils/logger.scoped.js";
4
4
  import { getSettledValue } from "../../utils/promise.js";
@@ -8,7 +8,7 @@ import { normalizePath, splitPath, stripFolderGlob } from "../../utils/path.js";
8
8
  import { PromiseMap } from "../../utils/promiseCache.js";
9
9
  import __decorate from "../../_virtual/@oxc-project+runtime/helpers/esm/decorate.js";
10
10
  import { createDisposable } from "../../utils/disposable.js";
11
- import { gitConfigsStatus } from "../exec/git.js";
11
+ import { GitErrors, defaultExceptionHandler, gitConfigsStatus } from "../exec/git.js";
12
12
  import { GitFileWorkingTreeStatus } from "../../git/models/fileStatus.js";
13
13
  import _usingCtx from "../../_virtual/@oxc-project+runtime/helpers/esm/usingCtx.js";
14
14
  import { parseGitConflictFiles } from "../parsers/indexParser.js";
@@ -98,7 +98,8 @@ var StatusGitSubProvider = class {
98
98
  priority: options?.priority,
99
99
  correlationKey: options?.correlationKey,
100
100
  untracked: options?.untracked,
101
- branch: options?.branch
101
+ branch: options?.branch,
102
+ errors: "throw"
102
103
  }, cancellation);
103
104
  const status = parseGitStatus(result.stdout, repoPath, porcelainVersion);
104
105
  if (options?.branch === false) {
@@ -126,7 +127,9 @@ var StatusGitSubProvider = class {
126
127
  async getStatusForPathCore(repoPath, pathOrUri, options, cancellation) {
127
128
  const relativePath = stripFolderGlob(splitPath(pathOrUri, repoPath)[0]);
128
129
  if (options.renames !== false) {
129
- const status = await this.getStatus(repoPath, void 0, cancellation);
130
+ const status = await this.getStatus(repoPath, void 0, cancellation).catch((ex) => {
131
+ defaultExceptionHandler(ex, repoPath);
132
+ });
130
133
  if (status == null) return void 0;
131
134
  if (options.exact) {
132
135
  const file = status.files.find((f) => f.path === relativePath);
@@ -155,6 +158,7 @@ var StatusGitSubProvider = class {
155
158
  configs: gitConfigsStatus,
156
159
  env: { GIT_OPTIONAL_LOCKS: "0" },
157
160
  correlationKey: options?.correlationKey,
161
+ ...options?.errors != null ? { errors: options.errors } : void 0,
158
162
  ...options?.priority != null ? { priority: options.priority } : void 0
159
163
  }, ...params, "--", ...pathspecs);
160
164
  }
@@ -163,179 +167,152 @@ var StatusGitSubProvider = class {
163
167
  const staged = options?.staged ?? true;
164
168
  const unstaged = options?.unstaged ?? true;
165
169
  const untracked = options?.untracked ?? true;
166
- const throwOnError = options?.throwOnError ?? false;
167
170
  const priority = options?.priority ?? "default";
168
- return this.dedupeByStatusGeneration(repoPath, `hasWorkingChanges:${staged}:${unstaged}:${untracked}:${throwOnError}:${priority}`, async (correlationKey, signal) => {
169
- try {
170
- if (staged || unstaged) {
171
- if ((await this.git.run({
172
- cwd: repoPath,
173
- cancellation: signal,
174
- errors: "ignore",
175
- correlationKey,
176
- ...options?.priority != null ? { priority: options.priority } : void 0
177
- }, "diff", "--quiet", staged && unstaged ? "HEAD" : staged ? "--staged" : void 0)).exitCode === 1) {
178
- if (staged && unstaged) scope?.addExitInfo("has staged and unstaged changes");
179
- else if (staged) scope?.addExitInfo("has staged changes");
180
- else scope?.addExitInfo("has unstaged changes");
181
- return true;
182
- }
171
+ return this.dedupeByStatusGeneration(repoPath, `hasWorkingChanges:${staged}:${unstaged}:${untracked}:${priority}`, async (correlationKey, signal) => {
172
+ if (staged || unstaged) {
173
+ const diffQuiet = (revision) => this.git.run({
174
+ cwd: repoPath,
175
+ cancellation: signal,
176
+ errors: "throw",
177
+ expectedExitCodes: [1],
178
+ correlationKey,
179
+ ...options?.priority != null ? { priority: options.priority } : void 0
180
+ }, "diff", "--quiet", revision, "--");
181
+ let result;
182
+ if (staged && unstaged) try {
183
+ result = await diffQuiet("HEAD");
184
+ } catch (ex) {
185
+ if (GitErrors.badRevision.exec(String(ex))?.[1]?.toUpperCase() !== "HEAD") throw ex;
186
+ result = await diffQuiet(await this.provider.revision.getEmptyTreeSha(repoPath));
183
187
  }
184
- if (untracked) {
185
- if (await this.hasUntrackedFiles(repoPath, signal)) {
186
- scope?.addExitInfo("has untracked files");
187
- return true;
188
- }
188
+ else result = await diffQuiet(staged ? "--staged" : void 0);
189
+ if (result.exitCode === 1) {
190
+ if (staged && unstaged) scope?.addExitInfo("has staged and unstaged changes");
191
+ else if (staged) scope?.addExitInfo("has staged changes");
192
+ else scope?.addExitInfo("has unstaged changes");
193
+ return true;
189
194
  }
190
- scope?.addExitInfo("no working changes");
191
- return false;
192
- } catch (ex) {
193
- if (isCancellationError(ex)) throw ex;
194
- scope?.error(ex);
195
- scope?.addExitInfo("error checking for changes");
196
- if (throwOnError) throw ex;
197
- return false;
198
195
  }
196
+ if (untracked) {
197
+ if (await this.hasUntrackedFiles(repoPath, signal)) {
198
+ scope?.addExitInfo("has untracked files");
199
+ return true;
200
+ }
201
+ }
202
+ scope?.addExitInfo("no working changes");
203
+ return false;
199
204
  }, cancellation);
200
205
  }
201
206
  getWorkingChangesState(repoPath, cancellation) {
202
207
  const scope = getScopedLogger();
203
208
  return this.dedupeByStatusGeneration(repoPath, "getWorkingChangesState", async (correlationKey, signal) => {
204
- try {
205
- const [stagedResult, unstagedResult, untrackedResult] = await Promise.allSettled([
206
- this.git.run({
207
- cwd: repoPath,
208
- cancellation: signal,
209
- errors: "ignore",
210
- correlationKey
211
- }, "diff", "--quiet", "--staged"),
212
- this.git.run({
213
- cwd: repoPath,
214
- cancellation: signal,
215
- errors: "ignore",
216
- correlationKey
217
- }, "diff", "--quiet"),
218
- this.hasUntrackedFiles(repoPath, signal)
219
- ]);
220
- const result = {
221
- staged: getSettledValue(stagedResult)?.exitCode === 1,
222
- unstaged: getSettledValue(unstagedResult)?.exitCode === 1,
223
- untracked: getSettledValue(untrackedResult) === true
224
- };
225
- scope?.addExitInfo(result.staged || result.unstaged || result.untracked ? `has ${result.staged ? "staged" : ""}${result.unstaged ? result.staged ? ", unstaged" : "unstaged " : ""}${result.untracked ? result.staged || result.unstaged ? ", untracked" : "untracked" : ""} changes` : "no working changes");
226
- return result;
227
- } catch (ex) {
228
- if (isCancellationError(ex)) throw ex;
229
- scope?.error(ex);
230
- scope?.addExitInfo("error checking for changes");
231
- return {
232
- staged: false,
233
- unstaged: false,
234
- untracked: false
235
- };
236
- }
209
+ const [stagedResult, unstagedResult, untrackedResult] = await Promise.allSettled([
210
+ this.git.run({
211
+ cwd: repoPath,
212
+ cancellation: signal,
213
+ errors: "throw",
214
+ expectedExitCodes: [1],
215
+ correlationKey
216
+ }, "diff", "--quiet", "--staged"),
217
+ this.git.run({
218
+ cwd: repoPath,
219
+ cancellation: signal,
220
+ errors: "throw",
221
+ expectedExitCodes: [1],
222
+ correlationKey
223
+ }, "diff", "--quiet"),
224
+ this.hasUntrackedFiles(repoPath, signal)
225
+ ]);
226
+ for (const settled of [
227
+ stagedResult,
228
+ unstagedResult,
229
+ untrackedResult
230
+ ]) if (settled.status === "rejected") throw settled.reason;
231
+ const result = {
232
+ staged: getSettledValue(stagedResult)?.exitCode === 1,
233
+ unstaged: getSettledValue(unstagedResult)?.exitCode === 1,
234
+ untracked: getSettledValue(untrackedResult) === true
235
+ };
236
+ scope?.addExitInfo(result.staged || result.unstaged || result.untracked ? `has ${result.staged ? "staged" : ""}${result.unstaged ? result.staged ? ", unstaged" : "unstaged " : ""}${result.untracked ? result.staged || result.unstaged ? ", untracked" : "untracked" : ""} changes` : "no working changes");
237
+ return result;
237
238
  }, cancellation);
238
239
  }
239
240
  hasConflictingFiles(repoPath, cancellation) {
240
241
  return this.dedupeByStatusGeneration(repoPath, "hasConflictingFiles", async (_correlationKey, signal) => {
241
242
  try {
242
- try {
243
- var _usingCtx$1 = _usingCtx();
244
- const stream = this.git.stream({
245
- cwd: repoPath,
246
- cancellation: signal
247
- }, "ls-files", "--unmerged");
248
- _usingCtx$1.u(createDisposable(() => void stream.return?.(void 0)));
249
- for await (const _chunk of stream) return true;
250
- return false;
251
- } catch (_) {
252
- _usingCtx$1.e = _;
253
- } finally {
254
- _usingCtx$1.d();
255
- }
256
- } catch (ex) {
257
- if (isCancellationError(ex)) throw ex;
243
+ var _usingCtx$1 = _usingCtx();
244
+ const stream = this.git.stream({
245
+ cwd: repoPath,
246
+ cancellation: signal
247
+ }, "ls-files", "--unmerged");
248
+ _usingCtx$1.u(createDisposable(() => void stream.return?.(void 0)));
249
+ for await (const _chunk of stream) return true;
258
250
  return false;
251
+ } catch (_) {
252
+ _usingCtx$1.e = _;
253
+ } finally {
254
+ _usingCtx$1.d();
259
255
  }
260
256
  }, cancellation);
261
257
  }
262
258
  getConflictingFiles(repoPath, cancellation) {
263
259
  const scope = getScopedLogger();
264
260
  return this.dedupeByStatusGeneration(repoPath, "getConflictingFiles", async (correlationKey, signal) => {
265
- try {
266
- const result = await this.git.run({
267
- cwd: repoPath,
268
- cancellation: signal,
269
- errors: "ignore",
270
- correlationKey
271
- }, "ls-files", "-z", "--unmerged");
272
- if (!result.stdout) {
273
- scope?.addExitInfo("no conflicting files");
274
- return [];
275
- }
276
- const files = parseGitConflictFiles(result.stdout, repoPath);
277
- scope?.addExitInfo(`${String(files.length)} conflicting file(s)`);
278
- return files;
279
- } catch (ex) {
280
- if (isCancellationError(ex)) throw ex;
281
- scope?.error(ex);
282
- scope?.addExitInfo("error getting conflicting files");
261
+ const result = await this.git.run({
262
+ cwd: repoPath,
263
+ cancellation: signal,
264
+ errors: "throw",
265
+ correlationKey
266
+ }, "ls-files", "-z", "--unmerged");
267
+ if (!result.stdout) {
268
+ scope?.addExitInfo("no conflicting files");
283
269
  return [];
284
270
  }
271
+ const files = parseGitConflictFiles(result.stdout, repoPath);
272
+ scope?.addExitInfo(`${String(files.length)} conflicting file(s)`);
273
+ return files;
285
274
  }, cancellation);
286
275
  }
287
276
  async hasUntrackedFiles(repoPath, cancellation) {
288
277
  try {
289
- try {
290
- var _usingCtx3 = _usingCtx();
291
- const stream = this.git.stream({
292
- cwd: repoPath,
293
- cancellation
294
- }, "ls-files", "--others", "--exclude-standard");
295
- _usingCtx3.u(createDisposable(() => void stream.return?.(void 0)));
296
- for await (const _chunk of stream) return true;
297
- return false;
298
- } catch (_) {
299
- _usingCtx3.e = _;
300
- } finally {
301
- _usingCtx3.d();
302
- }
303
- } catch (ex) {
304
- if (isCancellationError(ex)) throw ex;
278
+ var _usingCtx3 = _usingCtx();
279
+ const stream = this.git.stream({
280
+ cwd: repoPath,
281
+ cancellation
282
+ }, "ls-files", "--others", "--exclude-standard");
283
+ _usingCtx3.u(createDisposable(() => void stream.return?.(void 0)));
284
+ for await (const _chunk of stream) return true;
305
285
  return false;
286
+ } catch (_) {
287
+ _usingCtx3.e = _;
288
+ } finally {
289
+ _usingCtx3.d();
306
290
  }
307
291
  }
308
292
  getUntrackedFiles(repoPath, cancellation) {
309
293
  const scope = getScopedLogger();
310
294
  return this.dedupeByStatusGeneration(repoPath, "getUntrackedFiles", async (correlationKey, signal) => {
311
- try {
312
- const result = await this.git.run({
313
- cwd: repoPath,
314
- cancellation: signal,
315
- errors: "ignore",
316
- correlationKey
317
- }, "ls-files", "-z", "--others", "--exclude-standard");
318
- if (!result.stdout) {
319
- scope?.addExitInfo("no untracked files");
320
- return [];
321
- }
322
- const files = [];
323
- for (const line of iterateByDelimiter(result.stdout, "\0")) {
324
- if (!line.length) continue;
325
- files.push({
326
- path: line,
327
- repoPath,
328
- status: GitFileWorkingTreeStatus.Untracked
329
- });
330
- }
331
- scope?.addExitInfo(`${String(files.length)} untracked file(s)`);
332
- return files;
333
- } catch (ex) {
334
- if (isCancellationError(ex)) throw ex;
335
- scope?.error(ex);
336
- scope?.addExitInfo("error getting untracked files");
295
+ const result = await this.git.run({
296
+ cwd: repoPath,
297
+ cancellation: signal,
298
+ errors: "throw",
299
+ correlationKey
300
+ }, "ls-files", "-z", "--others", "--exclude-standard");
301
+ if (!result.stdout) {
302
+ scope?.addExitInfo("no untracked files");
337
303
  return [];
338
304
  }
305
+ const files = [];
306
+ for (const line of iterateByDelimiter(result.stdout, "\0")) {
307
+ if (!line.length) continue;
308
+ files.push({
309
+ path: line,
310
+ repoPath,
311
+ status: GitFileWorkingTreeStatus.Untracked
312
+ });
313
+ }
314
+ scope?.addExitInfo(`${String(files.length)} untracked file(s)`);
315
+ return files;
339
316
  }, cancellation);
340
317
  }
341
318
  };
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","names":[],"sources":["../../../../git-cli/src/providers/status.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitFile } from '@gitlens/git/models/file.js';\nimport { GitFileWorkingTreeStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitConflictFile } from '@gitlens/git/models/staging.js';\nimport { GitStatus } from '@gitlens/git/models/status.js';\nimport type { GitStatusFile } from '@gitlens/git/models/statusFile.js';\nimport type { GitStatusSubProvider, GitWorkingChangesState } from '@gitlens/git/providers/status.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { isCancellationError, raceWithTimeout } from '@gitlens/utils/cancellation.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { createDisposable } from '@gitlens/utils/disposable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { normalizePath, splitPath, stripFolderGlob } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport { PromiseMap } from '@gitlens/utils/promiseCache.js';\nimport { iterateByDelimiter } from '@gitlens/utils/string.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { 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 { gitConfigsStatus } from '../exec/git.js';\nimport { parseGitConflictFiles } from '../parsers/indexParser.js';\nimport { parseGitStatus } from '../parsers/statusParser.js';\n\n/** Backstop when `advanced.git.timeout` is disabled (0). Independent of the command timeout so disabling it can't\n * also disable deadlock recovery — mirrors `@gate`'s always-on 5-min force-clear. */\nconst disabledTimeoutBackstopMs = 1000 * 60 * 5;\n\n/**\n * Deadlock-backstop duration for a status read (see `dedupeByStatusGeneration`), exported for testing.\n * Always returns a value so a wedged read recovers even with `advanced.git.timeout` disabled (which bounds git\n * *commands*, not deadlock recovery). With a timeout set, `gitTimeout * 2` sits above the per-command timeout so\n * `git.run` reads reject at their own timeout first; the backstop's real job is bounding the timeout-less\n * `git.stream` reads (`hasUntrackedFiles`/`hasConflictingFiles`).\n */\nexport function computeDeadlockBackstopMs(gitTimeout: number | undefined): number {\n\tconst timeout = gitTimeout ?? 60000;\n\treturn timeout > 0 ? timeout * 2 : disabledTimeoutBackstopMs;\n}\n\n/**\n * A non-default `untracked`/`branch` gets its own key, so a full-status caller never joins a narrower run; the\n * default stays `'getStatus'`, which `getStatusForPathCore`'s rename path joins.\n */\nfunction getStatusReadKey(options?: { untracked?: 'no' | 'normal' | 'all'; branch?: false }): string {\n\tif (options?.untracked == null && options?.branch !== false) return 'getStatus';\n\n\tconst parts: string[] = [];\n\tif (options?.untracked != null) {\n\t\tparts.push(`untracked=${options.untracked}`);\n\t}\n\tif (options?.branch === false) {\n\t\tparts.push('branch=false');\n\t}\n\treturn `getStatus:${parts.join(':')}`;\n}\n\nexport class StatusGitSubProvider implements GitStatusSubProvider {\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/** In-flight reads, keyed by `<read>\\0<repoPath>\\0<generation>`. `PromiseMap` (not a bare Map) so joiners\n\t * get per-caller cancellation: the shared run aborts only when ALL current callers do. */\n\tprivate readonly _pendingReads = new PromiseMap<string, unknown>();\n\n\t/**\n\t * Single-flight for point-in-time reads of mutable working-tree state — replaces `@gate`, which dedups on\n\t * repoPath with no notion of *when* a run started and so joins a pre-change read to a post-change caller\n\t * (see {@link Cache.getStatusGeneration}). Same-generation callers share one run (via a `PromiseMap`, so a\n\t * joiner cancelling can't reject the others); a caller in a newer generation gets a different key and a\n\t * fresh run; a `force` read advances the clock first, so it fences every later reader too, not just itself.\n\t * The exec-layer command dedup (`Git.pendingCommands`) is fenced automatically: each run carries this entry's\n\t * aggregate signal, whose id is part of the exec cache key, so a newer-generation run never joins an older\n\t * one's process; the generation-derived `correlationKey` is a readable second guard on that key. A `raceWithTimeout` backstop (scaled to `advanced.git.timeout`, see\n\t * {@link computeDeadlockBackstopMs}) replaces `@gate`'s 5-min force-clear so a never-settling read (a hung\n\t * `git.stream`, which has no per-command timeout) can't wedge same-generation callers — including blocking\n\t * awaiters like the commit flow — indefinitely.\n\t */\n\tprivate dedupeByStatusGeneration<T>(\n\t\trepoPath: string,\n\t\tread: string,\n\t\trun: (correlationKey: string, signal: AbortSignal | undefined) => Promise<T>,\n\t\tcancellation?: AbortSignal,\n\t\tforce?: boolean,\n\t): Promise<T> {\n\t\t// A `force` (user refresh) read is the user asserting the working tree may have changed without the watcher\n\t\t// observing it — the same class of event as a watcher tick, so it ADVANCES the clock rather than carving out\n\t\t// a private key for itself. A one-shot nonce would fence only this caller: the pre-assertion run stays\n\t\t// joinable, so the very next ordinary reader still picks up pre-change content — and, stamped with a newer\n\t\t// `Wip.revision` (assigned at producer start, not read start), applies it right back over the refreshed\n\t\t// result. Advancing is also CHEAPER than a nonce: concurrent readers join the one fresh read instead of each\n\t\t// spawning a private one.\n\t\tif (force) {\n\t\t\tthis.cache.incrementStatusGeneration(repoPath);\n\t\t}\n\t\tconst generation = this.cache.getStatusGeneration(repoPath);\n\t\t// `\\0` separators: `read`/`repoPath` are free-form (paths can contain `:`), so a printable delimiter could\n\t\t// collide (`getStatusForPath:/a:x` vs `getStatusForPath:/a` + `:x`).\n\t\tconst key = `${read}\\0${repoPath}\\0${generation}`;\n\t\tconst correlationKey = `status:${generation}`;\n\t\tconst backstopMs = computeDeadlockBackstopMs(this.git.options.gitTimeout);\n\n\t\treturn this._pendingReads.getOrCreate(\n\t\t\tkey,\n\t\t\t(cacheable, signal) => {\n\t\t\t\t// Point-in-time read: never memoize a settled value. `invalidate()` at the start makes the entry\n\t\t\t\t// self-evict on settle, so a later caller in this same generation re-reads (a newer generation\n\t\t\t\t// already gets a different key). `signal` is the aggregate — the run aborts only if every caller\n\t\t\t\t// cancels, so one caller's abort can't reject the others. The backstop rejects a wedged read so\n\t\t\t\t// waiters unblock and the entry self-evicts; it ALSO aborts the underlying git op (via `backstop`\n\t\t\t\t// linked into the run's signal) so a wedged read releases its GitQueue slot/process rather than\n\t\t\t\t// running orphaned — best-effort, since a truly-stuck process may ignore the abort.\n\t\t\t\tcacheable.invalidate();\n\t\t\t\tconst backstop = new AbortController();\n\t\t\t\tconst runSignal = signal != null ? AbortSignal.any([signal, backstop.signal]) : backstop.signal;\n\t\t\t\treturn raceWithTimeout(run(correlationKey, runSignal), backstopMs, backstop);\n\t\t\t},\n\t\t\tcancellation,\n\t\t) as Promise<T>;\n\t}\n\n\t@debug()\n\tgetStatus(\n\t\trepoPath: string | undefined,\n\t\toptions?: {\n\t\t\tpriority?: GitCommandPriority;\n\t\t\tforce?: boolean;\n\t\t\tuntracked?: 'no' | 'normal' | 'all';\n\t\t\tbranch?: false;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\t// `-u` already means `-uall`, so an explicit `'all'` shares the default run\n\t\tconst opts = options?.untracked === 'all' ? { ...options, untracked: undefined } : options;\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\tgetStatusReadKey(opts),\n\t\t\t(correlationKey, signal) =>\n\t\t\t\tthis.getStatusCore(repoPath, { ...opts, correlationKey: correlationKey }, signal),\n\t\t\tcancellation,\n\t\t\topts?.force,\n\t\t);\n\t}\n\n\tprivate async getStatusCore(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tpriority?: GitCommandPriority;\n\t\t\tcorrelationKey?: string;\n\t\t\tuntracked?: 'no' | 'normal' | 'all';\n\t\t\tbranch?: false;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tconst porcelainVersion = (await this.git.supports('git:status:porcelain-v2')) ? 2 : 1;\n\n\t\tconst result = await this.statusCore(\n\t\t\trepoPath,\n\t\t\tporcelainVersion,\n\t\t\t{\n\t\t\t\tsimilarityThreshold: this.context.config?.commits.similarityThreshold,\n\t\t\t\tpriority: options?.priority,\n\t\t\t\tcorrelationKey: options?.correlationKey,\n\t\t\t\tuntracked: options?.untracked,\n\t\t\t\tbranch: options?.branch,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion);\n\n\t\tif (options?.branch === false) {\n\t\t\t// Without `--branch` a clean tree prints nothing at all, which the parser reads as no status\n\t\t\tif (status == null && result.completion.status === 'exited' && result.exitCode === 0) {\n\t\t\t\treturn new GitStatus(normalizePath(repoPath), '', '', []);\n\t\t\t}\n\t\t\t// No branch name either, which `GitStatus` reads as detached, so there is no paused rebase to look up\n\t\t\treturn status;\n\t\t}\n\n\t\tif (status?.detached) {\n\t\t\tconst pausedOpStatus = await this.provider.pausedOps?.getPausedOperationStatus?.(\n\t\t\t\trepoPath,\n\t\t\t\tundefined,\n\t\t\t\tcancellation,\n\t\t\t);\n\t\t\tif (pausedOpStatus?.type === 'rebase') {\n\t\t\t\treturn new GitStatus(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tpausedOpStatus.incoming.name,\n\t\t\t\t\tstatus.sha,\n\t\t\t\t\tstatus.files,\n\t\t\t\t\tstatus.upstream,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn status;\n\t}\n\n\t@debug()\n\tasync getStatusForFile(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\toptions?: { renames?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile | undefined> {\n\t\tconst files = await this.getStatusForPathCore(\n\t\t\trepoPath,\n\t\t\ttoFsPath(pathOrUri),\n\t\t\t{ ...options, exact: true },\n\t\t\tcancellation,\n\t\t);\n\t\treturn files?.[0];\n\t}\n\n\t@debug()\n\tasync getStatusForPath(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\toptions?: { renames?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile[] | undefined> {\n\t\treturn this.getStatusForPathCore(repoPath, toFsPath(pathOrUri), { ...options, exact: false }, cancellation);\n\t}\n\n\tprivate async getStatusForPathCore(\n\t\trepoPath: string,\n\t\tpathOrUri: string,\n\t\toptions: { exact: boolean; renames?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile[] | undefined> {\n\t\tconst relativePath = stripFolderGlob(splitPath(pathOrUri, repoPath)[0]);\n\n\t\t// Rename-aware queries can't scope by pathspec (that disables Git's rename detection), so they run the\n\t\t// SAME full `git status` as `getStatus`. Delegate to it — sharing one process/dedup entry — and filter,\n\t\t// rather than spawning a second identical `git status`.\n\t\tif (options.renames !== false) {\n\t\t\tconst status = await this.getStatus(repoPath, undefined, cancellation);\n\t\t\tif (status == null) return undefined;\n\n\t\t\tif (options.exact) {\n\t\t\t\tconst file = status.files.find(f => f.path === relativePath);\n\t\t\t\treturn file ? [file] : undefined;\n\t\t\t}\n\t\t\treturn status.files.filter(f => f.path.startsWith(relativePath));\n\t\t}\n\n\t\t// Non-rename query: pathspec-scoped `git status` (a distinct command), deduped on its own key. `exact`\n\t\t// is NOT in the key — the pathspec-scoped command is identical for exact/non-exact, so both share one run.\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t// Free-form `relativePath` (may contain `:`) goes LAST so the prefix can't be shifted into it.\n\t\t\t`getStatusForPath:${relativePath}`,\n\t\t\t(correlationKey, signal) => this.getStatusForPathScoped(repoPath, relativePath, correlationKey, signal),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async getStatusForPathScoped(\n\t\trepoPath: string,\n\t\trelativePath: string,\n\t\tcorrelationKey: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile[] | undefined> {\n\t\tconst porcelainVersion = (await this.git.supports('git:status:porcelain-v2')) ? 2 : 1;\n\t\tconst result = await this.statusCore(\n\t\t\trepoPath,\n\t\t\tporcelainVersion,\n\t\t\t{ similarityThreshold: this.context.config?.commits.similarityThreshold, correlationKey: correlationKey },\n\t\t\tcancellation,\n\t\t\trelativePath,\n\t\t);\n\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion);\n\t\treturn status?.files;\n\t}\n\n\tprivate async statusCore(\n\t\trepoPath: string,\n\t\tporcelainVersion: number = 1,\n\t\toptions?: {\n\t\t\tsimilarityThreshold?: number | null;\n\t\t\tpriority?: GitCommandPriority;\n\t\t\tcorrelationKey?: string;\n\t\t\tuntracked?: 'no' | 'normal' | 'all';\n\t\t\tbranch?: false;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t\t...pathspecs: string[]\n\t): Promise<GitResult> {\n\t\tconst params = ['status', porcelainVersion >= 2 ? `--porcelain=v${porcelainVersion}` : '--porcelain'];\n\t\tif (options?.branch !== false) {\n\t\t\tparams.push('--branch');\n\t\t}\n\t\tparams.push(options?.untracked != null ? `-u${options.untracked}` : '-u');\n\t\tif (await this.git.supports('git:status:find-renames')) {\n\t\t\tparams.push(\n\t\t\t\t`--find-renames${options?.similarityThreshold == null ? '' : `=${options.similarityThreshold}%`}`,\n\t\t\t);\n\t\t}\n\n\t\treturn this.git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\tcancellation: cancellation,\n\t\t\t\tconfigs: gitConfigsStatus,\n\t\t\t\tenv: { GIT_OPTIONAL_LOCKS: '0' },\n\t\t\t\tcorrelationKey: options?.correlationKey,\n\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t},\n\t\t\t...params,\n\t\t\t'--',\n\t\t\t...pathspecs,\n\t\t);\n\t}\n\n\t@debug()\n\thasWorkingChanges(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tstaged?: boolean;\n\t\t\tunstaged?: boolean;\n\t\t\tuntracked?: boolean;\n\t\t\tthrowOnError?: boolean;\n\t\t\tpriority?: GitCommandPriority;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst staged = options?.staged ?? true;\n\t\tconst unstaged = options?.unstaged ?? true;\n\t\tconst untracked = options?.untracked ?? true;\n\t\t// `throwOnError` is in the key because it changes the RESULT on git failure (throw vs `false`) — a\n\t\t// throwing caller must not join, and be silently satisfied by, a non-throwing caller's graceful run.\n\t\t// `priority` is in the key for a different reason: it doesn't change the answer, but a joiner INHERITS\n\t\t// the in-flight run's scheduling. `GitQueue` refuses to start background work while anything is\n\t\t// waiting at normal/interactive, so letting a foreground caller (the overview's dirty pill, the\n\t\t// Worktrees view) join a `background` probe would strand it for the whole graph load. Splitting the\n\t\t// two lanes costs at most one extra spawn; joining costs unbounded foreground latency.\n\t\tconst throwOnError = options?.throwOnError ?? false;\n\t\tconst priority = options?.priority ?? 'default';\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t`hasWorkingChanges:${staged}:${unstaged}:${untracked}:${throwOnError}:${priority}`,\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\ttry {\n\t\t\t\t\tif (staged || unstaged) {\n\t\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\t\terrors: 'ignore',\n\t\t\t\t\t\t\t\tcorrelationKey: correlationKey,\n\t\t\t\t\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t'diff',\n\t\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t\tstaged && unstaged ? 'HEAD' : staged ? '--staged' : undefined,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (result.exitCode === 1) {\n\t\t\t\t\t\t\tif (staged && unstaged) {\n\t\t\t\t\t\t\t\tscope?.addExitInfo('has staged and unstaged changes');\n\t\t\t\t\t\t\t} else if (staged) {\n\t\t\t\t\t\t\t\tscope?.addExitInfo('has staged changes');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tscope?.addExitInfo('has unstaged changes');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for untracked files. NOTE: this runs through `git.stream`, which spawns directly\n\t\t\t\t\t// and never enters the queue — so `priority` above doesn't reach it. Only clean worktrees\n\t\t\t\t\t// get this far (a dirty one already returned above), and callers fanning out across many\n\t\t\t\t\t// worktrees are expected to bound their own concurrency.\n\t\t\t\t\tif (untracked) {\n\t\t\t\t\t\tconst hasUntracked = await this.hasUntrackedFiles(repoPath, signal);\n\t\t\t\t\t\tif (hasUntracked) {\n\t\t\t\t\t\t\tscope?.addExitInfo('has untracked files');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tscope?.addExitInfo('no working changes');\n\t\t\t\t\treturn false;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\t// Re-throw cancellation errors\n\t\t\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t\t\t// Log other errors and return false for graceful degradation\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\tscope?.addExitInfo('error checking for changes');\n\t\t\t\t\tif (throwOnError) throw ex;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug()\n\tgetWorkingChangesState(repoPath: string, cancellation?: AbortSignal): Promise<GitWorkingChangesState> {\n\t\tconst scope = getScopedLogger();\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'getWorkingChangesState',\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst [stagedResult, unstagedResult, untrackedResult] = await Promise.allSettled([\n\t\t\t\t\t\t// Check for staged changes\n\t\t\t\t\t\tthis.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, cancellation: signal, errors: 'ignore', correlationKey: correlationKey },\n\t\t\t\t\t\t\t'diff',\n\t\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t\t'--staged',\n\t\t\t\t\t\t),\n\t\t\t\t\t\t// Check for unstaged changes\n\t\t\t\t\t\tthis.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, cancellation: signal, errors: 'ignore', correlationKey: correlationKey },\n\t\t\t\t\t\t\t'diff',\n\t\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t),\n\t\t\t\t\t\t// Check for untracked files\n\t\t\t\t\t\tthis.hasUntrackedFiles(repoPath, signal),\n\t\t\t\t\t]);\n\n\t\t\t\t\tconst result = {\n\t\t\t\t\t\tstaged: getSettledValue(stagedResult)?.exitCode === 1,\n\t\t\t\t\t\tunstaged: getSettledValue(unstagedResult)?.exitCode === 1,\n\t\t\t\t\t\tuntracked: getSettledValue(untrackedResult) === true,\n\t\t\t\t\t};\n\n\t\t\t\t\tscope?.addExitInfo(\n\t\t\t\t\t\tresult.staged || result.unstaged || result.untracked\n\t\t\t\t\t\t\t? `has ${result.staged ? 'staged' : ''}${result.unstaged ? (result.staged ? ', unstaged' : 'unstaged ') : ''}${\n\t\t\t\t\t\t\t\t\tresult.untracked\n\t\t\t\t\t\t\t\t\t\t? result.staged || result.unstaged\n\t\t\t\t\t\t\t\t\t\t\t? ', untracked'\n\t\t\t\t\t\t\t\t\t\t\t: 'untracked'\n\t\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t\t} changes`\n\t\t\t\t\t\t\t: 'no working changes',\n\t\t\t\t\t);\n\n\t\t\t\t\treturn result;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\tscope?.addExitInfo('error checking for changes');\n\t\t\t\t\t// Return all false on error for graceful degradation\n\t\t\t\t\treturn { staged: false, unstaged: false, untracked: false };\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\thasConflictingFiles(repoPath: string, cancellation?: AbortSignal): Promise<boolean> {\n\t\t// Route through `dedupeByStatusGeneration` (like every other point-in-time read here) for the join-fence\n\t\t// and the `raceWithTimeout` backstop — a bare `git.stream` has no per-command timeout and could wedge.\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'hasConflictingFiles',\n\t\t\tasync (_correlationKey, signal) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst stream = this.git.stream({ cwd: repoPath, cancellation: signal }, 'ls-files', '--unmerged');\n\t\t\t\t\tusing _streamDisposer = createDisposable(() => void stream.return?.(undefined));\n\n\t\t\t\t\t// Early exit on first chunk - breaking causes SIGPIPE, killing git process\n\t\t\t\t\tfor await (const _chunk of stream) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\t// Re-throw cancellation errors\n\t\t\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug()\n\tgetConflictingFiles(repoPath: string, cancellation?: AbortSignal): Promise<GitConflictFile[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'getConflictingFiles',\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: signal, errors: 'ignore', correlationKey: correlationKey },\n\t\t\t\t\t\t'ls-files',\n\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t'--unmerged',\n\t\t\t\t\t);\n\n\t\t\t\t\tif (!result.stdout) {\n\t\t\t\t\t\tscope?.addExitInfo('no conflicting files');\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tconst files = parseGitConflictFiles(result.stdout, repoPath);\n\t\t\t\t\tscope?.addExitInfo(`${String(files.length)} conflicting file(s)`);\n\t\t\t\t\treturn files;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\t// Re-throw cancellation errors\n\t\t\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t\t\t// Log other errors and return empty array for graceful degradation\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\tscope?.addExitInfo('error getting conflicting files');\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async hasUntrackedFiles(repoPath: string, cancellation?: AbortSignal): Promise<boolean> {\n\t\ttry {\n\t\t\tconst stream = this.git.stream(\n\t\t\t\t{ cwd: repoPath, cancellation: cancellation },\n\t\t\t\t'ls-files',\n\t\t\t\t// '-z', // Unneeded since we are only looking for presence\n\t\t\t\t'--others',\n\t\t\t\t'--exclude-standard',\n\t\t\t);\n\t\t\tusing _streamDisposer = createDisposable(() => void stream.return?.(undefined));\n\n\t\t\t// Early exit on first chunk - breaking causes SIGPIPE, killing git process\n\t\t\tfor await (const _chunk of stream) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t} catch (ex) {\n\t\t\t// Re-throw cancellation errors\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t// Treat other errors as \"no untracked files\" for graceful degradation\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t@debug()\n\tgetUntrackedFiles(repoPath: string, cancellation?: AbortSignal): Promise<GitFile[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'getUntrackedFiles',\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: signal, errors: 'ignore', correlationKey: correlationKey },\n\t\t\t\t\t\t'ls-files',\n\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t'--others',\n\t\t\t\t\t\t'--exclude-standard',\n\t\t\t\t\t);\n\n\t\t\t\t\tif (!result.stdout) {\n\t\t\t\t\t\tscope?.addExitInfo('no untracked files');\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tconst files: GitFile[] = [];\n\n\t\t\t\t\tfor (const line of iterateByDelimiter(result.stdout, '\\0')) {\n\t\t\t\t\t\tif (!line.length) continue;\n\n\t\t\t\t\t\tfiles.push({ path: line, repoPath: repoPath, status: GitFileWorkingTreeStatus.Untracked });\n\t\t\t\t\t}\n\n\t\t\t\t\tscope?.addExitInfo(`${String(files.length)} untracked file(s)`);\n\t\t\t\t\treturn files;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\t// Re-throw cancellation errors\n\t\t\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t\t\t// Log other errors and return empty array for graceful degradation\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\tscope?.addExitInfo('error getting untracked files');\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"status.js","names":[],"sources":["../../../../git-cli/src/providers/status.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitFile } from '@gitlens/git/models/file.js';\nimport { GitFileWorkingTreeStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitConflictFile } from '@gitlens/git/models/staging.js';\nimport { GitStatus } from '@gitlens/git/models/status.js';\nimport type { GitStatusFile } from '@gitlens/git/models/statusFile.js';\nimport type { GitStatusSubProvider, GitWorkingChangesState } from '@gitlens/git/providers/status.js';\nimport type { GitCommandPriority, GitErrorHandling } from '@gitlens/git/run.types.js';\nimport { raceWithTimeout } from '@gitlens/utils/cancellation.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { createDisposable } from '@gitlens/utils/disposable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { normalizePath, splitPath, stripFolderGlob } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport { PromiseMap } from '@gitlens/utils/promiseCache.js';\nimport { iterateByDelimiter } from '@gitlens/utils/string.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { 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 { defaultExceptionHandler, gitConfigsStatus, GitErrors } from '../exec/git.js';\nimport { parseGitConflictFiles } from '../parsers/indexParser.js';\nimport { parseGitStatus } from '../parsers/statusParser.js';\n\n/** Backstop when `advanced.git.timeout` is disabled (0). Independent of the command timeout so disabling it can't\n * also disable deadlock recovery — mirrors `@gate`'s always-on 5-min force-clear. */\nconst disabledTimeoutBackstopMs = 1000 * 60 * 5;\n\n/**\n * Deadlock-backstop duration for a status read (see `dedupeByStatusGeneration`), exported for testing.\n * Always returns a value so a wedged read recovers even with `advanced.git.timeout` disabled (which bounds git\n * *commands*, not deadlock recovery). With a timeout set, `gitTimeout * 2` sits above the per-command timeout so\n * `git.run` reads reject at their own timeout first; the backstop's real job is bounding the timeout-less\n * `git.stream` reads (`hasUntrackedFiles`/`hasConflictingFiles`).\n */\nexport function computeDeadlockBackstopMs(gitTimeout: number | undefined): number {\n\tconst timeout = gitTimeout ?? 60000;\n\treturn timeout > 0 ? timeout * 2 : disabledTimeoutBackstopMs;\n}\n\n/**\n * A non-default `untracked`/`branch` gets its own key, so a full-status caller never joins a narrower run; the\n * default stays `'getStatus'`, which `getStatusForPathCore`'s rename path joins.\n */\nfunction getStatusReadKey(options?: { untracked?: 'no' | 'normal' | 'all'; branch?: false }): string {\n\tif (options?.untracked == null && options?.branch !== false) return 'getStatus';\n\n\tconst parts: string[] = [];\n\tif (options?.untracked != null) {\n\t\tparts.push(`untracked=${options.untracked}`);\n\t}\n\tif (options?.branch === false) {\n\t\tparts.push('branch=false');\n\t}\n\treturn `getStatus:${parts.join(':')}`;\n}\n\nexport class StatusGitSubProvider implements GitStatusSubProvider {\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/** In-flight reads, keyed by `<read>\\0<repoPath>\\0<generation>`. `PromiseMap` (not a bare Map) so joiners\n\t * get per-caller cancellation: the shared run aborts only when ALL current callers do. */\n\tprivate readonly _pendingReads = new PromiseMap<string, unknown>();\n\n\t/**\n\t * Single-flight for point-in-time reads of mutable working-tree state — replaces `@gate`, which dedups on\n\t * repoPath with no notion of *when* a run started and so joins a pre-change read to a post-change caller\n\t * (see {@link Cache.getStatusGeneration}). Same-generation callers share one run (via a `PromiseMap`, so a\n\t * joiner cancelling can't reject the others); a caller in a newer generation gets a different key and a\n\t * fresh run; a `force` read advances the clock first, so it fences every later reader too, not just itself.\n\t * The exec-layer command dedup (`Git.pendingCommands`) is fenced automatically: each run carries this entry's\n\t * aggregate signal, whose id is part of the exec cache key, so a newer-generation run never joins an older\n\t * one's process; the generation-derived `correlationKey` is a readable second guard on that key. A `raceWithTimeout` backstop (scaled to `advanced.git.timeout`, see\n\t * {@link computeDeadlockBackstopMs}) replaces `@gate`'s 5-min force-clear so a never-settling read (a hung\n\t * `git.stream`, which has no per-command timeout) can't wedge same-generation callers — including blocking\n\t * awaiters like the commit flow — indefinitely.\n\t */\n\tprivate dedupeByStatusGeneration<T>(\n\t\trepoPath: string,\n\t\tread: string,\n\t\trun: (correlationKey: string, signal: AbortSignal | undefined) => Promise<T>,\n\t\tcancellation?: AbortSignal,\n\t\tforce?: boolean,\n\t): Promise<T> {\n\t\t// A `force` (user refresh) read is the user asserting the working tree may have changed without the watcher\n\t\t// observing it — the same class of event as a watcher tick, so it ADVANCES the clock rather than carving out\n\t\t// a private key for itself. A one-shot nonce would fence only this caller: the pre-assertion run stays\n\t\t// joinable, so the very next ordinary reader still picks up pre-change content — and, stamped with a newer\n\t\t// `Wip.revision` (assigned at producer start, not read start), applies it right back over the refreshed\n\t\t// result. Advancing is also CHEAPER than a nonce: concurrent readers join the one fresh read instead of each\n\t\t// spawning a private one.\n\t\tif (force) {\n\t\t\tthis.cache.incrementStatusGeneration(repoPath);\n\t\t}\n\t\tconst generation = this.cache.getStatusGeneration(repoPath);\n\t\t// `\\0` separators: `read`/`repoPath` are free-form (paths can contain `:`), so a printable delimiter could\n\t\t// collide (`getStatusForPath:/a:x` vs `getStatusForPath:/a` + `:x`).\n\t\tconst key = `${read}\\0${repoPath}\\0${generation}`;\n\t\tconst correlationKey = `status:${generation}`;\n\t\tconst backstopMs = computeDeadlockBackstopMs(this.git.options.gitTimeout);\n\n\t\treturn this._pendingReads.getOrCreate(\n\t\t\tkey,\n\t\t\t(cacheable, signal) => {\n\t\t\t\t// Point-in-time read: never memoize a settled value. `invalidate()` at the start makes the entry\n\t\t\t\t// self-evict on settle, so a later caller in this same generation re-reads (a newer generation\n\t\t\t\t// already gets a different key). `signal` is the aggregate — the run aborts only if every caller\n\t\t\t\t// cancels, so one caller's abort can't reject the others. The backstop rejects a wedged read so\n\t\t\t\t// waiters unblock and the entry self-evicts; it ALSO aborts the underlying git op (via `backstop`\n\t\t\t\t// linked into the run's signal) so a wedged read releases its GitQueue slot/process rather than\n\t\t\t\t// running orphaned — best-effort, since a truly-stuck process may ignore the abort.\n\t\t\t\tcacheable.invalidate();\n\t\t\t\tconst backstop = new AbortController();\n\t\t\t\tconst runSignal = signal != null ? AbortSignal.any([signal, backstop.signal]) : backstop.signal;\n\t\t\t\treturn raceWithTimeout(run(correlationKey, runSignal), backstopMs, backstop);\n\t\t\t},\n\t\t\tcancellation,\n\t\t) as Promise<T>;\n\t}\n\n\t@debug()\n\tgetStatus(\n\t\trepoPath: string | undefined,\n\t\toptions?: {\n\t\t\tpriority?: GitCommandPriority;\n\t\t\tforce?: boolean;\n\t\t\tuntracked?: 'no' | 'normal' | 'all';\n\t\t\tbranch?: false;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\t// `-u` already means `-uall`, so an explicit `'all'` shares the default run\n\t\tconst opts = options?.untracked === 'all' ? { ...options, untracked: undefined } : options;\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\tgetStatusReadKey(opts),\n\t\t\t(correlationKey, signal) =>\n\t\t\t\tthis.getStatusCore(repoPath, { ...opts, correlationKey: correlationKey }, signal),\n\t\t\tcancellation,\n\t\t\topts?.force,\n\t\t);\n\t}\n\n\tprivate async getStatusCore(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tpriority?: GitCommandPriority;\n\t\t\tcorrelationKey?: string;\n\t\t\tuntracked?: 'no' | 'normal' | 'all';\n\t\t\tbranch?: false;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tconst porcelainVersion = (await this.git.supports('git:status:porcelain-v2')) ? 2 : 1;\n\n\t\tconst result = await this.statusCore(\n\t\t\trepoPath,\n\t\t\tporcelainVersion,\n\t\t\t{\n\t\t\t\tsimilarityThreshold: this.context.config?.commits.similarityThreshold,\n\t\t\t\tpriority: options?.priority,\n\t\t\t\tcorrelationKey: options?.correlationKey,\n\t\t\t\tuntracked: options?.untracked,\n\t\t\t\tbranch: options?.branch,\n\t\t\t\terrors: 'throw',\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion);\n\n\t\tif (options?.branch === false) {\n\t\t\t// Without `--branch` a clean tree prints nothing at all, which the parser reads as no status\n\t\t\tif (status == null && result.completion.status === 'exited' && result.exitCode === 0) {\n\t\t\t\treturn new GitStatus(normalizePath(repoPath), '', '', []);\n\t\t\t}\n\t\t\t// No branch name either, which `GitStatus` reads as detached, so there is no paused rebase to look up\n\t\t\treturn status;\n\t\t}\n\n\t\tif (status?.detached) {\n\t\t\tconst pausedOpStatus = await this.provider.pausedOps?.getPausedOperationStatus?.(\n\t\t\t\trepoPath,\n\t\t\t\tundefined,\n\t\t\t\tcancellation,\n\t\t\t);\n\t\t\tif (pausedOpStatus?.type === 'rebase') {\n\t\t\t\treturn new GitStatus(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tpausedOpStatus.incoming.name,\n\t\t\t\t\tstatus.sha,\n\t\t\t\t\tstatus.files,\n\t\t\t\t\tstatus.upstream,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn status;\n\t}\n\n\t@debug()\n\tasync getStatusForFile(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\toptions?: { renames?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile | undefined> {\n\t\tconst files = await this.getStatusForPathCore(\n\t\t\trepoPath,\n\t\t\ttoFsPath(pathOrUri),\n\t\t\t{ ...options, exact: true },\n\t\t\tcancellation,\n\t\t);\n\t\treturn files?.[0];\n\t}\n\n\t@debug()\n\tasync getStatusForPath(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\toptions?: { renames?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile[] | undefined> {\n\t\treturn this.getStatusForPathCore(repoPath, toFsPath(pathOrUri), { ...options, exact: false }, cancellation);\n\t}\n\n\tprivate async getStatusForPathCore(\n\t\trepoPath: string,\n\t\tpathOrUri: string,\n\t\toptions: { exact: boolean; renames?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile[] | undefined> {\n\t\tconst relativePath = stripFolderGlob(splitPath(pathOrUri, repoPath)[0]);\n\n\t\t// Rename-aware queries can't scope by pathspec (that disables Git's rename detection), so they run the\n\t\t// SAME full `git status` as `getStatus`. Delegate to it — sharing one process/dedup entry — and filter,\n\t\t// rather than spawning a second identical `git status`.\n\t\tif (options.renames !== false) {\n\t\t\t// The rename path keeps the default handling the scoped read gets\n\t\t\tconst status = await this.getStatus(repoPath, undefined, cancellation).catch((ex: unknown) => {\n\t\t\t\tdefaultExceptionHandler(ex as Error, repoPath);\n\t\t\t\treturn undefined;\n\t\t\t});\n\t\t\tif (status == null) return undefined;\n\n\t\t\tif (options.exact) {\n\t\t\t\tconst file = status.files.find(f => f.path === relativePath);\n\t\t\t\treturn file ? [file] : undefined;\n\t\t\t}\n\t\t\treturn status.files.filter(f => f.path.startsWith(relativePath));\n\t\t}\n\n\t\t// Non-rename query: pathspec-scoped `git status` (a distinct command), deduped on its own key. `exact`\n\t\t// is NOT in the key — the pathspec-scoped command is identical for exact/non-exact, so both share one run.\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t// Free-form `relativePath` (may contain `:`) goes LAST so the prefix can't be shifted into it.\n\t\t\t`getStatusForPath:${relativePath}`,\n\t\t\t(correlationKey, signal) => this.getStatusForPathScoped(repoPath, relativePath, correlationKey, signal),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async getStatusForPathScoped(\n\t\trepoPath: string,\n\t\trelativePath: string,\n\t\tcorrelationKey: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatusFile[] | undefined> {\n\t\tconst porcelainVersion = (await this.git.supports('git:status:porcelain-v2')) ? 2 : 1;\n\t\tconst result = await this.statusCore(\n\t\t\trepoPath,\n\t\t\tporcelainVersion,\n\t\t\t{ similarityThreshold: this.context.config?.commits.similarityThreshold, correlationKey: correlationKey },\n\t\t\tcancellation,\n\t\t\trelativePath,\n\t\t);\n\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion);\n\t\treturn status?.files;\n\t}\n\n\tprivate async statusCore(\n\t\trepoPath: string,\n\t\tporcelainVersion: number = 1,\n\t\toptions?: {\n\t\t\tsimilarityThreshold?: number | null;\n\t\t\tpriority?: GitCommandPriority;\n\t\t\tcorrelationKey?: string;\n\t\t\tuntracked?: 'no' | 'normal' | 'all';\n\t\t\tbranch?: false;\n\t\t\terrors?: GitErrorHandling;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t\t...pathspecs: string[]\n\t): Promise<GitResult> {\n\t\tconst params = ['status', porcelainVersion >= 2 ? `--porcelain=v${porcelainVersion}` : '--porcelain'];\n\t\tif (options?.branch !== false) {\n\t\t\tparams.push('--branch');\n\t\t}\n\t\tparams.push(options?.untracked != null ? `-u${options.untracked}` : '-u');\n\t\tif (await this.git.supports('git:status:find-renames')) {\n\t\t\tparams.push(\n\t\t\t\t`--find-renames${options?.similarityThreshold == null ? '' : `=${options.similarityThreshold}%`}`,\n\t\t\t);\n\t\t}\n\n\t\treturn this.git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\tcancellation: cancellation,\n\t\t\t\tconfigs: gitConfigsStatus,\n\t\t\t\tenv: { GIT_OPTIONAL_LOCKS: '0' },\n\t\t\t\tcorrelationKey: options?.correlationKey,\n\t\t\t\t...(options?.errors != null ? { errors: options.errors } : undefined),\n\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t},\n\t\t\t...params,\n\t\t\t'--',\n\t\t\t...pathspecs,\n\t\t);\n\t}\n\n\t@debug()\n\thasWorkingChanges(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tstaged?: boolean;\n\t\t\tunstaged?: boolean;\n\t\t\tuntracked?: boolean;\n\t\t\tpriority?: GitCommandPriority;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst staged = options?.staged ?? true;\n\t\tconst unstaged = options?.unstaged ?? true;\n\t\tconst untracked = options?.untracked ?? true;\n\t\t// `priority` is in the key even though it doesn't change the answer: a joiner INHERITS the in-flight run's\n\t\t// scheduling. `GitQueue` refuses to start background work while anything is waiting at normal/interactive,\n\t\t// so letting a foreground caller (the overview's dirty pill, the Worktrees view) join a `background` probe\n\t\t// would strand it for the whole graph load. Splitting the two lanes costs at most one extra spawn; joining\n\t\t// costs unbounded foreground latency.\n\t\tconst priority = options?.priority ?? 'default';\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t`hasWorkingChanges:${staged}:${unstaged}:${untracked}:${priority}`,\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\tif (staged || unstaged) {\n\t\t\t\t\tconst diffQuiet = (revision: string | undefined) =>\n\t\t\t\t\t\tthis.git.run(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\t\terrors: 'throw',\n\t\t\t\t\t\t\t\texpectedExitCodes: [1],\n\t\t\t\t\t\t\t\tcorrelationKey: correlationKey,\n\t\t\t\t\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t'diff',\n\t\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t\trevision,\n\t\t\t\t\t\t\t'--',\n\t\t\t\t\t\t);\n\n\t\t\t\t\tlet result;\n\t\t\t\t\tif (staged && unstaged) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresult = await diffQuiet('HEAD');\n\t\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t\t// Before the first commit HEAD names nothing; everything staged or modified is a change\n\t\t\t\t\t\t\t// against the empty tree. `diff HEAD --` names only HEAD, so its \"bad revision\" is that case\n\t\t\t\t\t\t\t// without re-validating HEAD (a corrupt HEAD then reads as dirty, the safe answer)\n\t\t\t\t\t\t\tif (GitErrors.badRevision.exec(String(ex))?.[1]?.toUpperCase() !== 'HEAD') throw ex;\n\n\t\t\t\t\t\t\tresult = await diffQuiet(await this.provider.revision.getEmptyTreeSha(repoPath));\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = await diffQuiet(staged ? '--staged' : undefined);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (result.exitCode === 1) {\n\t\t\t\t\t\tif (staged && unstaged) {\n\t\t\t\t\t\t\tscope?.addExitInfo('has staged and unstaged changes');\n\t\t\t\t\t\t} else if (staged) {\n\t\t\t\t\t\t\tscope?.addExitInfo('has staged changes');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tscope?.addExitInfo('has unstaged changes');\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Check for untracked files. NOTE: this runs through `git.stream`, which spawns directly\n\t\t\t\t// and never enters the queue — so `priority` above doesn't reach it. Only clean worktrees\n\t\t\t\t// get this far (a dirty one already returned above), and callers fanning out across many\n\t\t\t\t// worktrees are expected to bound their own concurrency.\n\t\t\t\tif (untracked) {\n\t\t\t\t\tconst hasUntracked = await this.hasUntrackedFiles(repoPath, signal);\n\t\t\t\t\tif (hasUntracked) {\n\t\t\t\t\t\tscope?.addExitInfo('has untracked files');\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tscope?.addExitInfo('no working changes');\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug()\n\tgetWorkingChangesState(repoPath: string, cancellation?: AbortSignal): Promise<GitWorkingChangesState> {\n\t\tconst scope = getScopedLogger();\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'getWorkingChangesState',\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\tconst [stagedResult, unstagedResult, untrackedResult] = await Promise.allSettled([\n\t\t\t\t\t// Check for staged changes\n\t\t\t\t\tthis.git.run(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\terrors: 'throw',\n\t\t\t\t\t\t\texpectedExitCodes: [1],\n\t\t\t\t\t\t\tcorrelationKey: correlationKey,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'diff',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t'--staged',\n\t\t\t\t\t),\n\t\t\t\t\t// Check for unstaged changes\n\t\t\t\t\tthis.git.run(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\terrors: 'throw',\n\t\t\t\t\t\t\texpectedExitCodes: [1],\n\t\t\t\t\t\t\tcorrelationKey: correlationKey,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'diff',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t),\n\t\t\t\t\t// Check for untracked files\n\t\t\t\t\tthis.hasUntrackedFiles(repoPath, signal),\n\t\t\t\t]);\n\n\t\t\t\tfor (const settled of [stagedResult, unstagedResult, untrackedResult]) {\n\t\t\t\t\tif (settled.status === 'rejected') throw settled.reason;\n\t\t\t\t}\n\n\t\t\t\tconst result = {\n\t\t\t\t\tstaged: getSettledValue(stagedResult)?.exitCode === 1,\n\t\t\t\t\tunstaged: getSettledValue(unstagedResult)?.exitCode === 1,\n\t\t\t\t\tuntracked: getSettledValue(untrackedResult) === true,\n\t\t\t\t};\n\n\t\t\t\tscope?.addExitInfo(\n\t\t\t\t\tresult.staged || result.unstaged || result.untracked\n\t\t\t\t\t\t? `has ${result.staged ? 'staged' : ''}${result.unstaged ? (result.staged ? ', unstaged' : 'unstaged ') : ''}${\n\t\t\t\t\t\t\t\tresult.untracked ? (result.staged || result.unstaged ? ', untracked' : 'untracked') : ''\n\t\t\t\t\t\t\t} changes`\n\t\t\t\t\t\t: 'no working changes',\n\t\t\t\t);\n\n\t\t\t\treturn result;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\thasConflictingFiles(repoPath: string, cancellation?: AbortSignal): Promise<boolean> {\n\t\t// Route through `dedupeByStatusGeneration` (like every other point-in-time read here) for the join-fence\n\t\t// and the `raceWithTimeout` backstop — a bare `git.stream` has no per-command timeout and could wedge.\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'hasConflictingFiles',\n\t\t\tasync (_correlationKey, signal) => {\n\t\t\t\tconst stream = this.git.stream({ cwd: repoPath, cancellation: signal }, 'ls-files', '--unmerged');\n\t\t\t\tusing _streamDisposer = createDisposable(() => void stream.return?.(undefined));\n\n\t\t\t\t// Early exit on first chunk - breaking causes SIGPIPE, killing git process\n\t\t\t\tfor await (const _chunk of stream) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug()\n\tgetConflictingFiles(repoPath: string, cancellation?: AbortSignal): Promise<GitConflictFile[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'getConflictingFiles',\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t{ cwd: repoPath, cancellation: signal, errors: 'throw', correlationKey: correlationKey },\n\t\t\t\t\t'ls-files',\n\t\t\t\t\t'-z',\n\t\t\t\t\t'--unmerged',\n\t\t\t\t);\n\n\t\t\t\tif (!result.stdout) {\n\t\t\t\t\tscope?.addExitInfo('no conflicting files');\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\n\t\t\t\tconst files = parseGitConflictFiles(result.stdout, repoPath);\n\t\t\t\tscope?.addExitInfo(`${String(files.length)} conflicting file(s)`);\n\t\t\t\treturn files;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async hasUntrackedFiles(repoPath: string, cancellation?: AbortSignal): Promise<boolean> {\n\t\tconst stream = this.git.stream(\n\t\t\t{ cwd: repoPath, cancellation: cancellation },\n\t\t\t'ls-files',\n\t\t\t// '-z', // Unneeded since we are only looking for presence\n\t\t\t'--others',\n\t\t\t'--exclude-standard',\n\t\t);\n\t\tusing _streamDisposer = createDisposable(() => void stream.return?.(undefined));\n\n\t\t// Early exit on first chunk - breaking causes SIGPIPE, killing git process\n\t\tfor await (const _chunk of stream) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@debug()\n\tgetUntrackedFiles(repoPath: string, cancellation?: AbortSignal): Promise<GitFile[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'getUntrackedFiles',\n\t\t\tasync (correlationKey, signal) => {\n\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t{ cwd: repoPath, cancellation: signal, errors: 'throw', correlationKey: correlationKey },\n\t\t\t\t\t'ls-files',\n\t\t\t\t\t'-z',\n\t\t\t\t\t'--others',\n\t\t\t\t\t'--exclude-standard',\n\t\t\t\t);\n\n\t\t\t\tif (!result.stdout) {\n\t\t\t\t\tscope?.addExitInfo('no untracked files');\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\n\t\t\t\tconst files: GitFile[] = [];\n\n\t\t\t\tfor (const line of iterateByDelimiter(result.stdout, '\\0')) {\n\t\t\t\t\tif (!line.length) continue;\n\n\t\t\t\t\tfiles.push({ path: line, repoPath: repoPath, status: GitFileWorkingTreeStatus.Untracked });\n\t\t\t\t}\n\n\t\t\t\tscope?.addExitInfo(`${String(files.length)} untracked file(s)`);\n\t\t\t\treturn files;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
@@ -15,7 +15,6 @@ export declare class StatusGitSubProvider implements GitStatusSubProvider {
15
15
  staged?: boolean;
16
16
  unstaged?: boolean;
17
17
  untracked?: boolean;
18
- throwOnError?: boolean;
19
18
  priority?: GitCommandPriority;
20
19
  }, _cancellation?: AbortSignal): Promise<boolean>;
21
20
  getWorkingChangesState(_repoPath: string, _cancellation?: AbortSignal): Promise<GitWorkingChangesState>;
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/status.ts"],"sourcesContent":["import type { GitFile } from '@gitlens/git/models/file.js';\nimport type { GitConflictFile } from '@gitlens/git/models/staging.js';\nimport { GitStatus } from '@gitlens/git/models/status.js';\nimport type { GitStatusSubProvider, GitWorkingChangesState } from '@gitlens/git/providers/status.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { HeadType } from '../../context.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nexport class StatusGitSubProvider implements GitStatusSubProvider {\n\tconstructor(private readonly provider: GitHubGitProviderInternal) {}\n\n\t@gate()\n\t@debug()\n\tasync getStatus(\n\t\trepoPath: string | undefined,\n\t\t_options?: { priority?: GitCommandPriority },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\tif (context == null) return undefined;\n\n\t\tconst revision = await context.metadata.getRevision();\n\t\tif (revision == null) return undefined;\n\n\t\treturn new GitStatus(\n\t\t\trepoPath,\n\t\t\trevision.name,\n\t\t\trevision.revision,\n\t\t\t[],\n\t\t\trevision.type === HeadType.Branch || revision.type === HeadType.RemoteBranch\n\t\t\t\t? { name: `origin/${revision.name}`, missing: false, state: { ahead: 0, behind: 0 } }\n\t\t\t\t: undefined,\n\t\t);\n\t}\n\n\thasWorkingChanges(\n\t\t_repoPath: string,\n\t\t_options?: {\n\t\t\tstaged?: boolean;\n\t\t\tunstaged?: boolean;\n\t\t\tuntracked?: boolean;\n\t\t\tthrowOnError?: boolean;\n\t\t\tpriority?: GitCommandPriority;\n\t\t},\n\t\t_cancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\treturn Promise.resolve(false);\n\t}\n\n\tgetWorkingChangesState(_repoPath: string, _cancellation?: AbortSignal): Promise<GitWorkingChangesState> {\n\t\treturn Promise.resolve({ staged: false, unstaged: false, untracked: false });\n\t}\n\n\thasConflictingFiles(_repoPath: string, _cancellation?: AbortSignal): Promise<boolean> {\n\t\treturn Promise.resolve(false);\n\t}\n\n\tgetConflictingFiles(_repoPath: string, _cancellation?: AbortSignal): Promise<GitConflictFile[]> {\n\t\treturn Promise.resolve([]);\n\t}\n\n\tgetUntrackedFiles(_repoPath: string, _cancellation?: AbortSignal): Promise<GitFile[]> {\n\t\treturn Promise.resolve([]);\n\t}\n}\n"],"mappings":";;;;;;AAUA,IAAa,uBAAb,MAAkE;CACpC;CAA7B,YAAY,UAAsD;EAArC,KAAA,WAAA;CAAsC;CAEnE,MAEM,UACL,UACA,UACA,eACiC;EACjC,IAAI,YAAY,MAAM,OAAO,KAAA;EAE7B,MAAM,UAAU,MAAM,KAAK,SAAS,wBAAwB,QAAQ;EACpE,IAAI,WAAW,MAAM,OAAO,KAAA;EAE5B,MAAM,WAAW,MAAM,QAAQ,SAAS,YAAY;EACpD,IAAI,YAAY,MAAM,OAAO,KAAA;EAE7B,OAAO,IAAI,UACV,UACA,SAAS,MACT,SAAS,UACT,CAAC,GACD,SAAS,SAAS,SAAS,UAAU,SAAS,SAAS,SAAS,eAC7D;GAAE,MAAM,UAAU,SAAS;GAAQ,SAAS;GAAO,OAAO;IAAE,OAAO;IAAG,QAAQ;GAAE;EAAE,IAClF,KAAA,CACJ;CACD;CAEA,kBACC,WACA,UAOA,eACmB;EACnB,OAAO,QAAQ,QAAQ,KAAK;CAC7B;CAEA,uBAAuB,WAAmB,eAA8D;EACvG,OAAO,QAAQ,QAAQ;GAAE,QAAQ;GAAO,UAAU;GAAO,WAAW;EAAM,CAAC;CAC5E;CAEA,oBAAoB,WAAmB,eAA+C;EACrF,OAAO,QAAQ,QAAQ,KAAK;CAC7B;CAEA,oBAAoB,WAAmB,eAAyD;EAC/F,OAAO,QAAQ,QAAQ,CAAC,CAAC;CAC1B;CAEA,kBAAkB,WAAmB,eAAiD;EACrF,OAAO,QAAQ,QAAQ,CAAC,CAAC;CAC1B;AACD;AAvDE,WAAA,CAAA,KAAK,GACL,MAAM,CAAA,GAAA,qBAAA,WAAA,aAAA,IAAA"}
1
+ {"version":3,"file":"status.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/status.ts"],"sourcesContent":["import type { GitFile } from '@gitlens/git/models/file.js';\nimport type { GitConflictFile } from '@gitlens/git/models/staging.js';\nimport { GitStatus } from '@gitlens/git/models/status.js';\nimport type { GitStatusSubProvider, GitWorkingChangesState } from '@gitlens/git/providers/status.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { HeadType } from '../../context.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nexport class StatusGitSubProvider implements GitStatusSubProvider {\n\tconstructor(private readonly provider: GitHubGitProviderInternal) {}\n\n\t@gate()\n\t@debug()\n\tasync getStatus(\n\t\trepoPath: string | undefined,\n\t\t_options?: { priority?: GitCommandPriority },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\tif (context == null) return undefined;\n\n\t\tconst revision = await context.metadata.getRevision();\n\t\tif (revision == null) return undefined;\n\n\t\treturn new GitStatus(\n\t\t\trepoPath,\n\t\t\trevision.name,\n\t\t\trevision.revision,\n\t\t\t[],\n\t\t\trevision.type === HeadType.Branch || revision.type === HeadType.RemoteBranch\n\t\t\t\t? { name: `origin/${revision.name}`, missing: false, state: { ahead: 0, behind: 0 } }\n\t\t\t\t: undefined,\n\t\t);\n\t}\n\n\thasWorkingChanges(\n\t\t_repoPath: string,\n\t\t_options?: {\n\t\t\tstaged?: boolean;\n\t\t\tunstaged?: boolean;\n\t\t\tuntracked?: boolean;\n\t\t\tpriority?: GitCommandPriority;\n\t\t},\n\t\t_cancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\treturn Promise.resolve(false);\n\t}\n\n\tgetWorkingChangesState(_repoPath: string, _cancellation?: AbortSignal): Promise<GitWorkingChangesState> {\n\t\treturn Promise.resolve({ staged: false, unstaged: false, untracked: false });\n\t}\n\n\thasConflictingFiles(_repoPath: string, _cancellation?: AbortSignal): Promise<boolean> {\n\t\treturn Promise.resolve(false);\n\t}\n\n\tgetConflictingFiles(_repoPath: string, _cancellation?: AbortSignal): Promise<GitConflictFile[]> {\n\t\treturn Promise.resolve([]);\n\t}\n\n\tgetUntrackedFiles(_repoPath: string, _cancellation?: AbortSignal): Promise<GitFile[]> {\n\t\treturn Promise.resolve([]);\n\t}\n}\n"],"mappings":";;;;;;AAUA,IAAa,uBAAb,MAAkE;CACpC;CAA7B,YAAY,UAAsD;EAArC,KAAA,WAAA;CAAsC;CAEnE,MAEM,UACL,UACA,UACA,eACiC;EACjC,IAAI,YAAY,MAAM,OAAO,KAAA;EAE7B,MAAM,UAAU,MAAM,KAAK,SAAS,wBAAwB,QAAQ;EACpE,IAAI,WAAW,MAAM,OAAO,KAAA;EAE5B,MAAM,WAAW,MAAM,QAAQ,SAAS,YAAY;EACpD,IAAI,YAAY,MAAM,OAAO,KAAA;EAE7B,OAAO,IAAI,UACV,UACA,SAAS,MACT,SAAS,UACT,CAAC,GACD,SAAS,SAAS,SAAS,UAAU,SAAS,SAAS,SAAS,eAC7D;GAAE,MAAM,UAAU,SAAS;GAAQ,SAAS;GAAO,OAAO;IAAE,OAAO;IAAG,QAAQ;GAAE;EAAE,IAClF,KAAA,CACJ;CACD;CAEA,kBACC,WACA,UAMA,eACmB;EACnB,OAAO,QAAQ,QAAQ,KAAK;CAC7B;CAEA,uBAAuB,WAAmB,eAA8D;EACvG,OAAO,QAAQ,QAAQ;GAAE,QAAQ;GAAO,UAAU;GAAO,WAAW;EAAM,CAAC;CAC5E;CAEA,oBAAoB,WAAmB,eAA+C;EACrF,OAAO,QAAQ,QAAQ,KAAK;CAC7B;CAEA,oBAAoB,WAAmB,eAAyD;EAC/F,OAAO,QAAQ,QAAQ,CAAC,CAAC;CAC1B;CAEA,kBAAkB,WAAmB,eAAiD;EACrF,OAAO,QAAQ,QAAQ,CAAC,CAAC;CAC1B;AACD;AAtDE,WAAA,CAAA,KAAK,GACL,MAAM,CAAA,GAAA,qBAAA,WAAA,aAAA,IAAA"}
@@ -21,6 +21,13 @@ import { CollectionMetadata, CollectionScopeFailure } from "@gitkraken/provider-
21
21
  * account-wide drain came to degrade it while its three siblings did not.
22
22
  */
23
23
  export declare function throwIfCallerContractError(ex: unknown): void;
24
+ /**
25
+ * Whether a failed query that covered several scopes would fail each scope's own read the same way: a rejected or
26
+ * rate-limited token, or a call the SDK refused before sending. Anything else (a query the provider rejects because
27
+ * one scope is gone or no longer visible, a server error) may be one scope's problem, so the scopes are worth
28
+ * reading on their own.
29
+ */
30
+ export declare function failsEveryScope(ex: unknown): boolean;
24
31
  /**
25
32
  * Maps a caught GitLens request error to the SDK collection failure vocabulary used inside provider fan-outs.
26
33
  */
@@ -25,6 +25,16 @@ function throwIfCallerContractError(ex) {
25
25
  if (isUnsupportedSortError(ex) || isInvalidRequestError(ex)) throw ex;
26
26
  }
27
27
  /**
28
+ * Whether a failed query that covered several scopes would fail each scope's own read the same way: a rejected or
29
+ * rate-limited token, or a call the SDK refused before sending. Anything else (a query the provider rejects because
30
+ * one scope is gone or no longer visible, a server error) may be one scope's problem, so the scopes are worth
31
+ * reading on their own.
32
+ */
33
+ function failsEveryScope(ex) {
34
+ const kind = toCollectionFailureKind(ex);
35
+ return kind === "authentication" || kind === "rate-limit" || isUnsupportedSortError(ex) || isInvalidRequestError(ex);
36
+ }
37
+ /**
28
38
  * Maps a caught GitLens request error to the SDK collection failure vocabulary used inside provider fan-outs.
29
39
  */
30
40
  function toCollectionFailureKind(ex) {
@@ -363,6 +373,6 @@ function mergeAssessmentInto(warnings, providerId, domain, connectionId, metadat
363
373
  };
364
374
  }
365
375
  //#endregion
366
- export { assessCollectionMetadata, attributeScopedAuthFailures, hasOnlyScopedAuthFailures, isIncompleteCollection, markCredentialRefusals, mergeAssessmentInto, throwIfCallerContractError, toCollectionFailureError, toCollectionFailureKind, toCollectionScopeFailure };
376
+ export { assessCollectionMetadata, attributeScopedAuthFailures, failsEveryScope, hasOnlyScopedAuthFailures, isIncompleteCollection, markCredentialRefusals, mergeAssessmentInto, throwIfCallerContractError, toCollectionFailureError, toCollectionFailureKind, toCollectionScopeFailure };
367
377
 
368
378
  //# sourceMappingURL=collectionMetadata.js.map