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.
- package/README.md +407 -0
- package/dist/backend/file-backend.d.mts +26 -0
- package/dist/backend/file-backend.mjs +83 -0
- package/dist/backend/file.d.mts +2 -0
- package/dist/backend/file.mjs +2 -0
- package/dist/backend/index.d.mts +2 -0
- package/dist/backend/index.mjs +1 -0
- package/dist/backend/memory-backend.d.mts +25 -0
- package/dist/backend/memory-backend.mjs +33 -0
- package/dist/backend/memory.d.mts +2 -0
- package/dist/backend/memory.mjs +2 -0
- package/dist/backend/types.d.mts +90 -0
- package/dist/core/errors.d.mts +124 -0
- package/dist/core/errors.mjs +168 -0
- package/dist/core/hash-digest.d.mts +35 -0
- package/dist/core/hash-digest.mjs +50 -0
- package/dist/core/hash-file.d.mts +20 -0
- package/dist/core/hash-file.mjs +27 -0
- package/dist/core/hash-path.d.mts +17 -0
- package/dist/core/hash-path.mjs +35 -0
- package/dist/core/types/odb.d.mts +63 -0
- package/dist/core/types/refs.d.mts +140 -0
- package/dist/core/types/refs.mjs +19 -0
- package/dist/core/types/shallow.d.mts +52 -0
- package/dist/core/types.d.mts +154 -0
- package/dist/core/types.mjs +43 -0
- package/dist/errors.d.mts +2 -0
- package/dist/errors.mjs +2 -0
- package/dist/hash-file.d.mts +2 -0
- package/dist/hash-file.mjs +2 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.mjs +14 -0
- package/dist/objects/author.d.mts +25 -0
- package/dist/objects/author.mjs +45 -0
- package/dist/objects/blob.d.mts +15 -0
- package/dist/objects/blob.mjs +20 -0
- package/dist/objects/codec.d.mts +46 -0
- package/dist/objects/codec.mjs +84 -0
- package/dist/objects/commit.d.mts +26 -0
- package/dist/objects/commit.mjs +160 -0
- package/dist/objects/index.d.mts +8 -0
- package/dist/objects/index.mjs +8 -0
- package/dist/objects/raw.d.mts +85 -0
- package/dist/objects/raw.mjs +111 -0
- package/dist/objects/tag.d.mts +26 -0
- package/dist/objects/tag.mjs +148 -0
- package/dist/objects/tree.d.mts +22 -0
- package/dist/objects/tree.mjs +66 -0
- package/dist/odb/file-utils.mjs +136 -0
- package/dist/odb/file.d.mts +22 -0
- package/dist/odb/file.mjs +66 -0
- package/dist/odb/memory.d.mts +22 -0
- package/dist/odb/memory.mjs +54 -0
- package/dist/pack/composite-store.d.mts +76 -0
- package/dist/pack/composite-store.mjs +133 -0
- package/dist/pack/constants.mjs +48 -0
- package/dist/pack/crc32.mjs +38 -0
- package/dist/pack/delta-apply.d.mts +21 -0
- package/dist/pack/delta-apply.mjs +71 -0
- package/dist/pack/delta-create.d.mts +28 -0
- package/dist/pack/delta-create.mjs +151 -0
- package/dist/pack/index.d.mts +16 -0
- package/dist/pack/index.mjs +13 -0
- package/dist/pack/object-header.d.mts +36 -0
- package/dist/pack/object-header.mjs +72 -0
- package/dist/pack/ofs-delta-offset.d.mts +35 -0
- package/dist/pack/ofs-delta-offset.mjs +59 -0
- package/dist/pack/pack-builder-types.d.mts +19 -0
- package/dist/pack/pack-builder.d.mts +52 -0
- package/dist/pack/pack-builder.mjs +80 -0
- package/dist/pack/pack-encoding.mjs +76 -0
- package/dist/pack/pack-index-reader.d.mts +57 -0
- package/dist/pack/pack-index-reader.mjs +90 -0
- package/dist/pack/pack-index-types.d.mts +16 -0
- package/dist/pack/pack-index-writer.d.mts +45 -0
- package/dist/pack/pack-index-writer.mjs +106 -0
- package/dist/pack/pack-reader-resolver.mjs +104 -0
- package/dist/pack/pack-reader-types.d.mts +31 -0
- package/dist/pack/pack-reader-types.mjs +22 -0
- package/dist/pack/pack-reader-utils.mjs +61 -0
- package/dist/pack/pack-reader.d.mts +81 -0
- package/dist/pack/pack-reader.mjs +171 -0
- package/dist/pack/pack-store-loader.mjs +79 -0
- package/dist/pack/pack-store-types.d.mts +16 -0
- package/dist/pack/pack-store.d.mts +55 -0
- package/dist/pack/pack-store.mjs +114 -0
- package/dist/pack/pack-writer.mjs +96 -0
- package/dist/pack/varint.d.mts +34 -0
- package/dist/pack/varint.mjs +57 -0
- package/dist/refs/file.d.mts +6 -0
- package/dist/refs/file.mjs +222 -0
- package/dist/refs/fs-utils.mjs +30 -0
- package/dist/refs/memory.d.mts +14 -0
- package/dist/refs/memory.mjs +104 -0
- package/dist/refs/names.d.mts +57 -0
- package/dist/refs/names.mjs +80 -0
- package/dist/refs/resolve.d.mts +33 -0
- package/dist/refs/resolve.mjs +55 -0
- package/dist/refs/shallow/file.d.mts +17 -0
- package/dist/refs/shallow/file.mjs +61 -0
- package/dist/refs/shallow/memory.d.mts +18 -0
- package/dist/refs/shallow/memory.mjs +33 -0
- package/dist/repository/core.d.mts +3 -0
- package/dist/repository/core.mjs +2 -0
- package/dist/repository/create.d.mts +22 -0
- package/dist/repository/create.mjs +43 -0
- package/dist/repository/file.d.mts +43 -0
- package/dist/repository/file.mjs +82 -0
- package/dist/repository/import/import-glob.mjs +44 -0
- package/dist/repository/import/import-plan-builder.mjs +625 -0
- package/dist/repository/import/import-session-types.d.mts +280 -0
- package/dist/repository/import/import-session.mjs +96 -0
- package/dist/repository/import/import-view.mjs +133 -0
- package/dist/repository/memory.d.mts +17 -0
- package/dist/repository/memory.mjs +33 -0
- package/dist/repository/ops/fetch-operations.mjs +20 -0
- package/dist/repository/ops/fetch-types.d.mts +82 -0
- package/dist/repository/ops/fetch-url.mjs +82 -0
- package/dist/repository/ops/fs-object-operations.mjs +31 -0
- package/dist/repository/ops/maintenance-operations.mjs +62 -0
- package/dist/repository/ops/maintenance-types.d.mts +42 -0
- package/dist/repository/ops/object-operations.mjs +65 -0
- package/dist/repository/ops/object-types.d.mts +109 -0
- package/dist/repository/ops/push-operations.mjs +16 -0
- package/dist/repository/ops/push-resolution.mjs +17 -0
- package/dist/repository/ops/push-types.d.mts +72 -0
- package/dist/repository/ops/push-url.mjs +45 -0
- package/dist/repository/ops/reachability.mjs +60 -0
- package/dist/repository/ops/ref-operations.mjs +86 -0
- package/dist/repository/ops/ref-types.d.mts +70 -0
- package/dist/repository/tree/tree-patch.d.mts +64 -0
- package/dist/repository/tree/tree-patch.mjs +268 -0
- package/dist/repository/tree/tree-walk.d.mts +46 -0
- package/dist/repository/tree/tree-walk.mjs +65 -0
- package/dist/repository/tree/tree-writer.mjs +68 -0
- package/dist/repository/types.d.mts +36 -0
- package/dist/sha1.d.mts +4 -0
- package/dist/sha1.mjs +4 -0
- package/dist/transport/client/receive-pack/http.d.mts +33 -0
- package/dist/transport/client/receive-pack/http.mjs +99 -0
- package/dist/transport/client/receive-pack/push-error.d.mts +23 -0
- package/dist/transport/client/receive-pack/push-error.mjs +32 -0
- package/dist/transport/client/receive-pack/push-pack-plan.d.mts +28 -0
- package/dist/transport/client/receive-pack/push-pack-plan.mjs +60 -0
- package/dist/transport/client/receive-pack/push-policy.d.mts +19 -0
- package/dist/transport/client/receive-pack/push-policy.mjs +64 -0
- package/dist/transport/client/receive-pack/push-ref-plan.d.mts +45 -0
- package/dist/transport/client/receive-pack/push-ref-plan.mjs +108 -0
- package/dist/transport/client/receive-pack/push-report.d.mts +28 -0
- package/dist/transport/client/receive-pack/push-report.mjs +84 -0
- package/dist/transport/client/receive-pack/push-request-plan.mjs +52 -0
- package/dist/transport/client/receive-pack/push.d.mts +32 -0
- package/dist/transport/client/receive-pack/push.mjs +97 -0
- package/dist/transport/client/receive-pack/request.d.mts +39 -0
- package/dist/transport/client/receive-pack/request.mjs +46 -0
- package/dist/transport/client/receive-pack/response.d.mts +26 -0
- package/dist/transport/client/receive-pack/response.mjs +52 -0
- package/dist/transport/client/receive-pack/result.d.mts +34 -0
- package/dist/transport/client/receive-pack/result.mjs +100 -0
- package/dist/transport/client/upload-pack/capability-advertisement.d.mts +56 -0
- package/dist/transport/client/upload-pack/capability-advertisement.mjs +130 -0
- package/dist/transport/client/upload-pack/fetch.d.mts +109 -0
- package/dist/transport/client/upload-pack/fetch.mjs +392 -0
- package/dist/transport/client/upload-pack/http.d.mts +29 -0
- package/dist/transport/client/upload-pack/http.mjs +79 -0
- package/dist/transport/client/upload-pack/ls-refs.d.mts +75 -0
- package/dist/transport/client/upload-pack/ls-refs.mjs +150 -0
- package/dist/transport/client/upload-pack/object-info.d.mts +65 -0
- package/dist/transport/client/upload-pack/object-info.mjs +111 -0
- package/dist/transport/client/upload-pack/types.d.mts +153 -0
- package/dist/transport/http/index.d.mts +3 -0
- package/dist/transport/http/index.mjs +2 -0
- package/dist/transport/http/smart-http.d.mts +46 -0
- package/dist/transport/http/smart-http.mjs +176 -0
- package/dist/transport/http/types.d.mts +27 -0
- package/dist/transport/index.d.mts +9 -0
- package/dist/transport/index.mjs +8 -0
- package/dist/transport/protocol/object-graph.d.mts +63 -0
- package/dist/transport/protocol/object-graph.mjs +149 -0
- package/dist/transport/protocol/pkt-line.d.mts +109 -0
- package/dist/transport/protocol/pkt-line.mjs +195 -0
- package/dist/transport/protocol/ref-advertisement.mjs +185 -0
- package/dist/transport/protocol/ref-collection.d.mts +38 -0
- package/dist/transport/protocol/ref-collection.mjs +63 -0
- package/dist/transport/protocol/ref-match.d.mts +39 -0
- package/dist/transport/protocol/ref-match.mjs +42 -0
- package/dist/transport/protocol/refspec.d.mts +44 -0
- package/dist/transport/protocol/refspec.mjs +79 -0
- package/dist/transport/protocol/side-band.d.mts +65 -0
- package/dist/transport/protocol/side-band.mjs +142 -0
- package/dist/transport/protocol/transport-capabilities.mjs +46 -0
- package/dist/transport/protocol/types.d.mts +148 -0
- package/dist/transport/protocol/update-refs.d.mts +68 -0
- package/dist/transport/protocol/update-refs.mjs +126 -0
- package/dist/transport/receive-pack.d.mts +11 -0
- package/dist/transport/receive-pack.mjs +11 -0
- package/dist/transport/server/receive-pack/advertise.d.mts +28 -0
- package/dist/transport/server/receive-pack/advertise.mjs +88 -0
- package/dist/transport/server/receive-pack/handler.d.mts +30 -0
- package/dist/transport/server/receive-pack/handler.mjs +156 -0
- package/dist/transport/server/receive-pack/index.d.mts +6 -0
- package/dist/transport/server/receive-pack/index.mjs +6 -0
- package/dist/transport/server/receive-pack/parse.d.mts +17 -0
- package/dist/transport/server/receive-pack/parse.mjs +80 -0
- package/dist/transport/server/receive-pack/report-status.mjs +64 -0
- package/dist/transport/server/receive-pack/service.d.mts +41 -0
- package/dist/transport/server/receive-pack/service.mjs +39 -0
- package/dist/transport/server/receive-pack/types.d.mts +56 -0
- package/dist/transport/server/receive-pack/types.mjs +25 -0
- package/dist/transport/server/receive-pack/unpack.mjs +119 -0
- package/dist/transport/server/upload-pack/advertise.d.mts +20 -0
- package/dist/transport/server/upload-pack/advertise.mjs +30 -0
- package/dist/transport/server/upload-pack/command.d.mts +43 -0
- package/dist/transport/server/upload-pack/command.mjs +56 -0
- package/dist/transport/server/upload-pack/fetch.d.mts +43 -0
- package/dist/transport/server/upload-pack/fetch.mjs +217 -0
- package/dist/transport/server/upload-pack/index.d.mts +7 -0
- package/dist/transport/server/upload-pack/index.mjs +7 -0
- package/dist/transport/server/upload-pack/ls-refs.d.mts +38 -0
- package/dist/transport/server/upload-pack/ls-refs.mjs +113 -0
- package/dist/transport/server/upload-pack/service.d.mts +40 -0
- package/dist/transport/server/upload-pack/service.mjs +51 -0
- package/dist/transport/server/upload-pack/types.d.mts +11 -0
- package/dist/transport/server/upload-pack/types.mjs +21 -0
- package/dist/transport/upload-pack.d.mts +7 -0
- package/dist/transport/upload-pack.mjs +6 -0
- package/package.json +98 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { sha1 } from "../../../core/types.mjs";
|
|
2
|
+
import { tryReadObject } from "../../../objects/raw.mjs";
|
|
3
|
+
import { resolveRefHash } from "../../../refs/resolve.mjs";
|
|
4
|
+
import { encodeFlushPkt, encodePktLine } from "../../protocol/pkt-line.mjs";
|
|
5
|
+
import { CAPABILITIES_REF, SERVER_AGENT, ZERO_HASH } from "./types.mjs";
|
|
6
|
+
//#region src/transport/server/receive-pack/advertise.ts
|
|
7
|
+
/**
|
|
8
|
+
* receive-pack ref 广告生成
|
|
9
|
+
*
|
|
10
|
+
* 处理 GET /info/refs?service=git-receive-pack 请求,
|
|
11
|
+
* 生成 v1 风格的 ref 广告(含 capabilities)。
|
|
12
|
+
*
|
|
13
|
+
* @see https://git-scm.com/docs/pack-protocol#_git_gt_transport
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* 读取仓库中的所有引用
|
|
17
|
+
*/
|
|
18
|
+
function readAllRefs(backend) {
|
|
19
|
+
const result = /* @__PURE__ */ new Map();
|
|
20
|
+
const headContent = backend.refs.read("HEAD");
|
|
21
|
+
if (headContent !== null) result.set("HEAD", headContent);
|
|
22
|
+
const refNames = backend.refs.listAll();
|
|
23
|
+
for (const ref of refNames) {
|
|
24
|
+
const content = backend.refs.read(ref);
|
|
25
|
+
if (content !== null) result.set(ref, content);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 生成 receive-pack 的 ref 广告
|
|
31
|
+
*
|
|
32
|
+
* 格式:
|
|
33
|
+
* ```
|
|
34
|
+
* 001e# service=git-receive-pack\n
|
|
35
|
+
* 0000
|
|
36
|
+
* <length><hash> <refname>\0<capabilities>\n ← 首行 ref 携带 capabilities
|
|
37
|
+
* <length><hash> <refname>\n ← 后续 ref
|
|
38
|
+
* ...
|
|
39
|
+
* 0000
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param backend - 仓库后端
|
|
43
|
+
* @returns 完整 advertisement(pkt-line 编码)
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const buf = advertiseReceivePack(backend);
|
|
48
|
+
* // Response 的 Content-Type 应为 "application/x-git-receive-pack-advertisement"
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function advertiseReceivePack(backend) {
|
|
52
|
+
const parts = [];
|
|
53
|
+
parts.push(encodePktLine("# service=git-receive-pack\n"));
|
|
54
|
+
parts.push(encodeFlushPkt());
|
|
55
|
+
const refs = readAllRefs(backend);
|
|
56
|
+
const capStr = [
|
|
57
|
+
"report-status",
|
|
58
|
+
"delete-refs",
|
|
59
|
+
"side-band-64k",
|
|
60
|
+
"ofs-delta",
|
|
61
|
+
"no-progress",
|
|
62
|
+
`agent=${SERVER_AGENT}`
|
|
63
|
+
].join(" ");
|
|
64
|
+
let firstRef = true;
|
|
65
|
+
for (const [refName, content] of refs) if (content.startsWith("ref: ")) {
|
|
66
|
+
const resolved = resolveRefHash(backend.refs, refName);
|
|
67
|
+
if (resolved === null) continue;
|
|
68
|
+
const line = firstRef ? `${resolved} ${refName}\0${capStr}\n` : `${resolved} ${refName}\n`;
|
|
69
|
+
parts.push(encodePktLine(line));
|
|
70
|
+
const target = content.slice(5);
|
|
71
|
+
parts.push(encodePktLine(`${resolved} ${refName} symref-target:${target}\n`));
|
|
72
|
+
firstRef = false;
|
|
73
|
+
} else if (/^[0-9a-f]{40}$/.test(content)) {
|
|
74
|
+
const hash = sha1(content);
|
|
75
|
+
const line = firstRef ? `${hash} ${refName}\0${capStr}\n` : `${hash} ${refName}\n`;
|
|
76
|
+
parts.push(encodePktLine(line));
|
|
77
|
+
if (refName.startsWith("refs/tags/")) {
|
|
78
|
+
const obj = tryReadObject(backend.objects, hash);
|
|
79
|
+
if (obj?.type === "tag") parts.push(encodePktLine(`${obj.object} ${refName}^{}\n`));
|
|
80
|
+
}
|
|
81
|
+
firstRef = false;
|
|
82
|
+
}
|
|
83
|
+
if (firstRef) parts.push(encodePktLine(`${ZERO_HASH} ${CAPABILITIES_REF}\0${capStr}\n`));
|
|
84
|
+
parts.push(encodeFlushPkt());
|
|
85
|
+
return Buffer.concat(parts);
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { advertiseReceivePack };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { RepositoryBackend } from "../../../backend/types.mjs";
|
|
2
|
+
import { ReceivePackOptions } from "./types.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/transport/server/receive-pack/handler.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* 处理 receive-pack push 请求
|
|
7
|
+
*
|
|
8
|
+
* 完整流程:
|
|
9
|
+
* 1. 验证请求体非空
|
|
10
|
+
* 2. 解析客户端命令
|
|
11
|
+
* 3. 检查 delete-refs 能力(如需要删除)
|
|
12
|
+
* 4. 解包 packfile(如有)
|
|
13
|
+
* 5. 检查组删除 / 更新 / 创建条件
|
|
14
|
+
* 6. 批量应用 ref 更新
|
|
15
|
+
* 7. 返回 report-status
|
|
16
|
+
*
|
|
17
|
+
* @param backend - 仓库后端
|
|
18
|
+
* @param body - 完整的请求体
|
|
19
|
+
* @param options - 处理选项
|
|
20
|
+
* @returns report-status 响应(Buffer)
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const response = handleReceivePackRequest(backend, requestBody);
|
|
25
|
+
* // Response 的 Content-Type 应为 "application/x-git-receive-pack-result"
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
declare function handleReceivePackRequest(backend: RepositoryBackend, body: Buffer, options?: ReceivePackOptions): Buffer;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { handleReceivePackRequest };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { resolveRefHash } from "../../../refs/resolve.mjs";
|
|
2
|
+
import { encodeFlushPkt } from "../../protocol/pkt-line.mjs";
|
|
3
|
+
import { ReceivePackServiceError, ZERO_HASH } from "./types.mjs";
|
|
4
|
+
import { parseReceivePackRequest } from "./parse.mjs";
|
|
5
|
+
import { generateReceivePackReport } from "./report-status.mjs";
|
|
6
|
+
import { unpackPackfile } from "./unpack.mjs";
|
|
7
|
+
//#region src/transport/server/receive-pack/handler.ts
|
|
8
|
+
/**
|
|
9
|
+
* receive-pack 主处理函数
|
|
10
|
+
*
|
|
11
|
+
* 整合请求解析、packfile 解包、ref 校验与事务更新,
|
|
12
|
+
* 生成 report-status 响应。
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* 校验单个 ref 更新命令的合法性
|
|
16
|
+
*
|
|
17
|
+
* 检查:
|
|
18
|
+
* - oldHash 必须匹配 ref 当前值(新建时可为 000...0)
|
|
19
|
+
* - newHash 对象必须存在
|
|
20
|
+
* - 标签不可覆盖(允许 force — 但 v1 协议中 force 不在命令中体现)
|
|
21
|
+
* - 删除操作需要 delete-refs 能力
|
|
22
|
+
*/
|
|
23
|
+
function checkRefUpdate(backend, cmd, _capabilities, _options) {
|
|
24
|
+
const { oldHash, newHash, refName } = cmd;
|
|
25
|
+
const isDelete = newHash === ZERO_HASH;
|
|
26
|
+
const isCreate = oldHash === ZERO_HASH;
|
|
27
|
+
const currentHash = resolveRefHash(backend.refs, refName);
|
|
28
|
+
if (isCreate) {
|
|
29
|
+
if (currentHash !== null) return {
|
|
30
|
+
ok: false,
|
|
31
|
+
error: `ref ${refName} already exists`
|
|
32
|
+
};
|
|
33
|
+
if (!backend.objects.exists(newHash)) return {
|
|
34
|
+
ok: false,
|
|
35
|
+
error: `object ${newHash} not found`
|
|
36
|
+
};
|
|
37
|
+
return { ok: true };
|
|
38
|
+
}
|
|
39
|
+
if (currentHash === null) return {
|
|
40
|
+
ok: false,
|
|
41
|
+
error: `ref ${refName} does not exist (expected ${oldHash})`
|
|
42
|
+
};
|
|
43
|
+
if (currentHash !== oldHash) return {
|
|
44
|
+
ok: false,
|
|
45
|
+
error: `ref ${refName} is at ${currentHash} but expected ${oldHash}`
|
|
46
|
+
};
|
|
47
|
+
if (isDelete) return { ok: true };
|
|
48
|
+
if (!backend.objects.exists(newHash)) return {
|
|
49
|
+
ok: false,
|
|
50
|
+
error: `object ${newHash} not found`
|
|
51
|
+
};
|
|
52
|
+
if (refName.startsWith("refs/tags/")) return {
|
|
53
|
+
ok: false,
|
|
54
|
+
error: `tag ${refName} already exists and cannot be overwritten without force`
|
|
55
|
+
};
|
|
56
|
+
return { ok: true };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 在事务中应用批量 ref 更新
|
|
60
|
+
*/
|
|
61
|
+
function applyRefUpdates(backend, commands) {
|
|
62
|
+
const hooks = backend.refTransactionHooks;
|
|
63
|
+
const tx = backend.refs.beginTransaction(hooks);
|
|
64
|
+
try {
|
|
65
|
+
for (const cmd of commands) if (cmd.newHash === ZERO_HASH) tx.delete(cmd.refName);
|
|
66
|
+
else tx.write(cmd.refName, cmd.newHash);
|
|
67
|
+
tx.commit();
|
|
68
|
+
} catch (err) {
|
|
69
|
+
tx.rollback();
|
|
70
|
+
throw err;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 处理 receive-pack push 请求
|
|
75
|
+
*
|
|
76
|
+
* 完整流程:
|
|
77
|
+
* 1. 验证请求体非空
|
|
78
|
+
* 2. 解析客户端命令
|
|
79
|
+
* 3. 检查 delete-refs 能力(如需要删除)
|
|
80
|
+
* 4. 解包 packfile(如有)
|
|
81
|
+
* 5. 检查组删除 / 更新 / 创建条件
|
|
82
|
+
* 6. 批量应用 ref 更新
|
|
83
|
+
* 7. 返回 report-status
|
|
84
|
+
*
|
|
85
|
+
* @param backend - 仓库后端
|
|
86
|
+
* @param body - 完整的请求体
|
|
87
|
+
* @param options - 处理选项
|
|
88
|
+
* @returns report-status 响应(Buffer)
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const response = handleReceivePackRequest(backend, requestBody);
|
|
93
|
+
* // Response 的 Content-Type 应为 "application/x-git-receive-pack-result"
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
function handleReceivePackRequest(backend, body, options) {
|
|
97
|
+
let parsed;
|
|
98
|
+
try {
|
|
99
|
+
parsed = parseReceivePackRequest(body);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
if (err instanceof ReceivePackServiceError) throw err;
|
|
102
|
+
throw new ReceivePackServiceError(`Failed to parse receive-pack request: ${err instanceof Error ? err.message : String(err)}`);
|
|
103
|
+
}
|
|
104
|
+
const { capabilities, commands, packfile } = parsed;
|
|
105
|
+
const hasReportStatus = capabilities.includes("report-status");
|
|
106
|
+
const hasSideBand = capabilities.includes("side-band-64k");
|
|
107
|
+
let unpackOk = true;
|
|
108
|
+
let unpackError;
|
|
109
|
+
if (packfile.length > 0) try {
|
|
110
|
+
unpackPackfile(backend.objects, packfile);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
unpackOk = false;
|
|
113
|
+
unpackError = err instanceof Error ? err.message : String(err);
|
|
114
|
+
}
|
|
115
|
+
const successfulUpdates = [];
|
|
116
|
+
const refResults = [];
|
|
117
|
+
if (unpackOk) {
|
|
118
|
+
for (const cmd of commands) {
|
|
119
|
+
const check = checkRefUpdate(backend, cmd, capabilities, options);
|
|
120
|
+
if (check.ok) {
|
|
121
|
+
successfulUpdates.push({
|
|
122
|
+
refName: cmd.refName,
|
|
123
|
+
newHash: cmd.newHash
|
|
124
|
+
});
|
|
125
|
+
refResults.push({
|
|
126
|
+
refName: cmd.refName,
|
|
127
|
+
success: true
|
|
128
|
+
});
|
|
129
|
+
} else refResults.push({
|
|
130
|
+
refName: cmd.refName,
|
|
131
|
+
success: false,
|
|
132
|
+
error: check.error
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (successfulUpdates.length > 0) try {
|
|
136
|
+
applyRefUpdates(backend, successfulUpdates);
|
|
137
|
+
} catch (err) {
|
|
138
|
+
for (const up of successfulUpdates) {
|
|
139
|
+
const idx = refResults.findIndex((r) => r.refName === up.refName);
|
|
140
|
+
if (idx !== -1) refResults[idx] = {
|
|
141
|
+
refName: up.refName,
|
|
142
|
+
success: false,
|
|
143
|
+
error: `transaction failed: ${err instanceof Error ? err.message : String(err)}`
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} else for (const cmd of commands) refResults.push({
|
|
148
|
+
refName: cmd.refName,
|
|
149
|
+
success: false,
|
|
150
|
+
error: "unpack error"
|
|
151
|
+
});
|
|
152
|
+
if (!hasReportStatus) return encodeFlushPkt();
|
|
153
|
+
return generateReceivePackReport(unpackOk, unpackError, refResults, hasSideBand);
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
export { handleReceivePackRequest };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { advertiseReceivePack } from "./advertise.mjs";
|
|
2
|
+
import { ParsedReceivePackRequest, ReceivePackCommand, ReceivePackOptions, ReceivePackServiceError, ReceivePackUpdateResult } from "./types.mjs";
|
|
3
|
+
import { parseReceivePackRequest } from "./parse.mjs";
|
|
4
|
+
import { handleReceivePackRequest } from "./handler.mjs";
|
|
5
|
+
import { ReceivePackService, createReceivePackService } from "./service.mjs";
|
|
6
|
+
export { type ParsedReceivePackRequest, type ReceivePackCommand, type ReceivePackOptions, type ReceivePackService, ReceivePackServiceError, type ReceivePackUpdateResult, advertiseReceivePack, createReceivePackService, handleReceivePackRequest, parseReceivePackRequest };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ReceivePackServiceError } from "./types.mjs";
|
|
2
|
+
import { advertiseReceivePack } from "./advertise.mjs";
|
|
3
|
+
import { parseReceivePackRequest } from "./parse.mjs";
|
|
4
|
+
import { handleReceivePackRequest } from "./handler.mjs";
|
|
5
|
+
import { createReceivePackService } from "./service.mjs";
|
|
6
|
+
export { ReceivePackServiceError, advertiseReceivePack, createReceivePackService, handleReceivePackRequest, parseReceivePackRequest };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ParsedReceivePackRequest } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/transport/server/receive-pack/parse.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* 解析 receive-pack 请求 body
|
|
6
|
+
*
|
|
7
|
+
* @param body - 完整的请求 body
|
|
8
|
+
* @returns 解析后的命令、能力与 packfile
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const { commands, capabilities, packfile } = parseReceivePackRequest(body);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare function parseReceivePackRequest(body: Buffer): ParsedReceivePackRequest;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { parseReceivePackRequest };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { sha1 } from "../../../core/types.mjs";
|
|
2
|
+
import { splitPktLinesFromBuffer } from "../../protocol/pkt-line.mjs";
|
|
3
|
+
import { ReceivePackServiceError } from "./types.mjs";
|
|
4
|
+
//#region src/transport/server/receive-pack/parse.ts
|
|
5
|
+
/**
|
|
6
|
+
* receive-pack 请求解析
|
|
7
|
+
*
|
|
8
|
+
* 解析客户端 POST 的 ref 命令与 capabilities。
|
|
9
|
+
*
|
|
10
|
+
* 请求格式:
|
|
11
|
+
* ```
|
|
12
|
+
* <old-hash> <new-hash> <refname>\0<capabilities>\n ← 首行
|
|
13
|
+
* <old-hash> <new-hash> <refname>\n ← 后续行
|
|
14
|
+
* ...
|
|
15
|
+
* 0000 ← flush
|
|
16
|
+
* <packfile data> ← packfile
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @see https://git-scm.com/docs/pack-protocol#_git_gt_transport
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* 解析单行命令
|
|
23
|
+
*
|
|
24
|
+
* 格式:<old-hash> SP <new-hash> SP <refname>
|
|
25
|
+
*/
|
|
26
|
+
function parseCommandLine(text) {
|
|
27
|
+
const parts = text.split(" ");
|
|
28
|
+
if (parts.length < 3) return null;
|
|
29
|
+
const oldHash = parts[0];
|
|
30
|
+
const newHash = parts[1];
|
|
31
|
+
const refName = parts.slice(2).join(" ");
|
|
32
|
+
if (!/^[0-9a-f]{40}$/.test(oldHash)) return null;
|
|
33
|
+
if (!/^[0-9a-f]{40}$/.test(newHash)) return null;
|
|
34
|
+
return {
|
|
35
|
+
oldHash: sha1(oldHash),
|
|
36
|
+
newHash: sha1(newHash),
|
|
37
|
+
refName
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 解析 receive-pack 请求 body
|
|
42
|
+
*
|
|
43
|
+
* @param body - 完整的请求 body
|
|
44
|
+
* @returns 解析后的命令、能力与 packfile
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const { commands, capabilities, packfile } = parseReceivePackRequest(body);
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function parseReceivePackRequest(body) {
|
|
52
|
+
const { lines, trailing } = splitPktLinesFromBuffer(body);
|
|
53
|
+
const dataLines = lines.filter((l) => l.type === "data");
|
|
54
|
+
if (dataLines.length === 0) throw new ReceivePackServiceError("No commands in receive-pack request");
|
|
55
|
+
const commands = [];
|
|
56
|
+
let capabilities = [];
|
|
57
|
+
for (let i = 0; i < dataLines.length; i++) {
|
|
58
|
+
const text = dataLines[i].payload.toString("utf-8").replace(/\n$/, "");
|
|
59
|
+
if (i === 0) {
|
|
60
|
+
const nulIndex = text.indexOf("\0");
|
|
61
|
+
if (nulIndex !== -1) {
|
|
62
|
+
const cmdPart = text.substring(0, nulIndex);
|
|
63
|
+
capabilities = text.substring(nulIndex + 1).split(" ").filter(Boolean);
|
|
64
|
+
const cmd = parseCommandLine(cmdPart);
|
|
65
|
+
if (cmd) commands.push(cmd);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const cmd = parseCommandLine(text);
|
|
70
|
+
if (cmd) commands.push(cmd);
|
|
71
|
+
}
|
|
72
|
+
if (commands.length === 0) throw new ReceivePackServiceError("No valid ref update commands");
|
|
73
|
+
return {
|
|
74
|
+
capabilities,
|
|
75
|
+
commands,
|
|
76
|
+
packfile: trailing
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { parseReceivePackRequest };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { encodeFlushPkt, encodePktLine } from "../../protocol/pkt-line.mjs";
|
|
2
|
+
//#region src/transport/server/receive-pack/report-status.ts
|
|
3
|
+
/**
|
|
4
|
+
* receive-pack report-status 响应生成
|
|
5
|
+
*
|
|
6
|
+
* 生成 unpack 状态和 ref 更新结果的 pkt-line 编码响应。
|
|
7
|
+
* 支持 side-band-64k 编码(progress 在 channel 2,report-status 在 channel 1)。
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* 编码 side-band 帧
|
|
11
|
+
*/
|
|
12
|
+
function encodeSideBandFrame(channel, data) {
|
|
13
|
+
const frame = Buffer.alloc(1 + data.length);
|
|
14
|
+
frame[0] = channel;
|
|
15
|
+
data.copy(frame, 1);
|
|
16
|
+
return encodePktLine(frame);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 生成 receive-pack 的 report-status 响应
|
|
20
|
+
*
|
|
21
|
+
* 格式(无 side-band):
|
|
22
|
+
* ```
|
|
23
|
+
* unpack <ok|error>\n
|
|
24
|
+
* ok <refname>\n
|
|
25
|
+
* ng <refname> <error>\n
|
|
26
|
+
* ...
|
|
27
|
+
* 0000
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* 格式(带 side-band-64k):
|
|
31
|
+
* ```
|
|
32
|
+
* <side-band channel 2: progress>
|
|
33
|
+
* <side-band channel 1: report-status lines>
|
|
34
|
+
* 0000
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @param unpackOk - 解包是否成功
|
|
38
|
+
* @param unpackError - 解包错误消息(unpackOk 为 false 时)
|
|
39
|
+
* @param refResults - 各 ref 的更新结果
|
|
40
|
+
* @param useSideBand - 是否使用 side-band-64k 编码
|
|
41
|
+
* @returns 完整的响应 Buffer
|
|
42
|
+
*/
|
|
43
|
+
function generateReceivePackReport(unpackOk, unpackError, refResults, useSideBand) {
|
|
44
|
+
const statusLines = [];
|
|
45
|
+
if (unpackOk) statusLines.push(Buffer.from("unpack ok\n", "utf-8"));
|
|
46
|
+
else statusLines.push(Buffer.from(`unpack ${unpackError ?? "unknown error"}\n`, "utf-8"));
|
|
47
|
+
for (const result of refResults) if (result.success) statusLines.push(Buffer.from(`ok ${result.refName}\n`, "utf-8"));
|
|
48
|
+
else statusLines.push(Buffer.from(`ng ${result.refName} ${result.error ?? "unknown error"}\n`, "utf-8"));
|
|
49
|
+
const reportStatusData = Buffer.concat(statusLines);
|
|
50
|
+
const pktParts = [];
|
|
51
|
+
const lines = reportStatusData.toString("utf-8").split("\n");
|
|
52
|
+
for (const line of lines) if (line.length > 0) pktParts.push(encodePktLine(line + "\n"));
|
|
53
|
+
pktParts.push(encodeFlushPkt());
|
|
54
|
+
const reportPktSequence = Buffer.concat(pktParts);
|
|
55
|
+
if (!useSideBand) return reportPktSequence;
|
|
56
|
+
const parts = [];
|
|
57
|
+
const progressMsg = `Unpacking objects: 100% (${refResults.length}/${refResults.length})\n`;
|
|
58
|
+
parts.push(encodeSideBandFrame(2, Buffer.from(progressMsg, "utf-8")));
|
|
59
|
+
parts.push(encodeSideBandFrame(1, reportPktSequence));
|
|
60
|
+
parts.push(encodeFlushPkt());
|
|
61
|
+
return Buffer.concat(parts);
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { generateReceivePackReport };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { RepositoryBackend } from "../../../backend/types.mjs";
|
|
2
|
+
import { ReceivePackOptions } from "./types.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/transport/server/receive-pack/service.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Receive-Pack 服务接口
|
|
7
|
+
*
|
|
8
|
+
* 提供协议无关的 receive-pack 能力:
|
|
9
|
+
* - advertise(): 生成服务 ref 广告
|
|
10
|
+
* - handleRequest(): 处理客户端请求
|
|
11
|
+
*/
|
|
12
|
+
interface ReceivePackService {
|
|
13
|
+
/**
|
|
14
|
+
* 生成 ref 广告
|
|
15
|
+
*/
|
|
16
|
+
advertise(): Buffer;
|
|
17
|
+
/**
|
|
18
|
+
* 处理请求
|
|
19
|
+
*
|
|
20
|
+
* @param body - 客户端请求体
|
|
21
|
+
* @returns 服务端响应
|
|
22
|
+
*/
|
|
23
|
+
handleRequest(body: Buffer): Buffer;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 创建 Receive-Pack 服务实例
|
|
27
|
+
*
|
|
28
|
+
* @param backend - 仓库后端
|
|
29
|
+
* @param options - 处理选项
|
|
30
|
+
* @returns ReceivePackService 实例
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const service = createReceivePackService(backend);
|
|
35
|
+
* const advertise = service.advertise();
|
|
36
|
+
* const response = service.handleRequest(body);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
declare function createReceivePackService(backend: RepositoryBackend, options?: ReceivePackOptions): ReceivePackService;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { ReceivePackService, createReceivePackService };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { advertiseReceivePack } from "./advertise.mjs";
|
|
2
|
+
import { handleReceivePackRequest } from "./handler.mjs";
|
|
3
|
+
//#region src/transport/server/receive-pack/service.ts
|
|
4
|
+
/**
|
|
5
|
+
* receive-pack 服务编排器
|
|
6
|
+
*
|
|
7
|
+
* 聚合 Git 协议 v1 receive-pack 的服务端能力:
|
|
8
|
+
* - ref 广告生成
|
|
9
|
+
* - push 请求处理
|
|
10
|
+
*
|
|
11
|
+
* 底层协议实现细节仍保留在各子模块中,
|
|
12
|
+
* 本文件仅提供协议无关的服务接口和工厂。
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* 创建 Receive-Pack 服务实例
|
|
16
|
+
*
|
|
17
|
+
* @param backend - 仓库后端
|
|
18
|
+
* @param options - 处理选项
|
|
19
|
+
* @returns ReceivePackService 实例
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const service = createReceivePackService(backend);
|
|
24
|
+
* const advertise = service.advertise();
|
|
25
|
+
* const response = service.handleRequest(body);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function createReceivePackService(backend, options) {
|
|
29
|
+
return {
|
|
30
|
+
advertise() {
|
|
31
|
+
return advertiseReceivePack(backend);
|
|
32
|
+
},
|
|
33
|
+
handleRequest(body) {
|
|
34
|
+
return handleReceivePackRequest(backend, body, options);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { createReceivePackService };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SHA1 } from "../../../core/types.mjs";
|
|
2
|
+
import { GitError } from "../../../core/errors.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/transport/server/receive-pack/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* receive-pack 服务错误
|
|
7
|
+
*
|
|
8
|
+
* 当请求解析、处理或响应生成过程中遇到可预见的错误时抛出。
|
|
9
|
+
*/
|
|
10
|
+
declare class ReceivePackServiceError extends GitError {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Receive-pack 命令(ref 更新)
|
|
15
|
+
*
|
|
16
|
+
* 表示客户端请求的一次 ref 变更。
|
|
17
|
+
*/
|
|
18
|
+
interface ReceivePackCommand {
|
|
19
|
+
/** 客户端声称的服务端当前哈希(新建时为 000...0) */
|
|
20
|
+
readonly oldHash: SHA1;
|
|
21
|
+
/** 要设置的目标哈希(删除时为 000...0) */
|
|
22
|
+
readonly newHash: SHA1;
|
|
23
|
+
/** 引用完整名称,如 "refs/heads/main" */
|
|
24
|
+
readonly refName: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 解析后的 receive-pack 请求
|
|
28
|
+
*/
|
|
29
|
+
interface ParsedReceivePackRequest {
|
|
30
|
+
/** 客户端能力列表(首行 NUL 后的内容) */
|
|
31
|
+
readonly capabilities: string[];
|
|
32
|
+
/** ref 更新命令列表 */
|
|
33
|
+
readonly commands: ReceivePackCommand[];
|
|
34
|
+
/** packfile 数据(可能为空) */
|
|
35
|
+
readonly packfile: Buffer;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 单个 ref 更新的处理结果
|
|
39
|
+
*/
|
|
40
|
+
interface ReceivePackUpdateResult {
|
|
41
|
+
readonly refName: string;
|
|
42
|
+
readonly success: boolean;
|
|
43
|
+
readonly error?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* receive-pack 处理选项
|
|
47
|
+
*/
|
|
48
|
+
interface ReceivePackOptions {
|
|
49
|
+
/**
|
|
50
|
+
* 是否拒绝非 fast-forward 推送(类似 receive.denyNonFastForwards)
|
|
51
|
+
* 默认 false
|
|
52
|
+
*/
|
|
53
|
+
readonly denyNonFastForwards?: boolean;
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { ParsedReceivePackRequest, ReceivePackCommand, ReceivePackOptions, ReceivePackServiceError, ReceivePackUpdateResult };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { GitError } from "../../../core/errors.mjs";
|
|
2
|
+
import { sha1 } from "../../../core/types.mjs";
|
|
3
|
+
//#region src/transport/server/receive-pack/types.ts
|
|
4
|
+
/**
|
|
5
|
+
* receive-pack 服务端类型定义与常量
|
|
6
|
+
*/
|
|
7
|
+
/** 零哈希(表示新建或删除引用) */
|
|
8
|
+
const ZERO_HASH = sha1("0000000000000000000000000000000000000000");
|
|
9
|
+
/** 服务端 agent 字符串 */
|
|
10
|
+
const SERVER_AGENT = "nano-git/0.1";
|
|
11
|
+
/** v1 广告中 prefix-ref 的 magic 名称 */
|
|
12
|
+
const CAPABILITIES_REF = "capabilities^{}";
|
|
13
|
+
/**
|
|
14
|
+
* receive-pack 服务错误
|
|
15
|
+
*
|
|
16
|
+
* 当请求解析、处理或响应生成过程中遇到可预见的错误时抛出。
|
|
17
|
+
*/
|
|
18
|
+
var ReceivePackServiceError = class extends GitError {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(`receive-pack: ${message}`);
|
|
21
|
+
this.name = "ReceivePackServiceError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { CAPABILITIES_REF, ReceivePackServiceError, SERVER_AGENT, ZERO_HASH };
|