@gitkraken/core-gitlens 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/dist/git/cache.d.ts +18 -5
- package/dist/git/cache.js +26 -8
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +5 -1
- package/dist/git/context.js.map +1 -1
- package/dist/git/errors.d.ts +28 -1
- package/dist/git/errors.js +45 -1
- package/dist/git/errors.js.map +1 -1
- package/dist/git/providers/branches.d.ts +5 -1
- package/dist/git/providers/commits.d.ts +24 -1
- package/dist/git/providers/config.d.ts +7 -1
- package/dist/git/providers/operations.d.ts +6 -0
- package/dist/git/providers/provider.d.ts +17 -0
- package/dist/git/providers/refs.d.ts +38 -3
- package/dist/git/providers/revision.d.ts +5 -1
- package/dist/git/providers/staging.d.ts +12 -0
- package/dist/git/providers/worktrees.d.ts +23 -3
- package/dist/git/run.types.d.ts +6 -0
- package/dist/git-cli/cliGitProvider.d.ts +17 -1
- package/dist/git-cli/cliGitProvider.js +37 -1
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/git.d.ts +12 -2
- package/dist/git-cli/exec/git.js +48 -17
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/exec/gitQueue.d.ts +4 -1
- package/dist/git-cli/exec/gitQueue.js +1 -1
- package/dist/git-cli/exec/gitQueue.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts +10 -1
- package/dist/git-cli/providers/branches.js +15 -8
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +23 -1
- package/dist/git-cli/providers/commits.js +57 -8
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.js +4 -3
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +1 -0
- package/dist/git-cli/providers/operations.js +39 -3
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/patch.js +20 -41
- package/dist/git-cli/providers/patch.js.map +1 -1
- package/dist/git-cli/providers/pausedOperations.js +2 -2
- package/dist/git-cli/providers/pausedOperations.js.map +1 -1
- package/dist/git-cli/providers/refs.d.ts +15 -3
- package/dist/git-cli/providers/refs.js +115 -10
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/revision.d.ts +3 -1
- package/dist/git-cli/providers/revision.js +9 -5
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/staging.d.ts +8 -0
- package/dist/git-cli/providers/staging.js +59 -7
- package/dist/git-cli/providers/staging.js.map +1 -1
- package/dist/git-cli/providers/worktrees.d.ts +31 -2
- package/dist/git-cli/providers/worktrees.js +75 -7
- package/dist/git-cli/providers/worktrees.js.map +1 -1
- package/dist/ipc/discovery.js +1 -1
- package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
- package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
- package/dist/plus/git-github/api/github.d.ts +64 -3
- package/dist/plus/git-github/api/github.js +237 -24
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/providers/github/branches.d.ts +3 -1
- package/dist/plus/git-github/providers/github/branches.js +2 -1
- package/dist/plus/git-github/providers/github/branches.js.map +1 -1
- package/dist/plus/git-github/providers/github/refs.d.ts +10 -3
- package/dist/plus/git-github/providers/github/refs.js +4 -4
- package/dist/plus/git-github/providers/github/refs.js.map +1 -1
- package/dist/plus/git-github/providers/github/revision.d.ts +3 -1
- package/dist/plus/git-github/providers/github/revision.js +1 -1
- package/dist/plus/git-github/providers/github/revision.js.map +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +48 -3
- package/dist/plus/integrations/collectionMetadata.js +138 -8
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/errors.d.ts +3 -1
- package/dist/plus/integrations/errors.js +7 -3
- package/dist/plus/integrations/errors.js.map +1 -1
- package/dist/plus/integrations/index.d.ts +6 -3
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +36 -10
- package/dist/plus/integrations/integrationService.js +16 -3
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +107 -37
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +129 -14
- package/dist/plus/integrations/models/gitHostIntegration.js +142 -18
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +117 -11
- package/dist/plus/integrations/models/integration.js +175 -13
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.d.ts +18 -5
- package/dist/plus/integrations/models/issuesIntegration.js +42 -10
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.d.ts +1 -1
- package/dist/plus/integrations/providers/azure/azure.js +14 -18
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/models.d.ts +29 -0
- package/dist/plus/integrations/providers/azure/models.js +112 -1
- package/dist/plus/integrations/providers/azure/models.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.d.ts +73 -3
- package/dist/plus/integrations/providers/azureDevOps.js +117 -3
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.js +2 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts +61 -0
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js +165 -23
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/models.d.ts +6 -1
- package/dist/plus/integrations/providers/bitbucket/models.js +4 -3
- package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js +2 -2
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +48 -2
- package/dist/plus/integrations/providers/bitbucket-server.js +51 -1
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.d.ts +45 -2
- package/dist/plus/integrations/providers/bitbucket.js +41 -2
- package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +49 -5
- package/dist/plus/integrations/providers/github.js +102 -7
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/gitlab.d.ts +35 -0
- package/dist/plus/integrations/providers/gitlab/gitlab.js +132 -15
- package/dist/plus/integrations/providers/gitlab/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/models.d.ts +1 -0
- package/dist/plus/integrations/providers/gitlab/models.js +1 -1
- package/dist/plus/integrations/providers/gitlab/models.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +49 -2
- package/dist/plus/integrations/providers/gitlab.js +80 -4
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/jira-server.d.ts +3 -3
- package/dist/plus/integrations/providers/jira-server.js +5 -8
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +9 -0
- package/dist/plus/integrations/providers/jira.js +13 -1
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/linear.js +1 -1
- package/dist/plus/integrations/providers/models.d.ts +13 -2
- package/dist/plus/integrations/providers/models.js +11 -1
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providerErrors.d.ts +9 -1
- package/dist/plus/integrations/providers/providerErrors.js +10 -1
- package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +60 -1
- package/dist/plus/integrations/providers/providersApi.js +137 -2
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.d.ts +42 -0
- package/dist/plus/integrations/providers/utils/providerPaging.js +58 -1
- package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
- package/dist/plus/integrations/providers/utils.d.ts +1 -1
- package/dist/plus/integrations/reads/broaden.js +1 -1
- package/dist/plus/integrations/reads/context.d.ts +1 -1
- package/dist/plus/integrations/reads/counts.js +1 -1
- package/dist/plus/integrations/reads/currentAccount.d.ts +35 -0
- package/dist/plus/integrations/reads/currentAccount.js +46 -0
- package/dist/plus/integrations/reads/currentAccount.js.map +1 -0
- package/dist/plus/integrations/reads/drains.d.ts +5 -2
- package/dist/plus/integrations/reads/drains.js +8 -4
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.js +1 -1
- package/dist/plus/integrations/reads/hierarchy.utils.js +1 -1
- package/dist/plus/integrations/reads/issueBatch.d.ts +72 -12
- package/dist/plus/integrations/reads/issueBatch.js +193 -48
- package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +1 -1
- package/dist/plus/integrations/reads/issues.js +1 -1
- package/dist/plus/integrations/reads/pullRequestBatch.d.ts +57 -0
- package/dist/plus/integrations/reads/pullRequestBatch.js +80 -0
- package/dist/plus/integrations/reads/pullRequestBatch.js.map +1 -0
- package/dist/plus/integrations/reads/pullRequestBranches.d.ts +58 -0
- package/dist/plus/integrations/reads/pullRequestBranches.js +111 -0
- package/dist/plus/integrations/reads/pullRequestBranches.js.map +1 -0
- package/dist/plus/integrations/reads/pullRequests.js +3 -3
- package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/resolveRepository.js +1 -1
- package/dist/plus/integrations/reads/sweeps.js +4 -4
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +87 -6
- package/dist/plus/integrations/results.js +9 -2
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/utils/env/node/exec.js +3 -3
- package/dist/utils/env/node/exec.js.map +1 -1
- package/docs/integrations.md +175 -35
- package/docs/kepler-git-write-api-parity.md +239 -0
- package/docs/kepler-read-api-parity.md +75 -28
- package/package.json +1 -1
- package/dist/plus/integrations/reads/trackerIssue.d.ts +0 -33
- package/dist/plus/integrations/reads/trackerIssue.js +0 -60
- package/dist/plus/integrations/reads/trackerIssue.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlab.js","names":["Logger"],"sources":["../../../../../../plus/integrations/src/providers/gitlab/gitlab.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Account } from '@gitlens/git/models/author.js';\nimport type { DefaultBranch } from '@gitlens/git/models/defaultBranch.js';\nimport type { IssueOrPullRequest } from '@gitlens/git/models/issueOrPullRequest.js';\nimport { PullRequest } from '@gitlens/git/models/pullRequest.js';\nimport type { PullRequestState } from '@gitlens/git/models/pullRequest.js';\nimport type { Provider } from '@gitlens/git/models/remoteProvider.js';\nimport type { RepositoryMetadata } from '@gitlens/git/models/repositoryMetadata.js';\nimport { CancellationError } from '@gitlens/utils/cancellation.js';\nimport { trace } from '@gitlens/utils/decorators/log.js';\nimport type { Disposable } from '@gitlens/utils/disposable.js';\nimport { Logger } from '@gitlens/utils/logger.js';\nimport type { ScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { maybeStopWatch } from '@gitlens/utils/stopwatch.js';\nimport { equalsIgnoreCase } from '@gitlens/utils/string.js';\nimport { joinUriPath, parseUri } from '@gitlens/utils/uri.js';\nimport type { TokenWithInfo } from '../../authentication/models.js';\nimport type { IntegrationServiceContext } from '../../context.js';\nimport {\n\tAuthenticationError,\n\tAuthenticationErrorReason,\n\tisRateLimitResponse,\n\tProviderFetchError,\n\tRequestClientError,\n\tRequestNotFoundError,\n\ttoRateLimitError,\n} from '../../errors.js';\nimport type { ProviderApiConfig } from '../apiConfig.js';\nimport { baseProviderApiConfig } from '../apiConfig.js';\nimport { selectGitLabUserForCommit } from './gitlab.utils.js';\nimport type {\n\tGitLabCommit,\n\tGitLabIssue,\n\tGitLabMergeRequest,\n\tGitLabMergeRequestFull,\n\tGitLabMergeRequestREST,\n\tGitLabMergeRequestState,\n\tGitLabProjectREST,\n\tGitLabSshKey,\n\tGitLabUser,\n} from './models.js';\nimport {\n\tfromGitLabMergeRequest,\n\tfromGitLabMergeRequestREST,\n\tfromGitLabMergeRequestState,\n\ttoGitLabMergeRequestState,\n} from './models.js';\n\n// drop it as soon as we switch to @gitkraken/providers-api\nconst gitlabUserIdPrefix = 'gid://gitlab/User/';\nconst gitlabMergeRequestIdPrefix = 'gid://gitlab/MergeRequest/';\n\nfunction buildGitLabUserId(id: string | number | undefined): string | undefined {\n\treturn typeof id === 'string' && id?.startsWith(gitlabUserIdPrefix)\n\t\t? id.substring(gitlabUserIdPrefix.length)\n\t\t: String(id);\n}\n\nexport class GitLabApi implements Disposable {\n\tprivate readonly _disposable: Disposable | undefined;\n\tprivate _projectIds = new Map<string, Promise<string | undefined>>();\n\n\tconstructor(private readonly config: ProviderApiConfig) {\n\t\tthis._disposable = config.onConfigChanged?.(() => this.resetCaches());\n\t}\n\n\tdispose(): void {\n\t\tthis._disposable?.dispose();\n\t}\n\n\tprivate resetCaches(): void {\n\t\tthis._projectIds.clear();\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, rev) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\trev: rev,\n\t\t}),\n\t})\n\tasync getAccountForCommit(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<Account | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);\n\t\tif (!projectId) return undefined;\n\n\t\ttry {\n\t\t\tconst commit = await this.request<GitLabCommit>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/projects/${projectId}/repository/commits/${rev}?stats=false`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t// ...options,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tlet users = await this.findUser(provider, token, commit.author_name, options, cancellation);\n\t\t\tlet user = selectGitLabUserForCommit(users, commit.author_name, commit.author_email);\n\n\t\t\t// If the name search was ambiguous (multiple users share the name), try an email-scoped search to\n\t\t\t// disambiguate before giving up — otherwise we'd show a stranger's avatar (see #2205)\n\t\t\tif (user == null && commit.author_email) {\n\t\t\t\tconst exactNameMatches = users.filter(u => equalsIgnoreCase(u.name, commit.author_name)).length;\n\t\t\t\tif (exactNameMatches > 1) {\n\t\t\t\t\tusers = await this.findUser(provider, token, commit.author_email, options, cancellation);\n\t\t\t\t\tuser = selectGitLabUserForCommit(users, commit.author_name, commit.author_email);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (user == null) return undefined;\n\n\t\t\t// If the avatarUrl is a relative URL, make it absolute using the webUrl (assuming the webUrl is the root URL with the username tacked on)\n\t\t\tif (user.avatarUrl && !/^([a-zA-Z][\\w+.-]+):/.test(user.avatarUrl)) {\n\t\t\t\tuser.avatarUrl = joinUriPath(parseUri(user.webUrl), '..', user.avatarUrl).toString();\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\tid: String(user.id),\n\t\t\t\tname: user.name || undefined,\n\t\t\t\temail: commit.author_email || undefined,\n\t\t\t\tavatarUrl: user.avatarUrl || undefined,\n\t\t\t\tusername: user.username || undefined,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, _owner, _repo, email) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\temail: email,\n\t\t}),\n\t})\n\tasync getAccountForEmail(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\t_owner: string,\n\t\t_repo: string,\n\t\temail: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t): Promise<Account | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst [user] = await this.findUser(provider, token, email, options);\n\t\t\tif (user == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\tid: String(user.id),\n\t\t\t\tname: user.name || undefined,\n\t\t\t\temail: user.publicEmail || undefined,\n\t\t\t\tavatarUrl: user.avatarUrl || undefined,\n\t\t\t\tusername: user.username || undefined,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, userId) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\tuserId: userId,\n\t\t}),\n\t})\n\tasync getUserSigningKeys(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tuserId: string | number,\n\t\toptions?: { baseUrl?: string },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitLabSshKey[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// SSH keys are public, so this works for any user with the current token (covered by the `read_user` scope).\n\t\ttry {\n\t\t\tconst keys = await this.request<GitLabSshKey[]>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/users/${userId}/keys`,\n\t\t\t\t{ method: 'GET' },\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\t// Exclude auth-only keys — only signing-capable keys belong in an allowed_signers file.\n\t\t\treturn keys?.filter(k => k.usage_type === 'signing' || k.usage_type === 'auth_and_signing') ?? [];\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return [];\n\n\t\t\tthis.handleException(ex, provider, scope);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t}),\n\t})\n\tasync getDefaultBranch(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<DefaultBranch | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject:\n\t\t\t\t\t| {\n\t\t\t\t\t\t\trepository: { rootRef: string } | null | undefined;\n\t\t\t\t\t }\n\t\t\t\t\t| null\n\t\t\t\t\t| undefined;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getDefaultBranch(\n\t$fullPath: ID!\n) {\n\tproject(fullPath: $fullPath) {\n\t\trepository {\n\t\t\trootRef\n\t\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tconst defaultBranch = rsp?.data?.project?.repository?.rootRef ?? undefined;\n\t\t\tif (defaultBranch == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\tname: defaultBranch,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, number) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tnumber: number,\n\t\t}),\n\t})\n\tasync getIssueOrPullRequest(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tnumber: number,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<IssueOrPullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject: {\n\t\t\t\t\tmergeRequest: GitLabMergeRequest | null;\n\t\t\t\t\tissue: GitLabIssue | null;\n\t\t\t\t} | null;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getIssueOrMergeRequest(\n\t$fullPath: ID!\n\t$iid: String!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tmergeRequest(iid: $iid) {\n\t\t\tauthor {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tavatarUrl\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tiid\n\t\t\ttitle\n\t\t\tdescription\n\t\t\tstate\n\t\t\tcreatedAt\n\t\t\tupdatedAt\n\t\t\tmergedAt\n\t\t\twebUrl\n\t\t}\n\t\tissue(iid: $iid) {\n\t\t\tauthor {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tavatarUrl\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tiid\n\t\t\ttitle\n\t\t\tdescription\n\t\t\tstate\n\t\t\tcreatedAt\n\t\t\tupdatedAt\n\t\t\tclosedAt\n\t\t\twebUrl\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t\tiid: String(number),\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tif (rsp?.data?.project?.issue != null) {\n\t\t\t\tconst issue = rsp.data.project.issue;\n\t\t\t\treturn {\n\t\t\t\t\tprovider: provider,\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tid: issue.iid,\n\t\t\t\t\tnodeId: undefined,\n\t\t\t\t\tcreatedDate: new Date(issue.createdAt),\n\t\t\t\t\tupdatedDate: new Date(issue.updatedAt),\n\t\t\t\t\ttitle: issue.title,\n\t\t\t\t\tclosed: issue.state === 'closed',\n\t\t\t\t\tclosedDate: issue.closedAt == null ? undefined : new Date(issue.closedAt),\n\t\t\t\t\turl: issue.webUrl,\n\t\t\t\t\tstate: issue.state === 'locked' ? 'closed' : issue.state,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (rsp?.data?.project?.mergeRequest != null) {\n\t\t\t\tconst mergeRequest = rsp.data.project.mergeRequest;\n\t\t\t\treturn {\n\t\t\t\t\tprovider: provider,\n\t\t\t\t\ttype: 'pullrequest',\n\t\t\t\t\tid: mergeRequest.iid,\n\t\t\t\t\tnodeId: undefined,\n\t\t\t\t\tcreatedDate: new Date(mergeRequest.createdAt),\n\t\t\t\t\tupdatedDate: new Date(mergeRequest.updatedAt),\n\t\t\t\t\ttitle: mergeRequest.title,\n\t\t\t\t\tclosed: mergeRequest.state === 'closed',\n\t\t\t\t\t// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL\n\t\t\t\t\tclosedDate: mergeRequest.state === 'closed' ? new Date(mergeRequest.updatedAt) : undefined,\n\t\t\t\t\turl: mergeRequest.webUrl,\n\t\t\t\t\tstate: mergeRequest.state === 'locked' ? 'closed' : mergeRequest.state,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, branch) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tbranch: branch,\n\t\t}),\n\t})\n\tasync getPullRequestForBranch(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tbranch: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t\tinclude?: GitLabMergeRequestState[];\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject: {\n\t\t\t\t\tmergeRequests?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t\topened?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t\tclosed?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t\tmerged?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t} | null;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst fragment = `\n\t\t\tnodes {\n\t\t\t\tiid\n\t\t\t\tauthor {\n\t\t\t\t\tid\n\t\t\t\t\tname\n\t\t\t\t\tavatarUrl\n\t\t\t\t\twebUrl\n\t\t\t\t}\n\t\t\t\ttitle\n\t\t\t\tdescription\n\t\t\t\tstate\n\t\t\t\tcreatedAt\n\t\t\t\tupdatedAt\n\t\t\t\tmergedAt\n\t\t\t\twebUrl\n\t\t\t}`;\n\n\t\t\tconst query = `query getMergeRequestForBranch(\n\t$fullPath: ID!\n\t$branches: [String!]\n) {\n\tproject(fullPath: $fullPath) {\n\t\t${\n\t\t\toptions?.include == null\n\t\t\t\t? `mergeRequests(sourceBranches: $branches sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t\t${\n\t\t\toptions?.include?.includes('opened')\n\t\t\t\t? `opened: mergeRequests(sourceBranches: $branches state: opened sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t\t${\n\t\t\toptions?.include?.includes('merged')\n\t\t\t\t? `merged: mergeRequests(sourceBranches: $branches state: merged sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t\t${\n\t\t\toptions?.include?.includes('closed')\n\t\t\t\t? `closed: mergeRequests(sourceBranches: $branches state: closed sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t\tbranches: [branch],\n\t\t\t\t\tstate: options?.include,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tlet pr: GitLabMergeRequest | undefined;\n\n\t\t\tif (options?.include == null) {\n\t\t\t\tpr = rsp?.data?.project?.mergeRequests?.nodes?.[0];\n\t\t\t} else {\n\t\t\t\tfor (const state of options.include) {\n\t\t\t\t\tlet mr;\n\t\t\t\t\tif (state === 'opened') {\n\t\t\t\t\t\tmr = rsp?.data?.project?.opened?.nodes?.[0];\n\t\t\t\t\t} else if (state === 'merged') {\n\t\t\t\t\t\tmr = rsp?.data?.project?.merged?.nodes?.[0];\n\t\t\t\t\t} else if (state === 'closed') {\n\t\t\t\t\t\tmr = rsp?.data?.project?.closed?.nodes?.[0];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (mr != null && (pr == null || new Date(mr.updatedAt) > new Date(pr.updatedAt))) {\n\t\t\t\t\t\tpr = mr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pr == null) return undefined;\n\n\t\t\treturn new PullRequest(\n\t\t\t\tprovider,\n\t\t\t\t{\n\t\t\t\t\tid: buildGitLabUserId(pr.author?.id) ?? '',\n\t\t\t\t\t// An absent author stays absent: no `'Unknown'` name a consumer can't tell from a real one, and no\n\t\t\t\t\t// `''` url/avatar that passes a presence check and renders as a link to nowhere. Matches\n\t\t\t\t\t// `fromProviderAccount`/`toIssueShape`.\n\t\t\t\t\tname: pr.author?.name ?? undefined,\n\t\t\t\t\tavatarUrl: pr.author?.avatarUrl ?? undefined,\n\t\t\t\t\turl: pr.author?.webUrl ?? undefined,\n\t\t\t\t},\n\t\t\t\t// oxlint-disable-next-line typescript/no-unnecessary-type-conversion\n\t\t\t\tString(pr.iid),\n\t\t\t\tundefined,\n\t\t\t\tpr.title,\n\t\t\t\tpr.webUrl,\n\t\t\t\t{ owner: owner, repo: repo },\n\t\t\t\tfromGitLabMergeRequestState(pr.state),\n\t\t\t\tnew Date(pr.createdAt),\n\t\t\t\tnew Date(pr.updatedAt),\n\t\t\t\t// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL\n\t\t\t\tpr.state !== 'closed' ? undefined : new Date(pr.updatedAt),\n\t\t\t\tpr.mergedAt == null ? undefined : new Date(pr.mergedAt),\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, rev) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\trev: rev,\n\t\t}),\n\t})\n\tasync getPullRequestForCommit(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);\n\t\tif (!projectId) return undefined;\n\n\t\ttry {\n\t\t\tconst mrs = await this.request<GitLabMergeRequestREST[]>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/projects/${projectId}/repository/commits/${rev}/merge_requests`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t// ...options,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\tif (mrs == null || mrs.length === 0) return undefined;\n\n\t\t\tif (mrs.length > 1) {\n\t\t\t\tmrs.sort(\n\t\t\t\t\t(a, b) =>\n\t\t\t\t\t\t(a.state === 'opened' ? -1 : 1) - (b.state === 'opened' ? -1 : 1) ||\n\t\t\t\t\t\tnew Date(b.updated_at).getTime() - new Date(a.updated_at).getTime(),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn fromGitLabMergeRequestREST(mrs[0], provider, { owner: owner, repo: repo });\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, id) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tid: id,\n\t\t}),\n\t})\n\tasync getPullRequest(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tid: number,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject: {\n\t\t\t\t\tmergeRequest: GitLabMergeRequestFull | null;\n\t\t\t\t} | null;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getMergeRequest(\n\t$fullPath: ID!\n\t$iid: String!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tmergeRequest(iid: $iid) {\n\t\t\tid,\n\t\t\tiid\n\t\t\tstate,\n\t\t\tauthor {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tavatarUrl\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tdiffRefs {\n\t\t\t\tbaseSha\n\t\t\t\theadSha\n\t\t\t}\n\t\t\ttitle\n\t\t\tdescription\n\t\t\twebUrl\n\t\t\tcreatedAt\n\t\t\tupdatedAt\n\t\t\tmergedAt\n\t\t\ttargetBranch\n\t\t\tsourceBranch\n\t\t\tproject {\n\t\t\t\tid\n\t\t\t\tfullPath\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tsourceProject {\n\t\t\t\tid\n\t\t\t\tfullPath\n\t\t\t\twebUrl\n\t\t\t}\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t\tiid: String(id),\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tif (rsp?.data?.project?.mergeRequest == null) return undefined;\n\n\t\t\tconst pr = rsp.data.project.mergeRequest;\n\t\t\treturn fromGitLabMergeRequest(pr, provider);\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t}),\n\t})\n\tasync getRepositoryMetadata(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<RepositoryMetadata | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);\n\t\tif (!projectId) return undefined;\n\n\t\ttry {\n\t\t\tconst proj = await this.request<GitLabProjectREST>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/projects/${projectId}`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t// ...options,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\tif (proj == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\towner: proj.namespace.full_path,\n\t\t\t\tname: proj.path,\n\t\t\t\tisFork: proj.forked_from_project != null,\n\t\t\t\tparent:\n\t\t\t\t\tproj.forked_from_project != null\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\towner: proj.forked_from_project.namespace.full_path,\n\t\t\t\t\t\t\t\tname: proj.forked_from_project.path,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t} satisfies RepositoryMetadata;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({ args: (provider, token) => ({ provider: provider.name, token: `<token:${token.microHash}>` }) })\n\tasync searchPullRequests(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\toptions?: {\n\t\t\tsearch?: string;\n\t\t\tuser?: string;\n\t\t\trepos?: string[];\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t\tinclude?: PullRequestState[];\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest[]> {\n\t\tconst scope = getScopedLogger();\n\t\tconst search = options?.search;\n\t\tif (!search) {\n\t\t\treturn [];\n\t\t}\n\n\t\ttry {\n\t\t\tconst perPageLimit = 20; // with bigger amount we exceed the max GraphQL complexity in the next query\n\t\t\tconst include = options?.include?.length ? options.include : undefined;\n\t\t\t// GitLab's search API takes a single `state` value, so push it server-side when exactly one state is\n\t\t\t// requested; that keeps the requested state from being crowded out of the `perPageLimit` slice. For\n\t\t\t// multiple states there's no single-value qualifier, so those are filtered client-side below.\n\t\t\tlet searchPath = `v4/search/?scope=merge_requests&search=${encodeURIComponent(search)}&per_page=${perPageLimit}`;\n\t\t\tif (include?.length === 1) {\n\t\t\t\tsearchPath += `&state=${encodeURIComponent(toGitLabMergeRequestState(include[0]))}`;\n\t\t\t}\n\n\t\t\tlet restPRs: GitLabMergeRequestREST[];\n\t\t\tif (include == null) {\n\t\t\t\t// Unfiltered search returns the first page as-is (as it did before state filtering existed).\n\t\t\t\trestPRs = await this.request<GitLabMergeRequestREST[]>(\n\t\t\t\t\tprovider,\n\t\t\t\t\ttoken,\n\t\t\t\t\toptions?.baseUrl,\n\t\t\t\t\tsearchPath,\n\t\t\t\t\t{ method: 'GET' },\n\t\t\t\t\tcancellation,\n\t\t\t\t\tscope,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// The search API returns MRs of all states in relevance order, so the requested state(s) may not\n\t\t\t\t// appear on the first page. Server-side `&state=` narrows the single-state case when honored, but it\n\t\t\t\t// can't express multiple states, so page through the results and accumulate matches until we fill the\n\t\t\t\t// detail-query cap (`perPageLimit`) or exhaust the search results. This keeps correctness whether\n\t\t\t\t// or not `&state=` takes effect. Bounded by `maxSearchPages` like the other paged provider drains in\n\t\t\t\t// this package so a large, low-match result set can't fan out into an unbounded request loop.\n\t\t\t\tconst maxSearchPages = 20;\n\t\t\t\tconst matches: GitLabMergeRequestREST[] = [];\n\t\t\t\tfor (let page = 1; page <= maxSearchPages; page++) {\n\t\t\t\t\tconst pagePRs = await this.request<GitLabMergeRequestREST[]>(\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\toptions?.baseUrl,\n\t\t\t\t\t\t`${searchPath}&page=${page}`,\n\t\t\t\t\t\t{ method: 'GET' },\n\t\t\t\t\t\tcancellation,\n\t\t\t\t\t\tscope,\n\t\t\t\t\t);\n\t\t\t\t\tfor (const pr of pagePRs) {\n\t\t\t\t\t\tif (include.includes(fromGitLabMergeRequestState(pr.state))) {\n\t\t\t\t\t\t\tmatches.push(pr);\n\t\t\t\t\t\t\tif (matches.length >= perPageLimit) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Stop once we've filled the cap or hit the last (partial or empty) page.\n\t\t\t\t\tif (matches.length >= perPageLimit || pagePRs.length < perPageLimit) break;\n\t\t\t\t}\n\t\t\t\trestPRs = matches;\n\t\t\t}\n\t\t\tif (restPRs.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tinterface QueryResult {\n\t\t\t\tdata: Record<`mergeRequest_${number}`, GitLabMergeRequestFull>;\n\t\t\t}\n\n\t\t\tconst queryArgs = restPRs.map((_, i) => `$id_${i}: MergeRequestID!`).join('\\n');\n\t\t\tconst queryFields = restPRs\n\t\t\t\t.map((_, i) => `mergeRequest_${i}: mergeRequest(id: $id_${i}) { ...mergeRequestFields }`)\n\t\t\t\t.join('\\n');\n\t\t\t// Set of fields includes only additional fields that are not included in GitLabMergeRequestREST.\n\t\t\t// It's limited as much as possible to reduce complexity of the query.\n\t\t\tconst queryMrFields = `fragment mergeRequestFields on MergeRequest {\n\t\t\t\tdiffRefs {\n\t\t\t\t\tbaseSha\n\t\t\t\t\theadSha\n\t\t\t\t}\n\t\t\t\tproject {\n\t\t\t\t\tid\n\t\t\t\t\tfullPath\n\t\t\t\t\twebUrl\n\t\t\t\t}\n\t\t\t\tsourceProject {\n\t\t\t\t\tid\n\t\t\t\t\tfullPath\n\t\t\t\t\twebUrl\n\t\t\t\t}\n\t\t\t}`;\n\t\t\tconst query = `query getMergeRequests (${queryArgs}) {${queryFields}} ${queryMrFields}`;\n\n\t\t\tconst params = restPRs.reduce<Record<`id_${number}`, string>>((ids, gitlabRestPr, i) => {\n\t\t\t\tids[`id_${i}`] = `${gitlabMergeRequestIdPrefix}${gitlabRestPr.id}`;\n\t\t\t\treturn ids;\n\t\t\t}, {});\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\tparams,\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\tif (rsp?.data != null) {\n\t\t\t\tconst resultPRs = restPRs.reduce<PullRequest[]>((accum, restPR, i) => {\n\t\t\t\t\tconst graphQlPR = rsp.data[`mergeRequest_${i}`];\n\t\t\t\t\tif (graphQlPR == null) {\n\t\t\t\t\t\treturn accum;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fullPr: GitLabMergeRequestFull = {\n\t\t\t\t\t\t...graphQlPR,\n\t\t\t\t\t\tiid: String(restPR.iid),\n\t\t\t\t\t\tid: String(restPR.id),\n\t\t\t\t\t\tstate: restPR.state,\n\t\t\t\t\t\t// An absent REST author stays absent (`null`, as GitLab's own shape expresses it) rather than a\n\t\t\t\t\t\t// synthesized `'Unknown'` stub: `fromGitLabMergeRequest` collapses `null` to an absent\n\t\t\t\t\t\t// `PullRequestMember.name`, whereas a placeholder here would launder into a real-looking name.\n\t\t\t\t\t\tauthor:\n\t\t\t\t\t\t\trestPR.author != null\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tid: buildGitLabUserId(restPR.author.id) ?? '',\n\t\t\t\t\t\t\t\t\t\tname: restPR.author.name,\n\t\t\t\t\t\t\t\t\t\tavatarUrl: restPR.author.avatar_url ?? null,\n\t\t\t\t\t\t\t\t\t\twebUrl: restPR.author.web_url,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\ttitle: restPR.title,\n\t\t\t\t\t\tdescription: restPR.description,\n\t\t\t\t\t\twebUrl: restPR.web_url,\n\t\t\t\t\t\tcreatedAt: restPR.created_at,\n\t\t\t\t\t\tupdatedAt: restPR.updated_at,\n\t\t\t\t\t\tmergedAt: restPR.merged_at,\n\t\t\t\t\t\tsourceBranch: restPR.source_branch,\n\t\t\t\t\t\ttargetBranch: restPR.target_branch,\n\t\t\t\t\t};\n\t\t\t\t\taccum.push(fromGitLabMergeRequest(fullPr, provider));\n\t\t\t\t\treturn accum;\n\t\t\t\t}, []);\n\t\t\t\treturn resultPRs;\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return [];\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\tprivate async findUser(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tsearch: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitLabUser[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tusers: {\n\t\t\t\t\tnodes: {\n\t\t\t\t\t\tid: string;\n\t\t\t\t\t\tname: string;\n\t\t\t\t\t\tusername: string;\n\t\t\t\t\t\tpublicEmail?: string;\n\t\t\t\t\t\tstate: string;\n\t\t\t\t\t\tavatarUrl: string;\n\t\t\t\t\t\twebUrl: string;\n\t\t\t\t\t}[];\n\t\t\t\t};\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query findUser(\n$search: String!\n) {\n\tusers(search: $search) {\n\t\tnodes {\n\t\t\tid\n\t\t\tname\n\t\t\tusername,\n\t\t\tpublicEmail,\n\t\t\tstate\n\t\t\tavatarUrl\n\t\t\twebUrl\n\t\t}\n\t}\n}`;\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tsearch: search,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tconst matches = rsp?.data?.users?.nodes;\n\t\t\tif (matches == null || matches.length === 0) return [];\n\n\t\t\tconst users: GitLabUser[] = [];\n\n\t\t\tfor (const user of matches) {\n\t\t\t\tconst match = /gid:\\/\\/gitlab\\/User\\/([0-9]+)\\b/.exec(user.id);\n\t\t\t\tif (match == null) continue;\n\n\t\t\t\tusers.push({\n\t\t\t\t\tid: parseInt(match[1], 10),\n\t\t\t\t\tname: user.name,\n\t\t\t\t\tusername: user.username,\n\t\t\t\t\tpublicEmail: user.publicEmail || undefined,\n\t\t\t\t\tstate: user.state,\n\t\t\t\t\tavatarUrl: user.avatarUrl,\n\t\t\t\t\twebUrl: user.webUrl,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn users;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return [];\n\n\t\t\tthis.handleException(ex, provider, scope);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tgetProjectId(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tgroup: string,\n\t\trepo: string,\n\t\tbaseUrl: string | undefined,\n\t\tcancellation: AbortSignal | undefined,\n\t): Promise<string | undefined> {\n\t\tconst { accessToken } = token;\n\t\tconst key = `${accessToken}|${group}/${repo}`;\n\n\t\tlet projectId = this._projectIds.get(key);\n\t\tif (projectId == null) {\n\t\t\tprojectId = this.getProjectIdCore(provider, token, group, repo, baseUrl, cancellation);\n\t\t\tthis._projectIds.set(key, projectId);\n\t\t}\n\n\t\treturn projectId;\n\t}\n\n\tprivate async getProjectIdCore(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tgroup: string,\n\t\trepo: string,\n\t\tbaseUrl: string | undefined,\n\t\tcancellation: AbortSignal | undefined,\n\t): Promise<string | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: { project: { id: string } };\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getProjectId(\n\t$fullPath: ID!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tid\n\t}\n}`;\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\tbaseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${group}/${repo}`,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tconst gid = rsp?.data?.project?.id;\n\t\t\tif (gid == null) return undefined;\n\n\t\t\tconst match = /gid:\\/\\/gitlab\\/Project\\/([0-9]+)\\b/.exec(gid);\n\t\t\tif (match == null) return undefined;\n\n\t\t\tconst projectId = match[1];\n\n\t\t\tscope?.addExitInfo(`projectId=${projectId}`);\n\t\t\treturn projectId;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthis.handleException(ex, provider, scope);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate async graphql<T extends object>(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tbaseUrl: string | undefined,\n\t\tquery: string,\n\t\tvariables: Record<string, any>,\n\t\tcancellation: AbortSignal | undefined,\n\t\tscope: ScopedLogger | undefined,\n\t): Promise<T | undefined> {\n\t\tconst { accessToken } = token;\n\t\tlet rsp: Response;\n\t\ttry {\n\t\t\tconst sw = maybeStopWatch(`[GITLAB] POST ${baseUrl}`, { log: { onlyExit: true } });\n\n\t\t\ttry {\n\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\trsp = await this.config.wrapForForcedInsecureSSL(provider.getIgnoreSSLErrors(), () =>\n\t\t\t\t\tthis.config.fetch(`${baseUrl ?? 'https://gitlab.com/api'}/graphql`, {\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\theaders: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },\n\t\t\t\t\t\tsignal: cancellation,\n\t\t\t\t\t\tbody: JSON.stringify({ query: query, variables: variables }),\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tif (rsp.ok) {\n\t\t\t\t\tconst data = (await rsp.json()) as T | { errors: { message: string }[] };\n\n\t\t\t\t\tif ('errors' in data) throw new ProviderFetchError('GitLab', rsp, data.errors);\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Reads the body so the 403 branch below can tell a throttled request from a permission failure.\n\t\t\t\tthrow await ProviderFetchError.fromResponse('GitLab', rsp);\n\t\t\t} finally {\n\t\t\t\tconst match = /(^[^({\\n]+)/.exec(query);\n\t\t\t\tconst message = ` ${match?.[1].trim() ?? query}`;\n\n\t\t\t\tsw?.stop({ message: message });\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof ProviderFetchError || ex.name === 'AbortError') {\n\t\t\t\tthis.handleRequestError(provider, token, ex, scope);\n\t\t\t} else if (Logger.isDebugging) {\n\t\t\t\tthis.config.onError?.(`GitLab request failed: ${ex.message}`);\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate async request<T>(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tbaseUrl: string | undefined,\n\t\troute: string,\n\t\toptions: { method: RequestInit['method'] } & Record<string, unknown>,\n\t\tcancellation: AbortSignal | undefined,\n\t\tscope: ScopedLogger | undefined,\n\t): Promise<T> {\n\t\tconst { accessToken } = token;\n\t\tconst url = `${baseUrl ?? 'https://gitlab.com/api'}/${route}`;\n\n\t\tlet rsp: Response;\n\t\ttry {\n\t\t\tconst sw = maybeStopWatch(`[GITLAB] ${options?.method ?? 'GET'} ${url}`, { log: { onlyExit: true } });\n\n\t\t\ttry {\n\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\trsp = await this.config.wrapForForcedInsecureSSL(provider.getIgnoreSSLErrors(), () =>\n\t\t\t\t\tthis.config.fetch(url, {\n\t\t\t\t\t\theaders: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },\n\t\t\t\t\t\tsignal: cancellation,\n\t\t\t\t\t\t...options,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tif (rsp.ok) {\n\t\t\t\t\treturn (await rsp.json()) as T;\n\t\t\t\t}\n\n\t\t\t\t// Reads the body so the 403 branch below can tell a throttled request from a permission failure.\n\t\t\t\tthrow await ProviderFetchError.fromResponse('GitLab', rsp);\n\t\t\t} finally {\n\t\t\t\tsw?.stop();\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof ProviderFetchError || ex.name === 'AbortError') {\n\t\t\t\tthis.handleRequestError(provider, token, ex, scope);\n\t\t\t} else if (Logger.isDebugging) {\n\t\t\t\tthis.config.onError?.(`GitLab request failed: ${ex.message}`);\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate handleRequestError(\n\t\tprovider: Provider | undefined,\n\t\ttoken: TokenWithInfo,\n\t\tex: ProviderFetchError | (Error & { name: 'AbortError' }),\n\t\tscope: ScopedLogger | undefined,\n\t): void {\n\t\tif (ex.name === 'AbortError' || !(ex instanceof ProviderFetchError)) throw new CancellationError(ex);\n\n\t\tconst { accessToken, ...tokenInfo } = token;\n\t\tswitch (ex.status) {\n\t\t\tcase 404: // Not found\n\t\t\tcase 410: // Gone\n\t\t\tcase 422: // Unprocessable Entity\n\t\t\t\tthrow new RequestNotFoundError(ex);\n\t\t\tcase 429: // Too Many Requests\n\t\t\t\tthrow toRateLimitError(ex, accessToken);\n\t\t\tcase 401: // Unauthorized\n\t\t\t\tthrow new AuthenticationError(tokenInfo, AuthenticationErrorReason.Unauthorized, ex);\n\t\t\tcase 403: // Forbidden\n\t\t\t\t// GitLab returns 403 for both a permission failure and a throttled request, so the message is the\n\t\t\t\t// discriminant (see `isRateLimitResponse`, shared with Bitbucket/Azure).\n\t\t\t\tif (isRateLimitResponse(ex)) throw toRateLimitError(ex, accessToken);\n\n\t\t\t\tthrow new AuthenticationError(tokenInfo, AuthenticationErrorReason.Forbidden, ex);\n\t\t\tcase 500: // Internal Server Error\n\t\t\t\tscope?.error(ex);\n\t\t\t\tif (ex.response != null) {\n\t\t\t\t\tprovider?.trackRequestException();\n\t\t\t\t\tthis.config.onRequestFailed?.(\n\t\t\t\t\t\tprovider == null || provider.id === 'gitlab'\n\t\t\t\t\t\t\t? l10n.t(\n\t\t\t\t\t\t\t\t\t'{0} failed to respond and might be experiencing issues. Please visit the [GitLab status page](https://status.gitlab.com) for more information.',\n\t\t\t\t\t\t\t\t\tprovider?.name ?? 'GitLab',\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: l10n.t('{0} failed to respond and might be experiencing issues.', provider.name),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase 502: // Bad Gateway\n\t\t\t\tscope?.error(ex);\n\t\t\t\t// GitHub seems to return this status code for timeouts\n\t\t\t\tif (ex.message.includes('timeout')) {\n\t\t\t\t\tprovider?.trackRequestException();\n\t\t\t\t\tthis.config.onRequestTimedOut?.(provider?.name ?? 'GitLab');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (ex.status >= 400 && ex.status < 500) throw new RequestClientError(ex);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tscope?.error(ex);\n\t\tif (Logger.isDebugging) {\n\t\t\tthis.config.onError?.(`GitLab request failed: ${(ex.response as any)?.errors?.[0]?.message ?? ex.message}`);\n\t\t}\n\t}\n\n\tprivate handleException(ex: Error, provider: Provider, scope: ScopedLogger | undefined): Error {\n\t\tscope?.error(ex);\n\t\t// debugger;\n\n\t\tif (ex instanceof AuthenticationError) {\n\t\t\tvoid this.showAuthenticationErrorMessage(ex, provider);\n\t\t}\n\t\treturn ex;\n\t}\n\n\tprivate async showAuthenticationErrorMessage(ex: AuthenticationError, provider: Provider) {\n\t\tif (ex.reason === AuthenticationErrorReason.Unauthorized || ex.reason === AuthenticationErrorReason.Forbidden) {\n\t\t\tconst reauthenticate = await this.config.onReauthenticationRequired?.(\n\t\t\t\tex.reason === AuthenticationErrorReason.Forbidden\n\t\t\t\t\t? l10n.t('{0}. Would you like to try reauthenticating to provide additional access?', ex.message)\n\t\t\t\t\t: l10n.t('{0}. Would you like to try reauthenticating?', ex.message),\n\t\t\t);\n\n\t\t\tif (reauthenticate) {\n\t\t\t\tawait provider.reauthenticate();\n\t\t\t\tthis.resetCaches();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.config.onError?.(ex.message);\n\t\t}\n\t}\n}\n\n/** Wires a {@link GitLabApi} from the full runtime context, mapping `ctx` down to the narrow config. */\nexport function createGitLabApi(ctx: IntegrationServiceContext): GitLabApi {\n\tconst config: ProviderApiConfig = {\n\t\t...baseProviderApiConfig(ctx),\n\t\t// Self-hosted GitLab keys its API base off `remotes`, so reset on both HTTP proxy and remotes changes.\n\t\tonConfigChanged: listener =>\n\t\t\tctx.config.onDidChange(e => {\n\t\t\t\tif (e.httpProxy || e.remotes) {\n\t\t\t\t\tlistener();\n\t\t\t\t}\n\t\t\t}),\n\t\tonReauthenticationRequired: message =>\n\t\t\tctx.hooks?.onReauthenticationRequired?.(message) ?? Promise.resolve(false),\n\t\tonRequestTimedOut: providerName => ctx.hooks?.ui?.onRequestTimedOut?.(providerName),\n\t};\n\n\treturn new GitLabApi(config);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gitlab.js","names":["Logger"],"sources":["../../../../../../plus/integrations/src/providers/gitlab/gitlab.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport { reportRequestFailure } from '@gitlens/git/errors.js';\nimport type { Account } from '@gitlens/git/models/author.js';\nimport type { DefaultBranch } from '@gitlens/git/models/defaultBranch.js';\nimport type { IssueOrPullRequest } from '@gitlens/git/models/issueOrPullRequest.js';\nimport { PullRequest } from '@gitlens/git/models/pullRequest.js';\nimport type { PullRequestState } from '@gitlens/git/models/pullRequest.js';\nimport type { Provider } from '@gitlens/git/models/remoteProvider.js';\nimport type { RepositoryMetadata } from '@gitlens/git/models/repositoryMetadata.js';\nimport { CancellationError } from '@gitlens/utils/cancellation.js';\nimport { trace } from '@gitlens/utils/decorators/log.js';\nimport type { Disposable } from '@gitlens/utils/disposable.js';\nimport { Logger } from '@gitlens/utils/logger.js';\nimport type { ScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { maybeStopWatch } from '@gitlens/utils/stopwatch.js';\nimport { equalsIgnoreCase } from '@gitlens/utils/string.js';\nimport { joinUriPath, parseUri } from '@gitlens/utils/uri.js';\nimport type { TokenWithInfo } from '../../authentication/models.js';\nimport type { IntegrationServiceContext } from '../../context.js';\nimport {\n\tAuthenticationError,\n\tAuthenticationErrorReason,\n\tisRateLimitResponse,\n\tProviderFetchError,\n\tRequestClientError,\n\tRequestNotFoundError,\n\ttoRateLimitError,\n} from '../../errors.js';\nimport type { ProviderApiConfig } from '../apiConfig.js';\nimport { baseProviderApiConfig } from '../apiConfig.js';\nimport { selectBranchPullRequests } from '../utils/providerPaging.js';\nimport { selectGitLabUserForCommit } from './gitlab.utils.js';\nimport type {\n\tGitLabCommit,\n\tGitLabIssue,\n\tGitLabMergeRequest,\n\tGitLabMergeRequestFull,\n\tGitLabMergeRequestREST,\n\tGitLabMergeRequestState,\n\tGitLabProjectREST,\n\tGitLabSshKey,\n\tGitLabUser,\n} from './models.js';\nimport {\n\tfromGitLabMergeRequest,\n\tfromGitLabMergeRequestREST,\n\tfromGitLabMergeRequestState,\n\tgetRepoNamespace,\n\ttoGitLabMergeRequestState,\n} from './models.js';\n\n// drop it as soon as we switch to @gitkraken/providers-api\nconst gitlabUserIdPrefix = 'gid://gitlab/User/';\nconst gitlabMergeRequestIdPrefix = 'gid://gitlab/MergeRequest/';\n\nfunction buildGitLabUserId(id: string | number | undefined): string | undefined {\n\treturn typeof id === 'string' && id?.startsWith(gitlabUserIdPrefix)\n\t\t? id.substring(gitlabUserIdPrefix.length)\n\t\t: String(id);\n}\n\nexport class GitLabApi implements Disposable {\n\tprivate readonly _disposable: Disposable | undefined;\n\tprivate _projectIds = new Map<string, Promise<string | undefined>>();\n\n\tconstructor(private readonly config: ProviderApiConfig) {\n\t\tthis._disposable = config.onConfigChanged?.(() => this.resetCaches());\n\t}\n\n\tdispose(): void {\n\t\tthis._disposable?.dispose();\n\t}\n\n\tprivate resetCaches(): void {\n\t\tthis._projectIds.clear();\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, rev) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\trev: rev,\n\t\t}),\n\t})\n\tasync getAccountForCommit(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<Account | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);\n\t\tif (!projectId) return undefined;\n\n\t\ttry {\n\t\t\tconst commit = await this.request<GitLabCommit>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/projects/${projectId}/repository/commits/${rev}?stats=false`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t// ...options,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tlet users = await this.findUser(provider, token, commit.author_name, options, cancellation);\n\t\t\tlet user = selectGitLabUserForCommit(users, commit.author_name, commit.author_email);\n\n\t\t\t// If the name search was ambiguous (multiple users share the name), try an email-scoped search to\n\t\t\t// disambiguate before giving up — otherwise we'd show a stranger's avatar (see #2205)\n\t\t\tif (user == null && commit.author_email) {\n\t\t\t\tconst exactNameMatches = users.filter(u => equalsIgnoreCase(u.name, commit.author_name)).length;\n\t\t\t\tif (exactNameMatches > 1) {\n\t\t\t\t\tusers = await this.findUser(provider, token, commit.author_email, options, cancellation);\n\t\t\t\t\tuser = selectGitLabUserForCommit(users, commit.author_name, commit.author_email);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (user == null) return undefined;\n\n\t\t\t// If the avatarUrl is a relative URL, make it absolute using the webUrl (assuming the webUrl is the root URL with the username tacked on)\n\t\t\tif (user.avatarUrl && !/^([a-zA-Z][\\w+.-]+):/.test(user.avatarUrl)) {\n\t\t\t\tuser.avatarUrl = joinUriPath(parseUri(user.webUrl), '..', user.avatarUrl).toString();\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\tid: String(user.id),\n\t\t\t\tname: user.name || undefined,\n\t\t\t\temail: commit.author_email || undefined,\n\t\t\t\tavatarUrl: user.avatarUrl || undefined,\n\t\t\t\tusername: user.username || undefined,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, _owner, _repo, email) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\temail: email,\n\t\t}),\n\t})\n\tasync getAccountForEmail(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\t_owner: string,\n\t\t_repo: string,\n\t\temail: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t): Promise<Account | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst [user] = await this.findUser(provider, token, email, options);\n\t\t\tif (user == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\tid: String(user.id),\n\t\t\t\tname: user.name || undefined,\n\t\t\t\temail: user.publicEmail || undefined,\n\t\t\t\tavatarUrl: user.avatarUrl || undefined,\n\t\t\t\tusername: user.username || undefined,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, userId) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\tuserId: userId,\n\t\t}),\n\t})\n\tasync getUserSigningKeys(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tuserId: string | number,\n\t\toptions?: { baseUrl?: string },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitLabSshKey[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// SSH keys are public, so this works for any user with the current token (covered by the `read_user` scope).\n\t\ttry {\n\t\t\tconst keys = await this.request<GitLabSshKey[]>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/users/${userId}/keys`,\n\t\t\t\t{ method: 'GET' },\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\t// Exclude auth-only keys — only signing-capable keys belong in an allowed_signers file.\n\t\t\treturn keys?.filter(k => k.usage_type === 'signing' || k.usage_type === 'auth_and_signing') ?? [];\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return [];\n\n\t\t\tthis.handleException(ex, provider, scope);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t}),\n\t})\n\tasync getDefaultBranch(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<DefaultBranch | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject:\n\t\t\t\t\t| {\n\t\t\t\t\t\t\trepository: { rootRef: string } | null | undefined;\n\t\t\t\t\t }\n\t\t\t\t\t| null\n\t\t\t\t\t| undefined;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getDefaultBranch(\n\t$fullPath: ID!\n) {\n\tproject(fullPath: $fullPath) {\n\t\trepository {\n\t\t\trootRef\n\t\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tconst defaultBranch = rsp?.data?.project?.repository?.rootRef ?? undefined;\n\t\t\tif (defaultBranch == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\tname: defaultBranch,\n\t\t\t};\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, number) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tnumber: number,\n\t\t}),\n\t})\n\tasync getIssueOrPullRequest(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tnumber: number,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<IssueOrPullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject: {\n\t\t\t\t\tmergeRequest: GitLabMergeRequest | null;\n\t\t\t\t\tissue: GitLabIssue | null;\n\t\t\t\t} | null;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getIssueOrMergeRequest(\n\t$fullPath: ID!\n\t$iid: String!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tmergeRequest(iid: $iid) {\n\t\t\tauthor {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tavatarUrl\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tiid\n\t\t\ttitle\n\t\t\tdescription\n\t\t\tstate\n\t\t\tcreatedAt\n\t\t\tupdatedAt\n\t\t\tmergedAt\n\t\t\twebUrl\n\t\t}\n\t\tissue(iid: $iid) {\n\t\t\tauthor {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tavatarUrl\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tiid\n\t\t\ttitle\n\t\t\tdescription\n\t\t\tstate\n\t\t\tcreatedAt\n\t\t\tupdatedAt\n\t\t\tclosedAt\n\t\t\twebUrl\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t\tiid: String(number),\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tif (rsp?.data?.project?.issue != null) {\n\t\t\t\tconst issue = rsp.data.project.issue;\n\t\t\t\treturn {\n\t\t\t\t\tprovider: provider,\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tid: issue.iid,\n\t\t\t\t\tnodeId: undefined,\n\t\t\t\t\tcreatedDate: new Date(issue.createdAt),\n\t\t\t\t\tupdatedDate: new Date(issue.updatedAt),\n\t\t\t\t\ttitle: issue.title,\n\t\t\t\t\tclosed: issue.state === 'closed',\n\t\t\t\t\tclosedDate: issue.closedAt == null ? undefined : new Date(issue.closedAt),\n\t\t\t\t\turl: issue.webUrl,\n\t\t\t\t\tstate: issue.state === 'locked' ? 'closed' : issue.state,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (rsp?.data?.project?.mergeRequest != null) {\n\t\t\t\tconst mergeRequest = rsp.data.project.mergeRequest;\n\t\t\t\treturn {\n\t\t\t\t\tprovider: provider,\n\t\t\t\t\ttype: 'pullrequest',\n\t\t\t\t\tid: mergeRequest.iid,\n\t\t\t\t\tnodeId: undefined,\n\t\t\t\t\tcreatedDate: new Date(mergeRequest.createdAt),\n\t\t\t\t\tupdatedDate: new Date(mergeRequest.updatedAt),\n\t\t\t\t\ttitle: mergeRequest.title,\n\t\t\t\t\tclosed: mergeRequest.state === 'closed',\n\t\t\t\t\t// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL\n\t\t\t\t\tclosedDate: mergeRequest.state === 'closed' ? new Date(mergeRequest.updatedAt) : undefined,\n\t\t\t\t\turl: mergeRequest.webUrl,\n\t\t\t\t\tstate: mergeRequest.state === 'locked' ? 'closed' : mergeRequest.state,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t/**\n\t * Whether `owner/repo` has issue `iid`. Strict like {@link getPullRequest}'s `strict`: `false` only for a `null`\n\t * project or issue, which is how GitLab's GraphQL answers a missing one; GraphQL `errors`, an empty response and\n\t * any HTTP error (a 404 means a wrong endpoint) all throw instead of reading as absent.\n\t */\n\t@trace({\n\t\targs: (provider, token, owner, repo, iid) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tiid: iid,\n\t\t}),\n\t})\n\tasync hasIssue(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tiid: number,\n\t\toptions: { baseUrl?: string; deferFailure?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: { project: { issue: { iid: string } | null } | null } | null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query hasIssue(\n\t$fullPath: ID!\n\t$iid: String!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tissue(iid: $iid) {\n\t\t\tiid\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{ fullPath: `${owner}/${repo}`, iid: String(iid) },\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t\toptions.deferFailure,\n\t\t\t);\n\t\t\tif (rsp?.data == null) throw new Error('GitLab returned no data for the issue');\n\n\t\t\treturn rsp.data.project?.issue != null;\n\t\t} catch (ex) {\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, branch) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tbranch: branch,\n\t\t}),\n\t})\n\tasync getPullRequestForBranch(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tbranch: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t\tinclude?: GitLabMergeRequestState[];\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject: {\n\t\t\t\t\tmergeRequests?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t\topened?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t\tclosed?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t\tmerged?: {\n\t\t\t\t\t\tnodes: GitLabMergeRequest[];\n\t\t\t\t\t} | null;\n\t\t\t\t} | null;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst fragment = `\n\t\t\tnodes {\n\t\t\t\tiid\n\t\t\t\tauthor {\n\t\t\t\t\tid\n\t\t\t\t\tname\n\t\t\t\t\tavatarUrl\n\t\t\t\t\twebUrl\n\t\t\t\t}\n\t\t\t\ttitle\n\t\t\t\tdescription\n\t\t\t\tstate\n\t\t\t\tcreatedAt\n\t\t\t\tupdatedAt\n\t\t\t\tmergedAt\n\t\t\t\twebUrl\n\t\t\t}`;\n\n\t\t\tconst query = `query getMergeRequestForBranch(\n\t$fullPath: ID!\n\t$branches: [String!]\n) {\n\tproject(fullPath: $fullPath) {\n\t\t${\n\t\t\toptions?.include == null\n\t\t\t\t? `mergeRequests(sourceBranches: $branches sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t\t${\n\t\t\toptions?.include?.includes('opened')\n\t\t\t\t? `opened: mergeRequests(sourceBranches: $branches state: opened sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t\t${\n\t\t\toptions?.include?.includes('merged')\n\t\t\t\t? `merged: mergeRequests(sourceBranches: $branches state: merged sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t\t${\n\t\t\toptions?.include?.includes('closed')\n\t\t\t\t? `closed: mergeRequests(sourceBranches: $branches state: closed sort: UPDATED_DESC first: 1) {\n\t\t\t${fragment}\n\t\t}`\n\t\t\t\t: ''\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t\tbranches: [branch],\n\t\t\t\t\tstate: options?.include,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tlet pr: GitLabMergeRequest | undefined;\n\n\t\t\tif (options?.include == null) {\n\t\t\t\tpr = rsp?.data?.project?.mergeRequests?.nodes?.[0];\n\t\t\t} else {\n\t\t\t\tfor (const state of options.include) {\n\t\t\t\t\tlet mr;\n\t\t\t\t\tif (state === 'opened') {\n\t\t\t\t\t\tmr = rsp?.data?.project?.opened?.nodes?.[0];\n\t\t\t\t\t} else if (state === 'merged') {\n\t\t\t\t\t\tmr = rsp?.data?.project?.merged?.nodes?.[0];\n\t\t\t\t\t} else if (state === 'closed') {\n\t\t\t\t\t\tmr = rsp?.data?.project?.closed?.nodes?.[0];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (mr != null && (pr == null || new Date(mr.updatedAt) > new Date(pr.updatedAt))) {\n\t\t\t\t\t\tpr = mr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pr == null) return undefined;\n\n\t\t\treturn new PullRequest(\n\t\t\t\tprovider,\n\t\t\t\t{\n\t\t\t\t\tid: buildGitLabUserId(pr.author?.id) ?? '',\n\t\t\t\t\t// An absent author stays absent: no `'Unknown'` name a consumer can't tell from a real one, and no\n\t\t\t\t\t// `''` url/avatar that passes a presence check and renders as a link to nowhere. Matches\n\t\t\t\t\t// `fromProviderAccount`/`toIssueShape`.\n\t\t\t\t\tname: pr.author?.name ?? undefined,\n\t\t\t\t\tavatarUrl: pr.author?.avatarUrl ?? undefined,\n\t\t\t\t\turl: pr.author?.webUrl ?? undefined,\n\t\t\t\t},\n\t\t\t\t// oxlint-disable-next-line typescript/no-unnecessary-type-conversion\n\t\t\t\tString(pr.iid),\n\t\t\t\tundefined,\n\t\t\t\tpr.title,\n\t\t\t\tpr.webUrl,\n\t\t\t\t{ owner: owner, repo: repo },\n\t\t\t\tfromGitLabMergeRequestState(pr.state),\n\t\t\t\tnew Date(pr.createdAt),\n\t\t\t\tnew Date(pr.updatedAt),\n\t\t\t\t// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL\n\t\t\t\tpr.state !== 'closed' ? undefined : new Date(pr.updatedAt),\n\t\t\t\tpr.mergedAt == null ? undefined : new Date(pr.mergedAt),\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, rev) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\trev: rev,\n\t\t}),\n\t})\n\tasync getPullRequestForCommit(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);\n\t\tif (!projectId) return undefined;\n\n\t\ttry {\n\t\t\tconst mrs = await this.request<GitLabMergeRequestREST[]>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/projects/${projectId}/repository/commits/${rev}/merge_requests`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t// ...options,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\tif (mrs == null || mrs.length === 0) return undefined;\n\n\t\t\tif (mrs.length > 1) {\n\t\t\t\tmrs.sort(\n\t\t\t\t\t(a, b) =>\n\t\t\t\t\t\t(a.state === 'opened' ? -1 : 1) - (b.state === 'opened' ? -1 : 1) ||\n\t\t\t\t\t\tnew Date(b.updated_at).getTime() - new Date(a.updated_at).getTime(),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn fromGitLabMergeRequestREST(mrs[0], provider, { owner: owner, repo: repo });\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo, id) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tid: id,\n\t\t}),\n\t})\n\tasync getPullRequest(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tid: number,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\t/**\n\t\t\t * Returns `undefined` only for a `null` project or merge request, which is how GitLab's GraphQL\n\t\t\t * answers a missing one. A thrown not-found or an empty response means the endpoint is wrong, so\n\t\t\t * both throw instead of reading as absent.\n\t\t\t */\n\t\t\tstrict?: boolean;\n\t\t\tdeferFailure?: boolean;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject: {\n\t\t\t\t\tmergeRequest: GitLabMergeRequestFull | null;\n\t\t\t\t} | null;\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getMergeRequest(\n\t$fullPath: ID!\n\t$iid: String!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tmergeRequest(iid: $iid) {\n\t\t\tid,\n\t\t\tiid\n\t\t\tstate,\n\t\t\tauthor {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tavatarUrl\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tdiffRefs {\n\t\t\t\tbaseSha\n\t\t\t\theadSha\n\t\t\t}\n\t\t\ttitle\n\t\t\tdescription\n\t\t\twebUrl\n\t\t\tcreatedAt\n\t\t\tupdatedAt\n\t\t\tmergedAt\n\t\t\ttargetBranch\n\t\t\tsourceBranch\n\t\t\tproject {\n\t\t\t\tid\n\t\t\t\tfullPath\n\t\t\t\twebUrl\n\t\t\t}\n\t\t\tsourceProject {\n\t\t\t\tid\n\t\t\t\tfullPath\n\t\t\t\twebUrl\n\t\t\t}\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${owner}/${repo}`,\n\t\t\t\t\tiid: String(id),\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t\toptions?.deferFailure,\n\t\t\t);\n\n\t\t\tif (rsp?.data == null) {\n\t\t\t\tif (options?.strict) throw new Error('GitLab returned no data for the merge request');\n\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tif (rsp.data.project?.mergeRequest == null) return undefined;\n\n\t\t\tconst pr = rsp.data.project.mergeRequest;\n\t\t\treturn fromGitLabMergeRequest(pr, provider);\n\t\t} catch (ex) {\n\t\t\tif (!options?.strict && ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t/**\n\t * The iids of the merge requests into `owner/repo` whose source is `branch`, in any state, newest first, at most\n\t * `limit`: from the project itself when `headOwner` is omitted, otherwise from a fork in the `headOwner`\n\t * namespace. Only the iids, so a caller resolves the rows through the same read as its by-number lookups.\n\t *\n\t * Keyed on the source branch NAME, so a merged request whose branch was deleted still matches. Strict like\n\t * {@link getPullRequest}'s `strict`: an empty list means GitLab answered, a `null` project included; a 404 or\n\t * an empty response means the endpoint is wrong and throws. Requests from a deleted fork carry no source\n\t * project and so match nothing.\n\t */\n\t@trace({\n\t\targs: (provider, token, owner, repo, branch) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\tbranch: branch,\n\t\t}),\n\t})\n\tasync getPullRequestNumbersForBranch(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\tbranch: string,\n\t\toptions: { baseUrl?: string; headOwner?: string; limit: number; deferFailure?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<{ numbers: number[]; truncated: boolean }> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface MergeRequestHead {\n\t\t\tiid: string;\n\t\t\tupdatedAt: string;\n\t\t\tsourceBranch: string;\n\t\t\tproject: { id: string };\n\t\t\tsourceProject: { id: string; fullPath: string } | null;\n\t\t}\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tproject: {\n\t\t\t\t\tmergeRequests: {\n\t\t\t\t\t\tcount: number;\n\t\t\t\t\t\tpageInfo: { hasNextPage: boolean };\n\t\t\t\t\t\tnodes: MergeRequestHead[];\n\t\t\t\t\t} | null;\n\t\t\t\t} | null;\n\t\t\t} | null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getMergeRequestsForBranch(\n\t$fullPath: ID!\n\t$branches: [String!]\n\t$limit: Int!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tmergeRequests(sourceBranches: $branches, state: all, sort: UPDATED_DESC, first: $limit) {\n\t\t\tcount\n\t\t\tpageInfo {\n\t\t\t\thasNextPage\n\t\t\t}\n\t\t\tnodes {\n\t\t\t\tiid\n\t\t\t\tupdatedAt\n\t\t\t\tsourceBranch\n\t\t\t\tproject {\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t\tsourceProject {\n\t\t\t\t\tid\n\t\t\t\t\tfullPath\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}`;\n\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{ fullPath: `${owner}/${repo}`, branches: [branch], limit: options.limit },\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t\toptions.deferFailure,\n\t\t\t);\n\t\t\tif (rsp?.data == null) throw new Error('GitLab returned no data for the merge requests by branch');\n\n\t\t\tconst project = rsp.data.project;\n\t\t\tif (project == null) return { numbers: [], truncated: false };\n\n\t\t\tconst connection = project.mergeRequests;\n\t\t\tif (connection == null) {\n\t\t\t\tthrow new Error(`GitLab returned no merge requests for ${owner}/${repo}:${branch}`);\n\t\t\t}\n\n\t\t\tconst headOwner = options.headOwner;\n\t\t\tconst { values, truncated } = selectBranchPullRequests(connection.nodes, {\n\t\t\t\tmatchesHead: mr => {\n\t\t\t\t\tif (mr.sourceBranch !== branch || mr.sourceProject == null) return false;\n\t\t\t\t\tif (headOwner == null) return mr.sourceProject.id === mr.project.id;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\tmr.sourceProject.id !== mr.project.id &&\n\t\t\t\t\t\tequalsIgnoreCase(getRepoNamespace(mr.sourceProject.fullPath), headOwner)\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tupdatedAt: mr => Date.parse(mr.updatedAt),\n\t\t\t\tmap: mr => {\n\t\t\t\t\tconst iid = Number(mr.iid);\n\t\t\t\t\tif (!Number.isSafeInteger(iid)) throw new Error(`GitLab returned a merge request iid '${mr.iid}'`);\n\n\t\t\t\t\treturn iid;\n\t\t\t\t},\n\t\t\t\tlimit: options.limit,\n\t\t\t\tmore: connection.pageInfo.hasNextPage || connection.count > connection.nodes.length,\n\t\t\t});\n\t\t\treturn { numbers: values, truncated: truncated };\n\t\t} catch (ex) {\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({\n\t\targs: (provider, token, owner, repo) => ({\n\t\t\tprovider: provider.name,\n\t\t\ttoken: `<token:${token.microHash}>`,\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t}),\n\t})\n\tasync getRepositoryMetadata(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\towner: string,\n\t\trepo: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<RepositoryMetadata | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst projectId = await this.getProjectId(provider, token, owner, repo, options?.baseUrl, cancellation);\n\t\tif (!projectId) return undefined;\n\n\t\ttry {\n\t\t\tconst proj = await this.request<GitLabProjectREST>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\t`v4/projects/${projectId}`,\n\t\t\t\t{\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t// ...options,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\tif (proj == null) return undefined;\n\n\t\t\treturn {\n\t\t\t\tprovider: provider,\n\t\t\t\towner: proj.namespace.full_path,\n\t\t\t\tname: proj.path,\n\t\t\t\tisFork: proj.forked_from_project != null,\n\t\t\t\tparent:\n\t\t\t\t\tproj.forked_from_project != null\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\towner: proj.forked_from_project.namespace.full_path,\n\t\t\t\t\t\t\t\tname: proj.forked_from_project.path,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t} satisfies RepositoryMetadata;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\t@trace({ args: (provider, token) => ({ provider: provider.name, token: `<token:${token.microHash}>` }) })\n\tasync searchPullRequests(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\toptions?: {\n\t\t\tsearch?: string;\n\t\t\tuser?: string;\n\t\t\trepos?: string[];\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t\tinclude?: PullRequestState[];\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<PullRequest[]> {\n\t\tconst scope = getScopedLogger();\n\t\tconst search = options?.search;\n\t\tif (!search) {\n\t\t\treturn [];\n\t\t}\n\n\t\ttry {\n\t\t\tconst perPageLimit = 20; // with bigger amount we exceed the max GraphQL complexity in the next query\n\t\t\tconst include = options?.include?.length ? options.include : undefined;\n\t\t\t// GitLab's search API takes a single `state` value, so push it server-side when exactly one state is\n\t\t\t// requested; that keeps the requested state from being crowded out of the `perPageLimit` slice. For\n\t\t\t// multiple states there's no single-value qualifier, so those are filtered client-side below.\n\t\t\tlet searchPath = `v4/search/?scope=merge_requests&search=${encodeURIComponent(search)}&per_page=${perPageLimit}`;\n\t\t\tif (include?.length === 1) {\n\t\t\t\tsearchPath += `&state=${encodeURIComponent(toGitLabMergeRequestState(include[0]))}`;\n\t\t\t}\n\n\t\t\tlet restPRs: GitLabMergeRequestREST[];\n\t\t\tif (include == null) {\n\t\t\t\t// Unfiltered search returns the first page as-is (as it did before state filtering existed).\n\t\t\t\trestPRs = await this.request<GitLabMergeRequestREST[]>(\n\t\t\t\t\tprovider,\n\t\t\t\t\ttoken,\n\t\t\t\t\toptions?.baseUrl,\n\t\t\t\t\tsearchPath,\n\t\t\t\t\t{ method: 'GET' },\n\t\t\t\t\tcancellation,\n\t\t\t\t\tscope,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// The search API returns MRs of all states in relevance order, so the requested state(s) may not\n\t\t\t\t// appear on the first page. Server-side `&state=` narrows the single-state case when honored, but it\n\t\t\t\t// can't express multiple states, so page through the results and accumulate matches until we fill the\n\t\t\t\t// detail-query cap (`perPageLimit`) or exhaust the search results. This keeps correctness whether\n\t\t\t\t// or not `&state=` takes effect. Bounded by `maxSearchPages` like the other paged provider drains in\n\t\t\t\t// this package so a large, low-match result set can't fan out into an unbounded request loop.\n\t\t\t\tconst maxSearchPages = 20;\n\t\t\t\tconst matches: GitLabMergeRequestREST[] = [];\n\t\t\t\tfor (let page = 1; page <= maxSearchPages; page++) {\n\t\t\t\t\tconst pagePRs = await this.request<GitLabMergeRequestREST[]>(\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\toptions?.baseUrl,\n\t\t\t\t\t\t`${searchPath}&page=${page}`,\n\t\t\t\t\t\t{ method: 'GET' },\n\t\t\t\t\t\tcancellation,\n\t\t\t\t\t\tscope,\n\t\t\t\t\t);\n\t\t\t\t\tfor (const pr of pagePRs) {\n\t\t\t\t\t\tif (include.includes(fromGitLabMergeRequestState(pr.state))) {\n\t\t\t\t\t\t\tmatches.push(pr);\n\t\t\t\t\t\t\tif (matches.length >= perPageLimit) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Stop once we've filled the cap or hit the last (partial or empty) page.\n\t\t\t\t\tif (matches.length >= perPageLimit || pagePRs.length < perPageLimit) break;\n\t\t\t\t}\n\t\t\t\trestPRs = matches;\n\t\t\t}\n\t\t\tif (restPRs.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tinterface QueryResult {\n\t\t\t\tdata: Record<`mergeRequest_${number}`, GitLabMergeRequestFull>;\n\t\t\t}\n\n\t\t\tconst queryArgs = restPRs.map((_, i) => `$id_${i}: MergeRequestID!`).join('\\n');\n\t\t\tconst queryFields = restPRs\n\t\t\t\t.map((_, i) => `mergeRequest_${i}: mergeRequest(id: $id_${i}) { ...mergeRequestFields }`)\n\t\t\t\t.join('\\n');\n\t\t\t// Set of fields includes only additional fields that are not included in GitLabMergeRequestREST.\n\t\t\t// It's limited as much as possible to reduce complexity of the query.\n\t\t\tconst queryMrFields = `fragment mergeRequestFields on MergeRequest {\n\t\t\t\tdiffRefs {\n\t\t\t\t\tbaseSha\n\t\t\t\t\theadSha\n\t\t\t\t}\n\t\t\t\tproject {\n\t\t\t\t\tid\n\t\t\t\t\tfullPath\n\t\t\t\t\twebUrl\n\t\t\t\t}\n\t\t\t\tsourceProject {\n\t\t\t\t\tid\n\t\t\t\t\tfullPath\n\t\t\t\t\twebUrl\n\t\t\t\t}\n\t\t\t}`;\n\t\t\tconst query = `query getMergeRequests (${queryArgs}) {${queryFields}} ${queryMrFields}`;\n\n\t\t\tconst params = restPRs.reduce<Record<`id_${number}`, string>>((ids, gitlabRestPr, i) => {\n\t\t\t\tids[`id_${i}`] = `${gitlabMergeRequestIdPrefix}${gitlabRestPr.id}`;\n\t\t\t\treturn ids;\n\t\t\t}, {});\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\tparams,\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\t\t\tif (rsp?.data != null) {\n\t\t\t\tconst resultPRs = restPRs.reduce<PullRequest[]>((accum, restPR, i) => {\n\t\t\t\t\tconst graphQlPR = rsp.data[`mergeRequest_${i}`];\n\t\t\t\t\tif (graphQlPR == null) {\n\t\t\t\t\t\treturn accum;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fullPr: GitLabMergeRequestFull = {\n\t\t\t\t\t\t...graphQlPR,\n\t\t\t\t\t\tiid: String(restPR.iid),\n\t\t\t\t\t\tid: String(restPR.id),\n\t\t\t\t\t\tstate: restPR.state,\n\t\t\t\t\t\t// An absent REST author stays absent (`null`, as GitLab's own shape expresses it) rather than a\n\t\t\t\t\t\t// synthesized `'Unknown'` stub: `fromGitLabMergeRequest` collapses `null` to an absent\n\t\t\t\t\t\t// `PullRequestMember.name`, whereas a placeholder here would launder into a real-looking name.\n\t\t\t\t\t\tauthor:\n\t\t\t\t\t\t\trestPR.author != null\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tid: buildGitLabUserId(restPR.author.id) ?? '',\n\t\t\t\t\t\t\t\t\t\tname: restPR.author.name,\n\t\t\t\t\t\t\t\t\t\tavatarUrl: restPR.author.avatar_url ?? null,\n\t\t\t\t\t\t\t\t\t\twebUrl: restPR.author.web_url,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\ttitle: restPR.title,\n\t\t\t\t\t\tdescription: restPR.description,\n\t\t\t\t\t\twebUrl: restPR.web_url,\n\t\t\t\t\t\tcreatedAt: restPR.created_at,\n\t\t\t\t\t\tupdatedAt: restPR.updated_at,\n\t\t\t\t\t\tmergedAt: restPR.merged_at,\n\t\t\t\t\t\tsourceBranch: restPR.source_branch,\n\t\t\t\t\t\ttargetBranch: restPR.target_branch,\n\t\t\t\t\t};\n\t\t\t\t\taccum.push(fromGitLabMergeRequest(fullPr, provider));\n\t\t\t\t\treturn accum;\n\t\t\t\t}, []);\n\t\t\t\treturn resultPRs;\n\t\t\t}\n\t\t\treturn [];\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return [];\n\n\t\t\tthrow this.handleException(ex, provider, scope);\n\t\t}\n\t}\n\n\tprivate async findUser(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tsearch: string,\n\t\toptions?: {\n\t\t\tbaseUrl?: string;\n\t\t\tavatarSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitLabUser[]> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: {\n\t\t\t\tusers: {\n\t\t\t\t\tnodes: {\n\t\t\t\t\t\tid: string;\n\t\t\t\t\t\tname: string;\n\t\t\t\t\t\tusername: string;\n\t\t\t\t\t\tpublicEmail?: string;\n\t\t\t\t\t\tstate: string;\n\t\t\t\t\t\tavatarUrl: string;\n\t\t\t\t\t\twebUrl: string;\n\t\t\t\t\t}[];\n\t\t\t\t};\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query findUser(\n$search: String!\n) {\n\tusers(search: $search) {\n\t\tnodes {\n\t\t\tid\n\t\t\tname\n\t\t\tusername,\n\t\t\tpublicEmail,\n\t\t\tstate\n\t\t\tavatarUrl\n\t\t\twebUrl\n\t\t}\n\t}\n}`;\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\toptions?.baseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tsearch: search,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tconst matches = rsp?.data?.users?.nodes;\n\t\t\tif (matches == null || matches.length === 0) return [];\n\n\t\t\tconst users: GitLabUser[] = [];\n\n\t\t\tfor (const user of matches) {\n\t\t\t\tconst match = /gid:\\/\\/gitlab\\/User\\/([0-9]+)\\b/.exec(user.id);\n\t\t\t\tif (match == null) continue;\n\n\t\t\t\tusers.push({\n\t\t\t\t\tid: parseInt(match[1], 10),\n\t\t\t\t\tname: user.name,\n\t\t\t\t\tusername: user.username,\n\t\t\t\t\tpublicEmail: user.publicEmail || undefined,\n\t\t\t\t\tstate: user.state,\n\t\t\t\t\tavatarUrl: user.avatarUrl,\n\t\t\t\t\twebUrl: user.webUrl,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn users;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return [];\n\n\t\t\tthis.handleException(ex, provider, scope);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tgetProjectId(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tgroup: string,\n\t\trepo: string,\n\t\tbaseUrl: string | undefined,\n\t\tcancellation: AbortSignal | undefined,\n\t): Promise<string | undefined> {\n\t\tconst { accessToken } = token;\n\t\tconst key = `${accessToken}|${group}/${repo}`;\n\n\t\tlet projectId = this._projectIds.get(key);\n\t\tif (projectId == null) {\n\t\t\tprojectId = this.getProjectIdCore(provider, token, group, repo, baseUrl, cancellation);\n\t\t\tthis._projectIds.set(key, projectId);\n\t\t}\n\n\t\treturn projectId;\n\t}\n\n\tprivate async getProjectIdCore(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tgroup: string,\n\t\trepo: string,\n\t\tbaseUrl: string | undefined,\n\t\tcancellation: AbortSignal | undefined,\n\t): Promise<string | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\tinterface QueryResult {\n\t\t\tdata: { project: { id: string } };\n\t\t}\n\n\t\ttry {\n\t\t\tconst query = `query getProjectId(\n\t$fullPath: ID!\n) {\n\tproject(fullPath: $fullPath) {\n\t\tid\n\t}\n}`;\n\t\t\tconst rsp = await this.graphql<QueryResult>(\n\t\t\t\tprovider,\n\t\t\t\ttoken,\n\t\t\t\tbaseUrl,\n\t\t\t\tquery,\n\t\t\t\t{\n\t\t\t\t\tfullPath: `${group}/${repo}`,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t\tscope,\n\t\t\t);\n\n\t\t\tconst gid = rsp?.data?.project?.id;\n\t\t\tif (gid == null) return undefined;\n\n\t\t\tconst match = /gid:\\/\\/gitlab\\/Project\\/([0-9]+)\\b/.exec(gid);\n\t\t\tif (match == null) return undefined;\n\n\t\t\tconst projectId = match[1];\n\n\t\t\tscope?.addExitInfo(`projectId=${projectId}`);\n\t\t\treturn projectId;\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof RequestNotFoundError) return undefined;\n\n\t\t\tthis.handleException(ex, provider, scope);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate async graphql<T extends object>(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tbaseUrl: string | undefined,\n\t\tquery: string,\n\t\tvariables: Record<string, any>,\n\t\tcancellation: AbortSignal | undefined,\n\t\tscope: ScopedLogger | undefined,\n\t\tdeferFailure?: boolean,\n\t): Promise<T | undefined> {\n\t\tconst { accessToken } = token;\n\t\tlet rsp: Response;\n\t\ttry {\n\t\t\tconst sw = maybeStopWatch(`[GITLAB] POST ${baseUrl}`, { log: { onlyExit: true } });\n\n\t\t\ttry {\n\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\trsp = await this.config.wrapForForcedInsecureSSL(provider.getIgnoreSSLErrors(), () =>\n\t\t\t\t\tthis.config.fetch(`${baseUrl ?? 'https://gitlab.com/api'}/graphql`, {\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\theaders: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },\n\t\t\t\t\t\tsignal: cancellation,\n\t\t\t\t\t\tbody: JSON.stringify({ query: query, variables: variables }),\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tif (rsp.ok) {\n\t\t\t\t\tconst data = (await rsp.json()) as T | { errors: { message: string }[] };\n\n\t\t\t\t\tif ('errors' in data) throw new ProviderFetchError('GitLab', rsp, data.errors);\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Reads the body so the 403 branch below can tell a throttled request from a permission failure.\n\t\t\t\tthrow await ProviderFetchError.fromResponse('GitLab', rsp);\n\t\t\t} finally {\n\t\t\t\tconst match = /(^[^({\\n]+)/.exec(query);\n\t\t\t\tconst message = ` ${match?.[1].trim() ?? query}`;\n\n\t\t\t\tsw?.stop({ message: message });\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof ProviderFetchError || ex.name === 'AbortError') {\n\t\t\t\tthis.handleRequestError(provider, token, ex, scope, deferFailure);\n\t\t\t} else if (Logger.isDebugging) {\n\t\t\t\tthis.config.onError?.(`GitLab request failed: ${ex.message}`);\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate async request<T>(\n\t\tprovider: Provider,\n\t\ttoken: TokenWithInfo,\n\t\tbaseUrl: string | undefined,\n\t\troute: string,\n\t\toptions: { method: RequestInit['method'] } & Record<string, unknown>,\n\t\tcancellation: AbortSignal | undefined,\n\t\tscope: ScopedLogger | undefined,\n\t): Promise<T> {\n\t\tconst { accessToken } = token;\n\t\tconst url = `${baseUrl ?? 'https://gitlab.com/api'}/${route}`;\n\n\t\tlet rsp: Response;\n\t\ttry {\n\t\t\tconst sw = maybeStopWatch(`[GITLAB] ${options?.method ?? 'GET'} ${url}`, { log: { onlyExit: true } });\n\n\t\t\ttry {\n\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\trsp = await this.config.wrapForForcedInsecureSSL(provider.getIgnoreSSLErrors(), () =>\n\t\t\t\t\tthis.config.fetch(url, {\n\t\t\t\t\t\theaders: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },\n\t\t\t\t\t\tsignal: cancellation,\n\t\t\t\t\t\t...options,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tif (rsp.ok) {\n\t\t\t\t\treturn (await rsp.json()) as T;\n\t\t\t\t}\n\n\t\t\t\t// Reads the body so the 403 branch below can tell a throttled request from a permission failure.\n\t\t\t\tthrow await ProviderFetchError.fromResponse('GitLab', rsp);\n\t\t\t} finally {\n\t\t\t\tsw?.stop();\n\t\t\t}\n\t\t} catch (ex) {\n\t\t\tif (ex instanceof ProviderFetchError || ex.name === 'AbortError') {\n\t\t\t\tthis.handleRequestError(provider, token, ex, scope, undefined);\n\t\t\t} else if (Logger.isDebugging) {\n\t\t\t\tthis.config.onError?.(`GitLab request failed: ${ex.message}`);\n\t\t\t}\n\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\tprivate handleRequestError(\n\t\tprovider: Provider | undefined,\n\t\ttoken: TokenWithInfo,\n\t\tex: ProviderFetchError | (Error & { name: 'AbortError' }),\n\t\tscope: ScopedLogger | undefined,\n\t\tdeferFailure: boolean | undefined,\n\t): void {\n\t\tif (ex.name === 'AbortError' || !(ex instanceof ProviderFetchError)) throw new CancellationError(ex);\n\n\t\tconst { accessToken, ...tokenInfo } = token;\n\t\tswitch (ex.status) {\n\t\t\tcase 404: // Not found\n\t\t\tcase 410: // Gone\n\t\t\tcase 422: // Unprocessable Entity\n\t\t\t\tthrow new RequestNotFoundError(ex);\n\t\t\tcase 429: // Too Many Requests\n\t\t\t\tthrow toRateLimitError(ex, accessToken);\n\t\t\tcase 401: // Unauthorized\n\t\t\t\tthrow new AuthenticationError(tokenInfo, AuthenticationErrorReason.Unauthorized, ex);\n\t\t\tcase 403: // Forbidden\n\t\t\t\t// GitLab returns 403 for both a permission failure and a throttled request, so the message is the\n\t\t\t\t// discriminant (see `isRateLimitResponse`, shared with Bitbucket/Azure).\n\t\t\t\tif (isRateLimitResponse(ex)) throw toRateLimitError(ex, accessToken);\n\n\t\t\t\tthrow new AuthenticationError(tokenInfo, AuthenticationErrorReason.Forbidden, ex);\n\t\t\tcase 500: // Internal Server Error\n\t\t\t\tscope?.error(ex);\n\t\t\t\tif (ex.response != null) {\n\t\t\t\t\treportRequestFailure(\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\tex,\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\tthis.config.onRequestFailed?.(\n\t\t\t\t\t\t\t\tprovider == null || provider.id === 'gitlab'\n\t\t\t\t\t\t\t\t\t? l10n.t(\n\t\t\t\t\t\t\t\t\t\t\t'{0} failed to respond and might be experiencing issues. Please visit the [GitLab status page](https://status.gitlab.com) for more information.',\n\t\t\t\t\t\t\t\t\t\t\tprovider?.name ?? 'GitLab',\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: l10n.t('{0} failed to respond and might be experiencing issues.', provider.name),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\tdeferFailure,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase 502: // Bad Gateway\n\t\t\t\tscope?.error(ex);\n\t\t\t\t// GitHub seems to return this status code for timeouts\n\t\t\t\tif (ex.message.includes('timeout')) {\n\t\t\t\t\treportRequestFailure(\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\tex,\n\t\t\t\t\t\t() => this.config.onRequestTimedOut?.(provider?.name ?? 'GitLab'),\n\t\t\t\t\t\tdeferFailure,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (ex.status >= 400 && ex.status < 500) throw new RequestClientError(ex);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tscope?.error(ex);\n\t\tif (Logger.isDebugging) {\n\t\t\tthis.config.onError?.(`GitLab request failed: ${(ex.response as any)?.errors?.[0]?.message ?? ex.message}`);\n\t\t}\n\t}\n\n\tprivate handleException(ex: Error, provider: Provider, scope: ScopedLogger | undefined): Error {\n\t\tscope?.error(ex);\n\t\t// debugger;\n\n\t\tif (ex instanceof AuthenticationError) {\n\t\t\tvoid this.showAuthenticationErrorMessage(ex, provider);\n\t\t}\n\t\treturn ex;\n\t}\n\n\tprivate async showAuthenticationErrorMessage(ex: AuthenticationError, provider: Provider) {\n\t\tif (ex.reason === AuthenticationErrorReason.Unauthorized || ex.reason === AuthenticationErrorReason.Forbidden) {\n\t\t\tconst reauthenticate = await this.config.onReauthenticationRequired?.(\n\t\t\t\tex.reason === AuthenticationErrorReason.Forbidden\n\t\t\t\t\t? l10n.t('{0}. Would you like to try reauthenticating to provide additional access?', ex.message)\n\t\t\t\t\t: l10n.t('{0}. Would you like to try reauthenticating?', ex.message),\n\t\t\t);\n\n\t\t\tif (reauthenticate) {\n\t\t\t\tawait provider.reauthenticate();\n\t\t\t\tthis.resetCaches();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.config.onError?.(ex.message);\n\t\t}\n\t}\n}\n\n/** Wires a {@link GitLabApi} from the full runtime context, mapping `ctx` down to the narrow config. */\nexport function createGitLabApi(ctx: IntegrationServiceContext): GitLabApi {\n\tconst config: ProviderApiConfig = {\n\t\t...baseProviderApiConfig(ctx),\n\t\t// Self-hosted GitLab keys its API base off `remotes`, so reset on both HTTP proxy and remotes changes.\n\t\tonConfigChanged: listener =>\n\t\t\tctx.config.onDidChange(e => {\n\t\t\t\tif (e.httpProxy || e.remotes) {\n\t\t\t\t\tlistener();\n\t\t\t\t}\n\t\t\t}),\n\t\tonReauthenticationRequired: message =>\n\t\t\tctx.hooks?.onReauthenticationRequired?.(message) ?? Promise.resolve(false),\n\t\tonRequestTimedOut: providerName => ctx.hooks?.ui?.onRequestTimedOut?.(providerName),\n\t};\n\n\treturn new GitLabApi(config);\n}\n"],"mappings":"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"}
|
|
@@ -136,5 +136,6 @@ export interface GitLabProjectREST {
|
|
|
136
136
|
}
|
|
137
137
|
export declare function fromGitLabMergeRequestProvidersApi(pr: ProviderPullRequest, provider: Integration): PullRequest;
|
|
138
138
|
export declare function fromGitLabMergeRequest(pr: GitLabMergeRequestFull, provider: Provider): PullRequest;
|
|
139
|
+
export declare function getRepoNamespace(projectFullPath: string): string;
|
|
139
140
|
//#endregion
|
|
140
141
|
//# sourceMappingURL=models.d.ts.map
|
|
@@ -79,6 +79,6 @@ function getRepoNamespace(projectFullPath) {
|
|
|
79
79
|
return projectFullPath.split("/").slice(0, -1).join("/");
|
|
80
80
|
}
|
|
81
81
|
//#endregion
|
|
82
|
-
export { fromGitLabMergeRequest, fromGitLabMergeRequestProvidersApi, fromGitLabMergeRequestREST, fromGitLabMergeRequestState, toGitLabMergeRequestState };
|
|
82
|
+
export { fromGitLabMergeRequest, fromGitLabMergeRequestProvidersApi, fromGitLabMergeRequestREST, fromGitLabMergeRequestState, getRepoNamespace, toGitLabMergeRequestState };
|
|
83
83
|
|
|
84
84
|
//# sourceMappingURL=models.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","names":[],"sources":["../../../../../../plus/integrations/src/providers/gitlab/models.ts"],"sourcesContent":["import type { PullRequestRefs, PullRequestState } from '@gitlens/git/models/pullRequest.js';\nimport { PullRequest, PullRequestMergeableState } from '@gitlens/git/models/pullRequest.js';\nimport type { Provider } from '@gitlens/git/models/remoteProvider.js';\nimport type { Integration } from '../../models/integration.js';\nimport type { ProviderPullRequest } from '../models.js';\nimport { fromProviderPullRequest } from '../models.js';\n\nexport interface GitLabUser {\n\tid: number;\n\tname: string;\n\tusername: string;\n\tpublicEmail: string | undefined;\n\tstate: string;\n\tavatarUrl: string | undefined;\n\twebUrl: string;\n}\n\n/** A user's SSH key as returned by `GET /users/:id/keys`. */\nexport interface GitLabSshKey {\n\tid: number;\n\ttitle: string;\n\tkey: string;\n\tcreated_at: string;\n\texpires_at: string | null;\n\t/** Whether the key can be used for authentication, signing, or both. */\n\tusage_type: 'auth' | 'signing' | 'auth_and_signing';\n}\n\nexport interface GitLabCommit {\n\tid: string;\n\tshort_id: string;\n\tcreated_at: Date;\n\tparent_ids: string[];\n\ttitle: string;\n\tmessage: string;\n\tauthor_name: string;\n\tauthor_email: string;\n\tauthored_date: Date;\n\tcommitter_name: string;\n\tcommitter_email: string;\n\tcommitted_date: Date;\n\tstatus: string;\n\tproject_id: number;\n}\n\nexport interface GitLabIssue {\n\tiid: string;\n\tauthor: {\n\t\tname: string;\n\t\tavatarUrl: string | null;\n\t\twebUrl: string;\n\t} | null;\n\ttitle: string;\n\tdescription: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tclosedAt: string;\n\twebUrl: string;\n\tstate: 'opened' | 'closed' | 'locked';\n}\n\nexport interface GitLabMergeRequest {\n\tiid: string;\n\tauthor: {\n\t\tid: string;\n\t\tname: string;\n\t\tavatarUrl: string | null;\n\t\twebUrl: string;\n\t} | null;\n\ttitle: string;\n\tdescription: string | null;\n\tstate: GitLabMergeRequestState;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tmergedAt: string | null;\n\twebUrl: string;\n}\n\nexport interface GitLabRepositoryStub {\n\tid: string;\n\tfullPath: string;\n\twebUrl: string;\n}\n\nexport interface GitLabMergeRequestFull extends GitLabMergeRequest {\n\tid: string;\n\ttargetBranch: string;\n\tsourceBranch: string;\n\tdiffRefs: {\n\t\tbaseSha: string | null;\n\t\theadSha: string;\n\t} | null;\n\tproject: GitLabRepositoryStub;\n\tsourceProject: GitLabRepositoryStub | null;\n}\n\nexport type GitLabMergeRequestState = 'opened' | 'closed' | 'locked' | 'merged';\n\nexport function fromGitLabMergeRequestState(state: GitLabMergeRequestState): PullRequestState {\n\treturn state === 'locked' ? 'closed' : state;\n}\n\nexport function toGitLabMergeRequestState(state: PullRequestState): GitLabMergeRequestState {\n\treturn state;\n}\n\nexport interface GitLabMergeRequestREST {\n\tid: number;\n\tiid: number;\n\tauthor: {\n\t\tid: string;\n\t\tname: string;\n\t\tavatar_url?: string;\n\t\tweb_url: string;\n\t} | null;\n\ttitle: string;\n\tdescription: string;\n\tstate: GitLabMergeRequestState;\n\tcreated_at: string;\n\tupdated_at: string;\n\tclosed_at: string | null;\n\tmerged_at: string | null;\n\tdiff_refs: {\n\t\tbase_sha: string;\n\t\thead_sha: string;\n\t\tstart_sha: string;\n\t};\n\tsource_branch: string;\n\tsource_project_id: number;\n\ttarget_branch: string;\n\ttarget_project_id: number;\n\tweb_url: string;\n}\n\nexport function fromGitLabMergeRequestREST(\n\tpr: GitLabMergeRequestREST,\n\tprovider: Provider,\n\trepo: { owner: string; repo: string },\n): PullRequest {\n\treturn new PullRequest(\n\t\tprovider,\n\t\t{\n\t\t\tid: pr.author?.id ?? '',\n\t\t\t// An absent author stays absent — no invented `'Unknown'` name, no `''` url/avatar. See\n\t\t\t// `PullRequestMember.name`.\n\t\t\tname: pr.author?.name ?? undefined,\n\t\t\tavatarUrl: pr.author?.avatar_url ?? undefined,\n\t\t\turl: pr.author?.web_url ?? undefined,\n\t\t},\n\t\tString(pr.iid),\n\t\tundefined,\n\t\tpr.title,\n\t\tpr.web_url,\n\t\trepo,\n\t\tfromGitLabMergeRequestState(pr.state),\n\t\tnew Date(pr.created_at),\n\t\tnew Date(pr.updated_at),\n\t\tpr.closed_at == null ? undefined : new Date(pr.closed_at),\n\t\tpr.merged_at == null ? undefined : new Date(pr.merged_at),\n\t);\n}\n\nexport interface GitLabProjectREST {\n\tnamespace: {\n\t\tpath: string;\n\t\tfull_path: string;\n\t};\n\tpath: string;\n\n\tforked_from_project?: {\n\t\tnamespace: {\n\t\t\tpath: string;\n\t\t\tfull_path: string;\n\t\t};\n\t\tpath: string;\n\t};\n}\n\nexport function fromGitLabMergeRequestProvidersApi(pr: ProviderPullRequest, provider: Integration): PullRequest {\n\tconst wrappedPr: ProviderPullRequest = {\n\t\t...pr,\n\t\t// @gitkraken/providers-api returns global ID as id, while allover GitLens we use internal ID (iid) that is returned as `number`:\n\t\tid: String(pr.number),\n\t\t// Substitute some defaults that are needed to enable PRs because @gitkraken/providers-api always returns null here:\n\t\t// Discussed: https://github.com/gitkraken/provider-apis-package-js/blob/6ee521eb6b46bbb759d9c68646979c3b25681d90/src/providers/gitlab/gitlab.ts#L597\n\t\tpermissions: pr.permissions ?? {\n\t\t\tcanMerge: true,\n\t\t\tcanMergeAndBypassProtections: false,\n\t\t},\n\t};\n\treturn fromProviderPullRequest(wrappedPr, provider);\n}\n\nexport function fromGitLabMergeRequest(pr: GitLabMergeRequestFull, provider: Provider): PullRequest {\n\tlet avatarUrl: string | undefined;\n\ttry {\n\t\tavatarUrl = new URL(pr.author?.avatarUrl ?? '').toString();\n\t} catch {\n\t\ttry {\n\t\t\tconst authorUrl = new URL(pr.author?.webUrl ?? '');\n\t\t\tauthorUrl.pathname = '';\n\t\t\tauthorUrl.search = '';\n\t\t\tauthorUrl.hash = '';\n\t\t\tavatarUrl = pr.author?.avatarUrl ? authorUrl.toString() + pr.author?.avatarUrl : undefined;\n\t\t} catch {\n\t\t\tavatarUrl = undefined;\n\t\t}\n\t}\n\tconst [owner, repo] = pr.project.fullPath.split('/');\n\n\treturn new PullRequest(\n\t\tprovider,\n\t\t{\n\t\t\t// author\n\t\t\tid: pr.author?.id ?? '',\n\t\t\t// An absent author stays absent — no invented `'Unknown'` name, no `''` url. See `PullRequestMember.name`.\n\t\t\tname: pr.author?.name ?? undefined,\n\t\t\tavatarUrl: avatarUrl,\n\t\t\turl: pr.author?.webUrl ?? undefined,\n\t\t},\n\t\tpr.iid, // id\n\t\tpr.id, // nodeId\n\t\tpr.title,\n\t\tpr.webUrl || '',\n\t\t{\n\t\t\t// IssueRepository\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\turl: pr.project.webUrl,\n\t\t},\n\t\tfromGitLabMergeRequestState(pr.state), // PullRequestState\n\t\tnew Date(pr.createdAt),\n\t\tnew Date(pr.updatedAt),\n\t\t// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL\n\t\tpr.state !== 'closed' ? undefined : new Date(pr.updatedAt),\n\t\tpr.mergedAt == null ? undefined : new Date(pr.mergedAt),\n\t\tPullRequestMergeableState.Unknown,\n\t\tundefined, // viewerCanUpdate\n\t\tfromGitLabMergeRequestRefs(pr), // PullRequestRefs\n\t);\n}\n\nfunction fromGitLabMergeRequestRefs(pr: GitLabMergeRequestFull): PullRequestRefs | undefined {\n\tif (pr.sourceProject == null) {\n\t\treturn undefined;\n\t}\n\t// GitLab terminology: sourceBranch = branch with changes (head), targetBranch = merge target (base)\n\treturn {\n\t\thead: {\n\t\t\towner: getRepoNamespace(pr.sourceProject.fullPath),\n\t\t\tbranch: pr.sourceBranch,\n\t\t\texists: true,\n\t\t\turl: pr.sourceProject.webUrl,\n\t\t\trepo: pr.sourceProject.fullPath,\n\t\t\tsha: pr.diffRefs?.headSha || '',\n\t\t},\n\t\tbase: {\n\t\t\towner: getRepoNamespace(pr.project.fullPath),\n\t\t\tbranch: pr.targetBranch,\n\t\t\texists: true,\n\t\t\turl: pr.project.webUrl,\n\t\t\trepo: pr.project.fullPath,\n\t\t\tsha: pr.diffRefs?.baseSha || '',\n\t\t},\n\t\tisCrossRepository: pr.sourceProject.id !== pr.project.id,\n\t};\n}\n\
|
|
1
|
+
{"version":3,"file":"models.js","names":[],"sources":["../../../../../../plus/integrations/src/providers/gitlab/models.ts"],"sourcesContent":["import type { PullRequestRefs, PullRequestState } from '@gitlens/git/models/pullRequest.js';\nimport { PullRequest, PullRequestMergeableState } from '@gitlens/git/models/pullRequest.js';\nimport type { Provider } from '@gitlens/git/models/remoteProvider.js';\nimport type { Integration } from '../../models/integration.js';\nimport type { ProviderPullRequest } from '../models.js';\nimport { fromProviderPullRequest } from '../models.js';\n\nexport interface GitLabUser {\n\tid: number;\n\tname: string;\n\tusername: string;\n\tpublicEmail: string | undefined;\n\tstate: string;\n\tavatarUrl: string | undefined;\n\twebUrl: string;\n}\n\n/** A user's SSH key as returned by `GET /users/:id/keys`. */\nexport interface GitLabSshKey {\n\tid: number;\n\ttitle: string;\n\tkey: string;\n\tcreated_at: string;\n\texpires_at: string | null;\n\t/** Whether the key can be used for authentication, signing, or both. */\n\tusage_type: 'auth' | 'signing' | 'auth_and_signing';\n}\n\nexport interface GitLabCommit {\n\tid: string;\n\tshort_id: string;\n\tcreated_at: Date;\n\tparent_ids: string[];\n\ttitle: string;\n\tmessage: string;\n\tauthor_name: string;\n\tauthor_email: string;\n\tauthored_date: Date;\n\tcommitter_name: string;\n\tcommitter_email: string;\n\tcommitted_date: Date;\n\tstatus: string;\n\tproject_id: number;\n}\n\nexport interface GitLabIssue {\n\tiid: string;\n\tauthor: {\n\t\tname: string;\n\t\tavatarUrl: string | null;\n\t\twebUrl: string;\n\t} | null;\n\ttitle: string;\n\tdescription: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tclosedAt: string;\n\twebUrl: string;\n\tstate: 'opened' | 'closed' | 'locked';\n}\n\nexport interface GitLabMergeRequest {\n\tiid: string;\n\tauthor: {\n\t\tid: string;\n\t\tname: string;\n\t\tavatarUrl: string | null;\n\t\twebUrl: string;\n\t} | null;\n\ttitle: string;\n\tdescription: string | null;\n\tstate: GitLabMergeRequestState;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tmergedAt: string | null;\n\twebUrl: string;\n}\n\nexport interface GitLabRepositoryStub {\n\tid: string;\n\tfullPath: string;\n\twebUrl: string;\n}\n\nexport interface GitLabMergeRequestFull extends GitLabMergeRequest {\n\tid: string;\n\ttargetBranch: string;\n\tsourceBranch: string;\n\tdiffRefs: {\n\t\tbaseSha: string | null;\n\t\theadSha: string;\n\t} | null;\n\tproject: GitLabRepositoryStub;\n\tsourceProject: GitLabRepositoryStub | null;\n}\n\nexport type GitLabMergeRequestState = 'opened' | 'closed' | 'locked' | 'merged';\n\nexport function fromGitLabMergeRequestState(state: GitLabMergeRequestState): PullRequestState {\n\treturn state === 'locked' ? 'closed' : state;\n}\n\nexport function toGitLabMergeRequestState(state: PullRequestState): GitLabMergeRequestState {\n\treturn state;\n}\n\nexport interface GitLabMergeRequestREST {\n\tid: number;\n\tiid: number;\n\tauthor: {\n\t\tid: string;\n\t\tname: string;\n\t\tavatar_url?: string;\n\t\tweb_url: string;\n\t} | null;\n\ttitle: string;\n\tdescription: string;\n\tstate: GitLabMergeRequestState;\n\tcreated_at: string;\n\tupdated_at: string;\n\tclosed_at: string | null;\n\tmerged_at: string | null;\n\tdiff_refs: {\n\t\tbase_sha: string;\n\t\thead_sha: string;\n\t\tstart_sha: string;\n\t};\n\tsource_branch: string;\n\tsource_project_id: number;\n\ttarget_branch: string;\n\ttarget_project_id: number;\n\tweb_url: string;\n}\n\nexport function fromGitLabMergeRequestREST(\n\tpr: GitLabMergeRequestREST,\n\tprovider: Provider,\n\trepo: { owner: string; repo: string },\n): PullRequest {\n\treturn new PullRequest(\n\t\tprovider,\n\t\t{\n\t\t\tid: pr.author?.id ?? '',\n\t\t\t// An absent author stays absent — no invented `'Unknown'` name, no `''` url/avatar. See\n\t\t\t// `PullRequestMember.name`.\n\t\t\tname: pr.author?.name ?? undefined,\n\t\t\tavatarUrl: pr.author?.avatar_url ?? undefined,\n\t\t\turl: pr.author?.web_url ?? undefined,\n\t\t},\n\t\tString(pr.iid),\n\t\tundefined,\n\t\tpr.title,\n\t\tpr.web_url,\n\t\trepo,\n\t\tfromGitLabMergeRequestState(pr.state),\n\t\tnew Date(pr.created_at),\n\t\tnew Date(pr.updated_at),\n\t\tpr.closed_at == null ? undefined : new Date(pr.closed_at),\n\t\tpr.merged_at == null ? undefined : new Date(pr.merged_at),\n\t);\n}\n\nexport interface GitLabProjectREST {\n\tnamespace: {\n\t\tpath: string;\n\t\tfull_path: string;\n\t};\n\tpath: string;\n\n\tforked_from_project?: {\n\t\tnamespace: {\n\t\t\tpath: string;\n\t\t\tfull_path: string;\n\t\t};\n\t\tpath: string;\n\t};\n}\n\nexport function fromGitLabMergeRequestProvidersApi(pr: ProviderPullRequest, provider: Integration): PullRequest {\n\tconst wrappedPr: ProviderPullRequest = {\n\t\t...pr,\n\t\t// @gitkraken/providers-api returns global ID as id, while allover GitLens we use internal ID (iid) that is returned as `number`:\n\t\tid: String(pr.number),\n\t\t// Substitute some defaults that are needed to enable PRs because @gitkraken/providers-api always returns null here:\n\t\t// Discussed: https://github.com/gitkraken/provider-apis-package-js/blob/6ee521eb6b46bbb759d9c68646979c3b25681d90/src/providers/gitlab/gitlab.ts#L597\n\t\tpermissions: pr.permissions ?? {\n\t\t\tcanMerge: true,\n\t\t\tcanMergeAndBypassProtections: false,\n\t\t},\n\t};\n\treturn fromProviderPullRequest(wrappedPr, provider);\n}\n\nexport function fromGitLabMergeRequest(pr: GitLabMergeRequestFull, provider: Provider): PullRequest {\n\tlet avatarUrl: string | undefined;\n\ttry {\n\t\tavatarUrl = new URL(pr.author?.avatarUrl ?? '').toString();\n\t} catch {\n\t\ttry {\n\t\t\tconst authorUrl = new URL(pr.author?.webUrl ?? '');\n\t\t\tauthorUrl.pathname = '';\n\t\t\tauthorUrl.search = '';\n\t\t\tauthorUrl.hash = '';\n\t\t\tavatarUrl = pr.author?.avatarUrl ? authorUrl.toString() + pr.author?.avatarUrl : undefined;\n\t\t} catch {\n\t\t\tavatarUrl = undefined;\n\t\t}\n\t}\n\tconst [owner, repo] = pr.project.fullPath.split('/');\n\n\treturn new PullRequest(\n\t\tprovider,\n\t\t{\n\t\t\t// author\n\t\t\tid: pr.author?.id ?? '',\n\t\t\t// An absent author stays absent — no invented `'Unknown'` name, no `''` url. See `PullRequestMember.name`.\n\t\t\tname: pr.author?.name ?? undefined,\n\t\t\tavatarUrl: avatarUrl,\n\t\t\turl: pr.author?.webUrl ?? undefined,\n\t\t},\n\t\tpr.iid, // id\n\t\tpr.id, // nodeId\n\t\tpr.title,\n\t\tpr.webUrl || '',\n\t\t{\n\t\t\t// IssueRepository\n\t\t\towner: owner,\n\t\t\trepo: repo,\n\t\t\turl: pr.project.webUrl,\n\t\t},\n\t\tfromGitLabMergeRequestState(pr.state), // PullRequestState\n\t\tnew Date(pr.createdAt),\n\t\tnew Date(pr.updatedAt),\n\t\t// TODO@eamodio this isn't right, but GitLab doesn't seem to provide a closedAt on merge requests in GraphQL\n\t\tpr.state !== 'closed' ? undefined : new Date(pr.updatedAt),\n\t\tpr.mergedAt == null ? undefined : new Date(pr.mergedAt),\n\t\tPullRequestMergeableState.Unknown,\n\t\tundefined, // viewerCanUpdate\n\t\tfromGitLabMergeRequestRefs(pr), // PullRequestRefs\n\t);\n}\n\nfunction fromGitLabMergeRequestRefs(pr: GitLabMergeRequestFull): PullRequestRefs | undefined {\n\tif (pr.sourceProject == null) {\n\t\treturn undefined;\n\t}\n\t// GitLab terminology: sourceBranch = branch with changes (head), targetBranch = merge target (base)\n\treturn {\n\t\thead: {\n\t\t\towner: getRepoNamespace(pr.sourceProject.fullPath),\n\t\t\tbranch: pr.sourceBranch,\n\t\t\texists: true,\n\t\t\turl: pr.sourceProject.webUrl,\n\t\t\trepo: pr.sourceProject.fullPath,\n\t\t\tsha: pr.diffRefs?.headSha || '',\n\t\t},\n\t\tbase: {\n\t\t\towner: getRepoNamespace(pr.project.fullPath),\n\t\t\tbranch: pr.targetBranch,\n\t\t\texists: true,\n\t\t\turl: pr.project.webUrl,\n\t\t\trepo: pr.project.fullPath,\n\t\t\tsha: pr.diffRefs?.baseSha || '',\n\t\t},\n\t\tisCrossRepository: pr.sourceProject.id !== pr.project.id,\n\t};\n}\n\nexport function getRepoNamespace(projectFullPath: string): string {\n\treturn projectFullPath.split('/').slice(0, -1).join('/');\n}\n"],"mappings":";;;AAkGA,SAAgB,4BAA4B,OAAkD;CAC7F,OAAO,UAAU,WAAW,WAAW;AACxC;AAEA,SAAgB,0BAA0B,OAAkD;CAC3F,OAAO;AACR;AA8BA,SAAgB,2BACf,IACA,UACA,MACc;CACd,OAAO,IAAI,YACV,UACA;EACC,IAAI,GAAG,QAAQ,MAAM;EAGrB,MAAM,GAAG,QAAQ,QAAQ,KAAA;EACzB,WAAW,GAAG,QAAQ,cAAc,KAAA;EACpC,KAAK,GAAG,QAAQ,WAAW,KAAA;CAC5B,GACA,OAAO,GAAG,GAAG,GACb,KAAA,GACA,GAAG,OACH,GAAG,SACH,MACA,4BAA4B,GAAG,KAAK,GACpC,IAAI,KAAK,GAAG,UAAU,GACtB,IAAI,KAAK,GAAG,UAAU,GACtB,GAAG,aAAa,OAAO,KAAA,IAAY,IAAI,KAAK,GAAG,SAAS,GACxD,GAAG,aAAa,OAAO,KAAA,IAAY,IAAI,KAAK,GAAG,SAAS,CACzD;AACD;AAkBA,SAAgB,mCAAmC,IAAyB,UAAoC;CAC/G,MAAM,YAAiC;EACtC,GAAG;EAEH,IAAI,OAAO,GAAG,MAAM;EAGpB,aAAa,GAAG,eAAe;GAC9B,UAAU;GACV,8BAA8B;EAC/B;CACD;CACA,OAAO,wBAAwB,WAAW,QAAQ;AACnD;AAEA,SAAgB,uBAAuB,IAA4B,UAAiC;CACnG,IAAI;CACJ,IAAI;EACH,YAAY,IAAI,IAAI,GAAG,QAAQ,aAAa,EAAE,CAAC,CAAC,SAAS;CAC1D,QAAQ;EACP,IAAI;GACH,MAAM,YAAY,IAAI,IAAI,GAAG,QAAQ,UAAU,EAAE;GACjD,UAAU,WAAW;GACrB,UAAU,SAAS;GACnB,UAAU,OAAO;GACjB,YAAY,GAAG,QAAQ,YAAY,UAAU,SAAS,IAAI,GAAG,QAAQ,YAAY,KAAA;EAClF,QAAQ;GACP,YAAY,KAAA;EACb;CACD;CACA,MAAM,CAAC,OAAO,QAAQ,GAAG,QAAQ,SAAS,MAAM,GAAG;CAEnD,OAAO,IAAI,YACV,UACA;EAEC,IAAI,GAAG,QAAQ,MAAM;EAErB,MAAM,GAAG,QAAQ,QAAQ,KAAA;EACd;EACX,KAAK,GAAG,QAAQ,UAAU,KAAA;CAC3B,GACA,GAAG,KACH,GAAG,IACH,GAAG,OACH,GAAG,UAAU,IACb;EAEQ;EACD;EACN,KAAK,GAAG,QAAQ;CACjB,GACA,4BAA4B,GAAG,KAAK,GACpC,IAAI,KAAK,GAAG,SAAS,GACrB,IAAI,KAAK,GAAG,SAAS,GAErB,GAAG,UAAU,WAAW,KAAA,IAAY,IAAI,KAAK,GAAG,SAAS,GACzD,GAAG,YAAY,OAAO,KAAA,IAAY,IAAI,KAAK,GAAG,QAAQ,GAAA,WAEtD,KAAA,GACA,2BAA2B,EAAE,CAC9B;AACD;AAEA,SAAS,2BAA2B,IAAyD;CAC5F,IAAI,GAAG,iBAAiB,MACvB;CAGD,OAAO;EACN,MAAM;GACL,OAAO,iBAAiB,GAAG,cAAc,QAAQ;GACjD,QAAQ,GAAG;GACX,QAAQ;GACR,KAAK,GAAG,cAAc;GACtB,MAAM,GAAG,cAAc;GACvB,KAAK,GAAG,UAAU,WAAW;EAC9B;EACA,MAAM;GACL,OAAO,iBAAiB,GAAG,QAAQ,QAAQ;GAC3C,QAAQ,GAAG;GACX,QAAQ;GACR,KAAK,GAAG,QAAQ;GAChB,MAAM,GAAG,QAAQ;GACjB,KAAK,GAAG,UAAU,WAAW;EAC9B;EACA,mBAAmB,GAAG,cAAc,OAAO,GAAG,QAAQ;CACvD;AACD;AAEA,SAAgB,iBAAiB,iBAAiC;CACjE,OAAO,gBAAgB,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,GAAG;AACxD"}
|
|
@@ -2,18 +2,18 @@ import { Emitter } from "../../../utils/event.js";
|
|
|
2
2
|
import { RepositoryDescriptor } from "../../../git/models/resourceDescriptor.js";
|
|
3
3
|
import { IssueOrPullRequest, IssueOrPullRequestState } from "../../../git/models/issueOrPullRequest.js";
|
|
4
4
|
import { Issue, IssueShape } from "../../../git/models/issue.js";
|
|
5
|
-
import { PullRequest, PullRequestFilter, PullRequestMergeMethod, PullRequestStateFilter } from "../../../git/models/pullRequest.js";
|
|
5
|
+
import { PullRequest, PullRequestFilter, PullRequestMergeMethod, PullRequestShape, PullRequestStateFilter } from "../../../git/models/pullRequest.js";
|
|
6
6
|
import { Account } from "../../../git/models/author.js";
|
|
7
7
|
import { DefaultBranch } from "../../../git/models/defaultBranch.js";
|
|
8
8
|
import { RepositoryMetadata } from "../../../git/models/repositoryMetadata.js";
|
|
9
9
|
import { PullRequestUrlIdentity } from "../../../git/utils/pullRequest.utils.js";
|
|
10
10
|
import { ProviderAuthenticationSession } from "../authentication/models.js";
|
|
11
11
|
import { GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId } from "../constants.js";
|
|
12
|
+
import { ProviderOrganization } from "../results.js";
|
|
12
13
|
import { ProvidersApi } from "./providersApi.js";
|
|
13
14
|
import { AccountWideIssuesResult, SearchMyIssuesOptions } from "../models/issueReads.js";
|
|
14
15
|
import { GitHostIntegration, SearchMyPullRequestsOptions, SearchPullRequestsOptions } from "../models/gitHostIntegration.js";
|
|
15
16
|
import "../models/integration.js";
|
|
16
|
-
import { ProviderOrganization } from "../results.js";
|
|
17
17
|
import { ProviderApiPagedResult, ProviderHierarchyResult, ProviderPullRequest, ProviderRepository } from "./models.js";
|
|
18
18
|
import { IntegrationConnectionChangeEvent } from "../integrationService.js";
|
|
19
19
|
import { IntegrationAuthenticationService } from "../authentication/integrationAuthenticationService.js";
|
|
@@ -56,6 +56,53 @@ declare abstract class GitLabIntegrationBase<ID extends GitLabIntegrationIds> ex
|
|
|
56
56
|
}): Promise<PullRequest | undefined>;
|
|
57
57
|
protected getProviderPullRequestForCommit(session: ProviderAuthenticationSession, repo: GitLabRepositoryDescriptor, rev: string): Promise<PullRequest | undefined>;
|
|
58
58
|
protected getProviderPullRequest(session: ProviderAuthenticationSession, resource: GitLabRepositoryDescriptor, id: string): Promise<PullRequest | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* One request per target, settled independently so one target's failure rejects only its own slot; through the
|
|
61
|
+
* SDK's issue read and the conversion the repo-scoped list rows take. GitLens' own GitLab client can't alias
|
|
62
|
+
* the read instead: it fails a whole document on any GraphQL error, where a batch needs per-target errors.
|
|
63
|
+
*/
|
|
64
|
+
protected getProviderIssuesBatch(session: ProviderAuthenticationSession, coordinates: readonly {
|
|
65
|
+
owner: string;
|
|
66
|
+
repo: string;
|
|
67
|
+
number: number;
|
|
68
|
+
project?: string;
|
|
69
|
+
}[], cancellation?: AbortSignal): Promise<PromiseSettledResult<IssueShape | undefined>[] | undefined>;
|
|
70
|
+
/**
|
|
71
|
+
* One request per target, settled independently so one target's failure rejects only its own slot; through
|
|
72
|
+
* the same SDK read and conversion the manager's list rows take.
|
|
73
|
+
*/
|
|
74
|
+
protected getProviderPullRequestsBatch(session: ProviderAuthenticationSession, coordinates: readonly {
|
|
75
|
+
owner: string;
|
|
76
|
+
repo: string;
|
|
77
|
+
number: number;
|
|
78
|
+
project?: string;
|
|
79
|
+
}[], options: {
|
|
80
|
+
currentAccount?: {
|
|
81
|
+
id: string;
|
|
82
|
+
username?: string;
|
|
83
|
+
};
|
|
84
|
+
} | undefined, cancellation?: AbortSignal): Promise<PromiseSettledResult<PullRequestShape | undefined>[] | undefined>;
|
|
85
|
+
/**
|
|
86
|
+
* Two steps, because provider-apis has no source-branch filter: GitLens' own GitLab client finds each branch's
|
|
87
|
+
* matching iids, one request per target, then {@link getProviderPullRequestsBatch} resolves them — so a row is
|
|
88
|
+
* the one `getPullRequestsBatch` returns for that merge request, `url` and `authoredByMe` included.
|
|
89
|
+
*/
|
|
90
|
+
protected getProviderPullRequestsForBranches(session: ProviderAuthenticationSession, targets: readonly {
|
|
91
|
+
owner: string;
|
|
92
|
+
repo: string;
|
|
93
|
+
project?: string;
|
|
94
|
+
branch: string;
|
|
95
|
+
headOwner?: string;
|
|
96
|
+
}[], options: {
|
|
97
|
+
currentAccount?: {
|
|
98
|
+
id: string;
|
|
99
|
+
username?: string;
|
|
100
|
+
};
|
|
101
|
+
limit: number;
|
|
102
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<{
|
|
103
|
+
pullRequests: PullRequestShape[];
|
|
104
|
+
truncated: boolean;
|
|
105
|
+
}>[] | undefined>;
|
|
59
106
|
getRepoInfo(repo: {
|
|
60
107
|
owner: string;
|
|
61
108
|
name: string;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { uniqueBy } from "../../../utils/iterable.js";
|
|
2
2
|
import { CancellationError } from "../../../utils/cancellation.js";
|
|
3
|
-
import { batch } from "../../../utils/promise.js";
|
|
3
|
+
import { batch, mapSettledBounded } from "../../../utils/promise.js";
|
|
4
4
|
import "../../../git/models/pullRequest.js";
|
|
5
5
|
import { IntegrationReadUnavailableError } from "../errors.js";
|
|
6
|
-
import { toCollectionScopeFailure } from "../collectionMetadata.js";
|
|
7
6
|
import "../constants.js";
|
|
7
|
+
import { toCollectionScopeFailure } from "../collectionMetadata.js";
|
|
8
8
|
import { toTokenWithInfo } from "../authentication/models.js";
|
|
9
9
|
import "../providerFilters.js";
|
|
10
|
-
import { collectProviderPagedResult, mergeCollectionMetadata } from "./utils/providerPaging.js";
|
|
11
|
-
import { ProviderPullRequestReviewState, getProviderPullRequestIdentity, providersMetadata, toIssueShape, toProviderPullRequestStates } from "./models.js";
|
|
10
|
+
import { collectProviderPagedResult, mergeCollectionMetadata, resolveBranchPullRequests } from "./utils/providerPaging.js";
|
|
11
|
+
import { ProviderPullRequestReviewState, fromProviderPullRequest, getProviderPullRequestIdentity, providersMetadata, toIssueShape, toProviderPullRequestStates } from "./models.js";
|
|
12
12
|
import { getGitLabPullRequestIdentityFromMaybeUrl, matchesGitLabOrgNamespace } from "./gitlab/gitlab.utils.js";
|
|
13
13
|
import { fromGitLabMergeRequestProvidersApi } from "./gitlab/models.js";
|
|
14
14
|
import { GitHostIntegration } from "../models/gitHostIntegration.js";
|
|
@@ -132,6 +132,82 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
132
132
|
async getProviderPullRequest(session, resource, id) {
|
|
133
133
|
return (await this.authenticationService.apis.gitlab)?.getPullRequest(this, toTokenWithInfo(this.id, session), resource.owner, resource.name, parseInt(id, 10), { baseUrl: this.apiBaseUrlFor(session) });
|
|
134
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* One request per target, settled independently so one target's failure rejects only its own slot; through the
|
|
137
|
+
* SDK's issue read and the conversion the repo-scoped list rows take. GitLens' own GitLab client can't alias
|
|
138
|
+
* the read instead: it fails a whole document on any GraphQL error, where a batch needs per-target errors.
|
|
139
|
+
*/
|
|
140
|
+
async getProviderIssuesBatch(session, coordinates, cancellation) {
|
|
141
|
+
const api = await this.getProvidersApi();
|
|
142
|
+
const tokenWithInfo = toTokenWithInfo(this.id, session);
|
|
143
|
+
const baseUrl = this.enterpriseBaseUrlFor(session);
|
|
144
|
+
const confirmBaseUrl = this.apiBaseUrlFor(session);
|
|
145
|
+
return mapSettledBounded(coordinates, 6, async (c) => {
|
|
146
|
+
const issue = await api.getIssueForRepo(tokenWithInfo, {
|
|
147
|
+
namespace: c.owner,
|
|
148
|
+
name: c.repo
|
|
149
|
+
}, c.number, {
|
|
150
|
+
isPAT: this.isEnterprise,
|
|
151
|
+
baseUrl
|
|
152
|
+
});
|
|
153
|
+
if (issue != null) {
|
|
154
|
+
const shape = toIssueShape(issue, this);
|
|
155
|
+
if (shape == null) throw new Error(`GitLab returned issue ${c.number} without a URL or update time`);
|
|
156
|
+
return shape;
|
|
157
|
+
}
|
|
158
|
+
const gitlab = await this.authenticationService.apis.gitlab;
|
|
159
|
+
if (gitlab == null) throw new IntegrationReadUnavailableError(this.name, "cannot confirm a missing issue");
|
|
160
|
+
if (await gitlab.hasIssue(this, tokenWithInfo, c.owner, c.repo, c.number, {
|
|
161
|
+
baseUrl: confirmBaseUrl,
|
|
162
|
+
deferFailure: true
|
|
163
|
+
}, cancellation)) throw new Error(`GitLab reported issue ${c.number} missing, then found it`);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* One request per target, settled independently so one target's failure rejects only its own slot; through
|
|
168
|
+
* the same SDK read and conversion the manager's list rows take.
|
|
169
|
+
*/
|
|
170
|
+
async getProviderPullRequestsBatch(session, coordinates, options, cancellation) {
|
|
171
|
+
const api = await this.getProvidersApi();
|
|
172
|
+
const tokenWithInfo = toTokenWithInfo(this.id, session);
|
|
173
|
+
const baseUrl = this.enterpriseBaseUrlFor(session);
|
|
174
|
+
const confirmBaseUrl = this.apiBaseUrlFor(session);
|
|
175
|
+
return mapSettledBounded(coordinates, 6, async (c) => {
|
|
176
|
+
const pr = await api.getPullRequestForRepo(tokenWithInfo, {
|
|
177
|
+
namespace: c.owner,
|
|
178
|
+
name: c.repo
|
|
179
|
+
}, c.number, {
|
|
180
|
+
isPAT: this.isEnterprise,
|
|
181
|
+
baseUrl
|
|
182
|
+
});
|
|
183
|
+
if (pr != null) return fromProviderPullRequest(pr, this, { currentAccount: options?.currentAccount });
|
|
184
|
+
const gitlab = await this.authenticationService.apis.gitlab;
|
|
185
|
+
if (gitlab == null) throw new IntegrationReadUnavailableError(this.name, "cannot confirm a missing merge request");
|
|
186
|
+
if (await gitlab.getPullRequest(this, tokenWithInfo, c.owner, c.repo, c.number, {
|
|
187
|
+
baseUrl: confirmBaseUrl,
|
|
188
|
+
strict: true,
|
|
189
|
+
deferFailure: true
|
|
190
|
+
}, cancellation) != null) throw new Error(`GitLab reported pull request ${c.number} missing, then found it`);
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Two steps, because provider-apis has no source-branch filter: GitLens' own GitLab client finds each branch's
|
|
195
|
+
* matching iids, one request per target, then {@link getProviderPullRequestsBatch} resolves them — so a row is
|
|
196
|
+
* the one `getPullRequestsBatch` returns for that merge request, `url` and `authoredByMe` included.
|
|
197
|
+
*/
|
|
198
|
+
async getProviderPullRequestsForBranches(session, targets, options, cancellation) {
|
|
199
|
+
const gitlab = await this.authenticationService.apis.gitlab;
|
|
200
|
+
if (gitlab == null) return void 0;
|
|
201
|
+
const tokenWithInfo = toTokenWithInfo(this.id, session);
|
|
202
|
+
const apiBaseUrl = this.apiBaseUrlFor(session);
|
|
203
|
+
const found = await mapSettledBounded(targets, 6, (t) => gitlab.getPullRequestNumbersForBranch(this, tokenWithInfo, t.owner, t.repo, t.branch, {
|
|
204
|
+
baseUrl: apiBaseUrl,
|
|
205
|
+
headOwner: t.headOwner,
|
|
206
|
+
limit: options.limit,
|
|
207
|
+
deferFailure: true
|
|
208
|
+
}, cancellation));
|
|
209
|
+
return resolveBranchPullRequests(targets, found, (coordinates) => this.getProviderPullRequestsBatch(session, coordinates, { currentAccount: options.currentAccount }, cancellation));
|
|
210
|
+
}
|
|
135
211
|
async getRepoInfo(repo) {
|
|
136
212
|
const api = await this.getProvidersApi();
|
|
137
213
|
const session = await this.resolveReadSession(repo.connectionId, void 0);
|