@gitkraken/core-gitlens 0.16.3 → 0.16.4
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 +25 -1
- package/dist/git/cache.d.ts +64 -5
- package/dist/git/cache.js +75 -5
- package/dist/git/cache.js.map +1 -1
- package/dist/git/models/branch.d.ts +0 -6
- package/dist/git/models/branch.js.map +1 -1
- package/dist/git/providers/branches.d.ts +65 -1
- package/dist/git/providers/refs.d.ts +3 -2
- package/dist/git/providers/shared/remotes.js +5 -5
- package/dist/git/providers/shared/remotes.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts +135 -39
- package/dist/git-cli/providers/branches.js +846 -264
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.js +37 -20
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.js +16 -10
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/contributors.js +3 -3
- package/dist/git-cli/providers/contributors.js.map +1 -1
- package/dist/git-cli/providers/diff.js +15 -12
- package/dist/git-cli/providers/diff.js.map +1 -1
- package/dist/git-cli/providers/graph.js +17 -14
- package/dist/git-cli/providers/graph.js.map +1 -1
- package/dist/git-cli/providers/maintenance.js +3 -3
- package/dist/git-cli/providers/maintenance.js.map +1 -1
- package/dist/git-cli/providers/patch.js +4 -1
- package/dist/git-cli/providers/patch.js.map +1 -1
- package/dist/git-cli/providers/pausedOperations.js +2 -2
- package/dist/git-cli/providers/pausedOperations.js.map +1 -1
- package/dist/git-cli/providers/refs.js +16 -13
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/remotes.js +4 -1
- package/dist/git-cli/providers/remotes.js.map +1 -1
- package/dist/git-cli/providers/revision.js +14 -11
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/stash.js +2 -2
- package/dist/git-cli/providers/stash.js.map +1 -1
- package/dist/git-cli/providers/status.js +7 -7
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/git-cli/providers/tags.js +6 -3
- package/dist/git-cli/providers/tags.js.map +1 -1
- package/dist/git-cli/providers/worktrees.js +3 -3
- package/dist/git-cli/providers/worktrees.js.map +1 -1
- package/dist/plus/git-github/providers/github/branches.d.ts +9 -1
- package/dist/plus/git-github/providers/github/branches.js +54 -8
- package/dist/plus/git-github/providers/github/branches.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +1 -0
- package/dist/plus/integrations/reads/drains.d.ts +1 -0
- package/dist/utils/decorators/log.d.ts +3 -1
- package/dist/utils/decorators/log.js +61 -45
- package/dist/utils/decorators/log.js.map +1 -1
- package/dist/utils/logger.d.ts +15 -1
- package/dist/utils/logger.js +30 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/logger.scoped.d.ts +12 -1
- package/dist/utils/logger.scoped.js +38 -4
- package/dist/utils/logger.scoped.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { MaybePausedResult } from "../../utils/promise.js";
|
|
2
1
|
import { Shape } from "../../utils/types.js";
|
|
3
2
|
import { GitBranchReference } from "./reference.js";
|
|
4
3
|
//#region ../git/src/models/branch.d.ts
|
|
@@ -104,10 +103,5 @@ export interface GitTrackingUpstream {
|
|
|
104
103
|
readonly state: GitTrackingState;
|
|
105
104
|
}
|
|
106
105
|
export type GitBranchStatus = 'local' | 'detached' | 'ahead' | 'behind' | 'diverged' | 'upToDate' | 'missingUpstream' | 'remote';
|
|
107
|
-
export interface BranchTargetInfo {
|
|
108
|
-
mergeTargetBranch: MaybePausedResult<string | undefined>;
|
|
109
|
-
baseBranch: string | undefined;
|
|
110
|
-
defaultBranch: string | undefined;
|
|
111
|
-
}
|
|
112
106
|
//#endregion
|
|
113
107
|
//# sourceMappingURL=branch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch.js","names":[],"sources":["../../../../git/src/models/branch.ts"],"sourcesContent":["import { formatDate, fromNow } from '@gitlens/utils/date.js';\nimport { loggable } from '@gitlens/utils/decorators/log.js';\nimport { memoize } from '@gitlens/utils/decorators/memoize.js';\nimport { serializable } from '@gitlens/utils/decorators/serializable.js';\nimport { getBranchId, getRemoteNameFromBranchName, getRemoteNameSlashIndex } from '@gitlens/utils/gitRefs.js';\nimport type { MaybePausedResult } from '@gitlens/utils/promise.js';\nimport type { Shape } from '@gitlens/utils/types.js';\nimport {\n\tformatDetachedHeadName,\n\tgetBranchTrackingWithoutRemote,\n\tisDetachedHead,\n\tparseRefName,\n} from '../utils/branch.utils.js';\nimport { getUpstreamStatus } from '../utils/status.utils.js';\nimport type { GitBranchReference } from './reference.js';\n\nexport type BranchDisposition = 'starred' | 'archived';\n\n/** The `.git/gk/config` keys (`branch.<name>.<key>`) a branch's {@link BranchMetadata} is read from */\nexport type BranchMetadataGkConfigKey =\n\t| 'gk-last-accessed'\n\t| 'gk-last-modified'\n\t| 'gk-agent-last-activity'\n\t| 'gk-disposition';\n\n/**\n * A branch's `.git/gk/config` metadata. Unlike other cached values, the cache updates these objects in place when a\n * key changes (see `Cache.patchBranchMetadata`), so every `GitBranch` holding one, old or new, reads the new value\n */\nexport interface BranchMetadata {\n\tlastAccessedAt?: string;\n\tlastModifiedAt?: string;\n\tagentLastActivityAt?: string;\n\tdisposition?: BranchDisposition;\n}\n\nexport type GitBranchShape = Shape<GitBranch>;\n\n/**\n * Each metadata object's last parsed stamps. Not `@memoize`d on the branch: the cache updates `BranchMetadata` in\n * place, so a parse is reused only while its stamp is unchanged — and shared by every branch holding the object.\n */\nconst stampDates = new WeakMap<BranchMetadata, Partial<Record<StampField, { stamp: string; date: Date }>>>();\ntype StampField = 'lastAccessedAt' | 'lastModifiedAt';\n\nfunction getStampDate(metadata: BranchMetadata, field: StampField): Date | undefined {\n\tconst stamp = metadata[field];\n\tif (!stamp) return undefined;\n\n\tlet parsed = stampDates.get(metadata);\n\tif (parsed == null) {\n\t\tparsed = {};\n\t\tstampDates.set(metadata, parsed);\n\t}\n\n\tlet entry = parsed[field];\n\tif (entry?.stamp !== stamp) {\n\t\tentry = { stamp: stamp, date: new Date(stamp) };\n\t\tparsed[field] = entry;\n\t}\n\treturn entry.date;\n}\n\n@loggable(i => i.id)\n@serializable\nexport class GitBranch implements GitBranchReference {\n\treadonly refType = 'branch';\n\treadonly detached: boolean;\n\treadonly id: string;\n\n\tprivate readonly _name: string;\n\tget name(): string {\n\t\treturn this._name;\n\t}\n\n\tprivate readonly _remote: boolean;\n\tget remote(): boolean {\n\t\treturn this._remote;\n\t}\n\n\tconstructor(\n\t\tpublic readonly repoPath: string,\n\t\tpublic readonly refName: string,\n\t\tpublic readonly current: boolean,\n\t\tpublic readonly date: Date | undefined,\n\t\t/**\n\t\t * GK config metadata (dates, disposition), shared with the cache and updated in place: comparing an old and a\n\t\t * new branch can't detect a changed stamp (no change event fires for one either)\n\t\t */\n\t\tpublic readonly metadata: BranchMetadata | undefined,\n\t\tpublic readonly sha?: string,\n\t\tpublic readonly upstream?: GitTrackingUpstream,\n\t\tpublic readonly worktree?: { path: string; isDefault: boolean } | false,\n\t\tdetached: boolean = false,\n\t\tpublic readonly rebasing: boolean = false,\n\t) {\n\t\t({ name: this._name, remote: this._remote } = parseRefName(refName));\n\n\t\tthis.detached = detached || (this.current ? isDetachedHead(this._name) : false);\n\t\tif (this.detached) {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this.sha!);\n\t\t\tthis._name = formatDetachedHeadName(this.sha!);\n\t\t} else {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this._name);\n\t\t}\n\n\t\tthis.upstream = upstream?.name ? upstream : undefined;\n\t}\n\n\tget archived(): boolean {\n\t\treturn this.metadata?.disposition === 'archived';\n\t}\n\n\t@memoize()\n\tget basename(): string {\n\t\tconst name = this.nameWithoutRemote;\n\t\tconst index = name.lastIndexOf('/');\n\t\treturn index !== -1 ? name.substring(index + 1) : name;\n\t}\n\n\tget disposition(): BranchDisposition | undefined {\n\t\treturn this.metadata?.disposition;\n\t}\n\n\t/** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */\n\tget effectiveDate(): Date | undefined {\n\t\tlet maxTime: number | undefined;\n\n\t\tconst accessed = this.lastAccessedDate?.getTime();\n\t\tif (accessed != null && (maxTime == null || accessed > maxTime)) {\n\t\t\tmaxTime = accessed;\n\t\t}\n\n\t\tconst modified = this.lastModifiedDate?.getTime();\n\t\tif (modified != null && (maxTime == null || modified > maxTime)) {\n\t\t\tmaxTime = modified;\n\t\t}\n\n\t\tconst date = this.date?.getTime();\n\t\tif (date != null && (maxTime == null || date > maxTime)) {\n\t\t\tmaxTime = date;\n\t\t}\n\n\t\treturn maxTime != null ? new Date(maxTime) : undefined;\n\t}\n\n\tget lastAccessedDate(): Date | undefined {\n\t\treturn this.metadata != null ? getStampDate(this.metadata, 'lastAccessedAt') : undefined;\n\t}\n\n\t/** When a checkout's working tree or index last changed while on this branch (`gk-last-modified`), not only commits */\n\tget lastModifiedDate(): Date | undefined {\n\t\treturn this.metadata != null ? getStampDate(this.metadata, 'lastModifiedAt') : undefined;\n\t}\n\n\t@memoize()\n\tget nameWithoutRemote(): string {\n\t\treturn this.remote ? this.name.substring(getRemoteNameSlashIndex(this.name) + 1) : this.name;\n\t}\n\n\tget ref(): string {\n\t\treturn this.detached ? this.sha! : this._name;\n\t}\n\n\t@memoize()\n\tget remoteName(): string | undefined {\n\t\tif (this.remote) return getRemoteNameFromBranchName(this.name);\n\t\tif (this.upstream?.local) return undefined;\n\t\tif (this.upstream != null) return this.upstream.remote ?? getRemoteNameFromBranchName(this.upstream.name);\n\n\t\treturn undefined;\n\t}\n\n\tget starred(): boolean {\n\t\treturn this.metadata?.disposition === 'starred';\n\t}\n\n\tget status(): GitBranchStatus {\n\t\tif (this.remote) return 'remote';\n\t\tif (this.upstream == null) return this.detached ? 'detached' : 'local';\n\n\t\tif (this.upstream.missing) return 'missingUpstream';\n\t\tif (this.upstream.state.ahead && this.upstream.state.behind) return 'diverged';\n\t\tif (this.upstream.state.ahead) return 'ahead';\n\t\tif (this.upstream.state.behind) return 'behind';\n\t\treturn 'upToDate';\n\t}\n\n\t@memoize()\n\tget trackingWithoutRemote(): string | undefined {\n\t\treturn getBranchTrackingWithoutRemote(this);\n\t}\n\n\t/** Creates a copy of this branch with a different repoPath and optionally a different current flag — ONLY used for worktree-aware caching */\n\twithRepoPath(repoPath: string, current?: boolean): GitBranch {\n\t\tconst newCurrent = current ?? this.current;\n\t\tif (repoPath === this.repoPath && newCurrent === this.current) return this;\n\t\treturn new GitBranch(\n\t\t\trepoPath,\n\t\t\tthis.refName,\n\t\t\tnewCurrent,\n\t\t\tthis.date,\n\t\t\tthis.metadata,\n\t\t\tthis.sha,\n\t\t\tthis.upstream,\n\t\t\tthis.worktree,\n\t\t\tthis.detached,\n\t\t\tthis.rebasing,\n\t\t);\n\t}\n\n\tstatic is(branch: unknown): branch is GitBranch {\n\t\treturn branch instanceof GitBranch;\n\t}\n\n\tstatic formatDate(branch: GitBranchShape, format?: string | null): string {\n\t\treturn branch.date != null ? formatDate(branch.date, format ?? 'MMMM Do, YYYY h:mma') : '';\n\t}\n\n\tstatic formatDateFromNow(branch: GitBranchShape): string {\n\t\treturn branch.date != null ? fromNow(branch.date) : '';\n\t}\n\n\tstatic formatDateWithStyle(\n\t\tbranch: GitBranchShape,\n\t\tformatting: { dateStyle: string; dateFormat: string | null },\n\t): string {\n\t\treturn formatting.dateStyle === 'absolute'\n\t\t\t? GitBranch.formatDate(branch, formatting.dateFormat)\n\t\t\t: GitBranch.formatDateFromNow(branch);\n\t}\n\n\tstatic getTrackingStatus(\n\t\tbranch: GitBranchShape,\n\t\toptions?: {\n\t\t\tcount?: boolean;\n\t\t\tempty?: string;\n\t\t\texpand?: boolean;\n\t\t\ticons?: boolean;\n\t\t\tprefix?: string;\n\t\t\tseparator?: string;\n\t\t\tsuffix?: string;\n\t\t},\n\t): string {\n\t\treturn getUpstreamStatus(branch.upstream, options);\n\t}\n}\n\nexport interface GitTrackingState {\n\treadonly ahead: number;\n\treadonly behind: number;\n}\n\nexport interface GitTrackingUpstream {\n\treadonly name: string;\n\t/**\n\t * The remote the upstream is on (`branch.<name>.remote`) as git reports it, so a remote whose own name contains a\n\t * `/` stays whole. `undefined` when git is too old to report it (before 2.23 here) or the upstream is a local branch\n\t */\n\treadonly remote?: string;\n\t/**\n\t * The branch's name on its {@link remote} (`branch.<name>.merge` without `refs/heads/`), so a custom fetch refspec\n\t * can't misname it. `undefined` when git is too old to report it or the upstream is a local branch\n\t */\n\treadonly remoteBranch?: string;\n\t/** The upstream is a branch in this repository (`branch.<name>.remote = .`), so it has no remote */\n\treadonly local?: boolean;\n\treadonly missing: boolean;\n\treadonly state: GitTrackingState;\n}\n\nexport type GitBranchStatus =\n\t| 'local'\n\t| 'detached'\n\t| 'ahead'\n\t| 'behind'\n\t| 'diverged'\n\t| 'upToDate'\n\t| 'missingUpstream'\n\t| 'remote';\n\nexport interface BranchTargetInfo {\n\tmergeTargetBranch: MaybePausedResult<string | undefined>;\n\tbaseBranch: string | undefined;\n\tdefaultBranch: string | undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"branch.js","names":[],"sources":["../../../../git/src/models/branch.ts"],"sourcesContent":["import { formatDate, fromNow } from '@gitlens/utils/date.js';\nimport { loggable } from '@gitlens/utils/decorators/log.js';\nimport { memoize } from '@gitlens/utils/decorators/memoize.js';\nimport { serializable } from '@gitlens/utils/decorators/serializable.js';\nimport { getBranchId, getRemoteNameFromBranchName, getRemoteNameSlashIndex } from '@gitlens/utils/gitRefs.js';\nimport type { Shape } from '@gitlens/utils/types.js';\nimport {\n\tformatDetachedHeadName,\n\tgetBranchTrackingWithoutRemote,\n\tisDetachedHead,\n\tparseRefName,\n} from '../utils/branch.utils.js';\nimport { getUpstreamStatus } from '../utils/status.utils.js';\nimport type { GitBranchReference } from './reference.js';\n\nexport type BranchDisposition = 'starred' | 'archived';\n\n/** The `.git/gk/config` keys (`branch.<name>.<key>`) a branch's {@link BranchMetadata} is read from */\nexport type BranchMetadataGkConfigKey =\n\t| 'gk-last-accessed'\n\t| 'gk-last-modified'\n\t| 'gk-agent-last-activity'\n\t| 'gk-disposition';\n\n/**\n * A branch's `.git/gk/config` metadata. Unlike other cached values, the cache updates these objects in place when a\n * key changes (see `Cache.patchBranchMetadata`), so every `GitBranch` holding one, old or new, reads the new value\n */\nexport interface BranchMetadata {\n\tlastAccessedAt?: string;\n\tlastModifiedAt?: string;\n\tagentLastActivityAt?: string;\n\tdisposition?: BranchDisposition;\n}\n\nexport type GitBranchShape = Shape<GitBranch>;\n\n/**\n * Each metadata object's last parsed stamps. Not `@memoize`d on the branch: the cache updates `BranchMetadata` in\n * place, so a parse is reused only while its stamp is unchanged — and shared by every branch holding the object.\n */\nconst stampDates = new WeakMap<BranchMetadata, Partial<Record<StampField, { stamp: string; date: Date }>>>();\ntype StampField = 'lastAccessedAt' | 'lastModifiedAt';\n\nfunction getStampDate(metadata: BranchMetadata, field: StampField): Date | undefined {\n\tconst stamp = metadata[field];\n\tif (!stamp) return undefined;\n\n\tlet parsed = stampDates.get(metadata);\n\tif (parsed == null) {\n\t\tparsed = {};\n\t\tstampDates.set(metadata, parsed);\n\t}\n\n\tlet entry = parsed[field];\n\tif (entry?.stamp !== stamp) {\n\t\tentry = { stamp: stamp, date: new Date(stamp) };\n\t\tparsed[field] = entry;\n\t}\n\treturn entry.date;\n}\n\n@loggable(i => i.id)\n@serializable\nexport class GitBranch implements GitBranchReference {\n\treadonly refType = 'branch';\n\treadonly detached: boolean;\n\treadonly id: string;\n\n\tprivate readonly _name: string;\n\tget name(): string {\n\t\treturn this._name;\n\t}\n\n\tprivate readonly _remote: boolean;\n\tget remote(): boolean {\n\t\treturn this._remote;\n\t}\n\n\tconstructor(\n\t\tpublic readonly repoPath: string,\n\t\tpublic readonly refName: string,\n\t\tpublic readonly current: boolean,\n\t\tpublic readonly date: Date | undefined,\n\t\t/**\n\t\t * GK config metadata (dates, disposition), shared with the cache and updated in place: comparing an old and a\n\t\t * new branch can't detect a changed stamp (no change event fires for one either)\n\t\t */\n\t\tpublic readonly metadata: BranchMetadata | undefined,\n\t\tpublic readonly sha?: string,\n\t\tpublic readonly upstream?: GitTrackingUpstream,\n\t\tpublic readonly worktree?: { path: string; isDefault: boolean } | false,\n\t\tdetached: boolean = false,\n\t\tpublic readonly rebasing: boolean = false,\n\t) {\n\t\t({ name: this._name, remote: this._remote } = parseRefName(refName));\n\n\t\tthis.detached = detached || (this.current ? isDetachedHead(this._name) : false);\n\t\tif (this.detached) {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this.sha!);\n\t\t\tthis._name = formatDetachedHeadName(this.sha!);\n\t\t} else {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this._name);\n\t\t}\n\n\t\tthis.upstream = upstream?.name ? upstream : undefined;\n\t}\n\n\tget archived(): boolean {\n\t\treturn this.metadata?.disposition === 'archived';\n\t}\n\n\t@memoize()\n\tget basename(): string {\n\t\tconst name = this.nameWithoutRemote;\n\t\tconst index = name.lastIndexOf('/');\n\t\treturn index !== -1 ? name.substring(index + 1) : name;\n\t}\n\n\tget disposition(): BranchDisposition | undefined {\n\t\treturn this.metadata?.disposition;\n\t}\n\n\t/** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */\n\tget effectiveDate(): Date | undefined {\n\t\tlet maxTime: number | undefined;\n\n\t\tconst accessed = this.lastAccessedDate?.getTime();\n\t\tif (accessed != null && (maxTime == null || accessed > maxTime)) {\n\t\t\tmaxTime = accessed;\n\t\t}\n\n\t\tconst modified = this.lastModifiedDate?.getTime();\n\t\tif (modified != null && (maxTime == null || modified > maxTime)) {\n\t\t\tmaxTime = modified;\n\t\t}\n\n\t\tconst date = this.date?.getTime();\n\t\tif (date != null && (maxTime == null || date > maxTime)) {\n\t\t\tmaxTime = date;\n\t\t}\n\n\t\treturn maxTime != null ? new Date(maxTime) : undefined;\n\t}\n\n\tget lastAccessedDate(): Date | undefined {\n\t\treturn this.metadata != null ? getStampDate(this.metadata, 'lastAccessedAt') : undefined;\n\t}\n\n\t/** When a checkout's working tree or index last changed while on this branch (`gk-last-modified`), not only commits */\n\tget lastModifiedDate(): Date | undefined {\n\t\treturn this.metadata != null ? getStampDate(this.metadata, 'lastModifiedAt') : undefined;\n\t}\n\n\t@memoize()\n\tget nameWithoutRemote(): string {\n\t\treturn this.remote ? this.name.substring(getRemoteNameSlashIndex(this.name) + 1) : this.name;\n\t}\n\n\tget ref(): string {\n\t\treturn this.detached ? this.sha! : this._name;\n\t}\n\n\t@memoize()\n\tget remoteName(): string | undefined {\n\t\tif (this.remote) return getRemoteNameFromBranchName(this.name);\n\t\tif (this.upstream?.local) return undefined;\n\t\tif (this.upstream != null) return this.upstream.remote ?? getRemoteNameFromBranchName(this.upstream.name);\n\n\t\treturn undefined;\n\t}\n\n\tget starred(): boolean {\n\t\treturn this.metadata?.disposition === 'starred';\n\t}\n\n\tget status(): GitBranchStatus {\n\t\tif (this.remote) return 'remote';\n\t\tif (this.upstream == null) return this.detached ? 'detached' : 'local';\n\n\t\tif (this.upstream.missing) return 'missingUpstream';\n\t\tif (this.upstream.state.ahead && this.upstream.state.behind) return 'diverged';\n\t\tif (this.upstream.state.ahead) return 'ahead';\n\t\tif (this.upstream.state.behind) return 'behind';\n\t\treturn 'upToDate';\n\t}\n\n\t@memoize()\n\tget trackingWithoutRemote(): string | undefined {\n\t\treturn getBranchTrackingWithoutRemote(this);\n\t}\n\n\t/** Creates a copy of this branch with a different repoPath and optionally a different current flag — ONLY used for worktree-aware caching */\n\twithRepoPath(repoPath: string, current?: boolean): GitBranch {\n\t\tconst newCurrent = current ?? this.current;\n\t\tif (repoPath === this.repoPath && newCurrent === this.current) return this;\n\t\treturn new GitBranch(\n\t\t\trepoPath,\n\t\t\tthis.refName,\n\t\t\tnewCurrent,\n\t\t\tthis.date,\n\t\t\tthis.metadata,\n\t\t\tthis.sha,\n\t\t\tthis.upstream,\n\t\t\tthis.worktree,\n\t\t\tthis.detached,\n\t\t\tthis.rebasing,\n\t\t);\n\t}\n\n\tstatic is(branch: unknown): branch is GitBranch {\n\t\treturn branch instanceof GitBranch;\n\t}\n\n\tstatic formatDate(branch: GitBranchShape, format?: string | null): string {\n\t\treturn branch.date != null ? formatDate(branch.date, format ?? 'MMMM Do, YYYY h:mma') : '';\n\t}\n\n\tstatic formatDateFromNow(branch: GitBranchShape): string {\n\t\treturn branch.date != null ? fromNow(branch.date) : '';\n\t}\n\n\tstatic formatDateWithStyle(\n\t\tbranch: GitBranchShape,\n\t\tformatting: { dateStyle: string; dateFormat: string | null },\n\t): string {\n\t\treturn formatting.dateStyle === 'absolute'\n\t\t\t? GitBranch.formatDate(branch, formatting.dateFormat)\n\t\t\t: GitBranch.formatDateFromNow(branch);\n\t}\n\n\tstatic getTrackingStatus(\n\t\tbranch: GitBranchShape,\n\t\toptions?: {\n\t\t\tcount?: boolean;\n\t\t\tempty?: string;\n\t\t\texpand?: boolean;\n\t\t\ticons?: boolean;\n\t\t\tprefix?: string;\n\t\t\tseparator?: string;\n\t\t\tsuffix?: string;\n\t\t},\n\t): string {\n\t\treturn getUpstreamStatus(branch.upstream, options);\n\t}\n}\n\nexport interface GitTrackingState {\n\treadonly ahead: number;\n\treadonly behind: number;\n}\n\nexport interface GitTrackingUpstream {\n\treadonly name: string;\n\t/**\n\t * The remote the upstream is on (`branch.<name>.remote`) as git reports it, so a remote whose own name contains a\n\t * `/` stays whole. `undefined` when git is too old to report it (before 2.23 here) or the upstream is a local branch\n\t */\n\treadonly remote?: string;\n\t/**\n\t * The branch's name on its {@link remote} (`branch.<name>.merge` without `refs/heads/`), so a custom fetch refspec\n\t * can't misname it. `undefined` when git is too old to report it or the upstream is a local branch\n\t */\n\treadonly remoteBranch?: string;\n\t/** The upstream is a branch in this repository (`branch.<name>.remote = .`), so it has no remote */\n\treadonly local?: boolean;\n\treadonly missing: boolean;\n\treadonly state: GitTrackingState;\n}\n\nexport type GitBranchStatus =\n\t| 'local'\n\t| 'detached'\n\t| 'ahead'\n\t| 'behind'\n\t| 'diverged'\n\t| 'upToDate'\n\t| 'missingUpstream'\n\t| 'remote';\n"],"mappings":";;;;;;;;;;;;;;AAyCA,MAAM,6BAAa,IAAI,QAAoF;AAG3G,SAAS,aAAa,UAA0B,OAAqC;CACpF,MAAM,QAAQ,SAAS;CACvB,IAAI,CAAC,OAAO,OAAO,KAAA;CAEnB,IAAI,SAAS,WAAW,IAAI,QAAQ;CACpC,IAAI,UAAU,MAAM;EACnB,SAAS,CAAC;EACV,WAAW,IAAI,UAAU,MAAM;CAChC;CAEA,IAAI,QAAQ,OAAO;CACnB,IAAI,OAAO,UAAU,OAAO;EAC3B,QAAQ;GAAS;GAAO,MAAM,IAAI,KAAK,KAAK;EAAE;EAC9C,OAAO,SAAS;CACjB;CACA,OAAO,MAAM;AACd;AAIO,IAAM,YAAA,aAAN,MAAM,UAAwC;CAgBnC;CACA;CACA;CACA;CAKA;CACA;CACA;CACA;CAEA;CA5BjB,UAAmB;CACnB;CACA;CAEA;CACA,IAAI,OAAe;EAClB,OAAO,KAAK;CACb;CAEA;CACA,IAAI,SAAkB;EACrB,OAAO,KAAK;CACb;CAEA,YACC,UACA,SACA,SACA,MAKA,UACA,KACA,UACA,UACA,WAAoB,OACpB,WAAoC,OACnC;EAde,KAAA,WAAA;EACA,KAAA,UAAA;EACA,KAAA,UAAA;EACA,KAAA,OAAA;EAKA,KAAA,WAAA;EACA,KAAA,MAAA;EACA,KAAA,WAAA;EACA,KAAA,WAAA;EAEA,KAAA,WAAA;EAEhB,CAAC,CAAE,MAAM,KAAK,OAAO,QAAQ,KAAK,WAAY,aAAa,OAAO;EAElE,KAAK,WAAW,aAAa,KAAK,UAAU,eAAe,KAAK,KAAK,IAAI;EACzE,IAAI,KAAK,UAAU;GAClB,KAAK,KAAK,YAAY,UAAU,KAAK,SAAS,KAAK,GAAI;GACvD,KAAK,QAAQ,uBAAuB,KAAK,GAAI;EAC9C,OACC,KAAK,KAAK,YAAY,UAAU,KAAK,SAAS,KAAK,KAAK;EAGzD,KAAK,WAAW,UAAU,OAAO,WAAW,KAAA;CAC7C;CAEA,IAAI,WAAoB;EACvB,OAAO,KAAK,UAAU,gBAAgB;CACvC;CAEA,IACI,WAAmB;EACtB,MAAM,OAAO,KAAK;EAClB,MAAM,QAAQ,KAAK,YAAY,GAAG;EAClC,OAAO,UAAU,KAAK,KAAK,UAAU,QAAQ,CAAC,IAAI;CACnD;CAEA,IAAI,cAA6C;EAChD,OAAO,KAAK,UAAU;CACvB;;CAGA,IAAI,gBAAkC;EACrC,IAAI;EAEJ,MAAM,WAAW,KAAK,kBAAkB,QAAQ;EAChD,IAAI,YAAY,SAAS,WAAW,QAAQ,WAAW,UACtD,UAAU;EAGX,MAAM,WAAW,KAAK,kBAAkB,QAAQ;EAChD,IAAI,YAAY,SAAS,WAAW,QAAQ,WAAW,UACtD,UAAU;EAGX,MAAM,OAAO,KAAK,MAAM,QAAQ;EAChC,IAAI,QAAQ,SAAS,WAAW,QAAQ,OAAO,UAC9C,UAAU;EAGX,OAAO,WAAW,OAAO,IAAI,KAAK,OAAO,IAAI,KAAA;CAC9C;CAEA,IAAI,mBAAqC;EACxC,OAAO,KAAK,YAAY,OAAO,aAAa,KAAK,UAAU,gBAAgB,IAAI,KAAA;CAChF;;CAGA,IAAI,mBAAqC;EACxC,OAAO,KAAK,YAAY,OAAO,aAAa,KAAK,UAAU,gBAAgB,IAAI,KAAA;CAChF;CAEA,IACI,oBAA4B;EAC/B,OAAO,KAAK,SAAS,KAAK,KAAK,UAAU,wBAAwB,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK;CACzF;CAEA,IAAI,MAAc;EACjB,OAAO,KAAK,WAAW,KAAK,MAAO,KAAK;CACzC;CAEA,IACI,aAAiC;EACpC,IAAI,KAAK,QAAQ,OAAO,4BAA4B,KAAK,IAAI;EAC7D,IAAI,KAAK,UAAU,OAAO,OAAO,KAAA;EACjC,IAAI,KAAK,YAAY,MAAM,OAAO,KAAK,SAAS,UAAU,4BAA4B,KAAK,SAAS,IAAI;CAGzG;CAEA,IAAI,UAAmB;EACtB,OAAO,KAAK,UAAU,gBAAgB;CACvC;CAEA,IAAI,SAA0B;EAC7B,IAAI,KAAK,QAAQ,OAAO;EACxB,IAAI,KAAK,YAAY,MAAM,OAAO,KAAK,WAAW,aAAa;EAE/D,IAAI,KAAK,SAAS,SAAS,OAAO;EAClC,IAAI,KAAK,SAAS,MAAM,SAAS,KAAK,SAAS,MAAM,QAAQ,OAAO;EACpE,IAAI,KAAK,SAAS,MAAM,OAAO,OAAO;EACtC,IAAI,KAAK,SAAS,MAAM,QAAQ,OAAO;EACvC,OAAO;CACR;CAEA,IACI,wBAA4C;EAC/C,OAAO,+BAA+B,IAAI;CAC3C;;CAGA,aAAa,UAAkB,SAA8B;EAC5D,MAAM,aAAa,WAAW,KAAK;EACnC,IAAI,aAAa,KAAK,YAAY,eAAe,KAAK,SAAS,OAAO;EACtE,OAAO,IAAA,WACN,UACA,KAAK,SACL,YACA,KAAK,MACL,KAAK,UACL,KAAK,KACL,KAAK,UACL,KAAK,UACL,KAAK,UACL,KAAK,QACN;CACD;CAEA,OAAO,GAAG,QAAsC;EAC/C,OAAO,kBAAA;CACR;CAEA,OAAO,WAAW,QAAwB,QAAgC;EACzE,OAAO,OAAO,QAAQ,OAAO,WAAW,OAAO,MAAM,UAAU,qBAAqB,IAAI;CACzF;CAEA,OAAO,kBAAkB,QAAgC;EACxD,OAAO,OAAO,QAAQ,OAAO,QAAQ,OAAO,IAAI,IAAI;CACrD;CAEA,OAAO,oBACN,QACA,YACS;EACT,OAAO,WAAW,cAAc,aAAA,WACnB,WAAW,QAAQ,WAAW,UAAU,IAAA,WACxC,kBAAkB,MAAM;CACtC;CAEA,OAAO,kBACN,QACA,SASS;EACT,OAAO,kBAAkB,OAAO,UAAU,OAAO;CAClD;AACD;AArIE,WAAA,CAAA,QAAQ,CAAA,GAAA,UAAA,WAAA,YAAA,IAAA;AA0CR,WAAA,CAAA,QAAQ,CAAA,GAAA,UAAA,WAAA,qBAAA,IAAA;AASR,WAAA,CAAA,QAAQ,CAAA,GAAA,UAAA,WAAA,cAAA,IAAA;AAwBR,WAAA,CAAA,QAAQ,CAAA,GAAA,UAAA,WAAA,yBAAA,IAAA;AA7HT,YAAA,aAAA,WAAA,CAAA,UAAS,MAAK,EAAE,EAAE,GAClB,YAAA,GAAA,SAAA"}
|
|
@@ -44,6 +44,47 @@ export interface AheadOfBase {
|
|
|
44
44
|
/** The default branch the read resolved from local refs and the remotes' `HEAD` symrefs, `null` when none did; absent when it didn't consult the default branch (a recorded candidate decided the base first) */
|
|
45
45
|
readonly defaultBranch?: string | null;
|
|
46
46
|
}
|
|
47
|
+
/** Which source decided a merge target (see `getMergeTarget`): an {@link AheadOfBaseTier}, the pull request's base, or the branch HEAD was on when the branch was created */
|
|
48
|
+
export type MergeTargetTier = AheadOfBaseTier | 'pr' | 'inferred';
|
|
49
|
+
export interface MergeTarget {
|
|
50
|
+
/** The ref the branch is measured against: the chosen target or its tracking ref, whichever the branch forked from nearer */
|
|
51
|
+
readonly ref: string;
|
|
52
|
+
/** Where the branch forked from `ref`: git's `--fork-point` reading of `ref`'s reflog, else the merge base; `undefined` when they share no history */
|
|
53
|
+
readonly forkPoint: string | undefined;
|
|
54
|
+
readonly tier: MergeTargetTier;
|
|
55
|
+
}
|
|
56
|
+
export interface MergeTargetOptions {
|
|
57
|
+
/** Leaves the user's merge target out: the order a merge-target picker shows as "automatic" */
|
|
58
|
+
skipUserTarget?: boolean;
|
|
59
|
+
/** A target to try before every other source, as `getAheadOfBase`'s */
|
|
60
|
+
preferredTarget?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Read only when no stored merge target is usable. Its base, on the branch's remote, is tried after the stored
|
|
63
|
+
* targets and before the recorded base, and is stored as the detected target (never the user's) unless the pull
|
|
64
|
+
* request is part of a stack or the branch is a remote-tracking one
|
|
65
|
+
*/
|
|
66
|
+
getAssociatedPullRequest?: () => Promise<{
|
|
67
|
+
refs?: {
|
|
68
|
+
base?: {
|
|
69
|
+
branch: string;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
stack?: unknown;
|
|
73
|
+
} | undefined>;
|
|
74
|
+
/**
|
|
75
|
+
* Also reads VS Code's `vscode-merge-base` as the recorded base, and, for a branch its reflog says was created from
|
|
76
|
+
* `HEAD`, takes the branch HEAD was on when it was first checked out (tier `'inferred'`). The inferred branch is
|
|
77
|
+
* never stored
|
|
78
|
+
*/
|
|
79
|
+
inferBase?: boolean;
|
|
80
|
+
/** `'remote'` lets the default-branch read contact the remote when local refs name none; `'local'` (the default) never does */
|
|
81
|
+
defaultBranch?: 'local' | 'remote';
|
|
82
|
+
/** Asked for the default branch when git names none */
|
|
83
|
+
getFallbackDefaultBranch?: () => Promise<string | undefined>;
|
|
84
|
+
/** Answers a target that is the branch itself at the branch's own commit (including its upstream there), instead of `undefined` */
|
|
85
|
+
keepSelfAtTip?: boolean;
|
|
86
|
+
priority?: GitCommandPriority;
|
|
87
|
+
}
|
|
47
88
|
/** A ref {@link GitPushTarget} names, with its commit from the cached ref list */
|
|
48
89
|
export interface GitPushTargetRef {
|
|
49
90
|
/** The full ref name: `refs/remotes/origin/main`, or `refs/heads/main` for an upstream that is a local branch */
|
|
@@ -90,8 +131,11 @@ export interface GitBranchesSubProvider {
|
|
|
90
131
|
paging?: PagingOptions | undefined;
|
|
91
132
|
sort?: boolean | BranchSortOptions | undefined;
|
|
92
133
|
}, cancellation?: AbortSignal): Promise<PagedResult<GitBranch>>;
|
|
134
|
+
/** Measured against the branch's {@link getMergeTarget}, which reads the pull request and the reflog guess, may ask the remote for its default branch, and keeps a target that is the branch itself */
|
|
93
135
|
getBranchContributionsOverview(repoPath: string, ref: string, options?: {
|
|
94
136
|
associatedPullRequest?: Promise<PullRequest | undefined>;
|
|
137
|
+
/** Asked for the default branch when git names none (see {@link MergeTargetOptions.getFallbackDefaultBranch}) */
|
|
138
|
+
getFallbackDefaultBranch?: () => Promise<string | undefined>;
|
|
95
139
|
priority?: GitCommandPriority;
|
|
96
140
|
}, cancellation?: AbortSignal): Promise<BranchContributionsOverview | undefined>;
|
|
97
141
|
getBranchesWithCommits(repoPath: string, shas: string[], branch?: string, options?: {
|
|
@@ -103,6 +147,25 @@ export interface GitBranchesSubProvider {
|
|
|
103
147
|
mode?: 'contains' | 'pointsAt';
|
|
104
148
|
remotes?: boolean;
|
|
105
149
|
}, cancellation?: AbortSignal): Promise<string[]>;
|
|
150
|
+
/**
|
|
151
|
+
* The ref `branch` (a local branch, or a remote-tracking one such as `origin/feature`) is measured against, by the
|
|
152
|
+
* rules of {@link getAheadOfBase} but measured from the branch's own tip rather than HEAD: `preferredTarget`, the
|
|
153
|
+
* user's merge target (unless `skipUserTarget`), the detected one, the pull request's base (`getAssociatedPullRequest`),
|
|
154
|
+
* the recorded base, then — on the default branch — its upstream (tier `'upstream'`), else the branch the reflog
|
|
155
|
+
* says it was created from (or, with `inferBase`, the one HEAD was on when it was first checked out: tier
|
|
156
|
+
* `'inferred'`) unless the default branch forked strictly nearer, else the default branch. The default branch is
|
|
157
|
+
* read from local refs; with `defaultBranch: 'remote'` the remote is asked when they name none, and
|
|
158
|
+
* `getFallbackDefaultBranch` last. A candidate that is empty, flag-like or the branch itself falls through, as does
|
|
159
|
+
* one git confirms is gone; one that couldn't be checked is kept. A remote-tracking branch has no stored targets,
|
|
160
|
+
* reflog or upstream of its own (its pull request's base is still tried), and is itself as its local branch or its
|
|
161
|
+
* copy on any remote. `undefined` for a detached HEAD or an empty name, when nothing resolves, or — unless
|
|
162
|
+
* `keepSelfAtTip` — when the target is the branch itself at the branch's own commit.
|
|
163
|
+
*
|
|
164
|
+
* Answers are cached with the ref tips, stored keys and config they were read from, and a later call re-reads
|
|
165
|
+
* only those (all cached) to confirm them, so a warm call runs no git, and a ref moving that the answer didn't
|
|
166
|
+
* read re-measures nothing. A later call asks the pull request again only when the answer reached it and stored nothing.
|
|
167
|
+
*/
|
|
168
|
+
getMergeTarget(repoPath: string, branch: string, options?: MergeTargetOptions, cancellation?: AbortSignal): Promise<MergeTarget | undefined>;
|
|
106
169
|
getDefaultBranchName(repoPath: string | undefined, remote?: string,
|
|
107
170
|
/**
|
|
108
171
|
* `local`: resolve only from the local `refs/remotes/<remote>/HEAD` symref and never contact the
|
|
@@ -150,7 +213,8 @@ export interface GitBranchesSubProvider {
|
|
|
150
213
|
* detached) was cut from. Candidates in trust
|
|
151
214
|
* order: the user's merge target, the detected one, then the base recorded against the branch — only recorded bases
|
|
152
215
|
* count, never a reflog guess. Each is measured as itself or its tracking ref, whichever forked nearer HEAD; a stale
|
|
153
|
-
* target (one
|
|
216
|
+
* target (one git confirms names no ref, a flag-like one, or the branch itself) falls through to the next — one that
|
|
217
|
+
* couldn't be checked is kept, so its count rejects — and the default branch
|
|
154
218
|
* is used when none survives: the `HEAD` symref of the `upstream` remote, else `origin`, else the first remote, as its
|
|
155
219
|
* local branch or else the remote ref; then, in the same remote order, `<remote>/main` or `<remote>/master`, again as
|
|
156
220
|
* the local branch or else the remote ref; then `init.defaultBranch`, `main`, `master` — from local refs only, never
|
|
@@ -18,8 +18,9 @@ export interface GitRefsSubProvider {
|
|
|
18
18
|
}, cancellation?: AbortSignal): Promise<GitReference | undefined>;
|
|
19
19
|
/**
|
|
20
20
|
* Reads `ref`'s reflog, newest first, optionally keeping only entries whose message matches `grep` (git's
|
|
21
|
-
* `--grep-reflog` pattern). Resolves `[]` when nothing matches or `ref` has no
|
|
22
|
-
* read fails (e.g. `ref` doesn't exist), so "no answer" is distinguishable from
|
|
21
|
+
* `--grep-reflog` pattern, as a basic regular expression). Resolves `[]` when nothing matches or `ref` has no
|
|
22
|
+
* reflog, and rejects when the read fails (e.g. `ref` doesn't exist), so "no answer" is distinguishable from
|
|
23
|
+
* "never read".
|
|
23
24
|
*/
|
|
24
25
|
getReflogEntries?(repoPath: string, ref: string, options?: {
|
|
25
26
|
grep?: string;
|
|
@@ -42,11 +42,11 @@ var RemotesGitProviderBase = class {
|
|
|
42
42
|
this.context.hooks?.repository?.onChanged?.(repoPath, ["remotes", "remoteProviders"]);
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
-
__decorate([debug()], RemotesGitProviderBase.prototype, "getRemote", null);
|
|
46
|
-
__decorate([debug()], RemotesGitProviderBase.prototype, "getDefaultRemote", null);
|
|
47
|
-
__decorate([debug()], RemotesGitProviderBase.prototype, "getRemotesWithProviders", null);
|
|
48
|
-
__decorate([debug()], RemotesGitProviderBase.prototype, "getBestRemoteWithProvider", null);
|
|
49
|
-
__decorate([debug()], RemotesGitProviderBase.prototype, "getBestRemotesWithProviders", null);
|
|
45
|
+
__decorate([debug({ quiet: true })], RemotesGitProviderBase.prototype, "getRemote", null);
|
|
46
|
+
__decorate([debug({ quiet: true })], RemotesGitProviderBase.prototype, "getDefaultRemote", null);
|
|
47
|
+
__decorate([debug({ quiet: true })], RemotesGitProviderBase.prototype, "getRemotesWithProviders", null);
|
|
48
|
+
__decorate([debug({ quiet: true })], RemotesGitProviderBase.prototype, "getBestRemoteWithProvider", null);
|
|
49
|
+
__decorate([debug({ quiet: true })], RemotesGitProviderBase.prototype, "getBestRemotesWithProviders", null);
|
|
50
50
|
__decorate([debug()], RemotesGitProviderBase.prototype, "setRemoteAsDefault", null);
|
|
51
51
|
//#endregion
|
|
52
52
|
export { RemotesGitProviderBase };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remotes.js","names":[],"sources":["../../../../../git/src/providers/shared/remotes.ts"],"sourcesContent":["import { debug } from '@gitlens/utils/decorators/log.js';\nimport { sortCompare } from '@gitlens/utils/string.js';\nimport type { Cache } from '../../cache.js';\nimport type { GitServiceContext } from '../../context.js';\nimport type { GitRemote } from '../../models/remote.js';\nimport type { RemoteProvider } from '../../models/remoteProvider.js';\nimport { getDefaultRemoteOrHighlander } from '../../utils/remote.utils.js';\nimport type { GitProvider } from '../provider.js';\nimport type { GitRemotesSubProvider } from '../remotes.js';\n\nexport abstract class RemotesGitProviderBase implements GitRemotesSubProvider {\n\tconstructor(\n\t\tprotected readonly context: GitServiceContext,\n\t\tprotected readonly cache: Cache,\n\t\tprotected readonly provider: GitProvider,\n\t) {}\n\n\tabstract getRemotes(\n\t\trepoPath: string | undefined,\n\t\toptions?: { filter?: (remote: GitRemote) => boolean; sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]>;\n\n\t@debug()\n\tasync getRemote(\n\t\trepoPath: string | undefined,\n\t\tname: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst remotes = await this.getRemotes(repoPath, undefined, cancellation);\n\t\treturn remotes.find(r => r.name === name);\n\t}\n\n\t@debug()\n\tasync getDefaultRemote(repoPath: string, cancellation?: AbortSignal): Promise<GitRemote | undefined> {\n\t\tconst remotes = await this.getRemotes(repoPath, undefined, cancellation);\n\t\treturn getDefaultRemoteOrHighlander(remotes);\n\t}\n\n\t@debug()\n\tasync getRemotesWithProviders(\n\t\trepoPath: string,\n\t\toptions?: { sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote<RemoteProvider>[]> {\n\t\tconst remotes = await this.getRemotes(repoPath, options, cancellation);\n\t\treturn remotes.filter((r): r is GitRemote<RemoteProvider> => r.provider != null);\n\t}\n\n\t@debug()\n\tasync getBestRemoteWithProvider(\n\t\trepoPath: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote<RemoteProvider> | undefined> {\n\t\tconst remotes = await this.getBestRemotesWithProviders(repoPath, cancellation);\n\t\treturn remotes[0];\n\t}\n\n\t@debug()\n\tasync getBestRemotesWithProviders(\n\t\trepoPath: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote<RemoteProvider>[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst remotes = this.cache.bestRemotes.getOrCreate(\n\t\t\trepoPath,\n\t\t\tasync (_cacheable, aggregateSignal) => {\n\t\t\t\tconst remotes = await this.getRemotesWithProviders(repoPath, { sort: true }, aggregateSignal);\n\t\t\t\tif (remotes.length === 0) return [];\n\t\t\t\tif (remotes.length === 1) return [...remotes];\n\n\t\t\t\tif (this.context.remotes?.sort != null) {\n\t\t\t\t\treturn this.context.remotes.sort(remotes, aggregateSignal);\n\t\t\t\t}\n\n\t\t\t\t// Fallback: sort by name when no host sort is provided\n\t\t\t\treturn remotes.toSorted((a, b) => sortCompare(a.name, b.name));\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\treturn [...(await remotes)];\n\t}\n\n\t@debug()\n\tasync setRemoteAsDefault(repoPath: string, name: string, value: boolean = true): Promise<void> {\n\t\t// setGkConfig is optional — providers that don't support git config (e.g. GitHub) silently skip persistence\n\t\tawait this.provider.config.setGkConfig?.(repoPath, 'gk.defaultRemote', value ? name : undefined);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes', 'remoteProviders']);\n\t}\n}\n"],"mappings":";;;;;AAUA,IAAsB,yBAAtB,MAA8E;CAEzD;CACA;CACA;CAHpB,YACC,SACA,OACA,UACC;EAHkB,KAAA,UAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACjB;CAQH,MACM,UACL,UACA,MACA,cACiC;EACjC,IAAI,YAAY,MAAM,OAAO,KAAA;EAG7B,QAAO,MADe,KAAK,WAAW,UAAU,KAAA,GAAW,YAAY,EAAA,CACxD,MAAK,MAAK,EAAE,SAAS,IAAI;CACzC;CAEA,MACM,iBAAiB,UAAkB,cAA4D;EACpG,MAAM,UAAU,MAAM,KAAK,WAAW,UAAU,KAAA,GAAW,YAAY;EACvE,OAAO,6BAA6B,OAAO;CAC5C;CAEA,MACM,wBACL,UACA,SACA,cACuC;EAEvC,QAAO,MADe,KAAK,WAAW,UAAU,SAAS,YAAY,EAAA,CACtD,QAAQ,MAAsC,EAAE,YAAY,IAAI;CAChF;CAEA,MACM,0BACL,UACA,cACiD;EAEjD,QAAO,MADe,KAAK,4BAA4B,UAAU,YAAY,EAAA,CAC9D;CAChB;CAEA,MACM,4BACL,UACA,cACuC;EACvC,IAAI,CAAC,UAAU,OAAO,CAAC;EAmBvB,OAAO,CAAC,GAAI,MAjBI,KAAK,MAAM,YAAY,YACtC,UACA,OAAO,YAAY,oBAAoB;GACtC,MAAM,UAAU,MAAM,KAAK,wBAAwB,UAAU,EAAE,MAAM,KAAK,GAAG,eAAe;GAC5F,IAAI,QAAQ,WAAW,GAAG,OAAO,CAAC;GAClC,IAAI,QAAQ,WAAW,GAAG,OAAO,CAAC,GAAG,OAAO;GAE5C,IAAI,KAAK,QAAQ,SAAS,QAAQ,MACjC,OAAO,KAAK,QAAQ,QAAQ,KAAK,SAAS,eAAe;GAI1D,OAAO,QAAQ,UAAU,GAAG,MAAM,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC;EAC9D,GACA,YAGuB,CAAE;CAC3B;CAEA,MACM,mBAAmB,UAAkB,MAAc,QAAiB,MAAqB;EAE9F,MAAM,KAAK,SAAS,OAAO,cAAc,UAAU,oBAAoB,QAAQ,OAAO,KAAA,CAAS;EAC/F,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,SAAS;EACxD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,iBAAiB,CAAC;CACrF;AACD;AAvEE,WAAA,CAAA,MAAM,CAAA,GAAA,uBAAA,WAAA,aAAA,IAAA;
|
|
1
|
+
{"version":3,"file":"remotes.js","names":[],"sources":["../../../../../git/src/providers/shared/remotes.ts"],"sourcesContent":["import { debug } from '@gitlens/utils/decorators/log.js';\nimport { sortCompare } from '@gitlens/utils/string.js';\nimport type { Cache } from '../../cache.js';\nimport type { GitServiceContext } from '../../context.js';\nimport type { GitRemote } from '../../models/remote.js';\nimport type { RemoteProvider } from '../../models/remoteProvider.js';\nimport { getDefaultRemoteOrHighlander } from '../../utils/remote.utils.js';\nimport type { GitProvider } from '../provider.js';\nimport type { GitRemotesSubProvider } from '../remotes.js';\n\nexport abstract class RemotesGitProviderBase implements GitRemotesSubProvider {\n\tconstructor(\n\t\tprotected readonly context: GitServiceContext,\n\t\tprotected readonly cache: Cache,\n\t\tprotected readonly provider: GitProvider,\n\t) {}\n\n\tabstract getRemotes(\n\t\trepoPath: string | undefined,\n\t\toptions?: { filter?: (remote: GitRemote) => boolean; sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]>;\n\n\t@debug({ quiet: true })\n\tasync getRemote(\n\t\trepoPath: string | undefined,\n\t\tname: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst remotes = await this.getRemotes(repoPath, undefined, cancellation);\n\t\treturn remotes.find(r => r.name === name);\n\t}\n\n\t@debug({ quiet: true })\n\tasync getDefaultRemote(repoPath: string, cancellation?: AbortSignal): Promise<GitRemote | undefined> {\n\t\tconst remotes = await this.getRemotes(repoPath, undefined, cancellation);\n\t\treturn getDefaultRemoteOrHighlander(remotes);\n\t}\n\n\t@debug({ quiet: true })\n\tasync getRemotesWithProviders(\n\t\trepoPath: string,\n\t\toptions?: { sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote<RemoteProvider>[]> {\n\t\tconst remotes = await this.getRemotes(repoPath, options, cancellation);\n\t\treturn remotes.filter((r): r is GitRemote<RemoteProvider> => r.provider != null);\n\t}\n\n\t@debug({ quiet: true })\n\tasync getBestRemoteWithProvider(\n\t\trepoPath: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote<RemoteProvider> | undefined> {\n\t\tconst remotes = await this.getBestRemotesWithProviders(repoPath, cancellation);\n\t\treturn remotes[0];\n\t}\n\n\t@debug({ quiet: true })\n\tasync getBestRemotesWithProviders(\n\t\trepoPath: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote<RemoteProvider>[]> {\n\t\tif (!repoPath) return [];\n\n\t\tconst remotes = this.cache.bestRemotes.getOrCreate(\n\t\t\trepoPath,\n\t\t\tasync (_cacheable, aggregateSignal) => {\n\t\t\t\tconst remotes = await this.getRemotesWithProviders(repoPath, { sort: true }, aggregateSignal);\n\t\t\t\tif (remotes.length === 0) return [];\n\t\t\t\tif (remotes.length === 1) return [...remotes];\n\n\t\t\t\tif (this.context.remotes?.sort != null) {\n\t\t\t\t\treturn this.context.remotes.sort(remotes, aggregateSignal);\n\t\t\t\t}\n\n\t\t\t\t// Fallback: sort by name when no host sort is provided\n\t\t\t\treturn remotes.toSorted((a, b) => sortCompare(a.name, b.name));\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\treturn [...(await remotes)];\n\t}\n\n\t@debug()\n\tasync setRemoteAsDefault(repoPath: string, name: string, value: boolean = true): Promise<void> {\n\t\t// setGkConfig is optional — providers that don't support git config (e.g. GitHub) silently skip persistence\n\t\tawait this.provider.config.setGkConfig?.(repoPath, 'gk.defaultRemote', value ? name : undefined);\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes', 'remoteProviders']);\n\t}\n}\n"],"mappings":";;;;;AAUA,IAAsB,yBAAtB,MAA8E;CAEzD;CACA;CACA;CAHpB,YACC,SACA,OACA,UACC;EAHkB,KAAA,UAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACjB;CAQH,MACM,UACL,UACA,MACA,cACiC;EACjC,IAAI,YAAY,MAAM,OAAO,KAAA;EAG7B,QAAO,MADe,KAAK,WAAW,UAAU,KAAA,GAAW,YAAY,EAAA,CACxD,MAAK,MAAK,EAAE,SAAS,IAAI;CACzC;CAEA,MACM,iBAAiB,UAAkB,cAA4D;EACpG,MAAM,UAAU,MAAM,KAAK,WAAW,UAAU,KAAA,GAAW,YAAY;EACvE,OAAO,6BAA6B,OAAO;CAC5C;CAEA,MACM,wBACL,UACA,SACA,cACuC;EAEvC,QAAO,MADe,KAAK,WAAW,UAAU,SAAS,YAAY,EAAA,CACtD,QAAQ,MAAsC,EAAE,YAAY,IAAI;CAChF;CAEA,MACM,0BACL,UACA,cACiD;EAEjD,QAAO,MADe,KAAK,4BAA4B,UAAU,YAAY,EAAA,CAC9D;CAChB;CAEA,MACM,4BACL,UACA,cACuC;EACvC,IAAI,CAAC,UAAU,OAAO,CAAC;EAmBvB,OAAO,CAAC,GAAI,MAjBI,KAAK,MAAM,YAAY,YACtC,UACA,OAAO,YAAY,oBAAoB;GACtC,MAAM,UAAU,MAAM,KAAK,wBAAwB,UAAU,EAAE,MAAM,KAAK,GAAG,eAAe;GAC5F,IAAI,QAAQ,WAAW,GAAG,OAAO,CAAC;GAClC,IAAI,QAAQ,WAAW,GAAG,OAAO,CAAC,GAAG,OAAO;GAE5C,IAAI,KAAK,QAAQ,SAAS,QAAQ,MACjC,OAAO,KAAK,QAAQ,QAAQ,KAAK,SAAS,eAAe;GAI1D,OAAO,QAAQ,UAAU,GAAG,MAAM,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC;EAC9D,GACA,YAGuB,CAAE;CAC3B;CAEA,MACM,mBAAmB,UAAkB,MAAc,QAAiB,MAAqB;EAE9F,MAAM,KAAK,SAAS,OAAO,cAAc,UAAU,oBAAoB,QAAQ,OAAO,KAAA,CAAS;EAC/F,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,SAAS;EACxD,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,iBAAiB,CAAC;CACrF;AACD;AAvEE,WAAA,CAAA,MAAM,EAAE,OAAO,KAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,aAAA,IAAA;AAYrB,WAAA,CAAA,MAAM,EAAE,OAAO,KAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,oBAAA,IAAA;AAMrB,WAAA,CAAA,MAAM,EAAE,OAAO,KAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,2BAAA,IAAA;AAUrB,WAAA,CAAA,MAAM,EAAE,OAAO,KAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,6BAAA,IAAA;AASrB,WAAA,CAAA,MAAM,EAAE,OAAO,KAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,+BAAA,IAAA;AA2BrB,WAAA,CAAA,MAAM,CAAA,GAAA,uBAAA,WAAA,sBAAA,IAAA"}
|
|
@@ -5,7 +5,7 @@ import { ConflictDetectionResult } from "../../git/models/mergeConflicts.js";
|
|
|
5
5
|
import { GitServiceContext } from "../../git/context.js";
|
|
6
6
|
import { GitCommandPriority } from "../../git/run.types.js";
|
|
7
7
|
import { BranchSortOptions } from "../../git/utils/sorting.js";
|
|
8
|
-
import { AheadOfBase, BranchContributionsOverview, GitBranchMergedStatus, GitBranchesSubProvider, GitPushTarget } from "../../git/providers/branches.js";
|
|
8
|
+
import { AheadOfBase, BranchContributionsOverview, GitBranchMergedStatus, GitBranchesSubProvider, GitPushTarget, MergeTarget, MergeTargetOptions } from "../../git/providers/branches.js";
|
|
9
9
|
import { Cache, GkConfigInvalidationTarget } from "../../git/cache.js";
|
|
10
10
|
import { Git } from "../exec/git.js";
|
|
11
11
|
import { CliGitProviderInternal } from "../cliGitProvider.js";
|
|
@@ -18,18 +18,20 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
18
18
|
/** Ahead/behind counts by `<baseSha>...<tipSha>` range, from the per-tip fallback; a pair of commits always counts the same */
|
|
19
19
|
private readonly aheadBehindBySha;
|
|
20
20
|
/**
|
|
21
|
-
* For a base that moved only forward, what its reflog reaches (else `false`), by `<
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* For a base that moved only forward, what its reflog reaches (else `false`), by `<commonPath>\0<ref>`, then by the
|
|
22
|
+
* tip it moved from. A fetch moves one base under every worktree at once, so they share the one check, joining it
|
|
23
|
+
* while it runs. The reads hold for the tip the ref moved to, the reflog they read, stamped by its file's size and
|
|
24
|
+
* mtime (else by the cached ref list, through what it derives so the list itself isn't held, when there's no file
|
|
25
|
+
* to stamp), and the replace refs, which change what's reachable; a change to any of them starts the ref over. Every
|
|
26
|
+
* move appends to the reflog, so a ref moved away and back to the same tip between reads doesn't find the answer
|
|
27
|
+
* taken before
|
|
24
28
|
*/
|
|
25
29
|
private readonly baseMovedForward;
|
|
26
30
|
/**
|
|
27
31
|
* For a base that moved, the count of the commits its new tip lacks for each local branch a worktree has checked
|
|
28
|
-
* out, by tip sha,
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* checked-out branches are counted: the shared walk runs until every counted branch meets the new tip, so an
|
|
32
|
-
* unrelated old or orphan branch no worktree uses would make it deeper than any worktree's own count
|
|
32
|
+
* out, by tip sha, by `<commonPath>\0<newTip>`, with the replace refs it was counted under and the tips it counted.
|
|
33
|
+
* The counts don't depend on the ref or where it moved from, so each worktree the move reached finds its HEAD's
|
|
34
|
+
* count in the one read, even one whose previous answer was taken at another old tip
|
|
33
35
|
*/
|
|
34
36
|
private readonly aheadOfMovedBase;
|
|
35
37
|
/**
|
|
@@ -45,6 +47,11 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
45
47
|
* it once
|
|
46
48
|
*/
|
|
47
49
|
private readonly _branchCreatedFrom;
|
|
50
|
+
/**
|
|
51
|
+
* The branch HEAD was on when each `commonPath\0branch` was first checked out, as git wrote it, for a branch
|
|
52
|
+
* created from `HEAD`; only found ones, since a later checkout can write one
|
|
53
|
+
*/
|
|
54
|
+
private readonly _branchCheckedOutFrom;
|
|
48
55
|
/** Bumped each time a key's created-from is forgotten, so a reflog read in flight across that doesn't store it */
|
|
49
56
|
private readonly _branchCreatedFromGenerations;
|
|
50
57
|
/**
|
|
@@ -75,6 +82,7 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
75
82
|
position: number;
|
|
76
83
|
};
|
|
77
84
|
} | undefined>;
|
|
85
|
+
getFallbackDefaultBranch?: () => Promise<string | undefined>;
|
|
78
86
|
priority?: GitCommandPriority;
|
|
79
87
|
}, cancellation?: AbortSignal): Promise<BranchContributionsOverview | undefined>;
|
|
80
88
|
getBranchesWithCommits(repoPath: string, commits: string[], branch?: string, options?: {
|
|
@@ -140,8 +148,9 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
140
148
|
priority?: GitCommandPriority;
|
|
141
149
|
}, cancellation?: AbortSignal): Promise<string | undefined>;
|
|
142
150
|
/**
|
|
143
|
-
* `
|
|
144
|
-
*
|
|
151
|
+
* The branch `ref` was created from, else the branch HEAD was on when it was first checked out, each as its
|
|
152
|
+
* upstream when it has one. `failed` separates "the reflog ran and had no answer" from "the read never happened" —
|
|
153
|
+
* the caller caches the former forever and must not cache the latter.
|
|
145
154
|
*/
|
|
146
155
|
private getBaseBranchFromReflog;
|
|
147
156
|
/**
|
|
@@ -151,12 +160,37 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
151
160
|
*/
|
|
152
161
|
private getReflogCreatedFrom;
|
|
153
162
|
/**
|
|
154
|
-
* The
|
|
155
|
-
*
|
|
156
|
-
|
|
157
|
-
|
|
163
|
+
* The worktree `branch` is checked out in, whose HEAD reflog holds its checkouts; else the main worktree, never the
|
|
164
|
+
* caller's, since every worktree of the repository shares the answer
|
|
165
|
+
*/
|
|
166
|
+
private getCheckoutPath;
|
|
167
|
+
/**
|
|
168
|
+
* The branch HEAD was on when `branch` was first checked out at `repoPath` (the oldest `checkout: moving from
|
|
169
|
+
* <name> to <branch>` in its HEAD reflog), as git wrote it. `undefined` when there is no such entry. Rejects when the
|
|
170
|
+
* reflog can't be read.
|
|
171
|
+
*/
|
|
172
|
+
private getCheckoutSource;
|
|
173
|
+
/**
|
|
174
|
+
* The branch `branch` was created from, as a base for {@link resolveBase}: the name its own reflog gives, when that
|
|
175
|
+
* is a local or remote-tracking branch in the cached ref list and not `branch` itself or its copy on a remote
|
|
176
|
+
* (`git switch <branch>` creates it from `<remote>/<branch>`). Never the checkout history in HEAD's reflog, which
|
|
177
|
+
* on a long-lived checkout names whatever was checked out last. `fromHead` when the reflog says it was created
|
|
178
|
+
* from `HEAD`.
|
|
158
179
|
*/
|
|
159
180
|
private getCreatedFromTarget;
|
|
181
|
+
/**
|
|
182
|
+
* For a branch its reflog says was created from `HEAD`, the branch HEAD was on when it was first checked out (see
|
|
183
|
+
* {@link getCheckoutSource}), read in the worktree it is checked out in, else the main worktree, and kept as a base
|
|
184
|
+
* like {@link getCreatedFromTarget}'s. Remembered once found, as the created-from name is; a reflog with no such
|
|
185
|
+
* entry yet marks the answer for eviction on the next checkout, which may write one.
|
|
186
|
+
*/
|
|
187
|
+
private getInferredCreatedFrom;
|
|
188
|
+
/**
|
|
189
|
+
* `name` as a base for `branch`: only a local or remote-tracking branch in the cached ref list — a sha, a tag or a
|
|
190
|
+
* revision expression (`main~2`) names no `refs/heads/` or `refs/remotes/` ref — and not `branch` itself or its
|
|
191
|
+
* copy on a remote.
|
|
192
|
+
*/
|
|
193
|
+
private getListedBaseName;
|
|
160
194
|
getAheadOfBaseConfigKey(repoPath: string, cancellation?: AbortSignal): Promise<string | undefined>;
|
|
161
195
|
getAheadOfBaseConfigEntries(repoPath: string, cancellation?: AbortSignal): Promise<readonly (readonly [key: string, value: string | undefined])[] | undefined>;
|
|
162
196
|
/**
|
|
@@ -193,6 +227,16 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
193
227
|
* or git can't say.
|
|
194
228
|
*/
|
|
195
229
|
private getMovedForward;
|
|
230
|
+
/**
|
|
231
|
+
* A stamp of `ref`'s reflog file in the common git directory, by its size and mtime; `undefined` when there's no
|
|
232
|
+
* file to stat (a reftable repository, or a ref without a reflog)
|
|
233
|
+
*/
|
|
234
|
+
private getReflogStamp;
|
|
235
|
+
/**
|
|
236
|
+
* A stamp of the common git directory's `shallow` file, by its size and mtime; `null` when the repository isn't
|
|
237
|
+
* shallow, `undefined` when that can't be read
|
|
238
|
+
*/
|
|
239
|
+
private getShallowStamp;
|
|
196
240
|
/**
|
|
197
241
|
* Reads {@link getMovedForward} from git, in `commonPath`, which holds the refs, their reflogs and the objects for
|
|
198
242
|
* every worktree. Not bound to one caller's cancellation, since every worktree the move reached rides this one
|
|
@@ -201,25 +245,72 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
201
245
|
*/
|
|
202
246
|
private readMovedForward;
|
|
203
247
|
/**
|
|
204
|
-
* For a base moved to `newTip`,
|
|
205
|
-
*
|
|
206
|
-
* its count too. Only those branches are counted: the one walk runs until every counted branch
|
|
207
|
-
* unrelated old or orphan branch would make it deeper than any worktree's own count
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
248
|
+
* For a base moved to `newTip`, the count of the commits `newTip` lacks for `head`, from one count of each local
|
|
249
|
+
* branch a worktree has checked out in `records` (the cached ref list), by tip sha, so a detached HEAD at one of
|
|
250
|
+
* those tips finds its count too. Only those branches are counted: the one walk runs until every counted branch
|
|
251
|
+
* meets `newTip`, so an unrelated old or orphan branch would make it deeper than any worktree's own count. Which
|
|
252
|
+
* branches it counts only bounds that walk, since a commit's count past `newTip` doesn't depend on what else is
|
|
253
|
+
* counted, so a read that counted `head` answers it for a later list (one with a branch created at `newTip` since,
|
|
254
|
+
* say) while the replace refs match; a `head` it didn't count starts a read over the current list's checked-out
|
|
255
|
+
* branches. `undefined` when no checked-out branch is at `head` or `records` can't tell which are checked out, git
|
|
256
|
+
* can't count them in one pass (before 2.41), or git couldn't say.
|
|
211
257
|
*/
|
|
212
258
|
private getAheadOfMovedBase;
|
|
213
259
|
/**
|
|
214
|
-
* Reads {@link getAheadOfMovedBase} from git, in `commonPath`, which holds every
|
|
215
|
-
* one caller's cancellation, since every worktree the move reached rides this one
|
|
260
|
+
* Reads {@link getAheadOfMovedBase} for the `checkedOut` branches from git, in `commonPath`, which holds every
|
|
261
|
+
* worktree's branches. Not bound to one caller's cancellation, since every worktree the move reached rides this one
|
|
262
|
+
* read.
|
|
216
263
|
*/
|
|
217
264
|
private readAheadOfMovedBase;
|
|
265
|
+
getMergeTarget(repoPath: string, branch: string, options?: MergeTargetOptions, cancellation?: AbortSignal): Promise<MergeTarget | undefined>;
|
|
218
266
|
/**
|
|
219
|
-
*
|
|
220
|
-
*
|
|
267
|
+
* Where {@link getMergeTarget} measures `branch` from: its local branch's ref, or — for a remote-tracking branch given
|
|
268
|
+
* by its short name (`origin/feature`) — that ref, with `selfName` its name on the remote
|
|
221
269
|
*/
|
|
222
|
-
private
|
|
270
|
+
private getMergeTargetSource;
|
|
271
|
+
/** Resolves {@link getMergeTarget}'s answer with what it was read from; `pinnable` is false when it can't be confirmed later */
|
|
272
|
+
private resolveMergeTarget;
|
|
273
|
+
/** Whether everything `entry` was read from still reads the same; while nothing changed, every read here is cached */
|
|
274
|
+
private isMergeTargetCurrent;
|
|
275
|
+
/**
|
|
276
|
+
* The base `branch` is measured against from `reads.from`, in {@link getMergeTarget}'s order; `getAheadOfBase`'s
|
|
277
|
+
* options never reach the pull request, the reflog guess or the remote. `selfName` is the name a self check
|
|
278
|
+
* compares with: `branch`, or a remote-tracking branch's name on its remote, which has no stored targets, reflog or
|
|
279
|
+
* upstream of its own. A `'preferred'` target is already known not to be the branch itself at `from`'s commit; any
|
|
280
|
+
* other target isn't checked here.
|
|
281
|
+
*/
|
|
282
|
+
private resolveBase;
|
|
283
|
+
/**
|
|
284
|
+
* The first usable stored candidate, most trusted first: the user's merge target (unless `skipUserTarget`), the
|
|
285
|
+
* detected one, the pull request's base (`getAssociatedPullRequest`, read only when neither is usable), then the
|
|
286
|
+
* recorded base — only its stored value (and with `inferBase`, VS Code's), never `getBaseBranchName`'s reflog
|
|
287
|
+
* guess, which on a long-lived checkout names whatever branch was last checked out from. A remote-tracking branch
|
|
288
|
+
* has no stored keys of its own, so only its pull request's base is tried, and never recorded.
|
|
289
|
+
*/
|
|
290
|
+
private getStoredBaseTarget;
|
|
291
|
+
/**
|
|
292
|
+
* The branch's stored merge keys as read, in {@link storedMergeKeys} order, then VS Code's recorded base when
|
|
293
|
+
* `inferBase`. A failed read is absent, and leaves `reads`' answer unpinned.
|
|
294
|
+
*/
|
|
295
|
+
private readStoredMergeKeys;
|
|
296
|
+
/**
|
|
297
|
+
* The pull request's base as a candidate on the branch's remote; `undefined` when there is none, the branch has no
|
|
298
|
+
* remote, or either can't be read (which leaves `reads`' answer unpinned)
|
|
299
|
+
*/
|
|
300
|
+
private getPullRequestBaseCandidate;
|
|
301
|
+
/**
|
|
302
|
+
* The default branch for {@link resolveBase}: {@link getLocalDefaultBranchName}; when that names none, with
|
|
303
|
+
* `defaultBranch: 'remote'`, the default the first of those remotes reports; then `getFallbackDefaultBranch`. A
|
|
304
|
+
* remote-qualified answer is taken as its local branch when there is one
|
|
305
|
+
*/
|
|
306
|
+
private getDefaultBranchForBase;
|
|
307
|
+
/** `local` when the cached ref list names that branch (depended on either way), else `remoteName` */
|
|
308
|
+
private preferListedLocalBranch;
|
|
309
|
+
/**
|
|
310
|
+
* The branch `branch` was created from (tier `'created'`); with `inferBase`, for one created from `HEAD`, the
|
|
311
|
+
* branch HEAD was on when it was first checked out (tier `'inferred'`)
|
|
312
|
+
*/
|
|
313
|
+
private getCreatedFromSource;
|
|
223
314
|
/**
|
|
224
315
|
* The base for a branch created from `createdFrom`: that branch, unless the default branch forked strictly nearer
|
|
225
316
|
* HEAD, as it does once `createdFrom` merged into it and the branch was rebased onto it. A stacked branch's
|
|
@@ -257,14 +348,13 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
257
348
|
private isSelfRef;
|
|
258
349
|
/** The repo's remote names from the cached remote list; empty when it can't be read */
|
|
259
350
|
private getRemoteNames;
|
|
260
|
-
/** Whether `ref` names `branch` itself (see {@link isSelfRef}) and sits at HEAD's commit; tips are read only after the name matched */
|
|
261
|
-
private isSelfAtHead;
|
|
262
351
|
/**
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
* guess, which on a long-lived checkout names whatever branch was last checked out from. A failed read is absent.
|
|
352
|
+
* Whether `ref` names `selfName` itself (see {@link isSelfRef}) and sits at `reads.from`'s commit; tips are read
|
|
353
|
+
* only after the name matched. HEAD's commit is asked of git, a branch's read from the cached ref list
|
|
266
354
|
*/
|
|
267
|
-
private
|
|
355
|
+
private isSelfAtTip;
|
|
356
|
+
/** The remotes a default branch is read from, in order: `upstream`, `origin`, then the first remote */
|
|
357
|
+
private getPreferredRemotes;
|
|
268
358
|
/**
|
|
269
359
|
* The repo's default branch from local refs only, never the network: the `HEAD` symref of the `upstream` remote,
|
|
270
360
|
* else of `origin`, else of the first remote, as its local branch or else as the remote ref; then, in the same
|
|
@@ -283,16 +373,17 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
283
373
|
/** {@link getNearestForkTarget} with the `upstream` remote's copy of `candidate` as its contender */
|
|
284
374
|
private getUpstreamNearestForkTarget;
|
|
285
375
|
/**
|
|
286
|
-
* A candidate base as the ref
|
|
287
|
-
* nearer
|
|
376
|
+
* A candidate base as the ref `reads.from` is measured against: the candidate or its tracking ref, whichever forked
|
|
377
|
+
* nearer, so a stale local base defers to its upstream while one carrying unpushed work wins over it. A
|
|
288
378
|
* `contender` other than the tracking ref is taken only when it forked strictly nearer than both, so a tie keeps
|
|
289
|
-
* the candidate's own pick. A candidate none forks from is used as-is
|
|
290
|
-
* candidate is unusable.
|
|
379
|
+
* the candidate's own pick. A candidate none forks from is used as-is unless git confirms it names no ref: one the
|
|
380
|
+
* cached ref list names is kept, and so is one whose check fails. `undefined` when the candidate is unusable.
|
|
291
381
|
*/
|
|
292
382
|
private getNearestForkTarget;
|
|
293
383
|
/**
|
|
294
384
|
* `<name>@{u}`, without asking git when the cached ref list shows `name` can't have one: a failed lookup isn't
|
|
295
|
-
* cached, so asking it of a remote-tracking ref (`origin/main`, the usual default) re-spawns on every read.
|
|
385
|
+
* cached, so asking it of a remote-tracking ref (`origin/main`, the usual default) re-spawns on every read. The
|
|
386
|
+
* list's own upstream isn't used: a config-only change (`git branch -u`) doesn't refresh it.
|
|
296
387
|
*/
|
|
297
388
|
private getUpstreamName;
|
|
298
389
|
/**
|
|
@@ -306,8 +397,13 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
306
397
|
* so an empty one is asked of git instead, rather than read as every ref being absent.
|
|
307
398
|
*/
|
|
308
399
|
private getRefTip;
|
|
309
|
-
/**
|
|
400
|
+
/** Where `reads.from` forked from `ref`: git's fork-point reading of `ref`'s reflog when it has one, else their merge base */
|
|
310
401
|
private getForkPoint;
|
|
402
|
+
/**
|
|
403
|
+
* `getMergeBase`, sharing its cached and in-flight reads, but telling git's exit 1 (no common ancestor, or no fork
|
|
404
|
+
* point) from a read that failed. Both answer `undefined`; a failed one also clears `reads.pinnable`.
|
|
405
|
+
*/
|
|
406
|
+
private readMergeBase;
|
|
311
407
|
/**
|
|
312
408
|
* The stored merge target — the user's pick, else the one detected from its PR — skipping any whose branch git
|
|
313
409
|
* confirms is gone so resolution falls through to the next source. A target that couldn't be checked is kept.
|