@gitkraken/core-gitlens 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -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/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/docs/kepler-git-write-api-parity.md +140 -14
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refs.js","names":[],"sources":["../../../../git-cli/src/providers/refs.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { ReferenceUpdateError } from '@gitlens/git/errors.js';\nimport type { GitBranch } from '@gitlens/git/models/branch.js';\nimport type { GitReference, GitRefTip, RefRecord } from '@gitlens/git/models/reference.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTag } from '@gitlens/git/models/tag.js';\nimport type { GitRefsSubProvider } from '@gitlens/git/providers/refs.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { isRemoteHEAD } from '@gitlens/git/utils/branch.utils.js';\nimport { createReference } from '@gitlens/git/utils/reference.utils.js';\nimport { isSha, isShaWithOptionalRevisionSuffix, isUncommitted } from '@gitlens/git/utils/revision.utils.js';\nimport { compareRefTips } from '@gitlens/git/utils/sorting.js';\nimport { CancellationError, isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { debug, trace } from '@gitlens/utils/decorators/log.js';\nimport { createDisposable } from '@gitlens/utils/disposable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { maybeStopWatch } from '@gitlens/utils/stopwatch.js';\nimport { iterateAsyncByDelimiter } from '@gitlens/utils/string.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git, GitError } from '../exec/git.js';\nimport { getGitCommandError, gitConfigsBranch } from '../exec/git.js';\nimport { getRefParser } from '../parsers/refParser.js';\n\nexport class RefsGitSubProvider implements GitRefsSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync checkIfCouldBeValidBranchOrTagName(repoPath: string, ref: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'throw' }, 'check-ref-format', '--branch', ref);\n\t\t\treturn Boolean(result.stdout.trim());\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Raw `git for-each-ref` records covering branches, remotes, tags, and replace-refs in a single\n\t * pass. CLI-internal — siblings call via `this.provider.refs.getRefs(...)`. The `RefRecord` shape\n\t * is `for-each-ref`-specific and intentionally absent from the public `GitRefsSubProvider`\n\t * interface.\n\t */\n\t@debug()\n\tasync getRefs(repoPath: string, cancellation?: AbortSignal, options?: { force?: boolean }): Promise<RefRecord[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// Forces a fresh enumeration: evicts the shared cache entry (and the derived `refTips` projection,\n\t\t// which would otherwise still answer from the old records) so the factory below re-runs and\n\t\t// repopulates both from one spawn. Deliberately `delete`, not `invalidate` — soft-invalidation\n\t\t// leaves an in-flight entry rideable, so a caller needing a point-in-time read (the graph's tip\n\t\t// gate) could join an enumeration that started before the change it's trying to detect. Evicting\n\t\t// is safe mid-flight: the in-flight factory's settle is ownership-guarded and won't evict the\n\t\t// successor installed here.\n\t\tif (options?.force) {\n\t\t\tconst commonPath = this.cache.getCommonPath(repoPath);\n\t\t\tthis.cache.refs.delete(commonPath);\n\t\t\tthis.cache.refTips.delete(commonPath);\n\t\t}\n\n\t\treturn this.cache.getRefs(\n\t\t\trepoPath,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst supported = await this.git.supported('git:for-each-ref');\n\t\t\t\t\tconst parser = getRefParser(supported);\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: commonPath, cancellation: signal, configs: gitConfigsBranch, errors: 'ignore' },\n\t\t\t\t\t\t'for-each-ref',\n\t\t\t\t\t\t...parser.arguments,\n\t\t\t\t\t\t'refs/heads/',\n\t\t\t\t\t\t'refs/remotes/',\n\t\t\t\t\t\t'refs/tags/',\n\t\t\t\t\t\t// `git replace`/grafts — not surfaced to branch/tag/refTip consumers (filtered by\n\t\t\t\t\t\t// refname prefix), but needed by the graph's replace-ref change gate (graph.ts).\n\t\t\t\t\t\t'refs/replace/',\n\t\t\t\t\t);\n\t\t\t\t\t// Under `errors: 'ignore'` a cancelled run RESOLVES empty rather than throwing, so the\n\t\t\t\t\t// catch below never sees it and an empty enumeration would be cached as a real answer —\n\t\t\t\t\t// permanently, since this map has no TTL. Same guard `git.run`'s own caching path uses.\n\t\t\t\t\t// The graph's tip gate calls this with `force: true` and supersedes itself freely, so it\n\t\t\t\t\t// is routinely the sole registrant on the aggregate whose abort kills the spawn.\n\t\t\t\t\t// Covers a FAILED enumeration too, not just a cancelled one: a transient `for-each-ref`\n\t\t\t\t\t// failure (a lingering `index.lock`, EMFILE, the git dir briefly unavailable) also\n\t\t\t\t\t// resolves empty, and caching that `[]` would blank every branch, tag and ref-tip\n\t\t\t\t\t// consumer for the rest of the session. A genuinely ref-less repo still exits cleanly\n\t\t\t\t\t// with empty stdout, so it caches as before.\n\t\t\t\t\tif (result.completion.status !== 'exited' || result.exitCode !== 0 || signal?.aborted) {\n\t\t\t\t\t\tcacheable?.invalidate();\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\t\t\t\t\tif (!result?.stdout) return [];\n\n\t\t\t\t\tusing sw = maybeStopWatch(scope, { log: { onlyExit: true, level: 'debug' } });\n\n\t\t\t\t\tconst records = [...parser.parse(result.stdout)];\n\n\t\t\t\t\tsw?.stop({ suffix: ` parsed ${records.length} ref records` });\n\n\t\t\t\t\treturn records;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tcacheable?.invalidate();\n\t\t\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t\t\tscope?.error(ex);\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\t@debug()\n\tasync getRefTips(\n\t\trepoPath: string,\n\t\toptions?: { include?: ReadonlyArray<'heads' | 'remotes' | 'tags'> },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRefTip[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// Cache always holds the full set; subset filtering is applied on read so callers asking\n\t\t// for different subsets share one cache entry.\n\t\tconst all = await this.cache.getRefTips(\n\t\t\trepoPath,\n\t\t\tasync (_commonPath, _cacheable, signal) => {\n\t\t\t\tconst records = await this.getRefs(repoPath, signal);\n\n\t\t\t\tusing sw = maybeStopWatch(scope, { log: { onlyExit: true, level: 'debug' } });\n\n\t\t\t\tconst tips: GitRefTip[] = [];\n\t\t\t\tfor (const record of records) {\n\t\t\t\t\tconst fullName = record.name;\n\t\t\t\t\tif (!fullName) continue;\n\t\t\t\t\t// Skip refs/remotes/<remote>/HEAD — symbolic, not a real tip.\n\t\t\t\t\tif (isRemoteHEAD(fullName)) continue;\n\n\t\t\t\t\tlet type: GitRefTip['type'];\n\t\t\t\t\tlet name: string;\n\t\t\t\t\tif (fullName.startsWith('refs/heads/')) {\n\t\t\t\t\t\ttype = 'branch';\n\t\t\t\t\t\tname = fullName.substring(11);\n\t\t\t\t\t} else if (fullName.startsWith('refs/remotes/')) {\n\t\t\t\t\t\ttype = 'remote';\n\t\t\t\t\t\tname = fullName.substring(13);\n\t\t\t\t\t} else if (fullName.startsWith('refs/tags/')) {\n\t\t\t\t\t\ttype = 'tag';\n\t\t\t\t\t\tname = fullName.substring(10);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Annotated tags: peeledObjectname is the commit SHA; objectname is the tag-object SHA.\n\t\t\t\t\t// Lightweight tags / branches: peeledObjectname is empty; objectname is already the commit SHA.\n\t\t\t\t\tconst sha = record.peeledObjectname || record.objectname;\n\n\t\t\t\t\ttips.push({ type: type, name: name, fullName: fullName, sha: sha });\n\t\t\t\t}\n\n\t\t\t\tsw?.stop({ suffix: ` projected ${tips.length} ref tips` });\n\n\t\t\t\treturn tips;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\tconst include = options?.include;\n\t\tif (include == null || (include.includes('heads') && include.includes('remotes') && include.includes('tags'))) {\n\t\t\treturn all;\n\t\t}\n\n\t\treturn all.filter(r => {\n\t\t\tswitch (r.type) {\n\t\t\t\tcase 'branch':\n\t\t\t\t\treturn include.includes('heads');\n\t\t\t\tcase 'remote':\n\t\t\t\t\treturn include.includes('remotes');\n\t\t\t\tcase 'tag':\n\t\t\t\t\treturn include.includes('tags');\n\t\t\t}\n\t\t});\n\t}\n\n\t@debug()\n\tasync getRefsContainingShas(\n\t\trepoPath: string,\n\t\tshas: ReadonlySet<string> | readonly string[],\n\t\toldestSha: string,\n\t\toptions?: { include?: ReadonlyArray<'heads' | 'remotes' | 'tags'> },\n\t\tcancellation?: AbortSignal,\n\t): Promise<Map<string, GitRefTip[]>> {\n\t\tconst targetShas = shas instanceof Set ? shas : new Set(shas);\n\t\tif (!targetShas.size || !oldestSha) return new Map();\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst tips = await this.getRefTips(repoPath, options, cancellation);\n\t\tif (cancellation?.aborted) throw new CancellationError();\n\t\tif (!tips.length) return new Map();\n\n\t\t// Index tips by full ref name (for projection back to GitRefTip later) and seed the\n\t\t// propagation map by tip SHA. Multiple refs sharing a tip (e.g. local + remote-tracking)\n\t\t// collapse into one Set entry whose union covers all of them.\n\t\tconst tipsByName = new Map<string, GitRefTip>();\n\t\tconst propMap = new Map<string, Set<string>>();\n\t\tfor (const tip of tips) {\n\t\t\ttipsByName.set(tip.fullName, tip);\n\t\t\tlet names = propMap.get(tip.sha);\n\t\t\tif (names == null) {\n\t\t\t\tnames = new Set();\n\t\t\t\tpropMap.set(tip.sha, names);\n\t\t\t}\n\t\t\tnames.add(tip.fullName);\n\t\t}\n\n\t\tusing sw = maybeStopWatch(scope, { log: { onlyExit: true, level: 'debug' } });\n\n\t\t// `^<oldestSha>^@` excludes the parents of <oldestSha> and everything older. When <oldestSha>\n\t\t// is a root commit, `^@` resolves to nothing and the walk is naturally unbounded — git\n\t\t// doesn't error in that case (no negative refs to apply).\n\t\tconst stream = this.git.stream(\n\t\t\t{ cwd: repoPath, cancellation: cancellation, configs: gitConfigsBranch },\n\t\t\t'rev-list',\n\t\t\t'--topo-order',\n\t\t\t'--parents',\n\t\t\t'--all',\n\t\t\t`^${oldestSha}^@`,\n\t\t);\n\t\tusing _streamDisposer = createDisposable(() => void stream.return?.(undefined));\n\n\t\t// Topological propagation: `--topo-order` emits all children of X before X's own line, so\n\t\t// by the time we process \"X P1 P2...\" every child has already merged its set into X. We\n\t\t// then forward X's accumulated set to each parent — one-pass and correct.\n\t\ttry {\n\t\t\tfor await (const line of iterateAsyncByDelimiter(stream, '\\n')) {\n\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\t\t\t\tif (!line) continue;\n\n\t\t\t\tconst firstSpace = line.indexOf(' ');\n\t\t\t\tconst sha = firstSpace === -1 ? line : line.substring(0, firstSpace);\n\t\t\t\tif (!sha) continue;\n\n\t\t\t\tconst refs = propMap.get(sha);\n\t\t\t\tif (!refs?.size) continue;\n\n\t\t\t\tif (firstSpace === -1) continue; // No parents — nothing to propagate to\n\n\t\t\t\t// Walk parent SHAs by index without splitting the whole line.\n\t\t\t\tlet start = firstSpace + 1;\n\t\t\t\twhile (start < line.length) {\n\t\t\t\t\tconst next = line.indexOf(' ', start);\n\t\t\t\t\tconst parentSha = next === -1 ? line.substring(start) : line.substring(start, next);\n\t\t\t\t\tif (parentSha) {\n\t\t\t\t\t\tlet parentRefs = propMap.get(parentSha);\n\t\t\t\t\t\tif (parentRefs == null) {\n\t\t\t\t\t\t\tparentRefs = new Set(refs);\n\t\t\t\t\t\t\tpropMap.set(parentSha, parentRefs);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (const name of refs) {\n\t\t\t\t\t\t\t\tparentRefs.add(name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (next === -1) break;\n\n\t\t\t\t\tstart = next + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tscope?.error(ex);\n\t\t\treturn new Map();\n\t\t}\n\n\t\t// Project to targets, materialize GitRefTip[], sort.\n\t\tconst result = new Map<string, GitRefTip[]>();\n\t\tfor (const sha of targetShas) {\n\t\t\tconst names = propMap.get(sha);\n\t\t\tif (!names?.size) continue;\n\n\t\t\tconst refs: GitRefTip[] = [];\n\t\t\tfor (const name of names) {\n\t\t\t\tconst tip = tipsByName.get(name);\n\t\t\t\tif (tip != null) {\n\t\t\t\t\trefs.push(tip);\n\t\t\t\t}\n\t\t\t}\n\t\t\trefs.sort(compareRefTips);\n\t\t\tresult.set(sha, refs);\n\t\t}\n\n\t\tsw?.stop({ suffix: ` resolved ${result.size}/${targetShas.size} target shas` });\n\n\t\treturn result;\n\t}\n\n\t@debug()\n\tasync getMergeBase(\n\t\trepoPath: string,\n\t\tref1: string,\n\t\tref2: string,\n\t\toptions?: { forkPoint?: boolean; priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\tcancellation: cancellation,\n\t\t\t\t\t// Why: ref1/ref2 are usually branch names; correctness relies on the gitResults cache being\n\t\t\t\t\t// cleared on 'heads'/'remotes' events when refs move. Web (no fs watcher) sees up to\n\t\t\t\t\t// `accessTTL` of staleness — acceptable trade-off for the perf win on graph/branch reads.\n\t\t\t\t\tcaching: { cache: this.cache.gitResults, options: { accessTTL: 5 * 60 * 1000 } },\n\t\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t\t},\n\t\t\t\t'merge-base',\n\t\t\t\toptions?.forkPoint ? '--fork-point' : undefined,\n\t\t\t\tref1,\n\t\t\t\tref2,\n\t\t\t);\n\t\t\tif (!result.stdout) return undefined;\n\n\t\t\treturn result.stdout.split('\\n')[0].trim() || undefined;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitReference | undefined> {\n\t\tif (!ref || ref === deletedOrMissing) return undefined;\n\n\t\tconst valid = options?.force\n\t\t\t? await this.validateReference(repoPath, ref, { force: true }, cancellation)\n\t\t\t: await this.isValidReference(repoPath, ref, undefined, cancellation);\n\t\tif (!valid) return undefined;\n\n\t\tif (ref !== 'HEAD' && !isShaWithOptionalRevisionSuffix(ref)) {\n\t\t\tconst branch = await this.provider.branches.getBranch(\n\t\t\t\trepoPath,\n\t\t\t\tref,\n\t\t\t\toptions?.force ? { force: true } : undefined,\n\t\t\t\tcancellation,\n\t\t\t);\n\t\t\tif (branch != null) {\n\t\t\t\treturn createReference(branch.ref, repoPath, {\n\t\t\t\t\tid: branch.id,\n\t\t\t\t\trefType: 'branch',\n\t\t\t\t\tname: branch.name,\n\t\t\t\t\tremote: branch.remote,\n\t\t\t\t\tupstream: branch.upstream,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Not forced: a tag that moves is rare enough that `force` is scoped to branches and validation.\n\t\t\tconst tag = await this.provider.tags.getTag(repoPath, ref, cancellation);\n\t\t\tif (tag != null) {\n\t\t\t\treturn createReference(tag.ref, repoPath, {\n\t\t\t\t\tid: tag.id,\n\t\t\t\t\trefType: 'tag',\n\t\t\t\t\tname: tag.name,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn createReference(ref, repoPath, { refType: 'revision' });\n\t}\n\n\t@debug()\n\tasync getSymbolicReferenceName(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tconst supportsEndOfOptions = await this.git.supports('git:rev-parse:end-of-options');\n\n\t\tconst result = await this.git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\tcancellation: cancellation,\n\t\t\t\terrors: 'ignore',\n\t\t\t\t// Why: a fixed ref name's symbolic name is itself stable; only HEAD is mutable, and the\n\t\t\t\t// gitResults cache is cleared on 'head' events. 60s TTL is the failsafe for watcher\n\t\t\t\t// latency / web — matches the other \"resolve symbolic state\" calls in commits.ts.\n\t\t\t\tcaching: { cache: this.cache.gitResults, options: { accessTTL: 60 * 1000 } },\n\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t},\n\t\t\t'rev-parse',\n\t\t\t'--verify',\n\t\t\t'--quiet',\n\t\t\t'--symbolic-full-name',\n\t\t\t'--abbrev-ref',\n\t\t\tsupportsEndOfOptions ? '--end-of-options' : undefined,\n\t\t\tref,\n\t\t);\n\t\treturn result.stdout.trim() || undefined;\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync hasBranchOrTag(\n\t\trepoPath: string | undefined,\n\t\toptions?: {\n\t\t\tfilter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean };\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tif (repoPath == null) return false;\n\n\t\tconst [{ values: branches }, { values: tags }] = await Promise.all([\n\t\t\tthis.provider.branches.getBranches(\n\t\t\t\trepoPath,\n\t\t\t\t{ filter: options?.filter?.branches, sort: false },\n\t\t\t\tcancellation,\n\t\t\t),\n\t\t\tthis.provider.tags.getTags(repoPath, { filter: options?.filter?.tags, sort: false }, cancellation),\n\t\t]);\n\n\t\treturn branches.length !== 0 || tags.length !== 0;\n\t}\n\n\t@debug()\n\tasync isValidReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tpathOrUri?: string | Uri,\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tconst path = pathOrUri != null ? toFsPath(pathOrUri) : undefined;\n\t\tconst relativePath = path ? this.provider.getRelativePath(path, repoPath) : undefined;\n\t\treturn Boolean(\n\t\t\t(await this.validateReference(repoPath, ref, { relativePath: relativePath }, cancellation))?.length,\n\t\t);\n\t}\n\n\t@trace()\n\tasync validateReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { relativePath?: string; force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tif (!ref) return undefined;\n\t\tif (ref === deletedOrMissing || isUncommitted(ref)) return ref;\n\n\t\tconst relativePath = options?.relativePath;\n\t\tconst supportsEndOfOptions = await this.git.supports('git:rev-parse:end-of-options');\n\n\t\t// Why: a SHA-only validation (no path suffix) is effectively immutable — 5-min TTL is safe.\n\t\t// Otherwise the resolved SHA can shift on ref move (or working-tree change for path-scoped\n\t\t// validation); rely on gitResults being cleared on 'head'/'heads'/'remotes' events, with 60s\n\t\t// TTL as the failsafe for watcher latency / web.\n\t\tconst stable = relativePath == null && isSha(ref);\n\t\tconst result = await this.git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\tcancellation: cancellation,\n\t\t\t\terrors: 'ignore',\n\t\t\t\tcaching: {\n\t\t\t\t\tcache: this.cache.gitResults,\n\t\t\t\t\toptions: { accessTTL: stable ? 5 * 60 * 1000 : 60 * 1000 },\n\t\t\t\t\tforce: options?.force,\n\t\t\t\t},\n\t\t\t},\n\t\t\t'rev-parse',\n\t\t\t'--verify',\n\t\t\tsupportsEndOfOptions ? '--end-of-options' : undefined,\n\t\t\trelativePath ? `${ref}:./${relativePath}` : `${ref}^{commit}`,\n\t\t);\n\t\treturn result.stdout.trim() || undefined;\n\t}\n\n\t@debug()\n\tasync deleteReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { expected?: string },\n\t\tcancellation?: AbortSignal,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// `--no-deref`: without it git deletes what a symbolic ref points to rather than the ref itself, so\n\t\t// deleting `refs/remotes/origin/HEAD` would take `origin/main` with it\n\t\tconst args = ['update-ref', '-d', '--no-deref', ref];\n\t\tif (options?.expected != null) {\n\t\t\targs.push(options.expected);\n\t\t}\n\n\t\t// `HEAD` is either the checked-out branch or, detached, the repository's own HEAD file — neither\n\t\t// may be deleted\n\t\tif (ref === 'HEAD') {\n\t\t\tthrow new ReferenceUpdateError({\n\t\t\t\treason: 'checkedOut',\n\t\t\t\taction: 'delete',\n\t\t\t\tref: ref,\n\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t});\n\t\t}\n\n\t\t// `update-ref -d` has none of `git branch -d`'s guards or cleanup, so a local branch gets them here:\n\t\t// deleting one checked out in a worktree would leave that worktree on a branch that no longer exists.\n\t\tconst branch = ref.startsWith('refs/heads/') ? ref.substring('refs/heads/'.length) : undefined;\n\t\tif (branch != null) {\n\t\t\t// Read git's worktree list directly rather than the cached one: that names a worktree's branch\n\t\t\t// only when the separately cached branch list has it, so a worktree or branch made outside core\n\t\t\t// since the last read would slip past this guard.\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'throw' },\n\t\t\t\t'worktree',\n\t\t\t\t'list',\n\t\t\t\t'--porcelain',\n\t\t\t);\n\t\t\tif (result.stdout.split('\\n').some(l => l.trim() === `branch ${ref}`)) {\n\t\t\t\tthrow new ReferenceUpdateError({\n\t\t\t\t\treason: 'checkedOut',\n\t\t\t\t\taction: 'delete',\n\t\t\t\t\tref: ref,\n\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// `errors: 'throw'`: the default handler resolves a `GitWarnings` match (e.g. \"not a git\n\t\t\t// repository\"), which would report a write that never happened as done\n\t\t\tawait this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, ...args);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'update-ref-delete',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew ReferenceUpdateError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\taction: 'delete',\n\t\t\t\t\t\t\tref: ref,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (branch != null) {\n\t\t\t// What `git branch -d` removes itself (the upstream and other per-branch settings), then GitLens's own\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'ignore' }, 'config', '--remove-section', `branch.${branch}`);\n\t\t\tawait this.provider.branches.forgetDeletedBranch(repoPath, branch);\n\t\t\t// A single combined reset/announce rather than this plus `fireReferenceChanged`'s own\n\t\t\t// `'branches'`/`['heads']` — a branch delete only needs one of each.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'config');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.fireReferenceChanged(repoPath, ref);\n\t}\n\n\t@debug()\n\tasync updateReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tsha: string,\n\t\toptions?: { expected?: string | 'absent' },\n\t\tcancellation?: AbortSignal,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['update-ref', ref, sha];\n\t\tif (options?.expected != null) {\n\t\t\t// Git's own compare-and-swap old-value argument, which makes the update atomic against a\n\t\t\t// concurrent writer. An EMPTY old value is how git spells \"the ref must not exist yet\"; the\n\t\t\t// empty string has to reach argv intact, which it does because the executor drops only\n\t\t\t// null/undefined.\n\t\t\targs.push(options.expected === 'absent' ? '' : options.expected);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, ...args);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'update-ref',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew ReferenceUpdateError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\taction: 'update',\n\t\t\t\t\t\t\tref: ref,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tthis.fireReferenceChanged(repoPath, ref);\n\t}\n\n\t/** Announces a ref mutation to the cache and repository hooks. */\n\tprivate fireReferenceChanged(repoPath: string, ref: string): void {\n\t\tif (ref === 'HEAD') {\n\t\t\t// `update-ref HEAD` moves whatever HEAD resolves to — the checked-out branch, or a detached HEAD\n\t\t\t// — which also changes what the index and working tree are compared against.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads']);\n\t\t} else if (ref.startsWith('refs/heads/')) {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);\n\t\t} else if (ref.startsWith('refs/tags/')) {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'tags');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['tags']);\n\t\t} else if (ref.startsWith('refs/remotes/')) {\n\t\t\t// Remote-tracking branches are read through the branch and ref-tip caches, which `'branches'`\n\t\t\t// clears; `'remotes'` covers only the configured remotes, which a ref write cannot change.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t\t} else if (ref === 'refs/stash') {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\t}\n\t\t// A ref outside those namespaces (a consumer's own bookkeeping under `refs/<tool>/`) is visible to\n\t\t// nothing core caches, and announcing it as an unknown change would make a host refresh everything\n\t\t// for a write it cannot observe.\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,IAAa,qBAAb,MAA8D;CAE3C;CACA;CACA;CACA;CAJlB,YACC,SACA,KACA,OACA,UACC;EAJgB,KAAA,UAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACf;CAEH,MACM,mCAAmC,UAAkB,KAA+B;EACzF,IAAI;GACH,MAAM,SAAS,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;GAAQ,GAAG,oBAAoB,YAAY,GAAG;GACzG,OAAO,QAAQ,OAAO,OAAO,KAAK,CAAC;EACpC,QAAQ;GACP,OAAO;EACR;CACD;;;;;;;CAQA,MACM,QAAQ,UAAkB,cAA4B,SAAqD;EAChH,IAAI,CAAC,UAAU,OAAO,CAAC;EAEvB,MAAM,QAAQ,gBAAgB;EAS9B,IAAI,SAAS,OAAO;GACnB,MAAM,aAAa,KAAK,MAAM,cAAc,QAAQ;GACpD,KAAK,MAAM,KAAK,OAAO,UAAU;GACjC,KAAK,MAAM,QAAQ,OAAO,UAAU;EACrC;EAEA,OAAO,KAAK,MAAM,QACjB,UACA,OAAO,YAAY,WAAW,WAAW;GACxC,IAAI;;;KACH,MAAM,YAAY,MAAM,KAAK,IAAI,UAAU,kBAAkB;KAC7D,MAAM,SAAS,aAAa,SAAS;KACrC,MAAM,SAAS,MAAM,KAAK,IAAI,IAC7B;MAAE,KAAK;MAAY,cAAc;MAAQ,SAAS;MAAkB,QAAQ;KAAS,GACrF,gBACA,GAAG,OAAO,WACV,eACA,iBACA,cAGA,eACD;KAWA,IAAI,OAAO,WAAW,WAAW,YAAY,OAAO,aAAa,KAAK,QAAQ,SAAS;MACtF,WAAW,WAAW;MACtB,OAAO,CAAC;KACT;KACA,IAAI,CAAC,QAAQ,QAAQ,OAAO,CAAC;KAE7B,MAAM,KAAA,YAAA,EAAK,eAAe,OAAO,EAAE,KAAK;MAAE,UAAU;MAAM,OAAO;KAAQ,EAAE,CAAC,CAAA;KAE5E,MAAM,UAAU,CAAC,GAAG,OAAO,MAAM,OAAO,MAAM,CAAC;KAE/C,IAAI,KAAK,EAAE,QAAQ,WAAW,QAAQ,OAAO,cAAc,CAAC;KAE5D,OAAO;;;;;;GACR,SAAS,IAAI;IACZ,WAAW,WAAW;IACtB,IAAI,oBAAoB,EAAE,GAAG,MAAM;IAEnC,OAAO,MAAM,EAAE;IACf,OAAO,CAAC;GACT;EACD,GACA,YACD;CACD;CAEA,MACM,WACL,UACA,SACA,cACuB;EACvB,IAAI,CAAC,UAAU,OAAO,CAAC;EAEvB,MAAM,QAAQ,gBAAgB;EAI9B,MAAM,MAAM,MAAM,KAAK,MAAM,WAC5B,UACA,OAAO,aAAa,YAAY,WAAW;;;IAC1C,MAAM,UAAU,MAAM,KAAK,QAAQ,UAAU,MAAM;IAEnD,MAAM,KAAA,WAAA,EAAK,eAAe,OAAO,EAAE,KAAK;KAAE,UAAU;KAAM,OAAO;IAAQ,EAAE,CAAC,CAAA;IAE5E,MAAM,OAAoB,CAAC;IAC3B,KAAK,MAAM,UAAU,SAAS;KAC7B,MAAM,WAAW,OAAO;KACxB,IAAI,CAAC,UAAU;KAEf,IAAI,aAAa,QAAQ,GAAG;KAE5B,IAAI;KACJ,IAAI;KACJ,IAAI,SAAS,WAAW,aAAa,GAAG;MACvC,OAAO;MACP,OAAO,SAAS,UAAU,EAAE;KAC7B,OAAO,IAAI,SAAS,WAAW,eAAe,GAAG;MAChD,OAAO;MACP,OAAO,SAAS,UAAU,EAAE;KAC7B,OAAO,IAAI,SAAS,WAAW,YAAY,GAAG;MAC7C,OAAO;MACP,OAAO,SAAS,UAAU,EAAE;KAC7B,OACC;KAKD,MAAM,MAAM,OAAO,oBAAoB,OAAO;KAE9C,KAAK,KAAK;MAAQ;MAAY;MAAgB;MAAe;KAAI,CAAC;IACnE;IAEA,IAAI,KAAK,EAAE,QAAQ,cAAc,KAAK,OAAO,WAAW,CAAC;IAEzD,OAAO;;;;;;EACR,GACA,YACD;EAEA,MAAM,UAAU,SAAS;EACzB,IAAI,WAAW,QAAS,QAAQ,SAAS,OAAO,KAAK,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,MAAM,GAC1G,OAAO;EAGR,OAAO,IAAI,QAAO,MAAK;GACtB,QAAQ,EAAE,MAAV;IACC,KAAK,UACJ,OAAO,QAAQ,SAAS,OAAO;IAChC,KAAK,UACJ,OAAO,QAAQ,SAAS,SAAS;IAClC,KAAK,OACJ,OAAO,QAAQ,SAAS,MAAM;GAChC;EACD,CAAC;CACF;CAEA,MACM,sBACL,UACA,MACA,WACA,SACA,cACoC;;;GACpC,MAAM,aAAa,gBAAgB,MAAM,OAAO,IAAI,IAAI,IAAI;GAC5D,IAAI,CAAC,WAAW,QAAQ,CAAC,WAAW,uBAAO,IAAI,IAAI;GAEnD,MAAM,QAAQ,gBAAgB;GAE9B,MAAM,OAAO,MAAM,KAAK,WAAW,UAAU,SAAS,YAAY;GAClE,IAAI,cAAc,SAAS,MAAM,IAAI,kBAAkB;GACvD,IAAI,CAAC,KAAK,QAAQ,uBAAO,IAAI,IAAI;GAKjC,MAAM,6BAAa,IAAI,IAAuB;GAC9C,MAAM,0BAAU,IAAI,IAAyB;GAC7C,KAAK,MAAM,OAAO,MAAM;IACvB,WAAW,IAAI,IAAI,UAAU,GAAG;IAChC,IAAI,QAAQ,QAAQ,IAAI,IAAI,GAAG;IAC/B,IAAI,SAAS,MAAM;KAClB,wBAAQ,IAAI,IAAI;KAChB,QAAQ,IAAI,IAAI,KAAK,KAAK;IAC3B;IACA,MAAM,IAAI,IAAI,QAAQ;GACvB;GAEA,MAAM,KAAA,WAAA,EAAK,eAAe,OAAO,EAAE,KAAK;IAAE,UAAU;IAAM,OAAO;GAAQ,EAAE,CAAC,CAAA;GAK5E,MAAM,SAAS,KAAK,IAAI,OACvB;IAAE,KAAK;IAAwB;IAAc,SAAS;GAAiB,GACvE,YACA,gBACA,aACA,SACA,IAAI,UAAU,GACf;GACwB,WAAA,EAAA,uBAAuB,KAAK,OAAO,SAAS,KAAA,CAAS,CAAC,CAAA;GAK9E,IAAI;IACH,WAAW,MAAM,QAAQ,wBAAwB,QAAQ,IAAI,GAAG;KAC/D,IAAI,cAAc,SAAS,MAAM,IAAI,kBAAkB;KACvD,IAAI,CAAC,MAAM;KAEX,MAAM,aAAa,KAAK,QAAQ,GAAG;KACnC,MAAM,MAAM,eAAe,KAAK,OAAO,KAAK,UAAU,GAAG,UAAU;KACnE,IAAI,CAAC,KAAK;KAEV,MAAM,OAAO,QAAQ,IAAI,GAAG;KAC5B,IAAI,CAAC,MAAM,MAAM;KAEjB,IAAI,eAAe,IAAI;KAGvB,IAAI,QAAQ,aAAa;KACzB,OAAO,QAAQ,KAAK,QAAQ;MAC3B,MAAM,OAAO,KAAK,QAAQ,KAAK,KAAK;MACpC,MAAM,YAAY,SAAS,KAAK,KAAK,UAAU,KAAK,IAAI,KAAK,UAAU,OAAO,IAAI;MAClF,IAAI,WAAW;OACd,IAAI,aAAa,QAAQ,IAAI,SAAS;OACtC,IAAI,cAAc,MAAM;QACvB,aAAa,IAAI,IAAI,IAAI;QACzB,QAAQ,IAAI,WAAW,UAAU;OAClC,OACC,KAAK,MAAM,QAAQ,MAClB,WAAW,IAAI,IAAI;MAGtB;MACA,IAAI,SAAS,IAAI;MAEjB,QAAQ,OAAO;KAChB;IACD;GACD,SAAS,IAAI;IACZ,IAAI,oBAAoB,EAAE,GAAG,MAAM;IAEnC,OAAO,MAAM,EAAE;IACf,uBAAO,IAAI,IAAI;GAChB;GAGA,MAAM,yBAAS,IAAI,IAAyB;GAC5C,KAAK,MAAM,OAAO,YAAY;IAC7B,MAAM,QAAQ,QAAQ,IAAI,GAAG;IAC7B,IAAI,CAAC,OAAO,MAAM;IAElB,MAAM,OAAoB,CAAC;IAC3B,KAAK,MAAM,QAAQ,OAAO;KACzB,MAAM,MAAM,WAAW,IAAI,IAAI;KAC/B,IAAI,OAAO,MACV,KAAK,KAAK,GAAG;IAEf;IACA,KAAK,KAAK,cAAc;IACxB,OAAO,IAAI,KAAK,IAAI;GACrB;GAEA,IAAI,KAAK,EAAE,QAAQ,aAAa,OAAO,KAAK,GAAG,WAAW,KAAK,cAAc,CAAC;GAE9E,OAAO;;;;;;CACR;CAEA,MACM,aACL,UACA,MACA,MACA,SACA,cAC8B;EAC9B,MAAM,QAAQ,gBAAgB;EAE9B,IAAI;GACH,MAAM,SAAS,MAAM,KAAK,IAAI,IAC7B;IACC,KAAK;IACS;IAId,SAAS;KAAE,OAAO,KAAK,MAAM;KAAY,SAAS,EAAE,WAAW,IAAc;IAAE;IAC/E,GAAI,SAAS,YAAY,OAAO,EAAE,UAAU,QAAQ,SAAS,IAAI,KAAA;GAClE,GACA,cACA,SAAS,YAAY,iBAAiB,KAAA,GACtC,MACA,IACD;GACA,IAAI,CAAC,OAAO,QAAQ,OAAO,KAAA;GAE3B,OAAO,OAAO,OAAO,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,KAAK,KAAA;EAC/C,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,IAAI,oBAAoB,EAAE,GAAG,MAAM;GAEnC;EACD;CACD;CAEA,MACM,aACL,UACA,KACA,SACA,cACoC;EACpC,IAAI,CAAC,OAAO,QAAA,6CAA0B,OAAO,KAAA;EAK7C,IAAI,EAHU,SAAS,QACpB,MAAM,KAAK,kBAAkB,UAAU,KAAK,EAAE,OAAO,KAAK,GAAG,YAAY,IACzE,MAAM,KAAK,iBAAiB,UAAU,KAAK,KAAA,GAAW,YAAY,IACzD,OAAO,KAAA;EAEnB,IAAI,QAAQ,UAAU,CAAC,gCAAgC,GAAG,GAAG;GAC5D,MAAM,SAAS,MAAM,KAAK,SAAS,SAAS,UAC3C,UACA,KACA,SAAS,QAAQ,EAAE,OAAO,KAAK,IAAI,KAAA,GACnC,YACD;GACA,IAAI,UAAU,MACb,OAAO,gBAAgB,OAAO,KAAK,UAAU;IAC5C,IAAI,OAAO;IACX,SAAS;IACT,MAAM,OAAO;IACb,QAAQ,OAAO;IACf,UAAU,OAAO;GAClB,CAAC;GAIF,MAAM,MAAM,MAAM,KAAK,SAAS,KAAK,OAAO,UAAU,KAAK,YAAY;GACvE,IAAI,OAAO,MACV,OAAO,gBAAgB,IAAI,KAAK,UAAU;IACzC,IAAI,IAAI;IACR,SAAS;IACT,MAAM,IAAI;GACX,CAAC;EAEH;EAEA,OAAO,gBAAgB,KAAK,UAAU,EAAE,SAAS,WAAW,CAAC;CAC9D;CAEA,MACM,yBACL,UACA,KACA,SACA,cAC8B;EAC9B,MAAM,uBAAuB,MAAM,KAAK,IAAI,SAAS,8BAA8B;EAqBnF,QAAO,MAnBc,KAAK,IAAI,IAC7B;GACC,KAAK;GACS;GACd,QAAQ;GAIR,SAAS;IAAE,OAAO,KAAK,MAAM;IAAY,SAAS,EAAE,WAAW,IAAU;GAAE;GAC3E,GAAI,SAAS,YAAY,OAAO,EAAE,UAAU,QAAQ,SAAS,IAAI,KAAA;EAClE,GACA,aACA,YACA,WACA,wBACA,gBACA,uBAAuB,qBAAqB,KAAA,GAC5C,GACD,EAAA,CACc,OAAO,KAAK,KAAK,KAAA;CAChC;CAEA,MACM,eACL,UACA,SAGA,cACmB;EACnB,IAAI,YAAY,MAAM,OAAO;EAE7B,MAAM,CAAC,EAAE,QAAQ,YAAY,EAAE,QAAQ,UAAU,MAAM,QAAQ,IAAI,CAClE,KAAK,SAAS,SAAS,YACtB,UACA;GAAE,QAAQ,SAAS,QAAQ;GAAU,MAAM;EAAM,GACjD,YACD,GACA,KAAK,SAAS,KAAK,QAAQ,UAAU;GAAE,QAAQ,SAAS,QAAQ;GAAM,MAAM;EAAM,GAAG,YAAY,CAClG,CAAC;EAED,OAAO,SAAS,WAAW,KAAK,KAAK,WAAW;CACjD;CAEA,MACM,iBACL,UACA,KACA,WACA,cACmB;EACnB,MAAM,OAAO,aAAa,OAAO,SAAS,SAAS,IAAI,KAAA;EACvD,MAAM,eAAe,OAAO,KAAK,SAAS,gBAAgB,MAAM,QAAQ,IAAI,KAAA;EAC5E,OAAO,SACL,MAAM,KAAK,kBAAkB,UAAU,KAAK,EAAgB,aAAa,GAAG,YAAY,EAAA,EAAI,MAC9F;CACD;CAEA,MACM,kBACL,UACA,KACA,SACA,cAC8B;EAC9B,IAAI,CAAC,KAAK,OAAO,KAAA;EACjB,IAAI,QAAA,+CAA4B,cAAc,GAAG,GAAG,OAAO;EAE3D,MAAM,eAAe,SAAS;EAC9B,MAAM,uBAAuB,MAAM,KAAK,IAAI,SAAS,8BAA8B;EAMnF,MAAM,SAAS,gBAAgB,QAAQ,MAAM,GAAG;EAiBhD,QAAO,MAhBc,KAAK,IAAI,IAC7B;GACC,KAAK;GACS;GACd,QAAQ;GACR,SAAS;IACR,OAAO,KAAK,MAAM;IAClB,SAAS,EAAE,WAAW,SAAS,MAAgB,IAAU;IACzD,OAAO,SAAS;GACjB;EACD,GACA,aACA,YACA,uBAAuB,qBAAqB,KAAA,GAC5C,eAAe,GAAG,IAAI,KAAK,iBAAiB,GAAG,IAAI,UACpD,EAAA,CACc,OAAO,KAAK,KAAK,KAAA;CAChC;CAEA,MACM,gBACL,UACA,KACA,SACA,cACgB;EAChB,MAAM,QAAQ,gBAAgB;EAI9B,MAAM,OAAO;GAAC;GAAc;GAAM;GAAc;EAAG;EACnD,IAAI,SAAS,YAAY,MACxB,KAAK,KAAK,QAAQ,QAAQ;EAK3B,IAAI,QAAQ,QACX,MAAM,IAAI,qBAAqB;GAC9B,QAAQ;GACR,QAAQ;GACH;GACL,YAAY;IAAY;IAAgB;GAAK;EAC9C,CAAC;EAKF,MAAM,SAAS,IAAI,WAAW,aAAa,IAAI,IAAI,UAAU,EAAoB,IAAI,KAAA;EACrF,IAAI,UAAU,MAUT;QAAA,MANiB,KAAK,IAAI,IAC7B;IAAE,KAAK;IAAwB;IAAc,QAAQ;GAAQ,GAC7D,YACA,QACA,aACD,EAAA,CACW,OAAO,MAAM,IAAI,CAAC,CAAC,MAAK,MAAK,EAAE,KAAK,MAAM,UAAU,KAAK,GACnE,MAAM,IAAI,qBAAqB;IAC9B,QAAQ;IACR,QAAQ;IACH;IACL,YAAY;KAAY;KAAgB;IAAK;GAC9C,CAAC;EAAA;EAIH,IAAI;GAGH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAwB;IAAc,QAAQ;GAAQ,GAAG,GAAG,IAAI;EAC3F,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,IAAI,oBAAoB,EAAE,GAAG,MAAM;GAEnC,MAAM,mBACL,qBACA,KACA,WACC,IAAI,qBACH;IACS;IACR,QAAQ;IACH;IACL,YAAY;KAAY;KAAgB;IAAK;GAC9C,GACA,EACD,CACF;EACD;EAEA,IAAI,UAAU,MAAM;GAEnB,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;GAAS,GAAG,UAAU,oBAAoB,UAAU,QAAQ;GACxG,MAAM,KAAK,SAAS,SAAS,oBAAoB,UAAU,MAAM;GAGjE,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;GAC/D;EACD;EAEA,KAAK,qBAAqB,UAAU,GAAG;CACxC;CAEA,MACM,gBACL,UACA,KACA,KACA,SACA,cACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,OAAO;GAAC;GAAc;GAAK;EAAG;EACpC,IAAI,SAAS,YAAY,MAKxB,KAAK,KAAK,QAAQ,aAAa,WAAW,KAAK,QAAQ,QAAQ;EAGhE,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAwB;IAAc,QAAQ;GAAQ,GAAG,GAAG,IAAI;EAC3F,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,IAAI,oBAAoB,EAAE,GAAG,MAAM;GAEnC,MAAM,mBACL,cACA,KACA,WACC,IAAI,qBACH;IACS;IACR,QAAQ;IACH;IACL,YAAY;KAAY;KAAgB;IAAK;GAC9C,GACA,EACD,CACF;EACD;EAEA,KAAK,qBAAqB,UAAU,GAAG;CACxC;;CAGA,qBAA6B,UAAkB,KAAmB;EACjE,IAAI,QAAQ,QAAQ;GAGnB,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,YAAY,QAAQ;GACnE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,QAAQ,OAAO,CAAC;EACxE,OAAO,IAAI,IAAI,WAAW,aAAa,GAAG;GACzC,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,UAAU;GACzD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;EAChE,OAAO,IAAI,IAAI,WAAW,YAAY,GAAG;GACxC,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,MAAM;GACrD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,MAAM,CAAC;EAC/D,OAAO,IAAI,IAAI,WAAW,eAAe,GAAG;GAG3C,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,UAAU;GACzD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,SAAS,CAAC;EAClE,OAAO,IAAI,QAAQ,cAAc;GAChC,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,SAAS;GACxD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,OAAO,CAAC;EAChE;CAID;AACD;AAzmBE,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,sCAAA,IAAA;AAgBN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,WAAA,IAAA;AAuEN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,cAAA,IAAA;AAwEN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,yBAAA,IAAA;AAkHN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,gBAAA,IAAA;AAqCN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,gBAAA,IAAA;AA6CN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,4BAAA,IAAA;AA+BN,WAAA,CAAA,MAAM,EAAE,OAAM,cAAa,EAAY,SAAS,GAAG,CAAC,CAAA,GAAA,mBAAA,WAAA,kBAAA,IAAA;AAsBpD,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,oBAAA,IAAA;AAcN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,qBAAA,IAAA;AAqCN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,mBAAA,IAAA;AAwFN,WAAA,CAAA,MAAM,CAAA,GAAA,mBAAA,WAAA,mBAAA,IAAA"}
|
|
1
|
+
{"version":3,"file":"refs.js","names":[],"sources":["../../../../git-cli/src/providers/refs.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { ReferenceUpdateError } from '@gitlens/git/errors.js';\nimport type { GitBranch } from '@gitlens/git/models/branch.js';\nimport type { GitReference, GitRefTip, RefRecord } from '@gitlens/git/models/reference.js';\nimport type { GitReflogEntry } from '@gitlens/git/models/reflog.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTag } from '@gitlens/git/models/tag.js';\nimport type { GitRefsSubProvider } from '@gitlens/git/providers/refs.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { isRemoteHEAD } from '@gitlens/git/utils/branch.utils.js';\nimport { createReference } from '@gitlens/git/utils/reference.utils.js';\nimport { isSha, isShaWithOptionalRevisionSuffix, isUncommitted } from '@gitlens/git/utils/revision.utils.js';\nimport { compareRefTips } from '@gitlens/git/utils/sorting.js';\nimport { CancellationError, isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { debug, trace } from '@gitlens/utils/decorators/log.js';\nimport { createDisposable } from '@gitlens/utils/disposable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { maybeStopWatch } from '@gitlens/utils/stopwatch.js';\nimport { iterateAsyncByDelimiter } from '@gitlens/utils/string.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git, GitError } from '../exec/git.js';\nimport { getGitCommandError, gitConfigsBranch, gitConfigsLog } from '../exec/git.js';\nimport { getReflogEntryParser } from '../parsers/reflogParser.js';\nimport { getRefParser } from '../parsers/refParser.js';\n\nexport class RefsGitSubProvider implements GitRefsSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync checkIfCouldBeValidBranchOrTagName(repoPath: string, ref: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'throw' }, 'check-ref-format', '--branch', ref);\n\t\t\treturn Boolean(result.stdout.trim());\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Raw `git for-each-ref` records covering branches, remotes, tags, and replace-refs in a single\n\t * pass. CLI-internal — siblings call via `this.provider.refs.getRefs(...)`. The `RefRecord` shape\n\t * is `for-each-ref`-specific and intentionally absent from the public `GitRefsSubProvider`\n\t * interface.\n\t */\n\t@debug()\n\tasync getRefs(repoPath: string, cancellation?: AbortSignal, options?: { force?: boolean }): Promise<RefRecord[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// Forces a fresh enumeration: evicts the shared cache entry (and the derived `refTips` projection,\n\t\t// which would otherwise still answer from the old records) so the factory below re-runs and\n\t\t// repopulates both from one spawn. Deliberately `delete`, not `invalidate` — soft-invalidation\n\t\t// leaves an in-flight entry rideable, so a caller needing a point-in-time read (the graph's tip\n\t\t// gate) could join an enumeration that started before the change it's trying to detect. Evicting\n\t\t// is safe mid-flight: the in-flight factory's settle is ownership-guarded and won't evict the\n\t\t// successor installed here.\n\t\tif (options?.force) {\n\t\t\tconst commonPath = this.cache.getCommonPath(repoPath);\n\t\t\tthis.cache.refs.delete(commonPath);\n\t\t\tthis.cache.refTips.delete(commonPath);\n\t\t}\n\n\t\treturn this.cache.getRefs(\n\t\t\trepoPath,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst supported = await this.git.supported('git:for-each-ref');\n\t\t\t\t\tconst parser = getRefParser(supported);\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: commonPath, cancellation: signal, configs: gitConfigsBranch, errors: 'ignore' },\n\t\t\t\t\t\t'for-each-ref',\n\t\t\t\t\t\t...parser.arguments,\n\t\t\t\t\t\t'refs/heads/',\n\t\t\t\t\t\t'refs/remotes/',\n\t\t\t\t\t\t'refs/tags/',\n\t\t\t\t\t\t// `git replace`/grafts — not surfaced to branch/tag/refTip consumers (filtered by\n\t\t\t\t\t\t// refname prefix), but needed by the graph's replace-ref change gate (graph.ts).\n\t\t\t\t\t\t'refs/replace/',\n\t\t\t\t\t);\n\t\t\t\t\t// Under `errors: 'ignore'` a cancelled run RESOLVES empty rather than throwing, so the\n\t\t\t\t\t// catch below never sees it and an empty enumeration would be cached as a real answer —\n\t\t\t\t\t// permanently, since this map has no TTL. Same guard `git.run`'s own caching path uses.\n\t\t\t\t\t// The graph's tip gate calls this with `force: true` and supersedes itself freely, so it\n\t\t\t\t\t// is routinely the sole registrant on the aggregate whose abort kills the spawn.\n\t\t\t\t\t// Covers a FAILED enumeration too, not just a cancelled one: a transient `for-each-ref`\n\t\t\t\t\t// failure (a lingering `index.lock`, EMFILE, the git dir briefly unavailable) also\n\t\t\t\t\t// resolves empty, and caching that `[]` would blank every branch, tag and ref-tip\n\t\t\t\t\t// consumer for the rest of the session. A genuinely ref-less repo still exits cleanly\n\t\t\t\t\t// with empty stdout, so it caches as before.\n\t\t\t\t\tif (result.completion.status !== 'exited' || result.exitCode !== 0 || signal?.aborted) {\n\t\t\t\t\t\tcacheable?.invalidate();\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\t\t\t\t\tif (!result?.stdout) return [];\n\n\t\t\t\t\tusing sw = maybeStopWatch(scope, { log: { onlyExit: true, level: 'debug' } });\n\n\t\t\t\t\tconst records = [...parser.parse(result.stdout)];\n\n\t\t\t\t\tsw?.stop({ suffix: ` parsed ${records.length} ref records` });\n\n\t\t\t\t\treturn records;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tcacheable?.invalidate();\n\t\t\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\t\t\tscope?.error(ex);\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\t@debug()\n\tasync getRefTips(\n\t\trepoPath: string,\n\t\toptions?: { include?: ReadonlyArray<'heads' | 'remotes' | 'tags'> },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRefTip[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// Cache always holds the full set; subset filtering is applied on read so callers asking\n\t\t// for different subsets share one cache entry.\n\t\tconst all = await this.cache.getRefTips(\n\t\t\trepoPath,\n\t\t\tasync (_commonPath, _cacheable, signal) => {\n\t\t\t\tconst records = await this.getRefs(repoPath, signal);\n\n\t\t\t\tusing sw = maybeStopWatch(scope, { log: { onlyExit: true, level: 'debug' } });\n\n\t\t\t\tconst tips: GitRefTip[] = [];\n\t\t\t\tfor (const record of records) {\n\t\t\t\t\tconst fullName = record.name;\n\t\t\t\t\tif (!fullName) continue;\n\t\t\t\t\t// Skip refs/remotes/<remote>/HEAD — symbolic, not a real tip.\n\t\t\t\t\tif (isRemoteHEAD(fullName)) continue;\n\n\t\t\t\t\tlet type: GitRefTip['type'];\n\t\t\t\t\tlet name: string;\n\t\t\t\t\tif (fullName.startsWith('refs/heads/')) {\n\t\t\t\t\t\ttype = 'branch';\n\t\t\t\t\t\tname = fullName.substring(11);\n\t\t\t\t\t} else if (fullName.startsWith('refs/remotes/')) {\n\t\t\t\t\t\ttype = 'remote';\n\t\t\t\t\t\tname = fullName.substring(13);\n\t\t\t\t\t} else if (fullName.startsWith('refs/tags/')) {\n\t\t\t\t\t\ttype = 'tag';\n\t\t\t\t\t\tname = fullName.substring(10);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Annotated tags: peeledObjectname is the commit SHA; objectname is the tag-object SHA.\n\t\t\t\t\t// Lightweight tags / branches: peeledObjectname is empty; objectname is already the commit SHA.\n\t\t\t\t\tconst sha = record.peeledObjectname || record.objectname;\n\n\t\t\t\t\ttips.push({ type: type, name: name, fullName: fullName, sha: sha });\n\t\t\t\t}\n\n\t\t\t\tsw?.stop({ suffix: ` projected ${tips.length} ref tips` });\n\n\t\t\t\treturn tips;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\tconst include = options?.include;\n\t\tif (include == null || (include.includes('heads') && include.includes('remotes') && include.includes('tags'))) {\n\t\t\treturn all;\n\t\t}\n\n\t\treturn all.filter(r => {\n\t\t\tswitch (r.type) {\n\t\t\t\tcase 'branch':\n\t\t\t\t\treturn include.includes('heads');\n\t\t\t\tcase 'remote':\n\t\t\t\t\treturn include.includes('remotes');\n\t\t\t\tcase 'tag':\n\t\t\t\t\treturn include.includes('tags');\n\t\t\t}\n\t\t});\n\t}\n\n\t@debug()\n\tasync getRefsContainingShas(\n\t\trepoPath: string,\n\t\tshas: ReadonlySet<string> | readonly string[],\n\t\toldestSha: string,\n\t\toptions?: { include?: ReadonlyArray<'heads' | 'remotes' | 'tags'> },\n\t\tcancellation?: AbortSignal,\n\t): Promise<Map<string, GitRefTip[]>> {\n\t\tconst targetShas = shas instanceof Set ? shas : new Set(shas);\n\t\tif (!targetShas.size || !oldestSha) return new Map();\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst tips = await this.getRefTips(repoPath, options, cancellation);\n\t\tif (cancellation?.aborted) throw new CancellationError();\n\t\tif (!tips.length) return new Map();\n\n\t\t// Index tips by full ref name (for projection back to GitRefTip later) and seed the\n\t\t// propagation map by tip SHA. Multiple refs sharing a tip (e.g. local + remote-tracking)\n\t\t// collapse into one Set entry whose union covers all of them.\n\t\tconst tipsByName = new Map<string, GitRefTip>();\n\t\tconst propMap = new Map<string, Set<string>>();\n\t\tfor (const tip of tips) {\n\t\t\ttipsByName.set(tip.fullName, tip);\n\t\t\tlet names = propMap.get(tip.sha);\n\t\t\tif (names == null) {\n\t\t\t\tnames = new Set();\n\t\t\t\tpropMap.set(tip.sha, names);\n\t\t\t}\n\t\t\tnames.add(tip.fullName);\n\t\t}\n\n\t\tusing sw = maybeStopWatch(scope, { log: { onlyExit: true, level: 'debug' } });\n\n\t\t// `^<oldestSha>^@` excludes the parents of <oldestSha> and everything older. When <oldestSha>\n\t\t// is a root commit, `^@` resolves to nothing and the walk is naturally unbounded — git\n\t\t// doesn't error in that case (no negative refs to apply).\n\t\tconst stream = this.git.stream(\n\t\t\t{ cwd: repoPath, cancellation: cancellation, configs: gitConfigsBranch },\n\t\t\t'rev-list',\n\t\t\t'--topo-order',\n\t\t\t'--parents',\n\t\t\t'--all',\n\t\t\t`^${oldestSha}^@`,\n\t\t);\n\t\tusing _streamDisposer = createDisposable(() => void stream.return?.(undefined));\n\n\t\t// Topological propagation: `--topo-order` emits all children of X before X's own line, so\n\t\t// by the time we process \"X P1 P2...\" every child has already merged its set into X. We\n\t\t// then forward X's accumulated set to each parent — one-pass and correct.\n\t\ttry {\n\t\t\tfor await (const line of iterateAsyncByDelimiter(stream, '\\n')) {\n\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\t\t\t\tif (!line) continue;\n\n\t\t\t\tconst firstSpace = line.indexOf(' ');\n\t\t\t\tconst sha = firstSpace === -1 ? line : line.substring(0, firstSpace);\n\t\t\t\tif (!sha) continue;\n\n\t\t\t\tconst refs = propMap.get(sha);\n\t\t\t\tif (!refs?.size) continue;\n\n\t\t\t\tif (firstSpace === -1) continue; // No parents — nothing to propagate to\n\n\t\t\t\t// Walk parent SHAs by index without splitting the whole line.\n\t\t\t\tlet start = firstSpace + 1;\n\t\t\t\twhile (start < line.length) {\n\t\t\t\t\tconst next = line.indexOf(' ', start);\n\t\t\t\t\tconst parentSha = next === -1 ? line.substring(start) : line.substring(start, next);\n\t\t\t\t\tif (parentSha) {\n\t\t\t\t\t\tlet parentRefs = propMap.get(parentSha);\n\t\t\t\t\t\tif (parentRefs == null) {\n\t\t\t\t\t\t\tparentRefs = new Set(refs);\n\t\t\t\t\t\t\tpropMap.set(parentSha, parentRefs);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (const name of refs) {\n\t\t\t\t\t\t\t\tparentRefs.add(name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (next === -1) break;\n\n\t\t\t\t\tstart = next + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tscope?.error(ex);\n\t\t\treturn new Map();\n\t\t}\n\n\t\t// Project to targets, materialize GitRefTip[], sort.\n\t\tconst result = new Map<string, GitRefTip[]>();\n\t\tfor (const sha of targetShas) {\n\t\t\tconst names = propMap.get(sha);\n\t\t\tif (!names?.size) continue;\n\n\t\t\tconst refs: GitRefTip[] = [];\n\t\t\tfor (const name of names) {\n\t\t\t\tconst tip = tipsByName.get(name);\n\t\t\t\tif (tip != null) {\n\t\t\t\t\trefs.push(tip);\n\t\t\t\t}\n\t\t\t}\n\t\t\trefs.sort(compareRefTips);\n\t\t\tresult.set(sha, refs);\n\t\t}\n\n\t\tsw?.stop({ suffix: ` resolved ${result.size}/${targetShas.size} target shas` });\n\n\t\treturn result;\n\t}\n\n\t@debug()\n\tasync getMergeBase(\n\t\trepoPath: string,\n\t\tref1: string,\n\t\tref2: string,\n\t\toptions?: { forkPoint?: boolean; priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\tcancellation: cancellation,\n\t\t\t\t\t// Why: ref1/ref2 are usually branch names; correctness relies on the gitResults cache being\n\t\t\t\t\t// cleared on 'heads'/'remotes' events when refs move. Web (no fs watcher) sees up to\n\t\t\t\t\t// `accessTTL` of staleness — acceptable trade-off for the perf win on graph/branch reads.\n\t\t\t\t\tcaching: { cache: this.cache.gitResults, options: { accessTTL: 5 * 60 * 1000 } },\n\t\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t\t},\n\t\t\t\t'merge-base',\n\t\t\t\toptions?.forkPoint ? '--fork-point' : undefined,\n\t\t\t\tref1,\n\t\t\t\tref2,\n\t\t\t);\n\t\t\tif (!result.stdout) return undefined;\n\n\t\t\treturn result.stdout.split('\\n')[0].trim() || undefined;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getReflogEntries(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { grep?: string; priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitReflogEntry[]> {\n\t\t// `show` so a branch named `delete`, `expire` or `exists` isn't read as that subcommand, and the trailing\n\t\t// `--` so one named like a tracked file isn't rejected as ambiguous\n\t\tconst parser = getReflogEntryParser();\n\t\tconst args = ['reflog', 'show', ...parser.arguments];\n\t\tif (options?.grep) {\n\t\t\targs.push(`--grep-reflog=${options.grep}`);\n\t\t}\n\t\targs.push(ref, '--');\n\n\t\tconst result = await this.git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\terrors: 'throw',\n\t\t\t\tcancellation: cancellation,\n\t\t\t\t// A user's `log.showSignature` would print gpg output into the records\n\t\t\t\tconfigs: gitConfigsLog,\n\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t},\n\t\t\t...args,\n\t\t);\n\n\t\tconst entries: GitReflogEntry[] = [];\n\t\tfor (const entry of parser.parse(result.stdout)) {\n\t\t\tentries.push({ sha: entry.sha, message: entry.subject });\n\t\t}\n\t\treturn entries;\n\t}\n\n\t@debug()\n\tasync getReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitReference | undefined> {\n\t\tif (!ref || ref === deletedOrMissing) return undefined;\n\n\t\tconst valid = options?.force\n\t\t\t? await this.validateReference(repoPath, ref, { force: true }, cancellation)\n\t\t\t: await this.isValidReference(repoPath, ref, undefined, cancellation);\n\t\tif (!valid) return undefined;\n\n\t\tif (ref !== 'HEAD' && !isShaWithOptionalRevisionSuffix(ref)) {\n\t\t\tconst branch = await this.provider.branches.getBranch(\n\t\t\t\trepoPath,\n\t\t\t\tref,\n\t\t\t\toptions?.force ? { force: true } : undefined,\n\t\t\t\tcancellation,\n\t\t\t);\n\t\t\tif (branch != null) {\n\t\t\t\treturn createReference(branch.ref, repoPath, {\n\t\t\t\t\tid: branch.id,\n\t\t\t\t\trefType: 'branch',\n\t\t\t\t\tname: branch.name,\n\t\t\t\t\tremote: branch.remote,\n\t\t\t\t\tupstream: branch.upstream,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Not forced: a tag that moves is rare enough that `force` is scoped to branches and validation.\n\t\t\tconst tag = await this.provider.tags.getTag(repoPath, ref, cancellation);\n\t\t\tif (tag != null) {\n\t\t\t\treturn createReference(tag.ref, repoPath, {\n\t\t\t\t\tid: tag.id,\n\t\t\t\t\trefType: 'tag',\n\t\t\t\t\tname: tag.name,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn createReference(ref, repoPath, { refType: 'revision' });\n\t}\n\n\t@debug()\n\tasync getSymbolicReferenceName(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tconst supportsEndOfOptions = await this.git.supports('git:rev-parse:end-of-options');\n\n\t\tconst result = await this.git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\tcancellation: cancellation,\n\t\t\t\terrors: 'ignore',\n\t\t\t\t// Why: a fixed ref name's symbolic name is itself stable; only HEAD is mutable, and the\n\t\t\t\t// gitResults cache is cleared on 'head' events. 60s TTL is the failsafe for watcher\n\t\t\t\t// latency / web — matches the other \"resolve symbolic state\" calls in commits.ts.\n\t\t\t\tcaching: { cache: this.cache.gitResults, options: { accessTTL: 60 * 1000 } },\n\t\t\t\t...(options?.priority != null ? { priority: options.priority } : undefined),\n\t\t\t},\n\t\t\t'rev-parse',\n\t\t\t'--verify',\n\t\t\t'--quiet',\n\t\t\t'--symbolic-full-name',\n\t\t\t'--abbrev-ref',\n\t\t\tsupportsEndOfOptions ? '--end-of-options' : undefined,\n\t\t\tref,\n\t\t);\n\t\treturn result.stdout.trim() || undefined;\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync hasBranchOrTag(\n\t\trepoPath: string | undefined,\n\t\toptions?: {\n\t\t\tfilter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean };\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tif (repoPath == null) return false;\n\n\t\tconst [{ values: branches }, { values: tags }] = await Promise.all([\n\t\t\tthis.provider.branches.getBranches(\n\t\t\t\trepoPath,\n\t\t\t\t{ filter: options?.filter?.branches, sort: false },\n\t\t\t\tcancellation,\n\t\t\t),\n\t\t\tthis.provider.tags.getTags(repoPath, { filter: options?.filter?.tags, sort: false }, cancellation),\n\t\t]);\n\n\t\treturn branches.length !== 0 || tags.length !== 0;\n\t}\n\n\t@debug()\n\tasync isValidReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tpathOrUri?: string | Uri,\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tconst path = pathOrUri != null ? toFsPath(pathOrUri) : undefined;\n\t\tconst relativePath = path ? this.provider.getRelativePath(path, repoPath) : undefined;\n\t\treturn Boolean(\n\t\t\t(await this.validateReference(repoPath, ref, { relativePath: relativePath }, cancellation))?.length,\n\t\t);\n\t}\n\n\t@trace()\n\tasync validateReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { relativePath?: string; force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tif (!ref) return undefined;\n\t\tif (ref === deletedOrMissing || isUncommitted(ref)) return ref;\n\n\t\tconst relativePath = options?.relativePath;\n\t\tconst supportsEndOfOptions = await this.git.supports('git:rev-parse:end-of-options');\n\n\t\t// Why: a SHA-only validation (no path suffix) is effectively immutable — 5-min TTL is safe.\n\t\t// Otherwise the resolved SHA can shift on ref move (or working-tree change for path-scoped\n\t\t// validation); rely on gitResults being cleared on 'head'/'heads'/'remotes' events, with 60s\n\t\t// TTL as the failsafe for watcher latency / web.\n\t\tconst stable = relativePath == null && isSha(ref);\n\t\tconst result = await this.git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\tcancellation: cancellation,\n\t\t\t\terrors: 'ignore',\n\t\t\t\tcaching: {\n\t\t\t\t\tcache: this.cache.gitResults,\n\t\t\t\t\toptions: { accessTTL: stable ? 5 * 60 * 1000 : 60 * 1000 },\n\t\t\t\t\tforce: options?.force,\n\t\t\t\t},\n\t\t\t},\n\t\t\t'rev-parse',\n\t\t\t'--verify',\n\t\t\tsupportsEndOfOptions ? '--end-of-options' : undefined,\n\t\t\trelativePath ? `${ref}:./${relativePath}` : `${ref}^{commit}`,\n\t\t);\n\t\treturn result.stdout.trim() || undefined;\n\t}\n\n\t@debug()\n\tasync deleteReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { expected?: string },\n\t\tcancellation?: AbortSignal,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// `--no-deref`: without it git deletes what a symbolic ref points to rather than the ref itself, so\n\t\t// deleting `refs/remotes/origin/HEAD` would take `origin/main` with it\n\t\tconst args = ['update-ref', '-d', '--no-deref', ref];\n\t\tif (options?.expected != null) {\n\t\t\targs.push(options.expected);\n\t\t}\n\n\t\t// `HEAD` is either the checked-out branch or, detached, the repository's own HEAD file — neither\n\t\t// may be deleted\n\t\tif (ref === 'HEAD') {\n\t\t\tthrow new ReferenceUpdateError({\n\t\t\t\treason: 'checkedOut',\n\t\t\t\taction: 'delete',\n\t\t\t\tref: ref,\n\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t});\n\t\t}\n\n\t\t// `update-ref -d` has none of `git branch -d`'s guards or cleanup, so a local branch gets them here:\n\t\t// deleting one checked out in a worktree would leave that worktree on a branch that no longer exists.\n\t\tconst branch = ref.startsWith('refs/heads/') ? ref.substring('refs/heads/'.length) : undefined;\n\t\tif (branch != null) {\n\t\t\t// Read git's worktree list directly rather than the cached one: that names a worktree's branch\n\t\t\t// only when the separately cached branch list has it, so a worktree or branch made outside core\n\t\t\t// since the last read would slip past this guard.\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'throw' },\n\t\t\t\t'worktree',\n\t\t\t\t'list',\n\t\t\t\t'--porcelain',\n\t\t\t);\n\t\t\tif (result.stdout.split('\\n').some(l => l.trim() === `branch ${ref}`)) {\n\t\t\t\tthrow new ReferenceUpdateError({\n\t\t\t\t\treason: 'checkedOut',\n\t\t\t\t\taction: 'delete',\n\t\t\t\t\tref: ref,\n\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// `errors: 'throw'`: the default handler resolves a `GitWarnings` match (e.g. \"not a git\n\t\t\t// repository\"), which would report a write that never happened as done\n\t\t\tawait this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, ...args);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'update-ref-delete',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew ReferenceUpdateError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\taction: 'delete',\n\t\t\t\t\t\t\tref: ref,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (branch != null) {\n\t\t\t// What `git branch -d` removes itself (the upstream and other per-branch settings), then GitLens's own\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'ignore' }, 'config', '--remove-section', `branch.${branch}`);\n\t\t\tawait this.provider.branches.forgetDeletedBranch(repoPath, branch);\n\t\t\t// A single combined reset/announce rather than this plus `fireReferenceChanged`'s own\n\t\t\t// `'branches'`/`['heads']` — a branch delete only needs one of each.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'config');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.fireReferenceChanged(repoPath, ref);\n\t}\n\n\t@debug()\n\tasync updateReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tsha: string,\n\t\toptions?: { expected?: string | 'absent' },\n\t\tcancellation?: AbortSignal,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['update-ref', ref, sha];\n\t\tif (options?.expected != null) {\n\t\t\t// Git's own compare-and-swap old-value argument, which makes the update atomic against a\n\t\t\t// concurrent writer. An EMPTY old value is how git spells \"the ref must not exist yet\"; the\n\t\t\t// empty string has to reach argv intact, which it does because the executor drops only\n\t\t\t// null/undefined.\n\t\t\targs.push(options.expected === 'absent' ? '' : options.expected);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, ...args);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'update-ref',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew ReferenceUpdateError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\taction: 'update',\n\t\t\t\t\t\t\tref: ref,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tthis.fireReferenceChanged(repoPath, ref);\n\t}\n\n\t/** Announces a ref mutation to the cache and repository hooks. */\n\tprivate fireReferenceChanged(repoPath: string, ref: string): void {\n\t\tif (ref === 'HEAD') {\n\t\t\t// `update-ref HEAD` moves whatever HEAD resolves to — the checked-out branch, or a detached HEAD\n\t\t\t// — which also changes what the index and working tree are compared against.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads']);\n\t\t} else if (ref.startsWith('refs/heads/')) {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);\n\t\t} else if (ref.startsWith('refs/tags/')) {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'tags');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['tags']);\n\t\t} else if (ref.startsWith('refs/remotes/')) {\n\t\t\t// Remote-tracking branches are read through the branch and ref-tip caches, which `'branches'`\n\t\t\t// clears; `'remotes'` covers only the configured remotes, which a ref write cannot change.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t\t} else if (ref === 'refs/stash') {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'stashes');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['stash']);\n\t\t}\n\t\t// A ref outside those namespaces (a consumer's own bookkeeping under `refs/<tool>/`) is visible to\n\t\t// nothing core caches, and announcing it as an unknown change would make a host refresh everything\n\t\t// for a write it cannot observe.\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -43,7 +43,8 @@ var RemotesGitSubProvider = class extends RemotesGitProviderBase {
|
|
|
43
43
|
}
|
|
44
44
|
async addRemote(repoPath, name, url, options) {
|
|
45
45
|
await this.git.run({ cwd: repoPath }, "remote", "add", options?.fetch ? "-f" : void 0, name, url);
|
|
46
|
-
this.context.hooks?.cache?.onReset?.(repoPath, "remotes");
|
|
46
|
+
if (options?.fetch) this.context.hooks?.cache?.onReset?.(repoPath, "remotes", "branches");
|
|
47
|
+
else this.context.hooks?.cache?.onReset?.(repoPath, "remotes");
|
|
47
48
|
this.context.hooks?.repository?.onChanged?.(repoPath, ["remotes"]);
|
|
48
49
|
}
|
|
49
50
|
async addRemoteWithResult(repoPath, name, url, options) {
|
|
@@ -58,7 +59,7 @@ var RemotesGitSubProvider = class extends RemotesGitProviderBase {
|
|
|
58
59
|
}
|
|
59
60
|
async removeRemote(repoPath, name) {
|
|
60
61
|
await this.git.run({ cwd: repoPath }, "remote", "remove", name);
|
|
61
|
-
this.context.hooks?.cache?.onReset?.(repoPath, "remotes");
|
|
62
|
+
this.context.hooks?.cache?.onReset?.(repoPath, "remotes", "branches");
|
|
62
63
|
this.context.hooks?.repository?.onChanged?.(repoPath, ["remotes"]);
|
|
63
64
|
}
|
|
64
65
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remotes.js","names":[],"sources":["../../../../git-cli/src/providers/remotes.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitRemote } from '@gitlens/git/models/remote.js';\nimport type { GitRemotesSubProvider } from '@gitlens/git/providers/remotes.js';\nimport { RemotesGitProviderBase } from '@gitlens/git/providers/shared/remotes.js';\nimport { createRemoteProviderMatcher } from '@gitlens/git/remotes/matcher.js';\nimport { sortRemotes } from '@gitlens/git/utils/sorting.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { parseGitRemotes } from '../parsers/remoteParser.js';\n\nexport class RemotesGitSubProvider extends RemotesGitProviderBase implements GitRemotesSubProvider {\n\tconstructor(\n\t\tcontext: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tcache: Cache,\n\t\tprovider: CliGitProviderInternal,\n\t) {\n\t\tsuper(context, cache, provider);\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync getRemotes(\n\t\trepoPath: string | undefined,\n\t\toptions?: { filter?: (remote: GitRemote) => boolean; sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]> {\n\t\tif (repoPath == null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\tlet remotes = await this.cache.getRemotes(\n\t\t\trepoPath,\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 configs = await this.context.remotes?.getCustomProviders?.(repoPath);\n\t\t\t\tconst remoteProviderMatcher = createRemoteProviderMatcher(configs, this.context.remotes);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\tcaching: { cache: this.cache.gitResults, commonPath: commonPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'remote',\n\t\t\t\t\t\t'-v',\n\t\t\t\t\t);\n\n\t\t\t\t\t// Fetch default remote name from GK config before parsing so it's set at construction time\n\t\t\t\t\tconst defaultName = await this.provider.config.getGkConfig?.(repoPath, 'gk.defaultRemote');\n\t\t\t\t\tconst remotes = parseGitRemotes(result.stdout, commonPath, remoteProviderMatcher, defaultName);\n\n\t\t\t\t\treturn remotes;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\tif (options?.filter != null) {\n\t\t\tremotes = remotes.filter(options.filter);\n\t\t}\n\n\t\tif (options?.sort) {\n\t\t\tsortRemotes(remotes);\n\t\t}\n\n\t\treturn remotes;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemote(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'add', options?.fetch ? '-f' : undefined, name, url);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemoteWithResult(\n\t\trepoPath: string,\n\t\tname: string,\n\t\turl: string,\n\t\toptions?: { fetch?: boolean },\n\t): Promise<GitRemote | undefined> {\n\t\tawait this.addRemote(repoPath, name, url, options);\n\t\tconst [remote] = await this.getRemotes(repoPath, { filter: r => r.url === url });\n\t\treturn remote;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync pruneRemote(repoPath: string, name: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'prune', name);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync removeRemote(repoPath: string, name: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'remove', name);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t}\n}\n"],"mappings":";;;;;;;;;AAcA,IAAa,wBAAb,cAA2C,uBAAwD;CAGhF;CAFlB,YACC,SACA,KACA,OACA,UACC;EACD,MAAM,SAAS,OAAO,QAAQ;EAJb,KAAA,MAAA;CAKlB;CAEA,MACM,WACL,UACA,SACA,cACuB;EACvB,IAAI,YAAY,MAAM,OAAO,CAAC;EAE9B,MAAM,QAAQ,gBAAgB;EAE9B,IAAI,UAAU,MAAM,KAAK,MAAM,WAC9B,UACA,OAAO,YAAY,WAAW,WAAW;GAExC,WAAW;GACX,MAAM,UAAU,MAAM,KAAK,QAAQ,SAAS,qBAAqB,QAAQ;GACzE,MAAM,wBAAwB,4BAA4B,SAAS,KAAK,QAAQ,OAAO;GAEvF,IAAI;IACH,MAAM,SAAS,MAAM,KAAK,IAAI,IAC7B;KACC,KAAK;KACL,cAAc;KACd,SAAS;MAAE,OAAO,KAAK,MAAM;MAAwB;KAAW;IACjE,GACA,UACA,IACD;IAGA,MAAM,cAAc,MAAM,KAAK,SAAS,OAAO,cAAc,UAAU,kBAAkB;IAGzF,OAFgB,gBAAgB,OAAO,QAAQ,YAAY,uBAAuB,WAErE;GACd,SAAS,IAAI;IACZ,UAAU,WAAW;IACrB,OAAO,MAAM,EAAE;IACf,OAAO,CAAC;GACT;EACD,GACA,YACD;EAEA,IAAI,SAAS,UAAU,MACtB,UAAU,QAAQ,OAAO,QAAQ,MAAM;EAGxC,IAAI,SAAS,MACZ,YAAY,OAAO;EAGpB,OAAO;CACR;CAEA,MAEM,UAAU,UAAkB,MAAc,KAAa,SAA8C;EAC1G,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,UAAU,OAAO,SAAS,QAAQ,OAAO,KAAA,GAAW,MAAM,GAAG;
|
|
1
|
+
{"version":3,"file":"remotes.js","names":[],"sources":["../../../../git-cli/src/providers/remotes.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitRemote } from '@gitlens/git/models/remote.js';\nimport type { GitRemotesSubProvider } from '@gitlens/git/providers/remotes.js';\nimport { RemotesGitProviderBase } from '@gitlens/git/providers/shared/remotes.js';\nimport { createRemoteProviderMatcher } from '@gitlens/git/remotes/matcher.js';\nimport { sortRemotes } from '@gitlens/git/utils/sorting.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { parseGitRemotes } from '../parsers/remoteParser.js';\n\nexport class RemotesGitSubProvider extends RemotesGitProviderBase implements GitRemotesSubProvider {\n\tconstructor(\n\t\tcontext: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tcache: Cache,\n\t\tprovider: CliGitProviderInternal,\n\t) {\n\t\tsuper(context, cache, provider);\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync getRemotes(\n\t\trepoPath: string | undefined,\n\t\toptions?: { filter?: (remote: GitRemote) => boolean; sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]> {\n\t\tif (repoPath == null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\tlet remotes = await this.cache.getRemotes(\n\t\t\trepoPath,\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 configs = await this.context.remotes?.getCustomProviders?.(repoPath);\n\t\t\t\tconst remoteProviderMatcher = createRemoteProviderMatcher(configs, this.context.remotes);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\tcaching: { cache: this.cache.gitResults, commonPath: commonPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'remote',\n\t\t\t\t\t\t'-v',\n\t\t\t\t\t);\n\n\t\t\t\t\t// Fetch default remote name from GK config before parsing so it's set at construction time\n\t\t\t\t\tconst defaultName = await this.provider.config.getGkConfig?.(repoPath, 'gk.defaultRemote');\n\t\t\t\t\tconst remotes = parseGitRemotes(result.stdout, commonPath, remoteProviderMatcher, defaultName);\n\n\t\t\t\t\treturn remotes;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\tif (options?.filter != null) {\n\t\t\tremotes = remotes.filter(options.filter);\n\t\t}\n\n\t\tif (options?.sort) {\n\t\t\tsortRemotes(remotes);\n\t\t}\n\n\t\treturn remotes;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemote(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'add', options?.fetch ? '-f' : undefined, name, url);\n\t\t// A fetch creates the remote's tracking branches, which the branch, ref and history caches hold\n\t\tif (options?.fetch) {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\t} else {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes');\n\t\t}\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemoteWithResult(\n\t\trepoPath: string,\n\t\tname: string,\n\t\turl: string,\n\t\toptions?: { fetch?: boolean },\n\t): Promise<GitRemote | undefined> {\n\t\tawait this.addRemote(repoPath, name, url, options);\n\t\tconst [remote] = await this.getRemotes(repoPath, { filter: r => r.url === url });\n\t\treturn remote;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync pruneRemote(repoPath: string, name: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'prune', name);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync removeRemote(repoPath: string, name: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'remove', name);\n\t\t// Removing a remote deletes its tracking branches too\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t}\n}\n"],"mappings":";;;;;;;;;AAcA,IAAa,wBAAb,cAA2C,uBAAwD;CAGhF;CAFlB,YACC,SACA,KACA,OACA,UACC;EACD,MAAM,SAAS,OAAO,QAAQ;EAJb,KAAA,MAAA;CAKlB;CAEA,MACM,WACL,UACA,SACA,cACuB;EACvB,IAAI,YAAY,MAAM,OAAO,CAAC;EAE9B,MAAM,QAAQ,gBAAgB;EAE9B,IAAI,UAAU,MAAM,KAAK,MAAM,WAC9B,UACA,OAAO,YAAY,WAAW,WAAW;GAExC,WAAW;GACX,MAAM,UAAU,MAAM,KAAK,QAAQ,SAAS,qBAAqB,QAAQ;GACzE,MAAM,wBAAwB,4BAA4B,SAAS,KAAK,QAAQ,OAAO;GAEvF,IAAI;IACH,MAAM,SAAS,MAAM,KAAK,IAAI,IAC7B;KACC,KAAK;KACL,cAAc;KACd,SAAS;MAAE,OAAO,KAAK,MAAM;MAAwB;KAAW;IACjE,GACA,UACA,IACD;IAGA,MAAM,cAAc,MAAM,KAAK,SAAS,OAAO,cAAc,UAAU,kBAAkB;IAGzF,OAFgB,gBAAgB,OAAO,QAAQ,YAAY,uBAAuB,WAErE;GACd,SAAS,IAAI;IACZ,UAAU,WAAW;IACrB,OAAO,MAAM,EAAE;IACf,OAAO,CAAC;GACT;EACD,GACA,YACD;EAEA,IAAI,SAAS,UAAU,MACtB,UAAU,QAAQ,OAAO,QAAQ,MAAM;EAGxC,IAAI,SAAS,MACZ,YAAY,OAAO;EAGpB,OAAO;CACR;CAEA,MAEM,UAAU,UAAkB,MAAc,KAAa,SAA8C;EAC1G,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,UAAU,OAAO,SAAS,QAAQ,OAAO,KAAA,GAAW,MAAM,GAAG;EAEnG,IAAI,SAAS,OACZ,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW,UAAU;OAEpE,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,SAAS;EAEzD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,SAAS,CAAC;CAClE;CAEA,MAEM,oBACL,UACA,MACA,KACA,SACiC;EACjC,MAAM,KAAK,UAAU,UAAU,MAAM,KAAK,OAAO;EACjD,MAAM,CAAC,UAAU,MAAM,KAAK,WAAW,UAAU,EAAE,SAAQ,MAAK,EAAE,QAAQ,IAAI,CAAC;EAC/E,OAAO;CACR;CAEA,MAEM,YAAY,UAAkB,MAA6B;EAChE,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,UAAU,SAAS,IAAI;EAC7D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW,UAAU;EACpE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,SAAS,CAAC;CAClE;CAEA,MAEM,aAAa,UAAkB,MAA6B;EACjE,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,UAAU,UAAU,IAAI;EAE9D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW,UAAU;EACpE,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,SAAS,CAAC;CAClE;AACD;AAhGE,WAAA,CAAA,MAAM,EAAE,OAAM,cAAa,EAAY,SAAS,GAAG,CAAC,CAAA,GAAA,sBAAA,WAAA,cAAA,IAAA;AAsDpD,WAAA,CAAA,KAAK,GACL,MAAM,CAAA,GAAA,sBAAA,WAAA,aAAA,IAAA;AAYN,WAAA,CAAA,KAAK,GACL,MAAM,CAAA,GAAA,sBAAA,WAAA,uBAAA,IAAA;AAYN,WAAA,CAAA,KAAK,GACL,MAAM,CAAA,GAAA,sBAAA,WAAA,eAAA,IAAA;AAON,WAAA,CAAA,KAAK,GACL,MAAM,CAAA,GAAA,sBAAA,WAAA,gBAAA,IAAA"}
|
|
@@ -15,6 +15,8 @@ export declare class RevisionGitSubProvider implements GitRevisionSubProvider {
|
|
|
15
15
|
exists(repoPath: string, path: string, revOrOptions?: string | {
|
|
16
16
|
untracked?: 'only' | 'include';
|
|
17
17
|
}): Promise<boolean>;
|
|
18
|
+
/** `hash-object` without `-w` computes the id in the repository's format without storing anything */
|
|
19
|
+
getEmptyTreeSha(repoPath: string): Promise<string>;
|
|
18
20
|
getRevisionContent(repoPath: string, path: string, rev: string): Promise<Uint8Array | undefined>;
|
|
19
21
|
getSubmoduleHead(repoPath: string, submodulePath: string): Promise<string | undefined>;
|
|
20
22
|
getTreeEntryForRevision(repoPath: string, path: string, rev: string): Promise<GitTreeEntry | undefined>;
|
|
@@ -44,6 +44,16 @@ var RevisionGitSubProvider = class {
|
|
|
44
44
|
return Boolean(result.stdout.trim());
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
|
+
/** `hash-object` without `-w` computes the id in the repository's format without storing anything */
|
|
48
|
+
getEmptyTreeSha(repoPath) {
|
|
49
|
+
return this.cache.getEmptyTreeSha(repoPath, async () => {
|
|
50
|
+
return (await this.git.run({
|
|
51
|
+
cwd: repoPath,
|
|
52
|
+
stdin: "",
|
|
53
|
+
errors: "throw"
|
|
54
|
+
}, "hash-object", "-t", "tree", "--stdin")).stdout.trim();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
47
57
|
getRevisionContent(repoPath, path, rev) {
|
|
48
58
|
const [relativePath, root] = splitPath(path, repoPath);
|
|
49
59
|
return this.showContentCore(root, relativePath, rev, {
|
|
@@ -277,6 +287,7 @@ var RevisionGitSubProvider = class {
|
|
|
277
287
|
};
|
|
278
288
|
}
|
|
279
289
|
};
|
|
290
|
+
__decorate([debug()], RevisionGitSubProvider.prototype, "getEmptyTreeSha", null);
|
|
280
291
|
__decorate([gate(), debug()], RevisionGitSubProvider.prototype, "getRevisionContent", null);
|
|
281
292
|
__decorate([debug()], RevisionGitSubProvider.prototype, "getSubmoduleHead", null);
|
|
282
293
|
__decorate([gate(), debug()], RevisionGitSubProvider.prototype, "getTreeEntryForRevision", null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revision.js","names":[],"sources":["../../../../git-cli/src/providers/revision.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { ShowError } from '@gitlens/git/errors.js';\nimport type { GitFileStatus } from '@gitlens/git/models/fileStatus.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTreeEntry } from '@gitlens/git/models/tree.js';\nimport type { GitRevisionSubProvider, ResolvedRevision } from '@gitlens/git/providers/revision.js';\nimport {\n\tisRevisionWithSuffix,\n\tisSha,\n\tisUncommitted,\n\tisUncommittedStaged,\n\tisUncommittedWithParentSuffix,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { first } from '@gitlens/utils/iterable.js';\nimport { splitPath } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { GitErrorHandling, GitRunOptions } from '../exec/exec.types.js';\nimport type { Git } from '../exec/git.js';\nimport { defaultExceptionHandler, getGitCommandError, gitConfigsLog, GitErrors } from '../exec/git.js';\nimport { parseGitLsFilesStaged } from '../parsers/indexParser.js';\nimport { getShaAndFileSummaryLogParser } from '../parsers/logParser.js';\nimport { parseGitTree } from '../parsers/treeParser.js';\n\nconst emptyArray: readonly GitTreeEntry[] = Object.freeze([]);\n\nexport class RevisionGitSubProvider implements GitRevisionSubProvider {\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\texists(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\trevOrOptions?: string | { untracked?: 'only' | 'include' },\n\t): Promise<boolean> {\n\t\tlet rev: string | undefined;\n\t\tlet untracked: 'only' | 'include' | undefined;\n\t\tif (typeof revOrOptions === 'string') {\n\t\t\trev = revOrOptions;\n\t\t} else if (revOrOptions != null) {\n\t\t\tuntracked = revOrOptions.untracked;\n\t\t}\n\n\t\tconst cacheKey = `${path}\\0${rev ?? ''}\\0${untracked ?? ''}`;\n\t\treturn this.cache.fileExistence.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\tconst args = ['ls-files'];\n\t\t\tif (rev) {\n\t\t\t\tif (!isUncommitted(rev)) {\n\t\t\t\t\targs.push(`--with-tree=${rev}`);\n\t\t\t\t} else if (isUncommittedStaged(rev)) {\n\t\t\t\t\targs.push('--stage');\n\t\t\t\t}\n\t\t\t} else if (untracked === 'only') {\n\t\t\t\targs.push('-o');\n\t\t\t} else if (untracked === 'include') {\n\t\t\t\t// Tracked (cached) OR untracked (others)\n\t\t\t\targs.push('-c', '-o');\n\t\t\t}\n\n\t\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'ignore' }, ...args, '--', path);\n\t\t\treturn Boolean(result.stdout.trim());\n\t\t});\n\t}\n\n\t@gate()\n\t@debug()\n\tgetRevisionContent(repoPath: string, path: string, rev: string): Promise<Uint8Array | undefined> {\n\t\tconst [relativePath, root] = splitPath(path, repoPath);\n\t\treturn this.showContentCore<Buffer>(root, relativePath, rev, { encoding: 'buffer', errors: 'throw' });\n\t}\n\n\t@debug()\n\tasync getSubmoduleHead(repoPath: string, submodulePath: string): Promise<string | undefined> {\n\t\t// Verify the path is a submodule (gitlink commit) in the parent tree, not just a regular directory\n\t\tconst treeEntry = await this.getTreeEntryForRevision(repoPath, submodulePath, 'HEAD');\n\t\tif (treeEntry?.type !== 'commit') return undefined;\n\n\t\tconst [relativePath, root] = splitPath(submodulePath, repoPath);\n\t\tconst submoduleFullPath = this.provider.getAbsoluteUri(relativePath, root).fsPath;\n\n\t\tconst result = await this.git.run({ cwd: submoduleFullPath, errors: 'ignore' }, 'rev-parse', 'HEAD');\n\t\tconst sha = result.stdout.trim();\n\t\treturn sha || undefined;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync getTreeEntryForRevision(repoPath: string, path: string, rev: string): Promise<GitTreeEntry | undefined> {\n\t\tif (!repoPath || !path) return undefined;\n\n\t\tconst [relativePath, root] = splitPath(path, repoPath);\n\n\t\tif (isUncommittedStaged(rev)) {\n\t\t\tlet result = await this.git.run(\n\t\t\t\t{ cwd: root, errors: 'ignore' },\n\t\t\t\t'ls-files',\n\t\t\t\t'-z',\n\t\t\t\t'--stage',\n\t\t\t\t'--',\n\t\t\t\trelativePath,\n\t\t\t);\n\n\t\t\tconst entries = parseGitLsFilesStaged(result.stdout, true);\n\t\t\tif (entries.length === 0) return undefined;\n\n\t\t\tconst entry = entries[0];\n\t\t\tresult = await this.git.run({ cwd: root }, 'cat-file', '-s', entry.oid);\n\t\t\tconst size = parseInt(result.stdout.trim(), 10) || 0;\n\n\t\t\treturn { ref: rev, oid: entry.oid, path: relativePath, size: size, type: 'blob' };\n\t\t}\n\n\t\tconst [entry] = await this.getTreeForRevisionCore(repoPath, rev, path);\n\t\treturn entry;\n\t}\n\n\t@debug()\n\tasync getTrackedFiles(repoPath: string): Promise<string[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'ignore' }, 'ls-files', '-z');\n\t\tconst data = result.stdout;\n\t\tif (!data) return [];\n\n\t\treturn [...new Set(data.split('\\0').filter(Boolean))];\n\t}\n\n\t@debug()\n\tasync getTreeForRevision(repoPath: string, rev: string): Promise<GitTreeEntry[]> {\n\t\treturn repoPath ? this.getTreeForRevisionCore(repoPath, rev) : [];\n\t}\n\n\t@gate()\n\tprivate async getTreeForRevisionCore(repoPath: string, rev: string, path?: string): Promise<GitTreeEntry[]> {\n\t\tconst hasPath = Boolean(path);\n\t\tconst args = hasPath ? ['ls-tree', '-l', rev, '--', path] : ['ls-tree', '-lrt', rev, '--'];\n\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'ignore' }, ...args);\n\t\tconst data = result.stdout.trim();\n\t\tif (!data) return emptyArray as GitTreeEntry[];\n\n\t\treturn parseGitTree(data, rev, hasPath);\n\t}\n\n\tprivate async showContentCore<T extends string | Buffer>(\n\t\trepoPath: string | undefined,\n\t\tpath: string,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tencoding?: string;\n\t\t\terrors?: GitErrorHandling;\n\t\t},\n\t): Promise<T | undefined> {\n\t\tconst [file, root] = splitPath(path, repoPath, true);\n\n\t\tif (isUncommittedStaged(rev)) {\n\t\t\trev = ':';\n\t\t}\n\t\tif (isUncommitted(rev)) throw new Error(`ref=${rev} is uncommitted`);\n\n\t\tconst opts: GitRunOptions = {\n\t\t\tconfigs: gitConfigsLog,\n\t\t\tcwd: root,\n\t\t\tencoding: options?.encoding ?? 'utf8',\n\t\t\terrors: 'throw',\n\t\t};\n\t\tconst args = rev.endsWith(':') ? `${rev}./${file}` : `${rev}:./${file}`;\n\t\tconst params = ['show', '--textconv', args, '--'];\n\n\t\ttry {\n\t\t\tconst result = await this.git.run<T>(opts, ...params);\n\t\t\treturn result.stdout;\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif (rev === ':' && GitErrors.badRevision.test(msg)) {\n\t\t\t\treturn this.showContentCore<T>(repoPath, path, 'HEAD:', options);\n\t\t\t}\n\n\t\t\tconst error = getGitCommandError(\n\t\t\t\t'show',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew ShowError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\trev: rev,\n\t\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath ?? '', args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (options?.errors === 'throw') throw error;\n\n\t\t\tif (\n\t\t\t\tShowError.is(error, 'invalidObject') ||\n\t\t\t\tShowError.is(error, 'invalidRevision') ||\n\t\t\t\tShowError.is(error, 'notFound') ||\n\t\t\t\tShowError.is(error, 'notInRevision')\n\t\t\t) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tdefaultExceptionHandler(ex, opts.cwd);\n\t\t\treturn '' as T;\n\t\t}\n\t}\n\n\t@debug({ args: (repoPath, shas) => ({ repoPath: repoPath, shas: `${shas.size} value(s)` }) })\n\tasync resolveShas(repoPath: string, shas: ReadonlySet<string>, cancellation?: AbortSignal): Promise<Set<string>> {\n\t\tconst resolved = new Set<string>();\n\t\tconst prefixes: string[] = [];\n\n\t\tfor (const value of shas) {\n\t\t\t// Pure hex 4-40 chars: resolve to full commit SHA(s) via disambiguation. Everything else\n\t\t\t// (refs, suffixed SHAs like `^`/`~1`/`:path`, non-hex, <4 hex) passes through unchanged.\n\t\t\tif (/^[0-9a-f]{4,40}$/i.test(value)) {\n\t\t\t\tprefixes.push(value);\n\t\t\t} else {\n\t\t\t\tresolved.add(value);\n\t\t\t}\n\t\t}\n\n\t\tif (prefixes.length) {\n\t\t\t// List every object (any type) whose id starts with any prefix (empty + exit 0 if none)\n\t\t\tconst rp = await this.git.run(\n\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t'rev-parse',\n\t\t\t\t...prefixes.map(p => `--disambiguate=${p}`),\n\t\t\t);\n\t\t\tconst oids = rp.stdout.split('\\n').filter(Boolean);\n\t\t\tif (oids.length) {\n\t\t\t\t// `--disambiguate` has no type filter, so keep only commit objects\n\t\t\t\tconst cf = await this.git.run(\n\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore', stdin: `${oids.join('\\n')}\\n` },\n\t\t\t\t\t'cat-file',\n\t\t\t\t\t'--batch-check=%(objectname) %(objecttype)',\n\t\t\t\t);\n\t\t\t\tfor (const line of cf.stdout.split('\\n')) {\n\t\t\t\t\tconst [oid, type] = line.split(' ');\n\t\t\t\t\tif (type === 'commit') {\n\t\t\t\t\t\tresolved.add(oid);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn resolved;\n\t}\n\n\t@debug()\n\tasync resolveRevision(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tpathOrUri?: string | Uri,\n\t\toptions?: { force?: boolean },\n\t): Promise<ResolvedRevision> {\n\t\tconst path = pathOrUri != null ? toFsPath(pathOrUri) : undefined;\n\t\tif (!ref || ref === deletedOrMissing) return { sha: ref, revision: ref };\n\n\t\tif (path == null) {\n\t\t\tif (isSha(ref)) return { sha: ref, revision: ref };\n\t\t\tif (ref.endsWith('^3')) return { sha: ref, revision: ref };\n\t\t} else if (isUncommitted(ref)) {\n\t\t\t// Uncommitted refs depend on index/working-tree state — resolve without caching\n\t\t\treturn this.resolveRevisionCore(repoPath, ref, path);\n\t\t}\n\n\t\tconst key = path != null ? `${ref}|${this.provider.getRelativePath(path, repoPath)}` : ref;\n\t\tif (options?.force) {\n\t\t\t// Hard-delete first: a later caller must never join a read that started before this one.\n\t\t\tthis.cache.resolvedRevisions.delete(repoPath, key);\n\t\t}\n\n\t\treturn this.cache.resolvedRevisions.getOrCreate(repoPath, key, () =>\n\t\t\tthis.resolveRevisionCore(repoPath, ref, path, options?.force),\n\t\t);\n\t}\n\n\tprivate async resolveRevisionCore(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tpath: string | undefined,\n\t\tforce?: boolean,\n\t): Promise<ResolvedRevision> {\n\t\tif (path == null) {\n\t\t\tconst sha = await this.provider.refs.validateReference(repoPath, ref, force ? { force: true } : undefined);\n\t\t\tif (sha == null) return { sha: ref, revision: ref };\n\n\t\t\treturn {\n\t\t\t\tsha: sha,\n\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? sha : ref,\n\t\t\t};\n\t\t}\n\n\t\tif (isUncommittedWithParentSuffix(ref)) {\n\t\t\tref = 'HEAD';\n\t\t}\n\t\tconst relativePath = this.provider.getRelativePath(path, repoPath);\n\n\t\tif (isUncommitted(ref)) {\n\t\t\tif (!isUncommittedStaged(ref)) {\n\t\t\t\treturn { sha: ref, revision: ref };\n\t\t\t}\n\n\t\t\t// Ensure that the file is actually staged\n\t\t\tconst status = await this.provider.status.getStatusForFile?.(repoPath, relativePath, { renames: false });\n\t\t\tif (status?.indexStatus) return { sha: ref, revision: ref };\n\n\t\t\tref = 'HEAD';\n\t\t}\n\n\t\tconst resolvedRevisionCaching = { cache: this.cache.gitResults, options: { accessTTL: 5 * 60 * 1000 } };\n\n\t\tconst parser = getShaAndFileSummaryLogParser();\n\t\tlet result = await this.git.run(\n\t\t\t// Forced here only: this read is keyed by `ref`, which can move; the follow-up below is keyed by a sha\n\t\t\t{ cwd: repoPath, errors: 'ignore', caching: { ...resolvedRevisionCaching, force: force } },\n\t\t\t'log',\n\t\t\t...parser.arguments,\n\t\t\t'-n1',\n\t\t\tref,\n\t\t\t'--',\n\t\t\trelativePath,\n\t\t);\n\n\t\tlet commit = first(parser.parse(result.stdout));\n\t\tlet file = commit?.files.find(f => f.path === relativePath);\n\t\tif (file == null) {\n\t\t\treturn {\n\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t};\n\t\t}\n\n\t\tif (file.status === 'A') {\n\t\t\treturn {\n\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t\tstatus: file.status as GitFileStatus,\n\t\t\t\toriginalPath: file.originalPath,\n\t\t\t};\n\t\t}\n\n\t\tif (file.status === 'D') {\n\t\t\t// If the file was deleted, check if it was moved or renamed\n\t\t\tresult = await this.git.run(\n\t\t\t\t{ cwd: repoPath, errors: 'ignore', caching: resolvedRevisionCaching },\n\t\t\t\t'log',\n\t\t\t\t...parser.arguments,\n\t\t\t\t'-n1',\n\n\t\t\t\tcommit!.sha,\n\t\t\t\t'--',\n\t\t\t);\n\n\t\t\tcommit = first(parser.parse(result.stdout));\n\t\t\tfile = commit?.files.find(f => f.path === relativePath || f.originalPath === relativePath);\n\t\t\tif (file == null) {\n\t\t\t\treturn {\n\t\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t// If it looks like non-sha like without a suffix then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t\tstatus: file.status as GitFileStatus,\n\t\t\t\tpath: file.path,\n\t\t\t\toriginalPath: file.originalPath,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\tstatus: file.status as GitFileStatus,\n\t\t\toriginalPath: file.originalPath,\n\t\t};\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"revision.js","names":[],"sources":["../../../../git-cli/src/providers/revision.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { ShowError } from '@gitlens/git/errors.js';\nimport type { GitFileStatus } from '@gitlens/git/models/fileStatus.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTreeEntry } from '@gitlens/git/models/tree.js';\nimport type { GitRevisionSubProvider, ResolvedRevision } from '@gitlens/git/providers/revision.js';\nimport {\n\tisRevisionWithSuffix,\n\tisSha,\n\tisUncommitted,\n\tisUncommittedStaged,\n\tisUncommittedWithParentSuffix,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { first } from '@gitlens/utils/iterable.js';\nimport { splitPath } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { GitErrorHandling, GitRunOptions } from '../exec/exec.types.js';\nimport type { Git } from '../exec/git.js';\nimport { defaultExceptionHandler, getGitCommandError, gitConfigsLog, GitErrors } from '../exec/git.js';\nimport { parseGitLsFilesStaged } from '../parsers/indexParser.js';\nimport { getShaAndFileSummaryLogParser } from '../parsers/logParser.js';\nimport { parseGitTree } from '../parsers/treeParser.js';\n\nconst emptyArray: readonly GitTreeEntry[] = Object.freeze([]);\n\nexport class RevisionGitSubProvider implements GitRevisionSubProvider {\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\texists(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\trevOrOptions?: string | { untracked?: 'only' | 'include' },\n\t): Promise<boolean> {\n\t\tlet rev: string | undefined;\n\t\tlet untracked: 'only' | 'include' | undefined;\n\t\tif (typeof revOrOptions === 'string') {\n\t\t\trev = revOrOptions;\n\t\t} else if (revOrOptions != null) {\n\t\t\tuntracked = revOrOptions.untracked;\n\t\t}\n\n\t\tconst cacheKey = `${path}\\0${rev ?? ''}\\0${untracked ?? ''}`;\n\t\treturn this.cache.fileExistence.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\tconst args = ['ls-files'];\n\t\t\tif (rev) {\n\t\t\t\tif (!isUncommitted(rev)) {\n\t\t\t\t\targs.push(`--with-tree=${rev}`);\n\t\t\t\t} else if (isUncommittedStaged(rev)) {\n\t\t\t\t\targs.push('--stage');\n\t\t\t\t}\n\t\t\t} else if (untracked === 'only') {\n\t\t\t\targs.push('-o');\n\t\t\t} else if (untracked === 'include') {\n\t\t\t\t// Tracked (cached) OR untracked (others)\n\t\t\t\targs.push('-c', '-o');\n\t\t\t}\n\n\t\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'ignore' }, ...args, '--', path);\n\t\t\treturn Boolean(result.stdout.trim());\n\t\t});\n\t}\n\n\t/** `hash-object` without `-w` computes the id in the repository's format without storing anything */\n\t@debug()\n\tgetEmptyTreeSha(repoPath: string): Promise<string> {\n\t\treturn this.cache.getEmptyTreeSha(repoPath, async () => {\n\t\t\tconst result = await this.git.run(\n\t\t\t\t{ cwd: repoPath, stdin: '', errors: 'throw' },\n\t\t\t\t'hash-object',\n\t\t\t\t'-t',\n\t\t\t\t'tree',\n\t\t\t\t'--stdin',\n\t\t\t);\n\t\t\treturn result.stdout.trim();\n\t\t});\n\t}\n\n\t@gate()\n\t@debug()\n\tgetRevisionContent(repoPath: string, path: string, rev: string): Promise<Uint8Array | undefined> {\n\t\tconst [relativePath, root] = splitPath(path, repoPath);\n\t\treturn this.showContentCore<Buffer>(root, relativePath, rev, { encoding: 'buffer', errors: 'throw' });\n\t}\n\n\t@debug()\n\tasync getSubmoduleHead(repoPath: string, submodulePath: string): Promise<string | undefined> {\n\t\t// Verify the path is a submodule (gitlink commit) in the parent tree, not just a regular directory\n\t\tconst treeEntry = await this.getTreeEntryForRevision(repoPath, submodulePath, 'HEAD');\n\t\tif (treeEntry?.type !== 'commit') return undefined;\n\n\t\tconst [relativePath, root] = splitPath(submodulePath, repoPath);\n\t\tconst submoduleFullPath = this.provider.getAbsoluteUri(relativePath, root).fsPath;\n\n\t\tconst result = await this.git.run({ cwd: submoduleFullPath, errors: 'ignore' }, 'rev-parse', 'HEAD');\n\t\tconst sha = result.stdout.trim();\n\t\treturn sha || undefined;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync getTreeEntryForRevision(repoPath: string, path: string, rev: string): Promise<GitTreeEntry | undefined> {\n\t\tif (!repoPath || !path) return undefined;\n\n\t\tconst [relativePath, root] = splitPath(path, repoPath);\n\n\t\tif (isUncommittedStaged(rev)) {\n\t\t\tlet result = await this.git.run(\n\t\t\t\t{ cwd: root, errors: 'ignore' },\n\t\t\t\t'ls-files',\n\t\t\t\t'-z',\n\t\t\t\t'--stage',\n\t\t\t\t'--',\n\t\t\t\trelativePath,\n\t\t\t);\n\n\t\t\tconst entries = parseGitLsFilesStaged(result.stdout, true);\n\t\t\tif (entries.length === 0) return undefined;\n\n\t\t\tconst entry = entries[0];\n\t\t\tresult = await this.git.run({ cwd: root }, 'cat-file', '-s', entry.oid);\n\t\t\tconst size = parseInt(result.stdout.trim(), 10) || 0;\n\n\t\t\treturn { ref: rev, oid: entry.oid, path: relativePath, size: size, type: 'blob' };\n\t\t}\n\n\t\tconst [entry] = await this.getTreeForRevisionCore(repoPath, rev, path);\n\t\treturn entry;\n\t}\n\n\t@debug()\n\tasync getTrackedFiles(repoPath: string): Promise<string[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'ignore' }, 'ls-files', '-z');\n\t\tconst data = result.stdout;\n\t\tif (!data) return [];\n\n\t\treturn [...new Set(data.split('\\0').filter(Boolean))];\n\t}\n\n\t@debug()\n\tasync getTreeForRevision(repoPath: string, rev: string): Promise<GitTreeEntry[]> {\n\t\treturn repoPath ? this.getTreeForRevisionCore(repoPath, rev) : [];\n\t}\n\n\t@gate()\n\tprivate async getTreeForRevisionCore(repoPath: string, rev: string, path?: string): Promise<GitTreeEntry[]> {\n\t\tconst hasPath = Boolean(path);\n\t\tconst args = hasPath ? ['ls-tree', '-l', rev, '--', path] : ['ls-tree', '-lrt', rev, '--'];\n\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'ignore' }, ...args);\n\t\tconst data = result.stdout.trim();\n\t\tif (!data) return emptyArray as GitTreeEntry[];\n\n\t\treturn parseGitTree(data, rev, hasPath);\n\t}\n\n\tprivate async showContentCore<T extends string | Buffer>(\n\t\trepoPath: string | undefined,\n\t\tpath: string,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tencoding?: string;\n\t\t\terrors?: GitErrorHandling;\n\t\t},\n\t): Promise<T | undefined> {\n\t\tconst [file, root] = splitPath(path, repoPath, true);\n\n\t\tif (isUncommittedStaged(rev)) {\n\t\t\trev = ':';\n\t\t}\n\t\tif (isUncommitted(rev)) throw new Error(`ref=${rev} is uncommitted`);\n\n\t\tconst opts: GitRunOptions = {\n\t\t\tconfigs: gitConfigsLog,\n\t\t\tcwd: root,\n\t\t\tencoding: options?.encoding ?? 'utf8',\n\t\t\terrors: 'throw',\n\t\t};\n\t\tconst args = rev.endsWith(':') ? `${rev}./${file}` : `${rev}:./${file}`;\n\t\tconst params = ['show', '--textconv', args, '--'];\n\n\t\ttry {\n\t\t\tconst result = await this.git.run<T>(opts, ...params);\n\t\t\treturn result.stdout;\n\t\t} catch (ex) {\n\t\t\tconst msg: string = ex?.toString() ?? '';\n\t\t\tif (rev === ':' && GitErrors.badRevision.test(msg)) {\n\t\t\t\treturn this.showContentCore<T>(repoPath, path, 'HEAD:', options);\n\t\t\t}\n\n\t\t\tconst error = getGitCommandError(\n\t\t\t\t'show',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew ShowError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason ?? 'other',\n\t\t\t\t\t\t\trev: rev,\n\t\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath ?? '', args: params },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (options?.errors === 'throw') throw error;\n\n\t\t\tif (\n\t\t\t\tShowError.is(error, 'invalidObject') ||\n\t\t\t\tShowError.is(error, 'invalidRevision') ||\n\t\t\t\tShowError.is(error, 'notFound') ||\n\t\t\t\tShowError.is(error, 'notInRevision')\n\t\t\t) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tdefaultExceptionHandler(ex, opts.cwd);\n\t\t\treturn '' as T;\n\t\t}\n\t}\n\n\t@debug({ args: (repoPath, shas) => ({ repoPath: repoPath, shas: `${shas.size} value(s)` }) })\n\tasync resolveShas(repoPath: string, shas: ReadonlySet<string>, cancellation?: AbortSignal): Promise<Set<string>> {\n\t\tconst resolved = new Set<string>();\n\t\tconst prefixes: string[] = [];\n\n\t\tfor (const value of shas) {\n\t\t\t// Pure hex 4-40 chars: resolve to full commit SHA(s) via disambiguation. Everything else\n\t\t\t// (refs, suffixed SHAs like `^`/`~1`/`:path`, non-hex, <4 hex) passes through unchanged.\n\t\t\tif (/^[0-9a-f]{4,40}$/i.test(value)) {\n\t\t\t\tprefixes.push(value);\n\t\t\t} else {\n\t\t\t\tresolved.add(value);\n\t\t\t}\n\t\t}\n\n\t\tif (prefixes.length) {\n\t\t\t// List every object (any type) whose id starts with any prefix (empty + exit 0 if none)\n\t\t\tconst rp = await this.git.run(\n\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t'rev-parse',\n\t\t\t\t...prefixes.map(p => `--disambiguate=${p}`),\n\t\t\t);\n\t\t\tconst oids = rp.stdout.split('\\n').filter(Boolean);\n\t\t\tif (oids.length) {\n\t\t\t\t// `--disambiguate` has no type filter, so keep only commit objects\n\t\t\t\tconst cf = await this.git.run(\n\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore', stdin: `${oids.join('\\n')}\\n` },\n\t\t\t\t\t'cat-file',\n\t\t\t\t\t'--batch-check=%(objectname) %(objecttype)',\n\t\t\t\t);\n\t\t\t\tfor (const line of cf.stdout.split('\\n')) {\n\t\t\t\t\tconst [oid, type] = line.split(' ');\n\t\t\t\t\tif (type === 'commit') {\n\t\t\t\t\t\tresolved.add(oid);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn resolved;\n\t}\n\n\t@debug()\n\tasync resolveRevision(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tpathOrUri?: string | Uri,\n\t\toptions?: { force?: boolean },\n\t): Promise<ResolvedRevision> {\n\t\tconst path = pathOrUri != null ? toFsPath(pathOrUri) : undefined;\n\t\tif (!ref || ref === deletedOrMissing) return { sha: ref, revision: ref };\n\n\t\tif (path == null) {\n\t\t\tif (isSha(ref)) return { sha: ref, revision: ref };\n\t\t\tif (ref.endsWith('^3')) return { sha: ref, revision: ref };\n\t\t} else if (isUncommitted(ref)) {\n\t\t\t// Uncommitted refs depend on index/working-tree state — resolve without caching\n\t\t\treturn this.resolveRevisionCore(repoPath, ref, path);\n\t\t}\n\n\t\tconst key = path != null ? `${ref}|${this.provider.getRelativePath(path, repoPath)}` : ref;\n\t\tif (options?.force) {\n\t\t\t// Hard-delete first: a later caller must never join a read that started before this one.\n\t\t\tthis.cache.resolvedRevisions.delete(repoPath, key);\n\t\t}\n\n\t\treturn this.cache.resolvedRevisions.getOrCreate(repoPath, key, () =>\n\t\t\tthis.resolveRevisionCore(repoPath, ref, path, options?.force),\n\t\t);\n\t}\n\n\tprivate async resolveRevisionCore(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tpath: string | undefined,\n\t\tforce?: boolean,\n\t): Promise<ResolvedRevision> {\n\t\tif (path == null) {\n\t\t\tconst sha = await this.provider.refs.validateReference(repoPath, ref, force ? { force: true } : undefined);\n\t\t\tif (sha == null) return { sha: ref, revision: ref };\n\n\t\t\treturn {\n\t\t\t\tsha: sha,\n\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? sha : ref,\n\t\t\t};\n\t\t}\n\n\t\tif (isUncommittedWithParentSuffix(ref)) {\n\t\t\tref = 'HEAD';\n\t\t}\n\t\tconst relativePath = this.provider.getRelativePath(path, repoPath);\n\n\t\tif (isUncommitted(ref)) {\n\t\t\tif (!isUncommittedStaged(ref)) {\n\t\t\t\treturn { sha: ref, revision: ref };\n\t\t\t}\n\n\t\t\t// Ensure that the file is actually staged\n\t\t\tconst status = await this.provider.status.getStatusForFile?.(repoPath, relativePath, { renames: false });\n\t\t\tif (status?.indexStatus) return { sha: ref, revision: ref };\n\n\t\t\tref = 'HEAD';\n\t\t}\n\n\t\tconst resolvedRevisionCaching = { cache: this.cache.gitResults, options: { accessTTL: 5 * 60 * 1000 } };\n\n\t\tconst parser = getShaAndFileSummaryLogParser();\n\t\tlet result = await this.git.run(\n\t\t\t// Forced here only: this read is keyed by `ref`, which can move; the follow-up below is keyed by a sha\n\t\t\t{ cwd: repoPath, errors: 'ignore', caching: { ...resolvedRevisionCaching, force: force } },\n\t\t\t'log',\n\t\t\t...parser.arguments,\n\t\t\t'-n1',\n\t\t\tref,\n\t\t\t'--',\n\t\t\trelativePath,\n\t\t);\n\n\t\tlet commit = first(parser.parse(result.stdout));\n\t\tlet file = commit?.files.find(f => f.path === relativePath);\n\t\tif (file == null) {\n\t\t\treturn {\n\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t};\n\t\t}\n\n\t\tif (file.status === 'A') {\n\t\t\treturn {\n\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t\tstatus: file.status as GitFileStatus,\n\t\t\t\toriginalPath: file.originalPath,\n\t\t\t};\n\t\t}\n\n\t\tif (file.status === 'D') {\n\t\t\t// If the file was deleted, check if it was moved or renamed\n\t\t\tresult = await this.git.run(\n\t\t\t\t{ cwd: repoPath, errors: 'ignore', caching: resolvedRevisionCaching },\n\t\t\t\t'log',\n\t\t\t\t...parser.arguments,\n\t\t\t\t'-n1',\n\n\t\t\t\tcommit!.sha,\n\t\t\t\t'--',\n\t\t\t);\n\n\t\t\tcommit = first(parser.parse(result.stdout));\n\t\t\tfile = commit?.files.find(f => f.path === relativePath || f.originalPath === relativePath);\n\t\t\tif (file == null) {\n\t\t\t\treturn {\n\t\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t\t// If it looks like non-sha like without a suffix then preserve it as the friendly name\n\t\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\t\tstatus: file.status as GitFileStatus,\n\t\t\t\tpath: file.path,\n\t\t\t\toriginalPath: file.originalPath,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsha: commit?.sha ?? deletedOrMissing,\n\t\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\t\trevision: isRevisionWithSuffix(ref) ? (commit?.sha ?? ref) : ref,\n\t\t\tstatus: file.status as GitFileStatus,\n\t\t\toriginalPath: file.originalPath,\n\t\t};\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Uri } from "../../utils/uri.js";
|
|
2
2
|
import { GitServiceContext } from "../../git/context.js";
|
|
3
3
|
import { Cache } from "../../git/cache.js";
|
|
4
|
+
import { GitOperationRunOptions } from "../../git/providers/operations.js";
|
|
4
5
|
import { DisposableTemporaryGitIndex, GitStagingSubProvider } from "../../git/providers/staging.js";
|
|
5
6
|
import { Git } from "../exec/git.js";
|
|
6
7
|
import { CliGitProviderInternal } from "../cliGitProvider.js";
|
|
@@ -34,7 +35,7 @@ export declare class StagingGitSubProvider implements GitStagingSubProvider {
|
|
|
34
35
|
directories?: boolean;
|
|
35
36
|
force?: boolean;
|
|
36
37
|
ignored?: boolean;
|
|
37
|
-
}): Promise<void>;
|
|
38
|
+
}, runOptions?: GitOperationRunOptions): Promise<void>;
|
|
38
39
|
/** What every index or working-tree mutation announces, so cached status is re-read and hosts are told. */
|
|
39
40
|
private announceIndexChanged;
|
|
40
41
|
}
|
|
@@ -143,17 +143,21 @@ var StagingGitSubProvider = class {
|
|
|
143
143
|
await this.git.run({ cwd: repoPath }, "reset", "-q");
|
|
144
144
|
this.announceIndexChanged(repoPath);
|
|
145
145
|
}
|
|
146
|
-
async clean(repoPath, options) {
|
|
146
|
+
async clean(repoPath, options, runOptions) {
|
|
147
147
|
const args = ["clean"];
|
|
148
148
|
if (options?.force ?? true) args.push("-f");
|
|
149
149
|
if (options?.directories) args.push("-d");
|
|
150
150
|
if (options?.ignored) args.push("-x");
|
|
151
151
|
if (options?.paths == null) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
try {
|
|
153
|
+
await this.git.run({
|
|
154
|
+
cwd: repoPath,
|
|
155
|
+
errors: "throw",
|
|
156
|
+
...runOptions
|
|
157
|
+
}, ...args);
|
|
158
|
+
} finally {
|
|
159
|
+
this.announceIndexChanged(repoPath);
|
|
160
|
+
}
|
|
157
161
|
return;
|
|
158
162
|
}
|
|
159
163
|
const paths = options.paths.map(toFsPath);
|
|
@@ -164,7 +168,8 @@ var StagingGitSubProvider = class {
|
|
|
164
168
|
try {
|
|
165
169
|
for (const batch of batches) await this.git.run({
|
|
166
170
|
cwd: repoPath,
|
|
167
|
-
errors: "throw"
|
|
171
|
+
errors: "throw",
|
|
172
|
+
...runOptions
|
|
168
173
|
}, ...args, "--", ...batch);
|
|
169
174
|
} finally {
|
|
170
175
|
this.announceIndexChanged(repoPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staging.js","names":["fs"],"sources":["../../../../git-cli/src/providers/staging.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport { tmpdir } from 'os';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { DisposableTemporaryGitIndex, GitStagingSubProvider } from '@gitlens/git/providers/staging.js';\nimport { countStringLength } from '@gitlens/utils/array.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { mixinAsyncDisposable } from '@gitlens/utils/disposable.js';\nimport { chunk } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { maxGitCliLength } from '../exec/git.js';\n\nexport class StagingGitSubProvider implements GitStagingSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync createTemporaryIndex(\n\t\trepoPath: string,\n\t\tfrom: 'empty' | 'current' | 'ref',\n\t\tref?: string,\n\t): Promise<DisposableTemporaryGitIndex> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Create a temporary index file\n\t\tconst tempDir = await fs.mkdtemp(joinPaths(tmpdir(), 'gl-'));\n\t\tconst tempIndex = joinPaths(tempDir, 'index');\n\n\t\tasync function dispose() {\n\t\t\t// Delete the temporary index file\n\t\t\ttry {\n\t\t\t\tawait fs.rm(tempDir, { recursive: true });\n\t\t\t} catch {\n\t\t\t\t// ignore cleanup errors\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Tell Git to use our soon to be created index file\n\t\t\tconst env = { GIT_INDEX_FILE: tempIndex };\n\n\t\t\tswitch (from) {\n\t\t\t\tcase 'empty':\n\t\t\t\t\t// Leave the temp index empty\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'current': {\n\t\t\t\t\t// Copy the current index to preserve staged state\n\t\t\t\t\tconst gitDir = await this.provider.config.getGitDir?.(repoPath);\n\t\t\t\t\tif (gitDir == null) throw new Error(l10n.t('Unable to determine git directory for {0}', repoPath));\n\n\t\t\t\t\tconst currentIndex = joinPaths(gitDir.uri.fsPath, 'index');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fs.copyFile(currentIndex, tempIndex);\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t// A repo that has never staged anything has no index file yet; git reads a missing\n\t\t\t\t\t\t// `GIT_INDEX_FILE` as an empty index, which is what 'current' means there. Any other\n\t\t\t\t\t\t// failure is real — don't silently hand back an index claiming everything is deleted.\n\t\t\t\t\t\tif ((ex as NodeJS.ErrnoException)?.code !== 'ENOENT') throw ex;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'ref': {\n\t\t\t\t\tif (ref == null) throw new Error(l10n.t(\"ref is required when from is 'ref'\"));\n\n\t\t\t\t\t// Create the temp index file from a base ref/sha\n\t\t\t\t\tconst newIndexResult = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, env: env },\n\t\t\t\t\t\t'ls-tree',\n\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t'-r',\n\t\t\t\t\t\t'--full-name',\n\t\t\t\t\t\tref,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (newIndexResult.stdout.trim()) {\n\t\t\t\t\t\t// Write the tree to our temp index\n\t\t\t\t\t\tawait this.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, env: env, stdin: newIndexResult.stdout },\n\t\t\t\t\t\t\t'update-index',\n\t\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t\t'--index-info',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mixinAsyncDisposable({ path: tempIndex, env: { GIT_INDEX_FILE: tempIndex } }, dispose);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\n\t\t\tvoid dispose();\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(pathOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync stageFiles(\n\t\trepoPath: string,\n\t\tpathsOrUris: (string | Uri)[],\n\t\toptions?: { intentToAdd?: boolean; index?: DisposableTemporaryGitIndex },\n\t): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run(\n\t\t\t\t\t{ cwd: repoPath, env: options?.index?.env },\n\t\t\t\t\t'add',\n\t\t\t\t\toptions?.intentToAdd ? '-N' : '-A',\n\t\t\t\t\t'--',\n\t\t\t\t\t...batch,\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Announced even when a later batch fails, since the earlier ones already changed the index. A\n\t\t\t// temporary index (used for partial-stage previews / diff building) is not the repository's real\n\t\t\t// index — firing repo-change hooks for it would invalidate status caches for a mutation nothing\n\t\t\t// else can observe.\n\t\t\tif (options?.index == null) {\n\t\t\t\tthis.announceIndexChanged(repoPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(directoryOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(pathOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageFiles(repoPath: string, pathsOrUris: (string | Uri)[]): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already changed the index\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t@debug()\n\tasync unstageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(directoryOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync removeFile(repoPath: string, pathOrUri: string | Uri, options?: { force?: boolean }): Promise<void> {\n\t\tconst args = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--', toFsPath(pathOrUri));\n\t\tawait this.git.run({ cwd: repoPath }, ...args);\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync removeFiles(repoPath: string, pathsOrUris: (string | Uri)[], options?: { force?: boolean }): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\tconst args: string[] = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--');\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath }, ...args, ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already changed the index\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A');\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q');\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync clean(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tpaths?: (string | Uri)[];\n\t\t\tdirectories?: boolean;\n\t\t\tforce?: boolean;\n\t\t\tignored?: boolean;\n\t\t},\n\t): Promise<void> {\n\t\tconst args = ['clean'];\n\t\tif (options?.force ?? true) {\n\t\t\targs.push('-f');\n\t\t}\n\t\tif (options?.directories) {\n\t\t\targs.push('-d');\n\t\t}\n\t\tif (options?.ignored) {\n\t\t\targs.push('-x');\n\t\t}\n\n\t\tif (options?.paths == null) {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...args);\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tconst paths = options.paths.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process paths in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...args, '--', ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already removed files\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t/** What every index or working-tree mutation announces, so cached status is re-read and hosts are told. */\n\tprivate announceIndexChanged(repoPath: string): void {\n\t\t// `diff` and `tracking` too, as a watcher-observed index change clears them: a file's working-vs-index\n\t\t// diff and whether it is tracked both change when it is staged, unstaged or removed\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'status', 'diff', 'tracking');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['index']);\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"staging.js","names":["fs"],"sources":["../../../../git-cli/src/providers/staging.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport { tmpdir } from 'os';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitOperationRunOptions } from '@gitlens/git/providers/operations.js';\nimport type { DisposableTemporaryGitIndex, GitStagingSubProvider } from '@gitlens/git/providers/staging.js';\nimport { countStringLength } from '@gitlens/utils/array.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { mixinAsyncDisposable } from '@gitlens/utils/disposable.js';\nimport { chunk } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { maxGitCliLength } from '../exec/git.js';\n\nexport class StagingGitSubProvider implements GitStagingSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync createTemporaryIndex(\n\t\trepoPath: string,\n\t\tfrom: 'empty' | 'current' | 'ref',\n\t\tref?: string,\n\t): Promise<DisposableTemporaryGitIndex> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Create a temporary index file\n\t\tconst tempDir = await fs.mkdtemp(joinPaths(tmpdir(), 'gl-'));\n\t\tconst tempIndex = joinPaths(tempDir, 'index');\n\n\t\tasync function dispose() {\n\t\t\t// Delete the temporary index file\n\t\t\ttry {\n\t\t\t\tawait fs.rm(tempDir, { recursive: true });\n\t\t\t} catch {\n\t\t\t\t// ignore cleanup errors\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Tell Git to use our soon to be created index file\n\t\t\tconst env = { GIT_INDEX_FILE: tempIndex };\n\n\t\t\tswitch (from) {\n\t\t\t\tcase 'empty':\n\t\t\t\t\t// Leave the temp index empty\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'current': {\n\t\t\t\t\t// Copy the current index to preserve staged state\n\t\t\t\t\tconst gitDir = await this.provider.config.getGitDir?.(repoPath);\n\t\t\t\t\tif (gitDir == null) throw new Error(l10n.t('Unable to determine git directory for {0}', repoPath));\n\n\t\t\t\t\tconst currentIndex = joinPaths(gitDir.uri.fsPath, 'index');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fs.copyFile(currentIndex, tempIndex);\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t// A repo that has never staged anything has no index file yet; git reads a missing\n\t\t\t\t\t\t// `GIT_INDEX_FILE` as an empty index, which is what 'current' means there. Any other\n\t\t\t\t\t\t// failure is real — don't silently hand back an index claiming everything is deleted.\n\t\t\t\t\t\tif ((ex as NodeJS.ErrnoException)?.code !== 'ENOENT') throw ex;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'ref': {\n\t\t\t\t\tif (ref == null) throw new Error(l10n.t(\"ref is required when from is 'ref'\"));\n\n\t\t\t\t\t// Create the temp index file from a base ref/sha\n\t\t\t\t\tconst newIndexResult = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, env: env },\n\t\t\t\t\t\t'ls-tree',\n\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t'-r',\n\t\t\t\t\t\t'--full-name',\n\t\t\t\t\t\tref,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (newIndexResult.stdout.trim()) {\n\t\t\t\t\t\t// Write the tree to our temp index\n\t\t\t\t\t\tawait this.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, env: env, stdin: newIndexResult.stdout },\n\t\t\t\t\t\t\t'update-index',\n\t\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t\t'--index-info',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mixinAsyncDisposable({ path: tempIndex, env: { GIT_INDEX_FILE: tempIndex } }, dispose);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\n\t\t\tvoid dispose();\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(pathOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync stageFiles(\n\t\trepoPath: string,\n\t\tpathsOrUris: (string | Uri)[],\n\t\toptions?: { intentToAdd?: boolean; index?: DisposableTemporaryGitIndex },\n\t): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run(\n\t\t\t\t\t{ cwd: repoPath, env: options?.index?.env },\n\t\t\t\t\t'add',\n\t\t\t\t\toptions?.intentToAdd ? '-N' : '-A',\n\t\t\t\t\t'--',\n\t\t\t\t\t...batch,\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Announced even when a later batch fails, since the earlier ones already changed the index. A\n\t\t\t// temporary index (used for partial-stage previews / diff building) is not the repository's real\n\t\t\t// index — firing repo-change hooks for it would invalidate status caches for a mutation nothing\n\t\t\t// else can observe.\n\t\t\tif (options?.index == null) {\n\t\t\t\tthis.announceIndexChanged(repoPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(directoryOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(pathOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageFiles(repoPath: string, pathsOrUris: (string | Uri)[]): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already changed the index\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t@debug()\n\tasync unstageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(directoryOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync removeFile(repoPath: string, pathOrUri: string | Uri, options?: { force?: boolean }): Promise<void> {\n\t\tconst args = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--', toFsPath(pathOrUri));\n\t\tawait this.git.run({ cwd: repoPath }, ...args);\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync removeFiles(repoPath: string, pathsOrUris: (string | Uri)[], options?: { force?: boolean }): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\tconst args: string[] = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--');\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath }, ...args, ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already changed the index\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A');\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q');\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync clean(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tpaths?: (string | Uri)[];\n\t\t\tdirectories?: boolean;\n\t\t\tforce?: boolean;\n\t\t\tignored?: boolean;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst args = ['clean'];\n\t\tif (options?.force ?? true) {\n\t\t\targs.push('-f');\n\t\t}\n\t\tif (options?.directories) {\n\t\t\targs.push('-d');\n\t\t}\n\t\tif (options?.ignored) {\n\t\t\targs.push('-x');\n\t\t}\n\n\t\tif (options?.paths == null) {\n\t\t\ttry {\n\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...args);\n\t\t\t} finally {\n\t\t\t\t// A clean that failed or was cancelled partway may already have removed files\n\t\t\t\tthis.announceIndexChanged(repoPath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst paths = options.paths.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process paths in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...args, '--', ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already removed files\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t/** What every index or working-tree mutation announces, so cached status is re-read and hosts are told. */\n\tprivate announceIndexChanged(repoPath: string): void {\n\t\t// `diff` and `tracking` too, as a watcher-observed index change clears them: a file's working-vs-index\n\t\t// diff and whether it is tracked both change when it is staged, unstaged or removed\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'status', 'diff', 'tracking');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['index']);\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { GitStashCommit } from "../../git/models/commit.js";
|
|
|
4
4
|
import { GitServiceContext } from "../../git/context.js";
|
|
5
5
|
import { GitStash } from "../../git/models/stash.js";
|
|
6
6
|
import { Cache } from "../../git/cache.js";
|
|
7
|
+
import { GitOperationRunOptions } from "../../git/providers/operations.js";
|
|
7
8
|
import { GitStashSubProvider, StashApplyResult } from "../../git/providers/stash.js";
|
|
8
9
|
import { Git } from "../exec/git.js";
|
|
9
10
|
import { CliGitProviderInternal } from "../cliGitProvider.js";
|
|
@@ -17,7 +18,7 @@ export declare class StashGitSubProvider implements GitStashSubProvider {
|
|
|
17
18
|
applyStash(repoPath: string, stashNameOrSha: string, options?: {
|
|
18
19
|
deleteAfter?: boolean;
|
|
19
20
|
index?: boolean;
|
|
20
|
-
}): Promise<StashApplyResult>;
|
|
21
|
+
}, runOptions?: GitOperationRunOptions): Promise<StashApplyResult>;
|
|
21
22
|
private applyStashCore;
|
|
22
23
|
createStash(repoPath: string, message?: string): Promise<string | undefined>;
|
|
23
24
|
getStash(repoPath: string, options?: {
|
|
@@ -36,7 +37,7 @@ export declare class StashGitSubProvider implements GitStashSubProvider {
|
|
|
36
37
|
includeUntracked?: boolean;
|
|
37
38
|
keepIndex?: boolean;
|
|
38
39
|
onlyStaged?: boolean;
|
|
39
|
-
}): Promise<void>;
|
|
40
|
+
}, runOptions?: GitOperationRunOptions): Promise<void>;
|
|
40
41
|
private stashPushCore;
|
|
41
42
|
saveSnapshot(repoPath: string, message?: string): Promise<void>;
|
|
42
43
|
}
|