nano-git 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 (227) hide show
  1. package/README.md +407 -0
  2. package/dist/backend/file-backend.d.mts +26 -0
  3. package/dist/backend/file-backend.mjs +83 -0
  4. package/dist/backend/file.d.mts +2 -0
  5. package/dist/backend/file.mjs +2 -0
  6. package/dist/backend/index.d.mts +2 -0
  7. package/dist/backend/index.mjs +1 -0
  8. package/dist/backend/memory-backend.d.mts +25 -0
  9. package/dist/backend/memory-backend.mjs +33 -0
  10. package/dist/backend/memory.d.mts +2 -0
  11. package/dist/backend/memory.mjs +2 -0
  12. package/dist/backend/types.d.mts +90 -0
  13. package/dist/core/errors.d.mts +124 -0
  14. package/dist/core/errors.mjs +168 -0
  15. package/dist/core/hash-digest.d.mts +35 -0
  16. package/dist/core/hash-digest.mjs +50 -0
  17. package/dist/core/hash-file.d.mts +20 -0
  18. package/dist/core/hash-file.mjs +27 -0
  19. package/dist/core/hash-path.d.mts +17 -0
  20. package/dist/core/hash-path.mjs +35 -0
  21. package/dist/core/types/odb.d.mts +63 -0
  22. package/dist/core/types/refs.d.mts +140 -0
  23. package/dist/core/types/refs.mjs +19 -0
  24. package/dist/core/types/shallow.d.mts +52 -0
  25. package/dist/core/types.d.mts +154 -0
  26. package/dist/core/types.mjs +43 -0
  27. package/dist/errors.d.mts +2 -0
  28. package/dist/errors.mjs +2 -0
  29. package/dist/hash-file.d.mts +2 -0
  30. package/dist/hash-file.mjs +2 -0
  31. package/dist/index.d.mts +16 -0
  32. package/dist/index.mjs +14 -0
  33. package/dist/objects/author.d.mts +25 -0
  34. package/dist/objects/author.mjs +45 -0
  35. package/dist/objects/blob.d.mts +15 -0
  36. package/dist/objects/blob.mjs +20 -0
  37. package/dist/objects/codec.d.mts +46 -0
  38. package/dist/objects/codec.mjs +84 -0
  39. package/dist/objects/commit.d.mts +26 -0
  40. package/dist/objects/commit.mjs +160 -0
  41. package/dist/objects/index.d.mts +8 -0
  42. package/dist/objects/index.mjs +8 -0
  43. package/dist/objects/raw.d.mts +85 -0
  44. package/dist/objects/raw.mjs +111 -0
  45. package/dist/objects/tag.d.mts +26 -0
  46. package/dist/objects/tag.mjs +148 -0
  47. package/dist/objects/tree.d.mts +22 -0
  48. package/dist/objects/tree.mjs +66 -0
  49. package/dist/odb/file-utils.mjs +136 -0
  50. package/dist/odb/file.d.mts +22 -0
  51. package/dist/odb/file.mjs +66 -0
  52. package/dist/odb/memory.d.mts +22 -0
  53. package/dist/odb/memory.mjs +54 -0
  54. package/dist/pack/composite-store.d.mts +76 -0
  55. package/dist/pack/composite-store.mjs +133 -0
  56. package/dist/pack/constants.mjs +48 -0
  57. package/dist/pack/crc32.mjs +38 -0
  58. package/dist/pack/delta-apply.d.mts +21 -0
  59. package/dist/pack/delta-apply.mjs +71 -0
  60. package/dist/pack/delta-create.d.mts +28 -0
  61. package/dist/pack/delta-create.mjs +151 -0
  62. package/dist/pack/index.d.mts +16 -0
  63. package/dist/pack/index.mjs +13 -0
  64. package/dist/pack/object-header.d.mts +36 -0
  65. package/dist/pack/object-header.mjs +72 -0
  66. package/dist/pack/ofs-delta-offset.d.mts +35 -0
  67. package/dist/pack/ofs-delta-offset.mjs +59 -0
  68. package/dist/pack/pack-builder-types.d.mts +19 -0
  69. package/dist/pack/pack-builder.d.mts +52 -0
  70. package/dist/pack/pack-builder.mjs +80 -0
  71. package/dist/pack/pack-encoding.mjs +76 -0
  72. package/dist/pack/pack-index-reader.d.mts +57 -0
  73. package/dist/pack/pack-index-reader.mjs +90 -0
  74. package/dist/pack/pack-index-types.d.mts +16 -0
  75. package/dist/pack/pack-index-writer.d.mts +45 -0
  76. package/dist/pack/pack-index-writer.mjs +106 -0
  77. package/dist/pack/pack-reader-resolver.mjs +104 -0
  78. package/dist/pack/pack-reader-types.d.mts +31 -0
  79. package/dist/pack/pack-reader-types.mjs +22 -0
  80. package/dist/pack/pack-reader-utils.mjs +61 -0
  81. package/dist/pack/pack-reader.d.mts +81 -0
  82. package/dist/pack/pack-reader.mjs +171 -0
  83. package/dist/pack/pack-store-loader.mjs +79 -0
  84. package/dist/pack/pack-store-types.d.mts +16 -0
  85. package/dist/pack/pack-store.d.mts +55 -0
  86. package/dist/pack/pack-store.mjs +114 -0
  87. package/dist/pack/pack-writer.mjs +96 -0
  88. package/dist/pack/varint.d.mts +34 -0
  89. package/dist/pack/varint.mjs +57 -0
  90. package/dist/refs/file.d.mts +6 -0
  91. package/dist/refs/file.mjs +222 -0
  92. package/dist/refs/fs-utils.mjs +30 -0
  93. package/dist/refs/memory.d.mts +14 -0
  94. package/dist/refs/memory.mjs +104 -0
  95. package/dist/refs/names.d.mts +57 -0
  96. package/dist/refs/names.mjs +80 -0
  97. package/dist/refs/resolve.d.mts +33 -0
  98. package/dist/refs/resolve.mjs +55 -0
  99. package/dist/refs/shallow/file.d.mts +17 -0
  100. package/dist/refs/shallow/file.mjs +61 -0
  101. package/dist/refs/shallow/memory.d.mts +18 -0
  102. package/dist/refs/shallow/memory.mjs +33 -0
  103. package/dist/repository/core.d.mts +3 -0
  104. package/dist/repository/core.mjs +2 -0
  105. package/dist/repository/create.d.mts +22 -0
  106. package/dist/repository/create.mjs +43 -0
  107. package/dist/repository/file.d.mts +43 -0
  108. package/dist/repository/file.mjs +82 -0
  109. package/dist/repository/import/import-glob.mjs +44 -0
  110. package/dist/repository/import/import-plan-builder.mjs +625 -0
  111. package/dist/repository/import/import-session-types.d.mts +280 -0
  112. package/dist/repository/import/import-session.mjs +96 -0
  113. package/dist/repository/import/import-view.mjs +133 -0
  114. package/dist/repository/memory.d.mts +17 -0
  115. package/dist/repository/memory.mjs +33 -0
  116. package/dist/repository/ops/fetch-operations.mjs +20 -0
  117. package/dist/repository/ops/fetch-types.d.mts +82 -0
  118. package/dist/repository/ops/fetch-url.mjs +82 -0
  119. package/dist/repository/ops/fs-object-operations.mjs +31 -0
  120. package/dist/repository/ops/maintenance-operations.mjs +62 -0
  121. package/dist/repository/ops/maintenance-types.d.mts +42 -0
  122. package/dist/repository/ops/object-operations.mjs +65 -0
  123. package/dist/repository/ops/object-types.d.mts +109 -0
  124. package/dist/repository/ops/push-operations.mjs +16 -0
  125. package/dist/repository/ops/push-resolution.mjs +17 -0
  126. package/dist/repository/ops/push-types.d.mts +72 -0
  127. package/dist/repository/ops/push-url.mjs +45 -0
  128. package/dist/repository/ops/reachability.mjs +60 -0
  129. package/dist/repository/ops/ref-operations.mjs +86 -0
  130. package/dist/repository/ops/ref-types.d.mts +70 -0
  131. package/dist/repository/tree/tree-patch.d.mts +64 -0
  132. package/dist/repository/tree/tree-patch.mjs +268 -0
  133. package/dist/repository/tree/tree-walk.d.mts +46 -0
  134. package/dist/repository/tree/tree-walk.mjs +65 -0
  135. package/dist/repository/tree/tree-writer.mjs +68 -0
  136. package/dist/repository/types.d.mts +36 -0
  137. package/dist/sha1.d.mts +4 -0
  138. package/dist/sha1.mjs +4 -0
  139. package/dist/transport/client/receive-pack/http.d.mts +33 -0
  140. package/dist/transport/client/receive-pack/http.mjs +99 -0
  141. package/dist/transport/client/receive-pack/push-error.d.mts +23 -0
  142. package/dist/transport/client/receive-pack/push-error.mjs +32 -0
  143. package/dist/transport/client/receive-pack/push-pack-plan.d.mts +28 -0
  144. package/dist/transport/client/receive-pack/push-pack-plan.mjs +60 -0
  145. package/dist/transport/client/receive-pack/push-policy.d.mts +19 -0
  146. package/dist/transport/client/receive-pack/push-policy.mjs +64 -0
  147. package/dist/transport/client/receive-pack/push-ref-plan.d.mts +45 -0
  148. package/dist/transport/client/receive-pack/push-ref-plan.mjs +108 -0
  149. package/dist/transport/client/receive-pack/push-report.d.mts +28 -0
  150. package/dist/transport/client/receive-pack/push-report.mjs +84 -0
  151. package/dist/transport/client/receive-pack/push-request-plan.mjs +52 -0
  152. package/dist/transport/client/receive-pack/push.d.mts +32 -0
  153. package/dist/transport/client/receive-pack/push.mjs +97 -0
  154. package/dist/transport/client/receive-pack/request.d.mts +39 -0
  155. package/dist/transport/client/receive-pack/request.mjs +46 -0
  156. package/dist/transport/client/receive-pack/response.d.mts +26 -0
  157. package/dist/transport/client/receive-pack/response.mjs +52 -0
  158. package/dist/transport/client/receive-pack/result.d.mts +34 -0
  159. package/dist/transport/client/receive-pack/result.mjs +100 -0
  160. package/dist/transport/client/upload-pack/capability-advertisement.d.mts +56 -0
  161. package/dist/transport/client/upload-pack/capability-advertisement.mjs +130 -0
  162. package/dist/transport/client/upload-pack/fetch.d.mts +109 -0
  163. package/dist/transport/client/upload-pack/fetch.mjs +392 -0
  164. package/dist/transport/client/upload-pack/http.d.mts +29 -0
  165. package/dist/transport/client/upload-pack/http.mjs +79 -0
  166. package/dist/transport/client/upload-pack/ls-refs.d.mts +75 -0
  167. package/dist/transport/client/upload-pack/ls-refs.mjs +150 -0
  168. package/dist/transport/client/upload-pack/object-info.d.mts +65 -0
  169. package/dist/transport/client/upload-pack/object-info.mjs +111 -0
  170. package/dist/transport/client/upload-pack/types.d.mts +153 -0
  171. package/dist/transport/http/index.d.mts +3 -0
  172. package/dist/transport/http/index.mjs +2 -0
  173. package/dist/transport/http/smart-http.d.mts +46 -0
  174. package/dist/transport/http/smart-http.mjs +176 -0
  175. package/dist/transport/http/types.d.mts +27 -0
  176. package/dist/transport/index.d.mts +9 -0
  177. package/dist/transport/index.mjs +8 -0
  178. package/dist/transport/protocol/object-graph.d.mts +63 -0
  179. package/dist/transport/protocol/object-graph.mjs +149 -0
  180. package/dist/transport/protocol/pkt-line.d.mts +109 -0
  181. package/dist/transport/protocol/pkt-line.mjs +195 -0
  182. package/dist/transport/protocol/ref-advertisement.mjs +185 -0
  183. package/dist/transport/protocol/ref-collection.d.mts +38 -0
  184. package/dist/transport/protocol/ref-collection.mjs +63 -0
  185. package/dist/transport/protocol/ref-match.d.mts +39 -0
  186. package/dist/transport/protocol/ref-match.mjs +42 -0
  187. package/dist/transport/protocol/refspec.d.mts +44 -0
  188. package/dist/transport/protocol/refspec.mjs +79 -0
  189. package/dist/transport/protocol/side-band.d.mts +65 -0
  190. package/dist/transport/protocol/side-band.mjs +142 -0
  191. package/dist/transport/protocol/transport-capabilities.mjs +46 -0
  192. package/dist/transport/protocol/types.d.mts +148 -0
  193. package/dist/transport/protocol/update-refs.d.mts +68 -0
  194. package/dist/transport/protocol/update-refs.mjs +126 -0
  195. package/dist/transport/receive-pack.d.mts +11 -0
  196. package/dist/transport/receive-pack.mjs +11 -0
  197. package/dist/transport/server/receive-pack/advertise.d.mts +28 -0
  198. package/dist/transport/server/receive-pack/advertise.mjs +88 -0
  199. package/dist/transport/server/receive-pack/handler.d.mts +30 -0
  200. package/dist/transport/server/receive-pack/handler.mjs +156 -0
  201. package/dist/transport/server/receive-pack/index.d.mts +6 -0
  202. package/dist/transport/server/receive-pack/index.mjs +6 -0
  203. package/dist/transport/server/receive-pack/parse.d.mts +17 -0
  204. package/dist/transport/server/receive-pack/parse.mjs +80 -0
  205. package/dist/transport/server/receive-pack/report-status.mjs +64 -0
  206. package/dist/transport/server/receive-pack/service.d.mts +41 -0
  207. package/dist/transport/server/receive-pack/service.mjs +39 -0
  208. package/dist/transport/server/receive-pack/types.d.mts +56 -0
  209. package/dist/transport/server/receive-pack/types.mjs +25 -0
  210. package/dist/transport/server/receive-pack/unpack.mjs +119 -0
  211. package/dist/transport/server/upload-pack/advertise.d.mts +20 -0
  212. package/dist/transport/server/upload-pack/advertise.mjs +30 -0
  213. package/dist/transport/server/upload-pack/command.d.mts +43 -0
  214. package/dist/transport/server/upload-pack/command.mjs +56 -0
  215. package/dist/transport/server/upload-pack/fetch.d.mts +43 -0
  216. package/dist/transport/server/upload-pack/fetch.mjs +217 -0
  217. package/dist/transport/server/upload-pack/index.d.mts +7 -0
  218. package/dist/transport/server/upload-pack/index.mjs +7 -0
  219. package/dist/transport/server/upload-pack/ls-refs.d.mts +38 -0
  220. package/dist/transport/server/upload-pack/ls-refs.mjs +113 -0
  221. package/dist/transport/server/upload-pack/service.d.mts +40 -0
  222. package/dist/transport/server/upload-pack/service.mjs +51 -0
  223. package/dist/transport/server/upload-pack/types.d.mts +11 -0
  224. package/dist/transport/server/upload-pack/types.mjs +21 -0
  225. package/dist/transport/upload-pack.d.mts +7 -0
  226. package/dist/transport/upload-pack.mjs +6 -0
  227. package/package.json +98 -0
@@ -0,0 +1,150 @@
1
+ import { GitError } from "../../../core/errors.mjs";
2
+ import { sha1 } from "../../../core/types.mjs";
3
+ import { parsePktLines } from "../../protocol/pkt-line.mjs";
4
+ //#region src/transport/client/upload-pack/ls-refs.ts
5
+ /**
6
+ * v2 ls-refs 命令
7
+ *
8
+ * 在 Git Wire 协议 v2 中,ls-refs 替代了 v1 的 ref advertisement。
9
+ * 服务端通过独立的 `ls-refs` 命令返回引用列表。
10
+ *
11
+ * 请求格式:
12
+ * ```
13
+ * command=ls-refs\n
14
+ * agent=nano-git/0.1\n
15
+ * 0001
16
+ * symrefs\n
17
+ * peel\n
18
+ * ref-prefix refs/heads/\n
19
+ * 0000
20
+ * ```
21
+ *
22
+ * 响应格式:
23
+ * ```
24
+ * <oid> <refname>[ <attr>...]\n
25
+ * ...
26
+ * 0000
27
+ * ```
28
+ *
29
+ * @see https://git-scm.com/docs/protocol-v2#_ls_refs
30
+ */
31
+ /**
32
+ * ls-refs 命令错误
33
+ */
34
+ var LsRefsError = class extends GitError {
35
+ constructor(message) {
36
+ super(`ls-refs error: ${message}`);
37
+ this.name = "LsRefsError";
38
+ }
39
+ };
40
+ /**
41
+ * 执行 ls-refs 命令
42
+ *
43
+ * @param transport - v2 传输接口
44
+ * @param options - ls-refs 请求选项
45
+ * @returns 解析后的 ref 条目列表
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const entries = await lsRefs(transport, {
50
+ * symrefs: true,
51
+ * peel: true,
52
+ * refPrefixes: ["refs/heads/"],
53
+ * });
54
+ * ```
55
+ */
56
+ async function lsRefs(transport, options) {
57
+ const args = [];
58
+ if (options?.symrefs) args.push("symrefs");
59
+ if (options?.peel) args.push("peel");
60
+ if (options?.unborn) args.push("unborn");
61
+ if (options?.refPrefixes) for (const prefix of options.refPrefixes) args.push(`ref-prefix ${prefix}`);
62
+ return parseLsRefsResponse(await transport.command("ls-refs", args));
63
+ }
64
+ /**
65
+ * 解析 ls-refs 响应
66
+ *
67
+ * 从原始 Buffer 中解析 ls-refs 条目。
68
+ *
69
+ * @param data - ls-refs 命令的原始响应数据
70
+ * @returns 解析后的 ref 条目列表
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * const entries = parseLsRefsResponse(response);
75
+ * console.log(entries[0].refname); // "refs/heads/main"
76
+ * ```
77
+ */
78
+ function parseLsRefsResponse(data) {
79
+ const lines = parsePktLines(data);
80
+ const entries = [];
81
+ for (const line of lines) {
82
+ if (line.type !== "data") continue;
83
+ const text = line.payload.toString("utf-8").trim();
84
+ if (text.length === 0) continue;
85
+ const spaceIdx = text.indexOf(" ");
86
+ if (spaceIdx === -1) continue;
87
+ const oid = text.substring(0, spaceIdx);
88
+ const parts = text.substring(spaceIdx + 1).trim().split(" ");
89
+ const entry = {
90
+ oid,
91
+ refname: parts[0]
92
+ };
93
+ for (let i = 1; i < parts.length; i++) {
94
+ const attr = parts[i];
95
+ if (attr.startsWith("symref-target:")) entry.symrefTarget = attr.substring(14);
96
+ else if (attr.startsWith("peeled:")) entry.peeled = attr.substring(7);
97
+ }
98
+ entries.push(entry);
99
+ }
100
+ return entries;
101
+ }
102
+ /**
103
+ * 将 v2 ls-refs 结果转换为 v1 兼容的 RefAdvertisement
104
+ *
105
+ * 用于 ImportSession 的透明升级:v2 获取 refs 后,
106
+ * 包装为 v1 的 RefAdvertisement 格式,使上游代码无需改动。
107
+ *
108
+ * @param entries - ls-refs 返回的 ref 条目
109
+ * @returns v1 兼容的 RefAdvertisement
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * const entries = await lsRefs(transport);
114
+ * const adv = lsRefsToRefAdvertisement(entries);
115
+ * // 可传递给 ImportSession
116
+ * ```
117
+ */
118
+ function lsRefsToRefAdvertisement(entries) {
119
+ const refs = [];
120
+ let defaultBranch;
121
+ const peeledMap = /* @__PURE__ */ new Map();
122
+ for (const entry of entries) if (entry.peeled) {
123
+ const baseName = entry.refname.endsWith("^{}") ? entry.refname.slice(0, -3) : entry.refname;
124
+ peeledMap.set(baseName, entry.peeled);
125
+ }
126
+ for (const entry of entries) {
127
+ if (entry.oid === "unborn") continue;
128
+ if (entry.refname.endsWith("^{}")) continue;
129
+ const ref = {
130
+ hash: sha1(entry.oid),
131
+ name: entry.refname
132
+ };
133
+ if (entry.symrefTarget) ref.symrefTarget = entry.symrefTarget;
134
+ const peeled = peeledMap.get(entry.refname);
135
+ if (peeled) ref.peeled = sha1(peeled);
136
+ refs.push(ref);
137
+ if (entry.refname === "HEAD" && entry.symrefTarget) defaultBranch = entry.symrefTarget;
138
+ }
139
+ if (!defaultBranch && refs.length > 0) {
140
+ const mainBranch = refs.find((r) => r.name === "refs/heads/main" || r.name === "refs/heads/master");
141
+ if (mainBranch) defaultBranch = mainBranch.name;
142
+ }
143
+ return {
144
+ capabilities: {},
145
+ refs,
146
+ defaultBranch
147
+ };
148
+ }
149
+ //#endregion
150
+ export { LsRefsError, lsRefs, lsRefsToRefAdvertisement, parseLsRefsResponse };
@@ -0,0 +1,65 @@
1
+ import { GitError } from "../../../core/errors.mjs";
2
+ import { V2GitServiceTransport } from "./types.mjs";
3
+
4
+ //#region src/transport/client/upload-pack/object-info.d.ts
5
+ /**
6
+ * object-info 命令错误
7
+ */
8
+ declare class ObjectInfoError extends GitError {
9
+ constructor(message: string);
10
+ }
11
+ /**
12
+ * object-info 查询结果条目
13
+ */
14
+ interface ObjectInfoResult {
15
+ readonly oid: string;
16
+ readonly size?: number;
17
+ }
18
+ /**
19
+ * object-info 查询响应
20
+ */
21
+ interface ObjectInfoQueryResult {
22
+ readonly attrs: string[];
23
+ readonly objects: ObjectInfoResult[];
24
+ }
25
+ /**
26
+ * 执行 object-info 命令
27
+ *
28
+ * 批量查询远端对象的元数据(如 size),无需下载对象内容。
29
+ *
30
+ * @param transport - v2 传输接口
31
+ * @param oids - 要查询的 OID 列表
32
+ * @returns 查询结果
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const result = await objectInfo(transport, [
37
+ * "95d09f2b10159347eece71399a7e2e907ea3df4f",
38
+ * ]);
39
+ * console.log(result.objects[0]?.size); // 文件大小(字节)
40
+ * ```
41
+ */
42
+ declare function objectInfo(transport: V2GitServiceTransport, oids: string[]): Promise<ObjectInfoQueryResult>;
43
+ /**
44
+ * 解析 object-info 响应
45
+ *
46
+ * 格式:
47
+ * ```
48
+ * size\n
49
+ * <oid1> <size1>\n
50
+ * <oid2> <size2>\n
51
+ * 0000
52
+ * ```
53
+ *
54
+ * @param data - 原始响应数据
55
+ * @returns 解析后的查询结果
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * const result = parseObjectInfoResponse(response);
60
+ * console.log(result.attrs); // ["size"]
61
+ * ```
62
+ */
63
+ declare function parseObjectInfoResponse(data: Buffer): ObjectInfoQueryResult;
64
+ //#endregion
65
+ export { ObjectInfoError, ObjectInfoQueryResult, ObjectInfoResult, objectInfo, parseObjectInfoResponse };
@@ -0,0 +1,111 @@
1
+ import { GitError } from "../../../core/errors.mjs";
2
+ import { parsePktLines } from "../../protocol/pkt-line.mjs";
3
+ //#region src/transport/client/upload-pack/object-info.ts
4
+ /**
5
+ * v2 object-info 命令
6
+ *
7
+ * 在 Git Wire 协议 v2 中,object-info 命令用于批量查询对象信息(如 size),
8
+ * 而不需要实际获取对象内容。主要用于 partial clone 场景。
9
+ *
10
+ * 请求格式:
11
+ * ```
12
+ * command=object-info\n
13
+ * 0001
14
+ * size\n
15
+ * oid <oid1>\n
16
+ * oid <oid2>\n
17
+ * 0000
18
+ * ```
19
+ *
20
+ * 响应格式:
21
+ * ```
22
+ * size\n
23
+ * <oid1> <size1>\n
24
+ * <oid2> <size2>\n
25
+ * 0000
26
+ * ```
27
+ *
28
+ * @see https://git-scm.com/docs/protocol-v2#_object_info
29
+ */
30
+ /**
31
+ * object-info 命令错误
32
+ */
33
+ var ObjectInfoError = class extends GitError {
34
+ constructor(message) {
35
+ super(`object-info error: ${message}`);
36
+ this.name = "ObjectInfoError";
37
+ }
38
+ };
39
+ /**
40
+ * 执行 object-info 命令
41
+ *
42
+ * 批量查询远端对象的元数据(如 size),无需下载对象内容。
43
+ *
44
+ * @param transport - v2 传输接口
45
+ * @param oids - 要查询的 OID 列表
46
+ * @returns 查询结果
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * const result = await objectInfo(transport, [
51
+ * "95d09f2b10159347eece71399a7e2e907ea3df4f",
52
+ * ]);
53
+ * console.log(result.objects[0]?.size); // 文件大小(字节)
54
+ * ```
55
+ */
56
+ async function objectInfo(transport, oids) {
57
+ if (oids.length === 0) throw new ObjectInfoError("No OIDs specified for object-info");
58
+ const args = ["size"];
59
+ for (const oid of oids) args.push(`oid ${oid}`);
60
+ return parseObjectInfoResponse(await transport.command("object-info", args));
61
+ }
62
+ /**
63
+ * 解析 object-info 响应
64
+ *
65
+ * 格式:
66
+ * ```
67
+ * size\n
68
+ * <oid1> <size1>\n
69
+ * <oid2> <size2>\n
70
+ * 0000
71
+ * ```
72
+ *
73
+ * @param data - 原始响应数据
74
+ * @returns 解析后的查询结果
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const result = parseObjectInfoResponse(response);
79
+ * console.log(result.attrs); // ["size"]
80
+ * ```
81
+ */
82
+ function parseObjectInfoResponse(data) {
83
+ const pktLines = parsePktLines(data);
84
+ const objects = [];
85
+ let attrs = [];
86
+ for (const line of pktLines) {
87
+ if (line.type !== "data") continue;
88
+ const text = line.payload.toString("utf-8").trim();
89
+ if (text.length === 0) continue;
90
+ if (attrs.length === 0) {
91
+ attrs = text.split(" ");
92
+ continue;
93
+ }
94
+ const spaceIdx = text.indexOf(" ");
95
+ if (spaceIdx === -1) objects.push({ oid: text });
96
+ else {
97
+ const oid = text.substring(0, spaceIdx);
98
+ const sizeStr = text.substring(spaceIdx + 1).trim();
99
+ objects.push({
100
+ oid,
101
+ size: parseInt(sizeStr, 10)
102
+ });
103
+ }
104
+ }
105
+ return {
106
+ attrs,
107
+ objects
108
+ };
109
+ }
110
+ //#endregion
111
+ export { ObjectInfoError, objectInfo, parseObjectInfoResponse };
@@ -0,0 +1,153 @@
1
+ //#region src/transport/client/upload-pack/types.d.ts
2
+ /**
3
+ * Git Wire 协议 v2 类型定义
4
+ *
5
+ * 定义了协议 v2 特有的类型:能力广告、命令式传输接口等。
6
+ * 协议无关的共享类型见 protocol/types.ts。
7
+ */
8
+ /**
9
+ * v2 能力广告中的单个命令条目
10
+ *
11
+ * 表示服务端广告的 v2 命令及附加特性。
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const cmd: V2CommandEntry = {
16
+ * name: "fetch",
17
+ * features: ["shallow", "ref-in-want"],
18
+ * };
19
+ * ```
20
+ */
21
+ interface V2CommandEntry {
22
+ /** 命令名称,如 "ls-refs"、"fetch"、"push"、"object-info" */
23
+ readonly name: string;
24
+ /** 命令附加特性列表(在 capability 值中声明) */
25
+ readonly features: string[];
26
+ }
27
+ /**
28
+ * v2 能力广告(服务端响应)
29
+ *
30
+ * 对应协议 v2 的能力广告格式:
31
+ * ```
32
+ * version 2\n
33
+ * ls-refs\n
34
+ * fetch=shallow ref-in-want\n
35
+ * push\n
36
+ * object-info\n
37
+ * agent=nano-git/0.1\n
38
+ * 0000
39
+ * ```
40
+ */
41
+ interface V2CapabilityAdvertisement {
42
+ /** 服务端能力键值对 */
43
+ readonly capabilities: Record<string, string | true>;
44
+ /** 服务端支持的 v2 命令列表 */
45
+ readonly commands: V2CommandEntry[];
46
+ /** 服务端 agent 字符串 */
47
+ readonly agent?: string;
48
+ }
49
+ /**
50
+ * v2 Git 服务传输接口
51
+ *
52
+ * 与 v1 的 GitServiceTransport 不同,v2 是命令式的。
53
+ * - advertise() 只返回能力广告,不含 refs
54
+ * - command() 发送单个命令并返回原始响应
55
+ */
56
+ interface V2GitServiceTransport {
57
+ /** 获取能力广告 */
58
+ advertise(): Promise<V2CapabilityAdvertisement>;
59
+ /**
60
+ * 执行 v2 命令
61
+ *
62
+ * @param command - 命令名称,如 "ls-refs"、"fetch"
63
+ * @param args - 命令参数列表
64
+ * @param capabilities - 本次请求携带的能力列表(不含 agent)
65
+ * @param body - 额外的原始 body 数据(如 push 的 packfile)
66
+ */
67
+ command(command: string, args?: string[], capabilities?: string[], body?: Buffer): Promise<Buffer>;
68
+ }
69
+ /**
70
+ * ls-refs 输出条目
71
+ *
72
+ * 对应 v2 ls-refs 响应中的单行 ref。
73
+ * ```
74
+ * <obj-id> SP <refname> [SP <ref-attribute> ...] LF
75
+ * ```
76
+ */
77
+ interface LsRefsEntry {
78
+ /** 对象哈希,unborn 分支时为 "unborn" */
79
+ readonly oid: string;
80
+ /** 引用全名 */
81
+ readonly refname: string;
82
+ /** 符号引用目标(如有) */
83
+ readonly symrefTarget?: string;
84
+ /** peeled 对象哈希(如有) */
85
+ readonly peeled?: string;
86
+ }
87
+ /**
88
+ * v2 fetch 请求参数
89
+ */
90
+ interface V2FetchRequest {
91
+ readonly wants: string[];
92
+ readonly haves?: string[];
93
+ readonly done?: boolean;
94
+ readonly wantRefs?: string[];
95
+ readonly thinPack?: boolean;
96
+ readonly noProgress?: boolean;
97
+ readonly includeTag?: boolean;
98
+ readonly ofsDelta?: boolean;
99
+ readonly shallow?: string[];
100
+ readonly deepen?: number;
101
+ readonly deepenRelative?: boolean;
102
+ readonly deepenSince?: number;
103
+ readonly deepenNot?: string[];
104
+ readonly filter?: string;
105
+ readonly sidebandAll?: boolean;
106
+ readonly waitForDone?: boolean;
107
+ }
108
+ /**
109
+ * v2 fetch 响应
110
+ *
111
+ * 响应包含多个由 delimiter (0001) 分隔的节。
112
+ */
113
+ interface V2FetchResponse {
114
+ /** acknowledgments 节 */
115
+ readonly acknowledgments?: {
116
+ readonly nak?: boolean;
117
+ readonly acks: string[];
118
+ readonly ready?: boolean;
119
+ };
120
+ /** shallow-info 节 */
121
+ readonly shallowInfo?: {
122
+ readonly shallow: string[];
123
+ readonly unshallow: string[];
124
+ };
125
+ /** wanted-refs 节 */
126
+ readonly wantedRefs?: Array<{
127
+ oid: string;
128
+ refname: string;
129
+ }>;
130
+ /** packfile-uris 节 */
131
+ readonly packfileUris?: Array<{
132
+ oid: string;
133
+ uri: string;
134
+ }>;
135
+ /** 原始 packfile buffer */
136
+ readonly packfile?: Buffer;
137
+ }
138
+ /**
139
+ * object-info 结果条目
140
+ */
141
+ interface ObjectInfoEntry {
142
+ readonly oid: string;
143
+ readonly size?: number;
144
+ }
145
+ /**
146
+ * object-info 响应
147
+ */
148
+ interface ObjectInfoResponse {
149
+ readonly attrs: string[];
150
+ readonly objects: ObjectInfoEntry[];
151
+ }
152
+ //#endregion
153
+ export { LsRefsEntry, ObjectInfoEntry, ObjectInfoResponse, V2CapabilityAdvertisement, V2CommandEntry, V2FetchRequest, V2FetchResponse, V2GitServiceTransport };
@@ -0,0 +1,3 @@
1
+ import { SmartHttpHandler } from "./types.mjs";
2
+ import { createSmartHttpHandler } from "./smart-http.mjs";
3
+ export { type SmartHttpHandler, createSmartHttpHandler };
@@ -0,0 +1,2 @@
1
+ import { createSmartHttpHandler } from "./smart-http.mjs";
2
+ export { createSmartHttpHandler };
@@ -0,0 +1,46 @@
1
+ import { RepositoryBackend } from "../../backend/types.mjs";
2
+ import { SmartHttpHandler } from "./types.mjs";
3
+
4
+ //#region src/transport/http/smart-http.d.ts
5
+ /**
6
+ * 创建 Smart HTTP 处理函数
7
+ *
8
+ * 类似 git-http-backend 的核心入口。
9
+ * 接收标准 Request,返回标准 Response,框架无关。
10
+ *
11
+ * @param backend - 仓库后端
12
+ * @returns HTTP 处理函数
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Bun.serve — 直接作为 fetch 处理器
17
+ * import { createSmartHttpHandler } from "nano-git/transport/http";
18
+ * import { openRepository } from "nano-git/repository/file";
19
+ * Bun.serve({ port: 8080, fetch: createSmartHttpHandler(openRepository("/repo")) });
20
+ *
21
+ * // Node.js http
22
+ * import { createServer } from "node:http";
23
+ * const handler = createSmartHttpHandler(openRepository("/repo"));
24
+ * createServer(async (req, res) => {
25
+ * const url = new URL(req.url ?? "/", `http://${req.headers.host}`);
26
+ * const body = await new Promise<Buffer>((resolve) => {
27
+ * const chunks: Buffer[] = [];
28
+ * req.on("data", (c) => chunks.push(c));
29
+ * req.on("end", () => resolve(Buffer.concat(chunks)));
30
+ * });
31
+ * const response = await handler(new Request(url, {
32
+ * method: req.method,
33
+ * headers: Object.fromEntries(Object.entries(req.headers).map(([k, v]) => [k, String(v)])),
34
+ * body: req.method === "POST" ? body : undefined,
35
+ * }));
36
+ * res.writeHead(response.status, Object.fromEntries(response.headers));
37
+ * res.end(Buffer.from(await response.arrayBuffer()));
38
+ * }).listen(8080);
39
+ *
40
+ * // Cloudflare Workers / Deno
41
+ * export default { fetch: createSmartHttpHandler(openRepository("./repo")) };
42
+ * ```
43
+ */
44
+ declare function createSmartHttpHandler(backend: RepositoryBackend): SmartHttpHandler;
45
+ //#endregion
46
+ export { createSmartHttpHandler };