gitx.do 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/blame.d.ts +259 -0
- package/dist/cli/commands/blame.d.ts.map +1 -0
- package/dist/cli/commands/blame.js +609 -0
- package/dist/cli/commands/blame.js.map +1 -0
- package/dist/cli/commands/branch.d.ts +249 -0
- package/dist/cli/commands/branch.d.ts.map +1 -0
- package/dist/cli/commands/branch.js +693 -0
- package/dist/cli/commands/branch.js.map +1 -0
- package/dist/cli/commands/commit.d.ts +182 -0
- package/dist/cli/commands/commit.d.ts.map +1 -0
- package/dist/cli/commands/commit.js +437 -0
- package/dist/cli/commands/commit.js.map +1 -0
- package/dist/cli/commands/diff.d.ts +464 -0
- package/dist/cli/commands/diff.d.ts.map +1 -0
- package/dist/cli/commands/diff.js +958 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/log.d.ts +239 -0
- package/dist/cli/commands/log.d.ts.map +1 -0
- package/dist/cli/commands/log.js +535 -0
- package/dist/cli/commands/log.js.map +1 -0
- package/dist/cli/commands/review.d.ts +457 -0
- package/dist/cli/commands/review.d.ts.map +1 -0
- package/dist/cli/commands/review.js +533 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/commands/status.d.ts +269 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +493 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/web.d.ts +199 -0
- package/dist/cli/commands/web.d.ts.map +1 -0
- package/dist/cli/commands/web.js +696 -0
- package/dist/cli/commands/web.js.map +1 -0
- package/dist/cli/fs-adapter.d.ts +656 -0
- package/dist/cli/fs-adapter.d.ts.map +1 -0
- package/dist/cli/fs-adapter.js +1179 -0
- package/dist/cli/fs-adapter.js.map +1 -0
- package/dist/cli/index.d.ts +387 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +523 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui/components/DiffView.d.ts +7 -0
- package/dist/cli/ui/components/DiffView.d.ts.map +1 -0
- package/dist/cli/ui/components/DiffView.js +11 -0
- package/dist/cli/ui/components/DiffView.js.map +1 -0
- package/dist/cli/ui/components/ErrorDisplay.d.ts +6 -0
- package/dist/cli/ui/components/ErrorDisplay.d.ts.map +1 -0
- package/dist/cli/ui/components/ErrorDisplay.js +11 -0
- package/dist/cli/ui/components/ErrorDisplay.js.map +1 -0
- package/dist/cli/ui/components/FuzzySearch.d.ts +9 -0
- package/dist/cli/ui/components/FuzzySearch.d.ts.map +1 -0
- package/dist/cli/ui/components/FuzzySearch.js +12 -0
- package/dist/cli/ui/components/FuzzySearch.js.map +1 -0
- package/dist/cli/ui/components/LoadingSpinner.d.ts +6 -0
- package/dist/cli/ui/components/LoadingSpinner.d.ts.map +1 -0
- package/dist/cli/ui/components/LoadingSpinner.js +10 -0
- package/dist/cli/ui/components/LoadingSpinner.js.map +1 -0
- package/dist/cli/ui/components/NavigationList.d.ts +9 -0
- package/dist/cli/ui/components/NavigationList.d.ts.map +1 -0
- package/dist/cli/ui/components/NavigationList.js +11 -0
- package/dist/cli/ui/components/NavigationList.js.map +1 -0
- package/dist/cli/ui/components/ScrollableContent.d.ts +8 -0
- package/dist/cli/ui/components/ScrollableContent.d.ts.map +1 -0
- package/dist/cli/ui/components/ScrollableContent.js +11 -0
- package/dist/cli/ui/components/ScrollableContent.js.map +1 -0
- package/dist/cli/ui/components/index.d.ts +7 -0
- package/dist/cli/ui/components/index.d.ts.map +1 -0
- package/dist/cli/ui/components/index.js +9 -0
- package/dist/cli/ui/components/index.js.map +1 -0
- package/dist/cli/ui/terminal-ui.d.ts +52 -0
- package/dist/cli/ui/terminal-ui.d.ts.map +1 -0
- package/dist/cli/ui/terminal-ui.js +121 -0
- package/dist/cli/ui/terminal-ui.js.map +1 -0
- package/dist/durable-object/object-store.d.ts +401 -23
- package/dist/durable-object/object-store.d.ts.map +1 -1
- package/dist/durable-object/object-store.js +414 -25
- package/dist/durable-object/object-store.js.map +1 -1
- package/dist/durable-object/schema.d.ts +188 -0
- package/dist/durable-object/schema.d.ts.map +1 -1
- package/dist/durable-object/schema.js +160 -0
- package/dist/durable-object/schema.js.map +1 -1
- package/dist/durable-object/wal.d.ts +336 -31
- package/dist/durable-object/wal.d.ts.map +1 -1
- package/dist/durable-object/wal.js +272 -27
- package/dist/durable-object/wal.js.map +1 -1
- package/dist/index.d.ts +379 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +379 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp/adapter.d.ts +579 -38
- package/dist/mcp/adapter.d.ts.map +1 -1
- package/dist/mcp/adapter.js +426 -33
- package/dist/mcp/adapter.js.map +1 -1
- package/dist/mcp/sandbox.d.ts +532 -29
- package/dist/mcp/sandbox.d.ts.map +1 -1
- package/dist/mcp/sandbox.js +389 -22
- package/dist/mcp/sandbox.js.map +1 -1
- package/dist/mcp/sdk-adapter.d.ts +478 -56
- package/dist/mcp/sdk-adapter.d.ts.map +1 -1
- package/dist/mcp/sdk-adapter.js +346 -44
- package/dist/mcp/sdk-adapter.js.map +1 -1
- package/dist/mcp/tools.d.ts +445 -30
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +363 -33
- package/dist/mcp/tools.js.map +1 -1
- package/dist/ops/blame.d.ts +424 -21
- package/dist/ops/blame.d.ts.map +1 -1
- package/dist/ops/blame.js +303 -20
- package/dist/ops/blame.js.map +1 -1
- package/dist/ops/branch.d.ts +583 -32
- package/dist/ops/branch.d.ts.map +1 -1
- package/dist/ops/branch.js +365 -23
- package/dist/ops/branch.js.map +1 -1
- package/dist/ops/commit-traversal.d.ts +164 -24
- package/dist/ops/commit-traversal.d.ts.map +1 -1
- package/dist/ops/commit-traversal.js +68 -2
- package/dist/ops/commit-traversal.js.map +1 -1
- package/dist/ops/commit.d.ts +387 -53
- package/dist/ops/commit.d.ts.map +1 -1
- package/dist/ops/commit.js +249 -29
- package/dist/ops/commit.js.map +1 -1
- package/dist/ops/merge-base.d.ts +195 -21
- package/dist/ops/merge-base.d.ts.map +1 -1
- package/dist/ops/merge-base.js +122 -12
- package/dist/ops/merge-base.js.map +1 -1
- package/dist/ops/merge.d.ts +600 -130
- package/dist/ops/merge.d.ts.map +1 -1
- package/dist/ops/merge.js +408 -60
- package/dist/ops/merge.js.map +1 -1
- package/dist/ops/tag.d.ts +67 -2
- package/dist/ops/tag.d.ts.map +1 -1
- package/dist/ops/tag.js +42 -1
- package/dist/ops/tag.js.map +1 -1
- package/dist/ops/tree-builder.d.ts +102 -6
- package/dist/ops/tree-builder.d.ts.map +1 -1
- package/dist/ops/tree-builder.js +30 -5
- package/dist/ops/tree-builder.js.map +1 -1
- package/dist/ops/tree-diff.d.ts +50 -2
- package/dist/ops/tree-diff.d.ts.map +1 -1
- package/dist/ops/tree-diff.js +50 -2
- package/dist/ops/tree-diff.js.map +1 -1
- package/dist/pack/delta.d.ts +211 -39
- package/dist/pack/delta.d.ts.map +1 -1
- package/dist/pack/delta.js +232 -46
- package/dist/pack/delta.js.map +1 -1
- package/dist/pack/format.d.ts +390 -28
- package/dist/pack/format.d.ts.map +1 -1
- package/dist/pack/format.js +344 -33
- package/dist/pack/format.js.map +1 -1
- package/dist/pack/full-generation.d.ts +313 -28
- package/dist/pack/full-generation.d.ts.map +1 -1
- package/dist/pack/full-generation.js +238 -19
- package/dist/pack/full-generation.js.map +1 -1
- package/dist/pack/generation.d.ts +346 -23
- package/dist/pack/generation.d.ts.map +1 -1
- package/dist/pack/generation.js +269 -21
- package/dist/pack/generation.js.map +1 -1
- package/dist/pack/index.d.ts +407 -86
- package/dist/pack/index.d.ts.map +1 -1
- package/dist/pack/index.js +351 -70
- package/dist/pack/index.js.map +1 -1
- package/dist/refs/branch.d.ts +517 -71
- package/dist/refs/branch.d.ts.map +1 -1
- package/dist/refs/branch.js +410 -26
- package/dist/refs/branch.js.map +1 -1
- package/dist/refs/storage.d.ts +610 -57
- package/dist/refs/storage.d.ts.map +1 -1
- package/dist/refs/storage.js +481 -29
- package/dist/refs/storage.js.map +1 -1
- package/dist/refs/tag.d.ts +677 -67
- package/dist/refs/tag.d.ts.map +1 -1
- package/dist/refs/tag.js +497 -30
- package/dist/refs/tag.js.map +1 -1
- package/dist/storage/lru-cache.d.ts +556 -53
- package/dist/storage/lru-cache.d.ts.map +1 -1
- package/dist/storage/lru-cache.js +439 -36
- package/dist/storage/lru-cache.js.map +1 -1
- package/dist/storage/object-index.d.ts +483 -38
- package/dist/storage/object-index.d.ts.map +1 -1
- package/dist/storage/object-index.js +388 -22
- package/dist/storage/object-index.js.map +1 -1
- package/dist/storage/r2-pack.d.ts +957 -94
- package/dist/storage/r2-pack.d.ts.map +1 -1
- package/dist/storage/r2-pack.js +756 -48
- package/dist/storage/r2-pack.js.map +1 -1
- package/dist/tiered/cdc-pipeline.d.ts +1610 -38
- package/dist/tiered/cdc-pipeline.d.ts.map +1 -1
- package/dist/tiered/cdc-pipeline.js +1131 -22
- package/dist/tiered/cdc-pipeline.js.map +1 -1
- package/dist/tiered/migration.d.ts +903 -41
- package/dist/tiered/migration.d.ts.map +1 -1
- package/dist/tiered/migration.js +646 -24
- package/dist/tiered/migration.js.map +1 -1
- package/dist/tiered/parquet-writer.d.ts +944 -47
- package/dist/tiered/parquet-writer.d.ts.map +1 -1
- package/dist/tiered/parquet-writer.js +667 -39
- package/dist/tiered/parquet-writer.js.map +1 -1
- package/dist/tiered/read-path.d.ts +728 -34
- package/dist/tiered/read-path.d.ts.map +1 -1
- package/dist/tiered/read-path.js +310 -27
- package/dist/tiered/read-path.js.map +1 -1
- package/dist/types/objects.d.ts +457 -0
- package/dist/types/objects.d.ts.map +1 -1
- package/dist/types/objects.js +305 -4
- package/dist/types/objects.js.map +1 -1
- package/dist/types/storage.d.ts +407 -35
- package/dist/types/storage.d.ts.map +1 -1
- package/dist/types/storage.js +27 -3
- package/dist/types/storage.js.map +1 -1
- package/dist/utils/hash.d.ts +133 -12
- package/dist/utils/hash.d.ts.map +1 -1
- package/dist/utils/hash.js +133 -12
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/sha1.d.ts +102 -9
- package/dist/utils/sha1.d.ts.map +1 -1
- package/dist/utils/sha1.js +114 -11
- package/dist/utils/sha1.js.map +1 -1
- package/dist/wire/capabilities.d.ts +896 -88
- package/dist/wire/capabilities.d.ts.map +1 -1
- package/dist/wire/capabilities.js +566 -62
- package/dist/wire/capabilities.js.map +1 -1
- package/dist/wire/pkt-line.d.ts +293 -15
- package/dist/wire/pkt-line.d.ts.map +1 -1
- package/dist/wire/pkt-line.js +251 -15
- package/dist/wire/pkt-line.js.map +1 -1
- package/dist/wire/receive-pack.d.ts +814 -64
- package/dist/wire/receive-pack.d.ts.map +1 -1
- package/dist/wire/receive-pack.js +542 -41
- package/dist/wire/receive-pack.js.map +1 -1
- package/dist/wire/smart-http.d.ts +575 -97
- package/dist/wire/smart-http.d.ts.map +1 -1
- package/dist/wire/smart-http.js +337 -46
- package/dist/wire/smart-http.js.map +1 -1
- package/dist/wire/upload-pack.d.ts +492 -98
- package/dist/wire/upload-pack.d.ts.map +1 -1
- package/dist/wire/upload-pack.js +347 -59
- package/dist/wire/upload-pack.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,26 +1,68 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Git receive-pack
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
2
|
+
* @fileoverview Git receive-pack Protocol Implementation
|
|
3
|
+
*
|
|
4
|
+
* This module implements the server-side of Git's receive-pack service, which
|
|
5
|
+
* handles `git-push` operations. It receives ref updates and packfile data
|
|
6
|
+
* from clients and applies them to the repository.
|
|
7
|
+
*
|
|
8
|
+
* @module wire/receive-pack
|
|
9
|
+
*
|
|
10
|
+
* ## Protocol Flow
|
|
11
|
+
*
|
|
12
|
+
* 1. **Ref Advertisement**: Server advertises current refs and capabilities
|
|
13
|
+
* 2. **Command Reception**: Client sends ref update commands (old-sha new-sha refname)
|
|
14
|
+
* 3. **Packfile Reception**: Client sends packfile with new objects (if needed)
|
|
15
|
+
* 4. **Validation**: Server validates packfile and ref updates
|
|
16
|
+
* 5. **Application**: Server applies updates and sends status report
|
|
17
|
+
*
|
|
18
|
+
* ## Security Considerations
|
|
19
|
+
*
|
|
20
|
+
* - Validates all SHA-1 hashes before processing
|
|
21
|
+
* - Checks fast-forward constraints for updates
|
|
22
|
+
* - Supports atomic pushes for consistency
|
|
23
|
+
* - Validates ref names according to Git rules
|
|
24
|
+
* - Supports pre-receive, update, and post-receive hooks
|
|
25
|
+
*
|
|
26
|
+
* @see {@link https://git-scm.com/docs/pack-protocol} Git Pack Protocol
|
|
27
|
+
* @see {@link https://git-scm.com/docs/git-receive-pack} git-receive-pack Documentation
|
|
28
|
+
*
|
|
29
|
+
* @example Basic push handling
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import {
|
|
32
|
+
* createReceiveSession,
|
|
33
|
+
* advertiseReceiveRefs,
|
|
34
|
+
* handleReceivePack
|
|
35
|
+
* } from './wire/receive-pack'
|
|
36
|
+
*
|
|
37
|
+
* // Create session and advertise refs
|
|
38
|
+
* const session = createReceiveSession('my-repo')
|
|
39
|
+
* const advertisement = await advertiseReceiveRefs(store, { atomic: true })
|
|
40
|
+
*
|
|
41
|
+
* // Handle push request
|
|
42
|
+
* const response = await handleReceivePack(session, requestBody, store)
|
|
43
|
+
* ```
|
|
18
44
|
*/
|
|
19
45
|
import { encodePktLine, FLUSH_PKT } from './pkt-line';
|
|
20
46
|
// ============================================================================
|
|
21
47
|
// Constants
|
|
22
48
|
// ============================================================================
|
|
23
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Zero SHA - used for ref creation and deletion.
|
|
51
|
+
*
|
|
52
|
+
* @description
|
|
53
|
+
* This 40-character string of zeros is used as a placeholder:
|
|
54
|
+
* - In `oldSha`: indicates a ref is being created (doesn't exist yet)
|
|
55
|
+
* - In `newSha`: indicates a ref is being deleted
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* // Check if this is a create operation
|
|
60
|
+
* const isCreate = cmd.oldSha === ZERO_SHA
|
|
61
|
+
*
|
|
62
|
+
* // Check if this is a delete operation
|
|
63
|
+
* const isDelete = cmd.newSha === ZERO_SHA
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
24
66
|
export const ZERO_SHA = '0'.repeat(40);
|
|
25
67
|
/** SHA-1 regex for validation */
|
|
26
68
|
const SHA1_REGEX = /^[0-9a-f]{40}$/i;
|
|
@@ -31,7 +73,27 @@ const decoder = new TextDecoder();
|
|
|
31
73
|
// Capability Functions
|
|
32
74
|
// ============================================================================
|
|
33
75
|
/**
|
|
34
|
-
* Build capability string for receive-pack
|
|
76
|
+
* Build capability string for receive-pack advertisement.
|
|
77
|
+
*
|
|
78
|
+
* @description
|
|
79
|
+
* Converts a capabilities object into a space-separated string suitable
|
|
80
|
+
* for inclusion in the ref advertisement. Boolean capabilities become
|
|
81
|
+
* simple names, while capabilities with values become "name=value".
|
|
82
|
+
*
|
|
83
|
+
* @param capabilities - Capabilities to advertise
|
|
84
|
+
* @returns Space-separated capability string
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const caps: ReceivePackCapabilities = {
|
|
89
|
+
* reportStatus: true,
|
|
90
|
+
* deleteRefs: true,
|
|
91
|
+
* atomic: true,
|
|
92
|
+
* agent: 'my-server/1.0'
|
|
93
|
+
* }
|
|
94
|
+
* const str = buildReceiveCapabilityString(caps)
|
|
95
|
+
* // 'report-status delete-refs atomic agent=my-server/1.0'
|
|
96
|
+
* ```
|
|
35
97
|
*/
|
|
36
98
|
export function buildReceiveCapabilityString(capabilities) {
|
|
37
99
|
const caps = [];
|
|
@@ -56,7 +118,25 @@ export function buildReceiveCapabilityString(capabilities) {
|
|
|
56
118
|
return caps.join(' ');
|
|
57
119
|
}
|
|
58
120
|
/**
|
|
59
|
-
* Parse capabilities from string
|
|
121
|
+
* Parse capabilities from string.
|
|
122
|
+
*
|
|
123
|
+
* @description
|
|
124
|
+
* Parses a space-separated capability string into a structured
|
|
125
|
+
* capabilities object.
|
|
126
|
+
*
|
|
127
|
+
* @param capsString - Space-separated capabilities
|
|
128
|
+
* @returns Parsed capabilities object
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const caps = parseReceiveCapabilities(
|
|
133
|
+
* 'report-status delete-refs atomic agent=git/2.30.0'
|
|
134
|
+
* )
|
|
135
|
+
* // caps.reportStatus === true
|
|
136
|
+
* // caps.deleteRefs === true
|
|
137
|
+
* // caps.atomic === true
|
|
138
|
+
* // caps.agent === 'git/2.30.0'
|
|
139
|
+
* ```
|
|
60
140
|
*/
|
|
61
141
|
export function parseReceiveCapabilities(capsString) {
|
|
62
142
|
const caps = {};
|
|
@@ -90,7 +170,21 @@ export function parseReceiveCapabilities(capsString) {
|
|
|
90
170
|
// Session Management
|
|
91
171
|
// ============================================================================
|
|
92
172
|
/**
|
|
93
|
-
* Create a new receive-pack session
|
|
173
|
+
* Create a new receive-pack session.
|
|
174
|
+
*
|
|
175
|
+
* @description
|
|
176
|
+
* Initializes a new session for a receive-pack operation. The session
|
|
177
|
+
* tracks state across the protocol phases.
|
|
178
|
+
*
|
|
179
|
+
* @param repoId - Repository identifier for logging/tracking
|
|
180
|
+
* @returns New session object
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const session = createReceiveSession('my-repo')
|
|
185
|
+
* // session.capabilities === {}
|
|
186
|
+
* // session.commands === []
|
|
187
|
+
* ```
|
|
94
188
|
*/
|
|
95
189
|
export function createReceiveSession(repoId) {
|
|
96
190
|
return {
|
|
@@ -103,7 +197,28 @@ export function createReceiveSession(repoId) {
|
|
|
103
197
|
// Ref Advertisement
|
|
104
198
|
// ============================================================================
|
|
105
199
|
/**
|
|
106
|
-
* Advertise refs to client
|
|
200
|
+
* Advertise refs to client.
|
|
201
|
+
*
|
|
202
|
+
* @description
|
|
203
|
+
* Generates the ref advertisement response for the initial phase of
|
|
204
|
+
* receive-pack. This includes:
|
|
205
|
+
* - HEAD reference with capabilities (or zero SHA for empty repos)
|
|
206
|
+
* - All refs sorted alphabetically
|
|
207
|
+
* - Peeled refs for annotated tags
|
|
208
|
+
*
|
|
209
|
+
* @param store - Object store to get refs from
|
|
210
|
+
* @param capabilities - Optional server capabilities to advertise
|
|
211
|
+
* @returns Pkt-line formatted ref advertisement
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* const advertisement = await advertiseReceiveRefs(store, {
|
|
216
|
+
* reportStatus: true,
|
|
217
|
+
* deleteRefs: true,
|
|
218
|
+
* atomic: true
|
|
219
|
+
* })
|
|
220
|
+
* // Send as response to GET /info/refs?service=git-receive-pack
|
|
221
|
+
* ```
|
|
107
222
|
*/
|
|
108
223
|
export async function advertiseReceiveRefs(store, capabilities) {
|
|
109
224
|
const refs = await store.getRefs();
|
|
@@ -157,7 +272,31 @@ export async function advertiseReceiveRefs(store, capabilities) {
|
|
|
157
272
|
// Command Parsing
|
|
158
273
|
// ============================================================================
|
|
159
274
|
/**
|
|
160
|
-
* Parse a single command line
|
|
275
|
+
* Parse a single command line.
|
|
276
|
+
*
|
|
277
|
+
* @description
|
|
278
|
+
* Parses a ref update command line in the format:
|
|
279
|
+
* `<old-sha> <new-sha> <refname>[NUL<capabilities>]`
|
|
280
|
+
*
|
|
281
|
+
* The first command line may include capabilities after a NUL byte.
|
|
282
|
+
*
|
|
283
|
+
* @param line - Command line to parse
|
|
284
|
+
* @returns Parsed command object
|
|
285
|
+
*
|
|
286
|
+
* @throws {Error} If the line format is invalid or SHAs are malformed
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```typescript
|
|
290
|
+
* // Simple command
|
|
291
|
+
* const cmd = parseCommandLine(
|
|
292
|
+
* 'abc123... def456... refs/heads/main'
|
|
293
|
+
* )
|
|
294
|
+
*
|
|
295
|
+
* // Command with capabilities (first line)
|
|
296
|
+
* const cmdWithCaps = parseCommandLine(
|
|
297
|
+
* 'abc123... def456... refs/heads/main\0report-status atomic'
|
|
298
|
+
* )
|
|
299
|
+
* ```
|
|
161
300
|
*/
|
|
162
301
|
export function parseCommandLine(line) {
|
|
163
302
|
// Check for capabilities after NUL byte
|
|
@@ -205,7 +344,9 @@ export function parseCommandLine(line) {
|
|
|
205
344
|
}
|
|
206
345
|
/**
|
|
207
346
|
* Find flush packet index - must be at start of string or preceded by newline,
|
|
208
|
-
* and not be part of a 40-character SHA
|
|
347
|
+
* and not be part of a 40-character SHA.
|
|
348
|
+
*
|
|
349
|
+
* @internal
|
|
209
350
|
*/
|
|
210
351
|
function findFlushPacket(str, startPos = 0) {
|
|
211
352
|
let searchPos = startPos;
|
|
@@ -232,7 +373,28 @@ function findFlushPacket(str, startPos = 0) {
|
|
|
232
373
|
return -1;
|
|
233
374
|
}
|
|
234
375
|
/**
|
|
235
|
-
* Parse complete receive-pack request
|
|
376
|
+
* Parse complete receive-pack request.
|
|
377
|
+
*
|
|
378
|
+
* @description
|
|
379
|
+
* Parses the full receive-pack request body, extracting:
|
|
380
|
+
* - Ref update commands
|
|
381
|
+
* - Capabilities (from first command)
|
|
382
|
+
* - Push options (if enabled)
|
|
383
|
+
* - Packfile data
|
|
384
|
+
*
|
|
385
|
+
* @param data - Raw request body as Uint8Array
|
|
386
|
+
* @returns Parsed request object
|
|
387
|
+
*
|
|
388
|
+
* @throws {Error} If the request format is invalid
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* ```typescript
|
|
392
|
+
* const request = parseReceivePackRequest(requestBody)
|
|
393
|
+
* // request.commands - array of RefUpdateCommand
|
|
394
|
+
* // request.capabilities - capabilities from first command
|
|
395
|
+
* // request.packfile - packfile binary data
|
|
396
|
+
* // request.pushOptions - push options (if enabled)
|
|
397
|
+
* ```
|
|
236
398
|
*/
|
|
237
399
|
export function parseReceivePackRequest(data) {
|
|
238
400
|
const str = decoder.decode(data);
|
|
@@ -309,7 +471,28 @@ export function parseReceivePackRequest(data) {
|
|
|
309
471
|
// Packfile Validation
|
|
310
472
|
// ============================================================================
|
|
311
473
|
/**
|
|
312
|
-
* Validate packfile structure
|
|
474
|
+
* Validate packfile structure.
|
|
475
|
+
*
|
|
476
|
+
* @description
|
|
477
|
+
* Validates a packfile's structure, including:
|
|
478
|
+
* - PACK signature (4 bytes)
|
|
479
|
+
* - Version number (must be 2 or 3)
|
|
480
|
+
* - Object count
|
|
481
|
+
* - Checksum (if verifyChecksum option is true)
|
|
482
|
+
*
|
|
483
|
+
* @param packfile - Packfile binary data
|
|
484
|
+
* @param options - Validation options
|
|
485
|
+
* @returns Validation result
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* ```typescript
|
|
489
|
+
* const result = await validatePackfile(packData, { verifyChecksum: true })
|
|
490
|
+
* if (!result.valid) {
|
|
491
|
+
* console.error('Invalid packfile:', result.error)
|
|
492
|
+
* } else {
|
|
493
|
+
* console.log('Objects in pack:', result.objectCount)
|
|
494
|
+
* }
|
|
495
|
+
* ```
|
|
313
496
|
*/
|
|
314
497
|
export async function validatePackfile(packfile, options) {
|
|
315
498
|
// Handle empty packfile
|
|
@@ -361,7 +544,27 @@ export async function validatePackfile(packfile, options) {
|
|
|
361
544
|
return { valid: true, objectCount };
|
|
362
545
|
}
|
|
363
546
|
/**
|
|
364
|
-
* Unpack objects from packfile
|
|
547
|
+
* Unpack objects from packfile.
|
|
548
|
+
*
|
|
549
|
+
* @description
|
|
550
|
+
* Extracts and stores objects from a packfile into the object store.
|
|
551
|
+
* Handles both regular objects and delta-compressed objects.
|
|
552
|
+
*
|
|
553
|
+
* @param packfile - Packfile binary data
|
|
554
|
+
* @param _store - Object store to store unpacked objects
|
|
555
|
+
* @param options - Unpack options
|
|
556
|
+
* @returns Unpack result
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```typescript
|
|
560
|
+
* const result = await unpackObjects(packfile, store, {
|
|
561
|
+
* resolveDelta: true,
|
|
562
|
+
* onProgress: (msg) => console.log(msg)
|
|
563
|
+
* })
|
|
564
|
+
* if (result.success) {
|
|
565
|
+
* console.log('Unpacked', result.objectsUnpacked, 'objects')
|
|
566
|
+
* }
|
|
567
|
+
* ```
|
|
365
568
|
*/
|
|
366
569
|
export async function unpackObjects(packfile, _store, options) {
|
|
367
570
|
const unpackedShas = [];
|
|
@@ -409,7 +612,29 @@ export async function unpackObjects(packfile, _store, options) {
|
|
|
409
612
|
// Ref Validation
|
|
410
613
|
// ============================================================================
|
|
411
614
|
/**
|
|
412
|
-
* Validate ref name according to git rules
|
|
615
|
+
* Validate ref name according to git rules.
|
|
616
|
+
*
|
|
617
|
+
* @description
|
|
618
|
+
* Validates a ref name against Git's naming rules:
|
|
619
|
+
* - Must not be empty
|
|
620
|
+
* - Must not start or end with `/`
|
|
621
|
+
* - Must not contain `//` or `..`
|
|
622
|
+
* - Must not contain control characters
|
|
623
|
+
* - Must not contain spaces, `~`, `^`, `:`, or `@{`
|
|
624
|
+
* - Must not end with `.lock`
|
|
625
|
+
* - Components must not start with `.`
|
|
626
|
+
*
|
|
627
|
+
* @param refName - Ref name to validate
|
|
628
|
+
* @returns true if the ref name is valid
|
|
629
|
+
*
|
|
630
|
+
* @example
|
|
631
|
+
* ```typescript
|
|
632
|
+
* validateRefName('refs/heads/main') // true
|
|
633
|
+
* validateRefName('refs/heads/feature') // true
|
|
634
|
+
* validateRefName('refs/heads/.hidden') // false (starts with .)
|
|
635
|
+
* validateRefName('refs/heads/a..b') // false (contains ..)
|
|
636
|
+
* validateRefName('refs/heads/a b') // false (contains space)
|
|
637
|
+
* ```
|
|
413
638
|
*/
|
|
414
639
|
export function validateRefName(refName) {
|
|
415
640
|
// Must not be empty
|
|
@@ -461,7 +686,30 @@ export function validateRefName(refName) {
|
|
|
461
686
|
return true;
|
|
462
687
|
}
|
|
463
688
|
/**
|
|
464
|
-
* Validate fast-forward update
|
|
689
|
+
* Validate fast-forward update.
|
|
690
|
+
*
|
|
691
|
+
* @description
|
|
692
|
+
* Checks if updating a ref from oldSha to newSha is a fast-forward.
|
|
693
|
+
* A fast-forward means oldSha is an ancestor of newSha.
|
|
694
|
+
*
|
|
695
|
+
* Creation and deletion are always allowed (not fast-forward questions).
|
|
696
|
+
*
|
|
697
|
+
* @param oldSha - Current ref value (or ZERO_SHA for create)
|
|
698
|
+
* @param newSha - New ref value (or ZERO_SHA for delete)
|
|
699
|
+
* @param store - Object store to check ancestry
|
|
700
|
+
* @returns true if the update is allowed
|
|
701
|
+
*
|
|
702
|
+
* @example
|
|
703
|
+
* ```typescript
|
|
704
|
+
* // Fast-forward update
|
|
705
|
+
* const ok = await validateFastForward(parent, child, store) // true
|
|
706
|
+
*
|
|
707
|
+
* // Non-fast-forward update
|
|
708
|
+
* const notOk = await validateFastForward(child, parent, store) // false
|
|
709
|
+
*
|
|
710
|
+
* // Creation always allowed
|
|
711
|
+
* const create = await validateFastForward(ZERO_SHA, sha, store) // true
|
|
712
|
+
* ```
|
|
465
713
|
*/
|
|
466
714
|
export async function validateFastForward(oldSha, newSha, store) {
|
|
467
715
|
// Creation is always allowed
|
|
@@ -476,7 +724,29 @@ export async function validateFastForward(oldSha, newSha, store) {
|
|
|
476
724
|
return store.isAncestor(oldSha, newSha);
|
|
477
725
|
}
|
|
478
726
|
/**
|
|
479
|
-
* Check ref permissions
|
|
727
|
+
* Check ref permissions.
|
|
728
|
+
*
|
|
729
|
+
* @description
|
|
730
|
+
* Checks whether a ref operation is allowed based on:
|
|
731
|
+
* - Protected refs (cannot be modified)
|
|
732
|
+
* - Allowed ref patterns (must match at least one)
|
|
733
|
+
* - Force push restrictions on protected branches
|
|
734
|
+
*
|
|
735
|
+
* @param refName - Ref being modified
|
|
736
|
+
* @param operation - Type of operation
|
|
737
|
+
* @param options - Permission check options
|
|
738
|
+
* @returns Permission check result
|
|
739
|
+
*
|
|
740
|
+
* @example
|
|
741
|
+
* ```typescript
|
|
742
|
+
* const result = await checkRefPermissions(
|
|
743
|
+
* 'refs/heads/main',
|
|
744
|
+
* 'force-update',
|
|
745
|
+
* { protectedRefs: ['refs/heads/main'] }
|
|
746
|
+
* )
|
|
747
|
+
* // result.allowed === false
|
|
748
|
+
* // result.reason === 'force push not allowed on protected branch'
|
|
749
|
+
* ```
|
|
480
750
|
*/
|
|
481
751
|
export async function checkRefPermissions(refName, operation, options) {
|
|
482
752
|
// Check protected refs
|
|
@@ -502,7 +772,8 @@ export async function checkRefPermissions(refName, operation, options) {
|
|
|
502
772
|
return { allowed: true };
|
|
503
773
|
}
|
|
504
774
|
/**
|
|
505
|
-
* Simple glob pattern matching
|
|
775
|
+
* Simple glob pattern matching.
|
|
776
|
+
* @internal
|
|
506
777
|
*/
|
|
507
778
|
function matchPattern(str, pattern) {
|
|
508
779
|
// Convert glob pattern to regex
|
|
@@ -517,7 +788,31 @@ function matchPattern(str, pattern) {
|
|
|
517
788
|
// Ref Updates
|
|
518
789
|
// ============================================================================
|
|
519
790
|
/**
|
|
520
|
-
* Process ref update commands
|
|
791
|
+
* Process ref update commands.
|
|
792
|
+
*
|
|
793
|
+
* @description
|
|
794
|
+
* Validates and processes ref update commands without actually
|
|
795
|
+
* applying them. Checks:
|
|
796
|
+
* - Ref name validity
|
|
797
|
+
* - Current ref state matches expected old SHA
|
|
798
|
+
* - Fast-forward constraints (unless force push)
|
|
799
|
+
* - Delete-refs capability for deletions
|
|
800
|
+
*
|
|
801
|
+
* @param session - Current session state
|
|
802
|
+
* @param commands - Commands to process
|
|
803
|
+
* @param store - Object store
|
|
804
|
+
* @param options - Processing options
|
|
805
|
+
* @returns Processing result with per-ref status
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```typescript
|
|
809
|
+
* const result = await processCommands(session, commands, store)
|
|
810
|
+
* for (const refResult of result.results) {
|
|
811
|
+
* if (!refResult.success) {
|
|
812
|
+
* console.error(`Failed to update ${refResult.refName}: ${refResult.error}`)
|
|
813
|
+
* }
|
|
814
|
+
* }
|
|
815
|
+
* ```
|
|
521
816
|
*/
|
|
522
817
|
export async function processCommands(session, commands, store, options) {
|
|
523
818
|
const results = [];
|
|
@@ -573,7 +868,20 @@ export async function processCommands(session, commands, store, options) {
|
|
|
573
868
|
return { results };
|
|
574
869
|
}
|
|
575
870
|
/**
|
|
576
|
-
* Update refs in the store
|
|
871
|
+
* Update refs in the store.
|
|
872
|
+
*
|
|
873
|
+
* @description
|
|
874
|
+
* Actually applies ref updates to the object store. Should only be
|
|
875
|
+
* called after validation via processCommands.
|
|
876
|
+
*
|
|
877
|
+
* @param commands - Commands to apply
|
|
878
|
+
* @param store - Object store
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* ```typescript
|
|
882
|
+
* // After validation
|
|
883
|
+
* await updateRefs(commands, store)
|
|
884
|
+
* ```
|
|
577
885
|
*/
|
|
578
886
|
export async function updateRefs(commands, store) {
|
|
579
887
|
for (const cmd of commands) {
|
|
@@ -586,7 +894,25 @@ export async function updateRefs(commands, store) {
|
|
|
586
894
|
}
|
|
587
895
|
}
|
|
588
896
|
/**
|
|
589
|
-
* Atomic ref update - all or nothing
|
|
897
|
+
* Atomic ref update - all or nothing.
|
|
898
|
+
*
|
|
899
|
+
* @description
|
|
900
|
+
* Applies all ref updates atomically. If any update fails, all
|
|
901
|
+
* changes are rolled back to the original state.
|
|
902
|
+
*
|
|
903
|
+
* @param commands - Commands to apply
|
|
904
|
+
* @param store - Object store
|
|
905
|
+
* @returns Atomic update result
|
|
906
|
+
*
|
|
907
|
+
* @example
|
|
908
|
+
* ```typescript
|
|
909
|
+
* const result = await atomicRefUpdate(commands, store)
|
|
910
|
+
* if (result.success) {
|
|
911
|
+
* console.log('All refs updated successfully')
|
|
912
|
+
* } else {
|
|
913
|
+
* console.error('Atomic push failed, all changes rolled back')
|
|
914
|
+
* }
|
|
915
|
+
* ```
|
|
590
916
|
*/
|
|
591
917
|
export async function atomicRefUpdate(commands, store) {
|
|
592
918
|
const results = [];
|
|
@@ -642,7 +968,32 @@ export async function atomicRefUpdate(commands, store) {
|
|
|
642
968
|
}
|
|
643
969
|
}
|
|
644
970
|
/**
|
|
645
|
-
* Execute pre-receive hook
|
|
971
|
+
* Execute pre-receive hook.
|
|
972
|
+
*
|
|
973
|
+
* @description
|
|
974
|
+
* Runs the pre-receive hook before any refs are updated.
|
|
975
|
+
* The hook receives all commands and can reject the entire push.
|
|
976
|
+
*
|
|
977
|
+
* @param commands - Commands to be executed
|
|
978
|
+
* @param _store - Object store
|
|
979
|
+
* @param hookFn - Hook function to execute
|
|
980
|
+
* @param env - Environment variables for the hook
|
|
981
|
+
* @param options - Hook options
|
|
982
|
+
* @returns Hook result
|
|
983
|
+
*
|
|
984
|
+
* @example
|
|
985
|
+
* ```typescript
|
|
986
|
+
* const result = await executePreReceiveHook(
|
|
987
|
+
* commands,
|
|
988
|
+
* store,
|
|
989
|
+
* async (cmds, env) => {
|
|
990
|
+
* // Validate commands
|
|
991
|
+
* return { success: true }
|
|
992
|
+
* },
|
|
993
|
+
* { GIT_DIR: '/path/to/repo' },
|
|
994
|
+
* { timeout: 30000 }
|
|
995
|
+
* )
|
|
996
|
+
* ```
|
|
646
997
|
*/
|
|
647
998
|
export async function executePreReceiveHook(commands, _store, hookFn, env = {}, options) {
|
|
648
999
|
const timeout = options?.timeout || 30000;
|
|
@@ -661,7 +1012,30 @@ export async function executePreReceiveHook(commands, _store, hookFn, env = {},
|
|
|
661
1012
|
}
|
|
662
1013
|
}
|
|
663
1014
|
/**
|
|
664
|
-
* Execute update hook for each ref
|
|
1015
|
+
* Execute update hook for each ref.
|
|
1016
|
+
*
|
|
1017
|
+
* @description
|
|
1018
|
+
* Runs the update hook for each ref being updated.
|
|
1019
|
+
* Unlike pre-receive, this hook can reject individual refs.
|
|
1020
|
+
*
|
|
1021
|
+
* @param commands - Commands being executed
|
|
1022
|
+
* @param _store - Object store
|
|
1023
|
+
* @param hookFn - Hook function to execute per-ref
|
|
1024
|
+
* @param env - Environment variables for the hook
|
|
1025
|
+
* @returns Results for each ref
|
|
1026
|
+
*
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```typescript
|
|
1029
|
+
* const { results } = await executeUpdateHook(
|
|
1030
|
+
* commands,
|
|
1031
|
+
* store,
|
|
1032
|
+
* async (refName, oldSha, newSha, env) => {
|
|
1033
|
+
* // Check if update is allowed for this ref
|
|
1034
|
+
* return { success: true }
|
|
1035
|
+
* },
|
|
1036
|
+
* { GIT_DIR: '/path/to/repo' }
|
|
1037
|
+
* )
|
|
1038
|
+
* ```
|
|
665
1039
|
*/
|
|
666
1040
|
export async function executeUpdateHook(commands, _store, hookFn, env = {}) {
|
|
667
1041
|
const results = [];
|
|
@@ -676,7 +1050,33 @@ export async function executeUpdateHook(commands, _store, hookFn, env = {}) {
|
|
|
676
1050
|
return { results };
|
|
677
1051
|
}
|
|
678
1052
|
/**
|
|
679
|
-
* Execute post-receive hook
|
|
1053
|
+
* Execute post-receive hook.
|
|
1054
|
+
*
|
|
1055
|
+
* @description
|
|
1056
|
+
* Runs the post-receive hook after all refs are updated.
|
|
1057
|
+
* This hook cannot affect the push result but is useful for
|
|
1058
|
+
* notifications, CI triggers, etc.
|
|
1059
|
+
*
|
|
1060
|
+
* @param commands - Commands that were executed
|
|
1061
|
+
* @param results - Results of ref updates
|
|
1062
|
+
* @param _store - Object store
|
|
1063
|
+
* @param hookFn - Hook function to execute
|
|
1064
|
+
* @param options - Hook options
|
|
1065
|
+
* @returns Hook execution result
|
|
1066
|
+
*
|
|
1067
|
+
* @example
|
|
1068
|
+
* ```typescript
|
|
1069
|
+
* const { hookSuccess } = await executePostReceiveHook(
|
|
1070
|
+
* commands,
|
|
1071
|
+
* results,
|
|
1072
|
+
* store,
|
|
1073
|
+
* async (cmds, results, env) => {
|
|
1074
|
+
* // Trigger CI, send notifications, etc.
|
|
1075
|
+
* return { success: true }
|
|
1076
|
+
* },
|
|
1077
|
+
* { pushOptions: ['ci.skip'] }
|
|
1078
|
+
* )
|
|
1079
|
+
* ```
|
|
680
1080
|
*/
|
|
681
1081
|
export async function executePostReceiveHook(commands, results, _store, hookFn, options) {
|
|
682
1082
|
// Filter to only successful updates
|
|
@@ -696,7 +1096,27 @@ export async function executePostReceiveHook(commands, results, _store, hookFn,
|
|
|
696
1096
|
};
|
|
697
1097
|
}
|
|
698
1098
|
/**
|
|
699
|
-
* Execute post-update hook
|
|
1099
|
+
* Execute post-update hook.
|
|
1100
|
+
*
|
|
1101
|
+
* @description
|
|
1102
|
+
* Runs the post-update hook with the names of successfully updated refs.
|
|
1103
|
+
* Simpler than post-receive, takes only ref names as arguments.
|
|
1104
|
+
*
|
|
1105
|
+
* @param _commands - Commands that were executed
|
|
1106
|
+
* @param results - Results of ref updates
|
|
1107
|
+
* @param hookFn - Hook function to execute
|
|
1108
|
+
*
|
|
1109
|
+
* @example
|
|
1110
|
+
* ```typescript
|
|
1111
|
+
* await executePostUpdateHook(
|
|
1112
|
+
* commands,
|
|
1113
|
+
* results,
|
|
1114
|
+
* async (refNames) => {
|
|
1115
|
+
* console.log('Updated refs:', refNames)
|
|
1116
|
+
* return { success: true }
|
|
1117
|
+
* }
|
|
1118
|
+
* )
|
|
1119
|
+
* ```
|
|
700
1120
|
*/
|
|
701
1121
|
export async function executePostUpdateHook(_commands, results, hookFn) {
|
|
702
1122
|
// Get successfully updated ref names
|
|
@@ -710,7 +1130,29 @@ export async function executePostUpdateHook(_commands, results, hookFn) {
|
|
|
710
1130
|
// Report Status Formatting
|
|
711
1131
|
// ============================================================================
|
|
712
1132
|
/**
|
|
713
|
-
* Format report-status response
|
|
1133
|
+
* Format report-status response.
|
|
1134
|
+
*
|
|
1135
|
+
* @description
|
|
1136
|
+
* Creates a pkt-line formatted status report response to send
|
|
1137
|
+
* to the client after processing the push. The format is:
|
|
1138
|
+
* 1. Unpack status: "unpack ok" or "unpack <error>"
|
|
1139
|
+
* 2. Ref status lines: "ok <refname>" or "ng <refname> <error>"
|
|
1140
|
+
* 3. Flush packet
|
|
1141
|
+
*
|
|
1142
|
+
* @param input - Status report data
|
|
1143
|
+
* @returns Pkt-line formatted status report
|
|
1144
|
+
*
|
|
1145
|
+
* @example
|
|
1146
|
+
* ```typescript
|
|
1147
|
+
* const report = formatReportStatus({
|
|
1148
|
+
* unpackStatus: 'ok',
|
|
1149
|
+
* refResults: [
|
|
1150
|
+
* { refName: 'refs/heads/main', success: true },
|
|
1151
|
+
* { refName: 'refs/heads/feature', success: false, error: 'non-fast-forward' }
|
|
1152
|
+
* ]
|
|
1153
|
+
* })
|
|
1154
|
+
* // "0010unpack ok\n0019ok refs/heads/main\n002cng refs/heads/feature non-fast-forward\n0000"
|
|
1155
|
+
* ```
|
|
714
1156
|
*/
|
|
715
1157
|
export function formatReportStatus(input) {
|
|
716
1158
|
const lines = [];
|
|
@@ -731,7 +1173,26 @@ export function formatReportStatus(input) {
|
|
|
731
1173
|
return lines.join('');
|
|
732
1174
|
}
|
|
733
1175
|
/**
|
|
734
|
-
* Format report-status-v2 response
|
|
1176
|
+
* Format report-status-v2 response.
|
|
1177
|
+
*
|
|
1178
|
+
* @description
|
|
1179
|
+
* Creates an extended status report for report-status-v2 capability.
|
|
1180
|
+
* Adds option lines before the unpack status and supports forced
|
|
1181
|
+
* update indication.
|
|
1182
|
+
*
|
|
1183
|
+
* @param input - Status report data
|
|
1184
|
+
* @returns Pkt-line formatted v2 status report
|
|
1185
|
+
*
|
|
1186
|
+
* @example
|
|
1187
|
+
* ```typescript
|
|
1188
|
+
* const report = formatReportStatusV2({
|
|
1189
|
+
* unpackStatus: 'ok',
|
|
1190
|
+
* refResults: [
|
|
1191
|
+
* { refName: 'refs/heads/main', success: true, forced: true }
|
|
1192
|
+
* ],
|
|
1193
|
+
* options: { 'object-format': 'sha1' }
|
|
1194
|
+
* })
|
|
1195
|
+
* ```
|
|
735
1196
|
*/
|
|
736
1197
|
export function formatReportStatusV2(input) {
|
|
737
1198
|
const lines = [];
|
|
@@ -762,7 +1223,27 @@ export function formatReportStatusV2(input) {
|
|
|
762
1223
|
return lines.join('');
|
|
763
1224
|
}
|
|
764
1225
|
/**
|
|
765
|
-
* Format rejection message
|
|
1226
|
+
* Format rejection message.
|
|
1227
|
+
*
|
|
1228
|
+
* @description
|
|
1229
|
+
* Creates a rejection message in the appropriate format based
|
|
1230
|
+
* on the client's capabilities (side-band or report-status).
|
|
1231
|
+
*
|
|
1232
|
+
* @param refName - Ref that was rejected
|
|
1233
|
+
* @param reason - Reason for rejection
|
|
1234
|
+
* @param options - Formatting options
|
|
1235
|
+
* @returns Formatted rejection message
|
|
1236
|
+
*
|
|
1237
|
+
* @example
|
|
1238
|
+
* ```typescript
|
|
1239
|
+
* // Side-band format
|
|
1240
|
+
* const msg = rejectPush('refs/heads/main', 'protected branch', { sideBand: true })
|
|
1241
|
+
* // Returns Uint8Array with side-band channel 3 message
|
|
1242
|
+
*
|
|
1243
|
+
* // Report-status format
|
|
1244
|
+
* const msg = rejectPush('refs/heads/main', 'protected branch', { reportStatus: true })
|
|
1245
|
+
* // Returns "ng refs/heads/main protected branch"
|
|
1246
|
+
* ```
|
|
766
1247
|
*/
|
|
767
1248
|
export function rejectPush(refName, reason, options) {
|
|
768
1249
|
if (options.sideBand) {
|
|
@@ -784,7 +1265,27 @@ export function rejectPush(refName, reason, options) {
|
|
|
784
1265
|
// Full Receive-Pack Handler
|
|
785
1266
|
// ============================================================================
|
|
786
1267
|
/**
|
|
787
|
-
* Handle complete receive-pack request
|
|
1268
|
+
* Handle complete receive-pack request.
|
|
1269
|
+
*
|
|
1270
|
+
* @description
|
|
1271
|
+
* This is the main entry point that handles the full receive-pack
|
|
1272
|
+
* protocol flow:
|
|
1273
|
+
* 1. Parse request (commands, capabilities, packfile)
|
|
1274
|
+
* 2. Validate and unpack packfile (if present)
|
|
1275
|
+
* 3. Process each ref update command
|
|
1276
|
+
* 4. Return status report (if requested)
|
|
1277
|
+
*
|
|
1278
|
+
* @param session - Receive pack session
|
|
1279
|
+
* @param request - Raw request data
|
|
1280
|
+
* @param store - Object store
|
|
1281
|
+
* @returns Response data (status report or empty)
|
|
1282
|
+
*
|
|
1283
|
+
* @example
|
|
1284
|
+
* ```typescript
|
|
1285
|
+
* const session = createReceiveSession('my-repo')
|
|
1286
|
+
* const response = await handleReceivePack(session, requestBody, store)
|
|
1287
|
+
* // response contains status report if report-status was enabled
|
|
1288
|
+
* ```
|
|
788
1289
|
*/
|
|
789
1290
|
export async function handleReceivePack(session, request, store) {
|
|
790
1291
|
// Parse the request
|