@gitkraken/core-gitlens 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/dist/git/cache.d.ts +38 -8
  3. package/dist/git/cache.d.ts.map +1 -1
  4. package/dist/git/cache.js +120 -55
  5. package/dist/git/cache.js.map +1 -1
  6. package/dist/git/context.d.ts +19 -0
  7. package/dist/git/context.d.ts.map +1 -1
  8. package/dist/git/context.js.map +1 -1
  9. package/dist/git/features.d.ts +1 -1
  10. package/dist/git/features.d.ts.map +1 -1
  11. package/dist/git/features.js +1 -0
  12. package/dist/git/features.js.map +1 -1
  13. package/dist/git/models/commit.d.ts.map +1 -1
  14. package/dist/git/models/commit.js.map +1 -1
  15. package/dist/git/models/graph.d.ts +96 -0
  16. package/dist/git/models/graph.d.ts.map +1 -1
  17. package/dist/git/models/graph.js +24 -1
  18. package/dist/git/models/graph.js.map +1 -1
  19. package/dist/git/models/reference.d.ts +31 -0
  20. package/dist/git/models/reference.d.ts.map +1 -1
  21. package/dist/git/models/remote.d.ts.map +1 -1
  22. package/dist/git/models/remote.js.map +1 -1
  23. package/dist/git/models/remoteProvider.d.ts +1 -0
  24. package/dist/git/models/remoteProvider.d.ts.map +1 -1
  25. package/dist/git/models/remoteProvider.js.map +1 -1
  26. package/dist/git/models/repository.d.ts +30 -13
  27. package/dist/git/models/repository.d.ts.map +1 -1
  28. package/dist/git/models/repository.js +89 -87
  29. package/dist/git/models/repository.js.map +1 -1
  30. package/dist/git/models/search.d.ts +2 -2
  31. package/dist/git/models/search.d.ts.map +1 -1
  32. package/dist/git/models/statusFile.d.ts +9 -0
  33. package/dist/git/models/statusFile.d.ts.map +1 -1
  34. package/dist/git/models/statusFile.js +11 -0
  35. package/dist/git/models/statusFile.js.map +1 -1
  36. package/dist/git/models/worktree.d.ts +4 -1
  37. package/dist/git/models/worktree.d.ts.map +1 -1
  38. package/dist/git/models/worktree.js +2 -2
  39. package/dist/git/models/worktree.js.map +1 -1
  40. package/dist/git/parsers/diffParser.d.ts.map +1 -1
  41. package/dist/git/parsers/diffParser.js.map +1 -1
  42. package/dist/git/providers/branches.d.ts +15 -4
  43. package/dist/git/providers/branches.d.ts.map +1 -1
  44. package/dist/git/providers/commits.d.ts +4 -0
  45. package/dist/git/providers/commits.d.ts.map +1 -1
  46. package/dist/git/providers/config.d.ts +5 -4
  47. package/dist/git/providers/config.d.ts.map +1 -1
  48. package/dist/git/providers/operations.d.ts +61 -12
  49. package/dist/git/providers/operations.d.ts.map +1 -1
  50. package/dist/git/providers/pausedOperations.d.ts +3 -1
  51. package/dist/git/providers/pausedOperations.d.ts.map +1 -1
  52. package/dist/git/providers/refs.d.ts +23 -2
  53. package/dist/git/providers/refs.d.ts.map +1 -1
  54. package/dist/git/providers/staging.d.ts +16 -0
  55. package/dist/git/providers/staging.d.ts.map +1 -1
  56. package/dist/git/providers/status.d.ts +4 -1
  57. package/dist/git/providers/status.d.ts.map +1 -1
  58. package/dist/git/remotes/azure-devops.d.ts.map +1 -1
  59. package/dist/git/remotes/azure-devops.js.map +1 -1
  60. package/dist/git/remotes/custom.d.ts +2 -0
  61. package/dist/git/remotes/custom.d.ts.map +1 -1
  62. package/dist/git/remotes/custom.js +20 -0
  63. package/dist/git/remotes/custom.js.map +1 -1
  64. package/dist/git/{exec.types.d.ts → run.types.d.ts} +22 -3
  65. package/dist/git/run.types.d.ts.map +1 -0
  66. package/dist/git/run.types.js +2 -0
  67. package/dist/git/run.types.js.map +1 -0
  68. package/dist/git/service.d.ts.map +1 -1
  69. package/dist/git/service.js.map +1 -1
  70. package/dist/git/utils/autolink.utils.d.ts.map +1 -1
  71. package/dist/git/utils/autolink.utils.js.map +1 -1
  72. package/dist/git/utils/blame.utils.d.ts.map +1 -1
  73. package/dist/git/utils/blame.utils.js.map +1 -1
  74. package/dist/git/utils/conflictResolution.utils.d.ts +6 -0
  75. package/dist/git/utils/conflictResolution.utils.d.ts.map +1 -0
  76. package/dist/git/utils/conflictResolution.utils.js +25 -0
  77. package/dist/git/utils/conflictResolution.utils.js.map +1 -0
  78. package/dist/git/utils/contributor.utils.d.ts +3 -0
  79. package/dist/git/utils/contributor.utils.d.ts.map +1 -1
  80. package/dist/git/utils/contributor.utils.js +22 -0
  81. package/dist/git/utils/contributor.utils.js.map +1 -1
  82. package/dist/git/utils/fileStatus.utils.d.ts +2 -1
  83. package/dist/git/utils/fileStatus.utils.d.ts.map +1 -1
  84. package/dist/git/utils/fileStatus.utils.js +4 -0
  85. package/dist/git/utils/fileStatus.utils.js.map +1 -1
  86. package/dist/git/utils/reachability.utils.d.ts +37 -0
  87. package/dist/git/utils/reachability.utils.d.ts.map +1 -0
  88. package/dist/git/utils/reachability.utils.js +96 -0
  89. package/dist/git/utils/reachability.utils.js.map +1 -0
  90. package/dist/git/utils/search.utils.d.ts.map +1 -1
  91. package/dist/git/utils/search.utils.js +3 -0
  92. package/dist/git/utils/search.utils.js.map +1 -1
  93. package/dist/git/utils/sorting.d.ts +8 -0
  94. package/dist/git/utils/sorting.d.ts.map +1 -1
  95. package/dist/git/utils/sorting.js +15 -0
  96. package/dist/git/utils/sorting.js.map +1 -1
  97. package/dist/git/utils/status.utils.d.ts.map +1 -1
  98. package/dist/git/utils/status.utils.js.map +1 -1
  99. package/dist/git/watching/classifyChange.d.ts.map +1 -1
  100. package/dist/git/watching/classifyChange.js +8 -0
  101. package/dist/git/watching/classifyChange.js.map +1 -1
  102. package/dist/git/watching/gitIgnoreFilter.js +1 -1
  103. package/dist/git/watching/gitIgnoreFilter.js.map +1 -1
  104. package/dist/git/watching/initWatcher.d.ts.map +1 -1
  105. package/dist/git/watching/initWatcher.js.map +1 -1
  106. package/dist/git/watching/watchGroup.d.ts.map +1 -1
  107. package/dist/git/watching/watchGroup.js.map +1 -1
  108. package/dist/git/watching/watchService.d.ts +4 -2
  109. package/dist/git/watching/watchService.d.ts.map +1 -1
  110. package/dist/git/watching/watchService.js +31 -6
  111. package/dist/git/watching/watchService.js.map +1 -1
  112. package/dist/git/watching/watchSession.d.ts +14 -12
  113. package/dist/git/watching/watchSession.d.ts.map +1 -1
  114. package/dist/git/watching/watchSession.js +56 -55
  115. package/dist/git/watching/watchSession.js.map +1 -1
  116. package/dist/git-cli/exec/exec.types.d.ts +1 -1
  117. package/dist/git-cli/exec/exec.types.d.ts.map +1 -1
  118. package/dist/git-cli/exec/git.d.ts +3 -3
  119. package/dist/git-cli/exec/git.d.ts.map +1 -1
  120. package/dist/git-cli/exec/git.js.map +1 -1
  121. package/dist/git-cli/exec/gitQueue.d.ts +10 -2
  122. package/dist/git-cli/exec/gitQueue.d.ts.map +1 -1
  123. package/dist/git-cli/exec/gitQueue.js +39 -12
  124. package/dist/git-cli/exec/gitQueue.js.map +1 -1
  125. package/dist/git-cli/parsers/blameParser.d.ts.map +1 -1
  126. package/dist/git-cli/parsers/blameParser.js.map +1 -1
  127. package/dist/git-cli/parsers/logParser.js.map +1 -1
  128. package/dist/git-cli/parsers/refParser.d.ts +3 -30
  129. package/dist/git-cli/parsers/refParser.d.ts.map +1 -1
  130. package/dist/git-cli/parsers/refParser.js +30 -30
  131. package/dist/git-cli/parsers/refParser.js.map +1 -1
  132. package/dist/git-cli/providers/blame.d.ts.map +1 -1
  133. package/dist/git-cli/providers/blame.js.map +1 -1
  134. package/dist/git-cli/providers/branches.d.ts +15 -5
  135. package/dist/git-cli/providers/branches.d.ts.map +1 -1
  136. package/dist/git-cli/providers/branches.js +99 -68
  137. package/dist/git-cli/providers/branches.js.map +1 -1
  138. package/dist/git-cli/providers/commits.d.ts +1 -0
  139. package/dist/git-cli/providers/commits.d.ts.map +1 -1
  140. package/dist/git-cli/providers/commits.js +86 -30
  141. package/dist/git-cli/providers/commits.js.map +1 -1
  142. package/dist/git-cli/providers/config.d.ts +19 -6
  143. package/dist/git-cli/providers/config.d.ts.map +1 -1
  144. package/dist/git-cli/providers/config.js +86 -38
  145. package/dist/git-cli/providers/config.js.map +1 -1
  146. package/dist/git-cli/providers/diff.d.ts.map +1 -1
  147. package/dist/git-cli/providers/diff.js +5 -3
  148. package/dist/git-cli/providers/diff.js.map +1 -1
  149. package/dist/git-cli/providers/graph.d.ts.map +1 -1
  150. package/dist/git-cli/providers/graph.js +139 -16
  151. package/dist/git-cli/providers/graph.js.map +1 -1
  152. package/dist/git-cli/providers/operations.d.ts +17 -14
  153. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  154. package/dist/git-cli/providers/operations.js +135 -63
  155. package/dist/git-cli/providers/operations.js.map +1 -1
  156. package/dist/git-cli/providers/patch.d.ts.map +1 -1
  157. package/dist/git-cli/providers/patch.js.map +1 -1
  158. package/dist/git-cli/providers/pausedOperations.d.ts +3 -1
  159. package/dist/git-cli/providers/pausedOperations.d.ts.map +1 -1
  160. package/dist/git-cli/providers/pausedOperations.js +7 -1
  161. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  162. package/dist/git-cli/providers/refs.d.ts +19 -2
  163. package/dist/git-cli/providers/refs.d.ts.map +1 -1
  164. package/dist/git-cli/providers/refs.js +286 -2
  165. package/dist/git-cli/providers/refs.js.map +1 -1
  166. package/dist/git-cli/providers/revision.js.map +1 -1
  167. package/dist/git-cli/providers/staging.d.ts +6 -0
  168. package/dist/git-cli/providers/staging.d.ts.map +1 -1
  169. package/dist/git-cli/providers/staging.js +32 -0
  170. package/dist/git-cli/providers/staging.js.map +1 -1
  171. package/dist/git-cli/providers/stash.d.ts.map +1 -1
  172. package/dist/git-cli/providers/stash.js +20 -2
  173. package/dist/git-cli/providers/stash.js.map +1 -1
  174. package/dist/git-cli/providers/status.d.ts +4 -1
  175. package/dist/git-cli/providers/status.d.ts.map +1 -1
  176. package/dist/git-cli/providers/status.js +8 -4
  177. package/dist/git-cli/providers/status.js.map +1 -1
  178. package/dist/git-cli/providers/tags.d.ts.map +1 -1
  179. package/dist/git-cli/providers/tags.js +10 -6
  180. package/dist/git-cli/providers/tags.js.map +1 -1
  181. package/dist/ipc/discovery.d.ts +49 -0
  182. package/dist/ipc/discovery.d.ts.map +1 -0
  183. package/dist/ipc/discovery.js +147 -0
  184. package/dist/ipc/discovery.js.map +1 -0
  185. package/dist/ipc/ipcServer.d.ts +20 -0
  186. package/dist/ipc/ipcServer.d.ts.map +1 -0
  187. package/dist/ipc/ipcServer.js +162 -0
  188. package/dist/ipc/ipcServer.js.map +1 -0
  189. package/dist/plus/agents/providers/claudeCodeProvider.d.ts +167 -0
  190. package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -0
  191. package/dist/plus/agents/providers/claudeCodeProvider.js +1786 -0
  192. package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -0
  193. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts +36 -0
  194. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts.map +1 -0
  195. package/dist/plus/agents/providers/claudeCodeTranscript.js +171 -0
  196. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -0
  197. package/dist/plus/agents/sanitizePrompt.d.ts +15 -0
  198. package/dist/plus/agents/sanitizePrompt.d.ts.map +1 -0
  199. package/dist/plus/agents/sanitizePrompt.js +103 -0
  200. package/dist/plus/agents/sanitizePrompt.js.map +1 -0
  201. package/dist/plus/agents/stateMachine.d.ts +32 -0
  202. package/dist/plus/agents/stateMachine.d.ts.map +1 -0
  203. package/dist/plus/agents/stateMachine.js +180 -0
  204. package/dist/plus/agents/stateMachine.js.map +1 -0
  205. package/dist/plus/agents/types.d.ts +254 -0
  206. package/dist/plus/agents/types.d.ts.map +1 -0
  207. package/dist/plus/agents/types.js +49 -0
  208. package/dist/plus/agents/types.js.map +1 -0
  209. package/dist/plus/ai/errors.d.ts +4 -1
  210. package/dist/plus/ai/errors.d.ts.map +1 -1
  211. package/dist/plus/ai/errors.js +38 -0
  212. package/dist/plus/ai/errors.js.map +1 -1
  213. package/dist/plus/ai/models/model.d.ts +1 -1
  214. package/dist/plus/ai/models/model.d.ts.map +1 -1
  215. package/dist/plus/ai/models/model.js.map +1 -1
  216. package/dist/plus/ai/models/promptTemplates.d.ts +11 -2
  217. package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
  218. package/dist/plus/ai/models/provider.d.ts +3 -0
  219. package/dist/plus/ai/models/provider.d.ts.map +1 -1
  220. package/dist/plus/ai/prompts.d.ts +1 -0
  221. package/dist/plus/ai/prompts.d.ts.map +1 -1
  222. package/dist/plus/ai/prompts.js +48 -8
  223. package/dist/plus/ai/prompts.js.map +1 -1
  224. package/dist/plus/ai/providers/gitkrakenProvider.d.ts +1 -1
  225. package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
  226. package/dist/plus/ai/providers/gitkrakenProvider.js +4 -1
  227. package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
  228. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +4 -3
  229. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
  230. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +9 -6
  231. package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
  232. package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
  233. package/dist/plus/ai/utils/ai.utils.js +2 -0
  234. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  235. package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
  236. package/dist/plus/ai/utils/results.utils.js.map +1 -1
  237. package/dist/plus/git-github/api/github.d.ts +12 -1
  238. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  239. package/dist/plus/git-github/api/github.js +245 -51
  240. package/dist/plus/git-github/api/github.js.map +1 -1
  241. package/dist/plus/git-github/api/types.d.ts +8 -0
  242. package/dist/plus/git-github/api/types.d.ts.map +1 -1
  243. package/dist/plus/git-github/models.d.ts +1 -1
  244. package/dist/plus/git-github/models.d.ts.map +1 -1
  245. package/dist/plus/git-github/models.js.map +1 -1
  246. package/dist/plus/git-github/providers/github/blame.d.ts.map +1 -1
  247. package/dist/plus/git-github/providers/github/blame.js.map +1 -1
  248. package/dist/plus/git-github/providers/github/branches.d.ts +5 -1
  249. package/dist/plus/git-github/providers/github/branches.d.ts.map +1 -1
  250. package/dist/plus/git-github/providers/github/branches.js +47 -24
  251. package/dist/plus/git-github/providers/github/branches.js.map +1 -1
  252. package/dist/plus/git-github/providers/github/commits.d.ts.map +1 -1
  253. package/dist/plus/git-github/providers/github/commits.js +144 -92
  254. package/dist/plus/git-github/providers/github/commits.js.map +1 -1
  255. package/dist/plus/git-github/providers/github/diff.d.ts +1 -1
  256. package/dist/plus/git-github/providers/github/diff.d.ts.map +1 -1
  257. package/dist/plus/git-github/providers/github/diff.js +23 -9
  258. package/dist/plus/git-github/providers/github/diff.js.map +1 -1
  259. package/dist/plus/git-github/providers/github/refs.d.ts +9 -1
  260. package/dist/plus/git-github/providers/github/refs.d.ts.map +1 -1
  261. package/dist/plus/git-github/providers/github/refs.js +39 -14
  262. package/dist/plus/git-github/providers/github/refs.js.map +1 -1
  263. package/dist/plus/git-github/providers/github/revision.d.ts.map +1 -1
  264. package/dist/plus/git-github/providers/github/revision.js +1 -2
  265. package/dist/plus/git-github/providers/github/revision.js.map +1 -1
  266. package/dist/plus/git-github/providers/github/status.d.ts +4 -1
  267. package/dist/plus/git-github/providers/github/status.d.ts.map +1 -1
  268. package/dist/plus/git-github/providers/github/status.js +1 -1
  269. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  270. package/dist/plus/git-github/providers/github/tags.d.ts.map +1 -1
  271. package/dist/plus/git-github/providers/github/tags.js +35 -36
  272. package/dist/plus/git-github/providers/github/tags.js.map +1 -1
  273. package/dist/plus/git-github/providers/githubGitProvider.d.ts.map +1 -1
  274. package/dist/plus/git-github/providers/githubGitProvider.js.map +1 -1
  275. package/dist/utils/color.d.ts.map +1 -1
  276. package/dist/utils/color.js.map +1 -1
  277. package/dist/utils/date.d.ts.map +1 -1
  278. package/dist/utils/date.js +6 -0
  279. package/dist/utils/date.js.map +1 -1
  280. package/dist/utils/debounce.js +1 -1
  281. package/dist/utils/decorators/serializable.d.ts.map +1 -1
  282. package/dist/utils/decorators/serializable.js.map +1 -1
  283. package/dist/utils/dedupedAsyncCache.d.ts +37 -0
  284. package/dist/utils/dedupedAsyncCache.d.ts.map +1 -0
  285. package/dist/utils/dedupedAsyncCache.js +68 -0
  286. package/dist/utils/dedupedAsyncCache.js.map +1 -0
  287. package/dist/utils/diff.d.ts +2 -0
  288. package/dist/utils/diff.d.ts.map +1 -0
  289. package/dist/utils/diff.js +53 -0
  290. package/dist/utils/diff.js.map +1 -0
  291. package/dist/utils/disposable.d.ts.map +1 -1
  292. package/dist/utils/disposable.js.map +1 -1
  293. package/dist/utils/env/node/exec.d.ts.map +1 -1
  294. package/dist/utils/env/node/exec.js.map +1 -1
  295. package/dist/utils/error.d.ts.map +1 -1
  296. package/dist/utils/error.js.map +1 -1
  297. package/dist/utils/iterable.d.ts +7 -1
  298. package/dist/utils/iterable.d.ts.map +1 -1
  299. package/dist/utils/iterable.js +12 -4
  300. package/dist/utils/iterable.js.map +1 -1
  301. package/dist/utils/logger.d.ts.map +1 -1
  302. package/dist/utils/logger.js.map +1 -1
  303. package/dist/utils/lruMap.d.ts +9 -0
  304. package/dist/utils/lruMap.d.ts.map +1 -1
  305. package/dist/utils/lruMap.js +26 -4
  306. package/dist/utils/lruMap.js.map +1 -1
  307. package/dist/utils/markdown.d.ts.map +1 -1
  308. package/dist/utils/markdown.js.map +1 -1
  309. package/dist/utils/mru.d.ts.map +1 -1
  310. package/dist/utils/mru.js.map +1 -1
  311. package/dist/utils/object.d.ts +22 -1
  312. package/dist/utils/object.d.ts.map +1 -1
  313. package/dist/utils/object.js +56 -3
  314. package/dist/utils/object.js.map +1 -1
  315. package/dist/utils/paging.js +14 -15
  316. package/dist/utils/paging.js.map +1 -1
  317. package/dist/utils/path.d.ts.map +1 -1
  318. package/dist/utils/path.js.map +1 -1
  319. package/dist/utils/promise.d.ts +1 -0
  320. package/dist/utils/promise.d.ts.map +1 -1
  321. package/dist/utils/promise.js +17 -0
  322. package/dist/utils/promise.js.map +1 -1
  323. package/dist/utils/promiseCache.d.ts +10 -0
  324. package/dist/utils/promiseCache.d.ts.map +1 -1
  325. package/dist/utils/promiseCache.js +34 -4
  326. package/dist/utils/promiseCache.js.map +1 -1
  327. package/dist/utils/string.d.ts.map +1 -1
  328. package/dist/utils/string.js +1 -1
  329. package/dist/utils/string.js.map +1 -1
  330. package/dist/utils/uri.d.ts.map +1 -1
  331. package/dist/utils/uri.js.map +1 -1
  332. package/dist/utils/version.d.ts.map +1 -1
  333. package/dist/utils/version.js.map +1 -1
  334. package/package.json +13 -1
  335. package/src/git/cache.ts +192 -90
  336. package/src/git/context.ts +21 -0
  337. package/src/git/features.ts +2 -0
  338. package/src/git/models/commit.ts +1 -0
  339. package/src/git/models/graph.ts +97 -0
  340. package/src/git/models/reference.ts +33 -0
  341. package/src/git/models/remote.ts +1 -0
  342. package/src/git/models/remoteProvider.ts +1 -0
  343. package/src/git/models/repository.ts +105 -96
  344. package/src/git/models/search.ts +2 -2
  345. package/src/git/models/statusFile.ts +12 -0
  346. package/src/git/models/worktree.ts +10 -2
  347. package/src/git/parsers/diffParser.ts +2 -0
  348. package/src/git/providers/branches.ts +22 -4
  349. package/src/git/providers/commits.ts +4 -0
  350. package/src/git/providers/config.ts +3 -5
  351. package/src/git/providers/operations.ts +65 -1
  352. package/src/git/providers/pausedOperations.ts +1 -0
  353. package/src/git/providers/refs.ts +32 -3
  354. package/src/git/providers/staging.ts +12 -0
  355. package/src/git/providers/status.ts +6 -1
  356. package/src/git/remotes/azure-devops.ts +2 -0
  357. package/src/git/remotes/custom.ts +23 -0
  358. package/src/git/{exec.types.ts → run.types.ts} +22 -2
  359. package/src/git/service.ts +1 -0
  360. package/src/git/utils/autolink.utils.ts +1 -0
  361. package/src/git/utils/blame.utils.ts +2 -0
  362. package/src/git/utils/conflictResolution.utils.ts +31 -0
  363. package/src/git/utils/contributor.utils.ts +24 -0
  364. package/src/git/utils/fileStatus.utils.ts +7 -1
  365. package/src/git/utils/reachability.utils.ts +109 -0
  366. package/src/git/utils/search.utils.ts +2 -0
  367. package/src/git/utils/sorting.ts +17 -0
  368. package/src/git/utils/status.utils.ts +1 -0
  369. package/src/git/watching/classifyChange.ts +9 -0
  370. package/src/git/watching/gitIgnoreFilter.ts +2 -2
  371. package/src/git/watching/initWatcher.ts +2 -0
  372. package/src/git/watching/watchGroup.ts +3 -0
  373. package/src/git/watching/watchService.ts +45 -7
  374. package/src/git/watching/watchSession.ts +71 -55
  375. package/src/git-cli/exec/exec.types.ts +2 -2
  376. package/src/git-cli/exec/git.ts +6 -5
  377. package/src/git-cli/exec/gitQueue.ts +41 -12
  378. package/src/git-cli/parsers/blameParser.ts +1 -0
  379. package/src/git-cli/parsers/logParser.ts +1 -0
  380. package/src/git-cli/parsers/refParser.ts +33 -34
  381. package/src/git-cli/providers/blame.ts +1 -0
  382. package/src/git-cli/providers/branches.ts +165 -93
  383. package/src/git-cli/providers/commits.ts +107 -37
  384. package/src/git-cli/providers/config.ts +101 -48
  385. package/src/git-cli/providers/diff.ts +10 -3
  386. package/src/git-cli/providers/graph.ts +156 -16
  387. package/src/git-cli/providers/operations.ts +208 -83
  388. package/src/git-cli/providers/patch.ts +1 -0
  389. package/src/git-cli/providers/pausedOperations.ts +8 -0
  390. package/src/git-cli/providers/refs.ts +247 -3
  391. package/src/git-cli/providers/revision.ts +2 -2
  392. package/src/git-cli/providers/staging.ts +33 -0
  393. package/src/git-cli/providers/stash.ts +20 -2
  394. package/src/git-cli/providers/status.ts +24 -5
  395. package/src/git-cli/providers/tags.ts +15 -16
  396. package/src/ipc/discovery.ts +186 -0
  397. package/src/ipc/ipcServer.ts +171 -0
  398. package/src/plus/agents/providers/claudeCodeProvider.ts +2122 -0
  399. package/src/plus/agents/providers/claudeCodeTranscript.ts +214 -0
  400. package/src/plus/agents/sanitizePrompt.ts +109 -0
  401. package/src/plus/agents/stateMachine.ts +197 -0
  402. package/src/plus/agents/types.ts +325 -0
  403. package/src/plus/ai/errors.ts +40 -0
  404. package/src/plus/ai/models/model.ts +1 -0
  405. package/src/plus/ai/models/promptTemplates.ts +13 -0
  406. package/src/plus/ai/models/provider.ts +7 -1
  407. package/src/plus/ai/prompts.ts +49 -8
  408. package/src/plus/ai/providers/gitkrakenProvider.ts +4 -0
  409. package/src/plus/ai/providers/openAICompatibleProviderBase.ts +21 -4
  410. package/src/plus/ai/utils/ai.utils.ts +2 -0
  411. package/src/plus/ai/utils/results.utils.ts +2 -0
  412. package/src/plus/git-github/api/github.ts +315 -57
  413. package/src/plus/git-github/api/types.ts +15 -0
  414. package/src/plus/git-github/models.ts +1 -1
  415. package/src/plus/git-github/providers/github/blame.ts +2 -0
  416. package/src/plus/git-github/providers/github/branches.ts +61 -31
  417. package/src/plus/git-github/providers/github/commits.ts +231 -160
  418. package/src/plus/git-github/providers/github/diff.ts +27 -19
  419. package/src/plus/git-github/providers/github/refs.ts +58 -23
  420. package/src/plus/git-github/providers/github/revision.ts +1 -2
  421. package/src/plus/git-github/providers/github/status.ts +6 -1
  422. package/src/plus/git-github/providers/github/tags.ts +61 -62
  423. package/src/plus/git-github/providers/githubGitProvider.ts +1 -0
  424. package/src/utils/color.ts +2 -0
  425. package/src/utils/date.ts +5 -0
  426. package/src/utils/debounce.ts +1 -1
  427. package/src/utils/decorators/serializable.ts +1 -0
  428. package/src/utils/dedupedAsyncCache.ts +74 -0
  429. package/src/utils/diff.ts +61 -0
  430. package/src/utils/disposable.ts +2 -0
  431. package/src/utils/env/node/exec.ts +2 -0
  432. package/src/utils/error.ts +1 -0
  433. package/src/utils/iterable.ts +17 -3
  434. package/src/utils/logger.ts +1 -0
  435. package/src/utils/lruMap.ts +29 -4
  436. package/src/utils/markdown.ts +1 -0
  437. package/src/utils/mru.ts +2 -0
  438. package/src/utils/object.ts +55 -4
  439. package/src/utils/paging.ts +14 -14
  440. package/src/utils/path.ts +1 -0
  441. package/src/utils/promise.ts +22 -0
  442. package/src/utils/promiseCache.ts +48 -16
  443. package/src/utils/string.ts +3 -1
  444. package/src/utils/uri.ts +1 -0
  445. package/src/utils/version.ts +1 -0
  446. package/dist/git/exec.types.d.ts.map +0 -1
  447. package/dist/git/exec.types.js +0 -2
  448. package/dist/git/exec.types.js.map +0 -1
@@ -19,6 +19,14 @@ export interface GitGraphRowHead {
19
19
  isCurrentHead: boolean;
20
20
  context?: string | object;
21
21
  upstream?: { name: string; id: string };
22
+ /** Set when this branch is checked out in a (non-default) worktree. Grouped so producers can't
23
+ * half-populate id-without-path or vice versa. GitLens consumers should read this field. */
24
+ worktree?: { id: string; path: string };
25
+ /** Upstream-component-compatibility mirror of `worktree?.id`. The bundled
26
+ * `@gitkraken/gitkraken-components` library still reads `worktreeId` to switch between
27
+ * WORKTREE and HEAD ref-badge styling — keeping it populated preserves the visual cue.
28
+ * Producers MUST set this whenever they set `worktree`; do not read it from GitLens code,
29
+ * read `worktree.id` instead. */
22
30
  worktreeId?: string;
23
31
  }
24
32
 
@@ -40,11 +48,43 @@ export interface GitGraphRowTag {
40
48
  context?: string | object;
41
49
  }
42
50
 
51
+ /**
52
+ * Compact, host-computed flags for a commit/stash row, shipped instead of the bulky serialized
53
+ * `contexts.row`/`contexts.avatar` blobs (which duplicated sha/message/repoPath already on the row).
54
+ * The webview reconstructs the full webview-item contexts from these flags + row fields + repoPath.
55
+ * Bit 0: reachable-from-HEAD (`+current`); Bit 1: unique-to-one-local-branch (`+unique`);
56
+ * Bit 2: has-children — set ONLY on undo-eligible tip rows (active HEAD + worktree HEADs) that have a
57
+ * child, to gate Undo Commit to leaf tips (undoing a commit other work is stacked on is unsafe). It is
58
+ * NOT a general has-children signal: non-tip rows never carry it (the host only computes it for tips);
59
+ * Bit 3: unpushed/ahead-of-upstream (`+unpublished`).
60
+ * Bit 4: history-rewriteable (`+rewriteable`) — on the first-parent chain from HEAD up to (excluding)
61
+ * the first merge commit, so a plain (non-`--rebase-merges`) interactive rebase can safely rewrite it;
62
+ * gates squash/drop/reword/modify. Strictly narrower than `+current` (reachable-from-HEAD includes a
63
+ * merge's other-parent ancestry, which is NOT safely rewriteable).
64
+ * (`+HEAD` derives from `row.heads[].isCurrentHead`; contributor `+current` from `row.isCurrentUser`.)
65
+ */
66
+ export const enum GitGraphRowContextFlags {
67
+ None = 0,
68
+ ReachableFromHead = 1 << 0,
69
+ UniqueToBranch = 1 << 1,
70
+ HasChildren = 1 << 2,
71
+ Unpublished = 1 << 3,
72
+ RewriteableFromHead = 1 << 4,
73
+ }
74
+
43
75
  /**
44
76
  * Context data attached to graph row regions for command/menu handling.
45
77
  * Structurally compatible with @gitkraken/gitkraken-components RowContexts.
46
78
  */
47
79
  export interface GitGraphRowContexts {
80
+ /** Compact replacement for the serialized commit `row`/`avatar` contexts; see {@link GitGraphRowContextFlags}. */
81
+ flags?: GitGraphRowContextFlags;
82
+ /**
83
+ * Index into the per-graph `GraphReachabilityTable.sets` for this row's reachable-refs set,
84
+ * shipped instead of the per-row `reachability` object (which dominated the graph payload). The
85
+ * webview rebuilds `row.reachability` from the shared table. Absent ⇒ no reachability for this row.
86
+ */
87
+ reachabilityIndex?: number;
48
88
  row?: string | object;
49
89
  ref?: string | object;
50
90
  refGroups?: Record<string, string | object>;
@@ -63,6 +103,28 @@ export interface GitGraphRowStats {
63
103
  deletions: number;
64
104
  }
65
105
 
106
+ /**
107
+ * Wire encoding for per-row reachability, shipped once per graph payload instead of inline on every
108
+ * row. Git reachability is monotone (adjacent commits share ref-sets), so the rows collapse to a
109
+ * relatively small number of distinct sets over the repo's ref universe — `dictionary` (the shared
110
+ * ref list) + `sets` (distinct membership bitmaps, base64; bit i ⇒ `dictionary[i]` reachable) + a
111
+ * per-row index (`GitGraphRowContexts.reachabilityIndex`) reconstructs every row's `reachability`
112
+ * client-side for a fraction of the bytes the inline objects cost. `current` is a per-ref property
113
+ * (the checked-out HEAD branch) and lives in the dictionary entry.
114
+ *
115
+ * The table is append-only within a graph generation, so the host ships only the entries appended
116
+ * since its last push (a delta) on same-generation pagination and the full table on a new generation;
117
+ * `id` lets the webview tell the two apart (same `id` ⇒ append the delta, new `id` ⇒ replace + reset
118
+ * its decode cache). A fresh `getGraph` walk mints a new `id`; `more()` keeps the same one.
119
+ */
120
+ export interface GraphReachabilityTable {
121
+ /** Generation id — stable across `more()` pagination, new per fresh graph walk. */
122
+ readonly id: number;
123
+ readonly dictionary: GitCommitReachability['refs'];
124
+ /** Distinct ref-membership bitmaps, base64-encoded `Uint8Array` of `ceil(dictionary.length/8)` bytes. */
125
+ readonly sets: string[];
126
+ }
127
+
66
128
  /** Library-owned graph row type. Structurally compatible with @gitkraken/gitkraken-components GraphRow. */
67
129
  export interface GitGraphRow {
68
130
  sha: string;
@@ -78,6 +140,12 @@ export interface GitGraphRow {
78
140
  tags?: GitGraphRowTag[];
79
141
  contexts?: GitGraphRowContexts;
80
142
  stats?: GitGraphRowStats;
143
+ /**
144
+ * Transient, set only for the duration of {@link GraphRowProcessor.processRow} (the row processor's
145
+ * `+unique` decision reads it). The provider strips it before pushing the row and records the
146
+ * reachable-ref set into the shared {@link GitGraph.reachability} table instead (see
147
+ * {@link GitGraphRowContexts.reachabilityIndex}), so emitted rows do NOT retain the per-row arrays.
148
+ */
81
149
  reachability?: GitCommitReachability;
82
150
  isCurrentUser?: boolean;
83
151
  }
@@ -99,6 +167,22 @@ export interface GitGraph {
99
167
  /** SHAs reachable from HEAD (for enrichment: marking commits on the current branch) */
100
168
  readonly reachableFromHEAD?: ReadonlySet<string>;
101
169
 
170
+ /**
171
+ * SHAs on the first-parent chain from HEAD up to (excluding) the first merge commit — i.e. the
172
+ * commits a plain interactive rebase can safely rewrite. Empty when HEAD itself is a merge. Used by
173
+ * the graph's history-rewriting commands (squash/drop/reword/modify) to validate selections.
174
+ */
175
+ readonly rewriteableFromHEAD?: ReadonlySet<string>;
176
+
177
+ /**
178
+ * Shared, append-only reachability table for the loaded rows (the primary representation — rows
179
+ * carry only a {@link GitGraphRowContexts.reachabilityIndex} into it, not per-row ref arrays).
180
+ * Grows monotonically across {@link more} pagination within a graph session: indices already
181
+ * assigned never change, so consumers can decode any row on demand and cache by index. Absent ⇒
182
+ * no row in the graph has reachability. See {@link GraphReachabilityTable}.
183
+ */
184
+ readonly reachability?: GraphReachabilityTable;
185
+
102
186
  /** The rows for the set of commits requested */
103
187
  readonly rows: GitGraphRow[];
104
188
  readonly id?: string;
@@ -178,5 +262,18 @@ export interface GraphContext {
178
262
  readonly branchIdOfMainWorktree: string | undefined;
179
263
  readonly stashes: ReadonlyMap<string, GitStashCommit> | undefined;
180
264
  readonly reachableFromHEAD: ReadonlySet<string>;
265
+ /** SHAs on the first-parent chain from HEAD up to (excluding) the first merge commit — the commits
266
+ * a plain interactive rebase can safely rewrite. Empty when HEAD is a merge. Sets the
267
+ * {@link GitGraphRowContextFlags.RewriteableFromHead} flag, gating squash/drop/reword/modify. */
268
+ readonly rewriteableFromHEAD: ReadonlySet<string>;
269
+ /** The subset of undo-eligible tip shas (active HEAD + worktree HEADs) that have at least one
270
+ * child — i.e. are NOT leaves. Scoped to tips (not all commits) for performance; do not treat as
271
+ * a general has-children signal. Sets the {@link GitGraphRowContextFlags.HasChildren} flag, which
272
+ * gates Undo Commit to leaf tips. */
273
+ readonly tipShasWithChildren: ReadonlySet<string>;
274
+ /** SHAs reachable from HEAD's tracking-upstream tip, or `undefined` when HEAD has no upstream.
275
+ * A commit reachable from HEAD but NOT from this set is unpushed (`+unpublished`); `undefined`
276
+ * means there's no upstream to be ahead of, so nothing is flagged. */
277
+ readonly reachableFromHeadUpstream: ReadonlySet<string> | undefined;
181
278
  readonly avatars: Map<string, string>;
182
279
  }
@@ -45,3 +45,36 @@ export interface GitTagReference {
45
45
  }
46
46
 
47
47
  export type GitReference = GitBranchReference | GitRevisionReference | GitStashReference | GitTagReference;
48
+
49
+ /**
50
+ * Lightweight ref-tip tuple — the minimum needed to map a SHA back to the refs that point at it.
51
+ * No upstream tracking, ahead/behind, annotation, etc. — use `GitBranch`/`GitTag` for those.
52
+ */
53
+ export interface GitRefTip {
54
+ readonly type: 'branch' | 'remote' | 'tag';
55
+ /** Short name: `main`, `origin/main`, `v1.2.0` */
56
+ readonly name: string;
57
+ /** Full refname: `refs/heads/main`, `refs/remotes/origin/main`, `refs/tags/v1.2.0` */
58
+ readonly fullName: string;
59
+ /** Tip object SHA. For annotated tags, the peeled commit SHA */
60
+ readonly sha: string;
61
+ }
62
+
63
+ /**
64
+ * Raw parsed `git for-each-ref` record covering every field the unified format emits.
65
+ * Inapplicable fields come back as empty strings from git (e.g. `upstream` on a tag,
66
+ * `peeledObjectname` on a branch).
67
+ */
68
+ export interface RefRecord {
69
+ current: string;
70
+ name: string;
71
+ objectname: string;
72
+ peeledObjectname: string;
73
+ upstream: string;
74
+ upstreamTracking: string;
75
+ committerDate: string;
76
+ creatorDate: string;
77
+ authorDate: string;
78
+ subject: string;
79
+ worktreePath?: string;
80
+ }
@@ -71,6 +71,7 @@ export class GitRemote<TProvider extends RemoteProvider | undefined = RemoteProv
71
71
  matches(urlOrDomain: string, path?: string): boolean {
72
72
  if (path == null) {
73
73
  if (equalsIgnoreCase(urlOrDomain, this.url)) return true;
74
+
74
75
  [, urlOrDomain, path] = parseGitRemoteUrl(urlOrDomain);
75
76
  }
76
77
 
@@ -74,6 +74,7 @@ export interface RemotesUrlsConfig {
74
74
  readonly fileInCommit: string;
75
75
  readonly fileLine: string;
76
76
  readonly fileRange: string;
77
+ readonly avatar?: string;
77
78
  }
78
79
 
79
80
  export abstract class RemoteProvider<T extends ResourceDescriptor = ResourceDescriptor> implements ProviderReference {
@@ -7,7 +7,6 @@ import type { UnifiedDisposable } from '../../utils/disposable.js';
7
7
  import { createDisposable } from '../../utils/disposable.js';
8
8
  import type { Event } from '../../utils/event.js';
9
9
  import { Emitter } from '../../utils/event.js';
10
- import { getScopedLogger } from '../../utils/logger.scoped.js';
11
10
  import { basename, normalizePath } from '../../utils/path.js';
12
11
  import type { Uri } from '../../utils/uri.js';
13
12
  import { fileUri } from '../../utils/uri.js';
@@ -84,8 +83,6 @@ export interface RepositoryInit {
84
83
  readonly gitDir: GitDir | undefined;
85
84
  readonly index: number;
86
85
  readonly root: boolean;
87
- readonly closed?: boolean;
88
- readonly suspended?: boolean;
89
86
  readonly watchService: RepositoryWatchService;
90
87
  }
91
88
 
@@ -118,19 +115,21 @@ export class Repository {
118
115
  readonly root: boolean;
119
116
 
120
117
  protected readonly _gitDir: GitDir | undefined;
121
- protected _pendingResumeTimer: ReturnType<typeof setTimeout> | undefined;
122
118
  protected _repoSubscription: RepositorySubscription | undefined;
123
- protected _suspended: boolean;
124
119
  protected _watchHandle: WatchHandle | undefined;
125
120
  protected readonly _watchService: RepositoryWatchService;
126
121
 
127
122
  private _pendingWorkingTreeChange?: RepositoryWorkingTreeChangeEvent;
128
123
  private _pendingWorkingTreeFlush = false;
129
124
  private _repoChangeListener: UnifiedDisposable | undefined;
125
+ /** Outstanding leases on the shared {@link _watchHandle} across `watch()` + `watchWorkingTree()`. */
126
+ private _watchHandleRefs = 0;
127
+ /** Outstanding `watch()` (repo-change) leases; drives the single shared bridge subscription. */
128
+ private _watchRefs = 0;
129
+ private _disposed = false;
130
130
 
131
131
  constructor(init: RepositoryInit) {
132
132
  ({
133
- closed: this._closed = init.closed ?? false,
134
133
  id: this.id,
135
134
  index: this.index,
136
135
  gitDir: this._gitDir,
@@ -138,7 +137,6 @@ export class Repository {
138
137
  path: this.path,
139
138
  provider: this.provider,
140
139
  root: this.root,
141
- suspended: this._suspended = init.suspended ?? false,
142
140
  uri: this.uri,
143
141
  watchService: this._watchService,
144
142
  } = init);
@@ -156,45 +154,25 @@ export class Repository {
156
154
  this._name = `${prefix}${this._name}`;
157
155
  }
158
156
  }
159
-
160
- this.setupWatching();
161
157
  }
162
158
 
163
159
  dispose(): void {
164
- clearTimeout(this._pendingResumeTimer);
160
+ this._disposed = true;
165
161
  this._repoChangeListener?.dispose();
166
162
  this._repoChangeListener = undefined;
167
163
  this._repoSubscription?.dispose();
168
164
  this._repoSubscription = undefined;
169
165
  this._watchHandle?.dispose();
170
166
  this._watchHandle = undefined;
167
+ this._watchHandleRefs = 0;
168
+ this._watchRefs = 0;
171
169
  this._onDidChange.dispose();
172
170
  this._onDidChangeWorkingTree.dispose();
173
171
  }
174
172
 
175
- protected _closed: boolean;
176
- get closed(): boolean {
177
- return this._closed;
178
- }
179
- set closed(value: boolean) {
180
- const changed = this._closed !== value;
181
- this._closed = value;
182
- if (changed) {
183
- if (this._closed) {
184
- // When closing, fire immediately even if suspended
185
- this.fireChange('closed', true);
186
-
187
- this._repoChangeListener?.dispose();
188
- this._repoChangeListener = undefined;
189
- this._repoSubscription?.dispose();
190
- this._repoSubscription = undefined;
191
- } else {
192
- this.setupWatching();
193
- this.fireChange('opened');
194
- }
195
-
196
- this.onClosedChanged(value);
197
- }
173
+ /** Indicates whether this repository currently has an active `watch()` (repo-change) lease. */
174
+ get watching(): boolean {
175
+ return this._watchRefs > 0;
198
176
  }
199
177
 
200
178
  get etag(): number {
@@ -249,41 +227,6 @@ export class Repository {
249
227
  return this.provider.virtual;
250
228
  }
251
229
 
252
- @trace({ onlyExit: true })
253
- suspend(): void {
254
- this._suspended = true;
255
- this._watchHandle?.session.suspend();
256
-
257
- if (this._pendingResumeTimer != null) {
258
- clearTimeout(this._pendingResumeTimer);
259
- this._pendingResumeTimer = undefined;
260
- }
261
- }
262
-
263
- @trace({ onlyExit: true })
264
- resume(delayMs?: number): void {
265
- if (delayMs) {
266
- if (this._pendingResumeTimer != null) {
267
- clearTimeout(this._pendingResumeTimer);
268
- }
269
- this._pendingResumeTimer = setTimeout(() => {
270
- this._pendingResumeTimer = undefined;
271
- this.resume();
272
- }, delayMs);
273
- return;
274
- }
275
-
276
- const scope = getScopedLogger();
277
-
278
- if (!this._suspended) {
279
- scope?.addExitInfo('ignored; not suspended');
280
- return;
281
- }
282
-
283
- this._suspended = false;
284
- this._watchHandle?.session.resume();
285
- }
286
-
287
230
  waitForRepoChange(timeoutMs: number): Promise<boolean> {
288
231
  let timeoutId: ReturnType<typeof setTimeout> | undefined;
289
232
  let listener: UnifiedDisposable | undefined;
@@ -313,17 +256,57 @@ export class Repository {
313
256
  ]);
314
257
  }
315
258
 
259
+ /**
260
+ * Starts watching this repository's `.git` directory for repo-change events (delivered via
261
+ * {@link onDidChange}) and returns a lease. Ref-counted: the underlying watch handle is acquired
262
+ * on the first lease (across `watch()` and {@link watchWorkingTree}) and released when the last
263
+ * is disposed. The model is inert until watched. No-ops (returns a disposable that does nothing)
264
+ * for repositories without a git directory (e.g. virtual repos).
265
+ */
266
+ @trace({ onlyExit: true })
267
+ watch(): UnifiedDisposable {
268
+ const acquired = this.acquireWatchHandle();
269
+ if (acquired == null) return createDisposable(() => {});
270
+
271
+ if (this._watchRefs++ === 0) {
272
+ const sub = acquired.handle.session.subscribe();
273
+ this._repoSubscription = sub;
274
+ this._repoChangeListener = sub.onDidChange(e => this.onSessionRepoChange(e));
275
+ }
276
+
277
+ return createDisposable(
278
+ () => {
279
+ // Repo already torn down — its handle/subscriptions are gone; skip to avoid a negative refcount
280
+ if (this._disposed) return;
281
+
282
+ if (--this._watchRefs === 0) {
283
+ this._repoChangeListener?.dispose();
284
+ this._repoChangeListener = undefined;
285
+ this._repoSubscription?.dispose();
286
+ this._repoSubscription = undefined;
287
+ }
288
+ acquired.lease.dispose();
289
+ },
290
+ { once: true },
291
+ );
292
+ }
293
+
316
294
  @trace({ onlyExit: true })
317
295
  watchWorkingTree(delay: number = 2500): UnifiedDisposable {
318
- const sub = this._watchHandle?.session.subscribeToWorkingTree({ delayMs: delay });
319
- if (sub == null) return createDisposable(() => {});
296
+ const acquired = this.acquireWatchHandle();
297
+ if (acquired == null) return createDisposable(() => {});
320
298
 
299
+ const sub = acquired.handle.session.subscribeToWorkingTree({ delayMs: delay });
321
300
  const listener = sub.onDidChangeWorkingTree(e => this.onWorkingTreeChanged(e.paths));
322
301
 
323
- return createDisposable(() => {
324
- listener.dispose();
325
- sub.dispose();
326
- });
302
+ return createDisposable(
303
+ () => {
304
+ listener.dispose();
305
+ sub.dispose();
306
+ acquired.lease.dispose();
307
+ },
308
+ { once: true },
309
+ );
327
310
  }
328
311
 
329
312
  /**
@@ -338,7 +321,7 @@ export class Repository {
338
321
  protected fireChange(change: RepositoryChange, force: boolean): void;
339
322
  @trace()
340
323
  protected fireChange(...args: RepositoryChange[] | [RepositoryChange, boolean]): void {
341
- const lastArg = args[args.length - 1];
324
+ const lastArg = args.at(-1);
342
325
  const force = typeof lastArg === 'boolean' ? lastArg : false;
343
326
  const changes = (force ? args.slice(0, -1) : args) as RepositoryChange[];
344
327
 
@@ -353,14 +336,28 @@ export class Repository {
353
336
  this._watchHandle?.session.fireChange(...changes);
354
337
  }
355
338
 
356
- /** Called when the closed state changes. Override to add behavior (e.g., branch access tracking). */
357
- protected onClosedChanged(_closed: boolean): void {}
358
-
359
339
  /** Called when the watch service notifies of FETCH_HEAD changes. */
360
340
  protected onFetchHeadChanged(): void {
361
- this._lastFetched = undefined;
362
- // Force-fire so the event arrives immediately (no debounce); downstream consumers must
363
- // invalidate any cached fetch timestamp before reading a fresh value.
341
+ // Don't reset `_lastFetched` here: the FS watcher can fire even when the on-disk mtime
342
+ // hasn't advanced (atomic-rename / lock-file activity emits `change` events without an
343
+ // mtime bump), and wiping would clobber a fresher value set by `markFetched()`.
344
+ // `getLastFetched()` reconciles in-memory vs FS via `Math.max`. Force-fire so consumers
345
+ // invalidate their caches and re-read.
346
+ this.fireChange('lastFetched', true);
347
+ }
348
+
349
+ /**
350
+ * Marks the repository as having just been fetched. Use after a GitLens-initiated fetch/pull
351
+ * completes so the "last fetched" UI tracks the attempt even when git skipped rewriting
352
+ * `.git/FETCH_HEAD` (modern git omits the rewrite when all refs are up-to-date). The
353
+ * in-memory timestamp is reconciled with the on-disk mtime by {@link getLastFetched} via
354
+ * `Math.max`, so this is monotonic.
355
+ */
356
+ markFetched(timestamp: number = Date.now()): void {
357
+ const next = Math.max(this._lastFetched ?? 0, timestamp);
358
+ if (next === this._lastFetched) return;
359
+
360
+ this._lastFetched = next;
364
361
  this.fireChange('lastFetched', true);
365
362
  }
366
363
 
@@ -397,38 +394,50 @@ export class Repository {
397
394
  (this._pendingWorkingTreeChange.uris as Set<Uri>).add(fileUri(p));
398
395
  }
399
396
 
400
- if (this._suspended) return;
401
397
  if (this._pendingWorkingTreeFlush) return;
402
398
 
403
399
  this._pendingWorkingTreeFlush = true;
404
400
  queueMicrotask(() => {
405
401
  this._pendingWorkingTreeFlush = false;
406
402
  const e = this._pendingWorkingTreeChange;
407
- if (e == null || this._suspended) return;
403
+ if (e == null) return;
404
+
408
405
  this._pendingWorkingTreeChange = undefined;
409
406
  this._onDidChangeWorkingTree.fire(e);
410
407
  });
411
408
  }
412
409
 
413
- @trace({ onlyExit: true })
414
- private setupWatching(): void {
415
- if (this._gitDir == null || this._closed) return;
416
- if (this._repoSubscription != null) return;
417
-
418
- const scope = getScopedLogger();
410
+ /**
411
+ * Lazily acquires (and ref-counts) the shared {@link _watchHandle} for this repository, returning
412
+ * the handle plus a one-shot lease whose disposal decrements the ref count (releasing the handle
413
+ * when the last lease is gone). Returns `undefined` for repositories without a git directory.
414
+ */
415
+ private acquireWatchHandle(): { handle: WatchHandle; lease: UnifiedDisposable } | undefined {
416
+ if (this._gitDir == null || this._disposed) return undefined;
419
417
 
420
418
  this._watchHandle ??= this._watchService.watch(this.path, this._gitDir, {
421
419
  onFetchHeadChanged: () => this.onFetchHeadChanged(),
422
420
  onGitIgnoreChanged: () => this.onGitIgnoreChanged(),
423
421
  onIgnoresChanged: () => this.onIgnoresChanged(),
424
422
  } satisfies WatchHooks);
425
- if (this._watchHandle == null) return;
426
-
427
- const sub = this._watchHandle.session.subscribe();
428
- this._repoSubscription = sub;
429
- this._repoChangeListener = sub.onDidChange(e => this.onSessionRepoChange(e));
430
-
431
- scope?.trace(`subscribed to repo changes for '${this.uri.toString()}'`);
423
+ const handle = this._watchHandle;
424
+ if (handle == null) return undefined;
425
+
426
+ this._watchHandleRefs++;
427
+ const lease = createDisposable(
428
+ () => {
429
+ // Repo already torn down — the handle is gone; skip to avoid a negative refcount
430
+ if (this._disposed) return;
431
+
432
+ if (--this._watchHandleRefs === 0) {
433
+ this._watchHandle?.dispose();
434
+ this._watchHandle = undefined;
435
+ }
436
+ },
437
+ { once: true },
438
+ );
439
+
440
+ return { handle: handle, lease: lease };
432
441
  }
433
442
 
434
443
  static is(repository: unknown): repository is Repository {
@@ -96,8 +96,8 @@ export interface ParsedSearchQuery {
96
96
  export interface SearchQueryFilters {
97
97
  /** Specifies whether the search results will be filtered to specific files */
98
98
  files: boolean;
99
- /** Specifies whether the search results will be filtered to a specific type, only `stash` and `tip` are supported */
100
- type?: 'stash' | 'tip';
99
+ /** Specifies whether the search results will be filtered to a specific type, only `stash`, `tip`, and `wip` are supported */
100
+ type?: 'stash' | 'tip' | 'wip';
101
101
  /** Specifies whether the search results will be filtered to a specific ref or ref range */
102
102
  refs: boolean;
103
103
  }
@@ -94,6 +94,18 @@ export class GitStatusFile implements GitFile {
94
94
  return this.conflictStatus != null;
95
95
  }
96
96
 
97
+ /**
98
+ * True when the file has both staged (index) and unstaged (working-tree) changes and is not
99
+ * conflicted. Used by the host-side discard flows to apply partial-discard semantics — drop the
100
+ * working-tree delta while preserving the staged portion. Centralized here so those host paths
101
+ * agree on what "mixed" means. (The webview button predicate can't consume this getter — it
102
+ * runs against the wire `GitFileChangeShape` and infers the same state from the duplicate
103
+ * staged/unstaged rows the WIP feed emits per mixed path.)
104
+ */
105
+ get mixed(): boolean {
106
+ return this.indexStatus != null && this.workingTreeStatus != null && this.conflictStatus == null;
107
+ }
108
+
97
109
  get staged(): boolean {
98
110
  return this.indexStatus != null;
99
111
  }
@@ -6,6 +6,7 @@ import { basename, normalizePath, relative } from '../../utils/path.js';
6
6
  import type { Shape } from '../../utils/types.js';
7
7
  import type { Uri } from '../../utils/uri.js';
8
8
  import { getRepositoryService } from '../repositoryService.js';
9
+ import type { GitCommandPriority } from '../run.types.js';
9
10
  import { getRepositoryOrWorktreePath } from '../utils/repository.utils.js';
10
11
  import { shortenRevision } from '../utils/revision.utils.js';
11
12
  import type { GitBranch } from './branch.js';
@@ -73,6 +74,7 @@ export class GitWorktree {
73
74
  const relativePath = normalizePath(relative(this.workspaceFolder.uri.fsPath, this.uri.fsPath));
74
75
  return relativePath || this.workspaceFolder.name;
75
76
  }
77
+
76
78
  const relativePath = normalizePath(relative(this.repoPath, this.uri.fsPath));
77
79
  return relativePath || normalizePath(this.uri.fsPath);
78
80
  }
@@ -135,10 +137,15 @@ export class GitWorktree {
135
137
  : GitWorktree.formatDateFromNow(worktree);
136
138
  }
137
139
 
138
- static async getStatus(worktree: GitWorktree, cancellation?: AbortSignal): Promise<GitStatus | undefined> {
140
+ static async getStatus(
141
+ worktree: GitWorktree,
142
+ options?: { priority?: GitCommandPriority },
143
+ cancellation?: AbortSignal,
144
+ ): Promise<GitStatus | undefined> {
139
145
  if (worktree.type === 'bare') return undefined;
146
+
140
147
  const repo = getRepositoryService(worktree.path);
141
- return repo?.status.getStatus(cancellation);
148
+ return repo?.status.getStatus(options, cancellation);
142
149
  }
143
150
 
144
151
  static async hasWorkingChanges(
@@ -146,6 +153,7 @@ export class GitWorktree {
146
153
  options?: { staged?: boolean; unstaged?: boolean; untracked?: boolean },
147
154
  ): Promise<boolean | undefined> {
148
155
  if (worktree.type === 'bare') return undefined;
156
+
149
157
  const repo = getRepositoryService(worktree.path);
150
158
  return repo?.status.hasWorkingChanges(options);
151
159
  }
@@ -413,6 +413,7 @@ export function parseGitDiffNumStatFiles(data: string, repoPath: string): GitFil
413
413
  i++;
414
414
  continue;
415
415
  }
416
+
416
417
  const tabIndex2 = field.indexOf('\t', tabIndex1 + 1);
417
418
  if (tabIndex2 === -1) {
418
419
  i++;
@@ -427,6 +428,7 @@ export function parseGitDiffNumStatFiles(data: string, repoPath: string): GitFil
427
428
  if (path === '') {
428
429
  // Rename or copy: next two fields are oldPath and newPath (summary pass distinguishes R vs C)
429
430
  if (i + 2 >= fields.length) break;
431
+
430
432
  originalPath = fields[++i];
431
433
  path = fields[++i];
432
434
  }
@@ -1,10 +1,12 @@
1
1
  import type { PagedResult, PagingOptions } from '../../utils/paging.js';
2
+ import type { GkConfigInvalidationTarget } from '../cache.js';
2
3
  import type { BranchDisposition, GitBranch } from '../models/branch.js';
3
4
  import type { GitCommitStats } from '../models/commit.js';
4
5
  import type { GitContributor } from '../models/contributor.js';
5
6
  import type { ConflictDetectionResult } from '../models/mergeConflicts.js';
6
7
  import type { PullRequest } from '../models/pullRequest.js';
7
8
  import type { GitBranchReference } from '../models/reference.js';
9
+ import type { GitCommandPriority } from '../run.types.js';
8
10
  import type { BranchSortOptions } from '../utils/sorting.js';
9
11
 
10
12
  export interface BranchContributionsOverview extends GitCommitStats<number> {
@@ -43,7 +45,7 @@ export interface GitBranchesSubProvider {
43
45
  getBranchContributionsOverview(
44
46
  repoPath: string,
45
47
  ref: string,
46
- options?: { associatedPullRequest?: Promise<PullRequest | undefined> },
48
+ options?: { associatedPullRequest?: Promise<PullRequest | undefined>; priority?: GitCommandPriority },
47
49
  cancellation?: AbortSignal,
48
50
  ): Promise<BranchContributionsOverview | undefined>;
49
51
  getBranchesWithCommits(
@@ -58,6 +60,7 @@ export interface GitBranchesSubProvider {
58
60
  getDefaultBranchName(
59
61
  repoPath: string | undefined,
60
62
  remote?: string,
63
+ options?: { priority?: GitCommandPriority },
61
64
  cancellation?: AbortSignal,
62
65
  ): Promise<string | undefined>;
63
66
 
@@ -94,7 +97,12 @@ export interface GitBranchesSubProvider {
94
97
  targetBranch: string,
95
98
  cancellation?: AbortSignal,
96
99
  ): Promise<ConflictDetectionResult>;
97
- getBaseBranchName?(repoPath: string, ref: string, cancellation?: AbortSignal): Promise<string | undefined>;
100
+ getBaseBranchName?(
101
+ repoPath: string,
102
+ ref: string,
103
+ options?: { priority?: GitCommandPriority },
104
+ cancellation?: AbortSignal,
105
+ ): Promise<string | undefined>;
98
106
  getStoredMergeTargetBranchName?(repoPath: string, ref: string): Promise<string | undefined>;
99
107
  getStoredDetectedMergeTargetBranchName?(repoPath: string, ref: string): Promise<string | undefined>;
100
108
  getStoredUserMergeTargetBranchName?(repoPath: string, ref: string): Promise<string | undefined>;
@@ -108,7 +116,17 @@ export interface GitBranchesSubProvider {
108
116
  branchName: string,
109
117
  disposition: BranchDisposition | undefined,
110
118
  ): Promise<void>;
111
- storeBaseBranchName?(repoPath: string, ref: string, base: string): Promise<void>;
112
- storeMergeTargetBranchName?(repoPath: string, ref: string, target: string): Promise<void>;
119
+ storeBaseBranchName?(
120
+ repoPath: string,
121
+ ref: string,
122
+ base: string,
123
+ options?: { skipInvalidation?: readonly GkConfigInvalidationTarget[] },
124
+ ): Promise<void>;
125
+ storeMergeTargetBranchName?(
126
+ repoPath: string,
127
+ ref: string,
128
+ target: string,
129
+ options?: { skipInvalidation?: readonly GkConfigInvalidationTarget[] },
130
+ ): Promise<void>;
113
131
  storeUserMergeTargetBranchName?(repoPath: string, ref: string, target: string | undefined): Promise<void>;
114
132
  }
@@ -78,6 +78,10 @@ export interface GitCommitReachability {
78
78
  export interface GitCommitsSubProvider {
79
79
  getCommit(repoPath: string, rev: string, cancellation?: AbortSignal): Promise<GitCommit | undefined>;
80
80
  getCommitCount(repoPath: string, rev: string, cancellation?: AbortSignal): Promise<number | undefined>;
81
+ /** Whether `rev` has any commits not reachable from any remote-tracking ref (i.e. unpushed/unpublished).
82
+ * Cheap early-exit probe (`rev-list --not --remotes <rev> -n 1`) — it does NOT count them. Returns
83
+ * `undefined` when it can't be determined. */
84
+ hasUnpublishedCommits?(repoPath: string, rev: string, cancellation?: AbortSignal): Promise<boolean | undefined>;
81
85
  /** Cheap author/committer date lookup for a single revision. Skips the full commit parse (no files, parents, or message) — use when only the dates are needed. Pass a full SHA so caching stays correct (commits are immutable; refs are not). */
82
86
  getCommitDates?(
83
87
  repoPath: string,