@gitkraken/core-gitlens 0.7.2 → 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 +41 -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 +47 -16
- 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 +2 -1
- 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/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 +58 -6
- 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/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/index.d.ts +5 -2
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +35 -9
- 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 +128 -13
- package/dist/plus/integrations/models/gitHostIntegration.js +130 -17
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +51 -3
- package/dist/plus/integrations/models/integration.js +125 -18
- 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 +40 -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 +13 -17
- 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 +54 -2
- package/dist/plus/integrations/providers/azureDevOps.js +80 -2
- 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 +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +38 -1
- package/dist/plus/integrations/providers/bitbucket-server.js +33 -1
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.d.ts +36 -1
- package/dist/plus/integrations/providers/bitbucket.js +29 -1
- package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +48 -4
- package/dist/plus/integrations/providers/github.js +101 -6
- 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 +48 -1
- package/dist/plus/integrations/providers/gitlab.js +79 -3
- 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 +3 -3
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts +12 -1
- 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 +59 -0
- package/dist/plus/integrations/providers/providersApi.js +136 -1
- 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/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 +4 -1
- package/dist/plus/integrations/reads/drains.js +7 -3
- package/dist/plus/integrations/reads/drains.js.map +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/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/sweeps.js +3 -3
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +5 -2
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/utils/env/node/exec.js +1 -1
- package/dist/utils/env/node/exec.js.map +1 -1
- package/docs/integrations.md +90 -36
- 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":"staging.js","names":["fs"],"sources":["../../../../git-cli/src/providers/staging.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport { tmpdir } from 'os';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { DisposableTemporaryGitIndex, GitStagingSubProvider } from '@gitlens/git/providers/staging.js';\nimport { countStringLength } from '@gitlens/utils/array.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { mixinAsyncDisposable } from '@gitlens/utils/disposable.js';\nimport { chunk } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { maxGitCliLength } from '../exec/git.js';\n\nexport class StagingGitSubProvider implements GitStagingSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync createTemporaryIndex(\n\t\trepoPath: string,\n\t\tfrom: 'empty' | 'current' | 'ref',\n\t\tref?: string,\n\t): Promise<DisposableTemporaryGitIndex> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Create a temporary index file\n\t\tconst tempDir = await fs.mkdtemp(joinPaths(tmpdir(), 'gl-'));\n\t\tconst tempIndex = joinPaths(tempDir, 'index');\n\n\t\tasync function dispose() {\n\t\t\t// Delete the temporary index file\n\t\t\ttry {\n\t\t\t\tawait fs.rm(tempDir, { recursive: true });\n\t\t\t} catch {\n\t\t\t\t// ignore cleanup errors\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Tell Git to use our soon to be created index file\n\t\t\tconst env = { GIT_INDEX_FILE: tempIndex };\n\n\t\t\tswitch (from) {\n\t\t\t\tcase 'empty':\n\t\t\t\t\t// Leave the temp index empty\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'current': {\n\t\t\t\t\t// Copy the current index to preserve staged state\n\t\t\t\t\tconst gitDir = await this.provider.config.getGitDir?.(repoPath);\n\t\t\t\t\tif (gitDir == null) throw new Error(l10n.t('Unable to determine git directory for {0}', repoPath));\n\n\t\t\t\t\tconst currentIndex = joinPaths(gitDir.uri.fsPath, 'index');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fs.copyFile(currentIndex, tempIndex);\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t// A repo that has never staged anything has no index file yet; git reads a missing\n\t\t\t\t\t\t// `GIT_INDEX_FILE` as an empty index, which is what 'current' means there. Any other\n\t\t\t\t\t\t// failure is real — don't silently hand back an index claiming everything is deleted.\n\t\t\t\t\t\tif ((ex as NodeJS.ErrnoException)?.code !== 'ENOENT') throw ex;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'ref': {\n\t\t\t\t\tif (ref == null) throw new Error(l10n.t(\"ref is required when from is 'ref'\"));\n\n\t\t\t\t\t// Create the temp index file from a base ref/sha\n\t\t\t\t\tconst newIndexResult = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, env: env },\n\t\t\t\t\t\t'ls-tree',\n\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t'-r',\n\t\t\t\t\t\t'--full-name',\n\t\t\t\t\t\tref,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (newIndexResult.stdout.trim()) {\n\t\t\t\t\t\t// Write the tree to our temp index\n\t\t\t\t\t\tawait this.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, env: env, stdin: newIndexResult.stdout },\n\t\t\t\t\t\t\t'update-index',\n\t\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t\t'--index-info',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mixinAsyncDisposable({ path: tempIndex, env: { GIT_INDEX_FILE: tempIndex } }, dispose);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\n\t\t\tvoid dispose();\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(pathOrUri));\n\t}\n\n\t@debug()\n\tasync stageFiles(\n\t\trepoPath: string,\n\t\tpathsOrUris: (string | Uri)[],\n\t\toptions?: { intentToAdd?: boolean; index?: DisposableTemporaryGitIndex },\n\t): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\tfor (const batch of batches) {\n\t\t\tawait this.git.run(\n\t\t\t\t{ cwd: repoPath, env: options?.index?.env },\n\t\t\t\t'add',\n\t\t\t\toptions?.intentToAdd ? '-N' : '-A',\n\t\t\t\t'--',\n\t\t\t\t...batch,\n\t\t\t);\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(directoryOrUri));\n\t}\n\n\t@debug()\n\tasync unstageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(pathOrUri));\n\t}\n\n\t@debug()\n\tasync unstageFiles(repoPath: string, pathsOrUris: (string | Uri)[]): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\tfor (const batch of batches) {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', ...batch);\n\t\t}\n\t}\n\n\t@debug()\n\tasync unstageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(directoryOrUri));\n\t}\n\n\t@debug()\n\tasync removeFile(repoPath: string, pathOrUri: string | Uri, options?: { force?: boolean }): Promise<void> {\n\t\tconst args = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--', toFsPath(pathOrUri));\n\t\tawait this.git.run({ cwd: repoPath }, ...args);\n\t}\n\n\t@debug()\n\tasync removeFiles(repoPath: string, pathsOrUris: (string | Uri)[], options?: { force?: boolean }): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\tconst args: string[] = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--');\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\tfor (const batch of batches) {\n\t\t\tawait this.git.run({ cwd: repoPath }, ...args, ...batch);\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A');\n\t}\n\n\t@debug()\n\tasync unstageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q');\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"staging.js","names":["fs"],"sources":["../../../../git-cli/src/providers/staging.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport { tmpdir } from 'os';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { DisposableTemporaryGitIndex, GitStagingSubProvider } from '@gitlens/git/providers/staging.js';\nimport { countStringLength } from '@gitlens/utils/array.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { mixinAsyncDisposable } from '@gitlens/utils/disposable.js';\nimport { chunk } from '@gitlens/utils/iterable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths } from '@gitlens/utils/path.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { maxGitCliLength } from '../exec/git.js';\n\nexport class StagingGitSubProvider implements GitStagingSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync createTemporaryIndex(\n\t\trepoPath: string,\n\t\tfrom: 'empty' | 'current' | 'ref',\n\t\tref?: string,\n\t): Promise<DisposableTemporaryGitIndex> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Create a temporary index file\n\t\tconst tempDir = await fs.mkdtemp(joinPaths(tmpdir(), 'gl-'));\n\t\tconst tempIndex = joinPaths(tempDir, 'index');\n\n\t\tasync function dispose() {\n\t\t\t// Delete the temporary index file\n\t\t\ttry {\n\t\t\t\tawait fs.rm(tempDir, { recursive: true });\n\t\t\t} catch {\n\t\t\t\t// ignore cleanup errors\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Tell Git to use our soon to be created index file\n\t\t\tconst env = { GIT_INDEX_FILE: tempIndex };\n\n\t\t\tswitch (from) {\n\t\t\t\tcase 'empty':\n\t\t\t\t\t// Leave the temp index empty\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'current': {\n\t\t\t\t\t// Copy the current index to preserve staged state\n\t\t\t\t\tconst gitDir = await this.provider.config.getGitDir?.(repoPath);\n\t\t\t\t\tif (gitDir == null) throw new Error(l10n.t('Unable to determine git directory for {0}', repoPath));\n\n\t\t\t\t\tconst currentIndex = joinPaths(gitDir.uri.fsPath, 'index');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fs.copyFile(currentIndex, tempIndex);\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t// A repo that has never staged anything has no index file yet; git reads a missing\n\t\t\t\t\t\t// `GIT_INDEX_FILE` as an empty index, which is what 'current' means there. Any other\n\t\t\t\t\t\t// failure is real — don't silently hand back an index claiming everything is deleted.\n\t\t\t\t\t\tif ((ex as NodeJS.ErrnoException)?.code !== 'ENOENT') throw ex;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'ref': {\n\t\t\t\t\tif (ref == null) throw new Error(l10n.t(\"ref is required when from is 'ref'\"));\n\n\t\t\t\t\t// Create the temp index file from a base ref/sha\n\t\t\t\t\tconst newIndexResult = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, env: env },\n\t\t\t\t\t\t'ls-tree',\n\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t'-r',\n\t\t\t\t\t\t'--full-name',\n\t\t\t\t\t\tref,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (newIndexResult.stdout.trim()) {\n\t\t\t\t\t\t// Write the tree to our temp index\n\t\t\t\t\t\tawait this.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, env: env, stdin: newIndexResult.stdout },\n\t\t\t\t\t\t\t'update-index',\n\t\t\t\t\t\t\t'-z',\n\t\t\t\t\t\t\t'--index-info',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mixinAsyncDisposable({ path: tempIndex, env: { GIT_INDEX_FILE: tempIndex } }, dispose);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\n\t\t\tvoid dispose();\n\t\t\tthrow ex;\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(pathOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync stageFiles(\n\t\trepoPath: string,\n\t\tpathsOrUris: (string | Uri)[],\n\t\toptions?: { intentToAdd?: boolean; index?: DisposableTemporaryGitIndex },\n\t): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run(\n\t\t\t\t\t{ cwd: repoPath, env: options?.index?.env },\n\t\t\t\t\t'add',\n\t\t\t\t\toptions?.intentToAdd ? '-N' : '-A',\n\t\t\t\t\t'--',\n\t\t\t\t\t...batch,\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Announced even when a later batch fails, since the earlier ones already changed the index. A\n\t\t\t// temporary index (used for partial-stage previews / diff building) is not the repository's real\n\t\t\t// index — firing repo-change hooks for it would invalidate status caches for a mutation nothing\n\t\t\t// else can observe.\n\t\t\tif (options?.index == null) {\n\t\t\t\tthis.announceIndexChanged(repoPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A', '--', toFsPath(directoryOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageFile(repoPath: string, pathOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(pathOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageFiles(repoPath: string, pathsOrUris: (string | Uri)[]): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already changed the index\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t@debug()\n\tasync unstageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q', '--', toFsPath(directoryOrUri));\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync removeFile(repoPath: string, pathOrUri: string | Uri, options?: { force?: boolean }): Promise<void> {\n\t\tconst args = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--', toFsPath(pathOrUri));\n\t\tawait this.git.run({ cwd: repoPath }, ...args);\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync removeFiles(repoPath: string, pathsOrUris: (string | Uri)[], options?: { force?: boolean }): Promise<void> {\n\t\tconst paths = pathsOrUris.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\tconst args: string[] = ['rm'];\n\t\tif (options?.force) {\n\t\t\targs.push('-f');\n\t\t}\n\t\targs.push('--');\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process files in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath }, ...args, ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already changed the index\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t@debug()\n\tasync stageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'add', '-A');\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync unstageAll(repoPath: string): Promise<void> {\n\t\tawait this.git.run({ cwd: repoPath }, 'reset', '-q');\n\t\tthis.announceIndexChanged(repoPath);\n\t}\n\n\t@debug()\n\tasync clean(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tpaths?: (string | Uri)[];\n\t\t\tdirectories?: boolean;\n\t\t\tforce?: boolean;\n\t\t\tignored?: boolean;\n\t\t},\n\t): Promise<void> {\n\t\tconst args = ['clean'];\n\t\tif (options?.force ?? true) {\n\t\t\targs.push('-f');\n\t\t}\n\t\tif (options?.directories) {\n\t\t\targs.push('-d');\n\t\t}\n\t\tif (options?.ignored) {\n\t\t\targs.push('-x');\n\t\t}\n\n\t\tif (options?.paths == null) {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...args);\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t\treturn;\n\t\t}\n\n\t\tconst paths = options.paths.map(toFsPath);\n\t\tif (!paths.length) return;\n\n\t\t// Calculate a safe batch size based on average path length\n\t\tconst avgPathLength = countStringLength(paths) / paths.length;\n\t\tconst batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength));\n\n\t\t// Process paths in batches (will be a single batch if under the limit)\n\t\tconst batches = chunk(paths, batchSize);\n\t\ttry {\n\t\t\tfor (const batch of batches) {\n\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...args, '--', ...batch);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Even when a later batch fails, the earlier ones already removed files\n\t\t\tthis.announceIndexChanged(repoPath);\n\t\t}\n\t}\n\n\t/** What every index or working-tree mutation announces, so cached status is re-read and hosts are told. */\n\tprivate announceIndexChanged(repoPath: string): void {\n\t\t// `diff` and `tracking` too, as a watcher-observed index change clears them: a file's working-vs-index\n\t\t// diff and whether it is tracked both change when it is staged, unstaged or removed\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'status', 'diff', 'tracking');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['index']);\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { Uri } from "../../utils/uri.js";
|
|
|
2
2
|
import { GitServiceContext } from "../../git/context.js";
|
|
3
3
|
import { GitWorktree } from "../../git/models/worktree.js";
|
|
4
4
|
import { Cache } from "../../git/cache.js";
|
|
5
|
+
import { GitOperationRunOptions } from "../../git/providers/operations.js";
|
|
5
6
|
import { GitWorktreesSubProvider } from "../../git/providers/worktrees.js";
|
|
6
7
|
import { Git } from "../exec/git.js";
|
|
7
8
|
import { CliGitProviderInternal } from "../cliGitProvider.js";
|
|
@@ -12,25 +13,53 @@ export declare class WorktreesGitSubProvider implements GitWorktreesSubProvider
|
|
|
12
13
|
private readonly cache;
|
|
13
14
|
private readonly provider;
|
|
14
15
|
constructor(context: GitServiceContext, git: Git, cache: Cache, provider: CliGitProviderInternal);
|
|
16
|
+
/**
|
|
17
|
+
* Creates a worktree (`git worktree add`). `runOptions` are spread into the underlying `git.run` call, so a
|
|
18
|
+
* large checkout can run without the default command timeout (`{ timeout: 0 }`) and still be cancelled.
|
|
19
|
+
*/
|
|
15
20
|
createWorktree(repoPath: string, path: string, options?: {
|
|
16
21
|
commitish?: string;
|
|
17
22
|
createBranch?: string;
|
|
18
23
|
detach?: boolean;
|
|
19
24
|
force?: boolean;
|
|
20
25
|
noTracking?: boolean;
|
|
21
|
-
}): Promise<void>;
|
|
26
|
+
}, runOptions?: GitOperationRunOptions): Promise<void>;
|
|
22
27
|
createWorktreeWithResult(repoPath: string, path: string, options?: {
|
|
23
28
|
commitish?: string;
|
|
24
29
|
createBranch?: string;
|
|
25
30
|
detach?: boolean;
|
|
26
31
|
force?: boolean;
|
|
27
32
|
noTracking?: boolean;
|
|
28
|
-
}): Promise<GitWorktree | undefined>;
|
|
33
|
+
}, runOptions?: GitOperationRunOptions): Promise<GitWorktree | undefined>;
|
|
29
34
|
getWorktree(repoPath: string, predicate: (w: GitWorktree) => boolean, cancellation?: AbortSignal): Promise<GitWorktree | undefined>;
|
|
30
35
|
getWorktrees(repoPath: string, cancellation?: AbortSignal): Promise<GitWorktree[]>;
|
|
31
36
|
getWorktreesDefaultUri(repoPath: string): Uri | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Deletes a worktree (`git worktree remove`). Pass `force: 'locked'` to also override a locked worktree.
|
|
39
|
+
*
|
|
40
|
+
* `runOptions` are spread into the underlying `git.run` call (e.g. `{ timeout: 0 }` for a large worktree
|
|
41
|
+
* whose removal may exceed the default command timeout).
|
|
42
|
+
*
|
|
43
|
+
* On failure, the thrown {@link WorktreeDeleteError}'s `original` property carries the raw
|
|
44
|
+
* {@link GitError} (stderr/stdout/exit code) untouched — a caller that needs to classify a
|
|
45
|
+
* platform-specific failure (e.g. a Windows file-lock retry) can read it directly rather than parsing
|
|
46
|
+
* the typed error's message.
|
|
47
|
+
*/
|
|
32
48
|
deleteWorktree(repoPath: string, path: string | Uri, options?: {
|
|
33
49
|
force?: boolean | 'locked';
|
|
50
|
+
}, runOptions?: GitOperationRunOptions): Promise<void>;
|
|
51
|
+
pruneWorktrees(repoPath: string, options?: {
|
|
52
|
+
expire?: string;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Raw worktree paths currently known to git (`worktree <path>` lines from `--porcelain`), normalized the
|
|
56
|
+
* same way {@link deleteWorktree} does. A failed listing (`errors: 'ignore'`) yields an empty set rather
|
|
57
|
+
* than throwing — used by `pruneWorktrees` to diff before/after, where a transient read failure must not
|
|
58
|
+
* be mistaken for every worktree having vanished.
|
|
59
|
+
*/
|
|
60
|
+
private listWorktreePaths;
|
|
61
|
+
lockWorktree(repoPath: string, path: string | Uri, options?: {
|
|
62
|
+
reason?: string;
|
|
34
63
|
}): Promise<void>;
|
|
35
64
|
unlockWorktree(repoPath: string, path: string | Uri): Promise<void>;
|
|
36
65
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isCancellationError } from "../../utils/cancellation.js";
|
|
1
2
|
import { getScopedLogger } from "../../utils/logger.scoped.js";
|
|
2
3
|
import { getSettledValue } from "../../utils/promise.js";
|
|
3
4
|
import { debug } from "../../utils/decorators/log.js";
|
|
@@ -27,7 +28,11 @@ var WorktreesGitSubProvider = class {
|
|
|
27
28
|
this.cache = cache;
|
|
28
29
|
this.provider = provider;
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Creates a worktree (`git worktree add`). `runOptions` are spread into the underlying `git.run` call, so a
|
|
33
|
+
* large checkout can run without the default command timeout (`{ timeout: 0 }`) and still be cancelled.
|
|
34
|
+
*/
|
|
35
|
+
async createWorktree(repoPath, path, options, runOptions) {
|
|
31
36
|
const scope = getScopedLogger();
|
|
32
37
|
const args = ["worktree", "add"];
|
|
33
38
|
if (options?.force) args.push("--force");
|
|
@@ -37,12 +42,16 @@ var WorktreesGitSubProvider = class {
|
|
|
37
42
|
args.push(path);
|
|
38
43
|
if (options?.commitish) args.push(options.commitish);
|
|
39
44
|
try {
|
|
40
|
-
await this.git.run({
|
|
45
|
+
await this.git.run({
|
|
46
|
+
cwd: repoPath,
|
|
47
|
+
...runOptions
|
|
48
|
+
}, ...args);
|
|
41
49
|
if (options?.createBranch) this.cache.deleteBaseBranchName(repoPath, options.createBranch);
|
|
42
50
|
this.context.hooks?.cache?.onReset?.(repoPath, ...options?.createBranch ? ["branches", "worktrees"] : ["worktrees"]);
|
|
43
51
|
this.context.hooks?.repository?.onChanged?.(repoPath, options?.createBranch ? ["worktrees", "heads"] : ["worktrees"]);
|
|
44
52
|
} catch (ex) {
|
|
45
53
|
scope?.error(ex);
|
|
54
|
+
if (isCancellationError(ex)) throw ex;
|
|
46
55
|
throw getGitCommandError("worktree-create", ex, (reason) => new WorktreeCreateError({
|
|
47
56
|
reason,
|
|
48
57
|
gitCommand: {
|
|
@@ -52,10 +61,10 @@ var WorktreesGitSubProvider = class {
|
|
|
52
61
|
}, ex));
|
|
53
62
|
}
|
|
54
63
|
}
|
|
55
|
-
async createWorktreeWithResult(repoPath, path, options) {
|
|
56
|
-
await this.createWorktree(repoPath, path, options);
|
|
64
|
+
async createWorktreeWithResult(repoPath, path, options, runOptions) {
|
|
65
|
+
await this.createWorktree(repoPath, path, options, runOptions);
|
|
57
66
|
const normalized = normalizePath(path);
|
|
58
|
-
return this.getWorktree(repoPath, (w) => normalizePath(w.path) === normalized);
|
|
67
|
+
return this.getWorktree(repoPath, (w) => normalizePath(w.path) === normalized, runOptions?.cancellation);
|
|
59
68
|
}
|
|
60
69
|
async getWorktree(repoPath, predicate, cancellation) {
|
|
61
70
|
return (await this.getWorktrees(repoPath, cancellation)).find(predicate);
|
|
@@ -83,7 +92,18 @@ var WorktreesGitSubProvider = class {
|
|
|
83
92
|
getWorktreesDefaultUri(repoPath) {
|
|
84
93
|
return this.context.workspace?.getWorktreeDefaultUri?.(repoPath);
|
|
85
94
|
}
|
|
86
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Deletes a worktree (`git worktree remove`). Pass `force: 'locked'` to also override a locked worktree.
|
|
97
|
+
*
|
|
98
|
+
* `runOptions` are spread into the underlying `git.run` call (e.g. `{ timeout: 0 }` for a large worktree
|
|
99
|
+
* whose removal may exceed the default command timeout).
|
|
100
|
+
*
|
|
101
|
+
* On failure, the thrown {@link WorktreeDeleteError}'s `original` property carries the raw
|
|
102
|
+
* {@link GitError} (stderr/stdout/exit code) untouched — a caller that needs to classify a
|
|
103
|
+
* platform-specific failure (e.g. a Windows file-lock retry) can read it directly rather than parsing
|
|
104
|
+
* the typed error's message.
|
|
105
|
+
*/
|
|
106
|
+
async deleteWorktree(repoPath, path, options, runOptions) {
|
|
87
107
|
const scope = getScopedLogger();
|
|
88
108
|
await this.git.ensureSupports("git:worktrees", (requiredVersion, installedVersion) => l10n.t("Deleting worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.", requiredVersion, installedVersion));
|
|
89
109
|
const args = ["worktree", "remove"];
|
|
@@ -97,11 +117,13 @@ var WorktreesGitSubProvider = class {
|
|
|
97
117
|
try {
|
|
98
118
|
await this.git.run({
|
|
99
119
|
cwd: repoPath,
|
|
100
|
-
errors: "throw"
|
|
120
|
+
errors: "throw",
|
|
121
|
+
...runOptions
|
|
101
122
|
}, ...args);
|
|
102
123
|
deleted = true;
|
|
103
124
|
} catch (ex) {
|
|
104
125
|
scope?.error(ex);
|
|
126
|
+
if (isCancellationError(ex)) throw ex;
|
|
105
127
|
const gitError = getGitCommandError("worktree-delete", ex, (reason) => new WorktreeDeleteError({
|
|
106
128
|
reason,
|
|
107
129
|
lockReason: reason === "locked" ? getLockReason(ex) : void 0,
|
|
@@ -160,6 +182,50 @@ var WorktreesGitSubProvider = class {
|
|
|
160
182
|
}
|
|
161
183
|
}
|
|
162
184
|
}
|
|
185
|
+
async pruneWorktrees(repoPath, options) {
|
|
186
|
+
await this.git.ensureSupports("git:worktrees", (requiredVersion, installedVersion) => l10n.t("Pruning worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.", requiredVersion, installedVersion));
|
|
187
|
+
const before = await this.listWorktreePaths(repoPath);
|
|
188
|
+
const args = ["worktree", "prune"];
|
|
189
|
+
if (options?.expire) args.push("--expire", options.expire);
|
|
190
|
+
await this.git.run({
|
|
191
|
+
cwd: repoPath,
|
|
192
|
+
errors: "throw"
|
|
193
|
+
}, ...args);
|
|
194
|
+
const after = await this.listWorktreePaths(repoPath);
|
|
195
|
+
if (before != null && after != null) {
|
|
196
|
+
for (const path of before) if (!after.has(path)) this.cache.unregisterRepoPath(path);
|
|
197
|
+
}
|
|
198
|
+
this.context.hooks?.cache?.onReset?.(repoPath, "worktrees");
|
|
199
|
+
this.context.hooks?.repository?.onChanged?.(repoPath, ["worktrees"]);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Raw worktree paths currently known to git (`worktree <path>` lines from `--porcelain`), normalized the
|
|
203
|
+
* same way {@link deleteWorktree} does. A failed listing (`errors: 'ignore'`) yields an empty set rather
|
|
204
|
+
* than throwing — used by `pruneWorktrees` to diff before/after, where a transient read failure must not
|
|
205
|
+
* be mistaken for every worktree having vanished.
|
|
206
|
+
*/
|
|
207
|
+
async listWorktreePaths(repoPath) {
|
|
208
|
+
const result = await this.git.run({
|
|
209
|
+
cwd: repoPath,
|
|
210
|
+
errors: "ignore"
|
|
211
|
+
}, "worktree", "list", "--porcelain");
|
|
212
|
+
if (result.completion.status !== "exited" || result.exitCode !== 0) return void 0;
|
|
213
|
+
const paths = /* @__PURE__ */ new Set();
|
|
214
|
+
for (const line of result.stdout.split("\n")) if (line.startsWith("worktree ")) paths.add(normalizePath(toFsPath(line.slice(9).trim())));
|
|
215
|
+
return paths;
|
|
216
|
+
}
|
|
217
|
+
async lockWorktree(repoPath, path, options) {
|
|
218
|
+
await this.git.ensureSupports("git:worktrees", (requiredVersion, installedVersion) => l10n.t("Locking worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.", requiredVersion, installedVersion));
|
|
219
|
+
const args = ["worktree", "lock"];
|
|
220
|
+
if (options?.reason) args.push("--reason", options.reason);
|
|
221
|
+
args.push(normalizePath(toFsPath(path)));
|
|
222
|
+
await this.git.run({
|
|
223
|
+
cwd: repoPath,
|
|
224
|
+
errors: "throw"
|
|
225
|
+
}, ...args);
|
|
226
|
+
this.context.hooks?.cache?.onReset?.(repoPath, "worktrees");
|
|
227
|
+
this.context.hooks?.repository?.onChanged?.(repoPath, ["worktrees"]);
|
|
228
|
+
}
|
|
163
229
|
async unlockWorktree(repoPath, path) {
|
|
164
230
|
await this.git.ensureSupports("git:worktrees", (requiredVersion, installedVersion) => l10n.t("Unlocking worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.", requiredVersion, installedVersion));
|
|
165
231
|
await this.git.run({
|
|
@@ -175,6 +241,8 @@ __decorate([debug()], WorktreesGitSubProvider.prototype, "getWorktree", null);
|
|
|
175
241
|
__decorate([debug()], WorktreesGitSubProvider.prototype, "getWorktrees", null);
|
|
176
242
|
__decorate([debug()], WorktreesGitSubProvider.prototype, "getWorktreesDefaultUri", null);
|
|
177
243
|
__decorate([debug()], WorktreesGitSubProvider.prototype, "deleteWorktree", null);
|
|
244
|
+
__decorate([debug()], WorktreesGitSubProvider.prototype, "pruneWorktrees", null);
|
|
245
|
+
__decorate([debug()], WorktreesGitSubProvider.prototype, "lockWorktree", null);
|
|
178
246
|
__decorate([debug()], WorktreesGitSubProvider.prototype, "unlockWorktree", null);
|
|
179
247
|
//#endregion
|
|
180
248
|
export { WorktreesGitSubProvider };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktrees.js","names":["fs"],"sources":["../../../../git-cli/src/providers/worktrees.ts"],"sourcesContent":["import { exec } from 'child_process';\nimport { promises as fs } from 'fs';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { WorktreeCreateError, WorktreeDeleteError } from '@gitlens/git/errors.js';\nimport type { GitWorktree, WorkspaceFolderResolver } from '@gitlens/git/models/worktree.js';\nimport type { GitWorktreesSubProvider } from '@gitlens/git/providers/worktrees.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { isWindows } from '@gitlens/utils/env/node/platform.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { basename, normalizePath } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fileUri, toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git, GitError } from '../exec/git.js';\nimport { getGitCommandError, GitErrors } from '../exec/git.js';\nimport { parseGitWorktrees } from '../parsers/worktreeParser.js';\n\n/** Extracts the lock reason from Git's `cannot remove a locked working tree` output, when it provides one */\nfunction getLockReason(ex: GitError): string | undefined {\n\treturn GitErrors.worktreeLockedReason.exec(ex.stderr || ex.stdout || ex.message || '')?.[1].trim() || undefined;\n}\n\nexport class WorktreesGitSubProvider implements GitWorktreesSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tasync createWorktree(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\toptions?: {\n\t\t\tcommitish?: string;\n\t\t\tcreateBranch?: string;\n\t\t\tdetach?: boolean;\n\t\t\tforce?: boolean;\n\t\t\tnoTracking?: boolean;\n\t\t},\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['worktree', 'add'];\n\t\tif (options?.force) {\n\t\t\targs.push('--force');\n\t\t}\n\t\tif (options?.createBranch) {\n\t\t\targs.push('-b', options.createBranch);\n\t\t}\n\t\tif (options?.createBranch && options.noTracking) {\n\t\t\targs.push('--no-track');\n\t\t}\n\t\tif (options?.detach) {\n\t\t\targs.push('--detach');\n\t\t}\n\t\targs.push(path);\n\t\tif (options?.commitish) {\n\t\t\targs.push(options.commitish);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, ...args);\n\n\t\t\tif (options?.createBranch) {\n\t\t\t\t// Evict the cached base only — see `checkout -b` for why the persisted keys are left alone.\n\t\t\t\tthis.cache.deleteBaseBranchName(repoPath, options.createBranch);\n\t\t\t}\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(\n\t\t\t\trepoPath,\n\t\t\t\t...(options?.createBranch ? (['branches', 'worktrees'] as const) : (['worktrees'] as const)),\n\t\t\t);\n\t\t\tthis.context.hooks?.repository?.onChanged?.(\n\t\t\t\trepoPath,\n\t\t\t\toptions?.createBranch ? ['worktrees', 'heads'] : ['worktrees'],\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'worktree-create',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew WorktreeCreateError(\n\t\t\t\t\t\t{ reason: reason, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tasync createWorktreeWithResult(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\toptions?: {\n\t\t\tcommitish?: string;\n\t\t\tcreateBranch?: string;\n\t\t\tdetach?: boolean;\n\t\t\tforce?: boolean;\n\t\t\tnoTracking?: boolean;\n\t\t},\n\t): Promise<GitWorktree | undefined> {\n\t\tawait this.createWorktree(repoPath, path, options);\n\t\tconst normalized = normalizePath(path);\n\t\treturn this.getWorktree(repoPath, w => normalizePath(w.path) === normalized);\n\t}\n\n\t@debug()\n\tasync getWorktree(\n\t\trepoPath: string,\n\t\tpredicate: (w: GitWorktree) => boolean,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitWorktree | undefined> {\n\t\treturn (await this.getWorktrees(repoPath, cancellation)).find(predicate);\n\t}\n\n\t@debug()\n\tasync getWorktrees(repoPath: string, cancellation?: AbortSignal): Promise<GitWorktree[]> {\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Displaying worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\treturn this.cache.getWorktrees(\n\t\t\trepoPath,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\t// Prefer the aggregate signal from the cache; fall back to the caller's cancellation.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst [dataResult, branchesResult] = await Promise.allSettled([\n\t\t\t\t\tthis.git.run({ cwd: commonPath, cancellation: signal }, 'worktree', 'list', '--porcelain'),\n\t\t\t\t\tthis.provider.branches.getBranches(commonPath, undefined, signal),\n\t\t\t\t]);\n\n\t\t\t\tif (dataResult.status === 'rejected') {\n\t\t\t\t\t// Don't cache a bogus empty result for a transient command failure — retry on next access.\n\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t}\n\n\t\t\t\tconst getWorkspaceFolder: WorkspaceFolderResolver | undefined = this.context.workspace\n\t\t\t\t\t? uri => {\n\t\t\t\t\t\t\tconst folder = this.context.workspace!.getFolder(uri.fsPath);\n\t\t\t\t\t\t\tif (folder == null) return undefined;\n\t\t\t\t\t\t\treturn { uri: fileUri(folder.path), name: basename(folder.path) };\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined;\n\n\t\t\t\treturn parseGitWorktrees(\n\t\t\t\t\tgetSettledValue(dataResult)?.stdout,\n\t\t\t\t\tcommonPath,\n\t\t\t\t\tgetSettledValue(branchesResult)?.values ?? [],\n\t\t\t\t\tgetWorkspaceFolder,\n\t\t\t\t);\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug()\n\tgetWorktreesDefaultUri(repoPath: string): Uri | undefined {\n\t\treturn this.context.workspace?.getWorktreeDefaultUri?.(repoPath);\n\t}\n\n\t@debug()\n\tasync deleteWorktree(\n\t\trepoPath: string,\n\t\tpath: string | Uri,\n\t\toptions?: { force?: boolean | 'locked' },\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Deleting worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tconst args = ['worktree', 'remove'];\n\t\tif (options?.force) {\n\t\t\targs.push('--force');\n\t\t\t// Git requires a second `--force` to remove a locked worktree\n\t\t\tif (options.force === 'locked') {\n\t\t\t\targs.push('--force');\n\t\t\t}\n\t\t}\n\n\t\tconst pathStr = normalizePath(toFsPath(path));\n\t\targs.push(pathStr);\n\n\t\tlet deleted = false;\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...args);\n\t\t\tdeleted = true;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tconst gitError = getGitCommandError(\n\t\t\t\t'worktree-delete',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew WorktreeDeleteError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\tlockReason: reason === 'locked' ? getLockReason(ex as GitError) : undefined,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (gitError.details.reason === 'directoryNotEmpty') {\n\t\t\t\tscope?.warn(\n\t\t\t\t\t`Failed to fully delete worktree '${pathStr}' because it is not empty. Attempting to delete it manually.`,\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tawait fs.rm(pathStr, { force: true, recursive: true });\n\t\t\t\t\tdeleted = true;\n\t\t\t\t\treturn;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tif (isWindows) {\n\t\t\t\t\t\tconst match = /EPERM: operation not permitted, unlink '(.*?)'/i.exec((ex as GitError).message);\n\t\t\t\t\t\tif (match != null) {\n\t\t\t\t\t\t\tscope?.warn(\n\t\t\t\t\t\t\t\t`Failed to manually delete '${pathStr}' because it is in use. Attempting to forcefully delete it.`,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Windows-specific: `del` via cmd.exe to force-remove a locked symlink.\n\t\t\t\t\t\t\t// Node's fs.rm/unlink fails with EPERM when the symlink target is in use.\n\t\t\t\t\t\t\tfunction deleteInUseSymlink(symlink: string) {\n\t\t\t\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\t\t\t\texec(`del \"${symlink}\"`, (ex, stdout, stderr) => {\n\t\t\t\t\t\t\t\t\t\tif (ex) {\n\t\t\t\t\t\t\t\t\t\t\treject(ex instanceof Error ? ex : new Error(String(ex)));\n\t\t\t\t\t\t\t\t\t\t} else if (stderr) {\n\t\t\t\t\t\t\t\t\t\t\treject(new Error(stderr));\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tresolve(stdout);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst [, file] = match;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait deleteInUseSymlink(file);\n\t\t\t\t\t\t\t\tawait fs.rm(pathStr, { force: true, recursive: true, maxRetries: 1, retryDelay: 1 });\n\t\t\t\t\t\t\t\tdeleted = true;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t\t\tscope?.error(ex, `Failed to forcefully delete '${pathStr}' because it is in use.`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow gitError;\n\t\t} finally {\n\t\t\tif (deleted) {\n\t\t\t\t// Clean up Cache registry + per-worktree cache entries for the deleted worktree.\n\t\t\t\t// Order matters: unregister before emitting the repo-level change so any listener\n\t\t\t\t// that re-queries worktree-aware state sees the registry already updated.\n\t\t\t\tthis.cache.unregisterRepoPath(pathStr);\n\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'worktrees');\n\t\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['worktrees']);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug()\n\tasync unlockWorktree(repoPath: string, path: string | Uri): Promise<void> {\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Unlocking worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, 'worktree', 'unlock', normalizePath(toFsPath(path)));\n\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'worktrees');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['worktrees']);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,SAAS,cAAc,IAAkC;CACxD,OAAO,UAAU,qBAAqB,KAAK,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,KAAA;AACvG;AAEA,IAAa,0BAAb,MAAwE;CAErD;CACA;CACA;CACA;CAJlB,YACC,SACA,KACA,OACA,UACC;EAJgB,KAAA,UAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACf;CAEH,MACM,eACL,UACA,MACA,SAOgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,OAAO,CAAC,YAAY,KAAK;EAC/B,IAAI,SAAS,OACZ,KAAK,KAAK,SAAS;EAEpB,IAAI,SAAS,cACZ,KAAK,KAAK,MAAM,QAAQ,YAAY;EAErC,IAAI,SAAS,gBAAgB,QAAQ,YACpC,KAAK,KAAK,YAAY;EAEvB,IAAI,SAAS,QACZ,KAAK,KAAK,UAAU;EAErB,KAAK,KAAK,IAAI;EACd,IAAI,SAAS,WACZ,KAAK,KAAK,QAAQ,SAAS;EAG5B,IAAI;GACH,MAAM,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,GAAG,GAAG,IAAI;GAE7C,IAAI,SAAS,cAEZ,KAAK,MAAM,qBAAqB,UAAU,QAAQ,YAAY;GAG/D,KAAK,QAAQ,OAAO,OAAO,UAC1B,UACA,GAAI,SAAS,eAAgB,CAAC,YAAY,WAAW,IAAe,CAAC,WAAW,CACjF;GACA,KAAK,QAAQ,OAAO,YAAY,YAC/B,UACA,SAAS,eAAe,CAAC,aAAa,OAAO,IAAI,CAAC,WAAW,CAC9D;EACD,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,mBACL,mBACA,KACA,WACC,IAAI,oBACH;IAAU;IAAQ,YAAY;KAAY;KAAgB;IAAK;GAAE,GACjE,EACD,CACF;EACD;CACD;CAEA,MAAM,yBACL,UACA,MACA,SAOmC;EACnC,MAAM,KAAK,eAAe,UAAU,MAAM,OAAO;EACjD,MAAM,aAAa,cAAc,IAAI;EACrC,OAAO,KAAK,YAAY,WAAU,MAAK,cAAc,EAAE,IAAI,MAAM,UAAU;CAC5E;CAEA,MACM,YACL,UACA,WACA,cACmC;EACnC,QAAQ,MAAM,KAAK,aAAa,UAAU,YAAY,EAAA,CAAG,KAAK,SAAS;CACxE;CAEA,MACM,aAAa,UAAkB,cAAoD;EACxF,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,+JACA,iBACA,gBACD,CACD;EAEA,OAAO,KAAK,MAAM,aACjB,UACA,OAAO,YAAY,WAAW,WAAW;GAExC,WAAW;GACX,MAAM,CAAC,YAAY,kBAAkB,MAAM,QAAQ,WAAW,CAC7D,KAAK,IAAI,IAAI;IAAE,KAAK;IAAY,cAAc;GAAO,GAAG,YAAY,QAAQ,aAAa,GACzF,KAAK,SAAS,SAAS,YAAY,YAAY,KAAA,GAAW,MAAM,CACjE,CAAC;GAED,IAAI,WAAW,WAAW,YAEzB,UAAU,WAAW;GAGtB,MAAM,qBAA0D,KAAK,QAAQ,aAC1E,QAAO;IACP,MAAM,SAAS,KAAK,QAAQ,UAAW,UAAU,IAAI,MAAM;IAC3D,IAAI,UAAU,MAAM,OAAO,KAAA;IAC3B,OAAO;KAAE,KAAK,QAAQ,OAAO,IAAI;KAAG,MAAM,SAAS,OAAO,IAAI;IAAE;GACjE,IACC,KAAA;GAEH,OAAO,kBACN,gBAAgB,UAAU,CAAC,EAAE,QAC7B,YACA,gBAAgB,cAAc,CAAC,EAAE,UAAU,CAAC,GAC5C,kBACD;EACD,GACA,YACD;CACD;CAEA,uBACuB,UAAmC;EACzD,OAAO,KAAK,QAAQ,WAAW,wBAAwB,QAAQ;CAChE;CAEA,MACM,eACL,UACA,MACA,SACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,6JACA,iBACA,gBACD,CACD;EAEA,MAAM,OAAO,CAAC,YAAY,QAAQ;EAClC,IAAI,SAAS,OAAO;GACnB,KAAK,KAAK,SAAS;GAEnB,IAAI,QAAQ,UAAU,UACrB,KAAK,KAAK,SAAS;EAErB;EAEA,MAAM,UAAU,cAAc,SAAS,IAAI,CAAC;EAC5C,KAAK,KAAK,OAAO;EAEjB,IAAI,UAAU;EACd,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;GAAQ,GAAG,GAAG,IAAI;GAC9D,UAAU;EACX,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GACf,MAAM,WAAW,mBAChB,mBACA,KACA,WACC,IAAI,oBACH;IACS;IACR,YAAY,WAAW,WAAW,cAAc,EAAc,IAAI,KAAA;IAClE,YAAY;KAAY;KAAgB;IAAK;GAC9C,GACA,EACD,CACF;GAEA,IAAI,SAAS,QAAQ,WAAW,qBAAqB;IACpD,OAAO,KACN,oCAAoC,QAAQ,6DAC7C;IACA,IAAI;KACH,MAAMA,SAAG,GAAG,SAAS;MAAE,OAAO;MAAM,WAAW;KAAK,CAAC;KACrD,UAAU;KACV;IACD,SAAS,IAAI;KACZ,IAAI,WAAW;MACd,MAAM,QAAQ,kDAAkD,KAAM,GAAgB,OAAO;MAC7F,IAAI,SAAS,MAAM;OAClB,OAAO,KACN,8BAA8B,QAAQ,4DACvC;OAIA,SAAS,mBAAmB,SAAiB;QAC5C,OAAO,IAAI,SAAS,SAAS,WAAW;SACvC,KAAK,QAAQ,QAAQ,KAAK,IAAI,QAAQ,WAAW;UAChD,IAAI,IACH,OAAO,cAAc,QAAQ,KAAK,IAAI,MAAM,OAAO,EAAE,CAAC,CAAC;eACjD,IAAI,QACV,OAAO,IAAI,MAAM,MAAM,CAAC;eAExB,QAAQ,MAAM;SAEhB,CAAC;QACF,CAAC;OACF;OAEA,MAAM,GAAG,QAAQ;OACjB,IAAI;QACH,MAAM,mBAAmB,IAAI;QAC7B,MAAMA,SAAG,GAAG,SAAS;SAAE,OAAO;SAAM,WAAW;SAAM,YAAY;SAAG,YAAY;QAAE,CAAC;QACnF,UAAU;QACV;OACD,SAAS,IAAI;QACZ,OAAO,MAAM,IAAI,gCAAgC,QAAQ,wBAAwB;OAClF;MACD;KACD;IACD;GACD;GAEA,MAAM;EACP,UAAU;GACT,IAAI,SAAS;IAIZ,KAAK,MAAM,mBAAmB,OAAO;IACrC,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW;IAC1D,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,CAAC;GACpE;EACD;CACD;CAEA,MACM,eAAe,UAAkB,MAAmC;EACzE,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,8JACA,iBACA,gBACD,CACD;EAEA,MAAM,KAAK,IAAI,IAAI;GAAE,KAAK;GAAU,QAAQ;EAAQ,GAAG,YAAY,UAAU,cAAc,SAAS,IAAI,CAAC,CAAC;EAE1G,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW;EAC1D,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,CAAC;CACpE;AACD;AAlQE,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,kBAAA,IAAA;AA8EN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,eAAA,IAAA;AASN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,gBAAA,IAAA;AA4CN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,0BAAA,IAAA;AAKN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,kBAAA,IAAA;AA2GN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,kBAAA,IAAA"}
|
|
1
|
+
{"version":3,"file":"worktrees.js","names":["fs"],"sources":["../../../../git-cli/src/providers/worktrees.ts"],"sourcesContent":["import { exec } from 'child_process';\nimport { promises as fs } from 'fs';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { WorktreeCreateError, WorktreeDeleteError } from '@gitlens/git/errors.js';\nimport type { GitWorktree, WorkspaceFolderResolver } from '@gitlens/git/models/worktree.js';\nimport type { GitOperationRunOptions } from '@gitlens/git/providers/operations.js';\nimport type { GitWorktreesSubProvider } from '@gitlens/git/providers/worktrees.js';\nimport { isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { isWindows } from '@gitlens/utils/env/node/platform.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { basename, normalizePath } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fileUri, toFsPath } from '@gitlens/utils/uri.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git, GitError } from '../exec/git.js';\nimport { getGitCommandError, GitErrors } from '../exec/git.js';\nimport { parseGitWorktrees } from '../parsers/worktreeParser.js';\n\n/** Extracts the lock reason from Git's `cannot remove a locked working tree` output, when it provides one */\nfunction getLockReason(ex: GitError): string | undefined {\n\treturn GitErrors.worktreeLockedReason.exec(ex.stderr || ex.stdout || ex.message || '')?.[1].trim() || undefined;\n}\n\nexport class WorktreesGitSubProvider implements GitWorktreesSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t/**\n\t * Creates a worktree (`git worktree add`). `runOptions` are spread into the underlying `git.run` call, so a\n\t * large checkout can run without the default command timeout (`{ timeout: 0 }`) and still be cancelled.\n\t */\n\t@debug()\n\tasync createWorktree(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\toptions?: {\n\t\t\tcommitish?: string;\n\t\t\tcreateBranch?: string;\n\t\t\tdetach?: boolean;\n\t\t\tforce?: boolean;\n\t\t\tnoTracking?: boolean;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst args = ['worktree', 'add'];\n\t\tif (options?.force) {\n\t\t\targs.push('--force');\n\t\t}\n\t\tif (options?.createBranch) {\n\t\t\targs.push('-b', options.createBranch);\n\t\t}\n\t\tif (options?.createBranch && options.noTracking) {\n\t\t\targs.push('--no-track');\n\t\t}\n\t\tif (options?.detach) {\n\t\t\targs.push('--detach');\n\t\t}\n\t\targs.push(path);\n\t\tif (options?.commitish) {\n\t\t\targs.push(options.commitish);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, ...runOptions }, ...args);\n\n\t\t\tif (options?.createBranch) {\n\t\t\t\t// Evict the cached base only — see `checkout -b` for why the persisted keys are left alone.\n\t\t\t\tthis.cache.deleteBaseBranchName(repoPath, options.createBranch);\n\t\t\t}\n\n\t\t\tthis.context.hooks?.cache?.onReset?.(\n\t\t\t\trepoPath,\n\t\t\t\t...(options?.createBranch ? (['branches', 'worktrees'] as const) : (['worktrees'] as const)),\n\t\t\t);\n\t\t\tthis.context.hooks?.repository?.onChanged?.(\n\t\t\t\trepoPath,\n\t\t\t\toptions?.createBranch ? ['worktrees', 'heads'] : ['worktrees'],\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\t// A cancelled or timed-out checkout is not git refusing the worktree\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'worktree-create',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew WorktreeCreateError(\n\t\t\t\t\t\t{ reason: reason, gitCommand: { repoPath: repoPath, args: args } },\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tasync createWorktreeWithResult(\n\t\trepoPath: string,\n\t\tpath: string,\n\t\toptions?: {\n\t\t\tcommitish?: string;\n\t\t\tcreateBranch?: string;\n\t\t\tdetach?: boolean;\n\t\t\tforce?: boolean;\n\t\t\tnoTracking?: boolean;\n\t\t},\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<GitWorktree | undefined> {\n\t\tawait this.createWorktree(repoPath, path, options, runOptions);\n\t\tconst normalized = normalizePath(path);\n\t\treturn this.getWorktree(repoPath, w => normalizePath(w.path) === normalized, runOptions?.cancellation);\n\t}\n\n\t@debug()\n\tasync getWorktree(\n\t\trepoPath: string,\n\t\tpredicate: (w: GitWorktree) => boolean,\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitWorktree | undefined> {\n\t\treturn (await this.getWorktrees(repoPath, cancellation)).find(predicate);\n\t}\n\n\t@debug()\n\tasync getWorktrees(repoPath: string, cancellation?: AbortSignal): Promise<GitWorktree[]> {\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Displaying worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\treturn this.cache.getWorktrees(\n\t\t\trepoPath,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\t// Prefer the aggregate signal from the cache; fall back to the caller's cancellation.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst [dataResult, branchesResult] = await Promise.allSettled([\n\t\t\t\t\tthis.git.run({ cwd: commonPath, cancellation: signal }, 'worktree', 'list', '--porcelain'),\n\t\t\t\t\tthis.provider.branches.getBranches(commonPath, undefined, signal),\n\t\t\t\t]);\n\n\t\t\t\tif (dataResult.status === 'rejected') {\n\t\t\t\t\t// Don't cache a bogus empty result for a transient command failure — retry on next access.\n\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t}\n\n\t\t\t\tconst getWorkspaceFolder: WorkspaceFolderResolver | undefined = this.context.workspace\n\t\t\t\t\t? uri => {\n\t\t\t\t\t\t\tconst folder = this.context.workspace!.getFolder(uri.fsPath);\n\t\t\t\t\t\t\tif (folder == null) return undefined;\n\t\t\t\t\t\t\treturn { uri: fileUri(folder.path), name: basename(folder.path) };\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined;\n\n\t\t\t\treturn parseGitWorktrees(\n\t\t\t\t\tgetSettledValue(dataResult)?.stdout,\n\t\t\t\t\tcommonPath,\n\t\t\t\t\tgetSettledValue(branchesResult)?.values ?? [],\n\t\t\t\t\tgetWorkspaceFolder,\n\t\t\t\t);\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t@debug()\n\tgetWorktreesDefaultUri(repoPath: string): Uri | undefined {\n\t\treturn this.context.workspace?.getWorktreeDefaultUri?.(repoPath);\n\t}\n\n\t/**\n\t * Deletes a worktree (`git worktree remove`). Pass `force: 'locked'` to also override a locked worktree.\n\t *\n\t * `runOptions` are spread into the underlying `git.run` call (e.g. `{ timeout: 0 }` for a large worktree\n\t * whose removal may exceed the default command timeout).\n\t *\n\t * On failure, the thrown {@link WorktreeDeleteError}'s `original` property carries the raw\n\t * {@link GitError} (stderr/stdout/exit code) untouched — a caller that needs to classify a\n\t * platform-specific failure (e.g. a Windows file-lock retry) can read it directly rather than parsing\n\t * the typed error's message.\n\t */\n\t@debug()\n\tasync deleteWorktree(\n\t\trepoPath: string,\n\t\tpath: string | Uri,\n\t\toptions?: { force?: boolean | 'locked' },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Deleting worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tconst args = ['worktree', 'remove'];\n\t\tif (options?.force) {\n\t\t\targs.push('--force');\n\t\t\t// Git requires a second `--force` to remove a locked worktree\n\t\t\tif (options.force === 'locked') {\n\t\t\t\targs.push('--force');\n\t\t\t}\n\t\t}\n\n\t\tconst pathStr = normalizePath(toFsPath(path));\n\t\targs.push(pathStr);\n\n\t\tlet deleted = false;\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...args);\n\t\t\tdeleted = true;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\t// A cancelled or timed-out removal (`runOptions.cancellation`/`timeout`) is not git refusing it, and\n\t\t\t// wrapping it would hand the caller a `WorktreeDeleteError` whose `original` is no `GitError` at all\n\t\t\tif (isCancellationError(ex)) throw ex;\n\n\t\t\tconst gitError = getGitCommandError(\n\t\t\t\t'worktree-delete',\n\t\t\t\tex as GitError,\n\t\t\t\treason =>\n\t\t\t\t\tnew WorktreeDeleteError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\tlockReason: reason === 'locked' ? getLockReason(ex as GitError) : undefined,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex as GitError,\n\t\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (gitError.details.reason === 'directoryNotEmpty') {\n\t\t\t\tscope?.warn(\n\t\t\t\t\t`Failed to fully delete worktree '${pathStr}' because it is not empty. Attempting to delete it manually.`,\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tawait fs.rm(pathStr, { force: true, recursive: true });\n\t\t\t\t\tdeleted = true;\n\t\t\t\t\treturn;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tif (isWindows) {\n\t\t\t\t\t\tconst match = /EPERM: operation not permitted, unlink '(.*?)'/i.exec((ex as GitError).message);\n\t\t\t\t\t\tif (match != null) {\n\t\t\t\t\t\t\tscope?.warn(\n\t\t\t\t\t\t\t\t`Failed to manually delete '${pathStr}' because it is in use. Attempting to forcefully delete it.`,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Windows-specific: `del` via cmd.exe to force-remove a locked symlink.\n\t\t\t\t\t\t\t// Node's fs.rm/unlink fails with EPERM when the symlink target is in use.\n\t\t\t\t\t\t\tfunction deleteInUseSymlink(symlink: string) {\n\t\t\t\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\t\t\t\texec(`del \"${symlink}\"`, (ex, stdout, stderr) => {\n\t\t\t\t\t\t\t\t\t\tif (ex) {\n\t\t\t\t\t\t\t\t\t\t\treject(ex instanceof Error ? ex : new Error(String(ex)));\n\t\t\t\t\t\t\t\t\t\t} else if (stderr) {\n\t\t\t\t\t\t\t\t\t\t\treject(new Error(stderr));\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tresolve(stdout);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst [, file] = match;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait deleteInUseSymlink(file);\n\t\t\t\t\t\t\t\tawait fs.rm(pathStr, { force: true, recursive: true, maxRetries: 1, retryDelay: 1 });\n\t\t\t\t\t\t\t\tdeleted = true;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t\t\tscope?.error(ex, `Failed to forcefully delete '${pathStr}' because it is in use.`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow gitError;\n\t\t} finally {\n\t\t\tif (deleted) {\n\t\t\t\t// Clean up Cache registry + per-worktree cache entries for the deleted worktree.\n\t\t\t\t// Order matters: unregister before emitting the repo-level change so any listener\n\t\t\t\t// that re-queries worktree-aware state sees the registry already updated.\n\t\t\t\tthis.cache.unregisterRepoPath(pathStr);\n\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'worktrees');\n\t\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['worktrees']);\n\t\t\t}\n\t\t}\n\t}\n\n\t@debug()\n\tasync pruneWorktrees(repoPath: string, options?: { expire?: string }): Promise<void> {\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Pruning worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tconst before = await this.listWorktreePaths(repoPath);\n\n\t\tconst args = ['worktree', 'prune'];\n\t\tif (options?.expire) {\n\t\t\targs.push('--expire', options.expire);\n\t\t}\n\n\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...args);\n\n\t\tconst after = await this.listWorktreePaths(repoPath);\n\n\t\t// Order matters (see `deleteWorktree`): unregister before emitting the repo-level change so any\n\t\t// listener that re-queries worktree-aware state sees the registry already updated.\n\t\tif (before != null && after != null) {\n\t\t\tfor (const path of before) {\n\t\t\t\tif (!after.has(path)) {\n\t\t\t\t\tthis.cache.unregisterRepoPath(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'worktrees');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['worktrees']);\n\t}\n\n\t/**\n\t * Raw worktree paths currently known to git (`worktree <path>` lines from `--porcelain`), normalized the\n\t * same way {@link deleteWorktree} does. A failed listing (`errors: 'ignore'`) yields an empty set rather\n\t * than throwing — used by `pruneWorktrees` to diff before/after, where a transient read failure must not\n\t * be mistaken for every worktree having vanished.\n\t */\n\tprivate async listWorktreePaths(repoPath: string): Promise<Set<string> | undefined> {\n\t\tconst result = await this.git.run({ cwd: repoPath, errors: 'ignore' }, 'worktree', 'list', '--porcelain');\n\t\t// A failed listing is not an empty one: read as empty, the after-prune one would unregister everything\n\t\tif (result.completion.status !== 'exited' || result.exitCode !== 0) return undefined;\n\n\t\tconst paths = new Set<string>();\n\t\tfor (const line of result.stdout.split('\\n')) {\n\t\t\tif (line.startsWith('worktree ')) {\n\t\t\t\tpaths.add(normalizePath(toFsPath(line.slice('worktree '.length).trim())));\n\t\t\t}\n\t\t}\n\t\treturn paths;\n\t}\n\n\t@debug()\n\tasync lockWorktree(repoPath: string, path: string | Uri, options?: { reason?: string }): Promise<void> {\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Locking worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tconst args = ['worktree', 'lock'];\n\t\tif (options?.reason) {\n\t\t\targs.push('--reason', options.reason);\n\t\t}\n\t\targs.push(normalizePath(toFsPath(path)));\n\n\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...args);\n\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'worktrees');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['worktrees']);\n\t}\n\n\t@debug()\n\tasync unlockWorktree(repoPath: string, path: string | Uri): Promise<void> {\n\t\tawait this.git.ensureSupports('git:worktrees', (requiredVersion, installedVersion) =>\n\t\t\tl10n.t(\n\t\t\t\t'Unlocking worktrees requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git and try again.',\n\t\t\t\trequiredVersion,\n\t\t\t\tinstalledVersion,\n\t\t\t),\n\t\t);\n\n\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, 'worktree', 'unlock', normalizePath(toFsPath(path)));\n\n\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'worktrees');\n\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['worktrees']);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,SAAS,cAAc,IAAkC;CACxD,OAAO,UAAU,qBAAqB,KAAK,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,KAAA;AACvG;AAEA,IAAa,0BAAb,MAAwE;CAErD;CACA;CACA;CACA;CAJlB,YACC,SACA,KACA,OACA,UACC;EAJgB,KAAA,UAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;CACf;;;;;CAMH,MACM,eACL,UACA,MACA,SAOA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,OAAO,CAAC,YAAY,KAAK;EAC/B,IAAI,SAAS,OACZ,KAAK,KAAK,SAAS;EAEpB,IAAI,SAAS,cACZ,KAAK,KAAK,MAAM,QAAQ,YAAY;EAErC,IAAI,SAAS,gBAAgB,QAAQ,YACpC,KAAK,KAAK,YAAY;EAEvB,IAAI,SAAS,QACZ,KAAK,KAAK,UAAU;EAErB,KAAK,KAAK,IAAI;EACd,IAAI,SAAS,WACZ,KAAK,KAAK,QAAQ,SAAS;EAG5B,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,GAAG;GAAW,GAAG,GAAG,IAAI;GAE5D,IAAI,SAAS,cAEZ,KAAK,MAAM,qBAAqB,UAAU,QAAQ,YAAY;GAG/D,KAAK,QAAQ,OAAO,OAAO,UAC1B,UACA,GAAI,SAAS,eAAgB,CAAC,YAAY,WAAW,IAAe,CAAC,WAAW,CACjF;GACA,KAAK,QAAQ,OAAO,YAAY,YAC/B,UACA,SAAS,eAAe,CAAC,aAAa,OAAO,IAAI,CAAC,WAAW,CAC9D;EACD,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GAEf,IAAI,oBAAoB,EAAE,GAAG,MAAM;GAEnC,MAAM,mBACL,mBACA,KACA,WACC,IAAI,oBACH;IAAU;IAAQ,YAAY;KAAY;KAAgB;IAAK;GAAE,GACjE,EACD,CACF;EACD;CACD;CAEA,MAAM,yBACL,UACA,MACA,SAOA,YACmC;EACnC,MAAM,KAAK,eAAe,UAAU,MAAM,SAAS,UAAU;EAC7D,MAAM,aAAa,cAAc,IAAI;EACrC,OAAO,KAAK,YAAY,WAAU,MAAK,cAAc,EAAE,IAAI,MAAM,YAAY,YAAY,YAAY;CACtG;CAEA,MACM,YACL,UACA,WACA,cACmC;EACnC,QAAQ,MAAM,KAAK,aAAa,UAAU,YAAY,EAAA,CAAG,KAAK,SAAS;CACxE;CAEA,MACM,aAAa,UAAkB,cAAoD;EACxF,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,+JACA,iBACA,gBACD,CACD;EAEA,OAAO,KAAK,MAAM,aACjB,UACA,OAAO,YAAY,WAAW,WAAW;GAExC,WAAW;GACX,MAAM,CAAC,YAAY,kBAAkB,MAAM,QAAQ,WAAW,CAC7D,KAAK,IAAI,IAAI;IAAE,KAAK;IAAY,cAAc;GAAO,GAAG,YAAY,QAAQ,aAAa,GACzF,KAAK,SAAS,SAAS,YAAY,YAAY,KAAA,GAAW,MAAM,CACjE,CAAC;GAED,IAAI,WAAW,WAAW,YAEzB,UAAU,WAAW;GAGtB,MAAM,qBAA0D,KAAK,QAAQ,aAC1E,QAAO;IACP,MAAM,SAAS,KAAK,QAAQ,UAAW,UAAU,IAAI,MAAM;IAC3D,IAAI,UAAU,MAAM,OAAO,KAAA;IAC3B,OAAO;KAAE,KAAK,QAAQ,OAAO,IAAI;KAAG,MAAM,SAAS,OAAO,IAAI;IAAE;GACjE,IACC,KAAA;GAEH,OAAO,kBACN,gBAAgB,UAAU,CAAC,EAAE,QAC7B,YACA,gBAAgB,cAAc,CAAC,EAAE,UAAU,CAAC,GAC5C,kBACD;EACD,GACA,YACD;CACD;CAEA,uBACuB,UAAmC;EACzD,OAAO,KAAK,QAAQ,WAAW,wBAAwB,QAAQ;CAChE;;;;;;;;;;;;CAaA,MACM,eACL,UACA,MACA,SACA,YACgB;EAChB,MAAM,QAAQ,gBAAgB;EAE9B,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,6JACA,iBACA,gBACD,CACD;EAEA,MAAM,OAAO,CAAC,YAAY,QAAQ;EAClC,IAAI,SAAS,OAAO;GACnB,KAAK,KAAK,SAAS;GAEnB,IAAI,QAAQ,UAAU,UACrB,KAAK,KAAK,SAAS;EAErB;EAEA,MAAM,UAAU,cAAc,SAAS,IAAI,CAAC;EAC5C,KAAK,KAAK,OAAO;EAEjB,IAAI,UAAU;EACd,IAAI;GACH,MAAM,KAAK,IAAI,IAAI;IAAE,KAAK;IAAU,QAAQ;IAAS,GAAG;GAAW,GAAG,GAAG,IAAI;GAC7E,UAAU;EACX,SAAS,IAAI;GACZ,OAAO,MAAM,EAAE;GAGf,IAAI,oBAAoB,EAAE,GAAG,MAAM;GAEnC,MAAM,WAAW,mBAChB,mBACA,KACA,WACC,IAAI,oBACH;IACS;IACR,YAAY,WAAW,WAAW,cAAc,EAAc,IAAI,KAAA;IAClE,YAAY;KAAY;KAAgB;IAAK;GAC9C,GACA,EACD,CACF;GAEA,IAAI,SAAS,QAAQ,WAAW,qBAAqB;IACpD,OAAO,KACN,oCAAoC,QAAQ,6DAC7C;IACA,IAAI;KACH,MAAMA,SAAG,GAAG,SAAS;MAAE,OAAO;MAAM,WAAW;KAAK,CAAC;KACrD,UAAU;KACV;IACD,SAAS,IAAI;KACZ,IAAI,WAAW;MACd,MAAM,QAAQ,kDAAkD,KAAM,GAAgB,OAAO;MAC7F,IAAI,SAAS,MAAM;OAClB,OAAO,KACN,8BAA8B,QAAQ,4DACvC;OAIA,SAAS,mBAAmB,SAAiB;QAC5C,OAAO,IAAI,SAAS,SAAS,WAAW;SACvC,KAAK,QAAQ,QAAQ,KAAK,IAAI,QAAQ,WAAW;UAChD,IAAI,IACH,OAAO,cAAc,QAAQ,KAAK,IAAI,MAAM,OAAO,EAAE,CAAC,CAAC;eACjD,IAAI,QACV,OAAO,IAAI,MAAM,MAAM,CAAC;eAExB,QAAQ,MAAM;SAEhB,CAAC;QACF,CAAC;OACF;OAEA,MAAM,GAAG,QAAQ;OACjB,IAAI;QACH,MAAM,mBAAmB,IAAI;QAC7B,MAAMA,SAAG,GAAG,SAAS;SAAE,OAAO;SAAM,WAAW;SAAM,YAAY;SAAG,YAAY;QAAE,CAAC;QACnF,UAAU;QACV;OACD,SAAS,IAAI;QACZ,OAAO,MAAM,IAAI,gCAAgC,QAAQ,wBAAwB;OAClF;MACD;KACD;IACD;GACD;GAEA,MAAM;EACP,UAAU;GACT,IAAI,SAAS;IAIZ,KAAK,MAAM,mBAAmB,OAAO;IACrC,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW;IAC1D,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,CAAC;GACpE;EACD;CACD;CAEA,MACM,eAAe,UAAkB,SAA8C;EACpF,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,4JACA,iBACA,gBACD,CACD;EAEA,MAAM,SAAS,MAAM,KAAK,kBAAkB,QAAQ;EAEpD,MAAM,OAAO,CAAC,YAAY,OAAO;EACjC,IAAI,SAAS,QACZ,KAAK,KAAK,YAAY,QAAQ,MAAM;EAGrC,MAAM,KAAK,IAAI,IAAI;GAAE,KAAK;GAAU,QAAQ;EAAQ,GAAG,GAAG,IAAI;EAE9D,MAAM,QAAQ,MAAM,KAAK,kBAAkB,QAAQ;EAInD,IAAI,UAAU,QAAQ,SAAS,MACzB;QAAA,MAAM,QAAQ,QAClB,IAAI,CAAC,MAAM,IAAI,IAAI,GAClB,KAAK,MAAM,mBAAmB,IAAI;EAAA;EAKrC,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW;EAC1D,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,CAAC;CACpE;;;;;;;CAQA,MAAc,kBAAkB,UAAoD;EACnF,MAAM,SAAS,MAAM,KAAK,IAAI,IAAI;GAAE,KAAK;GAAU,QAAQ;EAAS,GAAG,YAAY,QAAQ,aAAa;EAExG,IAAI,OAAO,WAAW,WAAW,YAAY,OAAO,aAAa,GAAG,OAAO,KAAA;EAE3E,MAAM,wBAAQ,IAAI,IAAY;EAC9B,KAAK,MAAM,QAAQ,OAAO,OAAO,MAAM,IAAI,GAC1C,IAAI,KAAK,WAAW,WAAW,GAC9B,MAAM,IAAI,cAAc,SAAS,KAAK,MAAM,CAAkB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;EAG1E,OAAO;CACR;CAEA,MACM,aAAa,UAAkB,MAAoB,SAA8C;EACtG,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,4JACA,iBACA,gBACD,CACD;EAEA,MAAM,OAAO,CAAC,YAAY,MAAM;EAChC,IAAI,SAAS,QACZ,KAAK,KAAK,YAAY,QAAQ,MAAM;EAErC,KAAK,KAAK,cAAc,SAAS,IAAI,CAAC,CAAC;EAEvC,MAAM,KAAK,IAAI,IAAI;GAAE,KAAK;GAAU,QAAQ;EAAQ,GAAG,GAAG,IAAI;EAE9D,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW;EAC1D,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,CAAC;CACpE;CAEA,MACM,eAAe,UAAkB,MAAmC;EACzE,MAAM,KAAK,IAAI,eAAe,kBAAkB,iBAAiB,qBAChE,KAAK,EACJ,8JACA,iBACA,gBACD,CACD;EAEA,MAAM,KAAK,IAAI,IAAI;GAAE,KAAK;GAAU,QAAQ;EAAQ,GAAG,YAAY,UAAU,cAAc,SAAS,IAAI,CAAC,CAAC;EAE1G,KAAK,QAAQ,OAAO,OAAO,UAAU,UAAU,WAAW;EAC1D,KAAK,QAAQ,OAAO,YAAY,YAAY,UAAU,CAAC,WAAW,CAAC;CACpE;AACD;AApWE,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,kBAAA,IAAA;AAmFN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,eAAA,IAAA;AASN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,gBAAA,IAAA;AA4CN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,0BAAA,IAAA;AAgBN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,kBAAA,IAAA;AAgHN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,kBAAA,IAAA;AAuDN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,gBAAA,IAAA;AAsBN,WAAA,CAAA,MAAM,CAAA,GAAA,wBAAA,WAAA,kBAAA,IAAA"}
|
|
@@ -395,8 +395,10 @@ export declare class GitHubApi {
|
|
|
395
395
|
*
|
|
396
396
|
* Returns POSITIONALLY — one slot per input coordinate, in order — for the same reason {@link countIssues}
|
|
397
397
|
* does: a caller's key is arbitrary text and would break the GraphQL document, so the aliases are generated
|
|
398
|
-
* and the caller maps back by index. `
|
|
399
|
-
* to this token)
|
|
398
|
+
* and the caller maps back by index. A `fulfilled` slot with `undefined` means the issue does not exist (or
|
|
399
|
+
* is not visible to this token) — a PROVEN ABSENCE. A `rejected` slot means only THAT target failed — e.g. an
|
|
400
|
+
* org enforcing SAML SSO the token isn't authorized for — which is not proof the issue is gone, so it must
|
|
401
|
+
* not be cached as absent. A whole-request failure (bad credentials, rate limit, no data at all) still throws.
|
|
400
402
|
*/
|
|
401
403
|
getIssuesBatch(provider: Provider, token: GitHubTokenInfo, coordinates: readonly {
|
|
402
404
|
owner: string;
|
|
@@ -406,7 +408,66 @@ export declare class GitHubApi {
|
|
|
406
408
|
baseUrl?: string;
|
|
407
409
|
avatarSize?: number;
|
|
408
410
|
includeBody?: boolean;
|
|
409
|
-
}, cancellation?: AbortSignal): Promise<
|
|
411
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<IssueShape | undefined>[]>;
|
|
412
|
+
/**
|
|
413
|
+
* Resolves several pull requests, in any state (open/closed/merged), BY COORDINATE — `(owner, repo, number)`
|
|
414
|
+
* — in one request, via aliased `repository` fields rather than aliased searches. The pull-request twin of
|
|
415
|
+
* {@link getIssuesBatch}; see that method for why aliasing the point read (exact number, no result ceiling,
|
|
416
|
+
* a proven absence) is the design.
|
|
417
|
+
*
|
|
418
|
+
* Selects the FULL {@link gqlPullRequestFragment} — not the lite shape {@link getPullRequest} uses — so a
|
|
419
|
+
* row from this read carries the same fields (reviews, review requests, checks, diff stats, assignees,
|
|
420
|
+
* mergeable state) as {@link searchMyPullRequestsPage}'s account-wide rows.
|
|
421
|
+
*
|
|
422
|
+
* Returns POSITIONALLY — one slot per input coordinate, in order — for the same reason {@link getIssuesBatch}
|
|
423
|
+
* does: a caller's key is arbitrary text and would break the GraphQL document, so the aliases are generated
|
|
424
|
+
* and the caller maps back by index. A `fulfilled` slot with `undefined` means the pull request (or its
|
|
425
|
+
* repository) does not exist or is not visible to this token — a PROVEN ABSENCE. A `rejected` slot means only
|
|
426
|
+
* THAT target failed — e.g. an org enforcing SAML SSO the token isn't authorized for — which is not proof the
|
|
427
|
+
* pull request is gone, so it must not be cached as absent. A whole-request failure still throws.
|
|
428
|
+
*/
|
|
429
|
+
getPullRequestsBatch(provider: Provider, token: GitHubTokenInfo, coordinates: readonly {
|
|
430
|
+
owner: string;
|
|
431
|
+
repo: string;
|
|
432
|
+
number: number;
|
|
433
|
+
}[], options?: {
|
|
434
|
+
baseUrl?: string;
|
|
435
|
+
avatarSize?: number;
|
|
436
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<PullRequest | undefined>[]>;
|
|
437
|
+
/**
|
|
438
|
+
* Finds, for several branches in one request, every pull request whose head is that branch — in any state,
|
|
439
|
+
* most recently updated first, up to `limit` per branch. Each target names the BASE repository the pull
|
|
440
|
+
* requests are opened against, the head branch's short name and, for a branch that lives in a fork,
|
|
441
|
+
* `headOwner`, the fork's owner.
|
|
442
|
+
*
|
|
443
|
+
* Keyed on the head ref NAME (`repository.pullRequests(headRefName:)`) rather than on the ref itself
|
|
444
|
+
* (`repository.ref(qualifiedName:).associatedPullRequests`, which {@link getPullRequestForBranch} uses): a
|
|
445
|
+
* merged pull request's branch is usually deleted afterwards, and the ref lookup then answers "none" for a
|
|
446
|
+
* pull request that exists.
|
|
447
|
+
*
|
|
448
|
+
* `headRefName` matches every fork's branch of that name too, so rows are kept only when their head
|
|
449
|
+
* repository is the base repository itself (`headOwner` omitted) or a fork owned by `headOwner` — otherwise
|
|
450
|
+
* a `main` in the base repository would claim every fork's `main`. That filter runs after the server's
|
|
451
|
+
* `limit`, so `truncated` is set whenever the server matched more rows than it returned, since any of the
|
|
452
|
+
* unfetched ones might have passed it.
|
|
453
|
+
*
|
|
454
|
+
* Returns POSITIONALLY, with the same per-alias rules as {@link getPullRequestsBatch}: a missing base
|
|
455
|
+
* repository (NOT_FOUND on a null repository) is a PROVEN "none" — an empty list — while any other error on
|
|
456
|
+
* a target's alias rejects only that target, and a whole-request failure still throws.
|
|
457
|
+
*/
|
|
458
|
+
getPullRequestsForBranches(provider: Provider, token: GitHubTokenInfo, targets: readonly {
|
|
459
|
+
owner: string;
|
|
460
|
+
repo: string;
|
|
461
|
+
branch: string;
|
|
462
|
+
headOwner?: string;
|
|
463
|
+
}[], options: {
|
|
464
|
+
baseUrl?: string;
|
|
465
|
+
avatarSize?: number;
|
|
466
|
+
limit: number;
|
|
467
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<{
|
|
468
|
+
pullRequests: PullRequest[];
|
|
469
|
+
truncated: boolean;
|
|
470
|
+
}>[]>;
|
|
410
471
|
/**
|
|
411
472
|
* The PR twin of {@link countIssues}: counts pull requests for several scopes in ONE request via aliased
|
|
412
473
|
* `search` fields selecting only `issueCount` with `first: 0`. Same positional/undefined contract as the issue
|