@camaradesuk/git-worktree-tools 1.9.0 → 1.11.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 (531) hide show
  1. package/README.md +52 -31
  2. package/dist/cli/cleanpr.js +74 -53
  3. package/dist/cli/cleanpr.js.map +1 -1
  4. package/dist/cli/lswt.js +32 -56
  5. package/dist/cli/lswt.js.map +1 -1
  6. package/dist/cli/newpr.d.ts +13 -1
  7. package/dist/cli/newpr.d.ts.map +1 -1
  8. package/dist/cli/newpr.js +159 -153
  9. package/dist/cli/newpr.js.map +1 -1
  10. package/dist/cli/prs.d.ts +3 -10
  11. package/dist/cli/prs.d.ts.map +1 -1
  12. package/dist/cli/prs.js +6 -168
  13. package/dist/cli/prs.js.map +1 -1
  14. package/dist/cli/wt/clean.d.ts +6 -2
  15. package/dist/cli/wt/clean.d.ts.map +1 -1
  16. package/dist/cli/wt/clean.js +401 -20
  17. package/dist/cli/wt/clean.js.map +1 -1
  18. package/dist/cli/wt/completion.d.ts +3 -0
  19. package/dist/cli/wt/completion.d.ts.map +1 -1
  20. package/dist/cli/wt/completion.js +80 -9
  21. package/dist/cli/wt/completion.js.map +1 -1
  22. package/dist/cli/wt/config.d.ts +3 -1
  23. package/dist/cli/wt/config.d.ts.map +1 -1
  24. package/dist/cli/wt/config.js +323 -32
  25. package/dist/cli/wt/config.js.map +1 -1
  26. package/dist/cli/wt/interactive-menu.d.ts +2 -0
  27. package/dist/cli/wt/interactive-menu.d.ts.map +1 -1
  28. package/dist/cli/wt/interactive-menu.js +346 -73
  29. package/dist/cli/wt/interactive-menu.js.map +1 -1
  30. package/dist/cli/wt/link.d.ts +3 -1
  31. package/dist/cli/wt/link.d.ts.map +1 -1
  32. package/dist/cli/wt/link.js +125 -38
  33. package/dist/cli/wt/link.js.map +1 -1
  34. package/dist/cli/wt/list.d.ts +4 -1
  35. package/dist/cli/wt/list.d.ts.map +1 -1
  36. package/dist/cli/wt/list.js +85 -16
  37. package/dist/cli/wt/list.js.map +1 -1
  38. package/dist/cli/wt/new.d.ts +8 -2
  39. package/dist/cli/wt/new.d.ts.map +1 -1
  40. package/dist/cli/wt/new.js +91 -46
  41. package/dist/cli/wt/new.js.map +1 -1
  42. package/dist/cli/wt/prs.d.ts +2 -1
  43. package/dist/cli/wt/prs.d.ts.map +1 -1
  44. package/dist/cli/wt/prs.js +3 -164
  45. package/dist/cli/wt/prs.js.map +1 -1
  46. package/dist/cli/wt/run-command.d.ts +4 -2
  47. package/dist/cli/wt/run-command.d.ts.map +1 -1
  48. package/dist/cli/wt/run-command.js +6 -4
  49. package/dist/cli/wt/run-command.js.map +1 -1
  50. package/dist/cli/wt/state.d.ts +3 -1
  51. package/dist/cli/wt/state.d.ts.map +1 -1
  52. package/dist/cli/wt/state.js +74 -10
  53. package/dist/cli/wt/state.js.map +1 -1
  54. package/dist/cli/wt.d.ts.map +1 -1
  55. package/dist/cli/wt.js +50 -36
  56. package/dist/cli/wt.js.map +1 -1
  57. package/dist/cli/wtconfig.js +99 -22
  58. package/dist/cli/wtconfig.js.map +1 -1
  59. package/dist/cli/wtlink.js +85 -61
  60. package/dist/cli/wtlink.js.map +1 -1
  61. package/dist/cli/wtstate.js +21 -2
  62. package/dist/cli/wtstate.js.map +1 -1
  63. package/dist/lib/cleanpr/args.d.ts.map +1 -1
  64. package/dist/lib/cleanpr/args.js +20 -0
  65. package/dist/lib/cleanpr/args.js.map +1 -1
  66. package/dist/lib/cleanpr/types.d.ts +6 -0
  67. package/dist/lib/cleanpr/types.d.ts.map +1 -1
  68. package/dist/lib/colors.d.ts +5 -0
  69. package/dist/lib/colors.d.ts.map +1 -1
  70. package/dist/lib/colors.js +13 -6
  71. package/dist/lib/colors.js.map +1 -1
  72. package/dist/lib/constants.d.ts +12 -4
  73. package/dist/lib/constants.d.ts.map +1 -1
  74. package/dist/lib/constants.js +24 -5
  75. package/dist/lib/constants.js.map +1 -1
  76. package/dist/lib/deprecation.d.ts +18 -0
  77. package/dist/lib/deprecation.d.ts.map +1 -0
  78. package/dist/lib/deprecation.js +28 -0
  79. package/dist/lib/deprecation.js.map +1 -0
  80. package/dist/lib/logger.d.ts +40 -155
  81. package/dist/lib/logger.d.ts.map +1 -1
  82. package/dist/lib/logger.js +349 -420
  83. package/dist/lib/logger.js.map +1 -1
  84. package/dist/lib/lswt/args.d.ts.map +1 -1
  85. package/dist/lib/lswt/args.js +15 -1
  86. package/dist/lib/lswt/args.js.map +1 -1
  87. package/dist/lib/lswt/index.d.ts +1 -0
  88. package/dist/lib/lswt/index.d.ts.map +1 -1
  89. package/dist/lib/lswt/index.js +2 -0
  90. package/dist/lib/lswt/index.js.map +1 -1
  91. package/dist/lib/lswt/table.d.ts +15 -0
  92. package/dist/lib/lswt/table.d.ts.map +1 -0
  93. package/dist/lib/lswt/table.js +61 -0
  94. package/dist/lib/lswt/table.js.map +1 -0
  95. package/dist/lib/lswt/types.d.ts +4 -0
  96. package/dist/lib/lswt/types.d.ts.map +1 -1
  97. package/dist/lib/newpr/args.d.ts.map +1 -1
  98. package/dist/lib/newpr/args.js +21 -0
  99. package/dist/lib/newpr/args.js.map +1 -1
  100. package/dist/lib/newpr/types.d.ts +6 -0
  101. package/dist/lib/newpr/types.d.ts.map +1 -1
  102. package/dist/lib/prs/command.d.ts +21 -0
  103. package/dist/lib/prs/command.d.ts.map +1 -0
  104. package/dist/lib/prs/command.js +175 -0
  105. package/dist/lib/prs/command.js.map +1 -0
  106. package/dist/lib/prs/interactive.d.ts.map +1 -1
  107. package/dist/lib/prs/interactive.js +15 -2
  108. package/dist/lib/prs/interactive.js.map +1 -1
  109. package/dist/lib/prs/types.d.ts +15 -0
  110. package/dist/lib/prs/types.d.ts.map +1 -1
  111. package/dist/lib/ui/error.d.ts +31 -0
  112. package/dist/lib/ui/error.d.ts.map +1 -0
  113. package/dist/lib/ui/error.js +47 -0
  114. package/dist/lib/ui/error.js.map +1 -0
  115. package/dist/lib/ui/index.d.ts +15 -0
  116. package/dist/lib/ui/index.d.ts.map +1 -0
  117. package/dist/lib/ui/index.js +19 -0
  118. package/dist/lib/ui/index.js.map +1 -0
  119. package/dist/lib/ui/output.d.ts +18 -0
  120. package/dist/lib/ui/output.d.ts.map +1 -0
  121. package/dist/lib/ui/output.js +31 -0
  122. package/dist/lib/ui/output.js.map +1 -0
  123. package/dist/lib/ui/spinner.d.ts +10 -0
  124. package/dist/lib/ui/spinner.d.ts.map +1 -0
  125. package/dist/lib/ui/spinner.js +10 -0
  126. package/dist/lib/ui/spinner.js.map +1 -0
  127. package/dist/lib/ui/status.d.ts +65 -0
  128. package/dist/lib/ui/status.d.ts.map +1 -0
  129. package/dist/lib/ui/status.js +100 -0
  130. package/dist/lib/ui/status.js.map +1 -0
  131. package/dist/lib/ui/table.d.ts +39 -0
  132. package/dist/lib/ui/table.d.ts.map +1 -0
  133. package/dist/lib/ui/table.js +45 -0
  134. package/dist/lib/ui/table.js.map +1 -0
  135. package/dist/lib/ui/theme.d.ts +34 -0
  136. package/dist/lib/ui/theme.d.ts.map +1 -0
  137. package/dist/lib/ui/theme.js +37 -0
  138. package/dist/lib/ui/theme.js.map +1 -0
  139. package/dist/lib/wtlink/link-configs.js +7 -7
  140. package/dist/lib/wtlink/link-configs.js.map +1 -1
  141. package/dist/lib/wtlink/validate-manifest.d.ts.map +1 -1
  142. package/dist/lib/wtlink/validate-manifest.js +5 -5
  143. package/dist/lib/wtlink/validate-manifest.js.map +1 -1
  144. package/dist/lib/wtstate/args.d.ts.map +1 -1
  145. package/dist/lib/wtstate/args.js +2 -0
  146. package/dist/lib/wtstate/args.js.map +1 -1
  147. package/dist/mcp/server.d.ts +2 -1
  148. package/dist/mcp/server.d.ts.map +1 -1
  149. package/dist/mcp/server.js +264 -44
  150. package/dist/mcp/server.js.map +1 -1
  151. package/package.json +13 -3
  152. package/dist/api/list.test.d.ts +0 -5
  153. package/dist/api/list.test.d.ts.map +0 -1
  154. package/dist/api/list.test.js +0 -390
  155. package/dist/api/list.test.js.map +0 -1
  156. package/dist/cli/cleanpr.test.d.ts +0 -2
  157. package/dist/cli/cleanpr.test.d.ts.map +0 -1
  158. package/dist/cli/cleanpr.test.js +0 -954
  159. package/dist/cli/cleanpr.test.js.map +0 -1
  160. package/dist/cli/lswt.test.d.ts +0 -2
  161. package/dist/cli/lswt.test.d.ts.map +0 -1
  162. package/dist/cli/lswt.test.js +0 -386
  163. package/dist/cli/lswt.test.js.map +0 -1
  164. package/dist/cli/newpr.test.d.ts +0 -2
  165. package/dist/cli/newpr.test.d.ts.map +0 -1
  166. package/dist/cli/newpr.test.js +0 -1182
  167. package/dist/cli/newpr.test.js.map +0 -1
  168. package/dist/cli/prs.test.d.ts +0 -8
  169. package/dist/cli/prs.test.d.ts.map +0 -1
  170. package/dist/cli/prs.test.js +0 -410
  171. package/dist/cli/prs.test.js.map +0 -1
  172. package/dist/cli/wt/completion.test.d.ts +0 -5
  173. package/dist/cli/wt/completion.test.d.ts.map +0 -1
  174. package/dist/cli/wt/completion.test.js +0 -173
  175. package/dist/cli/wt/completion.test.js.map +0 -1
  176. package/dist/cli/wt/config.test.d.ts +0 -5
  177. package/dist/cli/wt/config.test.d.ts.map +0 -1
  178. package/dist/cli/wt/config.test.js +0 -260
  179. package/dist/cli/wt/config.test.js.map +0 -1
  180. package/dist/cli/wt/entry.test.d.ts +0 -8
  181. package/dist/cli/wt/entry.test.d.ts.map +0 -1
  182. package/dist/cli/wt/entry.test.js +0 -201
  183. package/dist/cli/wt/entry.test.js.map +0 -1
  184. package/dist/cli/wt/init.test.d.ts +0 -5
  185. package/dist/cli/wt/init.test.d.ts.map +0 -1
  186. package/dist/cli/wt/init.test.js +0 -165
  187. package/dist/cli/wt/init.test.js.map +0 -1
  188. package/dist/cli/wt/init.unit.test.d.ts +0 -5
  189. package/dist/cli/wt/init.unit.test.d.ts.map +0 -1
  190. package/dist/cli/wt/init.unit.test.js +0 -432
  191. package/dist/cli/wt/init.unit.test.js.map +0 -1
  192. package/dist/cli/wt/interactive-menu.test.d.ts +0 -10
  193. package/dist/cli/wt/interactive-menu.test.d.ts.map +0 -1
  194. package/dist/cli/wt/interactive-menu.test.js +0 -739
  195. package/dist/cli/wt/interactive-menu.test.js.map +0 -1
  196. package/dist/cli/wt/prs.test.d.ts +0 -5
  197. package/dist/cli/wt/prs.test.d.ts.map +0 -1
  198. package/dist/cli/wt/prs.test.js +0 -410
  199. package/dist/cli/wt/prs.test.js.map +0 -1
  200. package/dist/cli/wt/run-command.test.d.ts +0 -5
  201. package/dist/cli/wt/run-command.test.d.ts.map +0 -1
  202. package/dist/cli/wt/run-command.test.js +0 -88
  203. package/dist/cli/wt/run-command.test.js.map +0 -1
  204. package/dist/cli/wt/wt.test.d.ts +0 -8
  205. package/dist/cli/wt/wt.test.d.ts.map +0 -1
  206. package/dist/cli/wt/wt.test.js +0 -521
  207. package/dist/cli/wt/wt.test.js.map +0 -1
  208. package/dist/cli/wt.unit.test.d.ts +0 -7
  209. package/dist/cli/wt.unit.test.d.ts.map +0 -1
  210. package/dist/cli/wt.unit.test.js +0 -182
  211. package/dist/cli/wt.unit.test.js.map +0 -1
  212. package/dist/cli/wtconfig.test.d.ts +0 -5
  213. package/dist/cli/wtconfig.test.d.ts.map +0 -1
  214. package/dist/cli/wtconfig.test.js +0 -1289
  215. package/dist/cli/wtconfig.test.js.map +0 -1
  216. package/dist/cli/wtlink.test.d.ts +0 -2
  217. package/dist/cli/wtlink.test.d.ts.map +0 -1
  218. package/dist/cli/wtlink.test.js +0 -249
  219. package/dist/cli/wtlink.test.js.map +0 -1
  220. package/dist/cli/wtstate.test.d.ts +0 -5
  221. package/dist/cli/wtstate.test.d.ts.map +0 -1
  222. package/dist/cli/wtstate.test.js +0 -193
  223. package/dist/cli/wtstate.test.js.map +0 -1
  224. package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts +0 -2
  225. package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts.map +0 -1
  226. package/dist/e2e/cleanpr/cleanpr.e2e.test.js +0 -326
  227. package/dist/e2e/cleanpr/cleanpr.e2e.test.js.map +0 -1
  228. package/dist/e2e/cli.e2e.test.d.ts +0 -2
  229. package/dist/e2e/cli.e2e.test.d.ts.map +0 -1
  230. package/dist/e2e/cli.e2e.test.js +0 -417
  231. package/dist/e2e/cli.e2e.test.js.map +0 -1
  232. package/dist/e2e/lswt/lswt.e2e.test.d.ts +0 -2
  233. package/dist/e2e/lswt/lswt.e2e.test.d.ts.map +0 -1
  234. package/dist/e2e/lswt/lswt.e2e.test.js +0 -361
  235. package/dist/e2e/lswt/lswt.e2e.test.js.map +0 -1
  236. package/dist/e2e/newpr/newpr.e2e.test.d.ts +0 -2
  237. package/dist/e2e/newpr/newpr.e2e.test.d.ts.map +0 -1
  238. package/dist/e2e/newpr/newpr.e2e.test.js +0 -286
  239. package/dist/e2e/newpr/newpr.e2e.test.js.map +0 -1
  240. package/dist/e2e/newpr/scenarios.e2e.test.d.ts +0 -2
  241. package/dist/e2e/newpr/scenarios.e2e.test.d.ts.map +0 -1
  242. package/dist/e2e/newpr/scenarios.e2e.test.js +0 -426
  243. package/dist/e2e/newpr/scenarios.e2e.test.js.map +0 -1
  244. package/dist/e2e/newpr-full-flow.e2e.test.d.ts +0 -2
  245. package/dist/e2e/newpr-full-flow.e2e.test.d.ts.map +0 -1
  246. package/dist/e2e/newpr-full-flow.e2e.test.js +0 -280
  247. package/dist/e2e/newpr-full-flow.e2e.test.js.map +0 -1
  248. package/dist/e2e/prs/prs.e2e.test.d.ts +0 -7
  249. package/dist/e2e/prs/prs.e2e.test.d.ts.map +0 -1
  250. package/dist/e2e/prs/prs.e2e.test.js +0 -606
  251. package/dist/e2e/prs/prs.e2e.test.js.map +0 -1
  252. package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts +0 -2
  253. package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts.map +0 -1
  254. package/dist/e2e/workflows/pr-lifecycle.e2e.test.js +0 -298
  255. package/dist/e2e/workflows/pr-lifecycle.e2e.test.js.map +0 -1
  256. package/dist/e2e/wt/interactive-menu.e2e.test.d.ts +0 -8
  257. package/dist/e2e/wt/interactive-menu.e2e.test.d.ts.map +0 -1
  258. package/dist/e2e/wt/interactive-menu.e2e.test.js +0 -583
  259. package/dist/e2e/wt/interactive-menu.e2e.test.js.map +0 -1
  260. package/dist/e2e/wt/wt.e2e.test.d.ts +0 -9
  261. package/dist/e2e/wt/wt.e2e.test.d.ts.map +0 -1
  262. package/dist/e2e/wt/wt.e2e.test.js +0 -597
  263. package/dist/e2e/wt/wt.e2e.test.js.map +0 -1
  264. package/dist/e2e/wtlink/wtlink.e2e.test.d.ts +0 -2
  265. package/dist/e2e/wtlink/wtlink.e2e.test.d.ts.map +0 -1
  266. package/dist/e2e/wtlink/wtlink.e2e.test.js +0 -416
  267. package/dist/e2e/wtlink/wtlink.e2e.test.js.map +0 -1
  268. package/dist/integration/git.integration.test.d.ts +0 -2
  269. package/dist/integration/git.integration.test.d.ts.map +0 -1
  270. package/dist/integration/git.integration.test.js +0 -336
  271. package/dist/integration/git.integration.test.js.map +0 -1
  272. package/dist/integration/lswt-remote-pr.integration.test.d.ts +0 -2
  273. package/dist/integration/lswt-remote-pr.integration.test.d.ts.map +0 -1
  274. package/dist/integration/lswt-remote-pr.integration.test.js +0 -222
  275. package/dist/integration/lswt-remote-pr.integration.test.js.map +0 -1
  276. package/dist/integration/newpr-branchfrom-head.integration.test.d.ts +0 -2
  277. package/dist/integration/newpr-branchfrom-head.integration.test.d.ts.map +0 -1
  278. package/dist/integration/newpr-branchfrom-head.integration.test.js +0 -498
  279. package/dist/integration/newpr-branchfrom-head.integration.test.js.map +0 -1
  280. package/dist/integration/newpr.integration.test.d.ts +0 -2
  281. package/dist/integration/newpr.integration.test.d.ts.map +0 -1
  282. package/dist/integration/newpr.integration.test.js +0 -460
  283. package/dist/integration/newpr.integration.test.js.map +0 -1
  284. package/dist/integration/prs.integration.test.d.ts +0 -8
  285. package/dist/integration/prs.integration.test.d.ts.map +0 -1
  286. package/dist/integration/prs.integration.test.js +0 -478
  287. package/dist/integration/prs.integration.test.js.map +0 -1
  288. package/dist/lib/ai/base-provider.test.d.ts +0 -7
  289. package/dist/lib/ai/base-provider.test.d.ts.map +0 -1
  290. package/dist/lib/ai/base-provider.test.js +0 -319
  291. package/dist/lib/ai/base-provider.test.js.map +0 -1
  292. package/dist/lib/ai/cli-provider.test.d.ts +0 -5
  293. package/dist/lib/ai/cli-provider.test.d.ts.map +0 -1
  294. package/dist/lib/ai/cli-provider.test.js +0 -460
  295. package/dist/lib/ai/cli-provider.test.js.map +0 -1
  296. package/dist/lib/ai/fallback-provider.test.d.ts +0 -7
  297. package/dist/lib/ai/fallback-provider.test.d.ts.map +0 -1
  298. package/dist/lib/ai/fallback-provider.test.js +0 -165
  299. package/dist/lib/ai/fallback-provider.test.js.map +0 -1
  300. package/dist/lib/ai/generation-service.test.d.ts +0 -7
  301. package/dist/lib/ai/generation-service.test.d.ts.map +0 -1
  302. package/dist/lib/ai/generation-service.test.js +0 -213
  303. package/dist/lib/ai/generation-service.test.js.map +0 -1
  304. package/dist/lib/ai/provider-manager.test.d.ts +0 -5
  305. package/dist/lib/ai/provider-manager.test.d.ts.map +0 -1
  306. package/dist/lib/ai/provider-manager.test.js +0 -312
  307. package/dist/lib/ai/provider-manager.test.js.map +0 -1
  308. package/dist/lib/ai/repo-docs.test.d.ts +0 -5
  309. package/dist/lib/ai/repo-docs.test.d.ts.map +0 -1
  310. package/dist/lib/ai/repo-docs.test.js +0 -357
  311. package/dist/lib/ai/repo-docs.test.js.map +0 -1
  312. package/dist/lib/cleanpr/args.test.d.ts +0 -2
  313. package/dist/lib/cleanpr/args.test.d.ts.map +0 -1
  314. package/dist/lib/cleanpr/args.test.js +0 -269
  315. package/dist/lib/cleanpr/args.test.js.map +0 -1
  316. package/dist/lib/cleanpr/cleanup.test.d.ts +0 -2
  317. package/dist/lib/cleanpr/cleanup.test.d.ts.map +0 -1
  318. package/dist/lib/cleanpr/cleanup.test.js +0 -296
  319. package/dist/lib/cleanpr/cleanup.test.js.map +0 -1
  320. package/dist/lib/cleanpr/worktree-info.test.d.ts +0 -2
  321. package/dist/lib/cleanpr/worktree-info.test.d.ts.map +0 -1
  322. package/dist/lib/cleanpr/worktree-info.test.js +0 -228
  323. package/dist/lib/cleanpr/worktree-info.test.js.map +0 -1
  324. package/dist/lib/colors.test.d.ts +0 -2
  325. package/dist/lib/colors.test.d.ts.map +0 -1
  326. package/dist/lib/colors.test.js +0 -142
  327. package/dist/lib/colors.test.js.map +0 -1
  328. package/dist/lib/config-editor.test.d.ts +0 -11
  329. package/dist/lib/config-editor.test.d.ts.map +0 -1
  330. package/dist/lib/config-editor.test.js +0 -526
  331. package/dist/lib/config-editor.test.js.map +0 -1
  332. package/dist/lib/config-migration/detector.test.d.ts +0 -5
  333. package/dist/lib/config-migration/detector.test.d.ts.map +0 -1
  334. package/dist/lib/config-migration/detector.test.js +0 -201
  335. package/dist/lib/config-migration/detector.test.js.map +0 -1
  336. package/dist/lib/config-migration/reporter.test.d.ts +0 -5
  337. package/dist/lib/config-migration/reporter.test.d.ts.map +0 -1
  338. package/dist/lib/config-migration/reporter.test.js +0 -305
  339. package/dist/lib/config-migration/reporter.test.js.map +0 -1
  340. package/dist/lib/config-migration/runner.test.d.ts +0 -5
  341. package/dist/lib/config-migration/runner.test.d.ts.map +0 -1
  342. package/dist/lib/config-migration/runner.test.js +0 -235
  343. package/dist/lib/config-migration/runner.test.js.map +0 -1
  344. package/dist/lib/config-validation.test.d.ts +0 -5
  345. package/dist/lib/config-validation.test.d.ts.map +0 -1
  346. package/dist/lib/config-validation.test.js +0 -423
  347. package/dist/lib/config-validation.test.js.map +0 -1
  348. package/dist/lib/config.test.d.ts +0 -2
  349. package/dist/lib/config.test.d.ts.map +0 -1
  350. package/dist/lib/config.test.js +0 -566
  351. package/dist/lib/config.test.js.map +0 -1
  352. package/dist/lib/constants.test.d.ts +0 -5
  353. package/dist/lib/constants.test.d.ts.map +0 -1
  354. package/dist/lib/constants.test.js +0 -121
  355. package/dist/lib/constants.test.js.map +0 -1
  356. package/dist/lib/errors.test.d.ts +0 -2
  357. package/dist/lib/errors.test.d.ts.map +0 -1
  358. package/dist/lib/errors.test.js +0 -117
  359. package/dist/lib/errors.test.js.map +0 -1
  360. package/dist/lib/git.test.d.ts +0 -2
  361. package/dist/lib/git.test.d.ts.map +0 -1
  362. package/dist/lib/git.test.js +0 -608
  363. package/dist/lib/git.test.js.map +0 -1
  364. package/dist/lib/github.test.d.ts +0 -2
  365. package/dist/lib/github.test.d.ts.map +0 -1
  366. package/dist/lib/github.test.js +0 -441
  367. package/dist/lib/github.test.js.map +0 -1
  368. package/dist/lib/global-check.test.d.ts +0 -5
  369. package/dist/lib/global-check.test.d.ts.map +0 -1
  370. package/dist/lib/global-check.test.js +0 -150
  371. package/dist/lib/global-check.test.js.map +0 -1
  372. package/dist/lib/global-config.test.d.ts +0 -5
  373. package/dist/lib/global-config.test.d.ts.map +0 -1
  374. package/dist/lib/global-config.test.js +0 -282
  375. package/dist/lib/global-config.test.js.map +0 -1
  376. package/dist/lib/hooks/confirmation.test.d.ts +0 -7
  377. package/dist/lib/hooks/confirmation.test.d.ts.map +0 -1
  378. package/dist/lib/hooks/confirmation.test.js +0 -300
  379. package/dist/lib/hooks/confirmation.test.js.map +0 -1
  380. package/dist/lib/hooks/executor.test.d.ts +0 -5
  381. package/dist/lib/hooks/executor.test.d.ts.map +0 -1
  382. package/dist/lib/hooks/executor.test.js +0 -648
  383. package/dist/lib/hooks/executor.test.js.map +0 -1
  384. package/dist/lib/hooks/templates.test.d.ts +0 -5
  385. package/dist/lib/hooks/templates.test.d.ts.map +0 -1
  386. package/dist/lib/hooks/templates.test.js +0 -163
  387. package/dist/lib/hooks/templates.test.js.map +0 -1
  388. package/dist/lib/hooks/types.test.d.ts +0 -5
  389. package/dist/lib/hooks/types.test.d.ts.map +0 -1
  390. package/dist/lib/hooks/types.test.js +0 -132
  391. package/dist/lib/hooks/types.test.js.map +0 -1
  392. package/dist/lib/json-output.test.d.ts +0 -5
  393. package/dist/lib/json-output.test.d.ts.map +0 -1
  394. package/dist/lib/json-output.test.js +0 -261
  395. package/dist/lib/json-output.test.js.map +0 -1
  396. package/dist/lib/logger.test.d.ts +0 -5
  397. package/dist/lib/logger.test.d.ts.map +0 -1
  398. package/dist/lib/logger.test.js +0 -292
  399. package/dist/lib/logger.test.js.map +0 -1
  400. package/dist/lib/lswt/action-executors.test.d.ts +0 -2
  401. package/dist/lib/lswt/action-executors.test.d.ts.map +0 -1
  402. package/dist/lib/lswt/action-executors.test.js +0 -1127
  403. package/dist/lib/lswt/action-executors.test.js.map +0 -1
  404. package/dist/lib/lswt/actions.test.d.ts +0 -2
  405. package/dist/lib/lswt/actions.test.d.ts.map +0 -1
  406. package/dist/lib/lswt/actions.test.js +0 -497
  407. package/dist/lib/lswt/actions.test.js.map +0 -1
  408. package/dist/lib/lswt/args.test.d.ts +0 -2
  409. package/dist/lib/lswt/args.test.d.ts.map +0 -1
  410. package/dist/lib/lswt/args.test.js +0 -195
  411. package/dist/lib/lswt/args.test.js.map +0 -1
  412. package/dist/lib/lswt/environment.test.d.ts +0 -2
  413. package/dist/lib/lswt/environment.test.d.ts.map +0 -1
  414. package/dist/lib/lswt/environment.test.js +0 -544
  415. package/dist/lib/lswt/environment.test.js.map +0 -1
  416. package/dist/lib/lswt/formatters.test.d.ts +0 -2
  417. package/dist/lib/lswt/formatters.test.d.ts.map +0 -1
  418. package/dist/lib/lswt/formatters.test.js +0 -323
  419. package/dist/lib/lswt/formatters.test.js.map +0 -1
  420. package/dist/lib/lswt/fuzzy-search.test.d.ts +0 -5
  421. package/dist/lib/lswt/fuzzy-search.test.d.ts.map +0 -1
  422. package/dist/lib/lswt/fuzzy-search.test.js +0 -207
  423. package/dist/lib/lswt/fuzzy-search.test.js.map +0 -1
  424. package/dist/lib/lswt/interactive.test.d.ts +0 -2
  425. package/dist/lib/lswt/interactive.test.d.ts.map +0 -1
  426. package/dist/lib/lswt/interactive.test.js +0 -771
  427. package/dist/lib/lswt/interactive.test.js.map +0 -1
  428. package/dist/lib/lswt/worktree-info.test.d.ts +0 -2
  429. package/dist/lib/lswt/worktree-info.test.d.ts.map +0 -1
  430. package/dist/lib/lswt/worktree-info.test.js +0 -484
  431. package/dist/lib/lswt/worktree-info.test.js.map +0 -1
  432. package/dist/lib/newpr/action-deps.test.d.ts +0 -5
  433. package/dist/lib/newpr/action-deps.test.d.ts.map +0 -1
  434. package/dist/lib/newpr/action-deps.test.js +0 -111
  435. package/dist/lib/newpr/action-deps.test.js.map +0 -1
  436. package/dist/lib/newpr/actions.test.d.ts +0 -2
  437. package/dist/lib/newpr/actions.test.d.ts.map +0 -1
  438. package/dist/lib/newpr/actions.test.js +0 -254
  439. package/dist/lib/newpr/actions.test.js.map +0 -1
  440. package/dist/lib/newpr/args.test.d.ts +0 -2
  441. package/dist/lib/newpr/args.test.d.ts.map +0 -1
  442. package/dist/lib/newpr/args.test.js +0 -479
  443. package/dist/lib/newpr/args.test.js.map +0 -1
  444. package/dist/lib/newpr/hook-runner.test.d.ts +0 -7
  445. package/dist/lib/newpr/hook-runner.test.d.ts.map +0 -1
  446. package/dist/lib/newpr/hook-runner.test.js +0 -422
  447. package/dist/lib/newpr/hook-runner.test.js.map +0 -1
  448. package/dist/lib/newpr/plan-generator.test.d.ts +0 -7
  449. package/dist/lib/newpr/plan-generator.test.d.ts.map +0 -1
  450. package/dist/lib/newpr/plan-generator.test.js +0 -387
  451. package/dist/lib/newpr/plan-generator.test.js.map +0 -1
  452. package/dist/lib/newpr/scenario-handler.test.d.ts +0 -2
  453. package/dist/lib/newpr/scenario-handler.test.d.ts.map +0 -1
  454. package/dist/lib/newpr/scenario-handler.test.js +0 -256
  455. package/dist/lib/newpr/scenario-handler.test.js.map +0 -1
  456. package/dist/lib/prompts.test.d.ts +0 -2
  457. package/dist/lib/prompts.test.d.ts.map +0 -1
  458. package/dist/lib/prompts.test.js +0 -807
  459. package/dist/lib/prompts.test.js.map +0 -1
  460. package/dist/lib/prs/actions.test.d.ts +0 -5
  461. package/dist/lib/prs/actions.test.d.ts.map +0 -1
  462. package/dist/lib/prs/actions.test.js +0 -356
  463. package/dist/lib/prs/actions.test.js.map +0 -1
  464. package/dist/lib/prs/data.test.d.ts +0 -5
  465. package/dist/lib/prs/data.test.d.ts.map +0 -1
  466. package/dist/lib/prs/data.test.js +0 -417
  467. package/dist/lib/prs/data.test.js.map +0 -1
  468. package/dist/lib/prs/details.test.d.ts +0 -5
  469. package/dist/lib/prs/details.test.d.ts.map +0 -1
  470. package/dist/lib/prs/details.test.js +0 -325
  471. package/dist/lib/prs/details.test.js.map +0 -1
  472. package/dist/lib/prs/filters.test.d.ts +0 -5
  473. package/dist/lib/prs/filters.test.d.ts.map +0 -1
  474. package/dist/lib/prs/filters.test.js +0 -312
  475. package/dist/lib/prs/filters.test.js.map +0 -1
  476. package/dist/lib/prs/formatters.test.d.ts +0 -2
  477. package/dist/lib/prs/formatters.test.d.ts.map +0 -1
  478. package/dist/lib/prs/formatters.test.js +0 -387
  479. package/dist/lib/prs/formatters.test.js.map +0 -1
  480. package/dist/lib/prs/interactive.test.d.ts +0 -5
  481. package/dist/lib/prs/interactive.test.d.ts.map +0 -1
  482. package/dist/lib/prs/interactive.test.js +0 -364
  483. package/dist/lib/prs/interactive.test.js.map +0 -1
  484. package/dist/lib/schema.test.d.ts +0 -10
  485. package/dist/lib/schema.test.d.ts.map +0 -1
  486. package/dist/lib/schema.test.js +0 -309
  487. package/dist/lib/schema.test.js.map +0 -1
  488. package/dist/lib/state-detection.test.d.ts +0 -2
  489. package/dist/lib/state-detection.test.d.ts.map +0 -1
  490. package/dist/lib/state-detection.test.js +0 -451
  491. package/dist/lib/state-detection.test.js.map +0 -1
  492. package/dist/lib/wtconfig/config-manager.test.d.ts +0 -5
  493. package/dist/lib/wtconfig/config-manager.test.d.ts.map +0 -1
  494. package/dist/lib/wtconfig/config-manager.test.js +0 -501
  495. package/dist/lib/wtconfig/config-manager.test.js.map +0 -1
  496. package/dist/lib/wtconfig/environment.test.d.ts +0 -5
  497. package/dist/lib/wtconfig/environment.test.d.ts.map +0 -1
  498. package/dist/lib/wtconfig/environment.test.js +0 -285
  499. package/dist/lib/wtconfig/environment.test.js.map +0 -1
  500. package/dist/lib/wtlink/config-manifest.test.d.ts +0 -2
  501. package/dist/lib/wtlink/config-manifest.test.d.ts.map +0 -1
  502. package/dist/lib/wtlink/config-manifest.test.js +0 -486
  503. package/dist/lib/wtlink/config-manifest.test.js.map +0 -1
  504. package/dist/lib/wtlink/link-configs.test.d.ts +0 -2
  505. package/dist/lib/wtlink/link-configs.test.d.ts.map +0 -1
  506. package/dist/lib/wtlink/link-configs.test.js +0 -612
  507. package/dist/lib/wtlink/link-configs.test.js.map +0 -1
  508. package/dist/lib/wtlink/main-menu.test.d.ts +0 -5
  509. package/dist/lib/wtlink/main-menu.test.d.ts.map +0 -1
  510. package/dist/lib/wtlink/main-menu.test.js +0 -126
  511. package/dist/lib/wtlink/main-menu.test.js.map +0 -1
  512. package/dist/lib/wtlink/manage-manifest.test.d.ts +0 -2
  513. package/dist/lib/wtlink/manage-manifest.test.d.ts.map +0 -1
  514. package/dist/lib/wtlink/manage-manifest.test.js +0 -714
  515. package/dist/lib/wtlink/manage-manifest.test.js.map +0 -1
  516. package/dist/lib/wtlink/validate-manifest.test.d.ts +0 -2
  517. package/dist/lib/wtlink/validate-manifest.test.d.ts.map +0 -1
  518. package/dist/lib/wtlink/validate-manifest.test.js +0 -220
  519. package/dist/lib/wtlink/validate-manifest.test.js.map +0 -1
  520. package/dist/lib/wtstate/analyze.test.d.ts +0 -5
  521. package/dist/lib/wtstate/analyze.test.d.ts.map +0 -1
  522. package/dist/lib/wtstate/analyze.test.js +0 -282
  523. package/dist/lib/wtstate/analyze.test.js.map +0 -1
  524. package/dist/lib/wtstate/args.test.d.ts +0 -5
  525. package/dist/lib/wtstate/args.test.d.ts.map +0 -1
  526. package/dist/lib/wtstate/args.test.js +0 -120
  527. package/dist/lib/wtstate/args.test.js.map +0 -1
  528. package/dist/mcp/server.test.d.ts +0 -9
  529. package/dist/mcp/server.test.d.ts.map +0 -1
  530. package/dist/mcp/server.test.js +0 -439
  531. package/dist/mcp/server.test.js.map +0 -1
@@ -1,608 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { spawnSync, execSync, spawn, } from 'child_process';
3
- import * as path from 'path';
4
- import { EventEmitter } from 'stream';
5
- import * as git from './git.js';
6
- // Mock child_process
7
- vi.mock('child_process', () => ({
8
- spawnSync: vi.fn(),
9
- execSync: vi.fn(),
10
- spawn: vi.fn(),
11
- }));
12
- const mockSpawnSync = vi.mocked(spawnSync);
13
- const mockExecSync = vi.mocked(execSync);
14
- const mockSpawn = vi.mocked(spawn);
15
- /**
16
- * Helper to create a successful spawnSync result
17
- */
18
- function mockSpawnSuccess(stdout) {
19
- return {
20
- status: 0,
21
- signal: null,
22
- output: ['', stdout, ''],
23
- pid: 123,
24
- stdout,
25
- stderr: '',
26
- error: undefined,
27
- };
28
- }
29
- /**
30
- * Helper to create a failed spawnSync result
31
- */
32
- function mockSpawnFailure(stderr) {
33
- return {
34
- status: 1,
35
- signal: null,
36
- output: ['', '', stderr],
37
- pid: 123,
38
- stdout: '',
39
- stderr,
40
- error: undefined,
41
- };
42
- }
43
- describe('git', () => {
44
- beforeEach(() => {
45
- vi.clearAllMocks();
46
- });
47
- describe('exec', () => {
48
- it('executes git command and returns output with trailing whitespace trimmed', () => {
49
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('output with trailing whitespace \n'));
50
- const result = git.exec(['status']);
51
- // Leading whitespace is preserved (important for git status), trailing is trimmed
52
- expect(result).toBe('output with trailing whitespace');
53
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['status'], expect.any(Object));
54
- });
55
- it('preserves leading whitespace in output', () => {
56
- // Leading spaces are significant in git status --porcelain output
57
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(' M file.txt\n'));
58
- const result = git.exec(['status', '--porcelain']);
59
- expect(result).toBe(' M file.txt');
60
- });
61
- it('passes cwd option correctly', () => {
62
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('output'));
63
- git.exec(['status'], { cwd: '/some/path' });
64
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['status'], expect.objectContaining({ cwd: '/some/path' }));
65
- });
66
- it('throws error with stderr message on failure', () => {
67
- mockSpawnSync.mockReturnValue(mockSpawnFailure('fatal: not a git repository'));
68
- expect(() => git.exec(['status'])).toThrow('Git command failed');
69
- });
70
- });
71
- describe('execSafe', () => {
72
- it('returns output on success', () => {
73
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('output'));
74
- const result = git.execSafe(['status']);
75
- expect(result).toBe('output');
76
- });
77
- it('returns null on failure', () => {
78
- mockSpawnSync.mockReturnValue(mockSpawnFailure('Command failed'));
79
- const result = git.execSafe(['status']);
80
- expect(result).toBeNull();
81
- });
82
- });
83
- describe('getRepoRoot', () => {
84
- it('returns normalized path from git rev-parse', () => {
85
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('/home/user/repo\n'));
86
- const result = git.getRepoRoot();
87
- expect(result).toContain('repo');
88
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['rev-parse', '--show-toplevel'], expect.any(Object));
89
- });
90
- });
91
- describe('getRepoName', () => {
92
- it('extracts name from SSH remote URL', () => {
93
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('git@github.com:org/my-repo.git'));
94
- const result = git.getRepoName('/repo');
95
- expect(result).toBe('my-repo');
96
- });
97
- it('extracts name from HTTPS remote URL', () => {
98
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('https://github.com/org/my-repo.git'));
99
- const result = git.getRepoName('/repo');
100
- expect(result).toBe('my-repo');
101
- });
102
- it('extracts name from URL without .git suffix', () => {
103
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('https://github.com/org/my-repo'));
104
- const result = git.getRepoName('/repo');
105
- expect(result).toBe('my-repo');
106
- });
107
- it('falls back to directory name when no remote', () => {
108
- mockSpawnSync.mockReturnValue(mockSpawnFailure('No remote'));
109
- const result = git.getRepoName('/home/user/my-project');
110
- expect(result).toBe('my-project');
111
- });
112
- it('extracts name from Unix local path with .git suffix', () => {
113
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('/path/to/my-repo.git'));
114
- const result = git.getRepoName('/repo');
115
- expect(result).toBe('my-repo');
116
- });
117
- it('extracts name from Windows local path with .git suffix', () => {
118
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('C:\\Users\\test\\repos\\my-repo.git'));
119
- const result = git.getRepoName('/repo');
120
- expect(result).toBe('my-repo');
121
- });
122
- it('extracts name from Windows local path without .git suffix', () => {
123
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('C:\\Users\\test\\repos\\my-repo'));
124
- const result = git.getRepoName('/repo');
125
- expect(result).toBe('my-repo');
126
- });
127
- it('extracts name from Windows short path format', () => {
128
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\main-repo.git'));
129
- const result = git.getRepoName('/repo');
130
- expect(result).toBe('main-repo');
131
- });
132
- });
133
- describe('getCurrentBranch', () => {
134
- it('returns branch name', () => {
135
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('feature/my-branch'));
136
- const result = git.getCurrentBranch();
137
- expect(result).toBe('feature/my-branch');
138
- });
139
- it('returns null for detached HEAD', () => {
140
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('HEAD'));
141
- const result = git.getCurrentBranch();
142
- expect(result).toBeNull();
143
- });
144
- });
145
- describe('isDetachedHead', () => {
146
- it('returns true when in detached HEAD state', () => {
147
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('HEAD'));
148
- expect(git.isDetachedHead()).toBe(true);
149
- });
150
- it('returns false when on a branch', () => {
151
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('main'));
152
- expect(git.isDetachedHead()).toBe(false);
153
- });
154
- });
155
- describe('getWorkingTreeStatus', () => {
156
- it('returns clean for empty status', () => {
157
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
158
- expect(git.getWorkingTreeStatus()).toBe('clean');
159
- });
160
- it('returns staged_only for staged changes', () => {
161
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('M file.txt'));
162
- expect(git.getWorkingTreeStatus()).toBe('staged_only');
163
- });
164
- it('returns unstaged_only for unstaged changes', () => {
165
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(' M file.txt'));
166
- expect(git.getWorkingTreeStatus()).toBe('unstaged_only');
167
- });
168
- it('returns unstaged_only for untracked files', () => {
169
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('?? newfile.txt'));
170
- expect(git.getWorkingTreeStatus()).toBe('unstaged_only');
171
- });
172
- it('returns both for staged and unstaged changes', () => {
173
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('MM file.txt'));
174
- expect(git.getWorkingTreeStatus()).toBe('both');
175
- });
176
- it('returns both for staged changes and untracked files', () => {
177
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('M staged.txt\n?? untracked.txt'));
178
- expect(git.getWorkingTreeStatus()).toBe('both');
179
- });
180
- });
181
- describe('getStagedFiles', () => {
182
- it('returns list of staged files', () => {
183
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('file1.txt\nfile2.txt\n'));
184
- const result = git.getStagedFiles();
185
- expect(result).toEqual(['file1.txt', 'file2.txt']);
186
- });
187
- it('returns empty array when nothing staged', () => {
188
- mockSpawnSync.mockReturnValue(mockSpawnFailure('No staged files'));
189
- const result = git.getStagedFiles();
190
- expect(result).toEqual([]);
191
- });
192
- });
193
- describe('getUnstagedFiles', () => {
194
- it('returns list of unstaged and untracked files', () => {
195
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(' M modified.txt\n?? untracked.txt'));
196
- const result = git.getUnstagedFiles();
197
- expect(result).toEqual(['modified.txt', 'untracked.txt']);
198
- });
199
- it('excludes staged-only files', () => {
200
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('M staged.txt\n M both.txt'));
201
- const result = git.getUnstagedFiles();
202
- expect(result).toEqual(['both.txt']);
203
- });
204
- it('returns empty array when working tree is clean', () => {
205
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
206
- const result = git.getUnstagedFiles();
207
- expect(result).toEqual([]);
208
- });
209
- });
210
- describe('listWorktrees', () => {
211
- it('parses worktree list porcelain output', () => {
212
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo\n' +
213
- 'HEAD abc123def456\n' +
214
- 'branch refs/heads/main\n' +
215
- '\n' +
216
- 'worktree /home/user/repo.pr42\n' +
217
- 'HEAD def456abc123\n' +
218
- 'branch refs/heads/feature/test\n' +
219
- '\n'));
220
- const result = git.listWorktrees();
221
- expect(result).toHaveLength(2);
222
- expect(result[0]).toEqual({
223
- path: '/home/user/repo',
224
- commit: 'abc123def456',
225
- branch: 'main',
226
- isMain: true,
227
- isBare: false,
228
- isLocked: false,
229
- isPrunable: false,
230
- });
231
- expect(result[1]).toEqual({
232
- path: '/home/user/repo.pr42',
233
- commit: 'def456abc123',
234
- branch: 'feature/test',
235
- isMain: false,
236
- isBare: false,
237
- isLocked: false,
238
- isPrunable: false,
239
- });
240
- });
241
- it('handles bare repository', () => {
242
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo.git\n' + 'bare\n' + '\n'));
243
- const result = git.listWorktrees();
244
- expect(result[0].isBare).toBe(true);
245
- expect(result[0].isMain).toBe(true);
246
- });
247
- it('handles locked and prunable worktrees', () => {
248
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo.pr1\n' +
249
- 'HEAD abc123\n' +
250
- 'branch refs/heads/test\n' +
251
- 'locked\n' +
252
- 'prunable\n' +
253
- '\n'));
254
- const result = git.listWorktrees();
255
- expect(result[0].isLocked).toBe(true);
256
- expect(result[0].isPrunable).toBe(true);
257
- });
258
- it('handles detached HEAD in worktree', () => {
259
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo\n' + 'HEAD abc123\n' + 'detached\n' + '\n'));
260
- const result = git.listWorktrees();
261
- expect(result[0].branch).toBeNull();
262
- });
263
- });
264
- describe('getCommitRelationship', () => {
265
- it('returns same when HEAD equals base', () => {
266
- mockSpawnSync
267
- .mockReturnValueOnce(mockSpawnSuccess('abc123')) // getHeadCommit
268
- .mockReturnValueOnce(mockSpawnSuccess('abc123')); // getRefCommit
269
- const result = git.getCommitRelationship('main');
270
- expect(result).toBe('same');
271
- });
272
- it('returns divergent when base branch does not exist', () => {
273
- mockSpawnSync
274
- .mockReturnValueOnce(mockSpawnSuccess('abc123')) // getHeadCommit
275
- .mockReturnValueOnce(mockSpawnFailure('unknown revision')); // getRefCommit fails
276
- const result = git.getCommitRelationship('main');
277
- expect(result).toBe('divergent');
278
- });
279
- });
280
- describe('getCommitsAhead', () => {
281
- it('returns list of commits ahead of base', () => {
282
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123 First commit\ndef456 Second commit'));
283
- const result = git.getCommitsAhead('main');
284
- expect(result).toEqual(['abc123 First commit', 'def456 Second commit']);
285
- });
286
- it('returns empty array when not ahead', () => {
287
- mockSpawnSync.mockReturnValue(mockSpawnFailure('No commits'));
288
- const result = git.getCommitsAhead('main');
289
- expect(result).toEqual([]);
290
- });
291
- });
292
- describe('addWorktree', () => {
293
- it('creates worktree with existing branch', () => {
294
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
295
- git.addWorktree('/path/to/worktree', 'feature-branch');
296
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'add', '/path/to/worktree', 'feature-branch'], expect.any(Object));
297
- });
298
- it('creates worktree with new branch', () => {
299
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
300
- git.addWorktree('/path/to/worktree', 'new-branch', { createBranch: true });
301
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree'], expect.any(Object));
302
- });
303
- it('creates worktree with new branch from start point', () => {
304
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
305
- git.addWorktree('/path/to/worktree', 'new-branch', {
306
- createBranch: true,
307
- startPoint: 'origin/main',
308
- });
309
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree', 'origin/main'], expect.any(Object));
310
- });
311
- });
312
- describe('removeWorktree', () => {
313
- it('removes worktree', () => {
314
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
315
- git.removeWorktree('/path/to/worktree');
316
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'remove', '/path/to/worktree'], expect.any(Object));
317
- });
318
- it('force removes worktree', () => {
319
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
320
- git.removeWorktree('/path/to/worktree', { force: true });
321
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'remove', '--force', '/path/to/worktree'], expect.any(Object));
322
- });
323
- });
324
- describe('createBranch', () => {
325
- it('creates branch from HEAD', () => {
326
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
327
- git.createBranch('new-branch');
328
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', 'new-branch'], expect.any(Object));
329
- });
330
- it('creates branch from start point', () => {
331
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
332
- git.createBranch('new-branch', 'origin/main');
333
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', 'new-branch', 'origin/main'], expect.any(Object));
334
- });
335
- });
336
- describe('deleteBranch', () => {
337
- it('deletes branch with -d flag', () => {
338
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
339
- git.deleteBranch('old-branch');
340
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', '-d', 'old-branch'], expect.any(Object));
341
- });
342
- it('force deletes branch with -D flag', () => {
343
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
344
- git.deleteBranch('old-branch', { force: true });
345
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', '-D', 'old-branch'], expect.any(Object));
346
- });
347
- });
348
- describe('commit', () => {
349
- it('creates commit with message', () => {
350
- mockSpawnSync
351
- .mockReturnValueOnce(mockSpawnSuccess('')) // commit
352
- .mockReturnValueOnce(mockSpawnSuccess('abc123')); // getHeadCommit
353
- const result = git.commit({ message: 'Test commit' });
354
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['commit', '-m', 'Test commit'], expect.any(Object));
355
- expect(result).toBe('abc123');
356
- });
357
- it('creates commit with all flag', () => {
358
- mockSpawnSync
359
- .mockReturnValueOnce(mockSpawnSuccess(''))
360
- .mockReturnValueOnce(mockSpawnSuccess('abc123'));
361
- git.commit({ message: 'Test commit', all: true });
362
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['commit', '-a', '-m', 'Test commit'], expect.any(Object));
363
- });
364
- it('creates empty commit when allowed', () => {
365
- mockSpawnSync
366
- .mockReturnValueOnce(mockSpawnSuccess(''))
367
- .mockReturnValueOnce(mockSpawnSuccess('abc123'));
368
- git.commit({ message: 'Empty commit', allowEmpty: true });
369
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['commit', '--allow-empty', '-m', 'Empty commit'], expect.any(Object));
370
- });
371
- });
372
- describe('push', () => {
373
- it('pushes to remote', () => {
374
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
375
- git.push();
376
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['push'], expect.any(Object));
377
- });
378
- it('pushes with upstream flag', () => {
379
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
380
- git.push({ setUpstream: true, remote: 'origin', branch: 'feature' });
381
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['push', '-u', 'origin', 'feature'], expect.any(Object));
382
- });
383
- it('force pushes', () => {
384
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
385
- git.push({ force: true });
386
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['push', '--force'], expect.any(Object));
387
- });
388
- });
389
- describe('stash', () => {
390
- it('creates stash and returns reference', () => {
391
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved working directory'));
392
- const result = git.stash();
393
- expect(result).toBe('stash@{0}');
394
- });
395
- it('returns null when nothing to stash', () => {
396
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('No local changes to save'));
397
- const result = git.stash();
398
- expect(result).toBeNull();
399
- });
400
- it('stashes with keep-index flag', () => {
401
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved'));
402
- git.stash({ keepIndex: true });
403
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['stash', 'push', '--keep-index'], expect.any(Object));
404
- });
405
- it('stashes with message', () => {
406
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved'));
407
- git.stash({ message: 'WIP: feature' });
408
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['stash', 'push', '-m', 'WIP: feature'], expect.any(Object));
409
- });
410
- it('stashes untracked files', () => {
411
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved'));
412
- git.stash({ includeUntracked: true });
413
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['stash', 'push', '--include-untracked'], expect.any(Object));
414
- });
415
- });
416
- describe('branchExists', () => {
417
- it('returns true when branch exists', () => {
418
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123'));
419
- expect(git.branchExists('main')).toBe(true);
420
- });
421
- it('returns false when branch does not exist', () => {
422
- mockSpawnSync.mockReturnValue(mockSpawnFailure('unknown revision'));
423
- expect(git.branchExists('nonexistent')).toBe(false);
424
- });
425
- });
426
- describe('remoteBranchExists', () => {
427
- it('returns true when remote branch exists', () => {
428
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123'));
429
- expect(git.remoteBranchExists('main')).toBe(true);
430
- });
431
- it('returns false when remote branch does not exist', () => {
432
- mockSpawnSync.mockReturnValue(mockSpawnFailure('unknown revision'));
433
- expect(git.remoteBranchExists('nonexistent')).toBe(false);
434
- });
435
- it('checks specific remote', () => {
436
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123'));
437
- git.remoteBranchExists('main', 'upstream');
438
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['rev-parse', '--verify', 'refs/remotes/upstream/main'], expect.any(Object));
439
- });
440
- });
441
- describe('getMainWorktreeRoot', () => {
442
- it('returns repo root when in main worktree', () => {
443
- // Use path.join to create platform-appropriate paths
444
- const repoPath = path.join('/home', 'user', 'repo');
445
- const gitDir = path.join(repoPath, '.git');
446
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(gitDir));
447
- const result = git.getMainWorktreeRoot(repoPath);
448
- expect(result).toBe(path.resolve(repoPath));
449
- });
450
- it('returns main worktree root when in linked worktree', () => {
451
- const mainRepo = path.join('/home', 'user', 'main-repo');
452
- const worktreeGitDir = path.join(mainRepo, '.git', 'worktrees', 'feature-branch');
453
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(worktreeGitDir));
454
- const result = git.getMainWorktreeRoot(path.join('/home', 'user', 'main-repo.pr42'));
455
- expect(result).toBe(path.resolve(mainRepo));
456
- });
457
- it('falls back to getRepoRoot when commonDir is null', () => {
458
- const fallbackPath = path.join('/fallback', 'root');
459
- // First call (git-common-dir) fails, second call (show-toplevel) succeeds
460
- mockSpawnSync
461
- .mockReturnValueOnce(mockSpawnFailure('failed'))
462
- .mockReturnValueOnce(mockSpawnSuccess(fallbackPath));
463
- const result = git.getMainWorktreeRoot();
464
- expect(result).toContain('fallback');
465
- });
466
- });
467
- describe('isGitIgnored', () => {
468
- it('returns true when file is ignored', () => {
469
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('node_modules/'));
470
- expect(git.isGitIgnored('node_modules/')).toBe(true);
471
- });
472
- it('returns false when file is not ignored', () => {
473
- mockSpawnSync.mockReturnValue(mockSpawnFailure('no output for unignored files'));
474
- expect(git.isGitIgnored('src/index.ts')).toBe(false);
475
- });
476
- it('returns false when check-ignore returns empty', () => {
477
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
478
- expect(git.isGitIgnored('src/index.ts')).toBe(false);
479
- });
480
- });
481
- describe('checkGitInstalled', () => {
482
- it('returns true when git is installed', () => {
483
- mockExecSync.mockReturnValue('git version 2.39.0');
484
- expect(git.checkGitInstalled()).toBe(true);
485
- });
486
- it('returns false when git is not installed', () => {
487
- mockExecSync.mockImplementation(() => {
488
- throw new Error('command not found: git');
489
- });
490
- expect(git.checkGitInstalled()).toBe(false);
491
- });
492
- });
493
- // ============================================================================
494
- // Async function tests
495
- // ============================================================================
496
- /**
497
- * Helper to create a mock child process for async spawn
498
- */
499
- function createMockChildProcess(stdout, stderr, exitCode) {
500
- const child = new EventEmitter();
501
- // Create mock readable streams
502
- const mockStdout = new EventEmitter();
503
- const mockStderr = new EventEmitter();
504
- child.stdout = mockStdout;
505
- child.stderr = mockStderr;
506
- // Emit data and close event on next tick
507
- process.nextTick(() => {
508
- if (stdout) {
509
- child.stdout?.emit('data', Buffer.from(stdout));
510
- }
511
- if (stderr) {
512
- child.stderr?.emit('data', Buffer.from(stderr));
513
- }
514
- child.emit('close', exitCode);
515
- });
516
- return child;
517
- }
518
- describe('execAsync', () => {
519
- it('executes git command and returns output', async () => {
520
- mockSpawn.mockReturnValue(createMockChildProcess('output\n', '', 0));
521
- const result = await git.execAsync(['status']);
522
- expect(result).toBe('output');
523
- expect(mockSpawn).toHaveBeenCalledWith('git', ['status'], expect.any(Object));
524
- });
525
- it('rejects on non-zero exit code', async () => {
526
- mockSpawn.mockReturnValue(createMockChildProcess('', 'fatal: error', 1));
527
- await expect(git.execAsync(['invalid'])).rejects.toThrow('Git command failed');
528
- });
529
- it('rejects on spawn error', async () => {
530
- const child = new EventEmitter();
531
- child.stdout = new EventEmitter();
532
- child.stderr = new EventEmitter();
533
- mockSpawn.mockReturnValue(child);
534
- const promise = git.execAsync(['status']);
535
- process.nextTick(() => {
536
- child.emit('error', new Error('spawn failed'));
537
- });
538
- await expect(promise).rejects.toThrow('spawn failed');
539
- });
540
- it('passes cwd option correctly', async () => {
541
- mockSpawn.mockReturnValue(createMockChildProcess('output', '', 0));
542
- await git.execAsync(['status'], { cwd: '/some/path' });
543
- expect(mockSpawn).toHaveBeenCalledWith('git', ['status'], expect.objectContaining({ cwd: '/some/path' }));
544
- });
545
- });
546
- describe('fetchAsync', () => {
547
- it('fetches from remote', async () => {
548
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
549
- await git.fetchAsync('origin');
550
- expect(mockSpawn).toHaveBeenCalledWith('git', ['fetch', 'origin'], expect.any(Object));
551
- });
552
- it('uses default remote', async () => {
553
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
554
- await git.fetchAsync();
555
- expect(mockSpawn).toHaveBeenCalledWith('git', ['fetch', 'origin'], expect.any(Object));
556
- });
557
- });
558
- describe('addWorktreeAsync', () => {
559
- it('creates worktree with existing branch', async () => {
560
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
561
- await git.addWorktreeAsync('/path/to/worktree', 'feature-branch');
562
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'add', '/path/to/worktree', 'feature-branch'], expect.any(Object));
563
- });
564
- it('creates worktree with new branch', async () => {
565
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
566
- await git.addWorktreeAsync('/path/to/worktree', 'new-branch', { createBranch: true });
567
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree'], expect.any(Object));
568
- });
569
- it('creates worktree with new branch from start point', async () => {
570
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
571
- await git.addWorktreeAsync('/path/to/worktree', 'new-branch', {
572
- createBranch: true,
573
- startPoint: 'origin/main',
574
- });
575
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree', 'origin/main'], expect.any(Object));
576
- });
577
- });
578
- describe('removeWorktreeAsync', () => {
579
- it('removes worktree', async () => {
580
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
581
- await git.removeWorktreeAsync('/path/to/worktree');
582
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'remove', '/path/to/worktree'], expect.any(Object));
583
- });
584
- it('force removes worktree', async () => {
585
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
586
- await git.removeWorktreeAsync('/path/to/worktree', { force: true });
587
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'remove', '--force', '/path/to/worktree'], expect.any(Object));
588
- });
589
- });
590
- describe('pushAsync', () => {
591
- it('pushes to remote', async () => {
592
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
593
- await git.pushAsync();
594
- expect(mockSpawn).toHaveBeenCalledWith('git', ['push'], expect.any(Object));
595
- });
596
- it('pushes with upstream flag', async () => {
597
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
598
- await git.pushAsync({ setUpstream: true, remote: 'origin', branch: 'feature' });
599
- expect(mockSpawn).toHaveBeenCalledWith('git', ['push', '-u', 'origin', 'feature'], expect.any(Object));
600
- });
601
- it('force pushes', async () => {
602
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
603
- await git.pushAsync({ force: true });
604
- expect(mockSpawn).toHaveBeenCalledWith('git', ['push', '--force'], expect.any(Object));
605
- });
606
- });
607
- });
608
- //# sourceMappingURL=git.test.js.map