import { concatBytes } from "./pktline";
import { fromHex, toHex } from "../crypto";
const encoder = new TextEncoder();
export type GitObjectType = "commit" | "tree" | "blob" | "tag";
export type RawObject = { type: GitObjectType; content: Uint8Array; sha: string };
export type TreeItem = { mode: string; name: string; sha: string };
export type Signature = { name: string; email: string; timestamp: number; timezone: string };
const PACK_TYPE_CODES: Record<GitObjectType, number> = { commit: 1, tree: 2, blob: 3, tag: 4 };
const PACK_VERSION = 2;
const SIZE_LOW_BITS = 4;
const SIZE_LOW_MASK = 0x0f;
const SIZE_CONTINUATION_BITS = 7;
const SIZE_CONTINUATION_MASK = 0x7f;
const CONTINUATION_FLAG = 0x80;
export const TREE_MODE = "40000";
async function sha1(bytes: Uint8Array<ArrayBuffer>): Promise<string> {
return toHex(await crypto.subtle.digest("SHA-1", bytes));
}
export async function makeObject(type: GitObjectType, content: Uint8Array): Promise<RawObject> {
const header = encoder.encode(`${type} ${content.byteLength}\0`);
return { type, content, sha: await sha1(concatBytes([header, content])) };
}
export function makeBlob(content: Uint8Array | string): Promise<RawObject> {
return makeObject("blob", typeof content === "string" ? encoder.encode(content) : content);
}
function treeSortKey(item: TreeItem): string {
return item.mode === TREE_MODE ? `${item.name}/` : item.name;
}
function compareBytes(left: string, right: string): number {
const leftBytes = encoder.encode(left);
const rightBytes = encoder.encode(right);
const length = Math.min(leftBytes.byteLength, rightBytes.byteLength);