@gitkraken/core-gitlens 0.7.1 → 0.8.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 +48 -1
- package/dist/git/cache.d.ts +18 -5
- package/dist/git/cache.js +26 -8
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +5 -1
- package/dist/git/context.js.map +1 -1
- package/dist/git/errors.d.ts +28 -1
- package/dist/git/errors.js +45 -1
- package/dist/git/errors.js.map +1 -1
- package/dist/git/providers/branches.d.ts +5 -1
- package/dist/git/providers/commits.d.ts +24 -1
- package/dist/git/providers/config.d.ts +7 -1
- package/dist/git/providers/operations.d.ts +6 -0
- package/dist/git/providers/provider.d.ts +17 -0
- package/dist/git/providers/refs.d.ts +38 -3
- package/dist/git/providers/revision.d.ts +5 -1
- package/dist/git/providers/staging.d.ts +12 -0
- package/dist/git/providers/worktrees.d.ts +23 -3
- package/dist/git/run.types.d.ts +6 -0
- package/dist/git-cli/cliGitProvider.d.ts +17 -1
- package/dist/git-cli/cliGitProvider.js +37 -1
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/git.d.ts +12 -2
- package/dist/git-cli/exec/git.js +48 -17
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/exec/gitQueue.d.ts +4 -1
- package/dist/git-cli/exec/gitQueue.js +1 -1
- package/dist/git-cli/exec/gitQueue.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts +10 -1
- package/dist/git-cli/providers/branches.js +15 -8
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +23 -1
- package/dist/git-cli/providers/commits.js +57 -8
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.js +4 -3
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +1 -0
- package/dist/git-cli/providers/operations.js +39 -3
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/patch.js +20 -41
- 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.d.ts +15 -3
- package/dist/git-cli/providers/refs.js +115 -10
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/revision.d.ts +3 -1
- package/dist/git-cli/providers/revision.js +9 -5
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/staging.d.ts +8 -0
- package/dist/git-cli/providers/staging.js +59 -7
- package/dist/git-cli/providers/staging.js.map +1 -1
- package/dist/git-cli/providers/worktrees.d.ts +31 -2
- package/dist/git-cli/providers/worktrees.js +75 -7
- package/dist/git-cli/providers/worktrees.js.map +1 -1
- package/dist/ipc/discovery.js +1 -1
- package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
- package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
- package/dist/plus/git-github/api/github.d.ts +64 -3
- package/dist/plus/git-github/api/github.js +237 -24
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/providers/github/branches.d.ts +3 -1
- package/dist/plus/git-github/providers/github/branches.js +2 -1
- package/dist/plus/git-github/providers/github/branches.js.map +1 -1
- package/dist/plus/git-github/providers/github/refs.d.ts +10 -3
- package/dist/plus/git-github/providers/github/refs.js +4 -4
- package/dist/plus/git-github/providers/github/refs.js.map +1 -1
- package/dist/plus/git-github/providers/github/revision.d.ts +3 -1
- package/dist/plus/git-github/providers/github/revision.js +1 -1
- package/dist/plus/git-github/providers/github/revision.js.map +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +48 -3
- package/dist/plus/integrations/collectionMetadata.js +138 -8
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/errors.d.ts +3 -1
- package/dist/plus/integrations/errors.js +7 -3
- package/dist/plus/integrations/errors.js.map +1 -1
- package/dist/plus/integrations/index.d.ts +6 -3
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +36 -10
- package/dist/plus/integrations/integrationService.js +16 -3
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +107 -37
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +129 -14
- package/dist/plus/integrations/models/gitHostIntegration.js +142 -18
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +117 -11
- package/dist/plus/integrations/models/integration.js +175 -13
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.d.ts +18 -5
- package/dist/plus/integrations/models/issuesIntegration.js +42 -10
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.d.ts +1 -1
- package/dist/plus/integrations/providers/azure/azure.js +14 -18
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/models.d.ts +29 -0
- package/dist/plus/integrations/providers/azure/models.js +112 -1
- package/dist/plus/integrations/providers/azure/models.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.d.ts +73 -3
- package/dist/plus/integrations/providers/azureDevOps.js +117 -3
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.js +2 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts +61 -0
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js +165 -23
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/models.d.ts +6 -1
- package/dist/plus/integrations/providers/bitbucket/models.js +4 -3
- package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js +2 -2
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +48 -2
- package/dist/plus/integrations/providers/bitbucket-server.js +51 -1
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.d.ts +45 -2
- package/dist/plus/integrations/providers/bitbucket.js +41 -2
- package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +49 -5
- package/dist/plus/integrations/providers/github.js +102 -7
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/gitlab.d.ts +35 -0
- package/dist/plus/integrations/providers/gitlab/gitlab.js +132 -15
- package/dist/plus/integrations/providers/gitlab/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/models.d.ts +1 -0
- package/dist/plus/integrations/providers/gitlab/models.js +1 -1
- package/dist/plus/integrations/providers/gitlab/models.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +49 -2
- package/dist/plus/integrations/providers/gitlab.js +80 -4
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/jira-server.d.ts +3 -3
- package/dist/plus/integrations/providers/jira-server.js +5 -8
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +9 -0
- package/dist/plus/integrations/providers/jira.js +13 -1
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/linear.js +1 -1
- package/dist/plus/integrations/providers/models.d.ts +13 -2
- package/dist/plus/integrations/providers/models.js +11 -1
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providerErrors.d.ts +9 -1
- package/dist/plus/integrations/providers/providerErrors.js +10 -1
- package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +60 -1
- package/dist/plus/integrations/providers/providersApi.js +137 -2
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.d.ts +42 -0
- package/dist/plus/integrations/providers/utils/providerPaging.js +58 -1
- package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
- package/dist/plus/integrations/providers/utils.d.ts +1 -1
- package/dist/plus/integrations/reads/broaden.js +1 -1
- package/dist/plus/integrations/reads/context.d.ts +1 -1
- package/dist/plus/integrations/reads/counts.js +1 -1
- package/dist/plus/integrations/reads/currentAccount.d.ts +35 -0
- package/dist/plus/integrations/reads/currentAccount.js +46 -0
- package/dist/plus/integrations/reads/currentAccount.js.map +1 -0
- package/dist/plus/integrations/reads/drains.d.ts +5 -2
- package/dist/plus/integrations/reads/drains.js +8 -4
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.js +1 -1
- package/dist/plus/integrations/reads/hierarchy.utils.js +1 -1
- package/dist/plus/integrations/reads/issueBatch.d.ts +72 -12
- package/dist/plus/integrations/reads/issueBatch.js +193 -48
- package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +1 -1
- package/dist/plus/integrations/reads/issues.js +1 -1
- package/dist/plus/integrations/reads/pullRequestBatch.d.ts +57 -0
- package/dist/plus/integrations/reads/pullRequestBatch.js +80 -0
- package/dist/plus/integrations/reads/pullRequestBatch.js.map +1 -0
- package/dist/plus/integrations/reads/pullRequestBranches.d.ts +58 -0
- package/dist/plus/integrations/reads/pullRequestBranches.js +111 -0
- package/dist/plus/integrations/reads/pullRequestBranches.js.map +1 -0
- package/dist/plus/integrations/reads/pullRequests.js +3 -3
- package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/resolveRepository.js +1 -1
- package/dist/plus/integrations/reads/sweeps.js +4 -4
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +87 -6
- package/dist/plus/integrations/results.js +9 -2
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/utils/env/node/exec.js +3 -3
- package/dist/utils/env/node/exec.js.map +1 -1
- package/docs/integrations.md +175 -35
- package/docs/kepler-git-write-api-parity.md +239 -0
- package/docs/kepler-read-api-parity.md +75 -28
- package/package.json +1 -1
- package/dist/plus/integrations/reads/trackerIssue.d.ts +0 -33
- package/dist/plus/integrations/reads/trackerIssue.js +0 -60
- package/dist/plus/integrations/reads/trackerIssue.js.map +0 -1
|
@@ -10,7 +10,9 @@ export declare class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
10
10
|
private readonly cache;
|
|
11
11
|
private readonly provider;
|
|
12
12
|
constructor(cache: Cache, provider: GitHubGitProviderInternal);
|
|
13
|
-
getBranch(repoPath: string, name?: string,
|
|
13
|
+
getBranch(repoPath: string, name?: string, options?: {
|
|
14
|
+
force?: boolean;
|
|
15
|
+
}, cancellation?: AbortSignal): Promise<GitBranch | undefined>;
|
|
14
16
|
getBranches(repoPath: string | undefined, options?: {
|
|
15
17
|
filter?: (b: GitBranch) => boolean;
|
|
16
18
|
ordering?: 'date' | 'author-date' | 'topo' | null;
|
|
@@ -16,8 +16,9 @@ var BranchesGitSubProvider = class {
|
|
|
16
16
|
this.cache = cache;
|
|
17
17
|
this.provider = provider;
|
|
18
18
|
}
|
|
19
|
-
async getBranch(repoPath, name, cancellation) {
|
|
19
|
+
async getBranch(repoPath, name, options, cancellation) {
|
|
20
20
|
const scope = getScopedLogger();
|
|
21
|
+
if (options?.force) this.cache.evictCaches(repoPath, "branches");
|
|
21
22
|
if (name != null) {
|
|
22
23
|
const { values: [branch] } = await this.getBranches(repoPath, { filter: (b) => b.name === name }, cancellation);
|
|
23
24
|
return branch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branches.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/branches.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport { GitBranch } from '@gitlens/git/models/branch.js';\nimport type { BranchContributionsOverview, GitBranchesSubProvider } from '@gitlens/git/providers/branches.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { createRevisionRange, stripOrigin } from '@gitlens/git/utils/revision.utils.js';\nimport type { BranchSortOptions } from '@gitlens/git/utils/sorting.js';\nimport { sortBranches, sortContributors } from '@gitlens/git/utils/sorting.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { PagedResult, PagingOptions } from '@gitlens/utils/paging.js';\nimport { emptyPagedResult } from '@gitlens/utils/paging.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { CacheController } from '@gitlens/utils/promiseCache.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport { HeadType } from '../../context.js';\nimport type { GitHubBranch } from '../../models.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nexport class BranchesGitSubProvider implements GitBranchesSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync getBranch(repoPath: string, name?: string, cancellation?: AbortSignal): Promise<GitBranch | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tif (name != null) {\n\t\t\tconst {\n\t\t\t\tvalues: [branch],\n\t\t\t} = await this.getBranches(repoPath, { filter: b => b.name === name }, cancellation);\n\t\t\treturn branch;\n\t\t}\n\n\t\treturn this.cache.branch.getOrCreate(\n\t\t\trepoPath,\n\t\t\tasync (_cacheable, signal): Promise<GitBranch | undefined> => {\n\t\t\t\t// Prefer the cache-provided aggregate signal (only fires when every joined\n\t\t\t\t// caller aborts); fall back to this caller's cancellation for the first-caller path.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst {\n\t\t\t\t\tvalues: [branch],\n\t\t\t\t} = await this.getBranches(repoPath, { filter: b => b.current }, signal);\n\t\t\t\tif (branch != null) return branch;\n\n\t\t\t\ttry {\n\t\t\t\t\tconst { metadata } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\t\t\tconst revision = await metadata.getRevision();\n\t\t\t\t\tswitch (revision.type) {\n\t\t\t\t\t\tcase HeadType.Tag:\n\t\t\t\t\t\tcase HeadType.Commit:\n\t\t\t\t\t\t\treturn new GitBranch(\n\t\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t\t`refs/heads/${revision.name}`,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\trevision.revision,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn undefined;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tdebugger;\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync getBranches(\n\t\trepoPath: string | undefined,\n\t\toptions?: {\n\t\t\tfilter?: (b: GitBranch) => boolean;\n\t\t\tordering?: 'date' | 'author-date' | 'topo' | null;\n\t\t\tpaging?: PagingOptions;\n\t\t\tsort?: boolean | BranchSortOptions;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PagedResult<GitBranch>> {\n\t\tif (repoPath == null) return emptyPagedResult;\n\n\t\tconst path = repoPath;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst load = async (cacheable?: CacheController): Promise<PagedResult<GitBranch>> => {\n\t\t\ttry {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(path);\n\n\t\t\t\tconst branches: GitBranch[] = [];\n\n\t\t\t\tconst commitOrdering = options?.ordering;\n\n\t\t\t\tfunction addBranches(branch: GitHubBranch, current: boolean) {\n\t\t\t\t\tconst date = new Date(\n\t\t\t\t\t\tcommitOrdering === 'author-date' ? branch.target.authoredDate : branch.target.committedDate,\n\t\t\t\t\t);\n\t\t\t\t\tconst ref = branch.target.oid;\n\n\t\t\t\t\tbranches.push(\n\t\t\t\t\t\tnew GitBranch(\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\t`refs/heads/${branch.name}`,\n\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\tdate,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tref,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: `origin/${branch.name}`,\n\t\t\t\t\t\t\t\tmissing: false,\n\t\t\t\t\t\t\t\tstate: { ahead: 0, behind: 0 },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew GitBranch(\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\t`refs/remotes/origin/${branch.name}`,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tdate,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tref,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tlet currentBranch: string | undefined;\n\n\t\t\t\tconst revision = await metadata.getRevision();\n\t\t\t\tswitch (revision.type) {\n\t\t\t\t\tcase HeadType.Branch:\n\t\t\t\t\t\tcurrentBranch = revision.name;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HeadType.RemoteBranch: {\n\t\t\t\t\t\tconst index = revision.name.indexOf(':');\n\t\t\t\t\t\tcurrentBranch = index === -1 ? revision.name : revision.name.substring(index + 1);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet cursor = options?.paging?.cursor;\n\t\t\t\tconst loadAll = cursor == null;\n\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst result = await github.getBranches(\n\t\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\t\t{ cursor: cursor },\n\t\t\t\t\t);\n\n\t\t\t\t\tfor (const branch of result.values) {\n\t\t\t\t\t\taddBranches(branch, branch.name === currentBranch);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!result.paging?.more || !loadAll) return { ...result, values: branches };\n\n\t\t\t\t\tcursor = result.paging.cursor;\n\t\t\t\t}\n\t\t\t} catch (ex) {\n\t\t\t\tscope?.error(ex);\n\t\t\t\tdebugger;\n\n\t\t\t\t// Mark the cache entry invalidated so the empty fallback self-evicts on settle\n\t\t\t\t// rather than getting stuck serving stale emptiness to subsequent callers.\n\t\t\t\tcacheable?.invalidate();\n\t\t\t\treturn emptyPagedResult;\n\t\t\t}\n\t\t};\n\n\t\t// Compose cache key with cursor so re-loads of the same page hit the cache;\n\t\t// `repoPath` (no suffix) is reserved for the full \"all branches\" entry.\n\t\t// TODO: `cache.branches` is `PromiseMap<RepoPath, ...>` keyed exactly by repoPath, so\n\t\t// `clearCaches('branches')` / `unregisterRepoPath` will not invalidate composite-key entries.\n\t\t// Acceptable today because branches don't change during a virtual-repo session, but the entries\n\t\t// leak in memory until provider GC. Long-term: switch to RepoPromiseCacheMap or add prefix-invalidate.\n\t\tconst cacheKey = options?.paging?.cursor != null ? `${path}#${options.paging.cursor}` : path;\n\t\tconst branchesPromise = this.cache.branches.getOrCreate(cacheKey, cacheable => load(cacheable), cancellation);\n\n\t\tlet result = await branchesPromise;\n\t\tif (options?.filter != null) {\n\t\t\tresult = {\n\t\t\t\t...result,\n\t\t\t\tvalues: result.values.filter(options.filter),\n\t\t\t};\n\t\t}\n\n\t\tif (options?.sort != null) {\n\t\t\tsortBranches(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@debug()\n\tasync getBranchContributionsOverview(\n\t\trepoPath: string,\n\t\tref: string,\n\t\t// `priority` is unused — the GitHub provider doesn't go through the local git command\n\t\t// queue, so the priority signal has no effect here. Accepted for interface compatibility.\n\t\toptions?: {\n\t\t\tassociatedPullRequest?: Promise<{ refs?: { base?: { branch: string } } } | undefined>;\n\t\t\tpriority?: GitCommandPriority;\n\t\t},\n\t\t_cancellation?: AbortSignal,\n\t): Promise<BranchContributionsOverview | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Expensive body — runs only on cache miss. Closes over `mergeTarget` so the cache key\n\t\t// (`${ref}|${mergeTarget}`) fully captures every input that affects the result.\n\t\tconst fetchBody = async (mergeTarget: string): Promise<BranchContributionsOverview | undefined> => {\n\t\t\tconst mergeBase = await this.provider.refs.getMergeBase(repoPath, ref, mergeTarget);\n\t\t\tif (mergeBase == null) return undefined;\n\n\t\t\t// Fetch the merge-base commit's committer date in parallel with contributors so consumers\n\t\t\t// that just need the date for the scope window don't pay a separate round-trip.\n\t\t\t// `allSettled` so a transient failure in one side doesn't drop the overview entirely.\n\t\t\tconst [contributorsSettled, mergeBaseCommitSettled] = await Promise.allSettled([\n\t\t\t\tthis.provider.contributors.getContributors(repoPath, createRevisionRange(mergeBase, ref, '..'), {\n\t\t\t\t\tstats: true,\n\t\t\t\t}),\n\t\t\t\tthis.provider.commits.getCommit(repoPath, mergeBase),\n\t\t\t]);\n\n\t\t\tconst result = getSettledValue(contributorsSettled) ?? { contributors: [] };\n\t\t\tconst mergeBaseCommit = getSettledValue(mergeBaseCommitSettled);\n\n\t\t\tsortContributors(result.contributors, { orderBy: 'score:desc' });\n\n\t\t\tlet totalCommits = 0;\n\t\t\tlet totalFiles = 0;\n\t\t\tlet totalAdditions = 0;\n\t\t\tlet totalDeletions = 0;\n\t\t\tlet firstCommitTimestamp;\n\t\t\tlet latestCommitTimestamp;\n\n\t\t\tfor (const c of result.contributors) {\n\t\t\t\ttotalCommits += c.contributionCount;\n\t\t\t\ttotalFiles += c.stats?.files ?? 0;\n\t\t\t\ttotalAdditions += c.stats?.additions ?? 0;\n\t\t\t\ttotalDeletions += c.stats?.deletions ?? 0;\n\n\t\t\t\tconst firstTimestamp = c.firstCommitDate?.getTime();\n\t\t\t\tconst latestTimestamp = c.latestCommitDate?.getTime();\n\n\t\t\t\tif (firstTimestamp != null || latestTimestamp != null) {\n\t\t\t\t\tfirstCommitTimestamp =\n\t\t\t\t\t\tfirstCommitTimestamp != null\n\t\t\t\t\t\t\t? Math.min(firstCommitTimestamp, firstTimestamp ?? Infinity, latestTimestamp ?? Infinity)\n\t\t\t\t\t\t\t: (firstTimestamp ?? latestTimestamp);\n\n\t\t\t\t\tlatestCommitTimestamp =\n\t\t\t\t\t\tlatestCommitTimestamp != null\n\t\t\t\t\t\t\t? Math.max(latestCommitTimestamp, firstTimestamp ?? -Infinity, latestTimestamp ?? -Infinity)\n\t\t\t\t\t\t\t: (latestTimestamp ?? firstTimestamp);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tbranch: ref,\n\t\t\t\tmergeTarget: mergeTarget,\n\t\t\t\tmergeBase: mergeBase,\n\t\t\t\tmergeBaseDate: mergeBaseCommit?.committer?.date ?? mergeBaseCommit?.author?.date,\n\n\t\t\t\tcommits: totalCommits,\n\t\t\t\tfiles: totalFiles,\n\t\t\t\tadditions: totalAdditions,\n\t\t\t\tdeletions: totalDeletions,\n\n\t\t\t\tlatestCommitDate: latestCommitTimestamp != null ? new Date(latestCommitTimestamp) : undefined,\n\t\t\t\tfirstCommitDate: firstCommitTimestamp != null ? new Date(firstCommitTimestamp) : undefined,\n\n\t\t\t\tcontributors: result.contributors,\n\t\t\t};\n\t\t};\n\n\t\ttry {\n\t\t\t// Resolve `mergeTarget` (PR base or default branch). Only the expensive body below is\n\t\t\t// cached — keyed on `${ref}|${mergeTarget}` so callers that resolve to the same target\n\t\t\t// share the result, while differing targets get independent slots.\n\t\t\tlet mergeTarget: string | undefined;\n\n\t\t\tif (options?.associatedPullRequest != null) {\n\t\t\t\tconst pr = await options.associatedPullRequest;\n\t\t\t\tif (pr?.refs?.base != null) {\n\t\t\t\t\tmergeTarget = pr.refs.base.branch;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmergeTarget ??= await this.getDefaultBranchName(repoPath);\n\t\t\tif (mergeTarget == null) return undefined;\n\n\t\t\t// Safe to cache despite PR retargeting: the cache key includes the resolved `mergeTarget`,\n\t\t\t// so a retargeted PR resolves to a fresh slot and the old entry is stale-but-unused (and\n\t\t\t// TTL-evicts). The prior \"no outer cache here\" rationale assumed a `ref`-only key.\n\t\t\tconst resolvedTarget = mergeTarget;\n\t\t\treturn await this.cache.getBranchOverview(repoPath, `${ref}|${resolvedTarget}`, () =>\n\t\t\t\tfetchBody(resolvedTarget),\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getBranchesWithCommits(\n\t\trepoPath: string,\n\t\tshas: string[],\n\t\tbranch?: string | undefined,\n\t\toptions?:\n\t\t\t| { all?: boolean; commitDate?: Date; mode?: 'contains' | 'pointsAt' }\n\t\t\t| { commitDate?: Date; mode?: 'contains' | 'pointsAt'; remotes?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string[]> {\n\t\tif (repoPath == null || options?.commitDate == null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\tlet branches;\n\n\t\t\tif (branch) {\n\t\t\t\tbranches = await github.getBranchWithCommit(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tbranch,\n\t\t\t\t\tshas.map(stripOrigin),\n\t\t\t\t\toptions?.mode ?? 'contains',\n\t\t\t\t\toptions?.commitDate,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tbranches = await github.getBranchesWithCommits(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tshas.map(stripOrigin),\n\t\t\t\t\toptions?.mode ?? 'contains',\n\t\t\t\t\toptions?.commitDate,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn branches;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t@debug()\n\tasync getDefaultBranchName(\n\t\trepoPath: string | undefined,\n\t\tremote?: string,\n\t\t// `priority` is unused — the GitHub provider doesn't go through the local git command queue, so the\n\t\t// priority signal has no effect here. `local` asks for a network-free resolution (the graph's hot\n\t\t// path): a remote repo has no local symref to read, so honor that contract by returning undefined\n\t\t// rather than making the API round-trip the caller explicitly asked to avoid.\n\t\toptions?: { priority?: GitCommandPriority; local?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tif (repoPath == null) return undefined;\n\t\tif (options?.local) return undefined;\n\n\t\tremote ??= 'origin';\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// Throw inside the factory so RepoPromiseCacheMap's default `expireOnError` evicts the\n\t\t// entry — a transient API failure shouldn't poison the cache for the rest of the session.\n\t\t// The outer try/catch preserves the existing `undefined`-on-error contract for callers.\n\t\ttry {\n\t\t\treturn await this.cache.getDefaultBranchName(repoPath, remote, async () => {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\t\treturn github.getDefaultBranchName(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t);\n\t\t\t});\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"branches.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/branches.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport { GitBranch } from '@gitlens/git/models/branch.js';\nimport type { BranchContributionsOverview, GitBranchesSubProvider } from '@gitlens/git/providers/branches.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { createRevisionRange, stripOrigin } from '@gitlens/git/utils/revision.utils.js';\nimport type { BranchSortOptions } from '@gitlens/git/utils/sorting.js';\nimport { sortBranches, sortContributors } from '@gitlens/git/utils/sorting.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { PagedResult, PagingOptions } from '@gitlens/utils/paging.js';\nimport { emptyPagedResult } from '@gitlens/utils/paging.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { CacheController } from '@gitlens/utils/promiseCache.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport { HeadType } from '../../context.js';\nimport type { GitHubBranch } from '../../models.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nexport class BranchesGitSubProvider implements GitBranchesSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync getBranch(\n\t\trepoPath: string,\n\t\tname?: string,\n\t\toptions?: { force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitBranch | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tif (options?.force) {\n\t\t\tthis.cache.evictCaches(repoPath, 'branches');\n\t\t}\n\n\t\tif (name != null) {\n\t\t\tconst {\n\t\t\t\tvalues: [branch],\n\t\t\t} = await this.getBranches(repoPath, { filter: b => b.name === name }, cancellation);\n\t\t\treturn branch;\n\t\t}\n\n\t\treturn this.cache.branch.getOrCreate(\n\t\t\trepoPath,\n\t\t\tasync (_cacheable, signal): Promise<GitBranch | undefined> => {\n\t\t\t\t// Prefer the cache-provided aggregate signal (only fires when every joined\n\t\t\t\t// caller aborts); fall back to this caller's cancellation for the first-caller path.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst {\n\t\t\t\t\tvalues: [branch],\n\t\t\t\t} = await this.getBranches(repoPath, { filter: b => b.current }, signal);\n\t\t\t\tif (branch != null) return branch;\n\n\t\t\t\ttry {\n\t\t\t\t\tconst { metadata } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\t\t\tconst revision = await metadata.getRevision();\n\t\t\t\t\tswitch (revision.type) {\n\t\t\t\t\t\tcase HeadType.Tag:\n\t\t\t\t\t\tcase HeadType.Commit:\n\t\t\t\t\t\t\treturn new GitBranch(\n\t\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t\t`refs/heads/${revision.name}`,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\trevision.revision,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn undefined;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tdebugger;\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync getBranches(\n\t\trepoPath: string | undefined,\n\t\toptions?: {\n\t\t\tfilter?: (b: GitBranch) => boolean;\n\t\t\tordering?: 'date' | 'author-date' | 'topo' | null;\n\t\t\tpaging?: PagingOptions;\n\t\t\tsort?: boolean | BranchSortOptions;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PagedResult<GitBranch>> {\n\t\tif (repoPath == null) return emptyPagedResult;\n\n\t\tconst path = repoPath;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst load = async (cacheable?: CacheController): Promise<PagedResult<GitBranch>> => {\n\t\t\ttry {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(path);\n\n\t\t\t\tconst branches: GitBranch[] = [];\n\n\t\t\t\tconst commitOrdering = options?.ordering;\n\n\t\t\t\tfunction addBranches(branch: GitHubBranch, current: boolean) {\n\t\t\t\t\tconst date = new Date(\n\t\t\t\t\t\tcommitOrdering === 'author-date' ? branch.target.authoredDate : branch.target.committedDate,\n\t\t\t\t\t);\n\t\t\t\t\tconst ref = branch.target.oid;\n\n\t\t\t\t\tbranches.push(\n\t\t\t\t\t\tnew GitBranch(\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\t`refs/heads/${branch.name}`,\n\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\tdate,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tref,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: `origin/${branch.name}`,\n\t\t\t\t\t\t\t\tmissing: false,\n\t\t\t\t\t\t\t\tstate: { ahead: 0, behind: 0 },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew GitBranch(\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\t`refs/remotes/origin/${branch.name}`,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tdate,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tref,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tlet currentBranch: string | undefined;\n\n\t\t\t\tconst revision = await metadata.getRevision();\n\t\t\t\tswitch (revision.type) {\n\t\t\t\t\tcase HeadType.Branch:\n\t\t\t\t\t\tcurrentBranch = revision.name;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HeadType.RemoteBranch: {\n\t\t\t\t\t\tconst index = revision.name.indexOf(':');\n\t\t\t\t\t\tcurrentBranch = index === -1 ? revision.name : revision.name.substring(index + 1);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet cursor = options?.paging?.cursor;\n\t\t\t\tconst loadAll = cursor == null;\n\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst result = await github.getBranches(\n\t\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\t\t{ cursor: cursor },\n\t\t\t\t\t);\n\n\t\t\t\t\tfor (const branch of result.values) {\n\t\t\t\t\t\taddBranches(branch, branch.name === currentBranch);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!result.paging?.more || !loadAll) return { ...result, values: branches };\n\n\t\t\t\t\tcursor = result.paging.cursor;\n\t\t\t\t}\n\t\t\t} catch (ex) {\n\t\t\t\tscope?.error(ex);\n\t\t\t\tdebugger;\n\n\t\t\t\t// Mark the cache entry invalidated so the empty fallback self-evicts on settle\n\t\t\t\t// rather than getting stuck serving stale emptiness to subsequent callers.\n\t\t\t\tcacheable?.invalidate();\n\t\t\t\treturn emptyPagedResult;\n\t\t\t}\n\t\t};\n\n\t\t// Compose cache key with cursor so re-loads of the same page hit the cache;\n\t\t// `repoPath` (no suffix) is reserved for the full \"all branches\" entry.\n\t\t// TODO: `cache.branches` is `PromiseMap<RepoPath, ...>` keyed exactly by repoPath, so\n\t\t// `clearCaches('branches')` / `unregisterRepoPath` will not invalidate composite-key entries.\n\t\t// Acceptable today because branches don't change during a virtual-repo session, but the entries\n\t\t// leak in memory until provider GC. Long-term: switch to RepoPromiseCacheMap or add prefix-invalidate.\n\t\tconst cacheKey = options?.paging?.cursor != null ? `${path}#${options.paging.cursor}` : path;\n\t\tconst branchesPromise = this.cache.branches.getOrCreate(cacheKey, cacheable => load(cacheable), cancellation);\n\n\t\tlet result = await branchesPromise;\n\t\tif (options?.filter != null) {\n\t\t\tresult = {\n\t\t\t\t...result,\n\t\t\t\tvalues: result.values.filter(options.filter),\n\t\t\t};\n\t\t}\n\n\t\tif (options?.sort != null) {\n\t\t\tsortBranches(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@debug()\n\tasync getBranchContributionsOverview(\n\t\trepoPath: string,\n\t\tref: string,\n\t\t// `priority` is unused — the GitHub provider doesn't go through the local git command\n\t\t// queue, so the priority signal has no effect here. Accepted for interface compatibility.\n\t\toptions?: {\n\t\t\tassociatedPullRequest?: Promise<{ refs?: { base?: { branch: string } } } | undefined>;\n\t\t\tpriority?: GitCommandPriority;\n\t\t},\n\t\t_cancellation?: AbortSignal,\n\t): Promise<BranchContributionsOverview | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Expensive body — runs only on cache miss. Closes over `mergeTarget` so the cache key\n\t\t// (`${ref}|${mergeTarget}`) fully captures every input that affects the result.\n\t\tconst fetchBody = async (mergeTarget: string): Promise<BranchContributionsOverview | undefined> => {\n\t\t\tconst mergeBase = await this.provider.refs.getMergeBase(repoPath, ref, mergeTarget);\n\t\t\tif (mergeBase == null) return undefined;\n\n\t\t\t// Fetch the merge-base commit's committer date in parallel with contributors so consumers\n\t\t\t// that just need the date for the scope window don't pay a separate round-trip.\n\t\t\t// `allSettled` so a transient failure in one side doesn't drop the overview entirely.\n\t\t\tconst [contributorsSettled, mergeBaseCommitSettled] = await Promise.allSettled([\n\t\t\t\tthis.provider.contributors.getContributors(repoPath, createRevisionRange(mergeBase, ref, '..'), {\n\t\t\t\t\tstats: true,\n\t\t\t\t}),\n\t\t\t\tthis.provider.commits.getCommit(repoPath, mergeBase),\n\t\t\t]);\n\n\t\t\tconst result = getSettledValue(contributorsSettled) ?? { contributors: [] };\n\t\t\tconst mergeBaseCommit = getSettledValue(mergeBaseCommitSettled);\n\n\t\t\tsortContributors(result.contributors, { orderBy: 'score:desc' });\n\n\t\t\tlet totalCommits = 0;\n\t\t\tlet totalFiles = 0;\n\t\t\tlet totalAdditions = 0;\n\t\t\tlet totalDeletions = 0;\n\t\t\tlet firstCommitTimestamp;\n\t\t\tlet latestCommitTimestamp;\n\n\t\t\tfor (const c of result.contributors) {\n\t\t\t\ttotalCommits += c.contributionCount;\n\t\t\t\ttotalFiles += c.stats?.files ?? 0;\n\t\t\t\ttotalAdditions += c.stats?.additions ?? 0;\n\t\t\t\ttotalDeletions += c.stats?.deletions ?? 0;\n\n\t\t\t\tconst firstTimestamp = c.firstCommitDate?.getTime();\n\t\t\t\tconst latestTimestamp = c.latestCommitDate?.getTime();\n\n\t\t\t\tif (firstTimestamp != null || latestTimestamp != null) {\n\t\t\t\t\tfirstCommitTimestamp =\n\t\t\t\t\t\tfirstCommitTimestamp != null\n\t\t\t\t\t\t\t? Math.min(firstCommitTimestamp, firstTimestamp ?? Infinity, latestTimestamp ?? Infinity)\n\t\t\t\t\t\t\t: (firstTimestamp ?? latestTimestamp);\n\n\t\t\t\t\tlatestCommitTimestamp =\n\t\t\t\t\t\tlatestCommitTimestamp != null\n\t\t\t\t\t\t\t? Math.max(latestCommitTimestamp, firstTimestamp ?? -Infinity, latestTimestamp ?? -Infinity)\n\t\t\t\t\t\t\t: (latestTimestamp ?? firstTimestamp);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tbranch: ref,\n\t\t\t\tmergeTarget: mergeTarget,\n\t\t\t\tmergeBase: mergeBase,\n\t\t\t\tmergeBaseDate: mergeBaseCommit?.committer?.date ?? mergeBaseCommit?.author?.date,\n\n\t\t\t\tcommits: totalCommits,\n\t\t\t\tfiles: totalFiles,\n\t\t\t\tadditions: totalAdditions,\n\t\t\t\tdeletions: totalDeletions,\n\n\t\t\t\tlatestCommitDate: latestCommitTimestamp != null ? new Date(latestCommitTimestamp) : undefined,\n\t\t\t\tfirstCommitDate: firstCommitTimestamp != null ? new Date(firstCommitTimestamp) : undefined,\n\n\t\t\t\tcontributors: result.contributors,\n\t\t\t};\n\t\t};\n\n\t\ttry {\n\t\t\t// Resolve `mergeTarget` (PR base or default branch). Only the expensive body below is\n\t\t\t// cached — keyed on `${ref}|${mergeTarget}` so callers that resolve to the same target\n\t\t\t// share the result, while differing targets get independent slots.\n\t\t\tlet mergeTarget: string | undefined;\n\n\t\t\tif (options?.associatedPullRequest != null) {\n\t\t\t\tconst pr = await options.associatedPullRequest;\n\t\t\t\tif (pr?.refs?.base != null) {\n\t\t\t\t\tmergeTarget = pr.refs.base.branch;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmergeTarget ??= await this.getDefaultBranchName(repoPath);\n\t\t\tif (mergeTarget == null) return undefined;\n\n\t\t\t// Safe to cache despite PR retargeting: the cache key includes the resolved `mergeTarget`,\n\t\t\t// so a retargeted PR resolves to a fresh slot and the old entry is stale-but-unused (and\n\t\t\t// TTL-evicts). The prior \"no outer cache here\" rationale assumed a `ref`-only key.\n\t\t\tconst resolvedTarget = mergeTarget;\n\t\t\treturn await this.cache.getBranchOverview(repoPath, `${ref}|${resolvedTarget}`, () =>\n\t\t\t\tfetchBody(resolvedTarget),\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@debug()\n\tasync getBranchesWithCommits(\n\t\trepoPath: string,\n\t\tshas: string[],\n\t\tbranch?: string | undefined,\n\t\toptions?:\n\t\t\t| { all?: boolean; commitDate?: Date; mode?: 'contains' | 'pointsAt' }\n\t\t\t| { commitDate?: Date; mode?: 'contains' | 'pointsAt'; remotes?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string[]> {\n\t\tif (repoPath == null || options?.commitDate == null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\tlet branches;\n\n\t\t\tif (branch) {\n\t\t\t\tbranches = await github.getBranchWithCommit(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tbranch,\n\t\t\t\t\tshas.map(stripOrigin),\n\t\t\t\t\toptions?.mode ?? 'contains',\n\t\t\t\t\toptions?.commitDate,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tbranches = await github.getBranchesWithCommits(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tshas.map(stripOrigin),\n\t\t\t\t\toptions?.mode ?? 'contains',\n\t\t\t\t\toptions?.commitDate,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn branches;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t@debug()\n\tasync getDefaultBranchName(\n\t\trepoPath: string | undefined,\n\t\tremote?: string,\n\t\t// `priority` is unused — the GitHub provider doesn't go through the local git command queue, so the\n\t\t// priority signal has no effect here. `local` asks for a network-free resolution (the graph's hot\n\t\t// path): a remote repo has no local symref to read, so honor that contract by returning undefined\n\t\t// rather than making the API round-trip the caller explicitly asked to avoid.\n\t\toptions?: { priority?: GitCommandPriority; local?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tif (repoPath == null) return undefined;\n\t\tif (options?.local) return undefined;\n\n\t\tremote ??= 'origin';\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// Throw inside the factory so RepoPromiseCacheMap's default `expireOnError` evicts the\n\t\t// entry — a transient API failure shouldn't poison the cache for the rest of the session.\n\t\t// The outer try/catch preserves the existing `undefined`-on-error contract for callers.\n\t\ttry {\n\t\t\treturn await this.cache.getDefaultBranchName(repoPath, remote, async () => {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\t\treturn github.getDefaultBranchName(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t);\n\t\t\t});\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -15,7 +15,9 @@ export declare class RefsGitSubProvider implements GitRefsSubProvider {
|
|
|
15
15
|
forkPoint?: boolean;
|
|
16
16
|
priority?: GitCommandPriority;
|
|
17
17
|
}, _cancellation?: AbortSignal): Promise<string | undefined>;
|
|
18
|
-
getReference(repoPath: string, ref: string,
|
|
18
|
+
getReference(repoPath: string, ref: string, options?: {
|
|
19
|
+
force?: boolean;
|
|
20
|
+
}, _cancellation?: AbortSignal): Promise<GitReference | undefined>;
|
|
19
21
|
getRefTips(_repoPath: string, _options?: {
|
|
20
22
|
include?: ReadonlyArray<'heads' | 'remotes' | 'tags'>;
|
|
21
23
|
}, _cancellation?: AbortSignal): Promise<GitRefTip[]>;
|
|
@@ -29,8 +31,13 @@ export declare class RefsGitSubProvider implements GitRefsSubProvider {
|
|
|
29
31
|
};
|
|
30
32
|
}, cancellation?: AbortSignal): Promise<boolean>;
|
|
31
33
|
isValidReference(_repoPath: string, _ref: string, _pathOrUri?: string, _cancellation?: AbortSignal): Promise<boolean>;
|
|
32
|
-
validateReference(_repoPath: string, ref: string,
|
|
33
|
-
|
|
34
|
+
validateReference(_repoPath: string, ref: string, _options?: {
|
|
35
|
+
relativePath?: string;
|
|
36
|
+
force?: boolean;
|
|
37
|
+
}, _cancellation?: AbortSignal): Promise<string | undefined>;
|
|
38
|
+
updateReference(_repoPath: string, _ref: string, _sha: string, _options?: {
|
|
39
|
+
expected?: string | 'absent';
|
|
40
|
+
}, _cancellation?: AbortSignal): Promise<void>;
|
|
34
41
|
}
|
|
35
42
|
//#endregion
|
|
36
43
|
//# sourceMappingURL=refs.d.ts.map
|
|
@@ -36,11 +36,11 @@ var RefsGitSubProvider = class {
|
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
|
-
async getReference(repoPath, ref, _cancellation) {
|
|
39
|
+
async getReference(repoPath, ref, options, _cancellation) {
|
|
40
40
|
if (!ref || ref === "0000000000000000000000000000000000000000-") return void 0;
|
|
41
41
|
if (!await this.isValidReference(repoPath, ref)) return void 0;
|
|
42
42
|
if (ref !== "HEAD" && !isShaWithOptionalRevisionSuffix(ref)) {
|
|
43
|
-
const branch = await this.provider.branches.getBranch(repoPath, ref);
|
|
43
|
+
const branch = await this.provider.branches.getBranch(repoPath, ref, options?.force ? { force: true } : void 0);
|
|
44
44
|
if (branch != null) return createReference(branch.ref, repoPath, {
|
|
45
45
|
id: branch.id,
|
|
46
46
|
refType: "branch",
|
|
@@ -77,10 +77,10 @@ var RefsGitSubProvider = class {
|
|
|
77
77
|
isValidReference(_repoPath, _ref, _pathOrUri, _cancellation) {
|
|
78
78
|
return Promise.resolve(true);
|
|
79
79
|
}
|
|
80
|
-
validateReference(_repoPath, ref,
|
|
80
|
+
validateReference(_repoPath, ref, _options, _cancellation) {
|
|
81
81
|
return Promise.resolve(ref);
|
|
82
82
|
}
|
|
83
|
-
updateReference(_repoPath, _ref,
|
|
83
|
+
updateReference(_repoPath, _ref, _sha, _options, _cancellation) {
|
|
84
84
|
return Promise.resolve();
|
|
85
85
|
}
|
|
86
86
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refs.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/refs.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitBranch } from '@gitlens/git/models/branch.js';\nimport type { GitReference, GitRefTip } from '@gitlens/git/models/reference.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTag } from '@gitlens/git/models/tag.js';\nimport type { GitRefsSubProvider } from '@gitlens/git/providers/refs.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { createReference } from '@gitlens/git/utils/reference.utils.js';\nimport {\n\tcreateRevisionRange,\n\tisShaWithOptionalRevisionSuffix,\n\tstripOrigin,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\n// Since negative lookbehind isn't supported in all browsers, this leaves out the negative lookbehind condition `(?<!\\.lock)` to ensure the branch name doesn't end with `.lock`\n// oxlint-disable-next-line no-control-regex\nconst validBranchOrTagRegex = /^[^/](?!.*\\/\\.)(?!.*\\.\\.)(?!.*\\/\\/)(?!.*@\\{)[^\\x00-\\x1F\\x7F ~^:?*[\\\\]+[^./]$/;\n\nexport class RefsGitSubProvider implements GitRefsSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tcheckIfCouldBeValidBranchOrTagName(_repoPath: string, ref: string): Promise<boolean> {\n\t\treturn Promise.resolve(validBranchOrTagRegex.test(ref));\n\t}\n\n\t@debug()\n\tgetMergeBase(\n\t\trepoPath: string,\n\t\tref1: string,\n\t\tref2: string,\n\t\t_options?: { forkPoint?: boolean; priority?: GitCommandPriority },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\tconst a = stripOrigin(ref1);\n\t\tconst b = stripOrigin(ref2);\n\t\t// `merge-base` is symmetric, so normalize ref order in the cache key to coalesce\n\t\t// `(A, B)` and `(B, A)` lookups onto a single entry.\n\t\tconst [left, right] = a < b ? [a, b] : [b, a];\n\t\tconst cacheKey = `${left}...${right}`;\n\t\tconst queryRange = createRevisionRange(a, b, '...');\n\n\t\treturn this.cache.mergeBase.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\ttry {\n\t\t\t\tconst result = await github.getComparison(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tqueryRange,\n\t\t\t\t);\n\t\t\t\treturn result?.merge_base_commit?.sha;\n\t\t\t} catch (ex) {\n\t\t\t\tscope?.error(ex);\n\t\t\t\tdebugger;\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t});\n\t}\n\n\t@debug()\n\tasync getReference(
|
|
1
|
+
{"version":3,"file":"refs.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/refs.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitBranch } from '@gitlens/git/models/branch.js';\nimport type { GitReference, GitRefTip } from '@gitlens/git/models/reference.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTag } from '@gitlens/git/models/tag.js';\nimport type { GitRefsSubProvider } from '@gitlens/git/providers/refs.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { createReference } from '@gitlens/git/utils/reference.utils.js';\nimport {\n\tcreateRevisionRange,\n\tisShaWithOptionalRevisionSuffix,\n\tstripOrigin,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\n// Since negative lookbehind isn't supported in all browsers, this leaves out the negative lookbehind condition `(?<!\\.lock)` to ensure the branch name doesn't end with `.lock`\n// oxlint-disable-next-line no-control-regex\nconst validBranchOrTagRegex = /^[^/](?!.*\\/\\.)(?!.*\\.\\.)(?!.*\\/\\/)(?!.*@\\{)[^\\x00-\\x1F\\x7F ~^:?*[\\\\]+[^./]$/;\n\nexport class RefsGitSubProvider implements GitRefsSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tcheckIfCouldBeValidBranchOrTagName(_repoPath: string, ref: string): Promise<boolean> {\n\t\treturn Promise.resolve(validBranchOrTagRegex.test(ref));\n\t}\n\n\t@debug()\n\tgetMergeBase(\n\t\trepoPath: string,\n\t\tref1: string,\n\t\tref2: string,\n\t\t_options?: { forkPoint?: boolean; priority?: GitCommandPriority },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\tconst a = stripOrigin(ref1);\n\t\tconst b = stripOrigin(ref2);\n\t\t// `merge-base` is symmetric, so normalize ref order in the cache key to coalesce\n\t\t// `(A, B)` and `(B, A)` lookups onto a single entry.\n\t\tconst [left, right] = a < b ? [a, b] : [b, a];\n\t\tconst cacheKey = `${left}...${right}`;\n\t\tconst queryRange = createRevisionRange(a, b, '...');\n\n\t\treturn this.cache.mergeBase.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\ttry {\n\t\t\t\tconst result = await github.getComparison(\n\t\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\t\tmetadata.repo.owner,\n\t\t\t\t\tmetadata.repo.name,\n\t\t\t\t\tqueryRange,\n\t\t\t\t);\n\t\t\t\treturn result?.merge_base_commit?.sha;\n\t\t\t} catch (ex) {\n\t\t\t\tscope?.error(ex);\n\t\t\t\tdebugger;\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t});\n\t}\n\n\t@debug()\n\tasync getReference(\n\t\trepoPath: string,\n\t\tref: string,\n\t\toptions?: { force?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitReference | undefined> {\n\t\tif (!ref || ref === deletedOrMissing) return undefined;\n\n\t\tif (!(await this.isValidReference(repoPath, ref))) return undefined;\n\n\t\tif (ref !== 'HEAD' && !isShaWithOptionalRevisionSuffix(ref)) {\n\t\t\tconst branch = await this.provider.branches.getBranch(\n\t\t\t\trepoPath,\n\t\t\t\tref,\n\t\t\t\toptions?.force ? { force: true } : undefined,\n\t\t\t);\n\t\t\tif (branch != null) {\n\t\t\t\treturn createReference(branch.ref, repoPath, {\n\t\t\t\t\tid: branch.id,\n\t\t\t\t\trefType: 'branch',\n\t\t\t\t\tname: branch.name,\n\t\t\t\t\tremote: branch.remote,\n\t\t\t\t\tupstream: branch.upstream,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst tag = await this.provider.tags.getTag(repoPath, ref);\n\t\t\tif (tag != null) {\n\t\t\t\treturn createReference(tag.ref, repoPath, {\n\t\t\t\t\tid: tag.id,\n\t\t\t\t\trefType: 'tag',\n\t\t\t\t\tname: tag.name,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn createReference(ref, repoPath, { refType: 'revision' });\n\t}\n\n\t@debug()\n\tgetRefTips(\n\t\t_repoPath: string,\n\t\t_options?: { include?: ReadonlyArray<'heads' | 'remotes' | 'tags'> },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitRefTip[]> {\n\t\t// Not implemented for GitHub virtual repos — current consumers (timeline slice-by-branch)\n\t\t// gate this off via `!repo.virtual`. A future implementation can use GraphQL `refs` /\n\t\t// `commit.associatedRefs`.\n\t\treturn Promise.resolve([]);\n\t}\n\n\t@debug()\n\tgetRefsContainingShas(\n\t\t_repoPath: string,\n\t\t_shas: ReadonlySet<string> | readonly string[],\n\t\t_oldestSha: string,\n\t\t_options?: { include?: ReadonlyArray<'heads' | 'remotes' | 'tags'> },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<Map<string, GitRefTip[]>> {\n\t\t// See `getRefTips` — gated off for virtual repos until GraphQL `commit.associatedRefs` lands.\n\t\treturn Promise.resolve(new Map<string, GitRefTip[]>());\n\t}\n\n\t@debug()\n\tasync hasBranchOrTag(\n\t\trepoPath: string | undefined,\n\t\toptions?: { filter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean } },\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tif (repoPath == null) return false;\n\n\t\tconst [{ values: branches }, { values: tags }] = await Promise.all([\n\t\t\tthis.provider.branches.getBranches(\n\t\t\t\trepoPath,\n\t\t\t\t{ filter: options?.filter?.branches, sort: false },\n\t\t\t\tcancellation,\n\t\t\t),\n\t\t\tthis.provider.tags.getTags(repoPath, { filter: options?.filter?.tags, sort: false }, cancellation),\n\t\t]);\n\n\t\treturn branches.length !== 0 || tags.length !== 0;\n\t}\n\n\t@debug()\n\tisValidReference(\n\t\t_repoPath: string,\n\t\t_ref: string,\n\t\t_pathOrUri?: string,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\treturn Promise.resolve(true);\n\t}\n\n\t@debug()\n\tvalidateReference(\n\t\t_repoPath: string,\n\t\tref: string,\n\t\t_options?: { relativePath?: string; force?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\treturn Promise.resolve(ref);\n\t}\n\n\t@debug()\n\tupdateReference(\n\t\t_repoPath: string,\n\t\t_ref: string,\n\t\t_sha: string,\n\t\t_options?: { expected?: string | 'absent' },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -10,7 +10,9 @@ export declare class RevisionGitSubProvider implements GitRevisionSubProvider {
|
|
|
10
10
|
getTreeEntryForRevision(repoPath: string, path: string, rev: string): Promise<GitTreeEntry | undefined>;
|
|
11
11
|
getTrackedFiles(repoPath: string): Promise<string[]>;
|
|
12
12
|
getTreeForRevision(repoPath: string, rev: string): Promise<GitTreeEntry[]>;
|
|
13
|
-
resolveRevision(repoPath: string, ref: string, pathOrUri?: string | Uri
|
|
13
|
+
resolveRevision(repoPath: string, ref: string, pathOrUri?: string | Uri, _options?: {
|
|
14
|
+
force?: boolean;
|
|
15
|
+
}): Promise<ResolvedRevision>;
|
|
14
16
|
}
|
|
15
17
|
//#endregion
|
|
16
18
|
//# sourceMappingURL=revision.d.ts.map
|
|
@@ -57,7 +57,7 @@ var RevisionGitSubProvider = class {
|
|
|
57
57
|
});
|
|
58
58
|
return result;
|
|
59
59
|
}
|
|
60
|
-
async resolveRevision(repoPath, ref, pathOrUri) {
|
|
60
|
+
async resolveRevision(repoPath, ref, pathOrUri, _options) {
|
|
61
61
|
if (!ref || ref === "0000000000000000000000000000000000000000-") return {
|
|
62
62
|
sha: ref,
|
|
63
63
|
revision: ref
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revision.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/revision.ts"],"sourcesContent":["import { FileType } from '@gitlens/git/context.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTreeEntry } from '@gitlens/git/models/tree.js';\nimport type { GitRevisionSubProvider, ResolvedRevision } from '@gitlens/git/providers/revision.js';\nimport {\n\tisRevisionWithSuffix,\n\tisSha,\n\tisUncommitted,\n\tisUncommittedWithParentSuffix,\n\tstripOrigin,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nexport class RevisionGitSubProvider implements GitRevisionSubProvider {\n\tconstructor(private readonly provider: GitHubGitProviderInternal) {}\n\n\t@gate()\n\t@debug()\n\tgetRevisionContent(repoPath: string, path: string, rev: string): Promise<Uint8Array | undefined> {\n\t\tconst uri = rev\n\t\t\t? this.provider.createProviderUri(repoPath, rev, path)\n\t\t\t: this.provider.createVirtualUri(repoPath, rev, path);\n\n\t\treturn this.provider.context.fs.readFile(uri);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync getTreeEntryForRevision(repoPath: string, path: string, rev: string): Promise<GitTreeEntry | undefined> {\n\t\tif (repoPath == null || !path) return undefined;\n\n\t\tif (path) {\n\t\t\tpath = this.provider.getRelativePath(path, repoPath);\n\t\t}\n\n\t\tif (rev === 'HEAD') {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return undefined;\n\n\t\t\tconst revision = await context.metadata.getRevision();\n\t\t\trev = revision?.revision;\n\t\t}\n\n\t\tconst uri = rev\n\t\t\t? this.provider.createProviderUri(repoPath, rev, path)\n\t\t\t: this.provider.createVirtualUri(repoPath, rev, path);\n\n\t\tconst stats = await this.provider.context.fs.stat(uri);\n\t\tif (stats == null) return undefined;\n\n\t\treturn {\n\t\t\tref: rev,\n\t\t\toid: '',\n\t\t\tpath: this.provider.getRelativePath(uri, repoPath),\n\t\t\tsize: stats.size,\n\t\t\ttype: (stats.type & FileType.Directory) !== 0 ? 'tree' : 'blob',\n\t\t};\n\t}\n\n\t@debug()\n\tasync getTrackedFiles(repoPath: string): Promise<string[]> {\n\t\tconst tree = await this.getTreeForRevision(repoPath, 'HEAD');\n\t\treturn tree.filter(f => f.type === 'blob').map(f => f.path);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync getTreeForRevision(repoPath: string, rev: string): Promise<GitTreeEntry[]> {\n\t\tif (repoPath == null) return [];\n\n\t\tif (rev === 'HEAD') {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return [];\n\n\t\t\tconst revision = await context.metadata.getRevision();\n\t\t\trev = revision?.revision;\n\t\t}\n\n\t\tconst baseUri = rev\n\t\t\t? this.provider.createProviderUri(repoPath, rev)\n\t\t\t: this.provider.createVirtualUri(repoPath, rev);\n\n\t\tconst entries = await this.provider.context.fs.readDirectory(baseUri);\n\t\tif (entries == null) return [];\n\n\t\tconst result: GitTreeEntry[] = [];\n\t\tfor (const [path, type] of entries) {\n\t\t\tresult.push({\n\t\t\t\tref: rev,\n\t\t\t\toid: '',\n\t\t\t\tpath: path,\n\t\t\t\tsize: 0,\n\t\t\t\ttype: (type & FileType.Directory) !== 0 ? 'tree' : 'blob',\n\t\t\t});\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@debug()\n\tasync resolveRevision(
|
|
1
|
+
{"version":3,"file":"revision.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/revision.ts"],"sourcesContent":["import { FileType } from '@gitlens/git/context.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitTreeEntry } from '@gitlens/git/models/tree.js';\nimport type { GitRevisionSubProvider, ResolvedRevision } from '@gitlens/git/providers/revision.js';\nimport {\n\tisRevisionWithSuffix,\n\tisSha,\n\tisUncommitted,\n\tisUncommittedWithParentSuffix,\n\tstripOrigin,\n} from '@gitlens/git/utils/revision.utils.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nexport class RevisionGitSubProvider implements GitRevisionSubProvider {\n\tconstructor(private readonly provider: GitHubGitProviderInternal) {}\n\n\t@gate()\n\t@debug()\n\tgetRevisionContent(repoPath: string, path: string, rev: string): Promise<Uint8Array | undefined> {\n\t\tconst uri = rev\n\t\t\t? this.provider.createProviderUri(repoPath, rev, path)\n\t\t\t: this.provider.createVirtualUri(repoPath, rev, path);\n\n\t\treturn this.provider.context.fs.readFile(uri);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync getTreeEntryForRevision(repoPath: string, path: string, rev: string): Promise<GitTreeEntry | undefined> {\n\t\tif (repoPath == null || !path) return undefined;\n\n\t\tif (path) {\n\t\t\tpath = this.provider.getRelativePath(path, repoPath);\n\t\t}\n\n\t\tif (rev === 'HEAD') {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return undefined;\n\n\t\t\tconst revision = await context.metadata.getRevision();\n\t\t\trev = revision?.revision;\n\t\t}\n\n\t\tconst uri = rev\n\t\t\t? this.provider.createProviderUri(repoPath, rev, path)\n\t\t\t: this.provider.createVirtualUri(repoPath, rev, path);\n\n\t\tconst stats = await this.provider.context.fs.stat(uri);\n\t\tif (stats == null) return undefined;\n\n\t\treturn {\n\t\t\tref: rev,\n\t\t\toid: '',\n\t\t\tpath: this.provider.getRelativePath(uri, repoPath),\n\t\t\tsize: stats.size,\n\t\t\ttype: (stats.type & FileType.Directory) !== 0 ? 'tree' : 'blob',\n\t\t};\n\t}\n\n\t@debug()\n\tasync getTrackedFiles(repoPath: string): Promise<string[]> {\n\t\tconst tree = await this.getTreeForRevision(repoPath, 'HEAD');\n\t\treturn tree.filter(f => f.type === 'blob').map(f => f.path);\n\t}\n\n\t@gate()\n\t@debug()\n\tasync getTreeForRevision(repoPath: string, rev: string): Promise<GitTreeEntry[]> {\n\t\tif (repoPath == null) return [];\n\n\t\tif (rev === 'HEAD') {\n\t\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\t\tif (context == null) return [];\n\n\t\t\tconst revision = await context.metadata.getRevision();\n\t\t\trev = revision?.revision;\n\t\t}\n\n\t\tconst baseUri = rev\n\t\t\t? this.provider.createProviderUri(repoPath, rev)\n\t\t\t: this.provider.createVirtualUri(repoPath, rev);\n\n\t\tconst entries = await this.provider.context.fs.readDirectory(baseUri);\n\t\tif (entries == null) return [];\n\n\t\tconst result: GitTreeEntry[] = [];\n\t\tfor (const [path, type] of entries) {\n\t\t\tresult.push({\n\t\t\t\tref: rev,\n\t\t\t\toid: '',\n\t\t\t\tpath: path,\n\t\t\t\tsize: 0,\n\t\t\t\ttype: (type & FileType.Directory) !== 0 ? 'tree' : 'blob',\n\t\t\t});\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t@debug()\n\tasync resolveRevision(\n\t\trepoPath: string,\n\t\tref: string,\n\t\tpathOrUri?: string | Uri,\n\t\t// Nothing to force here — every call resolves fresh from the GitHub API; there is no cache to bypass.\n\t\t_options?: { force?: boolean },\n\t): Promise<ResolvedRevision> {\n\t\tif (!ref || ref === deletedOrMissing) return { sha: ref, revision: ref };\n\n\t\tlet relativePath;\n\t\tif (pathOrUri == null) {\n\t\t\tif (isSha(ref)) return { sha: ref, revision: ref };\n\t\t\tif (ref.endsWith('^3')) return { sha: ref, revision: ref };\n\t\t} else {\n\t\t\tif (isUncommittedWithParentSuffix(ref)) {\n\t\t\t\tref = 'HEAD';\n\t\t\t}\n\t\t\tif (isUncommitted(ref)) return { sha: ref, revision: ref };\n\n\t\t\trelativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\t\t}\n\n\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\tif (context == null) return { sha: ref, revision: ref };\n\n\t\tconst { metadata, github, session } = context;\n\n\t\tconst sha = await github.resolveReference(\n\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\tmetadata.repo.owner,\n\t\t\tmetadata.repo.name,\n\t\t\tstripOrigin(ref),\n\t\t\trelativePath,\n\t\t);\n\n\t\tif (sha == null) {\n\t\t\treturn { sha: relativePath ? deletedOrMissing : ref, revision: ref };\n\t\t}\n\t\t// If it looks like non-sha like then preserve it as the friendly name\n\t\treturn { sha: sha, revision: isRevisionWithSuffix(ref) ? sha : ref };\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TokenWithInfo } from "./authentication/models.js";
|
|
2
2
|
import { IntegrationIds } from "./constants.js";
|
|
3
|
-
import { ProviderWarning } from "./results.js";
|
|
3
|
+
import { ProviderWarning, ProviderWarningCause, ProviderWarningScope } from "./results.js";
|
|
4
4
|
import { CollectionMetadata, CollectionScopeFailure } from "@gitkraken/provider-apis";
|
|
5
5
|
//#region ../plus/integrations/src/collectionMetadata.d.ts
|
|
6
6
|
/**
|
|
@@ -25,9 +25,54 @@ export declare function throwIfCallerContractError(ex: unknown): void;
|
|
|
25
25
|
* Maps a caught GitLens request error to the SDK collection failure vocabulary used inside provider fan-outs.
|
|
26
26
|
*/
|
|
27
27
|
export declare function toCollectionFailureKind(ex: unknown): CollectionScopeFailure['kind'];
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* What an authentication refusal's response said, kept on the failure so the provider can name its cause once the
|
|
30
|
+
* credential behind it is confirmed (see `IntegrationBase.confirmScopedAuthFailures`). Only these facts are kept,
|
|
31
|
+
* never the response: its headers carry the provider's session cookies.
|
|
32
|
+
*/
|
|
33
|
+
export interface ProviderRefusal {
|
|
34
|
+
status: number;
|
|
35
|
+
/** The provider's own explanation: Azure DevOps' `X-TFS-ServiceError`, or the error body's message. */
|
|
36
|
+
detail?: string;
|
|
37
|
+
/** The provider's error type, when the body names one (Azure DevOps `typeKey`). */
|
|
38
|
+
typeKey?: string;
|
|
39
|
+
}
|
|
40
|
+
/** A scope failure as recorded here: the SDK's shape, plus what the refusal said and, once it is known, why. */
|
|
41
|
+
export interface ProviderScopeFailure extends CollectionScopeFailure {
|
|
42
|
+
refusal?: ProviderRefusal;
|
|
43
|
+
cause?: ProviderWarningCause;
|
|
44
|
+
/** The provider pinned the refusal on the credential itself, so it is published for the connection, unscoped. */
|
|
45
|
+
credentialRefused?: true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Builds a structured SDK scope failure from a caught GitLens request error.
|
|
49
|
+
*
|
|
50
|
+
* An authentication refusal is described in the provider's own words when it gives any, and otherwise by the
|
|
51
|
+
* error the provider's response raised, sanitized like any warning's (a page becomes its status), rather than by
|
|
52
|
+
* `AuthenticationError`'s generic "credentials are either invalid or expired": a scope refusing a sound credential
|
|
53
|
+
* is the case this failure exists to tell apart, and that sentence says the opposite.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toCollectionScopeFailure(scope: CollectionScopeFailure['scope'], ex: unknown): ProviderScopeFailure;
|
|
30
56
|
export declare function toCollectionFailureError(failure: CollectionScopeFailure, tokenWithInfo: TokenWithInfo): Error;
|
|
57
|
+
/**
|
|
58
|
+
* Whether `metadata` reports authentication failures only for scopes below the provider, with none for the
|
|
59
|
+
* connection itself. A credential revoked since a provider cached its discovery produces exactly this shape,
|
|
60
|
+
* the same one a scope's own refusal does; `IntegrationBase.confirmScopedAuthFailures` tells them apart.
|
|
61
|
+
*
|
|
62
|
+
* Classified exactly as {@link assessCollectionMetadata} classifies the warnings, so it agrees with what a
|
|
63
|
+
* consumer would be shown.
|
|
64
|
+
*/
|
|
65
|
+
export declare function hasOnlyScopedAuthFailures(metadata: CollectionMetadata | undefined): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Marks each scoped authentication failure in `metadata` whose refusal the provider pins on the credential, so it is
|
|
68
|
+
* published for the connection rather than for its scope. Returns whether any was.
|
|
69
|
+
*/
|
|
70
|
+
export declare function markCredentialRefusals(metadata: CollectionMetadata | undefined, isCredentialRefusal: (refusal: ProviderRefusal) => boolean): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Names the cause of each scoped authentication failure in `metadata` that kept its refusal. Only for a read whose
|
|
73
|
+
* credential was just confirmed: before that, the refusals this can name look exactly like a dead credential.
|
|
74
|
+
*/
|
|
75
|
+
export declare function attributeScopedAuthFailures(metadata: CollectionMetadata | undefined, describe: (refusal: ProviderRefusal, scope: ProviderWarningScope) => ProviderWarningCause | undefined): void;
|
|
31
76
|
/**
|
|
32
77
|
* Whether SDK metadata describes a read that may be missing results.
|
|
33
78
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AuthenticationError, RequestClientError, RequestNotFoundError, RequestRateLimitError } from "../../git/errors.js";
|
|
2
|
-
import { isRateLimitResponse } from "./errors.js";
|
|
3
|
-
import {
|
|
2
|
+
import { getResponseHeader, isRateLimitResponse } from "./errors.js";
|
|
3
|
+
import { getProviderResponseBodyMessage } from "./providers/providerErrors.js";
|
|
4
|
+
import { appendDedupedWarning, providerWarningMessage } from "./results.js";
|
|
4
5
|
import { isInvalidRequestError, isUnsupportedSortError } from "@gitkraken/provider-apis";
|
|
5
6
|
//#region ../plus/integrations/src/collectionMetadata.ts
|
|
6
7
|
/**
|
|
@@ -32,12 +33,49 @@ function toCollectionFailureKind(ex) {
|
|
|
32
33
|
if (ex instanceof RequestNotFoundError) return "not-found";
|
|
33
34
|
return "provider";
|
|
34
35
|
}
|
|
35
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Reads the refusal off an `AuthenticationError` that carries the provider's response: the SDK adapter's plain
|
|
38
|
+
* `{ status, headers, body }` (`providersApi.ts`), or the `Response` of a `ProviderFetchError`, whose body was
|
|
39
|
+
* already read into its message.
|
|
40
|
+
*/
|
|
41
|
+
function toProviderRefusal(ex) {
|
|
42
|
+
if (!(ex instanceof AuthenticationError)) return void 0;
|
|
43
|
+
const response = ex.original?.response;
|
|
44
|
+
if (typeof response?.status !== "number") return void 0;
|
|
45
|
+
const body = typeof response.body === "object" && response.body != null ? response.body : void 0;
|
|
46
|
+
const detail = decodeServiceError(getResponseHeader(response.headers, "x-tfs-serviceerror")) ?? getProviderResponseBodyMessage(body);
|
|
47
|
+
const typeKey = body != null && "typeKey" in body ? body.typeKey : void 0;
|
|
48
|
+
return {
|
|
49
|
+
status: response.status,
|
|
50
|
+
...detail ? { detail } : {},
|
|
51
|
+
...typeof typeKey === "string" ? { typeKey } : {}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Azure DevOps sends `X-TFS-ServiceError` percent-encoded. */
|
|
55
|
+
function decodeServiceError(value) {
|
|
56
|
+
if (typeof value !== "string" || !value) return void 0;
|
|
57
|
+
try {
|
|
58
|
+
return decodeURIComponent(value).trim() || void 0;
|
|
59
|
+
} catch {
|
|
60
|
+
return value.trim() || void 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Builds a structured SDK scope failure from a caught GitLens request error.
|
|
65
|
+
*
|
|
66
|
+
* An authentication refusal is described in the provider's own words when it gives any, and otherwise by the
|
|
67
|
+
* error the provider's response raised, sanitized like any warning's (a page becomes its status), rather than by
|
|
68
|
+
* `AuthenticationError`'s generic "credentials are either invalid or expired": a scope refusing a sound credential
|
|
69
|
+
* is the case this failure exists to tell apart, and that sentence says the opposite.
|
|
70
|
+
*/
|
|
36
71
|
function toCollectionScopeFailure(scope, ex) {
|
|
72
|
+
const refusal = toProviderRefusal(ex);
|
|
73
|
+
const message = refusal != null ? refusal.detail ?? providerWarningMessage(ex.original) : void 0;
|
|
37
74
|
return {
|
|
38
75
|
scope,
|
|
39
76
|
kind: toCollectionFailureKind(ex),
|
|
40
|
-
...ex instanceof Error && ex.message ? { message: ex.message } : {}
|
|
77
|
+
...message ? { message } : ex instanceof Error && ex.message ? { message: ex.message } : {},
|
|
78
|
+
...refusal != null ? { refusal } : {}
|
|
41
79
|
};
|
|
42
80
|
}
|
|
43
81
|
function collectionFailureKindToWarningKind(kind) {
|
|
@@ -89,11 +127,97 @@ function collectionScopeText(scope) {
|
|
|
89
127
|
if (scope?.repositoryId != null) parts.push(`repository ${scope.repositoryId}`);
|
|
90
128
|
return parts.length ? ` (${parts.join(", ")})` : "";
|
|
91
129
|
}
|
|
130
|
+
/** The cause in the consumer's terms, for the prose that goes with the structured {@link ProviderWarningCause}. */
|
|
131
|
+
function causeText(cause) {
|
|
132
|
+
switch (cause.reason) {
|
|
133
|
+
case "oauth-app-not-allowed": return "the organization does not allow third-party OAuth apps";
|
|
134
|
+
case "access-denied": return "the account has no access to it";
|
|
135
|
+
case "conditional-access": return "a Conditional Access policy blocked the request";
|
|
136
|
+
default:
|
|
137
|
+
cause.reason;
|
|
138
|
+
return "the provider refused the request";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
92
141
|
function collectionFailureMessage(failure) {
|
|
93
|
-
const
|
|
142
|
+
const text = failure.cause != null ? causeText(failure.cause) : failure.message;
|
|
143
|
+
const detail = text != null ? `: ${text}` : "";
|
|
94
144
|
return `Failed to read ${failure.kind} scope${collectionScopeText(failure.scope)}${detail}`;
|
|
95
145
|
}
|
|
96
146
|
/**
|
|
147
|
+
* Forwards the part of a failure's scope below the provider, so a consumer can tell "one organization refused
|
|
148
|
+
* this token" from "the connection's token is dead" without parsing {@link collectionFailureMessage}.
|
|
149
|
+
*
|
|
150
|
+
* `providerId` is dropped: the warning already names its provider, and a scope naming nothing below it is a
|
|
151
|
+
* failure of the connection itself. That is the distinction `getOrganizationsForUserResult` also draws before
|
|
152
|
+
* counting an auth failure against the connection, though it reads a scope with no keys but `providerId`, so an
|
|
153
|
+
* absent scope does not count there. Forwarding such a scope would make an account-wide failure look confined.
|
|
154
|
+
*
|
|
155
|
+
* Copied field by field, for the reason {@link toProviderWarningOmission} copies its scope.
|
|
156
|
+
*/
|
|
157
|
+
function toProviderWarningScope(scope) {
|
|
158
|
+
if (scope == null) return void 0;
|
|
159
|
+
const { resourceId, projectId, repositoryId } = scope;
|
|
160
|
+
if (resourceId == null && projectId == null && repositoryId == null) return void 0;
|
|
161
|
+
return {
|
|
162
|
+
...resourceId != null ? { resourceId } : {},
|
|
163
|
+
...projectId != null ? { projectId } : {},
|
|
164
|
+
...repositoryId != null ? { repositoryId } : {}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Whether `metadata` reports authentication failures only for scopes below the provider, with none for the
|
|
169
|
+
* connection itself. A credential revoked since a provider cached its discovery produces exactly this shape,
|
|
170
|
+
* the same one a scope's own refusal does; `IntegrationBase.confirmScopedAuthFailures` tells them apart.
|
|
171
|
+
*
|
|
172
|
+
* Classified exactly as {@link assessCollectionMetadata} classifies the warnings, so it agrees with what a
|
|
173
|
+
* consumer would be shown.
|
|
174
|
+
*/
|
|
175
|
+
function hasOnlyScopedAuthFailures(metadata) {
|
|
176
|
+
let scoped = false;
|
|
177
|
+
for (const failure of metadata?.failures ?? []) {
|
|
178
|
+
if (toCollectionFailureWarningKind(failure) !== "auth") continue;
|
|
179
|
+
if (toProviderWarningScope(failure.scope) == null || failure.credentialRefused) return false;
|
|
180
|
+
scoped = true;
|
|
181
|
+
}
|
|
182
|
+
return scoped;
|
|
183
|
+
}
|
|
184
|
+
/** The scoped authentication failures in `metadata` that kept their refusal, with the scope they are forwarded as. */
|
|
185
|
+
function* refusedScopes(metadata) {
|
|
186
|
+
for (const failure of metadata?.failures ?? []) {
|
|
187
|
+
if (failure.refusal == null || failure.credentialRefused || toCollectionFailureWarningKind(failure) !== "auth") continue;
|
|
188
|
+
const scope = toProviderWarningScope(failure.scope);
|
|
189
|
+
if (scope == null) continue;
|
|
190
|
+
yield {
|
|
191
|
+
failure,
|
|
192
|
+
scope
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Marks each scoped authentication failure in `metadata` whose refusal the provider pins on the credential, so it is
|
|
198
|
+
* published for the connection rather than for its scope. Returns whether any was.
|
|
199
|
+
*/
|
|
200
|
+
function markCredentialRefusals(metadata, isCredentialRefusal) {
|
|
201
|
+
let marked = false;
|
|
202
|
+
for (const { failure } of refusedScopes(metadata)) {
|
|
203
|
+
if (!isCredentialRefusal(failure.refusal)) continue;
|
|
204
|
+
failure.credentialRefused = true;
|
|
205
|
+
marked = true;
|
|
206
|
+
}
|
|
207
|
+
return marked;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Names the cause of each scoped authentication failure in `metadata` that kept its refusal. Only for a read whose
|
|
211
|
+
* credential was just confirmed: before that, the refusals this can name look exactly like a dead credential.
|
|
212
|
+
*/
|
|
213
|
+
function attributeScopedAuthFailures(metadata, describe) {
|
|
214
|
+
for (const { failure, scope } of refusedScopes(metadata)) {
|
|
215
|
+
if (failure.cause != null) continue;
|
|
216
|
+
const cause = describe(failure.refusal, scope);
|
|
217
|
+
if (cause != null) failure.cause = cause;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
97
221
|
* Explains one omission in the consumer's terms — what was left out and, where the SDK reports it, how much.
|
|
98
222
|
*
|
|
99
223
|
* An omission is a completeness fact, never a failure: the read succeeded, and the provider (or the SDK's own
|
|
@@ -172,13 +296,19 @@ function assessCollectionMetadata(providerId, domain, connectionId, metadata) {
|
|
|
172
296
|
const failures = metadata.failures ?? [];
|
|
173
297
|
for (const failure of failures) {
|
|
174
298
|
const kind = toCollectionFailureWarningKind(failure);
|
|
299
|
+
const scope = failure.credentialRefused ? void 0 : toProviderWarningScope(failure.scope);
|
|
175
300
|
appendDedupedWarning(warnings, {
|
|
176
301
|
providerId,
|
|
177
302
|
domain,
|
|
178
303
|
connectionId,
|
|
179
|
-
message: collectionFailureMessage(failure
|
|
304
|
+
message: collectionFailureMessage(failure.credentialRefused ? {
|
|
305
|
+
...failure,
|
|
306
|
+
scope: void 0
|
|
307
|
+
} : failure),
|
|
180
308
|
kind,
|
|
181
|
-
isAuth: kind === "auth"
|
|
309
|
+
isAuth: kind === "auth",
|
|
310
|
+
...scope != null ? { scope } : {},
|
|
311
|
+
...failure.cause != null ? { cause: { ...failure.cause } } : {}
|
|
182
312
|
});
|
|
183
313
|
}
|
|
184
314
|
const omissions = metadata.omissions ?? [];
|
|
@@ -230,6 +360,6 @@ function mergeAssessmentInto(warnings, providerId, domain, connectionId, metadat
|
|
|
230
360
|
};
|
|
231
361
|
}
|
|
232
362
|
//#endregion
|
|
233
|
-
export { assessCollectionMetadata, isIncompleteCollection, mergeAssessmentInto, throwIfCallerContractError, toCollectionFailureError, toCollectionFailureKind, toCollectionScopeFailure };
|
|
363
|
+
export { assessCollectionMetadata, attributeScopedAuthFailures, hasOnlyScopedAuthFailures, isIncompleteCollection, markCredentialRefusals, mergeAssessmentInto, throwIfCallerContractError, toCollectionFailureError, toCollectionFailureKind, toCollectionScopeFailure };
|
|
234
364
|
|
|
235
365
|
//# sourceMappingURL=collectionMetadata.js.map
|