@gitkraken/core-gitlens 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +21 -2
  2. package/dist/git/remotes/azure-devops.js +3 -3
  3. package/dist/git/remotes/azure-devops.js.map +1 -1
  4. package/dist/git-cli/exec/git.js +1 -1
  5. package/dist/git-cli/providers/config.js +2 -2
  6. package/dist/git-cli/providers/pausedOperations.js +2 -2
  7. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  8. package/dist/git-cli/providers/staging.js +1 -1
  9. package/dist/ipc/discovery.js +1 -1
  10. package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
  11. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  12. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
  13. package/dist/plus/integrations/authentication/configuredIntegrationService.js +9 -2
  14. package/dist/plus/integrations/authentication/configuredIntegrationService.js.map +1 -1
  15. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.js +1 -1
  16. package/dist/plus/integrations/index.d.ts +2 -2
  17. package/dist/plus/integrations/index.js.map +1 -1
  18. package/dist/plus/integrations/integrationService.d.ts +34 -0
  19. package/dist/plus/integrations/integrationService.js +90 -43
  20. package/dist/plus/integrations/integrationService.js.map +1 -1
  21. package/dist/plus/integrations/lite.js +5 -4
  22. package/dist/plus/integrations/lite.js.map +1 -1
  23. package/dist/plus/integrations/manager.d.ts +68 -23
  24. package/dist/plus/integrations/models/gitHostIntegration.d.ts +30 -14
  25. package/dist/plus/integrations/models/gitHostIntegration.js +59 -21
  26. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  27. package/dist/plus/integrations/models/integration.d.ts +3 -3
  28. package/dist/plus/integrations/models/integration.js +1 -1
  29. package/dist/plus/integrations/models/integration.js.map +1 -1
  30. package/dist/plus/integrations/models/issueReads.d.ts +17 -0
  31. package/dist/plus/integrations/models/pullRequestReads.d.ts +26 -0
  32. package/dist/plus/integrations/providers/azure/azure.d.ts +66 -1
  33. package/dist/plus/integrations/providers/azure/azure.js +192 -12
  34. package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
  35. package/dist/plus/integrations/providers/azure/search.d.ts +144 -0
  36. package/dist/plus/integrations/providers/azure/search.js +250 -0
  37. package/dist/plus/integrations/providers/azure/search.js.map +1 -0
  38. package/dist/plus/integrations/providers/azureDevOps.d.ts +54 -35
  39. package/dist/plus/integrations/providers/azureDevOps.js +154 -121
  40. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
  41. package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +176 -0
  42. package/dist/plus/integrations/providers/azureDevOpsServer.js +560 -0
  43. package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -0
  44. package/dist/plus/integrations/providers/bitbucket-server/discovery.d.ts +12 -0
  45. package/dist/plus/integrations/providers/bitbucket-server/discovery.js +128 -0
  46. package/dist/plus/integrations/providers/bitbucket-server/discovery.js.map +1 -0
  47. package/dist/plus/integrations/providers/bitbucket-server/models.d.ts +10 -1
  48. package/dist/plus/integrations/providers/bitbucket-server/models.js +3 -2
  49. package/dist/plus/integrations/providers/bitbucket-server/models.js.map +1 -1
  50. package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.d.ts +58 -0
  51. package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js +485 -0
  52. package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -0
  53. package/dist/plus/integrations/providers/bitbucket-server.d.ts +52 -3
  54. package/dist/plus/integrations/providers/bitbucket-server.js +96 -20
  55. package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
  56. package/dist/plus/integrations/providers/bitbucket.js +1 -1
  57. package/dist/plus/integrations/providers/github.d.ts +5 -5
  58. package/dist/plus/integrations/providers/github.js +34 -33
  59. package/dist/plus/integrations/providers/github.js.map +1 -1
  60. package/dist/plus/integrations/providers/gitlab.d.ts +5 -3
  61. package/dist/plus/integrations/providers/gitlab.js +31 -27
  62. package/dist/plus/integrations/providers/gitlab.js.map +1 -1
  63. package/dist/plus/integrations/providers/issueSorts.d.ts +1 -0
  64. package/dist/plus/integrations/providers/jira-server.d.ts +9 -0
  65. package/dist/plus/integrations/providers/jira-server.js +13 -2
  66. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  67. package/dist/plus/integrations/providers/jira.js +1 -1
  68. package/dist/plus/integrations/providers/linear.js +1 -1
  69. package/dist/plus/integrations/providers/models.d.ts +9 -0
  70. package/dist/plus/integrations/providers/models.js +86 -0
  71. package/dist/plus/integrations/providers/models.js.map +1 -1
  72. package/dist/plus/integrations/providers/providersApi.d.ts +10 -0
  73. package/dist/plus/integrations/providers/providersApi.js +16 -1
  74. package/dist/plus/integrations/providers/providersApi.js.map +1 -1
  75. package/dist/plus/integrations/providers/utils.d.ts +12 -1
  76. package/dist/plus/integrations/providers/utils.js +36 -6
  77. package/dist/plus/integrations/providers/utils.js.map +1 -1
  78. package/dist/plus/integrations/reads/broaden.js +5 -5
  79. package/dist/plus/integrations/reads/broaden.js.map +1 -1
  80. package/dist/plus/integrations/reads/counts.d.ts +18 -4
  81. package/dist/plus/integrations/reads/counts.js +66 -15
  82. package/dist/plus/integrations/reads/counts.js.map +1 -1
  83. package/dist/plus/integrations/reads/cursors.js +1 -1
  84. package/dist/plus/integrations/reads/drains.d.ts +1 -0
  85. package/dist/plus/integrations/reads/filters.d.ts +1 -1
  86. package/dist/plus/integrations/reads/filters.js +17 -12
  87. package/dist/plus/integrations/reads/filters.js.map +1 -1
  88. package/dist/plus/integrations/reads/hierarchy.js +1 -1
  89. package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
  90. package/dist/plus/integrations/reads/issueTracker.js +1 -1
  91. package/dist/plus/integrations/reads/issues.js +1 -1
  92. package/dist/plus/integrations/reads/paging.js +1 -1
  93. package/dist/plus/integrations/reads/resolveRepository.d.ts +12 -11
  94. package/dist/plus/integrations/reads/resolveRepository.js +109 -18
  95. package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
  96. package/dist/plus/integrations/reads/searchIssues.js +4 -2
  97. package/dist/plus/integrations/reads/searchIssues.js.map +1 -1
  98. package/dist/plus/integrations/reads/searchPullRequests.js +9 -3
  99. package/dist/plus/integrations/reads/searchPullRequests.js.map +1 -1
  100. package/dist/plus/integrations/reads/trackerIssue.d.ts +9 -5
  101. package/dist/plus/integrations/reads/trackerIssue.js +15 -9
  102. package/dist/plus/integrations/reads/trackerIssue.js.map +1 -1
  103. package/dist/plus/integrations/reads/warnings.d.ts +6 -2
  104. package/dist/plus/integrations/reads/warnings.js +15 -19
  105. package/dist/plus/integrations/reads/warnings.js.map +1 -1
  106. package/dist/plus/integrations/utils/domain.utils.d.ts +19 -0
  107. package/dist/plus/integrations/utils/domain.utils.js +36 -1
  108. package/dist/plus/integrations/utils/domain.utils.js.map +1 -1
  109. package/dist/plus/integrations/utils/integration.utils.d.ts +1 -0
  110. package/dist/plus/integrations/utils/integration.utils.js +12 -1
  111. package/dist/plus/integrations/utils/integration.utils.js.map +1 -1
  112. package/dist/utils/env/node/exec.js +2 -2
  113. package/docs/integrations.md +176 -73
  114. package/docs/kepler-read-api-parity.md +19 -6
  115. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -6,17 +6,35 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.7.1] - 2026-09-24
10
+
11
+ ### Added
12
+
13
+ - Adds Bitbucket Data Center to the filtered pull-request search and its count probe ([#5875](https://github.com/gitkraken/vscode-gitlens/issues/5875)). `getSupportedFilters(BitbucketServer).pullRequestSearch` now declares the relationships `Author`, `ReviewRequested` and `Reviewed`, the states `open`/`closed`/`merged`/`all`, `text`, `draft`, `includeArchived`, the repository scope and the sorts `updated:desc`/`updated:asc` — and nothing its REST API cannot express: no assignee or mention (its pull requests have neither), no date filters, no `created` order, and no organization scope, since there is no project-wide pull-request list. `searchPullRequestsPage` reads each requested repository × relationship as its own request, or the user's dashboard for a relationship without repositories (`Reviewed` as its reviewer and participant lists, since the dashboard only filters by review status together with a role), follows every facet's own `nextPageStart` so matches past the first page are found, and binds its cursor to the connection, the configured installation URL (context path included) and the query, refusing it under anything else. Every criterion is re-checked on the rows returned, so a server that ignores one (`draft` before 8.18) narrows the page instead of widening it, and a repository that fails is reported as a scoped warning with `fetchFailed` while the others still answer, and is retried once at the page it missed before being dropped. `countPullRequests` applies the same facets and predicates, so its count is exactly the number of rows the search returns — the union of the requested states, unlike GitHub's per-state maximum. Bitbucket Data Center has no count query, so it reads each facet's first page of up to 1,000 and reports a larger scope as a floor through the new optional `PullRequestCountResult.lowerBound`. Its pull requests now also report `isDraft` from the server's `draft` field rather than always `false` (plus/integrations)
14
+ - Adds Azure DevOps Server to the filtered searches and their counts ([#5876](https://github.com/gitkraken/vscode-gitlens/issues/5876)). `searchIssuesPage` and `countIssues` run one collection-scoped WIQL query, so every relationship is OR-ed in a single query and the count is the exact size of the match set the search pages through. `searchPullRequestsPage` and `countPullRequests` drain each repository or project facet, apply text, draft and dates the pull request API can't filter by, union by repository identity and page the ordered result from a keyset cursor. `getSupportedFilters()` declares only what each search implements, a search that would span collections is refused rather than widened, and past a result ceiling the read reports a `provider-limit` omission (with `limit` and `sort`, and no invented total) and the count `exceedsProviderLimit` instead of an understated number. `ProviderIssueSearchPage`/`ProviderPullRequestSearchPage` gain `limitReached` for such a ceiling, and a provider count slot may now refuse its own scope without failing the batch (an `Error` in `ProviderSearchCount` for issues and in `ProviderPullRequestCount | Error` for pull requests), or, for issues, report `'exceeds-limit'`. Every request stays on the selected connection's installation, with the collection applied once. Scope names are no longer refused for spaces or quotes on this provider, since it never puts them in a query string. `broadenIssues` now uses the collection search for Azure DevOps Server instead of draining repositories. Azure DevOps Services is unchanged (plus/integrations)
15
+
16
+ ### Fixed
17
+
18
+ - Fixes domainless self-managed Git issue associations resolving through an arbitrary primary or cached host ([#5883](https://github.com/gitkraken/vscode-gitlens/issues/5883)). `getIssueFromGitConfigEntityIdentifier` accepts an optional `getConfiguredIntegrations` callback and resolves a legacy association only when those connections identify exactly one host. Missing configuration or multiple hosts leave it unresolved, including cache-only reads. New Bitbucket Server issue identifiers carry their domain; existing domainless identifiers retain the single-host read path, and pull request identifiers keep their persisted shape. Jira Server still requires an explicit domain (plus/integrations)
19
+ - Fixes `IntegrationService.getMyIssues` and `getMyPullRequests` reading only one host of a self-managed provider ([#5873](https://github.com/gitkraken/vscode-gitlens/issues/5873)). Both resolved each id with `get(id)` and no domain, which answers with a single instance (the first cached, else the primary configured host), so a user connected to two GitHub Enterprise servers, GitLab instances, Bitbucket Data Centers, Azure DevOps Servers or Jira Data Center instances got results from one of them and no sign the others were skipped. Every self-managed id is now read on each configured host, local and cloud connections alike, and both reads run within `providerFanOutConcurrency`. A failing host still leaves the others' results in place, and results are not deduplicated on key, since two hosts routinely share `owner/repo#number`. With `openRepositoriesOnly`, multiple hosts receive only repositories whose remotes match exactly one host: by host and port for web remotes, or by hostname for SSH remotes. Ambiguous SSH remotes are skipped. A single host retains all of its provider's open repositories, including SSH aliases. `getRemoteHostMatcher` and `isWebRemoteScheme` move to `utils/domain.utils` for that (plus/integrations)
20
+ - Fixes branch-associated GitHub Enterprise and GitLab self-hosted issues being read back from the wrong host. `getEntityIdentifierInput` only recorded a `domain` when it rewrote a `github`/`gitlab` provider id, so an issue read through the self-managed integration, which already carries the enterprise id, was encoded with no host. It now records the host for those issues. The resolver passed to `getIssueFromGitConfigEntityIdentifier` receives the identifier's `domain` as a second argument, which a self-managed provider must honor. A resolver that ignores it keeps compiling and keeps its old behavior. Pull request identifiers are unchanged, since they are also the Launchpad uuid that stored pins and snoozes key on, and legacy issue identifiers without a host use the single-host compatibility path described above (plus/integrations)
21
+ - Fixes Azure DevOps Server's relationship-filtered pull request and issue reads matching nothing or failing ([#5876](https://github.com/gitkraken/vscode-gitlens/issues/5876)). Verified against a live Azure DevOps Server 2020: a person has one identity id at the server level and another in each collection, and the creator/reviewer filters only match the collection's, so the account-wide "my pull requests" read returned an empty account. It now resolves the id from each collection's own connection data. The repo-scoped reads, and the identity lookup behind their filters, also sent a PAT as a bearer token, which Azure DevOps Server refuses with `401`; they now send it as the Basic credential every other Azure read uses. Azure DevOps Services keeps its single account id, and its PAT sessions now send the PAT the same way on those repo-scoped reads (plus/integrations)
22
+ - Fixes an Azure DevOps Server connection addressed at a collection (`https://server/tfs/DefaultCollection`) failing every account-wide read ([#5876](https://github.com/gitkraken/vscode-gitlens/issues/5876)). Azure DevOps Server only lists collections at the server level and answers the route below a collection with a 404 page, so discovery failed; it now reports the collection that address names, read from the collection's own connection data. Organization and project links, repository lists by organization, account-wide issue reads, single issue reads, merges and the legacy pull request search also applied the collection a second time on such an address, and now apply it once (plus/integrations)
23
+
9
24
  ## [0.7.0] - 2026-09-22
10
25
 
11
26
  ### Fixed
12
27
 
28
+ - Fixes self-managed integrations dropping the installation path from API requests, including Azure DevOps Server virtual directories, while keeping existing connections usable ([#5871](https://github.com/gitkraken/vscode-gitlens/issues/5871))
13
29
  - Rejects a provider response that carries an HTML page under a success status instead of handing it on as data. Azure DevOps answers a rejected credential by redirecting to its sign-in page, which then returns `203 text/html` rather than `401`, and `response.ok` spans the whole 200-299 range — so the page was read as the body and passed to provider code typed as the JSON it is not. It surfaced as an opaque `TypeError` deep inside a provider, or as nothing at all on a route returning `void`, which made a bad credential look like a successful write. Such a response now raises `UnexpectedHtmlResponseError`. On Azure DevOps, the one provider known to answer a rejected credential this way, it is classified as an authentication failure so a fan-out reports what it actually was; on every other provider it stays a request failure, because a 2xx page there is far more likely a maintenance or WAF interstitial and calling that an auth failure would expire a valid cloud session and count against the budget that disconnects the integration. A page mislabelled as JSON is caught the same way, since `<` can never open valid JSON, and content types are matched case-insensitively as the spec requires. An empty body is exempt, since a write answering `204` can carry a stale `text/html` from its endpoint's usual responses and a sign-in page is never empty. The response attached to the error is stripped of its credential-bearing headers (the session cookie Azure sets, the challenges whose payload names the tenant) and its body cut to a diagnostic prefix, because an error is something a consumer may reasonably log or forward. Azure DevOps' own REST client takes the same guard on its direct reads, where the page previously reached `rsp.json()` and died as a bare `SyntaxError` that every caller reported as a missing work item. An `AuthenticationError` now propagates out of every one of those reads — the work-item and linked issue-or-PR lookups, the PR-for-branch and PR-for-commit reads, the current-user read, the repository-metadata and default-branch probes, which degrade quietly on a 404 by design but must not on a rejected credential, and the work-item state-list read, whose empty-list fallback was cached and so pinned every work item of that type to an unknown state long after the session recovery should have run. Everything else keeps its existing degrade-to-undefined behavior. A non-2xx keeps its own status error, which says more
14
30
  - Stops pre-encoding the Azure DevOps credential now that `@gitkraken/provider-apis` 0.59.0 encodes it. That release made `isPAT` produce a real HTTP Basic header, `base64(':' + token)`, where it previously emitted the token verbatim after `Basic ` — so every caller had to encode the pair itself, as this package did via `convertTokentoPAT`. Left alone, the secret would have been encoded twice and refused by Azure DevOps on every SDK-backed read; the raw secret is now handed over and provider-apis encodes it. The one observable change is the Basic username, which goes from `PAT` to empty — the form Azure DevOps documents and the SDK verified live. Azure DevOps' own REST paths in this package build their header directly and are unaffected, as is `getCurrentUser`, which asks for a bearer token
15
31
  - Fixes account-wide GitHub issue reads ignoring `itemsPerPage`. The facade dropped the requested size before `searchMyIssues`, so its three aliased searches defaulted to 100 full issue nodes and could exceed GitHub's GraphQL complexity limit. The page size now reaches every alias; omitted values keep the existing 100-item default. (plus/integrations, plus/git-github)
16
32
 
17
33
  ### Added
18
34
 
19
- - Adds Jira Server/Data Center as a self-hosted issue integration, `jira-server` ([#5864](https://github.com/gitkraken/vscode-gitlens/issues/5864)). It is the first id that is both an issue tracker and bound to a customer-run host, so the two properties are no longer fused: `IssuesSelfManagedHostIntegrationId` names the new family and the host-keyed machinery (integration and secret keys, the `connected:${id}:${domain}` flag, domain normalization, per-host primary selection, multi-account reconcile) moves to `isSelfManagedHostIntegrationId`, which spans both families, while `isGitSelfManagedHostIntegrationId` stays exactly where a read goes on to ask for repositories, pull requests or a git remote. `IntegrationKey`/`IntegrationConnectedKey` widen to match. A self-hosted instance is modelled as its own single synthetic resource, which keeps the resource → project contract of `IssuesIntegration` intact so `listOrgs`, `listProjects` and `listIssueTrackerIssuesPage` work unchanged; `listIssueTrackerIssuesPage` gains the `domain` its siblings already took. Every read is addressed to the connection's own base URL, and `ProviderAuthenticationSession` gains an optional `baseUrl` carrying the address exactly as configured: `domain` is the identity a self-managed connection is keyed by and is normalized to a bare host, so an instance mounted below a context path (`https://jira.example.com/jira`) was previously addressed at the root. The new field is populated from the wire domain on both cloud-session paths, mirrored onto `ConfiguredIntegrationDescriptor` so reconciliation can tell a re-pointed connection from an unchanged one without reading its secret (a routine check-in now re-fetches a connection whose address moved, which a normalized domain alone cannot see, refreshes the warm integration so it re-resolves rather than staying on the old path, and keys the Jira Server project cache by the address it read from rather than by host and token, which a same-token move cannot distinguish). A backend response that reports no domain keeps the address already configured rather than writing none, so a refresh cannot silently drop a context path the user never changed, and refused when it names a different host than the connection's key; `baseUrlFromDomain` (the path-preserving sibling of `hostFromDomain`) builds the URL and is now shared rather than private to `gitHostIntegration.ts`. The account-wide "my issues" read reports `truncated` when it stops at its page backstop or on a continuation the server never advances, instead of publishing the prefix as a complete account. The host guard on a self-managed cloud session now refuses only a session that NAMES a different host, and only when the fetch was scoped by a connection id WE have stored for that host (a caller-supplied or stale id is not evidence, and neither is the absence of one): the backend may return no domain at all (`toSession` defaults it to `''`), and treating that as a mismatch stranded the refresh and left the connection looking permanently disconnected — but an UNSCOPED fetch reaches the provider-global primary endpoint, whose token can belong to any configured host, so a domainless response is still refused there rather than being bound to whatever domain the caller asked for. `Integration.icon` now reports `providersMetadata.iconKey` rather than the integration id, which is what that field documents itself as and what every consumer rendering a `gl-provider-<key>` glicon needs: Jira Data Center draws with Jira's glyph, and the self-managed GitHub and GitLab ids now report the keys their metadata declares instead of ids the icon registry has no entry for. The Commit Graph's issue-integration check enumerates every configured host for a self-managed tracker rather than asking a single resolved instance, so one disconnected host no longer disables issue enrichment while another stays connected. Project issue reads address the project by its numeric id rather than its display name, since JQL resolves a `project = "<value>"` clause against key before name and a name colliding with another project's key would read that project's issues. A key that names no issue is reported as a lookup miss rather than a request failure, matching Jira Cloud's `getJiraIssueByKey` and the generic `getIssue`. Branch-association identifiers encode the host and project, since two self-hosted instances routinely issue the same issue keys; decoding one back is not wired up yet, because the resolver behind it takes no domain and would answer from whichever connection is primary
35
+ - Adds paginated discovery of Bitbucket Data Center projects and repositories, including project-scoped reads, with connection isolation and warnings for incomplete results ([#5874](https://github.com/gitkraken/vscode-gitlens/issues/5874))
36
+ - Adds Jira Server/Data Center as a self-hosted issue integration, `jira-server` ([#5864](https://github.com/gitkraken/vscode-gitlens/issues/5864)). It is the first id that is both an issue tracker and bound to a customer-run host, so the two properties are no longer fused: `IssuesSelfManagedHostIntegrationId` names the new family and the host-keyed machinery (integration and secret keys, the `connected:${id}:${domain}` flag, domain normalization, per-host primary selection, multi-account reconcile) moves to `isSelfManagedHostIntegrationId`, which spans both families, while `isGitSelfManagedHostIntegrationId` stays exactly where a read goes on to ask for repositories, pull requests or a git remote. `IntegrationKey`/`IntegrationConnectedKey` widen to match. A self-hosted instance is modelled as its own single synthetic resource, which keeps the resource → project contract of `IssuesIntegration` intact so `listOrgs`, `listProjects` and `listIssueTrackerIssuesPage` work unchanged; `listIssueTrackerIssuesPage` gains the `domain` its siblings already took. Every read is addressed to the connection's own base URL, and `ProviderAuthenticationSession` gains an optional `baseUrl` carrying the address exactly as configured: `domain` is the identity a self-managed connection is keyed by and is normalized to a bare host, so an instance mounted below a context path (`https://jira.example.com/jira`) was previously addressed at the root. The new field is populated from the wire domain on both cloud-session paths, mirrored onto `ConfiguredIntegrationDescriptor` so reconciliation can tell a re-pointed connection from an unchanged one without reading its secret (a routine check-in now re-fetches a connection whose address moved, which a normalized domain alone cannot see, refreshes the warm integration so it re-resolves rather than staying on the old path, and keys the Jira Server project cache by the address it read from rather than by host and token, which a same-token move cannot distinguish). A backend response that reports no domain keeps the address already configured rather than writing none, so a refresh cannot silently drop a context path the user never changed, and refused when it names a different host than the connection's key; `baseUrlFromDomain` (the path-preserving sibling of `hostFromDomain`) builds the URL and is now shared rather than private to `gitHostIntegration.ts`. The account-wide "my issues" read reports `truncated` when it stops at its page backstop or on a continuation the server never advances, instead of publishing the prefix as a complete account. The host guard on a self-managed cloud session now refuses only a session that NAMES a different host, and only when the fetch was scoped by a connection id WE have stored for that host (a caller-supplied or stale id is not evidence, and neither is the absence of one): the backend may return no domain at all (`toSession` defaults it to `''`), and treating that as a mismatch stranded the refresh and left the connection looking permanently disconnected — but an UNSCOPED fetch reaches the provider-global primary endpoint, whose token can belong to any configured host, so a domainless response is still refused there rather than being bound to whatever domain the caller asked for. `Integration.icon` now reports `providersMetadata.iconKey` rather than the integration id, which is what that field documents itself as and what every consumer rendering a `gl-provider-<key>` glicon needs: Jira Data Center draws with Jira's glyph, and the self-managed GitHub and GitLab ids now report the keys their metadata declares instead of ids the icon registry has no entry for. The Commit Graph's issue-integration check enumerates every configured host for a self-managed tracker rather than asking a single resolved instance, so one disconnected host no longer disables issue enrichment while another stays connected. Project issue reads address the project by its numeric id rather than its display name, since JQL resolves a `project = "<value>"` clause against key before name and a name colliding with another project's key would read that project's issues. A key that names no issue is reported as a lookup miss rather than a request failure, matching Jira Cloud's `getJiraIssueByKey` and the generic `getIssue`. Branch-association identifiers encode the host and project, since two self-hosted instances routinely issue the same issue keys, and decode back through the host they name (#5872, below)
37
+ - Threads the host through the two point reads that serve a Jira Data Center issue, so a branch association for one now round-trips and `getTrackerIssue` serves the tracker ([#5872](https://github.com/gitkraken/vscode-gitlens/issues/5872)). `getIssueFromGitConfigEntityIdentifier`'s resolver now takes `(id, domain?)`, fed from the identifier: a Jira Data Center identifier resolves the integration for the host it names, and one that names no host is dropped rather than answered from the primary connection, which would return a different instance's issue under the same key. Identifiers encoded for the other self-managed hosts (GitHub Enterprise, GitLab Self-Managed, Azure DevOps Server) likewise resolve the integration for the host they carry rather than the primary configured one. `getTrackerIssue` gains the `domain` its paged siblings already took; `resourceId` for Jira Data Center is the host, its single resource, and no `resourceUrl` is needed because the browser link is built from the connection's own base URL. Unlike the paged reads it never falls back to the primary connection for a self-managed tracker: it requires a `domain` or a `connectionId` with a configured host and refuses otherwise, because its `issue: undefined` is a proven absence a caller may cache and two self-hosted instances routinely issue the same keys. `JiraServerIntegration` implements the resource-id point read behind it, addressed to the session's base URL like every other read, so `supportsIssueLookupByResourceId` now reports true for it
20
38
  - Adds `IssueShape.iterations` and `Issue.iterations` so consumers can access Jira sprints and Azure work-item iterations, preserving provider-reported activity and dates without inventing metadata for Azure. Coverage varies per read, and an absent value means the read couldn't report one rather than that the issue has no sprint — see "Sprints and iterations" in `docs/integrations.md`. Azure's iteration reaches both the direct work-item read, parsed here from `System.IterationPath`, and the SDK-backed reads, which requires `@gitkraken/provider-apis` 0.59.0 for the `iteration` field it normalizes; the direct read mirrors that normalization exactly — the path is the identity and is kept verbatim, so one work item cannot end up with two identities depending on which read surfaced it ([#5856](https://github.com/gitkraken/vscode-gitlens/issues/5856)).
21
39
 
22
40
  ## [0.6.0] - 2026-09-14
@@ -354,7 +372,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
354
372
 
355
373
  - Initial release. Bundles `@gitlens/utils`, `@gitlens/git`, `@gitlens/git-cli`, `@gitlens/ai`, and `@gitlens/git-github` into a single core npm package with subpath exports.
356
374
 
357
- [unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.7.0...HEAD
375
+ [unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.7.1...HEAD
376
+ [0.7.1]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.7.0...gitkraken:releases/core/v0.7.1
358
377
  [0.7.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.6.0...gitkraken:releases/core/v0.7.0
359
378
  [0.6.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.5.116...gitkraken:releases/core/v0.6.0
360
379
  [0.5.116]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.5.115...gitkraken:releases/core/v0.5.116
@@ -29,10 +29,10 @@ function parseVstsHttpsUrl(url) {
29
29
  }
30
30
  const azureHttpsUrlRegex2 = /([^/]+)\/([^/]+)\/_git\/([^/]+)/;
31
31
  function parseAzureRepositoryPath(path, legacyVsts, cloud) {
32
- const segments = path.split("/");
32
+ const segments = path.split("/").map((segment) => decodeURIComponent(segment));
33
33
  const gitIndex = segments.length - 2;
34
34
  const projectIndex = gitIndex - 1;
35
- if (gitIndex < 1 || segments[gitIndex]?.toLowerCase() !== "_git" || segments.some((segment) => !segment || segment === "." || segment === "..")) return;
35
+ if (gitIndex < 1 || segments[gitIndex]?.toLowerCase() !== "_git" || segments.some((segment) => !segment || segment === "." || segment === ".." || /[/\\]/.test(segment))) return;
36
36
  const project = segments[projectIndex];
37
37
  const repository = segments[gitIndex + 1];
38
38
  if (!project || !repository) return void 0;
@@ -87,8 +87,8 @@ var AzureDevOpsRemoteProvider = class AzureDevOpsRemoteProvider extends RemotePr
87
87
  } else path = `${org}/${project}/_git/${rest}`;
88
88
  }
89
89
  }
90
- path = decodeURIComponent(path);
91
90
  const repositoryPath = parseAzureRepositoryPath(path, isVsts, domain.toLowerCase() === "dev.azure.com");
91
+ path = decodeURIComponent(path);
92
92
  super(domain, path, protocol, name, void 0, context);
93
93
  this.collection = repositoryPath?.collection;
94
94
  this.project = repositoryPath?.project;
@@ -1 +1 @@
1
- {"version":3,"file":"azure-devops.js","names":[],"sources":["../../../../git/src/remotes/azure-devops.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Brand, Unbrand } from '@gitlens/utils/brand.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport type { RemoteProviderContext } from '../context.js';\nimport type { AutolinkReference, DynamicAutolinkReference } from '../models/autolink.js';\nimport type { LineRange } from '../models/lineRange.js';\nimport type { ParsedRemoteFileUri, RemoteProviderId } from '../models/remoteProvider.js';\nimport { RemoteProvider } from '../models/remoteProvider.js';\nimport type { CreatePullRequestRemoteResource } from '../models/remoteResource.js';\nimport type { GkProviderId } from '../models/repositoryIdentities.js';\nimport type { ResourceDescriptor } from '../models/resourceDescriptor.js';\nimport type { GitRevisionRangeNotation } from '../models/revision.js';\n\nconst gitRegex = /\\/_git\\/?/i;\nconst gitTailRegex = /\\/_git(?:\\/.*)?$/i;\nconst legacyDefaultCollectionRegex = /^DefaultCollection\\//i;\nconst orgAndProjectRegex = /^(.*?)\\/(.*?)\\/(.*)/;\nconst sshDomainRegex = /^(ssh|vs-ssh)\\./i;\nconst sshPathRegex = /^\\/?v\\d\\//i;\n\nconst azureSshUrlRegex = /^(?:[^@]+@)?([^:]+):v\\d\\//;\n\nconst vstsHostnameSuffix = '.visualstudio.com';\n\nexport function isVsts(domain: string): boolean {\n\treturn domain.endsWith(vstsHostnameSuffix);\n}\n\nfunction getVSTSOwner(url: URL): string {\n\treturn url.hostname.split('.')[0];\n}\n\nconst azureProjectRepoRegex = /([^/]+)\\/_git\\/([^/]+)/;\n\nfunction parseVstsHttpsUrl(url: URL): [string, string, string] {\n\tconst owner = getVSTSOwner(url);\n\tconst match = azureProjectRepoRegex.exec(url.pathname);\n\tif (match == null) throw new Error(`Invalid VSTS URL: ${url.toString()}`);\n\n\tconst [, project, repo] = match;\n\treturn [owner, project, repo];\n}\n\nconst azureHttpsUrlRegex2 = /([^/]+)\\/([^/]+)\\/_git\\/([^/]+)/;\n\ntype AzureRepositoryPath = {\n\tcollection: string | undefined;\n\tproject: string;\n\trepositoryPath: string;\n\tvirtualDirectory: string | undefined;\n};\n\nexport type AzureDevOpsRepositoryDescriptor = ResourceDescriptor & {\n\towner: string | undefined;\n\tname: string | undefined;\n\tvirtualDirectory?: string;\n};\n\nfunction parseAzureRepositoryPath(path: string, legacyVsts: boolean, cloud: boolean): AzureRepositoryPath | undefined {\n\tconst segments = path.split('/');\n\tconst gitIndex = segments.length - 2;\n\tconst projectIndex = gitIndex - 1;\n\tif (\n\t\tgitIndex < 1 ||\n\t\tsegments[gitIndex]?.toLowerCase() !== '_git' ||\n\t\tsegments.some(segment => !segment || segment === '.' || segment === '..')\n\t) {\n\t\treturn undefined;\n\t}\n\n\tconst project = segments[projectIndex];\n\tconst repository = segments[gitIndex + 1];\n\tif (!project || !repository) return undefined;\n\n\tconst collectionPath = segments.slice(0, projectIndex);\n\tif (legacyVsts) {\n\t\tif (collectionPath.length !== 0) return undefined;\n\n\t\treturn {\n\t\t\tcollection: undefined,\n\t\t\tproject: project,\n\t\t\trepositoryPath: `${project}/_git/${repository}`,\n\t\t\tvirtualDirectory: undefined,\n\t\t};\n\t}\n\n\tif (collectionPath.length === 0 || (cloud && collectionPath.length !== 1)) return undefined;\n\n\treturn {\n\t\tcollection: collectionPath.at(-1),\n\t\tproject: project,\n\t\trepositoryPath: `${project}/_git/${repository}`,\n\t\tvirtualDirectory: collectionPath.length > 1 ? collectionPath.slice(0, -1).join('/') : undefined,\n\t};\n}\n\nfunction parseAzureNewStyleUrl(url: URL): [string, string, string] {\n\tconst match = azureHttpsUrlRegex2.exec(url.pathname);\n\tif (match == null) throw new Error(`Invalid Azure URL: ${url.toString()}`);\n\n\tconst [, owner, project, repo] = match;\n\treturn [owner, project, repo];\n}\n\nexport function parseAzureHttpsUrl(url: string): [owner: string, project: string, repo: string];\nexport function parseAzureHttpsUrl(urlObj: URL): [owner: string, project: string, repo: string];\nexport function parseAzureHttpsUrl(arg: URL | string): [owner: string, project: string, repo: string] {\n\tconst url = typeof arg === 'string' ? new URL(arg) : arg;\n\tif (url.hostname.endsWith(vstsHostnameSuffix)) return parseVstsHttpsUrl(url);\n\treturn parseAzureNewStyleUrl(url);\n}\n\nexport class AzureDevOpsRemoteProvider extends RemoteProvider<AzureDevOpsRepositoryDescriptor> {\n\tprivate readonly collection: string | undefined;\n\tprivate readonly project: string | undefined;\n\tprivate readonly repositoryPath: string | undefined;\n\tprivate readonly virtualDirectory: string | undefined;\n\n\tconstructor(\n\t\tdomain: string,\n\t\tpath: string,\n\t\tprotocol?: string,\n\t\tname?: string,\n\t\tisVsts: boolean = false,\n\t\tcontext?: RemoteProviderContext,\n\t) {\n\t\tif (sshDomainRegex.test(domain)) {\n\t\t\tpath = path.replace(sshPathRegex, '');\n\t\t\tdomain = domain.replace(sshDomainRegex, '');\n\n\t\t\t// Add in /_git/ into ssh urls\n\t\t\tconst match = orgAndProjectRegex.exec(path);\n\t\t\tif (match != null) {\n\t\t\t\tconst [, org, project, rest] = match;\n\n\t\t\t\t// VSTS puts the org in the subdomain; modern Azure DevOps puts it in the path\n\t\t\t\tif (isVsts) {\n\t\t\t\t\tdomain = `${org}.${domain}`;\n\t\t\t\t\tpath = `${project}/_git/${rest}`;\n\t\t\t\t} else {\n\t\t\t\t\tpath = `${org}/${project}/_git/${rest}`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Azure DevOps allows projects and repository names with spaces. In that situation,\n\t\t// the `path` will be previously encoded during git clone\n\t\t// revert that encoding to avoid double-encoding by gitlens during copy remote and open remote\n\t\tpath = decodeURIComponent(path);\n\t\tconst repositoryPath = parseAzureRepositoryPath(path, isVsts, domain.toLowerCase() === 'dev.azure.com');\n\t\tsuper(domain, path, protocol, name, undefined, context);\n\t\tthis.collection = repositoryPath?.collection;\n\t\tthis.project = repositoryPath?.project;\n\t\tthis.repositoryPath = repositoryPath?.repositoryPath;\n\t\tthis.virtualDirectory = repositoryPath?.virtualDirectory;\n\t}\n\n\tprotected override get issueLinkPattern(): string {\n\t\tconst projectUrl = this.baseUrl.replace(gitTailRegex, '');\n\t\tconst orgUrl = projectUrl.substring(0, projectUrl.lastIndexOf('/'));\n\t\treturn `${orgUrl}/_workitems/edit/<num>`;\n\t}\n\n\tprivate _autolinks: (AutolinkReference | DynamicAutolinkReference)[] | undefined;\n\toverride get autolinks(): (AutolinkReference | DynamicAutolinkReference)[] {\n\t\t// Strip off any `_git` part from the repo url\n\t\tthis._autolinks ??= [\n\t\t\t...super.autolinks,\n\t\t\t{\n\t\t\t\tprefix: '#',\n\t\t\t\turl: this.issueLinkPattern,\n\t\t\t\talphanumeric: false,\n\t\t\t\tignoreCase: false,\n\t\t\t\ttitle: l10n.t('Open Work Item #{number} on {provider}', { number: '<num>', provider: this.name }),\n\n\t\t\t\ttype: 'issue',\n\t\t\t\tdescription: l10n.t('{provider} Work Item #{number}', { provider: this.name, number: '<num>' }),\n\t\t\t},\n\t\t\t{\n\t\t\t\t// Default Pull request message when merging a PR in ADO. Will not catch commits & pushes following a different pattern.\n\t\t\t\tprefix: 'PR ',\n\t\t\t\turl: `${this.baseUrl}/pullrequest/<num>`,\n\t\t\t\talphanumeric: false,\n\t\t\t\tignoreCase: false,\n\t\t\t\ttitle: l10n.t('Open Pull Request #{number} on {provider}', { number: '<num>', provider: this.name }),\n\n\t\t\t\ttype: 'pullrequest',\n\t\t\t\tdescription: l10n.t('{provider} Pull Request #{number}', {\n\t\t\t\t\tprovider: this.name,\n\t\t\t\t\tnumber: '<num>',\n\t\t\t\t}),\n\t\t\t},\n\t\t];\n\t\treturn this._autolinks;\n\t}\n\n\toverride get icon(): string {\n\t\treturn 'azdo';\n\t}\n\n\tget id(): RemoteProviderId {\n\t\treturn 'azure-devops';\n\t}\n\n\tget gkProviderId(): GkProviderId {\n\t\treturn 'azureDevops' satisfies Unbrand<GkProviderId> as Brand<GkProviderId>;\n\t}\n\n\tget name(): string {\n\t\treturn 'Azure DevOps';\n\t}\n\n\toverride get owner(): string | undefined {\n\t\tif (isVsts(this.domain)) {\n\t\t\treturn this.domain.split('.')[0];\n\t\t}\n\t\treturn this.collection ?? super.owner;\n\t}\n\n\toverride get repoName(): string | undefined {\n\t\tif (isVsts(this.domain)) {\n\t\t\treturn this.path;\n\t\t}\n\t\treturn this.repositoryPath ?? super.repoName;\n\t}\n\n\toverride get repoDesc(): AzureDevOpsRepositoryDescriptor {\n\t\tconst descriptor = super.repoDesc;\n\t\treturn this.virtualDirectory == null ? descriptor : { ...descriptor, virtualDirectory: this.virtualDirectory };\n\t}\n\n\toverride get providerDesc():\n\t\t| {\n\t\t\t\tid: GkProviderId;\n\t\t\t\trepoDomain: string;\n\t\t\t\trepoName: string;\n\t\t\t\trepoOwnerDomain: string;\n\t\t }\n\t\t| undefined {\n\t\tif (this.gkProviderId == null || this.owner == null || this.repoName == null || this.project == null) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tid: this.gkProviderId,\n\t\t\trepoDomain: this.project,\n\t\t\trepoName: this.repoName,\n\t\t\trepoOwnerDomain: this.owner,\n\t\t};\n\t}\n\n\tprivate _displayPath: string | undefined;\n\toverride get displayPath(): string {\n\t\tthis._displayPath ??= this.path.replace(gitRegex, '/').replace(legacyDefaultCollectionRegex, '');\n\t\treturn this._displayPath;\n\t}\n\n\tprivate static readonly fileQueryRegex = /path=([^&]+)/i;\n\tprivate static readonly rangeQueryRegex = /line=(\\d+)(?:&lineEnd=(\\d+))?/;\n\n\toverride parseRemoteFileUri(uri: Uri): ParsedRemoteFileUri | undefined {\n\t\tif (uri.authority !== this.domain) return undefined;\n\n\t\tlet startLine;\n\t\tlet endLine;\n\t\tif (uri.query) {\n\t\t\tconst rangeMatch = AzureDevOpsRemoteProvider.rangeQueryRegex.exec(uri.query);\n\t\t\tif (rangeMatch != null) {\n\t\t\t\tconst [, start, end] = rangeMatch;\n\t\t\t\tif (start) {\n\t\t\t\t\tstartLine = parseInt(start, 10);\n\t\t\t\t\tif (end) {\n\t\t\t\t\t\tendLine = parseInt(end, 10);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst fileMatch = AzureDevOpsRemoteProvider.fileQueryRegex.exec(uri.query);\n\t\tif (fileMatch == null) return undefined;\n\n\t\tconst [, path] = fileMatch;\n\n\t\treturn {\n\t\t\tstartLine: startLine,\n\t\t\tendLine: endLine,\n\t\t\tcandidates: [{ type: 'pathOnly', filePath: path }],\n\t\t};\n\t}\n\n\tprotected getUrlForBranches(): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/branches`);\n\t}\n\n\tprotected getUrlForBranch(branch: string): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/?version=GB${branch}&_a=history`);\n\t}\n\n\tprotected getUrlForCommit(sha: string): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/commit/${sha}`);\n\t}\n\n\tprotected override getUrlForComparison(base: string, head: string, _notation: GitRevisionRangeNotation): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/branchCompare?baseVersion=GB${base}&targetVersion=GB${head}`);\n\t}\n\n\tprotected override async getUrlForCreatePullRequest({\n\t\tbase,\n\t\thead,\n\t}: CreatePullRequestRemoteResource): Promise<string | undefined> {\n\t\tconst query = new URLSearchParams({ sourceRef: head.branch, targetRef: base.branch ?? '' });\n\n\t\tif (base.remote.url !== head.remote.url) {\n\t\t\tconst parsedBaseUrl = parseAzureUrl(base.remote.url);\n\t\t\tif (parsedBaseUrl == null) return undefined;\n\n\t\t\tconst { org: baseOrg, project: baseProject, repo: baseName } = parsedBaseUrl;\n\t\t\tconst repoInfo = await this.context?.getRepositoryInfo?.(this.id, {\n\t\t\t\towner: baseOrg,\n\t\t\t\tname: baseName,\n\t\t\t\tproject: baseProject,\n\t\t\t});\n\t\t\tif (!repoInfo) return undefined;\n\n\t\t\tquery.set('targetRepositoryId', repoInfo.id);\n\t\t}\n\n\t\treturn `${this.encodeUrl(`${this.getRepoBaseUrl(head.remote.path)}/pullrequestcreate`)}?${query.toString()}`;\n\t}\n\n\tprotected getUrlForFile(fileName: string, branch?: string, sha?: string, range?: LineRange): string {\n\t\tlet line;\n\t\tif (range != null) {\n\t\t\tif (range.startLine === range.endLine) {\n\t\t\t\tline = `&line=${range.startLine}&lineStartColumn=${range.startCharacter}&lineEndColumn=${range.endCharacter}`;\n\t\t\t} else {\n\t\t\t\tline = `&line=${range.startLine}&lineEnd=${range.endLine}&lineStartColumn=${range.startCharacter}&lineEndColumn=${range.endCharacter}`;\n\t\t\t}\n\t\t} else {\n\t\t\tline = '';\n\t\t}\n\n\t\tif (sha) return this.encodeUrl(`${this.baseUrl}?path=${fileName}&version=GC${sha}${line}&_a=contents`);\n\t\tif (branch) return this.encodeUrl(`${this.baseUrl}/?path=/${fileName}&version=GB${branch}&_a=contents${line}`);\n\t\treturn this.encodeUrl(`${this.baseUrl}?path=/${fileName}${line}`);\n\t}\n}\n\nfunction parseAzureUrl(url: string): { org: string; project: string; repo: string } | undefined {\n\tif (azureSshUrlRegex.test(url)) {\n\t\t// Examples of SSH urls:\n\t\t// - old one: bbbchiv@vs-ssh.visualstudio.com:v3/bbbchiv/MyFirstProject/test\n\t\t// - modern one: git@ssh.dev.azure.com:v3/bbbchiv2/MyFirstProject/test\n\t\turl = url.replace(azureSshUrlRegex, '');\n\t\tconst match = orgAndProjectRegex.exec(url);\n\t\tif (match != null) {\n\t\t\tconst [, org, project, rest] = match;\n\t\t\treturn { org: org, project: project, repo: rest };\n\t\t}\n\t} else {\n\t\tconst [org, project, rest] = parseAzureHttpsUrl(url);\n\t\treturn { org: org, project: project, repo: rest };\n\t}\n\treturn undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"azure-devops.js","names":[],"sources":["../../../../git/src/remotes/azure-devops.ts"],"sourcesContent":["import * as l10n from '@vscode/l10n';\nimport type { Brand, Unbrand } from '@gitlens/utils/brand.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport type { RemoteProviderContext } from '../context.js';\nimport type { AutolinkReference, DynamicAutolinkReference } from '../models/autolink.js';\nimport type { LineRange } from '../models/lineRange.js';\nimport type { ParsedRemoteFileUri, RemoteProviderId } from '../models/remoteProvider.js';\nimport { RemoteProvider } from '../models/remoteProvider.js';\nimport type { CreatePullRequestRemoteResource } from '../models/remoteResource.js';\nimport type { GkProviderId } from '../models/repositoryIdentities.js';\nimport type { ResourceDescriptor } from '../models/resourceDescriptor.js';\nimport type { GitRevisionRangeNotation } from '../models/revision.js';\n\nconst gitRegex = /\\/_git\\/?/i;\nconst gitTailRegex = /\\/_git(?:\\/.*)?$/i;\nconst legacyDefaultCollectionRegex = /^DefaultCollection\\//i;\nconst orgAndProjectRegex = /^(.*?)\\/(.*?)\\/(.*)/;\nconst sshDomainRegex = /^(ssh|vs-ssh)\\./i;\nconst sshPathRegex = /^\\/?v\\d\\//i;\n\nconst azureSshUrlRegex = /^(?:[^@]+@)?([^:]+):v\\d\\//;\n\nconst vstsHostnameSuffix = '.visualstudio.com';\n\nexport function isVsts(domain: string): boolean {\n\treturn domain.endsWith(vstsHostnameSuffix);\n}\n\nfunction getVSTSOwner(url: URL): string {\n\treturn url.hostname.split('.')[0];\n}\n\nconst azureProjectRepoRegex = /([^/]+)\\/_git\\/([^/]+)/;\n\nfunction parseVstsHttpsUrl(url: URL): [string, string, string] {\n\tconst owner = getVSTSOwner(url);\n\tconst match = azureProjectRepoRegex.exec(url.pathname);\n\tif (match == null) throw new Error(`Invalid VSTS URL: ${url.toString()}`);\n\n\tconst [, project, repo] = match;\n\treturn [owner, project, repo];\n}\n\nconst azureHttpsUrlRegex2 = /([^/]+)\\/([^/]+)\\/_git\\/([^/]+)/;\n\ntype AzureRepositoryPath = {\n\tcollection: string | undefined;\n\tproject: string;\n\trepositoryPath: string;\n\tvirtualDirectory: string | undefined;\n};\n\nexport type AzureDevOpsRepositoryDescriptor = ResourceDescriptor & {\n\towner: string | undefined;\n\tname: string | undefined;\n\tvirtualDirectory?: string;\n};\n\nfunction parseAzureRepositoryPath(path: string, legacyVsts: boolean, cloud: boolean): AzureRepositoryPath | undefined {\n\tconst segments = path.split('/').map(segment => decodeURIComponent(segment));\n\tconst gitIndex = segments.length - 2;\n\tconst projectIndex = gitIndex - 1;\n\tif (\n\t\tgitIndex < 1 ||\n\t\tsegments[gitIndex]?.toLowerCase() !== '_git' ||\n\t\tsegments.some(segment => !segment || segment === '.' || segment === '..' || /[/\\\\]/.test(segment))\n\t) {\n\t\treturn undefined;\n\t}\n\n\tconst project = segments[projectIndex];\n\tconst repository = segments[gitIndex + 1];\n\tif (!project || !repository) return undefined;\n\n\tconst collectionPath = segments.slice(0, projectIndex);\n\tif (legacyVsts) {\n\t\tif (collectionPath.length !== 0) return undefined;\n\n\t\treturn {\n\t\t\tcollection: undefined,\n\t\t\tproject: project,\n\t\t\trepositoryPath: `${project}/_git/${repository}`,\n\t\t\tvirtualDirectory: undefined,\n\t\t};\n\t}\n\n\tif (collectionPath.length === 0 || (cloud && collectionPath.length !== 1)) return undefined;\n\n\treturn {\n\t\tcollection: collectionPath.at(-1),\n\t\tproject: project,\n\t\trepositoryPath: `${project}/_git/${repository}`,\n\t\tvirtualDirectory: collectionPath.length > 1 ? collectionPath.slice(0, -1).join('/') : undefined,\n\t};\n}\n\nfunction parseAzureNewStyleUrl(url: URL): [string, string, string] {\n\tconst match = azureHttpsUrlRegex2.exec(url.pathname);\n\tif (match == null) throw new Error(`Invalid Azure URL: ${url.toString()}`);\n\n\tconst [, owner, project, repo] = match;\n\treturn [owner, project, repo];\n}\n\nexport function parseAzureHttpsUrl(url: string): [owner: string, project: string, repo: string];\nexport function parseAzureHttpsUrl(urlObj: URL): [owner: string, project: string, repo: string];\nexport function parseAzureHttpsUrl(arg: URL | string): [owner: string, project: string, repo: string] {\n\tconst url = typeof arg === 'string' ? new URL(arg) : arg;\n\tif (url.hostname.endsWith(vstsHostnameSuffix)) return parseVstsHttpsUrl(url);\n\treturn parseAzureNewStyleUrl(url);\n}\n\nexport class AzureDevOpsRemoteProvider extends RemoteProvider<AzureDevOpsRepositoryDescriptor> {\n\tprivate readonly collection: string | undefined;\n\tprivate readonly project: string | undefined;\n\tprivate readonly repositoryPath: string | undefined;\n\tprivate readonly virtualDirectory: string | undefined;\n\n\tconstructor(\n\t\tdomain: string,\n\t\tpath: string,\n\t\tprotocol?: string,\n\t\tname?: string,\n\t\tisVsts: boolean = false,\n\t\tcontext?: RemoteProviderContext,\n\t) {\n\t\tif (sshDomainRegex.test(domain)) {\n\t\t\tpath = path.replace(sshPathRegex, '');\n\t\t\tdomain = domain.replace(sshDomainRegex, '');\n\n\t\t\t// Add in /_git/ into ssh urls\n\t\t\tconst match = orgAndProjectRegex.exec(path);\n\t\t\tif (match != null) {\n\t\t\t\tconst [, org, project, rest] = match;\n\n\t\t\t\t// VSTS puts the org in the subdomain; modern Azure DevOps puts it in the path\n\t\t\t\tif (isVsts) {\n\t\t\t\t\tdomain = `${org}.${domain}`;\n\t\t\t\t\tpath = `${project}/_git/${rest}`;\n\t\t\t\t} else {\n\t\t\t\t\tpath = `${org}/${project}/_git/${rest}`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Azure DevOps allows projects and repository names with spaces. In that situation,\n\t\t// the `path` will be previously encoded during git clone\n\t\t// revert that encoding to avoid double-encoding by gitlens during copy remote and open remote\n\t\tconst repositoryPath = parseAzureRepositoryPath(path, isVsts, domain.toLowerCase() === 'dev.azure.com');\n\t\tpath = decodeURIComponent(path);\n\t\tsuper(domain, path, protocol, name, undefined, context);\n\t\tthis.collection = repositoryPath?.collection;\n\t\tthis.project = repositoryPath?.project;\n\t\tthis.repositoryPath = repositoryPath?.repositoryPath;\n\t\tthis.virtualDirectory = repositoryPath?.virtualDirectory;\n\t}\n\n\tprotected override get issueLinkPattern(): string {\n\t\tconst projectUrl = this.baseUrl.replace(gitTailRegex, '');\n\t\tconst orgUrl = projectUrl.substring(0, projectUrl.lastIndexOf('/'));\n\t\treturn `${orgUrl}/_workitems/edit/<num>`;\n\t}\n\n\tprivate _autolinks: (AutolinkReference | DynamicAutolinkReference)[] | undefined;\n\toverride get autolinks(): (AutolinkReference | DynamicAutolinkReference)[] {\n\t\t// Strip off any `_git` part from the repo url\n\t\tthis._autolinks ??= [\n\t\t\t...super.autolinks,\n\t\t\t{\n\t\t\t\tprefix: '#',\n\t\t\t\turl: this.issueLinkPattern,\n\t\t\t\talphanumeric: false,\n\t\t\t\tignoreCase: false,\n\t\t\t\ttitle: l10n.t('Open Work Item #{number} on {provider}', { number: '<num>', provider: this.name }),\n\n\t\t\t\ttype: 'issue',\n\t\t\t\tdescription: l10n.t('{provider} Work Item #{number}', { provider: this.name, number: '<num>' }),\n\t\t\t},\n\t\t\t{\n\t\t\t\t// Default Pull request message when merging a PR in ADO. Will not catch commits & pushes following a different pattern.\n\t\t\t\tprefix: 'PR ',\n\t\t\t\turl: `${this.baseUrl}/pullrequest/<num>`,\n\t\t\t\talphanumeric: false,\n\t\t\t\tignoreCase: false,\n\t\t\t\ttitle: l10n.t('Open Pull Request #{number} on {provider}', { number: '<num>', provider: this.name }),\n\n\t\t\t\ttype: 'pullrequest',\n\t\t\t\tdescription: l10n.t('{provider} Pull Request #{number}', {\n\t\t\t\t\tprovider: this.name,\n\t\t\t\t\tnumber: '<num>',\n\t\t\t\t}),\n\t\t\t},\n\t\t];\n\t\treturn this._autolinks;\n\t}\n\n\toverride get icon(): string {\n\t\treturn 'azdo';\n\t}\n\n\tget id(): RemoteProviderId {\n\t\treturn 'azure-devops';\n\t}\n\n\tget gkProviderId(): GkProviderId {\n\t\treturn 'azureDevops' satisfies Unbrand<GkProviderId> as Brand<GkProviderId>;\n\t}\n\n\tget name(): string {\n\t\treturn 'Azure DevOps';\n\t}\n\n\toverride get owner(): string | undefined {\n\t\tif (isVsts(this.domain)) {\n\t\t\treturn this.domain.split('.')[0];\n\t\t}\n\t\treturn this.collection ?? super.owner;\n\t}\n\n\toverride get repoName(): string | undefined {\n\t\tif (isVsts(this.domain)) {\n\t\t\treturn this.path;\n\t\t}\n\t\treturn this.repositoryPath ?? super.repoName;\n\t}\n\n\toverride get repoDesc(): AzureDevOpsRepositoryDescriptor {\n\t\tconst descriptor = super.repoDesc;\n\t\treturn this.virtualDirectory == null ? descriptor : { ...descriptor, virtualDirectory: this.virtualDirectory };\n\t}\n\n\toverride get providerDesc():\n\t\t| {\n\t\t\t\tid: GkProviderId;\n\t\t\t\trepoDomain: string;\n\t\t\t\trepoName: string;\n\t\t\t\trepoOwnerDomain: string;\n\t\t }\n\t\t| undefined {\n\t\tif (this.gkProviderId == null || this.owner == null || this.repoName == null || this.project == null) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tid: this.gkProviderId,\n\t\t\trepoDomain: this.project,\n\t\t\trepoName: this.repoName,\n\t\t\trepoOwnerDomain: this.owner,\n\t\t};\n\t}\n\n\tprivate _displayPath: string | undefined;\n\toverride get displayPath(): string {\n\t\tthis._displayPath ??= this.path.replace(gitRegex, '/').replace(legacyDefaultCollectionRegex, '');\n\t\treturn this._displayPath;\n\t}\n\n\tprivate static readonly fileQueryRegex = /path=([^&]+)/i;\n\tprivate static readonly rangeQueryRegex = /line=(\\d+)(?:&lineEnd=(\\d+))?/;\n\n\toverride parseRemoteFileUri(uri: Uri): ParsedRemoteFileUri | undefined {\n\t\tif (uri.authority !== this.domain) return undefined;\n\n\t\tlet startLine;\n\t\tlet endLine;\n\t\tif (uri.query) {\n\t\t\tconst rangeMatch = AzureDevOpsRemoteProvider.rangeQueryRegex.exec(uri.query);\n\t\t\tif (rangeMatch != null) {\n\t\t\t\tconst [, start, end] = rangeMatch;\n\t\t\t\tif (start) {\n\t\t\t\t\tstartLine = parseInt(start, 10);\n\t\t\t\t\tif (end) {\n\t\t\t\t\t\tendLine = parseInt(end, 10);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst fileMatch = AzureDevOpsRemoteProvider.fileQueryRegex.exec(uri.query);\n\t\tif (fileMatch == null) return undefined;\n\n\t\tconst [, path] = fileMatch;\n\n\t\treturn {\n\t\t\tstartLine: startLine,\n\t\t\tendLine: endLine,\n\t\t\tcandidates: [{ type: 'pathOnly', filePath: path }],\n\t\t};\n\t}\n\n\tprotected getUrlForBranches(): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/branches`);\n\t}\n\n\tprotected getUrlForBranch(branch: string): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/?version=GB${branch}&_a=history`);\n\t}\n\n\tprotected getUrlForCommit(sha: string): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/commit/${sha}`);\n\t}\n\n\tprotected override getUrlForComparison(base: string, head: string, _notation: GitRevisionRangeNotation): string {\n\t\treturn this.encodeUrl(`${this.baseUrl}/branchCompare?baseVersion=GB${base}&targetVersion=GB${head}`);\n\t}\n\n\tprotected override async getUrlForCreatePullRequest({\n\t\tbase,\n\t\thead,\n\t}: CreatePullRequestRemoteResource): Promise<string | undefined> {\n\t\tconst query = new URLSearchParams({ sourceRef: head.branch, targetRef: base.branch ?? '' });\n\n\t\tif (base.remote.url !== head.remote.url) {\n\t\t\tconst parsedBaseUrl = parseAzureUrl(base.remote.url);\n\t\t\tif (parsedBaseUrl == null) return undefined;\n\n\t\t\tconst { org: baseOrg, project: baseProject, repo: baseName } = parsedBaseUrl;\n\t\t\tconst repoInfo = await this.context?.getRepositoryInfo?.(this.id, {\n\t\t\t\towner: baseOrg,\n\t\t\t\tname: baseName,\n\t\t\t\tproject: baseProject,\n\t\t\t});\n\t\t\tif (!repoInfo) return undefined;\n\n\t\t\tquery.set('targetRepositoryId', repoInfo.id);\n\t\t}\n\n\t\treturn `${this.encodeUrl(`${this.getRepoBaseUrl(head.remote.path)}/pullrequestcreate`)}?${query.toString()}`;\n\t}\n\n\tprotected getUrlForFile(fileName: string, branch?: string, sha?: string, range?: LineRange): string {\n\t\tlet line;\n\t\tif (range != null) {\n\t\t\tif (range.startLine === range.endLine) {\n\t\t\t\tline = `&line=${range.startLine}&lineStartColumn=${range.startCharacter}&lineEndColumn=${range.endCharacter}`;\n\t\t\t} else {\n\t\t\t\tline = `&line=${range.startLine}&lineEnd=${range.endLine}&lineStartColumn=${range.startCharacter}&lineEndColumn=${range.endCharacter}`;\n\t\t\t}\n\t\t} else {\n\t\t\tline = '';\n\t\t}\n\n\t\tif (sha) return this.encodeUrl(`${this.baseUrl}?path=${fileName}&version=GC${sha}${line}&_a=contents`);\n\t\tif (branch) return this.encodeUrl(`${this.baseUrl}/?path=/${fileName}&version=GB${branch}&_a=contents${line}`);\n\t\treturn this.encodeUrl(`${this.baseUrl}?path=/${fileName}${line}`);\n\t}\n}\n\nfunction parseAzureUrl(url: string): { org: string; project: string; repo: string } | undefined {\n\tif (azureSshUrlRegex.test(url)) {\n\t\t// Examples of SSH urls:\n\t\t// - old one: bbbchiv@vs-ssh.visualstudio.com:v3/bbbchiv/MyFirstProject/test\n\t\t// - modern one: git@ssh.dev.azure.com:v3/bbbchiv2/MyFirstProject/test\n\t\turl = url.replace(azureSshUrlRegex, '');\n\t\tconst match = orgAndProjectRegex.exec(url);\n\t\tif (match != null) {\n\t\t\tconst [, org, project, rest] = match;\n\t\t\treturn { org: org, project: project, repo: rest };\n\t\t}\n\t} else {\n\t\tconst [org, project, rest] = parseAzureHttpsUrl(url);\n\t\treturn { org: org, project: project, repo: rest };\n\t}\n\treturn undefined;\n}\n"],"mappings":"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"}
@@ -11,8 +11,8 @@ import { CancelledRunError, RunError, fsExists, runSpawn } from "../../utils/env
11
11
  import { compare, fromString } from "../../utils/version.js";
12
12
  import { EventLoopMonitor } from "./eventLoopMonitor.js";
13
13
  import { GitQueue, getPrimaryGitCommand, inferGitCommandPriority } from "./gitQueue.js";
14
- import { spawn } from "child_process";
15
14
  import * as process from "process";
15
+ import { spawn } from "child_process";
16
16
  //#region ../git-cli/src/exec/git.ts
17
17
  const slowCallWarningThreshold = 2e3;
18
18
  /** Below this, a queue-wait annotation isn't worth adding to the log line. */
@@ -8,9 +8,9 @@ import __decorate from "../../_virtual/@oxc-project+runtime/helpers/esm/decorate
8
8
  import { WorkspaceUntrustedError } from "../../git/errors.js";
9
9
  import { fsExists } from "../../utils/env/node/exec.js";
10
10
  import { gate } from "../../utils/decorators/gate.js";
11
- import { promises } from "fs";
12
- import { env } from "process";
13
11
  import { hostname, userInfo } from "os";
12
+ import { env } from "process";
13
+ import { promises } from "fs";
14
14
  //#region ../git-cli/src/providers/config.ts
15
15
  const mappedAuthorRegex = /(.+)\s<(.+)>/;
16
16
  const emptyArray = Object.freeze([]);
@@ -9,8 +9,8 @@ import { PausedOperationAbortError, PausedOperationContinueError } from "../../g
9
9
  import { getGitCommandError } from "../exec/git.js";
10
10
  import { gate } from "../../utils/decorators/gate.js";
11
11
  import * as l10n from "@vscode/l10n";
12
- import { readdir } from "fs";
13
12
  import { readFile, stat } from "fs/promises";
13
+ import { readdir as readdir$1 } from "fs";
14
14
  //#region ../git-cli/src/providers/pausedOperations.ts
15
15
  const todoCommitRegex = /^(?:p(?:ick)?|revert)\s+([a-f0-9]+)(?:\s+(.+))?$/i;
16
16
  const orderedOperations = [
@@ -38,7 +38,7 @@ var PausedOperationsGitSubProvider = class {
38
38
  return this.cache.pausedOperationStatus.getOrCreate(repoPath, async (_cancellable) => {
39
39
  const gitDir = await this.provider.config.getGitDir(repoPath);
40
40
  const operations = await new Promise((resolve, _) => {
41
- readdir(gitDir.uri.fsPath, { withFileTypes: true }, (err, entries) => {
41
+ readdir$1(gitDir.uri.fsPath, { withFileTypes: true }, (err, entries) => {
42
42
  const operations = /* @__PURE__ */ new Set();
43
43
  if (err != null) {
44
44
  resolve(operations);
@@ -1 +1 @@
1
- {"version":3,"file":"pausedOperations.js","names":[],"sources":["../../../../git-cli/src/providers/pausedOperations.ts"],"sourcesContent":["import { readdir } from 'fs';\nimport { readFile, stat } from 'fs/promises';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { PausedOperationAbortError, PausedOperationContinueError } from '@gitlens/git/errors.js';\nimport type {\n\tGitCherryPickStatus,\n\tGitMergeStatus,\n\tGitPausedOperationStatus,\n\tGitRebaseStatus,\n\tGitRevertStatus,\n} from '@gitlens/git/models/pausedOperationStatus.js';\nimport type { GitBranchReference, GitTagReference } from '@gitlens/git/models/reference.js';\nimport type { GitDir } from '@gitlens/git/models/repository.js';\nimport type { GitPausedOperationsSubProvider } from '@gitlens/git/providers/pausedOperations.js';\nimport { createReference } from '@gitlens/git/utils/reference.utils.js';\nimport { CancellationError } from '@gitlens/utils/cancellation.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { getGitCommandError } from '../exec/git.js';\n\nconst todoCommitRegex = /^(?:p(?:ick)?|revert)\\s+([a-f0-9]+)(?:\\s+(.+))?$/i;\n\ntype Operation = 'cherry-pick' | 'merge' | 'rebase-apply' | 'rebase-merge' | 'revert' | 'sequencer';\n\n// Note: 'sequencer' is checked after specific HEAD files since those take precedence\n// The sequencer directory is used for multi-commit cherry-picks/reverts\nconst orderedOperations: Operation[] = ['rebase-apply', 'rebase-merge', 'merge', 'cherry-pick', 'revert', 'sequencer'];\n\nexport class PausedOperationsGitSubProvider implements GitPausedOperationsSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tgetPausedOperationStatus(\n\t\trepoPath: string,\n\t\toptions?: { force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitPausedOperationStatus | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Self-heal callers (WIP refresh) bypass the cache so a missed `'pausedOp'` FS-watcher\n\t\t// event (CLI-driven completion, torn-down secondary-worktree watcher) can't leave the\n\t\t// status stuck — the readdir-based detection is cheap enough to repeat on every tick.\n\t\tif (options?.force) {\n\t\t\tthis.cache.pausedOperationStatus.delete(repoPath);\n\t\t}\n\n\t\tconst status = this.cache.pausedOperationStatus.getOrCreate(repoPath, async _cancellable => {\n\t\t\tconst gitDir = await this.provider.config.getGitDir(repoPath);\n\n\t\t\tconst operations = await new Promise<Set<Operation>>((resolve, _) => {\n\t\t\t\treaddir(gitDir.uri.fsPath, { withFileTypes: true }, (err, entries) => {\n\t\t\t\t\tconst operations = new Set<Operation>();\n\t\t\t\t\tif (err != null) {\n\t\t\t\t\t\tresolve(operations);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (entries.length === 0) {\n\t\t\t\t\t\tresolve(operations);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet entry;\n\t\t\t\t\tfor (entry of entries) {\n\t\t\t\t\t\tif (entry.isFile()) {\n\t\t\t\t\t\t\tswitch (entry.name) {\n\t\t\t\t\t\t\t\tcase 'CHERRY_PICK_HEAD':\n\t\t\t\t\t\t\t\t\toperations.add('cherry-pick');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'MERGE_HEAD':\n\t\t\t\t\t\t\t\t\toperations.add('merge');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'REVERT_HEAD':\n\t\t\t\t\t\t\t\t\toperations.add('revert');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (entry.isDirectory()) {\n\t\t\t\t\t\t\tswitch (entry.name) {\n\t\t\t\t\t\t\t\tcase 'rebase-apply':\n\t\t\t\t\t\t\t\t\toperations.add('rebase-apply');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'rebase-merge':\n\t\t\t\t\t\t\t\t\toperations.add('rebase-merge');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'sequencer':\n\t\t\t\t\t\t\t\t\t// The sequencer directory is used for multi-commit cherry-picks/reverts\n\t\t\t\t\t\t\t\t\t// We'll determine the type by reading the todo file later\n\t\t\t\t\t\t\t\t\toperations.add('sequencer');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve(operations);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tif (!operations.size) return undefined;\n\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\tconst sortedOperations = [...operations].sort(\n\t\t\t\t(a, b) => orderedOperations.indexOf(a) - orderedOperations.indexOf(b),\n\t\t\t);\n\t\t\tscope?.info(`Detected paused operations: ${sortedOperations.join(', ')}`);\n\n\t\t\tconst operation = sortedOperations[0];\n\t\t\tswitch (operation) {\n\t\t\t\tcase 'cherry-pick': {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t'CHERRY_PICK_HEAD',\n\t\t\t\t\t);\n\t\t\t\t\tif (result.completion.status === 'cancelled' || cancellation?.aborted) {\n\t\t\t\t\t\tthrow new CancellationError();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst cherryPickHead = result.stdout.trim();\n\t\t\t\t\tif (!cherryPickHead) {\n\t\t\t\t\t\tscope?.addExitInfo('No CHERRY_PICK_HEAD found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult, messageResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, 'CHERRY_PICK_HEAD', 'HEAD', undefined, cancellation),\n\t\t\t\t\t\tthis.getCommitMessage(repoPath, cherryPickHead, cancellation),\n\t\t\t\t\t]);\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\t// Names the commit being applied, so consumers can say which one a skip would drop\n\t\t\t\t\tconst message = getSettledValue(messageResult);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'cherry-pick',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(cherryPickHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming: createReference(cherryPickHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t} satisfies GitCherryPickStatus;\n\t\t\t\t}\n\t\t\t\tcase 'merge': {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t'MERGE_HEAD',\n\t\t\t\t\t);\n\t\t\t\t\tif (result.completion.status === 'cancelled' || cancellation?.aborted) {\n\t\t\t\t\t\tthrow new CancellationError();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst mergeHead = result.stdout.trim();\n\t\t\t\t\tif (!mergeHead) {\n\t\t\t\t\t\tscope?.addExitInfo('No MERGE_HEAD found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult, possibleSourceBranchesResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, 'MERGE_HEAD', 'HEAD', undefined, cancellation),\n\t\t\t\t\t\tthis.provider.branches.getBranchesWithCommits(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t['MERGE_HEAD'],\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t{ all: true, mode: 'pointsAt' },\n\t\t\t\t\t\t\tcancellation,\n\t\t\t\t\t\t),\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\tconst possibleSourceBranches = getSettledValue(possibleSourceBranchesResult);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'merge',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(mergeHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming:\n\t\t\t\t\t\t\tpossibleSourceBranches?.length === 1\n\t\t\t\t\t\t\t\t? createReference(possibleSourceBranches[0], repoPath, {\n\t\t\t\t\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\t\t\t\t\tname: possibleSourceBranches[0],\n\t\t\t\t\t\t\t\t\t\tremote: false,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: createReference(mergeHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t} satisfies GitMergeStatus;\n\t\t\t\t}\n\t\t\t\tcase 'revert': {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t'REVERT_HEAD',\n\t\t\t\t\t);\n\t\t\t\t\tif (result.completion.status === 'cancelled' || cancellation?.aborted) {\n\t\t\t\t\t\tthrow new CancellationError();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst revertHead = result.stdout.trim();\n\t\t\t\t\tif (!revertHead) {\n\t\t\t\t\t\tscope?.addExitInfo('No REVERT_HEAD found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult, messageResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, 'REVERT_HEAD', 'HEAD', undefined, cancellation),\n\t\t\t\t\t\tthis.getCommitMessage(repoPath, revertHead, cancellation),\n\t\t\t\t\t]);\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\t// Names the commit being reverted, so consumers can say which one a skip would drop\n\t\t\t\t\tconst message = getSettledValue(messageResult);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'revert',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(revertHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming: createReference(revertHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t} satisfies GitRevertStatus;\n\t\t\t\t}\n\t\t\t\tcase 'rebase-apply':\n\t\t\t\tcase 'rebase-merge': {\n\t\t\t\t\tlet branch = await this.readDotGitFile(gitDir, [operation, 'head-name']);\n\t\t\t\t\tif (!branch) {\n\t\t\t\t\t\tscope?.addExitInfo(`No '${operation}/head-name' found`);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [\n\t\t\t\t\t\trebaseHeadResult,\n\t\t\t\t\t\torigHeadResult,\n\t\t\t\t\t\tontoResult,\n\t\t\t\t\t\tstepsNumberResult,\n\t\t\t\t\t\tstepsTotalResult,\n\t\t\t\t\t\tstepsMessageResult,\n\t\t\t\t\t\tisInteractiveResult,\n\t\t\t\t\t] = await Promise.allSettled([\n\t\t\t\t\t\tthis.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t\t'REBASE_HEAD',\n\t\t\t\t\t\t),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'orig-head']),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'onto']),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'msgnum'], { numeric: true }),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'end'], { numeric: true }),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'message'], { throw: true }).catch(() =>\n\t\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'message-squashed']),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tstat(joinPaths(gitDir.uri.fsPath, operation, 'interactive')).then(\n\t\t\t\t\t\t\t() => true,\n\t\t\t\t\t\t\t() => false,\n\t\t\t\t\t\t),\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst origHead = getSettledValue(origHeadResult);\n\t\t\t\t\tconst onto = getSettledValue(ontoResult);\n\t\t\t\t\tif (origHead == null || onto == null) {\n\t\t\t\t\t\tscope?.addExitInfo(`Neither '${operation}/orig-head' nor '${operation}/onto' found`);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst rebaseHead = getSettledValue(rebaseHeadResult)?.stdout.trim();\n\n\t\t\t\t\tif (branch.startsWith('refs/heads/')) {\n\t\t\t\t\t\tbranch = branch.substring(11).trim();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [mergeBaseResult, branchTipsResult, tagTipsResult] = await Promise.allSettled([\n\t\t\t\t\t\trebaseHead\n\t\t\t\t\t\t\t? this.provider.refs.getMergeBase(repoPath, rebaseHead, 'HEAD', undefined, cancellation)\n\t\t\t\t\t\t\t: this.provider.refs.getMergeBase(repoPath, onto, origHead, undefined, cancellation),\n\t\t\t\t\t\tthis.provider.branches.getBranchesWithCommits(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t[onto],\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tall: true,\n\t\t\t\t\t\t\t\tmode: 'pointsAt',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcancellation,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tthis.provider.tags.getTagsWithCommit(repoPath, onto, { mode: 'pointsAt' }, cancellation),\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\tconst branchTips = getSettledValue(branchTipsResult);\n\t\t\t\t\tconst tagTips = getSettledValue(tagTipsResult);\n\n\t\t\t\t\tlet ontoRef: GitBranchReference | GitTagReference | undefined;\n\t\t\t\t\tif (branchTips != null) {\n\t\t\t\t\t\tfor (const ref of branchTips) {\n\t\t\t\t\t\t\tif (ref.startsWith('(no branch, rebasing')) continue;\n\n\t\t\t\t\t\t\tontoRef = createReference(ref, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\t\t\tname: ref,\n\t\t\t\t\t\t\t\tremote: false,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (ontoRef == null && tagTips != null) {\n\t\t\t\t\t\tfor (const ref of tagTips) {\n\t\t\t\t\t\t\tif (ref.startsWith('(no branch, rebasing')) continue;\n\n\t\t\t\t\t\t\tontoRef = createReference(ref, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'tag',\n\t\t\t\t\t\t\t\tname: ref,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst stepsNumber = getSettledValue(stepsNumberResult) ?? 0;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'rebase',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(rebaseHead ?? origHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tonto: createReference(onto, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tsource: createReference(origHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tcurrent: ontoRef,\n\t\t\t\t\t\tincoming: createReference(branch, repoPath, {\n\t\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\t\tname: branch,\n\t\t\t\t\t\t\tremote: false,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tsteps: {\n\t\t\t\t\t\t\tcurrent: {\n\t\t\t\t\t\t\t\tnumber: stepsNumber,\n\t\t\t\t\t\t\t\tcommit: rebaseHead\n\t\t\t\t\t\t\t\t\t? createReference(rebaseHead, repoPath, {\n\t\t\t\t\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\t\t\t\t\tmessage: getSettledValue(stepsMessageResult),\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttotal: getSettledValue(stepsTotalResult) ?? 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\thasStarted: stepsNumber > 0,\n\t\t\t\t\t\t// REBASE_HEAD only exists when git is paused and waiting for user action\n\t\t\t\t\t\tisPaused: stepsNumber > 0 && rebaseHead != null,\n\t\t\t\t\t\t// 'interactive' file exists for `git rebase -i`, absent for `git pull --rebase`\n\t\t\t\t\t\tisInteractive: getSettledValue(isInteractiveResult) ?? false,\n\t\t\t\t\t} satisfies GitRebaseStatus;\n\t\t\t\t}\n\t\t\t\tcase 'sequencer': {\n\t\t\t\t\t// Used for multi-commit cherry-picks/reverts when CHERRY_PICK_HEAD/REVERT_HEAD don't exist\n\t\t\t\t\tconst todoContent = await this.readDotGitFile(gitDir, ['sequencer', 'todo']);\n\t\t\t\t\tif (!todoContent) {\n\t\t\t\t\t\tscope?.addExitInfo('No sequencer/todo file found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Get the first line and determine if it's a cherry-pick or revert\n\t\t\t\t\tconst firstLine = todoContent.split('\\n')[0]?.trim();\n\t\t\t\t\tif (!firstLine) {\n\t\t\t\t\t\tscope?.addExitInfo('Empty sequencer/todo file');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if it's a pick (cherry-pick) or revert command\n\t\t\t\t\t// Format: \"pick <sha> <message>\" or \"p <sha> <message>\" or \"revert <sha> <message>\"\n\t\t\t\t\tconst isCherryPick = /^p(?:ick)?\\s/.test(firstLine);\n\t\t\t\t\tconst isRevert = /^revert\\s/.test(firstLine);\n\n\t\t\t\t\tif (!isCherryPick && !isRevert) {\n\t\t\t\t\t\tscope?.addExitInfo(`Unknown sequencer command: ${firstLine}`);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Parse the commit sha being applied from the todo file\n\t\t\t\t\tconst match = firstLine.match(todoCommitRegex);\n\t\t\t\t\tconst currentCommitSha = match?.[1];\n\t\t\t\t\tif (!currentCommitSha) {\n\t\t\t\t\t\tscope?.addExitInfo('Could not parse commit sha from sequencer/todo');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// The todo line carries only the commit's SUBJECT (the other producers carry the full\n\t\t\t\t\t// message) — good enough to name the commit a skip would drop, without another git call\n\t\t\t\t\tconst message = match?.[2]?.trim() || undefined;\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, currentCommitSha, 'HEAD', undefined, cancellation),\n\t\t\t\t\t]);\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\n\t\t\t\t\tif (isCherryPick) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: 'cherry-pick',\n\t\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\t\tHEAD: createReference(currentCommitSha, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\t\tmessage: message,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\t\tincoming: createReference(currentCommitSha, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\t\tmessage: message,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t} satisfies GitCherryPickStatus;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'revert',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(currentCommitSha, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming: createReference(currentCommitSha, repoPath, {\n\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\tmessage: message,\n\t\t\t\t\t\t}),\n\t\t\t\t\t} satisfies GitRevertStatus;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn status;\n\t}\n\n\t/** Memoized per repo by sha — forced status re-reads on FS noise (every file save while resolving\n\t * conflicts) would otherwise re-spawn `git log` for an unchanging commit. */\n\tprivate readonly _commitMessageCache = new Map<string, { sha: string; message: string | undefined }>();\n\n\tprivate async getCommitMessage(\n\t\trepoPath: string,\n\t\tsha: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tconst cached = this._commitMessageCache.get(repoPath);\n\t\tif (cached?.sha === sha) return cached.message;\n\n\t\tconst result = await this.git.run(\n\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t'log',\n\t\t\t'-1',\n\t\t\t'--format=%B',\n\t\t\tsha,\n\t\t);\n\t\tconst message = result.stdout.trim() || undefined;\n\t\t// Don't cache a miss — a transient failure would otherwise stick for the operation's lifetime\n\t\tif (message != null) {\n\t\t\tthis._commitMessageCache.set(repoPath, { sha: sha, message: message });\n\t\t}\n\t\treturn message;\n\t}\n\n\tprivate async readDotGitFile(\n\t\tgitDir: GitDir,\n\t\tpathParts: string[],\n\t\toptions?: { numeric?: false; throw?: boolean; trim?: boolean },\n\t): Promise<string | undefined>;\n\tprivate async readDotGitFile(\n\t\tgitDir: GitDir,\n\t\tpathParts: string[],\n\t\toptions?: { numeric: true; throw?: boolean; trim?: boolean },\n\t): Promise<number | undefined>;\n\tprivate async readDotGitFile(\n\t\tgitDir: GitDir,\n\t\tpathParts: string[],\n\t\toptions?: { numeric?: boolean; throw?: boolean; trim?: boolean },\n\t): Promise<string | number | undefined> {\n\t\ttry {\n\t\t\tconst filePath = joinPaths(gitDir.uri.fsPath, ...pathParts);\n\t\t\tconst bytes = await readFile(filePath);\n\t\t\tlet contents = new TextDecoder('utf8').decode(bytes);\n\t\t\tcontents = (options?.trim ?? true) ? contents.trim() : contents;\n\n\t\t\tif (options?.numeric) {\n\t\t\t\tconst number = Number.parseInt(contents, 10);\n\t\t\t\treturn isNaN(number) ? undefined : number;\n\t\t\t}\n\n\t\t\treturn contents;\n\t\t} catch (ex) {\n\t\t\tif (options?.throw) throw ex;\n\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@gate((rp, o) => `${rp ?? ''}:${o?.quit ?? false}`)\n\t@debug()\n\tasync abortPausedOperation(repoPath: string, options?: { quit?: boolean }): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst status = await this.getPausedOperationStatus(repoPath);\n\t\tif (status == null) return;\n\n\t\tconst args = [status.type, options?.quit ? '--quit' : '--abort'];\n\n\t\ttry {\n\t\t\t// Unbounded like the operations it undoes — an abort of a large rebase can outrun the default\n\t\t\t// command timeout, and being SIGTERM'd partway through would leave the repo mid-abort.\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', timeout: 0 }, ...args);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'paused-operation-abort',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PausedOperationAbortError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\toperation: status,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@debug()\n\tasync continuePausedOperation(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tallowEmpty?: boolean;\n\t\t\tskip?: boolean;\n\t\t\tmessageEditor?: string;\n\t\t\teditorEnv?: Record<string, string>;\n\t\t},\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst status = await this.getPausedOperationStatus(repoPath);\n\t\tif (status == null) return;\n\n\t\tif (status.type === 'merge' && options?.skip) {\n\t\t\tthrow new Error(l10n.t('Skipping a merge is not supported'));\n\t\t}\n\n\t\tconst args = [status.type, options?.skip ? '--skip' : '--continue'];\n\n\t\t// Continuing after a conflicted step can open the commit-message editor (merge-backend rebases,\n\t\t// cherry-picks, and reverts). `GIT_EDITOR` is what git honors for that step, so set it on the\n\t\t// environment; also set `core.editor` config as a fallback.\n\t\tconst configs: string[] = [];\n\t\tlet env: Record<string, string | undefined> | undefined;\n\t\tif (options?.messageEditor) {\n\t\t\tconfigs.push('-c', `core.editor=${options.messageEditor}`);\n\t\t\tenv = { ...options.editorEnv, GIT_EDITOR: options.messageEditor };\n\t\t}\n\n\t\ttry {\n\t\t\tif (options?.allowEmpty) {\n\t\t\t\tconst commitArgs = ['commit', '--allow-empty', '--no-edit'];\n\t\t\t\ttry {\n\t\t\t\t\t// Git won't record the empty commit on its own; making it explicitly (`--no-edit` reuses the\n\t\t\t\t\t// message git already prepared) is what lets the operation move past it.\n\t\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...commitArgs);\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\t// Same reason taxonomy, but attributed to the commit that actually failed\n\t\t\t\t\tthrow getGitCommandError(\n\t\t\t\t\t\t'paused-operation-continue',\n\t\t\t\t\t\tex,\n\t\t\t\t\t\treason =>\n\t\t\t\t\t\t\tnew PausedOperationContinueError(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\t\t\toperation: status,\n\t\t\t\t\t\t\t\t\tskip: false,\n\t\t\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: commitArgs },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tex,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\terrors: 'throw',\n\t\t\t\t\tconfigs: configs,\n\t\t\t\t\tenv: env,\n\t\t\t\t\t// A `--continue` that opens the commit-message editor blocks for as long as the user leaves\n\t\t\t\t\t// that tab open, which is unbounded — the default `advanced.git.timeout` would SIGTERM it\n\t\t\t\t\t// mid-operation. The start paths (merge/rebase/revert) opt out for the same reason.\n\t\t\t\t\ttimeout: 0,\n\t\t\t\t\t// The runner dedups in-flight commands by args only — it ignores per-call `configs`/`env`.\n\t\t\t\t\t// A headless continue (with `GIT_EDITOR`) and a plain `--continue` would therefore collapse\n\t\t\t\t\t// into one execution, so the plain one could silently run headless (auto-accepting a commit\n\t\t\t\t\t// message) or the headless one could ride a plain continue and open an editor that hangs the\n\t\t\t\t\t// loop. Tag the headless variant so it can't share a pending command with the plain one.\n\t\t\t\t\tcorrelationKey: options?.messageEditor ? 'paused-op-continue-headless' : undefined,\n\t\t\t\t},\n\t\t\t\t...args,\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tif (PausedOperationContinueError.is(ex)) throw ex;\n\n\t\t\tconst error = getGitCommandError(\n\t\t\t\t'paused-operation-continue',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PausedOperationContinueError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\toperation: status,\n\t\t\t\t\t\t\tskip: options?.skip ?? false,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\n\t\t\t// An empty commit concludes a single-commit cherry-pick/revert outright, leaving its\n\t\t\t// `--continue` nothing to continue — the operation finished either way.\n\t\t\tif (!options?.allowEmpty || !PausedOperationContinueError.is(error, 'nothingToContinue')) {\n\t\t\t\tscope?.error(ex);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} finally {\n\t\t\t// Notify unconditionally rather than only on success: a throwing `--continue` can still have\n\t\t\t// mutated the repo (committing the resolved step, then stopping on the NEXT step's conflict or\n\t\t\t// empty commit), and the error alone can't distinguish that from a no-op failure. Invalidating\n\t\t\t// after a genuine no-op only costs a re-read; not invalidating after a real advance leaves\n\t\t\t// consumers rendering a stale step.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pausedOperations.js","names":[],"sources":["../../../../git-cli/src/providers/pausedOperations.ts"],"sourcesContent":["import { readdir } from 'fs';\nimport { readFile, stat } from 'fs/promises';\nimport * as l10n from '@vscode/l10n';\nimport type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport { PausedOperationAbortError, PausedOperationContinueError } from '@gitlens/git/errors.js';\nimport type {\n\tGitCherryPickStatus,\n\tGitMergeStatus,\n\tGitPausedOperationStatus,\n\tGitRebaseStatus,\n\tGitRevertStatus,\n} from '@gitlens/git/models/pausedOperationStatus.js';\nimport type { GitBranchReference, GitTagReference } from '@gitlens/git/models/reference.js';\nimport type { GitDir } from '@gitlens/git/models/repository.js';\nimport type { GitPausedOperationsSubProvider } from '@gitlens/git/providers/pausedOperations.js';\nimport { createReference } from '@gitlens/git/utils/reference.utils.js';\nimport { CancellationError } from '@gitlens/utils/cancellation.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport { joinPaths } from '@gitlens/utils/path.js';\nimport { getSettledValue } from '@gitlens/utils/promise.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { getGitCommandError } from '../exec/git.js';\n\nconst todoCommitRegex = /^(?:p(?:ick)?|revert)\\s+([a-f0-9]+)(?:\\s+(.+))?$/i;\n\ntype Operation = 'cherry-pick' | 'merge' | 'rebase-apply' | 'rebase-merge' | 'revert' | 'sequencer';\n\n// Note: 'sequencer' is checked after specific HEAD files since those take precedence\n// The sequencer directory is used for multi-commit cherry-picks/reverts\nconst orderedOperations: Operation[] = ['rebase-apply', 'rebase-merge', 'merge', 'cherry-pick', 'revert', 'sequencer'];\n\nexport class PausedOperationsGitSubProvider implements GitPausedOperationsSubProvider {\n\tconstructor(\n\t\tprivate readonly context: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tprivate readonly cache: Cache,\n\t\tprivate readonly provider: CliGitProviderInternal,\n\t) {}\n\n\t@debug()\n\tgetPausedOperationStatus(\n\t\trepoPath: string,\n\t\toptions?: { force?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitPausedOperationStatus | undefined> {\n\t\tconst scope = getScopedLogger();\n\n\t\t// Self-heal callers (WIP refresh) bypass the cache so a missed `'pausedOp'` FS-watcher\n\t\t// event (CLI-driven completion, torn-down secondary-worktree watcher) can't leave the\n\t\t// status stuck — the readdir-based detection is cheap enough to repeat on every tick.\n\t\tif (options?.force) {\n\t\t\tthis.cache.pausedOperationStatus.delete(repoPath);\n\t\t}\n\n\t\tconst status = this.cache.pausedOperationStatus.getOrCreate(repoPath, async _cancellable => {\n\t\t\tconst gitDir = await this.provider.config.getGitDir(repoPath);\n\n\t\t\tconst operations = await new Promise<Set<Operation>>((resolve, _) => {\n\t\t\t\treaddir(gitDir.uri.fsPath, { withFileTypes: true }, (err, entries) => {\n\t\t\t\t\tconst operations = new Set<Operation>();\n\t\t\t\t\tif (err != null) {\n\t\t\t\t\t\tresolve(operations);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (entries.length === 0) {\n\t\t\t\t\t\tresolve(operations);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet entry;\n\t\t\t\t\tfor (entry of entries) {\n\t\t\t\t\t\tif (entry.isFile()) {\n\t\t\t\t\t\t\tswitch (entry.name) {\n\t\t\t\t\t\t\t\tcase 'CHERRY_PICK_HEAD':\n\t\t\t\t\t\t\t\t\toperations.add('cherry-pick');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'MERGE_HEAD':\n\t\t\t\t\t\t\t\t\toperations.add('merge');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'REVERT_HEAD':\n\t\t\t\t\t\t\t\t\toperations.add('revert');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (entry.isDirectory()) {\n\t\t\t\t\t\t\tswitch (entry.name) {\n\t\t\t\t\t\t\t\tcase 'rebase-apply':\n\t\t\t\t\t\t\t\t\toperations.add('rebase-apply');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'rebase-merge':\n\t\t\t\t\t\t\t\t\toperations.add('rebase-merge');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'sequencer':\n\t\t\t\t\t\t\t\t\t// The sequencer directory is used for multi-commit cherry-picks/reverts\n\t\t\t\t\t\t\t\t\t// We'll determine the type by reading the todo file later\n\t\t\t\t\t\t\t\t\toperations.add('sequencer');\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve(operations);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tif (!operations.size) return undefined;\n\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\tconst sortedOperations = [...operations].sort(\n\t\t\t\t(a, b) => orderedOperations.indexOf(a) - orderedOperations.indexOf(b),\n\t\t\t);\n\t\t\tscope?.info(`Detected paused operations: ${sortedOperations.join(', ')}`);\n\n\t\t\tconst operation = sortedOperations[0];\n\t\t\tswitch (operation) {\n\t\t\t\tcase 'cherry-pick': {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t'CHERRY_PICK_HEAD',\n\t\t\t\t\t);\n\t\t\t\t\tif (result.completion.status === 'cancelled' || cancellation?.aborted) {\n\t\t\t\t\t\tthrow new CancellationError();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst cherryPickHead = result.stdout.trim();\n\t\t\t\t\tif (!cherryPickHead) {\n\t\t\t\t\t\tscope?.addExitInfo('No CHERRY_PICK_HEAD found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult, messageResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, 'CHERRY_PICK_HEAD', 'HEAD', undefined, cancellation),\n\t\t\t\t\t\tthis.getCommitMessage(repoPath, cherryPickHead, cancellation),\n\t\t\t\t\t]);\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\t// Names the commit being applied, so consumers can say which one a skip would drop\n\t\t\t\t\tconst message = getSettledValue(messageResult);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'cherry-pick',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(cherryPickHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming: createReference(cherryPickHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t} satisfies GitCherryPickStatus;\n\t\t\t\t}\n\t\t\t\tcase 'merge': {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t'MERGE_HEAD',\n\t\t\t\t\t);\n\t\t\t\t\tif (result.completion.status === 'cancelled' || cancellation?.aborted) {\n\t\t\t\t\t\tthrow new CancellationError();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst mergeHead = result.stdout.trim();\n\t\t\t\t\tif (!mergeHead) {\n\t\t\t\t\t\tscope?.addExitInfo('No MERGE_HEAD found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult, possibleSourceBranchesResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, 'MERGE_HEAD', 'HEAD', undefined, cancellation),\n\t\t\t\t\t\tthis.provider.branches.getBranchesWithCommits(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t['MERGE_HEAD'],\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t{ all: true, mode: 'pointsAt' },\n\t\t\t\t\t\t\tcancellation,\n\t\t\t\t\t\t),\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\tconst possibleSourceBranches = getSettledValue(possibleSourceBranchesResult);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'merge',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(mergeHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming:\n\t\t\t\t\t\t\tpossibleSourceBranches?.length === 1\n\t\t\t\t\t\t\t\t? createReference(possibleSourceBranches[0], repoPath, {\n\t\t\t\t\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\t\t\t\t\tname: possibleSourceBranches[0],\n\t\t\t\t\t\t\t\t\t\tremote: false,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: createReference(mergeHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t} satisfies GitMergeStatus;\n\t\t\t\t}\n\t\t\t\tcase 'revert': {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t'REVERT_HEAD',\n\t\t\t\t\t);\n\t\t\t\t\tif (result.completion.status === 'cancelled' || cancellation?.aborted) {\n\t\t\t\t\t\tthrow new CancellationError();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst revertHead = result.stdout.trim();\n\t\t\t\t\tif (!revertHead) {\n\t\t\t\t\t\tscope?.addExitInfo('No REVERT_HEAD found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult, messageResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, 'REVERT_HEAD', 'HEAD', undefined, cancellation),\n\t\t\t\t\t\tthis.getCommitMessage(repoPath, revertHead, cancellation),\n\t\t\t\t\t]);\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\t// Names the commit being reverted, so consumers can say which one a skip would drop\n\t\t\t\t\tconst message = getSettledValue(messageResult);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'revert',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(revertHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming: createReference(revertHead, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t} satisfies GitRevertStatus;\n\t\t\t\t}\n\t\t\t\tcase 'rebase-apply':\n\t\t\t\tcase 'rebase-merge': {\n\t\t\t\t\tlet branch = await this.readDotGitFile(gitDir, [operation, 'head-name']);\n\t\t\t\t\tif (!branch) {\n\t\t\t\t\t\tscope?.addExitInfo(`No '${operation}/head-name' found`);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [\n\t\t\t\t\t\trebaseHeadResult,\n\t\t\t\t\t\torigHeadResult,\n\t\t\t\t\t\tontoResult,\n\t\t\t\t\t\tstepsNumberResult,\n\t\t\t\t\t\tstepsTotalResult,\n\t\t\t\t\t\tstepsMessageResult,\n\t\t\t\t\t\tisInteractiveResult,\n\t\t\t\t\t] = await Promise.allSettled([\n\t\t\t\t\t\tthis.git.run(\n\t\t\t\t\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t\t\t\t\t'rev-parse',\n\t\t\t\t\t\t\t'--quiet',\n\t\t\t\t\t\t\t'--verify',\n\t\t\t\t\t\t\t'REBASE_HEAD',\n\t\t\t\t\t\t),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'orig-head']),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'onto']),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'msgnum'], { numeric: true }),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'end'], { numeric: true }),\n\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'message'], { throw: true }).catch(() =>\n\t\t\t\t\t\t\tthis.readDotGitFile(gitDir, [operation, 'message-squashed']),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tstat(joinPaths(gitDir.uri.fsPath, operation, 'interactive')).then(\n\t\t\t\t\t\t\t() => true,\n\t\t\t\t\t\t\t() => false,\n\t\t\t\t\t\t),\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst origHead = getSettledValue(origHeadResult);\n\t\t\t\t\tconst onto = getSettledValue(ontoResult);\n\t\t\t\t\tif (origHead == null || onto == null) {\n\t\t\t\t\t\tscope?.addExitInfo(`Neither '${operation}/orig-head' nor '${operation}/onto' found`);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst rebaseHead = getSettledValue(rebaseHeadResult)?.stdout.trim();\n\n\t\t\t\t\tif (branch.startsWith('refs/heads/')) {\n\t\t\t\t\t\tbranch = branch.substring(11).trim();\n\t\t\t\t\t}\n\n\t\t\t\t\tconst [mergeBaseResult, branchTipsResult, tagTipsResult] = await Promise.allSettled([\n\t\t\t\t\t\trebaseHead\n\t\t\t\t\t\t\t? this.provider.refs.getMergeBase(repoPath, rebaseHead, 'HEAD', undefined, cancellation)\n\t\t\t\t\t\t\t: this.provider.refs.getMergeBase(repoPath, onto, origHead, undefined, cancellation),\n\t\t\t\t\t\tthis.provider.branches.getBranchesWithCommits(\n\t\t\t\t\t\t\trepoPath,\n\t\t\t\t\t\t\t[onto],\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tall: true,\n\t\t\t\t\t\t\t\tmode: 'pointsAt',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcancellation,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tthis.provider.tags.getTagsWithCommit(repoPath, onto, { mode: 'pointsAt' }, cancellation),\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\t\t\t\t\tconst branchTips = getSettledValue(branchTipsResult);\n\t\t\t\t\tconst tagTips = getSettledValue(tagTipsResult);\n\n\t\t\t\t\tlet ontoRef: GitBranchReference | GitTagReference | undefined;\n\t\t\t\t\tif (branchTips != null) {\n\t\t\t\t\t\tfor (const ref of branchTips) {\n\t\t\t\t\t\t\tif (ref.startsWith('(no branch, rebasing')) continue;\n\n\t\t\t\t\t\t\tontoRef = createReference(ref, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\t\t\tname: ref,\n\t\t\t\t\t\t\t\tremote: false,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (ontoRef == null && tagTips != null) {\n\t\t\t\t\t\tfor (const ref of tagTips) {\n\t\t\t\t\t\t\tif (ref.startsWith('(no branch, rebasing')) continue;\n\n\t\t\t\t\t\t\tontoRef = createReference(ref, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'tag',\n\t\t\t\t\t\t\t\tname: ref,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst stepsNumber = getSettledValue(stepsNumberResult) ?? 0;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'rebase',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(rebaseHead ?? origHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tonto: createReference(onto, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tsource: createReference(origHead, repoPath, { refType: 'revision' }),\n\t\t\t\t\t\tcurrent: ontoRef,\n\t\t\t\t\t\tincoming: createReference(branch, repoPath, {\n\t\t\t\t\t\t\trefType: 'branch',\n\t\t\t\t\t\t\tname: branch,\n\t\t\t\t\t\t\tremote: false,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tsteps: {\n\t\t\t\t\t\t\tcurrent: {\n\t\t\t\t\t\t\t\tnumber: stepsNumber,\n\t\t\t\t\t\t\t\tcommit: rebaseHead\n\t\t\t\t\t\t\t\t\t? createReference(rebaseHead, repoPath, {\n\t\t\t\t\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\t\t\t\t\tmessage: getSettledValue(stepsMessageResult),\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttotal: getSettledValue(stepsTotalResult) ?? 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\thasStarted: stepsNumber > 0,\n\t\t\t\t\t\t// REBASE_HEAD only exists when git is paused and waiting for user action\n\t\t\t\t\t\tisPaused: stepsNumber > 0 && rebaseHead != null,\n\t\t\t\t\t\t// 'interactive' file exists for `git rebase -i`, absent for `git pull --rebase`\n\t\t\t\t\t\tisInteractive: getSettledValue(isInteractiveResult) ?? false,\n\t\t\t\t\t} satisfies GitRebaseStatus;\n\t\t\t\t}\n\t\t\t\tcase 'sequencer': {\n\t\t\t\t\t// Used for multi-commit cherry-picks/reverts when CHERRY_PICK_HEAD/REVERT_HEAD don't exist\n\t\t\t\t\tconst todoContent = await this.readDotGitFile(gitDir, ['sequencer', 'todo']);\n\t\t\t\t\tif (!todoContent) {\n\t\t\t\t\t\tscope?.addExitInfo('No sequencer/todo file found');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Get the first line and determine if it's a cherry-pick or revert\n\t\t\t\t\tconst firstLine = todoContent.split('\\n')[0]?.trim();\n\t\t\t\t\tif (!firstLine) {\n\t\t\t\t\t\tscope?.addExitInfo('Empty sequencer/todo file');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if it's a pick (cherry-pick) or revert command\n\t\t\t\t\t// Format: \"pick <sha> <message>\" or \"p <sha> <message>\" or \"revert <sha> <message>\"\n\t\t\t\t\tconst isCherryPick = /^p(?:ick)?\\s/.test(firstLine);\n\t\t\t\t\tconst isRevert = /^revert\\s/.test(firstLine);\n\n\t\t\t\t\tif (!isCherryPick && !isRevert) {\n\t\t\t\t\t\tscope?.addExitInfo(`Unknown sequencer command: ${firstLine}`);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Parse the commit sha being applied from the todo file\n\t\t\t\t\tconst match = firstLine.match(todoCommitRegex);\n\t\t\t\t\tconst currentCommitSha = match?.[1];\n\t\t\t\t\tif (!currentCommitSha) {\n\t\t\t\t\t\tscope?.addExitInfo('Could not parse commit sha from sequencer/todo');\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\t// The todo line carries only the commit's SUBJECT (the other producers carry the full\n\t\t\t\t\t// message) — good enough to name the commit a skip would drop, without another git call\n\t\t\t\t\tconst message = match?.[2]?.trim() || undefined;\n\n\t\t\t\t\tconst [branchResult, mergeBaseResult] = await Promise.allSettled([\n\t\t\t\t\t\tthis.provider.branches.getCurrentBranchReference(repoPath, cancellation),\n\t\t\t\t\t\tthis.provider.refs.getMergeBase(repoPath, currentCommitSha, 'HEAD', undefined, cancellation),\n\t\t\t\t\t]);\n\t\t\t\t\tif (cancellation?.aborted) throw new CancellationError();\n\n\t\t\t\t\tconst current = getSettledValue(branchResult)!;\n\t\t\t\t\tconst mergeBase = getSettledValue(mergeBaseResult);\n\n\t\t\t\t\tif (isCherryPick) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: 'cherry-pick',\n\t\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\t\tHEAD: createReference(currentCommitSha, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\t\tmessage: message,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\t\tincoming: createReference(currentCommitSha, repoPath, {\n\t\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\t\tmessage: message,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t} satisfies GitCherryPickStatus;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'revert',\n\t\t\t\t\t\trepoPath: repoPath,\n\t\t\t\t\t\tmergeBase: mergeBase,\n\t\t\t\t\t\tHEAD: createReference(currentCommitSha, repoPath, { refType: 'revision', message: message }),\n\t\t\t\t\t\tcurrent: current,\n\t\t\t\t\t\tincoming: createReference(currentCommitSha, repoPath, {\n\t\t\t\t\t\t\trefType: 'revision',\n\t\t\t\t\t\t\tmessage: message,\n\t\t\t\t\t\t}),\n\t\t\t\t\t} satisfies GitRevertStatus;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn status;\n\t}\n\n\t/** Memoized per repo by sha — forced status re-reads on FS noise (every file save while resolving\n\t * conflicts) would otherwise re-spawn `git log` for an unchanging commit. */\n\tprivate readonly _commitMessageCache = new Map<string, { sha: string; message: string | undefined }>();\n\n\tprivate async getCommitMessage(\n\t\trepoPath: string,\n\t\tsha: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string | undefined> {\n\t\tconst cached = this._commitMessageCache.get(repoPath);\n\t\tif (cached?.sha === sha) return cached.message;\n\n\t\tconst result = await this.git.run(\n\t\t\t{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },\n\t\t\t'log',\n\t\t\t'-1',\n\t\t\t'--format=%B',\n\t\t\tsha,\n\t\t);\n\t\tconst message = result.stdout.trim() || undefined;\n\t\t// Don't cache a miss — a transient failure would otherwise stick for the operation's lifetime\n\t\tif (message != null) {\n\t\t\tthis._commitMessageCache.set(repoPath, { sha: sha, message: message });\n\t\t}\n\t\treturn message;\n\t}\n\n\tprivate async readDotGitFile(\n\t\tgitDir: GitDir,\n\t\tpathParts: string[],\n\t\toptions?: { numeric?: false; throw?: boolean; trim?: boolean },\n\t): Promise<string | undefined>;\n\tprivate async readDotGitFile(\n\t\tgitDir: GitDir,\n\t\tpathParts: string[],\n\t\toptions?: { numeric: true; throw?: boolean; trim?: boolean },\n\t): Promise<number | undefined>;\n\tprivate async readDotGitFile(\n\t\tgitDir: GitDir,\n\t\tpathParts: string[],\n\t\toptions?: { numeric?: boolean; throw?: boolean; trim?: boolean },\n\t): Promise<string | number | undefined> {\n\t\ttry {\n\t\t\tconst filePath = joinPaths(gitDir.uri.fsPath, ...pathParts);\n\t\t\tconst bytes = await readFile(filePath);\n\t\t\tlet contents = new TextDecoder('utf8').decode(bytes);\n\t\t\tcontents = (options?.trim ?? true) ? contents.trim() : contents;\n\n\t\t\tif (options?.numeric) {\n\t\t\t\tconst number = Number.parseInt(contents, 10);\n\t\t\t\treturn isNaN(number) ? undefined : number;\n\t\t\t}\n\n\t\t\treturn contents;\n\t\t} catch (ex) {\n\t\t\tif (options?.throw) throw ex;\n\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t@gate((rp, o) => `${rp ?? ''}:${o?.quit ?? false}`)\n\t@debug()\n\tasync abortPausedOperation(repoPath: string, options?: { quit?: boolean }): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst status = await this.getPausedOperationStatus(repoPath);\n\t\tif (status == null) return;\n\n\t\tconst args = [status.type, options?.quit ? '--quit' : '--abort'];\n\n\t\ttry {\n\t\t\t// Unbounded like the operations it undoes — an abort of a large rebase can outrun the default\n\t\t\t// command timeout, and being SIGTERM'd partway through would leave the repo mid-abort.\n\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw', timeout: 0 }, ...args);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex);\n\t\t\tthrow getGitCommandError(\n\t\t\t\t'paused-operation-abort',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PausedOperationAbortError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\toperation: status,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t@debug()\n\tasync continuePausedOperation(\n\t\trepoPath: string,\n\t\toptions?: {\n\t\t\tallowEmpty?: boolean;\n\t\t\tskip?: boolean;\n\t\t\tmessageEditor?: string;\n\t\t\teditorEnv?: Record<string, string>;\n\t\t},\n\t): Promise<void> {\n\t\tconst scope = getScopedLogger();\n\n\t\tconst status = await this.getPausedOperationStatus(repoPath);\n\t\tif (status == null) return;\n\n\t\tif (status.type === 'merge' && options?.skip) {\n\t\t\tthrow new Error(l10n.t('Skipping a merge is not supported'));\n\t\t}\n\n\t\tconst args = [status.type, options?.skip ? '--skip' : '--continue'];\n\n\t\t// Continuing after a conflicted step can open the commit-message editor (merge-backend rebases,\n\t\t// cherry-picks, and reverts). `GIT_EDITOR` is what git honors for that step, so set it on the\n\t\t// environment; also set `core.editor` config as a fallback.\n\t\tconst configs: string[] = [];\n\t\tlet env: Record<string, string | undefined> | undefined;\n\t\tif (options?.messageEditor) {\n\t\t\tconfigs.push('-c', `core.editor=${options.messageEditor}`);\n\t\t\tenv = { ...options.editorEnv, GIT_EDITOR: options.messageEditor };\n\t\t}\n\n\t\ttry {\n\t\t\tif (options?.allowEmpty) {\n\t\t\t\tconst commitArgs = ['commit', '--allow-empty', '--no-edit'];\n\t\t\t\ttry {\n\t\t\t\t\t// Git won't record the empty commit on its own; making it explicitly (`--no-edit` reuses the\n\t\t\t\t\t// message git already prepared) is what lets the operation move past it.\n\t\t\t\t\tawait this.git.run({ cwd: repoPath, errors: 'throw' }, ...commitArgs);\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\t// Same reason taxonomy, but attributed to the commit that actually failed\n\t\t\t\t\tthrow getGitCommandError(\n\t\t\t\t\t\t'paused-operation-continue',\n\t\t\t\t\t\tex,\n\t\t\t\t\t\treason =>\n\t\t\t\t\t\t\tnew PausedOperationContinueError(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\t\t\toperation: status,\n\t\t\t\t\t\t\t\t\tskip: false,\n\t\t\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: commitArgs },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tex,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait this.git.run(\n\t\t\t\t{\n\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\terrors: 'throw',\n\t\t\t\t\tconfigs: configs,\n\t\t\t\t\tenv: env,\n\t\t\t\t\t// A `--continue` that opens the commit-message editor blocks for as long as the user leaves\n\t\t\t\t\t// that tab open, which is unbounded — the default `advanced.git.timeout` would SIGTERM it\n\t\t\t\t\t// mid-operation. The start paths (merge/rebase/revert) opt out for the same reason.\n\t\t\t\t\ttimeout: 0,\n\t\t\t\t\t// The runner dedups in-flight commands by args only — it ignores per-call `configs`/`env`.\n\t\t\t\t\t// A headless continue (with `GIT_EDITOR`) and a plain `--continue` would therefore collapse\n\t\t\t\t\t// into one execution, so the plain one could silently run headless (auto-accepting a commit\n\t\t\t\t\t// message) or the headless one could ride a plain continue and open an editor that hangs the\n\t\t\t\t\t// loop. Tag the headless variant so it can't share a pending command with the plain one.\n\t\t\t\t\tcorrelationKey: options?.messageEditor ? 'paused-op-continue-headless' : undefined,\n\t\t\t\t},\n\t\t\t\t...args,\n\t\t\t);\n\t\t} catch (ex) {\n\t\t\tif (PausedOperationContinueError.is(ex)) throw ex;\n\n\t\t\tconst error = getGitCommandError(\n\t\t\t\t'paused-operation-continue',\n\t\t\t\tex,\n\t\t\t\treason =>\n\t\t\t\t\tnew PausedOperationContinueError(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason: reason,\n\t\t\t\t\t\t\toperation: status,\n\t\t\t\t\t\t\tskip: options?.skip ?? false,\n\t\t\t\t\t\t\tgitCommand: { repoPath: repoPath, args: args },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tex,\n\t\t\t\t\t),\n\t\t\t);\n\n\t\t\t// An empty commit concludes a single-commit cherry-pick/revert outright, leaving its\n\t\t\t// `--continue` nothing to continue — the operation finished either way.\n\t\t\tif (!options?.allowEmpty || !PausedOperationContinueError.is(error, 'nothingToContinue')) {\n\t\t\t\tscope?.error(ex);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} finally {\n\t\t\t// Notify unconditionally rather than only on success: a throwing `--continue` can still have\n\t\t\t// mutated the repo (committing the resolved step, then stopping on the NEXT step's conflict or\n\t\t\t// empty commit), and the error alone can't distinguish that from a no-op failure. Invalidating\n\t\t\t// after a genuine no-op only costs a re-read; not invalidating after a real advance leaves\n\t\t\t// consumers rendering a stale step.\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -8,8 +8,8 @@ import __decorate from "../../_virtual/@oxc-project+runtime/helpers/esm/decorate
8
8
  import { mixinAsyncDisposable } from "../../utils/disposable.js";
9
9
  import { maxGitCliLength } from "../exec/git.js";
10
10
  import * as l10n from "@vscode/l10n";
11
- import { promises } from "fs";
12
11
  import { tmpdir } from "os";
12
+ import { promises } from "fs";
13
13
  //#region ../git-cli/src/providers/staging.ts
14
14
  var StagingGitSubProvider = class {
15
15
  context;
@@ -1,7 +1,7 @@
1
1
  import { join } from "path";
2
2
  import { mkdir, readFile, readdir, unlink, writeFile } from "fs/promises";
3
- import { kill, ppid } from "process";
4
3
  import { tmpdir } from "os";
4
+ import { kill, ppid } from "process";
5
5
  //#region ../ipc/src/discovery.ts
6
6
  /**
7
7
  * Directory scanned by `gk` binaries (and `@gitkraken/core-gitlens` consumers) for the
@@ -1,7 +1,7 @@
1
1
  import { basename, dirname, join } from "path";
2
- import { createReadStream } from "fs";
3
- import { open, readFile, readdir as readdir$1, stat } from "fs/promises";
2
+ import { open, readFile, readdir, stat } from "fs/promises";
4
3
  import { homedir } from "os";
4
+ import { createReadStream } from "fs";
5
5
  import { createInterface } from "readline";
6
6
  //#region ../plus/agents/src/providers/claudeCodeTranscript.ts
7
7
  /** Bytes read from each end of a transcript when summarizing. Titles and prompts cluster at both
@@ -269,7 +269,7 @@ var ClaudeCodeTranscriptReader = class {
269
269
  const cached = this._names.get(dir);
270
270
  if (cached != null && Date.now() - cached.resolvedAt < listingCacheTtlMs) return cached.names;
271
271
  const gen = this._listingGen;
272
- const names = (await readdir$1(dir, { withFileTypes: true })).filter((d) => d.isFile() && d.name.endsWith(".jsonl")).map((d) => d.name);
272
+ const names = (await readdir(dir, { withFileTypes: true })).filter((d) => d.isFile() && d.name.endsWith(".jsonl")).map((d) => d.name);
273
273
  if (gen === this._listingGen) this._names.set(dir, {
274
274
  names,
275
275
  resolvedAt: Date.now()
@@ -283,7 +283,7 @@ var ClaudeCodeTranscriptReader = class {
283
283
  if (cached != null && Date.now() - cached.resolvedAt < listingCacheTtlMs) return cached.dirs;
284
284
  const gen = this._listingGen;
285
285
  const root = this.getProjectsRoot();
286
- const dirs = (await readdir$1(root, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => join(root, d.name));
286
+ const dirs = (await readdir(root, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => join(root, d.name));
287
287
  if (gen === this._listingGen) this._projectDirs = {
288
288
  dirs,
289
289
  resolvedAt: Date.now()
@@ -487,7 +487,7 @@ var ClaudeCodeTranscriptReader = class {
487
487
  if (await directoryExists(exact)) return exact;
488
488
  let dirs;
489
489
  try {
490
- dirs = await readdir$1(root);
490
+ dirs = await readdir(root);
491
491
  } catch (ex) {
492
492
  if (!isMissingEntry(ex)) throw ex;
493
493
  return;
@@ -506,7 +506,7 @@ var ClaudeCodeTranscriptReader = class {
506
506
  const root = this.getProjectsRoot();
507
507
  let dirs;
508
508
  try {
509
- dirs = await readdir$1(root);
509
+ dirs = await readdir(root);
510
510
  } catch (ex) {
511
511
  if (!isMissingEntry(ex)) throw ex;
512
512
  return;