git-fs-s3 0.8.0 → 0.9.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 CHANGED
@@ -247,9 +247,9 @@ Every client-supplied ref name in a push is validated with `isSafeFullRefName` (
247
247
  - **Branches** — `listBranches`, `createBranchFrom`, `deleteBranchByName`.
248
248
  - **Commits** — `commitFilesToBare` (write one or more files as a single commit against a branch, creating it if new), `deleteFileFromBare`, `authorNow`.
249
249
  - **Trees** — `upsertTree`/`deleteFromTree` (overlay blobs onto a tree, return the new root oid), `listTreeEntries`, `findTreeEntry`.
250
- - **History** — `getCommitLog`/`getCommitHistory` (cached, resumable commit-chain walks — reuses a previously-walked prefix instead of re-walking from HEAD), `getFileContent`/`getFileFromRef`/`getTreeFromRef`, `getFileHistory` (per-file commit history), `getLastCommitsForTree` (the "last commit" column on a directory listing, batched two-phase prefetch-then-resolve).
251
- - **Diff** — `getCommitDiff`/`getDiffBetweenRefs`, unified-diff patches via the `diff` package (optional peer dependency).
252
- - **Merge** — `analyzeMerge` (fast-forward/diverged pre-check — not a real content-conflict check, see its doc comment) and `fastForwardMerge`. Neither does a real (non-fast-forward) content merge — for that, see [`git-edge`](https://www.npmjs.com/package/git-edge)'s `threeWayMerge`, an object-level three-way merge with no worktree needed, built to compose with this package (same `{ fs, gitdir, cache? }` shape) without either importing the other.
250
+ - **History** — `getCommitLog`/`getCommitHistory` (memoized commit-chain walks; pages are slices of the deepest walk), `getFileContent`/`getTreeFromRef`, `getFileHistory` (per-file commit history), `getLastCommitsForTree` (the "last commit" column on a directory listing), `summarizeCommit`.
251
+ - **Diff** — `getCommitDiff` (a commit against its first parent) and `getDiffBetweenRefs` (a pull request's three-dot diff, against the merge base); unified patches via the `diff` package (optional peer dependency).
252
+ - **Merge** — `analyzeMerge` (fast-forward/diverged pre-check — not a real content-conflict check, see its doc comment) and `fastForwardMerge`. Neither does a real (non-fast-forward) content merge — for that, see [`git-edge`](https://www.npmjs.com/package/git-edge)'s `threeWayMerge`, an object-level three-way merge with no worktree needed, built on this package (same `{ fs, gitdir, cache? }` shape; it stores merges through `withPackedWrites`).
253
253
 
254
254
  ```typescript
255
255
  import { commitFilesToBare, authorNow, getCommitLog } from "git-fs-s3/ops";
package/dist/http.js CHANGED
@@ -88,11 +88,12 @@ async function listAllRefs(repo, defaultBranch) {
88
88
  oid: b.commit
89
89
  }));
90
90
  const defaultRef = branches.find((b) => b.isDefault);
91
- const headSymref = defaultRef ? `refs/heads/${defaultRef.name}` : await Promise.resolve(git.currentBranch({ ...repo, fullname: true })).then((cb) => cb ?? `refs/heads/${defaultBranch}`).catch(() => `refs/heads/${defaultBranch}`);
92
- const headOid = branchRefs.find((r) => r?.name === headSymref)?.oid ?? await git.resolveRef({ ...repo, ref: "HEAD" }).catch(() => null);
91
+ const current = defaultRef ? null : await git.currentBranch({ ...repo, fullname: true }).catch(() => void 0);
92
+ const headSymref = defaultRef ? `refs/heads/${defaultRef.name}` : current ?? `refs/heads/${defaultBranch}`;
93
+ const headOid = branchRefs.find((r) => r.name === headSymref)?.oid ?? (defaultRef || current ? null : await git.resolveRef({ ...repo, ref: "HEAD" }).catch(() => null));
93
94
  const refs = [];
94
95
  if (headOid) refs.push({ name: "HEAD", oid: headOid });
95
- for (const r of branchRefs) if (r) refs.push(r);
96
+ refs.push(...branchRefs);
96
97
  for (const r of tagRefs) if (r) refs.push(r);
97
98
  return { refs, headSymref };
98
99
  }
@@ -935,6 +936,7 @@ export {
935
936
  listAllRefs,
936
937
  parsePktLines,
937
938
  parseReceivePackBody,
939
+ parseUploadPackRequest,
938
940
  pktLine,
939
941
  pktLineBuffer,
940
942
  rawFs,
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/http/info-refs.ts","../src/http/pkt-line.ts","../src/http/reachability.ts","../src/http/receive-pack.ts","../src/http/repack.ts","../src/http/pack-reuse.ts","../src/http/upload-pack.ts"],"sourcesContent":["import git from \"isomorphic-git\";\nimport { concat } from \"../edge-utils.js\";\nimport {\n\tlistBranches,\n\tlistLooseRefNames,\n\tresolveLooseRefFast,\n} from \"../ops/branch.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { FLUSH, pktLine } from \"./pkt-line.js\";\nimport { type GitHttpResult, type HttpHooks, runStep } from \"./types.js\";\n\nexport type GitService = \"git-upload-pack\" | \"git-receive-pack\";\n\n/** All refs with resolved oids, plus the symref HEAD should advertise. */\nexport async function listAllRefs(repo: Repo, defaultBranch: string) {\n\tconst [branches, tagNames] = await Promise.all([\n\t\tlistBranches(repo),\n\t\tlistLooseRefNames(repo, \"refs/tags\").then(\n\t\t\t(names) => names ?? git.listTags(repo),\n\t\t),\n\t]);\n\tconst tagRefs = await Promise.all(\n\t\ttagNames.map(async (tag) => {\n\t\t\tconst name = `refs/tags/${tag}`;\n\t\t\treturn resolveLooseRefFast(repo, name)\n\t\t\t\t.then((oid) => ({ name, oid }))\n\t\t\t\t.catch(() => null);\n\t\t}),\n\t);\n\tconst branchRefs = branches.map((b) => ({\n\t\tname: `refs/heads/${b.name}`,\n\t\toid: b.commit,\n\t}));\n\tconst defaultRef = branches.find((b) => b.isDefault);\n\tconst headSymref = defaultRef\n\t\t? `refs/heads/${defaultRef.name}`\n\t\t: await Promise.resolve(git.currentBranch({ ...repo, fullname: true }))\n\t\t\t\t.then((cb) => cb ?? `refs/heads/${defaultBranch}`)\n\t\t\t\t.catch(() => `refs/heads/${defaultBranch}`);\n\n\t// HEAD in a bare repo is almost always a symref to a branch whose oid\n\t// branchRefs already resolved above with one direct GET each — reuse it\n\t// instead of a second, separate resolveRef(\"HEAD\") call. isomorphic-git's\n\t// ref resolution runs its full multi-candidate expansion (refs/%s,\n\t// refs/tags/%s, refs/heads/%s, refs/remotes/%s, refs/remotes/%s/HEAD)\n\t// even when the symref target is already fully qualified, which used to\n\t// cost several guaranteed-404 R2 reads on every clone/fetch. Falls back\n\t// to the slow-but-correct path only when that lookup misses: detached\n\t// HEAD (points at a raw sha, not a symref) or a symref to a branch that\n\t// doesn't exist yet (freshly initialized, still-empty repo).\n\tconst headOid =\n\t\tbranchRefs.find((r) => r?.name === headSymref)?.oid ??\n\t\t(await git.resolveRef({ ...repo, ref: \"HEAD\" }).catch(() => null));\n\n\tconst refs: Array<{ name: string; oid: string }> = [];\n\tif (headOid) refs.push({ name: \"HEAD\", oid: headOid });\n\tfor (const r of branchRefs) if (r) refs.push(r);\n\tfor (const r of tagRefs) if (r) refs.push(r);\n\n\treturn { refs, headSymref };\n}\n\nexport interface InfoRefsOptions {\n\tservice: GitService;\n\t/** Advertised as HEAD when HEAD itself doesn't name an existing branch. */\n\tdefaultBranch: string;\n\t/** Advertised in the agent capability. Default \"git-fs-s3\". */\n\tagent?: string;\n}\n\n/**\n * `GET …/info/refs?service=…` — the ref advertisement. Authentication and\n * authorization are the caller's job before invoking this.\n *\n * Capabilities advertised match what the sibling handlers implement:\n * side-band-64k (honored by handleUploadPack's response framing — clients\n * like isomorphic-git unconditionally expect it), tip/reachable sha1 wants,\n * delete-refs and report-status for pushes.\n */\nexport async function handleInfoRefs(\n\trepo: Repo,\n\toptions: InfoRefsOptions,\n\thooks?: HttpHooks,\n): Promise<GitHttpResult> {\n\tconst { service } = options;\n\tconst agent = options.agent ?? \"git-fs-s3\";\n\tconst { refs, headSymref } = await runStep(hooks, \"listAllRefs\", () =>\n\t\tlistAllRefs(repo, options.defaultBranch),\n\t);\n\n\tconst isUpload = service === \"git-upload-pack\";\n\tconst caps = isUpload\n\t\t? `no-progress side-band-64k symref=HEAD:${headSymref} allow-tip-sha1-in-want allow-reachable-sha1-in-want agent=${agent}`\n\t\t: `report-status delete-refs side-band-64k agent=${agent}`;\n\n\tconst parts: Uint8Array[] = [pktLine(`# service=${service}\\n`), FLUSH];\n\n\tif (refs.length === 0) {\n\t\t// Empty repo: git needs this exact sentinel\n\t\tparts.push(\n\t\t\tpktLine(\n\t\t\t\t`0000000000000000000000000000000000000000 capabilities^{}\\0${caps}\\n`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\tlet first = true;\n\t\tfor (const { name, oid } of refs) {\n\t\t\tparts.push(\n\t\t\t\tpktLine(first ? `${oid} ${name}\\0${caps}\\n` : `${oid} ${name}\\n`),\n\t\t\t);\n\t\t\tfirst = false;\n\t\t}\n\t}\n\tparts.push(FLUSH);\n\n\treturn {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": `application/x-${service}-advertisement`,\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t},\n\t\tbody: concat(...parts),\n\t};\n}\n","/**\n * Git pkt-line framing (smart HTTP protocol wire format).\n *\n * Edge-compatible: uses Uint8Array instead of Buffer.\n */\n\nimport { concat, decodeAscii, decodeUtf8, encodeUtf8 } from \"../edge-utils.js\";\n\n/** Flush packet: exactly four zero bytes. */\nexport const FLUSH: Uint8Array<ArrayBuffer> = new Uint8Array([\n\t0x30, 0x30, 0x30, 0x30,\n]); // \"0000\"\n\n/** Frame a UTF-8 string as one pkt-line. */\nexport function pktLine(data: string): Uint8Array<ArrayBuffer> {\n\tconst body = encodeUtf8(data);\n\tconst len = (body.length + 4).toString(16).padStart(4, \"0\");\n\treturn concat(encodeUtf8(len), body);\n}\n\n/** Frame raw bytes as one pkt-line. */\nexport function pktLineBuffer(body: Uint8Array): Uint8Array<ArrayBuffer> {\n\tconst len = (body.length + 4).toString(16).padStart(4, \"0\");\n\treturn concat(encodeUtf8(len), body);\n}\n\n/** Decode pkt-lines to strings; `null` marks a flush-pkt. Stops on garbage. */\nexport function parsePktLines(buf: Uint8Array): Array<string | null> {\n\tconst lines: Array<string | null> = [];\n\tlet pos = 0;\n\twhile (pos + 4 <= buf.length) {\n\t\tconst len = Number.parseInt(decodeAscii(buf.subarray(pos, pos + 4)), 16);\n\t\tif (len === 0) {\n\t\t\tlines.push(null);\n\t\t\tpos += 4;\n\t\t} else if (len >= 4) {\n\t\t\tlines.push(decodeUtf8(buf.subarray(pos + 4, pos + len)));\n\t\t\tpos += len;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn lines;\n}\n\n/**\n * Per the git protocol, once side-band-64k has been negotiated, packfile\n * bytes in the upload-pack response must be chunked into pkt-lines each\n * prefixed with a control byte (0x01 = packfile data), terminated by a\n * flush-pkt. Without this, clients that don't special-case \"no side-band\" —\n * e.g. isomorphic-git's GitSideBand.demux, which always treats the response\n * as side-band-framed — misparse the raw packfile bytes as bogus pkt-line\n * length headers and spin forever. (Native `git` tolerates a raw unframed\n * stream when side-band isn't negotiated, so this only surfaces with\n * isomorphic-git as the HTTP client.)\n */\nconst SIDE_BAND_MAX_CHUNK = 65515;\n\nexport function sideBandPackfile(\n\tpackData: Uint8Array,\n): Uint8Array<ArrayBuffer> {\n\tconst parts: Uint8Array[] = [];\n\tfor (\n\t\tlet offset = 0;\n\t\toffset < packData.length;\n\t\toffset += SIDE_BAND_MAX_CHUNK\n\t) {\n\t\tconst chunk = packData.subarray(offset, offset + SIDE_BAND_MAX_CHUNK);\n\t\tparts.push(pktLineBuffer(concat(new Uint8Array([1]), chunk)));\n\t}\n\tparts.push(FLUSH);\n\treturn concat(...parts);\n}\n","import git from \"isomorphic-git\";\nimport type { Repo } from \"../ops/types.js\";\nimport type { HttpHooks } from \"./types.js\";\n\nexport interface ReachabilityResult {\n\toids: string[];\n\t/**\n\t * False if any object in the graph couldn't be read — repack uses this\n\t * (not a raw object-count comparison) to decide whether it's safe to\n\t * delete old packs: counts alone can't distinguish \"everything read fine\"\n\t * from \"some objects silently failed\".\n\t */\n\tcomplete: boolean;\n}\n\nconst delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * A read landing in the gap between a repack's new consolidated pack being\n * uploaded and the stale-pack cleanup finishing can transiently miss an\n * object that is not actually lost — it exists in the new pack the whole\n * time; the reader's cached pack listing was just taken mid-transition. One\n * retry after a short delay is enough to observe the consistent listing.\n */\nconst MISSING_OBJECT_RETRY_DELAY_MS = 200;\n\n/**\n * Walk the object graph from `startOids`, returning every reachable oid.\n * Concurrent traversal paths are deduplicated promise-per-oid; a missing\n * object is retried once, then reported through `hooks.onWarn` and\n * reflected in `complete: false`.\n *\n * `haveOids` bounds the walk: any oid in this set is assumed already\n * verified (it was reachable from a ref that existed before this call) and\n * is recorded in `seen` without being read or descended into. Without a\n * boundary, every call re-walks the *entire* history from scratch — for\n * receive-pack validation (see receive-pack.ts) that means every push pays\n * for reading every object in the repo, not just the ones it introduced,\n * and one transient read failure anywhere in that whole history rejects an\n * otherwise-valid push.\n *\n * Commits, trees and tags are read once each (parsed). Blobs have no\n * children, so `verifyBlobs: false` records a blob from its tree entry\n * without reading (and inflating) it — for callers that read every blob\n * themselves afterwards anyway, like upload-pack's `packObjects`. Leave it\n * true wherever the walk *is* the existence check (receive-pack, repack).\n */\nexport async function collectReachableOids(\n\trepo: Repo,\n\tstartOids: string[],\n\thooks?: HttpHooks,\n\thaveOids?: ReadonlySet<string> | readonly string[],\n\toptions?: { verifyBlobs?: boolean },\n): Promise<ReachabilityResult> {\n\tconst verifyBlobs = options?.verifyBlobs ?? true;\n\tconst have = haveOids instanceof Set ? haveOids : new Set(haveOids ?? []);\n\tconst seen = new Set<string>();\n\tlet complete = true;\n\tconst promises = new Map<string, Promise<void>>();\n\n\tasync function readAndVisitChildren(oid: string): Promise<void> {\n\t\tconst obj = await git.readObject({ ...repo, oid });\n\t\tseen.add(oid);\n\t\tconst children: [string, string | undefined][] = [];\n\t\tif (obj.type === \"commit\") {\n\t\t\tconst commit = obj.object as { tree: string; parent: string[] };\n\t\t\tchildren.push([commit.tree, \"tree\"]);\n\t\t\tfor (const parent of commit.parent) children.push([parent, \"commit\"]);\n\t\t} else if (obj.type === \"tree\") {\n\t\t\tconst tree = obj.object as { oid: string; type: string }[];\n\t\t\tfor (const entry of tree) {\n\t\t\t\t// Gitlinks (submodules, mode 160000) point at commits in another\n\t\t\t\t// repository; git never stores them here, so following one would\n\t\t\t\t// report a \"missing\" object and fail every walk over that history.\n\t\t\t\tif (entry.type === \"commit\") continue;\n\t\t\t\tchildren.push([entry.oid, entry.type]);\n\t\t\t}\n\t\t} else if (obj.type === \"tag\") {\n\t\t\tchildren.push([(obj.object as { object: string }).object, undefined]);\n\t\t}\n\t\tawait Promise.all(children.map(([child, type]) => visit(child, type)));\n\t}\n\n\tfunction visit(oid: string, type?: string): Promise<void> {\n\t\tconst existing = promises.get(oid);\n\t\tif (existing) return existing;\n\n\t\tif (have.has(oid) || (type === \"blob\" && !verifyBlobs)) {\n\t\t\tseen.add(oid);\n\t\t\tconst p = Promise.resolve();\n\t\t\tpromises.set(oid, p);\n\t\t\treturn p;\n\t\t}\n\n\t\tconst p = (async () => {\n\t\t\ttry {\n\t\t\t\tawait readAndVisitChildren(oid);\n\t\t\t} catch {\n\t\t\t\ttry {\n\t\t\t\t\tawait delay(MISSING_OBJECT_RETRY_DELAY_MS);\n\t\t\t\t\tawait readAndVisitChildren(oid);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tcomplete = false;\n\t\t\t\t\thooks?.onWarn?.(`missing object ${oid}`, err);\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\tpromises.set(oid, p);\n\t\treturn p;\n\t}\n\n\tawait Promise.all(startOids.map((oid) => visit(oid)));\n\treturn { oids: Array.from(seen), complete };\n}\n\n/**\n * Commit-only ancestry walk: every commit reachable from `startOids`\n * (annotated tags peeled), stopping at — and not descending into — commits in\n * `stopAt`. Reads commit objects only, never trees or blobs, so it costs a\n * fraction of {@link collectReachableOids} over the same history. Start oids\n * that don't exist (or aren't commits/tags) are skipped. Returns the commits\n * walked and the `stopAt` commits the walk ran into.\n */\nexport async function collectCommitAncestry(\n\trepo: Repo,\n\tstartOids: readonly string[],\n\tstopAt?: ReadonlySet<string>,\n): Promise<{ commits: Set<string>; boundary: Set<string> }> {\n\tconst commits = new Set<string>();\n\tconst boundary = new Set<string>();\n\tconst queued = new Set<string>();\n\tlet frontier = [...new Set(startOids)];\n\tconst BATCH = 50;\n\twhile (frontier.length > 0) {\n\t\tconst next: string[] = [];\n\t\tfor (let i = 0; i < frontier.length; i += BATCH) {\n\t\t\tawait Promise.all(\n\t\t\t\tfrontier.slice(i, i + BATCH).map(async (oid) => {\n\t\t\t\t\tif (stopAt?.has(oid)) {\n\t\t\t\t\t\tboundary.add(oid);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst object = await git\n\t\t\t\t\t\t.readObject({ ...repo, oid })\n\t\t\t\t\t\t.catch(() => null);\n\t\t\t\t\tif (object?.type === \"tag\") {\n\t\t\t\t\t\tconst target = (object.object as { object: string }).object;\n\t\t\t\t\t\tif (!queued.has(target)) {\n\t\t\t\t\t\t\tqueued.add(target);\n\t\t\t\t\t\t\tnext.push(target);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (object?.type !== \"commit\") return;\n\t\t\t\t\tcommits.add(oid);\n\t\t\t\t\tfor (const parent of (object.object as { parent: string[] }).parent) {\n\t\t\t\t\t\tif (!queued.has(parent)) {\n\t\t\t\t\t\t\tqueued.add(parent);\n\t\t\t\t\t\t\tnext.push(parent);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tfrontier = next;\n\t}\n\treturn { commits, boundary };\n}\n","import git from \"isomorphic-git\";\nimport { concat, decodeAscii, decodeUtf8 } from \"../edge-utils.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { storePack } from \"../pack-write.js\";\nimport { isSafeFullRefName } from \"../refs.js\";\nimport { FLUSH, pktLine, sideBandPackfile } from \"./pkt-line.js\";\nimport { collectReachableOids } from \"./reachability.js\";\nimport { type RepackOptions, repackRepository } from \"./repack.js\";\nimport { type GitHttpResult, type HttpHooks, rawFs, runStep } from \"./types.js\";\n\nconst ZERO_OID = \"0\".repeat(40);\nconst OID_RE = /^[0-9a-f]{40}$/;\n\nexport interface RefUpdateCommand {\n\toldOid: string;\n\tnewOid: string;\n\trefName: string;\n}\n\nexport interface RefUpdateResult {\n\trefName: string;\n\tok: boolean;\n\treason?: string;\n}\n\nexport interface ParsedReceivePack {\n\trefUpdates: RefUpdateCommand[];\n\tpackData: Uint8Array;\n\t/** Capabilities the client asked for on its first command line. */\n\tcapabilities: string[];\n}\n\n/**\n * Split a receive-pack body: pkt-line ref commands, flush, then raw PACK.\n * A command whose oids aren't 40 lowercase hex digits is dropped — it can\n * never be applied, and its oids would otherwise reach object-path lookups.\n */\nexport function parseReceivePackBody(body: Uint8Array): ParsedReceivePack {\n\tconst refUpdates: RefUpdateCommand[] = [];\n\tlet capabilities: string[] | undefined;\n\tlet pos = 0;\n\twhile (pos + 4 <= body.length) {\n\t\tconst len = Number.parseInt(decodeAscii(body.subarray(pos, pos + 4)), 16);\n\t\tif (len === 0) {\n\t\t\tpos += 4;\n\t\t\tbreak; // flush = end of ref update commands\n\t\t}\n\t\tif (len < 4) break;\n\t\t// The first command line carries NUL-separated capabilities.\n\t\tconst [line, caps] = decodeUtf8(body.subarray(pos + 4, pos + len))\n\t\t\t.replace(/\\n$/, \"\")\n\t\t\t.split(\"\\0\");\n\t\tif (capabilities === undefined) {\n\t\t\tcapabilities = (caps ?? \"\").split(\" \").filter(Boolean);\n\t\t}\n\t\tpos += len;\n\t\tconst [oldOid, newOid, refName] = (line ?? \"\").split(\" \");\n\t\tif (\n\t\t\toldOid &&\n\t\t\tnewOid &&\n\t\t\trefName &&\n\t\t\tOID_RE.test(oldOid) &&\n\t\t\tOID_RE.test(newOid)\n\t\t) {\n\t\t\trefUpdates.push({ oldOid, newOid, refName });\n\t\t}\n\t}\n\treturn {\n\t\trefUpdates,\n\t\tpackData: body.subarray(pos),\n\t\tcapabilities: capabilities ?? [],\n\t};\n}\n\n/** Initialize the repo when its HEAD doesn't exist yet (first push). */\nexport async function ensureRepoInitialized(\n\trepo: Repo,\n\tdefaultBranch: string,\n): Promise<void> {\n\tconst fsp = rawFs(repo);\n\ttry {\n\t\tawait fsp.stat(`${repo.gitdir}/HEAD`);\n\t} catch {\n\t\tawait fsp.mkdir(repo.gitdir, { recursive: true }).catch(() => {});\n\t\tawait git.init({ ...repo, dir: repo.gitdir, defaultBranch, bare: true });\n\t}\n}\n\n/** Write the incoming PACK into objects/pack/ and index it. */\nexport async function indexIncomingPack(\n\trepo: Repo,\n\tpackData: Uint8Array,\n\thooks?: HttpHooks,\n): Promise<string[]> {\n\tif (packData.length < 4) return [];\n\tconst packName = await runStep(\n\t\thooks,\n\t\t\"write + indexPack incoming pack\",\n\t\tasync () => {\n\t\t\t// Named by checksum (`pack-<sha>`), stored pack first, index last.\n\t\t\tconst { base } = await storePack(repo, packData);\n\t\t\treturn base;\n\t\t},\n\t);\n\treturn [\n\t\t`${repo.gitdir}/objects/pack/${packName}.pack`,\n\t\t`${repo.gitdir}/objects/pack/${packName}.idx`,\n\t];\n}\n\n/**\n * Validate a ref name and compare-and-swap it against its claimed current\n * oid. Returns the failure result to report if either check fails, or\n * `null` when both pass — shared by the preflight check (`validateRefUpdates`,\n * run before the possibly-slow pack indexing/graph-walk work, purely to\n * avoid doing that work for an update already doomed to fail) and the real\n * atomicity guarantee (`applyRefUpdates`, run again right before writing,\n * since a concurrent push could have moved the ref in the time that work\n * took).\n */\nasync function checkRefCas(\n\trepo: Repo,\n\trefName: string,\n\toldOid: string,\n): Promise<RefUpdateResult | null> {\n\tif (!isSafeFullRefName(refName)) {\n\t\treturn { refName, ok: false, reason: \"invalid ref name\" };\n\t}\n\tconst currentOid = await git\n\t\t.resolveRef({ ...repo, ref: refName })\n\t\t.catch(() => ZERO_OID);\n\treturn currentOid === oldOid\n\t\t? null\n\t\t: {\n\t\t\t\trefName,\n\t\t\t\tok: false,\n\t\t\t\treason: \"non-fast-forward, ref updated by another push\",\n\t\t\t};\n}\n\n/** Every branch/tag tip currently in the repo, as a validation boundary — see\n * its call site in {@link applyReceivePack}. */\nasync function collectExistingRefTips(repo: Repo): Promise<Set<string>> {\n\tconst [branches, tags] = await Promise.all([\n\t\tgit.listBranches(repo),\n\t\tgit.listTags(repo),\n\t]);\n\tconst refs = [\n\t\t...branches.map((b) => `refs/heads/${b}`),\n\t\t...tags.map((t) => `refs/tags/${t}`),\n\t];\n\tconst oids = await Promise.all(\n\t\trefs.map((ref) => git.resolveRef({ ...repo, ref }).catch(() => null)),\n\t);\n\treturn new Set(oids.filter((oid): oid is string => oid !== null));\n}\n\n/** The branch HEAD names, or null when HEAD is detached/unreadable. */\nasync function currentBranchRef(repo: Repo): Promise<string | null> {\n\treturn git\n\t\t.currentBranch({ ...repo, fullname: true })\n\t\t.then((ref) => ref ?? null)\n\t\t.catch(() => null);\n}\n\nasync function validateRefUpdates(\n\trepo: Repo,\n\trefUpdates: RefUpdateCommand[],\n): Promise<RefUpdateResult[]> {\n\tconst headRef = await currentBranchRef(repo);\n\tconst seen = new Set<string>();\n\treturn Promise.all(\n\t\trefUpdates.map(async ({ oldOid, newOid, refName }) => {\n\t\t\t// Two commands for one ref can't both be compare-and-swapped.\n\t\t\tif (seen.has(refName)) {\n\t\t\t\treturn { refName, ok: false, reason: \"duplicate ref update\" };\n\t\t\t}\n\t\t\tseen.add(refName);\n\t\t\t// Same rule as git's receive.denyDeleteCurrent: deleting the\n\t\t\t// branch HEAD names leaves every clone without a default branch.\n\t\t\tif (newOid === ZERO_OID && refName === headRef) {\n\t\t\t\treturn {\n\t\t\t\t\trefName,\n\t\t\t\t\tok: false,\n\t\t\t\t\treason: \"deletion of the current branch prohibited\",\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t(await checkRefCas(repo, refName, oldOid)) ?? { refName, ok: true }\n\t\t\t);\n\t\t}),\n\t);\n}\n\n/**\n * Apply ref updates, enforcing compare-and-swap against each command's\n * claimed oldOid. Every client-supplied refName is validated before any\n * filesystem call reads or writes through it.\n */\nexport async function applyRefUpdates(\n\trepo: Repo,\n\trefUpdates: RefUpdateCommand[],\n\thooks?: HttpHooks,\n): Promise<RefUpdateResult[]> {\n\treturn runStep(hooks, \"apply ref updates\", () =>\n\t\tPromise.all(\n\t\t\trefUpdates.map(async ({ oldOid, newOid, refName }) => {\n\t\t\t\tconst failure = await checkRefCas(repo, refName, oldOid);\n\t\t\t\tif (failure) return failure;\n\n\t\t\t\tif (newOid === ZERO_OID) {\n\t\t\t\t\tawait git.deleteRef({ ...repo, ref: refName }).catch(() => {});\n\t\t\t\t} else {\n\t\t\t\t\t// A branch must name a commit; a tag may name anything.\n\t\t\t\t\tif (refName.startsWith(\"refs/heads/\")) {\n\t\t\t\t\t\tconst { type } = await git\n\t\t\t\t\t\t\t.readObject({ ...repo, oid: newOid, format: \"content\" })\n\t\t\t\t\t\t\t.catch(() => ({ type: \"missing\" }));\n\t\t\t\t\t\tif (type !== \"commit\") {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\trefName,\n\t\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\t\treason: `branch must point at a commit, not a ${type}`,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tawait git.writeRef({\n\t\t\t\t\t\t...repo,\n\t\t\t\t\t\tref: refName,\n\t\t\t\t\t\tvalue: newOid,\n\t\t\t\t\t\tforce: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { refName, ok: true };\n\t\t\t}),\n\t\t),\n\t);\n}\n\n/**\n * The report-status response for a set of ref-update results — empty unless\n * the client asked for `report-status`, and side-band-64k framed when it\n * asked for that (git and isomorphic-git both do; isomorphic-git always\n * demuxes the response as side-band). `unpackError` reports a pack that\n * couldn't be stored or indexed.\n */\nexport function receivePackResponse(\n\tresults: RefUpdateResult[],\n\toptions?: { capabilities?: readonly string[]; unpackError?: string },\n): GitHttpResult {\n\tconst capabilities = options?.capabilities ?? [\"report-status\"];\n\tconst report = capabilities.includes(\"report-status\")\n\t\t? concat(\n\t\t\t\tpktLine(\n\t\t\t\t\toptions?.unpackError\n\t\t\t\t\t\t? `unpack ${options.unpackError}\\n`\n\t\t\t\t\t\t: \"unpack ok\\n\",\n\t\t\t\t),\n\t\t\t\t...results.map(({ refName, ok, reason }) =>\n\t\t\t\t\tpktLine(ok ? `ok ${refName}\\n` : `ng ${refName} ${reason}\\n`),\n\t\t\t\t),\n\t\t\t\tFLUSH,\n\t\t\t)\n\t\t: new Uint8Array();\n\tconst responseBody =\n\t\tcapabilities.includes(\"side-band-64k\") && report.length > 0\n\t\t\t? sideBandPackfile(report)\n\t\t\t: report;\n\n\treturn {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-git-receive-pack-result\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t},\n\t\tbody: responseBody,\n\t};\n}\n\nexport interface ApplyReceivePackOptions {\n\t/** HEAD's branch when a push initializes an empty repository. */\n\tdefaultBranch: string;\n\t/**\n\t * Repack tuning, or `false` to skip repacking entirely. The returned\n\t * `stalePackPaths` are gitdir-relative pack files the repack deleted from\n\t * this repo — after syncing to any secondary storage, delete them there\n\t * too.\n\t */\n\trepack?: RepackOptions | false;\n}\n\n/**\n * The storage half of a push against `repo`: initialize if needed, index the\n * incoming pack, CAS-apply ref updates, then repack when enough packs have\n * accumulated. Serialize concurrent pushes to the same repo externally (a\n * per-repo lock); build the HTTP response afterwards with\n * {@link receivePackResponse}.\n */\nexport interface ApplyReceivePackResult {\n\tresults: RefUpdateResult[];\n\tstalePackPaths: string[];\n\t/** Set when the incoming pack couldn't be stored or indexed. */\n\tunpackError?: string;\n}\n\nexport async function applyReceivePack(\n\trepo: Repo,\n\tparsed: { refUpdates: RefUpdateCommand[]; packData: Uint8Array },\n\toptions: ApplyReceivePackOptions,\n\thooks?: HttpHooks,\n): Promise<ApplyReceivePackResult> {\n\tawait ensureRepoInitialized(repo, options.defaultBranch);\n\tconst preflight = await validateRefUpdates(repo, parsed.refUpdates);\n\tconst acceptedUpdates = parsed.refUpdates.filter(\n\t\t(_, index) => preflight[index]?.ok,\n\t);\n\tconst fsp = rawFs(repo);\n\tconst packDir = `${repo.gitdir}/objects/pack`;\n\tconst existingPacks = new Set(\n\t\tawait fsp.readdir(packDir).catch(() => [] as string[]),\n\t);\n\tlet incomingPackPaths: string[];\n\ttry {\n\t\tincomingPackPaths = await indexIncomingPack(\n\t\t\trepo,\n\t\t\tacceptedUpdates.some((update) => update.newOid !== ZERO_OID)\n\t\t\t\t? parsed.packData\n\t\t\t\t: new Uint8Array(),\n\t\t\thooks,\n\t\t);\n\t} catch (err) {\n\t\thooks?.onWarn?.(\"receive-pack: incoming pack rejected\", err);\n\t\treturn {\n\t\t\tresults: preflight.map((result) =>\n\t\t\t\tresult.ok ? { ...result, ok: false, reason: \"unpacker error\" } : result,\n\t\t\t),\n\t\t\tstalePackPaths: [],\n\t\t\tunpackError: \"index-pack failed\",\n\t\t};\n\t}\n\t// A checksum-named pack identical to one already stored must survive the\n\t// cleanup below. Index first, so readers never see a half-removed pack.\n\tconst removableIncoming = incomingPackPaths\n\t\t.filter((path) => !existingPacks.has(path.slice(packDir.length + 1)))\n\t\t.sort((a, b) => Number(b.endsWith(\".idx\")) - Number(a.endsWith(\".idx\")));\n\n\tconst newTips = acceptedUpdates\n\t\t.filter((update) => update.newOid !== ZERO_OID)\n\t\t.map((update) => update.newOid);\n\tif (newTips.length > 0) {\n\t\t// Every oid reachable from an existing ref was already accepted by an\n\t\t// earlier push — not just the ref(s) this push happens to touch. A\n\t\t// brand-new branch (oldOid === ZERO_OID, so it has no pre-image of its\n\t\t// own) is the common case this matters for: creating a branch off an\n\t\t// existing one is still just one new commit's worth of new objects,\n\t\t// and shouldn't cost a walk of the entire repo history to validate.\n\t\tconst haveOids = await collectExistingRefTips(repo);\n\t\tfor (const update of acceptedUpdates) {\n\t\t\tif (update.oldOid !== ZERO_OID) haveOids.add(update.oldOid);\n\t\t}\n\t\tconst { complete } = await collectReachableOids(\n\t\t\trepo,\n\t\t\tnewTips,\n\t\t\thooks,\n\t\t\thaveOids,\n\t\t);\n\t\tif (!complete) {\n\t\t\tfor (const filepath of removableIncoming) {\n\t\t\t\tawait fsp.unlink(filepath).catch(() => {});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tresults: preflight.map((result) =>\n\t\t\t\t\tresult.ok\n\t\t\t\t\t\t? { ...result, ok: false, reason: \"incomplete object graph\" }\n\t\t\t\t\t\t: result,\n\t\t\t\t),\n\t\t\t\tstalePackPaths: [],\n\t\t\t};\n\t\t}\n\t}\n\n\tconst applied = await applyRefUpdates(repo, acceptedUpdates, hooks);\n\tconst results = preflight.map((result, index) =>\n\t\tresult.ok\n\t\t\t? (applied.find(\n\t\t\t\t\t(entry) => entry.refName === parsed.refUpdates[index]?.refName,\n\t\t\t\t) ?? result)\n\t\t\t: result,\n\t);\n\tconst repackOptions = options.repack;\n\tconst stalePackPaths =\n\t\trepackOptions === false || !results.some((result) => result.ok)\n\t\t\t? []\n\t\t\t: await runStep(hooks, \"repack\", () =>\n\t\t\t\t\trepackRepository(repo, repackOptions, hooks),\n\t\t\t\t);\n\treturn { results, stalePackPaths };\n}\n","/**\n * Pack consolidation: merge all packs into one, reusing stored (possibly\n * deltified) entries when every object is packed.\n *\n * Edge-compatible: uses Web Crypto (SHA-1), CompressionStream (deflate),\n * and Uint8Array throughout — no node:crypto, node:zlib, or Buffer.\n */\n\nimport git from \"isomorphic-git\";\nimport type { Repo } from \"../ops/types.js\";\nimport {\n\ttype PackFileName,\n\tpackFileName,\n\tparsePackDirectory,\n} from \"../pack-files.js\";\nimport {\n\tencodePack,\n\thashGitObject,\n\ttype PackObject,\n\ttype PackObjectType,\n\tpackBaseName,\n} from \"../pack-write.js\";\nimport { buildPackFromExistingPacks } from \"./pack-reuse.js\";\nimport { collectReachableOids } from \"./reachability.js\";\nimport { type HttpHooks, rawFs } from \"./types.js\";\n\n/**\n * Read every reachable object and independently re-derive its oid from the\n * bytes isomorphic-git handed back, instead of trusting the oid it was asked\n * for. isomorphic-git's *packed*-object read path never verifies the\n * resolved content's SHA-1 against the requested oid — only the\n * loose-object branch does.\n */\nasync function readAndVerifyObjects(\n\trepo: Repo,\n\toids: string[],\n): Promise<Map<string, PackObject>> {\n\tconst objects = new Map<string, PackObject>();\n\tconst BATCH_SIZE = 100;\n\tfor (let i = 0; i < oids.length; i += BATCH_SIZE) {\n\t\tconst batch = oids.slice(i, i + BATCH_SIZE);\n\t\tconst entries = await Promise.all(\n\t\t\tbatch.map(async (oid) => {\n\t\t\t\tconst { type, object } = await git.readObject({\n\t\t\t\t\t...repo,\n\t\t\t\t\toid,\n\t\t\t\t\tformat: \"content\",\n\t\t\t\t});\n\t\t\t\t// Own ArrayBuffer-backed copy: Web APIs (Blob, digest) reject\n\t\t\t\t// views that might sit on a SharedArrayBuffer.\n\t\t\t\tconst content = new Uint8Array(object as Uint8Array);\n\t\t\t\tconst actualOid = await hashGitObject(type, content);\n\t\t\t\tif (actualOid !== oid) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`repack: object ${oid} failed independent SHA-1 verification ` +\n\t\t\t\t\t\t\t`(recomputed ${actualOid}) — refusing to trust this read, aborting repack`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn { oid, type: type as PackObjectType, content };\n\t\t\t}),\n\t\t);\n\t\tfor (const { oid, type, content } of entries) {\n\t\t\tobjects.set(oid, { type, content });\n\t\t}\n\t}\n\treturn objects;\n}\n\n/**\n * Default repack threshold. Consolidating is O(total repo object count) —\n * so paying it on every push makes push latency grow with repo size forever.\n */\nexport const REPACK_PACK_COUNT_THRESHOLD = 4;\n\nasync function readPackDirectory(repo: Repo): Promise<PackFileName[]> {\n\tconst entries = await rawFs(repo)\n\t\t.readdir(`${repo.gitdir}/objects/pack`)\n\t\t.catch(() => [] as string[]);\n\treturn parsePackDirectory(entries);\n}\n\nasync function countPacks(repo: Repo): Promise<number> {\n\tconst files = await readPackDirectory(repo);\n\treturn files.filter((file) => file.kind === \"pack\").length;\n}\n\nexport interface RepackOptions {\n\t/** Skip repacking below this many accumulated packs. Default 4. */\n\tthreshold?: number;\n}\n\n/**\n * Consolidate all pack files into one, returning the gitdir-relative paths\n * of the old .pack/.idx files it removed — after syncing the new pack to any\n * secondary storage, delete those same paths there too.\n */\nexport async function repackRepository(\n\trepo: Repo,\n\toptions?: RepackOptions,\n\thooks?: HttpHooks,\n): Promise<string[]> {\n\tconst threshold = options?.threshold ?? REPACK_PACK_COUNT_THRESHOLD;\n\tconst fsp = rawFs(repo);\n\ttry {\n\t\tif ((await countPacks(repo)) < threshold) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst [branches, tags] = await Promise.all([\n\t\t\tgit.listBranches(repo),\n\t\t\tgit.listTags(repo),\n\t\t]);\n\t\tconst refNames = [\n\t\t\t...branches.map((b) => `refs/heads/${b}`),\n\t\t\t...tags.map((t) => `refs/tags/${t}`),\n\t\t];\n\t\tconst tipOids = (\n\t\t\tawait Promise.all(\n\t\t\t\trefNames.map((ref) =>\n\t\t\t\t\tgit.resolveRef({ ...repo, ref }).catch(() => null),\n\t\t\t\t),\n\t\t\t)\n\t\t).filter((oid): oid is string => oid !== null);\n\t\tif (tipOids.length === 0) return [];\n\n\t\t// Blobs aren't read here: indexPack below re-hashes every object the\n\t\t// new pack holds and the reachable-set check rejects a pack missing any,\n\t\t// so inflating every blob in history during the walk too would only\n\t\t// double the cost.\n\t\tconst { oids: reachable, complete } = await collectReachableOids(\n\t\t\trepo,\n\t\t\ttipOids,\n\t\t\thooks,\n\t\t\tundefined,\n\t\t\t{ verifyBlobs: false },\n\t\t);\n\t\tif (!complete || reachable.length === 0) return [];\n\n\t\tconst packDir = `${repo.gitdir}/objects/pack`;\n\t\t// Copy stored entries when everything is packed: keeps deltas, so\n\t\t// the consolidated pack is as compact as its sources. Loose objects\n\t\t// fall back to a verified, non-deltified rebuild.\n\t\tconst packBuffer =\n\t\t\t(await buildPackFromExistingPacks(repo, reachable)) ??\n\t\t\t(await (async () => {\n\t\t\t\tconst objects = await readAndVerifyObjects(repo, reachable);\n\t\t\t\treturn encodePack(\n\t\t\t\t\treachable.map((oid) => {\n\t\t\t\t\t\tconst object = objects.get(oid);\n\t\t\t\t\t\tif (!object) {\n\t\t\t\t\t\t\tthrow new Error(`repack: missing verified object for ${oid}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn object;\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t})());\n\n\t\tawait fsp.mkdir(packDir, { recursive: true });\n\t\tconst newBase = packBaseName(packBuffer);\n\t\tconst newPackFile = packFileName(newBase, \"pack\");\n\t\t// Checksum-named, so an identical pack may already be stored — never\n\t\t// delete that one on the abort path below.\n\t\tconst preexisting = (await readPackDirectory(repo)).some(\n\t\t\t(file) => file.base === newBase,\n\t\t);\n\t\tawait fsp.writeFile(`${packDir}/${newPackFile}`, packBuffer);\n\n\t\tconst { oids: indexedOids } = await git.indexPack({\n\t\t\t...repo,\n\t\t\tdir: packDir,\n\t\t\tfilepath: newPackFile,\n\t\t});\n\n\t\t// indexPack re-hashes every object it indexes, so this also verifies\n\t\t// the content. Reused packs may carry extra delta bases: superset is fine.\n\t\tconst indexed = new Set(indexedOids);\n\t\tif (reachable.some((oid) => !indexed.has(oid))) {\n\t\t\tif (!preexisting)\n\t\t\t\tawait Promise.all(\n\t\t\t\t\t([\"pack\", \"idx\"] as const).map((kind) =>\n\t\t\t\t\t\tfsp\n\t\t\t\t\t\t\t.unlink(`${packDir}/${packFileName(newBase, kind)}`)\n\t\t\t\t\t\t\t.catch(() => {}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\tthrow new Error(\n\t\t\t\t\"repack: indexed pack is missing reachable objects — aborting\",\n\t\t\t);\n\t\t}\n\n\t\tconst stale = (await readPackDirectory(repo)).filter(\n\t\t\t(file) => file.base !== newBase,\n\t\t);\n\t\t// Indexes first: readers find packs through their .idx, so a reader\n\t\t// listing mid-cleanup sees either a complete old pack or none of it.\n\t\tconst unlinkAll = (files: PackFileName[]) =>\n\t\t\tPromise.all(\n\t\t\t\tfiles.map((file) =>\n\t\t\t\t\tfsp.unlink(`${packDir}/${file.name}`).catch(() => {}),\n\t\t\t\t),\n\t\t\t);\n\t\tawait unlinkAll(stale.filter((file) => file.kind === \"idx\"));\n\t\tawait unlinkAll(stale.filter((file) => file.kind !== \"idx\"));\n\t\treturn stale.map((file) => `objects/pack/${file.name}`);\n\t} catch (err) {\n\t\thooks?.onWarn?.(\"repack failed (non-fatal)\", err);\n\t\treturn [];\n\t}\n}\n","/**\n * Build a packfile by copying already-compressed entries out of existing\n * packs (\"pack reuse\"), instead of inflating and re-deflating every object.\n *\n * Entries keep their stored form, deltas included, so the output is as\n * compact as the packs it came from. `OFS_DELTA` entries are rewritten as\n * `REF_DELTA` (base named by oid), since offsets don't survive the move into\n * a new pack; delta bases are always included and written before the deltas\n * that use them. Formats: gitformat-pack(5).\n *\n * Edge-compatible: Web Crypto SHA-1 and Uint8Array only.\n */\n\nimport { concat, encodeUtf8, fromHex, sha1, toHex } from \"../edge-utils.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { packFileName, parsePackDirectory } from \"../pack-files.js\";\nimport { rawFs } from \"./types.js\";\n\nconst OBJ_OFS_DELTA = 6;\nconst OBJ_REF_DELTA = 7;\nconst OID_BYTES = 20;\nconst PACK_TRAILER_BYTES = 20;\n\nconst IDX_V2 = {\n\tmagic: 0xff744f63,\n\tversion: 2,\n\theaderBytes: 8,\n\tfanoutEntries: 256,\n\t/** Offsets with this bit set index the 64-bit large-offset table. */\n\tlargeOffsetFlag: 0x80000000,\n} as const;\n\n/** One object's stored entry inside a pack. */\ninterface PackEntry {\n\treadonly pack: Uint8Array;\n\treadonly start: number;\n\treadonly end: number;\n}\n\n/** Every object stored in a pack, by oid, plus its offset → oid inverse. */\ninterface IndexedPack {\n\treadonly entries: Map<string, PackEntry>;\n\treadonly oidAtOffset: Map<number, string>;\n}\n\n/** An object's position in a pack, as listed by its `.idx`. */\nexport interface PackIndexEntry {\n\treadonly oid: string;\n\treadonly offset: number;\n}\n\n/** Entries of a version-2 `.idx`; `null` for any other format. */\nexport function readPackIndex(idx: Uint8Array): PackIndexEntry[] | null {\n\tconst view = new DataView(idx.buffer, idx.byteOffset, idx.byteLength);\n\tconst namesStart = IDX_V2.headerBytes + IDX_V2.fanoutEntries * 4;\n\tif (\n\t\tidx.byteLength < namesStart ||\n\t\tview.getUint32(0) !== IDX_V2.magic ||\n\t\tview.getUint32(4) !== IDX_V2.version\n\t) {\n\t\treturn null;\n\t}\n\t// The last fanout slot counts every object in the pack.\n\tconst count = view.getUint32(namesStart - 4);\n\tconst crcStart = namesStart + count * OID_BYTES;\n\tconst offsetsStart = crcStart + count * 4;\n\tif (idx.byteLength < offsetsStart + count * 4) return null;\n\n\tconst entries: PackIndexEntry[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tconst offset = view.getUint32(offsetsStart + i * 4);\n\t\t// Packs over 2 GiB never reach this in-memory path; let the caller\n\t\t// fall back instead of half-supporting the large-offset table.\n\t\tif (offset & IDX_V2.largeOffsetFlag) return null;\n\t\tconst at = namesStart + i * OID_BYTES;\n\t\tentries.push({ oid: toHex(idx.subarray(at, at + OID_BYTES)), offset });\n\t}\n\treturn entries;\n}\n\n/** Locate every entry of `pack` using its `.idx`. */\nfunction indexPack(idx: Uint8Array, pack: Uint8Array): IndexedPack | null {\n\tconst located = readPackIndex(idx);\n\tif (!located) return null;\n\n\t// An entry runs until the next entry's offset (or the pack trailer).\n\tlocated.sort((a, b) => a.offset - b.offset);\n\tconst entries = new Map<string, PackEntry>();\n\tconst oidAtOffset = new Map<number, string>();\n\tconst packEnd = pack.byteLength - PACK_TRAILER_BYTES;\n\tfor (let i = 0; i < located.length; i++) {\n\t\tconst { oid, offset } = located[i] as PackIndexEntry;\n\t\tconst end = located[i + 1]?.offset ?? packEnd;\n\t\tentries.set(oid, { pack, start: offset, end });\n\t\toidAtOffset.set(offset, oid);\n\t}\n\treturn { entries, oidAtOffset };\n}\n\n/** The variable-length type/size header that starts every pack entry. */\ninterface EntryHeader {\n\treadonly type: number;\n\treadonly size: number;\n\t/** Bytes the header occupies. */\n\treadonly length: number;\n}\n\nfunction readEntryHeader(bytes: Uint8Array, start: number): EntryHeader {\n\tlet byte = bytes[start] as number;\n\tconst type = (byte >> 4) & 0b111;\n\tlet size = byte & 0b1111;\n\tlet shift = 4;\n\tlet at = start + 1;\n\twhile (byte & 0x80) {\n\t\tbyte = bytes[at++] as number;\n\t\tsize += (byte & 0x7f) * 2 ** shift;\n\t\tshift += 7;\n\t}\n\treturn { type, size, length: at - start };\n}\n\nfunction encodeEntryHeader(type: number, size: number): Uint8Array {\n\tconst bytes: number[] = [];\n\tlet rest = Math.floor(size / 16);\n\tbytes.push((rest > 0 ? 0x80 : 0) | (type << 4) | (size % 16));\n\twhile (rest > 0) {\n\t\tconst low = rest % 128;\n\t\trest = Math.floor(rest / 128);\n\t\tbytes.push((rest > 0 ? 0x80 : 0) | low);\n\t}\n\treturn new Uint8Array(bytes);\n}\n\n/** `OFS_DELTA`'s negative base offset: big-endian base-128 with +1 carries. */\nfunction readOfsDeltaOffset(\n\tbytes: Uint8Array,\n\tstart: number,\n): { distance: number; length: number } {\n\tlet at = start;\n\tlet byte = bytes[at++] as number;\n\tlet distance = byte & 0x7f;\n\twhile (byte & 0x80) {\n\t\tbyte = bytes[at++] as number;\n\t\tdistance = (distance + 1) * 128 + (byte & 0x7f);\n\t}\n\treturn { distance, length: at - start };\n}\n\n/** A pack entry ready to copy, with the oid of its delta base if any. */\ninterface ReusableEntry {\n\treadonly bytes: Uint8Array;\n\treadonly baseOid: string | null;\n}\n\n/** Copy one entry, rewriting `OFS_DELTA` to `REF_DELTA`. */\nfunction reusableEntry(\n\tentry: PackEntry,\n\tindexed: IndexedPack,\n): ReusableEntry | null {\n\tconst { pack, start, end } = entry;\n\tconst header = readEntryHeader(pack, start);\n\tconst bodyStart = start + header.length;\n\tif (header.type === OBJ_REF_DELTA) {\n\t\treturn {\n\t\t\tbytes: pack.subarray(start, end),\n\t\t\tbaseOid: toHex(pack.subarray(bodyStart, bodyStart + OID_BYTES)),\n\t\t};\n\t}\n\tif (header.type !== OBJ_OFS_DELTA) {\n\t\treturn { bytes: pack.subarray(start, end), baseOid: null };\n\t}\n\tconst { distance, length } = readOfsDeltaOffset(pack, bodyStart);\n\tconst baseOid = indexed.oidAtOffset.get(start - distance);\n\tif (baseOid === undefined) return null;\n\treturn {\n\t\tbytes: concat(\n\t\t\tencodeEntryHeader(OBJ_REF_DELTA, header.size),\n\t\t\tfromHex(baseOid),\n\t\t\tpack.subarray(bodyStart + length, end),\n\t\t),\n\t\tbaseOid,\n\t};\n}\n\n/**\n * A pack holding at least `oids`, built from stored entries, or `null` when\n * any of them (or a delta base they need) isn't in a readable pack — e.g. a\n * loose object — so the caller should build the pack another way.\n */\nexport async function buildPackFromExistingPacks(\n\trepo: Repo,\n\toids: readonly string[],\n): Promise<Uint8Array | null> {\n\tconst fsp = rawFs(repo);\n\tconst packDir = `${repo.gitdir}/objects/pack`;\n\tconst packs = parsePackDirectory(\n\t\tawait fsp.readdir(packDir).catch(() => [] as string[]),\n\t).filter((file) => file.kind === \"pack\");\n\n\tconst indexes: IndexedPack[] = [];\n\tfor (const { base } of packs) {\n\t\t// A pack without a readable index can't be reused.\n\t\tconst [pack, idx] = await Promise.all([\n\t\t\tfsp.readFile(`${packDir}/${packFileName(base, \"pack\")}`),\n\t\t\tfsp.readFile(`${packDir}/${packFileName(base, \"idx\")}`),\n\t\t]).catch(() => [null, null]);\n\t\tif (!(pack instanceof Uint8Array) || !(idx instanceof Uint8Array)) {\n\t\t\treturn null;\n\t\t}\n\t\tconst indexed = indexPack(idx, pack);\n\t\tif (!indexed) return null;\n\t\tindexes.push(indexed);\n\t}\n\n\tconst locate = (oid: string): ReusableEntry | null => {\n\t\tfor (const indexed of indexes) {\n\t\t\tconst entry = indexed.entries.get(oid);\n\t\t\tif (entry) return reusableEntry(entry, indexed);\n\t\t}\n\t\treturn null;\n\t};\n\n\t// Depth-first so every base is written before the deltas that use it.\n\tconst ordered: Uint8Array[] = [];\n\tconst done = new Set<string>();\n\tconst pending = new Set<string>();\n\tconst visit = (oid: string): boolean => {\n\t\tif (done.has(oid)) return true;\n\t\tif (pending.has(oid)) return false; // a delta cycle means corruption\n\t\tconst entry = locate(oid);\n\t\tif (!entry) return false;\n\t\tpending.add(oid);\n\t\tif (entry.baseOid !== null && !visit(entry.baseOid)) return false;\n\t\tpending.delete(oid);\n\t\tdone.add(oid);\n\t\tordered.push(entry.bytes);\n\t\treturn true;\n\t};\n\tfor (const oid of oids) {\n\t\tif (!visit(oid)) return null;\n\t}\n\n\tconst header = new Uint8Array(12);\n\theader.set(encodeUtf8(\"PACK\"), 0);\n\tconst view = new DataView(header.buffer);\n\tview.setUint32(4, 2);\n\tview.setUint32(8, ordered.length);\n\tconst body = concat(header, ...ordered);\n\treturn concat(body, fromHex(await sha1(body)));\n}\n","import git from \"isomorphic-git\";\nimport { concat } from \"../edge-utils.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { packFileName, parsePackDirectory } from \"../pack-files.js\";\nimport { listAllRefs } from \"./info-refs.js\";\nimport { buildPackFromExistingPacks, readPackIndex } from \"./pack-reuse.js\";\nimport { parsePktLines, pktLine, sideBandPackfile } from \"./pkt-line.js\";\nimport { collectCommitAncestry, collectReachableOids } from \"./reachability.js\";\nimport { type GitHttpResult, type HttpHooks, rawFs, runStep } from \"./types.js\";\n\nconst ZERO_OID = \"0\".repeat(40);\n\nexport interface UploadPackOptions {\n\t/**\n\t * Called once before the reachability walk — wire loose-object detection\n\t * (`GitFs.detectLooseObjects`) here so a fully packed repo's walk doesn't\n\t * pay a doomed loose-object probe per object.\n\t */\n\tbeforeWalk?: () => Promise<void>;\n}\n\n/**\n * `POST …/git-upload-pack` — serve a clone/fetch. Authorization is the\n * caller's job. Negotiation is client-driven (no multi_ack advertised):\n * \"have\" batches without \"done\" get a bare NAK; the final batch gets the\n * packfile, side-band-64k framed.\n *\n * Fast path: a fresh clone (no haves) of a repo consolidated down to a\n * single pack serves that pack's bytes directly — skipping the O(objects)\n * traversal + repack entirely.\n */\nconst OID_RE = /^[0-9a-f]{40}$/;\nconst LOOSE_FANOUT_RE = /^[0-9a-f]{2}$/;\n\nfunction result(body: Uint8Array<ArrayBuffer>): GitHttpResult {\n\treturn {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-git-upload-pack-result\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t},\n\t\tbody,\n\t};\n}\n\n/** A protocol-level error the client prints (\"ERR …\"), not an HTTP failure. */\nfunction errorResult(message: string): GitHttpResult {\n\treturn result(pktLine(`ERR ${message}\\n`));\n}\n\n/** Parsed upload-pack request: oids are always 40 lowercase hex digits. */\nexport function parseUploadPackRequest(body: Uint8Array): {\n\twants: string[];\n\thaves: string[];\n\tdone: boolean;\n\tcapabilities: string[];\n\tinvalid: boolean;\n} {\n\tconst wants: string[] = [];\n\tconst haves: string[] = [];\n\tlet done = false;\n\tlet invalid = false;\n\tlet capabilities: string[] | undefined;\n\tfor (const line of parsePktLines(body)) {\n\t\tif (!line) continue;\n\t\tconst text = line.replace(/\\n$/, \"\");\n\t\tif (text.startsWith(\"want \")) {\n\t\t\tconst [oid, ...caps] = text.slice(5).split(\" \");\n\t\t\tif (capabilities === undefined) capabilities = caps.filter(Boolean);\n\t\t\tif (oid !== undefined && OID_RE.test(oid)) wants.push(oid);\n\t\t\telse invalid = true;\n\t\t} else if (text.startsWith(\"have \")) {\n\t\t\tconst oid = text.slice(5).trim();\n\t\t\tif (OID_RE.test(oid)) {\n\t\t\t\tif (oid !== ZERO_OID) haves.push(oid);\n\t\t\t} else {\n\t\t\t\tinvalid = true;\n\t\t\t}\n\t\t} else if (text === \"done\") {\n\t\t\tdone = true;\n\t\t}\n\t}\n\treturn {\n\t\twants: [...new Set(wants)],\n\t\thaves: [...new Set(haves)],\n\t\tdone,\n\t\tcapabilities: capabilities ?? [],\n\t\tinvalid,\n\t};\n}\n\n/**\n * The single pack a fresh clone can be served verbatim, or null. Only safe\n * when nothing lives outside it (no loose objects, exactly one pack) and it\n * holds every wanted object — a repo with commits written as loose objects\n * after its last repack would otherwise clone incomplete.\n */\nasync function servableSinglePack(\n\trepo: Repo,\n\twants: readonly string[],\n\thooks?: HttpHooks,\n): Promise<Uint8Array | null> {\n\tconst fsp = rawFs(repo);\n\tconst objectsDir = `${repo.gitdir}/objects`;\n\tconst [objectEntries, packEntries] = await runStep(\n\t\thooks,\n\t\t\"readdir objects + objects/pack\",\n\t\t() =>\n\t\t\tPromise.all([\n\t\t\t\tfsp.readdir(objectsDir).catch(() => [] as string[]),\n\t\t\t\tfsp.readdir(`${objectsDir}/pack`).catch(() => [] as string[]),\n\t\t\t]),\n\t);\n\tif (objectEntries.some((name) => LOOSE_FANOUT_RE.test(name))) return null;\n\tconst packs = parsePackDirectory(packEntries).filter(\n\t\t(file) => file.kind === \"pack\",\n\t);\n\tconst pack = packs[0];\n\tif (packs.length !== 1 || pack === undefined) return null;\n\tconst [packData, idxData] = await runStep(\n\t\thooks,\n\t\t\"read consolidated pack (fast path)\",\n\t\t() =>\n\t\t\tPromise.all([\n\t\t\t\tfsp.readFile(`${objectsDir}/pack/${pack.name}`),\n\t\t\t\tfsp.readFile(`${objectsDir}/pack/${packFileName(pack.base, \"idx\")}`),\n\t\t\t]).catch(() => [null, null] as const),\n\t);\n\tif (!(packData instanceof Uint8Array) || !(idxData instanceof Uint8Array)) {\n\t\treturn null;\n\t}\n\tconst indexed = readPackIndex(idxData);\n\tif (!indexed) return null;\n\tconst oids = new Set(indexed.map((entry) => entry.oid));\n\treturn wants.every((oid) => oids.has(oid)) ? packData : null;\n}\n\n/**\n * `POST …/git-upload-pack` — serve a clone/fetch. Authorization is the\n * caller's job. Negotiation is client-driven (no multi_ack advertised):\n * \"have\" batches without \"done\" get a bare NAK; the final batch gets the\n * packfile, side-band-64k framed when the client asked for it.\n *\n * Only objects reachable from the repository's refs are served: a want that\n * isn't a ref tip must be an ancestor of one (\"not our ref\" otherwise), so a\n * force-pushed-away commit still sitting in a pack can't be fetched by id.\n *\n * A fetch with haves reads only the client's commit ancestry plus the trees\n * of the boundary commits (the haves the new history builds on) — not every\n * tree the client already has.\n *\n * Fast path: a fresh clone (no haves) of a repo consolidated down to a\n * single pack, with no loose objects, serves that pack's bytes directly —\n * skipping the O(objects) traversal + repack entirely.\n */\nexport async function handleUploadPack(\n\trepo: Repo,\n\tbody: Uint8Array,\n\toptions?: UploadPackOptions,\n\thooks?: HttpHooks,\n): Promise<GitHttpResult> {\n\tconst request = parseUploadPackRequest(body);\n\tif (request.invalid) {\n\t\treturn errorResult(\"upload-pack: protocol error, malformed object id\");\n\t}\n\tconst { wants, haves, done, capabilities } = request;\n\tconst frame = (pack: Uint8Array) =>\n\t\tcapabilities.includes(\"side-band-64k\") || capabilities.includes(\"side-band\")\n\t\t\t? sideBandPackfile(pack)\n\t\t\t: concat(pack);\n\n\tif (wants.length === 0 || (haves.length > 0 && !done)) {\n\t\treturn result(concat(pktLine(\"NAK\\n\")));\n\t}\n\n\tconst { refs } = await runStep(hooks, \"listAllRefs\", () =>\n\t\tlistAllRefs(repo, \"HEAD\"),\n\t);\n\tconst tips = new Set(refs.map((ref) => ref.oid));\n\tconst untipped = wants.filter((oid) => !tips.has(oid));\n\tif (untipped.length > 0) {\n\t\tconst { commits } = await runStep(hooks, \"verify wants reachable\", () =>\n\t\t\tcollectCommitAncestry(repo, [...tips]),\n\t\t);\n\t\tconst missing = untipped.find((oid) => !commits.has(oid));\n\t\tif (missing !== undefined) {\n\t\t\treturn errorResult(`upload-pack: not our ref ${missing}`);\n\t\t}\n\t}\n\n\tif (haves.length === 0) {\n\t\tconst pack = await servableSinglePack(repo, wants, hooks);\n\t\tif (pack) return result(concat(pktLine(\"NAK\\n\"), frame(pack)));\n\t}\n\n\tif (options?.beforeWalk) {\n\t\tawait runStep(hooks, \"beforeWalk\", options.beforeWalk);\n\t}\n\n\tlet haveSet: Set<string> | undefined;\n\tif (haves.length > 0) {\n\t\thaveSet = await runStep(hooks, \"have boundary\", async () => {\n\t\t\t// Everything the client has: its commits' whole ancestry (commits\n\t\t\t// only), plus the full content of the commits our new history\n\t\t\t// builds on. Objects only older commits share may be re-sent —\n\t\t\t// git's own boundary approximation; never anything missing.\n\t\t\tconst { commits: clientCommits } = await collectCommitAncestry(\n\t\t\t\trepo,\n\t\t\t\thaves,\n\t\t\t);\n\t\t\tconst { boundary } = await collectCommitAncestry(\n\t\t\t\trepo,\n\t\t\t\twants,\n\t\t\t\tclientCommits,\n\t\t\t);\n\t\t\tconst boundaryTrees = await Promise.all(\n\t\t\t\t[...boundary].map(async (oid) => {\n\t\t\t\t\tconst { commit } = await git.readCommit({ ...repo, oid });\n\t\t\t\t\treturn commit.tree;\n\t\t\t\t}),\n\t\t\t);\n\t\t\tconst { oids: boundaryObjects } = await collectReachableOids(\n\t\t\t\trepo,\n\t\t\t\tboundaryTrees,\n\t\t\t\thooks,\n\t\t\t\tundefined,\n\t\t\t\t{ verifyBlobs: false },\n\t\t\t);\n\t\t\treturn new Set([...clientCommits, ...boundaryObjects]);\n\t\t});\n\t}\n\n\tconst { oids: wantOids, complete } = await runStep(\n\t\thooks,\n\t\t\"collectReachableOids(wants)\",\n\t\t() =>\n\t\t\tcollectReachableOids(repo, wants, hooks, haveSet, {\n\t\t\t\tverifyBlobs: false,\n\t\t\t}),\n\t);\n\tif (!complete) {\n\t\treturn errorResult(\"upload-pack: repository is missing objects\");\n\t}\n\t// Boundary oids are recorded as seen by the walk; drop them from the pack.\n\tconst oids = haveSet ? wantOids.filter((oid) => !haveSet.has(oid)) : wantOids;\n\n\t// Copy stored (already compressed, possibly deltified) entries when every\n\t// object is packed; build from scratch only when some aren't.\n\tconst reused = await runStep(\n\t\thooks,\n\t\t`reuse pack entries (${oids.length} oids)`,\n\t\t() => buildPackFromExistingPacks(repo, oids),\n\t);\n\tconst packBytes =\n\t\treused ??\n\t\t(await runStep(hooks, `packObjects (${oids.length} oids)`, async () => {\n\t\t\tconst { packfile } = await git.packObjects({ ...repo, oids });\n\t\t\treturn packfile instanceof Uint8Array\n\t\t\t\t? packfile\n\t\t\t\t: new Uint8Array(packfile ?? []);\n\t\t}));\n\n\treturn result(concat(pktLine(\"NAK\\n\"), frame(packBytes)));\n}\n"],"mappings":"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","names":["git","p","git","git","git","git","result","git","ZERO_OID","OID_RE","git"]}
1
+ {"version":3,"sources":["../src/http/info-refs.ts","../src/http/pkt-line.ts","../src/http/reachability.ts","../src/http/receive-pack.ts","../src/http/repack.ts","../src/http/pack-reuse.ts","../src/http/upload-pack.ts"],"sourcesContent":["import git from \"isomorphic-git\";\nimport { concat } from \"../edge-utils.js\";\nimport {\n\tlistBranches,\n\tlistLooseRefNames,\n\tresolveLooseRefFast,\n} from \"../ops/branch.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { FLUSH, pktLine } from \"./pkt-line.js\";\nimport { type GitHttpResult, type HttpHooks, runStep } from \"./types.js\";\n\nexport type GitService = \"git-upload-pack\" | \"git-receive-pack\";\n\n/** All refs with resolved oids, plus the symref HEAD should advertise. */\nexport async function listAllRefs(repo: Repo, defaultBranch: string) {\n\tconst [branches, tagNames] = await Promise.all([\n\t\tlistBranches(repo),\n\t\tlistLooseRefNames(repo, \"refs/tags\").then(\n\t\t\t(names) => names ?? git.listTags(repo),\n\t\t),\n\t]);\n\tconst tagRefs = await Promise.all(\n\t\ttagNames.map(async (tag) => {\n\t\t\tconst name = `refs/tags/${tag}`;\n\t\t\treturn resolveLooseRefFast(repo, name)\n\t\t\t\t.then((oid) => ({ name, oid }))\n\t\t\t\t.catch(() => null);\n\t\t}),\n\t);\n\tconst branchRefs = branches.map((b) => ({\n\t\tname: `refs/heads/${b.name}`,\n\t\toid: b.commit,\n\t}));\n\t// HEAD is almost always a symref to a listed branch: reuse that branch's\n\t// oid. Only a detached HEAD needs resolving; an unborn branch (empty repo)\n\t// has none — resolving it would just miss every candidate ref path.\n\tconst defaultRef = branches.find((b) => b.isDefault);\n\tconst current = defaultRef\n\t\t? null\n\t\t: await git\n\t\t\t\t.currentBranch({ ...repo, fullname: true })\n\t\t\t\t.catch(() => undefined);\n\tconst headSymref = defaultRef\n\t\t? `refs/heads/${defaultRef.name}`\n\t\t: (current ?? `refs/heads/${defaultBranch}`);\n\tconst headOid =\n\t\tbranchRefs.find((r) => r.name === headSymref)?.oid ??\n\t\t(defaultRef || current\n\t\t\t? null\n\t\t\t: await git.resolveRef({ ...repo, ref: \"HEAD\" }).catch(() => null));\n\n\tconst refs: Array<{ name: string; oid: string }> = [];\n\tif (headOid) refs.push({ name: \"HEAD\", oid: headOid });\n\trefs.push(...branchRefs);\n\tfor (const r of tagRefs) if (r) refs.push(r);\n\n\treturn { refs, headSymref };\n}\n\nexport interface InfoRefsOptions {\n\tservice: GitService;\n\t/** Advertised as HEAD when HEAD itself doesn't name an existing branch. */\n\tdefaultBranch: string;\n\t/** Advertised in the agent capability. Default \"git-fs-s3\". */\n\tagent?: string;\n}\n\n/**\n * `GET …/info/refs?service=…` — the ref advertisement. Authentication and\n * authorization are the caller's job before invoking this.\n *\n * Capabilities advertised match what the sibling handlers implement:\n * side-band-64k (honored by handleUploadPack's response framing — clients\n * like isomorphic-git unconditionally expect it), tip/reachable sha1 wants,\n * delete-refs and report-status for pushes.\n */\nexport async function handleInfoRefs(\n\trepo: Repo,\n\toptions: InfoRefsOptions,\n\thooks?: HttpHooks,\n): Promise<GitHttpResult> {\n\tconst { service } = options;\n\tconst agent = options.agent ?? \"git-fs-s3\";\n\tconst { refs, headSymref } = await runStep(hooks, \"listAllRefs\", () =>\n\t\tlistAllRefs(repo, options.defaultBranch),\n\t);\n\n\tconst isUpload = service === \"git-upload-pack\";\n\tconst caps = isUpload\n\t\t? `no-progress side-band-64k symref=HEAD:${headSymref} allow-tip-sha1-in-want allow-reachable-sha1-in-want agent=${agent}`\n\t\t: `report-status delete-refs side-band-64k agent=${agent}`;\n\n\tconst parts: Uint8Array[] = [pktLine(`# service=${service}\\n`), FLUSH];\n\n\tif (refs.length === 0) {\n\t\t// Empty repo: git needs this exact sentinel\n\t\tparts.push(\n\t\t\tpktLine(\n\t\t\t\t`0000000000000000000000000000000000000000 capabilities^{}\\0${caps}\\n`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\tlet first = true;\n\t\tfor (const { name, oid } of refs) {\n\t\t\tparts.push(\n\t\t\t\tpktLine(first ? `${oid} ${name}\\0${caps}\\n` : `${oid} ${name}\\n`),\n\t\t\t);\n\t\t\tfirst = false;\n\t\t}\n\t}\n\tparts.push(FLUSH);\n\n\treturn {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": `application/x-${service}-advertisement`,\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t},\n\t\tbody: concat(...parts),\n\t};\n}\n","/**\n * Git pkt-line framing (smart HTTP protocol wire format).\n *\n * Edge-compatible: uses Uint8Array instead of Buffer.\n */\n\nimport { concat, decodeAscii, decodeUtf8, encodeUtf8 } from \"../edge-utils.js\";\n\n/** Flush packet: exactly four zero bytes. */\nexport const FLUSH: Uint8Array<ArrayBuffer> = new Uint8Array([\n\t0x30, 0x30, 0x30, 0x30,\n]); // \"0000\"\n\n/** Frame a UTF-8 string as one pkt-line. */\nexport function pktLine(data: string): Uint8Array<ArrayBuffer> {\n\tconst body = encodeUtf8(data);\n\tconst len = (body.length + 4).toString(16).padStart(4, \"0\");\n\treturn concat(encodeUtf8(len), body);\n}\n\n/** Frame raw bytes as one pkt-line. */\nexport function pktLineBuffer(body: Uint8Array): Uint8Array<ArrayBuffer> {\n\tconst len = (body.length + 4).toString(16).padStart(4, \"0\");\n\treturn concat(encodeUtf8(len), body);\n}\n\n/** Decode pkt-lines to strings; `null` marks a flush-pkt. Stops on garbage. */\nexport function parsePktLines(buf: Uint8Array): Array<string | null> {\n\tconst lines: Array<string | null> = [];\n\tlet pos = 0;\n\twhile (pos + 4 <= buf.length) {\n\t\tconst len = Number.parseInt(decodeAscii(buf.subarray(pos, pos + 4)), 16);\n\t\tif (len === 0) {\n\t\t\tlines.push(null);\n\t\t\tpos += 4;\n\t\t} else if (len >= 4) {\n\t\t\tlines.push(decodeUtf8(buf.subarray(pos + 4, pos + len)));\n\t\t\tpos += len;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn lines;\n}\n\n/**\n * Per the git protocol, once side-band-64k has been negotiated, packfile\n * bytes in the upload-pack response must be chunked into pkt-lines each\n * prefixed with a control byte (0x01 = packfile data), terminated by a\n * flush-pkt. Without this, clients that don't special-case \"no side-band\" —\n * e.g. isomorphic-git's GitSideBand.demux, which always treats the response\n * as side-band-framed — misparse the raw packfile bytes as bogus pkt-line\n * length headers and spin forever. (Native `git` tolerates a raw unframed\n * stream when side-band isn't negotiated, so this only surfaces with\n * isomorphic-git as the HTTP client.)\n */\nconst SIDE_BAND_MAX_CHUNK = 65515;\n\nexport function sideBandPackfile(\n\tpackData: Uint8Array,\n): Uint8Array<ArrayBuffer> {\n\tconst parts: Uint8Array[] = [];\n\tfor (\n\t\tlet offset = 0;\n\t\toffset < packData.length;\n\t\toffset += SIDE_BAND_MAX_CHUNK\n\t) {\n\t\tconst chunk = packData.subarray(offset, offset + SIDE_BAND_MAX_CHUNK);\n\t\tparts.push(pktLineBuffer(concat(new Uint8Array([1]), chunk)));\n\t}\n\tparts.push(FLUSH);\n\treturn concat(...parts);\n}\n","import git from \"isomorphic-git\";\nimport type { Repo } from \"../ops/types.js\";\nimport type { HttpHooks } from \"./types.js\";\n\nexport interface ReachabilityResult {\n\toids: string[];\n\t/**\n\t * False if any object in the graph couldn't be read — repack uses this\n\t * (not a raw object-count comparison) to decide whether it's safe to\n\t * delete old packs: counts alone can't distinguish \"everything read fine\"\n\t * from \"some objects silently failed\".\n\t */\n\tcomplete: boolean;\n}\n\nconst delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * A read landing in the gap between a repack's new consolidated pack being\n * uploaded and the stale-pack cleanup finishing can transiently miss an\n * object that is not actually lost — it exists in the new pack the whole\n * time; the reader's cached pack listing was just taken mid-transition. One\n * retry after a short delay is enough to observe the consistent listing.\n */\nconst MISSING_OBJECT_RETRY_DELAY_MS = 200;\n\n/**\n * Walk the object graph from `startOids`, returning every reachable oid.\n * Concurrent traversal paths are deduplicated promise-per-oid; a missing\n * object is retried once, then reported through `hooks.onWarn` and\n * reflected in `complete: false`.\n *\n * `haveOids` bounds the walk: any oid in this set is assumed already\n * verified (it was reachable from a ref that existed before this call) and\n * is recorded in `seen` without being read or descended into. Without a\n * boundary, every call re-walks the *entire* history from scratch — for\n * receive-pack validation (see receive-pack.ts) that means every push pays\n * for reading every object in the repo, not just the ones it introduced,\n * and one transient read failure anywhere in that whole history rejects an\n * otherwise-valid push.\n *\n * Commits, trees and tags are read once each (parsed). Blobs have no\n * children, so `verifyBlobs: false` records a blob from its tree entry\n * without reading (and inflating) it — for callers that read every blob\n * themselves afterwards anyway, like upload-pack's `packObjects`. Leave it\n * true wherever the walk *is* the existence check (receive-pack, repack).\n */\nexport async function collectReachableOids(\n\trepo: Repo,\n\tstartOids: string[],\n\thooks?: HttpHooks,\n\thaveOids?: ReadonlySet<string> | readonly string[],\n\toptions?: { verifyBlobs?: boolean },\n): Promise<ReachabilityResult> {\n\tconst verifyBlobs = options?.verifyBlobs ?? true;\n\tconst have = haveOids instanceof Set ? haveOids : new Set(haveOids ?? []);\n\tconst seen = new Set<string>();\n\tlet complete = true;\n\tconst promises = new Map<string, Promise<void>>();\n\n\tasync function readAndVisitChildren(oid: string): Promise<void> {\n\t\tconst obj = await git.readObject({ ...repo, oid });\n\t\tseen.add(oid);\n\t\tconst children: [string, string | undefined][] = [];\n\t\tif (obj.type === \"commit\") {\n\t\t\tconst commit = obj.object as { tree: string; parent: string[] };\n\t\t\tchildren.push([commit.tree, \"tree\"]);\n\t\t\tfor (const parent of commit.parent) children.push([parent, \"commit\"]);\n\t\t} else if (obj.type === \"tree\") {\n\t\t\tconst tree = obj.object as { oid: string; type: string }[];\n\t\t\tfor (const entry of tree) {\n\t\t\t\t// Gitlinks (submodules, mode 160000) point at commits in another\n\t\t\t\t// repository; git never stores them here, so following one would\n\t\t\t\t// report a \"missing\" object and fail every walk over that history.\n\t\t\t\tif (entry.type === \"commit\") continue;\n\t\t\t\tchildren.push([entry.oid, entry.type]);\n\t\t\t}\n\t\t} else if (obj.type === \"tag\") {\n\t\t\tchildren.push([(obj.object as { object: string }).object, undefined]);\n\t\t}\n\t\tawait Promise.all(children.map(([child, type]) => visit(child, type)));\n\t}\n\n\tfunction visit(oid: string, type?: string): Promise<void> {\n\t\tconst existing = promises.get(oid);\n\t\tif (existing) return existing;\n\n\t\tif (have.has(oid) || (type === \"blob\" && !verifyBlobs)) {\n\t\t\tseen.add(oid);\n\t\t\tconst p = Promise.resolve();\n\t\t\tpromises.set(oid, p);\n\t\t\treturn p;\n\t\t}\n\n\t\tconst p = (async () => {\n\t\t\ttry {\n\t\t\t\tawait readAndVisitChildren(oid);\n\t\t\t} catch {\n\t\t\t\ttry {\n\t\t\t\t\tawait delay(MISSING_OBJECT_RETRY_DELAY_MS);\n\t\t\t\t\tawait readAndVisitChildren(oid);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tcomplete = false;\n\t\t\t\t\thooks?.onWarn?.(`missing object ${oid}`, err);\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\tpromises.set(oid, p);\n\t\treturn p;\n\t}\n\n\tawait Promise.all(startOids.map((oid) => visit(oid)));\n\treturn { oids: Array.from(seen), complete };\n}\n\n/**\n * Commit-only ancestry walk: every commit reachable from `startOids`\n * (annotated tags peeled), stopping at — and not descending into — commits in\n * `stopAt`. Reads commit objects only, never trees or blobs, so it costs a\n * fraction of {@link collectReachableOids} over the same history. Start oids\n * that don't exist (or aren't commits/tags) are skipped. Returns the commits\n * walked and the `stopAt` commits the walk ran into.\n */\nexport async function collectCommitAncestry(\n\trepo: Repo,\n\tstartOids: readonly string[],\n\tstopAt?: ReadonlySet<string>,\n): Promise<{ commits: Set<string>; boundary: Set<string> }> {\n\tconst commits = new Set<string>();\n\tconst boundary = new Set<string>();\n\tconst queued = new Set<string>();\n\tlet frontier = [...new Set(startOids)];\n\tconst BATCH = 50;\n\twhile (frontier.length > 0) {\n\t\tconst next: string[] = [];\n\t\tfor (let i = 0; i < frontier.length; i += BATCH) {\n\t\t\tawait Promise.all(\n\t\t\t\tfrontier.slice(i, i + BATCH).map(async (oid) => {\n\t\t\t\t\tif (stopAt?.has(oid)) {\n\t\t\t\t\t\tboundary.add(oid);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst object = await git\n\t\t\t\t\t\t.readObject({ ...repo, oid })\n\t\t\t\t\t\t.catch(() => null);\n\t\t\t\t\tif (object?.type === \"tag\") {\n\t\t\t\t\t\tconst target = (object.object as { object: string }).object;\n\t\t\t\t\t\tif (!queued.has(target)) {\n\t\t\t\t\t\t\tqueued.add(target);\n\t\t\t\t\t\t\tnext.push(target);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (object?.type !== \"commit\") return;\n\t\t\t\t\tcommits.add(oid);\n\t\t\t\t\tfor (const parent of (object.object as { parent: string[] }).parent) {\n\t\t\t\t\t\tif (!queued.has(parent)) {\n\t\t\t\t\t\t\tqueued.add(parent);\n\t\t\t\t\t\t\tnext.push(parent);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tfrontier = next;\n\t}\n\treturn { commits, boundary };\n}\n","import git from \"isomorphic-git\";\nimport { concat, decodeAscii, decodeUtf8 } from \"../edge-utils.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { storePack } from \"../pack-write.js\";\nimport { isSafeFullRefName } from \"../refs.js\";\nimport { FLUSH, pktLine, sideBandPackfile } from \"./pkt-line.js\";\nimport { collectReachableOids } from \"./reachability.js\";\nimport { type RepackOptions, repackRepository } from \"./repack.js\";\nimport { type GitHttpResult, type HttpHooks, rawFs, runStep } from \"./types.js\";\n\nconst ZERO_OID = \"0\".repeat(40);\nconst OID_RE = /^[0-9a-f]{40}$/;\n\nexport interface RefUpdateCommand {\n\toldOid: string;\n\tnewOid: string;\n\trefName: string;\n}\n\nexport interface RefUpdateResult {\n\trefName: string;\n\tok: boolean;\n\treason?: string;\n}\n\nexport interface ParsedReceivePack {\n\trefUpdates: RefUpdateCommand[];\n\tpackData: Uint8Array;\n\t/** Capabilities the client asked for on its first command line. */\n\tcapabilities: string[];\n}\n\n/**\n * Split a receive-pack body: pkt-line ref commands, flush, then raw PACK.\n * A command whose oids aren't 40 lowercase hex digits is dropped — it can\n * never be applied, and its oids would otherwise reach object-path lookups.\n */\nexport function parseReceivePackBody(body: Uint8Array): ParsedReceivePack {\n\tconst refUpdates: RefUpdateCommand[] = [];\n\tlet capabilities: string[] | undefined;\n\tlet pos = 0;\n\twhile (pos + 4 <= body.length) {\n\t\tconst len = Number.parseInt(decodeAscii(body.subarray(pos, pos + 4)), 16);\n\t\tif (len === 0) {\n\t\t\tpos += 4;\n\t\t\tbreak; // flush = end of ref update commands\n\t\t}\n\t\tif (len < 4) break;\n\t\t// The first command line carries NUL-separated capabilities.\n\t\tconst [line, caps] = decodeUtf8(body.subarray(pos + 4, pos + len))\n\t\t\t.replace(/\\n$/, \"\")\n\t\t\t.split(\"\\0\");\n\t\tif (capabilities === undefined) {\n\t\t\tcapabilities = (caps ?? \"\").split(\" \").filter(Boolean);\n\t\t}\n\t\tpos += len;\n\t\tconst [oldOid, newOid, refName] = (line ?? \"\").split(\" \");\n\t\tif (\n\t\t\toldOid &&\n\t\t\tnewOid &&\n\t\t\trefName &&\n\t\t\tOID_RE.test(oldOid) &&\n\t\t\tOID_RE.test(newOid)\n\t\t) {\n\t\t\trefUpdates.push({ oldOid, newOid, refName });\n\t\t}\n\t}\n\treturn {\n\t\trefUpdates,\n\t\tpackData: body.subarray(pos),\n\t\tcapabilities: capabilities ?? [],\n\t};\n}\n\n/** Initialize the repo when its HEAD doesn't exist yet (first push). */\nexport async function ensureRepoInitialized(\n\trepo: Repo,\n\tdefaultBranch: string,\n): Promise<void> {\n\tconst fsp = rawFs(repo);\n\ttry {\n\t\tawait fsp.stat(`${repo.gitdir}/HEAD`);\n\t} catch {\n\t\tawait fsp.mkdir(repo.gitdir, { recursive: true }).catch(() => {});\n\t\tawait git.init({ ...repo, dir: repo.gitdir, defaultBranch, bare: true });\n\t}\n}\n\n/** Write the incoming PACK into objects/pack/ and index it. */\nexport async function indexIncomingPack(\n\trepo: Repo,\n\tpackData: Uint8Array,\n\thooks?: HttpHooks,\n): Promise<string[]> {\n\tif (packData.length < 4) return [];\n\tconst packName = await runStep(\n\t\thooks,\n\t\t\"write + indexPack incoming pack\",\n\t\tasync () => {\n\t\t\t// Named by checksum (`pack-<sha>`), stored pack first, index last.\n\t\t\tconst { base } = await storePack(repo, packData);\n\t\t\treturn base;\n\t\t},\n\t);\n\treturn [\n\t\t`${repo.gitdir}/objects/pack/${packName}.pack`,\n\t\t`${repo.gitdir}/objects/pack/${packName}.idx`,\n\t];\n}\n\n/**\n * Validate a ref name and compare-and-swap it against its claimed current\n * oid. Returns the failure result to report if either check fails, or\n * `null` when both pass — shared by the preflight check (`validateRefUpdates`,\n * run before the possibly-slow pack indexing/graph-walk work, purely to\n * avoid doing that work for an update already doomed to fail) and the real\n * atomicity guarantee (`applyRefUpdates`, run again right before writing,\n * since a concurrent push could have moved the ref in the time that work\n * took).\n */\nasync function checkRefCas(\n\trepo: Repo,\n\trefName: string,\n\toldOid: string,\n): Promise<RefUpdateResult | null> {\n\tif (!isSafeFullRefName(refName)) {\n\t\treturn { refName, ok: false, reason: \"invalid ref name\" };\n\t}\n\tconst currentOid = await git\n\t\t.resolveRef({ ...repo, ref: refName })\n\t\t.catch(() => ZERO_OID);\n\treturn currentOid === oldOid\n\t\t? null\n\t\t: {\n\t\t\t\trefName,\n\t\t\t\tok: false,\n\t\t\t\treason: \"non-fast-forward, ref updated by another push\",\n\t\t\t};\n}\n\n/** Every branch/tag tip currently in the repo, as a validation boundary — see\n * its call site in {@link applyReceivePack}. */\nasync function collectExistingRefTips(repo: Repo): Promise<Set<string>> {\n\tconst [branches, tags] = await Promise.all([\n\t\tgit.listBranches(repo),\n\t\tgit.listTags(repo),\n\t]);\n\tconst refs = [\n\t\t...branches.map((b) => `refs/heads/${b}`),\n\t\t...tags.map((t) => `refs/tags/${t}`),\n\t];\n\tconst oids = await Promise.all(\n\t\trefs.map((ref) => git.resolveRef({ ...repo, ref }).catch(() => null)),\n\t);\n\treturn new Set(oids.filter((oid): oid is string => oid !== null));\n}\n\n/** The branch HEAD names, or null when HEAD is detached/unreadable. */\nasync function currentBranchRef(repo: Repo): Promise<string | null> {\n\treturn git\n\t\t.currentBranch({ ...repo, fullname: true })\n\t\t.then((ref) => ref ?? null)\n\t\t.catch(() => null);\n}\n\nasync function validateRefUpdates(\n\trepo: Repo,\n\trefUpdates: RefUpdateCommand[],\n): Promise<RefUpdateResult[]> {\n\tconst headRef = await currentBranchRef(repo);\n\tconst seen = new Set<string>();\n\treturn Promise.all(\n\t\trefUpdates.map(async ({ oldOid, newOid, refName }) => {\n\t\t\t// Two commands for one ref can't both be compare-and-swapped.\n\t\t\tif (seen.has(refName)) {\n\t\t\t\treturn { refName, ok: false, reason: \"duplicate ref update\" };\n\t\t\t}\n\t\t\tseen.add(refName);\n\t\t\t// Same rule as git's receive.denyDeleteCurrent: deleting the\n\t\t\t// branch HEAD names leaves every clone without a default branch.\n\t\t\tif (newOid === ZERO_OID && refName === headRef) {\n\t\t\t\treturn {\n\t\t\t\t\trefName,\n\t\t\t\t\tok: false,\n\t\t\t\t\treason: \"deletion of the current branch prohibited\",\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t(await checkRefCas(repo, refName, oldOid)) ?? { refName, ok: true }\n\t\t\t);\n\t\t}),\n\t);\n}\n\n/**\n * Apply ref updates, enforcing compare-and-swap against each command's\n * claimed oldOid. Every client-supplied refName is validated before any\n * filesystem call reads or writes through it.\n */\nexport async function applyRefUpdates(\n\trepo: Repo,\n\trefUpdates: RefUpdateCommand[],\n\thooks?: HttpHooks,\n): Promise<RefUpdateResult[]> {\n\treturn runStep(hooks, \"apply ref updates\", () =>\n\t\tPromise.all(\n\t\t\trefUpdates.map(async ({ oldOid, newOid, refName }) => {\n\t\t\t\tconst failure = await checkRefCas(repo, refName, oldOid);\n\t\t\t\tif (failure) return failure;\n\n\t\t\t\tif (newOid === ZERO_OID) {\n\t\t\t\t\tawait git.deleteRef({ ...repo, ref: refName }).catch(() => {});\n\t\t\t\t} else {\n\t\t\t\t\t// A branch must name a commit; a tag may name anything.\n\t\t\t\t\tif (refName.startsWith(\"refs/heads/\")) {\n\t\t\t\t\t\tconst { type } = await git\n\t\t\t\t\t\t\t.readObject({ ...repo, oid: newOid, format: \"content\" })\n\t\t\t\t\t\t\t.catch(() => ({ type: \"missing\" }));\n\t\t\t\t\t\tif (type !== \"commit\") {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\trefName,\n\t\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\t\treason: `branch must point at a commit, not a ${type}`,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tawait git.writeRef({\n\t\t\t\t\t\t...repo,\n\t\t\t\t\t\tref: refName,\n\t\t\t\t\t\tvalue: newOid,\n\t\t\t\t\t\tforce: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { refName, ok: true };\n\t\t\t}),\n\t\t),\n\t);\n}\n\n/**\n * The report-status response for a set of ref-update results — empty unless\n * the client asked for `report-status`, and side-band-64k framed when it\n * asked for that (git and isomorphic-git both do; isomorphic-git always\n * demuxes the response as side-band). `unpackError` reports a pack that\n * couldn't be stored or indexed.\n */\nexport function receivePackResponse(\n\tresults: RefUpdateResult[],\n\toptions?: { capabilities?: readonly string[]; unpackError?: string },\n): GitHttpResult {\n\tconst capabilities = options?.capabilities ?? [\"report-status\"];\n\tconst report = capabilities.includes(\"report-status\")\n\t\t? concat(\n\t\t\t\tpktLine(\n\t\t\t\t\toptions?.unpackError\n\t\t\t\t\t\t? `unpack ${options.unpackError}\\n`\n\t\t\t\t\t\t: \"unpack ok\\n\",\n\t\t\t\t),\n\t\t\t\t...results.map(({ refName, ok, reason }) =>\n\t\t\t\t\tpktLine(ok ? `ok ${refName}\\n` : `ng ${refName} ${reason}\\n`),\n\t\t\t\t),\n\t\t\t\tFLUSH,\n\t\t\t)\n\t\t: new Uint8Array();\n\tconst responseBody =\n\t\tcapabilities.includes(\"side-band-64k\") && report.length > 0\n\t\t\t? sideBandPackfile(report)\n\t\t\t: report;\n\n\treturn {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-git-receive-pack-result\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t},\n\t\tbody: responseBody,\n\t};\n}\n\nexport interface ApplyReceivePackOptions {\n\t/** HEAD's branch when a push initializes an empty repository. */\n\tdefaultBranch: string;\n\t/**\n\t * Repack tuning, or `false` to skip repacking entirely. The returned\n\t * `stalePackPaths` are gitdir-relative pack files the repack deleted from\n\t * this repo — after syncing to any secondary storage, delete them there\n\t * too.\n\t */\n\trepack?: RepackOptions | false;\n}\n\n/**\n * The storage half of a push against `repo`: initialize if needed, index the\n * incoming pack, CAS-apply ref updates, then repack when enough packs have\n * accumulated. Serialize concurrent pushes to the same repo externally (a\n * per-repo lock); build the HTTP response afterwards with\n * {@link receivePackResponse}.\n */\nexport interface ApplyReceivePackResult {\n\tresults: RefUpdateResult[];\n\tstalePackPaths: string[];\n\t/** Set when the incoming pack couldn't be stored or indexed. */\n\tunpackError?: string;\n}\n\nexport async function applyReceivePack(\n\trepo: Repo,\n\tparsed: { refUpdates: RefUpdateCommand[]; packData: Uint8Array },\n\toptions: ApplyReceivePackOptions,\n\thooks?: HttpHooks,\n): Promise<ApplyReceivePackResult> {\n\tawait ensureRepoInitialized(repo, options.defaultBranch);\n\tconst preflight = await validateRefUpdates(repo, parsed.refUpdates);\n\tconst acceptedUpdates = parsed.refUpdates.filter(\n\t\t(_, index) => preflight[index]?.ok,\n\t);\n\tconst fsp = rawFs(repo);\n\tconst packDir = `${repo.gitdir}/objects/pack`;\n\tconst existingPacks = new Set(\n\t\tawait fsp.readdir(packDir).catch(() => [] as string[]),\n\t);\n\tlet incomingPackPaths: string[];\n\ttry {\n\t\tincomingPackPaths = await indexIncomingPack(\n\t\t\trepo,\n\t\t\tacceptedUpdates.some((update) => update.newOid !== ZERO_OID)\n\t\t\t\t? parsed.packData\n\t\t\t\t: new Uint8Array(),\n\t\t\thooks,\n\t\t);\n\t} catch (err) {\n\t\thooks?.onWarn?.(\"receive-pack: incoming pack rejected\", err);\n\t\treturn {\n\t\t\tresults: preflight.map((result) =>\n\t\t\t\tresult.ok ? { ...result, ok: false, reason: \"unpacker error\" } : result,\n\t\t\t),\n\t\t\tstalePackPaths: [],\n\t\t\tunpackError: \"index-pack failed\",\n\t\t};\n\t}\n\t// A checksum-named pack identical to one already stored must survive the\n\t// cleanup below. Index first, so readers never see a half-removed pack.\n\tconst removableIncoming = incomingPackPaths\n\t\t.filter((path) => !existingPacks.has(path.slice(packDir.length + 1)))\n\t\t.sort((a, b) => Number(b.endsWith(\".idx\")) - Number(a.endsWith(\".idx\")));\n\n\tconst newTips = acceptedUpdates\n\t\t.filter((update) => update.newOid !== ZERO_OID)\n\t\t.map((update) => update.newOid);\n\tif (newTips.length > 0) {\n\t\t// Every oid reachable from an existing ref was already accepted by an\n\t\t// earlier push — not just the ref(s) this push happens to touch. A\n\t\t// brand-new branch (oldOid === ZERO_OID, so it has no pre-image of its\n\t\t// own) is the common case this matters for: creating a branch off an\n\t\t// existing one is still just one new commit's worth of new objects,\n\t\t// and shouldn't cost a walk of the entire repo history to validate.\n\t\tconst haveOids = await collectExistingRefTips(repo);\n\t\tfor (const update of acceptedUpdates) {\n\t\t\tif (update.oldOid !== ZERO_OID) haveOids.add(update.oldOid);\n\t\t}\n\t\tconst { complete } = await collectReachableOids(\n\t\t\trepo,\n\t\t\tnewTips,\n\t\t\thooks,\n\t\t\thaveOids,\n\t\t);\n\t\tif (!complete) {\n\t\t\tfor (const filepath of removableIncoming) {\n\t\t\t\tawait fsp.unlink(filepath).catch(() => {});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tresults: preflight.map((result) =>\n\t\t\t\t\tresult.ok\n\t\t\t\t\t\t? { ...result, ok: false, reason: \"incomplete object graph\" }\n\t\t\t\t\t\t: result,\n\t\t\t\t),\n\t\t\t\tstalePackPaths: [],\n\t\t\t};\n\t\t}\n\t}\n\n\tconst applied = await applyRefUpdates(repo, acceptedUpdates, hooks);\n\tconst results = preflight.map((result, index) =>\n\t\tresult.ok\n\t\t\t? (applied.find(\n\t\t\t\t\t(entry) => entry.refName === parsed.refUpdates[index]?.refName,\n\t\t\t\t) ?? result)\n\t\t\t: result,\n\t);\n\tconst repackOptions = options.repack;\n\tconst stalePackPaths =\n\t\trepackOptions === false || !results.some((result) => result.ok)\n\t\t\t? []\n\t\t\t: await runStep(hooks, \"repack\", () =>\n\t\t\t\t\trepackRepository(repo, repackOptions, hooks),\n\t\t\t\t);\n\treturn { results, stalePackPaths };\n}\n","/**\n * Pack consolidation: merge all packs into one, reusing stored (possibly\n * deltified) entries when every object is packed.\n *\n * Edge-compatible: uses Web Crypto (SHA-1), CompressionStream (deflate),\n * and Uint8Array throughout — no node:crypto, node:zlib, or Buffer.\n */\n\nimport git from \"isomorphic-git\";\nimport type { Repo } from \"../ops/types.js\";\nimport {\n\ttype PackFileName,\n\tpackFileName,\n\tparsePackDirectory,\n} from \"../pack-files.js\";\nimport {\n\tencodePack,\n\thashGitObject,\n\ttype PackObject,\n\ttype PackObjectType,\n\tpackBaseName,\n} from \"../pack-write.js\";\nimport { buildPackFromExistingPacks } from \"./pack-reuse.js\";\nimport { collectReachableOids } from \"./reachability.js\";\nimport { type HttpHooks, rawFs } from \"./types.js\";\n\n/**\n * Read every reachable object and independently re-derive its oid from the\n * bytes isomorphic-git handed back, instead of trusting the oid it was asked\n * for. isomorphic-git's *packed*-object read path never verifies the\n * resolved content's SHA-1 against the requested oid — only the\n * loose-object branch does.\n */\nasync function readAndVerifyObjects(\n\trepo: Repo,\n\toids: string[],\n): Promise<Map<string, PackObject>> {\n\tconst objects = new Map<string, PackObject>();\n\tconst BATCH_SIZE = 100;\n\tfor (let i = 0; i < oids.length; i += BATCH_SIZE) {\n\t\tconst batch = oids.slice(i, i + BATCH_SIZE);\n\t\tconst entries = await Promise.all(\n\t\t\tbatch.map(async (oid) => {\n\t\t\t\tconst { type, object } = await git.readObject({\n\t\t\t\t\t...repo,\n\t\t\t\t\toid,\n\t\t\t\t\tformat: \"content\",\n\t\t\t\t});\n\t\t\t\t// Own ArrayBuffer-backed copy: Web APIs (Blob, digest) reject\n\t\t\t\t// views that might sit on a SharedArrayBuffer.\n\t\t\t\tconst content = new Uint8Array(object as Uint8Array);\n\t\t\t\tconst actualOid = await hashGitObject(type, content);\n\t\t\t\tif (actualOid !== oid) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`repack: object ${oid} failed independent SHA-1 verification ` +\n\t\t\t\t\t\t\t`(recomputed ${actualOid}) — refusing to trust this read, aborting repack`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn { oid, type: type as PackObjectType, content };\n\t\t\t}),\n\t\t);\n\t\tfor (const { oid, type, content } of entries) {\n\t\t\tobjects.set(oid, { type, content });\n\t\t}\n\t}\n\treturn objects;\n}\n\n/**\n * Default repack threshold. Consolidating is O(total repo object count) —\n * so paying it on every push makes push latency grow with repo size forever.\n */\nexport const REPACK_PACK_COUNT_THRESHOLD = 4;\n\nasync function readPackDirectory(repo: Repo): Promise<PackFileName[]> {\n\tconst entries = await rawFs(repo)\n\t\t.readdir(`${repo.gitdir}/objects/pack`)\n\t\t.catch(() => [] as string[]);\n\treturn parsePackDirectory(entries);\n}\n\nasync function countPacks(repo: Repo): Promise<number> {\n\tconst files = await readPackDirectory(repo);\n\treturn files.filter((file) => file.kind === \"pack\").length;\n}\n\nexport interface RepackOptions {\n\t/** Skip repacking below this many accumulated packs. Default 4. */\n\tthreshold?: number;\n}\n\n/**\n * Consolidate all pack files into one, returning the gitdir-relative paths\n * of the old .pack/.idx files it removed — after syncing the new pack to any\n * secondary storage, delete those same paths there too.\n */\nexport async function repackRepository(\n\trepo: Repo,\n\toptions?: RepackOptions,\n\thooks?: HttpHooks,\n): Promise<string[]> {\n\tconst threshold = options?.threshold ?? REPACK_PACK_COUNT_THRESHOLD;\n\tconst fsp = rawFs(repo);\n\ttry {\n\t\tif ((await countPacks(repo)) < threshold) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst [branches, tags] = await Promise.all([\n\t\t\tgit.listBranches(repo),\n\t\t\tgit.listTags(repo),\n\t\t]);\n\t\tconst refNames = [\n\t\t\t...branches.map((b) => `refs/heads/${b}`),\n\t\t\t...tags.map((t) => `refs/tags/${t}`),\n\t\t];\n\t\tconst tipOids = (\n\t\t\tawait Promise.all(\n\t\t\t\trefNames.map((ref) =>\n\t\t\t\t\tgit.resolveRef({ ...repo, ref }).catch(() => null),\n\t\t\t\t),\n\t\t\t)\n\t\t).filter((oid): oid is string => oid !== null);\n\t\tif (tipOids.length === 0) return [];\n\n\t\t// Blobs aren't read here: indexPack below re-hashes every object the\n\t\t// new pack holds and the reachable-set check rejects a pack missing any,\n\t\t// so inflating every blob in history during the walk too would only\n\t\t// double the cost.\n\t\tconst { oids: reachable, complete } = await collectReachableOids(\n\t\t\trepo,\n\t\t\ttipOids,\n\t\t\thooks,\n\t\t\tundefined,\n\t\t\t{ verifyBlobs: false },\n\t\t);\n\t\tif (!complete || reachable.length === 0) return [];\n\n\t\tconst packDir = `${repo.gitdir}/objects/pack`;\n\t\t// Copy stored entries when everything is packed: keeps deltas, so\n\t\t// the consolidated pack is as compact as its sources. Loose objects\n\t\t// fall back to a verified, non-deltified rebuild.\n\t\tconst packBuffer =\n\t\t\t(await buildPackFromExistingPacks(repo, reachable)) ??\n\t\t\t(await (async () => {\n\t\t\t\tconst objects = await readAndVerifyObjects(repo, reachable);\n\t\t\t\treturn encodePack(\n\t\t\t\t\treachable.map((oid) => {\n\t\t\t\t\t\tconst object = objects.get(oid);\n\t\t\t\t\t\tif (!object) {\n\t\t\t\t\t\t\tthrow new Error(`repack: missing verified object for ${oid}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn object;\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t})());\n\n\t\tawait fsp.mkdir(packDir, { recursive: true });\n\t\tconst newBase = packBaseName(packBuffer);\n\t\tconst newPackFile = packFileName(newBase, \"pack\");\n\t\t// Checksum-named, so an identical pack may already be stored — never\n\t\t// delete that one on the abort path below.\n\t\tconst preexisting = (await readPackDirectory(repo)).some(\n\t\t\t(file) => file.base === newBase,\n\t\t);\n\t\tawait fsp.writeFile(`${packDir}/${newPackFile}`, packBuffer);\n\n\t\tconst { oids: indexedOids } = await git.indexPack({\n\t\t\t...repo,\n\t\t\tdir: packDir,\n\t\t\tfilepath: newPackFile,\n\t\t});\n\n\t\t// indexPack re-hashes every object it indexes, so this also verifies\n\t\t// the content. Reused packs may carry extra delta bases: superset is fine.\n\t\tconst indexed = new Set(indexedOids);\n\t\tif (reachable.some((oid) => !indexed.has(oid))) {\n\t\t\tif (!preexisting)\n\t\t\t\tawait Promise.all(\n\t\t\t\t\t([\"pack\", \"idx\"] as const).map((kind) =>\n\t\t\t\t\t\tfsp\n\t\t\t\t\t\t\t.unlink(`${packDir}/${packFileName(newBase, kind)}`)\n\t\t\t\t\t\t\t.catch(() => {}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\tthrow new Error(\n\t\t\t\t\"repack: indexed pack is missing reachable objects — aborting\",\n\t\t\t);\n\t\t}\n\n\t\tconst stale = (await readPackDirectory(repo)).filter(\n\t\t\t(file) => file.base !== newBase,\n\t\t);\n\t\t// Indexes first: readers find packs through their .idx, so a reader\n\t\t// listing mid-cleanup sees either a complete old pack or none of it.\n\t\tconst unlinkAll = (files: PackFileName[]) =>\n\t\t\tPromise.all(\n\t\t\t\tfiles.map((file) =>\n\t\t\t\t\tfsp.unlink(`${packDir}/${file.name}`).catch(() => {}),\n\t\t\t\t),\n\t\t\t);\n\t\tawait unlinkAll(stale.filter((file) => file.kind === \"idx\"));\n\t\tawait unlinkAll(stale.filter((file) => file.kind !== \"idx\"));\n\t\treturn stale.map((file) => `objects/pack/${file.name}`);\n\t} catch (err) {\n\t\thooks?.onWarn?.(\"repack failed (non-fatal)\", err);\n\t\treturn [];\n\t}\n}\n","/**\n * Build a packfile by copying already-compressed entries out of existing\n * packs (\"pack reuse\"), instead of inflating and re-deflating every object.\n *\n * Entries keep their stored form, deltas included, so the output is as\n * compact as the packs it came from. `OFS_DELTA` entries are rewritten as\n * `REF_DELTA` (base named by oid), since offsets don't survive the move into\n * a new pack; delta bases are always included and written before the deltas\n * that use them. Formats: gitformat-pack(5).\n *\n * Edge-compatible: Web Crypto SHA-1 and Uint8Array only.\n */\n\nimport { concat, encodeUtf8, fromHex, sha1, toHex } from \"../edge-utils.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { packFileName, parsePackDirectory } from \"../pack-files.js\";\nimport { rawFs } from \"./types.js\";\n\nconst OBJ_OFS_DELTA = 6;\nconst OBJ_REF_DELTA = 7;\nconst OID_BYTES = 20;\nconst PACK_TRAILER_BYTES = 20;\n\nconst IDX_V2 = {\n\tmagic: 0xff744f63,\n\tversion: 2,\n\theaderBytes: 8,\n\tfanoutEntries: 256,\n\t/** Offsets with this bit set index the 64-bit large-offset table. */\n\tlargeOffsetFlag: 0x80000000,\n} as const;\n\n/** One object's stored entry inside a pack. */\ninterface PackEntry {\n\treadonly pack: Uint8Array;\n\treadonly start: number;\n\treadonly end: number;\n}\n\n/** Every object stored in a pack, by oid, plus its offset → oid inverse. */\ninterface IndexedPack {\n\treadonly entries: Map<string, PackEntry>;\n\treadonly oidAtOffset: Map<number, string>;\n}\n\n/** An object's position in a pack, as listed by its `.idx`. */\ninterface PackIndexEntry {\n\treadonly oid: string;\n\treadonly offset: number;\n}\n\n/** Entries of a version-2 `.idx`; `null` for any other format. */\nexport function readPackIndex(idx: Uint8Array): PackIndexEntry[] | null {\n\tconst view = new DataView(idx.buffer, idx.byteOffset, idx.byteLength);\n\tconst namesStart = IDX_V2.headerBytes + IDX_V2.fanoutEntries * 4;\n\tif (\n\t\tidx.byteLength < namesStart ||\n\t\tview.getUint32(0) !== IDX_V2.magic ||\n\t\tview.getUint32(4) !== IDX_V2.version\n\t) {\n\t\treturn null;\n\t}\n\t// The last fanout slot counts every object in the pack.\n\tconst count = view.getUint32(namesStart - 4);\n\tconst crcStart = namesStart + count * OID_BYTES;\n\tconst offsetsStart = crcStart + count * 4;\n\tif (idx.byteLength < offsetsStart + count * 4) return null;\n\n\tconst entries: PackIndexEntry[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tconst offset = view.getUint32(offsetsStart + i * 4);\n\t\t// Packs over 2 GiB never reach this in-memory path; let the caller\n\t\t// fall back instead of half-supporting the large-offset table.\n\t\tif (offset & IDX_V2.largeOffsetFlag) return null;\n\t\tconst at = namesStart + i * OID_BYTES;\n\t\tentries.push({ oid: toHex(idx.subarray(at, at + OID_BYTES)), offset });\n\t}\n\treturn entries;\n}\n\n/** Locate every entry of `pack` using its `.idx`. */\nfunction indexPack(idx: Uint8Array, pack: Uint8Array): IndexedPack | null {\n\tconst located = readPackIndex(idx);\n\tif (!located) return null;\n\n\t// An entry runs until the next entry's offset (or the pack trailer).\n\tlocated.sort((a, b) => a.offset - b.offset);\n\tconst entries = new Map<string, PackEntry>();\n\tconst oidAtOffset = new Map<number, string>();\n\tconst packEnd = pack.byteLength - PACK_TRAILER_BYTES;\n\tfor (let i = 0; i < located.length; i++) {\n\t\tconst { oid, offset } = located[i] as PackIndexEntry;\n\t\tconst end = located[i + 1]?.offset ?? packEnd;\n\t\tentries.set(oid, { pack, start: offset, end });\n\t\toidAtOffset.set(offset, oid);\n\t}\n\treturn { entries, oidAtOffset };\n}\n\n/** The variable-length type/size header that starts every pack entry. */\ninterface EntryHeader {\n\treadonly type: number;\n\treadonly size: number;\n\t/** Bytes the header occupies. */\n\treadonly length: number;\n}\n\nfunction readEntryHeader(bytes: Uint8Array, start: number): EntryHeader {\n\tlet byte = bytes[start] as number;\n\tconst type = (byte >> 4) & 0b111;\n\tlet size = byte & 0b1111;\n\tlet shift = 4;\n\tlet at = start + 1;\n\twhile (byte & 0x80) {\n\t\tbyte = bytes[at++] as number;\n\t\tsize += (byte & 0x7f) * 2 ** shift;\n\t\tshift += 7;\n\t}\n\treturn { type, size, length: at - start };\n}\n\nfunction encodeEntryHeader(type: number, size: number): Uint8Array {\n\tconst bytes: number[] = [];\n\tlet rest = Math.floor(size / 16);\n\tbytes.push((rest > 0 ? 0x80 : 0) | (type << 4) | (size % 16));\n\twhile (rest > 0) {\n\t\tconst low = rest % 128;\n\t\trest = Math.floor(rest / 128);\n\t\tbytes.push((rest > 0 ? 0x80 : 0) | low);\n\t}\n\treturn new Uint8Array(bytes);\n}\n\n/** `OFS_DELTA`'s negative base offset: big-endian base-128 with +1 carries. */\nfunction readOfsDeltaOffset(\n\tbytes: Uint8Array,\n\tstart: number,\n): { distance: number; length: number } {\n\tlet at = start;\n\tlet byte = bytes[at++] as number;\n\tlet distance = byte & 0x7f;\n\twhile (byte & 0x80) {\n\t\tbyte = bytes[at++] as number;\n\t\tdistance = (distance + 1) * 128 + (byte & 0x7f);\n\t}\n\treturn { distance, length: at - start };\n}\n\n/** A pack entry ready to copy, with the oid of its delta base if any. */\ninterface ReusableEntry {\n\treadonly bytes: Uint8Array;\n\treadonly baseOid: string | null;\n}\n\n/** Copy one entry, rewriting `OFS_DELTA` to `REF_DELTA`. */\nfunction reusableEntry(\n\tentry: PackEntry,\n\tindexed: IndexedPack,\n): ReusableEntry | null {\n\tconst { pack, start, end } = entry;\n\tconst header = readEntryHeader(pack, start);\n\tconst bodyStart = start + header.length;\n\tif (header.type === OBJ_REF_DELTA) {\n\t\treturn {\n\t\t\tbytes: pack.subarray(start, end),\n\t\t\tbaseOid: toHex(pack.subarray(bodyStart, bodyStart + OID_BYTES)),\n\t\t};\n\t}\n\tif (header.type !== OBJ_OFS_DELTA) {\n\t\treturn { bytes: pack.subarray(start, end), baseOid: null };\n\t}\n\tconst { distance, length } = readOfsDeltaOffset(pack, bodyStart);\n\tconst baseOid = indexed.oidAtOffset.get(start - distance);\n\tif (baseOid === undefined) return null;\n\treturn {\n\t\tbytes: concat(\n\t\t\tencodeEntryHeader(OBJ_REF_DELTA, header.size),\n\t\t\tfromHex(baseOid),\n\t\t\tpack.subarray(bodyStart + length, end),\n\t\t),\n\t\tbaseOid,\n\t};\n}\n\n/**\n * A pack holding at least `oids`, built from stored entries, or `null` when\n * any of them (or a delta base they need) isn't in a readable pack — e.g. a\n * loose object — so the caller should build the pack another way.\n */\nexport async function buildPackFromExistingPacks(\n\trepo: Repo,\n\toids: readonly string[],\n): Promise<Uint8Array | null> {\n\tconst fsp = rawFs(repo);\n\tconst packDir = `${repo.gitdir}/objects/pack`;\n\tconst packs = parsePackDirectory(\n\t\tawait fsp.readdir(packDir).catch(() => [] as string[]),\n\t).filter((file) => file.kind === \"pack\");\n\n\tconst indexes: IndexedPack[] = [];\n\tfor (const { base } of packs) {\n\t\t// A pack without a readable index can't be reused.\n\t\tconst [pack, idx] = await Promise.all([\n\t\t\tfsp.readFile(`${packDir}/${packFileName(base, \"pack\")}`),\n\t\t\tfsp.readFile(`${packDir}/${packFileName(base, \"idx\")}`),\n\t\t]).catch(() => [null, null]);\n\t\tif (!(pack instanceof Uint8Array) || !(idx instanceof Uint8Array)) {\n\t\t\treturn null;\n\t\t}\n\t\tconst indexed = indexPack(idx, pack);\n\t\tif (!indexed) return null;\n\t\tindexes.push(indexed);\n\t}\n\n\tconst locate = (oid: string): ReusableEntry | null => {\n\t\tfor (const indexed of indexes) {\n\t\t\tconst entry = indexed.entries.get(oid);\n\t\t\tif (entry) return reusableEntry(entry, indexed);\n\t\t}\n\t\treturn null;\n\t};\n\n\t// Depth-first so every base is written before the deltas that use it.\n\tconst ordered: Uint8Array[] = [];\n\tconst done = new Set<string>();\n\tconst pending = new Set<string>();\n\tconst visit = (oid: string): boolean => {\n\t\tif (done.has(oid)) return true;\n\t\tif (pending.has(oid)) return false; // a delta cycle means corruption\n\t\tconst entry = locate(oid);\n\t\tif (!entry) return false;\n\t\tpending.add(oid);\n\t\tif (entry.baseOid !== null && !visit(entry.baseOid)) return false;\n\t\tpending.delete(oid);\n\t\tdone.add(oid);\n\t\tordered.push(entry.bytes);\n\t\treturn true;\n\t};\n\tfor (const oid of oids) {\n\t\tif (!visit(oid)) return null;\n\t}\n\n\tconst header = new Uint8Array(12);\n\theader.set(encodeUtf8(\"PACK\"), 0);\n\tconst view = new DataView(header.buffer);\n\tview.setUint32(4, 2);\n\tview.setUint32(8, ordered.length);\n\tconst body = concat(header, ...ordered);\n\treturn concat(body, fromHex(await sha1(body)));\n}\n","import git from \"isomorphic-git\";\nimport { concat } from \"../edge-utils.js\";\nimport type { Repo } from \"../ops/types.js\";\nimport { packFileName, parsePackDirectory } from \"../pack-files.js\";\nimport { listAllRefs } from \"./info-refs.js\";\nimport { buildPackFromExistingPacks, readPackIndex } from \"./pack-reuse.js\";\nimport { parsePktLines, pktLine, sideBandPackfile } from \"./pkt-line.js\";\nimport { collectCommitAncestry, collectReachableOids } from \"./reachability.js\";\nimport { type GitHttpResult, type HttpHooks, rawFs, runStep } from \"./types.js\";\n\nconst ZERO_OID = \"0\".repeat(40);\n\nexport interface UploadPackOptions {\n\t/**\n\t * Called once before the reachability walk — wire loose-object detection\n\t * (`GitFs.detectLooseObjects`) here so a fully packed repo's walk doesn't\n\t * pay a doomed loose-object probe per object.\n\t */\n\tbeforeWalk?: () => Promise<void>;\n}\n\n/**\n * `POST …/git-upload-pack` — serve a clone/fetch. Authorization is the\n * caller's job. Negotiation is client-driven (no multi_ack advertised):\n * \"have\" batches without \"done\" get a bare NAK; the final batch gets the\n * packfile, side-band-64k framed.\n *\n * Fast path: a fresh clone (no haves) of a repo consolidated down to a\n * single pack serves that pack's bytes directly — skipping the O(objects)\n * traversal + repack entirely.\n */\nconst OID_RE = /^[0-9a-f]{40}$/;\nconst LOOSE_FANOUT_RE = /^[0-9a-f]{2}$/;\n\nfunction result(body: Uint8Array<ArrayBuffer>): GitHttpResult {\n\treturn {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-git-upload-pack-result\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t},\n\t\tbody,\n\t};\n}\n\n/** A protocol-level error the client prints (\"ERR …\"), not an HTTP failure. */\nfunction errorResult(message: string): GitHttpResult {\n\treturn result(pktLine(`ERR ${message}\\n`));\n}\n\n/** Parsed upload-pack request: oids are always 40 lowercase hex digits. */\nexport function parseUploadPackRequest(body: Uint8Array): {\n\twants: string[];\n\thaves: string[];\n\tdone: boolean;\n\tcapabilities: string[];\n\tinvalid: boolean;\n} {\n\tconst wants: string[] = [];\n\tconst haves: string[] = [];\n\tlet done = false;\n\tlet invalid = false;\n\tlet capabilities: string[] | undefined;\n\tfor (const line of parsePktLines(body)) {\n\t\tif (!line) continue;\n\t\tconst text = line.replace(/\\n$/, \"\");\n\t\tif (text.startsWith(\"want \")) {\n\t\t\tconst [oid, ...caps] = text.slice(5).split(\" \");\n\t\t\tif (capabilities === undefined) capabilities = caps.filter(Boolean);\n\t\t\tif (oid !== undefined && OID_RE.test(oid)) wants.push(oid);\n\t\t\telse invalid = true;\n\t\t} else if (text.startsWith(\"have \")) {\n\t\t\tconst oid = text.slice(5).trim();\n\t\t\tif (OID_RE.test(oid)) {\n\t\t\t\tif (oid !== ZERO_OID) haves.push(oid);\n\t\t\t} else {\n\t\t\t\tinvalid = true;\n\t\t\t}\n\t\t} else if (text === \"done\") {\n\t\t\tdone = true;\n\t\t}\n\t}\n\treturn {\n\t\twants: [...new Set(wants)],\n\t\thaves: [...new Set(haves)],\n\t\tdone,\n\t\tcapabilities: capabilities ?? [],\n\t\tinvalid,\n\t};\n}\n\n/**\n * The single pack a fresh clone can be served verbatim, or null. Only safe\n * when nothing lives outside it (no loose objects, exactly one pack) and it\n * holds every wanted object — a repo with commits written as loose objects\n * after its last repack would otherwise clone incomplete.\n */\nasync function servableSinglePack(\n\trepo: Repo,\n\twants: readonly string[],\n\thooks?: HttpHooks,\n): Promise<Uint8Array | null> {\n\tconst fsp = rawFs(repo);\n\tconst objectsDir = `${repo.gitdir}/objects`;\n\tconst [objectEntries, packEntries] = await runStep(\n\t\thooks,\n\t\t\"readdir objects + objects/pack\",\n\t\t() =>\n\t\t\tPromise.all([\n\t\t\t\tfsp.readdir(objectsDir).catch(() => [] as string[]),\n\t\t\t\tfsp.readdir(`${objectsDir}/pack`).catch(() => [] as string[]),\n\t\t\t]),\n\t);\n\tif (objectEntries.some((name) => LOOSE_FANOUT_RE.test(name))) return null;\n\tconst packs = parsePackDirectory(packEntries).filter(\n\t\t(file) => file.kind === \"pack\",\n\t);\n\tconst pack = packs[0];\n\tif (packs.length !== 1 || pack === undefined) return null;\n\tconst [packData, idxData] = await runStep(\n\t\thooks,\n\t\t\"read consolidated pack (fast path)\",\n\t\t() =>\n\t\t\tPromise.all([\n\t\t\t\tfsp.readFile(`${objectsDir}/pack/${pack.name}`),\n\t\t\t\tfsp.readFile(`${objectsDir}/pack/${packFileName(pack.base, \"idx\")}`),\n\t\t\t]).catch(() => [null, null] as const),\n\t);\n\tif (!(packData instanceof Uint8Array) || !(idxData instanceof Uint8Array)) {\n\t\treturn null;\n\t}\n\tconst indexed = readPackIndex(idxData);\n\tif (!indexed) return null;\n\tconst oids = new Set(indexed.map((entry) => entry.oid));\n\treturn wants.every((oid) => oids.has(oid)) ? packData : null;\n}\n\n/**\n * `POST …/git-upload-pack` — serve a clone/fetch. Authorization is the\n * caller's job. Negotiation is client-driven (no multi_ack advertised):\n * \"have\" batches without \"done\" get a bare NAK; the final batch gets the\n * packfile, side-band-64k framed when the client asked for it.\n *\n * Only objects reachable from the repository's refs are served: a want that\n * isn't a ref tip must be an ancestor of one (\"not our ref\" otherwise), so a\n * force-pushed-away commit still sitting in a pack can't be fetched by id.\n *\n * A fetch with haves reads only the client's commit ancestry plus the trees\n * of the boundary commits (the haves the new history builds on) — not every\n * tree the client already has.\n *\n * Fast path: a fresh clone (no haves) of a repo consolidated down to a\n * single pack, with no loose objects, serves that pack's bytes directly —\n * skipping the O(objects) traversal + repack entirely.\n */\nexport async function handleUploadPack(\n\trepo: Repo,\n\tbody: Uint8Array,\n\toptions?: UploadPackOptions,\n\thooks?: HttpHooks,\n): Promise<GitHttpResult> {\n\tconst request = parseUploadPackRequest(body);\n\tif (request.invalid) {\n\t\treturn errorResult(\"upload-pack: protocol error, malformed object id\");\n\t}\n\tconst { wants, haves, done, capabilities } = request;\n\tconst frame = (pack: Uint8Array) =>\n\t\tcapabilities.includes(\"side-band-64k\") || capabilities.includes(\"side-band\")\n\t\t\t? sideBandPackfile(pack)\n\t\t\t: concat(pack);\n\n\tif (wants.length === 0 || (haves.length > 0 && !done)) {\n\t\treturn result(concat(pktLine(\"NAK\\n\")));\n\t}\n\n\tconst { refs } = await runStep(hooks, \"listAllRefs\", () =>\n\t\tlistAllRefs(repo, \"HEAD\"),\n\t);\n\tconst tips = new Set(refs.map((ref) => ref.oid));\n\tconst untipped = wants.filter((oid) => !tips.has(oid));\n\tif (untipped.length > 0) {\n\t\tconst { commits } = await runStep(hooks, \"verify wants reachable\", () =>\n\t\t\tcollectCommitAncestry(repo, [...tips]),\n\t\t);\n\t\tconst missing = untipped.find((oid) => !commits.has(oid));\n\t\tif (missing !== undefined) {\n\t\t\treturn errorResult(`upload-pack: not our ref ${missing}`);\n\t\t}\n\t}\n\n\tif (haves.length === 0) {\n\t\tconst pack = await servableSinglePack(repo, wants, hooks);\n\t\tif (pack) return result(concat(pktLine(\"NAK\\n\"), frame(pack)));\n\t}\n\n\tif (options?.beforeWalk) {\n\t\tawait runStep(hooks, \"beforeWalk\", options.beforeWalk);\n\t}\n\n\tlet haveSet: Set<string> | undefined;\n\tif (haves.length > 0) {\n\t\thaveSet = await runStep(hooks, \"have boundary\", async () => {\n\t\t\t// Everything the client has: its commits' whole ancestry (commits\n\t\t\t// only), plus the full content of the commits our new history\n\t\t\t// builds on. Objects only older commits share may be re-sent —\n\t\t\t// git's own boundary approximation; never anything missing.\n\t\t\tconst { commits: clientCommits } = await collectCommitAncestry(\n\t\t\t\trepo,\n\t\t\t\thaves,\n\t\t\t);\n\t\t\tconst { boundary } = await collectCommitAncestry(\n\t\t\t\trepo,\n\t\t\t\twants,\n\t\t\t\tclientCommits,\n\t\t\t);\n\t\t\tconst boundaryTrees = await Promise.all(\n\t\t\t\t[...boundary].map(async (oid) => {\n\t\t\t\t\tconst { commit } = await git.readCommit({ ...repo, oid });\n\t\t\t\t\treturn commit.tree;\n\t\t\t\t}),\n\t\t\t);\n\t\t\tconst { oids: boundaryObjects } = await collectReachableOids(\n\t\t\t\trepo,\n\t\t\t\tboundaryTrees,\n\t\t\t\thooks,\n\t\t\t\tundefined,\n\t\t\t\t{ verifyBlobs: false },\n\t\t\t);\n\t\t\treturn new Set([...clientCommits, ...boundaryObjects]);\n\t\t});\n\t}\n\n\tconst { oids: wantOids, complete } = await runStep(\n\t\thooks,\n\t\t\"collectReachableOids(wants)\",\n\t\t() =>\n\t\t\tcollectReachableOids(repo, wants, hooks, haveSet, {\n\t\t\t\tverifyBlobs: false,\n\t\t\t}),\n\t);\n\tif (!complete) {\n\t\treturn errorResult(\"upload-pack: repository is missing objects\");\n\t}\n\t// Boundary oids are recorded as seen by the walk; drop them from the pack.\n\tconst oids = haveSet ? wantOids.filter((oid) => !haveSet.has(oid)) : wantOids;\n\n\t// Copy stored (already compressed, possibly deltified) entries when every\n\t// object is packed; build from scratch only when some aren't.\n\tconst reused = await runStep(\n\t\thooks,\n\t\t`reuse pack entries (${oids.length} oids)`,\n\t\t() => buildPackFromExistingPacks(repo, oids),\n\t);\n\tconst packBytes =\n\t\treused ??\n\t\t(await runStep(hooks, `packObjects (${oids.length} oids)`, async () => {\n\t\t\tconst { packfile } = await git.packObjects({ ...repo, oids });\n\t\t\treturn packfile instanceof Uint8Array\n\t\t\t\t? packfile\n\t\t\t\t: new Uint8Array(packfile ?? []);\n\t\t}));\n\n\treturn result(concat(pktLine(\"NAK\\n\"), frame(packBytes)));\n}\n"],"mappings":"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","names":["git","p","git","git","git","git","result","git","ZERO_OID","OID_RE","git"]}