@gitkraken/core-gitlens 0.11.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/CHANGELOG.md +84 -1
  2. package/dist/git/cache.d.ts +84 -29
  3. package/dist/git/cache.js +188 -54
  4. package/dist/git/cache.js.map +1 -1
  5. package/dist/git/features.d.ts +1 -1
  6. package/dist/git/features.js +4 -0
  7. package/dist/git/features.js.map +1 -1
  8. package/dist/git/models/branch.d.ts +15 -2
  9. package/dist/git/models/branch.js +27 -5
  10. package/dist/git/models/branch.js.map +1 -1
  11. package/dist/git/models/issue.d.ts +3 -1
  12. package/dist/git/models/issue.js.map +1 -1
  13. package/dist/git/models/status.js +1 -1
  14. package/dist/git/models/worktree.d.ts +4 -1
  15. package/dist/git/models/worktree.js +4 -2
  16. package/dist/git/models/worktree.js.map +1 -1
  17. package/dist/git/providers/branches.d.ts +73 -8
  18. package/dist/git/providers/pausedOperations.d.ts +6 -0
  19. package/dist/git/providers/provider.d.ts +34 -2
  20. package/dist/git/providers/status.d.ts +8 -2
  21. package/dist/git/remotes/azure-devops.js +61 -53
  22. package/dist/git/remotes/azure-devops.js.map +1 -1
  23. package/dist/git/service.d.ts +8 -5
  24. package/dist/git/service.js +16 -8
  25. package/dist/git/service.js.map +1 -1
  26. package/dist/git/utils/branch.utils.d.ts +8 -1
  27. package/dist/git/utils/branch.utils.js +30 -1
  28. package/dist/git/utils/branch.utils.js.map +1 -1
  29. package/dist/git/utils/issue.utils.d.ts +3 -1
  30. package/dist/git/utils/issue.utils.js +5 -1
  31. package/dist/git/utils/issue.utils.js.map +1 -1
  32. package/dist/git/watching/changeEvent.d.ts +13 -2
  33. package/dist/git/watching/changeEvent.js +17 -3
  34. package/dist/git/watching/changeEvent.js.map +1 -1
  35. package/dist/git/watching/gitDirPoller.d.ts +111 -0
  36. package/dist/git/watching/gitDirPoller.js +266 -0
  37. package/dist/git/watching/gitDirPoller.js.map +1 -0
  38. package/dist/git/watching/provider.d.ts +16 -0
  39. package/dist/git/watching/watchGroup.d.ts +40 -4
  40. package/dist/git/watching/watchGroup.js +143 -17
  41. package/dist/git/watching/watchGroup.js.map +1 -1
  42. package/dist/git/watching/watchService.d.ts +70 -1
  43. package/dist/git/watching/watchService.js +158 -13
  44. package/dist/git/watching/watchService.js.map +1 -1
  45. package/dist/git/watching/watchSession.d.ts +44 -0
  46. package/dist/git/watching/watchSession.js +91 -6
  47. package/dist/git/watching/watchSession.js.map +1 -1
  48. package/dist/git/watching/watcherPatterns.d.ts +21 -0
  49. package/dist/git/watching/watcherPatterns.js +67 -1
  50. package/dist/git/watching/watcherPatterns.js.map +1 -1
  51. package/dist/git/watching/worktreeSummary.d.ts +34 -7
  52. package/dist/git/watching/worktreeSummary.js +39 -12
  53. package/dist/git/watching/worktreeSummary.js.map +1 -1
  54. package/dist/git-cli/cliGitProvider.d.ts +34 -2
  55. package/dist/git-cli/cliGitProvider.js +119 -17
  56. package/dist/git-cli/cliGitProvider.js.map +1 -1
  57. package/dist/git-cli/exec/commandClassifier.d.ts +15 -0
  58. package/dist/git-cli/exec/commandClassifier.js +48 -2
  59. package/dist/git-cli/exec/commandClassifier.js.map +1 -1
  60. package/dist/git-cli/exec/git.d.ts +15 -3
  61. package/dist/git-cli/exec/git.js +38 -17
  62. package/dist/git-cli/exec/git.js.map +1 -1
  63. package/dist/git-cli/exec/gitQueue.d.ts +2 -0
  64. package/dist/git-cli/exec/gitQueue.js +2 -1
  65. package/dist/git-cli/exec/gitQueue.js.map +1 -1
  66. package/dist/git-cli/exec/indexLock.d.ts +38 -0
  67. package/dist/git-cli/exec/indexLock.js +150 -0
  68. package/dist/git-cli/exec/indexLock.js.map +1 -0
  69. package/dist/git-cli/parsers/worktreeParser.js +42 -2
  70. package/dist/git-cli/parsers/worktreeParser.js.map +1 -1
  71. package/dist/git-cli/providers/branches.d.ts +109 -10
  72. package/dist/git-cli/providers/branches.js +624 -131
  73. package/dist/git-cli/providers/branches.js.map +1 -1
  74. package/dist/git-cli/providers/config.d.ts +9 -5
  75. package/dist/git-cli/providers/config.js +60 -27
  76. package/dist/git-cli/providers/config.js.map +1 -1
  77. package/dist/git-cli/providers/operations.d.ts +17 -0
  78. package/dist/git-cli/providers/operations.js +153 -96
  79. package/dist/git-cli/providers/operations.js.map +1 -1
  80. package/dist/git-cli/providers/pausedOperations.d.ts +8 -0
  81. package/dist/git-cli/providers/pausedOperations.js +60 -40
  82. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  83. package/dist/git-cli/providers/refs.js +11 -8
  84. package/dist/git-cli/providers/refs.js.map +1 -1
  85. package/dist/git-cli/providers/remotes.js +19 -10
  86. package/dist/git-cli/providers/remotes.js.map +1 -1
  87. package/dist/git-cli/providers/staging.js +40 -15
  88. package/dist/git-cli/providers/staging.js.map +1 -1
  89. package/dist/git-cli/providers/stash.d.ts +2 -0
  90. package/dist/git-cli/providers/stash.js +33 -18
  91. package/dist/git-cli/providers/stash.js.map +1 -1
  92. package/dist/git-cli/providers/status.d.ts +3 -1
  93. package/dist/git-cli/providers/status.js +38 -20
  94. package/dist/git-cli/providers/status.js.map +1 -1
  95. package/dist/git-cli/providers/tags.js +6 -4
  96. package/dist/git-cli/providers/tags.js.map +1 -1
  97. package/dist/git-cli/providers/worktrees.d.ts +1 -0
  98. package/dist/git-cli/providers/worktrees.js +60 -31
  99. package/dist/git-cli/providers/worktrees.js.map +1 -1
  100. package/dist/git-cli/service.d.ts +6 -0
  101. package/dist/git-cli/service.js +5 -2
  102. package/dist/git-cli/service.js.map +1 -1
  103. package/dist/ipc/discovery.js +1 -1
  104. package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
  105. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  106. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
  107. package/dist/plus/git-github/providers/github/status.d.ts +3 -1
  108. package/dist/plus/git-github/providers/github/status.js +1 -1
  109. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  110. package/dist/plus/integrations/collectionMetadata.d.ts +13 -2
  111. package/dist/plus/integrations/collectionMetadata.js +14 -2
  112. package/dist/plus/integrations/collectionMetadata.js.map +1 -1
  113. package/dist/plus/integrations/index.d.ts +2 -2
  114. package/dist/plus/integrations/index.js.map +1 -1
  115. package/dist/plus/integrations/integrationService.d.ts +1 -0
  116. package/dist/plus/integrations/integrationService.js +1 -1
  117. package/dist/plus/integrations/integrationService.js.map +1 -1
  118. package/dist/plus/integrations/manager.d.ts +1 -0
  119. package/dist/plus/integrations/models/gitHostIntegration.d.ts +41 -5
  120. package/dist/plus/integrations/models/gitHostIntegration.js +109 -30
  121. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  122. package/dist/plus/integrations/models/integration.js +1 -1
  123. package/dist/plus/integrations/models/issueReads.d.ts +17 -4
  124. package/dist/plus/integrations/providers/apiClients.d.ts +2 -0
  125. package/dist/plus/integrations/providers/apiClients.js +7 -1
  126. package/dist/plus/integrations/providers/apiClients.js.map +1 -1
  127. package/dist/plus/integrations/providers/azure/azure.d.ts +5 -4
  128. package/dist/plus/integrations/providers/azure/azure.js +38 -77
  129. package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
  130. package/dist/plus/integrations/providers/azure/azure.utils.js +20 -17
  131. package/dist/plus/integrations/providers/azure/azure.utils.js.map +1 -1
  132. package/dist/plus/integrations/providers/azure/models.d.ts +27 -10
  133. package/dist/plus/integrations/providers/azure/models.js +40 -20
  134. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  135. package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +23 -0
  136. package/dist/plus/integrations/providers/azure/workItemStateCategories.js +84 -0
  137. package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -0
  138. package/dist/plus/integrations/providers/azureDevOps.d.ts +44 -0
  139. package/dist/plus/integrations/providers/azureDevOps.js +113 -22
  140. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
  141. package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +45 -1
  142. package/dist/plus/integrations/providers/azureDevOpsServer.js +121 -6
  143. package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
  144. package/dist/plus/integrations/providers/issueSorts.d.ts +0 -1
  145. package/dist/plus/integrations/providers/jira-server.js +29 -19
  146. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  147. package/dist/plus/integrations/providers/jira.d.ts +5 -2
  148. package/dist/plus/integrations/providers/jira.js +63 -44
  149. package/dist/plus/integrations/providers/jira.js.map +1 -1
  150. package/dist/plus/integrations/providers/jiraIssueByKey.d.ts +3 -4
  151. package/dist/plus/integrations/providers/jiraIssueByKey.js +3 -4
  152. package/dist/plus/integrations/providers/jiraIssueByKey.js.map +1 -1
  153. package/dist/plus/integrations/providers/linearIssuesEtag.d.ts +5 -5
  154. package/dist/plus/integrations/providers/linearIssuesEtag.js +6 -6
  155. package/dist/plus/integrations/providers/linearIssuesEtag.js.map +1 -1
  156. package/dist/plus/integrations/providers/models.d.ts +12 -3
  157. package/dist/plus/integrations/providers/models.js +16 -9
  158. package/dist/plus/integrations/providers/models.js.map +1 -1
  159. package/dist/plus/integrations/providers/providersApi.d.ts +21 -33
  160. package/dist/plus/integrations/providers/providersApi.js +159 -49
  161. package/dist/plus/integrations/providers/providersApi.js.map +1 -1
  162. package/dist/plus/integrations/providers/utils/jiraIssueDrains.d.ts +49 -15
  163. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js +132 -10
  164. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js.map +1 -1
  165. package/dist/plus/integrations/providers/utils/providerPaging.js +8 -2
  166. package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
  167. package/dist/plus/integrations/reads/cursors.js +1 -1
  168. package/dist/plus/integrations/reads/drains.d.ts +0 -1
  169. package/dist/plus/integrations/reads/filters.d.ts +3 -3
  170. package/dist/plus/integrations/reads/filters.js.map +1 -1
  171. package/dist/plus/integrations/reads/hierarchy.js +2 -2
  172. package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
  173. package/dist/plus/integrations/reads/hierarchy.utils.d.ts +13 -0
  174. package/dist/plus/integrations/reads/hierarchy.utils.js +26 -1
  175. package/dist/plus/integrations/reads/hierarchy.utils.js.map +1 -1
  176. package/dist/plus/integrations/reads/issueBatch.d.ts +2 -1
  177. package/dist/plus/integrations/reads/issueBatch.js +1 -1
  178. package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
  179. package/dist/plus/integrations/reads/issueTracker.js +27 -18
  180. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  181. package/dist/plus/integrations/reads/issues.d.ts +2 -1
  182. package/dist/plus/integrations/reads/issues.js +19 -4
  183. package/dist/plus/integrations/reads/issues.js.map +1 -1
  184. package/dist/plus/integrations/reads/pullRequestBatch.js +1 -1
  185. package/dist/plus/integrations/reads/resolveRepository.js +12 -3
  186. package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
  187. package/dist/plus/integrations/reads/warnings.d.ts +11 -4
  188. package/dist/plus/integrations/reads/warnings.js +15 -5
  189. package/dist/plus/integrations/reads/warnings.js.map +1 -1
  190. package/dist/plus/integrations/results.d.ts +48 -4
  191. package/dist/plus/integrations/results.js +33 -13
  192. package/dist/plus/integrations/results.js.map +1 -1
  193. package/dist/plus/integrations/utils/integration.utils.d.ts +6 -1
  194. package/dist/plus/integrations/utils/integration.utils.js +8 -1
  195. package/dist/plus/integrations/utils/integration.utils.js.map +1 -1
  196. package/dist/utils/env/node/exec.js +2 -2
  197. package/dist/utils/promiseCache.d.ts +10 -0
  198. package/dist/utils/promiseCache.js +17 -2
  199. package/dist/utils/promiseCache.js.map +1 -1
  200. package/docs/integrations.md +93 -31
  201. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"features.js","names":[],"sources":["../../../git/src/features.ts"],"sourcesContent":["// GitFeature's must start with `git:` to be recognized in all usages\nexport type GitFeatures =\n\t| 'git:checkout:pathspec-from-file'\n\t| 'git:commit-graph'\n\t| 'git:commit-graph:changed-paths'\n\t| 'git:fetch:no-write-fetch-head'\n\t| 'git:for-each-ref:worktreePath'\n\t| 'git:fsmonitor'\n\t| 'git:fsmonitor:linux'\n\t| 'git:ignoreRevsFile'\n\t| 'git:index:skipHash'\n\t| 'git:maintenance'\n\t| 'git:maintenance:pack-refs'\n\t| 'git:maintenance:start'\n\t| 'git:maintenance:start:systemd'\n\t| 'git:manyFiles'\n\t| 'git:merge-tree:merge-base'\n\t| 'git:merge-tree:write-tree'\n\t| 'git:patch-id:binary-oids'\n\t| 'git:patch-id:verbatim'\n\t| 'git:push:force-if-includes'\n\t| 'git:rebase:autosquash'\n\t| 'git:rev-parse:end-of-options'\n\t| 'git:signing:ssh'\n\t| 'git:signing:x509'\n\t| 'git:sparse-index'\n\t| 'git:stash:push:pathspecs'\n\t| 'git:stash:push:staged'\n\t| 'git:stash:push:stdin'\n\t| 'git:status:find-renames'\n\t| 'git:status:porcelain-v2'\n\t| 'git:untrackedCache'\n\t| 'git:worktrees';\n\ntype ExtractPrefix<T> = T extends `${infer Prefix}:${infer Rest}`\n\t? Rest extends `${infer SubPrefix}:${string}`\n\t\t? T | `${Prefix}:${SubPrefix}` | Prefix\n\t\t: T | Prefix\n\t: never;\n\nexport type GitFeatureOrPrefix = ExtractPrefix<GitFeatures>;\nexport type FilteredGitFeatures<T extends GitFeatureOrPrefix> = T extends GitFeatures\n\t? T\n\t: Extract<GitFeatures, T | `${T}:${string}`>;\n\nexport const gitMinimumVersion = '2.7.2';\nexport const gitFeaturesByVersion = new Map<GitFeatures, string>([\n\t['git:checkout:pathspec-from-file', '2.26'],\n\t// 2.24 is when git READS the commit-graph file by default (core.commitGraph on); writing it for\n\t// older gits would be dead weight.\n\t['git:commit-graph', '2.24'],\n\t// Changed-path Bloom filters (`--changed-paths`), the v2 filter format — pre-2.31 shipped Bloom filters\n\t// with real correctness bugs (bad results for merge commits), so 2.31 is the safe floor to write them.\n\t['git:commit-graph:changed-paths', '2.31'],\n\t['git:fetch:no-write-fetch-head', '2.29'],\n\t['git:for-each-ref:worktreePath', '2.23'],\n\t// `core.fsmonitor=true` selects the built-in FSMonitor daemon (accepting a bool rather than only a\n\t// hook path). This 2.37 floor is the Windows + macOS one.\n\t['git:fsmonitor', '2.37'],\n\t// Linux got its own FSMonitor backend (inotify) only in 2.55, hence a separate floor. Note the backend\n\t// places a watch on EVERY directory, so a large repo can exhaust `fs.inotify.max_user_watches` and the\n\t// daemon fails at runtime even on a new enough git — the apply path must still probe, not just gate.\n\t['git:fsmonitor:linux', '2.55'],\n\t['git:ignoreRevsFile', '2.23'],\n\t// `index.skipHash` (skip the trailing index checksum for faster writes); part of `feature.manyFiles`.\n\t['git:index:skipHash', '2.40'],\n\t// `git maintenance run --task=…`. The `maintenance` builtin + `commit-graph`/`gc` tasks are 2.29, but\n\t// the loose-objects + incremental-repack tasks the auto tier uses landed in 2.30 (and `core.multiPackIndex`\n\t// is default-on from 2.30, so no separate midx config write is needed) — 2.30 is the safe floor.\n\t['git:maintenance', '2.30'],\n\t// The pack-refs maintenance task landed one release after the maintenance builtin.\n\t['git:maintenance:pack-refs', '2.31'],\n\t// `git maintenance start` — the subcommands exist from 2.30 (cron only); launchctl (macOS) + schtasks\n\t// (Windows) scheduling arrived in 2.31, so 2.31 is the cross-platform-safe floor.\n\t['git:maintenance:start', '2.31'],\n\t// `git maintenance start` systemd-timer scheduling. On Linux, 2.31–2.33 is cron-only and modern distros\n\t// often ship without cron (scheduling then silently fails); the systemd fallback arrived in 2.34.\n\t['git:maintenance:start:systemd', '2.34'],\n\t// `feature.manyFiles` umbrella (index v4 + untracked cache + skipHash where available).\n\t['git:manyFiles', '2.24'],\n\t['git:merge-tree:merge-base', '2.40'],\n\t// `merge-tree --write-tree` mode with `-z`/`--name-only`/`--no-messages`; the older trivial mode can't check conflicts\n\t['git:merge-tree:write-tree', '2.38'],\n\t// `patch-id` hashes a binary change through its blob ids; older ones hash the diff's text, so need `--binary` data\n\t['git:patch-id:binary-oids', '2.39'],\n\t// `patch-id --verbatim`: hashes whitespace and file-mode header lines instead of normalizing them away\n\t['git:patch-id:verbatim', '2.39'],\n\t['git:push:force-if-includes', '2.30.0'],\n\t// `--autosquash` WITHOUT `-i` (folding `fixup!`/`squash!` commits into a plain/automatic rebase).\n\t// Interactive rebases support autosquash on every git version GitLens supports, so this floor only\n\t// gates the non-interactive path.\n\t['git:rebase:autosquash', '2.44'],\n\t['git:rev-parse:end-of-options', '2.30'],\n\t['git:signing:ssh', '2.34.0'],\n\t['git:signing:x509', '2.19.0'],\n\t// Sparse-index support debuted earlier, but 2.33 shipped a corruption fix and 2.34 broadened command\n\t// support. Use 2.34 as the conservative floor before offering a repository mutation.\n\t['git:sparse-index', '2.34'],\n\t['git:stash:push:pathspecs', '2.13.2'],\n\t['git:stash:push:staged', '2.35.0'],\n\t['git:stash:push:stdin', '2.30.0'],\n\t['git:status:find-renames', '2.18'],\n\t['git:status:porcelain-v2', '2.11'],\n\t// `core.untrackedCache=true` (repo-local cache of untracked-file scans — the auto-tier config lever).\n\t['git:untrackedCache', '2.8'],\n\t['git:worktrees', '2.17.0'],\n]);\n"],"mappings":";AA6CA,MAAa,oBAAoB;AACjC,MAAa,uCAAuB,IAAI,IAAyB;CAChE,CAAC,mCAAmC,MAAM;CAG1C,CAAC,oBAAoB,MAAM;CAG3B,CAAC,kCAAkC,MAAM;CACzC,CAAC,iCAAiC,MAAM;CACxC,CAAC,iCAAiC,MAAM;CAGxC,CAAC,iBAAiB,MAAM;CAIxB,CAAC,uBAAuB,MAAM;CAC9B,CAAC,sBAAsB,MAAM;CAE7B,CAAC,sBAAsB,MAAM;CAI7B,CAAC,mBAAmB,MAAM;CAE1B,CAAC,6BAA6B,MAAM;CAGpC,CAAC,yBAAyB,MAAM;CAGhC,CAAC,iCAAiC,MAAM;CAExC,CAAC,iBAAiB,MAAM;CACxB,CAAC,6BAA6B,MAAM;CAEpC,CAAC,6BAA6B,MAAM;CAEpC,CAAC,4BAA4B,MAAM;CAEnC,CAAC,yBAAyB,MAAM;CAChC,CAAC,8BAA8B,QAAQ;CAIvC,CAAC,yBAAyB,MAAM;CAChC,CAAC,gCAAgC,MAAM;CACvC,CAAC,mBAAmB,QAAQ;CAC5B,CAAC,oBAAoB,QAAQ;CAG7B,CAAC,oBAAoB,MAAM;CAC3B,CAAC,4BAA4B,QAAQ;CACrC,CAAC,yBAAyB,QAAQ;CAClC,CAAC,wBAAwB,QAAQ;CACjC,CAAC,2BAA2B,MAAM;CAClC,CAAC,2BAA2B,MAAM;CAElC,CAAC,sBAAsB,KAAK;CAC5B,CAAC,iBAAiB,QAAQ;AAC3B,CAAC"}
1
+ {"version":3,"file":"features.js","names":[],"sources":["../../../git/src/features.ts"],"sourcesContent":["// GitFeature's must start with `git:` to be recognized in all usages\nexport type GitFeatures =\n\t| 'git:checkout:pathspec-from-file'\n\t| 'git:commit-graph'\n\t| 'git:commit-graph:changed-paths'\n\t| 'git:fetch:all-config'\n\t| 'git:fetch:follow-remote-head'\n\t| 'git:fetch:no-write-fetch-head'\n\t| 'git:for-each-ref:ahead-behind'\n\t| 'git:for-each-ref:worktreePath'\n\t| 'git:fsmonitor'\n\t| 'git:fsmonitor:linux'\n\t| 'git:ignoreRevsFile'\n\t| 'git:index:skipHash'\n\t| 'git:maintenance'\n\t| 'git:maintenance:pack-refs'\n\t| 'git:maintenance:start'\n\t| 'git:maintenance:start:systemd'\n\t| 'git:manyFiles'\n\t| 'git:merge-tree:merge-base'\n\t| 'git:merge-tree:write-tree'\n\t| 'git:patch-id:binary-oids'\n\t| 'git:patch-id:verbatim'\n\t| 'git:push:force-if-includes'\n\t| 'git:rebase:autosquash'\n\t| 'git:rev-parse:end-of-options'\n\t| 'git:signing:ssh'\n\t| 'git:signing:x509'\n\t| 'git:sparse-index'\n\t| 'git:stash:push:pathspecs'\n\t| 'git:stash:push:staged'\n\t| 'git:stash:push:stdin'\n\t| 'git:status:find-renames'\n\t| 'git:status:porcelain-v2'\n\t| 'git:untrackedCache'\n\t| 'git:worktree:list:lock-reason'\n\t| 'git:worktrees';\n\ntype ExtractPrefix<T> = T extends `${infer Prefix}:${infer Rest}`\n\t? Rest extends `${infer SubPrefix}:${string}`\n\t\t? T | `${Prefix}:${SubPrefix}` | Prefix\n\t\t: T | Prefix\n\t: never;\n\nexport type GitFeatureOrPrefix = ExtractPrefix<GitFeatures>;\nexport type FilteredGitFeatures<T extends GitFeatureOrPrefix> = T extends GitFeatures\n\t? T\n\t: Extract<GitFeatures, T | `${T}:${string}`>;\n\nexport const gitMinimumVersion = '2.7.2';\nexport const gitFeaturesByVersion = new Map<GitFeatures, string>([\n\t['git:checkout:pathspec-from-file', '2.26'],\n\t// 2.24 is when git READS the commit-graph file by default (core.commitGraph on); writing it for\n\t// older gits would be dead weight.\n\t['git:commit-graph', '2.24'],\n\t// Changed-path Bloom filters (`--changed-paths`), the v2 filter format — pre-2.31 shipped Bloom filters\n\t// with real correctness bugs (bad results for merge commits), so 2.31 is the safe floor to write them.\n\t['git:commit-graph:changed-paths', '2.31'],\n\t// A bare `fetch` reads every remote when `fetch.all` is set\n\t['git:fetch:all-config', '2.44'],\n\t// A fetch using a remote's configured refspecs creates its missing `refs/remotes/<remote>/HEAD`\n\t// (`remote.<name>.followRemoteHEAD`, default `create`)\n\t['git:fetch:follow-remote-head', '2.48'],\n\t['git:fetch:no-write-fetch-head', '2.29'],\n\t// `%(ahead-behind:<commit>)` in for-each-ref formats\n\t['git:for-each-ref:ahead-behind', '2.41'],\n\t['git:for-each-ref:worktreePath', '2.23'],\n\t// `core.fsmonitor=true` selects the built-in FSMonitor daemon (accepting a bool rather than only a\n\t// hook path). This 2.37 floor is the Windows + macOS one.\n\t['git:fsmonitor', '2.37'],\n\t// Linux got its own FSMonitor backend (inotify) only in 2.55, hence a separate floor. Note the backend\n\t// places a watch on EVERY directory, so a large repo can exhaust `fs.inotify.max_user_watches` and the\n\t// daemon fails at runtime even on a new enough git — the apply path must still probe, not just gate.\n\t['git:fsmonitor:linux', '2.55'],\n\t['git:ignoreRevsFile', '2.23'],\n\t// `index.skipHash` (skip the trailing index checksum for faster writes); part of `feature.manyFiles`.\n\t['git:index:skipHash', '2.40'],\n\t// `git maintenance run --task=…`. The `maintenance` builtin + `commit-graph`/`gc` tasks are 2.29, but\n\t// the loose-objects + incremental-repack tasks the auto tier uses landed in 2.30 (and `core.multiPackIndex`\n\t// is default-on from 2.30, so no separate midx config write is needed) — 2.30 is the safe floor.\n\t['git:maintenance', '2.30'],\n\t// The pack-refs maintenance task landed one release after the maintenance builtin.\n\t['git:maintenance:pack-refs', '2.31'],\n\t// `git maintenance start` — the subcommands exist from 2.30 (cron only); launchctl (macOS) + schtasks\n\t// (Windows) scheduling arrived in 2.31, so 2.31 is the cross-platform-safe floor.\n\t['git:maintenance:start', '2.31'],\n\t// `git maintenance start` systemd-timer scheduling. On Linux, 2.31–2.33 is cron-only and modern distros\n\t// often ship without cron (scheduling then silently fails); the systemd fallback arrived in 2.34.\n\t['git:maintenance:start:systemd', '2.34'],\n\t// `feature.manyFiles` umbrella (index v4 + untracked cache + skipHash where available).\n\t['git:manyFiles', '2.24'],\n\t['git:merge-tree:merge-base', '2.40'],\n\t// `merge-tree --write-tree` mode with `-z`/`--name-only`/`--no-messages`; the older trivial mode can't check conflicts\n\t['git:merge-tree:write-tree', '2.38'],\n\t// `patch-id` hashes a binary change through its blob ids; older ones hash the diff's text, so need `--binary` data\n\t['git:patch-id:binary-oids', '2.39'],\n\t// `patch-id --verbatim`: hashes whitespace and file-mode header lines instead of normalizing them away\n\t['git:patch-id:verbatim', '2.39'],\n\t['git:push:force-if-includes', '2.30.0'],\n\t// `--autosquash` WITHOUT `-i` (folding `fixup!`/`squash!` commits into a plain/automatic rebase).\n\t// Interactive rebases support autosquash on every git version GitLens supports, so this floor only\n\t// gates the non-interactive path.\n\t['git:rebase:autosquash', '2.44'],\n\t['git:rev-parse:end-of-options', '2.30'],\n\t['git:signing:ssh', '2.34.0'],\n\t['git:signing:x509', '2.19.0'],\n\t// Sparse-index support debuted earlier, but 2.33 shipped a corruption fix and 2.34 broadened command\n\t// support. Use 2.34 as the conservative floor before offering a repository mutation.\n\t['git:sparse-index', '2.34'],\n\t['git:stash:push:pathspecs', '2.13.2'],\n\t['git:stash:push:staged', '2.35.0'],\n\t['git:stash:push:stdin', '2.30.0'],\n\t['git:status:find-renames', '2.18'],\n\t['git:status:porcelain-v2', '2.11'],\n\t// `core.untrackedCache=true` (repo-local cache of untracked-file scans — the auto-tier config lever).\n\t['git:untrackedCache', '2.8'],\n\t// `worktree list --porcelain` prints a lock's reason (`locked <reason>`); older ones print a bare `locked`\n\t['git:worktree:list:lock-reason', '2.31'],\n\t['git:worktrees', '2.17.0'],\n]);\n"],"mappings":";AAiDA,MAAa,oBAAoB;AACjC,MAAa,uCAAuB,IAAI,IAAyB;CAChE,CAAC,mCAAmC,MAAM;CAG1C,CAAC,oBAAoB,MAAM;CAG3B,CAAC,kCAAkC,MAAM;CAEzC,CAAC,wBAAwB,MAAM;CAG/B,CAAC,gCAAgC,MAAM;CACvC,CAAC,iCAAiC,MAAM;CAExC,CAAC,iCAAiC,MAAM;CACxC,CAAC,iCAAiC,MAAM;CAGxC,CAAC,iBAAiB,MAAM;CAIxB,CAAC,uBAAuB,MAAM;CAC9B,CAAC,sBAAsB,MAAM;CAE7B,CAAC,sBAAsB,MAAM;CAI7B,CAAC,mBAAmB,MAAM;CAE1B,CAAC,6BAA6B,MAAM;CAGpC,CAAC,yBAAyB,MAAM;CAGhC,CAAC,iCAAiC,MAAM;CAExC,CAAC,iBAAiB,MAAM;CACxB,CAAC,6BAA6B,MAAM;CAEpC,CAAC,6BAA6B,MAAM;CAEpC,CAAC,4BAA4B,MAAM;CAEnC,CAAC,yBAAyB,MAAM;CAChC,CAAC,8BAA8B,QAAQ;CAIvC,CAAC,yBAAyB,MAAM;CAChC,CAAC,gCAAgC,MAAM;CACvC,CAAC,mBAAmB,QAAQ;CAC5B,CAAC,oBAAoB,QAAQ;CAG7B,CAAC,oBAAoB,MAAM;CAC3B,CAAC,4BAA4B,QAAQ;CACrC,CAAC,yBAAyB,QAAQ;CAClC,CAAC,wBAAwB,QAAQ;CACjC,CAAC,2BAA2B,MAAM;CAClC,CAAC,2BAA2B,MAAM;CAElC,CAAC,sBAAsB,KAAK;CAE5B,CAAC,iCAAiC,MAAM;CACxC,CAAC,iBAAiB,QAAQ;AAC3B,CAAC"}
@@ -3,6 +3,12 @@ import { Shape } from "../../utils/types.js";
3
3
  import { GitBranchReference } from "./reference.js";
4
4
  //#region ../git/src/models/branch.d.ts
5
5
  export type BranchDisposition = 'starred' | 'archived';
6
+ /** The `.git/gk/config` keys (`branch.<name>.<key>`) a branch's {@link BranchMetadata} is read from */
7
+ export type BranchMetadataGkConfigKey = 'gk-last-accessed' | 'gk-last-modified' | 'gk-agent-last-activity' | 'gk-disposition';
8
+ /**
9
+ * A branch's `.git/gk/config` metadata. Unlike other cached values, the cache updates these objects in place when a
10
+ * key changes (see `Cache.patchBranchMetadata`), so every `GitBranch` holding one, old or new, reads the new value
11
+ */
6
12
  export interface BranchMetadata {
7
13
  lastAccessedAt?: string;
8
14
  lastModifiedAt?: string;
@@ -15,7 +21,10 @@ export declare class GitBranch implements GitBranchReference {
15
21
  readonly refName: string;
16
22
  readonly current: boolean;
17
23
  readonly date: Date | undefined;
18
- /** GK config metadata (dates, disposition) */
24
+ /**
25
+ * GK config metadata (dates, disposition), shared with the cache and updated in place: comparing an old and a
26
+ * new branch can't detect a changed stamp (no change event fires for one either)
27
+ */
19
28
  readonly metadata: BranchMetadata | undefined;
20
29
  readonly sha?: string | undefined;
21
30
  readonly upstream?: GitTrackingUpstream | undefined;
@@ -32,7 +41,10 @@ export declare class GitBranch implements GitBranchReference {
32
41
  private readonly _remote;
33
42
  get remote(): boolean;
34
43
  constructor(repoPath: string, refName: string, current: boolean, date: Date | undefined,
35
- /** GK config metadata (dates, disposition) */
44
+ /**
45
+ * GK config metadata (dates, disposition), shared with the cache and updated in place: comparing an old and a
46
+ * new branch can't detect a changed stamp (no change event fires for one either)
47
+ */
36
48
  metadata: BranchMetadata | undefined, sha?: string | undefined, upstream?: GitTrackingUpstream | undefined, worktree?: {
37
49
  path: string;
38
50
  isDefault: boolean;
@@ -43,6 +55,7 @@ export declare class GitBranch implements GitBranchReference {
43
55
  /** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */
44
56
  get effectiveDate(): Date | undefined;
45
57
  get lastAccessedDate(): Date | undefined;
58
+ /** When a checkout's working tree or index last changed while on this branch (`gk-last-modified`), not only commits */
46
59
  get lastModifiedDate(): Date | undefined;
47
60
  get nameWithoutRemote(): string;
48
61
  get ref(): string;
@@ -1,13 +1,36 @@
1
1
  import { loggable } from "../../utils/decorators/log.js";
2
2
  import { memoize } from "../../utils/decorators/memoize.js";
3
3
  import { getBranchId, getRemoteNameFromBranchName, getRemoteNameSlashIndex } from "../../utils/gitRefs.js";
4
+ import { formatDetachedHeadName, getBranchTrackingWithoutRemote, isDetachedHead, parseRefName } from "../utils/branch.utils.js";
4
5
  import __decorate from "../../_virtual/@oxc-project+runtime/helpers/esm/decorate.js";
5
6
  import { formatDate, fromNow } from "../../utils/date.js";
6
7
  import { serializable } from "../../utils/decorators/serializable.js";
7
- import { formatDetachedHeadName, getBranchTrackingWithoutRemote, isDetachedHead, parseRefName } from "../utils/branch.utils.js";
8
8
  import { getUpstreamStatus } from "../utils/status.utils.js";
9
9
  //#region ../git/src/models/branch.ts
10
10
  var _GitBranch;
11
+ /**
12
+ * Each metadata object's last parsed stamps. Not `@memoize`d on the branch: the cache updates `BranchMetadata` in
13
+ * place, so a parse is reused only while its stamp is unchanged — and shared by every branch holding the object.
14
+ */
15
+ const stampDates = /* @__PURE__ */ new WeakMap();
16
+ function getStampDate(metadata, field) {
17
+ const stamp = metadata[field];
18
+ if (!stamp) return void 0;
19
+ let parsed = stampDates.get(metadata);
20
+ if (parsed == null) {
21
+ parsed = {};
22
+ stampDates.set(metadata, parsed);
23
+ }
24
+ let entry = parsed[field];
25
+ if (entry?.stamp !== stamp) {
26
+ entry = {
27
+ stamp,
28
+ date: new Date(stamp)
29
+ };
30
+ parsed[field] = entry;
31
+ }
32
+ return entry.date;
33
+ }
11
34
  let GitBranch = _GitBranch = class GitBranch {
12
35
  repoPath;
13
36
  refName;
@@ -70,10 +93,11 @@ let GitBranch = _GitBranch = class GitBranch {
70
93
  return maxTime != null ? new Date(maxTime) : void 0;
71
94
  }
72
95
  get lastAccessedDate() {
73
- return this.metadata?.lastAccessedAt ? new Date(this.metadata.lastAccessedAt) : void 0;
96
+ return this.metadata != null ? getStampDate(this.metadata, "lastAccessedAt") : void 0;
74
97
  }
98
+ /** When a checkout's working tree or index last changed while on this branch (`gk-last-modified`), not only commits */
75
99
  get lastModifiedDate() {
76
- return this.metadata?.lastModifiedAt ? new Date(this.metadata.lastModifiedAt) : void 0;
100
+ return this.metadata != null ? getStampDate(this.metadata, "lastModifiedAt") : void 0;
77
101
  }
78
102
  get nameWithoutRemote() {
79
103
  return this.remote ? this.name.substring(getRemoteNameSlashIndex(this.name) + 1) : this.name;
@@ -123,8 +147,6 @@ let GitBranch = _GitBranch = class GitBranch {
123
147
  }
124
148
  };
125
149
  __decorate([memoize()], GitBranch.prototype, "basename", null);
126
- __decorate([memoize()], GitBranch.prototype, "lastAccessedDate", null);
127
- __decorate([memoize()], GitBranch.prototype, "lastModifiedDate", null);
128
150
  __decorate([memoize()], GitBranch.prototype, "nameWithoutRemote", null);
129
151
  __decorate([memoize()], GitBranch.prototype, "remoteName", null);
130
152
  __decorate([memoize()], GitBranch.prototype, "trackingWithoutRemote", null);
@@ -1 +1 @@
1
- {"version":3,"file":"branch.js","names":[],"sources":["../../../../git/src/models/branch.ts"],"sourcesContent":["import { formatDate, fromNow } from '@gitlens/utils/date.js';\nimport { loggable } from '@gitlens/utils/decorators/log.js';\nimport { memoize } from '@gitlens/utils/decorators/memoize.js';\nimport { serializable } from '@gitlens/utils/decorators/serializable.js';\nimport { getBranchId, getRemoteNameFromBranchName, getRemoteNameSlashIndex } from '@gitlens/utils/gitRefs.js';\nimport type { MaybePausedResult } from '@gitlens/utils/promise.js';\nimport type { Shape } from '@gitlens/utils/types.js';\nimport {\n\tformatDetachedHeadName,\n\tgetBranchTrackingWithoutRemote,\n\tisDetachedHead,\n\tparseRefName,\n} from '../utils/branch.utils.js';\nimport { getUpstreamStatus } from '../utils/status.utils.js';\nimport type { GitBranchReference } from './reference.js';\n\nexport type BranchDisposition = 'starred' | 'archived';\n\nexport interface BranchMetadata {\n\tlastAccessedAt?: string;\n\tlastModifiedAt?: string;\n\tagentLastActivityAt?: string;\n\tdisposition?: BranchDisposition;\n}\n\nexport type GitBranchShape = Shape<GitBranch>;\n\n@loggable(i => i.id)\n@serializable\nexport class GitBranch implements GitBranchReference {\n\treadonly refType = 'branch';\n\treadonly detached: boolean;\n\treadonly id: string;\n\n\tprivate readonly _name: string;\n\tget name(): string {\n\t\treturn this._name;\n\t}\n\n\tprivate readonly _remote: boolean;\n\tget remote(): boolean {\n\t\treturn this._remote;\n\t}\n\n\tconstructor(\n\t\tpublic readonly repoPath: string,\n\t\tpublic readonly refName: string,\n\t\tpublic readonly current: boolean,\n\t\tpublic readonly date: Date | undefined,\n\t\t/** GK config metadata (dates, disposition) */\n\t\tpublic readonly metadata: BranchMetadata | undefined,\n\t\tpublic readonly sha?: string,\n\t\tpublic readonly upstream?: GitTrackingUpstream,\n\t\tpublic readonly worktree?: { path: string; isDefault: boolean } | false,\n\t\tdetached: boolean = false,\n\t\tpublic readonly rebasing: boolean = false,\n\t) {\n\t\t({ name: this._name, remote: this._remote } = parseRefName(refName));\n\n\t\tthis.detached = detached || (this.current ? isDetachedHead(this._name) : false);\n\t\tif (this.detached) {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this.sha!);\n\t\t\tthis._name = formatDetachedHeadName(this.sha!);\n\t\t} else {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this._name);\n\t\t}\n\n\t\tthis.upstream = upstream?.name ? upstream : undefined;\n\t}\n\n\tget archived(): boolean {\n\t\treturn this.metadata?.disposition === 'archived';\n\t}\n\n\t@memoize()\n\tget basename(): string {\n\t\tconst name = this.nameWithoutRemote;\n\t\tconst index = name.lastIndexOf('/');\n\t\treturn index !== -1 ? name.substring(index + 1) : name;\n\t}\n\n\tget disposition(): BranchDisposition | undefined {\n\t\treturn this.metadata?.disposition;\n\t}\n\n\t/** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */\n\tget effectiveDate(): Date | undefined {\n\t\tlet maxTime: number | undefined;\n\n\t\tconst accessed = this.lastAccessedDate?.getTime();\n\t\tif (accessed != null && (maxTime == null || accessed > maxTime)) {\n\t\t\tmaxTime = accessed;\n\t\t}\n\n\t\tconst modified = this.lastModifiedDate?.getTime();\n\t\tif (modified != null && (maxTime == null || modified > maxTime)) {\n\t\t\tmaxTime = modified;\n\t\t}\n\n\t\tconst date = this.date?.getTime();\n\t\tif (date != null && (maxTime == null || date > maxTime)) {\n\t\t\tmaxTime = date;\n\t\t}\n\n\t\treturn maxTime != null ? new Date(maxTime) : undefined;\n\t}\n\n\t@memoize()\n\tget lastAccessedDate(): Date | undefined {\n\t\treturn this.metadata?.lastAccessedAt ? new Date(this.metadata.lastAccessedAt) : undefined;\n\t}\n\n\t@memoize()\n\tget lastModifiedDate(): Date | undefined {\n\t\treturn this.metadata?.lastModifiedAt ? new Date(this.metadata.lastModifiedAt) : undefined;\n\t}\n\n\t@memoize()\n\tget nameWithoutRemote(): string {\n\t\treturn this.remote ? this.name.substring(getRemoteNameSlashIndex(this.name) + 1) : this.name;\n\t}\n\n\tget ref(): string {\n\t\treturn this.detached ? this.sha! : this._name;\n\t}\n\n\t@memoize()\n\tget remoteName(): string | undefined {\n\t\tif (this.remote) return getRemoteNameFromBranchName(this.name);\n\t\tif (this.upstream != null) return getRemoteNameFromBranchName(this.upstream.name);\n\n\t\treturn undefined;\n\t}\n\n\tget starred(): boolean {\n\t\treturn this.metadata?.disposition === 'starred';\n\t}\n\n\tget status(): GitBranchStatus {\n\t\tif (this.remote) return 'remote';\n\t\tif (this.upstream == null) return this.detached ? 'detached' : 'local';\n\n\t\tif (this.upstream.missing) return 'missingUpstream';\n\t\tif (this.upstream.state.ahead && this.upstream.state.behind) return 'diverged';\n\t\tif (this.upstream.state.ahead) return 'ahead';\n\t\tif (this.upstream.state.behind) return 'behind';\n\t\treturn 'upToDate';\n\t}\n\n\t@memoize()\n\tget trackingWithoutRemote(): string | undefined {\n\t\treturn getBranchTrackingWithoutRemote(this);\n\t}\n\n\t/** Creates a copy of this branch with a different repoPath and optionally a different current flag — ONLY used for worktree-aware caching */\n\twithRepoPath(repoPath: string, current?: boolean): GitBranch {\n\t\tconst newCurrent = current ?? this.current;\n\t\tif (repoPath === this.repoPath && newCurrent === this.current) return this;\n\t\treturn new GitBranch(\n\t\t\trepoPath,\n\t\t\tthis.refName,\n\t\t\tnewCurrent,\n\t\t\tthis.date,\n\t\t\tthis.metadata,\n\t\t\tthis.sha,\n\t\t\tthis.upstream,\n\t\t\tthis.worktree,\n\t\t\tthis.detached,\n\t\t\tthis.rebasing,\n\t\t);\n\t}\n\n\tstatic is(branch: unknown): branch is GitBranch {\n\t\treturn branch instanceof GitBranch;\n\t}\n\n\tstatic formatDate(branch: GitBranchShape, format?: string | null): string {\n\t\treturn branch.date != null ? formatDate(branch.date, format ?? 'MMMM Do, YYYY h:mma') : '';\n\t}\n\n\tstatic formatDateFromNow(branch: GitBranchShape): string {\n\t\treturn branch.date != null ? fromNow(branch.date) : '';\n\t}\n\n\tstatic formatDateWithStyle(\n\t\tbranch: GitBranchShape,\n\t\tformatting: { dateStyle: string; dateFormat: string | null },\n\t): string {\n\t\treturn formatting.dateStyle === 'absolute'\n\t\t\t? GitBranch.formatDate(branch, formatting.dateFormat)\n\t\t\t: GitBranch.formatDateFromNow(branch);\n\t}\n\n\tstatic getTrackingStatus(\n\t\tbranch: GitBranchShape,\n\t\toptions?: {\n\t\t\tcount?: boolean;\n\t\t\tempty?: string;\n\t\t\texpand?: boolean;\n\t\t\ticons?: boolean;\n\t\t\tprefix?: string;\n\t\t\tseparator?: string;\n\t\t\tsuffix?: string;\n\t\t},\n\t): string {\n\t\treturn getUpstreamStatus(branch.upstream, options);\n\t}\n}\n\nexport interface GitTrackingState {\n\treadonly ahead: number;\n\treadonly behind: number;\n}\n\nexport interface GitTrackingUpstream {\n\treadonly name: string;\n\treadonly missing: boolean;\n\treadonly state: GitTrackingState;\n}\n\nexport type GitBranchStatus =\n\t| 'local'\n\t| 'detached'\n\t| 'ahead'\n\t| 'behind'\n\t| 'diverged'\n\t| 'upToDate'\n\t| 'missingUpstream'\n\t| 'remote';\n\nexport interface BranchTargetInfo {\n\tmergeTargetBranch: MaybePausedResult<string | undefined>;\n\tbaseBranch: string | undefined;\n\tdefaultBranch: string | undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"branch.js","names":[],"sources":["../../../../git/src/models/branch.ts"],"sourcesContent":["import { formatDate, fromNow } from '@gitlens/utils/date.js';\nimport { loggable } from '@gitlens/utils/decorators/log.js';\nimport { memoize } from '@gitlens/utils/decorators/memoize.js';\nimport { serializable } from '@gitlens/utils/decorators/serializable.js';\nimport { getBranchId, getRemoteNameFromBranchName, getRemoteNameSlashIndex } from '@gitlens/utils/gitRefs.js';\nimport type { MaybePausedResult } from '@gitlens/utils/promise.js';\nimport type { Shape } from '@gitlens/utils/types.js';\nimport {\n\tformatDetachedHeadName,\n\tgetBranchTrackingWithoutRemote,\n\tisDetachedHead,\n\tparseRefName,\n} from '../utils/branch.utils.js';\nimport { getUpstreamStatus } from '../utils/status.utils.js';\nimport type { GitBranchReference } from './reference.js';\n\nexport type BranchDisposition = 'starred' | 'archived';\n\n/** The `.git/gk/config` keys (`branch.<name>.<key>`) a branch's {@link BranchMetadata} is read from */\nexport type BranchMetadataGkConfigKey =\n\t| 'gk-last-accessed'\n\t| 'gk-last-modified'\n\t| 'gk-agent-last-activity'\n\t| 'gk-disposition';\n\n/**\n * A branch's `.git/gk/config` metadata. Unlike other cached values, the cache updates these objects in place when a\n * key changes (see `Cache.patchBranchMetadata`), so every `GitBranch` holding one, old or new, reads the new value\n */\nexport interface BranchMetadata {\n\tlastAccessedAt?: string;\n\tlastModifiedAt?: string;\n\tagentLastActivityAt?: string;\n\tdisposition?: BranchDisposition;\n}\n\nexport type GitBranchShape = Shape<GitBranch>;\n\n/**\n * Each metadata object's last parsed stamps. Not `@memoize`d on the branch: the cache updates `BranchMetadata` in\n * place, so a parse is reused only while its stamp is unchanged — and shared by every branch holding the object.\n */\nconst stampDates = new WeakMap<BranchMetadata, Partial<Record<StampField, { stamp: string; date: Date }>>>();\ntype StampField = 'lastAccessedAt' | 'lastModifiedAt';\n\nfunction getStampDate(metadata: BranchMetadata, field: StampField): Date | undefined {\n\tconst stamp = metadata[field];\n\tif (!stamp) return undefined;\n\n\tlet parsed = stampDates.get(metadata);\n\tif (parsed == null) {\n\t\tparsed = {};\n\t\tstampDates.set(metadata, parsed);\n\t}\n\n\tlet entry = parsed[field];\n\tif (entry?.stamp !== stamp) {\n\t\tentry = { stamp: stamp, date: new Date(stamp) };\n\t\tparsed[field] = entry;\n\t}\n\treturn entry.date;\n}\n\n@loggable(i => i.id)\n@serializable\nexport class GitBranch implements GitBranchReference {\n\treadonly refType = 'branch';\n\treadonly detached: boolean;\n\treadonly id: string;\n\n\tprivate readonly _name: string;\n\tget name(): string {\n\t\treturn this._name;\n\t}\n\n\tprivate readonly _remote: boolean;\n\tget remote(): boolean {\n\t\treturn this._remote;\n\t}\n\n\tconstructor(\n\t\tpublic readonly repoPath: string,\n\t\tpublic readonly refName: string,\n\t\tpublic readonly current: boolean,\n\t\tpublic readonly date: Date | undefined,\n\t\t/**\n\t\t * GK config metadata (dates, disposition), shared with the cache and updated in place: comparing an old and a\n\t\t * new branch can't detect a changed stamp (no change event fires for one either)\n\t\t */\n\t\tpublic readonly metadata: BranchMetadata | undefined,\n\t\tpublic readonly sha?: string,\n\t\tpublic readonly upstream?: GitTrackingUpstream,\n\t\tpublic readonly worktree?: { path: string; isDefault: boolean } | false,\n\t\tdetached: boolean = false,\n\t\tpublic readonly rebasing: boolean = false,\n\t) {\n\t\t({ name: this._name, remote: this._remote } = parseRefName(refName));\n\n\t\tthis.detached = detached || (this.current ? isDetachedHead(this._name) : false);\n\t\tif (this.detached) {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this.sha!);\n\t\t\tthis._name = formatDetachedHeadName(this.sha!);\n\t\t} else {\n\t\t\tthis.id = getBranchId(repoPath, this._remote, this._name);\n\t\t}\n\n\t\tthis.upstream = upstream?.name ? upstream : undefined;\n\t}\n\n\tget archived(): boolean {\n\t\treturn this.metadata?.disposition === 'archived';\n\t}\n\n\t@memoize()\n\tget basename(): string {\n\t\tconst name = this.nameWithoutRemote;\n\t\tconst index = name.lastIndexOf('/');\n\t\treturn index !== -1 ? name.substring(index + 1) : name;\n\t}\n\n\tget disposition(): BranchDisposition | undefined {\n\t\treturn this.metadata?.disposition;\n\t}\n\n\t/** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */\n\tget effectiveDate(): Date | undefined {\n\t\tlet maxTime: number | undefined;\n\n\t\tconst accessed = this.lastAccessedDate?.getTime();\n\t\tif (accessed != null && (maxTime == null || accessed > maxTime)) {\n\t\t\tmaxTime = accessed;\n\t\t}\n\n\t\tconst modified = this.lastModifiedDate?.getTime();\n\t\tif (modified != null && (maxTime == null || modified > maxTime)) {\n\t\t\tmaxTime = modified;\n\t\t}\n\n\t\tconst date = this.date?.getTime();\n\t\tif (date != null && (maxTime == null || date > maxTime)) {\n\t\t\tmaxTime = date;\n\t\t}\n\n\t\treturn maxTime != null ? new Date(maxTime) : undefined;\n\t}\n\n\tget lastAccessedDate(): Date | undefined {\n\t\treturn this.metadata != null ? getStampDate(this.metadata, 'lastAccessedAt') : undefined;\n\t}\n\n\t/** When a checkout's working tree or index last changed while on this branch (`gk-last-modified`), not only commits */\n\tget lastModifiedDate(): Date | undefined {\n\t\treturn this.metadata != null ? getStampDate(this.metadata, 'lastModifiedAt') : undefined;\n\t}\n\n\t@memoize()\n\tget nameWithoutRemote(): string {\n\t\treturn this.remote ? this.name.substring(getRemoteNameSlashIndex(this.name) + 1) : this.name;\n\t}\n\n\tget ref(): string {\n\t\treturn this.detached ? this.sha! : this._name;\n\t}\n\n\t@memoize()\n\tget remoteName(): string | undefined {\n\t\tif (this.remote) return getRemoteNameFromBranchName(this.name);\n\t\tif (this.upstream != null) return getRemoteNameFromBranchName(this.upstream.name);\n\n\t\treturn undefined;\n\t}\n\n\tget starred(): boolean {\n\t\treturn this.metadata?.disposition === 'starred';\n\t}\n\n\tget status(): GitBranchStatus {\n\t\tif (this.remote) return 'remote';\n\t\tif (this.upstream == null) return this.detached ? 'detached' : 'local';\n\n\t\tif (this.upstream.missing) return 'missingUpstream';\n\t\tif (this.upstream.state.ahead && this.upstream.state.behind) return 'diverged';\n\t\tif (this.upstream.state.ahead) return 'ahead';\n\t\tif (this.upstream.state.behind) return 'behind';\n\t\treturn 'upToDate';\n\t}\n\n\t@memoize()\n\tget trackingWithoutRemote(): string | undefined {\n\t\treturn getBranchTrackingWithoutRemote(this);\n\t}\n\n\t/** Creates a copy of this branch with a different repoPath and optionally a different current flag — ONLY used for worktree-aware caching */\n\twithRepoPath(repoPath: string, current?: boolean): GitBranch {\n\t\tconst newCurrent = current ?? this.current;\n\t\tif (repoPath === this.repoPath && newCurrent === this.current) return this;\n\t\treturn new GitBranch(\n\t\t\trepoPath,\n\t\t\tthis.refName,\n\t\t\tnewCurrent,\n\t\t\tthis.date,\n\t\t\tthis.metadata,\n\t\t\tthis.sha,\n\t\t\tthis.upstream,\n\t\t\tthis.worktree,\n\t\t\tthis.detached,\n\t\t\tthis.rebasing,\n\t\t);\n\t}\n\n\tstatic is(branch: unknown): branch is GitBranch {\n\t\treturn branch instanceof GitBranch;\n\t}\n\n\tstatic formatDate(branch: GitBranchShape, format?: string | null): string {\n\t\treturn branch.date != null ? formatDate(branch.date, format ?? 'MMMM Do, YYYY h:mma') : '';\n\t}\n\n\tstatic formatDateFromNow(branch: GitBranchShape): string {\n\t\treturn branch.date != null ? fromNow(branch.date) : '';\n\t}\n\n\tstatic formatDateWithStyle(\n\t\tbranch: GitBranchShape,\n\t\tformatting: { dateStyle: string; dateFormat: string | null },\n\t): string {\n\t\treturn formatting.dateStyle === 'absolute'\n\t\t\t? GitBranch.formatDate(branch, formatting.dateFormat)\n\t\t\t: GitBranch.formatDateFromNow(branch);\n\t}\n\n\tstatic getTrackingStatus(\n\t\tbranch: GitBranchShape,\n\t\toptions?: {\n\t\t\tcount?: boolean;\n\t\t\tempty?: string;\n\t\t\texpand?: boolean;\n\t\t\ticons?: boolean;\n\t\t\tprefix?: string;\n\t\t\tseparator?: string;\n\t\t\tsuffix?: string;\n\t\t},\n\t): string {\n\t\treturn getUpstreamStatus(branch.upstream, options);\n\t}\n}\n\nexport interface GitTrackingState {\n\treadonly ahead: number;\n\treadonly behind: number;\n}\n\nexport interface GitTrackingUpstream {\n\treadonly name: string;\n\treadonly missing: boolean;\n\treadonly state: GitTrackingState;\n}\n\nexport type GitBranchStatus =\n\t| 'local'\n\t| 'detached'\n\t| 'ahead'\n\t| 'behind'\n\t| 'diverged'\n\t| 'upToDate'\n\t| 'missingUpstream'\n\t| 'remote';\n\nexport interface BranchTargetInfo {\n\tmergeTargetBranch: MaybePausedResult<string | undefined>;\n\tbaseBranch: string | undefined;\n\tdefaultBranch: string | undefined;\n}\n"],"mappings":"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"}
@@ -269,7 +269,9 @@ export type IssueProviderState = {
269
269
  id?: string;
270
270
  name: string;
271
271
  color?: string;
272
- category?: 'TO_DO' | 'IN_PROGRESS' | 'DONE';
272
+ /** The provider's workflow category. `CANCELED` is abandoned work (Linear's canceled and duplicate states, Azure's
273
+ * `Removed` category): closed like `DONE`, kept apart so a consumer can tell the two outcomes apart. */
274
+ category?: 'TO_DO' | 'IN_PROGRESS' | 'DONE' | 'CANCELED';
273
275
  };
274
276
  export interface IssueProject {
275
277
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"issue.js","names":[],"sources":["../../../../git/src/models/issue.ts"],"sourcesContent":["import { loggable } from '@gitlens/utils/decorators/log.js';\nimport type { RequireSome, RequireSomeWithProps } from '@gitlens/utils/types.js';\nimport type { IssueOrPullRequest, IssueOrPullRequestState } from './issueOrPullRequest.js';\nimport type { ProviderReference } from './remoteProvider.js';\nimport type { RepositoryIdentityDescriptor } from './repositoryIdentities.js';\n\n/** Selects which issue states a read should include. `all` covers open + closed. */\nexport type IssueStateFilter = 'open' | 'closed' | 'all';\n\n/**\n * One relationship a filtered issue search can constrain on.\n *\n * The last two are USER-INDEPENDENT — they describe the issue, not the caller — and neither is a SCOPE: either\n * one alone matches every such issue on the host, so a search using one still needs a repository/org scope.\n */\nexport type IssueSearchRelationship =\n\t/** Authored by the current user. */\n\t| 'authored'\n\t/** Assigned to the current user. */\n\t| 'assigned'\n\t/** Mentions the current user. */\n\t| 'mentioned'\n\t/** Assigned to ANYONE. Excludes unassigned issues — see {@link IssueSearchCriteria.relationships}. */\n\t| 'any-assignee'\n\t/** Assigned to nobody. The complement of `any-assignee`, not a broadening of it. */\n\t| 'unassigned';\n\n/**\n * A field an issue read can be ordered by, provider-neutral. No provider expresses all of them: each read\n * validates the requested key against the capability its provider declares and refuses one it can't express\n * server-side, rather than serving a differently-ordered list under the name of the one that was asked for.\n *\n * `closed` and `resolved` are deliberately SEPARATE, not two names for the same date. Azure DevOps tracks both\n * and they differ (an issue can be closed without being resolved and resolved without being closed), and Jira\n * has no close date at all — it models the equivalent as `resolutiondate`. Collapsing them would force one of\n * those two providers to lie about which date it ordered by.\n */\nexport type IssueSortField =\n\t/** Creation date. */\n\t| 'created'\n\t/** Last activity. */\n\t| 'updated'\n\t/** Close date. Only where the provider orders by it server-side — notably NOT GitHub. */\n\t| 'closed'\n\t/** Resolution date (Jira `resolutiondate`, Azure `ResolvedDate`). Distinct from `closed`. */\n\t| 'resolved'\n\t/** Number of comments. */\n\t| 'comments'\n\t/** Reactions/upvotes. */\n\t| 'reactions'\n\t/** The provider's own priority field. */\n\t| 'priority'\n\t/** Due date. */\n\t| 'dueDate'\n\t/** Alphabetical by title. */\n\t| 'title';\n\n/**\n * How an issue read is ordered, as `field:direction` — the same shape `BranchSorting`/`TagSorting` already use,\n * so it is one serializable string a consumer can persist, compare, or bind straight to a setting or a dropdown.\n */\nexport type IssueSorting = `${IssueSortField}:asc` | `${IssueSortField}:desc`;\n\n/**\n * The order every issue read that HAS a default applies when the caller asks for none: most recently updated\n * first, which is what those reads served before ordering was an option.\n *\n * One definition rather than one per layer, because it is a promise made in several places at once — the criteria\n * model documents it, the GitHub query emits it, and the result-ceiling warning quotes it — and three copies would\n * be free to disagree about what \"the default\" is.\n *\n * Note it is not a default every read has, and the two layers differ. The API client's account-wide \"my issues\"\n * search (`GitHubApi.searchMyIssues`) never requested an order, so a direct caller omitting `sort` still gets\n * GitHub's relevance order — the default is opt-in there, to keep that read's already-shipped results unchanged.\n * The FACADE does apply it: GitHub declares `updated:desc` among its account-wide keys, so\n * `readAccountWideIssuesPage` resolves the omission to this default and forwards it, and that read's emitted query\n * gained a `sort:updated` qualifier it did not have before. A read whose surface cannot express even this key is\n * the only one the facade leaves in the provider's own order.\n */\nexport const defaultIssueSort: IssueSorting = 'updated:desc';\n\n/**\n * What a filtered issue search narrows on: a provider-neutral criteria set, translated to each provider's own\n * query language by its integration.\n *\n * Structured rather than a provider query string so a consumer can render filter chips and hide the ones a\n * provider can't express, and so the same criteria mean the same thing on a provider whose query language looks\n * nothing like GitHub's search syntax. Every field is validated against the provider's declared capability\n * BEFORE the read runs, all-or-nothing: a criterion the provider can't express server-side refuses the whole\n * read rather than serving a list that was never narrowed. Client-side narrowing is not an option — the dropped\n * items still counted toward the page and cursor the provider produced, so a post-filter would leave the items\n * describing a different result set than the paging that came with them.\n */\nexport interface IssueSearchCriteria {\n\t/**\n\t * Relationships to constrain on, OR-ed together (each becomes its own provider query, unioned and deduped).\n\t * Omitted means NO relationship constraint at all — every issue in scope, assigned or not — which requires a\n\t * repository/org scope.\n\t *\n\t * `any-assignee` and `unassigned` partition the scope between them and are mutually exclusive; passing both is\n\t * refused rather than silently dropping one. Note that \"all visible issues\" is the OMITTED case, NOT\n\t * `any-assignee`, which excludes unassigned issues.\n\t */\n\trelationships?: IssueSearchRelationship[];\n\t/**\n\t * Free text, matched by the provider's own relevance rules — NOT a substring match, and not a way to smuggle\n\t * qualifiers: a token that would read as one is dropped, as are quotes and control characters, so text can\n\t * never re-scope the search. The structured criteria are the qualifier channel.\n\t */\n\ttext?: string;\n\t/** Issue states to include. Omitted reads open issues only. */\n\tstate?: IssueStateFilter;\n\t/** Labels the issue must carry — AND-ed, matching GitHub's own `label:` semantics. */\n\tlabels?: string[];\n\tmilestone?: string;\n\t/** ISO date (`YYYY-MM-DD`). The most effective narrowing criterion by far on a large scope. */\n\tupdatedAfter?: string;\n\t/** ISO date (`YYYY-MM-DD`). */\n\tcreatedAfter?: string;\n\t/** Issues with no linked pull request. */\n\twithoutLinkedPullRequest?: boolean;\n\t/** Includes issues in archived repositories, which are excluded by default. */\n\tincludeArchived?: boolean;\n\t/**\n\t * How to order the results. Omitted means `updated:desc`, which is what this search has always served.\n\t *\n\t * Validated like every other criterion — all-or-nothing against {@link IssueSearchCapabilities.sorts}: a key\n\t * the provider can't express server-side refuses the WHOLE read rather than falling back to the default.\n\t * Serving another order is not a smaller error than serving a wider result: combined with the provider's\n\t * result ceiling it returns a different subset than was asked for, and the paging that comes with it describes\n\t * that other subset.\n\t *\n\t * Do not change it mid-pagination. A cursor carries the sort it was produced under, and threading it under a\n\t * different key is refused rather than serving a sequence with gaps and repeats: drop the cursor instead.\n\t */\n\tsort?: IssueSorting;\n}\n\n/**\n * Which {@link IssueSearchCriteria} fields a provider's filtered issue search can express server-side.\n *\n * An empty `relationships` with every flag false means the provider has NO filtered issue search — the read is\n * refused outright, so a consumer should offer neither the surface nor its chips.\n */\nexport interface IssueSearchCapabilities {\n\t/** Relationships the search can constrain on. Empty means the search itself is unsupported. */\n\trelationships: IssueSearchRelationship[];\n\ttext: boolean;\n\tlabels: boolean;\n\tmilestone: boolean;\n\tupdatedAfter: boolean;\n\tcreatedAfter: boolean;\n\twithoutLinkedPullRequest: boolean;\n\t/** Whether {@link IssueSearchCriteria.state} can select anything other than the provider's default (open). */\n\tstates: boolean;\n\t/**\n\t * Sort keys the search can express IN SERVER. Always contains at least `updated:desc` — the historical default\n\t * — when the search exists at all, so it is never empty for a usable surface; a provider without a filtered\n\t * search reports an empty `relationships`, which is already the signal that there is no surface to order.\n\t */\n\tsorts: IssueSorting[];\n}\n\n/**\n * The read that produced an issue row, as a key for `getIssueFieldPresence` (`@gitlens/integrations`). It names a\n * READ, not a field set: the same tag can carry different fields on different providers.\n */\nexport type IssueProjection =\n\t/** A single-item read. */\n\t| 'point'\n\t/** The filtered search. */\n\t| 'search'\n\t/** The account-wide list, and the trackers' \"my issues\". */\n\t| 'account'\n\t/** A repository-scoped list. */\n\t| 'repos'\n\t/** A tracker project's issues (`listIssueTrackerIssuesPage`, `getIssuesForProject`). */\n\t| 'project'\n\t/** The batch read. */\n\t| 'batch';\n\nexport interface IssueShape extends IssueOrPullRequest {\n\t/** `undefined` when the provider can't resolve the author, e.g. a deleted GitHub account */\n\tauthor: IssueMember | undefined;\n\tassignees: IssueMember[];\n\t/** The provider's own workflow state, when it exposes one beyond the normalized open/closed state. */\n\tproviderState?: IssueProviderState;\n\trepository?: IssueRepository;\n\tlabels?: IssueLabel[];\n\tbody?: string;\n\t/**\n\t * The syntax used by `body`. When omitted, consumers should treat `body` as Markdown — except that Azure DevOps\n\t * work items and Bitbucket Cloud issues carry HTML with no `bodyFormat` set.\n\t */\n\tbodyFormat?: IssueBodyFormat;\n\tproject?: IssueProject;\n\tissueType?: string;\n\t/** An issue can belong to several Jira sprints; Azure reports one iteration. */\n\titerations?: IssueIteration[];\n\t/** The read that produced this row. Absent means unknown: a legacy row, or a provider or read not yet tagged. */\n\treadonly projection?: IssueProjection;\n}\n\n@loggable(i => i.id)\nexport class Issue implements IssueShape {\n\treadonly type = 'issue';\n\n\tconstructor(\n\t\tpublic readonly provider: ProviderReference,\n\t\tpublic readonly id: string,\n\t\tpublic readonly nodeId: string | undefined,\n\t\tpublic readonly title: string,\n\t\tpublic readonly url: string,\n\t\tpublic readonly createdDate: Date,\n\t\tpublic readonly updatedDate: Date,\n\t\tpublic readonly closed: boolean,\n\t\tpublic readonly state: IssueOrPullRequestState,\n\t\tpublic readonly author: IssueMember | undefined,\n\t\tpublic readonly assignees: IssueMember[],\n\t\tpublic readonly repository?: IssueRepository,\n\t\tpublic readonly closedDate?: Date,\n\t\tpublic readonly labels?: IssueLabel[],\n\t\tpublic readonly commentsCount?: number,\n\t\tpublic readonly thumbsUpCount?: number,\n\t\tpublic readonly body?: string,\n\t\tpublic readonly project?: IssueProject,\n\t\tpublic readonly number?: string,\n\t\tpublic readonly issueType?: string,\n\t\tpublic readonly providerState?: IssueProviderState,\n\t\tpublic readonly bodyFormat?: IssueBodyFormat,\n\t\tpublic readonly iterations?: IssueIteration[],\n\t\tpublic readonly projection?: IssueProjection,\n\t) {}\n\n\tstatic is(issue: unknown): issue is Issue {\n\t\treturn issue instanceof Issue;\n\t}\n}\n\nexport type IssueBodyFormat = 'markdown' | 'jira-wiki';\n\nexport const enum RepositoryAccessLevel {\n\tAdmin = 100,\n\tMaintain = 40,\n\tWrite = 30,\n\tTriage = 20,\n\tRead = 10,\n\tNone = 0,\n}\n\nexport interface IssueLabel {\n\tcolor?: string;\n\tname: string;\n}\n\n/**\n * Sprint metadata is optional because some providers only report an iteration path. An absent `isActive`\n * means unknown, not inactive, so consumers must not use it to exclude those iterations by default.\n */\nexport interface IssueIteration {\n\t/**\n\t * A sprint id on Jira, the verbatim iteration path on Azure — so it is only meaningful within the provider's\n\t * project, never across providers. Unique at read time but NOT durable: Azure rewrites the path when an\n\t * iteration node is renamed or re-parented, so don't persist it as a long-lived id.\n\t */\n\tid: string;\n\tname: string;\n\tisActive?: boolean;\n\tstartDate?: Date;\n\tendDate?: Date;\n}\n\nexport interface IssueMember {\n\tid: string;\n\t/**\n\t * Absent when the provider exposes no display name for the member. Optional on purpose: a fallback string\n\t * invented here (`'unknown'`, `''`) can't be told apart from a real name downstream, so it can't be undone by a\n\t * consumer that needs to render something else — or nothing at all, as when the member feeds an AI prompt.\n\t * Each consumer picks its own presentation.\n\t */\n\tname?: string;\n\t/** The provider's handle for this person, when it has one — GitHub's login, Azure's `uniqueName` (a UPN,\n\t * so an email), Bitbucket's mutable `nickname`. Display/labelling only: it is neither guaranteed present\n\t * (GitLab's native mapper has none) nor a stable identity, so never key a match off it. */\n\tusername?: string;\n\tavatarUrl?: string;\n\turl?: string;\n}\n\nexport type IssueProviderState = {\n\tid?: string;\n\tname: string;\n\tcolor?: string;\n\tcategory?: 'TO_DO' | 'IN_PROGRESS' | 'DONE';\n};\n\nexport interface IssueProject {\n\tid: string;\n\tname: string;\n\tresourceId: string;\n\tresourceName: string;\n}\n\nexport interface IssueRepository {\n\towner: string;\n\trepo: string;\n\taccessLevel?: RepositoryAccessLevel;\n\turl?: string;\n\tid?: string;\n}\n\nexport type IssueRepositoryIdentityDescriptor = RequireSomeWithProps<\n\tRequireSome<RepositoryIdentityDescriptor<string>, 'provider'>,\n\t'provider',\n\t'id' | 'domain' | 'repoDomain' | 'repoName'\n> &\n\tRequireSomeWithProps<RequireSome<RepositoryIdentityDescriptor<string>, 'remote'>, 'remote', 'domain'>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+EA,MAAa,mBAAiC;AA6HvC,IAAM,QAAA,SAAN,MAAM,MAA4B;CAIvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CA1BjB,OAAgB;CAEhB,YACC,UACA,IACA,QACA,OACA,KACA,aACA,aACA,QACA,OACA,QACA,WACA,YACA,YACA,QACA,eACA,eACA,MACA,SACA,QACA,WACA,eACA,YACA,YACA,YACC;EAxBe,KAAA,WAAA;EACA,KAAA,KAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,MAAA;EACA,KAAA,cAAA;EACA,KAAA,cAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,SAAA;EACA,KAAA,gBAAA;EACA,KAAA,gBAAA;EACA,KAAA,OAAA;EACA,KAAA,UAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,gBAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;CACd;CAEH,OAAO,GAAG,OAAgC;EACzC,OAAO,iBAAA;CACR;AACD;AAlCC,QAAA,SAAA,WAAA,CAAA,UAAS,MAAK,EAAE,EAAE,CAAA,GAAA,KAAA;AAsCnB,IAAkB,wBAAX,yBAAA,uBAAA;CACN,sBAAA,sBAAA,WAAA,OAAA;CACA,sBAAA,sBAAA,cAAA,MAAA;CACA,sBAAA,sBAAA,WAAA,MAAA;CACA,sBAAA,sBAAA,YAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,KAAA;;AACD,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"issue.js","names":[],"sources":["../../../../git/src/models/issue.ts"],"sourcesContent":["import { loggable } from '@gitlens/utils/decorators/log.js';\nimport type { RequireSome, RequireSomeWithProps } from '@gitlens/utils/types.js';\nimport type { IssueOrPullRequest, IssueOrPullRequestState } from './issueOrPullRequest.js';\nimport type { ProviderReference } from './remoteProvider.js';\nimport type { RepositoryIdentityDescriptor } from './repositoryIdentities.js';\n\n/** Selects which issue states a read should include. `all` covers open + closed. */\nexport type IssueStateFilter = 'open' | 'closed' | 'all';\n\n/**\n * One relationship a filtered issue search can constrain on.\n *\n * The last two are USER-INDEPENDENT — they describe the issue, not the caller — and neither is a SCOPE: either\n * one alone matches every such issue on the host, so a search using one still needs a repository/org scope.\n */\nexport type IssueSearchRelationship =\n\t/** Authored by the current user. */\n\t| 'authored'\n\t/** Assigned to the current user. */\n\t| 'assigned'\n\t/** Mentions the current user. */\n\t| 'mentioned'\n\t/** Assigned to ANYONE. Excludes unassigned issues — see {@link IssueSearchCriteria.relationships}. */\n\t| 'any-assignee'\n\t/** Assigned to nobody. The complement of `any-assignee`, not a broadening of it. */\n\t| 'unassigned';\n\n/**\n * A field an issue read can be ordered by, provider-neutral. No provider expresses all of them: each read\n * validates the requested key against the capability its provider declares and refuses one it can't express\n * server-side, rather than serving a differently-ordered list under the name of the one that was asked for.\n *\n * `closed` and `resolved` are deliberately SEPARATE, not two names for the same date. Azure DevOps tracks both\n * and they differ (an issue can be closed without being resolved and resolved without being closed), and Jira\n * has no close date at all — it models the equivalent as `resolutiondate`. Collapsing them would force one of\n * those two providers to lie about which date it ordered by.\n */\nexport type IssueSortField =\n\t/** Creation date. */\n\t| 'created'\n\t/** Last activity. */\n\t| 'updated'\n\t/** Close date. Only where the provider orders by it server-side — notably NOT GitHub. */\n\t| 'closed'\n\t/** Resolution date (Jira `resolutiondate`, Azure `ResolvedDate`). Distinct from `closed`. */\n\t| 'resolved'\n\t/** Number of comments. */\n\t| 'comments'\n\t/** Reactions/upvotes. */\n\t| 'reactions'\n\t/** The provider's own priority field. */\n\t| 'priority'\n\t/** Due date. */\n\t| 'dueDate'\n\t/** Alphabetical by title. */\n\t| 'title';\n\n/**\n * How an issue read is ordered, as `field:direction` — the same shape `BranchSorting`/`TagSorting` already use,\n * so it is one serializable string a consumer can persist, compare, or bind straight to a setting or a dropdown.\n */\nexport type IssueSorting = `${IssueSortField}:asc` | `${IssueSortField}:desc`;\n\n/**\n * The order every issue read that HAS a default applies when the caller asks for none: most recently updated\n * first, which is what those reads served before ordering was an option.\n *\n * One definition rather than one per layer, because it is a promise made in several places at once — the criteria\n * model documents it, the GitHub query emits it, and the result-ceiling warning quotes it — and three copies would\n * be free to disagree about what \"the default\" is.\n *\n * Note it is not a default every read has, and the two layers differ. The API client's account-wide \"my issues\"\n * search (`GitHubApi.searchMyIssues`) never requested an order, so a direct caller omitting `sort` still gets\n * GitHub's relevance order — the default is opt-in there, to keep that read's already-shipped results unchanged.\n * The FACADE does apply it: GitHub declares `updated:desc` among its account-wide keys, so\n * `readAccountWideIssuesPage` resolves the omission to this default and forwards it, and that read's emitted query\n * gained a `sort:updated` qualifier it did not have before. A read whose surface cannot express even this key is\n * the only one the facade leaves in the provider's own order.\n */\nexport const defaultIssueSort: IssueSorting = 'updated:desc';\n\n/**\n * What a filtered issue search narrows on: a provider-neutral criteria set, translated to each provider's own\n * query language by its integration.\n *\n * Structured rather than a provider query string so a consumer can render filter chips and hide the ones a\n * provider can't express, and so the same criteria mean the same thing on a provider whose query language looks\n * nothing like GitHub's search syntax. Every field is validated against the provider's declared capability\n * BEFORE the read runs, all-or-nothing: a criterion the provider can't express server-side refuses the whole\n * read rather than serving a list that was never narrowed. Client-side narrowing is not an option — the dropped\n * items still counted toward the page and cursor the provider produced, so a post-filter would leave the items\n * describing a different result set than the paging that came with them.\n */\nexport interface IssueSearchCriteria {\n\t/**\n\t * Relationships to constrain on, OR-ed together (each becomes its own provider query, unioned and deduped).\n\t * Omitted means NO relationship constraint at all — every issue in scope, assigned or not — which requires a\n\t * repository/org scope.\n\t *\n\t * `any-assignee` and `unassigned` partition the scope between them and are mutually exclusive; passing both is\n\t * refused rather than silently dropping one. Note that \"all visible issues\" is the OMITTED case, NOT\n\t * `any-assignee`, which excludes unassigned issues.\n\t */\n\trelationships?: IssueSearchRelationship[];\n\t/**\n\t * Free text, matched by the provider's own relevance rules — NOT a substring match, and not a way to smuggle\n\t * qualifiers: a token that would read as one is dropped, as are quotes and control characters, so text can\n\t * never re-scope the search. The structured criteria are the qualifier channel.\n\t */\n\ttext?: string;\n\t/** Issue states to include. Omitted reads open issues only. */\n\tstate?: IssueStateFilter;\n\t/** Labels the issue must carry — AND-ed, matching GitHub's own `label:` semantics. */\n\tlabels?: string[];\n\tmilestone?: string;\n\t/** ISO date (`YYYY-MM-DD`). The most effective narrowing criterion by far on a large scope. */\n\tupdatedAfter?: string;\n\t/** ISO date (`YYYY-MM-DD`). */\n\tcreatedAfter?: string;\n\t/** Issues with no linked pull request. */\n\twithoutLinkedPullRequest?: boolean;\n\t/** Includes issues in archived repositories, which are excluded by default. */\n\tincludeArchived?: boolean;\n\t/**\n\t * How to order the results. Omitted means `updated:desc`, which is what this search has always served.\n\t *\n\t * Validated like every other criterion — all-or-nothing against {@link IssueSearchCapabilities.sorts}: a key\n\t * the provider can't express server-side refuses the WHOLE read rather than falling back to the default.\n\t * Serving another order is not a smaller error than serving a wider result: combined with the provider's\n\t * result ceiling it returns a different subset than was asked for, and the paging that comes with it describes\n\t * that other subset.\n\t *\n\t * Do not change it mid-pagination. A cursor carries the sort it was produced under, and threading it under a\n\t * different key is refused rather than serving a sequence with gaps and repeats: drop the cursor instead.\n\t */\n\tsort?: IssueSorting;\n}\n\n/**\n * Which {@link IssueSearchCriteria} fields a provider's filtered issue search can express server-side.\n *\n * An empty `relationships` with every flag false means the provider has NO filtered issue search — the read is\n * refused outright, so a consumer should offer neither the surface nor its chips.\n */\nexport interface IssueSearchCapabilities {\n\t/** Relationships the search can constrain on. Empty means the search itself is unsupported. */\n\trelationships: IssueSearchRelationship[];\n\ttext: boolean;\n\tlabels: boolean;\n\tmilestone: boolean;\n\tupdatedAfter: boolean;\n\tcreatedAfter: boolean;\n\twithoutLinkedPullRequest: boolean;\n\t/** Whether {@link IssueSearchCriteria.state} can select anything other than the provider's default (open). */\n\tstates: boolean;\n\t/**\n\t * Sort keys the search can express IN SERVER. Always contains at least `updated:desc` — the historical default\n\t * — when the search exists at all, so it is never empty for a usable surface; a provider without a filtered\n\t * search reports an empty `relationships`, which is already the signal that there is no surface to order.\n\t */\n\tsorts: IssueSorting[];\n}\n\n/**\n * The read that produced an issue row, as a key for `getIssueFieldPresence` (`@gitlens/integrations`). It names a\n * READ, not a field set: the same tag can carry different fields on different providers.\n */\nexport type IssueProjection =\n\t/** A single-item read. */\n\t| 'point'\n\t/** The filtered search. */\n\t| 'search'\n\t/** The account-wide list, and the trackers' \"my issues\". */\n\t| 'account'\n\t/** A repository-scoped list. */\n\t| 'repos'\n\t/** A tracker project's issues (`listIssueTrackerIssuesPage`, `getIssuesForProject`). */\n\t| 'project'\n\t/** The batch read. */\n\t| 'batch';\n\nexport interface IssueShape extends IssueOrPullRequest {\n\t/** `undefined` when the provider can't resolve the author, e.g. a deleted GitHub account */\n\tauthor: IssueMember | undefined;\n\tassignees: IssueMember[];\n\t/** The provider's own workflow state, when it exposes one beyond the normalized open/closed state. */\n\tproviderState?: IssueProviderState;\n\trepository?: IssueRepository;\n\tlabels?: IssueLabel[];\n\tbody?: string;\n\t/**\n\t * The syntax used by `body`. When omitted, consumers should treat `body` as Markdown — except that Azure DevOps\n\t * work items and Bitbucket Cloud issues carry HTML with no `bodyFormat` set.\n\t */\n\tbodyFormat?: IssueBodyFormat;\n\tproject?: IssueProject;\n\tissueType?: string;\n\t/** An issue can belong to several Jira sprints; Azure reports one iteration. */\n\titerations?: IssueIteration[];\n\t/** The read that produced this row. Absent means unknown: a legacy row, or a provider or read not yet tagged. */\n\treadonly projection?: IssueProjection;\n}\n\n@loggable(i => i.id)\nexport class Issue implements IssueShape {\n\treadonly type = 'issue';\n\n\tconstructor(\n\t\tpublic readonly provider: ProviderReference,\n\t\tpublic readonly id: string,\n\t\tpublic readonly nodeId: string | undefined,\n\t\tpublic readonly title: string,\n\t\tpublic readonly url: string,\n\t\tpublic readonly createdDate: Date,\n\t\tpublic readonly updatedDate: Date,\n\t\tpublic readonly closed: boolean,\n\t\tpublic readonly state: IssueOrPullRequestState,\n\t\tpublic readonly author: IssueMember | undefined,\n\t\tpublic readonly assignees: IssueMember[],\n\t\tpublic readonly repository?: IssueRepository,\n\t\tpublic readonly closedDate?: Date,\n\t\tpublic readonly labels?: IssueLabel[],\n\t\tpublic readonly commentsCount?: number,\n\t\tpublic readonly thumbsUpCount?: number,\n\t\tpublic readonly body?: string,\n\t\tpublic readonly project?: IssueProject,\n\t\tpublic readonly number?: string,\n\t\tpublic readonly issueType?: string,\n\t\tpublic readonly providerState?: IssueProviderState,\n\t\tpublic readonly bodyFormat?: IssueBodyFormat,\n\t\tpublic readonly iterations?: IssueIteration[],\n\t\tpublic readonly projection?: IssueProjection,\n\t) {}\n\n\tstatic is(issue: unknown): issue is Issue {\n\t\treturn issue instanceof Issue;\n\t}\n}\n\nexport type IssueBodyFormat = 'markdown' | 'jira-wiki';\n\nexport const enum RepositoryAccessLevel {\n\tAdmin = 100,\n\tMaintain = 40,\n\tWrite = 30,\n\tTriage = 20,\n\tRead = 10,\n\tNone = 0,\n}\n\nexport interface IssueLabel {\n\tcolor?: string;\n\tname: string;\n}\n\n/**\n * Sprint metadata is optional because some providers only report an iteration path. An absent `isActive`\n * means unknown, not inactive, so consumers must not use it to exclude those iterations by default.\n */\nexport interface IssueIteration {\n\t/**\n\t * A sprint id on Jira, the verbatim iteration path on Azure — so it is only meaningful within the provider's\n\t * project, never across providers. Unique at read time but NOT durable: Azure rewrites the path when an\n\t * iteration node is renamed or re-parented, so don't persist it as a long-lived id.\n\t */\n\tid: string;\n\tname: string;\n\tisActive?: boolean;\n\tstartDate?: Date;\n\tendDate?: Date;\n}\n\nexport interface IssueMember {\n\tid: string;\n\t/**\n\t * Absent when the provider exposes no display name for the member. Optional on purpose: a fallback string\n\t * invented here (`'unknown'`, `''`) can't be told apart from a real name downstream, so it can't be undone by a\n\t * consumer that needs to render something else — or nothing at all, as when the member feeds an AI prompt.\n\t * Each consumer picks its own presentation.\n\t */\n\tname?: string;\n\t/** The provider's handle for this person, when it has one — GitHub's login, Azure's `uniqueName` (a UPN,\n\t * so an email), Bitbucket's mutable `nickname`. Display/labelling only: it is neither guaranteed present\n\t * (GitLab's native mapper has none) nor a stable identity, so never key a match off it. */\n\tusername?: string;\n\tavatarUrl?: string;\n\turl?: string;\n}\n\nexport type IssueProviderState = {\n\tid?: string;\n\tname: string;\n\tcolor?: string;\n\t/** The provider's workflow category. `CANCELED` is abandoned work (Linear's canceled and duplicate states, Azure's\n\t * `Removed` category): closed like `DONE`, kept apart so a consumer can tell the two outcomes apart. */\n\tcategory?: 'TO_DO' | 'IN_PROGRESS' | 'DONE' | 'CANCELED';\n};\n\nexport interface IssueProject {\n\tid: string;\n\tname: string;\n\tresourceId: string;\n\tresourceName: string;\n}\n\nexport interface IssueRepository {\n\towner: string;\n\trepo: string;\n\taccessLevel?: RepositoryAccessLevel;\n\turl?: string;\n\tid?: string;\n}\n\nexport type IssueRepositoryIdentityDescriptor = RequireSomeWithProps<\n\tRequireSome<RepositoryIdentityDescriptor<string>, 'provider'>,\n\t'provider',\n\t'id' | 'domain' | 'repoDomain' | 'repoName'\n> &\n\tRequireSomeWithProps<RequireSome<RepositoryIdentityDescriptor<string>, 'remote'>, 'remote', 'domain'>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+EA,MAAa,mBAAiC;AA6HvC,IAAM,QAAA,SAAN,MAAM,MAA4B;CAIvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CA1BjB,OAAgB;CAEhB,YACC,UACA,IACA,QACA,OACA,KACA,aACA,aACA,QACA,OACA,QACA,WACA,YACA,YACA,QACA,eACA,eACA,MACA,SACA,QACA,WACA,eACA,YACA,YACA,YACC;EAxBe,KAAA,WAAA;EACA,KAAA,KAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,MAAA;EACA,KAAA,cAAA;EACA,KAAA,cAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,SAAA;EACA,KAAA,gBAAA;EACA,KAAA,gBAAA;EACA,KAAA,OAAA;EACA,KAAA,UAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,gBAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;CACd;CAEH,OAAO,GAAG,OAAgC;EACzC,OAAO,iBAAA;CACR;AACD;AAlCC,QAAA,SAAA,WAAA,CAAA,UAAS,MAAK,EAAE,EAAE,CAAA,GAAA,KAAA;AAsCnB,IAAkB,wBAAX,yBAAA,uBAAA;CACN,sBAAA,sBAAA,WAAA,OAAA;CACA,sBAAA,sBAAA,cAAA,MAAA;CACA,sBAAA,sBAAA,WAAA,MAAA;CACA,sBAAA,sBAAA,YAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,KAAA;;AACD,EAAA,CAAA,CAAA"}
@@ -1,9 +1,9 @@
1
1
  import { loggable } from "../../utils/decorators/log.js";
2
2
  import { memoize } from "../../utils/decorators/memoize.js";
3
+ import { formatDetachedHeadName, isDetachedHead } from "../utils/branch.utils.js";
3
4
  import __decorate from "../../_virtual/@oxc-project+runtime/helpers/esm/decorate.js";
4
5
  import { serializable } from "../../utils/decorators/serializable.js";
5
6
  import { GitFileConflictStatus, GitFileIndexStatus, GitFileWorkingTreeStatus } from "./fileStatus.js";
6
- import { formatDetachedHeadName, isDetachedHead } from "../utils/branch.utils.js";
7
7
  import { getFormattedDiffStatus, getUpstreamStatus } from "../utils/status.utils.js";
8
8
  //#region ../git/src/models/status.ts
9
9
  var _GitStatus;
@@ -24,7 +24,10 @@ export declare class GitWorktree {
24
24
  readonly name: string;
25
25
  } | undefined);
26
26
  get date(): Date | undefined;
27
- /** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */
27
+ /**
28
+ * @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date. Not memoized: the stamps
29
+ * change in place (see `BranchMetadata`)
30
+ */
28
31
  get effectiveDate(): Date | undefined;
29
32
  /** Timestamp when the worktree branch was last accessed or modified */
30
33
  get lastAccessedDate(): Date | undefined;
@@ -33,7 +33,10 @@ let GitWorktree = _GitWorktree = class GitWorktree {
33
33
  get date() {
34
34
  return this.branch?.date;
35
35
  }
36
- /** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */
36
+ /**
37
+ * @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date. Not memoized: the stamps
38
+ * change in place (see `BranchMetadata`)
39
+ */
37
40
  get effectiveDate() {
38
41
  let maxTime;
39
42
  const accessed = this.lastAccessedDate?.getTime();
@@ -95,7 +98,6 @@ let GitWorktree = _GitWorktree = class GitWorktree {
95
98
  return getRepositoryService(worktree.path)?.status.hasWorkingChanges(options);
96
99
  }
97
100
  };
98
- __decorate([memoize()], GitWorktree.prototype, "effectiveDate", null);
99
101
  __decorate([memoize()], GitWorktree.prototype, "friendlyPath", null);
100
102
  __decorate([memoize()], GitWorktree.prototype, "name", null);
101
103
  GitWorktree = _GitWorktree = __decorate([loggable((i) => i.uri.toString()), serializable], GitWorktree);
@@ -1 +1 @@
1
- {"version":3,"file":"worktree.js","names":[],"sources":["../../../../git/src/models/worktree.ts"],"sourcesContent":["import { formatDate, fromNow } from '@gitlens/utils/date.js';\nimport { loggable } from '@gitlens/utils/decorators/log.js';\nimport { memoize } from '@gitlens/utils/decorators/memoize.js';\nimport { serializable } from '@gitlens/utils/decorators/serializable.js';\nimport { basename, normalizePath, relative } from '@gitlens/utils/path.js';\nimport type { Shape } from '@gitlens/utils/types.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { getRepositoryService } from '../repositoryService.js';\nimport type { GitCommandPriority } from '../run.types.js';\nimport { getRepositoryOrWorktreePath } from '../utils/repository.utils.js';\nimport { shortenRevision } from '../utils/revision.utils.js';\nimport type { GitBranch } from './branch.js';\nimport type { GitStatus } from './status.js';\n\nexport type GitWorktreeShape = Shape<GitWorktree>;\n\nexport type WorkspaceFolderResolver = (uri: Uri) => GitWorktree['workspaceFolder'] | undefined;\n\n@loggable(i => i.uri.toString())\n@serializable\nexport class GitWorktree {\n\tconstructor(\n\t\tpublic readonly isDefault: boolean,\n\t\tpublic readonly type: 'bare' | 'branch' | 'detached',\n\t\tpublic readonly repoPath: string,\n\t\tpublic readonly uri: Uri,\n\t\tpublic readonly locked: boolean | string,\n\t\tpublic readonly prunable: boolean | string,\n\t\tpublic readonly sha?: string,\n\t\tpublic readonly branch?: GitBranch,\n\t\tpublic readonly workspaceFolder?: { readonly uri: Uri; readonly name: string },\n\t) {}\n\n\tget date(): Date | undefined {\n\t\treturn this.branch?.date;\n\t}\n\n\t/** @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date */\n\t@memoize()\n\tget effectiveDate(): Date | undefined {\n\t\tlet maxTime: number | undefined;\n\n\t\tconst accessed = this.lastAccessedDate?.getTime();\n\t\tif (accessed != null && (maxTime == null || accessed > maxTime)) {\n\t\t\tmaxTime = accessed;\n\t\t}\n\n\t\tconst modified = this.lastModifiedDate?.getTime();\n\t\tif (modified != null && (maxTime == null || modified > maxTime)) {\n\t\t\tmaxTime = modified;\n\t\t}\n\n\t\tconst date = this.branch?.date?.getTime();\n\t\tif (date != null && (maxTime == null || date > maxTime)) {\n\t\t\tmaxTime = date;\n\t\t}\n\n\t\treturn maxTime != null ? new Date(maxTime) : undefined;\n\t}\n\n\t/** Timestamp when the worktree branch was last accessed or modified */\n\tget lastAccessedDate(): Date | undefined {\n\t\treturn this.branch?.lastAccessedDate;\n\t}\n\n\t/** Timestamp when the worktree branch was last modified (working changes / index) */\n\tget lastModifiedDate(): Date | undefined {\n\t\treturn this.branch?.lastModifiedDate;\n\t}\n\n\t@memoize()\n\tget friendlyPath(): string {\n\t\tif (this.workspaceFolder != null) {\n\t\t\tconst relativePath = normalizePath(relative(this.workspaceFolder.uri.fsPath, this.uri.fsPath));\n\t\t\treturn relativePath || this.workspaceFolder.name;\n\t\t}\n\n\t\tconst relativePath = normalizePath(relative(this.repoPath, this.uri.fsPath));\n\t\treturn relativePath || normalizePath(this.uri.fsPath);\n\t}\n\n\t@memoize()\n\tget name(): string {\n\t\tswitch (this.type) {\n\t\t\tcase 'bare':\n\t\t\t\treturn '(bare)';\n\t\t\tcase 'detached':\n\t\t\t\treturn `${basename(this.path)} (${shortenRevision(this.sha)})`;\n\t\t\tdefault:\n\t\t\t\treturn this.branch?.name || this.friendlyPath;\n\t\t}\n\t}\n\n\tget opened(): boolean {\n\t\treturn this.workspaceFolder?.uri.toString() === this.uri.toString();\n\t}\n\n\tget path(): string {\n\t\treturn getRepositoryOrWorktreePath(this.uri);\n\t}\n\n\t/** Creates a copy of this worktree with a different repoPath and updated branch — ONLY used for worktree-aware caching */\n\twithRepoPath(repoPath: string): GitWorktree {\n\t\tif (repoPath === this.repoPath) return this;\n\n\t\treturn new GitWorktree(\n\t\t\tthis.isDefault,\n\t\t\tthis.type,\n\t\t\trepoPath,\n\t\t\tthis.uri,\n\t\t\tthis.locked,\n\t\t\tthis.prunable,\n\t\t\tthis.sha,\n\t\t\tthis.branch?.withRepoPath(repoPath, true),\n\t\t\tthis.workspaceFolder,\n\t\t);\n\t}\n\n\tstatic is(worktree: unknown): worktree is GitWorktree {\n\t\treturn worktree instanceof GitWorktree;\n\t}\n\n\tstatic formatDate(worktree: GitWorktreeShape, format?: string | null): string {\n\t\treturn worktree.date != null ? formatDate(worktree.date, format ?? 'MMMM Do, YYYY h:mma') : '';\n\t}\n\n\tstatic formatDateFromNow(worktree: GitWorktreeShape): string {\n\t\treturn worktree.date != null ? fromNow(worktree.date) : '';\n\t}\n\n\tstatic formatDateWithStyle(\n\t\tworktree: GitWorktreeShape,\n\t\tformatting: { dateStyle: string; dateFormat: string | null },\n\t): string {\n\t\treturn formatting.dateStyle === 'absolute'\n\t\t\t? GitWorktree.formatDate(worktree, formatting.dateFormat)\n\t\t\t: GitWorktree.formatDateFromNow(worktree);\n\t}\n\n\tstatic async getStatus(\n\t\tworktree: GitWorktree,\n\t\toptions?: { priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tif (worktree.type === 'bare') return undefined;\n\n\t\tconst repo = getRepositoryService(worktree.path);\n\t\treturn repo?.status.getStatus(options, cancellation);\n\t}\n\n\tstatic async hasWorkingChanges(\n\t\tworktree: GitWorktree,\n\t\toptions?: { staged?: boolean; unstaged?: boolean; untracked?: boolean },\n\t): Promise<boolean | undefined> {\n\t\tif (worktree.type === 'bare') return undefined;\n\n\t\tconst repo = getRepositoryService(worktree.path);\n\t\treturn repo?.status.hasWorkingChanges(options);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"worktree.js","names":[],"sources":["../../../../git/src/models/worktree.ts"],"sourcesContent":["import { formatDate, fromNow } from '@gitlens/utils/date.js';\nimport { loggable } from '@gitlens/utils/decorators/log.js';\nimport { memoize } from '@gitlens/utils/decorators/memoize.js';\nimport { serializable } from '@gitlens/utils/decorators/serializable.js';\nimport { basename, normalizePath, relative } from '@gitlens/utils/path.js';\nimport type { Shape } from '@gitlens/utils/types.js';\nimport type { Uri } from '@gitlens/utils/uri.js';\nimport { getRepositoryService } from '../repositoryService.js';\nimport type { GitCommandPriority } from '../run.types.js';\nimport { getRepositoryOrWorktreePath } from '../utils/repository.utils.js';\nimport { shortenRevision } from '../utils/revision.utils.js';\nimport type { GitBranch } from './branch.js';\nimport type { GitStatus } from './status.js';\n\nexport type GitWorktreeShape = Shape<GitWorktree>;\n\nexport type WorkspaceFolderResolver = (uri: Uri) => GitWorktree['workspaceFolder'] | undefined;\n\n@loggable(i => i.uri.toString())\n@serializable\nexport class GitWorktree {\n\tconstructor(\n\t\tpublic readonly isDefault: boolean,\n\t\tpublic readonly type: 'bare' | 'branch' | 'detached',\n\t\tpublic readonly repoPath: string,\n\t\tpublic readonly uri: Uri,\n\t\tpublic readonly locked: boolean | string,\n\t\tpublic readonly prunable: boolean | string,\n\t\tpublic readonly sha?: string,\n\t\tpublic readonly branch?: GitBranch,\n\t\tpublic readonly workspaceFolder?: { readonly uri: Uri; readonly name: string },\n\t) {}\n\n\tget date(): Date | undefined {\n\t\treturn this.branch?.date;\n\t}\n\n\t/**\n\t * @returns The most recent date among lastModifiedDate, lastAccessedDate, and branch.date. Not memoized: the stamps\n\t * change in place (see `BranchMetadata`)\n\t */\n\tget effectiveDate(): Date | undefined {\n\t\tlet maxTime: number | undefined;\n\n\t\tconst accessed = this.lastAccessedDate?.getTime();\n\t\tif (accessed != null && (maxTime == null || accessed > maxTime)) {\n\t\t\tmaxTime = accessed;\n\t\t}\n\n\t\tconst modified = this.lastModifiedDate?.getTime();\n\t\tif (modified != null && (maxTime == null || modified > maxTime)) {\n\t\t\tmaxTime = modified;\n\t\t}\n\n\t\tconst date = this.branch?.date?.getTime();\n\t\tif (date != null && (maxTime == null || date > maxTime)) {\n\t\t\tmaxTime = date;\n\t\t}\n\n\t\treturn maxTime != null ? new Date(maxTime) : undefined;\n\t}\n\n\t/** Timestamp when the worktree branch was last accessed or modified */\n\tget lastAccessedDate(): Date | undefined {\n\t\treturn this.branch?.lastAccessedDate;\n\t}\n\n\t/** Timestamp when the worktree branch was last modified (working changes / index) */\n\tget lastModifiedDate(): Date | undefined {\n\t\treturn this.branch?.lastModifiedDate;\n\t}\n\n\t@memoize()\n\tget friendlyPath(): string {\n\t\tif (this.workspaceFolder != null) {\n\t\t\tconst relativePath = normalizePath(relative(this.workspaceFolder.uri.fsPath, this.uri.fsPath));\n\t\t\treturn relativePath || this.workspaceFolder.name;\n\t\t}\n\n\t\tconst relativePath = normalizePath(relative(this.repoPath, this.uri.fsPath));\n\t\treturn relativePath || normalizePath(this.uri.fsPath);\n\t}\n\n\t@memoize()\n\tget name(): string {\n\t\tswitch (this.type) {\n\t\t\tcase 'bare':\n\t\t\t\treturn '(bare)';\n\t\t\tcase 'detached':\n\t\t\t\treturn `${basename(this.path)} (${shortenRevision(this.sha)})`;\n\t\t\tdefault:\n\t\t\t\treturn this.branch?.name || this.friendlyPath;\n\t\t}\n\t}\n\n\tget opened(): boolean {\n\t\treturn this.workspaceFolder?.uri.toString() === this.uri.toString();\n\t}\n\n\tget path(): string {\n\t\treturn getRepositoryOrWorktreePath(this.uri);\n\t}\n\n\t/** Creates a copy of this worktree with a different repoPath and updated branch — ONLY used for worktree-aware caching */\n\twithRepoPath(repoPath: string): GitWorktree {\n\t\tif (repoPath === this.repoPath) return this;\n\n\t\treturn new GitWorktree(\n\t\t\tthis.isDefault,\n\t\t\tthis.type,\n\t\t\trepoPath,\n\t\t\tthis.uri,\n\t\t\tthis.locked,\n\t\t\tthis.prunable,\n\t\t\tthis.sha,\n\t\t\tthis.branch?.withRepoPath(repoPath, true),\n\t\t\tthis.workspaceFolder,\n\t\t);\n\t}\n\n\tstatic is(worktree: unknown): worktree is GitWorktree {\n\t\treturn worktree instanceof GitWorktree;\n\t}\n\n\tstatic formatDate(worktree: GitWorktreeShape, format?: string | null): string {\n\t\treturn worktree.date != null ? formatDate(worktree.date, format ?? 'MMMM Do, YYYY h:mma') : '';\n\t}\n\n\tstatic formatDateFromNow(worktree: GitWorktreeShape): string {\n\t\treturn worktree.date != null ? fromNow(worktree.date) : '';\n\t}\n\n\tstatic formatDateWithStyle(\n\t\tworktree: GitWorktreeShape,\n\t\tformatting: { dateStyle: string; dateFormat: string | null },\n\t): string {\n\t\treturn formatting.dateStyle === 'absolute'\n\t\t\t? GitWorktree.formatDate(worktree, formatting.dateFormat)\n\t\t\t: GitWorktree.formatDateFromNow(worktree);\n\t}\n\n\tstatic async getStatus(\n\t\tworktree: GitWorktree,\n\t\toptions?: { priority?: GitCommandPriority },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitStatus | undefined> {\n\t\tif (worktree.type === 'bare') return undefined;\n\n\t\tconst repo = getRepositoryService(worktree.path);\n\t\treturn repo?.status.getStatus(options, cancellation);\n\t}\n\n\tstatic async hasWorkingChanges(\n\t\tworktree: GitWorktree,\n\t\toptions?: { staged?: boolean; unstaged?: boolean; untracked?: boolean },\n\t): Promise<boolean | undefined> {\n\t\tif (worktree.type === 'bare') return undefined;\n\n\t\tconst repo = getRepositoryService(worktree.path);\n\t\treturn repo?.status.hasWorkingChanges(options);\n\t}\n}\n"],"mappings":"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"}
@@ -21,6 +21,8 @@ export interface BranchContributionsOverview extends GitCommitStats<number> {
21
21
  readonly firstCommitDate: Date | undefined;
22
22
  readonly contributors: GitContributor[];
23
23
  }
24
+ /** Which source decided a base (see `getAheadOfBase`) */
25
+ export type AheadOfBaseTier = 'preferred' | 'user' | 'detected' | 'recorded' | 'created' | 'default' | 'upstream';
24
26
  export interface AheadOfBase {
25
27
  /** The base HEAD was measured against; `undefined` when there is none (see `getAheadOfBase`) */
26
28
  readonly base: {
@@ -30,8 +32,14 @@ export interface AheadOfBase {
30
32
  readonly ahead: number;
31
33
  /** The commit `ref` pointed at, from the cached ref list; `undefined` when no listed ref matches it */
32
34
  readonly sha: string | undefined;
35
+ /** Where HEAD forked from `ref`: git's `--fork-point` reading of `ref`'s reflog, else the merge base; `undefined` when they share no history */
36
+ readonly forkPoint: string | undefined;
37
+ /** The source the base came from: the `preferredTarget` option, the user's merge target, the detected one, the base recorded against the branch, the branch git's reflog says this branch was created from (unless the default branch forked strictly nearer HEAD), the default branch, or — when the branch is the default branch — the branch's own upstream */
38
+ readonly tier: AheadOfBaseTier;
33
39
  } | undefined;
34
- /** Full ref names (`refs/heads/main`, `refs/remotes/origin/main`, `refs/remotes/origin/HEAD`) whose movement can change this answer, given with or without a base so a watcher also learns when one appears: the branch, every candidate compared up to the chosen one, their tracking refs, and the default-branch symref when the default was consulted. Lets a watcher recompute only when one of them moves. */
40
+ /** Why there is no base; set exactly when `base` is `undefined`: `'none'` when nothing resolved, `'self'` when the base is the branch itself at HEAD's commit (or the default branch has no upstream to measure against), `'unborn'` when HEAD has no commit yet */
41
+ readonly reason?: 'none' | 'self' | 'unborn';
42
+ /** Full ref names (`refs/heads/main`, `refs/remotes/origin/main`, `refs/remotes/origin/HEAD`) whose movement can change this answer, given with or without a base so a watcher also learns when one appears: the branch, every candidate compared up to the chosen one, their tracking refs, the default-branch symrefs and the `<remote>/main`/`<remote>/master` refs when the default was consulted, the `upstream` remote's copy of the created-from or default branch when it was compared, and the branch's upstream when it is the default branch. Lets a watcher recompute only when one of them moves. */
35
43
  readonly dependsOn: readonly string[];
36
44
  }
37
45
  export type MergeDetectionConfidence = 'highest' | 'high' | 'medium';
@@ -99,16 +107,61 @@ export interface GitBranchesSubProvider {
99
107
  /** Detects conflicts when an autostash is reapplied onto the tree an integration produced */
100
108
  getPotentialStashReapplyConflicts?(repoPath: string, ontoTreeOid: string, cancellation?: AbortSignal): Promise<ConflictDetectionResult>;
101
109
  /**
102
- * How far HEAD has moved past the base `branch` (the branch checked out at HEAD) was cut from. Candidates in trust
110
+ * How far HEAD has moved past the base `branch` (the branch checked out at HEAD, or `undefined` when HEAD is
111
+ * detached) was cut from. Candidates in trust
103
112
  * order: the user's merge target, the detected one, then the base recorded against the branch — only recorded bases
104
113
  * count, never a reflog guess. Each is measured as itself or its tracking ref, whichever forked nearer HEAD; a stale
105
- * target (one naming no ref, a flag-like one, or the branch itself) falls through to the next, and the local default
106
- * branch is used when none survives. The count is the right side of `<base>...HEAD`. `base` is `undefined` when no
107
- * base resolves, when the base is the branch itself (by name, or as its copy on one of the repo's remotes) at HEAD's
108
- * own commit, or when HEAD is detached or has no commit yet; `dependsOn` is given either way. `base.sha` is the tip of
109
- * `ref`, read from the cached ref list. Rejects when the count can't be read.
114
+ * target (one naming no ref, a flag-like one, or the branch itself) falls through to the next, and the default branch
115
+ * is used when none survives: the `HEAD` symref of the `upstream` remote, else `origin`, else the first remote, as its
116
+ * local branch or else the remote ref; then, in the same remote order, `<remote>/main` or `<remote>/master`, again as
117
+ * the local branch or else the remote ref; then `init.defaultBranch`, `main`, `master` — from local refs only, never
118
+ * the network. On the default branch itself the base is its upstream (`upstream/<branch>` when an `upstream` remote has
119
+ * it, else `<branch>@{u}`), tier `'upstream'`. The count is the right side of `<base>...HEAD`. `base` is `undefined`
120
+ * when no base resolves, when the base is the branch itself (by name, or as its copy on one of the repo's remotes) at
121
+ * HEAD's own commit — or the default branch has no upstream — or when HEAD has no commit yet; `reason`
122
+ * then says which (`'none'`, `'self'` or `'unborn'`) and `dependsOn` is given either way. `base.sha` is the tip of
123
+ * `ref`, read from the cached ref list; `base.forkPoint` is where HEAD forked from `ref` and `base.tier` the source
124
+ * that decided the base. On a detached HEAD (`undefined`, or a name `isDetachedHead` recognizes) only the default branch
125
+ * is tried, as tier `'default'` and with no self check. Rejects when the count can't be read.
126
+ *
127
+ * `options.skipUserTarget` leaves the user's merge target out, giving the order a merge-target picker shows as
128
+ * "automatic". `options.preferredTarget` is tried before every other source, also on a detached HEAD, and measured
129
+ * like a recorded candidate (tier `'preferred'`); one that is unusable — naming no ref, flag-like, the branch itself,
130
+ * or the branch's copy on one of the repo's remotes at HEAD's own commit — falls through to the usual order.
131
+ * Tier `'preferred'` means the preferred target is the base; any other tier, or no base, means it fell through.
110
132
  */
111
- getAheadOfBase?(repoPath: string, branch: string, cancellation?: AbortSignal): Promise<AheadOfBase>;
133
+ getAheadOfBase?(repoPath: string, branch: string | undefined, options?: {
134
+ /** Leaves the user's merge target out: the order a merge-target picker shows as "automatic" */
135
+ skipUserTarget?: boolean;
136
+ /** A target to try before every other source */
137
+ preferredTarget?: string;
138
+ }, cancellation?: AbortSignal): Promise<AheadOfBase>;
139
+ /**
140
+ * How far each branch has diverged from `base`, keyed by full ref name (`refs/heads/x`, plus `refs/remotes/<remote>/x`
141
+ * when `options.remotes` is set) so a local and a remote name can't collide. Symbolic refs such as
142
+ * `refs/remotes/origin/HEAD` are left out. `ahead` is the commits on the branch that `base` lacks and `behind` the
143
+ * commits on `base` that the branch lacks, i.e. the right and left sides of `base...branch`. `options.refs` limits it to
144
+ * those full ref names (in place of `remotes`), so a host counts only the branches it shows; an empty list answers
145
+ * empty without running git. One git run on git 2.41+, a bounded count per distinct tip before that. Rejects when
146
+ * `base` can't be resolved or the counts can't be read.
147
+ */
148
+ getAheadBehindCounts?(repoPath: string, base: string, options?: {
149
+ remotes?: boolean;
150
+ refs?: readonly string[];
151
+ }, cancellation?: AbortSignal): Promise<Map<string, {
152
+ ahead: number;
153
+ behind: number;
154
+ }>>;
155
+ /**
156
+ * The branches whose tips are reachable from `into`, as full ref names (`refs/heads/x`, plus `refs/remotes/<remote>/x`
157
+ * when `options.remotes` is set). Ancestry only: a branch squash-merged or cherry-picked into `into` is not included,
158
+ * so use `getBranchMergedStatus` for that heuristic per-branch answer. A branch whose tip equals `into`'s tip (never
159
+ * diverged) is included, as git reports it. Symbolic refs such as `refs/remotes/origin/HEAD` are left out. One git
160
+ * run. Not cached. Rejects when `into` can't be resolved or the branches can't be read.
161
+ */
162
+ getMergedBranches?(repoPath: string, into: string, options?: {
163
+ remotes?: boolean;
164
+ }, cancellation?: AbortSignal): Promise<Set<string>>;
112
165
  getBaseBranchName?(repoPath: string, ref: string, options?: {
113
166
  priority?: GitCommandPriority;
114
167
  }, cancellation?: AbortSignal): Promise<string | undefined>;
@@ -118,8 +171,20 @@ export interface GitBranchesSubProvider {
118
171
  }, cancellation?: AbortSignal): Promise<string | undefined>;
119
172
  getStoredDetectedMergeTargetBranchName?(repoPath: string, ref: string): Promise<string | undefined>;
120
173
  getStoredUserMergeTargetBranchName?(repoPath: string, ref: string): Promise<string | undefined>;
174
+ /**
175
+ * Stamps `branch.<name>.gk-last-accessed` in `.git/gk/config` for the branch checked out at `repoPath`, when the
176
+ * host checks it out or opens it. A no-op for a detached HEAD or no branch. Each key's write is attempted at most
177
+ * once per 5 minutes per branch, failed or not, and not when its stored value, from any process, is under 5 minutes
178
+ * old. Calls for different repositories never drop each other, and the promise settles once the write is done and
179
+ * never rejects.
180
+ */
121
181
  onCurrentBranchAccessed?(repoPath: string): Promise<void>;
182
+ /**
183
+ * Stamps `gk-last-modified` and `gk-last-accessed`: the checkout's working tree or index changed while on the
184
+ * branch — file edits and staging, not only commits. Otherwise as {@link onCurrentBranchAccessed}.
185
+ */
122
186
  onCurrentBranchModified?(repoPath: string): Promise<void>;
187
+ /** Stamps `gk-agent-last-activity`: an AI agent worked in the checkout. Otherwise as {@link onCurrentBranchAccessed} */
123
188
  onCurrentBranchAgentActivity?(repoPath: string): Promise<void>;
124
189
  renameBranch?(repoPath: string, oldName: string, newName: string): Promise<void>;
125
190
  setUpstreamBranch?(repoPath: string, name: string, upstream: string | undefined): Promise<void>;
@@ -4,6 +4,12 @@ export interface GitPausedOperationsSubProvider {
4
4
  getPausedOperationStatus(repoPath: string, options?: {
5
5
  force?: boolean;
6
6
  }, cancellation?: AbortSignal): Promise<GitPausedOperationStatus | undefined>;
7
+ /**
8
+ * Whether git's dir holds a sentinel of any in-progress operation (merge, cherry-pick, revert, rebase,
9
+ * `git am`, or a sequencer run with a todo) — presence only, so it is `true` even for states
10
+ * `getPausedOperationStatus` can't describe. Rejects when git's dir can't be read, rather than answering `false`
11
+ */
12
+ hasPausedOperation?(repoPath: string, cancellation?: AbortSignal): Promise<boolean>;
7
13
  abortPausedOperation(repoPath: string, options?: {
8
14
  quit?: boolean;
9
15
  }): Promise<void>;
@@ -24,6 +24,11 @@ import { GitStatusSubProvider } from "./status.js";
24
24
  import { GitTagsSubProvider } from "./tags.js";
25
25
  import { GitWorktreesSubProvider } from "./worktrees.js";
26
26
  //#region ../git/src/providers/provider.d.ts
27
+ /** One path a provider announced its own write for, with the changes it announced there */
28
+ export interface AnnouncedRepositoryChanges {
29
+ readonly repoPath: string;
30
+ readonly changes: readonly RepositoryChange[];
31
+ }
27
32
  /**
28
33
  * Common interface for all git providers (CLI, GitHub, etc.).
29
34
  * Consumers can register multiple providers and route operations transparently.
@@ -48,13 +53,40 @@ export interface GitProvider {
48
53
  * ancestor, and literal paths containing glob metacharacters are dropped (a watcher can't express them safely).
49
54
  */
50
55
  getIgnoredDirectories?(repoPath: string, cancellation?: AbortSignal): Promise<string[]>;
56
+ /**
57
+ * The working tree's ignored entries as repo-relative `/`-separated paths, the way `git status --ignored` lists
58
+ * them: an ignored file is one entry, and a directory whose entire contents are ignored is one entry with a
59
+ * trailing `/` (its contents aren't listed). Empty directories and `.git/` aren't listed. Sorted, and not capped —
60
+ * the caller limits what it shows. Unlike `getIgnoredDirectories` this is a listing, not a watcher-pruning set, so
61
+ * nothing is dropped or re-confirmed against the rules.
62
+ */
63
+ getIgnoredEntries?(repoPath: string, cancellation?: AbortSignal): Promise<string[]>;
64
+ /**
65
+ * An exact check of which of `paths` (repo-relative) git's ignore rules match — the subset that is ignored, as
66
+ * given. A tracked file isn't reported as ignored, even when a rule matches it. This is git's answer, where the
67
+ * in-memory `GitIgnoreFilter` errs toward not-ignored.
68
+ */
69
+ getIgnoredPaths?(repoPath: string, paths: readonly string[], cancellation?: AbortSignal): Promise<Set<string>>;
51
70
  getIgnoredUrisFilter?(repoPath: string): Promise<(uri: Uri) => boolean>;
52
71
  getLastFetchedTimestamp?(repoPath: string): Promise<number | undefined>;
53
72
  /**
54
- * Fires when an external write changed a branch's merge-relevant `.git/gk/config` keys — not for activity
55
- * timestamps, and not for the provider's own writes. See `Cache.onDidChangeMergeTargets`.
73
+ * Fires when a write changed a branch's merge-relevant `.git/gk/config` keys — not for activity timestamps. The
74
+ * provider's own key store fires it once, naming the branch, as the write completes; its section remove and
75
+ * rename don't, nor do its internal saves while answering a read (only another process's watcher reports those).
76
+ * See `Cache.onDidChangeMergeTargets`.
56
77
  */
57
78
  readonly onDidChangeMergeTargets?: Event<MergeTargetsChangeEvent>;
79
+ /**
80
+ * The repository's common path, as it appears in {@link onDidChangeMergeTargets} events; `undefined` when the
81
+ * provider can't tell, because `repoPath` was never registered with it
82
+ */
83
+ getCommonPath?(repoPath: string): string | undefined;
84
+ /**
85
+ * Fires as the provider announces one of its own writes to the host (`hooks.repository.onChanged`), once for each
86
+ * path it announces it for, sibling worktrees included — after the write finished and its caches were evicted.
87
+ * `GitService` forwards it to its watch service, so the write's own file events aren't announced a second time.
88
+ */
89
+ readonly onDidAnnounceChanges?: Event<AnnouncedRepositoryChanges>;
58
90
  /** Creates a new repository at `path` (`git init`), creating `path` itself if it doesn't yet exist. */
59
91
  init?(path: string, options?: {
60
92
  defaultBranch?: string;
@@ -39,8 +39,14 @@ export interface GitStatusSubProvider {
39
39
  hasConflictingFiles(repoPath: string, cancellation?: AbortSignal): Promise<boolean>;
40
40
  /** Rejects when git fails, rather than answering empty */
41
41
  getConflictingFiles(repoPath: string, cancellation?: AbortSignal): Promise<GitConflictFile[]>;
42
- /** Rejects when git fails, rather than answering empty */
43
- getUntrackedFiles(repoPath: string, cancellation?: AbortSignal): Promise<GitFile[]>;
42
+ /**
43
+ * Rejects when git fails, rather than answering empty.
44
+ * `paths` limits the read to repo-relative files or folders (matched literally, never as globs); an empty
45
+ * array answers empty without running git, and omitting it reads the whole working tree.
46
+ */
47
+ getUntrackedFiles(repoPath: string, options?: {
48
+ paths?: readonly string[];
49
+ }, cancellation?: AbortSignal): Promise<GitFile[]>;
44
50
  }
45
51
  //#endregion
46
52
  //# sourceMappingURL=status.d.ts.map