@gitkraken/core-gitlens 0.13.0 → 0.15.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 +43 -2
- package/dist/git/features.d.ts +1 -1
- package/dist/git/features.js +1 -0
- package/dist/git/features.js.map +1 -1
- package/dist/git/models/branch.d.ts +5 -0
- package/dist/git/models/branch.js +1 -1
- package/dist/git/models/branch.js.map +1 -1
- package/dist/git/models/reference.d.ts +3 -0
- package/dist/git/models/status.js +1 -1
- package/dist/git/parsers/diffParser.js +1 -1
- package/dist/git/providers/operations.d.ts +3 -2
- package/dist/git/providers/provider.d.ts +15 -4
- package/dist/git/providers/revision.d.ts +17 -3
- package/dist/git/run.types.d.ts +12 -0
- package/dist/git/utils/branch.utils.d.ts +4 -1
- package/dist/git/utils/branch.utils.js +20 -5
- package/dist/git/utils/branch.utils.js.map +1 -1
- package/dist/git/utils/reference.utils.d.ts +1 -0
- package/dist/git/utils/reference.utils.js.map +1 -1
- package/dist/git-cli/cliGitProvider.d.ts +8 -2
- package/dist/git-cli/cliGitProvider.js +75 -13
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/git.d.ts +5 -0
- package/dist/git-cli/exec/git.js +28 -5
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/exec/indexLock.d.ts +3 -2
- package/dist/git-cli/exec/indexLock.js +16 -6
- package/dist/git-cli/exec/indexLock.js.map +1 -1
- package/dist/git-cli/parsers/blameParser.js +2 -2
- package/dist/git-cli/parsers/refParser.js +4 -2
- package/dist/git-cli/parsers/refParser.js.map +1 -1
- package/dist/git-cli/parsers/statusParser.d.ts +6 -0
- package/dist/git-cli/parsers/statusParser.js +33 -3
- package/dist/git-cli/parsers/statusParser.js.map +1 -1
- package/dist/git-cli/providers/branchRemote.d.ts +14 -0
- package/dist/git-cli/providers/branchRemote.js +36 -0
- package/dist/git-cli/providers/branchRemote.js.map +1 -0
- package/dist/git-cli/providers/branches.js +6 -3
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.js +2 -2
- package/dist/git-cli/providers/config.js +2 -2
- package/dist/git-cli/providers/contributors.js +1 -1
- package/dist/git-cli/providers/graph.js +9 -6
- package/dist/git-cli/providers/graph.js.map +1 -1
- package/dist/git-cli/providers/operations.js +20 -16
- package/dist/git-cli/providers/operations.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/revision.d.ts +6 -2
- package/dist/git-cli/providers/revision.js +38 -12
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/staging.js +1 -1
- package/dist/git-cli/providers/status.js +2 -2
- 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/providers/github/revision.d.ts +6 -2
- package/dist/plus/git-github/providers/github/revision.js +15 -10
- package/dist/plus/git-github/providers/github/revision.js.map +1 -1
- package/dist/plus/git-github/providers/github/status.js +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +7 -0
- package/dist/plus/integrations/collectionMetadata.js +10 -1
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/errors.d.ts +5 -0
- package/dist/plus/integrations/errors.js +10 -1
- package/dist/plus/integrations/errors.js.map +1 -1
- package/dist/plus/integrations/index.d.ts +2 -2
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +6 -2
- package/dist/plus/integrations/models/gitHostIntegration.js +37 -7
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/issueReads.d.ts +1 -1
- package/dist/plus/integrations/models/issuesIntegration.d.ts +33 -3
- package/dist/plus/integrations/models/issuesIntegration.js +76 -5
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.js +1 -1
- package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +5 -0
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js +5 -0
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +9 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.js +17 -9
- package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.js +3 -2
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira-server.d.ts +3 -0
- package/dist/plus/integrations/providers/jira-server.js +15 -7
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +8 -0
- package/dist/plus/integrations/providers/jira.js +88 -58
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/linear.d.ts +4 -0
- package/dist/plus/integrations/providers/linear.js +23 -2
- package/dist/plus/integrations/providers/linear.js.map +1 -1
- package/dist/plus/integrations/providers/providerErrors.d.ts +24 -0
- package/dist/plus/integrations/providers/providerErrors.js +41 -4
- package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +1 -1
- package/dist/plus/integrations/providers/providersApi.js +15 -4
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/trello.d.ts +1 -0
- package/dist/plus/integrations/providers/trello.js +3 -0
- package/dist/plus/integrations/providers/trello.js.map +1 -1
- package/dist/plus/integrations/reads/cursors.js +23 -5
- package/dist/plus/integrations/reads/cursors.js.map +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +16 -0
- package/dist/plus/integrations/reads/drains.js +19 -1
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.js +5 -3
- package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.utils.d.ts +3 -2
- package/dist/plus/integrations/reads/hierarchy.utils.js +4 -7
- package/dist/plus/integrations/reads/hierarchy.utils.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +71 -7
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/plus/integrations/reads/selectionConfirmation.d.ts +69 -0
- package/dist/plus/integrations/reads/selectionConfirmation.js +79 -0
- package/dist/plus/integrations/reads/selectionConfirmation.js.map +1 -0
- package/dist/plus/integrations/reads/warnings.d.ts +9 -3
- package/dist/plus/integrations/reads/warnings.js +19 -3
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +30 -3
- package/dist/plus/integrations/results.js +2 -1
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/utils/env/node/exec.js +2 -2
- package/docs/integrations.md +59 -6
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reference.utils.js","names":[],"sources":["../../../../git/src/utils/reference.utils.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from '@gitlens/utils/gitRefs.js';\nimport type {\n\tGitBranchReference,\n\tGitReference,\n\tGitRevisionReference,\n\tGitStashReference,\n\tGitTagReference,\n} from '../models/reference.js';\nimport { isRevisionRange, isShaWithParentSuffix, shortenRevision } from './revision.utils.js';\n\ninterface GitBranchReferenceOptions {\n\trefType: 'branch';\n\tid?: string;\n\tname: string;\n\tremote: boolean;\n\tsha?: string;\n\tupstream?: { name: string; missing: boolean };\n\tworktree?: { path: string; isDefault: boolean } | boolean;\n}\n\ninterface GitCommitReferenceOptions {\n\trefType: 'revision';\n\tname?: string;\n\tmessage?: string;\n}\n\ninterface GitStashReferenceOptions {\n\trefType: 'stash';\n\tname: string;\n\tnumber: string | undefined;\n\tmessage?: string;\n\tstashOnRef?: string;\n}\n\ninterface GitTagReferenceOptions {\n\trefType: 'tag';\n\tid?: string;\n\tname: string;\n\tsha?: string;\n}\n\nexport function createReference(ref: string, repoPath: string, options: GitBranchReferenceOptions): GitBranchReference;\nexport function createReference(ref: string, repoPath: string, options: GitStashReferenceOptions): GitStashReference;\nexport function createReference(ref: string, repoPath: string, options: GitTagReferenceOptions): GitTagReference;\nexport function createReference(\n\tref: string,\n\trepoPath: string,\n\toptions?: GitCommitReferenceOptions,\n): GitRevisionReference;\nexport function createReference(\n\tref: string,\n\trepoPath: string,\n\toptions:\n\t\t| GitBranchReferenceOptions\n\t\t| GitStashReferenceOptions\n\t\t| GitTagReferenceOptions\n\t\t| GitCommitReferenceOptions = { refType: 'revision' },\n): GitReference {\n\tswitch (options.refType) {\n\t\tcase 'branch':\n\t\t\treturn {\n\t\t\t\trefType: 'branch',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tname: options.name,\n\t\t\t\tid: options.id,\n\t\t\t\tremote: options.remote,\n\t\t\t\tsha: options.sha,\n\t\t\t\tupstream: options.upstream,\n\t\t\t\tworktree: options.worktree,\n\t\t\t};\n\t\tcase 'stash':\n\t\t\treturn {\n\t\t\t\trefType: 'stash',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tsha: ref,\n\t\t\t\tname: options.name,\n\t\t\t\tstashNumber: options.number,\n\t\t\t\tmessage: options.message,\n\t\t\t\tstashOnRef: options.stashOnRef,\n\t\t\t};\n\t\tcase 'tag':\n\t\t\treturn {\n\t\t\t\trefType: 'tag',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tname: options.name,\n\t\t\t\tid: options.id,\n\t\t\t\tsha: options.sha,\n\t\t\t};\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\trefType: 'revision',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tsha: ref,\n\t\t\t\tname:\n\t\t\t\t\toptions.name ??\n\t\t\t\t\tshortenRevision(ref, {\n\t\t\t\t\t\tstrings: {\n\t\t\t\t\t\t\tuncommitted: l10n.t('Working Tree'),\n\t\t\t\t\t\t\tuncommittedStaged: l10n.t('Index'),\n\t\t\t\t\t\t\tworking: l10n.t('Working Tree'),\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\tmessage: options.message,\n\t\t\t};\n\t}\n}\n\nexport function getReferenceNameWithoutRemote(ref: GitReference): string {\n\tif (ref.refType === 'branch') {\n\t\treturn ref.remote ? getBranchNameWithoutRemote(ref.name) : ref.name;\n\t}\n\treturn ref.name;\n}\n\nexport function getReferenceTypeLabel(ref: GitReference | undefined): string {\n\tswitch (ref?.refType) {\n\t\tcase 'branch':\n\t\t\treturn l10n.t('Branch');\n\t\tcase 'stash':\n\t\t\treturn l10n.t('Stash');\n\t\tcase 'tag':\n\t\t\treturn l10n.t('Tag');\n\t\tdefault:\n\t\t\treturn l10n.t('Commit');\n\t}\n}\n\nexport function isBranchReference(ref: GitReference | undefined): ref is GitBranchReference {\n\treturn ref?.refType === 'branch';\n}\n\nexport function isGitReference(ref: unknown): ref is GitReference {\n\tif (ref == null || typeof ref !== 'object') return false;\n\n\tconst r = ref as GitReference;\n\treturn (\n\t\ttypeof r.refType === 'string' &&\n\t\ttypeof r.repoPath === 'string' &&\n\t\ttypeof r.ref === 'string' &&\n\t\ttypeof r.name === 'string'\n\t);\n}\n\nexport function isRevisionReference(ref: GitReference | undefined): ref is GitRevisionReference {\n\treturn ref?.refType === 'revision';\n}\n\nexport function isRevisionRangeReference(ref: GitReference | undefined): ref is GitRevisionReference {\n\treturn ref?.refType === 'revision' && isRevisionRange(ref.ref);\n}\n\nexport function isStashReference(ref: GitReference | undefined): ref is GitStashReference {\n\treturn ref?.refType === 'stash' || (ref?.refType === 'revision' && Boolean('stashName' in ref && ref.stashName));\n}\n\nexport function isTagReference(ref: GitReference | undefined): ref is GitTagReference {\n\treturn ref?.refType === 'tag';\n}\n\nexport function getReferenceLabel(\n\trefs: GitReference | GitReference[] | undefined,\n\toptions?: { capitalize?: boolean; expand?: boolean; icon?: boolean; label?: boolean; quoted?: boolean } | false,\n): string {\n\tif (refs == null) return '';\n\n\toptions =\n\t\toptions === false\n\t\t\t? {}\n\t\t\t: { expand: true, icon: true, label: options?.label ?? options?.expand ?? true, ...options };\n\n\tlet result;\n\tif (!Array.isArray(refs) || refs.length === 1) {\n\t\tconst ref = Array.isArray(refs) ? refs[0] : refs;\n\t\tlet refName = options?.quoted ? `'${ref.name}'` : ref.name;\n\t\tswitch (ref.refType) {\n\t\t\tcase 'branch': {\n\t\t\t\tif (ref.remote) {\n\t\t\t\t\trefName = `${getRemoteNameFromBranchName(refName)}: ${getBranchNameWithoutRemote(refName)}`;\n\t\t\t\t\trefName = options?.quoted ? `'${refName}'` : refName;\n\t\t\t\t}\n\n\t\t\t\tif (options.label) {\n\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\tif (options.capitalize && options.expand) {\n\t\t\t\t\t\t\tresult = ref.remote\n\t\t\t\t\t\t\t\t? l10n.t('Remote Branch $(git-branch)\\u00a0{0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('Branch $(git-branch)\\u00a0{0}', refName);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult = ref.remote\n\t\t\t\t\t\t\t\t? l10n.t('remote branch $(git-branch)\\u00a0{0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('branch $(git-branch)\\u00a0{0}', refName);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (options.capitalize && options.expand) {\n\t\t\t\t\t\tresult = ref.remote ? l10n.t('Remote Branch {0}', refName) : l10n.t('Branch {0}', refName);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = ref.remote ? l10n.t('remote branch {0}', refName) : l10n.t('branch {0}', refName);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult = options.icon ? `$(git-branch)\\u00a0${refName}` : refName;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'tag':\n\t\t\t\tif (options.label) {\n\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t? l10n.t('Tag $(tag)\\u00a0{0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('tag $(tag)\\u00a0{0}', refName);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t? l10n.t('Tag {0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('tag {0}', refName);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult = options.icon ? `$(tag)\\u00a0${refName}` : refName;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tif (isStashReference(ref)) {\n\t\t\t\t\tlet message;\n\t\t\t\t\tif (options.expand && ref.message) {\n\t\t\t\t\t\tmessage = `${ref.stashNumber != null ? `#${ref.stashNumber}: ` : ''}${\n\t\t\t\t\t\t\tref.message.length > 20 ? `${ref.message.substring(0, 20).trimEnd()}\\u2026` : ref.message\n\t\t\t\t\t\t}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst stashName = message ?? (ref.stashNumber ? `#${ref.stashNumber}` : ref.name);\n\t\t\t\t\tif (options.label) {\n\t\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t? l10n.t('Stash $(archive)\\u00a0{0}', message ?? ref.name)\n\t\t\t\t\t\t\t\t\t: l10n.t('stash $(archive)\\u00a0{0}', message ?? ref.name);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t? l10n.t('Stash {0}', stashName)\n\t\t\t\t\t\t\t\t\t: l10n.t('stash {0}', stashName);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = options.icon ? `$(archive)\\u00a0${message ?? ref.name}` : stashName;\n\t\t\t\t\t}\n\t\t\t\t} else if (isRevisionRange(ref.ref)) {\n\t\t\t\t\tresult = refName;\n\t\t\t\t} else {\n\t\t\t\t\tlet message;\n\t\t\t\t\tif (options.expand && ref.message) {\n\t\t\t\t\t\tmessage =\n\t\t\t\t\t\t\tref.message.length > 20\n\t\t\t\t\t\t\t\t? ` (${ref.message.substring(0, 20).trimEnd()}\\u2026)`\n\t\t\t\t\t\t\t\t: ` (${ref.message})`;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet before = false;\n\t\t\t\t\tif (options.expand && options.label && isShaWithParentSuffix(ref.ref)) {\n\t\t\t\t\t\trefName = ref.name.endsWith('^') ? ref.name.substring(0, ref.name.length - 1) : ref.name;\n\t\t\t\t\t\tif (options?.quoted) {\n\t\t\t\t\t\t\trefName = `'${refName}'`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbefore = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (options.label) {\n\t\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\t\tif (before) {\n\t\t\t\t\t\t\t\tresult = options.capitalize\n\t\t\t\t\t\t\t\t\t? l10n.t('Before commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t\t: l10n.t('before commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t\t? l10n.t('Commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t\t\t: l10n.t('commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (before) {\n\t\t\t\t\t\t\tresult = options.capitalize\n\t\t\t\t\t\t\t\t? l10n.t('Before commit {0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t: l10n.t('before commit {0}{1}', refName, message ?? '');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t? l10n.t('Commit {0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t\t: l10n.t('commit {0}{1}', refName, message ?? '');\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = options.icon\n\t\t\t\t\t\t\t? `$(git-commit)\\u00a0${refName}${message ?? ''}`\n\t\t\t\t\t\t\t: `${refName}${message ?? ''}`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tconst expanded = options.expand ? ` (${refs.map(r => r.name).join(', ')})` : '';\n\tswitch (refs[0].refType) {\n\t\tcase 'branch':\n\t\t\treturn l10n.t('{0} branches{1}', refs.length, expanded);\n\t\tcase 'tag':\n\t\t\treturn l10n.t('{0} tags{1}', refs.length, expanded);\n\t\tdefault:\n\t\t\treturn isStashReference(refs[0])\n\t\t\t\t? l10n.t('{0} stashes{1}', refs.length, expanded)\n\t\t\t\t: l10n.t('{0} commits{1}', refs.length, expanded);\n\t}\n}\n\nexport function getReferenceTypeIcon(ref: GitReference | undefined, webview?: boolean): string {\n\tswitch (ref?.refType) {\n\t\tcase 'branch':\n\t\t\tif (ref.remote) return 'cloud';\n\t\t\tif (ref.worktree) return webview ? 'gl-worktree' : 'gitlens-worktree';\n\t\t\treturn 'git-branch';\n\t\tcase 'tag':\n\t\t\treturn 'tag';\n\t\tcase 'stash':\n\t\t\treturn 'archive';\n\t\tdefault:\n\t\t\treturn 'git-commit';\n\t}\n}\n"],"mappings":";;;;AAkDA,SAAgB,gBACf,KACA,UACA,UAI+B,EAAE,SAAS,WAAW,GACtC;CACf,QAAQ,QAAQ,SAAhB;EACC,KAAK,UACJ,OAAO;GACN,SAAS;GACC;GACL;GACL,MAAM,QAAQ;GACd,IAAI,QAAQ;GACZ,QAAQ,QAAQ;GAChB,KAAK,QAAQ;GACb,UAAU,QAAQ;GAClB,UAAU,QAAQ;EACnB;EACD,KAAK,SACJ,OAAO;GACN,SAAS;GACC;GACL;GACL,KAAK;GACL,MAAM,QAAQ;GACd,aAAa,QAAQ;GACrB,SAAS,QAAQ;GACjB,YAAY,QAAQ;EACrB;EACD,KAAK,OACJ,OAAO;GACN,SAAS;GACC;GACL;GACL,MAAM,QAAQ;GACd,IAAI,QAAQ;GACZ,KAAK,QAAQ;EACd;EACD,SACC,OAAO;GACN,SAAS;GACC;GACL;GACL,KAAK;GACL,MACC,QAAQ,QACR,gBAAgB,KAAK,EACpB,SAAS;IACR,aAAa,KAAK,EAAE,cAAc;IAClC,mBAAmB,KAAK,EAAE,OAAO;IACjC,SAAS,KAAK,EAAE,cAAc;GAC/B,EACD,CAAC;GACF,SAAS,QAAQ;EAClB;CACF;AACD;AAEA,SAAgB,8BAA8B,KAA2B;CACxE,IAAI,IAAI,YAAY,UACnB,OAAO,IAAI,SAAS,2BAA2B,IAAI,IAAI,IAAI,IAAI;CAEhE,OAAO,IAAI;AACZ;AAEA,SAAgB,sBAAsB,KAAuC;CAC5E,QAAQ,KAAK,SAAb;EACC,KAAK,UACJ,OAAO,KAAK,EAAE,QAAQ;EACvB,KAAK,SACJ,OAAO,KAAK,EAAE,OAAO;EACtB,KAAK,OACJ,OAAO,KAAK,EAAE,KAAK;EACpB,SACC,OAAO,KAAK,EAAE,QAAQ;CACxB;AACD;AAEA,SAAgB,kBAAkB,KAA0D;CAC3F,OAAO,KAAK,YAAY;AACzB;AAEA,SAAgB,eAAe,KAAmC;CACjE,IAAI,OAAO,QAAQ,OAAO,QAAQ,UAAU,OAAO;CAEnD,MAAM,IAAI;CACV,OACC,OAAO,EAAE,YAAY,YACrB,OAAO,EAAE,aAAa,YACtB,OAAO,EAAE,QAAQ,YACjB,OAAO,EAAE,SAAS;AAEpB;AAEA,SAAgB,oBAAoB,KAA4D;CAC/F,OAAO,KAAK,YAAY;AACzB;AAEA,SAAgB,yBAAyB,KAA4D;CACpG,OAAO,KAAK,YAAY,cAAc,gBAAgB,IAAI,GAAG;AAC9D;AAEA,SAAgB,iBAAiB,KAAyD;CACzF,OAAO,KAAK,YAAY,WAAY,KAAK,YAAY,cAAc,QAAQ,eAAe,OAAO,IAAI,SAAS;AAC/G;AAEA,SAAgB,eAAe,KAAuD;CACrF,OAAO,KAAK,YAAY;AACzB;AAEA,SAAgB,kBACf,MACA,SACS;CACT,IAAI,QAAQ,MAAM,OAAO;CAEzB,UACC,YAAY,QACT,CAAC,IACD;EAAE,QAAQ;EAAM,MAAM;EAAM,OAAO,SAAS,SAAS,SAAS,UAAU;EAAM,GAAG;CAAQ;CAE7F,IAAI;CACJ,IAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,GAAG;EAC9C,MAAM,MAAM,MAAM,QAAQ,IAAI,IAAI,KAAK,KAAK;EAC5C,IAAI,UAAU,SAAS,SAAS,IAAI,IAAI,KAAK,KAAK,IAAI;EACtD,QAAQ,IAAI,SAAZ;GACC,KAAK;IACJ,IAAI,IAAI,QAAQ;KACf,UAAU,GAAG,4BAA4B,OAAO,EAAE,IAAI,2BAA2B,OAAO;KACxF,UAAU,SAAS,SAAS,IAAI,QAAQ,KAAK;IAC9C;IAEA,IAAI,QAAQ,OAAO;KAClB,IAAI,QAAQ,MAAM;MACjB,IAAI,QAAQ,cAAc,QAAQ,QACjC,SAAS,IAAI,SACV,KAAK,EAAE,sCAAwC,OAAO,IACtD,KAAK,EAAE,+BAAiC,OAAO;WAElD,SAAS,IAAI,SACV,KAAK,EAAE,sCAAwC,OAAO,IACtD,KAAK,EAAE,+BAAiC,OAAO;KAEpD,OAAO,IAAI,QAAQ,cAAc,QAAQ,QACxC,SAAS,IAAI,SAAS,KAAK,EAAE,qBAAqB,OAAO,IAAI,KAAK,EAAE,cAAc,OAAO;UAEzF,SAAS,IAAI,SAAS,KAAK,EAAE,qBAAqB,OAAO,IAAI,KAAK,EAAE,cAAc,OAAO;IAE3F,OACC,SAAS,QAAQ,OAAO,sBAAsB,YAAY;IAE3D;GAED,KAAK;IACJ,IAAI,QAAQ,OAAO;KAClB,IAAI,QAAQ,MACX,SACC,QAAQ,cAAc,QAAQ,SAC3B,KAAK,EAAE,qBAAuB,OAAO,IACrC,KAAK,EAAE,qBAAuB,OAAO;UAEzC,SACC,QAAQ,cAAc,QAAQ,SAC3B,KAAK,EAAE,WAAW,OAAO,IACzB,KAAK,EAAE,WAAW,OAAO;IAE/B,OACC,SAAS,QAAQ,OAAO,eAAe,YAAY;IAEpD;GACD,SACC,IAAI,iBAAiB,GAAG,GAAG;IAC1B,IAAI;IACJ,IAAI,QAAQ,UAAU,IAAI,SACzB,UAAU,GAAG,IAAI,eAAe,OAAO,IAAI,IAAI,YAAY,MAAM,KAChE,IAAI,QAAQ,SAAS,KAAK,GAAG,IAAI,QAAQ,UAAU,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,UAAU,IAAI;IAIpF,MAAM,YAAY,YAAY,IAAI,cAAc,IAAI,IAAI,gBAAgB,IAAI;IAC5E,IAAI,QAAQ,OAAO;KAClB,IAAI,QAAQ,MACX,SACC,QAAQ,cAAc,QAAQ,SAC3B,KAAK,EAAE,2BAA6B,WAAW,IAAI,IAAI,IACvD,KAAK,EAAE,2BAA6B,WAAW,IAAI,IAAI;UAE3D,SACC,QAAQ,cAAc,QAAQ,SAC3B,KAAK,EAAE,aAAa,SAAS,IAC7B,KAAK,EAAE,aAAa,SAAS;IAEnC,OACC,SAAS,QAAQ,OAAO,mBAAmB,WAAW,IAAI,SAAS;GAErE,OAAO,IAAI,gBAAgB,IAAI,GAAG,GACjC,SAAS;QACH;IACN,IAAI;IACJ,IAAI,QAAQ,UAAU,IAAI,SACzB,UACC,IAAI,QAAQ,SAAS,KAClB,KAAK,IAAI,QAAQ,UAAU,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,WAC5C,KAAK,IAAI,QAAQ;IAGtB,IAAI,SAAS;IACb,IAAI,QAAQ,UAAU,QAAQ,SAAS,sBAAsB,IAAI,GAAG,GAAG;KACtE,UAAU,IAAI,KAAK,SAAS,GAAG,IAAI,IAAI,KAAK,UAAU,GAAG,IAAI,KAAK,SAAS,CAAC,IAAI,IAAI;KACpF,IAAI,SAAS,QACZ,UAAU,IAAI,QAAQ;KAEvB,SAAS;IACV;IAEA,IAAI,QAAQ,OAAO;KAClB,IAAI,QAAQ,MAAM;MACjB,IAAI,QACH,SAAS,QAAQ,aACd,KAAK,EAAE,yCAA2C,SAAS,WAAW,EAAE,IACxE,KAAK,EAAE,yCAA2C,SAAS,WAAW,EAAE;WAE3E,SACC,QAAQ,cAAc,QAAQ,SAC3B,KAAK,EAAE,kCAAoC,SAAS,WAAW,EAAE,IACjE,KAAK,EAAE,kCAAoC,SAAS,WAAW,EAAE;KAEvE,OAAO,IAAI,QACV,SAAS,QAAQ,aACd,KAAK,EAAE,wBAAwB,SAAS,WAAW,EAAE,IACrD,KAAK,EAAE,wBAAwB,SAAS,WAAW,EAAE;UAExD,SACC,QAAQ,cAAc,QAAQ,SAC3B,KAAK,EAAE,iBAAiB,SAAS,WAAW,EAAE,IAC9C,KAAK,EAAE,iBAAiB,SAAS,WAAW,EAAE;IAEpD,OACC,SAAS,QAAQ,OACd,sBAAsB,UAAU,WAAW,OAC3C,GAAG,UAAU,WAAW;GAE7B;EAGF;EAEA,OAAO;CACR;CAEA,MAAM,WAAW,QAAQ,SAAS,KAAK,KAAK,KAAI,MAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,KAAK;CAC7E,QAAQ,KAAK,EAAE,CAAC,SAAhB;EACC,KAAK,UACJ,OAAO,KAAK,EAAE,mBAAmB,KAAK,QAAQ,QAAQ;EACvD,KAAK,OACJ,OAAO,KAAK,EAAE,eAAe,KAAK,QAAQ,QAAQ;EACnD,SACC,OAAO,iBAAiB,KAAK,EAAE,IAC5B,KAAK,EAAE,kBAAkB,KAAK,QAAQ,QAAQ,IAC9C,KAAK,EAAE,kBAAkB,KAAK,QAAQ,QAAQ;CACnD;AACD;AAEA,SAAgB,qBAAqB,KAA+B,SAA2B;CAC9F,QAAQ,KAAK,SAAb;EACC,KAAK;GACJ,IAAI,IAAI,QAAQ,OAAO;GACvB,IAAI,IAAI,UAAU,OAAO,UAAU,gBAAgB;GACnD,OAAO;EACR,KAAK,OACJ,OAAO;EACR,KAAK,SACJ,OAAO;EACR,SACC,OAAO;CACT;AACD"}
|
|
1
|
+
{"version":3,"file":"reference.utils.js","names":[],"sources":["../../../../git/src/utils/reference.utils.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from '@gitlens/utils/gitRefs.js';\nimport type {\n\tGitBranchReference,\n\tGitReference,\n\tGitRevisionReference,\n\tGitStashReference,\n\tGitTagReference,\n} from '../models/reference.js';\nimport { isRevisionRange, isShaWithParentSuffix, shortenRevision } from './revision.utils.js';\n\ninterface GitBranchReferenceOptions {\n\trefType: 'branch';\n\tid?: string;\n\tname: string;\n\tremote: boolean;\n\tsha?: string;\n\tupstream?: { name: string; missing: boolean; remote?: string };\n\tworktree?: { path: string; isDefault: boolean } | boolean;\n}\n\ninterface GitCommitReferenceOptions {\n\trefType: 'revision';\n\tname?: string;\n\tmessage?: string;\n}\n\ninterface GitStashReferenceOptions {\n\trefType: 'stash';\n\tname: string;\n\tnumber: string | undefined;\n\tmessage?: string;\n\tstashOnRef?: string;\n}\n\ninterface GitTagReferenceOptions {\n\trefType: 'tag';\n\tid?: string;\n\tname: string;\n\tsha?: string;\n}\n\nexport function createReference(ref: string, repoPath: string, options: GitBranchReferenceOptions): GitBranchReference;\nexport function createReference(ref: string, repoPath: string, options: GitStashReferenceOptions): GitStashReference;\nexport function createReference(ref: string, repoPath: string, options: GitTagReferenceOptions): GitTagReference;\nexport function createReference(\n\tref: string,\n\trepoPath: string,\n\toptions?: GitCommitReferenceOptions,\n): GitRevisionReference;\nexport function createReference(\n\tref: string,\n\trepoPath: string,\n\toptions:\n\t\t| GitBranchReferenceOptions\n\t\t| GitStashReferenceOptions\n\t\t| GitTagReferenceOptions\n\t\t| GitCommitReferenceOptions = { refType: 'revision' },\n): GitReference {\n\tswitch (options.refType) {\n\t\tcase 'branch':\n\t\t\treturn {\n\t\t\t\trefType: 'branch',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tname: options.name,\n\t\t\t\tid: options.id,\n\t\t\t\tremote: options.remote,\n\t\t\t\tsha: options.sha,\n\t\t\t\tupstream: options.upstream,\n\t\t\t\tworktree: options.worktree,\n\t\t\t};\n\t\tcase 'stash':\n\t\t\treturn {\n\t\t\t\trefType: 'stash',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tsha: ref,\n\t\t\t\tname: options.name,\n\t\t\t\tstashNumber: options.number,\n\t\t\t\tmessage: options.message,\n\t\t\t\tstashOnRef: options.stashOnRef,\n\t\t\t};\n\t\tcase 'tag':\n\t\t\treturn {\n\t\t\t\trefType: 'tag',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tname: options.name,\n\t\t\t\tid: options.id,\n\t\t\t\tsha: options.sha,\n\t\t\t};\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\trefType: 'revision',\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tref: ref,\n\t\t\t\tsha: ref,\n\t\t\t\tname:\n\t\t\t\t\toptions.name ??\n\t\t\t\t\tshortenRevision(ref, {\n\t\t\t\t\t\tstrings: {\n\t\t\t\t\t\t\tuncommitted: l10n.t('Working Tree'),\n\t\t\t\t\t\t\tuncommittedStaged: l10n.t('Index'),\n\t\t\t\t\t\t\tworking: l10n.t('Working Tree'),\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\tmessage: options.message,\n\t\t\t};\n\t}\n}\n\nexport function getReferenceNameWithoutRemote(ref: GitReference): string {\n\tif (ref.refType === 'branch') {\n\t\treturn ref.remote ? getBranchNameWithoutRemote(ref.name) : ref.name;\n\t}\n\treturn ref.name;\n}\n\nexport function getReferenceTypeLabel(ref: GitReference | undefined): string {\n\tswitch (ref?.refType) {\n\t\tcase 'branch':\n\t\t\treturn l10n.t('Branch');\n\t\tcase 'stash':\n\t\t\treturn l10n.t('Stash');\n\t\tcase 'tag':\n\t\t\treturn l10n.t('Tag');\n\t\tdefault:\n\t\t\treturn l10n.t('Commit');\n\t}\n}\n\nexport function isBranchReference(ref: GitReference | undefined): ref is GitBranchReference {\n\treturn ref?.refType === 'branch';\n}\n\nexport function isGitReference(ref: unknown): ref is GitReference {\n\tif (ref == null || typeof ref !== 'object') return false;\n\n\tconst r = ref as GitReference;\n\treturn (\n\t\ttypeof r.refType === 'string' &&\n\t\ttypeof r.repoPath === 'string' &&\n\t\ttypeof r.ref === 'string' &&\n\t\ttypeof r.name === 'string'\n\t);\n}\n\nexport function isRevisionReference(ref: GitReference | undefined): ref is GitRevisionReference {\n\treturn ref?.refType === 'revision';\n}\n\nexport function isRevisionRangeReference(ref: GitReference | undefined): ref is GitRevisionReference {\n\treturn ref?.refType === 'revision' && isRevisionRange(ref.ref);\n}\n\nexport function isStashReference(ref: GitReference | undefined): ref is GitStashReference {\n\treturn ref?.refType === 'stash' || (ref?.refType === 'revision' && Boolean('stashName' in ref && ref.stashName));\n}\n\nexport function isTagReference(ref: GitReference | undefined): ref is GitTagReference {\n\treturn ref?.refType === 'tag';\n}\n\nexport function getReferenceLabel(\n\trefs: GitReference | GitReference[] | undefined,\n\toptions?: { capitalize?: boolean; expand?: boolean; icon?: boolean; label?: boolean; quoted?: boolean } | false,\n): string {\n\tif (refs == null) return '';\n\n\toptions =\n\t\toptions === false\n\t\t\t? {}\n\t\t\t: { expand: true, icon: true, label: options?.label ?? options?.expand ?? true, ...options };\n\n\tlet result;\n\tif (!Array.isArray(refs) || refs.length === 1) {\n\t\tconst ref = Array.isArray(refs) ? refs[0] : refs;\n\t\tlet refName = options?.quoted ? `'${ref.name}'` : ref.name;\n\t\tswitch (ref.refType) {\n\t\t\tcase 'branch': {\n\t\t\t\tif (ref.remote) {\n\t\t\t\t\trefName = `${getRemoteNameFromBranchName(refName)}: ${getBranchNameWithoutRemote(refName)}`;\n\t\t\t\t\trefName = options?.quoted ? `'${refName}'` : refName;\n\t\t\t\t}\n\n\t\t\t\tif (options.label) {\n\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\tif (options.capitalize && options.expand) {\n\t\t\t\t\t\t\tresult = ref.remote\n\t\t\t\t\t\t\t\t? l10n.t('Remote Branch $(git-branch)\\u00a0{0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('Branch $(git-branch)\\u00a0{0}', refName);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult = ref.remote\n\t\t\t\t\t\t\t\t? l10n.t('remote branch $(git-branch)\\u00a0{0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('branch $(git-branch)\\u00a0{0}', refName);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (options.capitalize && options.expand) {\n\t\t\t\t\t\tresult = ref.remote ? l10n.t('Remote Branch {0}', refName) : l10n.t('Branch {0}', refName);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = ref.remote ? l10n.t('remote branch {0}', refName) : l10n.t('branch {0}', refName);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult = options.icon ? `$(git-branch)\\u00a0${refName}` : refName;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'tag':\n\t\t\t\tif (options.label) {\n\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t? l10n.t('Tag $(tag)\\u00a0{0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('tag $(tag)\\u00a0{0}', refName);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t? l10n.t('Tag {0}', refName)\n\t\t\t\t\t\t\t\t: l10n.t('tag {0}', refName);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult = options.icon ? `$(tag)\\u00a0${refName}` : refName;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tif (isStashReference(ref)) {\n\t\t\t\t\tlet message;\n\t\t\t\t\tif (options.expand && ref.message) {\n\t\t\t\t\t\tmessage = `${ref.stashNumber != null ? `#${ref.stashNumber}: ` : ''}${\n\t\t\t\t\t\t\tref.message.length > 20 ? `${ref.message.substring(0, 20).trimEnd()}\\u2026` : ref.message\n\t\t\t\t\t\t}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst stashName = message ?? (ref.stashNumber ? `#${ref.stashNumber}` : ref.name);\n\t\t\t\t\tif (options.label) {\n\t\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t? l10n.t('Stash $(archive)\\u00a0{0}', message ?? ref.name)\n\t\t\t\t\t\t\t\t\t: l10n.t('stash $(archive)\\u00a0{0}', message ?? ref.name);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t? l10n.t('Stash {0}', stashName)\n\t\t\t\t\t\t\t\t\t: l10n.t('stash {0}', stashName);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = options.icon ? `$(archive)\\u00a0${message ?? ref.name}` : stashName;\n\t\t\t\t\t}\n\t\t\t\t} else if (isRevisionRange(ref.ref)) {\n\t\t\t\t\tresult = refName;\n\t\t\t\t} else {\n\t\t\t\t\tlet message;\n\t\t\t\t\tif (options.expand && ref.message) {\n\t\t\t\t\t\tmessage =\n\t\t\t\t\t\t\tref.message.length > 20\n\t\t\t\t\t\t\t\t? ` (${ref.message.substring(0, 20).trimEnd()}\\u2026)`\n\t\t\t\t\t\t\t\t: ` (${ref.message})`;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet before = false;\n\t\t\t\t\tif (options.expand && options.label && isShaWithParentSuffix(ref.ref)) {\n\t\t\t\t\t\trefName = ref.name.endsWith('^') ? ref.name.substring(0, ref.name.length - 1) : ref.name;\n\t\t\t\t\t\tif (options?.quoted) {\n\t\t\t\t\t\t\trefName = `'${refName}'`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbefore = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (options.label) {\n\t\t\t\t\t\tif (options.icon) {\n\t\t\t\t\t\t\tif (before) {\n\t\t\t\t\t\t\t\tresult = options.capitalize\n\t\t\t\t\t\t\t\t\t? l10n.t('Before commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t\t: l10n.t('before commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t\t? l10n.t('Commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t\t\t: l10n.t('commit $(git-commit)\\u00a0{0}{1}', refName, message ?? '');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (before) {\n\t\t\t\t\t\t\tresult = options.capitalize\n\t\t\t\t\t\t\t\t? l10n.t('Before commit {0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t: l10n.t('before commit {0}{1}', refName, message ?? '');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult =\n\t\t\t\t\t\t\t\toptions.capitalize && options.expand\n\t\t\t\t\t\t\t\t\t? l10n.t('Commit {0}{1}', refName, message ?? '')\n\t\t\t\t\t\t\t\t\t: l10n.t('commit {0}{1}', refName, message ?? '');\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = options.icon\n\t\t\t\t\t\t\t? `$(git-commit)\\u00a0${refName}${message ?? ''}`\n\t\t\t\t\t\t\t: `${refName}${message ?? ''}`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tconst expanded = options.expand ? ` (${refs.map(r => r.name).join(', ')})` : '';\n\tswitch (refs[0].refType) {\n\t\tcase 'branch':\n\t\t\treturn l10n.t('{0} branches{1}', refs.length, expanded);\n\t\tcase 'tag':\n\t\t\treturn l10n.t('{0} tags{1}', refs.length, expanded);\n\t\tdefault:\n\t\t\treturn isStashReference(refs[0])\n\t\t\t\t? l10n.t('{0} stashes{1}', refs.length, expanded)\n\t\t\t\t: l10n.t('{0} commits{1}', refs.length, expanded);\n\t}\n}\n\nexport function getReferenceTypeIcon(ref: GitReference | undefined, webview?: boolean): string {\n\tswitch (ref?.refType) {\n\t\tcase 'branch':\n\t\t\tif (ref.remote) return 'cloud';\n\t\t\tif (ref.worktree) return webview ? 'gl-worktree' : 'gitlens-worktree';\n\t\t\treturn 'git-branch';\n\t\tcase 'tag':\n\t\t\treturn 'tag';\n\t\tcase 'stash':\n\t\t\treturn 'archive';\n\t\tdefault:\n\t\t\treturn 'git-commit';\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { GitProviderDescriptor } from "../git/providers/types.js";
|
|
|
4
4
|
import { GitIgnoreFilter } from "../git/watching/gitIgnoreFilter.js";
|
|
5
5
|
import { RepositoryChange } from "../git/models/repository.js";
|
|
6
6
|
import { GitServiceContext } from "../git/context.js";
|
|
7
|
+
import { GitCommandPriority } from "../git/run.types.js";
|
|
7
8
|
import { Cache, CachedGitTypes, MergeTargetsChangeEvent } from "../git/cache.js";
|
|
8
9
|
import { GitOperationRunOptions } from "../git/providers/operations.js";
|
|
9
10
|
import { AnnouncedRepositoryChanges, GitProvider } from "../git/providers/provider.js";
|
|
@@ -210,8 +211,13 @@ export declare class CliGitProvider implements GitProvider {
|
|
|
210
211
|
getLastFetchedTimestamp(repoPath: string): Promise<number | undefined>;
|
|
211
212
|
getIgnoreFilter(repoPath: string): GitIgnoreFilter;
|
|
212
213
|
getIgnoredDirectories(repoPath: string, cancellation?: AbortSignal): Promise<string[]>;
|
|
213
|
-
getIgnoredEntries(repoPath: string,
|
|
214
|
-
|
|
214
|
+
getIgnoredEntries(repoPath: string, options?: {
|
|
215
|
+
paths?: readonly string[];
|
|
216
|
+
priority?: GitCommandPriority;
|
|
217
|
+
}, cancellation?: AbortSignal): Promise<string[]>;
|
|
218
|
+
getIgnoredPaths(repoPath: string, paths: readonly string[], options?: {
|
|
219
|
+
priority?: GitCommandPriority;
|
|
220
|
+
}, cancellation?: AbortSignal): Promise<Set<string>>;
|
|
215
221
|
/** Every `.gitignore` git reads in the working tree (tracked, or untracked and not itself ignored), root included */
|
|
216
222
|
private getGitIgnorePaths;
|
|
217
223
|
private isTrackedWithDetails;
|
|
@@ -10,7 +10,8 @@ import { parseGitRemoteUrl } from "../git/utils/remote.utils.js";
|
|
|
10
10
|
import { GitIgnoreFilter } from "../git/watching/gitIgnoreFilter.js";
|
|
11
11
|
import { worktreeSharedChanges } from "./exec/commandClassifier.js";
|
|
12
12
|
import { fsExists } from "../utils/env/node/exec.js";
|
|
13
|
-
import { Git } from "./exec/git.js";
|
|
13
|
+
import { Git, batchLiteralPathspecs, gitConfigsStatus } from "./exec/git.js";
|
|
14
|
+
import { foldMatchingIgnored } from "./parsers/statusParser.js";
|
|
14
15
|
import { BlameGitSubProvider } from "./providers/blame.js";
|
|
15
16
|
import { BranchesGitSubProvider } from "./providers/branches.js";
|
|
16
17
|
import { StashGitSubProvider } from "./providers/stash.js";
|
|
@@ -441,7 +442,7 @@ var CliGitProvider = class {
|
|
|
441
442
|
const candidates = [];
|
|
442
443
|
for (const entry of iterateByDelimiter(listed.stdout, "\0")) if (entry.length > 1 && entry.endsWith("/")) candidates.push(entry);
|
|
443
444
|
if (!candidates.length) return [];
|
|
444
|
-
const confirmed = await this.getIgnoredPaths(repoPath, candidates, cancellation);
|
|
445
|
+
const confirmed = await this.getIgnoredPaths(repoPath, candidates, void 0, cancellation);
|
|
445
446
|
const directories = [];
|
|
446
447
|
for (const entry of confirmed) {
|
|
447
448
|
if (entry.length < 2 || !entry.endsWith("/") || /[*?[\]{}()!+@\\]/.test(entry)) continue;
|
|
@@ -461,31 +462,92 @@ var CliGitProvider = class {
|
|
|
461
462
|
}
|
|
462
463
|
return [...kept];
|
|
463
464
|
}
|
|
464
|
-
async getIgnoredEntries(repoPath, cancellation) {
|
|
465
|
-
const
|
|
465
|
+
async getIgnoredEntries(repoPath, options, cancellation) {
|
|
466
|
+
const paths = options?.paths;
|
|
467
|
+
if (paths != null && !paths.length) return [];
|
|
468
|
+
const args = [
|
|
469
|
+
"ls-files",
|
|
470
|
+
"-z",
|
|
471
|
+
"--others",
|
|
472
|
+
"--exclude-standard",
|
|
473
|
+
"--directory",
|
|
474
|
+
"--no-empty-directory"
|
|
475
|
+
];
|
|
476
|
+
const runOptions = {
|
|
466
477
|
cwd: repoPath,
|
|
467
478
|
errors: "throw",
|
|
468
|
-
cancellation
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
479
|
+
cancellation,
|
|
480
|
+
priority: options?.priority
|
|
481
|
+
};
|
|
482
|
+
const readListing = async (extra) => {
|
|
483
|
+
const listed = /* @__PURE__ */ new Set();
|
|
484
|
+
const prefix = [...args, ...extra];
|
|
485
|
+
for (const batch of paths != null ? batchLiteralPathspecs(paths, prefix) : [void 0]) {
|
|
486
|
+
const result = await this._git.run(runOptions, ...prefix, ...batch != null ? ["--", ...batch] : []);
|
|
487
|
+
for (const entry of iterateByDelimiter(result.stdout, "\0")) if (entry !== "") listed.add(entry);
|
|
488
|
+
}
|
|
489
|
+
return listed;
|
|
490
|
+
};
|
|
491
|
+
const [ignoredResult, untrackedResult] = await Promise.allSettled([readListing(["--ignored"]), readListing([])]);
|
|
492
|
+
if (ignoredResult.status === "rejected") throw ignoredResult.reason;
|
|
493
|
+
if (untrackedResult.status === "rejected") throw untrackedResult.reason;
|
|
494
|
+
const entries = /* @__PURE__ */ new Set();
|
|
495
|
+
for (const entry of ignoredResult.value) if (entry !== ".git/") entries.add(entry);
|
|
496
|
+
const folders = [];
|
|
497
|
+
for (const entry of untrackedResult.value) if (entry.endsWith("/")) folders.push(entry);
|
|
498
|
+
if (!folders.length) return [...entries].sort();
|
|
499
|
+
const matching = await this._git.supports("git:status:ignored-matching");
|
|
500
|
+
const prefix = [
|
|
501
|
+
"status",
|
|
502
|
+
"--porcelain",
|
|
503
|
+
"-z",
|
|
504
|
+
matching ? "--ignored=matching" : "--ignored",
|
|
505
|
+
matching ? "--untracked-files=all" : "--untracked-files=normal",
|
|
506
|
+
"--ignore-submodules=all"
|
|
507
|
+
];
|
|
508
|
+
const records = [];
|
|
509
|
+
for (const batch of batchLiteralPathspecs(folders, prefix)) {
|
|
510
|
+
const listed = await this._git.run({
|
|
511
|
+
...runOptions,
|
|
512
|
+
configs: [
|
|
513
|
+
...gitConfigsStatus,
|
|
514
|
+
"-c",
|
|
515
|
+
"status.renames=false"
|
|
516
|
+
],
|
|
517
|
+
env: { GIT_OPTIONAL_LOCKS: "0" }
|
|
518
|
+
}, ...prefix, "--", ...batch);
|
|
519
|
+
for (const record of iterateByDelimiter(listed.stdout, "\0")) if (matching) records.push(record);
|
|
520
|
+
else if (record.startsWith("!! ")) entries.add(record.substring(3));
|
|
474
521
|
}
|
|
475
|
-
|
|
522
|
+
if (matching) for (const entry of foldMatchingIgnored(records)) entries.add(entry);
|
|
523
|
+
return [...entries].sort();
|
|
476
524
|
}
|
|
477
|
-
async getIgnoredPaths(repoPath, paths, cancellation) {
|
|
525
|
+
async getIgnoredPaths(repoPath, paths, options, cancellation) {
|
|
478
526
|
if (!paths.length) return /* @__PURE__ */ new Set();
|
|
527
|
+
let prefixed;
|
|
528
|
+
const lines = paths.map((p) => {
|
|
529
|
+
if (!p.startsWith(":")) return p;
|
|
530
|
+
const sent = `./${p}`;
|
|
531
|
+
(prefixed ??= /* @__PURE__ */ new Map()).set(sent, p);
|
|
532
|
+
return sent;
|
|
533
|
+
});
|
|
479
534
|
const result = await this._git.run({
|
|
480
535
|
cwd: repoPath,
|
|
481
536
|
errors: "throw",
|
|
482
537
|
cancellation,
|
|
483
|
-
|
|
538
|
+
priority: options?.priority,
|
|
539
|
+
stdin: `${lines.join("\0")}\0`,
|
|
484
540
|
expectedExitCodes: [1]
|
|
485
541
|
}, "check-ignore", "-z", "--stdin");
|
|
486
542
|
const ignored = /* @__PURE__ */ new Set();
|
|
543
|
+
let given;
|
|
487
544
|
for (const entry of iterateByDelimiter(result.stdout, "\0")) {
|
|
488
545
|
if (!entry.length) continue;
|
|
546
|
+
const original = prefixed?.get(entry);
|
|
547
|
+
if (original != null) {
|
|
548
|
+
ignored.add(original);
|
|
549
|
+
if (!(given ??= new Set(paths)).has(entry)) continue;
|
|
550
|
+
}
|
|
489
551
|
ignored.add(entry);
|
|
490
552
|
}
|
|
491
553
|
return ignored;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliGitProvider.js","names":["fs"],"sources":["../../../git-cli/src/cliGitProvider.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport { homedir } from 'node:os';\nimport * as path from 'node:path';\nimport { env } from 'node:process';\nimport type { CachedGitTypes, MergeTargetsChangeEvent } from '@gitlens/git/cache.js';\nimport { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitFileStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitOperationRunOptions } from '@gitlens/git/providers/operations.js';\nimport type {\n\tAnnouncedRepositoryChanges,\n\tGitProvider,\n\tGitProviderDescriptor,\n} from '@gitlens/git/providers/provider.js';\nimport { parseGitRemoteUrl } from '@gitlens/git/utils/remote.utils.js';\nimport { isUncommitted } from '@gitlens/git/utils/revision.utils.js';\nimport { GitIgnoreFilter } from '@gitlens/git/watching/gitIgnoreFilter.js';\nimport type { Event } from '@gitlens/utils/event.js';\nimport { Emitter } from '@gitlens/utils/event.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths, maybeUri, normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport { iterateByDelimiter } from '@gitlens/utils/string.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fileUri, joinUriPath, parseUri, toFsPath } from '@gitlens/utils/uri.js';\nimport { worktreeSharedChanges } from './exec/commandClassifier.js';\nimport { fsExists } from './exec/exec.js';\nimport type { FilteredGitFeatures, GitFeatureOrPrefix, GitFeatures } from './exec/features.js';\nimport type { GitFeatureUnsupportedMessage, GitOptions } from './exec/git.js';\nimport { Git } from './exec/git.js';\nimport type { GitLocation } from './exec/locator.js';\nimport { BlameGitSubProvider } from './providers/blame.js';\nimport { BranchesGitSubProvider } from './providers/branches.js';\nimport { CommitsGitSubProvider } from './providers/commits.js';\nimport { ConfigGitSubProvider, isGitBooleanFalse, parseGitBoolean } from './providers/config.js';\nimport { ContributorsGitSubProvider } from './providers/contributors.js';\nimport { DiffGitSubProvider } from './providers/diff.js';\nimport { GraphGitSubProvider } from './providers/graph.js';\nimport { MaintenanceGitSubProvider } from './providers/maintenance.js';\nimport { OperationsGitSubProvider } from './providers/operations.js';\nimport { PatchGitSubProvider } from './providers/patch.js';\nimport { PausedOperationsGitSubProvider } from './providers/pausedOperations.js';\nimport { RefsGitSubProvider } from './providers/refs.js';\nimport { RemotesGitSubProvider } from './providers/remotes.js';\nimport { RevisionGitSubProvider } from './providers/revision.js';\nimport { StagingGitSubProvider } from './providers/staging.js';\nimport { StashGitSubProvider } from './providers/stash.js';\nimport { StatusGitSubProvider } from './providers/status.js';\nimport { TagsGitSubProvider } from './providers/tags.js';\nimport { WorktreesGitSubProvider } from './providers/worktrees.js';\n\nexport interface CliGitProviderOptions {\n\t/** Use an existing Cache instance, or one will be created */\n\tcache?: Cache;\n\t/** Context providing config and event bus hooks */\n\tcontext: GitServiceContext;\n\t/** Function that resolves the git binary location (path + version) */\n\tlocator: () => Promise<GitLocation>;\n\t/** Pre-built Git executor — when provided, used instead of creating a new Git from locator/options */\n\tgit?: Git;\n\t/** Git execution options (timeout, trust, queue config, hooks, etc.) */\n\tgitOptions?: GitOptions;\n\t/**\n\t * Whether repositories reached through this provider are on the LOCAL filesystem. `false` disables the\n\t * maintenance sub-provider entirely (Live Share): its probes stat local paths, and its writes are\n\t * rejected by the host's command allowlist, so inheriting it yields empty reports and swallowed\n\t * failures rather than an honest \"unsupported here\". Defaults to `true`.\n\t */\n\tlocalRepositories?: boolean;\n}\n\n/**\n * Exposes `isTrackedWithDetails` as a callable method for sub-providers.\n * The class declares it as a regular method, but TypeScript's structural\n * typing makes it inaccessible through the class type alone when consumed\n * internally — this type re-maps it to ensure sub-providers can call it.\n */\nexport type CliGitProviderInternal = Omit<CliGitProvider, 'isTrackedWithDetails'> & {\n\tisTrackedWithDetails: CliGitProvider['isTrackedWithDetails'];\n};\n\n/**\n * A fully-wired CLI-based git provider that executes git commands via `child_process`.\n * Implements both `CliGitProviderInternal` (for internal sub-provider wiring)\n * and `GitProvider` (for registration in a provider registry).\n *\n * @example\n * ```typescript\n * const provider = new CliGitProvider({\n * context: { events: myEvents },\n * locator: () => findGitPath(null),\n * gitOptions: { gitTimeout: 30000 },\n * });\n *\n * const branches = await provider.branches.getBranches(repoPath);\n * const status = await provider.status.getStatus(repoPath);\n * ```\n */\nexport class CliGitProvider implements GitProvider {\n\treadonly descriptor: GitProviderDescriptor = { id: 'git', name: 'Git', virtual: false };\n\n\tprivate readonly _cache: Cache;\n\tprivate readonly _cacheOwned: boolean;\n\tprivate readonly _git: Git;\n\n\treadonly context: GitServiceContext;\n\t/** The host's own hooks, before the provider wraps `cache.onReset` with its own clearing */\n\tprivate readonly _hostHooks: GitServiceContext['hooks'];\n\tprivate readonly _localRepositories: boolean;\n\n\tconstructor(options: CliGitProviderOptions) {\n\t\t// Every typed write announces itself through `onReset`, so the provider clears its own state there\n\t\t// rather than trusting each host to: a host with no handler still reads fresh after a write. A write\n\t\t// hard-evicts, so a caller after it never joins a read that started before it; watcher-driven clears\n\t\t// reach `Cache.clearCaches` directly and keep sharing in-flight reads.\n\t\tconst hostHooks = options.context.hooks;\n\t\tthis._hostHooks = hostHooks;\n\t\tthis.context = {\n\t\t\t...options.context,\n\t\t\thooks: {\n\t\t\t\t...hostHooks,\n\t\t\t\tcache: {\n\t\t\t\t\t...hostHooks?.cache,\n\t\t\t\t\tonReset: (repoPath, ...types) => {\n\t\t\t\t\t\tthis._cache.evictCaches(repoPath, ...types);\n\t\t\t\t\t\tthis._git.clearPendingCommands(this.getRepositoryPaths(repoPath));\n\t\t\t\t\t\thostHooks?.cache?.onReset?.(repoPath, ...types);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trepository: {\n\t\t\t\t\t...hostHooks?.repository,\n\t\t\t\t\tonChanged: (repoPath, changes) => {\n\t\t\t\t\t\t// Everything the watcher would have cleared for the write, since its own file events are\n\t\t\t\t\t\t// dropped once it is announced (the typed write's `onReset` names only what it must evict)\n\t\t\t\t\t\tthis.resetForChanges(repoPath, changes, undefined);\n\t\t\t\t\t\t// Worktrees share refs, tags, stash, remotes and config, so a typed write in one changes what\n\t\t\t\t\t\t// its siblings show; the host hears the shared part of it for each, and they read fresh.\n\t\t\t\t\t\t// Every path is reset before any is announced, so a read the host starts on hearing one path\n\t\t\t\t\t\t// isn't evicted by the next path's reset\n\t\t\t\t\t\tconst siblings = this.getSiblingChanges(repoPath, changes);\n\t\t\t\t\t\tfor (const [path, shared] of siblings) {\n\t\t\t\t\t\t\tthis.resetForChanges(path, shared, undefined, true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.announceChanged(repoPath, changes);\n\t\t\t\t\t\tfor (const [path, shared] of siblings) {\n\t\t\t\t\t\t\tthis.announceChanged(path, shared);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tthis._localRepositories = options.localRepositories ?? true;\n\t\tthis._git =\n\t\t\toptions.git ??\n\t\t\tnew Git(options.locator, {\n\t\t\t\t...options.gitOptions,\n\t\t\t\tisTrusted:\n\t\t\t\t\toptions.context.workspace?.isTrusted != null\n\t\t\t\t\t\t? () => options.context.workspace!.isTrusted!\n\t\t\t\t\t\t: undefined,\n\t\t\t});\n\t\tthis._cacheOwned = !(options.cache instanceof Cache);\n\t\tthis._cache = options.cache instanceof Cache ? options.cache : new Cache();\n\n\t\t// Wires a raw `git.run({ notify })` call back to this provider's own cache/host announcement —\n\t\t// unconditionally, so a host-supplied `options.git` gets bound exactly like one we construct here.\n\t\tthis._git.bindChangeNotifier((repoPaths, changes, sharedPaths) =>\n\t\t\tthis.notifyChangedCore(repoPaths, changes, undefined, sharedPaths),\n\t\t);\n\t}\n\n\t/** The underlying cache instance (for repo path registration, etc.) */\n\tget cache(): Cache {\n\t\treturn this._cache;\n\t}\n\n\tget onDidChangeMergeTargets(): Event<MergeTargetsChangeEvent> {\n\t\treturn this._cache.onDidChangeMergeTargets;\n\t}\n\n\tgetCommonPath(repoPath: string): string | undefined {\n\t\t// An unregistered path is its own common path in the cache, which would hide a sibling worktree's writes\n\t\treturn this._cache.isRegistered(repoPath) ? this._cache.getCommonPath(repoPath) : undefined;\n\t}\n\n\tprivate readonly _onDidAnnounceChanges = new Emitter<AnnouncedRepositoryChanges>();\n\tget onDidAnnounceChanges(): Event<AnnouncedRepositoryChanges> {\n\t\treturn this._onDidAnnounceChanges.event;\n\t}\n\n\t/** The underlying git execution instance (for sub-providers that need direct exec/stream access) */\n\tget git(): Git {\n\t\treturn this._git;\n\t}\n\n\t/** Returns whether the installed git version supports the given feature. */\n\tsupports(feature: GitFeatures): boolean | Promise<boolean> {\n\t\treturn this._git.supports(feature);\n\t}\n\n\t/** Returns all features matching the prefix that the installed git version supports. */\n\tsupported<T extends GitFeatureOrPrefix>(feature: T): FilteredGitFeatures<T>[] | Promise<FilteredGitFeatures<T>[]> {\n\t\treturn this._git.supported(feature);\n\t}\n\n\t/** Throws if the installed git version does not support the given feature. */\n\tasync ensureSupports(feature: GitFeatures, prefix: string, suffix: string): Promise<void>;\n\tasync ensureSupports(feature: GitFeatures, message: GitFeatureUnsupportedMessage): Promise<void>;\n\tasync ensureSupports(\n\t\tfeature: GitFeatures,\n\t\tprefixOrMessage: string | GitFeatureUnsupportedMessage,\n\t\tsuffix?: string,\n\t): Promise<void> {\n\t\treturn typeof prefixOrMessage === 'function'\n\t\t\t? this._git.ensureSupports(feature, prefixOrMessage)\n\t\t\t: this._git.ensureSupports(feature, prefixOrMessage, suffix!);\n\t}\n\n\t/** Returns the installed git version string. */\n\tasync version(): Promise<string> {\n\t\treturn this._git.version();\n\t}\n\n\t/** Returns the resolved git binary path. */\n\tasync path(): Promise<string> {\n\t\treturn this._git.path();\n\t}\n\n\tasync clone(\n\t\turl: string,\n\t\tparentPath: string,\n\t\toptions?: { folderName?: string },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<string | undefined> {\n\t\tlet folderPath: string;\n\t\tif (options?.folderName) {\n\t\t\tfolderPath = joinPaths(parentPath, options.folderName);\n\t\t} else {\n\t\t\tconst [, , remotePath] = parseGitRemoteUrl(url);\n\t\t\tconst remoteName = remotePath.split('/').pop();\n\t\t\tif (!remoteName) return undefined;\n\n\t\t\tlet count = 0;\n\t\t\tfolderPath = joinPaths(parentPath, remoteName);\n\t\t\twhile ((await fsExists(folderPath)) && count < 20) {\n\t\t\t\tcount++;\n\t\t\t\tfolderPath = joinPaths(parentPath, `${remoteName}-${count}`);\n\t\t\t}\n\t\t}\n\n\t\t// `throw`: the default handler swallows `remoteConnectionError`, which would return a folder never cloned\n\t\tawait this._git.run({ cwd: parentPath, errors: 'throw', ...runOptions }, 'clone', url, folderPath);\n\n\t\treturn folderPath;\n\t}\n\n\t/** Creates a new repository at `targetPath` (`git init`), creating it first if it doesn't yet exist. */\n\tasync init(targetPath: string, options?: { defaultBranch?: string; bare?: boolean }): Promise<void> {\n\t\tawait fs.mkdir(targetPath, { recursive: true });\n\n\t\tconst args = ['init'];\n\t\tif (options?.defaultBranch) {\n\t\t\targs.push('-b', options.defaultBranch);\n\t\t}\n\t\tif (options?.bare) {\n\t\t\targs.push('--bare');\n\t\t}\n\n\t\t// Run inside the target rather than naming it from its parent: a relative `targetPath` would otherwise\n\t\t// be resolved against the parent a second time\n\t\tawait this._git.run({ cwd: targetPath }, ...args);\n\t}\n\n\t/**\n\t * Notifies the provider that `repoPath` was mutated outside of a typed sub-provider method — e.g. a\n\t * consumer that ran a command through the raw `git.run`/`provider.git.run` escape hatch. Fires the same\n\t * `cache.onReset`/`repository.onChanged` hooks a typed mutator would, so, exactly as after a typed write,\n\t * the provider hard-evicts its own caches for `repoPath` and drops its pending commands for the repository\n\t * (its sibling worktrees included) before the host's handlers run.\n\t *\n\t * What is reset: `options.cache` when given (`'all'` for everything, `[]` for nothing); otherwise the\n\t * cache types `changes` map to, the same mapping a file watcher's changes get, status clock included.\n\t * An empty `changes`, or one naming `'unknown'` or `'closed'`, resets everything. Changes that map to\n\t * no cache type (e.g. `'starred'`) reset nothing, and `onReset` doesn't fire; `onChanged` always fires.\n\t */\n\tnotifyChanged(\n\t\trepoPath: string,\n\t\tchanges: readonly RepositoryChange[],\n\t\toptions?: { cache?: readonly CachedGitTypes[] | 'all' },\n\t): void {\n\t\tthis.notifyChangedCore([repoPath], changes, options);\n\t}\n\n\t/**\n\t * {@link notifyChanged} for one change seen from several paths, e.g. a `-C` shared-state verb announced\n\t * for both its target and the caller's `cwd`. Each path's caches are reset and the host's `onReset` fires\n\t * for each, since a host may keep per-worktree state, but a repository's pending commands are dropped once\n\t * however many of its worktrees are named.\n\t *\n\t * Each path hears the announcement once: `repoPaths` hear all of `changes`, `sharedPaths` (reset and\n\t * `onReset`-ed like `repoPaths`) and then the other registered worktrees sharing a repository with any of\n\t * them (reset like a typed write's, with no `onReset`) hear the shared part of it, see\n\t * {@link getSiblingChanges}.\n\t */\n\tprivate notifyChangedCore(\n\t\trepoPaths: readonly string[],\n\t\tchanges: readonly RepositoryChange[],\n\t\toptions?: { cache?: readonly CachedGitTypes[] | 'all' },\n\t\tsharedPaths?: readonly string[],\n\t): void {\n\t\tconst announcements = new Map<string, readonly RepositoryChange[]>();\n\t\tfor (const repoPath of repoPaths) {\n\t\t\tannouncements.set(repoPath, [...changes]);\n\t\t}\n\t\tconst shared = sharedPaths?.length ? this.getSharedChanges(changes) : undefined;\n\t\tif (shared != null) {\n\t\t\tfor (const path of sharedPaths!) {\n\t\t\t\tif (!announcements.has(path)) {\n\t\t\t\t\tannouncements.set(path, shared);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst resets: { repoPath: string; types: CachedGitTypes[] }[] = [];\n\t\tconst pendingPaths = new Set<string>();\n\t\tfor (const [repoPath, announced] of announcements) {\n\t\t\tconst types = this.resetForChanges(repoPath, announced, options?.cache);\n\t\t\tif (types == null) {\n\t\t\t\t// A gk config change is reconciled outside the cache types, but its re-read must not join a pre-write run\n\t\t\t\tif (options?.cache == null && announced.includes('gkConfig')) {\n\t\t\t\t\tfor (const path of this.getRepositoryPaths(repoPath)) {\n\t\t\t\t\t\tpendingPaths.add(path);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresets.push({ repoPath: repoPath, types: types });\n\t\t\tfor (const path of this.getRepositoryPaths(repoPath)) {\n\t\t\t\tpendingPaths.add(path);\n\t\t\t}\n\t\t}\n\n\t\t// The worktrees no one named: their shared refs, tags, stash, remotes and config just changed too\n\t\tconst named = [...announcements.keys()];\n\t\tfor (const repoPath of named) {\n\t\t\tfor (const [path, siblingChanges] of this.getSiblingChanges(repoPath, changes)) {\n\t\t\t\tif (announcements.has(path)) continue;\n\n\t\t\t\tannouncements.set(path, siblingChanges);\n\t\t\t\tthis.resetForChanges(path, siblingChanges, options?.cache, true);\n\t\t\t}\n\t\t}\n\n\t\tif (pendingPaths.size) {\n\t\t\tthis._git.clearPendingCommands([...pendingPaths]);\n\t\t}\n\t\tfor (const { repoPath, types } of resets) {\n\t\t\tthis._hostHooks?.cache?.onReset?.(repoPath, ...types);\n\t\t}\n\t\t// The host's own hook: `context.hooks.repository.onChanged` also fans out to siblings, which would\n\t\t// announce a path a second time\n\t\tfor (const [path, announced] of announcements) {\n\t\t\tthis.announceChanged(path, [...announced]);\n\t\t}\n\t}\n\n\t/**\n\t * Tells only the host's own `repository.onChanged` about `changes` — for a follow-up that is not a write of\n\t * core's, such as re-announcing an outside change once it was reconciled. Nothing is evicted, no sibling hears\n\t * it, and the watch layer doesn't take it for a write's announcement.\n\t */\n\tnotifyHost(repoPath: string, changes: RepositoryChange[]): void {\n\t\tthis._hostHooks?.repository?.onChanged?.(repoPath, changes);\n\t}\n\n\t/** Tells the host about a write for one path, after its caches were reset — the watch layer hears of it first */\n\tprivate announceChanged(repoPath: string, changes: RepositoryChange[]): void {\n\t\tthis._onDidAnnounceChanges.fire({ repoPath: repoPath, changes: changes });\n\t\tthis._hostHooks?.repository?.onChanged?.(repoPath, changes);\n\t}\n\n\t/**\n\t * What the worktrees sharing a repository hear of `changes` that ran in one of them: the part worktrees\n\t * share (see {@link worktreeSharedChanges}), or `undefined` when `changes` has none. An empty `changes` or\n\t * `'unknown'` means everything may have changed, so it reaches them as every shared kind — never as\n\t * `'unknown'` itself, which a host treats as the end of a watch session; `'closed'` concerns the one path\n\t * alone and reaches none.\n\t */\n\tprivate getSharedChanges(changes: readonly RepositoryChange[]): RepositoryChange[] | undefined {\n\t\tif (changes.includes('closed')) return undefined;\n\t\tif (!changes.length || changes.includes('unknown')) return [...worktreeSharedChanges];\n\n\t\tconst shared = changes.filter(c => worktreeSharedChanges.has(c));\n\t\treturn shared.length ? shared : undefined;\n\t}\n\n\t/** What each registered worktree sharing `repoPath`'s repository, other than `repoPath`, hears of `changes`. */\n\tprivate getSiblingChanges(repoPath: string, changes: readonly RepositoryChange[]): Map<string, RepositoryChange[]> {\n\t\tconst siblings = new Map<string, RepositoryChange[]>();\n\t\tconst shared = this.getSharedChanges(changes);\n\t\tif (shared == null) return siblings;\n\n\t\tconst self = normalizePath(repoPath);\n\t\tfor (const path of this._cache.getWorktreePaths(this._cache.getCommonPath(repoPath))) {\n\t\t\tif (path !== self) {\n\t\t\t\tsiblings.set(path, [...shared]);\n\t\t\t}\n\t\t}\n\t\treturn siblings;\n\t}\n\n\t/**\n\t * Evicts what a notified change reset for `repoPath`: the types reset (`[]` = all), or `undefined` for none.\n\t * A `sibling` shares its repository with a path already reset for the same change, which evicted the shared\n\t * entries for every worktree, so the changes evict only its own entries and advance its status clock.\n\t */\n\tprivate resetForChanges(\n\t\trepoPath: string,\n\t\tchanges: readonly RepositoryChange[],\n\t\tcache: readonly CachedGitTypes[] | 'all' | undefined,\n\t\tsibling: boolean = false,\n\t): CachedGitTypes[] | undefined {\n\t\tif (cache != null && cache !== 'all') {\n\t\t\tif (!cache.length) return undefined;\n\n\t\t\tthis._cache.evictCaches(repoPath, ...cache);\n\t\t\treturn [...cache];\n\t\t}\n\n\t\tif (cache === 'all' || !changes.length || changes.some(c => c === 'unknown' || c === 'closed')) {\n\t\t\tthis._cache.evictCaches(repoPath);\n\t\t\treturn [];\n\t\t}\n\n\t\tconst types = this._cache.applyRepositoryChanges(\n\t\t\trepoPath,\n\t\t\tchanges,\n\t\t\t'evict',\n\t\t\tsibling ? { worktreeOnly: true } : undefined,\n\t\t);\n\t\treturn types.length ? types : undefined;\n\t}\n\n\t/** `repoPath` and every worktree registered as sharing its repository, since a shared-ref write moves them all. */\n\tprivate getRepositoryPaths(repoPath: string): string[] {\n\t\tconst commonPath = this._cache.getCommonPath(repoPath);\n\t\treturn [...new Set([repoPath, commonPath, ...this._cache.getWorktreePaths(commonPath)])];\n\t}\n\n\tprivate _blame: BlameGitSubProvider | undefined;\n\tget blame(): BlameGitSubProvider {\n\t\treturn (this._blame ??= new BlameGitSubProvider(\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _branches: BranchesGitSubProvider | undefined;\n\tget branches(): BranchesGitSubProvider {\n\t\treturn (this._branches ??= new BranchesGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _commits: CommitsGitSubProvider | undefined;\n\tget commits(): CommitsGitSubProvider {\n\t\treturn (this._commits ??= new CommitsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _config: ConfigGitSubProvider | undefined;\n\tget config(): ConfigGitSubProvider {\n\t\treturn (this._config ??= new ConfigGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _contributors: ContributorsGitSubProvider | undefined;\n\tget contributors(): ContributorsGitSubProvider {\n\t\treturn (this._contributors ??= new ContributorsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _diff: DiffGitSubProvider | undefined;\n\tget diff(): DiffGitSubProvider {\n\t\treturn (this._diff ??= new DiffGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _graph: GraphGitSubProvider | undefined;\n\tget graph(): GraphGitSubProvider {\n\t\treturn (this._graph ??= new GraphGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _maintenance: MaintenanceGitSubProvider | undefined;\n\t// Optional so subclasses whose repos aren't local can report the capability as absent — see\n\t// `VslsGitProvider`. Consumers already treat `maintenance == null` as \"unsupported here\" (web builds\n\t// never register it at all).\n\tget maintenance(): MaintenanceGitSubProvider | undefined {\n\t\tif (!this._localRepositories) return undefined;\n\n\t\treturn (this._maintenance ??= new MaintenanceGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _ops: OperationsGitSubProvider | undefined;\n\tget ops(): OperationsGitSubProvider {\n\t\treturn (this._ops ??= new OperationsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _patch: PatchGitSubProvider | undefined;\n\tget patch(): PatchGitSubProvider {\n\t\treturn (this._patch ??= new PatchGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _pausedOps: PausedOperationsGitSubProvider | undefined;\n\tget pausedOps(): PausedOperationsGitSubProvider {\n\t\treturn (this._pausedOps ??= new PausedOperationsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _refs: RefsGitSubProvider | undefined;\n\tget refs(): RefsGitSubProvider {\n\t\treturn (this._refs ??= new RefsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _remotes: RemotesGitSubProvider | undefined;\n\tget remotes(): RemotesGitSubProvider {\n\t\treturn (this._remotes ??= new RemotesGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _revision: RevisionGitSubProvider | undefined;\n\tget revision(): RevisionGitSubProvider {\n\t\treturn (this._revision ??= new RevisionGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _staging: StagingGitSubProvider | undefined;\n\tget staging(): StagingGitSubProvider {\n\t\treturn (this._staging ??= new StagingGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _stash: StashGitSubProvider | undefined;\n\tget stash(): StashGitSubProvider {\n\t\treturn (this._stash ??= new StashGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _status: StatusGitSubProvider | undefined;\n\tget status(): StatusGitSubProvider {\n\t\treturn (this._status ??= new StatusGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _tags: TagsGitSubProvider | undefined;\n\tget tags(): TagsGitSubProvider {\n\t\treturn (this._tags ??= new TagsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _worktrees: WorktreesGitSubProvider | undefined;\n\tget worktrees(): WorktreesGitSubProvider {\n\t\treturn (this._worktrees ??= new WorktreesGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tgetAbsoluteUri(pathOrUri: string | Uri, base: string | Uri): Uri {\n\t\tconst baseUri = typeof base !== 'string' ? base : fileUri(base);\n\t\tif (typeof pathOrUri !== 'string') return pathOrUri;\n\t\tif (maybeUri(pathOrUri)) return parseUri(pathOrUri);\n\t\tif (path.isAbsolute(pathOrUri)) return fileUri(pathOrUri);\n\t\treturn joinUriPath(baseUri, pathOrUri);\n\t}\n\n\tgetRelativePath(pathOrUri: string | Uri, base: string | Uri): string {\n\t\tconst [relativePath] = splitPath(toFsPath(pathOrUri), toFsPath(base));\n\t\treturn relativePath;\n\t}\n\n\tasync excludeIgnoredUris(repoPath: string, uris: Uri[]): Promise<Uri[]> {\n\t\tconst filter = this.getIgnoreFilter(repoPath);\n\t\tawait filter.ready();\n\t\treturn uris.filter(uri => {\n\t\t\tconst relativePath = normalizePath(path.relative(repoPath, toFsPath(uri)));\n\t\t\treturn !relativePath || !filter.isIgnored(relativePath);\n\t\t});\n\t}\n\n\tasync getIgnoredUrisFilter(repoPath: string): Promise<(uri: Uri) => boolean> {\n\t\tconst filter = this.getIgnoreFilter(repoPath);\n\t\tawait filter.ready();\n\t\treturn (uri: Uri) => {\n\t\t\tconst relativePath = normalizePath(path.relative(repoPath, toFsPath(uri)));\n\t\t\treturn relativePath ? filter.isIgnored(relativePath) : false;\n\t\t};\n\t}\n\n\tasync getLastFetchedTimestamp(repoPath: string): Promise<number | undefined> {\n\t\treturn this._cache.getLastFetchedTimestamp(repoPath, async (commonPath): Promise<number | undefined> => {\n\t\t\tconst gitDir = await this.config.getGitDir?.(commonPath);\n\t\t\tif (gitDir == null) return undefined;\n\n\t\t\tconst gitDirUri = gitDir.commonUri ?? gitDir.uri;\n\t\t\tconst fetchHeadUri = joinUriPath(gitDirUri, 'FETCH_HEAD');\n\t\t\tconst stats = await this.context.fs.stat(fetchHeadUri);\n\t\t\t// If the file is empty, assume the fetch failed, and don't update the timestamp\n\t\t\tif (stats != null && stats.size > 0) return stats.mtime;\n\n\t\t\treturn undefined;\n\t\t});\n\t}\n\n\tgetIgnoreFilter(repoPath: string): GitIgnoreFilter {\n\t\tlet filter = this._cache.gitIgnore.get(repoPath);\n\t\tif (filter == null) {\n\t\t\tconst gitDir = this._cache.gitDir.get(repoPath);\n\t\t\tconst gitDirPath = gitDir?.uri.fsPath ?? `${repoPath}/.git`;\n\t\t\tfilter = new GitIgnoreFilter({\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tgitDirPath: gitDirPath,\n\t\t\t\tfs: this.context.fs,\n\t\t\t\t// Resolved the way git resolves it; unset, git reads its default location instead\n\t\t\t\tgetGlobalExcludesPath:\n\t\t\t\t\tthis.config.getConfig != null\n\t\t\t\t\t\t? async () => {\n\t\t\t\t\t\t\t\tconst configured = await this.config.getConfig(repoPath, 'core.excludesFile');\n\t\t\t\t\t\t\t\treturn configured != null\n\t\t\t\t\t\t\t\t\t? resolveGitPathConfig(configured, repoPath)\n\t\t\t\t\t\t\t\t\t: getDefaultGlobalExcludesPath();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t// `info/exclude` lives in the COMMON git dir — a linked worktree's own git dir has none\n\t\t\t\tgetInfoExcludePath: async () => {\n\t\t\t\t\tconst gitDir = await this.config.getGitDir?.(repoPath);\n\t\t\t\t\tif (gitDir == null) return undefined;\n\n\t\t\t\t\treturn `${(gitDir.commonUri ?? gitDir.uri).fsPath}/info/exclude`;\n\t\t\t\t},\n\t\t\t\tgetGitIgnorePaths: () => this.getGitIgnorePaths(repoPath),\n\t\t\t\tgetIgnoreCase: async () => {\n\t\t\t\t\tconst value = await this.config.getConfig?.(repoPath, 'core.ignorecase');\n\t\t\t\t\tif (value == null) return undefined;\n\t\t\t\t\tif (parseGitBoolean(value)) return true;\n\n\t\t\t\t\treturn isGitBooleanFalse(value) ? false : undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis._cache.gitIgnore.set(repoPath, filter);\n\t\t}\n\t\treturn filter;\n\t}\n\n\tasync getIgnoredDirectories(repoPath: string, cancellation?: AbortSignal): Promise<string[]> {\n\t\t// `--directory` collapses a directory to one entry when everything in it is ignored — which includes\n\t\t// directories no rule matches whose current contents merely happen to be ignored (a `logs/` holding only\n\t\t// `*.log` files under a `*.log` rule), so each candidate is confirmed against the rules below\n\t\tconst listed = await this._git.run(\n\t\t\t{ cwd: repoPath, errors: 'throw', cancellation: cancellation },\n\t\t\t'ls-files',\n\t\t\t'-z',\n\t\t\t'--others',\n\t\t\t'--ignored',\n\t\t\t'--exclude-standard',\n\t\t\t'--directory',\n\t\t);\n\n\t\tconst candidates: string[] = [];\n\t\tfor (const entry of iterateByDelimiter(listed.stdout, '\\0')) {\n\t\t\tif (entry.length > 1 && entry.endsWith('/')) {\n\t\t\t\tcandidates.push(entry);\n\t\t\t}\n\t\t}\n\t\tif (!candidates.length) return [];\n\n\t\tconst confirmed = await this.getIgnoredPaths(repoPath, candidates, cancellation);\n\n\t\tconst directories: string[] = [];\n\t\tfor (const entry of confirmed) {\n\t\t\t// Never `.git` itself, and no name a watcher would read as a pattern\n\t\t\tif (entry.length < 2 || !entry.endsWith('/') || /[*?[\\]{}()!+@\\\\]/.test(entry)) continue;\n\n\t\t\tconst directory = entry.substring(0, entry.length - 1);\n\t\t\tif (directory === '.git') continue;\n\n\t\t\tdirectories.push(directory);\n\t\t}\n\n\t\t// A path sorts after every prefix of it, so an entry's ancestors have already been kept (or not) by the time it\n\t\t// is checked — and the kept set comes out sorted\n\t\tdirectories.sort();\n\n\t\tconst kept = new Set<string>();\n\t\tfor (const directory of directories) {\n\t\t\tlet beneathKept = false;\n\t\t\tfor (let i = directory.indexOf('/'); i !== -1; i = directory.indexOf('/', i + 1)) {\n\t\t\t\tif (kept.has(directory.substring(0, i))) {\n\t\t\t\t\tbeneathKept = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!beneathKept) {\n\t\t\t\tkept.add(directory);\n\t\t\t}\n\t\t}\n\n\t\treturn [...kept];\n\t}\n\n\tasync getIgnoredEntries(repoPath: string, cancellation?: AbortSignal): Promise<string[]> {\n\t\tconst listed = await this._git.run(\n\t\t\t{ cwd: repoPath, errors: 'throw', cancellation: cancellation },\n\t\t\t'ls-files',\n\t\t\t'-z',\n\t\t\t'--others',\n\t\t\t'--ignored',\n\t\t\t'--exclude-standard',\n\t\t\t'--directory',\n\t\t\t'--no-empty-directory',\n\t\t);\n\n\t\tconst entries: string[] = [];\n\t\tfor (const entry of iterateByDelimiter(listed.stdout, '\\0')) {\n\t\t\tif (!entry.length || entry === '.git/') continue;\n\n\t\t\tentries.push(entry);\n\t\t}\n\t\treturn entries.sort();\n\t}\n\n\tasync getIgnoredPaths(\n\t\trepoPath: string,\n\t\tpaths: readonly string[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<Set<string>> {\n\t\tif (!paths.length) return new Set();\n\n\t\t// Exits 1 when nothing matches, which is an answer\n\t\tconst result = await this._git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\terrors: 'throw',\n\t\t\t\tcancellation: cancellation,\n\t\t\t\tstdin: `${paths.join('\\0')}\\0`,\n\t\t\t\texpectedExitCodes: [1],\n\t\t\t},\n\t\t\t'check-ignore',\n\t\t\t'-z',\n\t\t\t'--stdin',\n\t\t);\n\n\t\tconst ignored = new Set<string>();\n\t\tfor (const entry of iterateByDelimiter(result.stdout, '\\0')) {\n\t\t\tif (!entry.length) continue;\n\n\t\t\tignored.add(entry);\n\t\t}\n\t\treturn ignored;\n\t}\n\n\t/** Every `.gitignore` git reads in the working tree (tracked, or untracked and not itself ignored), root included */\n\tprivate async getGitIgnorePaths(repoPath: string): Promise<string[]> {\n\t\tconst result = await this._git.run(\n\t\t\t{ cwd: repoPath, errors: 'throw' },\n\t\t\t'ls-files',\n\t\t\t'-z',\n\t\t\t'--cached',\n\t\t\t'--others',\n\t\t\t'--exclude-standard',\n\t\t\t'--',\n\t\t\t':(glob)**/.gitignore',\n\t\t);\n\n\t\tconst paths: string[] = [];\n\t\tfor (const line of iterateByDelimiter(result.stdout, '\\0')) {\n\t\t\tif (!line.length) continue;\n\n\t\t\tpaths.push(line);\n\t\t}\n\t\treturn paths;\n\t}\n\n\tprivate async isTrackedWithDetails(\n\t\tfilePath: string,\n\t\trepoPath: string,\n\t\trev?: string,\n\t): Promise<{ path: string; status?: GitFileStatus; originalPath?: string } | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst [relativePath, root] = splitPath(filePath, repoPath);\n\n\t\t\t// Check if the file exists in the working tree first (better cache reuse)\n\t\t\tlet tracked = await this.revision.exists(root, relativePath);\n\t\t\tif (tracked) return { path: relativePath };\n\n\t\t\t// If a specific revision was provided, check there too\n\t\t\tif (rev && !isUncommitted(rev)) {\n\t\t\t\ttracked = await this.revision.exists(root, relativePath, rev);\n\t\t\t\tif (!tracked) {\n\t\t\t\t\t// Check the parent revision (file might have been deleted in this rev)\n\t\t\t\t\ttracked = await this.revision.exists(root, relativePath, `${rev}^`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn tracked ? { path: relativePath } : undefined;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tthis._onDidAnnounceChanges.dispose();\n\t\tthis._git.dispose();\n\t\tif (this._cacheOwned) {\n\t\t\tthis._cache.dispose();\n\t\t}\n\t}\n}\n\n/**\n * Resolves a pathname config value the way git does: a leading `~/` (or a bare `~`) is the home directory, and a\n * relative path is taken from the repository root. Done here rather than with `git config --type=path`, which needs\n * git 2.18, newer than the minimum supported version.\n */\nfunction resolveGitPathConfig(value: string, repoPath: string): string {\n\tif (value === '~' || value.startsWith('~/')) {\n\t\treturn path.join(env.HOME || homedir(), value.substring(1));\n\t}\n\n\treturn path.resolve(repoPath, value);\n}\n\n/** Where git reads global excludes when `core.excludesFile` is unset: `$XDG_CONFIG_HOME/git/ignore`, else `$HOME/.config/git/ignore` */\nfunction getDefaultGlobalExcludesPath(): string | undefined {\n\tconst xdgConfigHome = env.XDG_CONFIG_HOME;\n\tif (xdgConfigHome) return path.join(xdgConfigHome, 'git', 'ignore');\n\n\tconst home = env.HOME || homedir();\n\treturn home ? path.join(home, '.config', 'git', 'ignore') : undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cliGitProvider.js","names":["fs"],"sources":["../../../git-cli/src/cliGitProvider.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport { homedir } from 'node:os';\nimport * as path from 'node:path';\nimport { env } from 'node:process';\nimport type { CachedGitTypes, MergeTargetsChangeEvent } from '@gitlens/git/cache.js';\nimport { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitFileStatus } from '@gitlens/git/models/fileStatus.js';\nimport type { RepositoryChange } from '@gitlens/git/models/repository.js';\nimport { deletedOrMissing } from '@gitlens/git/models/revision.js';\nimport type { GitOperationRunOptions } from '@gitlens/git/providers/operations.js';\nimport type {\n\tAnnouncedRepositoryChanges,\n\tGitProvider,\n\tGitProviderDescriptor,\n} from '@gitlens/git/providers/provider.js';\nimport type { GitCommandPriority } from '@gitlens/git/run.types.js';\nimport { parseGitRemoteUrl } from '@gitlens/git/utils/remote.utils.js';\nimport { isUncommitted } from '@gitlens/git/utils/revision.utils.js';\nimport { GitIgnoreFilter } from '@gitlens/git/watching/gitIgnoreFilter.js';\nimport type { Event } from '@gitlens/utils/event.js';\nimport { Emitter } from '@gitlens/utils/event.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths, maybeUri, normalizePath, splitPath } from '@gitlens/utils/path.js';\nimport { iterateByDelimiter } from '@gitlens/utils/string.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { fileUri, joinUriPath, parseUri, toFsPath } from '@gitlens/utils/uri.js';\nimport { worktreeSharedChanges } from './exec/commandClassifier.js';\nimport { fsExists } from './exec/exec.js';\nimport type { FilteredGitFeatures, GitFeatureOrPrefix, GitFeatures } from './exec/features.js';\nimport type { GitFeatureUnsupportedMessage, GitOptions } from './exec/git.js';\nimport { batchLiteralPathspecs, Git, gitConfigsStatus } from './exec/git.js';\nimport type { GitLocation } from './exec/locator.js';\nimport { foldMatchingIgnored } from './parsers/statusParser.js';\nimport { BlameGitSubProvider } from './providers/blame.js';\nimport { BranchesGitSubProvider } from './providers/branches.js';\nimport { CommitsGitSubProvider } from './providers/commits.js';\nimport { ConfigGitSubProvider, isGitBooleanFalse, parseGitBoolean } from './providers/config.js';\nimport { ContributorsGitSubProvider } from './providers/contributors.js';\nimport { DiffGitSubProvider } from './providers/diff.js';\nimport { GraphGitSubProvider } from './providers/graph.js';\nimport { MaintenanceGitSubProvider } from './providers/maintenance.js';\nimport { OperationsGitSubProvider } from './providers/operations.js';\nimport { PatchGitSubProvider } from './providers/patch.js';\nimport { PausedOperationsGitSubProvider } from './providers/pausedOperations.js';\nimport { RefsGitSubProvider } from './providers/refs.js';\nimport { RemotesGitSubProvider } from './providers/remotes.js';\nimport { RevisionGitSubProvider } from './providers/revision.js';\nimport { StagingGitSubProvider } from './providers/staging.js';\nimport { StashGitSubProvider } from './providers/stash.js';\nimport { StatusGitSubProvider } from './providers/status.js';\nimport { TagsGitSubProvider } from './providers/tags.js';\nimport { WorktreesGitSubProvider } from './providers/worktrees.js';\n\nexport interface CliGitProviderOptions {\n\t/** Use an existing Cache instance, or one will be created */\n\tcache?: Cache;\n\t/** Context providing config and event bus hooks */\n\tcontext: GitServiceContext;\n\t/** Function that resolves the git binary location (path + version) */\n\tlocator: () => Promise<GitLocation>;\n\t/** Pre-built Git executor — when provided, used instead of creating a new Git from locator/options */\n\tgit?: Git;\n\t/** Git execution options (timeout, trust, queue config, hooks, etc.) */\n\tgitOptions?: GitOptions;\n\t/**\n\t * Whether repositories reached through this provider are on the LOCAL filesystem. `false` disables the\n\t * maintenance sub-provider entirely (Live Share): its probes stat local paths, and its writes are\n\t * rejected by the host's command allowlist, so inheriting it yields empty reports and swallowed\n\t * failures rather than an honest \"unsupported here\". Defaults to `true`.\n\t */\n\tlocalRepositories?: boolean;\n}\n\n/**\n * Exposes `isTrackedWithDetails` as a callable method for sub-providers.\n * The class declares it as a regular method, but TypeScript's structural\n * typing makes it inaccessible through the class type alone when consumed\n * internally — this type re-maps it to ensure sub-providers can call it.\n */\nexport type CliGitProviderInternal = Omit<CliGitProvider, 'isTrackedWithDetails'> & {\n\tisTrackedWithDetails: CliGitProvider['isTrackedWithDetails'];\n};\n\n/**\n * A fully-wired CLI-based git provider that executes git commands via `child_process`.\n * Implements both `CliGitProviderInternal` (for internal sub-provider wiring)\n * and `GitProvider` (for registration in a provider registry).\n *\n * @example\n * ```typescript\n * const provider = new CliGitProvider({\n * context: { events: myEvents },\n * locator: () => findGitPath(null),\n * gitOptions: { gitTimeout: 30000 },\n * });\n *\n * const branches = await provider.branches.getBranches(repoPath);\n * const status = await provider.status.getStatus(repoPath);\n * ```\n */\nexport class CliGitProvider implements GitProvider {\n\treadonly descriptor: GitProviderDescriptor = { id: 'git', name: 'Git', virtual: false };\n\n\tprivate readonly _cache: Cache;\n\tprivate readonly _cacheOwned: boolean;\n\tprivate readonly _git: Git;\n\n\treadonly context: GitServiceContext;\n\t/** The host's own hooks, before the provider wraps `cache.onReset` with its own clearing */\n\tprivate readonly _hostHooks: GitServiceContext['hooks'];\n\tprivate readonly _localRepositories: boolean;\n\n\tconstructor(options: CliGitProviderOptions) {\n\t\t// Every typed write announces itself through `onReset`, so the provider clears its own state there\n\t\t// rather than trusting each host to: a host with no handler still reads fresh after a write. A write\n\t\t// hard-evicts, so a caller after it never joins a read that started before it; watcher-driven clears\n\t\t// reach `Cache.clearCaches` directly and keep sharing in-flight reads.\n\t\tconst hostHooks = options.context.hooks;\n\t\tthis._hostHooks = hostHooks;\n\t\tthis.context = {\n\t\t\t...options.context,\n\t\t\thooks: {\n\t\t\t\t...hostHooks,\n\t\t\t\tcache: {\n\t\t\t\t\t...hostHooks?.cache,\n\t\t\t\t\tonReset: (repoPath, ...types) => {\n\t\t\t\t\t\tthis._cache.evictCaches(repoPath, ...types);\n\t\t\t\t\t\tthis._git.clearPendingCommands(this.getRepositoryPaths(repoPath));\n\t\t\t\t\t\thostHooks?.cache?.onReset?.(repoPath, ...types);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trepository: {\n\t\t\t\t\t...hostHooks?.repository,\n\t\t\t\t\tonChanged: (repoPath, changes) => {\n\t\t\t\t\t\t// Everything the watcher would have cleared for the write, since its own file events are\n\t\t\t\t\t\t// dropped once it is announced (the typed write's `onReset` names only what it must evict)\n\t\t\t\t\t\tthis.resetForChanges(repoPath, changes, undefined);\n\t\t\t\t\t\t// Worktrees share refs, tags, stash, remotes and config, so a typed write in one changes what\n\t\t\t\t\t\t// its siblings show; the host hears the shared part of it for each, and they read fresh.\n\t\t\t\t\t\t// Every path is reset before any is announced, so a read the host starts on hearing one path\n\t\t\t\t\t\t// isn't evicted by the next path's reset\n\t\t\t\t\t\tconst siblings = this.getSiblingChanges(repoPath, changes);\n\t\t\t\t\t\tfor (const [path, shared] of siblings) {\n\t\t\t\t\t\t\tthis.resetForChanges(path, shared, undefined, true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.announceChanged(repoPath, changes);\n\t\t\t\t\t\tfor (const [path, shared] of siblings) {\n\t\t\t\t\t\t\tthis.announceChanged(path, shared);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tthis._localRepositories = options.localRepositories ?? true;\n\t\tthis._git =\n\t\t\toptions.git ??\n\t\t\tnew Git(options.locator, {\n\t\t\t\t...options.gitOptions,\n\t\t\t\tisTrusted:\n\t\t\t\t\toptions.context.workspace?.isTrusted != null\n\t\t\t\t\t\t? () => options.context.workspace!.isTrusted!\n\t\t\t\t\t\t: undefined,\n\t\t\t});\n\t\tthis._cacheOwned = !(options.cache instanceof Cache);\n\t\tthis._cache = options.cache instanceof Cache ? options.cache : new Cache();\n\n\t\t// Wires a raw `git.run({ notify })` call back to this provider's own cache/host announcement —\n\t\t// unconditionally, so a host-supplied `options.git` gets bound exactly like one we construct here.\n\t\tthis._git.bindChangeNotifier((repoPaths, changes, sharedPaths) =>\n\t\t\tthis.notifyChangedCore(repoPaths, changes, undefined, sharedPaths),\n\t\t);\n\t}\n\n\t/** The underlying cache instance (for repo path registration, etc.) */\n\tget cache(): Cache {\n\t\treturn this._cache;\n\t}\n\n\tget onDidChangeMergeTargets(): Event<MergeTargetsChangeEvent> {\n\t\treturn this._cache.onDidChangeMergeTargets;\n\t}\n\n\tgetCommonPath(repoPath: string): string | undefined {\n\t\t// An unregistered path is its own common path in the cache, which would hide a sibling worktree's writes\n\t\treturn this._cache.isRegistered(repoPath) ? this._cache.getCommonPath(repoPath) : undefined;\n\t}\n\n\tprivate readonly _onDidAnnounceChanges = new Emitter<AnnouncedRepositoryChanges>();\n\tget onDidAnnounceChanges(): Event<AnnouncedRepositoryChanges> {\n\t\treturn this._onDidAnnounceChanges.event;\n\t}\n\n\t/** The underlying git execution instance (for sub-providers that need direct exec/stream access) */\n\tget git(): Git {\n\t\treturn this._git;\n\t}\n\n\t/** Returns whether the installed git version supports the given feature. */\n\tsupports(feature: GitFeatures): boolean | Promise<boolean> {\n\t\treturn this._git.supports(feature);\n\t}\n\n\t/** Returns all features matching the prefix that the installed git version supports. */\n\tsupported<T extends GitFeatureOrPrefix>(feature: T): FilteredGitFeatures<T>[] | Promise<FilteredGitFeatures<T>[]> {\n\t\treturn this._git.supported(feature);\n\t}\n\n\t/** Throws if the installed git version does not support the given feature. */\n\tasync ensureSupports(feature: GitFeatures, prefix: string, suffix: string): Promise<void>;\n\tasync ensureSupports(feature: GitFeatures, message: GitFeatureUnsupportedMessage): Promise<void>;\n\tasync ensureSupports(\n\t\tfeature: GitFeatures,\n\t\tprefixOrMessage: string | GitFeatureUnsupportedMessage,\n\t\tsuffix?: string,\n\t): Promise<void> {\n\t\treturn typeof prefixOrMessage === 'function'\n\t\t\t? this._git.ensureSupports(feature, prefixOrMessage)\n\t\t\t: this._git.ensureSupports(feature, prefixOrMessage, suffix!);\n\t}\n\n\t/** Returns the installed git version string. */\n\tasync version(): Promise<string> {\n\t\treturn this._git.version();\n\t}\n\n\t/** Returns the resolved git binary path. */\n\tasync path(): Promise<string> {\n\t\treturn this._git.path();\n\t}\n\n\tasync clone(\n\t\turl: string,\n\t\tparentPath: string,\n\t\toptions?: { folderName?: string },\n\t\trunOptions?: GitOperationRunOptions,\n\t): Promise<string | undefined> {\n\t\tlet folderPath: string;\n\t\tif (options?.folderName) {\n\t\t\tfolderPath = joinPaths(parentPath, options.folderName);\n\t\t} else {\n\t\t\tconst [, , remotePath] = parseGitRemoteUrl(url);\n\t\t\tconst remoteName = remotePath.split('/').pop();\n\t\t\tif (!remoteName) return undefined;\n\n\t\t\tlet count = 0;\n\t\t\tfolderPath = joinPaths(parentPath, remoteName);\n\t\t\twhile ((await fsExists(folderPath)) && count < 20) {\n\t\t\t\tcount++;\n\t\t\t\tfolderPath = joinPaths(parentPath, `${remoteName}-${count}`);\n\t\t\t}\n\t\t}\n\n\t\t// `throw`: the default handler swallows `remoteConnectionError`, which would return a folder never cloned\n\t\tawait this._git.run({ cwd: parentPath, errors: 'throw', ...runOptions }, 'clone', url, folderPath);\n\n\t\treturn folderPath;\n\t}\n\n\t/** Creates a new repository at `targetPath` (`git init`), creating it first if it doesn't yet exist. */\n\tasync init(targetPath: string, options?: { defaultBranch?: string; bare?: boolean }): Promise<void> {\n\t\tawait fs.mkdir(targetPath, { recursive: true });\n\n\t\tconst args = ['init'];\n\t\tif (options?.defaultBranch) {\n\t\t\targs.push('-b', options.defaultBranch);\n\t\t}\n\t\tif (options?.bare) {\n\t\t\targs.push('--bare');\n\t\t}\n\n\t\t// Run inside the target rather than naming it from its parent: a relative `targetPath` would otherwise\n\t\t// be resolved against the parent a second time\n\t\tawait this._git.run({ cwd: targetPath }, ...args);\n\t}\n\n\t/**\n\t * Notifies the provider that `repoPath` was mutated outside of a typed sub-provider method — e.g. a\n\t * consumer that ran a command through the raw `git.run`/`provider.git.run` escape hatch. Fires the same\n\t * `cache.onReset`/`repository.onChanged` hooks a typed mutator would, so, exactly as after a typed write,\n\t * the provider hard-evicts its own caches for `repoPath` and drops its pending commands for the repository\n\t * (its sibling worktrees included) before the host's handlers run.\n\t *\n\t * What is reset: `options.cache` when given (`'all'` for everything, `[]` for nothing); otherwise the\n\t * cache types `changes` map to, the same mapping a file watcher's changes get, status clock included.\n\t * An empty `changes`, or one naming `'unknown'` or `'closed'`, resets everything. Changes that map to\n\t * no cache type (e.g. `'starred'`) reset nothing, and `onReset` doesn't fire; `onChanged` always fires.\n\t */\n\tnotifyChanged(\n\t\trepoPath: string,\n\t\tchanges: readonly RepositoryChange[],\n\t\toptions?: { cache?: readonly CachedGitTypes[] | 'all' },\n\t): void {\n\t\tthis.notifyChangedCore([repoPath], changes, options);\n\t}\n\n\t/**\n\t * {@link notifyChanged} for one change seen from several paths, e.g. a `-C` shared-state verb announced\n\t * for both its target and the caller's `cwd`. Each path's caches are reset and the host's `onReset` fires\n\t * for each, since a host may keep per-worktree state, but a repository's pending commands are dropped once\n\t * however many of its worktrees are named.\n\t *\n\t * Each path hears the announcement once: `repoPaths` hear all of `changes`, `sharedPaths` (reset and\n\t * `onReset`-ed like `repoPaths`) and then the other registered worktrees sharing a repository with any of\n\t * them (reset like a typed write's, with no `onReset`) hear the shared part of it, see\n\t * {@link getSiblingChanges}.\n\t */\n\tprivate notifyChangedCore(\n\t\trepoPaths: readonly string[],\n\t\tchanges: readonly RepositoryChange[],\n\t\toptions?: { cache?: readonly CachedGitTypes[] | 'all' },\n\t\tsharedPaths?: readonly string[],\n\t): void {\n\t\tconst announcements = new Map<string, readonly RepositoryChange[]>();\n\t\tfor (const repoPath of repoPaths) {\n\t\t\tannouncements.set(repoPath, [...changes]);\n\t\t}\n\t\tconst shared = sharedPaths?.length ? this.getSharedChanges(changes) : undefined;\n\t\tif (shared != null) {\n\t\t\tfor (const path of sharedPaths!) {\n\t\t\t\tif (!announcements.has(path)) {\n\t\t\t\t\tannouncements.set(path, shared);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst resets: { repoPath: string; types: CachedGitTypes[] }[] = [];\n\t\tconst pendingPaths = new Set<string>();\n\t\tfor (const [repoPath, announced] of announcements) {\n\t\t\tconst types = this.resetForChanges(repoPath, announced, options?.cache);\n\t\t\tif (types == null) {\n\t\t\t\t// A gk config change is reconciled outside the cache types, but its re-read must not join a pre-write run\n\t\t\t\tif (options?.cache == null && announced.includes('gkConfig')) {\n\t\t\t\t\tfor (const path of this.getRepositoryPaths(repoPath)) {\n\t\t\t\t\t\tpendingPaths.add(path);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresets.push({ repoPath: repoPath, types: types });\n\t\t\tfor (const path of this.getRepositoryPaths(repoPath)) {\n\t\t\t\tpendingPaths.add(path);\n\t\t\t}\n\t\t}\n\n\t\t// The worktrees no one named: their shared refs, tags, stash, remotes and config just changed too\n\t\tconst named = [...announcements.keys()];\n\t\tfor (const repoPath of named) {\n\t\t\tfor (const [path, siblingChanges] of this.getSiblingChanges(repoPath, changes)) {\n\t\t\t\tif (announcements.has(path)) continue;\n\n\t\t\t\tannouncements.set(path, siblingChanges);\n\t\t\t\tthis.resetForChanges(path, siblingChanges, options?.cache, true);\n\t\t\t}\n\t\t}\n\n\t\tif (pendingPaths.size) {\n\t\t\tthis._git.clearPendingCommands([...pendingPaths]);\n\t\t}\n\t\tfor (const { repoPath, types } of resets) {\n\t\t\tthis._hostHooks?.cache?.onReset?.(repoPath, ...types);\n\t\t}\n\t\t// The host's own hook: `context.hooks.repository.onChanged` also fans out to siblings, which would\n\t\t// announce a path a second time\n\t\tfor (const [path, announced] of announcements) {\n\t\t\tthis.announceChanged(path, [...announced]);\n\t\t}\n\t}\n\n\t/**\n\t * Tells only the host's own `repository.onChanged` about `changes` — for a follow-up that is not a write of\n\t * core's, such as re-announcing an outside change once it was reconciled. Nothing is evicted, no sibling hears\n\t * it, and the watch layer doesn't take it for a write's announcement.\n\t */\n\tnotifyHost(repoPath: string, changes: RepositoryChange[]): void {\n\t\tthis._hostHooks?.repository?.onChanged?.(repoPath, changes);\n\t}\n\n\t/** Tells the host about a write for one path, after its caches were reset — the watch layer hears of it first */\n\tprivate announceChanged(repoPath: string, changes: RepositoryChange[]): void {\n\t\tthis._onDidAnnounceChanges.fire({ repoPath: repoPath, changes: changes });\n\t\tthis._hostHooks?.repository?.onChanged?.(repoPath, changes);\n\t}\n\n\t/**\n\t * What the worktrees sharing a repository hear of `changes` that ran in one of them: the part worktrees\n\t * share (see {@link worktreeSharedChanges}), or `undefined` when `changes` has none. An empty `changes` or\n\t * `'unknown'` means everything may have changed, so it reaches them as every shared kind — never as\n\t * `'unknown'` itself, which a host treats as the end of a watch session; `'closed'` concerns the one path\n\t * alone and reaches none.\n\t */\n\tprivate getSharedChanges(changes: readonly RepositoryChange[]): RepositoryChange[] | undefined {\n\t\tif (changes.includes('closed')) return undefined;\n\t\tif (!changes.length || changes.includes('unknown')) return [...worktreeSharedChanges];\n\n\t\tconst shared = changes.filter(c => worktreeSharedChanges.has(c));\n\t\treturn shared.length ? shared : undefined;\n\t}\n\n\t/** What each registered worktree sharing `repoPath`'s repository, other than `repoPath`, hears of `changes`. */\n\tprivate getSiblingChanges(repoPath: string, changes: readonly RepositoryChange[]): Map<string, RepositoryChange[]> {\n\t\tconst siblings = new Map<string, RepositoryChange[]>();\n\t\tconst shared = this.getSharedChanges(changes);\n\t\tif (shared == null) return siblings;\n\n\t\tconst self = normalizePath(repoPath);\n\t\tfor (const path of this._cache.getWorktreePaths(this._cache.getCommonPath(repoPath))) {\n\t\t\tif (path !== self) {\n\t\t\t\tsiblings.set(path, [...shared]);\n\t\t\t}\n\t\t}\n\t\treturn siblings;\n\t}\n\n\t/**\n\t * Evicts what a notified change reset for `repoPath`: the types reset (`[]` = all), or `undefined` for none.\n\t * A `sibling` shares its repository with a path already reset for the same change, which evicted the shared\n\t * entries for every worktree, so the changes evict only its own entries and advance its status clock.\n\t */\n\tprivate resetForChanges(\n\t\trepoPath: string,\n\t\tchanges: readonly RepositoryChange[],\n\t\tcache: readonly CachedGitTypes[] | 'all' | undefined,\n\t\tsibling: boolean = false,\n\t): CachedGitTypes[] | undefined {\n\t\tif (cache != null && cache !== 'all') {\n\t\t\tif (!cache.length) return undefined;\n\n\t\t\tthis._cache.evictCaches(repoPath, ...cache);\n\t\t\treturn [...cache];\n\t\t}\n\n\t\tif (cache === 'all' || !changes.length || changes.some(c => c === 'unknown' || c === 'closed')) {\n\t\t\tthis._cache.evictCaches(repoPath);\n\t\t\treturn [];\n\t\t}\n\n\t\tconst types = this._cache.applyRepositoryChanges(\n\t\t\trepoPath,\n\t\t\tchanges,\n\t\t\t'evict',\n\t\t\tsibling ? { worktreeOnly: true } : undefined,\n\t\t);\n\t\treturn types.length ? types : undefined;\n\t}\n\n\t/** `repoPath` and every worktree registered as sharing its repository, since a shared-ref write moves them all. */\n\tprivate getRepositoryPaths(repoPath: string): string[] {\n\t\tconst commonPath = this._cache.getCommonPath(repoPath);\n\t\treturn [...new Set([repoPath, commonPath, ...this._cache.getWorktreePaths(commonPath)])];\n\t}\n\n\tprivate _blame: BlameGitSubProvider | undefined;\n\tget blame(): BlameGitSubProvider {\n\t\treturn (this._blame ??= new BlameGitSubProvider(\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _branches: BranchesGitSubProvider | undefined;\n\tget branches(): BranchesGitSubProvider {\n\t\treturn (this._branches ??= new BranchesGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _commits: CommitsGitSubProvider | undefined;\n\tget commits(): CommitsGitSubProvider {\n\t\treturn (this._commits ??= new CommitsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _config: ConfigGitSubProvider | undefined;\n\tget config(): ConfigGitSubProvider {\n\t\treturn (this._config ??= new ConfigGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _contributors: ContributorsGitSubProvider | undefined;\n\tget contributors(): ContributorsGitSubProvider {\n\t\treturn (this._contributors ??= new ContributorsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _diff: DiffGitSubProvider | undefined;\n\tget diff(): DiffGitSubProvider {\n\t\treturn (this._diff ??= new DiffGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _graph: GraphGitSubProvider | undefined;\n\tget graph(): GraphGitSubProvider {\n\t\treturn (this._graph ??= new GraphGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _maintenance: MaintenanceGitSubProvider | undefined;\n\t// Optional so subclasses whose repos aren't local can report the capability as absent — see\n\t// `VslsGitProvider`. Consumers already treat `maintenance == null` as \"unsupported here\" (web builds\n\t// never register it at all).\n\tget maintenance(): MaintenanceGitSubProvider | undefined {\n\t\tif (!this._localRepositories) return undefined;\n\n\t\treturn (this._maintenance ??= new MaintenanceGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _ops: OperationsGitSubProvider | undefined;\n\tget ops(): OperationsGitSubProvider {\n\t\treturn (this._ops ??= new OperationsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _patch: PatchGitSubProvider | undefined;\n\tget patch(): PatchGitSubProvider {\n\t\treturn (this._patch ??= new PatchGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _pausedOps: PausedOperationsGitSubProvider | undefined;\n\tget pausedOps(): PausedOperationsGitSubProvider {\n\t\treturn (this._pausedOps ??= new PausedOperationsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _refs: RefsGitSubProvider | undefined;\n\tget refs(): RefsGitSubProvider {\n\t\treturn (this._refs ??= new RefsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _remotes: RemotesGitSubProvider | undefined;\n\tget remotes(): RemotesGitSubProvider {\n\t\treturn (this._remotes ??= new RemotesGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _revision: RevisionGitSubProvider | undefined;\n\tget revision(): RevisionGitSubProvider {\n\t\treturn (this._revision ??= new RevisionGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _staging: StagingGitSubProvider | undefined;\n\tget staging(): StagingGitSubProvider {\n\t\treturn (this._staging ??= new StagingGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _stash: StashGitSubProvider | undefined;\n\tget stash(): StashGitSubProvider {\n\t\treturn (this._stash ??= new StashGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _status: StatusGitSubProvider | undefined;\n\tget status(): StatusGitSubProvider {\n\t\treturn (this._status ??= new StatusGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _tags: TagsGitSubProvider | undefined;\n\tget tags(): TagsGitSubProvider {\n\t\treturn (this._tags ??= new TagsGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tprivate _worktrees: WorktreesGitSubProvider | undefined;\n\tget worktrees(): WorktreesGitSubProvider {\n\t\treturn (this._worktrees ??= new WorktreesGitSubProvider(\n\t\t\tthis.context,\n\t\t\tthis._git,\n\t\t\tthis._cache,\n\t\t\tthis as unknown as CliGitProviderInternal,\n\t\t));\n\t}\n\n\tgetAbsoluteUri(pathOrUri: string | Uri, base: string | Uri): Uri {\n\t\tconst baseUri = typeof base !== 'string' ? base : fileUri(base);\n\t\tif (typeof pathOrUri !== 'string') return pathOrUri;\n\t\tif (maybeUri(pathOrUri)) return parseUri(pathOrUri);\n\t\tif (path.isAbsolute(pathOrUri)) return fileUri(pathOrUri);\n\t\treturn joinUriPath(baseUri, pathOrUri);\n\t}\n\n\tgetRelativePath(pathOrUri: string | Uri, base: string | Uri): string {\n\t\tconst [relativePath] = splitPath(toFsPath(pathOrUri), toFsPath(base));\n\t\treturn relativePath;\n\t}\n\n\tasync excludeIgnoredUris(repoPath: string, uris: Uri[]): Promise<Uri[]> {\n\t\tconst filter = this.getIgnoreFilter(repoPath);\n\t\tawait filter.ready();\n\t\treturn uris.filter(uri => {\n\t\t\tconst relativePath = normalizePath(path.relative(repoPath, toFsPath(uri)));\n\t\t\treturn !relativePath || !filter.isIgnored(relativePath);\n\t\t});\n\t}\n\n\tasync getIgnoredUrisFilter(repoPath: string): Promise<(uri: Uri) => boolean> {\n\t\tconst filter = this.getIgnoreFilter(repoPath);\n\t\tawait filter.ready();\n\t\treturn (uri: Uri) => {\n\t\t\tconst relativePath = normalizePath(path.relative(repoPath, toFsPath(uri)));\n\t\t\treturn relativePath ? filter.isIgnored(relativePath) : false;\n\t\t};\n\t}\n\n\tasync getLastFetchedTimestamp(repoPath: string): Promise<number | undefined> {\n\t\treturn this._cache.getLastFetchedTimestamp(repoPath, async (commonPath): Promise<number | undefined> => {\n\t\t\tconst gitDir = await this.config.getGitDir?.(commonPath);\n\t\t\tif (gitDir == null) return undefined;\n\n\t\t\tconst gitDirUri = gitDir.commonUri ?? gitDir.uri;\n\t\t\tconst fetchHeadUri = joinUriPath(gitDirUri, 'FETCH_HEAD');\n\t\t\tconst stats = await this.context.fs.stat(fetchHeadUri);\n\t\t\t// If the file is empty, assume the fetch failed, and don't update the timestamp\n\t\t\tif (stats != null && stats.size > 0) return stats.mtime;\n\n\t\t\treturn undefined;\n\t\t});\n\t}\n\n\tgetIgnoreFilter(repoPath: string): GitIgnoreFilter {\n\t\tlet filter = this._cache.gitIgnore.get(repoPath);\n\t\tif (filter == null) {\n\t\t\tconst gitDir = this._cache.gitDir.get(repoPath);\n\t\t\tconst gitDirPath = gitDir?.uri.fsPath ?? `${repoPath}/.git`;\n\t\t\tfilter = new GitIgnoreFilter({\n\t\t\t\trepoPath: repoPath,\n\t\t\t\tgitDirPath: gitDirPath,\n\t\t\t\tfs: this.context.fs,\n\t\t\t\t// Resolved the way git resolves it; unset, git reads its default location instead\n\t\t\t\tgetGlobalExcludesPath:\n\t\t\t\t\tthis.config.getConfig != null\n\t\t\t\t\t\t? async () => {\n\t\t\t\t\t\t\t\tconst configured = await this.config.getConfig(repoPath, 'core.excludesFile');\n\t\t\t\t\t\t\t\treturn configured != null\n\t\t\t\t\t\t\t\t\t? resolveGitPathConfig(configured, repoPath)\n\t\t\t\t\t\t\t\t\t: getDefaultGlobalExcludesPath();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t// `info/exclude` lives in the COMMON git dir — a linked worktree's own git dir has none\n\t\t\t\tgetInfoExcludePath: async () => {\n\t\t\t\t\tconst gitDir = await this.config.getGitDir?.(repoPath);\n\t\t\t\t\tif (gitDir == null) return undefined;\n\n\t\t\t\t\treturn `${(gitDir.commonUri ?? gitDir.uri).fsPath}/info/exclude`;\n\t\t\t\t},\n\t\t\t\tgetGitIgnorePaths: () => this.getGitIgnorePaths(repoPath),\n\t\t\t\tgetIgnoreCase: async () => {\n\t\t\t\t\tconst value = await this.config.getConfig?.(repoPath, 'core.ignorecase');\n\t\t\t\t\tif (value == null) return undefined;\n\t\t\t\t\tif (parseGitBoolean(value)) return true;\n\n\t\t\t\t\treturn isGitBooleanFalse(value) ? false : undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis._cache.gitIgnore.set(repoPath, filter);\n\t\t}\n\t\treturn filter;\n\t}\n\n\tasync getIgnoredDirectories(repoPath: string, cancellation?: AbortSignal): Promise<string[]> {\n\t\t// `--directory` collapses a directory to one entry when everything in it is ignored — which includes\n\t\t// directories no rule matches whose current contents merely happen to be ignored (a `logs/` holding only\n\t\t// `*.log` files under a `*.log` rule), so each candidate is confirmed against the rules below\n\t\tconst listed = await this._git.run(\n\t\t\t{ cwd: repoPath, errors: 'throw', cancellation: cancellation },\n\t\t\t'ls-files',\n\t\t\t'-z',\n\t\t\t'--others',\n\t\t\t'--ignored',\n\t\t\t'--exclude-standard',\n\t\t\t'--directory',\n\t\t);\n\n\t\tconst candidates: string[] = [];\n\t\tfor (const entry of iterateByDelimiter(listed.stdout, '\\0')) {\n\t\t\tif (entry.length > 1 && entry.endsWith('/')) {\n\t\t\t\tcandidates.push(entry);\n\t\t\t}\n\t\t}\n\t\tif (!candidates.length) return [];\n\n\t\tconst confirmed = await this.getIgnoredPaths(repoPath, candidates, undefined, cancellation);\n\n\t\tconst directories: string[] = [];\n\t\tfor (const entry of confirmed) {\n\t\t\t// Never `.git` itself, and no name a watcher would read as a pattern\n\t\t\tif (entry.length < 2 || !entry.endsWith('/') || /[*?[\\]{}()!+@\\\\]/.test(entry)) continue;\n\n\t\t\tconst directory = entry.substring(0, entry.length - 1);\n\t\t\tif (directory === '.git') continue;\n\n\t\t\tdirectories.push(directory);\n\t\t}\n\n\t\t// A path sorts after every prefix of it, so an entry's ancestors have already been kept (or not) by the time it\n\t\t// is checked — and the kept set comes out sorted\n\t\tdirectories.sort();\n\n\t\tconst kept = new Set<string>();\n\t\tfor (const directory of directories) {\n\t\t\tlet beneathKept = false;\n\t\t\tfor (let i = directory.indexOf('/'); i !== -1; i = directory.indexOf('/', i + 1)) {\n\t\t\t\tif (kept.has(directory.substring(0, i))) {\n\t\t\t\t\tbeneathKept = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!beneathKept) {\n\t\t\t\tkept.add(directory);\n\t\t\t}\n\t\t}\n\n\t\treturn [...kept];\n\t}\n\n\tasync getIgnoredEntries(\n\t\trepoPath: string,\n\t\toptions?: { paths?: readonly string[]; priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<string[]> {\n\t\tconst paths = options?.paths;\n\t\t// No pathspec means \"everything\" to git, which is not what an empty list asks for\n\t\tif (paths != null && !paths.length) return [];\n\n\t\t// `status --ignored` walks every ignored tree, and `ls-files --directory` drops the ignored entries inside a\n\t\t// new untracked folder, so status is asked only about those folders\n\t\tconst args = ['ls-files', '-z', '--others', '--exclude-standard', '--directory', '--no-empty-directory'];\n\t\tconst runOptions = {\n\t\t\tcwd: repoPath,\n\t\t\terrors: 'throw',\n\t\t\tcancellation: cancellation,\n\t\t\tpriority: options?.priority,\n\t\t} as const;\n\n\t\tconst readListing = async (extra: readonly string[]): Promise<Set<string>> => {\n\t\t\tconst listed = new Set<string>();\n\t\t\tconst prefix = [...args, ...extra];\n\t\t\tfor (const batch of paths != null ? batchLiteralPathspecs(paths, prefix) : [undefined]) {\n\t\t\t\tconst result = await this._git.run(runOptions, ...prefix, ...(batch != null ? ['--', ...batch] : []));\n\t\t\t\tfor (const entry of iterateByDelimiter(result.stdout, '\\0')) {\n\t\t\t\t\tif (entry !== '') {\n\t\t\t\t\t\tlisted.add(entry);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn listed;\n\t\t};\n\n\t\tconst [ignoredResult, untrackedResult] = await Promise.allSettled([\n\t\t\treadListing(['--ignored']),\n\t\t\treadListing([]),\n\t\t]);\n\t\tif (ignoredResult.status === 'rejected') throw ignoredResult.reason;\n\t\tif (untrackedResult.status === 'rejected') throw untrackedResult.reason;\n\n\t\tconst entries = new Set<string>();\n\t\tfor (const entry of ignoredResult.value) {\n\t\t\tif (entry !== '.git/') {\n\t\t\t\tentries.add(entry);\n\t\t\t}\n\t\t}\n\n\t\tconst folders: string[] = [];\n\t\tfor (const entry of untrackedResult.value) {\n\t\t\tif (entry.endsWith('/')) {\n\t\t\t\tfolders.push(entry);\n\t\t\t}\n\t\t}\n\t\tif (!folders.length) return [...entries].sort();\n\n\t\t// `matching` reports a folder an ignore rule matches without walking it, but lists each file of a folder that is\n\t\t// ignored only because all of its files are, so `all` untracked files are needed to fold those back\n\t\tconst matching = await this._git.supports('git:status:ignored-matching');\n\t\tconst prefix = [\n\t\t\t'status',\n\t\t\t'--porcelain',\n\t\t\t'-z',\n\t\t\tmatching ? '--ignored=matching' : '--ignored',\n\t\t\tmatching ? '--untracked-files=all' : '--untracked-files=normal',\n\t\t\t'--ignore-submodules=all',\n\t\t];\n\n\t\tconst records: string[] = [];\n\t\tfor (const batch of batchLiteralPathspecs(folders, prefix)) {\n\t\t\tconst listed = await this._git.run(\n\t\t\t\t{\n\t\t\t\t\t...runOptions,\n\t\t\t\t\tconfigs: [...gitConfigsStatus, '-c', 'status.renames=false'],\n\t\t\t\t\tenv: { GIT_OPTIONAL_LOCKS: '0' },\n\t\t\t\t},\n\t\t\t\t...prefix,\n\t\t\t\t'--',\n\t\t\t\t...batch,\n\t\t\t);\n\n\t\t\t// Only untracked folders are in scope, so there are no tracked entries, and no rename pairs, to step over\n\t\t\tfor (const record of iterateByDelimiter(listed.stdout, '\\0')) {\n\t\t\t\tif (matching) {\n\t\t\t\t\trecords.push(record);\n\t\t\t\t} else if (record.startsWith('!! ')) {\n\t\t\t\t\tentries.add(record.substring(3));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (matching) {\n\t\t\tfor (const entry of foldMatchingIgnored(records)) {\n\t\t\t\tentries.add(entry);\n\t\t\t}\n\t\t}\n\t\treturn [...entries].sort();\n\t}\n\n\tasync getIgnoredPaths(\n\t\trepoPath: string,\n\t\tpaths: readonly string[],\n\t\toptions?: { priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<Set<string>> {\n\t\tif (!paths.length) return new Set();\n\n\t\t// check-ignore reads each line as a pathspec, so a leading `:` would be parsed as magic; `./` makes it a literal path\n\t\tlet prefixed: Map<string, string> | undefined;\n\t\tconst lines = paths.map(p => {\n\t\t\tif (!p.startsWith(':')) return p;\n\n\t\t\tconst sent = `./${p}`;\n\t\t\t(prefixed ??= new Map()).set(sent, p);\n\t\t\treturn sent;\n\t\t});\n\n\t\t// Exits 1 when nothing matches, which is an answer\n\t\tconst result = await this._git.run(\n\t\t\t{\n\t\t\t\tcwd: repoPath,\n\t\t\t\terrors: 'throw',\n\t\t\t\tcancellation: cancellation,\n\t\t\t\tpriority: options?.priority,\n\t\t\t\tstdin: `${lines.join('\\0')}\\0`,\n\t\t\t\texpectedExitCodes: [1],\n\t\t\t},\n\t\t\t'check-ignore',\n\t\t\t'-z',\n\t\t\t'--stdin',\n\t\t);\n\n\t\tconst ignored = new Set<string>();\n\t\tlet given: Set<string> | undefined;\n\t\tfor (const entry of iterateByDelimiter(result.stdout, '\\0')) {\n\t\t\tif (!entry.length) continue;\n\n\t\t\tconst original = prefixed?.get(entry);\n\t\t\tif (original != null) {\n\t\t\t\tignored.add(original);\n\t\t\t\t// The caller may have spelled the same file as `./:…` too, and gets that spelling back as well\n\t\t\t\tif (!(given ??= new Set(paths)).has(entry)) continue;\n\t\t\t}\n\n\t\t\tignored.add(entry);\n\t\t}\n\t\treturn ignored;\n\t}\n\n\t/** Every `.gitignore` git reads in the working tree (tracked, or untracked and not itself ignored), root included */\n\tprivate async getGitIgnorePaths(repoPath: string): Promise<string[]> {\n\t\tconst result = await this._git.run(\n\t\t\t{ cwd: repoPath, errors: 'throw' },\n\t\t\t'ls-files',\n\t\t\t'-z',\n\t\t\t'--cached',\n\t\t\t'--others',\n\t\t\t'--exclude-standard',\n\t\t\t'--',\n\t\t\t':(glob)**/.gitignore',\n\t\t);\n\n\t\tconst paths: string[] = [];\n\t\tfor (const line of iterateByDelimiter(result.stdout, '\\0')) {\n\t\t\tif (!line.length) continue;\n\n\t\t\tpaths.push(line);\n\t\t}\n\t\treturn paths;\n\t}\n\n\tprivate async isTrackedWithDetails(\n\t\tfilePath: string,\n\t\trepoPath: string,\n\t\trev?: string,\n\t): Promise<{ path: string; status?: GitFileStatus; originalPath?: string } | undefined> {\n\t\tif (rev === deletedOrMissing) return undefined;\n\n\t\tconst scope = getScopedLogger();\n\n\t\ttry {\n\t\t\tconst [relativePath, root] = splitPath(filePath, repoPath);\n\n\t\t\t// Check if the file exists in the working tree first (better cache reuse)\n\t\t\tlet tracked = await this.revision.exists(root, relativePath);\n\t\t\tif (tracked) return { path: relativePath };\n\n\t\t\t// If a specific revision was provided, check there too\n\t\t\tif (rev && !isUncommitted(rev)) {\n\t\t\t\ttracked = await this.revision.exists(root, relativePath, rev);\n\t\t\t\tif (!tracked) {\n\t\t\t\t\t// Check the parent revision (file might have been deleted in this rev)\n\t\t\t\t\ttracked = await this.revision.exists(root, relativePath, `${rev}^`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn tracked ? { path: relativePath } : undefined;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tthis._onDidAnnounceChanges.dispose();\n\t\tthis._git.dispose();\n\t\tif (this._cacheOwned) {\n\t\t\tthis._cache.dispose();\n\t\t}\n\t}\n}\n\n/**\n * Resolves a pathname config value the way git does: a leading `~/` (or a bare `~`) is the home directory, and a\n * relative path is taken from the repository root. Done here rather than with `git config --type=path`, which needs\n * git 2.18, newer than the minimum supported version.\n */\nfunction resolveGitPathConfig(value: string, repoPath: string): string {\n\tif (value === '~' || value.startsWith('~/')) {\n\t\treturn path.join(env.HOME || homedir(), value.substring(1));\n\t}\n\n\treturn path.resolve(repoPath, value);\n}\n\n/** Where git reads global excludes when `core.excludesFile` is unset: `$XDG_CONFIG_HOME/git/ignore`, else `$HOME/.config/git/ignore` */\nfunction getDefaultGlobalExcludesPath(): string | undefined {\n\tconst xdgConfigHome = env.XDG_CONFIG_HOME;\n\tif (xdgConfigHome) return path.join(xdgConfigHome, 'git', 'ignore');\n\n\tconst home = env.HOME || homedir();\n\treturn home ? path.join(home, '.config', 'git', 'ignore') : undefined;\n}\n"],"mappings":"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"}
|
|
@@ -12,6 +12,11 @@ import { GitLocation } from "./locator.js";
|
|
|
12
12
|
export declare const slowCallWarningThreshold = 2000;
|
|
13
13
|
export type GitFeatureUnsupportedMessage = (requiredVersion: string, installedVersion: string) => string;
|
|
14
14
|
export declare const maxGitCliLength = 30000;
|
|
15
|
+
/**
|
|
16
|
+
* Splits `paths` into `:(literal)` pathspec batches that each fit the command-line length limit after `prefix`, so a
|
|
17
|
+
* folder named like a glob (`[id]/`) doesn't match its siblings.
|
|
18
|
+
*/
|
|
19
|
+
export declare function batchLiteralPathspecs(paths: readonly string[], prefix: readonly string[]): Iterable<readonly string[]>;
|
|
15
20
|
export declare const gitConfigsBranch: readonly ['-c', 'color.branch=false'];
|
|
16
21
|
export declare const gitConfigsDiff: readonly ['-c', 'color.diff=false', '-c', 'diff.mnemonicPrefix=false'];
|
|
17
22
|
export declare const gitConfigsLog: readonly ['-c', 'log.showSignature=false'];
|
package/dist/git-cli/exec/git.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { chunkByStringLength } from "../../utils/iterable.js";
|
|
1
2
|
import { getScopedCounter } from "../../utils/counter.js";
|
|
2
3
|
import { CancellationError, getAbortSignalId, isCancellationError } from "../../utils/cancellation.js";
|
|
3
4
|
import { getDurationMilliseconds, hrtime } from "../../utils/hrtime.js";
|
|
@@ -14,8 +15,8 @@ import { EventLoopMonitor } from "./eventLoopMonitor.js";
|
|
|
14
15
|
import { GitQueue, getPrimaryGitCommand, inferGitCommandPriority } from "./gitQueue.js";
|
|
15
16
|
import { KeyedSequencer, isConfigCommand, isIndexWriteCommand, retryWhileConfigLocked, retryWhileIndexLocked } from "./indexLock.js";
|
|
16
17
|
import { resolve } from "path";
|
|
17
|
-
import * as process from "process";
|
|
18
18
|
import { spawn } from "child_process";
|
|
19
|
+
import * as process from "process";
|
|
19
20
|
//#region ../git-cli/src/exec/git.ts
|
|
20
21
|
const slowCallWarningThreshold = 2e3;
|
|
21
22
|
/** Below this, a queue-wait annotation isn't worth adding to the log line. */
|
|
@@ -23,6 +24,15 @@ const queueWaitAnnotationThreshold = 100;
|
|
|
23
24
|
/** Below this, a measured event-loop stall isn't worth annotating — see {@link EventLoopMonitor}. */
|
|
24
25
|
const eventLoopDelayAnnotationThreshold = 500;
|
|
25
26
|
const maxGitCliLength = 3e4;
|
|
27
|
+
/**
|
|
28
|
+
* Splits `paths` into `:(literal)` pathspec batches that each fit the command-line length limit after `prefix`, so a
|
|
29
|
+
* folder named like a glob (`[id]/`) doesn't match its siblings.
|
|
30
|
+
*/
|
|
31
|
+
function batchLiteralPathspecs(paths, prefix) {
|
|
32
|
+
const perArgOverhead = 3;
|
|
33
|
+
const prefixLength = [...prefix, "--"].reduce((sum, arg) => sum + arg.length + perArgOverhead, 0);
|
|
34
|
+
return chunkByStringLength(paths.map((p) => `:(literal)${p}`), maxGitCliLength - prefixLength, perArgOverhead);
|
|
35
|
+
}
|
|
26
36
|
const gitConfigsBranch = ["-c", "color.branch=false"];
|
|
27
37
|
const gitConfigsDiff = [
|
|
28
38
|
"-c",
|
|
@@ -620,7 +630,7 @@ var Git = class {
|
|
|
620
630
|
const start = hrtime();
|
|
621
631
|
const startEpochMs = Date.now();
|
|
622
632
|
gitCommand = `[${options.cwd}] ${gitCommand}`;
|
|
623
|
-
const { cancellation, configs, correlationKey, errors: errorHandling, encoding, expectedExitCodes, runLocally: _, selfMaintenance, slownessCategory, ...opts } = options;
|
|
633
|
+
const { beforeIndexLockRetry, cancellation, configs, correlationKey, errors: errorHandling, encoding, expectedExitCodes, runLocally: _, selfMaintenance, slownessCategory, ...opts } = options;
|
|
624
634
|
const runTimeout = opts.timeout ?? this.options.gitTimeout ?? 6e4;
|
|
625
635
|
const runOpts = {
|
|
626
636
|
...opts,
|
|
@@ -630,9 +640,10 @@ var Git = class {
|
|
|
630
640
|
env: this.buildEnv(options.env),
|
|
631
641
|
quiet: errorHandling === "ignore"
|
|
632
642
|
};
|
|
633
|
-
const unshared = options?.stdin != null || options?.env != null && Object.keys(options.env).length > 0;
|
|
643
|
+
const unshared = options?.stdin != null || options?.env != null && Object.keys(options.env).length > 0 || beforeIndexLockRetry != null;
|
|
634
644
|
const cacheKey = `${correlationKey !== void 0 ? `${correlationKey}:` : ""}${unshared ? `${unsharedRunCounter.next()}:` : ""}${cancellation != null ? `${getAbortSignalId(cancellation)}:` : ""}${gitCommand}`;
|
|
635
645
|
let execStart;
|
|
646
|
+
let hookFailure;
|
|
636
647
|
let waiting;
|
|
637
648
|
let promise = this.pendingCommands.get(cacheKey)?.promise;
|
|
638
649
|
if (promise == null) {
|
|
@@ -654,7 +665,15 @@ var Git = class {
|
|
|
654
665
|
execStart = hrtime();
|
|
655
666
|
return this._runSpawn(gitPath, args, encoding ?? "utf8", runOpts);
|
|
656
667
|
}, cancellation);
|
|
657
|
-
const
|
|
668
|
+
const beforeRetry = beforeIndexLockRetry != null ? async (lockError) => {
|
|
669
|
+
try {
|
|
670
|
+
await beforeIndexLockRetry(lockError);
|
|
671
|
+
} catch (ex) {
|
|
672
|
+
if (ex !== lockError) hookFailure = { error: ex };
|
|
673
|
+
throw ex;
|
|
674
|
+
}
|
|
675
|
+
} : void 0;
|
|
676
|
+
const spawnWithRetry = writesIndex ? () => retryWhileIndexLocked(spawnQueued, cancellation, beforeRetry) : isConfigCommand(args) ? () => retryWhileConfigLocked(spawnQueued, cancellation) : spawnQueued;
|
|
658
677
|
(checkoutKey != null ? this._indexWrites.run(checkoutKey, cancellation, spawnWithRetry) : spawnWithRetry()).then(deferred.fulfill, (e) => deferred.cancel(e instanceof Error ? e : new Error(String(e)))).finally(() => {
|
|
659
678
|
if (this.pendingCommands.get(cacheKey)?.promise === deferred.promise) this.pendingCommands.delete(cacheKey);
|
|
660
679
|
}).catch(() => {});
|
|
@@ -689,6 +708,10 @@ var Git = class {
|
|
|
689
708
|
}
|
|
690
709
|
};
|
|
691
710
|
} catch (ex) {
|
|
711
|
+
if (hookFailure != null) {
|
|
712
|
+
exception = hookFailure.error instanceof Error ? hookFailure.error : new Error(String(hookFailure.error));
|
|
713
|
+
throw hookFailure.error;
|
|
714
|
+
}
|
|
692
715
|
if (expectedExitCodes?.length && ex instanceof RunError && !(ex instanceof CancelledRunError)) {
|
|
693
716
|
const code = toExitCode(ex.code);
|
|
694
717
|
if (code != null && expectedExitCodes.includes(code)) return {
|
|
@@ -1024,6 +1047,6 @@ function defaultExceptionHandler(ex, cwd, start) {
|
|
|
1024
1047
|
throw ex;
|
|
1025
1048
|
}
|
|
1026
1049
|
//#endregion
|
|
1027
|
-
export { Git, GitError, GitErrors, GitWarnings, classifySearchError, classifySigningError, defaultExceptionHandler, getGitCommandError, gitConfigsBranch, gitConfigsDiff, gitConfigsLog, gitConfigsLogWithFiles, gitConfigsLogWithSignatures, gitConfigsPull, gitConfigsStatus, inferSigningFormatFromError, maxGitCliLength, slowCallWarningThreshold };
|
|
1050
|
+
export { Git, GitError, GitErrors, GitWarnings, batchLiteralPathspecs, classifySearchError, classifySigningError, defaultExceptionHandler, getGitCommandError, gitConfigsBranch, gitConfigsDiff, gitConfigsLog, gitConfigsLogWithFiles, gitConfigsLogWithSignatures, gitConfigsPull, gitConfigsStatus, inferSigningFormatFromError, maxGitCliLength, slowCallWarningThreshold };
|
|
1028
1051
|
|
|
1029
1052
|
//# sourceMappingURL=git.js.map
|