@gitkraken/core-gitlens 0.17.0 → 0.18.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 +4 -1
- package/dist/git/cache.d.ts +7 -0
- package/dist/git/cache.js +21 -3
- package/dist/git/cache.js.map +1 -1
- package/dist/git/watching/gitIgnoreFilter.d.ts +21 -3
- package/dist/git/watching/gitIgnoreFilter.js +74 -14
- package/dist/git/watching/gitIgnoreFilter.js.map +1 -1
- package/dist/git/watching/provider.d.ts +9 -1
- package/dist/git/watching/watchService.d.ts +14 -1
- package/dist/git/watching/watchService.js +57 -16
- package/dist/git/watching/watchService.js.map +1 -1
- package/dist/git/watching/worktreeSummary.d.ts +38 -10
- package/dist/git/watching/worktreeSummary.js +164 -50
- package/dist/git/watching/worktreeSummary.js.map +1 -1
- package/dist/git-cli/cliGitProvider.js +4 -4
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/providers/branches.js +1 -32
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/config.d.ts +21 -0
- package/dist/git-cli/providers/config.js +72 -1
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +0 -1
- package/dist/plus/integrations/reads/drains.d.ts +0 -1
- package/package.json +1 -1
package/dist/git/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","names":[],"sources":["../../../git/src/cache.ts"],"sourcesContent":["import { exhaustiveArray } from '@gitlens/utils/array.js';\nimport { CancellationError, raceWithSignal } from '@gitlens/utils/cancellation.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { invalidateMemoized } from '@gitlens/utils/decorators/memoize.js';\nimport type { Event } from '@gitlens/utils/event.js';\nimport { Emitter } from '@gitlens/utils/event.js';\nimport { getBranchId } from '@gitlens/utils/gitRefs.js';\nimport type { PagedResult } from '@gitlens/utils/paging.js';\nimport { normalizePath } from '@gitlens/utils/path.js';\nimport type { PromiseOrValue } from '@gitlens/utils/promise.js';\nimport type { CacheController } from '@gitlens/utils/promiseCache.js';\nimport { PromiseCache, PromiseMap, RepoPromiseCacheMap } from '@gitlens/utils/promiseCache.js';\nimport type { ResourceUsage } from '@gitlens/utils/resourceUsage.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport type { ProgressiveGitBlame } from './models/blame.js';\nimport type { BranchMetadata, BranchMetadataGkConfigKey, GitBranch } from './models/branch.js';\nimport type { GitCommit, GitStashCommit } from './models/commit.js';\nimport type { GitContributor, GitContributorsStats } from './models/contributor.js';\nimport type { ParsedGitDiffHunks } from './models/diff.js';\nimport type { GitLog } from './models/log.js';\nimport type { ConflictDetectionResult } from './models/mergeConflicts.js';\nimport type { GitPausedOperationStatus } from './models/pausedOperationStatus.js';\nimport type { GitBranchReference, GitRefTip, RefRecord } from './models/reference.js';\nimport type { GitRemote } from './models/remote.js';\nimport type { RemoteProvider } from './models/remoteProvider.js';\nimport type { GitDir, RepositoryChange } from './models/repository.js';\nimport type { GitStash } from './models/stash.js';\nimport type { GitTag } from './models/tag.js';\nimport type { GitUser } from './models/user.js';\nimport type { GitWorktree } from './models/worktree.js';\nimport type { BranchContributionsOverview, GitBranchMergedStatus, MergeTarget } from './providers/branches.js';\nimport type { GitCommitReachability, LeftRightCommitCountResult } from './providers/commits.js';\nimport type { GitContributorsResult } from './providers/contributors.js';\nimport type { ResolvedRevision } from './providers/revision.js';\nimport type { GitResult } from './run.types.js';\nimport { parseBranchMetadataGkConfigKey, setBranchMetadataValue } from './utils/branch.utils.js';\nimport { createReference } from './utils/reference.utils.js';\nimport { getCommonRepositoryPath, getRepositoryOrWorktreePath } from './utils/repository.utils.js';\nimport type { GitIgnoreFilter } from './watching/gitIgnoreFilter.js';\n\ntype RepoPath = string;\n\n/** Cache types that are keyed by file path within a repo — support per-file clearing */\nexport type UriScopedCachedGitTypes = 'blame' | 'diff' | 'fileLog';\n\nconst uriScopedCachedGitTypes: UriScopedCachedGitTypes[] = ['blame', 'diff', 'fileLog'];\nexport function areUriScopedCachedGitTypes(types: string[]): types is UriScopedCachedGitTypes[] {\n\treturn types.every(t => uriScopedCachedGitTypes.includes(t as UriScopedCachedGitTypes));\n}\n\nexport type CachedGitTypes =\n\t| UriScopedCachedGitTypes\n\t| 'branch'\n\t| 'branches'\n\t| 'config'\n\t| 'contributors'\n\t| 'gitignore'\n\t| 'gkConfig'\n\t| 'lastFetched'\n\t| 'providers'\n\t| 'remotes'\n\t| 'stashes'\n\t| 'status'\n\t| 'tags'\n\t| 'tracking'\n\t| 'worktrees'\n\t/** Only the worktree list: unlike `'worktrees'`, no worktree's git results or merge targets */\n\t| 'worktreeList';\n\n/** Whether a reset of these types makes in-flight git runs stale (none or empty meaning every type) */\nexport function resetDropsPendingRuns(types: readonly CachedGitTypes[] | undefined): boolean {\n\t// A provider reset touches only remote-provider metadata, and the list's next read never joins a running\n\t// `worktree list`, as it runs under the cache's own signal: neither changes any git command's output\n\treturn !types?.length || types.some(t => t !== 'worktreeList' && t !== 'providers');\n}\n\n/**\n * What a gk-config reconcile did, so `Cache` knows whether the coarse fallback is still owed.\n *\n * `'deferred'` is NOT a failure — a pass already in flight folds the change into its trailing pass — and\n * must not trigger the fallback, or a burst of gk writes would coarse-clear on every one, which is exactly\n * the churn the key-aware reconcile replaced.\n */\nexport type GkReconcileOutcome = 'reconciled' | 'deferred' | 'failed';\n\n/** Fired by {@link Cache.onDidChangeMergeTargets} */\nexport interface MergeTargetsChangeEvent {\n\t/**\n\t * The repository's common path (the main worktree's, once registered). Merge keys live in the shared\n\t * `.git/gk/config`, so this fires once per change for the whole repository, not once per worktree.\n\t */\n\treadonly repoPath: string;\n\t/**\n\t * Branches whose merge-relevant keys (`gk-merge-base`, `gk-merge-target`, `gk-merge-target-user`,\n\t * `gk-target-base`) changed. `undefined` when it can't be told, so any branch's may have: the coarse fallback\n\t * (no reconciler, or a failed reconcile), or an external change with no earlier snapshot to diff against. Core's\n\t * own write names its one branch.\n\t */\n\treadonly refs: ReadonlySet<string> | undefined;\n}\n\nexport type ConflictDetectionCacheKey =\n\t| `apply:${string}:${string}:${string}`\n\t| `merge:${string}:${string}`\n\t| `reapply:${string}:${string}`;\n\n/**\n * Ceiling on how long a derived branch base is trusted. Long enough that repeated reads during normal use\n * are served from cache, short enough that a base that changed by a route with no eviction signal (an\n * external delete-and-recreate of a branch that is never checked out) self-heals without a reload.\n */\nconst baseBranchNameTTL = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Completed blame graphs retain several objects and substrings per line. Keep normal files hot, but let large\n * documents be owned by their active tracked-document snapshot instead of retaining a second long-lived owner.\n */\nconst maxCachedBlameLines = 5000;\n\nexport async function shouldEvictBlameCacheEntry(progressive: ProgressiveGitBlame | undefined): Promise<boolean> {\n\tif (progressive == null) return false;\n\n\ttry {\n\t\tconst blame = await progressive.completed;\n\t\treturn blame.lines.length > maxCachedBlameLines;\n\t} catch {\n\t\t// The provider factory resolves as soon as streaming starts, so a later stream failure must also be retried.\n\t\treturn true;\n\t}\n}\n\n/**\n * gkConfig keys that participate in the `branchOverviews` cache's mergeTarget/mergeBase lineage.\n * Capture group 1 is the ref name (which may itself contain `.`/`/`).\n */\nconst branchOverviewGkConfigKeysRegex = /^branch\\.(.+)\\.(?:gk-merge-(?:base|target(?:-user)?)|gk-target-base)$/;\n\n/** The ref of a gkConfig key the reconcile baseline tracks, or `undefined` for any other key */\nfunction getReconciledGkConfigRef(key: string): string | undefined {\n\treturn branchOverviewGkConfigKeysRegex.exec(key)?.[1] ?? parseBranchMetadataGkConfigKey(key)?.branch;\n}\n\n/** The value `cache` holds for `key`, `'pending'` while it is still being read, or `undefined` when nothing is cached */\nfunction getSettledOrPending<T>(\n\tcache: PromiseMap<string, T> | undefined,\n\tkey: string,\n): { value: T } | 'pending' | undefined {\n\tif (!cache?.has(key)) return undefined;\n\n\treturn cache.getSettled(key) ?? 'pending';\n}\n\n/**\n * Downstream caches that `deleteGkConfig` may invalidate when a `branch.<ref>.gk-...` key changes.\n * Callers performing a \"self-write\" (where the value being written matches what they just resolved,\n * so the about-to-be-evicted entry is exactly the entry they want to preserve) can opt out by\n * naming the targets to skip via `skipInvalidation`.\n */\nexport type GkConfigInvalidationTarget = 'branchOverviews' | 'baseBranchName';\n\n/**\n * A `getMergeTarget` answer with what it was read from, so a later call can confirm it from cached reads rather than\n * resolve it again (see {@link Cache.getMergeTarget})\n */\nexport interface CachedMergeTarget {\n\t/** The answer before `keepSelfAtTip` is applied */\n\treadonly result: MergeTarget | undefined;\n\t/** Whether `result` is the branch itself at the branch's own commit */\n\treadonly selfAtTip: boolean;\n\t/** Every full ref name whose presence or tip the answer depends on, with the commit it named then (`undefined` when absent) */\n\treadonly tips: ReadonlyArray<readonly [ref: string, tip: string | undefined]>;\n\t/**\n\t * The replace refs as read, as sorted `<name>\\0<sha>` lines ('' for none): replacing a commit moves merge bases\n\t * while every tip stands\n\t */\n\treadonly replaced: string;\n\t/**\n\t * The common git directory's `shallow` file as `<size>\\0<mtime>`, or `null` when the repo wasn't shallow: deepening\n\t * a shallow clone moves merge bases while every tip stands\n\t */\n\treadonly shallow: string | null;\n\t/** The `getAheadOfBaseConfigKey` snapshot the answer was read under */\n\treadonly configKey: string | undefined;\n\t/** The branch's stored merge keys as read, raw; `undefined` for a remote-tracking branch, which has none */\n\treadonly stored: readonly (string | undefined)[] | undefined;\n\t/** Set only when resolution reached the pull request and stored nothing: the base candidate it named, or `null` for none */\n\treadonly pullRequest?: string | null;\n\t/** Set only when the default branch was read: the name local refs gave, or `null` for none */\n\treadonly localDefault?: string | null;\n\t/** Set only when the remote was asked for its default branch: that remote, and its answer or `null` for none */\n\treadonly remoteDefault?: { readonly remote: string; readonly name: string | null };\n\t/** Set only when the caller's fallback default branch was asked: its answer, or `null` for none */\n\treadonly fallbackDefault?: string | null;\n\t/** The answer read HEAD's reflog for the branch it was created from and found none, which a later checkout can write */\n\treadonly evictOnCheckout: boolean;\n}\n\n/** A changed `branch.<branch>.<key>` gk config value for {@link Cache.patchBranchMetadata}; `undefined` is a removal */\nexport interface BranchMetadataChange {\n\treadonly branch: string;\n\treadonly key: BranchMetadataGkConfigKey;\n\treadonly value: string | undefined;\n}\n\n/** Per-worktree caches — cleared by repoPath directly */\ninterface Caches {\n\taheadOfBaseConfigKey: PromiseMap<RepoPath, string | undefined> | undefined;\n\tbestRemotes: PromiseMap<RepoPath, GitRemote<RemoteProvider>[]> | undefined;\n\tblame: RepoPromiseCacheMap<string, ProgressiveGitBlame | undefined> | undefined;\n\tbranch: PromiseMap<RepoPath, GitBranch | undefined> | undefined;\n\tcommit: RepoPromiseCacheMap<string, GitCommit | undefined> | undefined;\n\tcommitCount: RepoPromiseCacheMap<string, number | undefined> | undefined;\n\tconflictDetection: RepoPromiseCacheMap<ConflictDetectionCacheKey, ConflictDetectionResult> | undefined;\n\tcurrentBranchReference: PromiseCache<RepoPath, GitBranchReference | undefined> | undefined;\n\tcurrentUser: Map<RepoPath, GitUser | null> | undefined;\n\tdiff: RepoPromiseCacheMap<string, ParsedGitDiffHunks | undefined> | undefined;\n\tfileExistence: RepoPromiseCacheMap<string, boolean> | undefined;\n\tfileLog: RepoPromiseCacheMap<string, GitLog | undefined> | undefined;\n\tgitDir: Map<RepoPath, GitDir> | undefined;\n\tgitIgnore: Map<RepoPath, GitIgnoreFilter> | undefined;\n\tignoreRevsFile: PromiseCache<string, boolean> | undefined;\n\tleftRightCommitCount: RepoPromiseCacheMap<string, LeftRightCommitCountResult | undefined> | undefined;\n\tmergeBase: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tpatchIds: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tpausedOperationStatus: PromiseMap<RepoPath, GitPausedOperationStatus | undefined> | undefined;\n\treachability: RepoPromiseCacheMap<string, GitCommitReachability | undefined> | undefined;\n\tresolvedRevisions: RepoPromiseCacheMap<string, ResolvedRevision> | undefined;\n\ttrackedPaths: RepoPromiseCacheMap<string, [string, string] | false> | undefined;\n}\n\n/** Shared caches — cleared via commonPath + all worktree paths */\ninterface SharedCaches {\n\t/**\n\t * The `git config` listing behind `aheadOfBaseConfigKey`, read once in the main checkout for every checkout of the\n\t * repository; also the main checkout's own listing\n\t */\n\taheadOfBaseConfigListing: PromiseMap<RepoPath, string | undefined> | undefined;\n\tbaseBranchName: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tbranchMergedStatus: RepoPromiseCacheMap<string, GitBranchMergedStatus> | undefined;\n\tbranchMetadataMap: PromiseMap<RepoPath, Map<string, BranchMetadata>> | undefined;\n\tbranchOverviews: RepoPromiseCacheMap<string, BranchContributionsOverview | undefined> | undefined;\n\tbranches: PromiseMap<RepoPath, PagedResult<GitBranch>> | undefined;\n\tconfigKeys: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tconfigPatterns: RepoPromiseCacheMap<string, Map<string, string>> | undefined;\n\tcontributors: RepoPromiseCacheMap<string, GitContributorsResult> | undefined;\n\tcontributorsLite: RepoPromiseCacheMap<string, GitContributor[]> | undefined;\n\tcontributorsStats: RepoPromiseCacheMap<string, GitContributorsStats | undefined> | undefined;\n\tdefaultBranchName: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\t/** The empty tree's id — a property of the repository's object format, which never changes for its lifetime. */\n\temptyTreeSha: PromiseMap<RepoPath, string> | undefined;\n\tgitResults: RepoPromiseCacheMap<string, GitResult> | undefined;\n\tgkConfigMap: PromiseMap<RepoPath, Map<string, string>> | undefined;\n\tinitialCommitSha: PromiseMap<RepoPath, string | undefined> | undefined;\n\t/** Keyed by commonPath — `FETCH_HEAD` lives in the common git dir, shared across worktrees. */\n\tlastFetched: PromiseCache<RepoPath, number | undefined> | undefined;\n\tlogShas: RepoPromiseCacheMap<string, string[]> | undefined;\n\tmergeTargets: RepoPromiseCacheMap<string, CachedMergeTarget> | undefined;\n\trefs: PromiseMap<RepoPath, RefRecord[]> | undefined;\n\trefTips: PromiseMap<RepoPath, GitRefTip[]> | undefined;\n\tremotes: PromiseMap<RepoPath, GitRemote[]> | undefined;\n\tsharedBranches: PromiseMap<RepoPath, PagedResult<GitBranch>> | undefined;\n\tstashes: RepoPromiseCacheMap<string, GitStash> | undefined;\n\ttags: PromiseMap<RepoPath, PagedResult<GitTag>> | undefined;\n\tworktrees: PromiseMap<RepoPath, GitWorktree[]> | undefined;\n}\n\ntype AllCaches = Caches & SharedCaches;\n\n/** Compile-time enforced: adding a key to SharedCaches without listing it here is a type error */\nconst sharedCacheKeys: ReadonlySet<keyof AllCaches> = new Set(\n\texhaustiveArray<keyof SharedCaches>()([\n\t\t'aheadOfBaseConfigListing',\n\t\t'baseBranchName',\n\t\t'branchMergedStatus',\n\t\t'branchMetadataMap',\n\t\t'branchOverviews',\n\t\t'branches',\n\t\t'configKeys',\n\t\t'configPatterns',\n\t\t'contributors',\n\t\t'contributorsLite',\n\t\t'contributorsStats',\n\t\t'defaultBranchName',\n\t\t'emptyTreeSha',\n\t\t'gitResults',\n\t\t'gkConfigMap',\n\t\t'initialCommitSha',\n\t\t'lastFetched',\n\t\t'logShas',\n\t\t'mergeTargets',\n\t\t'refs',\n\t\t'refTips',\n\t\t'remotes',\n\t\t'sharedBranches',\n\t\t'stashes',\n\t\t'tags',\n\t\t'worktrees',\n\t]),\n);\n\nfunction createEmptyCaches(): AllCaches {\n\treturn {\n\t\taheadOfBaseConfigKey: undefined,\n\t\taheadOfBaseConfigListing: undefined,\n\t\tbaseBranchName: undefined,\n\t\tbestRemotes: undefined,\n\t\tblame: undefined,\n\t\tbranch: undefined,\n\t\tbranchMergedStatus: undefined,\n\t\tbranchMetadataMap: undefined,\n\t\tbranchOverviews: undefined,\n\t\tbranches: undefined,\n\t\tcommit: undefined,\n\t\tcommitCount: undefined,\n\t\tfileExistence: undefined,\n\t\tignoreRevsFile: undefined,\n\t\tleftRightCommitCount: undefined,\n\t\tmergeBase: undefined,\n\t\tmergeTargets: undefined,\n\t\tpatchIds: undefined,\n\t\tconfigKeys: undefined,\n\t\tconfigPatterns: undefined,\n\t\tconflictDetection: undefined,\n\t\tdiff: undefined,\n\t\tfileLog: undefined,\n\t\tcontributors: undefined,\n\t\tcontributorsLite: undefined,\n\t\tcontributorsStats: undefined,\n\t\tcurrentBranchReference: undefined,\n\t\tcurrentUser: undefined,\n\t\tdefaultBranchName: undefined,\n\t\temptyTreeSha: undefined,\n\t\tgitDir: undefined,\n\t\tgitIgnore: undefined,\n\t\tgitResults: undefined,\n\t\tgkConfigMap: undefined,\n\t\tinitialCommitSha: undefined,\n\t\tlastFetched: undefined,\n\t\tlogShas: undefined,\n\t\tpausedOperationStatus: undefined,\n\t\tresolvedRevisions: undefined,\n\t\treachability: undefined,\n\t\trefs: undefined,\n\t\trefTips: undefined,\n\t\tremotes: undefined,\n\t\tsharedBranches: undefined,\n\t\tstashes: undefined,\n\t\ttags: undefined,\n\t\ttrackedPaths: undefined,\n\t\tworktrees: undefined,\n\t};\n}\n\nexport class Cache implements Disposable {\n\tprivate _caches: AllCaches = createEmptyCaches();\n\tprivate _commonPathRegistry = new Map<RepoPath, string>();\n\t/** Reverse index: commonPath → set of worktree repoPaths that share it */\n\tprivate _worktreesByCommonPath = new Map<string, Set<RepoPath>>();\n\t/** Monotonic per-worktree \"status clock\" — see {@link getStatusGeneration}. */\n\tprivate _statusGenerations = new Map<RepoPath, number>();\n\t/** Monotonic per-path \"close clock\" — see {@link getCloseGeneration}. */\n\tprivate _closeGenerations = new Map<RepoPath, number>();\n\t/** Per commonPath, the `mergeTargets` keys a checkout evicts (see {@link CachedMergeTarget.evictOnCheckout}) */\n\tprivate _mergeTargetsEvictedOnCheckout = new Map<string, Set<string>>();\n\t/** Bumped on each checkout eviction, so a merge target resolved across one isn't kept for the next */\n\tprivate _mergeTargetCheckoutGeneration = 0;\n\t/** Each merge target answer's entry as `mergeTargets` stored it, so dropping a stale answer can't drop its successor */\n\tprivate _mergeTargetStored = new WeakMap<CachedMergeTarget, Promise<CachedMergeTarget>>();\n\n\t/**\n\t * Per-commonPath snapshot of the subset of `.git/gk/config` that derived caches depend on — merge-relevant keys\n\t * ({@link branchOverviewGkConfigKeysRegex}) and branch metadata keys ({@link parseBranchMetadataGkConfigKey}) —\n\t * used by {@link reconcileGkConfigMap} to diff a watcher `'gkConfig'` event down to only the keys that actually\n\t * changed, instead of coarsely re-deriving `baseBranchName`/`branchOverviews` and the branches on every gk write.\n\t * Absent means \"never observed\".\n\t */\n\tprivate _gkConfigSnapshots = new Map<string, Map<string, string>>();\n\n\tprivate readonly _onDidChangeMergeTargets = new Emitter<MergeTargetsChangeEvent>();\n\t/**\n\t * Fires when a `.git/gk/config` write changed a branch's merge-relevant keys — never for a write that only touched\n\t * other keys (activity timestamps). Core's own key store fires it once, as the write completes (see\n\t * {@link recordGkConfigWrite}), and the watcher's later report of that write doesn't fire it again; core's own\n\t * section remove and rename (a branch delete or rename) never fire it, nor do its internal saves while answering\n\t * a read (nobody awaits those, and only another process's watcher reports them). Fires after the derived caches were\n\t * cleared, so a listener's re-read sees the new values. A listener must not write merge keys back in response,\n\t * or it loops.\n\t */\n\tget onDidChangeMergeTargets(): Event<MergeTargetsChangeEvent> {\n\t\treturn this._onDidChangeMergeTargets.event;\n\t}\n\n\t/**\n\t * Reconciler registered by the CLI config sub-provider (see {@link setGkConfigReconciler}),\n\t * invoked on a watcher-observed `'gkConfig'` change instead of the coarse `clearCaches(repoPath,\n\t * 'gkConfig')` cascade. `undefined` (e.g. the GitHub provider, which has no `.git/gk/config`)\n\t * falls back to the coarse clear.\n\t */\n\tprivate _gkConfigReconciler:\n\t\t| ((\n\t\t\t\trepoPath: string,\n\t\t\t\tpriorSnapshot: ReadonlyMap<string, string> | undefined,\n\t\t ) => PromiseOrValue<GkReconcileOutcome>)\n\t\t| undefined;\n\n\t[Symbol.dispose](): void {\n\t\tthis.dispose();\n\t}\n\n\tdispose(): void {\n\t\tthis.reset();\n\t\tthis._onDidChangeMergeTargets.dispose();\n\t}\n\n\t/** Resource usage retained by instantiated sub-caches and their bookkeeping maps. */\n\tgetResourceUsage(): ResourceUsage {\n\t\tconst usage: ResourceUsage = {};\n\t\tfor (const [name, cache] of Object.entries(this._caches)) {\n\t\t\tif (cache != null) {\n\t\t\t\tusage[`cache.${name}.entries.count`] =\n\t\t\t\t\tcache instanceof RepoPromiseCacheMap ? cache.entryCount : cache.size;\n\t\t\t}\n\t\t}\n\t\tusage['cache.commonPathRegistry.entries.count'] = this._commonPathRegistry.size;\n\t\tusage['cache.worktreesByCommonPath.entries.count'] = this._worktreesByCommonPath.size;\n\t\tusage['cache.statusGenerations.entries.count'] = this._statusGenerations.size;\n\t\tusage['cache.closeGenerations.entries.count'] = this._closeGenerations.size;\n\t\tusage['cache.gkConfigSnapshots.entries.count'] = this._gkConfigSnapshots.size;\n\t\treturn usage;\n\t}\n\n\tget aheadOfBaseConfigKey(): PromiseMap<RepoPath, string | undefined> {\n\t\treturn (this._caches.aheadOfBaseConfigKey ??= new PromiseMap<RepoPath, string | undefined>());\n\t}\n\n\tget aheadOfBaseConfigListing(): PromiseMap<RepoPath, string | undefined> {\n\t\treturn (this._caches.aheadOfBaseConfigListing ??= new PromiseMap<RepoPath, string | undefined>());\n\t}\n\n\tget bestRemotes(): PromiseMap<RepoPath, GitRemote<RemoteProvider>[]> {\n\t\treturn (this._caches.bestRemotes ??= new PromiseMap<RepoPath, GitRemote<RemoteProvider>[]>());\n\t}\n\n\tget blame(): RepoPromiseCacheMap<string, ProgressiveGitBlame | undefined> {\n\t\treturn (this._caches.blame ??= new RepoPromiseCacheMap<string, ProgressiveGitBlame | undefined>({\n\t\t\tcreateTTL: 1000 * 60 * 10, // 10 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tget diff(): RepoPromiseCacheMap<string, ParsedGitDiffHunks | undefined> {\n\t\treturn (this._caches.diff ??= new RepoPromiseCacheMap<string, ParsedGitDiffHunks | undefined>({\n\t\t\tcreateTTL: 1000 * 60 * 10, // 10 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tget fileLog(): RepoPromiseCacheMap<string, GitLog | undefined> {\n\t\treturn (this._caches.fileLog ??= new RepoPromiseCacheMap<string, GitLog | undefined>({\n\t\t\tcreateTTL: 1000 * 60 * 10, // 10 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tprivate get mergeTargets(): RepoPromiseCacheMap<string, CachedMergeTarget> {\n\t\treturn (this._caches.mergeTargets ??= new RepoPromiseCacheMap<string, CachedMergeTarget>());\n\t}\n\n\tprivate get baseBranchName(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.baseBranchName ??= new RepoPromiseCacheMap<string, string | undefined>());\n\t}\n\n\tget branch(): PromiseMap<RepoPath, GitBranch | undefined> {\n\t\treturn (this._caches.branch ??= new PromiseMap<RepoPath, GitBranch | undefined>());\n\t}\n\n\tget branchMergedStatus(): RepoPromiseCacheMap<string, GitBranchMergedStatus> {\n\t\treturn (this._caches.branchMergedStatus ??= new RepoPromiseCacheMap<string, GitBranchMergedStatus>({\n\t\t\tcreateTTL: 1000 * 60 * 30, // 30 minutes — content-keyed on tip shas, so this is just a backstop\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 100, // Limit to 100 branch-pairs per repo\n\t\t}));\n\t}\n\n\tprivate get branchMetadataMap(): PromiseMap<RepoPath, Map<string, BranchMetadata>> {\n\t\treturn (this._caches.branchMetadataMap ??= new PromiseMap<RepoPath, Map<string, BranchMetadata>>());\n\t}\n\n\tprivate get branchOverviews(): RepoPromiseCacheMap<string, BranchContributionsOverview | undefined> {\n\t\treturn (this._caches.branchOverviews ??= new RepoPromiseCacheMap<\n\t\t\tstring,\n\t\t\tBranchContributionsOverview | undefined\n\t\t>(\n\t\t\t{ accessTTL: 1000 * 60 * 60 }, // 60 minutes\n\t\t));\n\t}\n\n\tget branches(): PromiseMap<RepoPath, PagedResult<GitBranch>> {\n\t\treturn (this._caches.branches ??= new PromiseMap<RepoPath, PagedResult<GitBranch>>());\n\t}\n\n\t/**\n\t * Internal cache for raw shared branch data (keyed by commonPath)\n\t * Separate from branches cache because branches need to be mapped for each worktree\n\t */\n\tprivate get sharedBranches(): PromiseMap<RepoPath, PagedResult<GitBranch>> {\n\t\treturn (this._caches.sharedBranches ??= new PromiseMap<RepoPath, PagedResult<GitBranch>>());\n\t}\n\n\tprivate get configKeys(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.configKeys ??= new RepoPromiseCacheMap<string, string | undefined>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds - ensures global config changes are picked up\n\t\t}));\n\t}\n\n\tprivate get configPatterns(): RepoPromiseCacheMap<string, Map<string, string>> {\n\t\treturn (this._caches.configPatterns ??= new RepoPromiseCacheMap<string, Map<string, string>>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds - ensures global config changes are picked up\n\t\t}));\n\t}\n\n\tprivate get gkConfigMap(): PromiseMap<RepoPath, Map<string, string>> {\n\t\treturn (this._caches.gkConfigMap ??= new PromiseMap<RepoPath, Map<string, string>>());\n\t}\n\n\tget currentBranchReference(): PromiseCache<RepoPath, GitBranchReference | undefined> {\n\t\treturn (this._caches.currentBranchReference ??= new PromiseCache<RepoPath, GitBranchReference | undefined>());\n\t}\n\n\tsetCurrentBranchReferenceIfAbsent(worktreePath: string, reference: GitBranchReference | undefined): void {\n\t\tif (this.currentBranchReference.get(worktreePath) == null) {\n\t\t\tthis.currentBranchReference.set(worktreePath, Promise.resolve(reference));\n\t\t}\n\t}\n\n\tget conflictDetection(): RepoPromiseCacheMap<ConflictDetectionCacheKey, ConflictDetectionResult> {\n\t\treturn (this._caches.conflictDetection ??= new RepoPromiseCacheMap<\n\t\t\tConflictDetectionCacheKey,\n\t\t\tConflictDetectionResult\n\t\t>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds\n\t\t}));\n\t}\n\n\tget contributors(): RepoPromiseCacheMap<string, GitContributorsResult> {\n\t\treturn (this._caches.contributors ??= new RepoPromiseCacheMap<string, GitContributorsResult>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget contributorsLite(): RepoPromiseCacheMap<string, GitContributor[]> {\n\t\treturn (this._caches.contributorsLite ??= new RepoPromiseCacheMap<string, GitContributor[]>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget contributorsStats(): RepoPromiseCacheMap<string, GitContributorsStats | undefined> {\n\t\treturn (this._caches.contributorsStats ??= new RepoPromiseCacheMap<string, GitContributorsStats | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget currentUser(): Map<RepoPath, GitUser | null> {\n\t\treturn (this._caches.currentUser ??= new Map<RepoPath, GitUser | null>());\n\t}\n\n\tget defaultBranchName(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.defaultBranchName ??= new RepoPromiseCacheMap<string, string | undefined>());\n\t}\n\n\tget emptyTreeSha(): PromiseMap<RepoPath, string> {\n\t\treturn (this._caches.emptyTreeSha ??= new PromiseMap<RepoPath, string>());\n\t}\n\n\tget gitDir(): Map<RepoPath, GitDir> {\n\t\treturn (this._caches.gitDir ??= new Map<RepoPath, GitDir>());\n\t}\n\n\tget gitIgnore(): Map<RepoPath, GitIgnoreFilter> {\n\t\treturn (this._caches.gitIgnore ??= new Map<RepoPath, GitIgnoreFilter>());\n\t}\n\n\tget gitResults(): RepoPromiseCacheMap<RepoPath, GitResult> {\n\t\treturn (this._caches.gitResults ??= new RepoPromiseCacheMap<RepoPath, GitResult>({ capacity: 200 }));\n\t}\n\n\tget initialCommitSha(): PromiseMap<RepoPath, string | undefined> {\n\t\treturn (this._caches.initialCommitSha ??= new PromiseMap<RepoPath, string | undefined>());\n\t}\n\n\tget lastFetched(): PromiseCache<RepoPath, number | undefined> {\n\t\treturn (this._caches.lastFetched ??= new PromiseCache<RepoPath, number | undefined>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds\n\t\t}));\n\t}\n\n\tget leftRightCommitCount(): RepoPromiseCacheMap<string, LeftRightCommitCountResult | undefined> {\n\t\treturn (this._caches.leftRightCommitCount ??= new RepoPromiseCacheMap<\n\t\t\tstring,\n\t\t\tLeftRightCommitCountResult | undefined\n\t\t>({\n\t\t\tcreateTTL: 1000 * 60 * 5, // 5 minutes max age — invalidated sooner on branch/remote changes\n\t\t\tcapacity: 50, // Limit to 50 ref-pairs per repo\n\t\t}));\n\t}\n\n\tget commit(): RepoPromiseCacheMap<string, GitCommit | undefined> {\n\t\treturn (this._caches.commit ??= new RepoPromiseCacheMap<string, GitCommit | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 100, // Limit to 100 commits per repo\n\t\t}));\n\t}\n\n\tget commitCount(): RepoPromiseCacheMap<string, number | undefined> {\n\t\treturn (this._caches.commitCount ??= new RepoPromiseCacheMap<string, number | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tget mergeBase(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.mergeBase ??= new RepoPromiseCacheMap<string, string | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\t/**\n\t * Patch IDs keyed by full commit sha (plus `paths` and `verbatim`). A commit's content is immutable, so no\n\t * ref or worktree event can make an entry stale and nothing clears it short of a full cache reset. A cached\n\t * `undefined` is a real answer (a merge commit, or a change that is empty after `paths`). Kept per worktree,\n\t * not per repository, since an ID depends on the attributes of the checkout it was read from. Sized above a range\n\t * read of a couple thousand commits, so one read doesn't evict its own ids before the next.\n\t */\n\tget patchIds(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.patchIds ??= new RepoPromiseCacheMap<string, string | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 5000,\n\t\t}));\n\t}\n\n\tget logShas(): RepoPromiseCacheMap<string, string[]> {\n\t\treturn (this._caches.logShas ??= new RepoPromiseCacheMap<string, string[]>({\n\t\t\tcreateTTL: 1000 * 60 * 5, // 5 minutes max age\n\t\t\taccessTTL: 1000 * 30, // 30 seconds if not accessed\n\t\t\tcapacity: 5, // Limit to 5 different ranges per repo\n\t\t}));\n\t}\n\n\tget pausedOperationStatus(): PromiseMap<RepoPath, GitPausedOperationStatus | undefined> {\n\t\treturn (this._caches.pausedOperationStatus ??= new PromiseMap<\n\t\t\tRepoPath,\n\t\t\tGitPausedOperationStatus | undefined\n\t\t>());\n\t}\n\n\tget resolvedRevisions(): RepoPromiseCacheMap<string, ResolvedRevision> {\n\t\treturn (this._caches.resolvedRevisions ??= new RepoPromiseCacheMap<string, ResolvedRevision>({\n\t\t\tcapacity: 100,\n\t\t}));\n\t}\n\n\tget refs(): PromiseMap<RepoPath, RefRecord[]> {\n\t\treturn (this._caches.refs ??= new PromiseMap<RepoPath, RefRecord[]>());\n\t}\n\n\tget refTips(): PromiseMap<RepoPath, GitRefTip[]> {\n\t\treturn (this._caches.refTips ??= new PromiseMap<RepoPath, GitRefTip[]>());\n\t}\n\n\tget reachability(): RepoPromiseCacheMap<string, GitCommitReachability | undefined> {\n\t\treturn (this._caches.reachability ??= new RepoPromiseCacheMap<string, GitCommitReachability | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 25, // Limit to 25 commits per repo\n\t\t}));\n\t}\n\n\tget remotes(): PromiseMap<RepoPath, GitRemote[]> {\n\t\treturn (this._caches.remotes ??= new PromiseMap<RepoPath, GitRemote[]>());\n\t}\n\n\tget stashes(): RepoPromiseCacheMap<string, GitStash> {\n\t\treturn (this._caches.stashes ??= new RepoPromiseCacheMap<string, GitStash>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget tags(): PromiseMap<RepoPath, PagedResult<GitTag>> {\n\t\treturn (this._caches.tags ??= new PromiseMap<RepoPath, PagedResult<GitTag>>());\n\t}\n\n\tget fileExistence(): RepoPromiseCacheMap<string, boolean> {\n\t\treturn (this._caches.fileExistence ??= new RepoPromiseCacheMap<string, boolean>({\n\t\t\tcreateTTL: 1000 * 10, // 10 seconds\n\t\t\tcapacity: 100,\n\t\t\texpireOnError: true,\n\t\t}));\n\t}\n\n\t// Key: repoPath (not the ignoreRevsFile path) so that per-repo cache resets (clearCaches with repoPath)\n\t// correctly evict the entry. The actual file path is used inside the factory closure in blame.ts.\n\tget ignoreRevsFile(): PromiseCache<string, boolean> {\n\t\treturn (this._caches.ignoreRevsFile ??= new PromiseCache<string, boolean>({\n\t\t\taccessTTL: 1000 * 60 * 60 * 2, // 2 hours\n\t\t\texpireOnError: true,\n\t\t}));\n\t}\n\n\tget trackedPaths(): RepoPromiseCacheMap<string, [string, string] | false> {\n\t\treturn (this._caches.trackedPaths ??= new RepoPromiseCacheMap<string, [string, string] | false>({\n\t\t\tcreateTTL: 1000 * 60, // 60 seconds\n\t\t\taccessTTL: 1000 * 30, // 30 seconds idle\n\t\t\tcapacity: 200,\n\t\t}));\n\t}\n\n\tget worktrees(): PromiseMap<RepoPath, GitWorktree[]> {\n\t\treturn (this._caches.worktrees ??= new PromiseMap<RepoPath, GitWorktree[]>());\n\t}\n\n\t@debug({ onlyExit: true })\n\tclearCaches(repoPath: string | undefined, ...types: CachedGitTypes[]): void {\n\t\tthis.clearCachesCore('share', repoPath, types);\n\t}\n\n\t/**\n\t * Hard-evicts the same cache keys {@link clearCaches} would clear for `repoPath`, but a shared\n\t * (commonPath-keyed) entry that is still in flight is deleted outright instead of soft-invalidated —\n\t * a caller after this call never joins a read that started before it. Use for a forced read/write\n\t * that must not be answered from pre-change work; `clearCaches` remains the right call whenever\n\t * letting an in-flight read complete and share its answer with new callers is fine.\n\t */\n\tevictCaches(repoPath: string, ...types: CachedGitTypes[]): void {\n\t\tthis.clearCachesCore('evict', repoPath, types);\n\t}\n\n\t/** `worktreeOnly` leaves the shared (commonPath-keyed) entries alone (see {@link applyRepositoryChanges}) */\n\tprivate clearCachesCore(\n\t\tinFlight: 'share' | 'evict',\n\t\trepoPath: string | undefined,\n\t\ttypes: readonly CachedGitTypes[],\n\t\tworktreeOnly: boolean = false,\n\t): void {\n\t\tconst keysToClear = new Set<keyof AllCaches>();\n\n\t\tif (!types.length) {\n\t\t\t// Clear all caches\n\t\t\tfor (const key of Object.keys(this._caches)) {\n\t\t\t\tkeysToClear.add(key as keyof AllCaches);\n\t\t\t}\n\n\t\t\tinvalidateMemoized('providers');\n\t\t\tthis.incrementStatusGenerations(repoPath);\n\t\t\tif (!worktreeOnly) {\n\t\t\t\tthis.evictMergeTargetsOnCheckout(repoPath);\n\t\t\t}\n\t\t} else {\n\t\t\t// Clear specific cache types\n\t\t\tif (types.includes('blame')) {\n\t\t\t\tkeysToClear.add('blame');\n\t\t\t}\n\t\t\tif (types.includes('diff')) {\n\t\t\t\tkeysToClear.add('diff');\n\t\t\t}\n\t\t\tif (types.includes('fileLog')) {\n\t\t\t\tkeysToClear.add('fileLog');\n\t\t\t}\n\n\t\t\t// Branch caches affected by HEAD/heads changes. `branchMergedStatus` is deliberately NOT\n\t\t\t// cleared here — it's content-keyed on the involved tip shas, so tip movement already\n\t\t\t// self-invalidates (a new key); evicting it here would only discard still-valid answers.\n\t\t\tif (types.includes('branch') || types.includes('branches')) {\n\t\t\t\tkeysToClear.add('branch');\n\t\t\t\tkeysToClear.add('branchOverviews');\n\t\t\t\t// `commit`/`commitCount` are keyed by symbolic ref or SHA — symbolic-ref entries\n\t\t\t\t// can drift when branches move; cascade-clear conservatively.\n\t\t\t\tkeysToClear.add('commit');\n\t\t\t\tkeysToClear.add('commitCount');\n\t\t\t\tkeysToClear.add('conflictDetection');\n\t\t\t\tkeysToClear.add('currentBranchReference');\n\t\t\t\tkeysToClear.add('leftRightCommitCount');\n\t\t\t\t// `mergeBase` keyed by ref-pairs — symbolic refs can move; cascade-clear.\n\t\t\t\tkeysToClear.add('mergeBase');\n\t\t\t\tkeysToClear.add('reachability');\n\t\t\t\tkeysToClear.add('resolvedRevisions');\n\t\t\t}\n\n\t\t\t// Shared branch caches (branch list, metadata). `baseBranchName` is deliberately NOT cleared\n\t\t\t// here — a branch's base is set at creation and only changes when its stored key changes\n\t\t\t// (`gkConfig`/`config` below) or the branch itself is created/renamed/deleted. Every op that\n\t\t\t// does one of those calls `deleteBaseBranchName` and moves or drops the branch's persisted\n\t\t\t// `branch.<ref>.gk-*` keys: `createBranch`/`deleteLocalBranch`/`renameBranch`, plus the two\n\t\t\t// paths that create a branch as a side effect (`checkout -b`, `worktree add -b`). Tip movement\n\t\t\t// can't change a base, so clearing on every commit only forced a `git reflog` re-derivation.\n\t\t\tif (types.includes('branch')) {\n\t\t\t\t// A checkout can change includeIf.onbranch without writing any config file.\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigKey');\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigListing');\n\t\t\t\t// `'branch'` comes from a HEAD change — a checkout — which appends `checkout: moving from X\n\t\t\t\t// to Y` to the reflog, exactly the entry `getBaseBranchName` greps for when nothing is\n\t\t\t\t// stored. A base derived as \"none\" BEFORE that entry existed is cached with no TTL, so\n\t\t\t\t// without this it stays \"none\" for the session even though the answer now exists.\n\t\t\t\t//\n\t\t\t\t// Deliberately not under `'branches'`: a tip move can't change a branch's base, so re-deriving\n\t\t\t\t// on every commit would be pure cost. Checkouts are user-driven and rare by comparison.\n\t\t\t\tkeysToClear.add('baseBranchName');\n\t\t\t}\n\n\t\t\t// Only the merge targets that found no checkout entry in HEAD's reflog: every other one is confirmed against\n\t\t\t// what it read when next asked. A checkout in a worktree this one doesn't watch arrives as `'worktreeHead'`,\n\t\t\t// which maps to the `'worktrees'` cache type\n\t\t\tif (!worktreeOnly && (types.includes('branch') || types.includes('worktrees'))) {\n\t\t\t\tthis.evictMergeTargetsOnCheckout(repoPath);\n\t\t\t}\n\n\t\t\tif (types.includes('branches')) {\n\t\t\t\tkeysToClear.add('branchMetadataMap');\n\t\t\t\tkeysToClear.add('branches');\n\t\t\t\tkeysToClear.add('sharedBranches');\n\t\t\t\tkeysToClear.add('defaultBranchName');\n\t\t\t\tkeysToClear.add('initialCommitSha');\n\t\t\t\tkeysToClear.add('logShas');\n\t\t\t\tkeysToClear.add('refs');\n\t\t\t\tkeysToClear.add('refTips');\n\t\t\t\t// No change type clears `emptyTreeSha`: a repository's object format never changes. A full reset\n\t\t\t\t// (no types) still clears it, along with everything else\n\t\t\t}\n\n\t\t\tif (types.includes('config')) {\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigKey');\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigListing');\n\t\t\t\t// `getBaseBranchName` falls back to `branch.<ref>.vscode-merge-base` (written by VS Code's\n\t\t\t\t// built-in Git), which lives in `.git/config` — so a config change is the only signal that\n\t\t\t\t// source changed. Cheap: config events are rare.\n\t\t\t\tkeysToClear.add('baseBranchName');\n\t\t\t\tkeysToClear.add('configKeys');\n\t\t\t\tkeysToClear.add('configPatterns');\n\t\t\t\tkeysToClear.add('currentBranchReference');\n\t\t\t\tkeysToClear.add('currentUser');\n\t\t\t\t// `gitDir` is immutable repo topology (toplevel/git-dir/common-dir/superproject) — a\n\t\t\t\t// `.git/config` content change never relocates it, and it's owned by the repo lifecycle\n\t\t\t\t// (registerRepoPath/unregisterRepoPath). Clearing it here forced a redundant `git rev-parse`\n\t\t\t\t// re-spawn (gitDir is read by getGkConfigPath→getGitDir on every gk op), so leave it warm.\n\t\t\t}\n\n\t\t\tif (types.includes('contributors')) {\n\t\t\t\tkeysToClear.add('branchOverviews');\n\t\t\t\tkeysToClear.add('contributors');\n\t\t\t\tkeysToClear.add('contributorsLite');\n\t\t\t\tkeysToClear.add('contributorsStats');\n\t\t\t}\n\n\t\t\tif (types.includes('gitignore')) {\n\t\t\t\tkeysToClear.add('gitIgnore');\n\t\t\t}\n\n\t\t\tif (types.includes('gkConfig')) {\n\t\t\t\tkeysToClear.add('gkConfigMap');\n\t\t\t\t// Derived from `branch.<ref>.gk-merge-base`/`vscode-merge-base`; clear so external\n\t\t\t\t// gkConfig mutations don't leave stale base-branch resolutions cached.\n\t\t\t\tkeysToClear.add('baseBranchName');\n\t\t\t\t// Cached overviews are keyed by `${ref}|${mergeTarget}`; bulk gkConfig changes can\n\t\t\t\t// affect any of the merge-target sources (stored, base, default), so clear all.\n\t\t\t\tkeysToClear.add('branchOverviews');\n\t\t\t}\n\n\t\t\tif (types.includes('lastFetched')) {\n\t\t\t\tkeysToClear.add('lastFetched');\n\t\t\t}\n\n\t\t\tif (types.includes('providers')) {\n\t\t\t\tkeysToClear.add('remotes');\n\t\t\t\tkeysToClear.add('bestRemotes');\n\t\t\t\tinvalidateMemoized('providers');\n\t\t\t}\n\n\t\t\tif (types.includes('remotes')) {\n\t\t\t\tkeysToClear.add('remotes');\n\t\t\t\tkeysToClear.add('bestRemotes');\n\t\t\t\tkeysToClear.add('defaultBranchName');\n\t\t\t}\n\n\t\t\tif (types.includes('stashes')) {\n\t\t\t\tkeysToClear.add('stashes');\n\t\t\t}\n\t\t\tif (types.includes('status')) {\n\t\t\t\tkeysToClear.add('pausedOperationStatus');\n\t\t\t\t// A caller asserting \"status changed\" (the post-op hooks in `operations.ts`, a user-initiated\n\t\t\t\t// refresh) has to advance the clock too — otherwise a `git status` still in flight from before\n\t\t\t\t// the operation can satisfy the read that follows it.\n\t\t\t\tthis.incrementStatusGenerations(repoPath);\n\t\t\t}\n\t\t\tif (types.includes('tags')) {\n\t\t\t\tkeysToClear.add('tags');\n\t\t\t\tkeysToClear.add('refs');\n\t\t\t\tkeysToClear.add('refTips');\n\t\t\t\t// `commit`/`commitCount` can be keyed by a tag name (e.g. the tag node's load-more count),\n\t\t\t\t// which re-points on a force-moved or deleted-and-recreated tag — same drift the\n\t\t\t\t// `branch`/`branches` cascade above clears for.\n\t\t\t\tkeysToClear.add('commit');\n\t\t\t\tkeysToClear.add('commitCount');\n\t\t\t\t// Same drift for a tag-named rev, and a `getLogShas` excluding tags lists different commits once a tag moves\n\t\t\t\tkeysToClear.add('logShas');\n\t\t\t\t// Keyed by the revision as given, so a tag name resolves to wherever the tag pointed when first read\n\t\t\t\tkeysToClear.add('resolvedRevisions');\n\t\t\t\t// Keyed by ref names too, so a count or fork point taken against a tag-named base would outlive its move\n\t\t\t\tkeysToClear.add('leftRightCommitCount');\n\t\t\t\tkeysToClear.add('mergeBase');\n\t\t\t}\n\n\t\t\tif (types.includes('tracking')) {\n\t\t\t\tkeysToClear.add('fileExistence');\n\t\t\t\tkeysToClear.add('trackedPaths');\n\t\t\t}\n\n\t\t\tif (types.includes('worktrees') || types.includes('worktreeList')) {\n\t\t\t\tkeysToClear.add('worktrees');\n\t\t\t}\n\n\t\t\t// Git results: cleared for any meaningful type change\n\t\t\tif (types.some(t => t !== 'gitignore' && t !== 'gkConfig' && t !== 'providers' && t !== 'worktreeList')) {\n\t\t\t\tkeysToClear.add('gitResults');\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of keysToClear) {\n\t\t\tconst cache = this._caches[key];\n\t\t\tif (cache == null) continue;\n\n\t\t\tif (repoPath == null) {\n\t\t\t\tcache.clear();\n\t\t\t} else if (key === 'aheadOfBaseConfigKey' && !worktreeOnly && (!types.length || types.includes('config'))) {\n\t\t\t\t// Config reports don't distinguish a common config write from a checkout-specific one.\n\t\t\t\tthis.evictShared(key, repoPath, 'evict');\n\t\t\t} else if (sharedCacheKeys.has(key)) {\n\t\t\t\tif (!worktreeOnly) {\n\t\t\t\t\t// A fresh config fingerprint must never be paired with a pre-change base command, nor taken from a\n\t\t\t\t\t// listing read before the change\n\t\t\t\t\tconst hardEvict =\n\t\t\t\t\t\tkey === 'aheadOfBaseConfigListing' ||\n\t\t\t\t\t\t(key === 'gitResults' && (types.includes('config') || types.includes('branch')));\n\t\t\t\t\tthis.evictShared(key, repoPath, hardEvict ? 'evict' : inFlight);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcache.delete(repoPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Evicts a single shared (commonPath-keyed) cache entry for `repoPath` and its sibling worktrees.\n\t * When `inFlight` is `'share'` (the default), prefers `invalidate` where supported so in-flight work\n\t * is shared across new callers and self-evicts on settle rather than spawning a duplicate factory.\n\t * `invalidate` does the right thing per-entry: entries with a `CacheController` (created via\n\t * `getOrCreate`) are marked invalidated; entries without one (created via plain `.set()`, e.g.\n\t * per-worktree mapper results) are hard-deleted. Caches that don't support `invalidate` fall back to\n\t * `delete`.\n\t *\n\t * When `inFlight` is `'evict'`, always hard-deletes regardless of `invalidate` support — a new caller\n\t * must never join a read that started before this eviction (see {@link evictCaches}).\n\t */\n\tprivate evictShared(key: keyof AllCaches, repoPath: string, inFlight: 'share' | 'evict' = 'share'): void {\n\t\tconst cache = this._caches[key];\n\t\tif (cache == null) return;\n\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst invalidate =\n\t\t\tinFlight === 'share' ? (cache as { invalidate?: (k: string) => void }).invalidate : undefined;\n\t\tif (typeof invalidate === 'function') {\n\t\t\tinvalidate.call(cache, commonPath);\n\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\tinvalidate.call(cache, worktreePath);\n\t\t\t}\n\t\t} else {\n\t\t\tcache.delete(commonPath);\n\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\tcache.delete(worktreePath);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Monotonic per-worktree counter, advanced whenever anything that can change `git status` output is\n\t * observed. `git status` and its siblings are point-in-time reads of mutable state, so deduplicating them\n\t * on repoPath alone is unsound — a run that started before a commit would satisfy a caller that arrived\n\t * after it. Callers stamp their in-flight run with the generation it started in and refuse older joins.\n\t * Kept per exact worktree path (never spread to the common path) and advanced on `unregisterRepoPath` so a\n\t * read in flight from a prior registration can't be joined after a reopen.\n\t *\n\t * Note: a run that never settles wedges only its own generation's callers (a newer generation gets a fresh\n\t * key). `git.run` recovers via its per-command timeout (default 60s); a hung `git.stream` is caught by the\n\t * status provider's `raceWithTimeout` backstop (scaled to `advanced.git.timeout`; see\n\t * `dedupeByStatusGeneration`), which rejects a wedged read so waiters unblock and a later caller retries.\n\t */\n\tgetStatusGeneration(repoPath: string): number {\n\t\treturn this._statusGenerations.get(repoPath) ?? 0;\n\t}\n\n\t/** Advances the status clock — see {@link getStatusGeneration}. */\n\tincrementStatusGeneration(repoPath: string): void {\n\t\tthis._statusGenerations.set(repoPath, this.getStatusGeneration(repoPath) + 1);\n\t}\n\n\t/**\n\t * Working-tree changes ride their own channel (`Repository.onDidChangeWorkingTree`), not\n\t * `onRepositoryChanged` — an external `git restore <file>` may touch no `.git` path we classify — so\n\t * they have to advance the status clock separately or a discard would never invalidate an in-flight read.\n\t */\n\tonWorkingTreeChanged(repoPath: string): void {\n\t\tthis.incrementStatusGeneration(repoPath);\n\t}\n\n\t/** Advances the status clock for one worktree, or for every known worktree when `repoPath` is undefined. */\n\tprivate incrementStatusGenerations(repoPath: string | undefined): void {\n\t\tif (repoPath != null) {\n\t\t\tthis.incrementStatusGeneration(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\t// Union of registered repos and any path that already carries a generation — a secondary-worktree\n\t\t// path incremented via its own watcher may never have been registered, but still has in-flight reads to fence.\n\t\tconst paths = new Set([...this._commonPathRegistry.keys(), ...this._statusGenerations.keys()]);\n\t\tfor (const path of paths) {\n\t\t\tthis.incrementStatusGeneration(path);\n\t\t}\n\t}\n\n\tgetCommonPath(repoPath: string): string {\n\t\treturn this._commonPathRegistry.get(repoPath) ?? repoPath;\n\t}\n\n\tgetWorktreePaths(commonPath: string): string[] {\n\t\tconst worktrees = this._worktreesByCommonPath.get(commonPath);\n\t\treturn worktrees != null ? [...worktrees] : [];\n\t}\n\n\tisWorktree(repoPath: string): boolean {\n\t\tconst commonPath = this._commonPathRegistry.get(repoPath);\n\t\treturn commonPath != null && commonPath !== repoPath;\n\t}\n\n\t/** Whether `repoPath` is currently registered (via {@link registerRepoPath}, not yet unregistered). */\n\tisRegistered(repoPath: string): boolean {\n\t\treturn this._commonPathRegistry.has(repoPath);\n\t}\n\n\t/**\n\t * Monotonic per-path counter advanced whenever `repoPath` is unregistered (repo closed, worktree\n\t * removed). Lets an async post-read step — e.g. the gk-config reconcile — detect that its target was\n\t * closed (and possibly reopened) mid-flight and bail. Unlike an `isRegistered` check it doesn't\n\t * require the caller to have registered in the first place, so it stays correct for consumers of\n\t * this package that don't wire up the host's repo lifecycle.\n\t */\n\tgetCloseGeneration(repoPath: string): number {\n\t\treturn this._closeGenerations.get(repoPath) ?? 0;\n\t}\n\n\t/** Clears file-scoped caches (blame, diff, fileLog) for a specific path within a repo */\n\tclearForPath(repoPath: string, path: string, ...types: UriScopedCachedGitTypes[]): void {\n\t\tconst prefix = `${normalizePath(path)}:`;\n\t\tif (!types.length || types.includes('blame')) {\n\t\t\tthis._caches.blame?.deleteByKeyPrefix(repoPath, prefix);\n\t\t}\n\t\tif (!types.length || types.includes('diff')) {\n\t\t\tthis._caches.diff?.deleteByKeyPrefix(repoPath, prefix);\n\t\t}\n\t\tif (!types.length || types.includes('fileLog')) {\n\t\t\tthis._caches.fileLog?.deleteByKeyPrefix(repoPath, prefix);\n\t\t}\n\t}\n\n\tregisterRepoPath(repoPath: Uri, gitDir: GitDir): void {\n\t\tconst normalizedPath = getRepositoryOrWorktreePath(repoPath);\n\t\tconst commonPath = gitDir.commonUri != null ? getCommonRepositoryPath(gitDir.commonUri) : normalizedPath;\n\t\tconst previousCommonPath = this._commonPathRegistry.get(normalizedPath);\n\t\tif (previousCommonPath != null && previousCommonPath !== commonPath) {\n\t\t\tthis.unregisterRepoPath(normalizedPath);\n\t\t}\n\t\tif (previousCommonPath !== commonPath) {\n\t\t\tthis._caches.aheadOfBaseConfigKey?.delete(normalizedPath);\n\t\t\tif (normalizedPath === commonPath) {\n\t\t\t\tthis._caches.aheadOfBaseConfigListing?.delete(commonPath);\n\t\t\t}\n\t\t\tthis._caches.gitResults?.delete(normalizedPath);\n\t\t}\n\t\tthis._commonPathRegistry.set(normalizedPath, commonPath);\n\n\t\tlet worktrees = this._worktreesByCommonPath.get(commonPath);\n\t\tif (worktrees == null) {\n\t\t\tworktrees = new Set();\n\t\t\tthis._worktreesByCommonPath.set(commonPath, worktrees);\n\t\t}\n\t\tworktrees.add(normalizedPath);\n\t}\n\n\t/**\n\t * Symmetric companion to `registerRepoPath`. Clears cache entries specific to `repoPath`\n\t * and removes the path from the registry.\n\t *\n\t * Call this when a worktree is deleted or a repo is closed so stale registry entries\n\t * and derived cache entries don't persist.\n\t *\n\t * Targeted — does NOT cascade to sibling worktrees sharing the same commonPath. Shared caches\n\t * stay warm until the last worktree closes, except raw git results co-located with a closing main\n\t * checkout: those must retire with its config fingerprint so reopening cannot attest an old command\n\t * with new config. Detached promises keep their existing callers and abort wiring. Other entries\n\t * use soft-invalidate where supported so any in-flight factory/mapper keeps its abort\n\t * wiring intact — a caller whose signal aborts after unregister can still propagate\n\t * cancellation into the underlying work rather than leaving it orphaned. Controller-backed\n\t * entries self-evict on settle; plain `.set()`-based entries hard-delete immediately.\n\t *\n\t * The status clock advances even for an unregistered path so a fresh registration cannot join a\n\t * status read that started before it.\n\t */\n\t@debug({ onlyExit: true })\n\tunregisterRepoPath(repoPath: string): void {\n\t\t// Advance the status clock on close so a status read still in flight from this registration can't be\n\t\t// joined by a read issued after the path is reopened (which would otherwise reuse the same generation).\n\t\tthis.incrementStatusGeneration(repoPath);\n\t\t// Advance the close clock so an async step that captured it before its read (see `getCloseGeneration`)\n\t\t// can tell its target went away mid-flight.\n\t\tthis._closeGenerations.set(repoPath, this.getCloseGeneration(repoPath) + 1);\n\n\t\tconst commonPath = this._commonPathRegistry.get(repoPath) ?? repoPath;\n\t\tconst worktrees = this._worktreesByCommonPath.get(commonPath);\n\t\t// After removing repoPath, would the commonPath have any worktrees left?\n\t\tconst isLastWorktree = worktrees == null || worktrees.size <= 1;\n\n\t\t// Targeted per-repoPath cleanup: for per-worktree caches, clear this repoPath's\n\t\t// entries. For shared caches, clear this repoPath's mapper entry (if it's a worktree\n\t\t// distinct from commonPath); only evict the shared commonPath entry when this was the\n\t\t// last worktree — otherwise siblings still rely on the shared data.\n\t\tfor (const key of Object.keys(this._caches) as (keyof AllCaches)[]) {\n\t\t\tconst cache = this._caches[key];\n\t\t\tif (cache == null) continue;\n\n\t\t\tif (key === 'aheadOfBaseConfigKey' || key === 'gitResults') {\n\t\t\t\tcache.delete(repoPath);\n\t\t\t\tif (key === 'gitResults' && isLastWorktree && repoPath !== commonPath) {\n\t\t\t\t\tcache.delete(commonPath);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// The main checkout's own listing, so it retires with that checkout as its config key does\n\t\t\tif (key === 'aheadOfBaseConfigListing') {\n\t\t\t\tif (repoPath === commonPath || isLastWorktree) {\n\t\t\t\t\tcache.delete(commonPath);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Prefer `invalidate` so in-flight abort wiring survives until the factory settles;\n\t\t\t// fall back to `delete` for plain `Map`-typed caches that don't track promises.\n\t\t\tconst invalidate = (cache as { invalidate?: (k: string) => void }).invalidate;\n\t\t\tconst evict =\n\t\t\t\ttypeof invalidate === 'function'\n\t\t\t\t\t? (k: string) => invalidate.call(cache, k)\n\t\t\t\t\t: (k: string) => cache.delete(k);\n\n\t\t\tif (sharedCacheKeys.has(key)) {\n\t\t\t\tif (repoPath !== commonPath) {\n\t\t\t\t\tevict(repoPath);\n\t\t\t\t}\n\t\t\t\tif (isLastWorktree) {\n\t\t\t\t\tevict(commonPath);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tevict(repoPath);\n\t\t\t}\n\t\t}\n\n\t\t// Shared, commonPath-keyed like `gkConfigMap` — only evict once no worktree still depends on it.\n\t\tif (isLastWorktree) {\n\t\t\tthis._gkConfigSnapshots.delete(commonPath);\n\t\t\tthis._mergeTargetsEvictedOnCheckout.delete(commonPath);\n\t\t}\n\n\t\tthis._commonPathRegistry.delete(repoPath);\n\n\t\tif (worktrees != null) {\n\t\t\tworktrees.delete(repoPath);\n\t\t\tif (worktrees.size === 0) {\n\t\t\t\tthis._worktreesByCommonPath.delete(commonPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug({ onlyExit: true })\n\treset(): void {\n\t\t// Advance the close clock BEFORE dropping the registry it reads from. Advancing rather than\n\t\t// clearing is the point: an async step that captured a generation must see a mismatch and bail,\n\t\t// where a cleared map would hand it a fresh `0` that matches and let it repopulate what was just\n\t\t// torn down. Union of registered paths and any already carrying a generation, mirroring\n\t\t// `incrementStatusGenerations`.\n\t\tfor (const path of new Set([...this._commonPathRegistry.keys(), ...this._closeGenerations.keys()])) {\n\t\t\tthis._closeGenerations.set(path, this.getCloseGeneration(path) + 1);\n\t\t}\n\n\t\tthis._commonPathRegistry.clear();\n\t\tthis._worktreesByCommonPath.clear();\n\t\tthis._statusGenerations.clear();\n\t\tthis._gkConfigSnapshots.clear();\n\t\tthis._mergeTargetsEvictedOnCheckout.clear();\n\t\tthis._gkConfigReconciler = undefined;\n\t\tthis._caches = createEmptyCaches();\n\t}\n\n\t/** Applies a watcher-observed change, sharing reads still in flight (see {@link applyRepositoryChanges}). */\n\t@debug({ onlyExit: true })\n\tonRepositoryChanged(repoPath: string, changes: Iterable<RepositoryChange>): void {\n\t\tconst changesSet = new Set(changes);\n\t\tif (changesSet.has('unknown') || changesSet.has('closed')) {\n\t\t\tthis.unregisterRepoPath(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.applyRepositoryChanges(repoPath, changesSet, 'share');\n\t}\n\n\t/**\n\t * Clears what `changes` can have made stale for `repoPath`, advances its status clock, and reconciles a\n\t * `'gkConfig'` change, returning the cache types it cleared. `inFlight` is as {@link clearCaches}\n\t * (`'share'`) vs {@link evictCaches} (`'evict'`). `'unknown'` and `'closed'` map to nothing here: the\n\t * watcher unregisters the path on them, and an announced write resets everything instead.\n\t *\n\t * `options.worktreeOnly` clears only `repoPath`'s own entries and status clock, leaving the shared\n\t * (commonPath-keyed) ones alone — for a sibling worktree once the change was applied to the worktree it ran in,\n\t * which already cleared them for every worktree of the repository.\n\t */\n\t@debug({ onlyExit: true })\n\tapplyRepositoryChanges(\n\t\trepoPath: string,\n\t\tchanges: Iterable<RepositoryChange>,\n\t\tinFlight: 'share' | 'evict',\n\t\toptions?: { worktreeOnly?: boolean },\n\t): CachedGitTypes[] {\n\t\tconst worktreeOnly = options?.worktreeOnly ?? false;\n\t\tconst changesSet = new Set(changes);\n\n\t\tconst hasAny = (...c: RepositoryChange[]) => c.some(ch => changesSet.has(ch));\n\n\t\t// Advance the status clock (see {@link getStatusGeneration}) for changes that alter `git status` output but\n\t\t// aren't mapped to the `'status'` cache type below: files (index/head/heads), untracked set (ignores/config),\n\t\t// ahead/behind (remotes). Paused-op changes advance it too, but via `clearCaches('status')` (see below) —\n\t\t// listing them here as well would double-increment the clock for a single change.\n\t\tif (hasAny('index', 'head', 'heads', 'remotes', 'ignores', 'config')) {\n\t\t\tthis.incrementStatusGeneration(repoPath);\n\t\t}\n\n\t\tconst types = new Set<CachedGitTypes>();\n\n\t\tif (hasAny('head')) {\n\t\t\ttypes.add('branch');\n\t\t}\n\n\t\t// A detached HEAD that moved (a commit or reset without a branch) comes as `head` without `heads`, and changes\n\t\t// what this tree compares against and the HEAD the branch and worktree lists show\n\t\tif (hasAny('index', 'head', 'heads', 'pausedOp')) {\n\t\t\ttypes.add('blame');\n\t\t\ttypes.add('diff');\n\t\t\ttypes.add('fileLog');\n\t\t}\n\n\t\tif (hasAny('index')) {\n\t\t\ttypes.add('tracking');\n\t\t}\n\n\t\tif (hasAny('config')) {\n\t\t\ttypes.add('config');\n\t\t\t// A branch's upstream lives in its `.git/config` section, and the branch list (and each worktree's branch)\n\t\t\t// carries it; a config change confined to branches' sections comes without the `remotes` that clears them\n\t\t\ttypes.add('branches');\n\t\t\ttypes.add('worktrees');\n\t\t}\n\n\t\tif (hasAny('head', 'heads')) {\n\t\t\ttypes.add('branches');\n\t\t\ttypes.add('contributors');\n\t\t\ttypes.add('worktrees');\n\t\t}\n\n\t\tif (hasAny('remotes')) {\n\t\t\ttypes.add('branches');\n\t\t\ttypes.add('contributors');\n\t\t\ttypes.add('remotes');\n\t\t\ttypes.add('worktrees');\n\t\t}\n\n\t\tif (hasAny('ignores')) {\n\t\t\ttypes.add('gitignore');\n\t\t}\n\n\t\tif (hasAny('gkConfig') && !worktreeOnly) {\n\t\t\t// Handled separately (not folded into `types`/`clearCaches` below) — a gk write is usually a\n\t\t\t// bookkeeping timestamp that can't affect `baseBranchName`/`branchOverviews`, so this reconciles\n\t\t\t// down to only the keys that actually changed instead of coarsely clearing both on every write.\n\t\t\tthis.handleGkConfigChanged(repoPath);\n\t\t}\n\n\t\tif (hasAny('lastFetched')) {\n\t\t\ttypes.add('lastFetched');\n\t\t}\n\n\t\tif (hasAny('remoteProviders')) {\n\t\t\ttypes.add('providers');\n\t\t}\n\n\t\tif (hasAny('cherryPick', 'merge', 'rebase', 'revert', 'pausedOp')) {\n\t\t\ttypes.add('branch');\n\t\t\ttypes.add('status');\n\t\t}\n\n\t\tif (hasAny('stash')) {\n\t\t\ttypes.add('stashes');\n\t\t}\n\n\t\tif (hasAny('tags')) {\n\t\t\ttypes.add('tags');\n\t\t}\n\n\t\t// A worktree's HEAD moving changes what git answers there, which any worktree's reads can ask about; an entry\n\t\t// added, removed, locked, unlocked or moved changes only the list\n\t\tif (hasAny('worktreeHead')) {\n\t\t\ttypes.add('worktrees');\n\t\t} else if (hasAny('worktrees')) {\n\t\t\ttypes.add('worktreeList');\n\t\t}\n\n\t\tif (types.size) {\n\t\t\tthis.clearCachesCore(inFlight, repoPath, [...types], worktreeOnly);\n\t\t}\n\t\treturn [...types];\n\t}\n\n\t/**\n\t * Handles a watcher-observed `'gkConfig'` change. If a reconciler is registered (see {@link setGkConfigReconciler}),\n\t * defers to it instead of coarsely clearing `baseBranchName`/`branchOverviews` — it evicts the cached bulk map\n\t * unless the file is unchanged since the map was read, reads it, and diffs it against the snapshot captured here\n\t * (i.e. as it stood right before this change), cascading only the refs whose merge-relevant keys actually\n\t * changed. Falls back to evicting the map and the coarse clear when no reconciler is registered (e.g. the GitHub\n\t * provider) so nothing can go stale.\n\t */\n\tprivate handleGkConfigChanged(repoPath: string): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\tif (this._gkConfigReconciler == null) {\n\t\t\t// Hard-delete rather than `evictShared`'s soft-invalidate: a soft-invalidated entry stays joinable, so a\n\t\t\t// read after this change could ride a bulk read that started before it.\n\t\t\t// Same reasoning as `refs.ts`'s `force: true` path and `deleteGkConfig`'s own hard delete.\n\t\t\tthis._caches.gkConfigMap?.delete(commonPath);\n\t\t\tthis.clearGkConfigCoarsely(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tconst priorSnapshot = this._gkConfigSnapshots.get(commonPath);\n\t\t// Fire-and-forget, but the outcome still decides whether the coarse clear is owed: a reconcile that\n\t\t// FAILED leaves every derived cache holding pre-change values with nothing else to correct them, so\n\t\t// it falls back to the blunt behavior that registering a reconciler replaced. Kept here rather than\n\t\t// in the reconciler so a bail path added later can't silently skip it — the return type makes each\n\t\t// one say what it did.\n\t\tlet outcome: PromiseOrValue<GkReconcileOutcome>;\n\t\ttry {\n\t\t\toutcome = this._gkConfigReconciler(repoPath, priorSnapshot);\n\t\t} catch {\n\t\t\t// Thrown before it could decide about the map, which it owns from the call on (see\n\t\t\t// `setGkConfigReconciler`), so drop it as the coarse path does\n\t\t\tthis._caches.gkConfigMap?.delete(commonPath);\n\t\t\tthis.clearGkConfigCoarsely(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tvoid Promise.resolve(outcome).then(\n\t\t\toutcome => {\n\t\t\t\tif (outcome === 'failed') {\n\t\t\t\t\tthis.clearGkConfigCoarsely(repoPath);\n\t\t\t\t}\n\t\t\t},\n\t\t\t// An exception escaping the reconciler is a failure by definition — and one its own `catch`\n\t\t\t// never saw, so nothing else will have cascaded.\n\t\t\t() => this.clearGkConfigCoarsely(repoPath),\n\t\t);\n\t}\n\n\t/**\n\t * The coarse fallback: every derived merge cache and the branches are cleared, so any branch's merge targets or\n\t * metadata may have changed. Evicting the branches even when only merge keys changed is the price of not knowing.\n\t */\n\tprivate clearGkConfigCoarsely(repoPath: string): void {\n\t\tthis.clearCaches(repoPath, 'gkConfig');\n\t\tthis.deleteBranchMetadata(repoPath);\n\t\tthis._onDidChangeMergeTargets.fire({ repoPath: this.getCommonPath(repoPath), refs: undefined });\n\t}\n\n\t/** Hard-evicts the cached bulk `.git/gk/config` map so the next read hits disk. */\n\tdeleteGkConfigMap(repoPath: string): void {\n\t\tthis._caches.gkConfigMap?.delete(this.getCommonPath(repoPath));\n\t}\n\n\t/**\n\t * Whether a write of `key` must first read the gk config to seed the reconcile snapshot: without one,\n\t * {@link recordGkConfigWrite} can't tell whether the write changed anything, and the watcher's reconcile of it\n\t * would report every branch as changed.\n\t */\n\tneedsGkConfigSnapshot(repoPath: string, key: string): boolean {\n\t\treturn getReconciledGkConfigRef(key) != null && !this._gkConfigSnapshots.has(this.getCommonPath(repoPath));\n\t}\n\n\t/** The gk config snapshot currently serving as the reconcile baseline. */\n\tgetGkConfigSnapshot(repoPath: string): ReadonlyMap<string, string> | undefined {\n\t\treturn this._gkConfigSnapshots.get(this.getCommonPath(repoPath));\n\t}\n\n\tgetBranches(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<PagedResult<GitBranch>>,\n\t\tmapper: (\n\t\t\tbranches: PagedResult<GitBranch>,\n\t\t\ttargetRepoPath: string,\n\t\t\tcommonPath: string,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<PagedResult<GitBranch>>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<PagedResult<GitBranch>> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\t// Register this caller with the shared factory's aggregate so that invariant 3\n\t\t// (factory aborts iff every waiter has aborted) holds for same-`repoPath` cache hits too.\n\t\t// The returned wrapped promise is deliberately discarded — we use the raw cached inner\n\t\t// below to build the mapped entry. Swallow any rejection on this dangling reference so\n\t\t// it doesn't surface as an unhandled rejection; the real caller-facing promise (via\n\t\t// `branches.getOrCreate` below) is where caller cancellation flows to.\n\t\tconst registration = this.sharedBranches.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => {\n\t\t\t\tconst p = Promise.resolve(factory(commonPath, cacheable, signal));\n\t\t\t\t// On factory invalidation, propagate to the derived per-worktree mapper entries\n\t\t\t\t// via soft-invalidate — existing waiters on the mapper complete, and the entry\n\t\t\t\t// self-evicts on mapper settle so the next callers build fresh derived entries.\n\t\t\t\tvoid p\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tif (cacheable.invalidated) {\n\t\t\t\t\t\t\tthis.branches.invalidate(commonPath);\n\t\t\t\t\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\t\t\t\t\tthis.branches.invalidate(worktreePath);\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\t// Swallow the cleanup chain's rejection so a rejected factory (e.g. cancellation)\n\t\t\t\t\t// doesn't surface as an unhandled rejection; the caller-facing promise handles it.\n\t\t\t\t\t.catch(() => {});\n\t\t\t\treturn p;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\tvoid registration.catch(() => {});\n\n\t\t// Build the per-`repoPath` mapped entry through `getOrCreate` so mapper internal git\n\t\t// work (e.g. `getCurrentBranchReferenceCore`) runs under a mapper-level aggregate signal\n\t\t// separate from the factory's. Subsequent same-`repoPath` cache hits register with this\n\t\t// aggregate too — invariant 2/3 hold at the mapper level.\n\t\treturn this.branches.getOrCreate(\n\t\t\trepoPath,\n\t\t\t(_cacheable, mapperSignal) => {\n\t\t\t\t// After `getOrCreate` above, `sharedBranches[commonPath]` holds the raw inner\n\t\t\t\t// factory promise. Fall back to `registration` in the paranoid case where a\n\t\t\t\t// synchronously-rejected factory got auto-evicted before we retrieve it.\n\t\t\t\tconst rawShared = this.sharedBranches.get(commonPath) ?? registration;\n\t\t\t\treturn Promise.resolve(rawShared).then(shared => mapper(shared, repoPath, commonPath, mapperSignal));\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate static readonly globalConfigKey = '';\n\n\t/**\n\t * Keyed by `repoPath` itself, not its common path: git reads a worktree's own `config.worktree` too, so worktrees\n\t * of one repository can see different values. A read that is the same for all of them runs from, and passes, the\n\t * common path. The same holds for {@link getConfigRegex}.\n\t */\n\tgetConfig(\n\t\trepoPath: string | undefined,\n\t\tkey: string,\n\t\tfactory: () => PromiseOrValue<string | undefined>,\n\t): Promise<string | undefined> {\n\t\tconst cacheKey = repoPath ?? Cache.globalConfigKey;\n\n\t\tconst result = this.configKeys.get(cacheKey, key);\n\t\tif (result != null) return result;\n\n\t\tconst factoryPromise = Promise.resolve(factory());\n\t\tthis.configKeys.set(cacheKey, key, factoryPromise);\n\t\treturn factoryPromise;\n\t}\n\n\t/** Keyed by `repoPath` itself, as {@link getConfig} is */\n\tgetConfigRegex(\n\t\trepoPath: string | undefined,\n\t\tpattern: string,\n\t\tfactory: () => PromiseOrValue<Map<string, string>>,\n\t): Promise<Map<string, string>> {\n\t\tconst cacheKey = repoPath ?? Cache.globalConfigKey;\n\n\t\tconst result = this.configPatterns.get(cacheKey, pattern);\n\t\tif (result != null) return result;\n\n\t\tconst factoryPromise = Promise.resolve(factory());\n\t\tthis.configPatterns.set(cacheKey, pattern, factoryPromise);\n\t\treturn factoryPromise;\n\t}\n\n\tdeleteConfig(repoPath: string | undefined, key: string): void {\n\t\tif (repoPath == null) {\n\t\t\tthis._caches.configKeys?.delete(Cache.globalConfigKey, key);\n\t\t\tthis._caches.configPatterns?.delete(Cache.globalConfigKey);\n\t\t\treturn;\n\t\t}\n\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tfor (const path of new Set([commonPath, repoPath, ...this.getWorktreePaths(commonPath)])) {\n\t\t\tthis._caches.configKeys?.delete(path, key);\n\t\t\tthis._caches.configPatterns?.delete(path);\n\t\t}\n\t}\n\n\t/**\n\t * The whole `.git/gk/config` is read once and cached as a single map per commonPath; per-key and\n\t * per-namespace gk lookups are served from it in-memory (see `getGkConfigMap` in the CLI config\n\t * sub-provider). Invalidated by `deleteGkConfig` (write) and, on a watcher `'gkConfig'` event, by the\n\t * reconciler when the file changed since the map was read (see {@link setGkConfigReconciler}), or by\n\t * `handleGkConfigChanged`'s coarse clear when none is registered. The first fresh read seeds the snapshot used by\n\t * `reconcileGkConfigMap`; later refreshes of that snapshot are owned by the reconcile itself.\n\t */\n\tgetGkConfigMap(\n\t\trepoPath: string,\n\t\tfactory: (cacheable: CacheController) => PromiseOrValue<Map<string, string>>,\n\t): Promise<Map<string, string>> {\n\t\treturn this.getSharedSimple(this.gkConfigMap, repoPath, async (commonPath, cacheable) => {\n\t\t\tconst map = await factory(cacheable);\n\t\t\t// Seed the reconcile baseline on first observation only. Refreshes belong to\n\t\t\t// `reconcileGkConfigMap` (after it has cascaded) and `recordGkConfigWrite` (our own writes):\n\t\t\t// an incidental read that happens to land between an external write and the watcher event\n\t\t\t// would otherwise advance the baseline to the post-change value, so the reconcile would diff\n\t\t\t// that value against itself and silently drop the change.\n\t\t\tif (!this._gkConfigSnapshots.has(commonPath)) {\n\t\t\t\tthis._gkConfigSnapshots.set(commonPath, this.extractReconciledGkConfig(map));\n\t\t\t}\n\t\t\treturn map;\n\t\t});\n\t}\n\n\t/** Extracts the subset of a gk config map that the reconcile baseline tracks (see {@link _gkConfigSnapshots}). */\n\tprivate extractReconciledGkConfig(map: ReadonlyMap<string, string>): Map<string, string> {\n\t\tconst subset = new Map<string, string>();\n\t\tfor (const [key, value] of map) {\n\t\t\tif (getReconciledGkConfigRef(key) != null) {\n\t\t\t\tsubset.set(key, value);\n\t\t\t}\n\t\t}\n\t\treturn subset;\n\t}\n\n\t/**\n\t * Clears the cached `.git/gk/config` map and invalidates the derived caches\n\t * (`baseBranchName`/`branchOverviews`) for the written key's ref.\n\t *\n\t * @param options.skipInvalidation Downstream caches the caller wants preserved despite this\n\t * write. Use when the value being written is exactly what was just resolved — e.g. the pull request's\n\t * `storeMergeTargetBranchName` self-write inside `getMergeTarget` (skip `'branchOverviews'`) or the\n\t * `vscode-merge-base` migration's `storeBaseBranchName` self-write (skip both `'baseBranchName'` and\n\t * `'branchOverviews'`). The bulk `gkConfigMap` map always\n\t * invalidates so subsequent reads see the new value.\n\t */\n\tdeleteGkConfig(\n\t\trepoPath: string,\n\t\tkey: string,\n\t\toptions?: { skipInvalidation?: readonly GkConfigInvalidationTarget[] },\n\t): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tthis._caches.gkConfigMap?.delete(commonPath);\n\t\tthis.cascadeGkConfigKeyChange(commonPath, key, options?.skipInvalidation);\n\t}\n\n\t/**\n\t * Keeps the gk config snapshot in sync with OUR OWN writes, so the next watcher-triggered\n\t * `reconcileGkConfigMap` diffs a self-write as unchanged rather than as an external change (which would\n\t * otherwise defeat `skipInvalidation`, or evict the branches a second time after a branch-activity stamp),\n\t * and fires {@link onDidChangeMergeTargets} naming the key's branch when a merge-relevant value differs from\n\t * the snapshot's, unless `announce` is `false` (an internal save while answering a read, which nobody awaits;\n\t * only another process's watcher reports it). No-ops for keys the snapshot doesn't track, and if no snapshot exists yet for this repo\n\t * (the writer seeds one first; see {@link needsGkConfigSnapshot}).\n\t */\n\trecordGkConfigWrite(\n\t\trepoPath: string,\n\t\tkey: string,\n\t\tvalue: string | undefined,\n\t\toptions?: { announce?: boolean },\n\t): void {\n\t\tconst ref = getReconciledGkConfigRef(key);\n\t\tif (ref == null) return;\n\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst snapshot = this._gkConfigSnapshots.get(commonPath);\n\t\tif (snapshot == null || snapshot.get(key) === value) return;\n\n\t\t// Copy-on-write: a reconcile in flight is holding this map as its `priorSnapshot` baseline, so\n\t\t// mutating it in place would silently move that baseline mid-diff.\n\t\tconst next = new Map(snapshot);\n\t\tif (value == null) {\n\t\t\tnext.delete(key);\n\t\t} else {\n\t\t\tnext.set(key, value);\n\t\t}\n\t\tthis._gkConfigSnapshots.set(commonPath, next);\n\n\t\tif (options?.announce === false || !branchOverviewGkConfigKeysRegex.test(key)) return;\n\n\t\tthis._onDidChangeMergeTargets.fire({ repoPath: commonPath, refs: new Set([ref]) });\n\t}\n\n\t/**\n\t * {@link recordGkConfigWrite} for a whole `branch.<ref>` section: our own `--remove-section` (a branch delete) or\n\t * `--rename-section` (a branch rename, to `renamedTo`), so the reconcile that follows doesn't report it as an\n\t * external merge-target or metadata change — the branch op's own ref change already evicts the branches.\n\t */\n\trecordGkConfigSectionWrite(repoPath: string, ref: string, renamedTo?: string): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst snapshot = this._gkConfigSnapshots.get(commonPath);\n\t\tif (snapshot == null) return;\n\n\t\tconst prefixLength = `branch.${ref}.`.length;\n\t\t// Copy-on-write, as in `recordGkConfigWrite`\n\t\tconst next = new Map<string, string>();\n\t\tfor (const [key, value] of snapshot) {\n\t\t\t// Matched on the captured ref, not a `branch.<ref>.` prefix, which would also take a dotted sibling\n\t\t\t// (`branch.feature.x.*` for `feature`) that `--remove-section`/`--rename-section` leaves in place\n\t\t\tif (getReconciledGkConfigRef(key) !== ref) {\n\t\t\t\tnext.set(key, value);\n\t\t\t} else if (renamedTo != null) {\n\t\t\t\tnext.set(`branch.${renamedTo}.${key.substring(prefixLength)}`, value);\n\t\t\t}\n\t\t}\n\t\tthis._gkConfigSnapshots.set(commonPath, next);\n\t}\n\n\t/**\n\t * Registers the reconciler invoked by {@link handleGkConfigChanged} on a watcher-observed\n\t * `'gkConfig'` change. Only one reconciler is kept — later registrations replace earlier ones,\n\t * which is harmless since every CLI config sub-provider sharing this `Cache` reconciles the same\n\t * underlying `.git/gk/config` file identically.\n\t *\n\t * The reconciler owns the cached bulk map: it is called synchronously as the change is reported, and must\n\t * hard-delete the map ({@link deleteGkConfigMap}) before it returns unless it knows the map still reflects the\n\t * file — a read after the change must see it, and the reconcile's own read must not ride a bulk read that\n\t * started before it. Only the reconciler can inspect the file, and keeping the map spares a re-read for every\n\t * report of an unchanged file (one per worktree sharing it, and one for each of core's own writes).\n\t */\n\tsetGkConfigReconciler(\n\t\treconciler: (\n\t\t\trepoPath: string,\n\t\t\tpriorSnapshot: ReadonlyMap<string, string> | undefined,\n\t\t) => PromiseOrValue<GkReconcileOutcome>,\n\t): void {\n\t\tthis._gkConfigReconciler = reconciler;\n\t}\n\n\t/**\n\t * Diffs the tracked subset of a gk config map (read after the change, or kept as still reflecting the file)\n\t * against `priorSnapshot` (captured by `handleGkConfigChanged` before the reconcile started, so it reflects the\n\t * pre-change state), cascading\n\t * `baseBranchName`/`branchOverviews` for every ref whose merge-relevant key actually changed, then firing\n\t * {@link onDidChangeMergeTargets} naming those refs. Changed branch metadata keys (another process's\n\t * activity stamps or disposition) are patched into the cached branches in one call, and never fire the event.\n\t * A key core itself wrote since `priorSnapshot` was captured (recorded in the live snapshot) is neither diffed nor\n\t * overwritten by this read, which may predate the write: its writer already cascaded and announced it.\n\t * `priorSnapshot` of `undefined` (never observed before this reconcile) is treated as \"everything\n\t * may have changed\" — a full coarse clear, same as the pre-existing watcher behavior. Returns\n\t * whether anything changed (i.e. whether a follow-up repository-changed event is warranted).\n\t */\n\treconcileGkConfigMap(\n\t\trepoPath: string,\n\t\tpriorSnapshot: ReadonlyMap<string, string> | undefined,\n\t\tfreshMap: ReadonlyMap<string, string>,\n\t): boolean {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst newSubset = this.extractReconciledGkConfig(freshMap);\n\n\t\tif (priorSnapshot == null) {\n\t\t\tthis._gkConfigSnapshots.set(commonPath, newSubset);\n\t\t\tthis.evictShared('baseBranchName', repoPath);\n\t\t\tthis.evictShared('branchOverviews', repoPath);\n\t\t\tthis.deleteBranchMetadata(repoPath);\n\t\t\tthis._onDidChangeMergeTargets.fire({ repoPath: commonPath, refs: undefined });\n\t\t\treturn true;\n\t\t}\n\n\t\t// Only core's own writes move the live snapshot off `priorSnapshot` before this point\n\t\tconst ownWrites = new Set<string>();\n\t\tconst live = this._gkConfigSnapshots.get(commonPath);\n\t\tif (live != null && live !== priorSnapshot) {\n\t\t\tfor (const key of new Set([...priorSnapshot.keys(), ...live.keys()])) {\n\t\t\t\tconst value = live.get(key);\n\t\t\t\tif (priorSnapshot.get(key) === value) continue;\n\n\t\t\t\townWrites.add(key);\n\t\t\t\tif (value == null) {\n\t\t\t\t\tnewSubset.delete(key);\n\t\t\t\t} else {\n\t\t\t\t\tnewSubset.set(key, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._gkConfigSnapshots.set(commonPath, newSubset);\n\n\t\tlet refs: Set<string> | undefined;\n\t\tconst metadataChanges: BranchMetadataChange[] = [];\n\t\tfor (const key of new Set([...priorSnapshot.keys(), ...newSubset.keys()])) {\n\t\t\tif (ownWrites.has(key)) continue;\n\n\t\t\tconst value = newSubset.get(key);\n\t\t\tif (priorSnapshot.get(key) === value) continue;\n\n\t\t\tconst ref = branchOverviewGkConfigKeysRegex.exec(key)?.[1];\n\t\t\tif (ref != null) {\n\t\t\t\tthis.cascadeGkConfigKeyChange(commonPath, key);\n\t\t\t\t(refs ??= new Set()).add(ref);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst metadataKey = parseBranchMetadataGkConfigKey(key);\n\t\t\tif (metadataKey != null) {\n\t\t\t\tmetadataChanges.push({ branch: metadataKey.branch, key: metadataKey.key, value: value });\n\t\t\t}\n\t\t}\n\n\t\tconst metadataChanged = metadataChanges.length > 0;\n\t\tif (metadataChanged) {\n\t\t\tthis.patchBranchMetadata(repoPath, metadataChanges);\n\t\t}\n\n\t\tif (refs == null) return metadataChanged;\n\n\t\tthis._onDidChangeMergeTargets.fire({ repoPath: commonPath, refs: refs });\n\t\treturn true;\n\t}\n\n\t/**\n\t * Shared per-ref cascade for a changed `branch.<ref>.gk-...` key: invalidates `baseBranchName` (for\n\t * `gk-merge-base`) and `branchOverviews` (for any merge-relevant key), honoring `skipInvalidation`.\n\t * Used by both a direct write (`deleteGkConfig`) and a reconciled external change\n\t * (`reconcileGkConfigMap`). No-ops for keys outside the merge-relevant subset.\n\t */\n\tprivate cascadeGkConfigKeyChange(\n\t\tcommonPath: string,\n\t\tkey: string,\n\t\tskip?: readonly GkConfigInvalidationTarget[],\n\t): void {\n\t\tconst refMatch = key.match(branchOverviewGkConfigKeysRegex);\n\t\tif (refMatch == null) return;\n\n\t\tconst ref = refMatch[1];\n\n\t\t// `getBaseBranchName` reads `branch.<ref>.gk-merge-base` and caches the resolved value\n\t\t// per-ref. A change to that key must invalidate the cached base or it keeps answering the pre-change value.\n\t\tif (key.endsWith('.gk-merge-base') && !skip?.includes('baseBranchName')) {\n\t\t\tthis._caches.baseBranchName?.delete(commonPath, ref);\n\t\t}\n\n\t\tif (skip?.includes('branchOverviews')) return;\n\n\t\t// When the change affects a branch's merge-target/base lineage, invalidate that branch's\n\t\t// cached overviews so subsequent reads pick up the new stored value rather than stale data.\n\t\t// `getBranchContributionsOverview` keys `branchOverviews` by `${ref}|${mergeTarget}`, so\n\t\t// invalidate every entry for the affected ref regardless of which target it resolved to.\n\t\t// Uses `invalidateByKeyPrefix` (not `deleteByKeyPrefix`) so an in-flight factory is still\n\t\t// shared with new callers instead of triggering a duplicate fetch.\n\t\t//\n\t\t// Sibling worktrees get their own bucket, not just the shared one: `getSharedOrCreateWithKey`\n\t\t// stores a per-worktree *mapped* entry under that worktree's own path, and prefix-invalidation\n\t\t// only reaches one bucket. The in-flight case self-propagates on settle, but an already-settled\n\t\t// overview would otherwise survive here — which the coarse `evictShared` path this replaced did\n\t\t// clear, since it iterated the worktrees.\n\t\tthis._caches.branchOverviews?.invalidateByKeyPrefix(commonPath, `${ref}|`);\n\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\tthis._caches.branchOverviews?.invalidateByKeyPrefix(worktreePath, `${ref}|`);\n\t\t}\n\t}\n\n\tasync getBranchOverview(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<BranchContributionsOverview | undefined>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<BranchContributionsOverview | undefined> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.branchOverviews,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) =>\n\t\t\t\tdata == null\n\t\t\t\t\t? data\n\t\t\t\t\t: {\n\t\t\t\t\t\t\t...data,\n\t\t\t\t\t\t\trepoPath: newRepoPath,\n\t\t\t\t\t\t\tcontributors: data.contributors.map(c => c.withRepoPath(newRepoPath)),\n\t\t\t\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync getContributors(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitContributorsResult>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitContributorsResult> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.contributors,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => ({\n\t\t\t\t...data,\n\t\t\t\tcontributors: data.contributors.map(c => c.withRepoPath(newRepoPath)),\n\t\t\t}),\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync getContributorsLite(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitContributor[]>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitContributor[]> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.contributorsLite,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => data.map(c => c.withRepoPath(newRepoPath)),\n\t\t\toptions,\n\t\t);\n\t}\n\n\tgetContributorsStats(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitContributorsStats | undefined>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitContributorsStats | undefined> {\n\t\treturn this.getSharedSimpleWithKey(this.contributorsStats, repoPath, cacheKey, factory, options);\n\t}\n\n\tgetBaseBranchName(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimpleWithKey(this.baseBranchName, repoPath, ref, factory, {\n\t\t\t// A bounded ceiling, because the eviction signals can't cover every way a base changes. The\n\t\t\t// `'branches'` cascade deliberately doesn't clear this — a tip move can't change a base, and\n\t\t\t// re-deriving per commit is the cost this exists to avoid — but that leaves a hole: a branch\n\t\t\t// deleted and recreated OUTSIDE GitLens, and never checked out, emits only `heads`. A base\n\t\t\t// derived as \"none\" before that would otherwise stay \"none\" for the session.\n\t\t\t//\n\t\t\t// `createTTL`, NOT `accessTTL`: the sliding variant resets on every read, so a branch card\n\t\t\t// polling this entry would hold it alive forever and never re-derive — the exact case the\n\t\t\t// ceiling exists for. Absolute from creation bounds staleness regardless of read frequency.\n\t\t\tcreateTTL: baseBranchNameTTL,\n\t\t\tcancellation: cancellation,\n\t\t});\n\t}\n\n\t/**\n\t * Clears the cached base branch for `ref`. Call from ops that create/rename/delete a branch — the\n\t * `'branches'` cascade no longer clears these, since tip movement can't change a branch's base.\n\t *\n\t * Only clears the cache. A branch's base is *persisted* as `branch.<ref>.gk-merge-base` and read back\n\t * before the reflog fallback, so an op that ends a branch's identity under a name must drop or move\n\t * that key too (`removeGkConfigBranchSection`/`renameGkConfigBranchSection`) — otherwise the\n\t * re-derivation this triggers just reads the stale value straight back.\n\t */\n\tdeleteBaseBranchName(repoPath: string, ref: string): void {\n\t\tthis._caches.baseBranchName?.delete(this.getCommonPath(repoPath), ref);\n\t}\n\n\t/**\n\t * Applies changed branch metadata keys (written here or reconciled from another process) to the cached branches\n\t * without re-reading them, by updating {@link BranchMetadata} objects in place — the one exception to cached values\n\t * never changing, since rebuilding every branch list, current branch and worktree list on every activity stamp\n\t * costs far more. Patches every object a cached branch of the repository's worktrees holds for a changed branch:\n\t * the cached map's, and any older map's that a cached branch list, current branch or worktree list still holds.\n\t *\n\t * Falls back to {@link deleteBranchMetadata} when one of them is still being read (it may have read the file\n\t * before the change), or the cached map or a cached branch of a changed name has no object to patch.\n\t */\n\tpatchBranchMetadata(repoPath: string, changes: readonly BranchMetadataChange[]): void {\n\t\tconst targets = new Map<string, Set<BranchMetadata>>();\n\t\tfor (const change of changes) {\n\t\t\ttargets.set(change.branch, new Set());\n\t\t}\n\n\t\tif (!this.collectBranchMetadata(this.getCommonPath(repoPath), targets)) {\n\t\t\tthis.deleteBranchMetadata(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const change of changes) {\n\t\t\tfor (const metadata of targets.get(change.branch)!) {\n\t\t\t\tsetBranchMetadataValue(metadata, change.key, change.value);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Adds to `targets` every metadata object a cached holder has for each named branch (see\n\t * {@link patchBranchMetadata}); `false` when the holders must be evicted instead.\n\t */\n\tprivate collectBranchMetadata(commonPath: string, targets: Map<string, Set<BranchMetadata>>): boolean {\n\t\tconst metadataMap = getSettledOrPending(this._caches.branchMetadataMap, commonPath);\n\t\tif (metadataMap === 'pending') return false;\n\n\t\tif (metadataMap != null) {\n\t\t\tfor (const [name, objects] of targets) {\n\t\t\t\tconst metadata = metadataMap.value.get(name);\n\t\t\t\t// The branch's first metadata: the cached branches built from this map hold none\n\t\t\t\tif (metadata == null) return false;\n\n\t\t\t\tobjects.add(metadata);\n\t\t\t}\n\t\t}\n\n\t\tconst add = (branch: GitBranch | undefined): boolean => {\n\t\t\tif (branch == null || branch.remote || branch.detached) return true;\n\n\t\t\tconst objects = targets.get(branch.name);\n\t\t\tif (objects == null) return true;\n\t\t\tif (branch.metadata == null) return false;\n\n\t\t\tobjects.add(branch.metadata);\n\t\t\treturn true;\n\t\t};\n\n\t\tfor (const path of new Set([commonPath, ...this.getWorktreePaths(commonPath)])) {\n\t\t\tfor (const cache of [this._caches.sharedBranches, this._caches.branches]) {\n\t\t\t\tconst branches = getSettledOrPending(cache, path);\n\t\t\t\tif (branches === 'pending' || (branches != null && !branches.value.values.every(add))) return false;\n\t\t\t}\n\n\t\t\tconst current = getSettledOrPending(this._caches.branch, path);\n\t\t\tif (current === 'pending' || (current != null && !add(current.value))) return false;\n\n\t\t\tconst worktrees = getSettledOrPending(this._caches.worktrees, path);\n\t\t\tif (worktrees === 'pending' || (worktrees != null && !worktrees.value.every(w => add(w.branch)))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Drops the cached branches and worktrees for `repoPath` and its sibling worktrees when their metadata changed in\n\t * a way {@link patchBranchMetadata} can't apply in place. Hard-evicts, so a read that started before the change\n\t * isn't joined.\n\t */\n\tdeleteBranchMetadata(repoPath: string): void {\n\t\tfor (const key of ['branchMetadataMap', 'sharedBranches', 'branches', 'branch', 'worktrees'] as const) {\n\t\t\tthis.evictShared(key, repoPath, 'evict');\n\t\t}\n\t}\n\n\tgetBranchMergedStatus(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitBranchMergedStatus>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitBranchMergedStatus> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.branchMergedStatus,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => {\n\t\t\t\tif (!data.merged) return data;\n\t\t\t\tif (data.localBranchOnly == null) return data;\n\n\t\t\t\tconst lbo = data.localBranchOnly;\n\t\t\t\treturn {\n\t\t\t\t\t...data,\n\t\t\t\t\tlocalBranchOnly: createReference(lbo.ref, newRepoPath, {\n\t\t\t\t\t\tid: getBranchId(newRepoPath, lbo.remote, lbo.name),\n\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\tname: lbo.name,\n\t\t\t\t\t\tremote: lbo.remote,\n\t\t\t\t\t\tupstream: lbo.upstream,\n\t\t\t\t\t\tsha: lbo.sha,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ cancellation: cancellation },\n\t\t);\n\t}\n\n\t/** Config can differ by checkout through config.worktree and conditional includes. */\n\tgetAheadOfBaseConfigKey(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\trepoPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.aheadOfBaseConfigKey.getOrCreate(\n\t\t\trepoPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(repoPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * One listing for every checkout of a repository, which serves a checkout's {@link getAheadOfBaseConfigKey} while\n\t * nothing makes config differ by checkout. Evicted with it, hard, so a read after a change never joins one from\n\t * before it.\n\t */\n\tgetAheadOfBaseConfigListing(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimple(this.aheadOfBaseConfigListing, repoPath, factory, cancellation);\n\t}\n\n\tgetBranchMetadataMap(\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string) => PromiseOrValue<Map<string, BranchMetadata>>,\n\t): Promise<Map<string, BranchMetadata>> {\n\t\treturn this.getSharedSimple(this.branchMetadataMap, repoPath, factory);\n\t}\n\n\tgetDefaultBranchName(\n\t\trepoPath: string,\n\t\tremote: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimpleWithKey(this.defaultBranchName, repoPath, remote, factory, {\n\t\t\tcancellation: cancellation,\n\t\t});\n\t}\n\n\t/** The cached default branch for one `remote` key, without reading it; `undefined` when none is cached */\n\tpeekDefaultBranchName(repoPath: string, remote: string): Promise<string | undefined> | undefined {\n\t\treturn this._caches.defaultBranchName?.get(this.getCommonPath(repoPath), remote);\n\t}\n\n\t/**\n\t * No TTL and not cleared by a ref or config change: the caller confirms a hit against what the answer was read from\n\t * (see {@link CachedMergeTarget}). A checkout evicts only the entries marked `evictOnCheckout`\n\t */\n\tgetMergeTarget(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<CachedMergeTarget>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<CachedMergeTarget> {\n\t\tconst pending = this.getSharedSimpleWithKey(\n\t\t\tthis.mergeTargets,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\tconst generation = this._mergeTargetCheckoutGeneration;\n\t\t\t\tconst entry = await factory(commonPath, cacheable, signal);\n\t\t\t\tif (entry.evictOnCheckout) {\n\t\t\t\t\t// A checkout while the reflog was read may have written the entry it found missing\n\t\t\t\t\tif (this._mergeTargetCheckoutGeneration !== generation) {\n\t\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\t\treturn entry;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet keys = this._mergeTargetsEvictedOnCheckout.get(commonPath);\n\t\t\t\t\tif (keys == null) {\n\t\t\t\t\t\tkeys = new Set();\n\t\t\t\t\t\tthis._mergeTargetsEvictedOnCheckout.set(commonPath, keys);\n\t\t\t\t\t}\n\t\t\t\t\tkeys.add(cacheKey);\n\t\t\t\t}\n\t\t\t\treturn entry;\n\t\t\t},\n\t\t\t{ cancellation: cancellation },\n\t\t);\n\n\t\t// Stored before the factory runs, so this is the entry the answer will come from\n\t\tconst stored = this.mergeTargets.get(this.getCommonPath(repoPath), cacheKey);\n\t\tif (stored == null) return pending;\n\n\t\treturn pending.then(entry => {\n\t\t\tthis._mergeTargetStored.set(entry, stored);\n\t\t\treturn entry;\n\t\t});\n\t}\n\n\t/**\n\t * Drops `stale`, an answer {@link getMergeTarget} gave for `cacheKey`, unless it was already replaced: callers that\n\t * found the same answer stale then share the one that replaced it rather than each resolving their own\n\t */\n\tdeleteMergeTarget(repoPath: string, cacheKey: string, stale: CachedMergeTarget): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst stored = this._mergeTargetStored.get(stale);\n\t\tif (stored != null && this._caches.mergeTargets?.get(commonPath, cacheKey) !== stored) return;\n\n\t\tthis._caches.mergeTargets?.delete(commonPath, cacheKey);\n\t}\n\n\tprivate evictMergeTargetsOnCheckout(repoPath: string | undefined): void {\n\t\tthis._mergeTargetCheckoutGeneration++;\n\n\t\tconst commonPaths =\n\t\t\trepoPath != null ? [this.getCommonPath(repoPath)] : [...this._mergeTargetsEvictedOnCheckout.keys()];\n\t\tfor (const commonPath of commonPaths) {\n\t\t\tconst keys = this._mergeTargetsEvictedOnCheckout.get(commonPath);\n\t\t\tif (keys == null) continue;\n\n\t\t\tthis._mergeTargetsEvictedOnCheckout.delete(commonPath);\n\t\t\tfor (const key of keys) {\n\t\t\t\tthis._caches.mergeTargets?.delete(commonPath, key);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Clears the cached default branch for one `remote` key (the networked lookup or its `:local` variant). */\n\tdeleteDefaultBranchName(repoPath: string, remote: string): void {\n\t\tthis._caches.defaultBranchName?.delete(this.getCommonPath(repoPath), remote);\n\t}\n\n\tgetInitialCommitSha(\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string) => PromiseOrValue<string | undefined>,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimple(this.initialCommitSha, repoPath, factory);\n\t}\n\n\t/** A rejected factory is never cached (`PromiseMap` evicts on rejection) — a failed read retries next time. */\n\tgetEmptyTreeSha(repoPath: string, factory: (commonPath: string) => PromiseOrValue<string>): Promise<string> {\n\t\treturn this.getSharedSimple(this.emptyTreeSha, repoPath, factory);\n\t}\n\n\tgetLastFetchedTimestamp(\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string) => PromiseOrValue<number | undefined>,\n\t): Promise<number | undefined> {\n\t\treturn this.getSharedSimple(this.lastFetched, repoPath, factory);\n\t}\n\n\tgetRefs(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<RefRecord[]>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<RefRecord[]> {\n\t\t// Raw ref records are repoPath-agnostic (no per-worktree binding to remap), so we key only\n\t\t// by commonPath and skip the per-worktree mapper that `getBranches`/`getTags` need.\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\treturn this.refs.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tgetRefTips(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitRefTip[]>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRefTip[]> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\treturn this.refTips.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tasync getRemotes(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitRemote[]>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]> {\n\t\treturn this.getSharedOrCreate(\n\t\t\tthis.remotes,\n\t\t\trepoPath,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => data.map(r => r.withRepoPath(newRepoPath)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tasync getStash(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitStash>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitStash> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.stashes,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => ({\n\t\t\t\trepoPath: newRepoPath,\n\t\t\t\tstashes: new Map(\n\t\t\t\t\tArray.from(data.stashes.entries(), ([sha, s]) => [\n\t\t\t\t\t\tsha,\n\t\t\t\t\t\ts.withRepoPath<GitStashCommit>(newRepoPath),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t}),\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync getTags(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<PagedResult<GitTag>>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<PagedResult<GitTag>> {\n\t\treturn this.getSharedOrCreate(\n\t\t\tthis.tags,\n\t\t\trepoPath,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => ({ ...data, values: data.values.map(t => t.withRepoPath(newRepoPath)) }),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tasync getWorktrees(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitWorktree[]>,\n\t\toptions?: { force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitWorktree[]> {\n\t\tif (options?.force) {\n\t\t\t// An aborted call must not cost every other caller the shared list\n\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\tthis.evictCaches(repoPath, 'worktreeList');\n\t\t}\n\n\t\treturn this.getSharedOrCreate(\n\t\t\tthis.worktrees,\n\t\t\trepoPath,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => data.map(w => w.withRepoPath(newRepoPath)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async getSharedOrCreate<T>(\n\t\tcache: PromiseMap<string, T>,\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\tmapper: (data: T, repoPath: string) => T,\n\t\tcancellation?: AbortSignal,\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\t// Always register this caller with the shared factory's aggregate so same-`repoPath` and\n\t\t// worktree-distinct concurrent callers both contribute — invariant 3 (factory aborts iff\n\t\t// every waiter aborts) holds uniformly. The wrapped return is our caller-facing promise\n\t\t// for the commonPath-keyed branch; the per-worktree branch uses `raceWithSignal` below.\n\t\tconst sharedPromise = cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => {\n\t\t\t\tconst p = Promise.resolve(factory(commonPath, cacheable, signal));\n\t\t\t\t// On factory invalidation (without rejection), propagate to the derived per-worktree\n\t\t\t\t// mapper entries so they don't persist past the shared factory's settle. Mapper\n\t\t\t\t// entries cached via `cache.set()` have no controller, so `invalidate` hard-deletes.\n\t\t\t\tvoid p\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tif (cacheable.invalidated) {\n\t\t\t\t\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\t\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\t\t\t\t\tcache.invalidate(worktreePath);\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\t// Swallow the cleanup chain's rejection so a rejected factory (e.g. cancellation)\n\t\t\t\t\t// doesn't surface as an unhandled rejection; the caller-facing promise handles it.\n\t\t\t\t\t.catch(() => {});\n\t\t\t\treturn p;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\t// Swallow any rejection on the registration wrapper so it isn't surfaced as an unhandled\n\t\t// rejection when we discard it below (existing-mapper path). The real caller-facing\n\t\t// promise is the returned value.\n\t\tvoid sharedPromise.catch(() => {});\n\n\t\tif (commonPath !== repoPath) {\n\t\t\t// Reuse the cached mapped entry for this worktree if present; otherwise derive it off\n\t\t\t// the raw inner shared promise so subsequent cache hits don't inherit the first\n\t\t\t// caller's signal wrap.\n\t\t\tconst existing = cache.get(repoPath);\n\t\t\tif (existing != null) {\n\t\t\t\treturn cancellation != null ? raceWithSignal(existing, cancellation) : existing;\n\t\t\t}\n\n\t\t\tconst rawShared = cache.get(commonPath) ?? sharedPromise;\n\t\t\tconst mappedPromise = Promise.resolve(rawShared).then(data => mapper(data, repoPath));\n\t\t\tcache.set(repoPath, mappedPromise);\n\t\t\treturn cancellation != null ? raceWithSignal(mappedPromise, cancellation) : mappedPromise;\n\t\t}\n\n\t\treturn sharedPromise;\n\t}\n\n\tprivate async getSharedOrCreateWithKey<T>(\n\t\tcache: RepoPromiseCacheMap<string, T>,\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\tmapper: (data: T, repoPath: string) => T,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst cancellation = options?.cancellation;\n\n\t\t// Always register with the shared factory's aggregate (see `getSharedOrCreate` comment).\n\t\tconst sharedPromise = cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\tcacheKey,\n\t\t\t(cacheable, signal) => {\n\t\t\t\tconst p = Promise.resolve(factory(commonPath, cacheable, signal));\n\t\t\t\t// On factory invalidation (without rejection), propagate to the derived per-worktree\n\t\t\t\t// mapper entries for this `cacheKey` so they don't persist past the shared factory's\n\t\t\t\t// settle. Mapper entries cached via `cache.set()` have no controller, so `invalidate`\n\t\t\t\t// hard-deletes.\n\t\t\t\tvoid p\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tif (cacheable.invalidated) {\n\t\t\t\t\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\t\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\t\t\t\t\tcache.invalidate(worktreePath, cacheKey);\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\t// Swallow the cleanup chain's rejection so a rejected factory (e.g. cancellation)\n\t\t\t\t\t// doesn't surface as an unhandled rejection; the caller-facing promise handles it.\n\t\t\t\t\t.catch(() => {});\n\t\t\t\treturn p;\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t\t// Swallow any rejection on the registration wrapper so it isn't surfaced as an unhandled\n\t\t// rejection when we discard it below (existing-mapper path).\n\t\tvoid sharedPromise.catch(() => {});\n\n\t\tif (commonPath !== repoPath) {\n\t\t\tconst existing = cache.get(repoPath, cacheKey);\n\t\t\tif (existing != null) {\n\t\t\t\treturn cancellation != null ? raceWithSignal(existing, cancellation) : existing;\n\t\t\t}\n\n\t\t\tconst rawShared = cache.get(commonPath, cacheKey) ?? sharedPromise;\n\t\t\tconst mappedPromise = Promise.resolve(rawShared).then(data => mapper(data, repoPath));\n\t\t\tcache.set(repoPath, cacheKey, mappedPromise, options);\n\t\t\treturn cancellation != null ? raceWithSignal(mappedPromise, cancellation) : mappedPromise;\n\t\t}\n\n\t\treturn sharedPromise;\n\t}\n\n\tprivate async getSharedSimple<T>(\n\t\tcache: PromiseMap<string, T> | PromiseCache<string, T>,\n\t\trepoPath: string,\n\t\t// `cacheable` is forwarded so a factory can refuse the entry when the read FAILED rather than\n\t\t// genuinely produced nothing — see `getSharedSimpleWithKey` for why that distinction matters.\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\t// Only a `PromiseMap` takes one; its factory's signal aborts once every waiter has aborted\n\t\tcancellation?: AbortSignal,\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\t// `PromiseMap.getOrCreate(key, factory, cancellation?)` and\n\t\t// `PromiseCache.getOrCreate(key, factory, options?)` have different 3rd-argument shapes,\n\t\t// so we dispatch on cache type. Both register a `CacheController` so `invalidate` works.\n\t\tif (cache instanceof PromiseCache) {\n\t\t\treturn cache.getOrCreate(commonPath, cacheable => Promise.resolve(factory(commonPath, cacheable)));\n\t\t}\n\t\treturn cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async getSharedSimpleWithKey<T>(\n\t\tcache: RepoPromiseCacheMap<string, T>,\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\t// `cacheable` is forwarded so a factory can distinguish \"the answer is genuinely nothing\" from \"the\n\t\t// read failed\": callers here set no TTL by default, so a failure resolved as `undefined` would\n\t\t// otherwise be served as a real answer until something explicitly evicts it.\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\toptions?: { accessTTL?: number; createTTL?: number; cancellation?: AbortSignal },\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\treturn cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\tcacheKey,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\toptions,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cache.js","names":[],"sources":["../../../git/src/cache.ts"],"sourcesContent":["import { exhaustiveArray } from '@gitlens/utils/array.js';\nimport { CancellationError, raceWithSignal } from '@gitlens/utils/cancellation.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { invalidateMemoized } from '@gitlens/utils/decorators/memoize.js';\nimport type { Event } from '@gitlens/utils/event.js';\nimport { Emitter } from '@gitlens/utils/event.js';\nimport { getBranchId } from '@gitlens/utils/gitRefs.js';\nimport type { PagedResult } from '@gitlens/utils/paging.js';\nimport { normalizePath } from '@gitlens/utils/path.js';\nimport type { PromiseOrValue } from '@gitlens/utils/promise.js';\nimport type { CacheController } from '@gitlens/utils/promiseCache.js';\nimport { PromiseCache, PromiseMap, RepoPromiseCacheMap } from '@gitlens/utils/promiseCache.js';\nimport type { ResourceUsage } from '@gitlens/utils/resourceUsage.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport type { ProgressiveGitBlame } from './models/blame.js';\nimport type { BranchMetadata, BranchMetadataGkConfigKey, GitBranch } from './models/branch.js';\nimport type { GitCommit, GitStashCommit } from './models/commit.js';\nimport type { GitContributor, GitContributorsStats } from './models/contributor.js';\nimport type { ParsedGitDiffHunks } from './models/diff.js';\nimport type { GitLog } from './models/log.js';\nimport type { ConflictDetectionResult } from './models/mergeConflicts.js';\nimport type { GitPausedOperationStatus } from './models/pausedOperationStatus.js';\nimport type { GitBranchReference, GitRefTip, RefRecord } from './models/reference.js';\nimport type { GitRemote } from './models/remote.js';\nimport type { RemoteProvider } from './models/remoteProvider.js';\nimport type { GitDir, RepositoryChange } from './models/repository.js';\nimport type { GitStash } from './models/stash.js';\nimport type { GitTag } from './models/tag.js';\nimport type { GitUser } from './models/user.js';\nimport type { GitWorktree } from './models/worktree.js';\nimport type { BranchContributionsOverview, GitBranchMergedStatus, MergeTarget } from './providers/branches.js';\nimport type { GitCommitReachability, LeftRightCommitCountResult } from './providers/commits.js';\nimport type { GitContributorsResult } from './providers/contributors.js';\nimport type { ResolvedRevision } from './providers/revision.js';\nimport type { GitResult } from './run.types.js';\nimport { parseBranchMetadataGkConfigKey, setBranchMetadataValue } from './utils/branch.utils.js';\nimport { createReference } from './utils/reference.utils.js';\nimport { getCommonRepositoryPath, getRepositoryOrWorktreePath } from './utils/repository.utils.js';\nimport type { GitIgnoreFilter } from './watching/gitIgnoreFilter.js';\n\ntype RepoPath = string;\n\n/** Cache types that are keyed by file path within a repo — support per-file clearing */\nexport type UriScopedCachedGitTypes = 'blame' | 'diff' | 'fileLog';\n\nconst uriScopedCachedGitTypes: UriScopedCachedGitTypes[] = ['blame', 'diff', 'fileLog'];\nexport function areUriScopedCachedGitTypes(types: string[]): types is UriScopedCachedGitTypes[] {\n\treturn types.every(t => uriScopedCachedGitTypes.includes(t as UriScopedCachedGitTypes));\n}\n\nexport type CachedGitTypes =\n\t| UriScopedCachedGitTypes\n\t| 'branch'\n\t| 'branches'\n\t| 'config'\n\t| 'contributors'\n\t| 'gitignore'\n\t| 'gkConfig'\n\t| 'lastFetched'\n\t| 'providers'\n\t| 'remotes'\n\t| 'stashes'\n\t| 'status'\n\t| 'tags'\n\t| 'tracking'\n\t| 'worktrees'\n\t/** Only the worktree list: unlike `'worktrees'`, no worktree's git results or merge targets */\n\t| 'worktreeList';\n\n/** Whether a reset of these types makes in-flight git runs stale (none or empty meaning every type) */\nexport function resetDropsPendingRuns(types: readonly CachedGitTypes[] | undefined): boolean {\n\t// A provider reset touches only remote-provider metadata, and the list's next read never joins a running\n\t// `worktree list`, as it runs under the cache's own signal: neither changes any git command's output\n\treturn !types?.length || types.some(t => t !== 'worktreeList' && t !== 'providers');\n}\n\n/**\n * What a gk-config reconcile did, so `Cache` knows whether the coarse fallback is still owed.\n *\n * `'deferred'` is NOT a failure — a pass already in flight folds the change into its trailing pass — and\n * must not trigger the fallback, or a burst of gk writes would coarse-clear on every one, which is exactly\n * the churn the key-aware reconcile replaced.\n */\nexport type GkReconcileOutcome = 'reconciled' | 'deferred' | 'failed';\n\n/** Fired by {@link Cache.onDidChangeMergeTargets} */\nexport interface MergeTargetsChangeEvent {\n\t/**\n\t * The repository's common path (the main worktree's, once registered). Merge keys live in the shared\n\t * `.git/gk/config`, so this fires once per change for the whole repository, not once per worktree.\n\t */\n\treadonly repoPath: string;\n\t/**\n\t * Branches whose merge-relevant keys (`gk-merge-base`, `gk-merge-target`, `gk-merge-target-user`,\n\t * `gk-target-base`) changed. `undefined` when it can't be told, so any branch's may have: the coarse fallback\n\t * (no reconciler, or a failed reconcile), or an external change with no earlier snapshot to diff against. Core's\n\t * own write names its one branch.\n\t */\n\treadonly refs: ReadonlySet<string> | undefined;\n}\n\nexport type ConflictDetectionCacheKey =\n\t| `apply:${string}:${string}:${string}`\n\t| `merge:${string}:${string}`\n\t| `reapply:${string}:${string}`;\n\n/**\n * Ceiling on how long a derived branch base is trusted. Long enough that repeated reads during normal use\n * are served from cache, short enough that a base that changed by a route with no eviction signal (an\n * external delete-and-recreate of a branch that is never checked out) self-heals without a reload.\n */\nconst baseBranchNameTTL = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Completed blame graphs retain several objects and substrings per line. Keep normal files hot, but let large\n * documents be owned by their active tracked-document snapshot instead of retaining a second long-lived owner.\n */\nconst maxCachedBlameLines = 5000;\n\nexport async function shouldEvictBlameCacheEntry(progressive: ProgressiveGitBlame | undefined): Promise<boolean> {\n\tif (progressive == null) return false;\n\n\ttry {\n\t\tconst blame = await progressive.completed;\n\t\treturn blame.lines.length > maxCachedBlameLines;\n\t} catch {\n\t\t// The provider factory resolves as soon as streaming starts, so a later stream failure must also be retried.\n\t\treturn true;\n\t}\n}\n\n/**\n * gkConfig keys that participate in the `branchOverviews` cache's mergeTarget/mergeBase lineage.\n * Capture group 1 is the ref name (which may itself contain `.`/`/`).\n */\nconst branchOverviewGkConfigKeysRegex = /^branch\\.(.+)\\.(?:gk-merge-(?:base|target(?:-user)?)|gk-target-base)$/;\n\n/** The ref of a gkConfig key the reconcile baseline tracks, or `undefined` for any other key */\nfunction getReconciledGkConfigRef(key: string): string | undefined {\n\treturn branchOverviewGkConfigKeysRegex.exec(key)?.[1] ?? parseBranchMetadataGkConfigKey(key)?.branch;\n}\n\n/** The value `cache` holds for `key`, `'pending'` while it is still being read, or `undefined` when nothing is cached */\nfunction getSettledOrPending<T>(\n\tcache: PromiseMap<string, T> | undefined,\n\tkey: string,\n): { value: T } | 'pending' | undefined {\n\tif (!cache?.has(key)) return undefined;\n\n\treturn cache.getSettled(key) ?? 'pending';\n}\n\n/**\n * Downstream caches that `deleteGkConfig` may invalidate when a `branch.<ref>.gk-...` key changes.\n * Callers performing a \"self-write\" (where the value being written matches what they just resolved,\n * so the about-to-be-evicted entry is exactly the entry they want to preserve) can opt out by\n * naming the targets to skip via `skipInvalidation`.\n */\nexport type GkConfigInvalidationTarget = 'branchOverviews' | 'baseBranchName';\n\n/**\n * A `getMergeTarget` answer with what it was read from, so a later call can confirm it from cached reads rather than\n * resolve it again (see {@link Cache.getMergeTarget})\n */\nexport interface CachedMergeTarget {\n\t/** The answer before `keepSelfAtTip` is applied */\n\treadonly result: MergeTarget | undefined;\n\t/** Whether `result` is the branch itself at the branch's own commit */\n\treadonly selfAtTip: boolean;\n\t/** Every full ref name whose presence or tip the answer depends on, with the commit it named then (`undefined` when absent) */\n\treadonly tips: ReadonlyArray<readonly [ref: string, tip: string | undefined]>;\n\t/**\n\t * The replace refs as read, as sorted `<name>\\0<sha>` lines ('' for none): replacing a commit moves merge bases\n\t * while every tip stands\n\t */\n\treadonly replaced: string;\n\t/**\n\t * The common git directory's `shallow` file as `<size>\\0<mtime>`, or `null` when the repo wasn't shallow: deepening\n\t * a shallow clone moves merge bases while every tip stands\n\t */\n\treadonly shallow: string | null;\n\t/** The `getAheadOfBaseConfigKey` snapshot the answer was read under */\n\treadonly configKey: string | undefined;\n\t/** The branch's stored merge keys as read, raw; `undefined` for a remote-tracking branch, which has none */\n\treadonly stored: readonly (string | undefined)[] | undefined;\n\t/** Set only when resolution reached the pull request and stored nothing: the base candidate it named, or `null` for none */\n\treadonly pullRequest?: string | null;\n\t/** Set only when the default branch was read: the name local refs gave, or `null` for none */\n\treadonly localDefault?: string | null;\n\t/** Set only when the remote was asked for its default branch: that remote, and its answer or `null` for none */\n\treadonly remoteDefault?: { readonly remote: string; readonly name: string | null };\n\t/** Set only when the caller's fallback default branch was asked: its answer, or `null` for none */\n\treadonly fallbackDefault?: string | null;\n\t/** The answer read HEAD's reflog for the branch it was created from and found none, which a later checkout can write */\n\treadonly evictOnCheckout: boolean;\n}\n\n/** A changed `branch.<branch>.<key>` gk config value for {@link Cache.patchBranchMetadata}; `undefined` is a removal */\nexport interface BranchMetadataChange {\n\treadonly branch: string;\n\treadonly key: BranchMetadataGkConfigKey;\n\treadonly value: string | undefined;\n}\n\n/** Per-worktree caches — cleared by repoPath directly */\ninterface Caches {\n\taheadOfBaseConfigKey: PromiseMap<RepoPath, string | undefined> | undefined;\n\tbestRemotes: PromiseMap<RepoPath, GitRemote<RemoteProvider>[]> | undefined;\n\tblame: RepoPromiseCacheMap<string, ProgressiveGitBlame | undefined> | undefined;\n\tbranch: PromiseMap<RepoPath, GitBranch | undefined> | undefined;\n\tcommit: RepoPromiseCacheMap<string, GitCommit | undefined> | undefined;\n\tcommitCount: RepoPromiseCacheMap<string, number | undefined> | undefined;\n\tconflictDetection: RepoPromiseCacheMap<ConflictDetectionCacheKey, ConflictDetectionResult> | undefined;\n\tcurrentBranchReference: PromiseCache<RepoPath, GitBranchReference | undefined> | undefined;\n\tcurrentUser: Map<RepoPath, GitUser | null> | undefined;\n\tdiff: RepoPromiseCacheMap<string, ParsedGitDiffHunks | undefined> | undefined;\n\tfileExistence: RepoPromiseCacheMap<string, boolean> | undefined;\n\tfileLog: RepoPromiseCacheMap<string, GitLog | undefined> | undefined;\n\tgitDir: Map<RepoPath, GitDir> | undefined;\n\tgitIgnore: Map<RepoPath, GitIgnoreFilter> | undefined;\n\tignoreRevsFile: PromiseCache<string, boolean> | undefined;\n\tleftRightCommitCount: RepoPromiseCacheMap<string, LeftRightCommitCountResult | undefined> | undefined;\n\tmergeBase: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tpatchIds: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tpausedOperationStatus: PromiseMap<RepoPath, GitPausedOperationStatus | undefined> | undefined;\n\treachability: RepoPromiseCacheMap<string, GitCommitReachability | undefined> | undefined;\n\tresolvedRevisions: RepoPromiseCacheMap<string, ResolvedRevision> | undefined;\n\ttrackedPaths: RepoPromiseCacheMap<string, [string, string] | false> | undefined;\n}\n\n/** Shared caches — cleared via commonPath + all worktree paths */\ninterface SharedCaches {\n\t/**\n\t * The `git config` listing behind `aheadOfBaseConfigKey`, read once in the main checkout for every checkout of the\n\t * repository; also the main checkout's own listing\n\t */\n\taheadOfBaseConfigListing: PromiseMap<RepoPath, string | undefined> | undefined;\n\tbaseBranchName: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tbranchMergedStatus: RepoPromiseCacheMap<string, GitBranchMergedStatus> | undefined;\n\tbranchMetadataMap: PromiseMap<RepoPath, Map<string, BranchMetadata>> | undefined;\n\tbranchOverviews: RepoPromiseCacheMap<string, BranchContributionsOverview | undefined> | undefined;\n\tbranches: PromiseMap<RepoPath, PagedResult<GitBranch>> | undefined;\n\tconfigKeys: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\tconfigPatterns: RepoPromiseCacheMap<string, Map<string, string>> | undefined;\n\tcontributors: RepoPromiseCacheMap<string, GitContributorsResult> | undefined;\n\tcontributorsLite: RepoPromiseCacheMap<string, GitContributor[]> | undefined;\n\tcontributorsStats: RepoPromiseCacheMap<string, GitContributorsStats | undefined> | undefined;\n\tdefaultBranchName: RepoPromiseCacheMap<string, string | undefined> | undefined;\n\t/** The empty tree's id — a property of the repository's object format, which never changes for its lifetime. */\n\temptyTreeSha: PromiseMap<RepoPath, string> | undefined;\n\tgitResults: RepoPromiseCacheMap<string, GitResult> | undefined;\n\tgkConfigMap: PromiseMap<RepoPath, Map<string, string>> | undefined;\n\t/**\n\t * The `git config` listing of the gitignore filter's inputs (`core.excludesFile`, `core.ignorecase`), read once in\n\t * the main checkout for every checkout of the repository\n\t */\n\tignoreConfigListing: PromiseMap<RepoPath, string | undefined> | undefined;\n\tinitialCommitSha: PromiseMap<RepoPath, string | undefined> | undefined;\n\t/** Keyed by commonPath — `FETCH_HEAD` lives in the common git dir, shared across worktrees. */\n\tlastFetched: PromiseCache<RepoPath, number | undefined> | undefined;\n\tlogShas: RepoPromiseCacheMap<string, string[]> | undefined;\n\tmergeTargets: RepoPromiseCacheMap<string, CachedMergeTarget> | undefined;\n\trefs: PromiseMap<RepoPath, RefRecord[]> | undefined;\n\trefTips: PromiseMap<RepoPath, GitRefTip[]> | undefined;\n\tremotes: PromiseMap<RepoPath, GitRemote[]> | undefined;\n\tsharedBranches: PromiseMap<RepoPath, PagedResult<GitBranch>> | undefined;\n\tstashes: RepoPromiseCacheMap<string, GitStash> | undefined;\n\ttags: PromiseMap<RepoPath, PagedResult<GitTag>> | undefined;\n\tworktrees: PromiseMap<RepoPath, GitWorktree[]> | undefined;\n}\n\ntype AllCaches = Caches & SharedCaches;\n\n/** Compile-time enforced: adding a key to SharedCaches without listing it here is a type error */\nconst sharedCacheKeys: ReadonlySet<keyof AllCaches> = new Set(\n\texhaustiveArray<keyof SharedCaches>()([\n\t\t'aheadOfBaseConfigListing',\n\t\t'baseBranchName',\n\t\t'branchMergedStatus',\n\t\t'branchMetadataMap',\n\t\t'branchOverviews',\n\t\t'branches',\n\t\t'configKeys',\n\t\t'configPatterns',\n\t\t'contributors',\n\t\t'contributorsLite',\n\t\t'contributorsStats',\n\t\t'defaultBranchName',\n\t\t'emptyTreeSha',\n\t\t'gitResults',\n\t\t'gkConfigMap',\n\t\t'ignoreConfigListing',\n\t\t'initialCommitSha',\n\t\t'lastFetched',\n\t\t'logShas',\n\t\t'mergeTargets',\n\t\t'refs',\n\t\t'refTips',\n\t\t'remotes',\n\t\t'sharedBranches',\n\t\t'stashes',\n\t\t'tags',\n\t\t'worktrees',\n\t]),\n);\n\nfunction createEmptyCaches(): AllCaches {\n\treturn {\n\t\taheadOfBaseConfigKey: undefined,\n\t\taheadOfBaseConfigListing: undefined,\n\t\tbaseBranchName: undefined,\n\t\tbestRemotes: undefined,\n\t\tblame: undefined,\n\t\tbranch: undefined,\n\t\tbranchMergedStatus: undefined,\n\t\tbranchMetadataMap: undefined,\n\t\tbranchOverviews: undefined,\n\t\tbranches: undefined,\n\t\tcommit: undefined,\n\t\tcommitCount: undefined,\n\t\tfileExistence: undefined,\n\t\tignoreRevsFile: undefined,\n\t\tleftRightCommitCount: undefined,\n\t\tmergeBase: undefined,\n\t\tmergeTargets: undefined,\n\t\tpatchIds: undefined,\n\t\tconfigKeys: undefined,\n\t\tconfigPatterns: undefined,\n\t\tconflictDetection: undefined,\n\t\tdiff: undefined,\n\t\tfileLog: undefined,\n\t\tcontributors: undefined,\n\t\tcontributorsLite: undefined,\n\t\tcontributorsStats: undefined,\n\t\tcurrentBranchReference: undefined,\n\t\tcurrentUser: undefined,\n\t\tdefaultBranchName: undefined,\n\t\temptyTreeSha: undefined,\n\t\tgitDir: undefined,\n\t\tgitIgnore: undefined,\n\t\tgitResults: undefined,\n\t\tgkConfigMap: undefined,\n\t\tignoreConfigListing: undefined,\n\t\tinitialCommitSha: undefined,\n\t\tlastFetched: undefined,\n\t\tlogShas: undefined,\n\t\tpausedOperationStatus: undefined,\n\t\tresolvedRevisions: undefined,\n\t\treachability: undefined,\n\t\trefs: undefined,\n\t\trefTips: undefined,\n\t\tremotes: undefined,\n\t\tsharedBranches: undefined,\n\t\tstashes: undefined,\n\t\ttags: undefined,\n\t\ttrackedPaths: undefined,\n\t\tworktrees: undefined,\n\t};\n}\n\nexport class Cache implements Disposable {\n\tprivate _caches: AllCaches = createEmptyCaches();\n\tprivate _commonPathRegistry = new Map<RepoPath, string>();\n\t/** Reverse index: commonPath → set of worktree repoPaths that share it */\n\tprivate _worktreesByCommonPath = new Map<string, Set<RepoPath>>();\n\t/** Monotonic per-worktree \"status clock\" — see {@link getStatusGeneration}. */\n\tprivate _statusGenerations = new Map<RepoPath, number>();\n\t/** Monotonic per-path \"close clock\" — see {@link getCloseGeneration}. */\n\tprivate _closeGenerations = new Map<RepoPath, number>();\n\t/** Per commonPath, the `mergeTargets` keys a checkout evicts (see {@link CachedMergeTarget.evictOnCheckout}) */\n\tprivate _mergeTargetsEvictedOnCheckout = new Map<string, Set<string>>();\n\t/** Bumped on each checkout eviction, so a merge target resolved across one isn't kept for the next */\n\tprivate _mergeTargetCheckoutGeneration = 0;\n\t/** Each merge target answer's entry as `mergeTargets` stored it, so dropping a stale answer can't drop its successor */\n\tprivate _mergeTargetStored = new WeakMap<CachedMergeTarget, Promise<CachedMergeTarget>>();\n\n\t/**\n\t * Per-commonPath snapshot of the subset of `.git/gk/config` that derived caches depend on — merge-relevant keys\n\t * ({@link branchOverviewGkConfigKeysRegex}) and branch metadata keys ({@link parseBranchMetadataGkConfigKey}) —\n\t * used by {@link reconcileGkConfigMap} to diff a watcher `'gkConfig'` event down to only the keys that actually\n\t * changed, instead of coarsely re-deriving `baseBranchName`/`branchOverviews` and the branches on every gk write.\n\t * Absent means \"never observed\".\n\t */\n\tprivate _gkConfigSnapshots = new Map<string, Map<string, string>>();\n\n\tprivate readonly _onDidChangeMergeTargets = new Emitter<MergeTargetsChangeEvent>();\n\t/**\n\t * Fires when a `.git/gk/config` write changed a branch's merge-relevant keys — never for a write that only touched\n\t * other keys (activity timestamps). Core's own key store fires it once, as the write completes (see\n\t * {@link recordGkConfigWrite}), and the watcher's later report of that write doesn't fire it again; core's own\n\t * section remove and rename (a branch delete or rename) never fire it, nor do its internal saves while answering\n\t * a read (nobody awaits those, and only another process's watcher reports them). Fires after the derived caches were\n\t * cleared, so a listener's re-read sees the new values. A listener must not write merge keys back in response,\n\t * or it loops.\n\t */\n\tget onDidChangeMergeTargets(): Event<MergeTargetsChangeEvent> {\n\t\treturn this._onDidChangeMergeTargets.event;\n\t}\n\n\t/**\n\t * Reconciler registered by the CLI config sub-provider (see {@link setGkConfigReconciler}),\n\t * invoked on a watcher-observed `'gkConfig'` change instead of the coarse `clearCaches(repoPath,\n\t * 'gkConfig')` cascade. `undefined` (e.g. the GitHub provider, which has no `.git/gk/config`)\n\t * falls back to the coarse clear.\n\t */\n\tprivate _gkConfigReconciler:\n\t\t| ((\n\t\t\t\trepoPath: string,\n\t\t\t\tpriorSnapshot: ReadonlyMap<string, string> | undefined,\n\t\t ) => PromiseOrValue<GkReconcileOutcome>)\n\t\t| undefined;\n\n\t[Symbol.dispose](): void {\n\t\tthis.dispose();\n\t}\n\n\tdispose(): void {\n\t\tthis.reset();\n\t\tthis._onDidChangeMergeTargets.dispose();\n\t}\n\n\t/** Resource usage retained by instantiated sub-caches and their bookkeeping maps. */\n\tgetResourceUsage(): ResourceUsage {\n\t\tconst usage: ResourceUsage = {};\n\t\tfor (const [name, cache] of Object.entries(this._caches)) {\n\t\t\tif (cache != null) {\n\t\t\t\tusage[`cache.${name}.entries.count`] =\n\t\t\t\t\tcache instanceof RepoPromiseCacheMap ? cache.entryCount : cache.size;\n\t\t\t}\n\t\t}\n\t\tusage['cache.commonPathRegistry.entries.count'] = this._commonPathRegistry.size;\n\t\tusage['cache.worktreesByCommonPath.entries.count'] = this._worktreesByCommonPath.size;\n\t\tusage['cache.statusGenerations.entries.count'] = this._statusGenerations.size;\n\t\tusage['cache.closeGenerations.entries.count'] = this._closeGenerations.size;\n\t\tusage['cache.gkConfigSnapshots.entries.count'] = this._gkConfigSnapshots.size;\n\t\treturn usage;\n\t}\n\n\tget aheadOfBaseConfigKey(): PromiseMap<RepoPath, string | undefined> {\n\t\treturn (this._caches.aheadOfBaseConfigKey ??= new PromiseMap<RepoPath, string | undefined>());\n\t}\n\n\tget aheadOfBaseConfigListing(): PromiseMap<RepoPath, string | undefined> {\n\t\treturn (this._caches.aheadOfBaseConfigListing ??= new PromiseMap<RepoPath, string | undefined>());\n\t}\n\n\tget bestRemotes(): PromiseMap<RepoPath, GitRemote<RemoteProvider>[]> {\n\t\treturn (this._caches.bestRemotes ??= new PromiseMap<RepoPath, GitRemote<RemoteProvider>[]>());\n\t}\n\n\tget blame(): RepoPromiseCacheMap<string, ProgressiveGitBlame | undefined> {\n\t\treturn (this._caches.blame ??= new RepoPromiseCacheMap<string, ProgressiveGitBlame | undefined>({\n\t\t\tcreateTTL: 1000 * 60 * 10, // 10 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tget diff(): RepoPromiseCacheMap<string, ParsedGitDiffHunks | undefined> {\n\t\treturn (this._caches.diff ??= new RepoPromiseCacheMap<string, ParsedGitDiffHunks | undefined>({\n\t\t\tcreateTTL: 1000 * 60 * 10, // 10 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tget fileLog(): RepoPromiseCacheMap<string, GitLog | undefined> {\n\t\treturn (this._caches.fileLog ??= new RepoPromiseCacheMap<string, GitLog | undefined>({\n\t\t\tcreateTTL: 1000 * 60 * 10, // 10 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tprivate get mergeTargets(): RepoPromiseCacheMap<string, CachedMergeTarget> {\n\t\treturn (this._caches.mergeTargets ??= new RepoPromiseCacheMap<string, CachedMergeTarget>());\n\t}\n\n\tprivate get baseBranchName(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.baseBranchName ??= new RepoPromiseCacheMap<string, string | undefined>());\n\t}\n\n\tget branch(): PromiseMap<RepoPath, GitBranch | undefined> {\n\t\treturn (this._caches.branch ??= new PromiseMap<RepoPath, GitBranch | undefined>());\n\t}\n\n\tget branchMergedStatus(): RepoPromiseCacheMap<string, GitBranchMergedStatus> {\n\t\treturn (this._caches.branchMergedStatus ??= new RepoPromiseCacheMap<string, GitBranchMergedStatus>({\n\t\t\tcreateTTL: 1000 * 60 * 30, // 30 minutes — content-keyed on tip shas, so this is just a backstop\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 100, // Limit to 100 branch-pairs per repo\n\t\t}));\n\t}\n\n\tprivate get branchMetadataMap(): PromiseMap<RepoPath, Map<string, BranchMetadata>> {\n\t\treturn (this._caches.branchMetadataMap ??= new PromiseMap<RepoPath, Map<string, BranchMetadata>>());\n\t}\n\n\tprivate get branchOverviews(): RepoPromiseCacheMap<string, BranchContributionsOverview | undefined> {\n\t\treturn (this._caches.branchOverviews ??= new RepoPromiseCacheMap<\n\t\t\tstring,\n\t\t\tBranchContributionsOverview | undefined\n\t\t>(\n\t\t\t{ accessTTL: 1000 * 60 * 60 }, // 60 minutes\n\t\t));\n\t}\n\n\tget branches(): PromiseMap<RepoPath, PagedResult<GitBranch>> {\n\t\treturn (this._caches.branches ??= new PromiseMap<RepoPath, PagedResult<GitBranch>>());\n\t}\n\n\t/**\n\t * Internal cache for raw shared branch data (keyed by commonPath)\n\t * Separate from branches cache because branches need to be mapped for each worktree\n\t */\n\tprivate get sharedBranches(): PromiseMap<RepoPath, PagedResult<GitBranch>> {\n\t\treturn (this._caches.sharedBranches ??= new PromiseMap<RepoPath, PagedResult<GitBranch>>());\n\t}\n\n\tprivate get configKeys(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.configKeys ??= new RepoPromiseCacheMap<string, string | undefined>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds - ensures global config changes are picked up\n\t\t}));\n\t}\n\n\tprivate get configPatterns(): RepoPromiseCacheMap<string, Map<string, string>> {\n\t\treturn (this._caches.configPatterns ??= new RepoPromiseCacheMap<string, Map<string, string>>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds - ensures global config changes are picked up\n\t\t}));\n\t}\n\n\tprivate get gkConfigMap(): PromiseMap<RepoPath, Map<string, string>> {\n\t\treturn (this._caches.gkConfigMap ??= new PromiseMap<RepoPath, Map<string, string>>());\n\t}\n\n\tget currentBranchReference(): PromiseCache<RepoPath, GitBranchReference | undefined> {\n\t\treturn (this._caches.currentBranchReference ??= new PromiseCache<RepoPath, GitBranchReference | undefined>());\n\t}\n\n\tsetCurrentBranchReferenceIfAbsent(worktreePath: string, reference: GitBranchReference | undefined): void {\n\t\tif (this.currentBranchReference.get(worktreePath) == null) {\n\t\t\tthis.currentBranchReference.set(worktreePath, Promise.resolve(reference));\n\t\t}\n\t}\n\n\tget conflictDetection(): RepoPromiseCacheMap<ConflictDetectionCacheKey, ConflictDetectionResult> {\n\t\treturn (this._caches.conflictDetection ??= new RepoPromiseCacheMap<\n\t\t\tConflictDetectionCacheKey,\n\t\t\tConflictDetectionResult\n\t\t>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds\n\t\t}));\n\t}\n\n\tget contributors(): RepoPromiseCacheMap<string, GitContributorsResult> {\n\t\treturn (this._caches.contributors ??= new RepoPromiseCacheMap<string, GitContributorsResult>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget contributorsLite(): RepoPromiseCacheMap<string, GitContributor[]> {\n\t\treturn (this._caches.contributorsLite ??= new RepoPromiseCacheMap<string, GitContributor[]>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget contributorsStats(): RepoPromiseCacheMap<string, GitContributorsStats | undefined> {\n\t\treturn (this._caches.contributorsStats ??= new RepoPromiseCacheMap<string, GitContributorsStats | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget currentUser(): Map<RepoPath, GitUser | null> {\n\t\treturn (this._caches.currentUser ??= new Map<RepoPath, GitUser | null>());\n\t}\n\n\tget defaultBranchName(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.defaultBranchName ??= new RepoPromiseCacheMap<string, string | undefined>());\n\t}\n\n\tget emptyTreeSha(): PromiseMap<RepoPath, string> {\n\t\treturn (this._caches.emptyTreeSha ??= new PromiseMap<RepoPath, string>());\n\t}\n\n\tget gitDir(): Map<RepoPath, GitDir> {\n\t\treturn (this._caches.gitDir ??= new Map<RepoPath, GitDir>());\n\t}\n\n\tget gitIgnore(): Map<RepoPath, GitIgnoreFilter> {\n\t\treturn (this._caches.gitIgnore ??= new Map<RepoPath, GitIgnoreFilter>());\n\t}\n\n\tget gitResults(): RepoPromiseCacheMap<RepoPath, GitResult> {\n\t\treturn (this._caches.gitResults ??= new RepoPromiseCacheMap<RepoPath, GitResult>({ capacity: 200 }));\n\t}\n\n\tget ignoreConfigListing(): PromiseMap<RepoPath, string | undefined> {\n\t\treturn (this._caches.ignoreConfigListing ??= new PromiseMap<RepoPath, string | undefined>());\n\t}\n\n\tget initialCommitSha(): PromiseMap<RepoPath, string | undefined> {\n\t\treturn (this._caches.initialCommitSha ??= new PromiseMap<RepoPath, string | undefined>());\n\t}\n\n\tget lastFetched(): PromiseCache<RepoPath, number | undefined> {\n\t\treturn (this._caches.lastFetched ??= new PromiseCache<RepoPath, number | undefined>({\n\t\t\tcreateTTL: 1000 * 30, // 30 seconds\n\t\t}));\n\t}\n\n\tget leftRightCommitCount(): RepoPromiseCacheMap<string, LeftRightCommitCountResult | undefined> {\n\t\treturn (this._caches.leftRightCommitCount ??= new RepoPromiseCacheMap<\n\t\t\tstring,\n\t\t\tLeftRightCommitCountResult | undefined\n\t\t>({\n\t\t\tcreateTTL: 1000 * 60 * 5, // 5 minutes max age — invalidated sooner on branch/remote changes\n\t\t\tcapacity: 50, // Limit to 50 ref-pairs per repo\n\t\t}));\n\t}\n\n\tget commit(): RepoPromiseCacheMap<string, GitCommit | undefined> {\n\t\treturn (this._caches.commit ??= new RepoPromiseCacheMap<string, GitCommit | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 100, // Limit to 100 commits per repo\n\t\t}));\n\t}\n\n\tget commitCount(): RepoPromiseCacheMap<string, number | undefined> {\n\t\treturn (this._caches.commitCount ??= new RepoPromiseCacheMap<string, number | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\tget mergeBase(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.mergeBase ??= new RepoPromiseCacheMap<string, string | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 50,\n\t\t}));\n\t}\n\n\t/**\n\t * Patch IDs keyed by full commit sha (plus `paths` and `verbatim`). A commit's content is immutable, so no\n\t * ref or worktree event can make an entry stale and nothing clears it short of a full cache reset. A cached\n\t * `undefined` is a real answer (a merge commit, or a change that is empty after `paths`). Kept per worktree,\n\t * not per repository, since an ID depends on the attributes of the checkout it was read from. Sized above a range\n\t * read of a couple thousand commits, so one read doesn't evict its own ids before the next.\n\t */\n\tget patchIds(): RepoPromiseCacheMap<string, string | undefined> {\n\t\treturn (this._caches.patchIds ??= new RepoPromiseCacheMap<string, string | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 5000,\n\t\t}));\n\t}\n\n\tget logShas(): RepoPromiseCacheMap<string, string[]> {\n\t\treturn (this._caches.logShas ??= new RepoPromiseCacheMap<string, string[]>({\n\t\t\tcreateTTL: 1000 * 60 * 5, // 5 minutes max age\n\t\t\taccessTTL: 1000 * 30, // 30 seconds if not accessed\n\t\t\tcapacity: 5, // Limit to 5 different ranges per repo\n\t\t}));\n\t}\n\n\tget pausedOperationStatus(): PromiseMap<RepoPath, GitPausedOperationStatus | undefined> {\n\t\treturn (this._caches.pausedOperationStatus ??= new PromiseMap<\n\t\t\tRepoPath,\n\t\t\tGitPausedOperationStatus | undefined\n\t\t>());\n\t}\n\n\tget resolvedRevisions(): RepoPromiseCacheMap<string, ResolvedRevision> {\n\t\treturn (this._caches.resolvedRevisions ??= new RepoPromiseCacheMap<string, ResolvedRevision>({\n\t\t\tcapacity: 100,\n\t\t}));\n\t}\n\n\tget refs(): PromiseMap<RepoPath, RefRecord[]> {\n\t\treturn (this._caches.refs ??= new PromiseMap<RepoPath, RefRecord[]>());\n\t}\n\n\tget refTips(): PromiseMap<RepoPath, GitRefTip[]> {\n\t\treturn (this._caches.refTips ??= new PromiseMap<RepoPath, GitRefTip[]>());\n\t}\n\n\tget reachability(): RepoPromiseCacheMap<string, GitCommitReachability | undefined> {\n\t\treturn (this._caches.reachability ??= new RepoPromiseCacheMap<string, GitCommitReachability | undefined>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t\tcapacity: 25, // Limit to 25 commits per repo\n\t\t}));\n\t}\n\n\tget remotes(): PromiseMap<RepoPath, GitRemote[]> {\n\t\treturn (this._caches.remotes ??= new PromiseMap<RepoPath, GitRemote[]>());\n\t}\n\n\tget stashes(): RepoPromiseCacheMap<string, GitStash> {\n\t\treturn (this._caches.stashes ??= new RepoPromiseCacheMap<string, GitStash>({\n\t\t\taccessTTL: 1000 * 60 * 60, // 60 minutes\n\t\t}));\n\t}\n\n\tget tags(): PromiseMap<RepoPath, PagedResult<GitTag>> {\n\t\treturn (this._caches.tags ??= new PromiseMap<RepoPath, PagedResult<GitTag>>());\n\t}\n\n\tget fileExistence(): RepoPromiseCacheMap<string, boolean> {\n\t\treturn (this._caches.fileExistence ??= new RepoPromiseCacheMap<string, boolean>({\n\t\t\tcreateTTL: 1000 * 10, // 10 seconds\n\t\t\tcapacity: 100,\n\t\t\texpireOnError: true,\n\t\t}));\n\t}\n\n\t// Key: repoPath (not the ignoreRevsFile path) so that per-repo cache resets (clearCaches with repoPath)\n\t// correctly evict the entry. The actual file path is used inside the factory closure in blame.ts.\n\tget ignoreRevsFile(): PromiseCache<string, boolean> {\n\t\treturn (this._caches.ignoreRevsFile ??= new PromiseCache<string, boolean>({\n\t\t\taccessTTL: 1000 * 60 * 60 * 2, // 2 hours\n\t\t\texpireOnError: true,\n\t\t}));\n\t}\n\n\tget trackedPaths(): RepoPromiseCacheMap<string, [string, string] | false> {\n\t\treturn (this._caches.trackedPaths ??= new RepoPromiseCacheMap<string, [string, string] | false>({\n\t\t\tcreateTTL: 1000 * 60, // 60 seconds\n\t\t\taccessTTL: 1000 * 30, // 30 seconds idle\n\t\t\tcapacity: 200,\n\t\t}));\n\t}\n\n\tget worktrees(): PromiseMap<RepoPath, GitWorktree[]> {\n\t\treturn (this._caches.worktrees ??= new PromiseMap<RepoPath, GitWorktree[]>());\n\t}\n\n\t@debug({ onlyExit: true })\n\tclearCaches(repoPath: string | undefined, ...types: CachedGitTypes[]): void {\n\t\tthis.clearCachesCore('share', repoPath, types);\n\t}\n\n\t/**\n\t * Hard-evicts the same cache keys {@link clearCaches} would clear for `repoPath`, but a shared\n\t * (commonPath-keyed) entry that is still in flight is deleted outright instead of soft-invalidated —\n\t * a caller after this call never joins a read that started before it. Use for a forced read/write\n\t * that must not be answered from pre-change work; `clearCaches` remains the right call whenever\n\t * letting an in-flight read complete and share its answer with new callers is fine.\n\t */\n\tevictCaches(repoPath: string, ...types: CachedGitTypes[]): void {\n\t\tthis.clearCachesCore('evict', repoPath, types);\n\t}\n\n\t/** `worktreeOnly` leaves the shared (commonPath-keyed) entries alone (see {@link applyRepositoryChanges}) */\n\tprivate clearCachesCore(\n\t\tinFlight: 'share' | 'evict',\n\t\trepoPath: string | undefined,\n\t\ttypes: readonly CachedGitTypes[],\n\t\tworktreeOnly: boolean = false,\n\t): void {\n\t\tconst keysToClear = new Set<keyof AllCaches>();\n\n\t\tif (!types.length) {\n\t\t\t// Clear all caches\n\t\t\tfor (const key of Object.keys(this._caches)) {\n\t\t\t\tkeysToClear.add(key as keyof AllCaches);\n\t\t\t}\n\n\t\t\tinvalidateMemoized('providers');\n\t\t\tthis.incrementStatusGenerations(repoPath);\n\t\t\tif (!worktreeOnly) {\n\t\t\t\tthis.evictMergeTargetsOnCheckout(repoPath);\n\t\t\t}\n\t\t} else {\n\t\t\t// Clear specific cache types\n\t\t\tif (types.includes('blame')) {\n\t\t\t\tkeysToClear.add('blame');\n\t\t\t}\n\t\t\tif (types.includes('diff')) {\n\t\t\t\tkeysToClear.add('diff');\n\t\t\t}\n\t\t\tif (types.includes('fileLog')) {\n\t\t\t\tkeysToClear.add('fileLog');\n\t\t\t}\n\n\t\t\t// Branch caches affected by HEAD/heads changes. `branchMergedStatus` is deliberately NOT\n\t\t\t// cleared here — it's content-keyed on the involved tip shas, so tip movement already\n\t\t\t// self-invalidates (a new key); evicting it here would only discard still-valid answers.\n\t\t\tif (types.includes('branch') || types.includes('branches')) {\n\t\t\t\tkeysToClear.add('branch');\n\t\t\t\tkeysToClear.add('branchOverviews');\n\t\t\t\t// `commit`/`commitCount` are keyed by symbolic ref or SHA — symbolic-ref entries\n\t\t\t\t// can drift when branches move; cascade-clear conservatively.\n\t\t\t\tkeysToClear.add('commit');\n\t\t\t\tkeysToClear.add('commitCount');\n\t\t\t\tkeysToClear.add('conflictDetection');\n\t\t\t\tkeysToClear.add('currentBranchReference');\n\t\t\t\tkeysToClear.add('leftRightCommitCount');\n\t\t\t\t// `mergeBase` keyed by ref-pairs — symbolic refs can move; cascade-clear.\n\t\t\t\tkeysToClear.add('mergeBase');\n\t\t\t\tkeysToClear.add('reachability');\n\t\t\t\tkeysToClear.add('resolvedRevisions');\n\t\t\t}\n\n\t\t\t// Shared branch caches (branch list, metadata). `baseBranchName` is deliberately NOT cleared\n\t\t\t// here — a branch's base is set at creation and only changes when its stored key changes\n\t\t\t// (`gkConfig`/`config` below) or the branch itself is created/renamed/deleted. Every op that\n\t\t\t// does one of those calls `deleteBaseBranchName` and moves or drops the branch's persisted\n\t\t\t// `branch.<ref>.gk-*` keys: `createBranch`/`deleteLocalBranch`/`renameBranch`, plus the two\n\t\t\t// paths that create a branch as a side effect (`checkout -b`, `worktree add -b`). Tip movement\n\t\t\t// can't change a base, so clearing on every commit only forced a `git reflog` re-derivation.\n\t\t\tif (types.includes('branch')) {\n\t\t\t\t// A checkout can change includeIf.onbranch without writing any config file.\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigKey');\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigListing');\n\t\t\t\tkeysToClear.add('ignoreConfigListing');\n\t\t\t\t// `'branch'` comes from a HEAD change — a checkout — which appends `checkout: moving from X\n\t\t\t\t// to Y` to the reflog, exactly the entry `getBaseBranchName` greps for when nothing is\n\t\t\t\t// stored. A base derived as \"none\" BEFORE that entry existed is cached with no TTL, so\n\t\t\t\t// without this it stays \"none\" for the session even though the answer now exists.\n\t\t\t\t//\n\t\t\t\t// Deliberately not under `'branches'`: a tip move can't change a branch's base, so re-deriving\n\t\t\t\t// on every commit would be pure cost. Checkouts are user-driven and rare by comparison.\n\t\t\t\tkeysToClear.add('baseBranchName');\n\t\t\t}\n\n\t\t\t// Only the merge targets that found no checkout entry in HEAD's reflog: every other one is confirmed against\n\t\t\t// what it read when next asked. A checkout in a worktree this one doesn't watch arrives as `'worktreeHead'`,\n\t\t\t// which maps to the `'worktrees'` cache type\n\t\t\tif (!worktreeOnly && (types.includes('branch') || types.includes('worktrees'))) {\n\t\t\t\tthis.evictMergeTargetsOnCheckout(repoPath);\n\t\t\t}\n\n\t\t\tif (types.includes('branches')) {\n\t\t\t\tkeysToClear.add('branchMetadataMap');\n\t\t\t\tkeysToClear.add('branches');\n\t\t\t\tkeysToClear.add('sharedBranches');\n\t\t\t\tkeysToClear.add('defaultBranchName');\n\t\t\t\tkeysToClear.add('initialCommitSha');\n\t\t\t\tkeysToClear.add('logShas');\n\t\t\t\tkeysToClear.add('refs');\n\t\t\t\tkeysToClear.add('refTips');\n\t\t\t\t// No change type clears `emptyTreeSha`: a repository's object format never changes. A full reset\n\t\t\t\t// (no types) still clears it, along with everything else\n\t\t\t}\n\n\t\t\tif (types.includes('config')) {\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigKey');\n\t\t\t\tkeysToClear.add('aheadOfBaseConfigListing');\n\t\t\t\tkeysToClear.add('ignoreConfigListing');\n\t\t\t\t// `getBaseBranchName` falls back to `branch.<ref>.vscode-merge-base` (written by VS Code's\n\t\t\t\t// built-in Git), which lives in `.git/config` — so a config change is the only signal that\n\t\t\t\t// source changed. Cheap: config events are rare.\n\t\t\t\tkeysToClear.add('baseBranchName');\n\t\t\t\tkeysToClear.add('configKeys');\n\t\t\t\tkeysToClear.add('configPatterns');\n\t\t\t\tkeysToClear.add('currentBranchReference');\n\t\t\t\tkeysToClear.add('currentUser');\n\t\t\t\t// `gitDir` is immutable repo topology (toplevel/git-dir/common-dir/superproject) — a\n\t\t\t\t// `.git/config` content change never relocates it, and it's owned by the repo lifecycle\n\t\t\t\t// (registerRepoPath/unregisterRepoPath). Clearing it here forced a redundant `git rev-parse`\n\t\t\t\t// re-spawn (gitDir is read by getGkConfigPath→getGitDir on every gk op), so leave it warm.\n\t\t\t}\n\n\t\t\tif (types.includes('contributors')) {\n\t\t\t\tkeysToClear.add('branchOverviews');\n\t\t\t\tkeysToClear.add('contributors');\n\t\t\t\tkeysToClear.add('contributorsLite');\n\t\t\t\tkeysToClear.add('contributorsStats');\n\t\t\t}\n\n\t\t\tif (types.includes('gitignore')) {\n\t\t\t\tkeysToClear.add('gitIgnore');\n\t\t\t}\n\n\t\t\tif (types.includes('gkConfig')) {\n\t\t\t\tkeysToClear.add('gkConfigMap');\n\t\t\t\t// Derived from `branch.<ref>.gk-merge-base`/`vscode-merge-base`; clear so external\n\t\t\t\t// gkConfig mutations don't leave stale base-branch resolutions cached.\n\t\t\t\tkeysToClear.add('baseBranchName');\n\t\t\t\t// Cached overviews are keyed by `${ref}|${mergeTarget}`; bulk gkConfig changes can\n\t\t\t\t// affect any of the merge-target sources (stored, base, default), so clear all.\n\t\t\t\tkeysToClear.add('branchOverviews');\n\t\t\t}\n\n\t\t\tif (types.includes('lastFetched')) {\n\t\t\t\tkeysToClear.add('lastFetched');\n\t\t\t}\n\n\t\t\tif (types.includes('providers')) {\n\t\t\t\tkeysToClear.add('remotes');\n\t\t\t\tkeysToClear.add('bestRemotes');\n\t\t\t\tinvalidateMemoized('providers');\n\t\t\t}\n\n\t\t\tif (types.includes('remotes')) {\n\t\t\t\tkeysToClear.add('remotes');\n\t\t\t\tkeysToClear.add('bestRemotes');\n\t\t\t\tkeysToClear.add('defaultBranchName');\n\t\t\t}\n\n\t\t\tif (types.includes('stashes')) {\n\t\t\t\tkeysToClear.add('stashes');\n\t\t\t}\n\t\t\tif (types.includes('status')) {\n\t\t\t\tkeysToClear.add('pausedOperationStatus');\n\t\t\t\t// A caller asserting \"status changed\" (the post-op hooks in `operations.ts`, a user-initiated\n\t\t\t\t// refresh) has to advance the clock too — otherwise a `git status` still in flight from before\n\t\t\t\t// the operation can satisfy the read that follows it.\n\t\t\t\tthis.incrementStatusGenerations(repoPath);\n\t\t\t}\n\t\t\tif (types.includes('tags')) {\n\t\t\t\tkeysToClear.add('tags');\n\t\t\t\tkeysToClear.add('refs');\n\t\t\t\tkeysToClear.add('refTips');\n\t\t\t\t// `commit`/`commitCount` can be keyed by a tag name (e.g. the tag node's load-more count),\n\t\t\t\t// which re-points on a force-moved or deleted-and-recreated tag — same drift the\n\t\t\t\t// `branch`/`branches` cascade above clears for.\n\t\t\t\tkeysToClear.add('commit');\n\t\t\t\tkeysToClear.add('commitCount');\n\t\t\t\t// Same drift for a tag-named rev, and a `getLogShas` excluding tags lists different commits once a tag moves\n\t\t\t\tkeysToClear.add('logShas');\n\t\t\t\t// Keyed by the revision as given, so a tag name resolves to wherever the tag pointed when first read\n\t\t\t\tkeysToClear.add('resolvedRevisions');\n\t\t\t\t// Keyed by ref names too, so a count or fork point taken against a tag-named base would outlive its move\n\t\t\t\tkeysToClear.add('leftRightCommitCount');\n\t\t\t\tkeysToClear.add('mergeBase');\n\t\t\t}\n\n\t\t\tif (types.includes('tracking')) {\n\t\t\t\tkeysToClear.add('fileExistence');\n\t\t\t\tkeysToClear.add('trackedPaths');\n\t\t\t}\n\n\t\t\tif (types.includes('worktrees') || types.includes('worktreeList')) {\n\t\t\t\tkeysToClear.add('worktrees');\n\t\t\t}\n\n\t\t\t// Git results: cleared for any meaningful type change\n\t\t\tif (types.some(t => t !== 'gitignore' && t !== 'gkConfig' && t !== 'providers' && t !== 'worktreeList')) {\n\t\t\t\tkeysToClear.add('gitResults');\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of keysToClear) {\n\t\t\tconst cache = this._caches[key];\n\t\t\tif (cache == null) continue;\n\n\t\t\tif (repoPath == null) {\n\t\t\t\tcache.clear();\n\t\t\t} else if (key === 'aheadOfBaseConfigKey' && !worktreeOnly && (!types.length || types.includes('config'))) {\n\t\t\t\t// Config reports don't distinguish a common config write from a checkout-specific one.\n\t\t\t\tthis.evictShared(key, repoPath, 'evict');\n\t\t\t} else if (sharedCacheKeys.has(key)) {\n\t\t\t\tif (!worktreeOnly) {\n\t\t\t\t\t// A fresh config fingerprint must never be paired with a pre-change base command, nor taken from a\n\t\t\t\t\t// listing read before the change\n\t\t\t\t\tconst hardEvict =\n\t\t\t\t\t\tkey === 'aheadOfBaseConfigListing' ||\n\t\t\t\t\t\tkey === 'ignoreConfigListing' ||\n\t\t\t\t\t\t(key === 'gitResults' && (types.includes('config') || types.includes('branch')));\n\t\t\t\t\tthis.evictShared(key, repoPath, hardEvict ? 'evict' : inFlight);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcache.delete(repoPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Evicts a single shared (commonPath-keyed) cache entry for `repoPath` and its sibling worktrees.\n\t * When `inFlight` is `'share'` (the default), prefers `invalidate` where supported so in-flight work\n\t * is shared across new callers and self-evicts on settle rather than spawning a duplicate factory.\n\t * `invalidate` does the right thing per-entry: entries with a `CacheController` (created via\n\t * `getOrCreate`) are marked invalidated; entries without one (created via plain `.set()`, e.g.\n\t * per-worktree mapper results) are hard-deleted. Caches that don't support `invalidate` fall back to\n\t * `delete`.\n\t *\n\t * When `inFlight` is `'evict'`, always hard-deletes regardless of `invalidate` support — a new caller\n\t * must never join a read that started before this eviction (see {@link evictCaches}).\n\t */\n\tprivate evictShared(key: keyof AllCaches, repoPath: string, inFlight: 'share' | 'evict' = 'share'): void {\n\t\tconst cache = this._caches[key];\n\t\tif (cache == null) return;\n\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst invalidate =\n\t\t\tinFlight === 'share' ? (cache as { invalidate?: (k: string) => void }).invalidate : undefined;\n\t\tif (typeof invalidate === 'function') {\n\t\t\tinvalidate.call(cache, commonPath);\n\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\tinvalidate.call(cache, worktreePath);\n\t\t\t}\n\t\t} else {\n\t\t\tcache.delete(commonPath);\n\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\tcache.delete(worktreePath);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Monotonic per-worktree counter, advanced whenever anything that can change `git status` output is\n\t * observed. `git status` and its siblings are point-in-time reads of mutable state, so deduplicating them\n\t * on repoPath alone is unsound — a run that started before a commit would satisfy a caller that arrived\n\t * after it. Callers stamp their in-flight run with the generation it started in and refuse older joins.\n\t * Kept per exact worktree path (never spread to the common path) and advanced on `unregisterRepoPath` so a\n\t * read in flight from a prior registration can't be joined after a reopen.\n\t *\n\t * Note: a run that never settles wedges only its own generation's callers (a newer generation gets a fresh\n\t * key). `git.run` recovers via its per-command timeout (default 60s); a hung `git.stream` is caught by the\n\t * status provider's `raceWithTimeout` backstop (scaled to `advanced.git.timeout`; see\n\t * `dedupeByStatusGeneration`), which rejects a wedged read so waiters unblock and a later caller retries.\n\t */\n\tgetStatusGeneration(repoPath: string): number {\n\t\treturn this._statusGenerations.get(repoPath) ?? 0;\n\t}\n\n\t/** Advances the status clock — see {@link getStatusGeneration}. */\n\tincrementStatusGeneration(repoPath: string): void {\n\t\tthis._statusGenerations.set(repoPath, this.getStatusGeneration(repoPath) + 1);\n\t}\n\n\t/**\n\t * Working-tree changes ride their own channel (`Repository.onDidChangeWorkingTree`), not\n\t * `onRepositoryChanged` — an external `git restore <file>` may touch no `.git` path we classify — so\n\t * they have to advance the status clock separately or a discard would never invalidate an in-flight read.\n\t */\n\tonWorkingTreeChanged(repoPath: string): void {\n\t\tthis.incrementStatusGeneration(repoPath);\n\t}\n\n\t/** Advances the status clock for one worktree, or for every known worktree when `repoPath` is undefined. */\n\tprivate incrementStatusGenerations(repoPath: string | undefined): void {\n\t\tif (repoPath != null) {\n\t\t\tthis.incrementStatusGeneration(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\t// Union of registered repos and any path that already carries a generation — a secondary-worktree\n\t\t// path incremented via its own watcher may never have been registered, but still has in-flight reads to fence.\n\t\tconst paths = new Set([...this._commonPathRegistry.keys(), ...this._statusGenerations.keys()]);\n\t\tfor (const path of paths) {\n\t\t\tthis.incrementStatusGeneration(path);\n\t\t}\n\t}\n\n\tgetCommonPath(repoPath: string): string {\n\t\treturn this._commonPathRegistry.get(repoPath) ?? repoPath;\n\t}\n\n\tgetWorktreePaths(commonPath: string): string[] {\n\t\tconst worktrees = this._worktreesByCommonPath.get(commonPath);\n\t\treturn worktrees != null ? [...worktrees] : [];\n\t}\n\n\tisWorktree(repoPath: string): boolean {\n\t\tconst commonPath = this._commonPathRegistry.get(repoPath);\n\t\treturn commonPath != null && commonPath !== repoPath;\n\t}\n\n\t/** Whether `repoPath` is currently registered (via {@link registerRepoPath}, not yet unregistered). */\n\tisRegistered(repoPath: string): boolean {\n\t\treturn this._commonPathRegistry.has(repoPath);\n\t}\n\n\t/**\n\t * Monotonic per-path counter advanced whenever `repoPath` is unregistered (repo closed, worktree\n\t * removed). Lets an async post-read step — e.g. the gk-config reconcile — detect that its target was\n\t * closed (and possibly reopened) mid-flight and bail. Unlike an `isRegistered` check it doesn't\n\t * require the caller to have registered in the first place, so it stays correct for consumers of\n\t * this package that don't wire up the host's repo lifecycle.\n\t */\n\tgetCloseGeneration(repoPath: string): number {\n\t\treturn this._closeGenerations.get(repoPath) ?? 0;\n\t}\n\n\t/** Clears file-scoped caches (blame, diff, fileLog) for a specific path within a repo */\n\tclearForPath(repoPath: string, path: string, ...types: UriScopedCachedGitTypes[]): void {\n\t\tconst prefix = `${normalizePath(path)}:`;\n\t\tif (!types.length || types.includes('blame')) {\n\t\t\tthis._caches.blame?.deleteByKeyPrefix(repoPath, prefix);\n\t\t}\n\t\tif (!types.length || types.includes('diff')) {\n\t\t\tthis._caches.diff?.deleteByKeyPrefix(repoPath, prefix);\n\t\t}\n\t\tif (!types.length || types.includes('fileLog')) {\n\t\t\tthis._caches.fileLog?.deleteByKeyPrefix(repoPath, prefix);\n\t\t}\n\t}\n\n\tregisterRepoPath(repoPath: Uri, gitDir: GitDir): void {\n\t\tconst normalizedPath = getRepositoryOrWorktreePath(repoPath);\n\t\tconst commonPath = gitDir.commonUri != null ? getCommonRepositoryPath(gitDir.commonUri) : normalizedPath;\n\t\tconst previousCommonPath = this._commonPathRegistry.get(normalizedPath);\n\t\tif (previousCommonPath != null && previousCommonPath !== commonPath) {\n\t\t\tthis.unregisterRepoPath(normalizedPath);\n\t\t}\n\t\tif (previousCommonPath !== commonPath) {\n\t\t\tthis._caches.aheadOfBaseConfigKey?.delete(normalizedPath);\n\t\t\tif (normalizedPath === commonPath) {\n\t\t\t\tthis._caches.aheadOfBaseConfigListing?.delete(commonPath);\n\t\t\t\tthis._caches.ignoreConfigListing?.delete(commonPath);\n\t\t\t}\n\t\t\tthis._caches.gitResults?.delete(normalizedPath);\n\t\t}\n\t\tthis._commonPathRegistry.set(normalizedPath, commonPath);\n\n\t\tlet worktrees = this._worktreesByCommonPath.get(commonPath);\n\t\tif (worktrees == null) {\n\t\t\tworktrees = new Set();\n\t\t\tthis._worktreesByCommonPath.set(commonPath, worktrees);\n\t\t}\n\t\tworktrees.add(normalizedPath);\n\t}\n\n\t/**\n\t * Symmetric companion to `registerRepoPath`. Clears cache entries specific to `repoPath`\n\t * and removes the path from the registry.\n\t *\n\t * Call this when a worktree is deleted or a repo is closed so stale registry entries\n\t * and derived cache entries don't persist.\n\t *\n\t * Targeted — does NOT cascade to sibling worktrees sharing the same commonPath. Shared caches\n\t * stay warm until the last worktree closes, except raw git results co-located with a closing main\n\t * checkout: those must retire with its config fingerprint so reopening cannot attest an old command\n\t * with new config. Detached promises keep their existing callers and abort wiring. Other entries\n\t * use soft-invalidate where supported so any in-flight factory/mapper keeps its abort\n\t * wiring intact — a caller whose signal aborts after unregister can still propagate\n\t * cancellation into the underlying work rather than leaving it orphaned. Controller-backed\n\t * entries self-evict on settle; plain `.set()`-based entries hard-delete immediately.\n\t *\n\t * The status clock advances even for an unregistered path so a fresh registration cannot join a\n\t * status read that started before it.\n\t */\n\t@debug({ onlyExit: true })\n\tunregisterRepoPath(repoPath: string): void {\n\t\t// Advance the status clock on close so a status read still in flight from this registration can't be\n\t\t// joined by a read issued after the path is reopened (which would otherwise reuse the same generation).\n\t\tthis.incrementStatusGeneration(repoPath);\n\t\t// Advance the close clock so an async step that captured it before its read (see `getCloseGeneration`)\n\t\t// can tell its target went away mid-flight.\n\t\tthis._closeGenerations.set(repoPath, this.getCloseGeneration(repoPath) + 1);\n\n\t\tconst commonPath = this._commonPathRegistry.get(repoPath) ?? repoPath;\n\t\tconst worktrees = this._worktreesByCommonPath.get(commonPath);\n\t\t// After removing repoPath, would the commonPath have any worktrees left?\n\t\tconst isLastWorktree = worktrees == null || worktrees.size <= 1;\n\n\t\t// Targeted per-repoPath cleanup: for per-worktree caches, clear this repoPath's\n\t\t// entries. For shared caches, clear this repoPath's mapper entry (if it's a worktree\n\t\t// distinct from commonPath); only evict the shared commonPath entry when this was the\n\t\t// last worktree — otherwise siblings still rely on the shared data.\n\t\tfor (const key of Object.keys(this._caches) as (keyof AllCaches)[]) {\n\t\t\tconst cache = this._caches[key];\n\t\t\tif (cache == null) continue;\n\n\t\t\tif (key === 'aheadOfBaseConfigKey' || key === 'gitResults') {\n\t\t\t\tcache.delete(repoPath);\n\t\t\t\tif (key === 'gitResults' && isLastWorktree && repoPath !== commonPath) {\n\t\t\t\t\tcache.delete(commonPath);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// The main checkout's own listing, so it retires with that checkout as its config key does\n\t\t\tif (key === 'aheadOfBaseConfigListing' || key === 'ignoreConfigListing') {\n\t\t\t\tif (repoPath === commonPath || isLastWorktree) {\n\t\t\t\t\tcache.delete(commonPath);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Prefer `invalidate` so in-flight abort wiring survives until the factory settles;\n\t\t\t// fall back to `delete` for plain `Map`-typed caches that don't track promises.\n\t\t\tconst invalidate = (cache as { invalidate?: (k: string) => void }).invalidate;\n\t\t\tconst evict =\n\t\t\t\ttypeof invalidate === 'function'\n\t\t\t\t\t? (k: string) => invalidate.call(cache, k)\n\t\t\t\t\t: (k: string) => cache.delete(k);\n\n\t\t\tif (sharedCacheKeys.has(key)) {\n\t\t\t\tif (repoPath !== commonPath) {\n\t\t\t\t\tevict(repoPath);\n\t\t\t\t}\n\t\t\t\tif (isLastWorktree) {\n\t\t\t\t\tevict(commonPath);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tevict(repoPath);\n\t\t\t}\n\t\t}\n\n\t\t// Shared, commonPath-keyed like `gkConfigMap` — only evict once no worktree still depends on it.\n\t\tif (isLastWorktree) {\n\t\t\tthis._gkConfigSnapshots.delete(commonPath);\n\t\t\tthis._mergeTargetsEvictedOnCheckout.delete(commonPath);\n\t\t}\n\n\t\tthis._commonPathRegistry.delete(repoPath);\n\n\t\tif (worktrees != null) {\n\t\t\tworktrees.delete(repoPath);\n\t\t\tif (worktrees.size === 0) {\n\t\t\t\tthis._worktreesByCommonPath.delete(commonPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug({ onlyExit: true })\n\treset(): void {\n\t\t// Advance the close clock BEFORE dropping the registry it reads from. Advancing rather than\n\t\t// clearing is the point: an async step that captured a generation must see a mismatch and bail,\n\t\t// where a cleared map would hand it a fresh `0` that matches and let it repopulate what was just\n\t\t// torn down. Union of registered paths and any already carrying a generation, mirroring\n\t\t// `incrementStatusGenerations`.\n\t\tfor (const path of new Set([...this._commonPathRegistry.keys(), ...this._closeGenerations.keys()])) {\n\t\t\tthis._closeGenerations.set(path, this.getCloseGeneration(path) + 1);\n\t\t}\n\n\t\tthis._commonPathRegistry.clear();\n\t\tthis._worktreesByCommonPath.clear();\n\t\tthis._statusGenerations.clear();\n\t\tthis._gkConfigSnapshots.clear();\n\t\tthis._mergeTargetsEvictedOnCheckout.clear();\n\t\tthis._gkConfigReconciler = undefined;\n\t\tthis._caches = createEmptyCaches();\n\t}\n\n\t/** Applies a watcher-observed change, sharing reads still in flight (see {@link applyRepositoryChanges}). */\n\t@debug({ onlyExit: true })\n\tonRepositoryChanged(repoPath: string, changes: Iterable<RepositoryChange>): void {\n\t\tconst changesSet = new Set(changes);\n\t\tif (changesSet.has('unknown') || changesSet.has('closed')) {\n\t\t\tthis.unregisterRepoPath(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.applyRepositoryChanges(repoPath, changesSet, 'share');\n\t}\n\n\t/**\n\t * Clears what `changes` can have made stale for `repoPath`, advances its status clock, and reconciles a\n\t * `'gkConfig'` change, returning the cache types it cleared. `inFlight` is as {@link clearCaches}\n\t * (`'share'`) vs {@link evictCaches} (`'evict'`). `'unknown'` and `'closed'` map to nothing here: the\n\t * watcher unregisters the path on them, and an announced write resets everything instead.\n\t *\n\t * `options.worktreeOnly` clears only `repoPath`'s own entries and status clock, leaving the shared\n\t * (commonPath-keyed) ones alone — for a sibling worktree once the change was applied to the worktree it ran in,\n\t * which already cleared them for every worktree of the repository.\n\t */\n\t@debug({ onlyExit: true })\n\tapplyRepositoryChanges(\n\t\trepoPath: string,\n\t\tchanges: Iterable<RepositoryChange>,\n\t\tinFlight: 'share' | 'evict',\n\t\toptions?: { worktreeOnly?: boolean },\n\t): CachedGitTypes[] {\n\t\tconst worktreeOnly = options?.worktreeOnly ?? false;\n\t\tconst changesSet = new Set(changes);\n\n\t\tconst hasAny = (...c: RepositoryChange[]) => c.some(ch => changesSet.has(ch));\n\n\t\t// Advance the status clock (see {@link getStatusGeneration}) for changes that alter `git status` output but\n\t\t// aren't mapped to the `'status'` cache type below: files (index/head/heads), untracked set (ignores/config),\n\t\t// ahead/behind (remotes). Paused-op changes advance it too, but via `clearCaches('status')` (see below) —\n\t\t// listing them here as well would double-increment the clock for a single change.\n\t\tif (hasAny('index', 'head', 'heads', 'remotes', 'ignores', 'config')) {\n\t\t\tthis.incrementStatusGeneration(repoPath);\n\t\t}\n\n\t\tconst types = new Set<CachedGitTypes>();\n\n\t\tif (hasAny('head')) {\n\t\t\ttypes.add('branch');\n\t\t}\n\n\t\t// A detached HEAD that moved (a commit or reset without a branch) comes as `head` without `heads`, and changes\n\t\t// what this tree compares against and the HEAD the branch and worktree lists show\n\t\tif (hasAny('index', 'head', 'heads', 'pausedOp')) {\n\t\t\ttypes.add('blame');\n\t\t\ttypes.add('diff');\n\t\t\ttypes.add('fileLog');\n\t\t}\n\n\t\tif (hasAny('index')) {\n\t\t\ttypes.add('tracking');\n\t\t}\n\n\t\tif (hasAny('config')) {\n\t\t\ttypes.add('config');\n\t\t\t// A branch's upstream lives in its `.git/config` section, and the branch list (and each worktree's branch)\n\t\t\t// carries it; a config change confined to branches' sections comes without the `remotes` that clears them\n\t\t\ttypes.add('branches');\n\t\t\ttypes.add('worktrees');\n\t\t}\n\n\t\tif (hasAny('head', 'heads')) {\n\t\t\ttypes.add('branches');\n\t\t\ttypes.add('contributors');\n\t\t\ttypes.add('worktrees');\n\t\t}\n\n\t\tif (hasAny('remotes')) {\n\t\t\ttypes.add('branches');\n\t\t\ttypes.add('contributors');\n\t\t\ttypes.add('remotes');\n\t\t\ttypes.add('worktrees');\n\t\t}\n\n\t\tif (hasAny('ignores')) {\n\t\t\ttypes.add('gitignore');\n\t\t}\n\n\t\tif (hasAny('gkConfig') && !worktreeOnly) {\n\t\t\t// Handled separately (not folded into `types`/`clearCaches` below) — a gk write is usually a\n\t\t\t// bookkeeping timestamp that can't affect `baseBranchName`/`branchOverviews`, so this reconciles\n\t\t\t// down to only the keys that actually changed instead of coarsely clearing both on every write.\n\t\t\tthis.handleGkConfigChanged(repoPath);\n\t\t}\n\n\t\tif (hasAny('lastFetched')) {\n\t\t\ttypes.add('lastFetched');\n\t\t}\n\n\t\tif (hasAny('remoteProviders')) {\n\t\t\ttypes.add('providers');\n\t\t}\n\n\t\tif (hasAny('cherryPick', 'merge', 'rebase', 'revert', 'pausedOp')) {\n\t\t\ttypes.add('branch');\n\t\t\ttypes.add('status');\n\t\t}\n\n\t\tif (hasAny('stash')) {\n\t\t\ttypes.add('stashes');\n\t\t}\n\n\t\tif (hasAny('tags')) {\n\t\t\ttypes.add('tags');\n\t\t}\n\n\t\t// A worktree's HEAD moving changes what git answers there, which any worktree's reads can ask about; an entry\n\t\t// added, removed, locked, unlocked or moved changes only the list\n\t\tif (hasAny('worktreeHead')) {\n\t\t\ttypes.add('worktrees');\n\t\t} else if (hasAny('worktrees')) {\n\t\t\ttypes.add('worktreeList');\n\t\t}\n\n\t\tif (types.size) {\n\t\t\tthis.clearCachesCore(inFlight, repoPath, [...types], worktreeOnly);\n\t\t}\n\t\treturn [...types];\n\t}\n\n\t/**\n\t * Handles a watcher-observed `'gkConfig'` change. If a reconciler is registered (see {@link setGkConfigReconciler}),\n\t * defers to it instead of coarsely clearing `baseBranchName`/`branchOverviews` — it evicts the cached bulk map\n\t * unless the file is unchanged since the map was read, reads it, and diffs it against the snapshot captured here\n\t * (i.e. as it stood right before this change), cascading only the refs whose merge-relevant keys actually\n\t * changed. Falls back to evicting the map and the coarse clear when no reconciler is registered (e.g. the GitHub\n\t * provider) so nothing can go stale.\n\t */\n\tprivate handleGkConfigChanged(repoPath: string): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\tif (this._gkConfigReconciler == null) {\n\t\t\t// Hard-delete rather than `evictShared`'s soft-invalidate: a soft-invalidated entry stays joinable, so a\n\t\t\t// read after this change could ride a bulk read that started before it.\n\t\t\t// Same reasoning as `refs.ts`'s `force: true` path and `deleteGkConfig`'s own hard delete.\n\t\t\tthis._caches.gkConfigMap?.delete(commonPath);\n\t\t\tthis.clearGkConfigCoarsely(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tconst priorSnapshot = this._gkConfigSnapshots.get(commonPath);\n\t\t// Fire-and-forget, but the outcome still decides whether the coarse clear is owed: a reconcile that\n\t\t// FAILED leaves every derived cache holding pre-change values with nothing else to correct them, so\n\t\t// it falls back to the blunt behavior that registering a reconciler replaced. Kept here rather than\n\t\t// in the reconciler so a bail path added later can't silently skip it — the return type makes each\n\t\t// one say what it did.\n\t\tlet outcome: PromiseOrValue<GkReconcileOutcome>;\n\t\ttry {\n\t\t\toutcome = this._gkConfigReconciler(repoPath, priorSnapshot);\n\t\t} catch {\n\t\t\t// Thrown before it could decide about the map, which it owns from the call on (see\n\t\t\t// `setGkConfigReconciler`), so drop it as the coarse path does\n\t\t\tthis._caches.gkConfigMap?.delete(commonPath);\n\t\t\tthis.clearGkConfigCoarsely(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tvoid Promise.resolve(outcome).then(\n\t\t\toutcome => {\n\t\t\t\tif (outcome === 'failed') {\n\t\t\t\t\tthis.clearGkConfigCoarsely(repoPath);\n\t\t\t\t}\n\t\t\t},\n\t\t\t// An exception escaping the reconciler is a failure by definition — and one its own `catch`\n\t\t\t// never saw, so nothing else will have cascaded.\n\t\t\t() => this.clearGkConfigCoarsely(repoPath),\n\t\t);\n\t}\n\n\t/**\n\t * The coarse fallback: every derived merge cache and the branches are cleared, so any branch's merge targets or\n\t * metadata may have changed. Evicting the branches even when only merge keys changed is the price of not knowing.\n\t */\n\tprivate clearGkConfigCoarsely(repoPath: string): void {\n\t\tthis.clearCaches(repoPath, 'gkConfig');\n\t\tthis.deleteBranchMetadata(repoPath);\n\t\tthis._onDidChangeMergeTargets.fire({ repoPath: this.getCommonPath(repoPath), refs: undefined });\n\t}\n\n\t/** Hard-evicts the cached bulk `.git/gk/config` map so the next read hits disk. */\n\tdeleteGkConfigMap(repoPath: string): void {\n\t\tthis._caches.gkConfigMap?.delete(this.getCommonPath(repoPath));\n\t}\n\n\t/**\n\t * Whether a write of `key` must first read the gk config to seed the reconcile snapshot: without one,\n\t * {@link recordGkConfigWrite} can't tell whether the write changed anything, and the watcher's reconcile of it\n\t * would report every branch as changed.\n\t */\n\tneedsGkConfigSnapshot(repoPath: string, key: string): boolean {\n\t\treturn getReconciledGkConfigRef(key) != null && !this._gkConfigSnapshots.has(this.getCommonPath(repoPath));\n\t}\n\n\t/** The gk config snapshot currently serving as the reconcile baseline. */\n\tgetGkConfigSnapshot(repoPath: string): ReadonlyMap<string, string> | undefined {\n\t\treturn this._gkConfigSnapshots.get(this.getCommonPath(repoPath));\n\t}\n\n\tgetBranches(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<PagedResult<GitBranch>>,\n\t\tmapper: (\n\t\t\tbranches: PagedResult<GitBranch>,\n\t\t\ttargetRepoPath: string,\n\t\t\tcommonPath: string,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<PagedResult<GitBranch>>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<PagedResult<GitBranch>> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\t// Register this caller with the shared factory's aggregate so that invariant 3\n\t\t// (factory aborts iff every waiter has aborted) holds for same-`repoPath` cache hits too.\n\t\t// The returned wrapped promise is deliberately discarded — we use the raw cached inner\n\t\t// below to build the mapped entry. Swallow any rejection on this dangling reference so\n\t\t// it doesn't surface as an unhandled rejection; the real caller-facing promise (via\n\t\t// `branches.getOrCreate` below) is where caller cancellation flows to.\n\t\tconst registration = this.sharedBranches.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => {\n\t\t\t\tconst p = Promise.resolve(factory(commonPath, cacheable, signal));\n\t\t\t\t// On factory invalidation, propagate to the derived per-worktree mapper entries\n\t\t\t\t// via soft-invalidate — existing waiters on the mapper complete, and the entry\n\t\t\t\t// self-evicts on mapper settle so the next callers build fresh derived entries.\n\t\t\t\tvoid p\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tif (cacheable.invalidated) {\n\t\t\t\t\t\t\tthis.branches.invalidate(commonPath);\n\t\t\t\t\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\t\t\t\t\tthis.branches.invalidate(worktreePath);\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\t// Swallow the cleanup chain's rejection so a rejected factory (e.g. cancellation)\n\t\t\t\t\t// doesn't surface as an unhandled rejection; the caller-facing promise handles it.\n\t\t\t\t\t.catch(() => {});\n\t\t\t\treturn p;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\tvoid registration.catch(() => {});\n\n\t\t// Build the per-`repoPath` mapped entry through `getOrCreate` so mapper internal git\n\t\t// work (e.g. `getCurrentBranchReferenceCore`) runs under a mapper-level aggregate signal\n\t\t// separate from the factory's. Subsequent same-`repoPath` cache hits register with this\n\t\t// aggregate too — invariant 2/3 hold at the mapper level.\n\t\treturn this.branches.getOrCreate(\n\t\t\trepoPath,\n\t\t\t(_cacheable, mapperSignal) => {\n\t\t\t\t// After `getOrCreate` above, `sharedBranches[commonPath]` holds the raw inner\n\t\t\t\t// factory promise. Fall back to `registration` in the paranoid case where a\n\t\t\t\t// synchronously-rejected factory got auto-evicted before we retrieve it.\n\t\t\t\tconst rawShared = this.sharedBranches.get(commonPath) ?? registration;\n\t\t\t\treturn Promise.resolve(rawShared).then(shared => mapper(shared, repoPath, commonPath, mapperSignal));\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate static readonly globalConfigKey = '';\n\n\t/**\n\t * Keyed by `repoPath` itself, not its common path: git reads a worktree's own `config.worktree` too, so worktrees\n\t * of one repository can see different values. A read that is the same for all of them runs from, and passes, the\n\t * common path. The same holds for {@link getConfigRegex}.\n\t */\n\tgetConfig(\n\t\trepoPath: string | undefined,\n\t\tkey: string,\n\t\tfactory: () => PromiseOrValue<string | undefined>,\n\t): Promise<string | undefined> {\n\t\tconst cacheKey = repoPath ?? Cache.globalConfigKey;\n\n\t\tconst result = this.configKeys.get(cacheKey, key);\n\t\tif (result != null) return result;\n\n\t\tconst factoryPromise = Promise.resolve(factory());\n\t\tthis.configKeys.set(cacheKey, key, factoryPromise);\n\t\treturn factoryPromise;\n\t}\n\n\t/** Keyed by `repoPath` itself, as {@link getConfig} is */\n\tgetConfigRegex(\n\t\trepoPath: string | undefined,\n\t\tpattern: string,\n\t\tfactory: () => PromiseOrValue<Map<string, string>>,\n\t): Promise<Map<string, string>> {\n\t\tconst cacheKey = repoPath ?? Cache.globalConfigKey;\n\n\t\tconst result = this.configPatterns.get(cacheKey, pattern);\n\t\tif (result != null) return result;\n\n\t\tconst factoryPromise = Promise.resolve(factory());\n\t\tthis.configPatterns.set(cacheKey, pattern, factoryPromise);\n\t\treturn factoryPromise;\n\t}\n\n\tdeleteConfig(repoPath: string | undefined, key: string): void {\n\t\tif (repoPath == null) {\n\t\t\tthis._caches.configKeys?.delete(Cache.globalConfigKey, key);\n\t\t\tthis._caches.configPatterns?.delete(Cache.globalConfigKey);\n\t\t\treturn;\n\t\t}\n\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tfor (const path of new Set([commonPath, repoPath, ...this.getWorktreePaths(commonPath)])) {\n\t\t\tthis._caches.configKeys?.delete(path, key);\n\t\t\tthis._caches.configPatterns?.delete(path);\n\t\t}\n\t}\n\n\t/**\n\t * The whole `.git/gk/config` is read once and cached as a single map per commonPath; per-key and\n\t * per-namespace gk lookups are served from it in-memory (see `getGkConfigMap` in the CLI config\n\t * sub-provider). Invalidated by `deleteGkConfig` (write) and, on a watcher `'gkConfig'` event, by the\n\t * reconciler when the file changed since the map was read (see {@link setGkConfigReconciler}), or by\n\t * `handleGkConfigChanged`'s coarse clear when none is registered. The first fresh read seeds the snapshot used by\n\t * `reconcileGkConfigMap`; later refreshes of that snapshot are owned by the reconcile itself.\n\t */\n\tgetGkConfigMap(\n\t\trepoPath: string,\n\t\tfactory: (cacheable: CacheController) => PromiseOrValue<Map<string, string>>,\n\t): Promise<Map<string, string>> {\n\t\treturn this.getSharedSimple(this.gkConfigMap, repoPath, async (commonPath, cacheable) => {\n\t\t\tconst map = await factory(cacheable);\n\t\t\t// Seed the reconcile baseline on first observation only. Refreshes belong to\n\t\t\t// `reconcileGkConfigMap` (after it has cascaded) and `recordGkConfigWrite` (our own writes):\n\t\t\t// an incidental read that happens to land between an external write and the watcher event\n\t\t\t// would otherwise advance the baseline to the post-change value, so the reconcile would diff\n\t\t\t// that value against itself and silently drop the change.\n\t\t\tif (!this._gkConfigSnapshots.has(commonPath)) {\n\t\t\t\tthis._gkConfigSnapshots.set(commonPath, this.extractReconciledGkConfig(map));\n\t\t\t}\n\t\t\treturn map;\n\t\t});\n\t}\n\n\t/** Extracts the subset of a gk config map that the reconcile baseline tracks (see {@link _gkConfigSnapshots}). */\n\tprivate extractReconciledGkConfig(map: ReadonlyMap<string, string>): Map<string, string> {\n\t\tconst subset = new Map<string, string>();\n\t\tfor (const [key, value] of map) {\n\t\t\tif (getReconciledGkConfigRef(key) != null) {\n\t\t\t\tsubset.set(key, value);\n\t\t\t}\n\t\t}\n\t\treturn subset;\n\t}\n\n\t/**\n\t * Clears the cached `.git/gk/config` map and invalidates the derived caches\n\t * (`baseBranchName`/`branchOverviews`) for the written key's ref.\n\t *\n\t * @param options.skipInvalidation Downstream caches the caller wants preserved despite this\n\t * write. Use when the value being written is exactly what was just resolved — e.g. the pull request's\n\t * `storeMergeTargetBranchName` self-write inside `getMergeTarget` (skip `'branchOverviews'`) or the\n\t * `vscode-merge-base` migration's `storeBaseBranchName` self-write (skip both `'baseBranchName'` and\n\t * `'branchOverviews'`). The bulk `gkConfigMap` map always\n\t * invalidates so subsequent reads see the new value.\n\t */\n\tdeleteGkConfig(\n\t\trepoPath: string,\n\t\tkey: string,\n\t\toptions?: { skipInvalidation?: readonly GkConfigInvalidationTarget[] },\n\t): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tthis._caches.gkConfigMap?.delete(commonPath);\n\t\tthis.cascadeGkConfigKeyChange(commonPath, key, options?.skipInvalidation);\n\t}\n\n\t/**\n\t * Keeps the gk config snapshot in sync with OUR OWN writes, so the next watcher-triggered\n\t * `reconcileGkConfigMap` diffs a self-write as unchanged rather than as an external change (which would\n\t * otherwise defeat `skipInvalidation`, or evict the branches a second time after a branch-activity stamp),\n\t * and fires {@link onDidChangeMergeTargets} naming the key's branch when a merge-relevant value differs from\n\t * the snapshot's, unless `announce` is `false` (an internal save while answering a read, which nobody awaits;\n\t * only another process's watcher reports it). No-ops for keys the snapshot doesn't track, and if no snapshot exists yet for this repo\n\t * (the writer seeds one first; see {@link needsGkConfigSnapshot}).\n\t */\n\trecordGkConfigWrite(\n\t\trepoPath: string,\n\t\tkey: string,\n\t\tvalue: string | undefined,\n\t\toptions?: { announce?: boolean },\n\t): void {\n\t\tconst ref = getReconciledGkConfigRef(key);\n\t\tif (ref == null) return;\n\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst snapshot = this._gkConfigSnapshots.get(commonPath);\n\t\tif (snapshot == null || snapshot.get(key) === value) return;\n\n\t\t// Copy-on-write: a reconcile in flight is holding this map as its `priorSnapshot` baseline, so\n\t\t// mutating it in place would silently move that baseline mid-diff.\n\t\tconst next = new Map(snapshot);\n\t\tif (value == null) {\n\t\t\tnext.delete(key);\n\t\t} else {\n\t\t\tnext.set(key, value);\n\t\t}\n\t\tthis._gkConfigSnapshots.set(commonPath, next);\n\n\t\tif (options?.announce === false || !branchOverviewGkConfigKeysRegex.test(key)) return;\n\n\t\tthis._onDidChangeMergeTargets.fire({ repoPath: commonPath, refs: new Set([ref]) });\n\t}\n\n\t/**\n\t * {@link recordGkConfigWrite} for a whole `branch.<ref>` section: our own `--remove-section` (a branch delete) or\n\t * `--rename-section` (a branch rename, to `renamedTo`), so the reconcile that follows doesn't report it as an\n\t * external merge-target or metadata change — the branch op's own ref change already evicts the branches.\n\t */\n\trecordGkConfigSectionWrite(repoPath: string, ref: string, renamedTo?: string): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst snapshot = this._gkConfigSnapshots.get(commonPath);\n\t\tif (snapshot == null) return;\n\n\t\tconst prefixLength = `branch.${ref}.`.length;\n\t\t// Copy-on-write, as in `recordGkConfigWrite`\n\t\tconst next = new Map<string, string>();\n\t\tfor (const [key, value] of snapshot) {\n\t\t\t// Matched on the captured ref, not a `branch.<ref>.` prefix, which would also take a dotted sibling\n\t\t\t// (`branch.feature.x.*` for `feature`) that `--remove-section`/`--rename-section` leaves in place\n\t\t\tif (getReconciledGkConfigRef(key) !== ref) {\n\t\t\t\tnext.set(key, value);\n\t\t\t} else if (renamedTo != null) {\n\t\t\t\tnext.set(`branch.${renamedTo}.${key.substring(prefixLength)}`, value);\n\t\t\t}\n\t\t}\n\t\tthis._gkConfigSnapshots.set(commonPath, next);\n\t}\n\n\t/**\n\t * Registers the reconciler invoked by {@link handleGkConfigChanged} on a watcher-observed\n\t * `'gkConfig'` change. Only one reconciler is kept — later registrations replace earlier ones,\n\t * which is harmless since every CLI config sub-provider sharing this `Cache` reconciles the same\n\t * underlying `.git/gk/config` file identically.\n\t *\n\t * The reconciler owns the cached bulk map: it is called synchronously as the change is reported, and must\n\t * hard-delete the map ({@link deleteGkConfigMap}) before it returns unless it knows the map still reflects the\n\t * file — a read after the change must see it, and the reconcile's own read must not ride a bulk read that\n\t * started before it. Only the reconciler can inspect the file, and keeping the map spares a re-read for every\n\t * report of an unchanged file (one per worktree sharing it, and one for each of core's own writes).\n\t */\n\tsetGkConfigReconciler(\n\t\treconciler: (\n\t\t\trepoPath: string,\n\t\t\tpriorSnapshot: ReadonlyMap<string, string> | undefined,\n\t\t) => PromiseOrValue<GkReconcileOutcome>,\n\t): void {\n\t\tthis._gkConfigReconciler = reconciler;\n\t}\n\n\t/**\n\t * Diffs the tracked subset of a gk config map (read after the change, or kept as still reflecting the file)\n\t * against `priorSnapshot` (captured by `handleGkConfigChanged` before the reconcile started, so it reflects the\n\t * pre-change state), cascading\n\t * `baseBranchName`/`branchOverviews` for every ref whose merge-relevant key actually changed, then firing\n\t * {@link onDidChangeMergeTargets} naming those refs. Changed branch metadata keys (another process's\n\t * activity stamps or disposition) are patched into the cached branches in one call, and never fire the event.\n\t * A key core itself wrote since `priorSnapshot` was captured (recorded in the live snapshot) is neither diffed nor\n\t * overwritten by this read, which may predate the write: its writer already cascaded and announced it.\n\t * `priorSnapshot` of `undefined` (never observed before this reconcile) is treated as \"everything\n\t * may have changed\" — a full coarse clear, same as the pre-existing watcher behavior. Returns\n\t * whether anything changed (i.e. whether a follow-up repository-changed event is warranted).\n\t */\n\treconcileGkConfigMap(\n\t\trepoPath: string,\n\t\tpriorSnapshot: ReadonlyMap<string, string> | undefined,\n\t\tfreshMap: ReadonlyMap<string, string>,\n\t): boolean {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst newSubset = this.extractReconciledGkConfig(freshMap);\n\n\t\tif (priorSnapshot == null) {\n\t\t\tthis._gkConfigSnapshots.set(commonPath, newSubset);\n\t\t\tthis.evictShared('baseBranchName', repoPath);\n\t\t\tthis.evictShared('branchOverviews', repoPath);\n\t\t\tthis.deleteBranchMetadata(repoPath);\n\t\t\tthis._onDidChangeMergeTargets.fire({ repoPath: commonPath, refs: undefined });\n\t\t\treturn true;\n\t\t}\n\n\t\t// Only core's own writes move the live snapshot off `priorSnapshot` before this point\n\t\tconst ownWrites = new Set<string>();\n\t\tconst live = this._gkConfigSnapshots.get(commonPath);\n\t\tif (live != null && live !== priorSnapshot) {\n\t\t\tfor (const key of new Set([...priorSnapshot.keys(), ...live.keys()])) {\n\t\t\t\tconst value = live.get(key);\n\t\t\t\tif (priorSnapshot.get(key) === value) continue;\n\n\t\t\t\townWrites.add(key);\n\t\t\t\tif (value == null) {\n\t\t\t\t\tnewSubset.delete(key);\n\t\t\t\t} else {\n\t\t\t\t\tnewSubset.set(key, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._gkConfigSnapshots.set(commonPath, newSubset);\n\n\t\tlet refs: Set<string> | undefined;\n\t\tconst metadataChanges: BranchMetadataChange[] = [];\n\t\tfor (const key of new Set([...priorSnapshot.keys(), ...newSubset.keys()])) {\n\t\t\tif (ownWrites.has(key)) continue;\n\n\t\t\tconst value = newSubset.get(key);\n\t\t\tif (priorSnapshot.get(key) === value) continue;\n\n\t\t\tconst ref = branchOverviewGkConfigKeysRegex.exec(key)?.[1];\n\t\t\tif (ref != null) {\n\t\t\t\tthis.cascadeGkConfigKeyChange(commonPath, key);\n\t\t\t\t(refs ??= new Set()).add(ref);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst metadataKey = parseBranchMetadataGkConfigKey(key);\n\t\t\tif (metadataKey != null) {\n\t\t\t\tmetadataChanges.push({ branch: metadataKey.branch, key: metadataKey.key, value: value });\n\t\t\t}\n\t\t}\n\n\t\tconst metadataChanged = metadataChanges.length > 0;\n\t\tif (metadataChanged) {\n\t\t\tthis.patchBranchMetadata(repoPath, metadataChanges);\n\t\t}\n\n\t\tif (refs == null) return metadataChanged;\n\n\t\tthis._onDidChangeMergeTargets.fire({ repoPath: commonPath, refs: refs });\n\t\treturn true;\n\t}\n\n\t/**\n\t * Shared per-ref cascade for a changed `branch.<ref>.gk-...` key: invalidates `baseBranchName` (for\n\t * `gk-merge-base`) and `branchOverviews` (for any merge-relevant key), honoring `skipInvalidation`.\n\t * Used by both a direct write (`deleteGkConfig`) and a reconciled external change\n\t * (`reconcileGkConfigMap`). No-ops for keys outside the merge-relevant subset.\n\t */\n\tprivate cascadeGkConfigKeyChange(\n\t\tcommonPath: string,\n\t\tkey: string,\n\t\tskip?: readonly GkConfigInvalidationTarget[],\n\t): void {\n\t\tconst refMatch = key.match(branchOverviewGkConfigKeysRegex);\n\t\tif (refMatch == null) return;\n\n\t\tconst ref = refMatch[1];\n\n\t\t// `getBaseBranchName` reads `branch.<ref>.gk-merge-base` and caches the resolved value\n\t\t// per-ref. A change to that key must invalidate the cached base or it keeps answering the pre-change value.\n\t\tif (key.endsWith('.gk-merge-base') && !skip?.includes('baseBranchName')) {\n\t\t\tthis._caches.baseBranchName?.delete(commonPath, ref);\n\t\t}\n\n\t\tif (skip?.includes('branchOverviews')) return;\n\n\t\t// When the change affects a branch's merge-target/base lineage, invalidate that branch's\n\t\t// cached overviews so subsequent reads pick up the new stored value rather than stale data.\n\t\t// `getBranchContributionsOverview` keys `branchOverviews` by `${ref}|${mergeTarget}`, so\n\t\t// invalidate every entry for the affected ref regardless of which target it resolved to.\n\t\t// Uses `invalidateByKeyPrefix` (not `deleteByKeyPrefix`) so an in-flight factory is still\n\t\t// shared with new callers instead of triggering a duplicate fetch.\n\t\t//\n\t\t// Sibling worktrees get their own bucket, not just the shared one: `getSharedOrCreateWithKey`\n\t\t// stores a per-worktree *mapped* entry under that worktree's own path, and prefix-invalidation\n\t\t// only reaches one bucket. The in-flight case self-propagates on settle, but an already-settled\n\t\t// overview would otherwise survive here — which the coarse `evictShared` path this replaced did\n\t\t// clear, since it iterated the worktrees.\n\t\tthis._caches.branchOverviews?.invalidateByKeyPrefix(commonPath, `${ref}|`);\n\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\tthis._caches.branchOverviews?.invalidateByKeyPrefix(worktreePath, `${ref}|`);\n\t\t}\n\t}\n\n\tasync getBranchOverview(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<BranchContributionsOverview | undefined>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<BranchContributionsOverview | undefined> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.branchOverviews,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) =>\n\t\t\t\tdata == null\n\t\t\t\t\t? data\n\t\t\t\t\t: {\n\t\t\t\t\t\t\t...data,\n\t\t\t\t\t\t\trepoPath: newRepoPath,\n\t\t\t\t\t\t\tcontributors: data.contributors.map(c => c.withRepoPath(newRepoPath)),\n\t\t\t\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync getContributors(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitContributorsResult>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitContributorsResult> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.contributors,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => ({\n\t\t\t\t...data,\n\t\t\t\tcontributors: data.contributors.map(c => c.withRepoPath(newRepoPath)),\n\t\t\t}),\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync getContributorsLite(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitContributor[]>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitContributor[]> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.contributorsLite,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => data.map(c => c.withRepoPath(newRepoPath)),\n\t\t\toptions,\n\t\t);\n\t}\n\n\tgetContributorsStats(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitContributorsStats | undefined>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitContributorsStats | undefined> {\n\t\treturn this.getSharedSimpleWithKey(this.contributorsStats, repoPath, cacheKey, factory, options);\n\t}\n\n\tgetBaseBranchName(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimpleWithKey(this.baseBranchName, repoPath, ref, factory, {\n\t\t\t// A bounded ceiling, because the eviction signals can't cover every way a base changes. The\n\t\t\t// `'branches'` cascade deliberately doesn't clear this — a tip move can't change a base, and\n\t\t\t// re-deriving per commit is the cost this exists to avoid — but that leaves a hole: a branch\n\t\t\t// deleted and recreated OUTSIDE GitLens, and never checked out, emits only `heads`. A base\n\t\t\t// derived as \"none\" before that would otherwise stay \"none\" for the session.\n\t\t\t//\n\t\t\t// `createTTL`, NOT `accessTTL`: the sliding variant resets on every read, so a branch card\n\t\t\t// polling this entry would hold it alive forever and never re-derive — the exact case the\n\t\t\t// ceiling exists for. Absolute from creation bounds staleness regardless of read frequency.\n\t\t\tcreateTTL: baseBranchNameTTL,\n\t\t\tcancellation: cancellation,\n\t\t});\n\t}\n\n\t/**\n\t * Clears the cached base branch for `ref`. Call from ops that create/rename/delete a branch — the\n\t * `'branches'` cascade no longer clears these, since tip movement can't change a branch's base.\n\t *\n\t * Only clears the cache. A branch's base is *persisted* as `branch.<ref>.gk-merge-base` and read back\n\t * before the reflog fallback, so an op that ends a branch's identity under a name must drop or move\n\t * that key too (`removeGkConfigBranchSection`/`renameGkConfigBranchSection`) — otherwise the\n\t * re-derivation this triggers just reads the stale value straight back.\n\t */\n\tdeleteBaseBranchName(repoPath: string, ref: string): void {\n\t\tthis._caches.baseBranchName?.delete(this.getCommonPath(repoPath), ref);\n\t}\n\n\t/**\n\t * Applies changed branch metadata keys (written here or reconciled from another process) to the cached branches\n\t * without re-reading them, by updating {@link BranchMetadata} objects in place — the one exception to cached values\n\t * never changing, since rebuilding every branch list, current branch and worktree list on every activity stamp\n\t * costs far more. Patches every object a cached branch of the repository's worktrees holds for a changed branch:\n\t * the cached map's, and any older map's that a cached branch list, current branch or worktree list still holds.\n\t *\n\t * Falls back to {@link deleteBranchMetadata} when one of them is still being read (it may have read the file\n\t * before the change), or the cached map or a cached branch of a changed name has no object to patch.\n\t */\n\tpatchBranchMetadata(repoPath: string, changes: readonly BranchMetadataChange[]): void {\n\t\tconst targets = new Map<string, Set<BranchMetadata>>();\n\t\tfor (const change of changes) {\n\t\t\ttargets.set(change.branch, new Set());\n\t\t}\n\n\t\tif (!this.collectBranchMetadata(this.getCommonPath(repoPath), targets)) {\n\t\t\tthis.deleteBranchMetadata(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const change of changes) {\n\t\t\tfor (const metadata of targets.get(change.branch)!) {\n\t\t\t\tsetBranchMetadataValue(metadata, change.key, change.value);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Adds to `targets` every metadata object a cached holder has for each named branch (see\n\t * {@link patchBranchMetadata}); `false` when the holders must be evicted instead.\n\t */\n\tprivate collectBranchMetadata(commonPath: string, targets: Map<string, Set<BranchMetadata>>): boolean {\n\t\tconst metadataMap = getSettledOrPending(this._caches.branchMetadataMap, commonPath);\n\t\tif (metadataMap === 'pending') return false;\n\n\t\tif (metadataMap != null) {\n\t\t\tfor (const [name, objects] of targets) {\n\t\t\t\tconst metadata = metadataMap.value.get(name);\n\t\t\t\t// The branch's first metadata: the cached branches built from this map hold none\n\t\t\t\tif (metadata == null) return false;\n\n\t\t\t\tobjects.add(metadata);\n\t\t\t}\n\t\t}\n\n\t\tconst add = (branch: GitBranch | undefined): boolean => {\n\t\t\tif (branch == null || branch.remote || branch.detached) return true;\n\n\t\t\tconst objects = targets.get(branch.name);\n\t\t\tif (objects == null) return true;\n\t\t\tif (branch.metadata == null) return false;\n\n\t\t\tobjects.add(branch.metadata);\n\t\t\treturn true;\n\t\t};\n\n\t\tfor (const path of new Set([commonPath, ...this.getWorktreePaths(commonPath)])) {\n\t\t\tfor (const cache of [this._caches.sharedBranches, this._caches.branches]) {\n\t\t\t\tconst branches = getSettledOrPending(cache, path);\n\t\t\t\tif (branches === 'pending' || (branches != null && !branches.value.values.every(add))) return false;\n\t\t\t}\n\n\t\t\tconst current = getSettledOrPending(this._caches.branch, path);\n\t\t\tif (current === 'pending' || (current != null && !add(current.value))) return false;\n\n\t\t\tconst worktrees = getSettledOrPending(this._caches.worktrees, path);\n\t\t\tif (worktrees === 'pending' || (worktrees != null && !worktrees.value.every(w => add(w.branch)))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Drops the cached branches and worktrees for `repoPath` and its sibling worktrees when their metadata changed in\n\t * a way {@link patchBranchMetadata} can't apply in place. Hard-evicts, so a read that started before the change\n\t * isn't joined.\n\t */\n\tdeleteBranchMetadata(repoPath: string): void {\n\t\tfor (const key of ['branchMetadataMap', 'sharedBranches', 'branches', 'branch', 'worktrees'] as const) {\n\t\t\tthis.evictShared(key, repoPath, 'evict');\n\t\t}\n\t}\n\n\tgetBranchMergedStatus(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitBranchMergedStatus>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitBranchMergedStatus> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.branchMergedStatus,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => {\n\t\t\t\tif (!data.merged) return data;\n\t\t\t\tif (data.localBranchOnly == null) return data;\n\n\t\t\t\tconst lbo = data.localBranchOnly;\n\t\t\t\treturn {\n\t\t\t\t\t...data,\n\t\t\t\t\tlocalBranchOnly: createReference(lbo.ref, newRepoPath, {\n\t\t\t\t\t\tid: getBranchId(newRepoPath, lbo.remote, lbo.name),\n\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\tname: lbo.name,\n\t\t\t\t\t\tremote: lbo.remote,\n\t\t\t\t\t\tupstream: lbo.upstream,\n\t\t\t\t\t\tsha: lbo.sha,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ cancellation: cancellation },\n\t\t);\n\t}\n\n\t/** Config can differ by checkout through config.worktree and conditional includes. */\n\tgetAheadOfBaseConfigKey(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\trepoPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.aheadOfBaseConfigKey.getOrCreate(\n\t\t\trepoPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(repoPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * One listing for every checkout of a repository, which serves a checkout's {@link getAheadOfBaseConfigKey} while\n\t * nothing makes config differ by checkout. Evicted with it, hard, so a read after a change never joins one from\n\t * before it.\n\t */\n\tgetAheadOfBaseConfigListing(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimple(this.aheadOfBaseConfigListing, repoPath, factory, cancellation);\n\t}\n\n\t/**\n\t * One listing of the gitignore filter's config inputs for every checkout of a repository, which serves a checkout's\n\t * filter while nothing makes config differ by checkout. Evicted hard, so a read after a change never joins one\n\t * from before it.\n\t */\n\tgetIgnoreConfigListing(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimple(this.ignoreConfigListing, repoPath, factory, cancellation);\n\t}\n\n\tgetBranchMetadataMap(\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string) => PromiseOrValue<Map<string, BranchMetadata>>,\n\t): Promise<Map<string, BranchMetadata>> {\n\t\treturn this.getSharedSimple(this.branchMetadataMap, repoPath, factory);\n\t}\n\n\tgetDefaultBranchName(\n\t\trepoPath: string,\n\t\tremote: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<string | undefined>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimpleWithKey(this.defaultBranchName, repoPath, remote, factory, {\n\t\t\tcancellation: cancellation,\n\t\t});\n\t}\n\n\t/** The cached default branch for one `remote` key, without reading it; `undefined` when none is cached */\n\tpeekDefaultBranchName(repoPath: string, remote: string): Promise<string | undefined> | undefined {\n\t\treturn this._caches.defaultBranchName?.get(this.getCommonPath(repoPath), remote);\n\t}\n\n\t/**\n\t * No TTL and not cleared by a ref or config change: the caller confirms a hit against what the answer was read from\n\t * (see {@link CachedMergeTarget}). A checkout evicts only the entries marked `evictOnCheckout`\n\t */\n\tgetMergeTarget(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<CachedMergeTarget>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<CachedMergeTarget> {\n\t\tconst pending = this.getSharedSimpleWithKey(\n\t\t\tthis.mergeTargets,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\tconst generation = this._mergeTargetCheckoutGeneration;\n\t\t\t\tconst entry = await factory(commonPath, cacheable, signal);\n\t\t\t\tif (entry.evictOnCheckout) {\n\t\t\t\t\t// A checkout while the reflog was read may have written the entry it found missing\n\t\t\t\t\tif (this._mergeTargetCheckoutGeneration !== generation) {\n\t\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\t\treturn entry;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet keys = this._mergeTargetsEvictedOnCheckout.get(commonPath);\n\t\t\t\t\tif (keys == null) {\n\t\t\t\t\t\tkeys = new Set();\n\t\t\t\t\t\tthis._mergeTargetsEvictedOnCheckout.set(commonPath, keys);\n\t\t\t\t\t}\n\t\t\t\t\tkeys.add(cacheKey);\n\t\t\t\t}\n\t\t\t\treturn entry;\n\t\t\t},\n\t\t\t{ cancellation: cancellation },\n\t\t);\n\n\t\t// Stored before the factory runs, so this is the entry the answer will come from\n\t\tconst stored = this.mergeTargets.get(this.getCommonPath(repoPath), cacheKey);\n\t\tif (stored == null) return pending;\n\n\t\treturn pending.then(entry => {\n\t\t\tthis._mergeTargetStored.set(entry, stored);\n\t\t\treturn entry;\n\t\t});\n\t}\n\n\t/**\n\t * Drops `stale`, an answer {@link getMergeTarget} gave for `cacheKey`, unless it was already replaced: callers that\n\t * found the same answer stale then share the one that replaced it rather than each resolving their own\n\t */\n\tdeleteMergeTarget(repoPath: string, cacheKey: string, stale: CachedMergeTarget): void {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst stored = this._mergeTargetStored.get(stale);\n\t\tif (stored != null && this._caches.mergeTargets?.get(commonPath, cacheKey) !== stored) return;\n\n\t\tthis._caches.mergeTargets?.delete(commonPath, cacheKey);\n\t}\n\n\tprivate evictMergeTargetsOnCheckout(repoPath: string | undefined): void {\n\t\tthis._mergeTargetCheckoutGeneration++;\n\n\t\tconst commonPaths =\n\t\t\trepoPath != null ? [this.getCommonPath(repoPath)] : [...this._mergeTargetsEvictedOnCheckout.keys()];\n\t\tfor (const commonPath of commonPaths) {\n\t\t\tconst keys = this._mergeTargetsEvictedOnCheckout.get(commonPath);\n\t\t\tif (keys == null) continue;\n\n\t\t\tthis._mergeTargetsEvictedOnCheckout.delete(commonPath);\n\t\t\tfor (const key of keys) {\n\t\t\t\tthis._caches.mergeTargets?.delete(commonPath, key);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Clears the cached default branch for one `remote` key (the networked lookup or its `:local` variant). */\n\tdeleteDefaultBranchName(repoPath: string, remote: string): void {\n\t\tthis._caches.defaultBranchName?.delete(this.getCommonPath(repoPath), remote);\n\t}\n\n\tgetInitialCommitSha(\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string) => PromiseOrValue<string | undefined>,\n\t): Promise<string | undefined> {\n\t\treturn this.getSharedSimple(this.initialCommitSha, repoPath, factory);\n\t}\n\n\t/** A rejected factory is never cached (`PromiseMap` evicts on rejection) — a failed read retries next time. */\n\tgetEmptyTreeSha(repoPath: string, factory: (commonPath: string) => PromiseOrValue<string>): Promise<string> {\n\t\treturn this.getSharedSimple(this.emptyTreeSha, repoPath, factory);\n\t}\n\n\tgetLastFetchedTimestamp(\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string) => PromiseOrValue<number | undefined>,\n\t): Promise<number | undefined> {\n\t\treturn this.getSharedSimple(this.lastFetched, repoPath, factory);\n\t}\n\n\tgetRefs(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<RefRecord[]>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<RefRecord[]> {\n\t\t// Raw ref records are repoPath-agnostic (no per-worktree binding to remap), so we key only\n\t\t// by commonPath and skip the per-worktree mapper that `getBranches`/`getTags` need.\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\treturn this.refs.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tgetRefTips(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitRefTip[]>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRefTip[]> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\treturn this.refTips.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tasync getRemotes(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitRemote[]>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]> {\n\t\treturn this.getSharedOrCreate(\n\t\t\tthis.remotes,\n\t\t\trepoPath,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => data.map(r => r.withRepoPath(newRepoPath)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tasync getStash(\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitStash>,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<GitStash> {\n\t\treturn this.getSharedOrCreateWithKey(\n\t\t\tthis.stashes,\n\t\t\trepoPath,\n\t\t\tcacheKey,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => ({\n\t\t\t\trepoPath: newRepoPath,\n\t\t\t\tstashes: new Map(\n\t\t\t\t\tArray.from(data.stashes.entries(), ([sha, s]) => [\n\t\t\t\t\t\tsha,\n\t\t\t\t\t\ts.withRepoPath<GitStashCommit>(newRepoPath),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t}),\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync getTags(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<PagedResult<GitTag>>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<PagedResult<GitTag>> {\n\t\treturn this.getSharedOrCreate(\n\t\t\tthis.tags,\n\t\t\trepoPath,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => ({ ...data, values: data.values.map(t => t.withRepoPath(newRepoPath)) }),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tasync getWorktrees(\n\t\trepoPath: string,\n\t\tfactory: (\n\t\t\tcommonPath: string,\n\t\t\tcacheable: CacheController,\n\t\t\tcancellation?: AbortSignal,\n\t\t) => PromiseOrValue<GitWorktree[]>,\n\t\toptions?: { force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitWorktree[]> {\n\t\tif (options?.force) {\n\t\t\t// An aborted call must not cost every other caller the shared list\n\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\tthis.evictCaches(repoPath, 'worktreeList');\n\t\t}\n\n\t\treturn this.getSharedOrCreate(\n\t\t\tthis.worktrees,\n\t\t\trepoPath,\n\t\t\tfactory,\n\t\t\t(data, newRepoPath) => data.map(w => w.withRepoPath(newRepoPath)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async getSharedOrCreate<T>(\n\t\tcache: PromiseMap<string, T>,\n\t\trepoPath: string,\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\tmapper: (data: T, repoPath: string) => T,\n\t\tcancellation?: AbortSignal,\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\t// Always register this caller with the shared factory's aggregate so same-`repoPath` and\n\t\t// worktree-distinct concurrent callers both contribute — invariant 3 (factory aborts iff\n\t\t// every waiter aborts) holds uniformly. The wrapped return is our caller-facing promise\n\t\t// for the commonPath-keyed branch; the per-worktree branch uses `raceWithSignal` below.\n\t\tconst sharedPromise = cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => {\n\t\t\t\tconst p = Promise.resolve(factory(commonPath, cacheable, signal));\n\t\t\t\t// On factory invalidation (without rejection), propagate to the derived per-worktree\n\t\t\t\t// mapper entries so they don't persist past the shared factory's settle. Mapper\n\t\t\t\t// entries cached via `cache.set()` have no controller, so `invalidate` hard-deletes.\n\t\t\t\tvoid p\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tif (cacheable.invalidated) {\n\t\t\t\t\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\t\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\t\t\t\t\tcache.invalidate(worktreePath);\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\t// Swallow the cleanup chain's rejection so a rejected factory (e.g. cancellation)\n\t\t\t\t\t// doesn't surface as an unhandled rejection; the caller-facing promise handles it.\n\t\t\t\t\t.catch(() => {});\n\t\t\t\treturn p;\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\t// Swallow any rejection on the registration wrapper so it isn't surfaced as an unhandled\n\t\t// rejection when we discard it below (existing-mapper path). The real caller-facing\n\t\t// promise is the returned value.\n\t\tvoid sharedPromise.catch(() => {});\n\n\t\tif (commonPath !== repoPath) {\n\t\t\t// Reuse the cached mapped entry for this worktree if present; otherwise derive it off\n\t\t\t// the raw inner shared promise so subsequent cache hits don't inherit the first\n\t\t\t// caller's signal wrap.\n\t\t\tconst existing = cache.get(repoPath);\n\t\t\tif (existing != null) {\n\t\t\t\treturn cancellation != null ? raceWithSignal(existing, cancellation) : existing;\n\t\t\t}\n\n\t\t\tconst rawShared = cache.get(commonPath) ?? sharedPromise;\n\t\t\tconst mappedPromise = Promise.resolve(rawShared).then(data => mapper(data, repoPath));\n\t\t\tcache.set(repoPath, mappedPromise);\n\t\t\treturn cancellation != null ? raceWithSignal(mappedPromise, cancellation) : mappedPromise;\n\t\t}\n\n\t\treturn sharedPromise;\n\t}\n\n\tprivate async getSharedOrCreateWithKey<T>(\n\t\tcache: RepoPromiseCacheMap<string, T>,\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\tmapper: (data: T, repoPath: string) => T,\n\t\toptions?: { accessTTL?: number; cancellation?: AbortSignal },\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\t\tconst cancellation = options?.cancellation;\n\n\t\t// Always register with the shared factory's aggregate (see `getSharedOrCreate` comment).\n\t\tconst sharedPromise = cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\tcacheKey,\n\t\t\t(cacheable, signal) => {\n\t\t\t\tconst p = Promise.resolve(factory(commonPath, cacheable, signal));\n\t\t\t\t// On factory invalidation (without rejection), propagate to the derived per-worktree\n\t\t\t\t// mapper entries for this `cacheKey` so they don't persist past the shared factory's\n\t\t\t\t// settle. Mapper entries cached via `cache.set()` have no controller, so `invalidate`\n\t\t\t\t// hard-deletes.\n\t\t\t\tvoid p\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tif (cacheable.invalidated) {\n\t\t\t\t\t\t\tfor (const worktreePath of this.getWorktreePaths(commonPath)) {\n\t\t\t\t\t\t\t\tif (worktreePath === commonPath) continue;\n\n\t\t\t\t\t\t\t\tcache.invalidate(worktreePath, cacheKey);\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\t// Swallow the cleanup chain's rejection so a rejected factory (e.g. cancellation)\n\t\t\t\t\t// doesn't surface as an unhandled rejection; the caller-facing promise handles it.\n\t\t\t\t\t.catch(() => {});\n\t\t\t\treturn p;\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t\t// Swallow any rejection on the registration wrapper so it isn't surfaced as an unhandled\n\t\t// rejection when we discard it below (existing-mapper path).\n\t\tvoid sharedPromise.catch(() => {});\n\n\t\tif (commonPath !== repoPath) {\n\t\t\tconst existing = cache.get(repoPath, cacheKey);\n\t\t\tif (existing != null) {\n\t\t\t\treturn cancellation != null ? raceWithSignal(existing, cancellation) : existing;\n\t\t\t}\n\n\t\t\tconst rawShared = cache.get(commonPath, cacheKey) ?? sharedPromise;\n\t\t\tconst mappedPromise = Promise.resolve(rawShared).then(data => mapper(data, repoPath));\n\t\t\tcache.set(repoPath, cacheKey, mappedPromise, options);\n\t\t\treturn cancellation != null ? raceWithSignal(mappedPromise, cancellation) : mappedPromise;\n\t\t}\n\n\t\treturn sharedPromise;\n\t}\n\n\tprivate async getSharedSimple<T>(\n\t\tcache: PromiseMap<string, T> | PromiseCache<string, T>,\n\t\trepoPath: string,\n\t\t// `cacheable` is forwarded so a factory can refuse the entry when the read FAILED rather than\n\t\t// genuinely produced nothing — see `getSharedSimpleWithKey` for why that distinction matters.\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\t// Only a `PromiseMap` takes one; its factory's signal aborts once every waiter has aborted\n\t\tcancellation?: AbortSignal,\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\t// `PromiseMap.getOrCreate(key, factory, cancellation?)` and\n\t\t// `PromiseCache.getOrCreate(key, factory, options?)` have different 3rd-argument shapes,\n\t\t// so we dispatch on cache type. Both register a `CacheController` so `invalidate` works.\n\t\tif (cache instanceof PromiseCache) {\n\t\t\treturn cache.getOrCreate(commonPath, cacheable => Promise.resolve(factory(commonPath, cacheable)));\n\t\t}\n\t\treturn cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async getSharedSimpleWithKey<T>(\n\t\tcache: RepoPromiseCacheMap<string, T>,\n\t\trepoPath: string,\n\t\tcacheKey: string,\n\t\t// `cacheable` is forwarded so a factory can distinguish \"the answer is genuinely nothing\" from \"the\n\t\t// read failed\": callers here set no TTL by default, so a failure resolved as `undefined` would\n\t\t// otherwise be served as a real answer until something explicitly evicts it.\n\t\tfactory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<T>,\n\t\toptions?: { accessTTL?: number; createTTL?: number; cancellation?: AbortSignal },\n\t): Promise<T> {\n\t\tconst commonPath = this.getCommonPath(repoPath);\n\n\t\treturn cache.getOrCreate(\n\t\t\tcommonPath,\n\t\t\tcacheKey,\n\t\t\t(cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)),\n\t\t\toptions,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
|