@gitkraken/core-gitlens 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -1
- package/dist/git/cache.d.ts +11 -0
- package/dist/git/cache.js +26 -3
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +3 -2
- package/dist/git/context.js.map +1 -1
- package/dist/git/features.d.ts +1 -1
- package/dist/git/features.js +1 -0
- package/dist/git/features.js.map +1 -1
- package/dist/git/models/reflog.d.ts +6 -0
- package/dist/git/models/reflog.js.map +1 -1
- package/dist/git/models/revision.d.ts +0 -1
- package/dist/git/models/revision.js +1 -2
- package/dist/git/models/revision.js.map +1 -1
- package/dist/git/providers/commits.d.ts +20 -1
- package/dist/git/providers/operations.d.ts +13 -0
- package/dist/git/providers/provider.d.ts +14 -4
- package/dist/git/providers/refs.d.ts +10 -0
- package/dist/git/providers/revision.d.ts +2 -0
- package/dist/git/providers/staging.d.ts +2 -1
- package/dist/git/providers/stash.d.ts +3 -2
- package/dist/git/providers/status.d.ts +4 -0
- package/dist/git/run.types.d.ts +16 -0
- package/dist/git-cli/cliGitProvider.d.ts +24 -3
- package/dist/git-cli/cliGitProvider.js +79 -17
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/commandClassifier.d.ts +31 -0
- package/dist/git-cli/exec/commandClassifier.js +391 -0
- package/dist/git-cli/exec/commandClassifier.js.map +1 -0
- package/dist/git-cli/exec/git.d.ts +24 -3
- package/dist/git-cli/exec/git.js +116 -12
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/parsers/reflogParser.d.ts +7 -0
- package/dist/git-cli/parsers/reflogParser.js +11 -1
- package/dist/git-cli/parsers/reflogParser.js.map +1 -1
- package/dist/git-cli/providers/branches.js +16 -14
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +4 -2
- package/dist/git-cli/providers/commits.js +55 -4
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/diff.js +4 -4
- package/dist/git-cli/providers/diff.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +12 -0
- package/dist/git-cli/providers/operations.js +26 -3
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/patch.js +2 -5
- package/dist/git-cli/providers/patch.js.map +1 -1
- package/dist/git-cli/providers/refs.d.ts +5 -0
- package/dist/git-cli/providers/refs.js +26 -1
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/remotes.js +3 -2
- package/dist/git-cli/providers/remotes.js.map +1 -1
- package/dist/git-cli/providers/revision.d.ts +2 -0
- package/dist/git-cli/providers/revision.js +11 -0
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/staging.d.ts +2 -1
- package/dist/git-cli/providers/staging.js +12 -7
- package/dist/git-cli/providers/staging.js.map +1 -1
- package/dist/git-cli/providers/stash.d.ts +3 -2
- package/dist/git-cli/providers/stash.js +34 -22
- package/dist/git-cli/providers/stash.js.map +1 -1
- package/dist/git-cli/providers/status.d.ts +2 -0
- package/dist/git-cli/providers/status.js +27 -9
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +13 -0
- package/dist/plus/git-github/api/github.js +36 -6
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/providers/github/commits.d.ts +4 -2
- package/dist/plus/git-github/providers/github/commits.js +3 -1
- package/dist/plus/git-github/providers/github/commits.js.map +1 -1
- package/dist/plus/git-github/providers/github/revision.d.ts +1 -0
- package/dist/plus/git-github/providers/github/revision.js +5 -0
- package/dist/plus/git-github/providers/github/revision.js.map +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +6 -0
- package/dist/plus/integrations/collectionMetadata.js +7 -4
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +13 -0
- package/dist/plus/integrations/models/gitHostIntegration.js +19 -0
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +16 -1
- package/dist/plus/integrations/providers/github.js +39 -1
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/reads/resolveRepository.js +26 -5
- package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
- package/docs/integrations.md +22 -5
- package/docs/kepler-git-write-api-parity.md +140 -14
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import { GitCommit } from "../../../../git/models/commit.js";
|
|
|
5
5
|
import { SearchQuery } from "../../../../git/models/search.js";
|
|
6
6
|
import { GitLog } from "../../../../git/models/log.js";
|
|
7
7
|
import { GitUser } from "../../../../git/models/user.js";
|
|
8
|
-
import { GitCommitsSubProvider, GitLogForPathOptions, GitLogOptions, GitLogShasOptions, GitSearchCommitsOptions, LeftRightCommitCountResult, SearchCommitsResult } from "../../../../git/providers/commits.js";
|
|
8
|
+
import { GitCommitsSubProvider, GitLogForPathOptions, GitLogOptions, GitLogShasOptions, GitRefExclusions, GitSearchCommitsOptions, LeftRightCommitCountResult, SearchCommitsResult } from "../../../../git/providers/commits.js";
|
|
9
9
|
import { Cache } from "../../../../git/cache.js";
|
|
10
10
|
import { GitHubGitProviderInternal } from "../githubProvider.js";
|
|
11
11
|
//#region ../plus/git-github/src/providers/github/commits.d.ts
|
|
@@ -14,7 +14,9 @@ export declare class CommitsGitSubProvider implements GitCommitsSubProvider {
|
|
|
14
14
|
private readonly provider;
|
|
15
15
|
constructor(cache: Cache, provider: GitHubGitProviderInternal);
|
|
16
16
|
getCommit(repoPath: string, rev: string, _cancellation?: AbortSignal): Promise<GitCommit | undefined>;
|
|
17
|
-
getCommitCount(repoPath: string, rev: string,
|
|
17
|
+
getCommitCount(repoPath: string, rev: string, options?: {
|
|
18
|
+
excluding?: GitRefExclusions;
|
|
19
|
+
}, _cancellation?: AbortSignal): Promise<number | undefined>;
|
|
18
20
|
getCommitFiles(repoPath: string, rev: string, _cancellation?: AbortSignal): Promise<GitFileChange[]>;
|
|
19
21
|
getCommitForFile(repoPath: string, pathOrUri: string | Uri, rev?: string | undefined, _options?: {
|
|
20
22
|
firstIfNotFound?: boolean;
|
|
@@ -49,8 +49,9 @@ var CommitsGitSubProvider = class {
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
|
-
getCommitCount(repoPath, rev, _cancellation) {
|
|
52
|
+
getCommitCount(repoPath, rev, options, _cancellation) {
|
|
53
53
|
if (repoPath == null) return Promise.resolve(void 0);
|
|
54
|
+
if (options?.excluding != null) return Promise.resolve(void 0);
|
|
54
55
|
return this.cache.commitCount.getOrCreate(repoPath, stripOrigin(rev), async () => {
|
|
55
56
|
const scope = getScopedLogger();
|
|
56
57
|
try {
|
|
@@ -316,6 +317,7 @@ var CommitsGitSubProvider = class {
|
|
|
316
317
|
}
|
|
317
318
|
async getLogShas(repoPath, rev, options, cancellation) {
|
|
318
319
|
if (repoPath == null) return [];
|
|
320
|
+
if (options?.excluding != null) return [];
|
|
319
321
|
const scope = getScopedLogger();
|
|
320
322
|
if (options?.authors?.length || options?.all) {
|
|
321
323
|
let log;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commits.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/commits.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport { GitCommit, GitCommitIdentity } from '@gitlens/git/models/commit.js';\nimport { GitFileChange } from '@gitlens/git/models/fileChange.js';\nimport { GitFileIndexStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitLog } from '@gitlens/git/models/log.js';\nimport type { GitRevisionRange } from '@gitlens/git/models/revision.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { SearchQuery } from '@gitlens/git/models/search.js';\nimport type { GitUser } from '@gitlens/git/models/user.js';\nimport type {\n\tGitCommitsSubProvider,\n\tGitLogForPathOptions,\n\tGitLogOptions,\n\tGitLogShasOptions,\n\tGitSearchCommitsOptions,\n\tLeftRightCommitCountResult,\n\tSearchCommitsResult,\n} from '@gitlens/git/providers/commits.js';\nimport { createUncommittedChangesCommit } from '@gitlens/git/utils/commit.utils.js';\nimport { createRevisionRange, isUncommitted, stripOrigin } from '@gitlens/git/utils/revision.utils.js';\nimport { parseSearchQueryGitHubCommand } from '@gitlens/git/utils/search.utils.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { first, last, map, some } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { isFolderGlob, normalizePath, stripFolderGlob } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { coerceUri, joinUriPath } from '@gitlens/utils/uri.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport type { GitHubCommit } from '../../models.js';\nimport { fromCommitFileStatus } from '../../models.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nfunction isViewer(name: string, viewer: string | undefined): boolean | undefined {\n\treturn (viewer != null && name === viewer) || undefined;\n}\n\nexport class CommitsGitSubProvider implements GitCommitsSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tgetCommit(repoPath: string, rev: string, _cancellation?: AbortSignal): Promise<GitCommit | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\t// Don't cache uncommitted-changes synthesis — it's date-sensitive\n\t\tif (isUncommitted(rev, true)) {\n\t\t\treturn (async () => {\n\t\t\t\treturn createUncommittedChangesCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\trev,\n\t\t\t\t\tnew Date(),\n\t\t\t\t\tawait this.provider.config.getCurrentUser(repoPath),\n\t\t\t\t);\n\t\t\t})();\n\t\t}\n\n\t\t// TODO: resolve symbolic refs (HEAD, branch names) to SHA before caching to avoid\n\t\t// short staleness windows. For now we cascade-clear on 'branch'/'branches'.\n\t\treturn this.cache.commit.getOrCreate(repoPath, stripOrigin(rev), async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\ttry {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\t\tconst commit = await github.getCommit(\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\tstripOrigin(rev),\n\t\t\t\t);\n\t\t\t\tif (commit == null) return undefined;\n\n\t\t\t\tconst repoUri = coerceUri(repoPath);\n\n\t\t\t\tconst { viewer = session.account.label } = commit;\n\n\t\t\t\treturn new GitCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tcommit.oid,\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\tcommit.message,\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.files?.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t},\n\t\t\t\t\t[],\n\t\t\t\t);\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\tgetCommitCount(repoPath: string, rev: string, _cancellation?: AbortSignal): Promise<number | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\treturn this.cache.commitCount.getOrCreate(repoPath, stripOrigin(rev), async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\ttry {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\t\tconst count = await github.getCommitCount(\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\tstripOrigin(rev),\n\t\t\t\t);\n\n\t\t\t\treturn count;\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 getCommitFiles(repoPath: string, rev: string, _cancellation?: AbortSignal): Promise<GitFileChange[]> {\n\t\tif (rev === deletedOrMissing || isUncommitted(rev)) return [];\n\n\t\tconst commit = await this.getCommit(repoPath, rev);\n\t\treturn [...(commit?.fileset?.files ?? [])];\n\t}\n\n\t@debug()\n\tasync getCommitForFile(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev?: string | undefined,\n\t\t_options?: { firstIfNotFound?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitCommit | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\tconst rootUri = this.provider.getProviderRootUri(this.provider.getAbsoluteUri(pathOrUri, repoPath));\n\t\tconst file = this.provider.getRelativePath(this.provider.getAbsoluteUri(pathOrUri, repoPath), rootUri);\n\n\t\t// Resolve HEAD/empty rev to the metadata revision so the cache key is stable across callers\n\t\tconst resolvedRev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\t\t// Path-scoped variant lives in the same slot as `getCommit` but with a `|file` suffix to\n\t\t// keep it distinct from the unscoped commit entry.\n\t\tconst cacheKey = `${stripOrigin(resolvedRev)}|${file}`;\n\n\t\treturn this.cache.commit.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\ttry {\n\t\t\t\tconst commit = await github.getCommitForFile(\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\tstripOrigin(resolvedRev),\n\t\t\t\t\tfile,\n\t\t\t\t);\n\t\t\t\tif (commit == null) return undefined;\n\n\t\t\t\tconst repoUri = coerceUri(repoPath);\n\t\t\t\tconst { viewer = session.account.label } = commit;\n\n\t\t\t\treturn new GitCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tcommit.oid,\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\tcommit.message,\n\t\t\t\t\tcommit.files != null\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfiles: undefined,\n\t\t\t\t\t\t\t\tfiltered: {\n\t\t\t\t\t\t\t\t\tfiles: commit.files?.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t\t\t\t\tpathspec: file,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t},\n\t\t\t\t\t[],\n\t\t\t\t);\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\tgetLeftRightCommitCount(\n\t\trepoPath: string,\n\t\trange: GitRevisionRange,\n\t\t_options?: { authors?: GitUser[]; excludeMerges?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<LeftRightCommitCountResult | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\treturn this.cache.leftRightCommitCount.getOrCreate(repoPath, stripOrigin(range), 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\tstripOrigin(range),\n\t\t\t\t);\n\n\t\t\t\tif (result == null) return undefined;\n\n\t\t\t\treturn {\n\t\t\t\t\tleft: result.behind_by,\n\t\t\t\t\tright: result.ahead_by,\n\t\t\t\t};\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 getLog(\n\t\trepoPath: string,\n\t\trev?: string | undefined,\n\t\toptions?: GitLogOptions,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitLog | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst limit = this.provider.getPagingLimit(options?.limit);\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\trev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\t\t\tconst result = await github.getCommits(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\tstripOrigin(rev),\n\t\t\t\t{\n\t\t\t\t\tall: options?.all,\n\t\t\t\t\tauthors: options?.authors,\n\t\t\t\t\tafter: options?.cursor,\n\t\t\t\t\tlimit: limit,\n\t\t\t\t\tsince: options?.since ? new Date(options.since) : undefined,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst commits = new Map<string, GitCommit>();\n\t\t\tconst repoUri = coerceUri(repoPath);\n\n\t\t\tconst { viewer = session.account.label } = result;\n\t\t\tfor (const commit of result.values) {\n\t\t\t\tlet c = commits.get(commit.oid);\n\t\t\t\tif (c == null) {\n\t\t\t\t\tc = new GitCommit(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tcommit.oid,\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\t\tcommit.message,\n\t\t\t\t\t\tcommit.files != null\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfiles: commit.files.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[],\n\t\t\t\t\t);\n\t\t\t\t\tcommits.set(commit.oid, c);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst log: GitLog = {\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: rev,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: limit,\n\t\t\t\thasMore: result.paging?.more ?? false,\n\t\t\t\tendingCursor: result.paging?.cursor,\n\t\t\t\tquery: (limit: number | undefined) => this.getLog(repoPath, rev, { ...options, limit: limit }),\n\t\t\t};\n\n\t\t\tif (log.hasMore) {\n\t\t\t\tlog.more = this.getLogMoreFn(log, rev, options);\n\t\t\t}\n\n\t\t\treturn log;\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\tprivate getLogMoreFn(\n\t\tlog: GitLog,\n\t\trev: string | undefined,\n\t\toptions?: GitLogOptions,\n\t): (limit: number | { until: string } | undefined) => Promise<GitLog> {\n\t\treturn async (limit: number | { until: string } | undefined) => {\n\t\t\tconst moreUntil = limit != null && typeof limit === 'object' ? limit.until : undefined;\n\t\t\tlet moreLimit = typeof limit === 'number' ? limit : undefined;\n\n\t\t\tif (moreUntil && some(log.commits.values(), c => c.ref === moreUntil)) {\n\t\t\t\treturn log;\n\t\t\t}\n\n\t\t\tmoreLimit = this.provider.getPagingLimit(moreLimit);\n\n\t\t\tconst moreLog = await this.getLog(log.repoPath, rev, {\n\t\t\t\t...options,\n\t\t\t\tlimit: moreLimit,\n\t\t\t\tcursor: log.endingCursor,\n\t\t\t});\n\t\t\t// If we can't find any more, assume we have everything\n\t\t\tif (moreLog == null) return { ...log, hasMore: false, more: undefined };\n\n\t\t\tconst commits = new Map([...log.commits, ...moreLog.commits]);\n\n\t\t\tconst mergedLog: GitLog = {\n\t\t\t\trepoPath: log.repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: log.sha,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: moreUntil == null ? (log.limit ?? 0) + moreLimit : undefined,\n\t\t\t\thasMore: moreUntil == null ? moreLog.hasMore : true,\n\t\t\t\t// The oldest commit SHA of the previous page — the graph webview compares this\n\t\t\t\t// against its last displayed row to determine the merge point for appending new rows\n\t\t\t\tstartingCursor: last(log.commits)?.[0],\n\t\t\t\tendingCursor: moreLog.endingCursor,\n\t\t\t\tpagedCommits: () => {\n\t\t\t\t\t// Remove any duplicates\n\t\t\t\t\tfor (const sha of log.commits.keys()) {\n\t\t\t\t\t\tmoreLog.commits.delete(sha);\n\t\t\t\t\t}\n\t\t\t\t\treturn moreLog.commits;\n\t\t\t\t},\n\t\t\t\tquery: log.query,\n\t\t\t};\n\t\t\tif (mergedLog.hasMore) {\n\t\t\t\tmergedLog.more = this.getLogMoreFn(mergedLog, rev, options);\n\t\t\t}\n\n\t\t\treturn mergedLog;\n\t\t};\n\t}\n\n\t@debug()\n\tasync getLogForPath(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev?: string | undefined,\n\t\toptions?: GitLogForPathOptions,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitLog | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\tif (repoPath != null && repoPath === relativePath) {\n\t\t\tthrow new Error(`Path cannot match the repository path; path=${relativePath}`);\n\t\t}\n\n\t\toptions = {\n\t\t\t...options,\n\t\t\tall: false /* not supported */,\n\t\t\tlimit: this.provider.getPagingLimit(options?.limit),\n\t\t\trenames: false /* not supported */,\n\t\t};\n\n\t\tif (isFolderGlob(relativePath)) {\n\t\t\trelativePath = stripFolderGlob(relativePath);\n\t\t\toptions.isFolder = true;\n\t\t} else if (options.isFolder == null) {\n\t\t\tconst tree = await this.provider.revision.getTreeEntryForRevision(repoPath, relativePath, rev || 'HEAD');\n\t\t\toptions.isFolder = tree?.type === 'tree';\n\t\t}\n\n\t\t// Note: document caching (TrackedGitDocument) is handled by the extension wrapper.\n\t\t// The library implementation always fetches fresh data.\n\t\treturn this.getLogForPathCore(repoPath, relativePath, rev, options);\n\t}\n\n\tprivate async getLogForPathCore(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\trev: string | undefined,\n\t\toptions: GitLogForPathOptions,\n\t): Promise<GitLog | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst limit = this.provider.getPagingLimit(options.limit);\n\n\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\tif (context == null) return undefined;\n\n\t\tconst { metadata, github, session } = context;\n\n\t\tconst uri = this.provider.getAbsoluteUri(path, repoPath);\n\t\tconst relativePath = this.provider.getRelativePath(uri, this.provider.getProviderRootUri(uri));\n\n\t\trev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\t\tconst result = await github.getCommits(\n\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\tmetadata.repo.owner,\n\t\t\tmetadata.repo.name,\n\t\t\tstripOrigin(rev),\n\t\t\t{\n\t\t\t\tall: options.all,\n\t\t\t\tafter: options.cursor,\n\t\t\t\tpath: relativePath,\n\t\t\t\tlimit: limit,\n\t\t\t\tsince: options.since ? new Date(options.since) : undefined,\n\t\t\t},\n\t\t);\n\n\t\tconst repoUri = coerceUri(repoPath);\n\t\tconst commits = new Map<string, GitCommit>();\n\n\t\tconst { viewer = session.account.label } = result;\n\t\tfor (const commit of result.values) {\n\t\t\tlet c = commits.get(commit.oid);\n\t\t\tif (c == null) {\n\t\t\t\tconst files = commit.files?.map(f => toFileChange(repoUri, repoPath, f));\n\n\t\t\t\tif (files != null && !options.isFolder && commit.changedFiles === 1) {\n\t\t\t\t\tconst index = files.findIndex(f => f.path === relativePath);\n\t\t\t\t\tif (index !== -1) {\n\t\t\t\t\t\tfiles.splice(\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\tnew GitFileChange(\n\t\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t\trelativePath,\n\t\t\t\t\t\t\t\tGitFileIndexStatus.Modified,\n\t\t\t\t\t\t\t\tjoinUriPath(repoUri, normalizePath(relativePath)),\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\tundefined,\n\t\t\t\t\t\t\t\tcommit.changedFiles === 1\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t\t\t\t\t\t\tchanges: 0,\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tc = new GitCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tcommit.oid,\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\tcommit.message,\n\t\t\t\t\t{ files: undefined, filtered: { files: files, pathspec: relativePath } },\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t},\n\t\t\t\t\t[],\n\t\t\t\t);\n\t\t\t\tcommits.set(commit.oid, c);\n\t\t\t}\n\t\t}\n\n\t\tconst log: GitLog = {\n\t\t\trepoPath: repoPath,\n\t\t\tcommits: commits,\n\t\t\tsha: rev,\n\t\t\tcount: commits.size,\n\t\t\tlimit: limit,\n\t\t\thasMore: result.paging?.more ?? false,\n\t\t\tendingCursor: result.paging?.cursor,\n\t\t\tquery: (limit: number | undefined) => this.getLogForPath(repoPath, path, rev, { ...options, limit: limit }),\n\t\t};\n\t\tif (log.hasMore) {\n\t\t\tlog.more = this.getLogForPathMoreFn(log, path, rev, options);\n\t\t}\n\n\t\treturn log;\n\t}\n\n\tprivate getLogForPathMoreFn(\n\t\tlog: GitLog,\n\t\trelativePath: string,\n\t\trev: string | undefined,\n\t\toptions: GitLogForPathOptions,\n\t): (limit: number | { until: string } | undefined) => Promise<GitLog> {\n\t\treturn async (limit: number | { until: string } | undefined) => {\n\t\t\tconst moreUntil = limit != null && typeof limit === 'object' ? limit.until : undefined;\n\t\t\tlet moreLimit = typeof limit === 'number' ? limit : undefined;\n\n\t\t\tif (moreUntil && some(log.commits.values(), c => c.ref === moreUntil)) {\n\t\t\t\treturn log;\n\t\t\t}\n\n\t\t\tmoreLimit = this.provider.getPagingLimit(moreLimit);\n\n\t\t\tconst moreLog = await this.getLogForPath(log.repoPath, relativePath, rev, {\n\t\t\t\t...options,\n\t\t\t\tlimit: moreUntil == null ? moreLimit : 0,\n\t\t\t\tcursor: log.endingCursor,\n\t\t\t});\n\t\t\t// If we can't find any more, assume we have everything\n\t\t\tif (moreLog == null) return { ...log, hasMore: false, more: undefined };\n\n\t\t\tconst commits = new Map([...log.commits, ...moreLog.commits]);\n\n\t\t\tconst mergedLog: GitLog = {\n\t\t\t\trepoPath: log.repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: log.sha,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: moreUntil == null ? (log.limit ?? 0) + moreLimit : undefined,\n\t\t\t\thasMore: moreUntil == null ? moreLog.hasMore : true,\n\t\t\t\tendingCursor: moreLog.endingCursor,\n\t\t\t\tquery: log.query,\n\t\t\t};\n\n\t\t\tif (mergedLog.hasMore) {\n\t\t\t\tmergedLog.more = this.getLogForPathMoreFn(mergedLog, relativePath, rev, options);\n\t\t\t}\n\n\t\t\treturn mergedLog;\n\t\t};\n\t}\n\n\t@debug()\n\tasync getLogShas(\n\t\trepoPath: string,\n\t\trev?: string | undefined,\n\t\toptions?: GitLogShasOptions,\n\t\tcancellation?: AbortSignal,\n\t): Promise<Iterable<string>> {\n\t\tif (repoPath == null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// `authors` and `all` filters aren't supported by the lightweight SHA-only query;\n\t\t// fall back to the full log path when set.\n\t\tif (options?.authors?.length || options?.all) {\n\t\t\tlet log: GitLog | undefined;\n\t\t\tif (options?.pathOrUri != null) {\n\t\t\t\tlog = await this.getLogForPath(repoPath, options.pathOrUri, rev, options, cancellation);\n\t\t\t} else {\n\t\t\t\tlog = await this.getLog(repoPath, rev, options, cancellation);\n\t\t\t}\n\t\t\tif (log == null) return [];\n\n\t\t\tconst shas = map(log.commits.values(), c => c.ref);\n\t\t\t// Note: reversal only applies to the first page — subsequent pages loaded via pagination are not reversed\n\t\t\treturn options?.reverse ? [...shas].reverse() : shas;\n\t\t}\n\n\t\tconst limit = this.provider.getPagingLimit(options?.limit);\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\trev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\n\t\t\tlet path: string | undefined;\n\t\t\tif (options?.pathOrUri != null) {\n\t\t\t\tconst rootUri = this.provider.getProviderRootUri(\n\t\t\t\t\tthis.provider.getAbsoluteUri(options.pathOrUri, repoPath),\n\t\t\t\t);\n\t\t\t\tpath = this.provider.getRelativePath(\n\t\t\t\t\tthis.provider.getAbsoluteUri(options.pathOrUri, repoPath),\n\t\t\t\t\trootUri,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst strippedRev = stripOrigin(rev);\n\t\t\tconst sinceISO = options?.since ? new Date(options.since).toISOString() : '';\n\t\t\tconst cacheKey = `${strippedRev}|${path ?? ''}|${sinceISO}|${limit}|${options?.cursor ?? ''}`;\n\n\t\t\tconst shas = await this.cache.logShas.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\t\tconst result = await github.getCommitShas(\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\tstrippedRev,\n\t\t\t\t\t{\n\t\t\t\t\t\tafter: options?.cursor,\n\t\t\t\t\t\tlimit: limit,\n\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\tsince: options?.since ? new Date(options.since) : undefined,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\treturn result.values;\n\t\t\t});\n\n\t\t\t// Note: reversal only applies to the first page — subsequent pages loaded via pagination are not reversed\n\t\t\treturn options?.reverse ? shas.toReversed() : shas;\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\tgetOldestUnpushedShaForPath(\n\t\t_repoPath: string,\n\t\t_pathOrUri: string | Uri,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\t// TODO@eamodio until we have access to the RemoteHub change store there isn't anything we can do here\n\t\treturn Promise.resolve(undefined);\n\t}\n\n\t@debug()\n\thasCommitBeenPushed(_repoPath: string, _rev: string, _cancellation?: AbortSignal): Promise<boolean> {\n\t\t// In this env we can't have unpushed commits\n\t\treturn Promise.resolve(true);\n\t}\n\n\t@debug()\n\tasync isAncestorOf(repoPath: string, rev1: string, rev2: string, _cancellation?: AbortSignal): Promise<boolean> {\n\t\tif (repoPath == null) return false;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\ttry {\n\t\t\tconst result = await github.getComparison(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\tcreateRevisionRange(stripOrigin(rev1), stripOrigin(rev2), '...'),\n\t\t\t);\n\n\t\t\tswitch (result?.status) {\n\t\t\t\tcase 'ahead':\n\t\t\t\tcase 'diverged':\n\t\t\t\t\treturn false;\n\t\t\t\tcase 'identical':\n\t\t\t\tcase 'behind':\n\t\t\t\t\treturn true;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t@debug({\n\t\targs: (repoPath, s) => ({\n\t\t\trepoPath: repoPath,\n\t\t\tsearch: `[${s.matchAll ? 'A' : ''}${s.matchCase ? 'C' : ''}${s.matchRegex ? 'R' : ''}${\n\t\t\t\ts.matchWholeWord ? 'W' : ''\n\t\t\t}]: ${s.query.length > 500 ? `${s.query.substring(0, 500)}...` : s.query}`,\n\t\t}),\n\t})\n\tasync searchCommits(\n\t\trepoPath: string,\n\t\tsearch: SearchQuery,\n\t\toptions?: GitSearchCommitsOptions,\n\t\tcancellation?: AbortSignal,\n\t): Promise<SearchCommitsResult> {\n\t\tif (repoPath == null) return { search: search, log: undefined };\n\n\t\tconst scope = getScopedLogger();\n\n\t\tsearch = { matchAll: false, matchCase: false, matchRegex: true, matchWholeWord: false, ...search };\n\t\t// Note: Natural language processing is handled by the extension wrapper.\n\n\t\tconst currentUser = search.query.includes('@me')\n\t\t\t? await this.provider.config.getCurrentUser(repoPath)\n\t\t\t: undefined;\n\t\tif (cancellation?.aborted) return { search: search, log: undefined };\n\n\t\tconst { args: queryArgs, operations } = parseSearchQueryGitHubCommand(search, currentUser);\n\n\t\tconst values = operations.get('commit:');\n\t\tif (values?.size) {\n\t\t\tconst commit = await this.getCommit(repoPath, first(values)!);\n\t\t\tif (commit == null) return { search: search, log: undefined };\n\n\t\t\treturn {\n\t\t\t\tsearch: search,\n\t\t\t\tlog: {\n\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\tcommits: new Map([[commit.sha, commit]]),\n\t\t\t\t\tsha: commit.sha,\n\t\t\t\t\tcount: 1,\n\t\t\t\t\tlimit: 1,\n\t\t\t\t\thasMore: false,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (!queryArgs.length) return { search: search, log: undefined };\n\n\t\tconst limit = this.provider.getPagingLimit(options?.limit);\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\tconst query = `repo:${metadata.repo.owner}/${metadata.repo.name}+${queryArgs.join('+').trim()}`;\n\n\t\t\tconst result = await github.searchCommits(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tcursor: options?.cursor,\n\t\t\t\t\tlimit: limit,\n\t\t\t\t\tsort:\n\t\t\t\t\t\toptions?.ordering === 'date'\n\t\t\t\t\t\t\t? 'committer-date'\n\t\t\t\t\t\t\t: options?.ordering === 'author-date'\n\t\t\t\t\t\t\t\t? 'author-date'\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (result == null) return { search: search, log: undefined };\n\n\t\t\tconst commits = new Map<string, GitCommit>();\n\t\t\tconst repoUri = coerceUri(repoPath);\n\n\t\t\tconst viewer = session.account.label;\n\t\t\tfor (const commit of result.values) {\n\t\t\t\tlet c = commits.get(commit.oid);\n\t\t\t\tif (c == null) {\n\t\t\t\t\tc = new GitCommit(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tcommit.oid,\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\t\tcommit.message,\n\t\t\t\t\t\tcommit.files != null\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfiles: commit.files.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[],\n\t\t\t\t\t);\n\t\t\t\t\tcommits.set(commit.oid, c);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst log: GitLog = {\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: undefined,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: limit,\n\t\t\t\thasMore: result.pageInfo?.hasNextPage ?? false,\n\t\t\t\tendingCursor: result.pageInfo?.endCursor ?? undefined,\n\t\t\t\tquery: (limit: number | undefined) =>\n\t\t\t\t\tthis.searchCommits(repoPath, search, { ...options, limit: limit }).then(r => r.log!),\n\t\t\t};\n\n\t\t\tif (log.hasMore) {\n\t\t\t\tconst searchCommitsCore = (log: GitLog): ((limit: number | undefined) => Promise<GitLog>) => {\n\t\t\t\t\treturn async (limit: number | undefined) => {\n\t\t\t\t\t\tlimit = this.provider.getPagingLimit(limit);\n\n\t\t\t\t\t\tconst moreLog = (\n\t\t\t\t\t\t\tawait this.searchCommits(log.repoPath, search, {\n\t\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t\tlimit: limit,\n\t\t\t\t\t\t\t\tcursor: log.endingCursor,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t).log;\n\t\t\t\t\t\t// If we can't find any more, assume we have everything\n\t\t\t\t\t\tif (moreLog == null) return { ...log, hasMore: false, more: undefined };\n\n\t\t\t\t\t\tconst commits = new Map([...log.commits, ...moreLog.commits]);\n\n\t\t\t\t\t\tconst mergedLog: GitLog = {\n\t\t\t\t\t\t\trepoPath: log.repoPath,\n\t\t\t\t\t\t\tcommits: commits,\n\t\t\t\t\t\t\tsha: log.sha,\n\t\t\t\t\t\t\tcount: commits.size,\n\t\t\t\t\t\t\tlimit: (log.limit ?? 0) + limit,\n\t\t\t\t\t\t\thasMore: moreLog.hasMore,\n\t\t\t\t\t\t\tendingCursor: moreLog.endingCursor,\n\t\t\t\t\t\t\tquery: log.query,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (mergedLog.hasMore) {\n\t\t\t\t\t\t\tmergedLog.more = searchCommitsCore(mergedLog);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn mergedLog;\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\tlog.more = searchCommitsCore(log);\n\t\t\t}\n\n\t\t\treturn { search: search, log: log };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn { search: search, log: undefined };\n\t\t}\n\t}\n}\n\n/** Converts a GitHub API file entry to a library GitFileChange */\nfunction toFileChange(repoUri: Uri, repoPath: string, f: NonNullable<GitHubCommit['files']>[0]): GitFileChange {\n\tconst path = f.filename ?? '';\n\treturn new GitFileChange(\n\t\trepoPath,\n\t\tpath,\n\t\tfromCommitFileStatus(f.status) ?? GitFileIndexStatus.Modified,\n\t\tjoinUriPath(repoUri, normalizePath(path)),\n\t\tf.previous_filename,\n\t\tf.previous_filename != null ? joinUriPath(repoUri, normalizePath(f.previous_filename)) : undefined,\n\t\tundefined,\n\t\t{\n\t\t\tadditions: f.additions ?? 0,\n\t\t\tdeletions: f.deletions ?? 0,\n\t\t\tchanges: f.changes ?? 0,\n\t\t},\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"commits.js","names":[],"sources":["../../../../../../plus/git-github/src/providers/github/commits.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport { GitCommit, GitCommitIdentity } from '@gitlens/git/models/commit.js';\nimport { GitFileChange } from '@gitlens/git/models/fileChange.js';\nimport { GitFileIndexStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { GitLog } from '@gitlens/git/models/log.js';\nimport type { GitRevisionRange } from '@gitlens/git/models/revision.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { SearchQuery } from '@gitlens/git/models/search.js';\nimport type { GitUser } from '@gitlens/git/models/user.js';\nimport type {\n\tGitCommitsSubProvider,\n\tGitLogForPathOptions,\n\tGitLogOptions,\n\tGitLogShasOptions,\n\tGitRefExclusions,\n\tGitSearchCommitsOptions,\n\tLeftRightCommitCountResult,\n\tSearchCommitsResult,\n} from '@gitlens/git/providers/commits.js';\nimport { createUncommittedChangesCommit } from '@gitlens/git/utils/commit.utils.js';\nimport { createRevisionRange, isUncommitted, stripOrigin } from '@gitlens/git/utils/revision.utils.js';\nimport { parseSearchQueryGitHubCommand } from '@gitlens/git/utils/search.utils.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { first, last, map, some } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { isFolderGlob, normalizePath, stripFolderGlob } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { coerceUri, joinUriPath } from '@gitlens/utils/uri.js';\nimport { toTokenInfo } from '../../api/tokenUtils.js';\nimport type { GitHubCommit } from '../../models.js';\nimport { fromCommitFileStatus } from '../../models.js';\nimport type { GitHubGitProviderInternal } from '../githubProvider.js';\n\nfunction isViewer(name: string, viewer: string | undefined): boolean | undefined {\n\treturn (viewer != null && name === viewer) || undefined;\n}\n\nexport class CommitsGitSubProvider implements GitCommitsSubProvider {\n\tconstructor(\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: GitHubGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tgetCommit(repoPath: string, rev: string, _cancellation?: AbortSignal): Promise<GitCommit | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\t// Don't cache uncommitted-changes synthesis — it's date-sensitive\n\t\tif (isUncommitted(rev, true)) {\n\t\t\treturn (async () => {\n\t\t\t\treturn createUncommittedChangesCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\trev,\n\t\t\t\t\tnew Date(),\n\t\t\t\t\tawait this.provider.config.getCurrentUser(repoPath),\n\t\t\t\t);\n\t\t\t})();\n\t\t}\n\n\t\t// TODO: resolve symbolic refs (HEAD, branch names) to SHA before caching to avoid\n\t\t// short staleness windows. For now we cascade-clear on 'branch'/'branches'.\n\t\treturn this.cache.commit.getOrCreate(repoPath, stripOrigin(rev), async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\ttry {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\t\tconst commit = await github.getCommit(\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\tstripOrigin(rev),\n\t\t\t\t);\n\t\t\t\tif (commit == null) return undefined;\n\n\t\t\t\tconst repoUri = coerceUri(repoPath);\n\n\t\t\t\tconst { viewer = session.account.label } = commit;\n\n\t\t\t\treturn new GitCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tcommit.oid,\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\tcommit.message,\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.files?.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t},\n\t\t\t\t\t[],\n\t\t\t\t);\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\tgetCommitCount(\n\t\trepoPath: string,\n\t\trev: string,\n\t\toptions?: { excluding?: GitRefExclusions },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<number | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\t\t// GitHub can't count against other refs, and a plain count would be the wrong answer\n\t\tif (options?.excluding != null) return Promise.resolve(undefined);\n\n\t\treturn this.cache.commitCount.getOrCreate(repoPath, stripOrigin(rev), async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\ttry {\n\t\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\t\tconst count = await github.getCommitCount(\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\tstripOrigin(rev),\n\t\t\t\t);\n\n\t\t\t\treturn count;\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 getCommitFiles(repoPath: string, rev: string, _cancellation?: AbortSignal): Promise<GitFileChange[]> {\n\t\tif (rev === deletedOrMissing || isUncommitted(rev)) return [];\n\n\t\tconst commit = await this.getCommit(repoPath, rev);\n\t\treturn [...(commit?.fileset?.files ?? [])];\n\t}\n\n\t@debug()\n\tasync getCommitForFile(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev?: string | undefined,\n\t\t_options?: { firstIfNotFound?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitCommit | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\tconst rootUri = this.provider.getProviderRootUri(this.provider.getAbsoluteUri(pathOrUri, repoPath));\n\t\tconst file = this.provider.getRelativePath(this.provider.getAbsoluteUri(pathOrUri, repoPath), rootUri);\n\n\t\t// Resolve HEAD/empty rev to the metadata revision so the cache key is stable across callers\n\t\tconst resolvedRev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\t\t// Path-scoped variant lives in the same slot as `getCommit` but with a `|file` suffix to\n\t\t// keep it distinct from the unscoped commit entry.\n\t\tconst cacheKey = `${stripOrigin(resolvedRev)}|${file}`;\n\n\t\treturn this.cache.commit.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\tconst scope = getScopedLogger();\n\n\t\t\ttry {\n\t\t\t\tconst commit = await github.getCommitForFile(\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\tstripOrigin(resolvedRev),\n\t\t\t\t\tfile,\n\t\t\t\t);\n\t\t\t\tif (commit == null) return undefined;\n\n\t\t\t\tconst repoUri = coerceUri(repoPath);\n\t\t\t\tconst { viewer = session.account.label } = commit;\n\n\t\t\t\treturn new GitCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tcommit.oid,\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\tcommit.message,\n\t\t\t\t\tcommit.files != null\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfiles: undefined,\n\t\t\t\t\t\t\t\tfiltered: {\n\t\t\t\t\t\t\t\t\tfiles: commit.files?.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t\t\t\t\tpathspec: file,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t},\n\t\t\t\t\t[],\n\t\t\t\t);\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\tgetLeftRightCommitCount(\n\t\trepoPath: string,\n\t\trange: GitRevisionRange,\n\t\t_options?: { authors?: GitUser[]; excludeMerges?: boolean },\n\t\t_cancellation?: AbortSignal,\n\t): Promise<LeftRightCommitCountResult | undefined> {\n\t\tif (repoPath == null) return Promise.resolve(undefined);\n\n\t\treturn this.cache.leftRightCommitCount.getOrCreate(repoPath, stripOrigin(range), 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\tstripOrigin(range),\n\t\t\t\t);\n\n\t\t\t\tif (result == null) return undefined;\n\n\t\t\t\treturn {\n\t\t\t\t\tleft: result.behind_by,\n\t\t\t\t\tright: result.ahead_by,\n\t\t\t\t};\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 getLog(\n\t\trepoPath: string,\n\t\trev?: string | undefined,\n\t\toptions?: GitLogOptions,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitLog | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst limit = this.provider.getPagingLimit(options?.limit);\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\trev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\t\t\tconst result = await github.getCommits(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\tstripOrigin(rev),\n\t\t\t\t{\n\t\t\t\t\tall: options?.all,\n\t\t\t\t\tauthors: options?.authors,\n\t\t\t\t\tafter: options?.cursor,\n\t\t\t\t\tlimit: limit,\n\t\t\t\t\tsince: options?.since ? new Date(options.since) : undefined,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst commits = new Map<string, GitCommit>();\n\t\t\tconst repoUri = coerceUri(repoPath);\n\n\t\t\tconst { viewer = session.account.label } = result;\n\t\t\tfor (const commit of result.values) {\n\t\t\t\tlet c = commits.get(commit.oid);\n\t\t\t\tif (c == null) {\n\t\t\t\t\tc = new GitCommit(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tcommit.oid,\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\t\tcommit.message,\n\t\t\t\t\t\tcommit.files != null\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfiles: commit.files.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[],\n\t\t\t\t\t);\n\t\t\t\t\tcommits.set(commit.oid, c);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst log: GitLog = {\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: rev,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: limit,\n\t\t\t\thasMore: result.paging?.more ?? false,\n\t\t\t\tendingCursor: result.paging?.cursor,\n\t\t\t\tquery: (limit: number | undefined) => this.getLog(repoPath, rev, { ...options, limit: limit }),\n\t\t\t};\n\n\t\t\tif (log.hasMore) {\n\t\t\t\tlog.more = this.getLogMoreFn(log, rev, options);\n\t\t\t}\n\n\t\t\treturn log;\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\tprivate getLogMoreFn(\n\t\tlog: GitLog,\n\t\trev: string | undefined,\n\t\toptions?: GitLogOptions,\n\t): (limit: number | { until: string } | undefined) => Promise<GitLog> {\n\t\treturn async (limit: number | { until: string } | undefined) => {\n\t\t\tconst moreUntil = limit != null && typeof limit === 'object' ? limit.until : undefined;\n\t\t\tlet moreLimit = typeof limit === 'number' ? limit : undefined;\n\n\t\t\tif (moreUntil && some(log.commits.values(), c => c.ref === moreUntil)) {\n\t\t\t\treturn log;\n\t\t\t}\n\n\t\t\tmoreLimit = this.provider.getPagingLimit(moreLimit);\n\n\t\t\tconst moreLog = await this.getLog(log.repoPath, rev, {\n\t\t\t\t...options,\n\t\t\t\tlimit: moreLimit,\n\t\t\t\tcursor: log.endingCursor,\n\t\t\t});\n\t\t\t// If we can't find any more, assume we have everything\n\t\t\tif (moreLog == null) return { ...log, hasMore: false, more: undefined };\n\n\t\t\tconst commits = new Map([...log.commits, ...moreLog.commits]);\n\n\t\t\tconst mergedLog: GitLog = {\n\t\t\t\trepoPath: log.repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: log.sha,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: moreUntil == null ? (log.limit ?? 0) + moreLimit : undefined,\n\t\t\t\thasMore: moreUntil == null ? moreLog.hasMore : true,\n\t\t\t\t// The oldest commit SHA of the previous page — the graph webview compares this\n\t\t\t\t// against its last displayed row to determine the merge point for appending new rows\n\t\t\t\tstartingCursor: last(log.commits)?.[0],\n\t\t\t\tendingCursor: moreLog.endingCursor,\n\t\t\t\tpagedCommits: () => {\n\t\t\t\t\t// Remove any duplicates\n\t\t\t\t\tfor (const sha of log.commits.keys()) {\n\t\t\t\t\t\tmoreLog.commits.delete(sha);\n\t\t\t\t\t}\n\t\t\t\t\treturn moreLog.commits;\n\t\t\t\t},\n\t\t\t\tquery: log.query,\n\t\t\t};\n\t\t\tif (mergedLog.hasMore) {\n\t\t\t\tmergedLog.more = this.getLogMoreFn(mergedLog, rev, options);\n\t\t\t}\n\n\t\t\treturn mergedLog;\n\t\t};\n\t}\n\n\t@debug()\n\tasync getLogForPath(\n\t\trepoPath: string,\n\t\tpathOrUri: string | Uri,\n\t\trev?: string | undefined,\n\t\toptions?: GitLogForPathOptions,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<GitLog | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tlet relativePath = this.provider.getRelativePath(pathOrUri, repoPath);\n\n\t\tif (repoPath != null && repoPath === relativePath) {\n\t\t\tthrow new Error(`Path cannot match the repository path; path=${relativePath}`);\n\t\t}\n\n\t\toptions = {\n\t\t\t...options,\n\t\t\tall: false /* not supported */,\n\t\t\tlimit: this.provider.getPagingLimit(options?.limit),\n\t\t\trenames: false /* not supported */,\n\t\t};\n\n\t\tif (isFolderGlob(relativePath)) {\n\t\t\trelativePath = stripFolderGlob(relativePath);\n\t\t\toptions.isFolder = true;\n\t\t} else if (options.isFolder == null) {\n\t\t\tconst tree = await this.provider.revision.getTreeEntryForRevision(repoPath, relativePath, rev || 'HEAD');\n\t\t\toptions.isFolder = tree?.type === 'tree';\n\t\t}\n\n\t\t// Note: document caching (TrackedGitDocument) is handled by the extension wrapper.\n\t\t// The library implementation always fetches fresh data.\n\t\treturn this.getLogForPathCore(repoPath, relativePath, rev, options);\n\t}\n\n\tprivate async getLogForPathCore(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\trev: string | undefined,\n\t\toptions: GitLogForPathOptions,\n\t): Promise<GitLog | undefined> {\n\t\tif (repoPath == null) return undefined;\n\n\t\tconst limit = this.provider.getPagingLimit(options.limit);\n\n\t\tconst context = await this.provider.ensureRepositoryContext(repoPath);\n\t\tif (context == null) return undefined;\n\n\t\tconst { metadata, github, session } = context;\n\n\t\tconst uri = this.provider.getAbsoluteUri(path, repoPath);\n\t\tconst relativePath = this.provider.getRelativePath(uri, this.provider.getProviderRootUri(uri));\n\n\t\trev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\t\tconst result = await github.getCommits(\n\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\tmetadata.repo.owner,\n\t\t\tmetadata.repo.name,\n\t\t\tstripOrigin(rev),\n\t\t\t{\n\t\t\t\tall: options.all,\n\t\t\t\tafter: options.cursor,\n\t\t\t\tpath: relativePath,\n\t\t\t\tlimit: limit,\n\t\t\t\tsince: options.since ? new Date(options.since) : undefined,\n\t\t\t},\n\t\t);\n\n\t\tconst repoUri = coerceUri(repoPath);\n\t\tconst commits = new Map<string, GitCommit>();\n\n\t\tconst { viewer = session.account.label } = result;\n\t\tfor (const commit of result.values) {\n\t\t\tlet c = commits.get(commit.oid);\n\t\t\tif (c == null) {\n\t\t\t\tconst files = commit.files?.map(f => toFileChange(repoUri, repoPath, f));\n\n\t\t\t\tif (files != null && !options.isFolder && commit.changedFiles === 1) {\n\t\t\t\t\tconst index = files.findIndex(f => f.path === relativePath);\n\t\t\t\t\tif (index !== -1) {\n\t\t\t\t\t\tfiles.splice(\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\tnew GitFileChange(\n\t\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t\trelativePath,\n\t\t\t\t\t\t\t\tGitFileIndexStatus.Modified,\n\t\t\t\t\t\t\t\tjoinUriPath(repoUri, normalizePath(relativePath)),\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\tundefined,\n\t\t\t\t\t\t\t\tcommit.changedFiles === 1\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t\t\t\t\t\t\tchanges: 0,\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tc = new GitCommit(\n\t\t\t\t\trepoPath,\n\t\t\t\t\tcommit.oid,\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t),\n\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\tcommit.message,\n\t\t\t\t\t{ files: undefined, filtered: { files: files, pathspec: relativePath } },\n\t\t\t\t\t{\n\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t},\n\t\t\t\t\t[],\n\t\t\t\t);\n\t\t\t\tcommits.set(commit.oid, c);\n\t\t\t}\n\t\t}\n\n\t\tconst log: GitLog = {\n\t\t\trepoPath: repoPath,\n\t\t\tcommits: commits,\n\t\t\tsha: rev,\n\t\t\tcount: commits.size,\n\t\t\tlimit: limit,\n\t\t\thasMore: result.paging?.more ?? false,\n\t\t\tendingCursor: result.paging?.cursor,\n\t\t\tquery: (limit: number | undefined) => this.getLogForPath(repoPath, path, rev, { ...options, limit: limit }),\n\t\t};\n\t\tif (log.hasMore) {\n\t\t\tlog.more = this.getLogForPathMoreFn(log, path, rev, options);\n\t\t}\n\n\t\treturn log;\n\t}\n\n\tprivate getLogForPathMoreFn(\n\t\tlog: GitLog,\n\t\trelativePath: string,\n\t\trev: string | undefined,\n\t\toptions: GitLogForPathOptions,\n\t): (limit: number | { until: string } | undefined) => Promise<GitLog> {\n\t\treturn async (limit: number | { until: string } | undefined) => {\n\t\t\tconst moreUntil = limit != null && typeof limit === 'object' ? limit.until : undefined;\n\t\t\tlet moreLimit = typeof limit === 'number' ? limit : undefined;\n\n\t\t\tif (moreUntil && some(log.commits.values(), c => c.ref === moreUntil)) {\n\t\t\t\treturn log;\n\t\t\t}\n\n\t\t\tmoreLimit = this.provider.getPagingLimit(moreLimit);\n\n\t\t\tconst moreLog = await this.getLogForPath(log.repoPath, relativePath, rev, {\n\t\t\t\t...options,\n\t\t\t\tlimit: moreUntil == null ? moreLimit : 0,\n\t\t\t\tcursor: log.endingCursor,\n\t\t\t});\n\t\t\t// If we can't find any more, assume we have everything\n\t\t\tif (moreLog == null) return { ...log, hasMore: false, more: undefined };\n\n\t\t\tconst commits = new Map([...log.commits, ...moreLog.commits]);\n\n\t\t\tconst mergedLog: GitLog = {\n\t\t\t\trepoPath: log.repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: log.sha,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: moreUntil == null ? (log.limit ?? 0) + moreLimit : undefined,\n\t\t\t\thasMore: moreUntil == null ? moreLog.hasMore : true,\n\t\t\t\tendingCursor: moreLog.endingCursor,\n\t\t\t\tquery: log.query,\n\t\t\t};\n\n\t\t\tif (mergedLog.hasMore) {\n\t\t\t\tmergedLog.more = this.getLogForPathMoreFn(mergedLog, relativePath, rev, options);\n\t\t\t}\n\n\t\t\treturn mergedLog;\n\t\t};\n\t}\n\n\t@debug()\n\tasync getLogShas(\n\t\trepoPath: string,\n\t\trev?: string | undefined,\n\t\toptions?: GitLogShasOptions,\n\t\tcancellation?: AbortSignal,\n\t): Promise<Iterable<string>> {\n\t\tif (repoPath == null) return [];\n\t\t// GitHub can't evaluate `--not`, and an unfiltered list would be the wrong answer\n\t\tif (options?.excluding != null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\t// `authors` and `all` filters aren't supported by the lightweight SHA-only query;\n\t\t// fall back to the full log path when set.\n\t\tif (options?.authors?.length || options?.all) {\n\t\t\tlet log: GitLog | undefined;\n\t\t\tif (options?.pathOrUri != null) {\n\t\t\t\tlog = await this.getLogForPath(repoPath, options.pathOrUri, rev, options, cancellation);\n\t\t\t} else {\n\t\t\t\tlog = await this.getLog(repoPath, rev, options, cancellation);\n\t\t\t}\n\t\t\tif (log == null) return [];\n\n\t\t\tconst shas = map(log.commits.values(), c => c.ref);\n\t\t\t// Note: reversal only applies to the first page — subsequent pages loaded via pagination are not reversed\n\t\t\treturn options?.reverse ? [...shas].reverse() : shas;\n\t\t}\n\n\t\tconst limit = this.provider.getPagingLimit(options?.limit);\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\trev = !rev || rev === 'HEAD' ? (await metadata.getRevision()).revision : rev;\n\n\t\t\tlet path: string | undefined;\n\t\t\tif (options?.pathOrUri != null) {\n\t\t\t\tconst rootUri = this.provider.getProviderRootUri(\n\t\t\t\t\tthis.provider.getAbsoluteUri(options.pathOrUri, repoPath),\n\t\t\t\t);\n\t\t\t\tpath = this.provider.getRelativePath(\n\t\t\t\t\tthis.provider.getAbsoluteUri(options.pathOrUri, repoPath),\n\t\t\t\t\trootUri,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst strippedRev = stripOrigin(rev);\n\t\t\tconst sinceISO = options?.since ? new Date(options.since).toISOString() : '';\n\t\t\tconst cacheKey = `${strippedRev}|${path ?? ''}|${sinceISO}|${limit}|${options?.cursor ?? ''}`;\n\n\t\t\tconst shas = await this.cache.logShas.getOrCreate(repoPath, cacheKey, async () => {\n\t\t\t\tconst result = await github.getCommitShas(\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\tstrippedRev,\n\t\t\t\t\t{\n\t\t\t\t\t\tafter: options?.cursor,\n\t\t\t\t\t\tlimit: limit,\n\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\tsince: options?.since ? new Date(options.since) : undefined,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\treturn result.values;\n\t\t\t});\n\n\t\t\t// Note: reversal only applies to the first page — subsequent pages loaded via pagination are not reversed\n\t\t\treturn options?.reverse ? shas.toReversed() : shas;\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\tgetOldestUnpushedShaForPath(\n\t\t_repoPath: string,\n\t\t_pathOrUri: string | Uri,\n\t\t_cancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\t// TODO@eamodio until we have access to the RemoteHub change store there isn't anything we can do here\n\t\treturn Promise.resolve(undefined);\n\t}\n\n\t@debug()\n\thasCommitBeenPushed(_repoPath: string, _rev: string, _cancellation?: AbortSignal): Promise<boolean> {\n\t\t// In this env we can't have unpushed commits\n\t\treturn Promise.resolve(true);\n\t}\n\n\t@debug()\n\tasync isAncestorOf(repoPath: string, rev1: string, rev2: string, _cancellation?: AbortSignal): Promise<boolean> {\n\t\tif (repoPath == null) return false;\n\n\t\tconst scope = getScopedLogger();\n\n\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\ttry {\n\t\t\tconst result = await github.getComparison(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tmetadata.repo.owner,\n\t\t\t\tmetadata.repo.name,\n\t\t\t\tcreateRevisionRange(stripOrigin(rev1), stripOrigin(rev2), '...'),\n\t\t\t);\n\n\t\t\tswitch (result?.status) {\n\t\t\t\tcase 'ahead':\n\t\t\t\tcase 'diverged':\n\t\t\t\t\treturn false;\n\t\t\t\tcase 'identical':\n\t\t\t\tcase 'behind':\n\t\t\t\t\treturn true;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t@debug({\n\t\targs: (repoPath, s) => ({\n\t\t\trepoPath: repoPath,\n\t\t\tsearch: `[${s.matchAll ? 'A' : ''}${s.matchCase ? 'C' : ''}${s.matchRegex ? 'R' : ''}${\n\t\t\t\ts.matchWholeWord ? 'W' : ''\n\t\t\t}]: ${s.query.length > 500 ? `${s.query.substring(0, 500)}...` : s.query}`,\n\t\t}),\n\t})\n\tasync searchCommits(\n\t\trepoPath: string,\n\t\tsearch: SearchQuery,\n\t\toptions?: GitSearchCommitsOptions,\n\t\tcancellation?: AbortSignal,\n\t): Promise<SearchCommitsResult> {\n\t\tif (repoPath == null) return { search: search, log: undefined };\n\n\t\tconst scope = getScopedLogger();\n\n\t\tsearch = { matchAll: false, matchCase: false, matchRegex: true, matchWholeWord: false, ...search };\n\t\t// Note: Natural language processing is handled by the extension wrapper.\n\n\t\tconst currentUser = search.query.includes('@me')\n\t\t\t? await this.provider.config.getCurrentUser(repoPath)\n\t\t\t: undefined;\n\t\tif (cancellation?.aborted) return { search: search, log: undefined };\n\n\t\tconst { args: queryArgs, operations } = parseSearchQueryGitHubCommand(search, currentUser);\n\n\t\tconst values = operations.get('commit:');\n\t\tif (values?.size) {\n\t\t\tconst commit = await this.getCommit(repoPath, first(values)!);\n\t\t\tif (commit == null) return { search: search, log: undefined };\n\n\t\t\treturn {\n\t\t\t\tsearch: search,\n\t\t\t\tlog: {\n\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\tcommits: new Map([[commit.sha, commit]]),\n\t\t\t\t\tsha: commit.sha,\n\t\t\t\t\tcount: 1,\n\t\t\t\t\tlimit: 1,\n\t\t\t\t\thasMore: false,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (!queryArgs.length) return { search: search, log: undefined };\n\n\t\tconst limit = this.provider.getPagingLimit(options?.limit);\n\n\t\ttry {\n\t\t\tconst { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);\n\n\t\t\tconst query = `repo:${metadata.repo.owner}/${metadata.repo.name}+${queryArgs.join('+').trim()}`;\n\n\t\t\tconst result = await github.searchCommits(\n\t\t\t\ttoTokenInfo(this.provider.authenticationProviderId, session),\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tcursor: options?.cursor,\n\t\t\t\t\tlimit: limit,\n\t\t\t\t\tsort:\n\t\t\t\t\t\toptions?.ordering === 'date'\n\t\t\t\t\t\t\t? 'committer-date'\n\t\t\t\t\t\t\t: options?.ordering === 'author-date'\n\t\t\t\t\t\t\t\t? 'author-date'\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (result == null) return { search: search, log: undefined };\n\n\t\t\tconst commits = new Map<string, GitCommit>();\n\t\t\tconst repoUri = coerceUri(repoPath);\n\n\t\t\tconst viewer = session.account.label;\n\t\t\tfor (const commit of result.values) {\n\t\t\t\tlet c = commits.get(commit.oid);\n\t\t\t\tif (c == null) {\n\t\t\t\t\tc = new GitCommit(\n\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\tcommit.oid,\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.author.name,\n\t\t\t\t\t\t\tcommit.author.email,\n\t\t\t\t\t\t\tnew Date(commit.author.date),\n\t\t\t\t\t\t\tcommit.author.avatarUrl,\n\t\t\t\t\t\t\tisViewer(commit.author.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew GitCommitIdentity(\n\t\t\t\t\t\t\tcommit.committer.name,\n\t\t\t\t\t\t\tcommit.committer.email,\n\t\t\t\t\t\t\tnew Date(commit.committer.date),\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tisViewer(commit.committer.name, viewer),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcommit.message.split('\\n', 1)[0],\n\t\t\t\t\t\tcommit.parents.nodes.map(p => p.oid),\n\t\t\t\t\t\tcommit.message,\n\t\t\t\t\t\tcommit.files != null\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfiles: commit.files.map(f => toFileChange(repoUri, repoPath, f)),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfiles: commit.changedFiles ?? 0,\n\t\t\t\t\t\t\tadditions: commit.additions ?? 0,\n\t\t\t\t\t\t\tdeletions: commit.deletions ?? 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[],\n\t\t\t\t\t);\n\t\t\t\t\tcommits.set(commit.oid, c);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst log: GitLog = {\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tcommits: commits,\n\t\t\t\tsha: undefined,\n\t\t\t\tcount: commits.size,\n\t\t\t\tlimit: limit,\n\t\t\t\thasMore: result.pageInfo?.hasNextPage ?? false,\n\t\t\t\tendingCursor: result.pageInfo?.endCursor ?? undefined,\n\t\t\t\tquery: (limit: number | undefined) =>\n\t\t\t\t\tthis.searchCommits(repoPath, search, { ...options, limit: limit }).then(r => r.log!),\n\t\t\t};\n\n\t\t\tif (log.hasMore) {\n\t\t\t\tconst searchCommitsCore = (log: GitLog): ((limit: number | undefined) => Promise<GitLog>) => {\n\t\t\t\t\treturn async (limit: number | undefined) => {\n\t\t\t\t\t\tlimit = this.provider.getPagingLimit(limit);\n\n\t\t\t\t\t\tconst moreLog = (\n\t\t\t\t\t\t\tawait this.searchCommits(log.repoPath, search, {\n\t\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t\tlimit: limit,\n\t\t\t\t\t\t\t\tcursor: log.endingCursor,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t).log;\n\t\t\t\t\t\t// If we can't find any more, assume we have everything\n\t\t\t\t\t\tif (moreLog == null) return { ...log, hasMore: false, more: undefined };\n\n\t\t\t\t\t\tconst commits = new Map([...log.commits, ...moreLog.commits]);\n\n\t\t\t\t\t\tconst mergedLog: GitLog = {\n\t\t\t\t\t\t\trepoPath: log.repoPath,\n\t\t\t\t\t\t\tcommits: commits,\n\t\t\t\t\t\t\tsha: log.sha,\n\t\t\t\t\t\t\tcount: commits.size,\n\t\t\t\t\t\t\tlimit: (log.limit ?? 0) + limit,\n\t\t\t\t\t\t\thasMore: moreLog.hasMore,\n\t\t\t\t\t\t\tendingCursor: moreLog.endingCursor,\n\t\t\t\t\t\t\tquery: log.query,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (mergedLog.hasMore) {\n\t\t\t\t\t\t\tmergedLog.more = searchCommitsCore(mergedLog);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn mergedLog;\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\tlog.more = searchCommitsCore(log);\n\t\t\t}\n\n\t\t\treturn { search: search, log: log };\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tdebugger;\n\t\t\treturn { search: search, log: undefined };\n\t\t}\n\t}\n}\n\n/** Converts a GitHub API file entry to a library GitFileChange */\nfunction toFileChange(repoUri: Uri, repoPath: string, f: NonNullable<GitHubCommit['files']>[0]): GitFileChange {\n\tconst path = f.filename ?? '';\n\treturn new GitFileChange(\n\t\trepoPath,\n\t\tpath,\n\t\tfromCommitFileStatus(f.status) ?? GitFileIndexStatus.Modified,\n\t\tjoinUriPath(repoUri, normalizePath(path)),\n\t\tf.previous_filename,\n\t\tf.previous_filename != null ? joinUriPath(repoUri, normalizePath(f.previous_filename)) : undefined,\n\t\tundefined,\n\t\t{\n\t\t\tadditions: f.additions ?? 0,\n\t\t\tdeletions: f.deletions ?? 0,\n\t\t\tchanges: f.changes ?? 0,\n\t\t},\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { GitHubGitProviderInternal } from "../githubProvider.js";
|
|
|
6
6
|
export declare class RevisionGitSubProvider implements GitRevisionSubProvider {
|
|
7
7
|
private readonly provider;
|
|
8
8
|
constructor(provider: GitHubGitProviderInternal);
|
|
9
|
+
getEmptyTreeSha(_repoPath: string): Promise<string>;
|
|
9
10
|
getRevisionContent(repoPath: string, path: string, rev: string): Promise<Uint8Array | undefined>;
|
|
10
11
|
getTreeEntryForRevision(repoPath: string, path: string, rev: string): Promise<GitTreeEntry | undefined>;
|
|
11
12
|
getTrackedFiles(repoPath: string): Promise<string[]>;
|
|
@@ -6,11 +6,16 @@ import { FileType } from "../../../../git/context.js";
|
|
|
6
6
|
import { gate } from "../../../../utils/decorators/gate.js";
|
|
7
7
|
import { toTokenInfo } from "../../api/tokenUtils.js";
|
|
8
8
|
//#region ../plus/git-github/src/providers/github/revision.ts
|
|
9
|
+
/** GitHub repositories are always SHA-1 */
|
|
10
|
+
const sha1EmptyTreeSha = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
9
11
|
var RevisionGitSubProvider = class {
|
|
10
12
|
provider;
|
|
11
13
|
constructor(provider) {
|
|
12
14
|
this.provider = provider;
|
|
13
15
|
}
|
|
16
|
+
getEmptyTreeSha(_repoPath) {
|
|
17
|
+
return Promise.resolve(sha1EmptyTreeSha);
|
|
18
|
+
}
|
|
14
19
|
getRevisionContent(repoPath, path, rev) {
|
|
15
20
|
const uri = rev ? this.provider.createProviderUri(repoPath, rev, path) : this.provider.createVirtualUri(repoPath, rev, path);
|
|
16
21
|
return this.provider.context.fs.readFile(uri);
|
|
@@ -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(\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":"
|
|
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\n/** GitHub repositories are always SHA-1 */\nconst sha1EmptyTreeSha = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';\n\nexport class RevisionGitSubProvider implements GitRevisionSubProvider {\n\tconstructor(private readonly provider: GitHubGitProviderInternal) {}\n\n\tgetEmptyTreeSha(_repoPath: string): Promise<string> {\n\t\treturn Promise.resolve(sha1EmptyTreeSha);\n\t}\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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"}
|
|
@@ -36,6 +36,12 @@ export interface ProviderRefusal {
|
|
|
36
36
|
detail?: string;
|
|
37
37
|
/** The provider's error type, when the body names one (Azure DevOps `typeKey`). */
|
|
38
38
|
typeKey?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The OAuth app the refused token belongs to, when the provider says (GitHub's `X-OAuth-Client-Id`). Not a
|
|
41
|
+
* secret: it is the app's public client id, which the page where a user asks an organization to approve the app
|
|
42
|
+
* is addressed by.
|
|
43
|
+
*/
|
|
44
|
+
oauthClientId?: string;
|
|
39
45
|
}
|
|
40
46
|
/** A scope failure as recorded here: the SDK's shape, plus what the refusal said and, once it is known, why. */
|
|
41
47
|
export interface ProviderScopeFailure extends CollectionScopeFailure {
|
|
@@ -35,20 +35,23 @@ function toCollectionFailureKind(ex) {
|
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Reads the refusal off an `AuthenticationError` that carries the provider's response: the SDK adapter's plain
|
|
38
|
-
* `{ status, headers, body }` (`providersApi.ts`),
|
|
39
|
-
* already read into its message.
|
|
38
|
+
* `{ status, headers, body }` (`providersApi.ts`), Octokit's `{ status, headers, data }` (the GitHub client's REST
|
|
39
|
+
* reads), or the `Response` of a `ProviderFetchError`, whose body was already read into its message.
|
|
40
40
|
*/
|
|
41
41
|
function toProviderRefusal(ex) {
|
|
42
42
|
if (!(ex instanceof AuthenticationError)) return void 0;
|
|
43
43
|
const response = ex.original?.response;
|
|
44
44
|
if (typeof response?.status !== "number") return void 0;
|
|
45
|
-
const
|
|
45
|
+
const raw = response.body ?? response.data;
|
|
46
|
+
const body = typeof raw === "object" && raw != null ? raw : void 0;
|
|
46
47
|
const detail = decodeServiceError(getResponseHeader(response.headers, "x-tfs-serviceerror")) ?? getProviderResponseBodyMessage(body);
|
|
47
48
|
const typeKey = body != null && "typeKey" in body ? body.typeKey : void 0;
|
|
49
|
+
const oauthClientId = getResponseHeader(response.headers, "x-oauth-client-id");
|
|
48
50
|
return {
|
|
49
51
|
status: response.status,
|
|
50
52
|
...detail ? { detail } : {},
|
|
51
|
-
...typeof typeKey === "string" ? { typeKey } : {}
|
|
53
|
+
...typeof typeKey === "string" ? { typeKey } : {},
|
|
54
|
+
...typeof oauthClientId === "string" && oauthClientId ? { oauthClientId } : {}
|
|
52
55
|
};
|
|
53
56
|
}
|
|
54
57
|
/** Azure DevOps sends `X-TFS-ServiceError` percent-encoded. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collectionMetadata.js","names":[],"sources":["../../../../plus/integrations/src/collectionMetadata.ts"],"sourcesContent":["import type {\n\tCollectionMetadata,\n\tCollectionOmission,\n\tCollectionScope,\n\tCollectionScopeFailure,\n} from '@gitkraken/provider-apis';\n// Matched by its `code` discriminator rather than by `instanceof`: the SDK ships one bundle per entry point, so\n// the class reached through the root is not the same object as the one reached through `/providers`.\nimport { isInvalidRequestError, isUnsupportedSortError } from '@gitkraken/provider-apis';\nimport {\n\tAuthenticationError,\n\tRequestClientError,\n\tRequestNotFoundError,\n\tRequestRateLimitError,\n} from '@gitlens/git/errors.js';\nimport type { TokenWithInfo } from './authentication/models.js';\nimport type { IntegrationIds } from './constants.js';\nimport type { ResponseHeaders } from './errors.js';\nimport { getResponseHeader, isRateLimitResponse } from './errors.js';\nimport { getProviderResponseBodyMessage } from './providers/providerErrors.js';\nimport type {\n\tProviderWarning,\n\tProviderWarningCause,\n\tProviderWarningOmission,\n\tProviderWarningScope,\n} from './results.js';\nimport { appendDedupedWarning, providerWarningMessage } from './results.js';\n\n/**\n * Re-throws an error that is a fact about the CALL rather than about one scope of a fan-out.\n *\n * Every provider fan-out catches per-scope rejections and records them as {@link CollectionScopeFailure}s, which is\n * right for auth, rate limits and a missing project: those really did happen to one scope, and the siblings that\n * succeeded must survive. A caller-contract error is the opposite — it is identical for every scope and was decided\n * before any request went out — so degrading it would hand back N indistinguishable failures and an empty `partial`\n * page, describing an invalid call as an incomplete read.\n *\n * Today that means the SDK's `UnsupportedSortError` and `InvalidRequestError` — the two codes it lists in its own\n * `CALLER_CONTRACT_ERROR_CODES`, both documented as \"never degraded into a `CollectionScopeFailure` or an\n * omission\". The second covers arguments rejected before the first request goes out: a project key list longer\n * than one Jira search can carry (or an empty one), a non-integer `pageSize`, an unknown current-user filter, or a\n * Jira Server read with no `baseUrl` to address. Called from every fan-out rather than spelled out in each, so a\n * fan-out added later inherits the rule instead of silently omitting it — which is exactly how Azure's\n * account-wide drain came to degrade it while its three siblings did not.\n */\nexport function throwIfCallerContractError(ex: unknown): void {\n\tif (isUnsupportedSortError(ex) || isInvalidRequestError(ex)) throw ex;\n}\n\n/**\n * Maps a caught GitLens request error to the SDK collection failure vocabulary used inside provider fan-outs.\n */\nexport function toCollectionFailureKind(ex: unknown): CollectionScopeFailure['kind'] {\n\tif (ex instanceof AuthenticationError) return 'authentication';\n\tif (ex instanceof RequestRateLimitError) return 'rate-limit';\n\tif (ex instanceof RequestNotFoundError) return 'not-found';\n\treturn 'provider';\n}\n\n/**\n * What an authentication refusal's response said, kept on the failure so the provider can name its cause once the\n * credential behind it is confirmed (see `IntegrationBase.confirmScopedAuthFailures`). Only these facts are kept,\n * never the response: its headers carry the provider's session cookies.\n */\nexport interface ProviderRefusal {\n\tstatus: number;\n\t/** The provider's own explanation: Azure DevOps' `X-TFS-ServiceError`, or the error body's message. */\n\tdetail?: string;\n\t/** The provider's error type, when the body names one (Azure DevOps `typeKey`). */\n\ttypeKey?: string;\n}\n\n/** A scope failure as recorded here: the SDK's shape, plus what the refusal said and, once it is known, why. */\nexport interface ProviderScopeFailure extends CollectionScopeFailure {\n\trefusal?: ProviderRefusal;\n\tcause?: ProviderWarningCause;\n\t/** The provider pinned the refusal on the credential itself, so it is published for the connection, unscoped. */\n\tcredentialRefused?: true;\n}\n\n/**\n * Reads the refusal off an `AuthenticationError` that carries the provider's response: the SDK adapter's plain\n * `{ status, headers, body }` (`providersApi.ts`), or the `Response` of a `ProviderFetchError`, whose body was\n * already read into its message.\n */\nfunction toProviderRefusal(ex: unknown): ProviderRefusal | undefined {\n\tif (!(ex instanceof AuthenticationError)) return undefined;\n\n\tconst response = (ex.original as { response?: unknown } | undefined)?.response as\n\t\t| { status?: unknown; headers?: ResponseHeaders; body?: unknown }\n\t\t| undefined;\n\tif (typeof response?.status !== 'number') return undefined;\n\n\t// Only a structured body: a string one is a page (a proxy's, a sign-in form), not an explanation.\n\tconst body = typeof response.body === 'object' && response.body != null ? response.body : undefined;\n\tconst detail =\n\t\tdecodeServiceError(getResponseHeader(response.headers, 'x-tfs-serviceerror')) ??\n\t\tgetProviderResponseBodyMessage(body);\n\tconst typeKey = body != null && 'typeKey' in body ? body.typeKey : undefined;\n\n\treturn {\n\t\tstatus: response.status,\n\t\t...(detail ? { detail: detail } : {}),\n\t\t...(typeof typeKey === 'string' ? { typeKey: typeKey } : {}),\n\t};\n}\n\n/** Azure DevOps sends `X-TFS-ServiceError` percent-encoded. */\nfunction decodeServiceError(value: unknown): string | undefined {\n\tif (typeof value !== 'string' || !value) return undefined;\n\n\ttry {\n\t\treturn decodeURIComponent(value).trim() || undefined;\n\t} catch {\n\t\treturn value.trim() || undefined;\n\t}\n}\n\n/**\n * Builds a structured SDK scope failure from a caught GitLens request error.\n *\n * An authentication refusal is described in the provider's own words when it gives any, and otherwise by the\n * error the provider's response raised, sanitized like any warning's (a page becomes its status), rather than by\n * `AuthenticationError`'s generic \"credentials are either invalid or expired\": a scope refusing a sound credential\n * is the case this failure exists to tell apart, and that sentence says the opposite.\n */\nexport function toCollectionScopeFailure(scope: CollectionScopeFailure['scope'], ex: unknown): ProviderScopeFailure {\n\tconst refusal = toProviderRefusal(ex);\n\tconst message =\n\t\trefusal != null ? (refusal.detail ?? providerWarningMessage((ex as AuthenticationError).original)) : undefined;\n\treturn {\n\t\tscope: scope,\n\t\tkind: toCollectionFailureKind(ex),\n\t\t...(message ? { message: message } : ex instanceof Error && ex.message ? { message: ex.message } : {}),\n\t\t...(refusal != null ? { refusal: refusal } : {}),\n\t};\n}\n\nfunction collectionFailureKindToWarningKind(kind: CollectionScopeFailure['kind']): ProviderWarning['kind'] {\n\tswitch (kind) {\n\t\tcase 'authentication':\n\t\t\treturn 'auth';\n\t\tcase 'rate-limit':\n\t\t\treturn 'rate-limit';\n\t\tcase 'not-found':\n\t\t\treturn 'not-found';\n\t\tdefault:\n\t\t\treturn 'other';\n\t}\n}\n\nfunction getCollectionFailureStatus(message: string | undefined): number | undefined {\n\tif (message == null) return undefined;\n\n\tconst match = /\\((\\d{3})\\)/.exec(message) ?? /^(?:HTTP\\s+)?(\\d{3})\\b/i.exec(message.trim());\n\treturn match != null ? Number(match[1]) : undefined;\n}\n\nfunction toCollectionFailureWarningKind(failure: CollectionScopeFailure): ProviderWarning['kind'] {\n\tconst mapped = collectionFailureKindToWarningKind(failure.kind);\n\tif (mapped !== 'other' || (failure.kind !== 'provider' && failure.kind !== 'unknown')) return mapped;\n\n\t// provider-apis currently groups several HTTP statuses under `provider` in partial fan-outs. The custom\n\t// fetch adapter retains the status in `message`, so recover the same neutral classification the thrown-error\n\t// path exposes instead of downgrading these structured failures to `other`.\n\tconst status = getCollectionFailureStatus(failure.message);\n\tswitch (status) {\n\t\tcase 401:\n\t\t\treturn 'auth';\n\t\tcase 403:\n\t\t\treturn isRateLimitResponse({ status: status, message: failure.message }) ? 'rate-limit' : 'auth';\n\t\tcase 404:\n\t\tcase 410:\n\t\tcase 422:\n\t\t\treturn 'not-found';\n\t\tcase 429:\n\t\t\treturn 'rate-limit';\n\t\tdefault:\n\t\t\treturn mapped;\n\t}\n}\n\nexport function toCollectionFailureError(failure: CollectionScopeFailure, tokenWithInfo: TokenWithInfo): Error {\n\tconst error = new Error(failure.message ?? 'Provider request failed');\n\tconst kind = toCollectionFailureWarningKind(failure);\n\tconst { accessToken, ...tokenInfo } = tokenWithInfo;\n\tif (kind === 'auth') return new AuthenticationError(tokenInfo, error.message, error);\n\tif (kind === 'rate-limit') return new RequestRateLimitError(error, accessToken, undefined);\n\tif (kind === 'not-found') return new RequestNotFoundError(error);\n\n\tconst status = getCollectionFailureStatus(failure.message);\n\tif (kind === 'other' && status != null && status >= 400 && status < 500) {\n\t\treturn new RequestClientError(error);\n\t}\n\n\treturn error;\n}\n\n/** ` (resource r, project p, repository o/n)` for the scope IDs present; empty when the scope names none. */\nfunction collectionScopeText(scope: CollectionScope | undefined): string {\n\tconst parts: string[] = [];\n\tif (scope?.resourceId != null) {\n\t\tparts.push(`resource ${scope.resourceId}`);\n\t}\n\tif (scope?.projectId != null) {\n\t\tparts.push(`project ${scope.projectId}`);\n\t}\n\tif (scope?.repositoryId != null) {\n\t\tparts.push(`repository ${scope.repositoryId}`);\n\t}\n\n\treturn parts.length ? ` (${parts.join(', ')})` : '';\n}\n\n/** The cause in the consumer's terms, for the prose that goes with the structured {@link ProviderWarningCause}. */\nfunction causeText(cause: ProviderWarningCause): string {\n\tswitch (cause.reason) {\n\t\tcase 'oauth-app-not-allowed':\n\t\t\treturn 'the organization does not allow third-party OAuth apps';\n\t\tcase 'access-denied':\n\t\t\treturn 'the account has no access to it';\n\t\tcase 'conditional-access':\n\t\t\treturn 'a Conditional Access policy blocked the request';\n\t\tdefault:\n\t\t\tcause.reason satisfies never;\n\t\t\treturn 'the provider refused the request';\n\t}\n}\n\nfunction collectionFailureMessage(failure: ProviderScopeFailure): string {\n\tconst text = failure.cause != null ? causeText(failure.cause) : failure.message;\n\tconst detail = text != null ? `: ${text}` : '';\n\treturn `Failed to read ${failure.kind} scope${collectionScopeText(failure.scope)}${detail}`;\n}\n\n/**\n * Forwards the part of a failure's scope below the provider, so a consumer can tell \"one organization refused\n * this token\" from \"the connection's token is dead\" without parsing {@link collectionFailureMessage}.\n *\n * `providerId` is dropped: the warning already names its provider, and a scope naming nothing below it is a\n * failure of the connection itself. That is the distinction `getOrganizationsForUserResult` also draws before\n * counting an auth failure against the connection, though it reads a scope with no keys but `providerId`, so an\n * absent scope does not count there. Forwarding such a scope would make an account-wide failure look confined.\n *\n * Copied field by field, for the reason {@link toProviderWarningOmission} copies its scope.\n */\nfunction toProviderWarningScope(scope: CollectionScope | undefined): ProviderWarningScope | undefined {\n\tif (scope == null) return undefined;\n\n\tconst { resourceId, projectId, repositoryId } = scope;\n\tif (resourceId == null && projectId == null && repositoryId == null) return undefined;\n\n\treturn {\n\t\t...(resourceId != null ? { resourceId: resourceId } : {}),\n\t\t...(projectId != null ? { projectId: projectId } : {}),\n\t\t...(repositoryId != null ? { repositoryId: repositoryId } : {}),\n\t};\n}\n\n/**\n * Whether `metadata` reports authentication failures only for scopes below the provider, with none for the\n * connection itself. A credential revoked since a provider cached its discovery produces exactly this shape,\n * the same one a scope's own refusal does; `IntegrationBase.confirmScopedAuthFailures` tells them apart.\n *\n * Classified exactly as {@link assessCollectionMetadata} classifies the warnings, so it agrees with what a\n * consumer would be shown.\n */\nexport function hasOnlyScopedAuthFailures(metadata: CollectionMetadata | undefined): boolean {\n\tlet scoped = false;\n\tfor (const failure of metadata?.failures ?? []) {\n\t\tif (toCollectionFailureWarningKind(failure) !== 'auth') continue;\n\t\tif (toProviderWarningScope(failure.scope) == null || (failure as ProviderScopeFailure).credentialRefused) {\n\t\t\treturn false;\n\t\t}\n\n\t\tscoped = true;\n\t}\n\treturn scoped;\n}\n\n/** The scoped authentication failures in `metadata` that kept their refusal, with the scope they are forwarded as. */\nfunction* refusedScopes(\n\tmetadata: CollectionMetadata | undefined,\n): Generator<{ failure: ProviderScopeFailure & { refusal: ProviderRefusal }; scope: ProviderWarningScope }> {\n\tfor (const failure of (metadata?.failures ?? []) as ProviderScopeFailure[]) {\n\t\tif (\n\t\t\tfailure.refusal == null ||\n\t\t\tfailure.credentialRefused ||\n\t\t\ttoCollectionFailureWarningKind(failure) !== 'auth'\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst scope = toProviderWarningScope(failure.scope);\n\t\tif (scope == null) continue;\n\n\t\tyield { failure: failure as ProviderScopeFailure & { refusal: ProviderRefusal }, scope: scope };\n\t}\n}\n\n/**\n * Marks each scoped authentication failure in `metadata` whose refusal the provider pins on the credential, so it is\n * published for the connection rather than for its scope. Returns whether any was.\n */\nexport function markCredentialRefusals(\n\tmetadata: CollectionMetadata | undefined,\n\tisCredentialRefusal: (refusal: ProviderRefusal) => boolean,\n): boolean {\n\tlet marked = false;\n\tfor (const { failure } of refusedScopes(metadata)) {\n\t\tif (!isCredentialRefusal(failure.refusal)) continue;\n\n\t\tfailure.credentialRefused = true;\n\t\tmarked = true;\n\t}\n\treturn marked;\n}\n\n/**\n * Names the cause of each scoped authentication failure in `metadata` that kept its refusal. Only for a read whose\n * credential was just confirmed: before that, the refusals this can name look exactly like a dead credential.\n */\nexport function attributeScopedAuthFailures(\n\tmetadata: CollectionMetadata | undefined,\n\tdescribe: (refusal: ProviderRefusal, scope: ProviderWarningScope) => ProviderWarningCause | undefined,\n): void {\n\tfor (const { failure, scope } of refusedScopes(metadata)) {\n\t\tif (failure.cause != null) continue;\n\n\t\tconst cause = describe(failure.refusal, scope);\n\t\tif (cause != null) {\n\t\t\tfailure.cause = cause;\n\t\t}\n\t}\n}\n\n/**\n * Explains one omission in the consumer's terms — what was left out and, where the SDK reports it, how much.\n *\n * An omission is a completeness fact, never a failure: the read succeeded, and the provider (or the SDK's own\n * recovery budget) is what withheld results. That is why these never contribute to `fetchFailed`. Whether a\n * retry would recover anything is a separate question this layer cannot answer — see the `recovery` note on\n * {@link toProviderWarningOmission}.\n */\nfunction collectionOmissionMessage(omission: CollectionOmission): string {\n\tconst scopeText = collectionScopeText(omission.scope);\n\tswitch (omission.kind) {\n\t\tcase 'provider-limit':\n\t\t\t// `totalCount` is the only figure saying how much was withheld; both fields are optional, so degrade\n\t\t\t// through the shapes the SDK can actually emit rather than printing `undefined`.\n\t\t\tif (omission.totalCount != null && omission.limit != null) {\n\t\t\t\treturn `Search${scopeText} matched ${omission.totalCount} results, but the provider exposes at most ${omission.limit}`;\n\t\t\t}\n\t\t\tif (omission.limit != null) {\n\t\t\t\treturn `Search${scopeText} exceeded the provider limit of ${omission.limit} results`;\n\t\t\t}\n\t\t\treturn `Search${scopeText} exceeded the provider's result limit`;\n\t\tcase 'recovery-budget':\n\t\t\treturn `Stopped recovering omitted results${scopeText} after reaching the request budget${\n\t\t\t\tomission.limit != null ? ` of ${omission.limit} requests` : ''\n\t\t\t}`;\n\t\tcase 'pagination-incomplete':\n\t\t\treturn `More results are available${scopeText} than this read returned`;\n\t\tdefault:\n\t\t\t// `CollectionOmissionKind` is a closed union, so this is unreachable today. Kept as a compile-time\n\t\t\t// guard rather than a silent fallback: an SDK bump that adds a kind breaks the build here instead\n\t\t\t// of quietly degrading it to a vague message.\n\t\t\tomission.kind satisfies never;\n\t\t\treturn `Some results were omitted${scopeText}; the read is incomplete`;\n\t}\n}\n\n/**\n * Forwards an SDK omission as the structured signal consumers read instead of parsing {@link\n * collectionOmissionMessage}'s prose.\n *\n * `results.ts` re-spells `CollectionOmissionKind` rather than importing it, so the published warning surface\n * carries no `@gitkraken/provider-apis` types (see the export block in `index.ts`). The return type is what\n * keeps the two unions honest: an SDK bump that adds a member fails to compile here, alongside\n * `collectionOmissionMessage`'s `satisfies never`.\n *\n * `scope` is copied because the SDK's own object is retained and re-merged across drained pages\n * (`providerPaging.ts`), and this one crosses the package boundary.\n *\n * `recovery` is always `'none'`, deliberately, and a scoped `pagination-incomplete` is why it looks wrong: the\n * SDK emits that one shape from situations with opposite remedies and says so itself — \"Either the read\n * deliberately took one page per scope, or the provider advertised another page it gave no way to reach.\" Its\n * `collectAcrossScopes` producers (Azure, Bitbucket, Bitbucket Server) are the first, its `drainAcrossScopes`\n * producers (GitLab, Jira) the second, and those report an omission only when a cursor STALLED — so re-reading\n * that scope stalls at the identical page. Nothing in `CollectionOmission` separates the two, so claiming\n * recoverability would ship the dead-end button `recovery` exists to prevent. Making the recoverable case\n * claimable needs provider-apis to say whether a scope was drained or merely sampled: a fact to forward, not\n * to guess here.\n */\nfunction toProviderWarningOmission(omission: CollectionOmission): ProviderWarningOmission {\n\treturn {\n\t\tkind: omission.kind,\n\t\trecovery: 'none',\n\t\t...(omission.limit != null ? { limit: omission.limit } : {}),\n\t\t// The SDK types this `number | null | undefined`; normalize to one absence for consumers.\n\t\t...(omission.totalCount != null ? { totalCount: omission.totalCount } : {}),\n\t\t...(omission.scope != null ? { scope: { ...omission.scope } } : {}),\n\t};\n}\n\n/**\n * Whether SDK metadata describes a read that may be missing results.\n *\n * A reported omission counts on its own rather than deferring to `completeness`. The SDK does couple the\n * two — every site that emits an omission degrades completeness in the same call — so today the omission\n * clause changes no outcome. It is defensive: the two facts arrive as independent fields, and a read that\n * names what it left out must not be publishable as whole if a future producer sets only one of them.\n *\n * This is the single definition of \"may be missing results\", shared with `getPagedResult`, so one metadata\n * object cannot be truncated at one layer and complete at another.\n */\nexport function isIncompleteCollection(metadata: CollectionMetadata | undefined): boolean {\n\tif (metadata == null) return false;\n\n\treturn metadata.completeness !== 'complete' || (metadata.omissions?.length ?? 0) > 0;\n}\n\n/** Converts internal SDK collection metadata into neutral provider facade signals. */\nexport function assessCollectionMetadata(\n\tproviderId: IntegrationIds,\n\tdomain: string | undefined,\n\tconnectionId: string | undefined,\n\tmetadata: CollectionMetadata | undefined,\n): { warnings: ProviderWarning[]; fetchFailed: boolean; truncated: boolean } {\n\tif (metadata == null) return { warnings: [], fetchFailed: false, truncated: false };\n\n\tconst warnings: ProviderWarning[] = [];\n\tconst failures: ProviderScopeFailure[] = metadata.failures ?? [];\n\tfor (const failure of failures) {\n\t\tconst kind = toCollectionFailureWarningKind(failure);\n\t\tconst scope = failure.credentialRefused ? undefined : toProviderWarningScope(failure.scope);\n\t\tappendDedupedWarning(warnings, {\n\t\t\tproviderId: providerId,\n\t\t\tdomain: domain,\n\t\t\tconnectionId: connectionId,\n\t\t\t// A credential-level refusal names no scope in prose either, so every scope's copy of it is one warning.\n\t\t\tmessage: collectionFailureMessage(failure.credentialRefused ? { ...failure, scope: undefined } : failure),\n\t\t\tkind: kind,\n\t\t\tisAuth: kind === 'auth',\n\t\t\t...(scope != null ? { scope: scope } : {}),\n\t\t\t// Copied for the reason the scope is: the failure object is retained and re-merged across pages.\n\t\t\t...(failure.cause != null ? { cause: { ...failure.cause } } : {}),\n\t\t});\n\t}\n\n\t// Omissions explain WHY a read is incomplete when nothing failed — a provider cap, an exhausted recovery\n\t// budget, an undrained scope. They classify as `other`, never `auth`, and are deliberately excluded from\n\t// `fetchFailed` below: the request itself succeeded. `omission` carries that same fact structurally, so a\n\t// consumer can act on it without parsing the message.\n\tconst omissions = metadata.omissions ?? [];\n\tfor (const omission of omissions) {\n\t\tappendDedupedWarning(warnings, {\n\t\t\tproviderId: providerId,\n\t\t\tdomain: domain,\n\t\t\tconnectionId: connectionId,\n\t\t\tmessage: collectionOmissionMessage(omission),\n\t\t\tkind: 'other',\n\t\t\tisAuth: false,\n\t\t\tomission: toProviderWarningOmission(omission),\n\t\t});\n\t}\n\n\tconst incomplete = isIncompleteCollection(metadata);\n\t// Only fall back to the generic message when nothing more specific was reported; an omission already\n\t// explains the incompleteness in the consumer's terms, so adding this on top would be noise.\n\t//\n\t// This one deliberately carries no `omission`: it fires precisely when the SDK reported incompleteness\n\t// WITHOUT saying what was left out, so there is no structured fact to forward and synthesizing one would\n\t// assert a specificity this layer does not have.\n\tif (incomplete && failures.length === 0 && omissions.length === 0) {\n\t\tappendDedupedWarning(warnings, {\n\t\t\tproviderId: providerId,\n\t\t\tdomain: domain,\n\t\t\tconnectionId: connectionId,\n\t\t\tmessage:\n\t\t\t\tmetadata.completeness === 'partial'\n\t\t\t\t\t? 'Some results were omitted; the read is incomplete'\n\t\t\t\t\t: 'Result completeness could not be confirmed',\n\t\t\tkind: 'other',\n\t\t\tisAuth: false,\n\t\t});\n\t}\n\n\treturn { warnings: warnings, fetchFailed: failures.length > 0, truncated: incomplete };\n}\n\n/**\n * Appends neutral warnings derived from SDK metadata and returns its failure/truncation assessment.\n *\n * `reported` says whether the metadata described this read's incompleteness at all. A caller that would\n * otherwise add its own generic \"this was truncated\" warning uses it to stay quiet — the same rule\n * {@link assessCollectionMetadata} applies to its own generic fallback, one layer up: whatever the metadata\n * reported already names this provider and, unless it was that same fallback, says something a consumer can\n * act on. Restating it in a weaker vocabulary is how one gap becomes two warnings with two different verdicts.\n *\n * `truncated` is the near-synonym that must NOT be used for that question: it comes from\n * {@link isIncompleteCollection}, which does not consider failures, so metadata carrying a typed failure\n * alongside `completeness: 'complete'` reports `truncated: false` while having already appended the warning\n * that explains everything. Gating on it would restate exactly the case this field exists to keep quiet.\n */\nexport function mergeAssessmentInto(\n\twarnings: ProviderWarning[],\n\tproviderId: IntegrationIds,\n\tdomain: string | undefined,\n\tconnectionId: string | undefined,\n\tmetadata: CollectionMetadata | undefined,\n): { fetchFailed: boolean; truncated: boolean; reported: boolean } {\n\tconst assessment = assessCollectionMetadata(providerId, domain, connectionId, metadata);\n\tfor (const warning of assessment.warnings) {\n\t\tappendDedupedWarning(warnings, warning);\n\t}\n\treturn {\n\t\tfetchFailed: assessment.fetchFailed,\n\t\ttruncated: assessment.truncated,\n\t\t// What the assessment PRODUCED, not what `appendDedupedWarning` accepted: a warning dropped as a\n\t\t// duplicate is still one the consumer will see, so it still makes a restatement redundant.\n\t\treported: assessment.warnings.length > 0,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"collectionMetadata.js","names":[],"sources":["../../../../plus/integrations/src/collectionMetadata.ts"],"sourcesContent":["import type {\n\tCollectionMetadata,\n\tCollectionOmission,\n\tCollectionScope,\n\tCollectionScopeFailure,\n} from '@gitkraken/provider-apis';\n// Matched by its `code` discriminator rather than by `instanceof`: the SDK ships one bundle per entry point, so\n// the class reached through the root is not the same object as the one reached through `/providers`.\nimport { isInvalidRequestError, isUnsupportedSortError } from '@gitkraken/provider-apis';\nimport {\n\tAuthenticationError,\n\tRequestClientError,\n\tRequestNotFoundError,\n\tRequestRateLimitError,\n} from '@gitlens/git/errors.js';\nimport type { TokenWithInfo } from './authentication/models.js';\nimport type { IntegrationIds } from './constants.js';\nimport type { ResponseHeaders } from './errors.js';\nimport { getResponseHeader, isRateLimitResponse } from './errors.js';\nimport { getProviderResponseBodyMessage } from './providers/providerErrors.js';\nimport type {\n\tProviderWarning,\n\tProviderWarningCause,\n\tProviderWarningOmission,\n\tProviderWarningScope,\n} from './results.js';\nimport { appendDedupedWarning, providerWarningMessage } from './results.js';\n\n/**\n * Re-throws an error that is a fact about the CALL rather than about one scope of a fan-out.\n *\n * Every provider fan-out catches per-scope rejections and records them as {@link CollectionScopeFailure}s, which is\n * right for auth, rate limits and a missing project: those really did happen to one scope, and the siblings that\n * succeeded must survive. A caller-contract error is the opposite — it is identical for every scope and was decided\n * before any request went out — so degrading it would hand back N indistinguishable failures and an empty `partial`\n * page, describing an invalid call as an incomplete read.\n *\n * Today that means the SDK's `UnsupportedSortError` and `InvalidRequestError` — the two codes it lists in its own\n * `CALLER_CONTRACT_ERROR_CODES`, both documented as \"never degraded into a `CollectionScopeFailure` or an\n * omission\". The second covers arguments rejected before the first request goes out: a project key list longer\n * than one Jira search can carry (or an empty one), a non-integer `pageSize`, an unknown current-user filter, or a\n * Jira Server read with no `baseUrl` to address. Called from every fan-out rather than spelled out in each, so a\n * fan-out added later inherits the rule instead of silently omitting it — which is exactly how Azure's\n * account-wide drain came to degrade it while its three siblings did not.\n */\nexport function throwIfCallerContractError(ex: unknown): void {\n\tif (isUnsupportedSortError(ex) || isInvalidRequestError(ex)) throw ex;\n}\n\n/**\n * Maps a caught GitLens request error to the SDK collection failure vocabulary used inside provider fan-outs.\n */\nexport function toCollectionFailureKind(ex: unknown): CollectionScopeFailure['kind'] {\n\tif (ex instanceof AuthenticationError) return 'authentication';\n\tif (ex instanceof RequestRateLimitError) return 'rate-limit';\n\tif (ex instanceof RequestNotFoundError) return 'not-found';\n\treturn 'provider';\n}\n\n/**\n * What an authentication refusal's response said, kept on the failure so the provider can name its cause once the\n * credential behind it is confirmed (see `IntegrationBase.confirmScopedAuthFailures`). Only these facts are kept,\n * never the response: its headers carry the provider's session cookies.\n */\nexport interface ProviderRefusal {\n\tstatus: number;\n\t/** The provider's own explanation: Azure DevOps' `X-TFS-ServiceError`, or the error body's message. */\n\tdetail?: string;\n\t/** The provider's error type, when the body names one (Azure DevOps `typeKey`). */\n\ttypeKey?: string;\n\t/**\n\t * The OAuth app the refused token belongs to, when the provider says (GitHub's `X-OAuth-Client-Id`). Not a\n\t * secret: it is the app's public client id, which the page where a user asks an organization to approve the app\n\t * is addressed by.\n\t */\n\toauthClientId?: string;\n}\n\n/** A scope failure as recorded here: the SDK's shape, plus what the refusal said and, once it is known, why. */\nexport interface ProviderScopeFailure extends CollectionScopeFailure {\n\trefusal?: ProviderRefusal;\n\tcause?: ProviderWarningCause;\n\t/** The provider pinned the refusal on the credential itself, so it is published for the connection, unscoped. */\n\tcredentialRefused?: true;\n}\n\n/**\n * Reads the refusal off an `AuthenticationError` that carries the provider's response: the SDK adapter's plain\n * `{ status, headers, body }` (`providersApi.ts`), Octokit's `{ status, headers, data }` (the GitHub client's REST\n * reads), or the `Response` of a `ProviderFetchError`, whose body was already read into its message.\n */\nfunction toProviderRefusal(ex: unknown): ProviderRefusal | undefined {\n\tif (!(ex instanceof AuthenticationError)) return undefined;\n\n\tconst response = (ex.original as { response?: unknown } | undefined)?.response as\n\t\t| { status?: unknown; headers?: ResponseHeaders; body?: unknown; data?: unknown }\n\t\t| undefined;\n\tif (typeof response?.status !== 'number') return undefined;\n\n\t// Only a structured body: a string one is a page (a proxy's, a sign-in form), not an explanation.\n\tconst raw = response.body ?? response.data;\n\tconst body = typeof raw === 'object' && raw != null ? raw : undefined;\n\tconst detail =\n\t\tdecodeServiceError(getResponseHeader(response.headers, 'x-tfs-serviceerror')) ??\n\t\tgetProviderResponseBodyMessage(body);\n\tconst typeKey = body != null && 'typeKey' in body ? body.typeKey : undefined;\n\tconst oauthClientId = getResponseHeader(response.headers, 'x-oauth-client-id');\n\n\treturn {\n\t\tstatus: response.status,\n\t\t...(detail ? { detail: detail } : {}),\n\t\t...(typeof typeKey === 'string' ? { typeKey: typeKey } : {}),\n\t\t...(typeof oauthClientId === 'string' && oauthClientId ? { oauthClientId: oauthClientId } : {}),\n\t};\n}\n\n/** Azure DevOps sends `X-TFS-ServiceError` percent-encoded. */\nfunction decodeServiceError(value: unknown): string | undefined {\n\tif (typeof value !== 'string' || !value) return undefined;\n\n\ttry {\n\t\treturn decodeURIComponent(value).trim() || undefined;\n\t} catch {\n\t\treturn value.trim() || undefined;\n\t}\n}\n\n/**\n * Builds a structured SDK scope failure from a caught GitLens request error.\n *\n * An authentication refusal is described in the provider's own words when it gives any, and otherwise by the\n * error the provider's response raised, sanitized like any warning's (a page becomes its status), rather than by\n * `AuthenticationError`'s generic \"credentials are either invalid or expired\": a scope refusing a sound credential\n * is the case this failure exists to tell apart, and that sentence says the opposite.\n */\nexport function toCollectionScopeFailure(scope: CollectionScopeFailure['scope'], ex: unknown): ProviderScopeFailure {\n\tconst refusal = toProviderRefusal(ex);\n\tconst message =\n\t\trefusal != null ? (refusal.detail ?? providerWarningMessage((ex as AuthenticationError).original)) : undefined;\n\treturn {\n\t\tscope: scope,\n\t\tkind: toCollectionFailureKind(ex),\n\t\t...(message ? { message: message } : ex instanceof Error && ex.message ? { message: ex.message } : {}),\n\t\t...(refusal != null ? { refusal: refusal } : {}),\n\t};\n}\n\nfunction collectionFailureKindToWarningKind(kind: CollectionScopeFailure['kind']): ProviderWarning['kind'] {\n\tswitch (kind) {\n\t\tcase 'authentication':\n\t\t\treturn 'auth';\n\t\tcase 'rate-limit':\n\t\t\treturn 'rate-limit';\n\t\tcase 'not-found':\n\t\t\treturn 'not-found';\n\t\tdefault:\n\t\t\treturn 'other';\n\t}\n}\n\nfunction getCollectionFailureStatus(message: string | undefined): number | undefined {\n\tif (message == null) return undefined;\n\n\tconst match = /\\((\\d{3})\\)/.exec(message) ?? /^(?:HTTP\\s+)?(\\d{3})\\b/i.exec(message.trim());\n\treturn match != null ? Number(match[1]) : undefined;\n}\n\nfunction toCollectionFailureWarningKind(failure: CollectionScopeFailure): ProviderWarning['kind'] {\n\tconst mapped = collectionFailureKindToWarningKind(failure.kind);\n\tif (mapped !== 'other' || (failure.kind !== 'provider' && failure.kind !== 'unknown')) return mapped;\n\n\t// provider-apis currently groups several HTTP statuses under `provider` in partial fan-outs. The custom\n\t// fetch adapter retains the status in `message`, so recover the same neutral classification the thrown-error\n\t// path exposes instead of downgrading these structured failures to `other`.\n\tconst status = getCollectionFailureStatus(failure.message);\n\tswitch (status) {\n\t\tcase 401:\n\t\t\treturn 'auth';\n\t\tcase 403:\n\t\t\treturn isRateLimitResponse({ status: status, message: failure.message }) ? 'rate-limit' : 'auth';\n\t\tcase 404:\n\t\tcase 410:\n\t\tcase 422:\n\t\t\treturn 'not-found';\n\t\tcase 429:\n\t\t\treturn 'rate-limit';\n\t\tdefault:\n\t\t\treturn mapped;\n\t}\n}\n\nexport function toCollectionFailureError(failure: CollectionScopeFailure, tokenWithInfo: TokenWithInfo): Error {\n\tconst error = new Error(failure.message ?? 'Provider request failed');\n\tconst kind = toCollectionFailureWarningKind(failure);\n\tconst { accessToken, ...tokenInfo } = tokenWithInfo;\n\tif (kind === 'auth') return new AuthenticationError(tokenInfo, error.message, error);\n\tif (kind === 'rate-limit') return new RequestRateLimitError(error, accessToken, undefined);\n\tif (kind === 'not-found') return new RequestNotFoundError(error);\n\n\tconst status = getCollectionFailureStatus(failure.message);\n\tif (kind === 'other' && status != null && status >= 400 && status < 500) {\n\t\treturn new RequestClientError(error);\n\t}\n\n\treturn error;\n}\n\n/** ` (resource r, project p, repository o/n)` for the scope IDs present; empty when the scope names none. */\nfunction collectionScopeText(scope: CollectionScope | undefined): string {\n\tconst parts: string[] = [];\n\tif (scope?.resourceId != null) {\n\t\tparts.push(`resource ${scope.resourceId}`);\n\t}\n\tif (scope?.projectId != null) {\n\t\tparts.push(`project ${scope.projectId}`);\n\t}\n\tif (scope?.repositoryId != null) {\n\t\tparts.push(`repository ${scope.repositoryId}`);\n\t}\n\n\treturn parts.length ? ` (${parts.join(', ')})` : '';\n}\n\n/** The cause in the consumer's terms, for the prose that goes with the structured {@link ProviderWarningCause}. */\nfunction causeText(cause: ProviderWarningCause): string {\n\tswitch (cause.reason) {\n\t\tcase 'oauth-app-not-allowed':\n\t\t\treturn 'the organization does not allow third-party OAuth apps';\n\t\tcase 'access-denied':\n\t\t\treturn 'the account has no access to it';\n\t\tcase 'conditional-access':\n\t\t\treturn 'a Conditional Access policy blocked the request';\n\t\tdefault:\n\t\t\tcause.reason satisfies never;\n\t\t\treturn 'the provider refused the request';\n\t}\n}\n\nfunction collectionFailureMessage(failure: ProviderScopeFailure): string {\n\tconst text = failure.cause != null ? causeText(failure.cause) : failure.message;\n\tconst detail = text != null ? `: ${text}` : '';\n\treturn `Failed to read ${failure.kind} scope${collectionScopeText(failure.scope)}${detail}`;\n}\n\n/**\n * Forwards the part of a failure's scope below the provider, so a consumer can tell \"one organization refused\n * this token\" from \"the connection's token is dead\" without parsing {@link collectionFailureMessage}.\n *\n * `providerId` is dropped: the warning already names its provider, and a scope naming nothing below it is a\n * failure of the connection itself. That is the distinction `getOrganizationsForUserResult` also draws before\n * counting an auth failure against the connection, though it reads a scope with no keys but `providerId`, so an\n * absent scope does not count there. Forwarding such a scope would make an account-wide failure look confined.\n *\n * Copied field by field, for the reason {@link toProviderWarningOmission} copies its scope.\n */\nfunction toProviderWarningScope(scope: CollectionScope | undefined): ProviderWarningScope | undefined {\n\tif (scope == null) return undefined;\n\n\tconst { resourceId, projectId, repositoryId } = scope;\n\tif (resourceId == null && projectId == null && repositoryId == null) return undefined;\n\n\treturn {\n\t\t...(resourceId != null ? { resourceId: resourceId } : {}),\n\t\t...(projectId != null ? { projectId: projectId } : {}),\n\t\t...(repositoryId != null ? { repositoryId: repositoryId } : {}),\n\t};\n}\n\n/**\n * Whether `metadata` reports authentication failures only for scopes below the provider, with none for the\n * connection itself. A credential revoked since a provider cached its discovery produces exactly this shape,\n * the same one a scope's own refusal does; `IntegrationBase.confirmScopedAuthFailures` tells them apart.\n *\n * Classified exactly as {@link assessCollectionMetadata} classifies the warnings, so it agrees with what a\n * consumer would be shown.\n */\nexport function hasOnlyScopedAuthFailures(metadata: CollectionMetadata | undefined): boolean {\n\tlet scoped = false;\n\tfor (const failure of metadata?.failures ?? []) {\n\t\tif (toCollectionFailureWarningKind(failure) !== 'auth') continue;\n\t\tif (toProviderWarningScope(failure.scope) == null || (failure as ProviderScopeFailure).credentialRefused) {\n\t\t\treturn false;\n\t\t}\n\n\t\tscoped = true;\n\t}\n\treturn scoped;\n}\n\n/** The scoped authentication failures in `metadata` that kept their refusal, with the scope they are forwarded as. */\nfunction* refusedScopes(\n\tmetadata: CollectionMetadata | undefined,\n): Generator<{ failure: ProviderScopeFailure & { refusal: ProviderRefusal }; scope: ProviderWarningScope }> {\n\tfor (const failure of (metadata?.failures ?? []) as ProviderScopeFailure[]) {\n\t\tif (\n\t\t\tfailure.refusal == null ||\n\t\t\tfailure.credentialRefused ||\n\t\t\ttoCollectionFailureWarningKind(failure) !== 'auth'\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst scope = toProviderWarningScope(failure.scope);\n\t\tif (scope == null) continue;\n\n\t\tyield { failure: failure as ProviderScopeFailure & { refusal: ProviderRefusal }, scope: scope };\n\t}\n}\n\n/**\n * Marks each scoped authentication failure in `metadata` whose refusal the provider pins on the credential, so it is\n * published for the connection rather than for its scope. Returns whether any was.\n */\nexport function markCredentialRefusals(\n\tmetadata: CollectionMetadata | undefined,\n\tisCredentialRefusal: (refusal: ProviderRefusal) => boolean,\n): boolean {\n\tlet marked = false;\n\tfor (const { failure } of refusedScopes(metadata)) {\n\t\tif (!isCredentialRefusal(failure.refusal)) continue;\n\n\t\tfailure.credentialRefused = true;\n\t\tmarked = true;\n\t}\n\treturn marked;\n}\n\n/**\n * Names the cause of each scoped authentication failure in `metadata` that kept its refusal. Only for a read whose\n * credential was just confirmed: before that, the refusals this can name look exactly like a dead credential.\n */\nexport function attributeScopedAuthFailures(\n\tmetadata: CollectionMetadata | undefined,\n\tdescribe: (refusal: ProviderRefusal, scope: ProviderWarningScope) => ProviderWarningCause | undefined,\n): void {\n\tfor (const { failure, scope } of refusedScopes(metadata)) {\n\t\tif (failure.cause != null) continue;\n\n\t\tconst cause = describe(failure.refusal, scope);\n\t\tif (cause != null) {\n\t\t\tfailure.cause = cause;\n\t\t}\n\t}\n}\n\n/**\n * Explains one omission in the consumer's terms — what was left out and, where the SDK reports it, how much.\n *\n * An omission is a completeness fact, never a failure: the read succeeded, and the provider (or the SDK's own\n * recovery budget) is what withheld results. That is why these never contribute to `fetchFailed`. Whether a\n * retry would recover anything is a separate question this layer cannot answer — see the `recovery` note on\n * {@link toProviderWarningOmission}.\n */\nfunction collectionOmissionMessage(omission: CollectionOmission): string {\n\tconst scopeText = collectionScopeText(omission.scope);\n\tswitch (omission.kind) {\n\t\tcase 'provider-limit':\n\t\t\t// `totalCount` is the only figure saying how much was withheld; both fields are optional, so degrade\n\t\t\t// through the shapes the SDK can actually emit rather than printing `undefined`.\n\t\t\tif (omission.totalCount != null && omission.limit != null) {\n\t\t\t\treturn `Search${scopeText} matched ${omission.totalCount} results, but the provider exposes at most ${omission.limit}`;\n\t\t\t}\n\t\t\tif (omission.limit != null) {\n\t\t\t\treturn `Search${scopeText} exceeded the provider limit of ${omission.limit} results`;\n\t\t\t}\n\t\t\treturn `Search${scopeText} exceeded the provider's result limit`;\n\t\tcase 'recovery-budget':\n\t\t\treturn `Stopped recovering omitted results${scopeText} after reaching the request budget${\n\t\t\t\tomission.limit != null ? ` of ${omission.limit} requests` : ''\n\t\t\t}`;\n\t\tcase 'pagination-incomplete':\n\t\t\treturn `More results are available${scopeText} than this read returned`;\n\t\tdefault:\n\t\t\t// `CollectionOmissionKind` is a closed union, so this is unreachable today. Kept as a compile-time\n\t\t\t// guard rather than a silent fallback: an SDK bump that adds a kind breaks the build here instead\n\t\t\t// of quietly degrading it to a vague message.\n\t\t\tomission.kind satisfies never;\n\t\t\treturn `Some results were omitted${scopeText}; the read is incomplete`;\n\t}\n}\n\n/**\n * Forwards an SDK omission as the structured signal consumers read instead of parsing {@link\n * collectionOmissionMessage}'s prose.\n *\n * `results.ts` re-spells `CollectionOmissionKind` rather than importing it, so the published warning surface\n * carries no `@gitkraken/provider-apis` types (see the export block in `index.ts`). The return type is what\n * keeps the two unions honest: an SDK bump that adds a member fails to compile here, alongside\n * `collectionOmissionMessage`'s `satisfies never`.\n *\n * `scope` is copied because the SDK's own object is retained and re-merged across drained pages\n * (`providerPaging.ts`), and this one crosses the package boundary.\n *\n * `recovery` is always `'none'`, deliberately, and a scoped `pagination-incomplete` is why it looks wrong: the\n * SDK emits that one shape from situations with opposite remedies and says so itself — \"Either the read\n * deliberately took one page per scope, or the provider advertised another page it gave no way to reach.\" Its\n * `collectAcrossScopes` producers (Azure, Bitbucket, Bitbucket Server) are the first, its `drainAcrossScopes`\n * producers (GitLab, Jira) the second, and those report an omission only when a cursor STALLED — so re-reading\n * that scope stalls at the identical page. Nothing in `CollectionOmission` separates the two, so claiming\n * recoverability would ship the dead-end button `recovery` exists to prevent. Making the recoverable case\n * claimable needs provider-apis to say whether a scope was drained or merely sampled: a fact to forward, not\n * to guess here.\n */\nfunction toProviderWarningOmission(omission: CollectionOmission): ProviderWarningOmission {\n\treturn {\n\t\tkind: omission.kind,\n\t\trecovery: 'none',\n\t\t...(omission.limit != null ? { limit: omission.limit } : {}),\n\t\t// The SDK types this `number | null | undefined`; normalize to one absence for consumers.\n\t\t...(omission.totalCount != null ? { totalCount: omission.totalCount } : {}),\n\t\t...(omission.scope != null ? { scope: { ...omission.scope } } : {}),\n\t};\n}\n\n/**\n * Whether SDK metadata describes a read that may be missing results.\n *\n * A reported omission counts on its own rather than deferring to `completeness`. The SDK does couple the\n * two — every site that emits an omission degrades completeness in the same call — so today the omission\n * clause changes no outcome. It is defensive: the two facts arrive as independent fields, and a read that\n * names what it left out must not be publishable as whole if a future producer sets only one of them.\n *\n * This is the single definition of \"may be missing results\", shared with `getPagedResult`, so one metadata\n * object cannot be truncated at one layer and complete at another.\n */\nexport function isIncompleteCollection(metadata: CollectionMetadata | undefined): boolean {\n\tif (metadata == null) return false;\n\n\treturn metadata.completeness !== 'complete' || (metadata.omissions?.length ?? 0) > 0;\n}\n\n/** Converts internal SDK collection metadata into neutral provider facade signals. */\nexport function assessCollectionMetadata(\n\tproviderId: IntegrationIds,\n\tdomain: string | undefined,\n\tconnectionId: string | undefined,\n\tmetadata: CollectionMetadata | undefined,\n): { warnings: ProviderWarning[]; fetchFailed: boolean; truncated: boolean } {\n\tif (metadata == null) return { warnings: [], fetchFailed: false, truncated: false };\n\n\tconst warnings: ProviderWarning[] = [];\n\tconst failures: ProviderScopeFailure[] = metadata.failures ?? [];\n\tfor (const failure of failures) {\n\t\tconst kind = toCollectionFailureWarningKind(failure);\n\t\tconst scope = failure.credentialRefused ? undefined : toProviderWarningScope(failure.scope);\n\t\tappendDedupedWarning(warnings, {\n\t\t\tproviderId: providerId,\n\t\t\tdomain: domain,\n\t\t\tconnectionId: connectionId,\n\t\t\t// A credential-level refusal names no scope in prose either, so every scope's copy of it is one warning.\n\t\t\tmessage: collectionFailureMessage(failure.credentialRefused ? { ...failure, scope: undefined } : failure),\n\t\t\tkind: kind,\n\t\t\tisAuth: kind === 'auth',\n\t\t\t...(scope != null ? { scope: scope } : {}),\n\t\t\t// Copied for the reason the scope is: the failure object is retained and re-merged across pages.\n\t\t\t...(failure.cause != null ? { cause: { ...failure.cause } } : {}),\n\t\t});\n\t}\n\n\t// Omissions explain WHY a read is incomplete when nothing failed — a provider cap, an exhausted recovery\n\t// budget, an undrained scope. They classify as `other`, never `auth`, and are deliberately excluded from\n\t// `fetchFailed` below: the request itself succeeded. `omission` carries that same fact structurally, so a\n\t// consumer can act on it without parsing the message.\n\tconst omissions = metadata.omissions ?? [];\n\tfor (const omission of omissions) {\n\t\tappendDedupedWarning(warnings, {\n\t\t\tproviderId: providerId,\n\t\t\tdomain: domain,\n\t\t\tconnectionId: connectionId,\n\t\t\tmessage: collectionOmissionMessage(omission),\n\t\t\tkind: 'other',\n\t\t\tisAuth: false,\n\t\t\tomission: toProviderWarningOmission(omission),\n\t\t});\n\t}\n\n\tconst incomplete = isIncompleteCollection(metadata);\n\t// Only fall back to the generic message when nothing more specific was reported; an omission already\n\t// explains the incompleteness in the consumer's terms, so adding this on top would be noise.\n\t//\n\t// This one deliberately carries no `omission`: it fires precisely when the SDK reported incompleteness\n\t// WITHOUT saying what was left out, so there is no structured fact to forward and synthesizing one would\n\t// assert a specificity this layer does not have.\n\tif (incomplete && failures.length === 0 && omissions.length === 0) {\n\t\tappendDedupedWarning(warnings, {\n\t\t\tproviderId: providerId,\n\t\t\tdomain: domain,\n\t\t\tconnectionId: connectionId,\n\t\t\tmessage:\n\t\t\t\tmetadata.completeness === 'partial'\n\t\t\t\t\t? 'Some results were omitted; the read is incomplete'\n\t\t\t\t\t: 'Result completeness could not be confirmed',\n\t\t\tkind: 'other',\n\t\t\tisAuth: false,\n\t\t});\n\t}\n\n\treturn { warnings: warnings, fetchFailed: failures.length > 0, truncated: incomplete };\n}\n\n/**\n * Appends neutral warnings derived from SDK metadata and returns its failure/truncation assessment.\n *\n * `reported` says whether the metadata described this read's incompleteness at all. A caller that would\n * otherwise add its own generic \"this was truncated\" warning uses it to stay quiet — the same rule\n * {@link assessCollectionMetadata} applies to its own generic fallback, one layer up: whatever the metadata\n * reported already names this provider and, unless it was that same fallback, says something a consumer can\n * act on. Restating it in a weaker vocabulary is how one gap becomes two warnings with two different verdicts.\n *\n * `truncated` is the near-synonym that must NOT be used for that question: it comes from\n * {@link isIncompleteCollection}, which does not consider failures, so metadata carrying a typed failure\n * alongside `completeness: 'complete'` reports `truncated: false` while having already appended the warning\n * that explains everything. Gating on it would restate exactly the case this field exists to keep quiet.\n */\nexport function mergeAssessmentInto(\n\twarnings: ProviderWarning[],\n\tproviderId: IntegrationIds,\n\tdomain: string | undefined,\n\tconnectionId: string | undefined,\n\tmetadata: CollectionMetadata | undefined,\n): { fetchFailed: boolean; truncated: boolean; reported: boolean } {\n\tconst assessment = assessCollectionMetadata(providerId, domain, connectionId, metadata);\n\tfor (const warning of assessment.warnings) {\n\t\tappendDedupedWarning(warnings, warning);\n\t}\n\treturn {\n\t\tfetchFailed: assessment.fetchFailed,\n\t\ttruncated: assessment.truncated,\n\t\t// What the assessment PRODUCED, not what `appendDedupedWarning` accepted: a warning dropped as a\n\t\t// duplicate is still one the consumer will see, so it still makes a restatement redundant.\n\t\treported: assessment.warnings.length > 0,\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ import { PullRequestUrlIdentity } from "../../../git/utils/pullRequest.utils.js"
|
|
|
10
10
|
import { ProviderAuthenticationSession } from "../authentication/models.js";
|
|
11
11
|
import { IntegrationIds } from "../constants.js";
|
|
12
12
|
import { ProviderOrganization } from "../results.js";
|
|
13
|
+
import { ProviderScopeFailure } from "../collectionMetadata.js";
|
|
13
14
|
import { ProviderPullRequestCount, ProviderPullRequestSearchPage } from "./pullRequestReads.js";
|
|
14
15
|
import { MyIssuesForReposOptions, ProviderIssueSearchPage, ProviderSearchCount } from "./issueReads.js";
|
|
15
16
|
import { BatchSlot, IntegrationBase, IntegrationResult, IntegrationType } from "./integration.js";
|
|
@@ -80,6 +81,18 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
80
81
|
project?: string;
|
|
81
82
|
connectionId?: string;
|
|
82
83
|
}): Promise<ProviderRepository | undefined>;
|
|
84
|
+
/**
|
|
85
|
+
* Settles what one repository's refusal of the credential means, as a batch read settles a refused target (see
|
|
86
|
+
* `IntegrationBase.settleBatchRefusals`): the scope failure it is recorded as, against that repository (and, on
|
|
87
|
+
* Azure DevOps, its project), with its cause named once the credential checks out. A refused credential throws
|
|
88
|
+
* its own error, which the caller reports for the connection instead of the repository's refusal.
|
|
89
|
+
*/
|
|
90
|
+
settleRepositoryRefusal(repo: {
|
|
91
|
+
owner: string;
|
|
92
|
+
name: string;
|
|
93
|
+
project?: string;
|
|
94
|
+
connectionId?: string;
|
|
95
|
+
}, refusal: unknown): Promise<ProviderScopeFailure | undefined>;
|
|
83
96
|
/** Stack membership for every stacked pull request in the repository, keyed by pull request number.
|
|
84
97
|
* Only hosts with a stacks concept implement this (currently GitHub). */
|
|
85
98
|
getStacksByPullRequestNumber?(owner: string, repo: string, cancellation?: AbortSignal): Promise<Map<number, PullRequestStackInfo> | undefined>;
|
|
@@ -137,6 +137,25 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
137
137
|
}
|
|
138
138
|
})() }), { expiryOverride: options?.expiryOverride });
|
|
139
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Settles what one repository's refusal of the credential means, as a batch read settles a refused target (see
|
|
142
|
+
* `IntegrationBase.settleBatchRefusals`): the scope failure it is recorded as, against that repository (and, on
|
|
143
|
+
* Azure DevOps, its project), with its cause named once the credential checks out. A refused credential throws
|
|
144
|
+
* its own error, which the caller reports for the connection instead of the repository's refusal.
|
|
145
|
+
*/
|
|
146
|
+
async settleRepositoryRefusal(repo, refusal) {
|
|
147
|
+
const session = await this.resolveReadSession(repo.connectionId, void 0);
|
|
148
|
+
if (session == null) return void 0;
|
|
149
|
+
const [slot] = await this.settleBatchRefusals(session, [{
|
|
150
|
+
owner: repo.owner,
|
|
151
|
+
repo: repo.name,
|
|
152
|
+
project: repo.project
|
|
153
|
+
}], [{
|
|
154
|
+
status: "rejected",
|
|
155
|
+
reason: refusal
|
|
156
|
+
}]);
|
|
157
|
+
return slot?.status === "rejected" ? slot.failure : void 0;
|
|
158
|
+
}
|
|
140
159
|
async getRepositoryMetadata(repo, options) {
|
|
141
160
|
const scope = getScopedLogger();
|
|
142
161
|
if (!(this.maybeConnected ?? await this.isConnected())) return void 0;
|