File
Blob: src/worker/git/pack/build.ts
| 1 | import type { GitObjectType } from "@/worker/git/core"; |
| 2 | import { objTypeCode, encodeObjHeader, concatChunks } from "@/worker/git/core"; |
| 3 | import { asBufferSource, deflate } from "@/worker/common"; |
| 4 | |
| 5 | /** |
| 6 | * Builds a PACKv2 file from a list of thick objects (no deltas expected here). |
| 7 | * Shared between upload-pack assembly and DO hydration segment builder. |
| 8 | */ |
| 9 | export async function buildPackV2( |
| 10 | objs: { type: GitObjectType; payload: Uint8Array }[] |
| 11 | ): Promise<Uint8Array> { |
| 12 | // Header: 'PACK' + version (2) + number of objects (big-endian) |
| 13 | const hdr = new Uint8Array(12); |
| 14 | hdr.set(new TextEncoder().encode("PACK"), 0); |
| 15 | const dv = new DataView(hdr.buffer); |
| 16 | dv.setUint32(4, 2); // version 2 |
| 17 | dv.setUint32(8, objs.length); |
| 18 | |
| 19 | const parts: Uint8Array[] = [hdr]; |
| 20 | for (const o of objs) { |
| 21 | const typeCode = objTypeCode(o.type); |
| 22 | const head = encodeObjHeader(typeCode, o.payload.byteLength); |
| 23 | parts.push(head); |
| 24 | const comp = await deflate(o.payload); |
| 25 | parts.push(comp); |
| 26 | } |
| 27 | const body = concatChunks(parts); |
| 28 | const sha = new Uint8Array(await crypto.subtle.digest("SHA-1", asBufferSource(body))); |
| 29 | const out = new Uint8Array(body.length + 20); |
| 30 | out.set(body, 0); |
| 31 | out.set(sha, body.length); |
| 32 | return out; |
| 33 | } |