@gitkraken/core-gitlens 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -1
- package/dist/git/cache.d.ts +11 -0
- package/dist/git/cache.js +26 -3
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +3 -2
- package/dist/git/context.js.map +1 -1
- package/dist/git/features.d.ts +1 -1
- package/dist/git/features.js +1 -0
- package/dist/git/features.js.map +1 -1
- package/dist/git/models/reflog.d.ts +6 -0
- package/dist/git/models/reflog.js.map +1 -1
- package/dist/git/models/revision.d.ts +0 -1
- package/dist/git/models/revision.js +1 -2
- package/dist/git/models/revision.js.map +1 -1
- package/dist/git/providers/commits.d.ts +20 -1
- package/dist/git/providers/operations.d.ts +13 -0
- package/dist/git/providers/provider.d.ts +14 -4
- package/dist/git/providers/refs.d.ts +10 -0
- package/dist/git/providers/revision.d.ts +2 -0
- package/dist/git/providers/staging.d.ts +2 -1
- package/dist/git/providers/stash.d.ts +3 -2
- package/dist/git/providers/status.d.ts +4 -0
- package/dist/git/run.types.d.ts +16 -0
- package/dist/git-cli/cliGitProvider.d.ts +24 -3
- package/dist/git-cli/cliGitProvider.js +79 -17
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/commandClassifier.d.ts +31 -0
- package/dist/git-cli/exec/commandClassifier.js +391 -0
- package/dist/git-cli/exec/commandClassifier.js.map +1 -0
- package/dist/git-cli/exec/git.d.ts +24 -3
- package/dist/git-cli/exec/git.js +116 -12
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/parsers/reflogParser.d.ts +7 -0
- package/dist/git-cli/parsers/reflogParser.js +11 -1
- package/dist/git-cli/parsers/reflogParser.js.map +1 -1
- package/dist/git-cli/providers/branches.js +16 -14
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +4 -2
- package/dist/git-cli/providers/commits.js +55 -4
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/diff.js +4 -4
- package/dist/git-cli/providers/diff.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +12 -0
- package/dist/git-cli/providers/operations.js +26 -3
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/patch.js +2 -5
- package/dist/git-cli/providers/patch.js.map +1 -1
- package/dist/git-cli/providers/refs.d.ts +5 -0
- package/dist/git-cli/providers/refs.js +26 -1
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/remotes.js +3 -2
- package/dist/git-cli/providers/remotes.js.map +1 -1
- package/dist/git-cli/providers/revision.d.ts +2 -0
- package/dist/git-cli/providers/revision.js +11 -0
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/staging.d.ts +2 -1
- package/dist/git-cli/providers/staging.js +12 -7
- package/dist/git-cli/providers/staging.js.map +1 -1
- package/dist/git-cli/providers/stash.d.ts +3 -2
- package/dist/git-cli/providers/stash.js +34 -22
- package/dist/git-cli/providers/stash.js.map +1 -1
- package/dist/git-cli/providers/status.d.ts +2 -0
- package/dist/git-cli/providers/status.js +27 -9
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +13 -0
- package/dist/plus/git-github/api/github.js +36 -6
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/providers/github/commits.d.ts +4 -2
- package/dist/plus/git-github/providers/github/commits.js +3 -1
- package/dist/plus/git-github/providers/github/commits.js.map +1 -1
- package/dist/plus/git-github/providers/github/revision.d.ts +1 -0
- package/dist/plus/git-github/providers/github/revision.js +5 -0
- package/dist/plus/git-github/providers/github/revision.js.map +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +6 -0
- package/dist/plus/integrations/collectionMetadata.js +7 -4
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +13 -0
- package/dist/plus/integrations/models/gitHostIntegration.js +19 -0
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +16 -1
- package/dist/plus/integrations/providers/github.js +39 -1
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/reads/resolveRepository.js +26 -5
- package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
- package/docs/integrations.md +22 -5
- package/docs/kepler-git-write-api-parity.md +140 -14
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { skip } from "../../utils/iterable.js";
|
|
2
2
|
import { countStringLength } from "../../utils/array.js";
|
|
3
|
+
import { isCancellationError } from "../../utils/cancellation.js";
|
|
3
4
|
import { getSettledValue } from "../../utils/promise.js";
|
|
4
5
|
import { debug } from "../../utils/decorators/log.js";
|
|
5
6
|
import { fileUri, joinUriPath, toFsPath } from "../../utils/uri.js";
|
|
@@ -27,20 +28,22 @@ var StashGitSubProvider = class {
|
|
|
27
28
|
this.cache = cache;
|
|
28
29
|
this.provider = provider;
|
|
29
30
|
}
|
|
30
|
-
async applyStash(repoPath, stashNameOrSha, options) {
|
|
31
|
+
async applyStash(repoPath, stashNameOrSha, options, runOptions) {
|
|
31
32
|
if (!stashNameOrSha) return { conflicted: false };
|
|
32
33
|
const args = ["stash", options?.deleteAfter ? "pop" : "apply"];
|
|
33
34
|
if (options?.index) args.push("--index");
|
|
34
35
|
args.push(stashNameOrSha);
|
|
35
|
-
return this.applyStashCore(repoPath, args, options?.deleteAfter ? "stash-pop" : "stash-apply");
|
|
36
|
+
return this.applyStashCore(repoPath, args, options?.deleteAfter ? "stash-pop" : "stash-apply", runOptions);
|
|
36
37
|
}
|
|
37
|
-
async applyStashCore(repoPath, args, conflictCommand) {
|
|
38
|
+
async applyStashCore(repoPath, args, conflictCommand, runOptions) {
|
|
38
39
|
try {
|
|
39
|
-
await this.git.run({
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
await this.git.run({
|
|
41
|
+
cwd: repoPath,
|
|
42
|
+
...runOptions
|
|
43
|
+
}, ...args);
|
|
42
44
|
return { conflicted: false };
|
|
43
45
|
} catch (ex) {
|
|
46
|
+
if (isCancellationError(ex)) throw ex;
|
|
44
47
|
if (ex instanceof Error) {
|
|
45
48
|
const msg = ex.message ?? "";
|
|
46
49
|
if (msg.includes("Auto-merging") && msg.includes("CONFLICT") || ex instanceof GitError && (ex.stdout?.includes("Auto-merging") && ex.stdout.includes("CONFLICT") || ex.stdout?.includes("needs merge"))) {
|
|
@@ -55,6 +58,9 @@ var StashGitSubProvider = class {
|
|
|
55
58
|
args
|
|
56
59
|
}
|
|
57
60
|
}, ex));
|
|
61
|
+
} finally {
|
|
62
|
+
this.context.hooks?.cache?.onReset?.(repoPath, "stashes", "status");
|
|
63
|
+
this.context.hooks?.repository?.onChanged?.(repoPath, ["stash"]);
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
async createStash(repoPath, message) {
|
|
@@ -159,12 +165,10 @@ var StashGitSubProvider = class {
|
|
|
159
165
|
this.context.hooks?.repository?.onChanged?.(repoPath, ["stash"]);
|
|
160
166
|
this.context.hooks?.cache?.onReset?.(repoPath, "stashes");
|
|
161
167
|
}
|
|
162
|
-
async saveStash(repoPath, message, pathsOrUris, options) {
|
|
168
|
+
async saveStash(repoPath, message, pathsOrUris, options, runOptions) {
|
|
163
169
|
const paths = pathsOrUris?.map(toFsPath);
|
|
164
170
|
if (!paths?.length) {
|
|
165
|
-
await this.stashPushCore(repoPath, message, options);
|
|
166
|
-
this.context.hooks?.repository?.onChanged?.(repoPath, ["stash"]);
|
|
167
|
-
this.context.hooks?.cache?.onReset?.(repoPath, "stashes", "status");
|
|
171
|
+
await this.stashPushCore(repoPath, message, options, runOptions);
|
|
168
172
|
return;
|
|
169
173
|
}
|
|
170
174
|
await this.git.ensureSupports("git:stash:push:pathspecs", (requiredVersion, installedVersion) => l10n.t("Stashing individual files requires a newer version of Git (>= {0}) than is currently installed ({1}). Please retry by stashing everything or install a more recent version of Git and try again.", requiredVersion, installedVersion));
|
|
@@ -176,11 +180,9 @@ var StashGitSubProvider = class {
|
|
|
176
180
|
...options,
|
|
177
181
|
pathspecs,
|
|
178
182
|
stdin
|
|
179
|
-
});
|
|
180
|
-
this.context.hooks?.cache?.onReset?.(repoPath, "stashes", "status");
|
|
181
|
-
this.context.hooks?.repository?.onChanged?.(repoPath, ["stash"]);
|
|
183
|
+
}, runOptions);
|
|
182
184
|
}
|
|
183
|
-
async stashPushCore(repoPath, message, options) {
|
|
185
|
+
async stashPushCore(repoPath, message, options, runOptions) {
|
|
184
186
|
const params = ["stash", "push"];
|
|
185
187
|
if ((options?.includeUntracked || options?.pathspecs?.length) && !options?.onlyStaged) params.push("--include-untracked");
|
|
186
188
|
if (options?.keepIndex && !(options?.includeUntracked && options?.pathspecs?.length)) params.push("--keep-index");
|
|
@@ -196,20 +198,25 @@ var StashGitSubProvider = class {
|
|
|
196
198
|
params.push("--pathspec-from-file=-", "--pathspec-file-nul", "--");
|
|
197
199
|
} else params.push("--", ...options.pathspecs);
|
|
198
200
|
} else params.push("--");
|
|
201
|
+
let nothingToSave = false;
|
|
199
202
|
try {
|
|
200
203
|
const result = await this.git.run({
|
|
201
204
|
cwd: repoPath,
|
|
205
|
+
...runOptions,
|
|
202
206
|
stdin
|
|
203
207
|
}, ...params);
|
|
204
|
-
if (GitErrors.stashNothingToSave.test(result.stdout))
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
208
|
+
if (GitErrors.stashNothingToSave.test(result.stdout)) {
|
|
209
|
+
nothingToSave = true;
|
|
210
|
+
throw new StashPushError({
|
|
211
|
+
reason: "nothingToSave",
|
|
212
|
+
gitCommand: {
|
|
213
|
+
repoPath,
|
|
214
|
+
args: params
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
211
218
|
} catch (ex) {
|
|
212
|
-
if (ex instanceof StashPushError) throw ex;
|
|
219
|
+
if (ex instanceof StashPushError || isCancellationError(ex)) throw ex;
|
|
213
220
|
throw getGitCommandError("stash-push", ex, (reason) => new StashPushError({
|
|
214
221
|
reason: reason ?? "other",
|
|
215
222
|
gitCommand: {
|
|
@@ -217,6 +224,11 @@ var StashGitSubProvider = class {
|
|
|
217
224
|
args: params
|
|
218
225
|
}
|
|
219
226
|
}, ex));
|
|
227
|
+
} finally {
|
|
228
|
+
if (!nothingToSave) {
|
|
229
|
+
this.context.hooks?.cache?.onReset?.(repoPath, "stashes", "status");
|
|
230
|
+
this.context.hooks?.repository?.onChanged?.(repoPath, ["stash"]);
|
|
231
|
+
}
|
|
220
232
|
}
|
|
221
233
|
}
|
|
222
234
|
async saveSnapshot(repoPath, message) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stash.js","names":[],"sources":["../../../../git-cli/src/providers/stash.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { StashApplyError, StashPushError } from '@gitlens/git/errors.js';\nimport type { GitStashCommit } from '@gitlens/git/models/commit.js';\nimport { GitCommit, GitCommitIdentity } from '@gitlens/git/models/commit.js';\nimport { GitFileChange } from '@gitlens/git/models/fileChange.js';\nimport type { GitFileStatus } from '@gitlens/git/models/fileStatus.js';\nimport { GitFileWorkingTreeStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitStash } from '@gitlens/git/models/stash.js';\nimport type { GitUser } from '@gitlens/git/models/user.js';\nimport type { GitStashSubProvider, StashApplyResult } from '@gitlens/git/providers/stash.js';\nimport { countStringLength } from '@gitlens/utils/array.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { skip } from '@gitlens/utils/iterable.js';\nimport { normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fileUri, joinUriPath, toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport { gitFeaturesByVersion } from '../exec/features.js';\nimport type { Git } from '../exec/git.js';\nimport { getGitCommandError, GitError, GitErrors, maxGitCliLength } from '../exec/git.js';\nimport type { ParsedStash, ParsedStashWithFiles } from '../parsers/logParser.js';\nimport { getStashFilesOnlyLogParser, getStashLogParser } from '../parsers/logParser.js';\nimport { createCommitFileset } from './commitFilesetUtils.js';\n\nexport class StashGitSubProvider implements GitStashSubProvider {\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@gate()\n\t@debug()\n\tasync applyStash(\n\t\trepoPath: string,\n\t\tstashNameOrSha: string,\n\t\toptions?: { deleteAfter?: boolean; index?: boolean },\n\t): Promise<StashApplyResult> {\n\t\tif (!stashNameOrSha) return { conflicted: false };\n\n\t\tconst args = ['stash', options?.deleteAfter ? 'pop' : 'apply'];\n\t\tif (options?.index) {\n\t\t\targs.push('--index');\n\t\t}\n\t\targs.push(stashNameOrSha);\n\t\treturn this.applyStashCore(repoPath, args, options?.deleteAfter ? 'stash-pop' : 'stash-apply');\n\t}\n\n\tprivate async applyStashCore(\n\t\trepoPath: string,\n\t\targs: string[],\n\t\tconflictCommand: 'stash-apply' | 'stash-pop',\n\t): Promise<StashApplyResult> {\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, ...args);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof Error) {\n\t\t\t\tconst msg: string = ex.message ?? '';\n\t\t\t\tif (\n\t\t\t\t\t(msg.includes('Auto-merging') && msg.includes('CONFLICT')) ||\n\t\t\t\t\t(ex instanceof GitError &&\n\t\t\t\t\t\t((ex.stdout?.includes('Auto-merging') && ex.stdout.includes('CONFLICT')) ||\n\t\t\t\t\t\t\tex.stdout?.includes('needs merge')))\n\t\t\t\t) {\n\t\t\t\t\tthis.context.hooks?.operations?.onConflicted?.(conflictCommand);\n\t\t\t\t\treturn { conflicted: true };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'stash-apply',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew StashApplyError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@debug()\n\tasync createStash(repoPath: string, message?: string): Promise<string | undefined> {\n\t\tconst args = ['stash', 'create'];\n\t\tif (message) {\n\t\t\targs.push(message);\n\t\t}\n\n\t\tconst result = await this.git.run({ cwd: repoPath }, ...args);\n\t\treturn result.stdout.trim() || undefined;\n\t}\n\n\t@debug()\n\tasync getStash(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tincludeFiles?: boolean;\n\t\t\treachableFrom?: string;\n\t\t\tsimilarityThreshold?: number | null;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStash | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\t// Resolve options against config up front so the cache key reflects the actual values used\n\t\t// to produce the cached payload — undefined inputs aren't conflated across config changes.\n\t\tconst cfg = this.context.config;\n\t\tconst includeFiles = options?.includeFiles ?? cfg?.commits.includeFileDetails?.(repoPath) ?? true;\n\t\tconst similarityThreshold = includeFiles\n\t\t\t? (options?.similarityThreshold ?? cfg?.commits.similarityThreshold ?? null)\n\t\t\t: null;\n\t\tconst reachableFrom = options?.reachableFrom;\n\n\t\t// Cache only the unfiltered stash list; reachability projection runs below by testing each\n\t\t// distinct stash parent against `reachableFrom` directly, so re-projecting is cheap\n\t\tconst cacheKey = `f${includeFiles ? 1 : 0}|s${similarityThreshold ?? ''}`;\n\n\t\tconst stash = await this.cache.getStash(\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tasync (commonPath, _cacheable, signal) => {\n\t\t\t\t// Prefer the aggregate signal from the cache; fall back to the caller's cancellation.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst parser = getStashLogParser(includeFiles);\n\t\t\t\tconst args = [...parser.arguments];\n\n\t\t\t\tif (includeFiles) {\n\t\t\t\t\targs.push(`-M${similarityThreshold == null ? '' : `${similarityThreshold}%`}`);\n\t\t\t\t}\n\n\t\t\t\tconst result = await this.git.run({ cwd: repoPath, cancellation: signal }, 'stash', 'list', ...args);\n\n\t\t\t\tconst currentUser = await this.provider.config.getCurrentUser(repoPath);\n\n\t\t\t\tconst stashes = new Map<string, GitStashCommit>();\n\t\t\t\tfor (const s of parser.parse(result.stdout)) {\n\t\t\t\t\tstashes.set(s.sha, createStash(s, commonPath, currentUser));\n\t\t\t\t}\n\n\t\t\t\treturn { repoPath: commonPath, stashes: stashes };\n\t\t\t},\n\t\t\t{ cancellation: cancellation },\n\t\t);\n\n\t\tif (stash == null || !reachableFrom || !stash.stashes.size) return stash;\n\n\t\t// Copy because the cached `stash.stashes` map is shared and must not be mutated.\n\t\tconst stashes = new Map(stash.stashes);\n\n\t\tconst reachableStashes = new Set<string>();\n\n\t\t// Metadata pass: a stash belongs on `reachableFrom` iff git's auto-prepended\n\t\t// `On <branch>: …` (or `WIP on <branch>: …`) prefix in the stash commit subject names\n\t\t// this branch. `stashOnRef` is parsed from %s in createStash, so this covers autostashes\n\t\t// and custom-reflog stashes too.\n\t\tfor (const [sha, s] of stash.stashes) {\n\t\t\tif (s.stashOnRef === reachableFrom) {\n\t\t\t\treachableStashes.add(sha);\n\t\t\t}\n\t\t}\n\n\t\t// Transitive pass for the rare detached-HEAD-on-stash chain (stash B created while HEAD\n\t\t// pointed at stash A). Such stashes have no `stashOnRef`, but if their parent is a stash\n\t\t// already marked reachable they should follow.\n\t\tlet changed;\n\t\tdo {\n\t\t\tchanged = false;\n\t\t\tfor (const [sha, s] of stash.stashes) {\n\t\t\t\tif (!reachableStashes.has(sha) && s.parents.some(p => reachableStashes.has(p))) {\n\t\t\t\t\treachableStashes.add(sha);\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (changed);\n\n\t\tfor (const [sha] of stash.stashes) {\n\t\t\tif (!reachableStashes.has(sha)) {\n\t\t\t\tstashes.delete(sha);\n\t\t\t}\n\t\t}\n\n\t\treturn { ...stash, stashes: stashes };\n\t}\n\n\t@debug()\n\tasync getStashCommitFiles(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { similarityThreshold?: number | null },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitFileChange[]> {\n\t\tconst [stashFilesResult, stashUntrackedFilesResult] = await Promise.allSettled([\n\t\t\t// Don't include untracked files here, because we won't be able to tell them apart from added (and we need the untracked status)\n\t\t\tthis.getStashCommitFilesCore(repoPath, ref, { untracked: false, ...options }, cancellation),\n\t\t\t// Check for any untracked files -- since git doesn't return them via `git stash list` :(\n\t\t\t// See https://stackoverflow.com/questions/12681529/\n\t\t\tthis.getStashCommitFilesCore(repoPath, ref, { untracked: 'only', ...options }, cancellation),\n\t\t]);\n\n\t\tlet files = getSettledValue(stashFilesResult);\n\t\tconst untrackedFiles = getSettledValue(stashUntrackedFilesResult);\n\n\t\tif (files?.length && untrackedFiles?.length) {\n\t\t\tfiles.push(...untrackedFiles);\n\t\t} else {\n\t\t\tfiles = files ?? untrackedFiles;\n\t\t}\n\n\t\treturn files ?? [];\n\t}\n\n\tprivate async getStashCommitFilesCore(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { similarityThreshold?: number | null; untracked?: boolean | 'only' },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitFileChange[] | undefined> {\n\t\tconst args = [];\n\t\tif (options?.untracked) {\n\t\t\targs.push(options?.untracked === 'only' ? '--only-untracked' : '--include-untracked');\n\t\t}\n\n\t\tconst similarityThreshold = options?.similarityThreshold ?? this.context.config?.commits.similarityThreshold;\n\t\tif (similarityThreshold != null) {\n\t\t\targs.push(`-M${similarityThreshold}%`);\n\t\t}\n\n\t\tconst parser = getStashFilesOnlyLogParser();\n\t\tconst result = await this.git.run(\n\t\t\t{ cwd: repoPath, cancellation: cancellation },\n\t\t\t'stash',\n\t\t\t'show',\n\t\t\t...args,\n\t\t\t...parser.arguments,\n\t\t\tref,\n\t\t);\n\n\t\tconst repoUri = fileUri(normalizePath(repoPath));\n\t\tfor (const s of parser.parse(result.stdout)) {\n\t\t\treturn (\n\t\t\t\ts.files?.map(\n\t\t\t\t\tf =>\n\t\t\t\t\t\tnew GitFileChange(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\tf.path,\n\t\t\t\t\t\t\t(options?.untracked === 'only'\n\t\t\t\t\t\t\t\t? GitFileWorkingTreeStatus.Untracked\n\t\t\t\t\t\t\t\t: f.status) as GitFileStatus,\n\t\t\t\t\t\t\tjoinUriPath(repoUri, normalizePath(f.path)),\n\t\t\t\t\t\t\tf.originalPath,\n\t\t\t\t\t\t\tf.originalPath != null ? joinUriPath(repoUri, normalizePath(f.originalPath)) : undefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tf.additions || f.deletions\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tadditions: f.additions ?? 0,\n\t\t\t\t\t\t\t\t\t\tdeletions: f.deletions ?? 0,\n\t\t\t\t\t\t\t\t\t\tchanges: 0,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tf.mode,\n\t\t\t\t\t\t),\n\t\t\t\t) ?? []\n\t\t\t);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t@debug()\n\tasync deleteStash(repoPath: string, stashName: string, sha?: string): Promise<void> {\n\t\tawait this.deleteStashCore(repoPath, stashName, sha);\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t}\n\n\t@gate()\n\tprivate async deleteStashCore(repoPath: string, stashName: string, sha?: string): Promise<string | undefined> {\n\t\tif (!stashName) return undefined;\n\n\t\tlet result;\n\t\tif (sha) {\n\t\t\tresult = await this.git.run(\n\t\t\t\t{ cwd: repoPath, errors: 'ignore' },\n\t\t\t\t'show',\n\t\t\t\t'--format=%H',\n\t\t\t\t'--no-patch',\n\t\t\t\tstashName,\n\t\t\t);\n\t\t\tif (result.stdout.trim() !== sha) {\n\t\t\t\tthrow new Error(l10n.t('Unable to delete stash; mismatch with stash number'));\n\t\t\t}\n\t\t}\n\n\t\tresult = await this.git.run({ cwd: repoPath }, 'stash', 'drop', stashName);\n\t\treturn result.stdout;\n\t}\n\n\t@debug()\n\tasync renameStash(\n\t\trepoPath: string,\n\t\tstashName: string,\n\t\tsha: string,\n\t\tmessage: string,\n\t\tstashOnRef?: string,\n\t): Promise<void> {\n\t\tawait this.deleteStashCore(repoPath, stashName, sha);\n\t\tawait this.git.run(\n\t\t\t{ cwd: repoPath },\n\t\t\t'stash',\n\t\t\t'store',\n\t\t\t'-m',\n\t\t\tstashOnRef ? `On ${stashOnRef}: ${message}` : message,\n\t\t\tsha,\n\t\t);\n\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t}\n\n\t@debug({ args: (repoPath, message, paths) => ({ repoPath: repoPath, message: message, paths: paths?.length }) })\n\tasync saveStash(\n\t\trepoPath: string,\n\t\tmessage?: string,\n\t\tpathsOrUris?: (string | Uri)[],\n\t\toptions?: { includeUntracked?: boolean; keepIndex?: boolean; onlyStaged?: boolean },\n\t): Promise<void> {\n\t\tconst paths = pathsOrUris?.map(toFsPath);\n\t\tif (!paths?.length) {\n\t\t\tawait this.stashPushCore(repoPath, message, options);\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes', 'status');\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.git.ensureSupports('git:stash:push:pathspecs', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Stashing individual files requires a newer version of Git (>= {0}) than is currently installed ({1}). Please retry by stashing everything or install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tconst pathspecs = paths.map(p => `./${splitPath(p, repoPath)[0]}`);\n\n\t\tlet stdin = await this.git.supports('git:stash:push:stdin');\n\t\tif (stdin && options?.onlyStaged && paths.length) {\n\t\t\t// Since Git doesn't support --staged with --pathspec-from-file try to pass them in directly\n\t\t\tstdin = false;\n\t\t}\n\n\t\t// If we don't support stdin, then error out if we are over the maximum allowed git cli length\n\t\tif (!stdin && countStringLength(pathspecs) > maxGitCliLength) {\n\t\t\tawait this.git.ensureSupports('git:stash:push:stdin', (requiredVersion, installedVersion) =>\n\t\t\t\tl10n.t(\n\t\t\t\t\t'Stashing so many files ({0}) at once requires a newer version of Git (>= {1}) than is currently installed ({2}). Please retry by stashing fewer files or install a more recent version of Git and try again.',\n\t\t\t\t\tpathspecs.length,\n\t\t\t\t\trequiredVersion,\n\t\t\t\t\tinstalledVersion,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tawait this.stashPushCore(repoPath, message, {\n\t\t\t...options,\n\t\t\tpathspecs: pathspecs,\n\t\t\tstdin: stdin,\n\t\t});\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes', 'status');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t}\n\n\tprivate async stashPushCore(\n\t\trepoPath: string,\n\t\tmessage?: string,\n\t\toptions?: {\n\t\t\tincludeUntracked?: boolean;\n\t\t\tkeepIndex?: boolean;\n\t\t\tonlyStaged?: boolean;\n\t\t\tpathspecs?: string[];\n\t\t\tstdin?: boolean;\n\t\t},\n\t): Promise<void> {\n\t\tconst params = ['stash', 'push'];\n\n\t\tif ((options?.includeUntracked || options?.pathspecs?.length) && !options?.onlyStaged) {\n\t\t\tparams.push('--include-untracked');\n\t\t}\n\n\t\t// `git stash push --keep-index --include-untracked -- <pathspec>` hits a bug in git when the\n\t\t// pathspec names an untracked file: the restoring checkout can't match an untracked path in the\n\t\t// index tree, so it fails and the staged changes are lost.\n\t\t//\n\t\t// $ mkdir stash-test && cd stash-test && git init\n\t\t// $ echo a > a.txt\n\t\t// $ git add a.txt\n\t\t// $ git commit -m init\n\t\t// $ echo b > b.txt\n\t\t// $ git stash push --keep-index --include-untracked -- b.txt\n\t\t// Saved working directory and index state WIP on main: 8a280fe init\n\t\t// error: pathspec ':(prefix:0)b.txt' did not match any file(s) known to git\n\t\t//\n\t\t// Only suppress --keep-index for that case — when the selection actually includes untracked\n\t\t// files (`includeUntracked`) AND we're stashing by pathspec. Keying off `includeUntracked` (the\n\t\t// caller's intent) rather than the `--include-untracked` flag is deliberate: we add\n\t\t// `--include-untracked` to every pathspec push above as a safety net, but a tracked-only\n\t\t// selection can — and must — still keep the index intact.\n\t\tif (options?.keepIndex && !(options?.includeUntracked && options?.pathspecs?.length)) {\n\t\t\tparams.push('--keep-index');\n\t\t}\n\n\t\tif (options?.onlyStaged) {\n\t\t\tif (await this.git.supports('git:stash:push:staged')) {\n\t\t\t\tparams.push('--staged');\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tl10n.t(\n\t\t\t\t\t\t'Git version {0} or higher is required for --staged',\n\t\t\t\t\t\tString(gitFeaturesByVersion.get('git:stash:push:staged')),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (message) {\n\t\t\tparams.push('-m', message);\n\t\t}\n\n\t\tlet stdin;\n\t\tif (options?.pathspecs?.length) {\n\t\t\tif (options.stdin) {\n\t\t\t\tstdin = options.pathspecs.join('\\0');\n\t\t\t\tparams.push('--pathspec-from-file=-', '--pathspec-file-nul', '--');\n\t\t\t} else {\n\t\t\t\tparams.push('--', ...options.pathspecs);\n\t\t\t}\n\t\t} else {\n\t\t\tparams.push('--');\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await this.git.run({ cwd: repoPath, stdin: stdin }, ...params);\n\t\t\tif (GitErrors.stashNothingToSave.test(result.stdout)) {\n\t\t\t\tthrow new StashPushError({\n\t\t\t\t\treason: 'nothingToSave',\n\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof StashPushError) throw ex;\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'stash-push',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew StashPushError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@debug()\n\tasync saveSnapshot(repoPath: string, message?: string): Promise<void> {\n\t\tconst result = await this.git.run({ cwd: repoPath }, 'stash', 'create');\n\t\tconst id = result.stdout.trim() || undefined;\n\t\tif (id == null) return;\n\n\t\tconst args = [];\n\t\tif (message) {\n\t\t\targs.push('-m', message);\n\t\t}\n\t\tawait this.git.run({ cwd: repoPath }, 'stash', 'store', ...args, id);\n\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t}\n}\n\nexport function convertStashesToStdin(stashOrStashes: GitStash | ReadonlyMap<string, GitStashCommit> | undefined): {\n\treadonly stdin: string | undefined;\n\treadonly stashes: Map<string, GitStashCommit>;\n\treadonly remappedIds: Map<string, string>;\n} {\n\tconst remappedIds = new Map<string, string>();\n\tif (stashOrStashes == null) return { stdin: undefined, stashes: new Map(), remappedIds: remappedIds };\n\n\tlet stdin: string | undefined;\n\tconst original = 'stashes' in stashOrStashes ? stashOrStashes.stashes : stashOrStashes;\n\tconst stashes = new Map<string, GitStashCommit>(original);\n\n\tif (original.size) {\n\t\tstdin = '';\n\t\tfor (const stash of original.values()) {\n\t\t\tstdin += `${stash.sha.substring(0, 9)}\\n`;\n\t\t\t// Include the stash's 2nd (index files) and 3rd (untracked files) parents (if they aren't already in the map)\n\t\t\tfor (const p of skip(stash.parents, 1)) {\n\t\t\t\tremappedIds.set(p, stash.sha);\n\n\t\t\t\tif (!stashes.has(p)) {\n\t\t\t\t\tstashes.set(p, stash);\n\t\t\t\t\tstdin += `${p.substring(0, 9)}\\n`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { stdin: stdin || undefined, stashes: stashes, remappedIds: remappedIds };\n}\n\nconst stashSummaryRegex =\n\t// oxlint-disable-next-line no-control-regex\n\t/(?:(?:(?<wip>WIP) on|On) (?<onref>[^/](?!.*\\/\\.)(?!.*\\.\\.)(?!.*\\/\\/)(?!.*@\\{)[^\\x00-\\x1F\\x7F ~^:?*[\\\\]+[^./]):\\s*)?(?<summary>.*)$/s;\n\nfunction createStash(\n\ts: ParsedStash | ParsedStashWithFiles,\n\trepoPath: string,\n\tcurrentUser: GitUser | undefined,\n): GitStashCommit {\n\t// `onRef` comes from the commit subject (%s), which git always prefixes with `On <branch>: …`\n\t// or `WIP on <branch>: …`. This holds even when the reflog message was customized\n\t// (autostash, `git stash store -m \"…\"`), so it's a reliable source\n\tlet onRef: string | undefined;\n\tconst subjectMatch = stashSummaryRegex.exec((s.commitSubject ?? '').trim());\n\tif (subjectMatch?.groups?.onref) {\n\t\tonRef = subjectMatch.groups.onref;\n\t}\n\n\t// The user-visible display message is derived from the reflog subject (%gs) so that short\n\t// custom messages like \"wip\", \"q\", or \"show args\" stay as the user wrote them instead of\n\t// being replaced by the verbose git-auto subject\n\tlet message = s.summary.trim();\n\tconst reflogMatch = stashSummaryRegex.exec(message);\n\tif (reflogMatch?.groups != null) {\n\t\tconst summary = reflogMatch.groups.summary.trim();\n\t\tif (summary.length === 0) {\n\t\t\tmessage = 'WIP';\n\t\t} else if (reflogMatch.groups.wip) {\n\t\t\tmessage = `WIP: ${summary}`;\n\t\t} else {\n\t\t\tmessage = summary;\n\t\t}\n\t}\n\n\tconst index = message.indexOf('\\n');\n\n\treturn new GitCommit(\n\t\trepoPath,\n\t\ts.sha,\n\t\tnew GitCommitIdentity(\n\t\t\tcurrentUser?.name ?? '',\n\t\t\tcurrentUser?.email,\n\t\t\tnew Date(Number(s.authorDate) * 1000),\n\t\t\tundefined,\n\t\t\ttrue,\n\t\t),\n\t\tnew GitCommitIdentity(\n\t\t\tcurrentUser?.name ?? '',\n\t\t\tcurrentUser?.email,\n\t\t\tnew Date(Number(s.committedDate) * 1000),\n\t\t\tundefined,\n\t\t\ttrue,\n\t\t),\n\t\tindex !== -1 ? message.substring(0, index) : message,\n\t\ts.parents.split(' ') ?? [],\n\t\tmessage,\n\t\tcreateCommitFileset(s, repoPath, undefined),\n\t\ts.stats,\n\t\tundefined,\n\t\tundefined,\n\t\ts.stashName,\n\t\tonRef,\n\t) as GitStashCommit;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stash.js","names":[],"sources":["../../../../git-cli/src/providers/stash.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { StashApplyError, StashPushError } from '@gitlens/git/errors.js';\nimport type { GitStashCommit } from '@gitlens/git/models/commit.js';\nimport { GitCommit, GitCommitIdentity } from '@gitlens/git/models/commit.js';\nimport { GitFileChange } from '@gitlens/git/models/fileChange.js';\nimport type { GitFileStatus } from '@gitlens/git/models/fileStatus.js';\nimport { GitFileWorkingTreeStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitStash } from '@gitlens/git/models/stash.js';\nimport type { GitUser } from '@gitlens/git/models/user.js';\nimport type { GitOperationRunOptions } from '@gitlens/git/providers/operations.js';\nimport type { GitStashSubProvider, StashApplyResult } from '@gitlens/git/providers/stash.js';\nimport { countStringLength } from '@gitlens/utils/array.js';\nimport { isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { skip } from '@gitlens/utils/iterable.js';\nimport { normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fileUri, joinUriPath, toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport { gitFeaturesByVersion } from '../exec/features.js';\nimport type { Git } from '../exec/git.js';\nimport { getGitCommandError, GitError, GitErrors, maxGitCliLength } from '../exec/git.js';\nimport type { ParsedStash, ParsedStashWithFiles } from '../parsers/logParser.js';\nimport { getStashFilesOnlyLogParser, getStashLogParser } from '../parsers/logParser.js';\nimport { createCommitFileset } from './commitFilesetUtils.js';\n\nexport class StashGitSubProvider implements GitStashSubProvider {\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@gate()\n\t@debug()\n\tasync applyStash(\n\t\trepoPath: string,\n\t\tstashNameOrSha: string,\n\t\toptions?: { deleteAfter?: boolean; index?: boolean },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<StashApplyResult> {\n\t\tif (!stashNameOrSha) return { conflicted: false };\n\n\t\tconst args = ['stash', options?.deleteAfter ? 'pop' : 'apply'];\n\t\tif (options?.index) {\n\t\t\targs.push('--index');\n\t\t}\n\t\targs.push(stashNameOrSha);\n\t\treturn this.applyStashCore(repoPath, args, options?.deleteAfter ? 'stash-pop' : 'stash-apply', runOptions);\n\t}\n\n\tprivate async applyStashCore(\n\t\trepoPath: string,\n\t\targs: string[],\n\t\tconflictCommand: 'stash-apply' | 'stash-pop',\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<StashApplyResult> {\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, ...runOptions }, ...args);\n\t\t\treturn { conflicted: false };\n\t\t} catch (ex) {\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tif (ex instanceof Error) {\n\t\t\t\tconst msg: string = ex.message ?? '';\n\t\t\t\tif (\n\t\t\t\t\t(msg.includes('Auto-merging') && msg.includes('CONFLICT')) ||\n\t\t\t\t\t(ex instanceof GitError &&\n\t\t\t\t\t\t((ex.stdout?.includes('Auto-merging') && ex.stdout.includes('CONFLICT')) ||\n\t\t\t\t\t\t\tex.stdout?.includes('needs merge')))\n\t\t\t\t) {\n\t\t\t\t\tthis.context.hooks?.operations?.onConflicted?.(conflictCommand);\n\t\t\t\t\treturn { conflicted: true };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'stash-apply',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew StashApplyError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t} finally {\n\t\t\t// A conflicted, failed or cancelled apply may already have changed the stash list or working tree\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\t}\n\t}\n\n\t@debug()\n\tasync createStash(repoPath: string, message?: string): Promise<string | undefined> {\n\t\tconst args = ['stash', 'create'];\n\t\tif (message) {\n\t\t\targs.push(message);\n\t\t}\n\n\t\tconst result = await this.git.run({ cwd: repoPath }, ...args);\n\t\treturn result.stdout.trim() || undefined;\n\t}\n\n\t@debug()\n\tasync getStash(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tincludeFiles?: boolean;\n\t\t\treachableFrom?: string;\n\t\t\tsimilarityThreshold?: number | null;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStash | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\t// Resolve options against config up front so the cache key reflects the actual values used\n\t\t// to produce the cached payload — undefined inputs aren't conflated across config changes.\n\t\tconst cfg = this.context.config;\n\t\tconst includeFiles = options?.includeFiles ?? cfg?.commits.includeFileDetails?.(repoPath) ?? true;\n\t\tconst similarityThreshold = includeFiles\n\t\t\t? (options?.similarityThreshold ?? cfg?.commits.similarityThreshold ?? null)\n\t\t\t: null;\n\t\tconst reachableFrom = options?.reachableFrom;\n\n\t\t// Cache only the unfiltered stash list; reachability projection runs below by testing each\n\t\t// distinct stash parent against `reachableFrom` directly, so re-projecting is cheap\n\t\tconst cacheKey = `f${includeFiles ? 1 : 0}|s${similarityThreshold ?? ''}`;\n\n\t\tconst stash = await this.cache.getStash(\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tasync (commonPath, _cacheable, signal) => {\n\t\t\t\t// Prefer the aggregate signal from the cache; fall back to the caller's cancellation.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst parser = getStashLogParser(includeFiles);\n\t\t\t\tconst args = [...parser.arguments];\n\n\t\t\t\tif (includeFiles) {\n\t\t\t\t\targs.push(`-M${similarityThreshold == null ? '' : `${similarityThreshold}%`}`);\n\t\t\t\t}\n\n\t\t\t\tconst result = await this.git.run({ cwd: repoPath, cancellation: signal }, 'stash', 'list', ...args);\n\n\t\t\t\tconst currentUser = await this.provider.config.getCurrentUser(repoPath);\n\n\t\t\t\tconst stashes = new Map<string, GitStashCommit>();\n\t\t\t\tfor (const s of parser.parse(result.stdout)) {\n\t\t\t\t\tstashes.set(s.sha, createStash(s, commonPath, currentUser));\n\t\t\t\t}\n\n\t\t\t\treturn { repoPath: commonPath, stashes: stashes };\n\t\t\t},\n\t\t\t{ cancellation: cancellation },\n\t\t);\n\n\t\tif (stash == null || !reachableFrom || !stash.stashes.size) return stash;\n\n\t\t// Copy because the cached `stash.stashes` map is shared and must not be mutated.\n\t\tconst stashes = new Map(stash.stashes);\n\n\t\tconst reachableStashes = new Set<string>();\n\n\t\t// Metadata pass: a stash belongs on `reachableFrom` iff git's auto-prepended\n\t\t// `On <branch>: …` (or `WIP on <branch>: …`) prefix in the stash commit subject names\n\t\t// this branch. `stashOnRef` is parsed from %s in createStash, so this covers autostashes\n\t\t// and custom-reflog stashes too.\n\t\tfor (const [sha, s] of stash.stashes) {\n\t\t\tif (s.stashOnRef === reachableFrom) {\n\t\t\t\treachableStashes.add(sha);\n\t\t\t}\n\t\t}\n\n\t\t// Transitive pass for the rare detached-HEAD-on-stash chain (stash B created while HEAD\n\t\t// pointed at stash A). Such stashes have no `stashOnRef`, but if their parent is a stash\n\t\t// already marked reachable they should follow.\n\t\tlet changed;\n\t\tdo {\n\t\t\tchanged = false;\n\t\t\tfor (const [sha, s] of stash.stashes) {\n\t\t\t\tif (!reachableStashes.has(sha) && s.parents.some(p => reachableStashes.has(p))) {\n\t\t\t\t\treachableStashes.add(sha);\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (changed);\n\n\t\tfor (const [sha] of stash.stashes) {\n\t\t\tif (!reachableStashes.has(sha)) {\n\t\t\t\tstashes.delete(sha);\n\t\t\t}\n\t\t}\n\n\t\treturn { ...stash, stashes: stashes };\n\t}\n\n\t@debug()\n\tasync getStashCommitFiles(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { similarityThreshold?: number | null },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitFileChange[]> {\n\t\tconst [stashFilesResult, stashUntrackedFilesResult] = await Promise.allSettled([\n\t\t\t// Don't include untracked files here, because we won't be able to tell them apart from added (and we need the untracked status)\n\t\t\tthis.getStashCommitFilesCore(repoPath, ref, { untracked: false, ...options }, cancellation),\n\t\t\t// Check for any untracked files -- since git doesn't return them via `git stash list` :(\n\t\t\t// See https://stackoverflow.com/questions/12681529/\n\t\t\tthis.getStashCommitFilesCore(repoPath, ref, { untracked: 'only', ...options }, cancellation),\n\t\t]);\n\n\t\tlet files = getSettledValue(stashFilesResult);\n\t\tconst untrackedFiles = getSettledValue(stashUntrackedFilesResult);\n\n\t\tif (files?.length && untrackedFiles?.length) {\n\t\t\tfiles.push(...untrackedFiles);\n\t\t} else {\n\t\t\tfiles = files ?? untrackedFiles;\n\t\t}\n\n\t\treturn files ?? [];\n\t}\n\n\tprivate async getStashCommitFilesCore(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { similarityThreshold?: number | null; untracked?: boolean | 'only' },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitFileChange[] | undefined> {\n\t\tconst args = [];\n\t\tif (options?.untracked) {\n\t\t\targs.push(options?.untracked === 'only' ? '--only-untracked' : '--include-untracked');\n\t\t}\n\n\t\tconst similarityThreshold = options?.similarityThreshold ?? this.context.config?.commits.similarityThreshold;\n\t\tif (similarityThreshold != null) {\n\t\t\targs.push(`-M${similarityThreshold}%`);\n\t\t}\n\n\t\tconst parser = getStashFilesOnlyLogParser();\n\t\tconst result = await this.git.run(\n\t\t\t{ cwd: repoPath, cancellation: cancellation },\n\t\t\t'stash',\n\t\t\t'show',\n\t\t\t...args,\n\t\t\t...parser.arguments,\n\t\t\tref,\n\t\t);\n\n\t\tconst repoUri = fileUri(normalizePath(repoPath));\n\t\tfor (const s of parser.parse(result.stdout)) {\n\t\t\treturn (\n\t\t\t\ts.files?.map(\n\t\t\t\t\tf =>\n\t\t\t\t\t\tnew GitFileChange(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\tf.path,\n\t\t\t\t\t\t\t(options?.untracked === 'only'\n\t\t\t\t\t\t\t\t? GitFileWorkingTreeStatus.Untracked\n\t\t\t\t\t\t\t\t: f.status) as GitFileStatus,\n\t\t\t\t\t\t\tjoinUriPath(repoUri, normalizePath(f.path)),\n\t\t\t\t\t\t\tf.originalPath,\n\t\t\t\t\t\t\tf.originalPath != null ? joinUriPath(repoUri, normalizePath(f.originalPath)) : undefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tf.additions || f.deletions\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tadditions: f.additions ?? 0,\n\t\t\t\t\t\t\t\t\t\tdeletions: f.deletions ?? 0,\n\t\t\t\t\t\t\t\t\t\tchanges: 0,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tf.mode,\n\t\t\t\t\t\t),\n\t\t\t\t) ?? []\n\t\t\t);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t@debug()\n\tasync deleteStash(repoPath: string, stashName: string, sha?: string): Promise<void> {\n\t\tawait this.deleteStashCore(repoPath, stashName, sha);\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t}\n\n\t@gate()\n\tprivate async deleteStashCore(repoPath: string, stashName: string, sha?: string): Promise<string | undefined> {\n\t\tif (!stashName) return undefined;\n\n\t\tlet result;\n\t\tif (sha) {\n\t\t\tresult = await this.git.run(\n\t\t\t\t{ cwd: repoPath, errors: 'ignore' },\n\t\t\t\t'show',\n\t\t\t\t'--format=%H',\n\t\t\t\t'--no-patch',\n\t\t\t\tstashName,\n\t\t\t);\n\t\t\tif (result.stdout.trim() !== sha) {\n\t\t\t\tthrow new Error(l10n.t('Unable to delete stash; mismatch with stash number'));\n\t\t\t}\n\t\t}\n\n\t\tresult = await this.git.run({ cwd: repoPath }, 'stash', 'drop', stashName);\n\t\treturn result.stdout;\n\t}\n\n\t@debug()\n\tasync renameStash(\n\t\trepoPath: string,\n\t\tstashName: string,\n\t\tsha: string,\n\t\tmessage: string,\n\t\tstashOnRef?: string,\n\t): Promise<void> {\n\t\tawait this.deleteStashCore(repoPath, stashName, sha);\n\t\tawait this.git.run(\n\t\t\t{ cwd: repoPath },\n\t\t\t'stash',\n\t\t\t'store',\n\t\t\t'-m',\n\t\t\tstashOnRef ? `On ${stashOnRef}: ${message}` : message,\n\t\t\tsha,\n\t\t);\n\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t}\n\n\t@debug({ args: (repoPath, message, paths) => ({ repoPath: repoPath, message: message, paths: paths?.length }) })\n\tasync saveStash(\n\t\trepoPath: string,\n\t\tmessage?: string,\n\t\tpathsOrUris?: (string | Uri)[],\n\t\toptions?: { includeUntracked?: boolean; keepIndex?: boolean; onlyStaged?: boolean },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst paths = pathsOrUris?.map(toFsPath);\n\t\tif (!paths?.length) {\n\t\t\tawait this.stashPushCore(repoPath, message, options, runOptions);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.git.ensureSupports('git:stash:push:pathspecs', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Stashing individual files requires a newer version of Git (>= {0}) than is currently installed ({1}). Please retry by stashing everything or install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tconst pathspecs = paths.map(p => `./${splitPath(p, repoPath)[0]}`);\n\n\t\tlet stdin = await this.git.supports('git:stash:push:stdin');\n\t\tif (stdin && options?.onlyStaged && paths.length) {\n\t\t\t// Since Git doesn't support --staged with --pathspec-from-file try to pass them in directly\n\t\t\tstdin = false;\n\t\t}\n\n\t\t// If we don't support stdin, then error out if we are over the maximum allowed git cli length\n\t\tif (!stdin && countStringLength(pathspecs) > maxGitCliLength) {\n\t\t\tawait this.git.ensureSupports('git:stash:push:stdin', (requiredVersion, installedVersion) =>\n\t\t\t\tl10n.t(\n\t\t\t\t\t'Stashing so many files ({0}) at once requires a newer version of Git (>= {1}) than is currently installed ({2}). Please retry by stashing fewer files or install a more recent version of Git and try again.',\n\t\t\t\t\tpathspecs.length,\n\t\t\t\t\trequiredVersion,\n\t\t\t\t\tinstalledVersion,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tawait this.stashPushCore(\n\t\t\trepoPath,\n\t\t\tmessage,\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tpathspecs: pathspecs,\n\t\t\t\tstdin: stdin,\n\t\t\t},\n\t\t\trunOptions,\n\t\t);\n\t}\n\n\tprivate async stashPushCore(\n\t\trepoPath: string,\n\t\tmessage?: string,\n\t\toptions?: {\n\t\t\tincludeUntracked?: boolean;\n\t\t\tkeepIndex?: boolean;\n\t\t\tonlyStaged?: boolean;\n\t\t\tpathspecs?: string[];\n\t\t\tstdin?: boolean;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst params = ['stash', 'push'];\n\n\t\tif ((options?.includeUntracked || options?.pathspecs?.length) && !options?.onlyStaged) {\n\t\t\tparams.push('--include-untracked');\n\t\t}\n\n\t\t// `git stash push --keep-index --include-untracked -- <pathspec>` hits a bug in git when the\n\t\t// pathspec names an untracked file: the restoring checkout can't match an untracked path in the\n\t\t// index tree, so it fails and the staged changes are lost.\n\t\t//\n\t\t// $ mkdir stash-test && cd stash-test && git init\n\t\t// $ echo a > a.txt\n\t\t// $ git add a.txt\n\t\t// $ git commit -m init\n\t\t// $ echo b > b.txt\n\t\t// $ git stash push --keep-index --include-untracked -- b.txt\n\t\t// Saved working directory and index state WIP on main: 8a280fe init\n\t\t// error: pathspec ':(prefix:0)b.txt' did not match any file(s) known to git\n\t\t//\n\t\t// Only suppress --keep-index for that case — when the selection actually includes untracked\n\t\t// files (`includeUntracked`) AND we're stashing by pathspec. Keying off `includeUntracked` (the\n\t\t// caller's intent) rather than the `--include-untracked` flag is deliberate: we add\n\t\t// `--include-untracked` to every pathspec push above as a safety net, but a tracked-only\n\t\t// selection can — and must — still keep the index intact.\n\t\tif (options?.keepIndex && !(options?.includeUntracked && options?.pathspecs?.length)) {\n\t\t\tparams.push('--keep-index');\n\t\t}\n\n\t\tif (options?.onlyStaged) {\n\t\t\tif (await this.git.supports('git:stash:push:staged')) {\n\t\t\t\tparams.push('--staged');\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tl10n.t(\n\t\t\t\t\t\t'Git version {0} or higher is required for --staged',\n\t\t\t\t\t\tString(gitFeaturesByVersion.get('git:stash:push:staged')),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (message) {\n\t\t\tparams.push('-m', message);\n\t\t}\n\n\t\tlet stdin;\n\t\tif (options?.pathspecs?.length) {\n\t\t\tif (options.stdin) {\n\t\t\t\tstdin = options.pathspecs.join('\\0');\n\t\t\t\tparams.push('--pathspec-from-file=-', '--pathspec-file-nul', '--');\n\t\t\t} else {\n\t\t\t\tparams.push('--', ...options.pathspecs);\n\t\t\t}\n\t\t} else {\n\t\t\tparams.push('--');\n\t\t}\n\n\t\tlet nothingToSave = false;\n\t\ttry {\n\t\t\tconst result = await this.git.run({ cwd: repoPath, ...runOptions, stdin: stdin }, ...params);\n\t\t\tif (GitErrors.stashNothingToSave.test(result.stdout)) {\n\t\t\t\tnothingToSave = true;\n\t\t\t\tthrow new StashPushError({\n\t\t\t\t\treason: 'nothingToSave',\n\t\t\t\t\tgitCommand: { repoPath: repoPath, args: params },\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof StashPushError || isCancellationError(ex)) throw ex;\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'stash-push',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew StashPushError(\n\t\t\t\t\t\t{ reason: reason ?? 'other', gitCommand: { repoPath: repoPath, args: params } },\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t} finally {\n\t\t\t// A failed or cancelled push may already have stashed, and reset the working tree; one with nothing to\n\t\t\t// save changed nothing\n\t\t\tif (!nothingToSave) {\n\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes', 'status');\n\t\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug()\n\tasync saveSnapshot(repoPath: string, message?: string): Promise<void> {\n\t\tconst result = await this.git.run({ cwd: repoPath }, 'stash', 'create');\n\t\tconst id = result.stdout.trim() || undefined;\n\t\tif (id == null) return;\n\n\t\tconst args = [];\n\t\tif (message) {\n\t\t\targs.push('-m', message);\n\t\t}\n\t\tawait this.git.run({ cwd: repoPath }, 'stash', 'store', ...args, id);\n\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t}\n}\n\nexport function convertStashesToStdin(stashOrStashes: GitStash | ReadonlyMap<string, GitStashCommit> | undefined): {\n\treadonly stdin: string | undefined;\n\treadonly stashes: Map<string, GitStashCommit>;\n\treadonly remappedIds: Map<string, string>;\n} {\n\tconst remappedIds = new Map<string, string>();\n\tif (stashOrStashes == null) return { stdin: undefined, stashes: new Map(), remappedIds: remappedIds };\n\n\tlet stdin: string | undefined;\n\tconst original = 'stashes' in stashOrStashes ? stashOrStashes.stashes : stashOrStashes;\n\tconst stashes = new Map<string, GitStashCommit>(original);\n\n\tif (original.size) {\n\t\tstdin = '';\n\t\tfor (const stash of original.values()) {\n\t\t\tstdin += `${stash.sha.substring(0, 9)}\\n`;\n\t\t\t// Include the stash's 2nd (index files) and 3rd (untracked files) parents (if they aren't already in the map)\n\t\t\tfor (const p of skip(stash.parents, 1)) {\n\t\t\t\tremappedIds.set(p, stash.sha);\n\n\t\t\t\tif (!stashes.has(p)) {\n\t\t\t\t\tstashes.set(p, stash);\n\t\t\t\t\tstdin += `${p.substring(0, 9)}\\n`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { stdin: stdin || undefined, stashes: stashes, remappedIds: remappedIds };\n}\n\nconst stashSummaryRegex =\n\t// oxlint-disable-next-line no-control-regex\n\t/(?:(?:(?<wip>WIP) on|On) (?<onref>[^/](?!.*\\/\\.)(?!.*\\.\\.)(?!.*\\/\\/)(?!.*@\\{)[^\\x00-\\x1F\\x7F ~^:?*[\\\\]+[^./]):\\s*)?(?<summary>.*)$/s;\n\nfunction createStash(\n\ts: ParsedStash | ParsedStashWithFiles,\n\trepoPath: string,\n\tcurrentUser: GitUser | undefined,\n): GitStashCommit {\n\t// `onRef` comes from the commit subject (%s), which git always prefixes with `On <branch>: …`\n\t// or `WIP on <branch>: …`. This holds even when the reflog message was customized\n\t// (autostash, `git stash store -m \"…\"`), so it's a reliable source\n\tlet onRef: string | undefined;\n\tconst subjectMatch = stashSummaryRegex.exec((s.commitSubject ?? '').trim());\n\tif (subjectMatch?.groups?.onref) {\n\t\tonRef = subjectMatch.groups.onref;\n\t}\n\n\t// The user-visible display message is derived from the reflog subject (%gs) so that short\n\t// custom messages like \"wip\", \"q\", or \"show args\" stay as the user wrote them instead of\n\t// being replaced by the verbose git-auto subject\n\tlet message = s.summary.trim();\n\tconst reflogMatch = stashSummaryRegex.exec(message);\n\tif (reflogMatch?.groups != null) {\n\t\tconst summary = reflogMatch.groups.summary.trim();\n\t\tif (summary.length === 0) {\n\t\t\tmessage = 'WIP';\n\t\t} else if (reflogMatch.groups.wip) {\n\t\t\tmessage = `WIP: ${summary}`;\n\t\t} else {\n\t\t\tmessage = summary;\n\t\t}\n\t}\n\n\tconst index = message.indexOf('\\n');\n\n\treturn new GitCommit(\n\t\trepoPath,\n\t\ts.sha,\n\t\tnew GitCommitIdentity(\n\t\t\tcurrentUser?.name ?? '',\n\t\t\tcurrentUser?.email,\n\t\t\tnew Date(Number(s.authorDate) * 1000),\n\t\t\tundefined,\n\t\t\ttrue,\n\t\t),\n\t\tnew GitCommitIdentity(\n\t\t\tcurrentUser?.name ?? '',\n\t\t\tcurrentUser?.email,\n\t\t\tnew Date(Number(s.committedDate) * 1000),\n\t\t\tundefined,\n\t\t\ttrue,\n\t\t),\n\t\tindex !== -1 ? message.substring(0, index) : message,\n\t\ts.parents.split(' ') ?? [],\n\t\tmessage,\n\t\tcreateCommitFileset(s, repoPath, undefined),\n\t\ts.stats,\n\t\tundefined,\n\t\tundefined,\n\t\ts.stashName,\n\t\tonRef,\n\t) as GitStashCommit;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA8BA,IAAa,sBAAb,MAAgE;CAE7C;CACA;CACA;CACA;CAJlB,YACC,SACA,KACA,OACA,UACC;EAJgB,KAAA,UAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACf;CAEH,MAEM,WACL,UACA,gBACA,SACA,YAC4B;EAC5B,IAAI,CAAC,gBAAgB,OAAO,EAAE,YAAY,MAAM;EAEhD,MAAM,OAAO,CAAC,SAAS,SAAS,cAAc,QAAQ,OAAO;EAC7D,IAAI,SAAS,OACZ,KAAK,KAAK,SAAS;EAEpB,KAAK,KAAK,cAAc;EACxB,OAAO,KAAK,eAAe,UAAU,MAAM,SAAS,cAAc,cAAc,eAAe,UAAU;CAC1G;CAEA,MAAc,eACb,UACA,MACA,iBACA,YAC4B;EAC5B,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,GAAG;GAAW,GAAG,GAAG,IAAI;GAC5D,OAAO,EAAE,YAAY,MAAM;EAC5B,SAAS,IAAI;GACZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;GAEnC,IAAI,cAAc,OAAO;IACxB,MAAM,MAAc,GAAG,WAAW;IAClC,IACE,IAAI,SAAS,cAAc,KAAK,IAAI,SAAS,UAAU,KACvD,cAAc,aACZ,GAAG,QAAQ,SAAS,cAAc,KAAK,GAAG,OAAO,SAAS,UAAU,KACrE,GAAG,QAAQ,SAAS,aAAa,IAClC;KACD,KAAK,QAAQ,OAAO,YAAY,eAAe,eAAe;KAC9D,OAAO,EAAE,YAAY,KAAK;IAC3B;GACD;GAEA,MAAM,mBACL,eACA,KACA,WACC,IAAI,gBACH;IAAE,QAAQ,UAAU;IAAS,YAAY;KAAY;KAAgB;IAAK;GAAE,GAC5E,EACD,CACF;EACD,UAAU;GAET,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW,QAAQ;GAClE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;EAChE;CACD;CAEA,MACM,YAAY,UAAkB,SAA+C;EAClF,MAAM,OAAO,CAAC,SAAS,QAAQ;EAC/B,IAAI,SACH,KAAK,KAAK,OAAO;EAIlB,QAAO,MADc,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,GAAG,IAAI,EAAA,CAC9C,OAAO,KAAK,KAAK,KAAA;CAChC;CAEA,MACM,SACL,UACA,SAKA,cACgC;EAChC,IAAI,YAAY,MAAM,OAAO,KAAA;EAI7B,MAAM,MAAM,KAAK,QAAQ;EACzB,MAAM,eAAe,SAAS,gBAAgB,KAAK,QAAQ,qBAAqB,QAAQ,KAAK;EAC7F,MAAM,sBAAsB,eACxB,SAAS,uBAAuB,KAAK,QAAQ,uBAAuB,OACrE;EACH,MAAM,gBAAgB,SAAS;EAI/B,MAAM,WAAW,IAAI,eAAe,IAAI,EAAE,IAAI,uBAAuB;EAErE,MAAM,QAAQ,MAAM,KAAK,MAAM,SAC9B,UACA,UACA,OAAO,YAAY,YAAY,WAAW;GAEzC,WAAW;GACX,MAAM,SAAS,kBAAkB,YAAY;GAC7C,MAAM,OAAO,CAAC,GAAG,OAAO,SAAS;GAEjC,IAAI,cACH,KAAK,KAAK,KAAK,uBAAuB,OAAO,KAAK,GAAG,oBAAoB,IAAI;GAG9E,MAAM,SAAS,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,cAAc;GAAO,GAAG,SAAS,QAAQ,GAAG,IAAI;GAEnG,MAAM,cAAc,MAAM,KAAK,SAAS,OAAO,eAAe,QAAQ;GAEtE,MAAM,0BAAU,IAAI,IAA4B;GAChD,KAAK,MAAM,KAAK,OAAO,MAAM,OAAO,MAAM,GACzC,QAAQ,IAAI,EAAE,KAAK,YAAY,GAAG,YAAY,WAAW,CAAC;GAG3D,OAAO;IAAE,UAAU;IAAqB;GAAQ;EACjD,GACA,EAAgB,aAAa,CAC9B;EAEA,IAAI,SAAS,QAAQ,CAAC,iBAAiB,CAAC,MAAM,QAAQ,MAAM,OAAO;EAGnE,MAAM,UAAU,IAAI,IAAI,MAAM,OAAO;EAErC,MAAM,mCAAmB,IAAI,IAAY;EAMzC,KAAK,MAAM,CAAC,KAAK,MAAM,MAAM,SAC5B,IAAI,EAAE,eAAe,eACpB,iBAAiB,IAAI,GAAG;EAO1B,IAAI;EACJ,GAAG;GACF,UAAU;GACV,KAAK,MAAM,CAAC,KAAK,MAAM,MAAM,SAC5B,IAAI,CAAC,iBAAiB,IAAI,GAAG,KAAK,EAAE,QAAQ,MAAK,MAAK,iBAAiB,IAAI,CAAC,CAAC,GAAG;IAC/E,iBAAiB,IAAI,GAAG;IACxB,UAAU;GACX;EAEF,SAAS;EAET,KAAK,MAAM,CAAC,QAAQ,MAAM,SACzB,IAAI,CAAC,iBAAiB,IAAI,GAAG,GAC5B,QAAQ,OAAO,GAAG;EAIpB,OAAO;GAAE,GAAG;GAAgB;EAAQ;CACrC;CAEA,MACM,oBACL,UACA,KACA,SACA,cAC2B;EAC3B,MAAM,CAAC,kBAAkB,6BAA6B,MAAM,QAAQ,WAAW,CAE9E,KAAK,wBAAwB,UAAU,KAAK;GAAE,WAAW;GAAO,GAAG;EAAQ,GAAG,YAAY,GAG1F,KAAK,wBAAwB,UAAU,KAAK;GAAE,WAAW;GAAQ,GAAG;EAAQ,GAAG,YAAY,CAC5F,CAAC;EAED,IAAI,QAAQ,gBAAgB,gBAAgB;EAC5C,MAAM,iBAAiB,gBAAgB,yBAAyB;EAEhE,IAAI,OAAO,UAAU,gBAAgB,QACpC,MAAM,KAAK,GAAG,cAAc;OAE5B,QAAQ,SAAS;EAGlB,OAAO,SAAS,CAAC;CAClB;CAEA,MAAc,wBACb,UACA,KACA,SACA,cACuC;EACvC,MAAM,OAAO,CAAC;EACd,IAAI,SAAS,WACZ,KAAK,KAAK,SAAS,cAAc,SAAS,qBAAqB,qBAAqB;EAGrF,MAAM,sBAAsB,SAAS,uBAAuB,KAAK,QAAQ,QAAQ,QAAQ;EACzF,IAAI,uBAAuB,MAC1B,KAAK,KAAK,KAAK,oBAAoB,EAAE;EAGtC,MAAM,SAAS,2BAA2B;EAC1C,MAAM,SAAS,MAAM,KAAK,IAAI,IAC7B;GAAE,KAAK;GAAwB;EAAa,GAC5C,SACA,QACA,GAAG,MACH,GAAG,OAAO,WACV,GACD;EAEA,MAAM,UAAU,QAAQ,cAAc,QAAQ,CAAC;EAC/C,KAAK,MAAM,KAAK,OAAO,MAAM,OAAO,MAAM,GACzC,OACC,EAAE,OAAO,KACR,MACC,IAAI,cACH,UACA,EAAE,MACD,SAAS,cAAc,SACrB,yBAAyB,YACzB,EAAE,QACL,YAAY,SAAS,cAAc,EAAE,IAAI,CAAC,GAC1C,EAAE,cACF,EAAE,gBAAgB,OAAO,YAAY,SAAS,cAAc,EAAE,YAAY,CAAC,IAAI,KAAA,GAC/E,KAAA,GACA,EAAE,aAAa,EAAE,YACd;GACA,WAAW,EAAE,aAAa;GAC1B,WAAW,EAAE,aAAa;GAC1B,SAAS;EACV,IACC,KAAA,GACH,KAAA,GACA,KAAA,GACA,EAAE,IACH,CACF,KAAK,CAAC;CAKT;CAEA,MACM,YAAY,UAAkB,WAAmB,KAA6B;EACnF,MAAM,KAAK,gBAAgB,UAAU,WAAW,GAAG;EACnD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;EAC/D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,SAAS;CACzD;CAEA,MACc,gBAAgB,UAAkB,WAAmB,KAA2C;EAC7G,IAAI,CAAC,WAAW,OAAO,KAAA;EAEvB,IAAI;EACJ,IAAI,KAAK;GACR,SAAS,MAAM,KAAK,IAAI,IACvB;IAAE,KAAK;IAAU,QAAQ;GAAS,GAClC,QACA,eACA,cACA,SACD;GACA,IAAI,OAAO,OAAO,KAAK,MAAM,KAC5B,MAAM,IAAI,MAAM,KAAK,EAAE,oDAAoD,CAAC;EAE9E;EAEA,SAAS,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,SAAS,QAAQ,SAAS;EACzE,OAAO,OAAO;CACf;CAEA,MACM,YACL,UACA,WACA,KACA,SACA,YACgB;EAChB,MAAM,KAAK,gBAAgB,UAAU,WAAW,GAAG;EACnD,MAAM,KAAK,IAAI,IACd,EAAE,KAAK,SAAS,GAChB,SACA,SACA,MACA,aAAa,MAAM,WAAW,IAAI,YAAY,SAC9C,GACD;EAEA,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;EAC/D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,SAAS;CACzD;CAEA,MACM,UACL,UACA,SACA,aACA,SACA,YACgB;EAChB,MAAM,QAAQ,aAAa,IAAI,QAAQ;EACvC,IAAI,CAAC,OAAO,QAAQ;GACnB,MAAM,KAAK,cAAc,UAAU,SAAS,SAAS,UAAU;GAC/D;EACD;EAEA,MAAM,KAAK,IAAI,eAAe,6BAA6B,iBAAiB,qBAC3E,KAAK,EACJ,oMACA,iBACA,gBACD,CACD;EAEA,MAAM,YAAY,MAAM,KAAI,MAAK,KAAK,UAAU,GAAG,QAAQ,CAAC,CAAC,IAAI;EAEjE,IAAI,QAAQ,MAAM,KAAK,IAAI,SAAS,sBAAsB;EAC1D,IAAI,SAAS,SAAS,cAAc,MAAM,QAEzC,QAAQ;EAIT,IAAI,CAAC,SAAS,kBAAkB,SAAS,IAAA,KACxC,MAAM,KAAK,IAAI,eAAe,yBAAyB,iBAAiB,qBACvE,KAAK,EACJ,gNACA,UAAU,QACV,iBACA,gBACD,CACD;EAGD,MAAM,KAAK,cACV,UACA,SACA;GACC,GAAG;GACQ;GACJ;EACR,GACA,UACD;CACD;CAEA,MAAc,cACb,UACA,SACA,SAOA,YACgB;EAChB,MAAM,SAAS,CAAC,SAAS,MAAM;EAE/B,KAAK,SAAS,oBAAoB,SAAS,WAAW,WAAW,CAAC,SAAS,YAC1E,OAAO,KAAK,qBAAqB;EAqBlC,IAAI,SAAS,aAAa,EAAE,SAAS,oBAAoB,SAAS,WAAW,SAC5E,OAAO,KAAK,cAAc;EAG3B,IAAI,SAAS,YAAY;GACxB,IAAI,MAAM,KAAK,IAAI,SAAS,uBAAuB,GAClD,OAAO,KAAK,UAAU;QAEtB,MAAM,IAAI,MACT,KAAK,EACJ,sDACA,OAAO,qBAAqB,IAAI,uBAAuB,CAAC,CACzD,CACD;EAEF;EAEA,IAAI,SACH,OAAO,KAAK,MAAM,OAAO;EAG1B,IAAI;EACJ,IAAI,SAAS,WAAW,QAAQ;GAC/B,IAAI,QAAQ,OAAO;IAClB,QAAQ,QAAQ,UAAU,KAAK,IAAI;IACnC,OAAO,KAAK,0BAA0B,uBAAuB,IAAI;GAClE,OACC,OAAO,KAAK,MAAM,GAAG,QAAQ,SAAS;EAExC,OACC,OAAO,KAAK,IAAI;EAGjB,IAAI,gBAAgB;EACpB,IAAI;GACH,MAAM,SAAS,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,GAAG;IAAmB;GAAM,GAAG,GAAG,MAAM;GAC3F,IAAI,UAAU,mBAAmB,KAAK,OAAO,MAAM,GAAG;IACrD,gBAAgB;IAChB,MAAM,IAAI,eAAe;KACxB,QAAQ;KACR,YAAY;MAAY;MAAU,MAAM;KAAO;IAChD,CAAC;GACF;EACD,SAAS,IAAI;GACZ,IAAI,cAAc,kBAAkB,oBAAoB,EAAE,GAAG,MAAM;GAEnE,MAAM,mBACL,cACA,KACA,WACC,IAAI,eACH;IAAE,QAAQ,UAAU;IAAS,YAAY;KAAY;KAAU,MAAM;IAAO;GAAE,GAC9E,EACD,CACF;EACD,UAAU;GAGT,IAAI,CAAC,eAAe;IACnB,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW,QAAQ;IAClE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;GAChE;EACD;CACD;CAEA,MACM,aAAa,UAAkB,SAAiC;EAErE,MAAM,MAAK,MADU,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,SAAS,QAAQ,EAAA,CACpD,OAAO,KAAK,KAAK,KAAA;EACnC,IAAI,MAAM,MAAM;EAEhB,MAAM,OAAO,CAAC;EACd,IAAI,SACH,KAAK,KAAK,MAAM,OAAO;EAExB,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,SAAS,SAAS,GAAG,MAAM,EAAE;EAEnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;EAC/D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,SAAS;CACzD;AACD;AArdE,WAAA,CAAA,KAAK,GACL,MAAM,CAAA,GAAA,oBAAA,WAAA,cAAA,IAAA;AA0DN,WAAA,CAAA,MAAM,CAAA,GAAA,oBAAA,WAAA,eAAA,IAAA;AAWN,WAAA,CAAA,MAAM,CAAA,GAAA,oBAAA,WAAA,YAAA,IAAA;AA4FN,WAAA,CAAA,MAAM,CAAA,GAAA,oBAAA,WAAA,uBAAA,IAAA;AAsFN,WAAA,CAAA,MAAM,CAAA,GAAA,oBAAA,WAAA,eAAA,IAAA;AAON,WAAA,CAAA,KAAK,CAAA,GAAA,oBAAA,WAAA,mBAAA,IAAA;AAsBL,WAAA,CAAA,MAAM,CAAA,GAAA,oBAAA,WAAA,eAAA,IAAA;AAsBN,WAAA,CAAA,MAAM,EAAE,OAAO,UAAU,SAAS,WAAW;CAAY;CAAmB;CAAS,OAAO,OAAO;AAAO,GAAG,CAAC,CAAA,GAAA,oBAAA,WAAA,aAAA,IAAA;AA2J9G,WAAA,CAAA,MAAM,CAAA,GAAA,oBAAA,WAAA,gBAAA,IAAA;AAiBR,SAAgB,sBAAsB,gBAIpC;CACD,MAAM,8BAAc,IAAI,IAAoB;CAC5C,IAAI,kBAAkB,MAAM,OAAO;EAAE,OAAO,KAAA;EAAW,yBAAS,IAAI,IAAI;EAAgB;CAAY;CAEpG,IAAI;CACJ,MAAM,WAAW,aAAa,iBAAiB,eAAe,UAAU;CACxE,MAAM,UAAU,IAAI,IAA4B,QAAQ;CAExD,IAAI,SAAS,MAAM;EAClB,QAAQ;EACR,KAAK,MAAM,SAAS,SAAS,OAAO,GAAG;GACtC,SAAS,GAAG,MAAM,IAAI,UAAU,GAAG,CAAC,EAAE;GAEtC,KAAK,MAAM,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;IACvC,YAAY,IAAI,GAAG,MAAM,GAAG;IAE5B,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG;KACpB,QAAQ,IAAI,GAAG,KAAK;KACpB,SAAS,GAAG,EAAE,UAAU,GAAG,CAAC,EAAE;IAC/B;GACD;EACD;CACD;CAEA,OAAO;EAAE,OAAO,SAAS,KAAA;EAAoB;EAAsB;CAAY;AAChF;AAEA,MAAM,oBAEL;AAED,SAAS,YACR,GACA,UACA,aACiB;CAIjB,IAAI;CACJ,MAAM,eAAe,kBAAkB,MAAM,EAAE,iBAAiB,GAAA,CAAI,KAAK,CAAC;CAC1E,IAAI,cAAc,QAAQ,OACzB,QAAQ,aAAa,OAAO;CAM7B,IAAI,UAAU,EAAE,QAAQ,KAAK;CAC7B,MAAM,cAAc,kBAAkB,KAAK,OAAO;CAClD,IAAI,aAAa,UAAU,MAAM;EAChC,MAAM,UAAU,YAAY,OAAO,QAAQ,KAAK;EAChD,IAAI,QAAQ,WAAW,GACtB,UAAU;OACJ,IAAI,YAAY,OAAO,KAC7B,UAAU,QAAQ;OAElB,UAAU;CAEZ;CAEA,MAAM,QAAQ,QAAQ,QAAQ,IAAI;CAElC,OAAO,IAAI,UACV,UACA,EAAE,KACF,IAAI,kBACH,aAAa,QAAQ,IACrB,aAAa,uBACb,IAAI,KAAK,OAAO,EAAE,UAAU,IAAI,GAAI,GACpC,KAAA,GACA,IACD,GACA,IAAI,kBACH,aAAa,QAAQ,IACrB,aAAa,uBACb,IAAI,KAAK,OAAO,EAAE,aAAa,IAAI,GAAI,GACvC,KAAA,GACA,IACD,GACA,UAAU,KAAK,QAAQ,UAAU,GAAG,KAAK,IAAI,SAC7C,EAAE,QAAQ,MAAM,GAAG,KAAK,CAAC,GACzB,SACA,oBAAoB,GAAG,UAAU,KAAA,CAAS,GAC1C,EAAE,OACF,KAAA,GACA,KAAA,GACA,EAAE,WACF,KACD;AACD"}
|
|
@@ -44,6 +44,8 @@ export declare class StatusGitSubProvider implements GitStatusSubProvider {
|
|
|
44
44
|
getStatus(repoPath: string | undefined, options?: {
|
|
45
45
|
priority?: GitCommandPriority;
|
|
46
46
|
force?: boolean;
|
|
47
|
+
untracked?: 'no' | 'normal' | 'all';
|
|
48
|
+
branch?: false;
|
|
47
49
|
}, cancellation?: AbortSignal): Promise<GitStatus | undefined>;
|
|
48
50
|
private getStatusCore;
|
|
49
51
|
getStatusForFile(repoPath: string, pathOrUri: string | Uri, options?: {
|
|
@@ -29,6 +29,17 @@ function computeDeadlockBackstopMs(gitTimeout) {
|
|
|
29
29
|
const timeout = gitTimeout ?? 6e4;
|
|
30
30
|
return timeout > 0 ? timeout * 2 : disabledTimeoutBackstopMs;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* A non-default `untracked`/`branch` gets its own key, so a full-status caller never joins a narrower run; the
|
|
34
|
+
* default stays `'getStatus'`, which `getStatusForPathCore`'s rename path joins.
|
|
35
|
+
*/
|
|
36
|
+
function getStatusReadKey(options) {
|
|
37
|
+
if (options?.untracked == null && options?.branch !== false) return "getStatus";
|
|
38
|
+
const parts = [];
|
|
39
|
+
if (options?.untracked != null) parts.push(`untracked=${options.untracked}`);
|
|
40
|
+
if (options?.branch === false) parts.push("branch=false");
|
|
41
|
+
return `getStatus:${parts.join(":")}`;
|
|
42
|
+
}
|
|
32
43
|
var StatusGitSubProvider = class {
|
|
33
44
|
context;
|
|
34
45
|
git;
|
|
@@ -71,20 +82,30 @@ var StatusGitSubProvider = class {
|
|
|
71
82
|
}
|
|
72
83
|
getStatus(repoPath, options, cancellation) {
|
|
73
84
|
if (repoPath == null) return Promise.resolve(void 0);
|
|
74
|
-
|
|
85
|
+
const opts = options?.untracked === "all" ? {
|
|
75
86
|
...options,
|
|
87
|
+
untracked: void 0
|
|
88
|
+
} : options;
|
|
89
|
+
return this.dedupeByStatusGeneration(repoPath, getStatusReadKey(opts), (correlationKey, signal) => this.getStatusCore(repoPath, {
|
|
90
|
+
...opts,
|
|
76
91
|
correlationKey
|
|
77
|
-
}, signal), cancellation,
|
|
92
|
+
}, signal), cancellation, opts?.force);
|
|
78
93
|
}
|
|
79
94
|
async getStatusCore(repoPath, options, cancellation) {
|
|
80
95
|
const porcelainVersion = await this.git.supports("git:status:porcelain-v2") ? 2 : 1;
|
|
81
96
|
const result = await this.statusCore(repoPath, porcelainVersion, {
|
|
82
97
|
similarityThreshold: this.context.config?.commits.similarityThreshold,
|
|
83
98
|
priority: options?.priority,
|
|
84
|
-
correlationKey: options?.correlationKey
|
|
99
|
+
correlationKey: options?.correlationKey,
|
|
100
|
+
untracked: options?.untracked,
|
|
101
|
+
branch: options?.branch
|
|
85
102
|
}, cancellation);
|
|
86
103
|
const repoUri = fileUri(normalizePath(repoPath));
|
|
87
104
|
const status = parseGitStatus(result.stdout, repoPath, porcelainVersion, (p) => joinUriPath(repoUri, normalizePath(p)));
|
|
105
|
+
if (options?.branch === false) {
|
|
106
|
+
if (status == null && result.completion.status === "exited" && result.exitCode === 0) return new GitStatus(normalizePath(repoPath), "", "", []);
|
|
107
|
+
return status;
|
|
108
|
+
}
|
|
88
109
|
if (status?.detached) {
|
|
89
110
|
const pausedOpStatus = await this.provider.pausedOps?.getPausedOperationStatus?.(repoPath, void 0, cancellation);
|
|
90
111
|
if (pausedOpStatus?.type === "rebase") return new GitStatus(repoPath, pausedOpStatus.incoming.name, status.sha, status.files, status.upstream, true);
|
|
@@ -126,12 +147,9 @@ var StatusGitSubProvider = class {
|
|
|
126
147
|
return parseGitStatus(result.stdout, repoPath, porcelainVersion, (p) => joinUriPath(repoUri, normalizePath(p)))?.files;
|
|
127
148
|
}
|
|
128
149
|
async statusCore(repoPath, porcelainVersion = 1, options, cancellation, ...pathspecs) {
|
|
129
|
-
const params = [
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
"--branch",
|
|
133
|
-
"-u"
|
|
134
|
-
];
|
|
150
|
+
const params = ["status", porcelainVersion >= 2 ? `--porcelain=v${porcelainVersion}` : "--porcelain"];
|
|
151
|
+
if (options?.branch !== false) params.push("--branch");
|
|
152
|
+
params.push(options?.untracked != null ? `-u${options.untracked}` : "-u");
|
|
135
153
|
if (await this.git.supports("git:status:find-renames")) params.push(`--find-renames${options?.similarityThreshold == null ? "" : `=${options.similarityThreshold}%`}`);
|
|
136
154
|
return this.git.run({
|
|
137
155
|
cwd: repoPath,
|
|
@@ -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 { fileUri, joinUriPath, 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\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?: { priority?: GitCommandPriority; force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\treturn this.dedupeByStatusGeneration(\n\t\t\trepoPath,\n\t\t\t'getStatus',\n\t\t\t(correlationKey, signal) =>\n\t\t\t\tthis.getStatusCore(repoPath, { ...options, correlationKey: correlationKey }, signal),\n\t\t\tcancellation,\n\t\t\toptions?.force,\n\t\t);\n\t}\n\n\tprivate async getStatusCore(\n\t\trepoPath: string,\n\t\toptions?: { priority?: GitCommandPriority; correlationKey?: string },\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},\n\t\t\tcancellation,\n\t\t);\n\t\tconst repoUri = fileUri(normalizePath(repoPath));\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion, p =>\n\t\t\tjoinUriPath(repoUri, normalizePath(p)),\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 repoUri = fileUri(normalizePath(repoPath));\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion, p =>\n\t\t\tjoinUriPath(repoUri, normalizePath(p)),\n\t\t);\n\t\treturn status?.files;\n\t}\n\n\tprivate async statusCore(\n\t\trepoPath: string,\n\t\tporcelainVersion: number = 1,\n\t\toptions?: { similarityThreshold?: number | null; priority?: GitCommandPriority; correlationKey?: string },\n\t\tcancellation?: AbortSignal,\n\t\t...pathspecs: string[]\n\t): Promise<GitResult> {\n\t\tconst params = [\n\t\t\t'status',\n\t\t\tporcelainVersion >= 2 ? `--porcelain=v${porcelainVersion}` : '--porcelain',\n\t\t\t'--branch',\n\t\t\t'-u',\n\t\t];\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":";;;;;;;;;;;;;;;;;;;AA4BA,MAAM,4BAA4B;;;;;;;;AASlC,SAAgB,0BAA0B,YAAwC;CACjF,MAAM,UAAU,cAAc;CAC9B,OAAO,UAAU,IAAI,UAAU,IAAI;AACpC;AAEA,IAAa,uBAAb,MAAkE;CAE/C;CACA;CACA;CACA;CAJlB,YACC,SACA,KACA,OACA,UACC;EAJgB,KAAA,UAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACf;;;CAIH,gBAAiC,IAAI,WAA4B;;;;;;;;;;;;;;CAejE,yBACC,UACA,MACA,KACA,cACA,OACa;EAQb,IAAI,OACH,KAAK,MAAM,0BAA0B,QAAQ;EAE9C,MAAM,aAAa,KAAK,MAAM,oBAAoB,QAAQ;EAG1D,MAAM,MAAM,GAAG,KAAK,IAAI,SAAS,IAAI;EACrC,MAAM,iBAAiB,UAAU;EACjC,MAAM,aAAa,0BAA0B,KAAK,IAAI,QAAQ,UAAU;EAExE,OAAO,KAAK,cAAc,YACzB,MACC,WAAW,WAAW;GAQtB,UAAU,WAAW;GACrB,MAAM,WAAW,IAAI,gBAAgB;GACrC,MAAM,YAAY,UAAU,OAAO,YAAY,IAAI,CAAC,QAAQ,SAAS,MAAM,CAAC,IAAI,SAAS;GACzF,OAAO,gBAAgB,IAAI,gBAAgB,SAAS,GAAG,YAAY,QAAQ;EAC5E,GACA,YACD;CACD;CAEA,UAEC,UACA,SACA,cACiC;EACjC,IAAI,YAAY,MAAM,OAAO,QAAQ,QAAQ,KAAA,CAAS;EAEtD,OAAO,KAAK,yBACX,UACA,cACC,gBAAgB,WAChB,KAAK,cAAc,UAAU;GAAE,GAAG;GAAyB;EAAe,GAAG,MAAM,GACpF,cACA,SAAS,KACV;CACD;CAEA,MAAc,cACb,UACA,SACA,cACiC;EACjC,MAAM,mBAAoB,MAAM,KAAK,IAAI,SAAS,yBAAyB,IAAK,IAAI;EAEpF,MAAM,SAAS,MAAM,KAAK,WACzB,UACA,kBACA;GACC,qBAAqB,KAAK,QAAQ,QAAQ,QAAQ;GAClD,UAAU,SAAS;GACnB,gBAAgB,SAAS;EAC1B,GACA,YACD;EACA,MAAM,UAAU,QAAQ,cAAc,QAAQ,CAAC;EAC/C,MAAM,SAAS,eAAe,OAAO,QAAQ,UAAU,mBAAkB,MACxE,YAAY,SAAS,cAAc,CAAC,CAAC,CACtC;EAEA,IAAI,QAAQ,UAAU;GACrB,MAAM,iBAAiB,MAAM,KAAK,SAAS,WAAW,2BACrD,UACA,KAAA,GACA,YACD;GACA,IAAI,gBAAgB,SAAS,UAC5B,OAAO,IAAI,UACV,UACA,eAAe,SAAS,MACxB,OAAO,KACP,OAAO,OACP,OAAO,UACP,IACD;EAEF;EACA,OAAO;CACR;CAEA,MACM,iBACL,UACA,WACA,SACA,cACqC;EAOrC,QAAO,MANa,KAAK,qBACxB,UACA,SAAS,SAAS,GAClB;GAAE,GAAG;GAAS,OAAO;EAAK,GAC1B,YACD,EAAA,GACe;CAChB;CAEA,MACM,iBACL,UACA,WACA,SACA,cACuC;EACvC,OAAO,KAAK,qBAAqB,UAAU,SAAS,SAAS,GAAG;GAAE,GAAG;GAAS,OAAO;EAAM,GAAG,YAAY;CAC3G;CAEA,MAAc,qBACb,UACA,WACA,SACA,cACuC;EACvC,MAAM,eAAe,gBAAgB,UAAU,WAAW,QAAQ,CAAC,CAAC,EAAE;EAKtE,IAAI,QAAQ,YAAY,OAAO;GAC9B,MAAM,SAAS,MAAM,KAAK,UAAU,UAAU,KAAA,GAAW,YAAY;GACrE,IAAI,UAAU,MAAM,OAAO,KAAA;GAE3B,IAAI,QAAQ,OAAO;IAClB,MAAM,OAAO,OAAO,MAAM,MAAK,MAAK,EAAE,SAAS,YAAY;IAC3D,OAAO,OAAO,CAAC,IAAI,IAAI,KAAA;GACxB;GACA,OAAO,OAAO,MAAM,QAAO,MAAK,EAAE,KAAK,WAAW,YAAY,CAAC;EAChE;EAIA,OAAO,KAAK,yBACX,UAEA,oBAAoB,iBACnB,gBAAgB,WAAW,KAAK,uBAAuB,UAAU,cAAc,gBAAgB,MAAM,GACtG,YACD;CACD;CAEA,MAAc,uBACb,UACA,cACA,gBACA,cACuC;EACvC,MAAM,mBAAoB,MAAM,KAAK,IAAI,SAAS,yBAAyB,IAAK,IAAI;EACpF,MAAM,SAAS,MAAM,KAAK,WACzB,UACA,kBACA;GAAE,qBAAqB,KAAK,QAAQ,QAAQ,QAAQ;GAAqC;EAAe,GACxG,cACA,YACD;EAEA,MAAM,UAAU,QAAQ,cAAc,QAAQ,CAAC;EAI/C,OAHe,eAAe,OAAO,QAAQ,UAAU,mBAAkB,MACxE,YAAY,SAAS,cAAc,CAAC,CAAC,CAE1B,CAAC,EAAE;CAChB;CAEA,MAAc,WACb,UACA,mBAA2B,GAC3B,SACA,cACA,GAAG,WACkB;EACrB,MAAM,SAAS;GACd;GACA,oBAAoB,IAAI,gBAAgB,qBAAqB;GAC7D;GACA;EACD;EACA,IAAI,MAAM,KAAK,IAAI,SAAS,yBAAyB,GACpD,OAAO,KACN,iBAAiB,SAAS,uBAAuB,OAAO,KAAK,IAAI,QAAQ,oBAAoB,IAC9F;EAGD,OAAO,KAAK,IAAI,IACf;GACC,KAAK;GACS;GACd,SAAS;GACT,KAAK,EAAE,oBAAoB,IAAI;GAC/B,gBAAgB,SAAS;GACzB,GAAI,SAAS,YAAY,OAAO,EAAE,UAAU,QAAQ,SAAS,IAAI,KAAA;EAClE,GACA,GAAG,QACH,MACA,GAAG,SACJ;CACD;CAEA,kBAEC,UACA,SAOA,cACmB;EACnB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,SAAS,SAAS,UAAU;EAClC,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,YAAY,SAAS,aAAa;EAQxC,MAAM,eAAe,SAAS,gBAAgB;EAC9C,MAAM,WAAW,SAAS,YAAY;EAEtC,OAAO,KAAK,yBACX,UACA,qBAAqB,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,YACxE,OAAO,gBAAgB,WAAW;GACjC,IAAI;IACH,IAAI,UAAU,UAaT;UAAA,MAZiB,KAAK,IAAI,IAC7B;MACC,KAAK;MACL,cAAc;MACd,QAAQ;MACQ;MAChB,GAAI,SAAS,YAAY,OAAO,EAAE,UAAU,QAAQ,SAAS,IAAI,KAAA;KAClE,GACA,QACA,WACA,UAAU,WAAW,SAAS,SAAS,aAAa,KAAA,CACrD,EAAA,CACW,aAAa,GAAG;MAC1B,IAAI,UAAU,UACb,OAAO,YAAY,iCAAiC;WAC9C,IAAI,QACV,OAAO,YAAY,oBAAoB;WAEvC,OAAO,YAAY,sBAAsB;MAE1C,OAAO;KACR;;IAOD,IAAI,WAEC;SAAA,MADuB,KAAK,kBAAkB,UAAU,MAAM,GAChD;MACjB,OAAO,YAAY,qBAAqB;MACxC,OAAO;KACR;;IAGD,OAAO,YAAY,oBAAoB;IACvC,OAAO;GACR,SAAS,IAAI;IAEZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;IAGnC,OAAO,MAAM,EAAE;IACf,OAAO,YAAY,4BAA4B;IAC/C,IAAI,cAAc,MAAM;IACxB,OAAO;GACR;EACD,GACA,YACD;CACD;CAEA,uBACuB,UAAkB,cAA6D;EACrG,MAAM,QAAQ,gBAAgB;EAE9B,OAAO,KAAK,yBACX,UACA,0BACA,OAAO,gBAAgB,WAAW;GACjC,IAAI;IACH,MAAM,CAAC,cAAc,gBAAgB,mBAAmB,MAAM,QAAQ,WAAW;KAEhF,KAAK,IAAI,IACR;MAAE,KAAK;MAAU,cAAc;MAAQ,QAAQ;MAA0B;KAAe,GACxF,QACA,WACA,UACD;KAEA,KAAK,IAAI,IACR;MAAE,KAAK;MAAU,cAAc;MAAQ,QAAQ;MAA0B;KAAe,GACxF,QACA,SACD;KAEA,KAAK,kBAAkB,UAAU,MAAM;IACxC,CAAC;IAED,MAAM,SAAS;KACd,QAAQ,gBAAgB,YAAY,CAAC,EAAE,aAAa;KACpD,UAAU,gBAAgB,cAAc,CAAC,EAAE,aAAa;KACxD,WAAW,gBAAgB,eAAe,MAAM;IACjD;IAEA,OAAO,YACN,OAAO,UAAU,OAAO,YAAY,OAAO,YACxC,OAAO,OAAO,SAAS,WAAW,KAAK,OAAO,WAAY,OAAO,SAAS,eAAe,cAAe,KACxG,OAAO,YACJ,OAAO,UAAU,OAAO,WACvB,gBACA,cACD,GACH,YACA,oBACJ;IAEA,OAAO;GACR,SAAS,IAAI;IACZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;IAEnC,OAAO,MAAM,EAAE;IACf,OAAO,YAAY,4BAA4B;IAE/C,OAAO;KAAE,QAAQ;KAAO,UAAU;KAAO,WAAW;IAAM;GAC3D;EACD,GACA,YACD;CACD;CAEA,oBAAoB,UAAkB,cAA8C;EAGnF,OAAO,KAAK,yBACX,UACA,uBACA,OAAO,iBAAiB,WAAW;GAClC,IAAI;;;KACH,MAAM,SAAS,KAAK,IAAI,OAAO;MAAE,KAAK;MAAU,cAAc;KAAO,GAAG,YAAY,YAAY;KACxE,YAAA,EAAA,uBAAuB,KAAK,OAAO,SAAS,KAAA,CAAS,CAAC,CAAA;KAG9E,WAAW,MAAM,UAAU,QAC1B,OAAO;KAGR,OAAO;;;;;;GACR,SAAS,IAAI;IAEZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;IAEnC,OAAO;GACR;EACD,GACA,YACD;CACD;CAEA,oBACoB,UAAkB,cAAwD;EAC7F,MAAM,QAAQ,gBAAgB;EAE9B,OAAO,KAAK,yBACX,UACA,uBACA,OAAO,gBAAgB,WAAW;GACjC,IAAI;IACH,MAAM,SAAS,MAAM,KAAK,IAAI,IAC7B;KAAE,KAAK;KAAU,cAAc;KAAQ,QAAQ;KAA0B;IAAe,GACxF,YACA,MACA,YACD;IAEA,IAAI,CAAC,OAAO,QAAQ;KACnB,OAAO,YAAY,sBAAsB;KACzC,OAAO,CAAC;IACT;IAEA,MAAM,QAAQ,sBAAsB,OAAO,QAAQ,QAAQ;IAC3D,OAAO,YAAY,GAAG,OAAO,MAAM,MAAM,EAAE,qBAAqB;IAChE,OAAO;GACR,SAAS,IAAI;IAEZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;IAGnC,OAAO,MAAM,EAAE;IACf,OAAO,YAAY,iCAAiC;IACpD,OAAO,CAAC;GACT;EACD,GACA,YACD;CACD;CAEA,MAAc,kBAAkB,UAAkB,cAA8C;EAC/F,IAAI;;;IACH,MAAM,SAAS,KAAK,IAAI,OACvB;KAAE,KAAK;KAAwB;IAAa,GAC5C,YAEA,YACA,oBACD;IACwB,WAAA,EAAA,uBAAuB,KAAK,OAAO,SAAS,KAAA,CAAS,CAAC,CAAA;IAG9E,WAAW,MAAM,UAAU,QAC1B,OAAO;IAGR,OAAO;;;;;;EACR,SAAS,IAAI;GAEZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;GAGnC,OAAO;EACR;CACD;CAEA,kBACkB,UAAkB,cAAgD;EACnF,MAAM,QAAQ,gBAAgB;EAE9B,OAAO,KAAK,yBACX,UACA,qBACA,OAAO,gBAAgB,WAAW;GACjC,IAAI;IACH,MAAM,SAAS,MAAM,KAAK,IAAI,IAC7B;KAAE,KAAK;KAAU,cAAc;KAAQ,QAAQ;KAA0B;IAAe,GACxF,YACA,MACA,YACA,oBACD;IAEA,IAAI,CAAC,OAAO,QAAQ;KACnB,OAAO,YAAY,oBAAoB;KACvC,OAAO,CAAC;IACT;IAEA,MAAM,QAAmB,CAAC;IAE1B,KAAK,MAAM,QAAQ,mBAAmB,OAAO,QAAQ,IAAI,GAAG;KAC3D,IAAI,CAAC,KAAK,QAAQ;KAElB,MAAM,KAAK;MAAE,MAAM;MAAgB;MAAU,QAAQ,yBAAyB;KAAU,CAAC;IAC1F;IAEA,OAAO,YAAY,GAAG,OAAO,MAAM,MAAM,EAAE,mBAAmB;IAC9D,OAAO;GACR,SAAS,IAAI;IAEZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;IAGnC,OAAO,MAAM,EAAE;IACf,OAAO,YAAY,+BAA+B;IAClD,OAAO,CAAC;GACT;EACD,GACA,YACD;CACD;AACD;AAzcE,WAAA,CAAA,MAAM,CAAA,GAAA,qBAAA,WAAA,aAAA,IAAA;AA4DN,WAAA,CAAA,MAAM,CAAA,GAAA,qBAAA,WAAA,oBAAA,IAAA;AAgBN,WAAA,CAAA,MAAM,CAAA,GAAA,qBAAA,WAAA,oBAAA,IAAA;AAmGN,WAAA,CAAA,MAAM,CAAA,GAAA,qBAAA,WAAA,qBAAA,IAAA;AAsFN,WAAA,CAAA,MAAM,CAAA,GAAA,qBAAA,WAAA,0BAAA,IAAA;AAuFN,WAAA,CAAA,MAAM,CAAA,GAAA,qBAAA,WAAA,uBAAA,IAAA;AAgEN,WAAA,CAAA,MAAM,CAAA,GAAA,qBAAA,WAAA,qBAAA,IAAA"}
|
|
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 { fileUri, joinUriPath, 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 repoUri = fileUri(normalizePath(repoPath));\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion, p =>\n\t\t\tjoinUriPath(repoUri, normalizePath(p)),\n\t\t);\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 repoUri = fileUri(normalizePath(repoPath));\n\t\tconst status = parseGitStatus(result.stdout, repoPath, porcelainVersion, p =>\n\t\t\tjoinUriPath(repoUri, normalizePath(p)),\n\t\t);\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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"}
|
|
@@ -81,6 +81,7 @@ export declare class GitHubApi {
|
|
|
81
81
|
getCurrentAccount(provider: Provider, token: GitHubTokenInfo, options?: {
|
|
82
82
|
baseUrl?: string;
|
|
83
83
|
avatarSize?: number;
|
|
84
|
+
silent?: boolean;
|
|
84
85
|
}): Promise<Account | undefined>;
|
|
85
86
|
getAccountForCommit(provider: Provider, token: GitHubTokenInfo, owner: string, repo: string, rev: string, options?: {
|
|
86
87
|
baseUrl?: string;
|
|
@@ -169,6 +170,18 @@ export declare class GitHubApi {
|
|
|
169
170
|
getTagsWithCommit(token: GitHubTokenInfo, owner: string, repo: string, ref: string, date: Date): Promise<string[]>;
|
|
170
171
|
getNextCommitRefs(token: GitHubTokenInfo, owner: string, repo: string, ref: string, path: string, sha: string): Promise<string[]>;
|
|
171
172
|
private getCommitDate;
|
|
173
|
+
/**
|
|
174
|
+
* Whether this credential can read the repository, asked of REST rather than GraphQL. GraphQL answers a
|
|
175
|
+
* repository hidden by its organization's OAuth App access restrictions exactly as it answers one that does not
|
|
176
|
+
* exist (`NOT_FOUND`), while REST answers `403` and says why, so this is how a GraphQL miss is told apart from
|
|
177
|
+
* one. Resolves `false` on a `404`; a refusal throws `AuthenticationError` carrying GitHub's response.
|
|
178
|
+
*
|
|
179
|
+
* Silent: the refusal it exists to surface is one organization's policy, which reauthenticating cannot fix, so it
|
|
180
|
+
* must not raise the reauthentication prompt a failed read otherwise raises.
|
|
181
|
+
*/
|
|
182
|
+
getRepositoryAccess(provider: Provider | undefined, token: GitHubTokenInfo, owner: string, repo: string, options?: {
|
|
183
|
+
baseUrl?: string;
|
|
184
|
+
}): Promise<boolean>;
|
|
172
185
|
getContributors(token: GitHubTokenInfo, owner: string, repo: string): Promise<GitHubContributor[]>;
|
|
173
186
|
getUserSshSigningKeys(provider: Provider | undefined, token: GitHubTokenInfo, username: string, options?: {
|
|
174
187
|
baseUrl?: string;
|