git-remote-ops 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/AGENTS.md +177 -0
  2. package/LICENSE +21 -0
  3. package/README.md +247 -0
  4. package/esm/_dnt.shims.js +72 -0
  5. package/esm/cli.js +217 -0
  6. package/esm/client.js +439 -0
  7. package/esm/deps/jsr.io/@cliffy/command/1.1.0/_argument_types.js +1 -0
  8. package/esm/deps/jsr.io/@cliffy/command/1.1.0/_errors.js +133 -0
  9. package/esm/deps/jsr.io/@cliffy/command/1.1.0/_spread.js +1 -0
  10. package/esm/deps/jsr.io/@cliffy/command/1.1.0/_type_utils.js +1 -0
  11. package/esm/deps/jsr.io/@cliffy/command/1.1.0/_utils.js +141 -0
  12. package/esm/deps/jsr.io/@cliffy/command/1.1.0/command.js +1861 -0
  13. package/esm/deps/jsr.io/@cliffy/command/1.1.0/help/_help_generator.js +357 -0
  14. package/esm/deps/jsr.io/@cliffy/command/1.1.0/mod.js +13 -0
  15. package/esm/deps/jsr.io/@cliffy/command/1.1.0/type.js +27 -0
  16. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/action_list.js +16 -0
  17. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/boolean.js +13 -0
  18. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/child_command.js +14 -0
  19. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/command.js +9 -0
  20. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/enum.js +24 -0
  21. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/file.js +12 -0
  22. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/integer.js +9 -0
  23. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/number.js +9 -0
  24. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/secret.js +7 -0
  25. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types/string.js +9 -0
  26. package/esm/deps/jsr.io/@cliffy/command/1.1.0/types.js +2 -0
  27. package/esm/deps/jsr.io/@cliffy/command/1.1.0/upgrade/_check_version.js +26 -0
  28. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/_errors.js +129 -0
  29. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/_utils.js +100 -0
  30. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/_validate_flags.js +166 -0
  31. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/flags.js +750 -0
  32. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/mod.js +55 -0
  33. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/types/boolean.js +11 -0
  34. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/types/integer.js +9 -0
  35. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/types/number.js +11 -0
  36. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/types/string.js +4 -0
  37. package/esm/deps/jsr.io/@cliffy/flags/1.1.0/types.js +1 -0
  38. package/esm/deps/jsr.io/@cliffy/internal/1.1.0/runtime/exit.js +16 -0
  39. package/esm/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_args.js +11 -0
  40. package/esm/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_columns.js +25 -0
  41. package/esm/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_env.js +18 -0
  42. package/esm/deps/jsr.io/@cliffy/internal/1.1.0/runtime/inspect.js +11 -0
  43. package/esm/deps/jsr.io/@cliffy/table/1.1.0/_layout.js +616 -0
  44. package/esm/deps/jsr.io/@cliffy/table/1.1.0/_utils.js +79 -0
  45. package/esm/deps/jsr.io/@cliffy/table/1.1.0/border.js +18 -0
  46. package/esm/deps/jsr.io/@cliffy/table/1.1.0/cell.js +190 -0
  47. package/esm/deps/jsr.io/@cliffy/table/1.1.0/column.js +117 -0
  48. package/esm/deps/jsr.io/@cliffy/table/1.1.0/consume_words.js +64 -0
  49. package/esm/deps/jsr.io/@cliffy/table/1.1.0/mod.js +42 -0
  50. package/esm/deps/jsr.io/@cliffy/table/1.1.0/row.js +82 -0
  51. package/esm/deps/jsr.io/@cliffy/table/1.1.0/table.js +341 -0
  52. package/esm/deps/jsr.io/@cliffy/table/1.1.0/unicode_width.js +101 -0
  53. package/esm/deps/jsr.io/@std/crypto/1.1.0/_types.js +2 -0
  54. package/esm/deps/jsr.io/@std/crypto/1.1.0/_wasm/lib/deno_std_wasm_crypto.internal.js +237 -0
  55. package/esm/deps/jsr.io/@std/crypto/1.1.0/_wasm/lib/deno_std_wasm_crypto.js +2277 -0
  56. package/esm/deps/jsr.io/@std/crypto/1.1.0/_wasm/mod.js +46 -0
  57. package/esm/deps/jsr.io/@std/crypto/1.1.0/aes_gcm.js +132 -0
  58. package/esm/deps/jsr.io/@std/crypto/1.1.0/crypto.js +270 -0
  59. package/esm/deps/jsr.io/@std/crypto/1.1.0/mod.js +23 -0
  60. package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.js +61 -0
  61. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common16.js +51 -0
  62. package/esm/deps/jsr.io/@std/encoding/1.0.10/_common_detach.js +13 -0
  63. package/esm/deps/jsr.io/@std/encoding/1.0.10/_types.js +2 -0
  64. package/esm/deps/jsr.io/@std/encoding/1.0.10/hex.js +87 -0
  65. package/esm/deps/jsr.io/@std/fmt/1.0.10/colors.js +903 -0
  66. package/esm/deps/jsr.io/@std/text/1.0.18/closest_string.js +46 -0
  67. package/esm/deps/jsr.io/@std/text/1.0.18/levenshtein_distance.js +127 -0
  68. package/esm/errors.js +38 -0
  69. package/esm/index.js +10 -0
  70. package/esm/logger.js +216 -0
  71. package/esm/objects/commit.js +47 -0
  72. package/esm/objects/index.js +2 -0
  73. package/esm/objects/tree.js +149 -0
  74. package/esm/pack/delta.js +179 -0
  75. package/esm/pack/index.js +3 -0
  76. package/esm/pack/objects.js +72 -0
  77. package/esm/pack/parser.js +304 -0
  78. package/esm/package.json +3 -0
  79. package/esm/protocol/index.js +3 -0
  80. package/esm/protocol/pkt_line.js +103 -0
  81. package/esm/protocol/refs.js +100 -0
  82. package/esm/protocol/upload_pack.js +259 -0
  83. package/esm/transport.js +128 -0
  84. package/esm/types.js +8 -0
  85. package/package.json +50 -0
  86. package/types/_dnt.shims.d.ts +16 -0
  87. package/types/_dnt.shims.d.ts.map +1 -0
  88. package/types/cli.d.ts +3 -0
  89. package/types/cli.d.ts.map +1 -0
  90. package/types/client.d.ts +108 -0
  91. package/types/client.d.ts.map +1 -0
  92. package/types/deps/jsr.io/@cliffy/command/1.1.0/_argument_types.d.ts +163 -0
  93. package/types/deps/jsr.io/@cliffy/command/1.1.0/_argument_types.d.ts.map +1 -0
  94. package/types/deps/jsr.io/@cliffy/command/1.1.0/_errors.d.ts +71 -0
  95. package/types/deps/jsr.io/@cliffy/command/1.1.0/_errors.d.ts.map +1 -0
  96. package/types/deps/jsr.io/@cliffy/command/1.1.0/_spread.d.ts +16 -0
  97. package/types/deps/jsr.io/@cliffy/command/1.1.0/_spread.d.ts.map +1 -0
  98. package/types/deps/jsr.io/@cliffy/command/1.1.0/_type_utils.d.ts +15 -0
  99. package/types/deps/jsr.io/@cliffy/command/1.1.0/_type_utils.d.ts.map +1 -0
  100. package/types/deps/jsr.io/@cliffy/command/1.1.0/_utils.d.ts +38 -0
  101. package/types/deps/jsr.io/@cliffy/command/1.1.0/_utils.d.ts.map +1 -0
  102. package/types/deps/jsr.io/@cliffy/command/1.1.0/command.d.ts +1086 -0
  103. package/types/deps/jsr.io/@cliffy/command/1.1.0/command.d.ts.map +1 -0
  104. package/types/deps/jsr.io/@cliffy/command/1.1.0/help/_help_generator.d.ts +33 -0
  105. package/types/deps/jsr.io/@cliffy/command/1.1.0/help/_help_generator.d.ts.map +1 -0
  106. package/types/deps/jsr.io/@cliffy/command/1.1.0/mod.d.ts +78 -0
  107. package/types/deps/jsr.io/@cliffy/command/1.1.0/mod.d.ts.map +1 -0
  108. package/types/deps/jsr.io/@cliffy/command/1.1.0/type.d.ts +51 -0
  109. package/types/deps/jsr.io/@cliffy/command/1.1.0/type.d.ts.map +1 -0
  110. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/action_list.d.ts +10 -0
  111. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/action_list.d.ts.map +1 -0
  112. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/boolean.d.ts +10 -0
  113. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/boolean.d.ts.map +1 -0
  114. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/child_command.d.ts +10 -0
  115. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/child_command.d.ts.map +1 -0
  116. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/command.d.ts +8 -0
  117. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/command.d.ts.map +1 -0
  118. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/enum.d.ts +11 -0
  119. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/enum.d.ts.map +1 -0
  120. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/file.d.ts +6 -0
  121. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/file.d.ts.map +1 -0
  122. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/integer.d.ts +8 -0
  123. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/integer.d.ts.map +1 -0
  124. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/number.d.ts +8 -0
  125. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/number.d.ts.map +1 -0
  126. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/secret.d.ts +6 -0
  127. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/secret.d.ts.map +1 -0
  128. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/string.d.ts +8 -0
  129. package/types/deps/jsr.io/@cliffy/command/1.1.0/types/string.d.ts.map +1 -0
  130. package/types/deps/jsr.io/@cliffy/command/1.1.0/types.d.ts +161 -0
  131. package/types/deps/jsr.io/@cliffy/command/1.1.0/types.d.ts.map +1 -0
  132. package/types/deps/jsr.io/@cliffy/command/1.1.0/upgrade/_check_version.d.ts +4 -0
  133. package/types/deps/jsr.io/@cliffy/command/1.1.0/upgrade/_check_version.d.ts.map +1 -0
  134. package/types/deps/jsr.io/@cliffy/flags/1.1.0/_errors.d.ts +67 -0
  135. package/types/deps/jsr.io/@cliffy/flags/1.1.0/_errors.d.ts.map +1 -0
  136. package/types/deps/jsr.io/@cliffy/flags/1.1.0/_utils.d.ts +17 -0
  137. package/types/deps/jsr.io/@cliffy/flags/1.1.0/_utils.d.ts.map +1 -0
  138. package/types/deps/jsr.io/@cliffy/flags/1.1.0/_validate_flags.d.ts +11 -0
  139. package/types/deps/jsr.io/@cliffy/flags/1.1.0/_validate_flags.d.ts.map +1 -0
  140. package/types/deps/jsr.io/@cliffy/flags/1.1.0/flags.d.ts +154 -0
  141. package/types/deps/jsr.io/@cliffy/flags/1.1.0/flags.d.ts.map +1 -0
  142. package/types/deps/jsr.io/@cliffy/flags/1.1.0/mod.d.ts +57 -0
  143. package/types/deps/jsr.io/@cliffy/flags/1.1.0/mod.d.ts.map +1 -0
  144. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/boolean.d.ts +4 -0
  145. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/boolean.d.ts.map +1 -0
  146. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/integer.d.ts +4 -0
  147. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/integer.d.ts.map +1 -0
  148. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/number.d.ts +4 -0
  149. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/number.d.ts.map +1 -0
  150. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/string.d.ts +4 -0
  151. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types/string.d.ts.map +1 -0
  152. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types.d.ts +170 -0
  153. package/types/deps/jsr.io/@cliffy/flags/1.1.0/types.d.ts.map +1 -0
  154. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/exit.d.ts +8 -0
  155. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/exit.d.ts.map +1 -0
  156. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_args.d.ts +7 -0
  157. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_args.d.ts.map +1 -0
  158. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_columns.d.ts +7 -0
  159. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_columns.d.ts.map +1 -0
  160. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_env.d.ts +8 -0
  161. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/get_env.d.ts.map +1 -0
  162. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/inspect.d.ts +7 -0
  163. package/types/deps/jsr.io/@cliffy/internal/1.1.0/runtime/inspect.d.ts.map +1 -0
  164. package/types/deps/jsr.io/@cliffy/table/1.1.0/_layout.d.ts +108 -0
  165. package/types/deps/jsr.io/@cliffy/table/1.1.0/_layout.d.ts.map +1 -0
  166. package/types/deps/jsr.io/@cliffy/table/1.1.0/_utils.d.ts +26 -0
  167. package/types/deps/jsr.io/@cliffy/table/1.1.0/_utils.d.ts.map +1 -0
  168. package/types/deps/jsr.io/@cliffy/table/1.1.0/border.d.ts +21 -0
  169. package/types/deps/jsr.io/@cliffy/table/1.1.0/border.d.ts.map +1 -0
  170. package/types/deps/jsr.io/@cliffy/table/1.1.0/cell.d.ts +155 -0
  171. package/types/deps/jsr.io/@cliffy/table/1.1.0/cell.d.ts.map +1 -0
  172. package/types/deps/jsr.io/@cliffy/table/1.1.0/column.d.ts +97 -0
  173. package/types/deps/jsr.io/@cliffy/table/1.1.0/column.d.ts.map +1 -0
  174. package/types/deps/jsr.io/@cliffy/table/1.1.0/consume_words.d.ts +30 -0
  175. package/types/deps/jsr.io/@cliffy/table/1.1.0/consume_words.d.ts.map +1 -0
  176. package/types/deps/jsr.io/@cliffy/table/1.1.0/mod.d.ts +43 -0
  177. package/types/deps/jsr.io/@cliffy/table/1.1.0/mod.d.ts.map +1 -0
  178. package/types/deps/jsr.io/@cliffy/table/1.1.0/row.d.ts +67 -0
  179. package/types/deps/jsr.io/@cliffy/table/1.1.0/row.d.ts.map +1 -0
  180. package/types/deps/jsr.io/@cliffy/table/1.1.0/table.d.ts +235 -0
  181. package/types/deps/jsr.io/@cliffy/table/1.1.0/table.d.ts.map +1 -0
  182. package/types/deps/jsr.io/@cliffy/table/1.1.0/unicode_width.d.ts +40 -0
  183. package/types/deps/jsr.io/@cliffy/table/1.1.0/unicode_width.d.ts.map +1 -0
  184. package/types/deps/jsr.io/@std/crypto/1.1.0/_types.d.ts +9 -0
  185. package/types/deps/jsr.io/@std/crypto/1.1.0/_types.d.ts.map +1 -0
  186. package/types/deps/jsr.io/@std/crypto/1.1.0/_wasm/lib/deno_std_wasm_crypto.d.ts +2 -0
  187. package/types/deps/jsr.io/@std/crypto/1.1.0/_wasm/lib/deno_std_wasm_crypto.d.ts.map +1 -0
  188. package/types/deps/jsr.io/@std/crypto/1.1.0/_wasm/lib/deno_std_wasm_crypto.internal.d.ts +69 -0
  189. package/types/deps/jsr.io/@std/crypto/1.1.0/_wasm/lib/deno_std_wasm_crypto.internal.d.ts.map +1 -0
  190. package/types/deps/jsr.io/@std/crypto/1.1.0/_wasm/mod.d.ts +13 -0
  191. package/types/deps/jsr.io/@std/crypto/1.1.0/_wasm/mod.d.ts.map +1 -0
  192. package/types/deps/jsr.io/@std/crypto/1.1.0/aes_gcm.d.ts +76 -0
  193. package/types/deps/jsr.io/@std/crypto/1.1.0/aes_gcm.d.ts.map +1 -0
  194. package/types/deps/jsr.io/@std/crypto/1.1.0/crypto.d.ts +149 -0
  195. package/types/deps/jsr.io/@std/crypto/1.1.0/crypto.d.ts.map +1 -0
  196. package/types/deps/jsr.io/@std/crypto/1.1.0/mod.d.ts +22 -0
  197. package/types/deps/jsr.io/@std/crypto/1.1.0/mod.d.ts.map +1 -0
  198. package/types/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.d.ts +40 -0
  199. package/types/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.d.ts.map +1 -0
  200. package/types/deps/jsr.io/@std/encoding/1.0.10/_common16.d.ts +23 -0
  201. package/types/deps/jsr.io/@std/encoding/1.0.10/_common16.d.ts.map +1 -0
  202. package/types/deps/jsr.io/@std/encoding/1.0.10/_common_detach.d.ts +4 -0
  203. package/types/deps/jsr.io/@std/encoding/1.0.10/_common_detach.d.ts.map +1 -0
  204. package/types/deps/jsr.io/@std/encoding/1.0.10/_types.d.ts +9 -0
  205. package/types/deps/jsr.io/@std/encoding/1.0.10/_types.d.ts.map +1 -0
  206. package/types/deps/jsr.io/@std/encoding/1.0.10/hex.d.ts +39 -0
  207. package/types/deps/jsr.io/@std/encoding/1.0.10/hex.d.ts.map +1 -0
  208. package/types/deps/jsr.io/@std/fmt/1.0.10/colors.d.ts +700 -0
  209. package/types/deps/jsr.io/@std/fmt/1.0.10/colors.d.ts.map +1 -0
  210. package/types/deps/jsr.io/@std/text/1.0.18/closest_string.d.ts +42 -0
  211. package/types/deps/jsr.io/@std/text/1.0.18/closest_string.d.ts.map +1 -0
  212. package/types/deps/jsr.io/@std/text/1.0.18/levenshtein_distance.d.ts +23 -0
  213. package/types/deps/jsr.io/@std/text/1.0.18/levenshtein_distance.d.ts.map +1 -0
  214. package/types/errors.d.ts +73 -0
  215. package/types/errors.d.ts.map +1 -0
  216. package/types/index.d.ts +14 -0
  217. package/types/index.d.ts.map +1 -0
  218. package/types/logger.d.ts +70 -0
  219. package/types/logger.d.ts.map +1 -0
  220. package/types/objects/commit.d.ts +23 -0
  221. package/types/objects/commit.d.ts.map +1 -0
  222. package/types/objects/index.d.ts +3 -0
  223. package/types/objects/index.d.ts.map +1 -0
  224. package/types/objects/tree.d.ts +49 -0
  225. package/types/objects/tree.d.ts.map +1 -0
  226. package/types/pack/delta.d.ts +47 -0
  227. package/types/pack/delta.d.ts.map +1 -0
  228. package/types/pack/index.d.ts +4 -0
  229. package/types/pack/index.d.ts.map +1 -0
  230. package/types/pack/objects.d.ts +53 -0
  231. package/types/pack/objects.d.ts.map +1 -0
  232. package/types/pack/parser.d.ts +61 -0
  233. package/types/pack/parser.d.ts.map +1 -0
  234. package/types/protocol/index.d.ts +4 -0
  235. package/types/protocol/index.d.ts.map +1 -0
  236. package/types/protocol/pkt_line.d.ts +44 -0
  237. package/types/protocol/pkt_line.d.ts.map +1 -0
  238. package/types/protocol/refs.d.ts +40 -0
  239. package/types/protocol/refs.d.ts.map +1 -0
  240. package/types/protocol/upload_pack.d.ts +45 -0
  241. package/types/protocol/upload_pack.d.ts.map +1 -0
  242. package/types/transport.d.ts +24 -0
  243. package/types/transport.d.ts.map +1 -0
  244. package/types/types.d.ts +121 -0
  245. package/types/types.d.ts.map +1 -0
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @module refs
3
+ *
4
+ * Decoders for the two flavours of `info/refs` response Git can return for the
5
+ * `git-upload-pack` service:
6
+ *
7
+ * - **Protocol v0/v1** — a flat stream of `<sha> <ref>` pkt-lines where the
8
+ * first ref also carries a NUL-separated capability list.
9
+ * - **Protocol v2** — a capability advertisement (`version 2`, then one
10
+ * `key[=args]` pkt-line per capability).
11
+ */
12
+ import { Result } from "better-result";
13
+ import { parsePktLines } from "./pkt_line.js";
14
+ const decoder = new TextDecoder();
15
+ /** ASCII `'#'` — leading byte of the optional `# service=...` banner line. */
16
+ const COMMENT_LINE = 0x23;
17
+ /** ASCII space separating sha from ref name. */
18
+ const SPACE = 0x20;
19
+ /** ASCII line-feed — trailing terminator on most advertisement lines. */
20
+ const LF = 0x0a;
21
+ /** Hex-encoded SHA-1 is always 40 chars. */
22
+ const SHA_LENGTH = 40;
23
+ function stripTrailingLf(payload) {
24
+ return payload.at(-1) === LF ? payload.subarray(0, payload.length - 1) : payload;
25
+ }
26
+ /**
27
+ * Parse a v0/v1 ref advertisement (response body of
28
+ * `GET /info/refs?service=git-upload-pack`).
29
+ *
30
+ * The first non-comment data line is special: its payload contains the ref
31
+ * pair, a NUL byte, then a space-separated list of capabilities. Subsequent
32
+ * lines are plain `<sha> <ref>\n` pairs.
33
+ *
34
+ * @param body Raw response bytes (including any `# service=...` banner).
35
+ * @returns The advertised refs (name → sha) and capabilities, or
36
+ * {@link PktLineError} if the pkt-line framing is malformed.
37
+ */
38
+ export function parseRefAdvertisement(body) {
39
+ const refs = new Map();
40
+ const capabilities = new Set();
41
+ let firstRef = true;
42
+ const lines = parsePktLines(body);
43
+ if (lines.isErr())
44
+ return Result.err(lines.error);
45
+ for (const { payload } of lines.value) {
46
+ if (payload === null || payload.length === 0 || payload[0] === COMMENT_LINE) {
47
+ continue;
48
+ }
49
+ let line = stripTrailingLf(payload);
50
+ if (firstRef) {
51
+ const nul = line.indexOf(0);
52
+ if (nul >= 0) {
53
+ const capText = decoder.decode(line.subarray(nul + 1));
54
+ for (const cap of capText.split(/\s+/).filter(Boolean)) {
55
+ capabilities.add(cap);
56
+ }
57
+ line = line.subarray(0, nul);
58
+ }
59
+ }
60
+ if (line.length >= SHA_LENGTH + 1 && line[SHA_LENGTH] === SPACE) {
61
+ refs.set(decoder.decode(line.subarray(SHA_LENGTH + 1)), decoder.decode(line.subarray(0, SHA_LENGTH)));
62
+ firstRef = false;
63
+ }
64
+ }
65
+ return Result.ok({ refs, capabilities });
66
+ }
67
+ /**
68
+ * Parse a v2 capability advertisement.
69
+ *
70
+ * The first data line is always `version 2`; we encode that as the synthetic
71
+ * capability `"version=2"` so callers can detect protocol v2 with a single
72
+ * lookup. For the `fetch` capability, any space-separated arguments (e.g.
73
+ * `shallow`, `filter`, `wait-for-done`) are added as separate set entries.
74
+ *
75
+ * @param body Raw response bytes from the `git-upload-pack` advertisement.
76
+ * @returns Set of capability tokens, or {@link PktLineError} on bad framing.
77
+ */
78
+ export function parseV2CapabilityAdvertisement(body) {
79
+ const capabilities = new Set();
80
+ const lines = parsePktLines(body);
81
+ if (lines.isErr())
82
+ return Result.err(lines.error);
83
+ for (const { payload } of lines.value) {
84
+ if (payload === null || payload.length === 0 || payload[0] === COMMENT_LINE) {
85
+ continue;
86
+ }
87
+ const line = decoder.decode(stripTrailingLf(payload));
88
+ if (line === "version 2") {
89
+ capabilities.add("version=2");
90
+ continue;
91
+ }
92
+ const [name, args] = line.split("=", 2);
93
+ capabilities.add(name);
94
+ if (name === "fetch" && args) {
95
+ for (const arg of args.split(/\s+/).filter(Boolean))
96
+ capabilities.add(arg);
97
+ }
98
+ }
99
+ return Result.ok(capabilities);
100
+ }
@@ -0,0 +1,259 @@
1
+ /**
2
+ * @module upload-pack
3
+ *
4
+ * Build `git-upload-pack` request bodies (protocol v0 and v2) and demux the
5
+ * sideband-multiplexed response back into a raw packfile.
6
+ *
7
+ * Sideband framing: each data pkt-line is prefixed by a single byte channel
8
+ * marker — `1` packfile bytes, `2` human-readable progress, `3` fatal error
9
+ * text. The packfile itself is the concatenation of all channel-1 payloads.
10
+ */
11
+ import { Result } from "better-result";
12
+ import { UploadPackError } from "../errors.js";
13
+ import { PACK_SIGNATURE } from "../pack/objects.js";
14
+ import { DELIM_PKT, FLUSH_PKT, parsePktLines, pktLine } from "./pkt_line.js";
15
+ const encoder = new TextEncoder();
16
+ const decoder = new TextDecoder();
17
+ /** Sideband channel for packfile bytes. */
18
+ const BAND_PACK = 1;
19
+ /** Sideband channel for human-readable progress messages. */
20
+ const BAND_PROGRESS = 2;
21
+ /** Sideband channel for fatal error text. */
22
+ const BAND_ERROR = 3;
23
+ /**
24
+ * Pkt-line payload prefixes that mark control / framing lines, not packfile
25
+ * data. Used to skip past the v2 section headers (`packfile\n` etc.) when
26
+ * hunting for the first real data line.
27
+ */
28
+ const CONTROL_PREFIXES = [
29
+ "version 2",
30
+ "shallow-info",
31
+ "wanted-refs",
32
+ "packfile",
33
+ "shallow ",
34
+ "unshallow ",
35
+ "NAK",
36
+ "ACK",
37
+ ];
38
+ /** Bytes of payload to peek at when matching against {@link CONTROL_PREFIXES}. */
39
+ const CONTROL_PREFIX_PEEK = 16;
40
+ function concat(parts) {
41
+ const length = parts.reduce((sum, part) => sum + part.length, 0);
42
+ const out = new Uint8Array(length);
43
+ let offset = 0;
44
+ for (const part of parts) {
45
+ out.set(part, offset);
46
+ offset += part.length;
47
+ }
48
+ return out;
49
+ }
50
+ /**
51
+ * Build the POST body for `/git-upload-pack`. Dispatches to a v0 or v2 encoder
52
+ * based on `options.protocolVersion` (defaults to v0).
53
+ *
54
+ * @returns Encoded request bytes, or {@link PktLineError} if any inner frame
55
+ * exceeds the pkt-line size cap.
56
+ */
57
+ export function buildFetchRequest(options) {
58
+ return options.protocolVersion === 2
59
+ ? buildV2FetchRequest(options)
60
+ : buildV0FetchRequest(options);
61
+ }
62
+ /**
63
+ * Encode a v0 fetch request: one `want <sha>` per oid (capabilities ride on
64
+ * the first `want` line, space-separated after the sha), optional `deepen`
65
+ * and `filter` lines, a flush, then `done`.
66
+ */
67
+ function buildV0FetchRequest(options) {
68
+ const lines = [];
69
+ for (let index = 0; index < options.wants.length; index++) {
70
+ const sha = options.wants[index];
71
+ const caps = index === 0 && options.caps.length > 0 ? ` ${options.caps.join(" ")}` : "";
72
+ const line = pktLine(encoder.encode(`want ${sha}${caps}\n`));
73
+ if (line.isErr())
74
+ return Result.err(line.error);
75
+ lines.push(line.value);
76
+ }
77
+ if (options.depth !== undefined) {
78
+ const line = pktLine(encoder.encode(`deepen ${options.depth}\n`));
79
+ if (line.isErr())
80
+ return Result.err(line.error);
81
+ lines.push(line.value);
82
+ }
83
+ if (options.filterSpec !== undefined) {
84
+ const line = pktLine(encoder.encode(`filter ${options.filterSpec}\n`));
85
+ if (line.isErr())
86
+ return Result.err(line.error);
87
+ lines.push(line.value);
88
+ }
89
+ lines.push(FLUSH_PKT);
90
+ const done = pktLine(encoder.encode("done\n"));
91
+ if (done.isErr())
92
+ return Result.err(done.error);
93
+ lines.push(done.value);
94
+ return Result.ok(concat(lines));
95
+ }
96
+ /**
97
+ * Encode a v2 fetch command. Header section carries `command=fetch` and an
98
+ * `agent=` string, separated from the argument section by a delim packet.
99
+ * The argument section lists transport hints (`thin-pack`, `ofs-delta`),
100
+ * `want` lines, optional `deepen`/`filter`, then `done` and a flush.
101
+ */
102
+ function buildV2FetchRequest(options) {
103
+ const lines = [];
104
+ for (const text of ["command=fetch\n", "agent=git-remote-ops-deno/0.1\n"]) {
105
+ const line = pktLine(encoder.encode(text));
106
+ if (line.isErr())
107
+ return Result.err(line.error);
108
+ lines.push(line.value);
109
+ }
110
+ lines.push(DELIM_PKT);
111
+ for (const text of ["thin-pack\n", "ofs-delta\n"]) {
112
+ const line = pktLine(encoder.encode(text));
113
+ if (line.isErr())
114
+ return Result.err(line.error);
115
+ lines.push(line.value);
116
+ }
117
+ for (const sha of options.wants) {
118
+ const line = pktLine(encoder.encode(`want ${sha}\n`));
119
+ if (line.isErr())
120
+ return Result.err(line.error);
121
+ lines.push(line.value);
122
+ }
123
+ if (options.depth !== undefined) {
124
+ const line = pktLine(encoder.encode(`deepen ${options.depth}\n`));
125
+ if (line.isErr())
126
+ return Result.err(line.error);
127
+ lines.push(line.value);
128
+ }
129
+ if (options.filterSpec !== undefined) {
130
+ const line = pktLine(encoder.encode(`filter ${options.filterSpec}\n`));
131
+ if (line.isErr())
132
+ return Result.err(line.error);
133
+ lines.push(line.value);
134
+ }
135
+ const done = pktLine(encoder.encode("done\n"));
136
+ if (done.isErr())
137
+ return Result.err(done.error);
138
+ lines.push(done.value, FLUSH_PKT);
139
+ return Result.ok(concat(lines));
140
+ }
141
+ /**
142
+ * Demultiplex sideband-framed `git-upload-pack` response bytes into three
143
+ * channel-segregated streams (pack / progress / errors). All payloads from a
144
+ * given channel are concatenated in order.
145
+ *
146
+ * Inputs that lack a sideband framing byte are dropped — callers needing the
147
+ * non-sideband path should use {@link extractPack}.
148
+ */
149
+ export function demuxSideband(body) {
150
+ const packChunks = [];
151
+ const progressChunks = [];
152
+ const errorChunks = [];
153
+ const lines = parsePktLines(body);
154
+ if (lines.isErr())
155
+ return Result.err(lines.error);
156
+ for (const { payload } of lines.value) {
157
+ if (payload === null || payload.length === 0)
158
+ continue;
159
+ const data = payload.subarray(1);
160
+ switch (payload[0]) {
161
+ case BAND_PACK:
162
+ packChunks.push(data);
163
+ break;
164
+ case BAND_PROGRESS:
165
+ progressChunks.push(data);
166
+ break;
167
+ case BAND_ERROR:
168
+ errorChunks.push(data);
169
+ break;
170
+ }
171
+ }
172
+ return Result.ok({
173
+ pack: concat(packChunks),
174
+ progress: concat(progressChunks),
175
+ errors: concat(errorChunks),
176
+ });
177
+ }
178
+ function findFirstDataPktLine(response) {
179
+ let previousOffset = 0;
180
+ const lines = parsePktLines(response);
181
+ if (lines.isErr())
182
+ return Result.err(lines.error);
183
+ for (const { offset, payload } of lines.value) {
184
+ if (payload === null) {
185
+ previousOffset = offset;
186
+ continue;
187
+ }
188
+ const head = decoder.decode(payload.subarray(0, Math.min(payload.length, CONTROL_PREFIX_PEEK)));
189
+ if (CONTROL_PREFIXES.some((prefix) => head.startsWith(prefix))) {
190
+ previousOffset = offset;
191
+ continue;
192
+ }
193
+ return Result.ok({ payload, bodyOffset: previousOffset });
194
+ }
195
+ return Result.err(new UploadPackError({
196
+ reason: "missing-data-pkt-line",
197
+ message: "no data in upload-pack response",
198
+ }));
199
+ }
200
+ /**
201
+ * Pull the packfile bytes out of a `git-upload-pack` response.
202
+ *
203
+ * Walks pkt-lines until it finds the first non-control data line and then
204
+ * picks the right strategy:
205
+ *
206
+ * 1. raw `PACK` signature inline — slice from there to end-of-buffer;
207
+ * 2. sideband byte (1/2/3) prefix — demux and return channel 1;
208
+ * 3. no framed data at all — fall back to a byte-level `PACK` search.
209
+ *
210
+ * @param response Raw HTTP response body.
211
+ * @param diagnostic Optional sink for non-fatal server stderr (channel 3).
212
+ */
213
+ export function extractPack(response, diagnostic) {
214
+ const first = findFirstDataPktLine(response);
215
+ if (first.isErr()) {
216
+ if (first.error._tag === "UploadPackError" && first.error.reason === "missing-data-pkt-line") {
217
+ const idx = indexOfBytes(response, PACK_SIGNATURE);
218
+ if (idx >= 0)
219
+ return Result.ok(response.subarray(idx));
220
+ }
221
+ return Result.err(first.error);
222
+ }
223
+ const { payload, bodyOffset } = first.value;
224
+ if (startsWith(payload, PACK_SIGNATURE)) {
225
+ return Result.ok(response.subarray(bodyOffset + PACK_SIGNATURE.length));
226
+ }
227
+ if (payload[0] === BAND_PACK || payload[0] === BAND_PROGRESS || payload[0] === BAND_ERROR) {
228
+ const data = demuxSideband(response.subarray(bodyOffset));
229
+ if (data.isErr())
230
+ return Result.err(data.error);
231
+ if (data.value.errors.length > 0) {
232
+ diagnostic?.(`server stderr: ${decoder.decode(data.value.errors)}`);
233
+ }
234
+ return Result.ok(data.value.pack);
235
+ }
236
+ return Result.err(new UploadPackError({
237
+ reason: "unrecognized-data-pkt-line",
238
+ message: `unrecognized data pkt-line (starts with ${Array.from(payload.subarray(0, 8)).join(",")})`,
239
+ }));
240
+ }
241
+ function startsWith(bytes, prefix) {
242
+ if (bytes.length < prefix.length)
243
+ return false;
244
+ for (let i = 0; i < prefix.length; i++) {
245
+ if (bytes[i] !== prefix[i])
246
+ return false;
247
+ }
248
+ return true;
249
+ }
250
+ function indexOfBytes(haystack, needle) {
251
+ outer: for (let i = 0; i <= haystack.length - needle.length; i++) {
252
+ for (let j = 0; j < needle.length; j++) {
253
+ if (haystack[i + j] !== needle[j])
254
+ continue outer;
255
+ }
256
+ return i;
257
+ }
258
+ return -1;
259
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @module transport
3
+ *
4
+ * Thin `fetch` wrappers for the two HTTP endpoints the smart-HTTP Git
5
+ * protocol uses:
6
+ *
7
+ * - `GET <repo>/info/refs?service=git-upload-pack` — capability/ref ad.
8
+ * - `POST <repo>/git-upload-pack` — the actual fetch request, body framed
9
+ * by the protocol layer.
10
+ *
11
+ * Both helpers turn errors into {@link TransportError} (never throw) and
12
+ * record timing / byte counts onto the supplied {@link Logger}.
13
+ */
14
+ import * as dntShim from "./_dnt.shims.js";
15
+ import { Result } from "better-result";
16
+ import { TransportError } from "./errors.js";
17
+ import { NULL_LOGGER } from "./logger.js";
18
+ /** Sent verbatim as `User-Agent`. Git servers sometimes log this. */
19
+ const USER_AGENT = "git/2.0 (git-remote-ops-deno)";
20
+ function trimUrl(url) {
21
+ return url.replace(/\/+$/, "");
22
+ }
23
+ function protocolHeaders(options) {
24
+ return options?.protocolVersion === 2 ? { "Git-Protocol": "version=2" } : {};
25
+ }
26
+ async function readResponse(response, method, url) {
27
+ if (!response.ok) {
28
+ return Result.err(new TransportError({
29
+ method,
30
+ url,
31
+ status: response.status,
32
+ statusText: response.statusText,
33
+ message: `${method} failed: ${response.status} ${response.statusText}`,
34
+ }));
35
+ }
36
+ const body = await Result.tryPromise({
37
+ try: () => response.arrayBuffer(),
38
+ catch: (cause) => new TransportError({
39
+ method,
40
+ url,
41
+ message: `${method} failed reading response body`,
42
+ cause,
43
+ }),
44
+ });
45
+ if (body.isErr())
46
+ return Result.err(body.error);
47
+ return Result.ok({
48
+ body: new Uint8Array(body.value),
49
+ status: response.status,
50
+ });
51
+ }
52
+ /**
53
+ * Issue a smart-HTTP GET to `${url}${path}`. Used to fetch the ref/capability
54
+ * advertisement. When `protocolVersion === 2`, sends `Git-Protocol: version=2`
55
+ * so the server responds with a v2 capability ad instead of the legacy format.
56
+ */
57
+ export async function getSmartHttp(url, path, options) {
58
+ const logger = options?.logger ?? NULL_LOGGER;
59
+ const requestUrl = `${trimUrl(url)}${path}`;
60
+ logger.debug(`GET ${path} (protocol=${options?.protocolVersion ?? 0})`);
61
+ const start = performance.now();
62
+ const response = await Result.tryPromise({
63
+ try: () => dntShim.fetch(requestUrl, {
64
+ headers: { "User-Agent": USER_AGENT, ...protocolHeaders(options) },
65
+ }),
66
+ catch: (cause) => new TransportError({
67
+ method: "GET",
68
+ url: requestUrl,
69
+ message: `GET ${path} failed`,
70
+ cause,
71
+ }),
72
+ });
73
+ if (response.isErr())
74
+ return Result.err(response.error);
75
+ const read = await readResponse(response.value, `GET ${path}`, requestUrl);
76
+ const durationMs = performance.now() - start;
77
+ if (read.isOk()) {
78
+ logger.recordHttp({ bytesIn: read.value.body.length, bytesOut: 0, durationMs });
79
+ logger.debug(`GET ${path} -> ${response.value.status}, ${read.value.body.length}B in ${durationMs.toFixed(1)}ms`);
80
+ }
81
+ return read;
82
+ }
83
+ /**
84
+ * POST a `git-upload-pack` request body. Sets the magic content/accept types
85
+ * the upload-pack service expects and forwards the response bytes as-is for
86
+ * the protocol layer to demux.
87
+ *
88
+ * `Connection: close` is set explicitly because some servers (notably
89
+ * `dumb-http-bridge` setups) hang on keep-alive.
90
+ */
91
+ export async function postUploadPack(url, body, options) {
92
+ const logger = options?.logger ?? NULL_LOGGER;
93
+ const requestUrl = `${trimUrl(url)}/git-upload-pack`;
94
+ logger.debug(`POST git-upload-pack (${body.length}B, protocol=${options?.protocolVersion ?? 0})`);
95
+ const start = performance.now();
96
+ const response = await Result.tryPromise({
97
+ try: () => dntShim.fetch(requestUrl, {
98
+ method: "POST",
99
+ body: body,
100
+ headers: {
101
+ "Content-Type": "application/x-git-upload-pack-request",
102
+ "Accept": "application/x-git-upload-pack-result",
103
+ "User-Agent": USER_AGENT,
104
+ "Connection": "close",
105
+ ...protocolHeaders(options),
106
+ },
107
+ }),
108
+ catch: (cause) => new TransportError({
109
+ method: "POST",
110
+ url: requestUrl,
111
+ message: "POST git-upload-pack failed",
112
+ cause,
113
+ }),
114
+ });
115
+ if (response.isErr())
116
+ return Result.err(response.error);
117
+ const read = await readResponse(response.value, "POST git-upload-pack", requestUrl);
118
+ const durationMs = performance.now() - start;
119
+ if (read.isOk()) {
120
+ logger.recordHttp({
121
+ bytesIn: read.value.body.length,
122
+ bytesOut: body.length,
123
+ durationMs,
124
+ });
125
+ logger.debug(`POST git-upload-pack -> ${response.value.status}, ${read.value.body.length}B in ${durationMs.toFixed(1)}ms`);
126
+ }
127
+ return read;
128
+ }
package/esm/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module types
3
+ *
4
+ * Public and internal type vocabulary. Anything that crosses a module
5
+ * boundary lives here so dependents don't end up importing each other's
6
+ * implementation files just to name a shape.
7
+ */
8
+ export {};
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "git-remote-ops",
3
+ "version": "0.1.0",
4
+ "description": "Read-only Git over smart HTTP. No clone, no subprocess.",
5
+ "keywords": [
6
+ "git",
7
+ "smart-http",
8
+ "upload-pack",
9
+ "packfile",
10
+ "partial-clone",
11
+ "shallow-clone"
12
+ ],
13
+ "author": "Goulin Khoge",
14
+ "homepage": "https://github.com/goulinkh/git-remote-ops#readme",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/goulinkh/git-remote-ops.git"
18
+ },
19
+ "license": "MIT",
20
+ "bugs": {
21
+ "url": "https://github.com/goulinkh/git-remote-ops/issues"
22
+ },
23
+ "module": "./esm/index.js",
24
+ "types": "./types/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "import": {
28
+ "types": "./types/index.d.ts",
29
+ "default": "./esm/index.js"
30
+ }
31
+ }
32
+ },
33
+ "scripts": {},
34
+ "bin": {
35
+ "git-remote-ops": "./esm/cli.js"
36
+ },
37
+ "engines": {
38
+ "node": ">=20"
39
+ },
40
+ "dependencies": {
41
+ "better-result": "^2",
42
+ "@deno/shim-deno": "~0.18.0",
43
+ "@deno/shim-crypto": "~0.3.1",
44
+ "undici": "^6.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^20.9.0"
48
+ },
49
+ "_generatedBy": "dnt@dev"
50
+ }
@@ -0,0 +1,16 @@
1
+ import { Deno } from "@deno/shim-deno";
2
+ export { Deno } from "@deno/shim-deno";
3
+ export { crypto, type Crypto, type SubtleCrypto, type AlgorithmIdentifier, type Algorithm, type RsaOaepParams, type BufferSource, type AesCtrParams, type AesCbcParams, type AesGcmParams, type CryptoKey, type KeyAlgorithm, type KeyType, type KeyUsage, type EcdhKeyDeriveParams, type HkdfParams, type HashAlgorithmIdentifier, type Pbkdf2Params, type AesDerivedKeyParams, type HmacImportParams, type JsonWebKey, type RsaOtherPrimesInfo, type KeyFormat, type RsaHashedKeyGenParams, type RsaKeyGenParams, type BigInteger, type EcKeyGenParams, type NamedCurve, type CryptoKeyPair, type AesKeyGenParams, type HmacKeyGenParams, type RsaHashedImportParams, type EcKeyImportParams, type AesKeyAlgorithm, type RsaPssParams, type EcdsaParams } from "@deno/shim-crypto";
4
+ import { fetch, File, FormData, Headers, Request, Response } from "undici";
5
+ export { fetch, File, FormData, Headers, Request, Response, type BodyInit, type HeadersInit, type ReferrerPolicy, type RequestInit, type RequestCache, type RequestMode, type RequestRedirect, type ResponseInit } from "undici";
6
+ export declare const dntGlobalThis: Omit<typeof globalThis, "fetch" | "File" | "FormData" | "Headers" | "Request" | "Response" | "crypto" | "Deno"> & {
7
+ Deno: typeof Deno;
8
+ crypto: import("@deno/shim-crypto").Crypto;
9
+ fetch: typeof fetch;
10
+ File: typeof File;
11
+ FormData: typeof FormData;
12
+ Headers: typeof Headers;
13
+ Request: typeof Request;
14
+ Response: typeof Response;
15
+ };
16
+ //# sourceMappingURL=_dnt.shims.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_dnt.shims.d.ts","sourceRoot":"","sources":["../src/_dnt.shims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,KAAK,uBAAuB,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,qBAAqB,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrvB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC;AAYjO,eAAO,MAAM,aAAa;;;;;;;;;CAA2C,CAAC"}
package/types/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @module client
3
+ *
4
+ * High-level read-only Git remote client. {@link RemoteGit} composes the
5
+ * transport, protocol, and pack layers behind a small surface: discover a
6
+ * server, ask for commits/trees/blobs, get them back as decoded objects.
7
+ *
8
+ * The client caches:
9
+ * - a single {@link ServerProfile} (capabilities + ref advertisement);
10
+ * - every object materialized by any prior fetch, in a process-lifetime
11
+ * map. Subsequent fetches dedupe wants against this map so multi-step
12
+ * workflows (commit → tree → blob) only pay for what's new.
13
+ */
14
+ import { Result } from "better-result";
15
+ import type { GitRemoteOpsError } from "./errors.js";
16
+ import { Logger } from "./logger.js";
17
+ import type { CommitInfo, FetchCommitOptions, GitObject, RemoteGitOptions, ServerProfile, TreeEntry } from "./types.js";
18
+ /**
19
+ * Read-only Git remote client over smart HTTP.
20
+ *
21
+ * One instance corresponds to one upstream `url`. Reuse it across operations
22
+ * so the cached profile and object store can do their job; throw it away
23
+ * when you're done with that remote.
24
+ */
25
+ export declare class RemoteGit {
26
+ readonly url: string;
27
+ readonly logger: Logger;
28
+ private profile;
29
+ private objects;
30
+ private snapshotCommits;
31
+ private diagnostic?;
32
+ private transportLogger;
33
+ private packLogger;
34
+ /**
35
+ * @param url Base repository URL (e.g. `https://github.com/owner/repo.git`).
36
+ * Trailing slashes are stripped.
37
+ * @param options Optional logger / diagnostic sink. When neither is given, a
38
+ * silent logger is used. Passing `diagnostic` alone gets you a `debug`
39
+ * logger routed to the diagnostic function.
40
+ */
41
+ constructor(url: string, options?: RemoteGitOptions);
42
+ /**
43
+ * Fetch and cache the server's ref/capability advertisement.
44
+ *
45
+ * Issues both a v0/v1 GET and a v2 GET. The v0 response is the source of
46
+ * truth for refs and base capabilities; if the v2 response advertises
47
+ * `version=2`, those caps are merged in and `protocolVersion` flips to 2.
48
+ * Subsequent client calls hit the cached profile until `discover()` runs again.
49
+ */
50
+ discover(): Promise<Result<ServerProfile, GitRemoteOpsError>>;
51
+ /**
52
+ * Confirm what the server *actually* honours, not just what it advertises.
53
+ *
54
+ * Some servers advertise `filter` but ignore it; others advertise `shallow`
55
+ * but reject deepen requests. We send minimal-cost shallow fetches with
56
+ * `blob:none` and `tree:0` filters and look at the returned pack to decide.
57
+ * Sets `supportsFilterBlobNone` / `supportsFilterTree0` on the cached profile.
58
+ *
59
+ * @param verbose Emit raw probe outcomes through {@link RemoteGitOptions.diagnostic}.
60
+ */
61
+ probe(verbose?: boolean): Promise<Result<ServerProfile, GitRemoteOpsError>>;
62
+ /** Return a snapshot of the advertised refs (name → sha). Triggers `discover()` if needed. */
63
+ lsRefs(): Promise<Result<Map<string, string>, GitRemoteOpsError>>;
64
+ /**
65
+ * Resolve `ref` to a 40-char hex sha against the cached advertisement.
66
+ *
67
+ * Tries the literal name, then `refs/heads/<ref>`, then `refs/tags/<ref>`.
68
+ * A 40-char hex input is accepted as-is even when it isn't in the ad — the
69
+ * server may still serve it as a `want`.
70
+ */
71
+ resolveRef(ref: string): Promise<Result<string, GitRemoteOpsError>>;
72
+ /**
73
+ * Fetch and decode a single commit reachable from `ref`.
74
+ *
75
+ * `options.depth` defaults to deep fetch; pass `1` for a snapshot. Filters
76
+ * are silently dropped if the server doesn't support them — we log an
77
+ * info-level message in that case.
78
+ */
79
+ fetchCommit(ref: string, options?: FetchCommitOptions): Promise<Result<{
80
+ commit: CommitInfo;
81
+ sha: string;
82
+ }, GitRemoteOpsError>>;
83
+ /** Fetch a blob by sha and return its raw contents. */
84
+ fetchBlob(sha: string): Promise<Result<Uint8Array, GitRemoteOpsError>>;
85
+ /**
86
+ * Fetch the commit at `ref` *and* its root tree from a single snapshot pack.
87
+ *
88
+ * Forces `parseFull: true` so the tree object — which the commit references
89
+ * but doesn't `want` directly — ends up in the local object store. Useful
90
+ * for "list files at HEAD" without a clone.
91
+ */
92
+ fetchTreeForCommit(ref: string, options?: FetchCommitOptions): Promise<Result<{
93
+ commit: CommitInfo;
94
+ commitSha: string;
95
+ entries: TreeEntry[];
96
+ }, GitRemoteOpsError>>;
97
+ /** Fetch and decode a single tree by sha. */
98
+ fetchTree(sha: string): Promise<Result<TreeEntry[], GitRemoteOpsError>>;
99
+ /** Look up an already-materialized object by sha. Does not fetch on miss. */
100
+ getObject(sha: string): GitObject | undefined;
101
+ private fetchObjects;
102
+ private probeFilter;
103
+ private fetchPack;
104
+ private normalizeWants;
105
+ private pickProbeSha;
106
+ private log;
107
+ }
108
+ //# sourceMappingURL=client.d.ts.map