Skip to content
File

Blob: src/worker/git/core/object-parse.ts

typescript70 lines
1/**
2 * Shared Git object parsing helpers
3 */
4 
5import { parseGitObject, type GitObjectType } from "./objects";
6import { parseCommitText } from "./commitParse";
7import { createInflateStream, bytesToHex, createBlobFromBytes } from "@/worker/common";
8 
9const td = new TextDecoder();
10 
11/**
12 * Inflate a zlib-compressed Git object (with header) and return its type and payload.
13 * Returns null on error.
14 */
15export async function inflateAndParseHeader(
16 zdata: Uint8Array
17): Promise<{ type: GitObjectType; payload: Uint8Array } | null> {
18 try {
19 const stream = createBlobFromBytes(zdata).stream().pipeThrough(createInflateStream());
20 const raw = new Uint8Array(await new Response(stream).arrayBuffer());
21 const { type, payload } = parseGitObject(raw);
22 return { type, payload };
23 } catch {
24 return null;
25 }
26}
27 
28/**
29 * Parse commit payload to extract referenced OIDs: tree and parents.
30 */
31export function parseCommitRefs(payload: Uint8Array): { tree?: string; parents: string[] } {
32 const text = td.decode(payload);
33 const { tree, parents } = parseCommitText(text);
34 return { tree, parents };
35}
36 
37/**
38 * Parse a tree payload and return child object OIDs.
39 * Git tree format: "<mode> <name>\0<20-byte-oid>" repeated.
40 */
41export function parseTreeChildOids(payload: Uint8Array): string[] {
42 const out: string[] = [];
43 let i = 0;
44 while (i < payload.length) {
45 let sp = i;
46 while (sp < payload.length && payload[sp] !== 0x20) sp++;
47 if (sp >= payload.length) break;
48 let nul = sp + 1;
49 while (nul < payload.length && payload[nul] !== 0x00) nul++;
50 if (nul + 20 > payload.length) break;
51 const oidBytes = payload.subarray(nul + 1, nul + 21);
52 out.push(bytesToHex(oidBytes));
53 i = nul + 21;
54 }
55 return out;
56}
57 
58/**
59 * Parse annotated tag payload to extract its target OID and type.
60 */
61export function parseTagTarget(
62 payload: Uint8Array
63): { targetOid: string; targetType: GitObjectType } | null {
64 const text = td.decode(payload);
65 const mObj = text.match(/^object\s+([0-9a-f]{40})/m);
66 const mType = text.match(/^type\s+(commit|tree|blob|tag)/m);
67 if (!mObj || !mType) return null;
68 return { targetOid: mObj[1].toLowerCase(), targetType: mType[1] as GitObjectType };
69}