gitx.do 0.1.1 → 0.1.3

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 (376) 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 -469
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +39 -481
  17. package/dist/index.js.map +1 -1
  18. package/dist/mcp/auth.d.ts +77 -0
  19. package/dist/mcp/auth.d.ts.map +1 -0
  20. package/dist/mcp/auth.js +278 -0
  21. package/dist/mcp/auth.js.map +1 -0
  22. package/dist/mcp/index.d.ts +13 -0
  23. package/dist/mcp/index.d.ts.map +1 -0
  24. package/dist/mcp/index.js +19 -0
  25. package/dist/mcp/index.js.map +1 -0
  26. package/dist/mcp/server.d.ts +200 -0
  27. package/dist/mcp/server.d.ts.map +1 -0
  28. package/dist/mcp/server.js +275 -0
  29. package/dist/mcp/server.js.map +1 -0
  30. package/dist/mcp/tool-registry.d.ts +47 -0
  31. package/dist/mcp/tool-registry.d.ts.map +1 -0
  32. package/dist/mcp/tool-registry.js +284 -0
  33. package/dist/mcp/tool-registry.js.map +1 -0
  34. package/dist/mcp/tools.d.ts +103 -515
  35. package/dist/mcp/tools.d.ts.map +1 -1
  36. package/dist/mcp/tools.js +676 -3087
  37. package/dist/mcp/tools.js.map +1 -1
  38. package/dist/mcp/types.d.ts +124 -0
  39. package/dist/mcp/types.d.ts.map +1 -0
  40. package/dist/mcp/types.js +9 -0
  41. package/dist/mcp/types.js.map +1 -0
  42. package/package.json +19 -21
  43. package/dist/cli/commands/add.d.ts +0 -176
  44. package/dist/cli/commands/add.d.ts.map +0 -1
  45. package/dist/cli/commands/add.js +0 -979
  46. package/dist/cli/commands/add.js.map +0 -1
  47. package/dist/cli/commands/blame.d.ts +0 -259
  48. package/dist/cli/commands/blame.d.ts.map +0 -1
  49. package/dist/cli/commands/blame.js +0 -609
  50. package/dist/cli/commands/blame.js.map +0 -1
  51. package/dist/cli/commands/branch.d.ts +0 -249
  52. package/dist/cli/commands/branch.d.ts.map +0 -1
  53. package/dist/cli/commands/branch.js +0 -693
  54. package/dist/cli/commands/branch.js.map +0 -1
  55. package/dist/cli/commands/checkout.d.ts +0 -73
  56. package/dist/cli/commands/checkout.d.ts.map +0 -1
  57. package/dist/cli/commands/checkout.js +0 -725
  58. package/dist/cli/commands/checkout.js.map +0 -1
  59. package/dist/cli/commands/commit.d.ts +0 -182
  60. package/dist/cli/commands/commit.d.ts.map +0 -1
  61. package/dist/cli/commands/commit.js +0 -457
  62. package/dist/cli/commands/commit.js.map +0 -1
  63. package/dist/cli/commands/diff.d.ts +0 -464
  64. package/dist/cli/commands/diff.d.ts.map +0 -1
  65. package/dist/cli/commands/diff.js +0 -959
  66. package/dist/cli/commands/diff.js.map +0 -1
  67. package/dist/cli/commands/log.d.ts +0 -239
  68. package/dist/cli/commands/log.d.ts.map +0 -1
  69. package/dist/cli/commands/log.js +0 -535
  70. package/dist/cli/commands/log.js.map +0 -1
  71. package/dist/cli/commands/merge.d.ts +0 -106
  72. package/dist/cli/commands/merge.d.ts.map +0 -1
  73. package/dist/cli/commands/merge.js +0 -852
  74. package/dist/cli/commands/merge.js.map +0 -1
  75. package/dist/cli/commands/review.d.ts +0 -457
  76. package/dist/cli/commands/review.d.ts.map +0 -1
  77. package/dist/cli/commands/review.js +0 -558
  78. package/dist/cli/commands/review.js.map +0 -1
  79. package/dist/cli/commands/stash.d.ts +0 -157
  80. package/dist/cli/commands/stash.d.ts.map +0 -1
  81. package/dist/cli/commands/stash.js +0 -655
  82. package/dist/cli/commands/stash.js.map +0 -1
  83. package/dist/cli/commands/status.d.ts +0 -269
  84. package/dist/cli/commands/status.d.ts.map +0 -1
  85. package/dist/cli/commands/status.js +0 -492
  86. package/dist/cli/commands/status.js.map +0 -1
  87. package/dist/cli/commands/web.d.ts +0 -199
  88. package/dist/cli/commands/web.d.ts.map +0 -1
  89. package/dist/cli/commands/web.js +0 -697
  90. package/dist/cli/commands/web.js.map +0 -1
  91. package/dist/cli/fs-adapter.d.ts +0 -656
  92. package/dist/cli/fs-adapter.d.ts.map +0 -1
  93. package/dist/cli/fs-adapter.js +0 -1177
  94. package/dist/cli/fs-adapter.js.map +0 -1
  95. package/dist/cli/fsx-cli-adapter.d.ts +0 -359
  96. package/dist/cli/fsx-cli-adapter.d.ts.map +0 -1
  97. package/dist/cli/fsx-cli-adapter.js +0 -619
  98. package/dist/cli/fsx-cli-adapter.js.map +0 -1
  99. package/dist/cli/index.d.ts +0 -387
  100. package/dist/cli/index.d.ts.map +0 -1
  101. package/dist/cli/index.js +0 -579
  102. package/dist/cli/index.js.map +0 -1
  103. package/dist/cli/ui/components/DiffView.d.ts +0 -12
  104. package/dist/cli/ui/components/DiffView.d.ts.map +0 -1
  105. package/dist/cli/ui/components/DiffView.js +0 -11
  106. package/dist/cli/ui/components/DiffView.js.map +0 -1
  107. package/dist/cli/ui/components/ErrorDisplay.d.ts +0 -10
  108. package/dist/cli/ui/components/ErrorDisplay.d.ts.map +0 -1
  109. package/dist/cli/ui/components/ErrorDisplay.js +0 -11
  110. package/dist/cli/ui/components/ErrorDisplay.js.map +0 -1
  111. package/dist/cli/ui/components/FuzzySearch.d.ts +0 -15
  112. package/dist/cli/ui/components/FuzzySearch.d.ts.map +0 -1
  113. package/dist/cli/ui/components/FuzzySearch.js +0 -12
  114. package/dist/cli/ui/components/FuzzySearch.js.map +0 -1
  115. package/dist/cli/ui/components/LoadingSpinner.d.ts +0 -10
  116. package/dist/cli/ui/components/LoadingSpinner.d.ts.map +0 -1
  117. package/dist/cli/ui/components/LoadingSpinner.js +0 -10
  118. package/dist/cli/ui/components/LoadingSpinner.js.map +0 -1
  119. package/dist/cli/ui/components/NavigationList.d.ts +0 -14
  120. package/dist/cli/ui/components/NavigationList.d.ts.map +0 -1
  121. package/dist/cli/ui/components/NavigationList.js +0 -11
  122. package/dist/cli/ui/components/NavigationList.js.map +0 -1
  123. package/dist/cli/ui/components/ScrollableContent.d.ts +0 -13
  124. package/dist/cli/ui/components/ScrollableContent.d.ts.map +0 -1
  125. package/dist/cli/ui/components/ScrollableContent.js +0 -11
  126. package/dist/cli/ui/components/ScrollableContent.js.map +0 -1
  127. package/dist/cli/ui/components/index.d.ts +0 -7
  128. package/dist/cli/ui/components/index.d.ts.map +0 -1
  129. package/dist/cli/ui/components/index.js +0 -9
  130. package/dist/cli/ui/components/index.js.map +0 -1
  131. package/dist/cli/ui/terminal-ui.d.ts +0 -85
  132. package/dist/cli/ui/terminal-ui.d.ts.map +0 -1
  133. package/dist/cli/ui/terminal-ui.js +0 -121
  134. package/dist/cli/ui/terminal-ui.js.map +0 -1
  135. package/dist/do/BashModule.d.ts +0 -871
  136. package/dist/do/BashModule.d.ts.map +0 -1
  137. package/dist/do/BashModule.js +0 -1143
  138. package/dist/do/BashModule.js.map +0 -1
  139. package/dist/do/FsModule.d.ts +0 -612
  140. package/dist/do/FsModule.d.ts.map +0 -1
  141. package/dist/do/FsModule.js +0 -1120
  142. package/dist/do/FsModule.js.map +0 -1
  143. package/dist/do/GitModule.d.ts +0 -635
  144. package/dist/do/GitModule.d.ts.map +0 -1
  145. package/dist/do/GitModule.js +0 -784
  146. package/dist/do/GitModule.js.map +0 -1
  147. package/dist/do/GitRepoDO.d.ts +0 -281
  148. package/dist/do/GitRepoDO.d.ts.map +0 -1
  149. package/dist/do/GitRepoDO.js +0 -479
  150. package/dist/do/GitRepoDO.js.map +0 -1
  151. package/dist/do/bash-ast.d.ts +0 -246
  152. package/dist/do/bash-ast.d.ts.map +0 -1
  153. package/dist/do/bash-ast.js +0 -888
  154. package/dist/do/bash-ast.js.map +0 -1
  155. package/dist/do/container-executor.d.ts +0 -491
  156. package/dist/do/container-executor.d.ts.map +0 -1
  157. package/dist/do/container-executor.js +0 -731
  158. package/dist/do/container-executor.js.map +0 -1
  159. package/dist/do/index.d.ts +0 -53
  160. package/dist/do/index.d.ts.map +0 -1
  161. package/dist/do/index.js +0 -91
  162. package/dist/do/index.js.map +0 -1
  163. package/dist/do/tiered-storage.d.ts +0 -403
  164. package/dist/do/tiered-storage.d.ts.map +0 -1
  165. package/dist/do/tiered-storage.js +0 -689
  166. package/dist/do/tiered-storage.js.map +0 -1
  167. package/dist/do/withBash.d.ts +0 -231
  168. package/dist/do/withBash.d.ts.map +0 -1
  169. package/dist/do/withBash.js +0 -244
  170. package/dist/do/withBash.js.map +0 -1
  171. package/dist/do/withFs.d.ts +0 -237
  172. package/dist/do/withFs.d.ts.map +0 -1
  173. package/dist/do/withFs.js +0 -387
  174. package/dist/do/withFs.js.map +0 -1
  175. package/dist/do/withGit.d.ts +0 -180
  176. package/dist/do/withGit.d.ts.map +0 -1
  177. package/dist/do/withGit.js +0 -271
  178. package/dist/do/withGit.js.map +0 -1
  179. package/dist/durable-object/object-store.d.ts +0 -633
  180. package/dist/durable-object/object-store.d.ts.map +0 -1
  181. package/dist/durable-object/object-store.js +0 -1164
  182. package/dist/durable-object/object-store.js.map +0 -1
  183. package/dist/durable-object/schema.d.ts.map +0 -1
  184. package/dist/durable-object/schema.js.map +0 -1
  185. package/dist/durable-object/wal.d.ts +0 -416
  186. package/dist/durable-object/wal.d.ts.map +0 -1
  187. package/dist/durable-object/wal.js +0 -445
  188. package/dist/durable-object/wal.js.map +0 -1
  189. package/dist/mcp/adapter.d.ts +0 -772
  190. package/dist/mcp/adapter.d.ts.map +0 -1
  191. package/dist/mcp/adapter.js +0 -895
  192. package/dist/mcp/adapter.js.map +0 -1
  193. package/dist/mcp/sandbox/miniflare-evaluator.d.ts +0 -22
  194. package/dist/mcp/sandbox/miniflare-evaluator.d.ts.map +0 -1
  195. package/dist/mcp/sandbox/miniflare-evaluator.js +0 -140
  196. package/dist/mcp/sandbox/miniflare-evaluator.js.map +0 -1
  197. package/dist/mcp/sandbox/object-store-proxy.d.ts +0 -32
  198. package/dist/mcp/sandbox/object-store-proxy.d.ts.map +0 -1
  199. package/dist/mcp/sandbox/object-store-proxy.js +0 -30
  200. package/dist/mcp/sandbox/object-store-proxy.js.map +0 -1
  201. package/dist/mcp/sandbox/template.d.ts +0 -17
  202. package/dist/mcp/sandbox/template.d.ts.map +0 -1
  203. package/dist/mcp/sandbox/template.js +0 -71
  204. package/dist/mcp/sandbox/template.js.map +0 -1
  205. package/dist/mcp/sandbox.d.ts +0 -764
  206. package/dist/mcp/sandbox.d.ts.map +0 -1
  207. package/dist/mcp/sandbox.js +0 -1362
  208. package/dist/mcp/sandbox.js.map +0 -1
  209. package/dist/mcp/sdk-adapter.d.ts +0 -835
  210. package/dist/mcp/sdk-adapter.d.ts.map +0 -1
  211. package/dist/mcp/sdk-adapter.js +0 -974
  212. package/dist/mcp/sdk-adapter.js.map +0 -1
  213. package/dist/mcp/tools/do.d.ts +0 -32
  214. package/dist/mcp/tools/do.d.ts.map +0 -1
  215. package/dist/mcp/tools/do.js +0 -117
  216. package/dist/mcp/tools/do.js.map +0 -1
  217. package/dist/ops/blame.d.ts +0 -551
  218. package/dist/ops/blame.d.ts.map +0 -1
  219. package/dist/ops/blame.js +0 -1037
  220. package/dist/ops/blame.js.map +0 -1
  221. package/dist/ops/branch.d.ts +0 -766
  222. package/dist/ops/branch.d.ts.map +0 -1
  223. package/dist/ops/branch.js +0 -950
  224. package/dist/ops/branch.js.map +0 -1
  225. package/dist/ops/commit-traversal.d.ts +0 -349
  226. package/dist/ops/commit-traversal.d.ts.map +0 -1
  227. package/dist/ops/commit-traversal.js +0 -821
  228. package/dist/ops/commit-traversal.js.map +0 -1
  229. package/dist/ops/commit.d.ts +0 -555
  230. package/dist/ops/commit.d.ts.map +0 -1
  231. package/dist/ops/commit.js +0 -826
  232. package/dist/ops/commit.js.map +0 -1
  233. package/dist/ops/merge-base.d.ts +0 -397
  234. package/dist/ops/merge-base.d.ts.map +0 -1
  235. package/dist/ops/merge-base.js +0 -691
  236. package/dist/ops/merge-base.js.map +0 -1
  237. package/dist/ops/merge.d.ts +0 -855
  238. package/dist/ops/merge.d.ts.map +0 -1
  239. package/dist/ops/merge.js +0 -1551
  240. package/dist/ops/merge.js.map +0 -1
  241. package/dist/ops/tag.d.ts +0 -247
  242. package/dist/ops/tag.d.ts.map +0 -1
  243. package/dist/ops/tag.js +0 -649
  244. package/dist/ops/tag.js.map +0 -1
  245. package/dist/ops/tree-builder.d.ts +0 -178
  246. package/dist/ops/tree-builder.d.ts.map +0 -1
  247. package/dist/ops/tree-builder.js +0 -271
  248. package/dist/ops/tree-builder.js.map +0 -1
  249. package/dist/ops/tree-diff.d.ts +0 -291
  250. package/dist/ops/tree-diff.d.ts.map +0 -1
  251. package/dist/ops/tree-diff.js +0 -705
  252. package/dist/ops/tree-diff.js.map +0 -1
  253. package/dist/pack/delta.d.ts +0 -248
  254. package/dist/pack/delta.d.ts.map +0 -1
  255. package/dist/pack/delta.js +0 -740
  256. package/dist/pack/delta.js.map +0 -1
  257. package/dist/pack/format.d.ts +0 -446
  258. package/dist/pack/format.d.ts.map +0 -1
  259. package/dist/pack/format.js +0 -572
  260. package/dist/pack/format.js.map +0 -1
  261. package/dist/pack/full-generation.d.ts +0 -612
  262. package/dist/pack/full-generation.d.ts.map +0 -1
  263. package/dist/pack/full-generation.js +0 -1378
  264. package/dist/pack/full-generation.js.map +0 -1
  265. package/dist/pack/generation.d.ts +0 -441
  266. package/dist/pack/generation.d.ts.map +0 -1
  267. package/dist/pack/generation.js +0 -707
  268. package/dist/pack/generation.js.map +0 -1
  269. package/dist/pack/index.d.ts +0 -502
  270. package/dist/pack/index.d.ts.map +0 -1
  271. package/dist/pack/index.js +0 -833
  272. package/dist/pack/index.js.map +0 -1
  273. package/dist/refs/branch.d.ts +0 -683
  274. package/dist/refs/branch.d.ts.map +0 -1
  275. package/dist/refs/branch.js +0 -881
  276. package/dist/refs/branch.js.map +0 -1
  277. package/dist/refs/storage.d.ts +0 -833
  278. package/dist/refs/storage.d.ts.map +0 -1
  279. package/dist/refs/storage.js +0 -1023
  280. package/dist/refs/storage.js.map +0 -1
  281. package/dist/refs/tag.d.ts +0 -860
  282. package/dist/refs/tag.d.ts.map +0 -1
  283. package/dist/refs/tag.js +0 -996
  284. package/dist/refs/tag.js.map +0 -1
  285. package/dist/storage/backend.d.ts +0 -425
  286. package/dist/storage/backend.d.ts.map +0 -1
  287. package/dist/storage/backend.js +0 -41
  288. package/dist/storage/backend.js.map +0 -1
  289. package/dist/storage/fsx-adapter.d.ts +0 -204
  290. package/dist/storage/fsx-adapter.d.ts.map +0 -1
  291. package/dist/storage/fsx-adapter.js +0 -518
  292. package/dist/storage/fsx-adapter.js.map +0 -1
  293. package/dist/storage/lru-cache.d.ts +0 -691
  294. package/dist/storage/lru-cache.d.ts.map +0 -1
  295. package/dist/storage/lru-cache.js +0 -813
  296. package/dist/storage/lru-cache.js.map +0 -1
  297. package/dist/storage/object-index.d.ts +0 -585
  298. package/dist/storage/object-index.d.ts.map +0 -1
  299. package/dist/storage/object-index.js +0 -532
  300. package/dist/storage/object-index.js.map +0 -1
  301. package/dist/storage/r2-pack.d.ts +0 -1257
  302. package/dist/storage/r2-pack.d.ts.map +0 -1
  303. package/dist/storage/r2-pack.js +0 -1773
  304. package/dist/storage/r2-pack.js.map +0 -1
  305. package/dist/tiered/cdc-pipeline.d.ts +0 -1888
  306. package/dist/tiered/cdc-pipeline.d.ts.map +0 -1
  307. package/dist/tiered/cdc-pipeline.js +0 -1880
  308. package/dist/tiered/cdc-pipeline.js.map +0 -1
  309. package/dist/tiered/migration.d.ts +0 -1104
  310. package/dist/tiered/migration.d.ts.map +0 -1
  311. package/dist/tiered/migration.js +0 -1217
  312. package/dist/tiered/migration.js.map +0 -1
  313. package/dist/tiered/parquet-writer.d.ts +0 -1145
  314. package/dist/tiered/parquet-writer.d.ts.map +0 -1
  315. package/dist/tiered/parquet-writer.js +0 -1183
  316. package/dist/tiered/parquet-writer.js.map +0 -1
  317. package/dist/tiered/read-path.d.ts +0 -835
  318. package/dist/tiered/read-path.d.ts.map +0 -1
  319. package/dist/tiered/read-path.js +0 -487
  320. package/dist/tiered/read-path.js.map +0 -1
  321. package/dist/types/capability.d.ts +0 -1385
  322. package/dist/types/capability.d.ts.map +0 -1
  323. package/dist/types/capability.js +0 -36
  324. package/dist/types/capability.js.map +0 -1
  325. package/dist/types/index.d.ts +0 -13
  326. package/dist/types/index.d.ts.map +0 -1
  327. package/dist/types/index.js +0 -18
  328. package/dist/types/index.js.map +0 -1
  329. package/dist/types/interfaces.d.ts +0 -673
  330. package/dist/types/interfaces.d.ts.map +0 -1
  331. package/dist/types/interfaces.js +0 -26
  332. package/dist/types/interfaces.js.map +0 -1
  333. package/dist/types/objects.d.ts +0 -692
  334. package/dist/types/objects.d.ts.map +0 -1
  335. package/dist/types/objects.js +0 -837
  336. package/dist/types/objects.js.map +0 -1
  337. package/dist/types/storage.d.ts +0 -603
  338. package/dist/types/storage.d.ts.map +0 -1
  339. package/dist/types/storage.js +0 -191
  340. package/dist/types/storage.js.map +0 -1
  341. package/dist/types/worker-loader.d.ts +0 -60
  342. package/dist/types/worker-loader.d.ts.map +0 -1
  343. package/dist/types/worker-loader.js +0 -62
  344. package/dist/types/worker-loader.js.map +0 -1
  345. package/dist/utils/hash.d.ts +0 -198
  346. package/dist/utils/hash.d.ts.map +0 -1
  347. package/dist/utils/hash.js +0 -272
  348. package/dist/utils/hash.js.map +0 -1
  349. package/dist/utils/sha1.d.ts +0 -325
  350. package/dist/utils/sha1.d.ts.map +0 -1
  351. package/dist/utils/sha1.js +0 -635
  352. package/dist/utils/sha1.js.map +0 -1
  353. package/dist/wire/capabilities.d.ts +0 -1044
  354. package/dist/wire/capabilities.d.ts.map +0 -1
  355. package/dist/wire/capabilities.js +0 -941
  356. package/dist/wire/capabilities.js.map +0 -1
  357. package/dist/wire/path-security.d.ts +0 -157
  358. package/dist/wire/path-security.d.ts.map +0 -1
  359. package/dist/wire/path-security.js +0 -307
  360. package/dist/wire/path-security.js.map +0 -1
  361. package/dist/wire/pkt-line.d.ts +0 -345
  362. package/dist/wire/pkt-line.d.ts.map +0 -1
  363. package/dist/wire/pkt-line.js +0 -381
  364. package/dist/wire/pkt-line.js.map +0 -1
  365. package/dist/wire/receive-pack.d.ts +0 -1059
  366. package/dist/wire/receive-pack.d.ts.map +0 -1
  367. package/dist/wire/receive-pack.js +0 -1414
  368. package/dist/wire/receive-pack.js.map +0 -1
  369. package/dist/wire/smart-http.d.ts +0 -799
  370. package/dist/wire/smart-http.d.ts.map +0 -1
  371. package/dist/wire/smart-http.js +0 -945
  372. package/dist/wire/smart-http.js.map +0 -1
  373. package/dist/wire/upload-pack.d.ts +0 -727
  374. package/dist/wire/upload-pack.d.ts.map +0 -1
  375. package/dist/wire/upload-pack.js +0 -1141
  376. package/dist/wire/upload-pack.js.map +0 -1
@@ -1,826 +0,0 @@
1
- /**
2
- * @fileoverview Commit Creation Operations
3
- *
4
- * Provides functionality for creating, formatting, and amending git commits.
5
- * Supports author/committer info, parent handling, GPG signing, and message formatting.
6
- *
7
- * ## Features
8
- *
9
- * - Create new commits with full metadata
10
- * - Amend existing commits
11
- * - GPG signature support
12
- * - Message formatting and validation
13
- * - Empty commit detection
14
- * - Author/committer timestamp handling
15
- *
16
- * ## Usage Example
17
- *
18
- * ```typescript
19
- * import { createCommit, formatCommitMessage } from './ops/commit'
20
- *
21
- * // Create a commit
22
- * const result = await createCommit(store, {
23
- * message: 'Add new feature',
24
- * tree: treeHash,
25
- * parents: [parentHash],
26
- * author: { name: 'John Doe', email: 'john@example.com' }
27
- * })
28
- *
29
- * console.log('Created commit:', result.sha)
30
- * ```
31
- *
32
- * @module ops/commit
33
- */
34
- // ============================================================================
35
- // Author/Timestamp Utilities
36
- // ============================================================================
37
- /**
38
- * Gets the current timezone offset string.
39
- *
40
- * Returns the local timezone in Git's format (e.g., '+0000', '-0500').
41
- *
42
- * @returns Timezone offset string
43
- *
44
- * @example
45
- * ```typescript
46
- * const tz = getCurrentTimezone()
47
- * // Returns something like '-0800' for Pacific time
48
- * ```
49
- */
50
- export function getCurrentTimezone() {
51
- const offset = new Date().getTimezoneOffset();
52
- const sign = offset <= 0 ? '+' : '-';
53
- const absOffset = Math.abs(offset);
54
- const hours = Math.floor(absOffset / 60);
55
- const minutes = absOffset % 60;
56
- return `${sign}${String(hours).padStart(2, '0')}${String(minutes).padStart(2, '0')}`;
57
- }
58
- /**
59
- * Formats a timestamp and timezone as git author/committer format.
60
- *
61
- * @param timestamp - Unix timestamp in seconds
62
- * @param timezone - Timezone offset string (e.g., '+0000', '-0500')
63
- * @returns Formatted string like "1234567890 +0000"
64
- *
65
- * @example
66
- * ```typescript
67
- * const formatted = formatTimestamp(1609459200, '+0000')
68
- * // Returns "1609459200 +0000"
69
- * ```
70
- */
71
- export function formatTimestamp(timestamp, timezone) {
72
- return `${timestamp} ${timezone}`;
73
- }
74
- /**
75
- * Parses a git timestamp string.
76
- *
77
- * @param timestampStr - Timestamp string like "1234567890 +0000"
78
- * @returns Object with parsed timestamp and timezone
79
- *
80
- * @throws {Error} If the format is invalid
81
- *
82
- * @example
83
- * ```typescript
84
- * const { timestamp, timezone } = parseTimestamp("1609459200 -0500")
85
- * // timestamp = 1609459200, timezone = "-0500"
86
- * ```
87
- */
88
- export function parseTimestamp(timestampStr) {
89
- const match = timestampStr.match(/^(\d+) ([+-]\d{4})$/);
90
- if (!match) {
91
- throw new Error(`Invalid timestamp format: ${timestampStr}`);
92
- }
93
- return {
94
- timestamp: parseInt(match[1], 10),
95
- timezone: match[2]
96
- };
97
- }
98
- /**
99
- * Creates an Author object with current timestamp.
100
- *
101
- * Convenience function for creating author information with
102
- * the current time and local timezone.
103
- *
104
- * @param name - Author name
105
- * @param email - Author email
106
- * @param timezone - Optional timezone (defaults to local timezone)
107
- * @returns Author object with current timestamp
108
- *
109
- * @example
110
- * ```typescript
111
- * const author = createAuthor('John Doe', 'john@example.com')
112
- * // { name: 'John Doe', email: 'john@example.com', timestamp: <now>, timezone: <local> }
113
- * ```
114
- */
115
- export function createAuthor(name, email, timezone) {
116
- return {
117
- name,
118
- email,
119
- timestamp: Math.floor(Date.now() / 1000),
120
- timezone: timezone ?? getCurrentTimezone()
121
- };
122
- }
123
- // ============================================================================
124
- // Message Formatting
125
- // ============================================================================
126
- /**
127
- * Wraps text at a specified column width.
128
- * @internal
129
- */
130
- function wrapText(text, column) {
131
- if (column <= 0)
132
- return text;
133
- const words = text.split(/\s+/);
134
- const lines = [];
135
- let currentLine = '';
136
- for (const word of words) {
137
- if (currentLine.length === 0) {
138
- currentLine = word;
139
- }
140
- else if (currentLine.length + 1 + word.length <= column) {
141
- currentLine += ' ' + word;
142
- }
143
- else {
144
- lines.push(currentLine);
145
- currentLine = word;
146
- }
147
- }
148
- if (currentLine.length > 0) {
149
- lines.push(currentLine);
150
- }
151
- return lines.join('\n');
152
- }
153
- /**
154
- * Formats a commit message according to git conventions.
155
- *
156
- * Applies various transformations based on the cleanup mode:
157
- * - Strips comments
158
- * - Normalizes whitespace
159
- * - Wraps long lines
160
- * - Removes scissors markers
161
- *
162
- * @param message - The raw commit message
163
- * @param options - Formatting options
164
- * @returns The formatted commit message
165
- *
166
- * @example
167
- * ```typescript
168
- * // Clean up a message
169
- * const formatted = formatCommitMessage(`
170
- * Add feature
171
- *
172
- * # This is a comment
173
- * Long description here
174
- * `, { cleanup: 'strip' })
175
- * // Returns: "Add feature\n\nLong description here"
176
- * ```
177
- */
178
- export function formatCommitMessage(message, options = {}) {
179
- const { cleanup = 'default', commentChar = '#', wrapColumn = 0 } = options;
180
- // Verbatim mode: return message as-is
181
- if (cleanup === 'verbatim') {
182
- return message;
183
- }
184
- let result = message;
185
- // Scissors mode: remove everything after scissors line
186
- if (cleanup === 'scissors') {
187
- const scissorsPattern = new RegExp(`^${commentChar} -+ >8 -+`, 'm');
188
- const scissorsMatch = result.match(scissorsPattern);
189
- if (scissorsMatch && scissorsMatch.index !== undefined) {
190
- result = result.slice(0, scissorsMatch.index);
191
- }
192
- }
193
- // Strip comments if cleanup is 'strip' or 'scissors'
194
- if (cleanup === 'strip' || cleanup === 'scissors') {
195
- const lines = result.split('\n');
196
- result = lines.filter(line => !line.startsWith(commentChar)).join('\n');
197
- }
198
- // Strip whitespace (for 'whitespace', 'strip', 'scissors', 'default')
199
- // Note: verbatim check already handled above, so this always runs
200
- if (true) {
201
- // Strip leading/trailing whitespace from each line
202
- const lines = result.split('\n');
203
- const trimmedLines = lines.map(line => line.trim());
204
- // Collapse multiple blank lines into one
205
- const collapsedLines = [];
206
- let lastWasBlank = false;
207
- for (const line of trimmedLines) {
208
- if (line === '') {
209
- if (!lastWasBlank) {
210
- collapsedLines.push(line);
211
- }
212
- lastWasBlank = true;
213
- }
214
- else {
215
- collapsedLines.push(line);
216
- lastWasBlank = false;
217
- }
218
- }
219
- result = collapsedLines.join('\n');
220
- // Trim leading/trailing blank lines
221
- result = result.replace(/^\n+/, '').replace(/\n+$/, '');
222
- }
223
- // Wrap body (not subject) if wrapColumn is specified
224
- if (wrapColumn > 0 && result.length > 0) {
225
- const lines = result.split('\n');
226
- if (lines.length > 0) {
227
- const subject = lines[0];
228
- const rest = lines.slice(1);
229
- // Find where body starts (after blank line)
230
- let bodyStartIndex = 0;
231
- for (let i = 0; i < rest.length; i++) {
232
- if (rest[i] === '') {
233
- bodyStartIndex = i + 1;
234
- break;
235
- }
236
- }
237
- // Wrap body lines
238
- const wrappedRest = [];
239
- for (let i = 0; i < rest.length; i++) {
240
- if (i >= bodyStartIndex && rest[i] !== '') {
241
- wrappedRest.push(wrapText(rest[i], wrapColumn));
242
- }
243
- else {
244
- wrappedRest.push(rest[i]);
245
- }
246
- }
247
- result = [subject, ...wrappedRest].join('\n');
248
- }
249
- }
250
- return result;
251
- }
252
- /**
253
- * Parses a commit message into subject and body.
254
- *
255
- * The subject is the first line. The body starts after the first
256
- * blank line following the subject.
257
- *
258
- * @param message - The commit message
259
- * @returns Object with subject (first line) and body (rest)
260
- *
261
- * @example
262
- * ```typescript
263
- * const { subject, body } = parseCommitMessage(
264
- * 'Add feature\n\nThis adds the new feature'
265
- * )
266
- * // subject = 'Add feature'
267
- * // body = 'This adds the new feature'
268
- * ```
269
- */
270
- export function parseCommitMessage(message) {
271
- if (!message) {
272
- return { subject: '', body: '' };
273
- }
274
- const lines = message.split('\n');
275
- const subject = lines[0] || '';
276
- // Find the body - it starts after the first blank line (or second line if no blank)
277
- let bodyStartIndex = 1;
278
- for (let i = 1; i < lines.length; i++) {
279
- if (lines[i] === '') {
280
- bodyStartIndex = i + 1;
281
- break;
282
- }
283
- }
284
- const body = lines.slice(bodyStartIndex).join('\n');
285
- return { subject, body };
286
- }
287
- /**
288
- * Validates a commit message format.
289
- *
290
- * Checks for common issues and provides warnings for style violations.
291
- * Returns errors for critical issues that would prevent commit creation.
292
- *
293
- * @param message - The commit message to validate
294
- * @returns Object with valid flag and any error/warning messages
295
- *
296
- * @example
297
- * ```typescript
298
- * const result = validateCommitMessage('Fix bug.')
299
- * // {
300
- * // valid: true,
301
- * // errors: [],
302
- * // warnings: ['Subject line should not end with a period']
303
- * // }
304
- * ```
305
- */
306
- export function validateCommitMessage(message) {
307
- const errors = [];
308
- const warnings = [];
309
- if (!message || message.trim() === '') {
310
- errors.push('Commit message is empty');
311
- return { valid: false, errors, warnings };
312
- }
313
- const { subject, body: _body } = parseCommitMessage(message);
314
- // Check subject line length (72 chars is conventional max)
315
- if (subject.length > 72) {
316
- warnings.push('Subject line exceeds 72 characters');
317
- }
318
- // Check if subject ends with a period
319
- if (subject.endsWith('.')) {
320
- warnings.push('Subject line should not end with a period');
321
- }
322
- // Check for missing blank line between subject and body
323
- const lines = message.split('\n');
324
- if (lines.length > 1 && lines[1] !== '') {
325
- warnings.push('Missing blank line between subject and body');
326
- }
327
- return { valid: errors.length === 0, errors, warnings };
328
- }
329
- // ============================================================================
330
- // GPG Signing
331
- // ============================================================================
332
- /**
333
- * Checks if a commit is signed.
334
- *
335
- * @param commit - The commit object
336
- * @returns true if the commit has a GPG signature
337
- *
338
- * @example
339
- * ```typescript
340
- * if (isCommitSigned(commit)) {
341
- * const sig = extractCommitSignature(commit)
342
- * // Verify signature...
343
- * }
344
- * ```
345
- */
346
- export function isCommitSigned(commit) {
347
- const signedCommit = commit;
348
- return signedCommit.gpgsig !== undefined && signedCommit.gpgsig !== null;
349
- }
350
- /**
351
- * Extracts the GPG signature from a signed commit.
352
- *
353
- * @param commit - The commit object
354
- * @returns The signature string if present, null otherwise
355
- */
356
- export function extractCommitSignature(commit) {
357
- const signedCommit = commit;
358
- return signedCommit.gpgsig ?? null;
359
- }
360
- /**
361
- * Adds a GPG signature to a commit.
362
- *
363
- * Creates a new commit object with the signature attached.
364
- * Does not modify the original commit object.
365
- *
366
- * @param commit - The unsigned commit object
367
- * @param signature - The GPG signature string
368
- * @returns The signed commit object
369
- */
370
- export function addSignatureToCommit(commit, signature) {
371
- const signedCommit = {
372
- ...commit,
373
- gpgsig: signature
374
- };
375
- return signedCommit;
376
- }
377
- // ============================================================================
378
- // Empty Commit Detection
379
- // ============================================================================
380
- /**
381
- * Extracts tree SHA from raw commit data.
382
- * @internal
383
- */
384
- function extractTreeFromCommitData(data) {
385
- const decoder = new TextDecoder();
386
- const content = decoder.decode(data);
387
- const match = content.match(/tree ([0-9a-f]{40})/);
388
- return match ? match[1] : null;
389
- }
390
- /**
391
- * Checks if a commit would be empty (same tree as parent).
392
- *
393
- * A commit is considered empty if its tree SHA is identical to
394
- * its parent's tree SHA, meaning no files were changed.
395
- *
396
- * @param store - The object store for reading objects
397
- * @param tree - The tree SHA for the new commit
398
- * @param parent - The parent commit SHA (or null for initial commit)
399
- * @returns true if the commit would have no changes
400
- *
401
- * @example
402
- * ```typescript
403
- * const isEmpty = await isEmptyCommit(store, newTreeSha, parentSha)
404
- * if (isEmpty && !options.allowEmpty) {
405
- * throw new Error('Nothing to commit')
406
- * }
407
- * ```
408
- */
409
- export async function isEmptyCommit(store, tree, parent) {
410
- // Initial commits are never "empty"
411
- if (parent === null) {
412
- return false;
413
- }
414
- const parentObj = await store.getObject(parent);
415
- if (!parentObj) {
416
- return false;
417
- }
418
- // Extract tree from parent commit
419
- const parentTree = extractTreeFromCommitData(parentObj.data);
420
- return parentTree === tree;
421
- }
422
- // ============================================================================
423
- // Validation Helpers
424
- // ============================================================================
425
- const SHA_REGEX = /^[0-9a-f]{40}$/;
426
- /**
427
- * Validates a SHA format.
428
- * @internal
429
- */
430
- function isValidSha(sha) {
431
- return SHA_REGEX.test(sha);
432
- }
433
- /**
434
- * Validates an email format.
435
- * @internal
436
- */
437
- function isValidEmail(email) {
438
- // Basic email validation - must contain @ and have something before and after
439
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
440
- }
441
- /**
442
- * Validates an author name.
443
- * @internal
444
- */
445
- function validateAuthorName(name) {
446
- if (name.includes('<') || name.includes('>')) {
447
- throw new Error('Author name cannot contain angle brackets');
448
- }
449
- if (name.includes('\n')) {
450
- throw new Error('Author name cannot contain newlines');
451
- }
452
- }
453
- /**
454
- * Validates commit options.
455
- * @internal
456
- */
457
- function validateCommitOptions(options) {
458
- // Validate tree
459
- if (!options.tree) {
460
- throw new Error('Tree SHA is required');
461
- }
462
- if (!isValidSha(options.tree)) {
463
- throw new Error('Invalid tree SHA format');
464
- }
465
- // Validate author
466
- if (!options.author) {
467
- throw new Error('Author is required');
468
- }
469
- validateAuthorName(options.author.name);
470
- if (!isValidEmail(options.author.email)) {
471
- throw new Error('Invalid author email format');
472
- }
473
- // Validate committer if provided
474
- if (options.committer) {
475
- validateAuthorName(options.committer.name);
476
- if (!isValidEmail(options.committer.email)) {
477
- throw new Error('Invalid committer email format');
478
- }
479
- }
480
- // Validate message
481
- if (!options.message || options.message.trim() === '') {
482
- throw new Error('Commit message is required');
483
- }
484
- // Validate parents
485
- if (options.parents) {
486
- for (const parent of options.parents) {
487
- if (!isValidSha(parent)) {
488
- throw new Error('Invalid parent SHA format');
489
- }
490
- }
491
- }
492
- // Validate timestamp if provided
493
- if (options.author.timestamp !== undefined && options.author.timestamp < 0) {
494
- throw new Error('Timestamp cannot be negative');
495
- }
496
- if (options.committer?.timestamp !== undefined && options.committer.timestamp < 0) {
497
- throw new Error('Timestamp cannot be negative');
498
- }
499
- }
500
- // ============================================================================
501
- // Commit Creation
502
- // ============================================================================
503
- /**
504
- * Resolves a CommitAuthor to a full Author with timestamp and timezone.
505
- * @internal
506
- */
507
- function resolveAuthor(commitAuthor) {
508
- return {
509
- name: commitAuthor.name,
510
- email: commitAuthor.email,
511
- timestamp: commitAuthor.timestamp ?? Math.floor(Date.now() / 1000),
512
- timezone: commitAuthor.timezone ?? getCurrentTimezone()
513
- };
514
- }
515
- /**
516
- * Serializes commit content to bytes (without the header).
517
- * @internal
518
- */
519
- function serializeCommitContent(commit) {
520
- const encoder = new TextEncoder();
521
- const lines = [];
522
- lines.push(`tree ${commit.tree}`);
523
- for (const parent of commit.parents) {
524
- lines.push(`parent ${parent}`);
525
- }
526
- lines.push(`author ${commit.author.name} <${commit.author.email}> ${commit.author.timestamp} ${commit.author.timezone}`);
527
- lines.push(`committer ${commit.committer.name} <${commit.committer.email}> ${commit.committer.timestamp} ${commit.committer.timezone}`);
528
- // Add gpgsig if present
529
- if (commit.gpgsig) {
530
- const sigLines = commit.gpgsig.split('\n');
531
- lines.push(`gpgsig ${sigLines[0]}`);
532
- for (let i = 1; i < sigLines.length; i++) {
533
- lines.push(` ${sigLines[i]}`);
534
- }
535
- }
536
- lines.push('');
537
- lines.push(commit.message);
538
- return encoder.encode(lines.join('\n'));
539
- }
540
- /**
541
- * Builds a commit object from options without storing it.
542
- *
543
- * Useful for creating commit objects for inspection or testing
544
- * without actually persisting them to the object store.
545
- *
546
- * @param options - Commit creation options
547
- * @returns The commit object (not stored)
548
- *
549
- * @example
550
- * ```typescript
551
- * const commit = buildCommitObject({
552
- * message: 'Test commit',
553
- * tree: treeSha,
554
- * parents: [parentSha],
555
- * author: { name: 'Test', email: 'test@example.com' }
556
- * })
557
- *
558
- * console.log(commit.message) // 'Test commit'
559
- * ```
560
- */
561
- export function buildCommitObject(options) {
562
- const author = resolveAuthor(options.author);
563
- const committer = options.committer ? resolveAuthor(options.committer) : author;
564
- const parents = options.parents ?? [];
565
- const commit = {
566
- type: 'commit',
567
- data: new Uint8Array(),
568
- tree: options.tree,
569
- parents,
570
- author,
571
- committer,
572
- message: options.message
573
- };
574
- // Set the data field
575
- commit.data = serializeCommitContent({
576
- tree: commit.tree,
577
- parents: commit.parents,
578
- author: commit.author,
579
- committer: commit.committer,
580
- message: commit.message
581
- });
582
- return commit;
583
- }
584
- /**
585
- * Creates a new commit.
586
- *
587
- * Creates a commit object with the specified options and stores it
588
- * in the object store. Handles validation, empty commit detection,
589
- * and optional GPG signing.
590
- *
591
- * @param store - The object store for reading/writing objects
592
- * @param options - Commit creation options
593
- * @returns The created commit result with SHA and commit object
594
- *
595
- * @throws {Error} If tree SHA is missing or invalid
596
- * @throws {Error} If author is missing or invalid
597
- * @throws {Error} If commit message is empty
598
- * @throws {Error} If commit would be empty and allowEmpty is false
599
- *
600
- * @example
601
- * ```typescript
602
- * // Basic commit
603
- * const result = await createCommit(store, {
604
- * message: 'Add new feature',
605
- * tree: treeSha,
606
- * parents: [headSha],
607
- * author: { name: 'John', email: 'john@example.com' }
608
- * })
609
- *
610
- * // Signed commit
611
- * const signedResult = await createCommit(store, {
612
- * message: 'Signed commit',
613
- * tree: treeSha,
614
- * parents: [headSha],
615
- * author: { name: 'John', email: 'john@example.com' },
616
- * signing: {
617
- * sign: true,
618
- * signer: async (data) => myGpgSign(data)
619
- * }
620
- * })
621
- *
622
- * // Initial commit (no parents)
623
- * const initialResult = await createCommit(store, {
624
- * message: 'Initial commit',
625
- * tree: treeSha,
626
- * parents: [],
627
- * author: { name: 'John', email: 'john@example.com' }
628
- * })
629
- * ```
630
- */
631
- export async function createCommit(store, options) {
632
- // Validate options
633
- validateCommitOptions(options);
634
- const parents = options.parents ?? [];
635
- // Check for empty commit
636
- if (options.allowEmpty === false && parents.length > 0) {
637
- const isEmpty = await isEmptyCommit(store, options.tree, parents[0]);
638
- if (isEmpty) {
639
- throw new Error('Nothing to commit (empty commit not allowed)');
640
- }
641
- }
642
- // Build the commit object
643
- let commit = buildCommitObject(options);
644
- // Sign if requested
645
- if (options.signing?.sign && options.signing.signer) {
646
- const commitData = serializeCommitContent({
647
- tree: commit.tree,
648
- parents: commit.parents,
649
- author: commit.author,
650
- committer: commit.committer,
651
- message: commit.message
652
- });
653
- const signature = await options.signing.signer(commitData);
654
- commit = addSignatureToCommit(commit, signature);
655
- // Update commit data with signature
656
- const signedCommit = commit;
657
- commit.data = serializeCommitContent({
658
- tree: commit.tree,
659
- parents: commit.parents,
660
- author: commit.author,
661
- committer: commit.committer,
662
- message: commit.message,
663
- gpgsig: signedCommit.gpgsig
664
- });
665
- }
666
- // Store the commit
667
- const sha = await store.storeObject('commit', commit.data);
668
- return {
669
- sha,
670
- commit,
671
- created: true
672
- };
673
- }
674
- // ============================================================================
675
- // Commit Amendment
676
- // ============================================================================
677
- /**
678
- * Parses a stored commit object from raw data.
679
- * Supports both git text format and JSON format (for testing).
680
- * @internal
681
- */
682
- function parseStoredCommit(data) {
683
- const decoder = new TextDecoder();
684
- const content = decoder.decode(data);
685
- // Try to parse as JSON first (for test compatibility)
686
- if (content.startsWith('{')) {
687
- try {
688
- const parsed = JSON.parse(content);
689
- return {
690
- tree: parsed.tree,
691
- parents: parsed.parents || [],
692
- author: parsed.author,
693
- committer: parsed.committer || parsed.author,
694
- message: parsed.message
695
- };
696
- }
697
- catch {
698
- // Not JSON, fall through to git format parsing
699
- }
700
- }
701
- // Parse git text format
702
- const lines = content.split('\n');
703
- let tree = '';
704
- const parents = [];
705
- let author = null;
706
- let committer = null;
707
- let messageStartIndex = 0;
708
- for (let i = 0; i < lines.length; i++) {
709
- const line = lines[i];
710
- if (line === '') {
711
- messageStartIndex = i + 1;
712
- break;
713
- }
714
- if (line.startsWith('tree ')) {
715
- tree = line.slice(5);
716
- }
717
- else if (line.startsWith('parent ')) {
718
- parents.push(line.slice(7));
719
- }
720
- else if (line.startsWith('author ')) {
721
- const match = line.match(/^author (.+) <(.+)> (\d+) ([+-]\d{4})$/);
722
- if (match) {
723
- author = {
724
- name: match[1],
725
- email: match[2],
726
- timestamp: parseInt(match[3], 10),
727
- timezone: match[4]
728
- };
729
- }
730
- }
731
- else if (line.startsWith('committer ')) {
732
- const match = line.match(/^committer (.+) <(.+)> (\d+) ([+-]\d{4})$/);
733
- if (match) {
734
- committer = {
735
- name: match[1],
736
- email: match[2],
737
- timestamp: parseInt(match[3], 10),
738
- timezone: match[4]
739
- };
740
- }
741
- }
742
- }
743
- const message = lines.slice(messageStartIndex).join('\n');
744
- if (!author) {
745
- author = { name: 'Unknown', email: 'unknown@example.com', timestamp: 0, timezone: '+0000' };
746
- }
747
- if (!committer) {
748
- committer = author;
749
- }
750
- return { tree, parents, author, committer, message };
751
- }
752
- /**
753
- * Amends an existing commit.
754
- *
755
- * Creates a new commit that replaces the specified commit.
756
- * The original commit is not modified. Only specified fields
757
- * in options will be changed from the original.
758
- *
759
- * Note: This does not update any refs. The caller is responsible
760
- * for updating HEAD or branch refs to point to the new commit.
761
- *
762
- * @param store - The object store for reading/writing objects
763
- * @param commitSha - SHA of the commit to amend
764
- * @param options - Amendment options (only specified fields are changed)
765
- * @returns The new commit result (original commit is not modified)
766
- *
767
- * @throws {Error} If the commit doesn't exist
768
- *
769
- * @example
770
- * ```typescript
771
- * // Change just the message
772
- * const newCommit = await amendCommit(store, headSha, {
773
- * message: 'Better commit message'
774
- * })
775
- *
776
- * // Update tree and committer
777
- * const newCommit = await amendCommit(store, headSha, {
778
- * tree: newTreeSha,
779
- * committer: { name: 'New Name', email: 'new@example.com' }
780
- * })
781
- * ```
782
- */
783
- export async function amendCommit(store, commitSha, options) {
784
- // Get the original commit
785
- const originalObj = await store.getObject(commitSha);
786
- if (!originalObj) {
787
- throw new Error(`Commit not found: ${commitSha}`);
788
- }
789
- // Parse the original commit
790
- const original = parseStoredCommit(originalObj.data);
791
- // Build new author
792
- let newAuthor = original.author;
793
- if (options.author) {
794
- newAuthor = resolveAuthor(options.author);
795
- }
796
- else if (options.resetAuthorDate) {
797
- newAuthor = {
798
- ...original.author,
799
- timestamp: Math.floor(Date.now() / 1000)
800
- };
801
- }
802
- // Build new committer (defaults to current time)
803
- let newCommitter;
804
- if (options.committer) {
805
- newCommitter = resolveAuthor(options.committer);
806
- }
807
- else {
808
- newCommitter = {
809
- ...original.committer,
810
- timestamp: Math.floor(Date.now() / 1000),
811
- timezone: getCurrentTimezone()
812
- };
813
- }
814
- // Build new commit
815
- const newCommitOptions = {
816
- message: options.message ?? original.message,
817
- tree: options.tree ?? original.tree,
818
- parents: original.parents,
819
- author: newAuthor,
820
- committer: newCommitter,
821
- signing: options.signing,
822
- allowEmpty: true
823
- };
824
- return createCommit(store, newCommitOptions);
825
- }
826
- //# sourceMappingURL=commit.js.map