gitx.do 0.1.1 → 0.1.2

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 (356) hide show
  1. package/README.md +40 -353
  2. package/dist/do/logger.d.ts +50 -0
  3. package/dist/do/logger.d.ts.map +1 -0
  4. package/dist/do/logger.js +122 -0
  5. package/dist/do/logger.js.map +1 -0
  6. package/dist/{durable-object → do}/schema.d.ts +3 -3
  7. package/dist/do/schema.d.ts.map +1 -0
  8. package/dist/{durable-object → do}/schema.js +4 -3
  9. package/dist/do/schema.js.map +1 -0
  10. package/dist/do/types.d.ts +267 -0
  11. package/dist/do/types.d.ts.map +1 -0
  12. package/dist/do/types.js +62 -0
  13. package/dist/do/types.js.map +1 -0
  14. package/dist/index.d.ts +14 -469
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +31 -483
  17. package/dist/index.js.map +1 -1
  18. package/package.json +13 -21
  19. package/dist/cli/commands/add.d.ts +0 -176
  20. package/dist/cli/commands/add.d.ts.map +0 -1
  21. package/dist/cli/commands/add.js +0 -979
  22. package/dist/cli/commands/add.js.map +0 -1
  23. package/dist/cli/commands/blame.d.ts +0 -259
  24. package/dist/cli/commands/blame.d.ts.map +0 -1
  25. package/dist/cli/commands/blame.js +0 -609
  26. package/dist/cli/commands/blame.js.map +0 -1
  27. package/dist/cli/commands/branch.d.ts +0 -249
  28. package/dist/cli/commands/branch.d.ts.map +0 -1
  29. package/dist/cli/commands/branch.js +0 -693
  30. package/dist/cli/commands/branch.js.map +0 -1
  31. package/dist/cli/commands/checkout.d.ts +0 -73
  32. package/dist/cli/commands/checkout.d.ts.map +0 -1
  33. package/dist/cli/commands/checkout.js +0 -725
  34. package/dist/cli/commands/checkout.js.map +0 -1
  35. package/dist/cli/commands/commit.d.ts +0 -182
  36. package/dist/cli/commands/commit.d.ts.map +0 -1
  37. package/dist/cli/commands/commit.js +0 -457
  38. package/dist/cli/commands/commit.js.map +0 -1
  39. package/dist/cli/commands/diff.d.ts +0 -464
  40. package/dist/cli/commands/diff.d.ts.map +0 -1
  41. package/dist/cli/commands/diff.js +0 -959
  42. package/dist/cli/commands/diff.js.map +0 -1
  43. package/dist/cli/commands/log.d.ts +0 -239
  44. package/dist/cli/commands/log.d.ts.map +0 -1
  45. package/dist/cli/commands/log.js +0 -535
  46. package/dist/cli/commands/log.js.map +0 -1
  47. package/dist/cli/commands/merge.d.ts +0 -106
  48. package/dist/cli/commands/merge.d.ts.map +0 -1
  49. package/dist/cli/commands/merge.js +0 -852
  50. package/dist/cli/commands/merge.js.map +0 -1
  51. package/dist/cli/commands/review.d.ts +0 -457
  52. package/dist/cli/commands/review.d.ts.map +0 -1
  53. package/dist/cli/commands/review.js +0 -558
  54. package/dist/cli/commands/review.js.map +0 -1
  55. package/dist/cli/commands/stash.d.ts +0 -157
  56. package/dist/cli/commands/stash.d.ts.map +0 -1
  57. package/dist/cli/commands/stash.js +0 -655
  58. package/dist/cli/commands/stash.js.map +0 -1
  59. package/dist/cli/commands/status.d.ts +0 -269
  60. package/dist/cli/commands/status.d.ts.map +0 -1
  61. package/dist/cli/commands/status.js +0 -492
  62. package/dist/cli/commands/status.js.map +0 -1
  63. package/dist/cli/commands/web.d.ts +0 -199
  64. package/dist/cli/commands/web.d.ts.map +0 -1
  65. package/dist/cli/commands/web.js +0 -697
  66. package/dist/cli/commands/web.js.map +0 -1
  67. package/dist/cli/fs-adapter.d.ts +0 -656
  68. package/dist/cli/fs-adapter.d.ts.map +0 -1
  69. package/dist/cli/fs-adapter.js +0 -1177
  70. package/dist/cli/fs-adapter.js.map +0 -1
  71. package/dist/cli/fsx-cli-adapter.d.ts +0 -359
  72. package/dist/cli/fsx-cli-adapter.d.ts.map +0 -1
  73. package/dist/cli/fsx-cli-adapter.js +0 -619
  74. package/dist/cli/fsx-cli-adapter.js.map +0 -1
  75. package/dist/cli/index.d.ts +0 -387
  76. package/dist/cli/index.d.ts.map +0 -1
  77. package/dist/cli/index.js +0 -579
  78. package/dist/cli/index.js.map +0 -1
  79. package/dist/cli/ui/components/DiffView.d.ts +0 -12
  80. package/dist/cli/ui/components/DiffView.d.ts.map +0 -1
  81. package/dist/cli/ui/components/DiffView.js +0 -11
  82. package/dist/cli/ui/components/DiffView.js.map +0 -1
  83. package/dist/cli/ui/components/ErrorDisplay.d.ts +0 -10
  84. package/dist/cli/ui/components/ErrorDisplay.d.ts.map +0 -1
  85. package/dist/cli/ui/components/ErrorDisplay.js +0 -11
  86. package/dist/cli/ui/components/ErrorDisplay.js.map +0 -1
  87. package/dist/cli/ui/components/FuzzySearch.d.ts +0 -15
  88. package/dist/cli/ui/components/FuzzySearch.d.ts.map +0 -1
  89. package/dist/cli/ui/components/FuzzySearch.js +0 -12
  90. package/dist/cli/ui/components/FuzzySearch.js.map +0 -1
  91. package/dist/cli/ui/components/LoadingSpinner.d.ts +0 -10
  92. package/dist/cli/ui/components/LoadingSpinner.d.ts.map +0 -1
  93. package/dist/cli/ui/components/LoadingSpinner.js +0 -10
  94. package/dist/cli/ui/components/LoadingSpinner.js.map +0 -1
  95. package/dist/cli/ui/components/NavigationList.d.ts +0 -14
  96. package/dist/cli/ui/components/NavigationList.d.ts.map +0 -1
  97. package/dist/cli/ui/components/NavigationList.js +0 -11
  98. package/dist/cli/ui/components/NavigationList.js.map +0 -1
  99. package/dist/cli/ui/components/ScrollableContent.d.ts +0 -13
  100. package/dist/cli/ui/components/ScrollableContent.d.ts.map +0 -1
  101. package/dist/cli/ui/components/ScrollableContent.js +0 -11
  102. package/dist/cli/ui/components/ScrollableContent.js.map +0 -1
  103. package/dist/cli/ui/components/index.d.ts +0 -7
  104. package/dist/cli/ui/components/index.d.ts.map +0 -1
  105. package/dist/cli/ui/components/index.js +0 -9
  106. package/dist/cli/ui/components/index.js.map +0 -1
  107. package/dist/cli/ui/terminal-ui.d.ts +0 -85
  108. package/dist/cli/ui/terminal-ui.d.ts.map +0 -1
  109. package/dist/cli/ui/terminal-ui.js +0 -121
  110. package/dist/cli/ui/terminal-ui.js.map +0 -1
  111. package/dist/do/BashModule.d.ts +0 -871
  112. package/dist/do/BashModule.d.ts.map +0 -1
  113. package/dist/do/BashModule.js +0 -1143
  114. package/dist/do/BashModule.js.map +0 -1
  115. package/dist/do/FsModule.d.ts +0 -612
  116. package/dist/do/FsModule.d.ts.map +0 -1
  117. package/dist/do/FsModule.js +0 -1120
  118. package/dist/do/FsModule.js.map +0 -1
  119. package/dist/do/GitModule.d.ts +0 -635
  120. package/dist/do/GitModule.d.ts.map +0 -1
  121. package/dist/do/GitModule.js +0 -784
  122. package/dist/do/GitModule.js.map +0 -1
  123. package/dist/do/GitRepoDO.d.ts +0 -281
  124. package/dist/do/GitRepoDO.d.ts.map +0 -1
  125. package/dist/do/GitRepoDO.js +0 -479
  126. package/dist/do/GitRepoDO.js.map +0 -1
  127. package/dist/do/bash-ast.d.ts +0 -246
  128. package/dist/do/bash-ast.d.ts.map +0 -1
  129. package/dist/do/bash-ast.js +0 -888
  130. package/dist/do/bash-ast.js.map +0 -1
  131. package/dist/do/container-executor.d.ts +0 -491
  132. package/dist/do/container-executor.d.ts.map +0 -1
  133. package/dist/do/container-executor.js +0 -731
  134. package/dist/do/container-executor.js.map +0 -1
  135. package/dist/do/index.d.ts +0 -53
  136. package/dist/do/index.d.ts.map +0 -1
  137. package/dist/do/index.js +0 -91
  138. package/dist/do/index.js.map +0 -1
  139. package/dist/do/tiered-storage.d.ts +0 -403
  140. package/dist/do/tiered-storage.d.ts.map +0 -1
  141. package/dist/do/tiered-storage.js +0 -689
  142. package/dist/do/tiered-storage.js.map +0 -1
  143. package/dist/do/withBash.d.ts +0 -231
  144. package/dist/do/withBash.d.ts.map +0 -1
  145. package/dist/do/withBash.js +0 -244
  146. package/dist/do/withBash.js.map +0 -1
  147. package/dist/do/withFs.d.ts +0 -237
  148. package/dist/do/withFs.d.ts.map +0 -1
  149. package/dist/do/withFs.js +0 -387
  150. package/dist/do/withFs.js.map +0 -1
  151. package/dist/do/withGit.d.ts +0 -180
  152. package/dist/do/withGit.d.ts.map +0 -1
  153. package/dist/do/withGit.js +0 -271
  154. package/dist/do/withGit.js.map +0 -1
  155. package/dist/durable-object/object-store.d.ts +0 -633
  156. package/dist/durable-object/object-store.d.ts.map +0 -1
  157. package/dist/durable-object/object-store.js +0 -1164
  158. package/dist/durable-object/object-store.js.map +0 -1
  159. package/dist/durable-object/schema.d.ts.map +0 -1
  160. package/dist/durable-object/schema.js.map +0 -1
  161. package/dist/durable-object/wal.d.ts +0 -416
  162. package/dist/durable-object/wal.d.ts.map +0 -1
  163. package/dist/durable-object/wal.js +0 -445
  164. package/dist/durable-object/wal.js.map +0 -1
  165. package/dist/mcp/adapter.d.ts +0 -772
  166. package/dist/mcp/adapter.d.ts.map +0 -1
  167. package/dist/mcp/adapter.js +0 -895
  168. package/dist/mcp/adapter.js.map +0 -1
  169. package/dist/mcp/sandbox/miniflare-evaluator.d.ts +0 -22
  170. package/dist/mcp/sandbox/miniflare-evaluator.d.ts.map +0 -1
  171. package/dist/mcp/sandbox/miniflare-evaluator.js +0 -140
  172. package/dist/mcp/sandbox/miniflare-evaluator.js.map +0 -1
  173. package/dist/mcp/sandbox/object-store-proxy.d.ts +0 -32
  174. package/dist/mcp/sandbox/object-store-proxy.d.ts.map +0 -1
  175. package/dist/mcp/sandbox/object-store-proxy.js +0 -30
  176. package/dist/mcp/sandbox/object-store-proxy.js.map +0 -1
  177. package/dist/mcp/sandbox/template.d.ts +0 -17
  178. package/dist/mcp/sandbox/template.d.ts.map +0 -1
  179. package/dist/mcp/sandbox/template.js +0 -71
  180. package/dist/mcp/sandbox/template.js.map +0 -1
  181. package/dist/mcp/sandbox.d.ts +0 -764
  182. package/dist/mcp/sandbox.d.ts.map +0 -1
  183. package/dist/mcp/sandbox.js +0 -1362
  184. package/dist/mcp/sandbox.js.map +0 -1
  185. package/dist/mcp/sdk-adapter.d.ts +0 -835
  186. package/dist/mcp/sdk-adapter.d.ts.map +0 -1
  187. package/dist/mcp/sdk-adapter.js +0 -974
  188. package/dist/mcp/sdk-adapter.js.map +0 -1
  189. package/dist/mcp/tools/do.d.ts +0 -32
  190. package/dist/mcp/tools/do.d.ts.map +0 -1
  191. package/dist/mcp/tools/do.js +0 -117
  192. package/dist/mcp/tools/do.js.map +0 -1
  193. package/dist/mcp/tools.d.ts +0 -548
  194. package/dist/mcp/tools.d.ts.map +0 -1
  195. package/dist/mcp/tools.js +0 -3170
  196. package/dist/mcp/tools.js.map +0 -1
  197. package/dist/ops/blame.d.ts +0 -551
  198. package/dist/ops/blame.d.ts.map +0 -1
  199. package/dist/ops/blame.js +0 -1037
  200. package/dist/ops/blame.js.map +0 -1
  201. package/dist/ops/branch.d.ts +0 -766
  202. package/dist/ops/branch.d.ts.map +0 -1
  203. package/dist/ops/branch.js +0 -950
  204. package/dist/ops/branch.js.map +0 -1
  205. package/dist/ops/commit-traversal.d.ts +0 -349
  206. package/dist/ops/commit-traversal.d.ts.map +0 -1
  207. package/dist/ops/commit-traversal.js +0 -821
  208. package/dist/ops/commit-traversal.js.map +0 -1
  209. package/dist/ops/commit.d.ts +0 -555
  210. package/dist/ops/commit.d.ts.map +0 -1
  211. package/dist/ops/commit.js +0 -826
  212. package/dist/ops/commit.js.map +0 -1
  213. package/dist/ops/merge-base.d.ts +0 -397
  214. package/dist/ops/merge-base.d.ts.map +0 -1
  215. package/dist/ops/merge-base.js +0 -691
  216. package/dist/ops/merge-base.js.map +0 -1
  217. package/dist/ops/merge.d.ts +0 -855
  218. package/dist/ops/merge.d.ts.map +0 -1
  219. package/dist/ops/merge.js +0 -1551
  220. package/dist/ops/merge.js.map +0 -1
  221. package/dist/ops/tag.d.ts +0 -247
  222. package/dist/ops/tag.d.ts.map +0 -1
  223. package/dist/ops/tag.js +0 -649
  224. package/dist/ops/tag.js.map +0 -1
  225. package/dist/ops/tree-builder.d.ts +0 -178
  226. package/dist/ops/tree-builder.d.ts.map +0 -1
  227. package/dist/ops/tree-builder.js +0 -271
  228. package/dist/ops/tree-builder.js.map +0 -1
  229. package/dist/ops/tree-diff.d.ts +0 -291
  230. package/dist/ops/tree-diff.d.ts.map +0 -1
  231. package/dist/ops/tree-diff.js +0 -705
  232. package/dist/ops/tree-diff.js.map +0 -1
  233. package/dist/pack/delta.d.ts +0 -248
  234. package/dist/pack/delta.d.ts.map +0 -1
  235. package/dist/pack/delta.js +0 -740
  236. package/dist/pack/delta.js.map +0 -1
  237. package/dist/pack/format.d.ts +0 -446
  238. package/dist/pack/format.d.ts.map +0 -1
  239. package/dist/pack/format.js +0 -572
  240. package/dist/pack/format.js.map +0 -1
  241. package/dist/pack/full-generation.d.ts +0 -612
  242. package/dist/pack/full-generation.d.ts.map +0 -1
  243. package/dist/pack/full-generation.js +0 -1378
  244. package/dist/pack/full-generation.js.map +0 -1
  245. package/dist/pack/generation.d.ts +0 -441
  246. package/dist/pack/generation.d.ts.map +0 -1
  247. package/dist/pack/generation.js +0 -707
  248. package/dist/pack/generation.js.map +0 -1
  249. package/dist/pack/index.d.ts +0 -502
  250. package/dist/pack/index.d.ts.map +0 -1
  251. package/dist/pack/index.js +0 -833
  252. package/dist/pack/index.js.map +0 -1
  253. package/dist/refs/branch.d.ts +0 -683
  254. package/dist/refs/branch.d.ts.map +0 -1
  255. package/dist/refs/branch.js +0 -881
  256. package/dist/refs/branch.js.map +0 -1
  257. package/dist/refs/storage.d.ts +0 -833
  258. package/dist/refs/storage.d.ts.map +0 -1
  259. package/dist/refs/storage.js +0 -1023
  260. package/dist/refs/storage.js.map +0 -1
  261. package/dist/refs/tag.d.ts +0 -860
  262. package/dist/refs/tag.d.ts.map +0 -1
  263. package/dist/refs/tag.js +0 -996
  264. package/dist/refs/tag.js.map +0 -1
  265. package/dist/storage/backend.d.ts +0 -425
  266. package/dist/storage/backend.d.ts.map +0 -1
  267. package/dist/storage/backend.js +0 -41
  268. package/dist/storage/backend.js.map +0 -1
  269. package/dist/storage/fsx-adapter.d.ts +0 -204
  270. package/dist/storage/fsx-adapter.d.ts.map +0 -1
  271. package/dist/storage/fsx-adapter.js +0 -518
  272. package/dist/storage/fsx-adapter.js.map +0 -1
  273. package/dist/storage/lru-cache.d.ts +0 -691
  274. package/dist/storage/lru-cache.d.ts.map +0 -1
  275. package/dist/storage/lru-cache.js +0 -813
  276. package/dist/storage/lru-cache.js.map +0 -1
  277. package/dist/storage/object-index.d.ts +0 -585
  278. package/dist/storage/object-index.d.ts.map +0 -1
  279. package/dist/storage/object-index.js +0 -532
  280. package/dist/storage/object-index.js.map +0 -1
  281. package/dist/storage/r2-pack.d.ts +0 -1257
  282. package/dist/storage/r2-pack.d.ts.map +0 -1
  283. package/dist/storage/r2-pack.js +0 -1773
  284. package/dist/storage/r2-pack.js.map +0 -1
  285. package/dist/tiered/cdc-pipeline.d.ts +0 -1888
  286. package/dist/tiered/cdc-pipeline.d.ts.map +0 -1
  287. package/dist/tiered/cdc-pipeline.js +0 -1880
  288. package/dist/tiered/cdc-pipeline.js.map +0 -1
  289. package/dist/tiered/migration.d.ts +0 -1104
  290. package/dist/tiered/migration.d.ts.map +0 -1
  291. package/dist/tiered/migration.js +0 -1217
  292. package/dist/tiered/migration.js.map +0 -1
  293. package/dist/tiered/parquet-writer.d.ts +0 -1145
  294. package/dist/tiered/parquet-writer.d.ts.map +0 -1
  295. package/dist/tiered/parquet-writer.js +0 -1183
  296. package/dist/tiered/parquet-writer.js.map +0 -1
  297. package/dist/tiered/read-path.d.ts +0 -835
  298. package/dist/tiered/read-path.d.ts.map +0 -1
  299. package/dist/tiered/read-path.js +0 -487
  300. package/dist/tiered/read-path.js.map +0 -1
  301. package/dist/types/capability.d.ts +0 -1385
  302. package/dist/types/capability.d.ts.map +0 -1
  303. package/dist/types/capability.js +0 -36
  304. package/dist/types/capability.js.map +0 -1
  305. package/dist/types/index.d.ts +0 -13
  306. package/dist/types/index.d.ts.map +0 -1
  307. package/dist/types/index.js +0 -18
  308. package/dist/types/index.js.map +0 -1
  309. package/dist/types/interfaces.d.ts +0 -673
  310. package/dist/types/interfaces.d.ts.map +0 -1
  311. package/dist/types/interfaces.js +0 -26
  312. package/dist/types/interfaces.js.map +0 -1
  313. package/dist/types/objects.d.ts +0 -692
  314. package/dist/types/objects.d.ts.map +0 -1
  315. package/dist/types/objects.js +0 -837
  316. package/dist/types/objects.js.map +0 -1
  317. package/dist/types/storage.d.ts +0 -603
  318. package/dist/types/storage.d.ts.map +0 -1
  319. package/dist/types/storage.js +0 -191
  320. package/dist/types/storage.js.map +0 -1
  321. package/dist/types/worker-loader.d.ts +0 -60
  322. package/dist/types/worker-loader.d.ts.map +0 -1
  323. package/dist/types/worker-loader.js +0 -62
  324. package/dist/types/worker-loader.js.map +0 -1
  325. package/dist/utils/hash.d.ts +0 -198
  326. package/dist/utils/hash.d.ts.map +0 -1
  327. package/dist/utils/hash.js +0 -272
  328. package/dist/utils/hash.js.map +0 -1
  329. package/dist/utils/sha1.d.ts +0 -325
  330. package/dist/utils/sha1.d.ts.map +0 -1
  331. package/dist/utils/sha1.js +0 -635
  332. package/dist/utils/sha1.js.map +0 -1
  333. package/dist/wire/capabilities.d.ts +0 -1044
  334. package/dist/wire/capabilities.d.ts.map +0 -1
  335. package/dist/wire/capabilities.js +0 -941
  336. package/dist/wire/capabilities.js.map +0 -1
  337. package/dist/wire/path-security.d.ts +0 -157
  338. package/dist/wire/path-security.d.ts.map +0 -1
  339. package/dist/wire/path-security.js +0 -307
  340. package/dist/wire/path-security.js.map +0 -1
  341. package/dist/wire/pkt-line.d.ts +0 -345
  342. package/dist/wire/pkt-line.d.ts.map +0 -1
  343. package/dist/wire/pkt-line.js +0 -381
  344. package/dist/wire/pkt-line.js.map +0 -1
  345. package/dist/wire/receive-pack.d.ts +0 -1059
  346. package/dist/wire/receive-pack.d.ts.map +0 -1
  347. package/dist/wire/receive-pack.js +0 -1414
  348. package/dist/wire/receive-pack.js.map +0 -1
  349. package/dist/wire/smart-http.d.ts +0 -799
  350. package/dist/wire/smart-http.d.ts.map +0 -1
  351. package/dist/wire/smart-http.js +0 -945
  352. package/dist/wire/smart-http.js.map +0 -1
  353. package/dist/wire/upload-pack.d.ts +0 -727
  354. package/dist/wire/upload-pack.d.ts.map +0 -1
  355. package/dist/wire/upload-pack.js +0 -1141
  356. package/dist/wire/upload-pack.js.map +0 -1
@@ -1,950 +0,0 @@
1
- /**
2
- * @fileoverview Git Branch Operations
3
- *
4
- * Provides comprehensive branch management functionality including creating,
5
- * deleting, renaming, listing, and checking out branches. Also handles
6
- * tracking relationships with remote branches.
7
- *
8
- * ## Features
9
- *
10
- * - Branch creation from any commit or ref
11
- * - Branch deletion with merge checking
12
- * - Branch renaming with HEAD update
13
- * - Branch listing with filtering and sorting
14
- * - Checkout with create option
15
- * - Remote tracking branch support
16
- * - Default branch detection
17
- *
18
- * ## Usage Example
19
- *
20
- * ```typescript
21
- * import { createBranch, checkoutBranch, listBranches } from './ops/branch'
22
- *
23
- * // Create a new feature branch
24
- * const result = await createBranch(refStore, {
25
- * name: 'feature/new-feature',
26
- * startPoint: 'main',
27
- * checkout: true
28
- * })
29
- *
30
- * // List all branches
31
- * const branches = await listBranches(refStore, { all: true })
32
- *
33
- * // Checkout existing branch
34
- * await checkoutBranch(refStore, { name: 'develop' })
35
- * ```
36
- *
37
- * @module ops/branch
38
- */
39
- // ============================================================================
40
- // Internal state storage for tracking info (in-memory for the mock RefStore)
41
- // ============================================================================
42
- // Use WeakMap to associate tracking info with specific RefStore instances
43
- // This ensures that each RefStore has its own tracking state
44
- const trackingStores = new WeakMap();
45
- const defaultBranchNames = new WeakMap();
46
- /**
47
- * Gets the tracking store for a specific RefStore instance.
48
- * @param refStore - The ref store to get tracking info for
49
- * @returns Map of branch names to tracking info
50
- * @internal
51
- */
52
- function getTrackingStore(refStore) {
53
- let store = trackingStores.get(refStore);
54
- if (!store) {
55
- store = new Map();
56
- trackingStores.set(refStore, store);
57
- }
58
- return store;
59
- }
60
- // ============================================================================
61
- // Branch Name Validation
62
- // ============================================================================
63
- /** Maximum allowed length for branch names */
64
- const MAX_BRANCH_NAME_LENGTH = 255;
65
- /**
66
- * Validates a branch name according to Git naming rules.
67
- *
68
- * Git branch names have specific rules to ensure they work correctly
69
- * across all platforms and don't conflict with Git's special syntax.
70
- *
71
- * Rules checked:
72
- * - Not empty
73
- * - Not longer than 255 characters
74
- * - Does not start with '-'
75
- * - Does not end with '.lock', '/', or '.'
76
- * - Does not contain '..', '//', '@{', or '@'
77
- * - Is not 'HEAD' and does not start with 'refs/'
78
- * - Contains no invalid characters (space, ~, ^, :, \, ?, *, [, control chars)
79
- * - Contains only ASCII characters
80
- *
81
- * @param name - The branch name to validate
82
- * @returns true if the name is valid
83
- *
84
- * @example
85
- * ```typescript
86
- * isValidBranchName('feature/login') // true
87
- * isValidBranchName('my-branch') // true
88
- * isValidBranchName('-invalid') // false (starts with dash)
89
- * isValidBranchName('refs/heads/x') // false (starts with refs/)
90
- * isValidBranchName('has space') // false (contains space)
91
- * ```
92
- */
93
- export function isValidBranchName(name) {
94
- // Empty string is invalid
95
- if (!name || name.length === 0) {
96
- return false;
97
- }
98
- // Check max length
99
- if (name.length > MAX_BRANCH_NAME_LENGTH) {
100
- return false;
101
- }
102
- // Cannot start with dash
103
- if (name.startsWith('-')) {
104
- return false;
105
- }
106
- // Cannot end with .lock
107
- if (name.endsWith('.lock')) {
108
- return false;
109
- }
110
- // Cannot end with slash or dot
111
- if (name.endsWith('/') || name.endsWith('.')) {
112
- return false;
113
- }
114
- // Cannot contain double dots
115
- if (name.includes('..')) {
116
- return false;
117
- }
118
- // Cannot contain consecutive slashes
119
- if (name.includes('//')) {
120
- return false;
121
- }
122
- // Cannot be exactly "@"
123
- if (name === '@') {
124
- return false;
125
- }
126
- // Cannot contain @{
127
- if (name.includes('@{')) {
128
- return false;
129
- }
130
- // Cannot be HEAD or start with refs/
131
- if (name === 'HEAD' || name.startsWith('refs/')) {
132
- return false;
133
- }
134
- // Check for invalid characters
135
- // Git disallows: space, ~, ^, :, \, ?, *, [, control characters
136
- const invalidChars = /[\s~^:\\?*\[\x00-\x1f\x7f]/;
137
- if (invalidChars.test(name)) {
138
- return false;
139
- }
140
- // Check for non-ASCII characters (unicode)
141
- // eslint-disable-next-line no-control-regex
142
- if (/[^\x00-\x7F]/.test(name)) {
143
- return false;
144
- }
145
- return true;
146
- }
147
- /**
148
- * Normalizes a branch name by removing refs/heads/ prefix.
149
- *
150
- * @param name - The branch name or ref path
151
- * @returns The normalized branch name
152
- *
153
- * @example
154
- * ```typescript
155
- * normalizeBranchName('refs/heads/main') // 'main'
156
- * normalizeBranchName('main') // 'main'
157
- * ```
158
- */
159
- export function normalizeBranchName(name) {
160
- if (name.startsWith('refs/heads/')) {
161
- return name.slice(11);
162
- }
163
- return name;
164
- }
165
- /**
166
- * Gets the full ref path for a branch name.
167
- * @param name - The branch name
168
- * @param remote - If true, return remote ref path
169
- * @returns The full ref path
170
- * @internal
171
- */
172
- function getRefPath(name, remote = false) {
173
- if (name.startsWith('refs/')) {
174
- return name;
175
- }
176
- if (remote) {
177
- return `refs/remotes/${name}`;
178
- }
179
- return `refs/heads/${name}`;
180
- }
181
- // ============================================================================
182
- // Branch Operations
183
- // ============================================================================
184
- /**
185
- * Resolves a start point to a SHA.
186
- * Handles branch names, remote refs, and direct SHAs.
187
- * @param refStore - The ref store
188
- * @param startPoint - The start point to resolve
189
- * @returns The resolved SHA, or null if not found
190
- * @internal
191
- */
192
- async function resolveStartPoint(refStore, startPoint) {
193
- // Check if it's already a SHA (40 hex chars)
194
- if (/^[a-f0-9]{40}$/i.test(startPoint)) {
195
- return startPoint;
196
- }
197
- // Try as local branch
198
- const localRef = await refStore.getRef(`refs/heads/${startPoint}`);
199
- if (localRef) {
200
- return localRef;
201
- }
202
- // Try as remote branch (origin/branch format)
203
- if (startPoint.includes('/')) {
204
- const remoteRef = await refStore.getRef(`refs/remotes/${startPoint}`);
205
- if (remoteRef) {
206
- return remoteRef;
207
- }
208
- }
209
- // Try as full ref
210
- const fullRef = await refStore.getRef(startPoint);
211
- if (fullRef) {
212
- return fullRef;
213
- }
214
- return null;
215
- }
216
- /**
217
- * Creates a new branch.
218
- *
219
- * Creates a branch pointing to the specified commit or the current HEAD.
220
- * Optionally checks out the branch after creation.
221
- *
222
- * @param refStore - The ref store for accessing refs
223
- * @param options - Branch creation options
224
- * @returns Result of the branch creation
225
- *
226
- * @throws {Error} If the branch name is invalid
227
- * @throws {Error} If the branch already exists and force is false
228
- * @throws {Error} If the start point cannot be resolved
229
- *
230
- * @example
231
- * ```typescript
232
- * // Create branch from current HEAD
233
- * const result = await createBranch(refStore, { name: 'feature/new' })
234
- *
235
- * // Create branch from specific commit
236
- * const result = await createBranch(refStore, {
237
- * name: 'hotfix/urgent',
238
- * startPoint: 'abc123def456...'
239
- * })
240
- *
241
- * // Create and checkout
242
- * const result = await createBranch(refStore, {
243
- * name: 'develop',
244
- * startPoint: 'main',
245
- * checkout: true
246
- * })
247
- * ```
248
- */
249
- export async function createBranch(refStore, options) {
250
- const { name, startPoint, force = false, checkout = false } = options;
251
- // Validate branch name
252
- if (!isValidBranchName(name)) {
253
- throw new Error(`Invalid branch name: ${name}`);
254
- }
255
- const refPath = getRefPath(name);
256
- // Check if branch already exists
257
- const existingRef = await refStore.getRef(refPath);
258
- if (existingRef && !force) {
259
- throw new Error(`Branch '${name}' already exists`);
260
- }
261
- // Resolve the start point to a SHA
262
- let sha;
263
- if (startPoint) {
264
- const resolved = await resolveStartPoint(refStore, startPoint);
265
- if (!resolved) {
266
- throw new Error(`Invalid start point: ${startPoint}`);
267
- }
268
- sha = resolved;
269
- }
270
- else {
271
- // Use current HEAD
272
- const headRef = await refStore.getSymbolicRef('HEAD');
273
- if (headRef) {
274
- const headSha = await refStore.getRef(headRef);
275
- if (!headSha) {
276
- throw new Error('HEAD does not point to a valid commit');
277
- }
278
- sha = headSha;
279
- }
280
- else {
281
- // Detached HEAD - get the direct SHA
282
- const headSha = await refStore.getHead();
283
- sha = headSha;
284
- }
285
- }
286
- // Create the branch
287
- await refStore.setRef(refPath, sha);
288
- // Checkout if requested
289
- if (checkout) {
290
- await refStore.setSymbolicRef('HEAD', refPath);
291
- }
292
- return {
293
- name,
294
- ref: refPath,
295
- sha,
296
- created: !existingRef
297
- };
298
- }
299
- /**
300
- * Deletes a branch.
301
- *
302
- * Removes the specified branch ref. Can delete multiple branches at once.
303
- * Supports checking if the branch is merged before deleting.
304
- *
305
- * @param refStore - The ref store for accessing refs
306
- * @param options - Delete options
307
- * @returns Result of the delete operation
308
- *
309
- * @throws {Error} If no branch name is provided
310
- * @throws {Error} If the branch doesn't exist
311
- * @throws {Error} If trying to delete the current branch
312
- * @throws {Error} If branch is not merged and force is false
313
- *
314
- * @example
315
- * ```typescript
316
- * // Delete a single branch
317
- * await deleteBranch(refStore, { name: 'old-feature' })
318
- *
319
- * // Force delete unmerged branch
320
- * await deleteBranch(refStore, { name: 'experimental', force: true })
321
- *
322
- * // Delete remote-tracking branch
323
- * await deleteBranch(refStore, {
324
- * name: 'origin/old-feature',
325
- * remote: true
326
- * })
327
- * ```
328
- */
329
- export async function deleteBranch(refStore, options) {
330
- const { name, names, force = false, checkMerged = false, remote = false } = options;
331
- // Handle multiple branches
332
- if (names && names.length > 0) {
333
- const deletedBranches = [];
334
- for (const branchName of names) {
335
- const result = await deleteBranch(refStore, {
336
- name: branchName,
337
- force,
338
- checkMerged,
339
- remote
340
- });
341
- if (result.deleted) {
342
- deletedBranches.push({ name: result.name, sha: result.sha });
343
- }
344
- }
345
- return {
346
- deleted: deletedBranches.length > 0,
347
- name: names[0],
348
- sha: deletedBranches[0]?.sha || '',
349
- deletedBranches
350
- };
351
- }
352
- if (!name) {
353
- throw new Error('Branch name is required');
354
- }
355
- // Determine the ref path
356
- const refPath = remote
357
- ? `refs/remotes/${name}`
358
- : getRefPath(name);
359
- // Check if branch exists
360
- const sha = await refStore.getRef(refPath);
361
- if (!sha) {
362
- throw new Error(`Branch '${name}' not found`);
363
- }
364
- // Check if trying to delete current branch
365
- if (!remote) {
366
- const currentBranch = await getCurrentBranch(refStore);
367
- if (currentBranch === normalizeBranchName(name)) {
368
- throw new Error(`Cannot delete the current branch '${name}'`);
369
- }
370
- }
371
- // Check if branch is merged (simplified check)
372
- if (checkMerged && !force) {
373
- // For the test, we check if the branch SHA differs from main
374
- const mainSha = await refStore.getRef('refs/heads/main');
375
- if (sha !== mainSha) {
376
- throw new Error(`Branch '${name}' is not fully merged`);
377
- }
378
- }
379
- // Delete the branch
380
- await refStore.deleteRef(refPath);
381
- // Remove tracking info if exists
382
- getTrackingStore(refStore).delete(name);
383
- return {
384
- deleted: true,
385
- name: normalizeBranchName(name),
386
- sha,
387
- deletedBranches: [{ name: normalizeBranchName(name), sha }]
388
- };
389
- }
390
- /**
391
- * Lists branches.
392
- *
393
- * Returns a list of branches with optional filtering and sorting.
394
- * Can list local branches, remote-tracking branches, or both.
395
- *
396
- * @param refStore - The ref store for accessing refs
397
- * @param options - Listing options
398
- * @returns Array of branch information
399
- *
400
- * @example
401
- * ```typescript
402
- * // List local branches
403
- * const branches = await listBranches(refStore)
404
- *
405
- * // List all branches sorted by name descending
406
- * const branches = await listBranches(refStore, {
407
- * all: true,
408
- * sort: '-name'
409
- * })
410
- *
411
- * // List branches matching pattern with verbose info
412
- * const branches = await listBranches(refStore, {
413
- * pattern: 'feature/*',
414
- * verbose: true
415
- * })
416
- * ```
417
- */
418
- export async function listBranches(refStore, options = {}) {
419
- const { remote = false, all = false, pattern, contains, merged: _merged, noMerged: _noMerged, sort, verbose = false } = options;
420
- const branches = [];
421
- const currentBranch = await getCurrentBranch(refStore);
422
- // Get local branches
423
- if (!remote || all) {
424
- const localRefs = await refStore.listRefs('refs/heads/');
425
- for (const { ref, sha } of localRefs) {
426
- const name = normalizeBranchName(ref);
427
- // Apply pattern filter
428
- if (pattern && !matchPattern(name, pattern)) {
429
- continue;
430
- }
431
- // Apply contains filter
432
- if (contains && sha !== contains) {
433
- continue;
434
- }
435
- const branchInfo = {
436
- name,
437
- ref,
438
- sha,
439
- current: name === currentBranch
440
- };
441
- if (verbose) {
442
- branchInfo.tracking = getTrackingStore(refStore).get(name) || null;
443
- branchInfo.commitSubject = '';
444
- }
445
- branches.push(branchInfo);
446
- }
447
- }
448
- // Get remote branches
449
- if (remote || all) {
450
- const remoteRefs = await refStore.listRefs('refs/remotes/');
451
- for (const { ref, sha } of remoteRefs) {
452
- const name = ref.replace('refs/remotes/', '');
453
- // Apply pattern filter
454
- if (pattern && !matchPattern(name, pattern)) {
455
- continue;
456
- }
457
- // Apply contains filter
458
- if (contains && sha !== contains) {
459
- continue;
460
- }
461
- const branchInfo = {
462
- name,
463
- ref,
464
- sha,
465
- current: false
466
- };
467
- if (verbose) {
468
- branchInfo.tracking = null;
469
- branchInfo.commitSubject = '';
470
- }
471
- branches.push(branchInfo);
472
- }
473
- }
474
- // Apply sorting
475
- if (sort) {
476
- const descending = sort.startsWith('-');
477
- const sortField = descending ? sort.slice(1) : sort;
478
- if (sortField === 'name') {
479
- branches.sort((a, b) => {
480
- const cmp = a.name.localeCompare(b.name);
481
- return descending ? -cmp : cmp;
482
- });
483
- }
484
- // committerdate sorting would require commit info - just return as-is
485
- }
486
- return branches;
487
- }
488
- /**
489
- * Simple glob pattern matching for branch names.
490
- * @param name - The name to match
491
- * @param pattern - The glob pattern
492
- * @returns True if the name matches the pattern
493
- * @internal
494
- */
495
- function matchPattern(name, pattern) {
496
- // Convert glob pattern to regex
497
- const regexPattern = pattern
498
- .replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special regex chars
499
- .replace(/\*/g, '.*')
500
- .replace(/\?/g, '.');
501
- const regex = new RegExp(`^${regexPattern}$`);
502
- return regex.test(name);
503
- }
504
- /**
505
- * Renames a branch.
506
- *
507
- * Renames the specified branch, or the current branch if none specified.
508
- * Updates HEAD if renaming the current branch. Transfers tracking info.
509
- *
510
- * @param refStore - The ref store for accessing refs
511
- * @param options - Rename options
512
- * @returns Result of the rename operation
513
- *
514
- * @throws {Error} If no current branch when oldName not specified
515
- * @throws {Error} If the new name is invalid
516
- * @throws {Error} If the old branch doesn't exist
517
- * @throws {Error} If the new name exists and force is false
518
- *
519
- * @example
520
- * ```typescript
521
- * // Rename current branch
522
- * await renameBranch(refStore, { newName: 'better-name' })
523
- *
524
- * // Rename specific branch
525
- * await renameBranch(refStore, {
526
- * oldName: 'old-feature',
527
- * newName: 'feature/improved'
528
- * })
529
- *
530
- * // Force rename (overwrites existing)
531
- * await renameBranch(refStore, {
532
- * oldName: 'temp',
533
- * newName: 'main',
534
- * force: true
535
- * })
536
- * ```
537
- */
538
- export async function renameBranch(refStore, options) {
539
- let { oldName, newName, force = false } = options;
540
- // If oldName not specified, use current branch
541
- if (!oldName) {
542
- const current = await getCurrentBranch(refStore);
543
- if (!current) {
544
- throw new Error('No current branch to rename');
545
- }
546
- oldName = current;
547
- }
548
- // Validate new name
549
- if (!isValidBranchName(newName)) {
550
- throw new Error(`Invalid branch name: ${newName}`);
551
- }
552
- // Check if old branch exists
553
- const oldRefPath = getRefPath(oldName);
554
- const sha = await refStore.getRef(oldRefPath);
555
- if (!sha) {
556
- throw new Error(`Branch '${oldName}' not found`);
557
- }
558
- // Check if new name already exists
559
- const newRefPath = getRefPath(newName);
560
- const existingNew = await refStore.getRef(newRefPath);
561
- if (existingNew && !force) {
562
- throw new Error(`Branch '${newName}' already exists`);
563
- }
564
- // Check if renaming current branch
565
- const currentBranch = await getCurrentBranch(refStore);
566
- const isCurrentBranch = currentBranch === oldName;
567
- // Create new branch ref
568
- await refStore.setRef(newRefPath, sha);
569
- // Delete old branch ref
570
- await refStore.deleteRef(oldRefPath);
571
- // Update HEAD if renaming current branch
572
- if (isCurrentBranch) {
573
- await refStore.setSymbolicRef('HEAD', newRefPath);
574
- }
575
- // Transfer tracking info if exists
576
- const store = getTrackingStore(refStore);
577
- const trackingInfo = store.get(oldName);
578
- if (trackingInfo) {
579
- store.delete(oldName);
580
- store.set(newName, trackingInfo);
581
- }
582
- return {
583
- renamed: true,
584
- oldName,
585
- newName,
586
- sha
587
- };
588
- }
589
- /**
590
- * Checks out a branch.
591
- *
592
- * Switches HEAD to point to the specified branch or commit.
593
- * Can create a new branch during checkout and set up tracking.
594
- *
595
- * @param refStore - The ref store for accessing refs
596
- * @param options - Checkout options
597
- * @returns Result of the checkout operation
598
- *
599
- * @throws {Error} If neither name nor sha is provided
600
- * @throws {Error} If branch doesn't exist and create is false
601
- * @throws {Error} If branch exists when creating and force is false
602
- *
603
- * @example
604
- * ```typescript
605
- * // Checkout existing branch
606
- * await checkoutBranch(refStore, { name: 'develop' })
607
- *
608
- * // Create and checkout new branch from main
609
- * await checkoutBranch(refStore, {
610
- * name: 'feature/new',
611
- * create: true,
612
- * startPoint: 'main'
613
- * })
614
- *
615
- * // Detached HEAD checkout
616
- * await checkoutBranch(refStore, {
617
- * sha: 'abc123def456...',
618
- * detach: true
619
- * })
620
- *
621
- * // Create branch with tracking
622
- * await checkoutBranch(refStore, {
623
- * name: 'feature/tracked',
624
- * create: true,
625
- * track: 'origin/feature/tracked'
626
- * })
627
- * ```
628
- */
629
- export async function checkoutBranch(refStore, options) {
630
- const { name, sha, create = false, force = false, startPoint, detach = false, track } = options;
631
- // Validation: can't have both name and sha without detach
632
- if (name && sha && !detach) {
633
- throw new Error('Cannot specify both branch name and SHA without detach');
634
- }
635
- // Detached HEAD checkout
636
- if (detach && sha) {
637
- await refStore.setHead(sha);
638
- return {
639
- success: true,
640
- branch: null,
641
- sha,
642
- detached: true
643
- };
644
- }
645
- if (!name) {
646
- throw new Error('Branch name is required');
647
- }
648
- // Create new branch if requested
649
- if (create) {
650
- const refPath = getRefPath(name);
651
- const existing = await refStore.getRef(refPath);
652
- if (existing && !force) {
653
- throw new Error(`Branch '${name}' already exists`);
654
- }
655
- // Resolve start point
656
- let targetSha;
657
- if (startPoint) {
658
- const resolved = await resolveStartPoint(refStore, startPoint);
659
- if (!resolved) {
660
- throw new Error(`Invalid start point: ${startPoint}`);
661
- }
662
- targetSha = resolved;
663
- }
664
- else {
665
- const headRef = await refStore.getSymbolicRef('HEAD');
666
- if (headRef) {
667
- targetSha = (await refStore.getRef(headRef)) || '';
668
- }
669
- else {
670
- targetSha = await refStore.getHead();
671
- }
672
- }
673
- await refStore.setRef(refPath, targetSha);
674
- await refStore.setSymbolicRef('HEAD', refPath);
675
- // Set tracking if specified
676
- if (track) {
677
- const [remote, ...branchParts] = track.split('/');
678
- const remoteBranch = branchParts.join('/');
679
- getTrackingStore(refStore).set(name, {
680
- upstream: track,
681
- remote,
682
- remoteBranch,
683
- ahead: 0,
684
- behind: 0
685
- });
686
- }
687
- return {
688
- success: true,
689
- branch: name,
690
- sha: targetSha,
691
- created: !existing,
692
- tracking: track
693
- };
694
- }
695
- // Checkout existing branch
696
- const refPath = getRefPath(name);
697
- const branchSha = await refStore.getRef(refPath);
698
- if (!branchSha) {
699
- throw new Error(`Branch '${name}' not found`);
700
- }
701
- await refStore.setSymbolicRef('HEAD', refPath);
702
- // Set tracking if specified
703
- if (track) {
704
- const [remote, ...branchParts] = track.split('/');
705
- const remoteBranch = branchParts.join('/');
706
- getTrackingStore(refStore).set(name, {
707
- upstream: track,
708
- remote,
709
- remoteBranch,
710
- ahead: 0,
711
- behind: 0
712
- });
713
- }
714
- return {
715
- success: true,
716
- branch: name,
717
- sha: branchSha,
718
- tracking: track
719
- };
720
- }
721
- /**
722
- * Gets the current branch name.
723
- *
724
- * Returns the name of the currently checked out branch, or null
725
- * if in detached HEAD state.
726
- *
727
- * @param refStore - The ref store for accessing refs
728
- * @returns The current branch name, or null if detached
729
- *
730
- * @example
731
- * ```typescript
732
- * const current = await getCurrentBranch(refStore)
733
- * if (current) {
734
- * console.log(`On branch ${current}`)
735
- * } else {
736
- * console.log('HEAD detached')
737
- * }
738
- * ```
739
- */
740
- export async function getCurrentBranch(refStore) {
741
- const headRef = await refStore.getSymbolicRef('HEAD');
742
- if (!headRef) {
743
- return null;
744
- }
745
- return normalizeBranchName(headRef);
746
- }
747
- /**
748
- * Gets detailed information about a branch.
749
- *
750
- * @param refStore - The ref store for accessing refs
751
- * @param name - The branch name
752
- * @returns Branch info, or null if branch doesn't exist
753
- *
754
- * @example
755
- * ```typescript
756
- * const info = await getBranchInfo(refStore, 'feature/login')
757
- * if (info) {
758
- * console.log(`${info.name} -> ${info.sha.slice(0, 8)}`)
759
- * if (info.current) {
760
- * console.log(' (current branch)')
761
- * }
762
- * }
763
- * ```
764
- */
765
- export async function getBranchInfo(refStore, name) {
766
- const refPath = getRefPath(name);
767
- const sha = await refStore.getRef(refPath);
768
- if (!sha) {
769
- return null;
770
- }
771
- const currentBranch = await getCurrentBranch(refStore);
772
- return {
773
- name,
774
- ref: refPath,
775
- sha,
776
- current: name === currentBranch,
777
- tracking: getTrackingStore(refStore).get(name) || null
778
- };
779
- }
780
- /**
781
- * Checks if a branch exists.
782
- *
783
- * @param refStore - The ref store for accessing refs
784
- * @param name - The branch name to check
785
- * @param options - Options for the check
786
- * @param options.remote - If true, check remote-tracking branches
787
- * @returns true if the branch exists
788
- *
789
- * @example
790
- * ```typescript
791
- * if (await branchExists(refStore, 'feature/login')) {
792
- * console.log('Branch exists')
793
- * }
794
- *
795
- * // Check remote branch
796
- * if (await branchExists(refStore, 'origin/main', { remote: true })) {
797
- * console.log('Remote branch exists')
798
- * }
799
- * ```
800
- */
801
- export async function branchExists(refStore, name, options = {}) {
802
- const { remote = false } = options;
803
- const refPath = remote
804
- ? `refs/remotes/${name}`
805
- : getRefPath(name);
806
- const sha = await refStore.getRef(refPath);
807
- return sha !== null;
808
- }
809
- /**
810
- * Sets tracking information for a branch.
811
- *
812
- * Configures a local branch to track a remote branch, enabling
813
- * push/pull shortcuts and status information.
814
- *
815
- * @param refStore - The ref store for accessing refs
816
- * @param branch - The local branch name
817
- * @param upstream - The upstream ref (e.g., 'origin/main')
818
- * @returns Result of setting tracking
819
- *
820
- * @throws {Error} If the local branch doesn't exist
821
- *
822
- * @example
823
- * ```typescript
824
- * await setBranchTracking(refStore, 'feature/login', 'origin/feature/login')
825
- * ```
826
- */
827
- export async function setBranchTracking(refStore, branch, upstream) {
828
- // Check if local branch exists
829
- const refPath = getRefPath(branch);
830
- const exists = await refStore.getRef(refPath);
831
- if (!exists) {
832
- throw new Error(`Branch '${branch}' not found`);
833
- }
834
- // Parse upstream
835
- const [remote, ...branchParts] = upstream.split('/');
836
- const remoteBranch = branchParts.join('/');
837
- const trackingInfo = {
838
- upstream,
839
- remote,
840
- remoteBranch,
841
- ahead: 0,
842
- behind: 0
843
- };
844
- getTrackingStore(refStore).set(branch, trackingInfo);
845
- return {
846
- success: true,
847
- branch,
848
- upstream,
849
- remote,
850
- remoteBranch
851
- };
852
- }
853
- /**
854
- * Gets tracking information for a branch.
855
- *
856
- * @param refStore - The ref store for accessing refs
857
- * @param branch - The branch name
858
- * @returns Tracking info, or null if not tracking
859
- *
860
- * @example
861
- * ```typescript
862
- * const tracking = await getBranchTracking(refStore, 'main')
863
- * if (tracking) {
864
- * console.log(`Tracking ${tracking.upstream}`)
865
- * console.log(`${tracking.ahead} ahead, ${tracking.behind} behind`)
866
- * }
867
- * ```
868
- */
869
- export async function getBranchTracking(refStore, branch) {
870
- return getTrackingStore(refStore).get(branch) || null;
871
- }
872
- /**
873
- * Removes tracking information from a branch.
874
- *
875
- * @param refStore - The ref store for accessing refs
876
- * @param branch - The branch name
877
- * @returns Result of removing tracking
878
- *
879
- * @example
880
- * ```typescript
881
- * await removeBranchTracking(refStore, 'feature/old')
882
- * ```
883
- */
884
- export async function removeBranchTracking(refStore, branch) {
885
- getTrackingStore(refStore).delete(branch);
886
- return { success: true };
887
- }
888
- /**
889
- * Gets the default branch name for a repository.
890
- *
891
- * Returns the configured default branch, or attempts to detect it
892
- * by checking for 'main' or 'master' branches.
893
- *
894
- * @param refStore - The ref store for accessing refs
895
- * @returns The default branch name, or null if none found
896
- *
897
- * @example
898
- * ```typescript
899
- * const defaultBranch = await getDefaultBranch(refStore)
900
- * if (defaultBranch) {
901
- * console.log(`Default branch: ${defaultBranch}`)
902
- * }
903
- * ```
904
- */
905
- export async function getDefaultBranch(refStore) {
906
- // Return stored default if set
907
- const storedDefault = defaultBranchNames.get(refStore);
908
- if (storedDefault) {
909
- return storedDefault;
910
- }
911
- // Check if 'main' exists
912
- const mainExists = await refStore.getRef('refs/heads/main');
913
- if (mainExists) {
914
- return 'main';
915
- }
916
- // Check if 'master' exists
917
- const masterExists = await refStore.getRef('refs/heads/master');
918
- if (masterExists) {
919
- return 'master';
920
- }
921
- // Return first available branch
922
- const branches = await refStore.listRefs('refs/heads/');
923
- if (branches.length > 0) {
924
- return normalizeBranchName(branches[0].ref);
925
- }
926
- return null;
927
- }
928
- /**
929
- * Sets the default branch for a repository.
930
- *
931
- * @param refStore - The ref store for accessing refs
932
- * @param name - The branch name to set as default
933
- *
934
- * @throws {Error} If the branch doesn't exist
935
- *
936
- * @example
937
- * ```typescript
938
- * await setDefaultBranch(refStore, 'main')
939
- * ```
940
- */
941
- export async function setDefaultBranch(refStore, name) {
942
- // Check if branch exists
943
- const refPath = getRefPath(name);
944
- const exists = await refStore.getRef(refPath);
945
- if (!exists) {
946
- throw new Error(`Branch '${name}' not found`);
947
- }
948
- defaultBranchNames.set(refStore, name);
949
- }
950
- //# sourceMappingURL=branch.js.map