gitx.do 0.1.0 → 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 (344) 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 +15 -415
  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 -174
  20. package/dist/cli/commands/add.d.ts.map +0 -1
  21. package/dist/cli/commands/add.js +0 -131
  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/commit.d.ts +0 -182
  32. package/dist/cli/commands/commit.d.ts.map +0 -1
  33. package/dist/cli/commands/commit.js +0 -437
  34. package/dist/cli/commands/commit.js.map +0 -1
  35. package/dist/cli/commands/diff.d.ts +0 -464
  36. package/dist/cli/commands/diff.d.ts.map +0 -1
  37. package/dist/cli/commands/diff.js +0 -958
  38. package/dist/cli/commands/diff.js.map +0 -1
  39. package/dist/cli/commands/log.d.ts +0 -239
  40. package/dist/cli/commands/log.d.ts.map +0 -1
  41. package/dist/cli/commands/log.js +0 -535
  42. package/dist/cli/commands/log.js.map +0 -1
  43. package/dist/cli/commands/merge.d.ts +0 -106
  44. package/dist/cli/commands/merge.d.ts.map +0 -1
  45. package/dist/cli/commands/merge.js +0 -55
  46. package/dist/cli/commands/merge.js.map +0 -1
  47. package/dist/cli/commands/review.d.ts +0 -457
  48. package/dist/cli/commands/review.d.ts.map +0 -1
  49. package/dist/cli/commands/review.js +0 -533
  50. package/dist/cli/commands/review.js.map +0 -1
  51. package/dist/cli/commands/status.d.ts +0 -269
  52. package/dist/cli/commands/status.d.ts.map +0 -1
  53. package/dist/cli/commands/status.js +0 -493
  54. package/dist/cli/commands/status.js.map +0 -1
  55. package/dist/cli/commands/web.d.ts +0 -199
  56. package/dist/cli/commands/web.d.ts.map +0 -1
  57. package/dist/cli/commands/web.js +0 -696
  58. package/dist/cli/commands/web.js.map +0 -1
  59. package/dist/cli/fs-adapter.d.ts +0 -656
  60. package/dist/cli/fs-adapter.d.ts.map +0 -1
  61. package/dist/cli/fs-adapter.js +0 -1179
  62. package/dist/cli/fs-adapter.js.map +0 -1
  63. package/dist/cli/fsx-cli-adapter.d.ts +0 -359
  64. package/dist/cli/fsx-cli-adapter.d.ts.map +0 -1
  65. package/dist/cli/fsx-cli-adapter.js +0 -619
  66. package/dist/cli/fsx-cli-adapter.js.map +0 -1
  67. package/dist/cli/index.d.ts +0 -387
  68. package/dist/cli/index.d.ts.map +0 -1
  69. package/dist/cli/index.js +0 -523
  70. package/dist/cli/index.js.map +0 -1
  71. package/dist/cli/ui/components/DiffView.d.ts +0 -7
  72. package/dist/cli/ui/components/DiffView.d.ts.map +0 -1
  73. package/dist/cli/ui/components/DiffView.js +0 -11
  74. package/dist/cli/ui/components/DiffView.js.map +0 -1
  75. package/dist/cli/ui/components/ErrorDisplay.d.ts +0 -6
  76. package/dist/cli/ui/components/ErrorDisplay.d.ts.map +0 -1
  77. package/dist/cli/ui/components/ErrorDisplay.js +0 -11
  78. package/dist/cli/ui/components/ErrorDisplay.js.map +0 -1
  79. package/dist/cli/ui/components/FuzzySearch.d.ts +0 -9
  80. package/dist/cli/ui/components/FuzzySearch.d.ts.map +0 -1
  81. package/dist/cli/ui/components/FuzzySearch.js +0 -12
  82. package/dist/cli/ui/components/FuzzySearch.js.map +0 -1
  83. package/dist/cli/ui/components/LoadingSpinner.d.ts +0 -6
  84. package/dist/cli/ui/components/LoadingSpinner.d.ts.map +0 -1
  85. package/dist/cli/ui/components/LoadingSpinner.js +0 -10
  86. package/dist/cli/ui/components/LoadingSpinner.js.map +0 -1
  87. package/dist/cli/ui/components/NavigationList.d.ts +0 -9
  88. package/dist/cli/ui/components/NavigationList.d.ts.map +0 -1
  89. package/dist/cli/ui/components/NavigationList.js +0 -11
  90. package/dist/cli/ui/components/NavigationList.js.map +0 -1
  91. package/dist/cli/ui/components/ScrollableContent.d.ts +0 -8
  92. package/dist/cli/ui/components/ScrollableContent.d.ts.map +0 -1
  93. package/dist/cli/ui/components/ScrollableContent.js +0 -11
  94. package/dist/cli/ui/components/ScrollableContent.js.map +0 -1
  95. package/dist/cli/ui/components/index.d.ts +0 -7
  96. package/dist/cli/ui/components/index.d.ts.map +0 -1
  97. package/dist/cli/ui/components/index.js +0 -9
  98. package/dist/cli/ui/components/index.js.map +0 -1
  99. package/dist/cli/ui/terminal-ui.d.ts +0 -52
  100. package/dist/cli/ui/terminal-ui.d.ts.map +0 -1
  101. package/dist/cli/ui/terminal-ui.js +0 -121
  102. package/dist/cli/ui/terminal-ui.js.map +0 -1
  103. package/dist/do/BashModule.d.ts +0 -871
  104. package/dist/do/BashModule.d.ts.map +0 -1
  105. package/dist/do/BashModule.js +0 -1143
  106. package/dist/do/BashModule.js.map +0 -1
  107. package/dist/do/FsModule.d.ts +0 -601
  108. package/dist/do/FsModule.d.ts.map +0 -1
  109. package/dist/do/FsModule.js +0 -1120
  110. package/dist/do/FsModule.js.map +0 -1
  111. package/dist/do/GitModule.d.ts +0 -635
  112. package/dist/do/GitModule.d.ts.map +0 -1
  113. package/dist/do/GitModule.js +0 -781
  114. package/dist/do/GitModule.js.map +0 -1
  115. package/dist/do/GitRepoDO.d.ts +0 -281
  116. package/dist/do/GitRepoDO.d.ts.map +0 -1
  117. package/dist/do/GitRepoDO.js +0 -479
  118. package/dist/do/GitRepoDO.js.map +0 -1
  119. package/dist/do/bash-ast.d.ts +0 -246
  120. package/dist/do/bash-ast.d.ts.map +0 -1
  121. package/dist/do/bash-ast.js +0 -888
  122. package/dist/do/bash-ast.js.map +0 -1
  123. package/dist/do/container-executor.d.ts +0 -491
  124. package/dist/do/container-executor.d.ts.map +0 -1
  125. package/dist/do/container-executor.js +0 -730
  126. package/dist/do/container-executor.js.map +0 -1
  127. package/dist/do/index.d.ts +0 -53
  128. package/dist/do/index.d.ts.map +0 -1
  129. package/dist/do/index.js +0 -91
  130. package/dist/do/index.js.map +0 -1
  131. package/dist/do/tiered-storage.d.ts +0 -403
  132. package/dist/do/tiered-storage.d.ts.map +0 -1
  133. package/dist/do/tiered-storage.js +0 -689
  134. package/dist/do/tiered-storage.js.map +0 -1
  135. package/dist/do/withBash.d.ts +0 -231
  136. package/dist/do/withBash.d.ts.map +0 -1
  137. package/dist/do/withBash.js +0 -244
  138. package/dist/do/withBash.js.map +0 -1
  139. package/dist/do/withFs.d.ts +0 -237
  140. package/dist/do/withFs.d.ts.map +0 -1
  141. package/dist/do/withFs.js +0 -387
  142. package/dist/do/withFs.js.map +0 -1
  143. package/dist/do/withGit.d.ts +0 -180
  144. package/dist/do/withGit.d.ts.map +0 -1
  145. package/dist/do/withGit.js +0 -271
  146. package/dist/do/withGit.js.map +0 -1
  147. package/dist/durable-object/object-store.d.ts +0 -633
  148. package/dist/durable-object/object-store.d.ts.map +0 -1
  149. package/dist/durable-object/object-store.js +0 -1161
  150. package/dist/durable-object/object-store.js.map +0 -1
  151. package/dist/durable-object/schema.d.ts.map +0 -1
  152. package/dist/durable-object/schema.js.map +0 -1
  153. package/dist/durable-object/wal.d.ts +0 -416
  154. package/dist/durable-object/wal.d.ts.map +0 -1
  155. package/dist/durable-object/wal.js +0 -445
  156. package/dist/durable-object/wal.js.map +0 -1
  157. package/dist/mcp/adapter.d.ts +0 -772
  158. package/dist/mcp/adapter.d.ts.map +0 -1
  159. package/dist/mcp/adapter.js +0 -895
  160. package/dist/mcp/adapter.js.map +0 -1
  161. package/dist/mcp/sandbox/miniflare-evaluator.d.ts +0 -22
  162. package/dist/mcp/sandbox/miniflare-evaluator.d.ts.map +0 -1
  163. package/dist/mcp/sandbox/miniflare-evaluator.js +0 -140
  164. package/dist/mcp/sandbox/miniflare-evaluator.js.map +0 -1
  165. package/dist/mcp/sandbox/object-store-proxy.d.ts +0 -32
  166. package/dist/mcp/sandbox/object-store-proxy.d.ts.map +0 -1
  167. package/dist/mcp/sandbox/object-store-proxy.js +0 -30
  168. package/dist/mcp/sandbox/object-store-proxy.js.map +0 -1
  169. package/dist/mcp/sandbox/template.d.ts +0 -17
  170. package/dist/mcp/sandbox/template.d.ts.map +0 -1
  171. package/dist/mcp/sandbox/template.js +0 -71
  172. package/dist/mcp/sandbox/template.js.map +0 -1
  173. package/dist/mcp/sandbox.d.ts +0 -764
  174. package/dist/mcp/sandbox.d.ts.map +0 -1
  175. package/dist/mcp/sandbox.js +0 -1362
  176. package/dist/mcp/sandbox.js.map +0 -1
  177. package/dist/mcp/sdk-adapter.d.ts +0 -835
  178. package/dist/mcp/sdk-adapter.d.ts.map +0 -1
  179. package/dist/mcp/sdk-adapter.js +0 -974
  180. package/dist/mcp/sdk-adapter.js.map +0 -1
  181. package/dist/mcp/tools/do.d.ts +0 -32
  182. package/dist/mcp/tools/do.d.ts.map +0 -1
  183. package/dist/mcp/tools/do.js +0 -115
  184. package/dist/mcp/tools/do.js.map +0 -1
  185. package/dist/mcp/tools.d.ts +0 -548
  186. package/dist/mcp/tools.d.ts.map +0 -1
  187. package/dist/mcp/tools.js +0 -1934
  188. package/dist/mcp/tools.js.map +0 -1
  189. package/dist/ops/blame.d.ts +0 -551
  190. package/dist/ops/blame.d.ts.map +0 -1
  191. package/dist/ops/blame.js +0 -1037
  192. package/dist/ops/blame.js.map +0 -1
  193. package/dist/ops/branch.d.ts +0 -766
  194. package/dist/ops/branch.d.ts.map +0 -1
  195. package/dist/ops/branch.js +0 -950
  196. package/dist/ops/branch.js.map +0 -1
  197. package/dist/ops/commit-traversal.d.ts +0 -349
  198. package/dist/ops/commit-traversal.d.ts.map +0 -1
  199. package/dist/ops/commit-traversal.js +0 -821
  200. package/dist/ops/commit-traversal.js.map +0 -1
  201. package/dist/ops/commit.d.ts +0 -555
  202. package/dist/ops/commit.d.ts.map +0 -1
  203. package/dist/ops/commit.js +0 -826
  204. package/dist/ops/commit.js.map +0 -1
  205. package/dist/ops/merge-base.d.ts +0 -397
  206. package/dist/ops/merge-base.d.ts.map +0 -1
  207. package/dist/ops/merge-base.js +0 -691
  208. package/dist/ops/merge-base.js.map +0 -1
  209. package/dist/ops/merge.d.ts +0 -855
  210. package/dist/ops/merge.d.ts.map +0 -1
  211. package/dist/ops/merge.js +0 -1551
  212. package/dist/ops/merge.js.map +0 -1
  213. package/dist/ops/tag.d.ts +0 -247
  214. package/dist/ops/tag.d.ts.map +0 -1
  215. package/dist/ops/tag.js +0 -649
  216. package/dist/ops/tag.js.map +0 -1
  217. package/dist/ops/tree-builder.d.ts +0 -178
  218. package/dist/ops/tree-builder.d.ts.map +0 -1
  219. package/dist/ops/tree-builder.js +0 -271
  220. package/dist/ops/tree-builder.js.map +0 -1
  221. package/dist/ops/tree-diff.d.ts +0 -291
  222. package/dist/ops/tree-diff.d.ts.map +0 -1
  223. package/dist/ops/tree-diff.js +0 -705
  224. package/dist/ops/tree-diff.js.map +0 -1
  225. package/dist/pack/delta.d.ts +0 -248
  226. package/dist/pack/delta.d.ts.map +0 -1
  227. package/dist/pack/delta.js +0 -736
  228. package/dist/pack/delta.js.map +0 -1
  229. package/dist/pack/format.d.ts +0 -446
  230. package/dist/pack/format.d.ts.map +0 -1
  231. package/dist/pack/format.js +0 -572
  232. package/dist/pack/format.js.map +0 -1
  233. package/dist/pack/full-generation.d.ts +0 -612
  234. package/dist/pack/full-generation.d.ts.map +0 -1
  235. package/dist/pack/full-generation.js +0 -1378
  236. package/dist/pack/full-generation.js.map +0 -1
  237. package/dist/pack/generation.d.ts +0 -441
  238. package/dist/pack/generation.d.ts.map +0 -1
  239. package/dist/pack/generation.js +0 -707
  240. package/dist/pack/generation.js.map +0 -1
  241. package/dist/pack/index.d.ts +0 -502
  242. package/dist/pack/index.d.ts.map +0 -1
  243. package/dist/pack/index.js +0 -833
  244. package/dist/pack/index.js.map +0 -1
  245. package/dist/refs/branch.d.ts +0 -668
  246. package/dist/refs/branch.d.ts.map +0 -1
  247. package/dist/refs/branch.js +0 -897
  248. package/dist/refs/branch.js.map +0 -1
  249. package/dist/refs/storage.d.ts +0 -833
  250. package/dist/refs/storage.d.ts.map +0 -1
  251. package/dist/refs/storage.js +0 -1023
  252. package/dist/refs/storage.js.map +0 -1
  253. package/dist/refs/tag.d.ts +0 -860
  254. package/dist/refs/tag.d.ts.map +0 -1
  255. package/dist/refs/tag.js +0 -996
  256. package/dist/refs/tag.js.map +0 -1
  257. package/dist/storage/backend.d.ts +0 -425
  258. package/dist/storage/backend.d.ts.map +0 -1
  259. package/dist/storage/backend.js +0 -41
  260. package/dist/storage/backend.js.map +0 -1
  261. package/dist/storage/fsx-adapter.d.ts +0 -204
  262. package/dist/storage/fsx-adapter.d.ts.map +0 -1
  263. package/dist/storage/fsx-adapter.js +0 -470
  264. package/dist/storage/fsx-adapter.js.map +0 -1
  265. package/dist/storage/lru-cache.d.ts +0 -691
  266. package/dist/storage/lru-cache.d.ts.map +0 -1
  267. package/dist/storage/lru-cache.js +0 -813
  268. package/dist/storage/lru-cache.js.map +0 -1
  269. package/dist/storage/object-index.d.ts +0 -585
  270. package/dist/storage/object-index.d.ts.map +0 -1
  271. package/dist/storage/object-index.js +0 -532
  272. package/dist/storage/object-index.js.map +0 -1
  273. package/dist/storage/r2-pack.d.ts +0 -1257
  274. package/dist/storage/r2-pack.d.ts.map +0 -1
  275. package/dist/storage/r2-pack.js +0 -1770
  276. package/dist/storage/r2-pack.js.map +0 -1
  277. package/dist/tiered/cdc-pipeline.d.ts +0 -1888
  278. package/dist/tiered/cdc-pipeline.d.ts.map +0 -1
  279. package/dist/tiered/cdc-pipeline.js +0 -1880
  280. package/dist/tiered/cdc-pipeline.js.map +0 -1
  281. package/dist/tiered/migration.d.ts +0 -1104
  282. package/dist/tiered/migration.d.ts.map +0 -1
  283. package/dist/tiered/migration.js +0 -1214
  284. package/dist/tiered/migration.js.map +0 -1
  285. package/dist/tiered/parquet-writer.d.ts +0 -1145
  286. package/dist/tiered/parquet-writer.d.ts.map +0 -1
  287. package/dist/tiered/parquet-writer.js +0 -1183
  288. package/dist/tiered/parquet-writer.js.map +0 -1
  289. package/dist/tiered/read-path.d.ts +0 -835
  290. package/dist/tiered/read-path.d.ts.map +0 -1
  291. package/dist/tiered/read-path.js +0 -487
  292. package/dist/tiered/read-path.js.map +0 -1
  293. package/dist/types/capability.d.ts +0 -1385
  294. package/dist/types/capability.d.ts.map +0 -1
  295. package/dist/types/capability.js +0 -36
  296. package/dist/types/capability.js.map +0 -1
  297. package/dist/types/index.d.ts +0 -13
  298. package/dist/types/index.d.ts.map +0 -1
  299. package/dist/types/index.js +0 -18
  300. package/dist/types/index.js.map +0 -1
  301. package/dist/types/objects.d.ts +0 -692
  302. package/dist/types/objects.d.ts.map +0 -1
  303. package/dist/types/objects.js +0 -837
  304. package/dist/types/objects.js.map +0 -1
  305. package/dist/types/storage.d.ts +0 -603
  306. package/dist/types/storage.d.ts.map +0 -1
  307. package/dist/types/storage.js +0 -191
  308. package/dist/types/storage.js.map +0 -1
  309. package/dist/types/worker-loader.d.ts +0 -60
  310. package/dist/types/worker-loader.d.ts.map +0 -1
  311. package/dist/types/worker-loader.js +0 -62
  312. package/dist/types/worker-loader.js.map +0 -1
  313. package/dist/utils/hash.d.ts +0 -197
  314. package/dist/utils/hash.d.ts.map +0 -1
  315. package/dist/utils/hash.js +0 -268
  316. package/dist/utils/hash.js.map +0 -1
  317. package/dist/utils/sha1.d.ts +0 -290
  318. package/dist/utils/sha1.d.ts.map +0 -1
  319. package/dist/utils/sha1.js +0 -582
  320. package/dist/utils/sha1.js.map +0 -1
  321. package/dist/wire/capabilities.d.ts +0 -1044
  322. package/dist/wire/capabilities.d.ts.map +0 -1
  323. package/dist/wire/capabilities.js +0 -941
  324. package/dist/wire/capabilities.js.map +0 -1
  325. package/dist/wire/path-security.d.ts +0 -157
  326. package/dist/wire/path-security.d.ts.map +0 -1
  327. package/dist/wire/path-security.js +0 -307
  328. package/dist/wire/path-security.js.map +0 -1
  329. package/dist/wire/pkt-line.d.ts +0 -345
  330. package/dist/wire/pkt-line.d.ts.map +0 -1
  331. package/dist/wire/pkt-line.js +0 -381
  332. package/dist/wire/pkt-line.js.map +0 -1
  333. package/dist/wire/receive-pack.d.ts +0 -1059
  334. package/dist/wire/receive-pack.d.ts.map +0 -1
  335. package/dist/wire/receive-pack.js +0 -1414
  336. package/dist/wire/receive-pack.js.map +0 -1
  337. package/dist/wire/smart-http.d.ts +0 -799
  338. package/dist/wire/smart-http.d.ts.map +0 -1
  339. package/dist/wire/smart-http.js +0 -945
  340. package/dist/wire/smart-http.js.map +0 -1
  341. package/dist/wire/upload-pack.d.ts +0 -727
  342. package/dist/wire/upload-pack.d.ts.map +0 -1
  343. package/dist/wire/upload-pack.js +0 -1138
  344. 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