import { concatBytes, FLUSH_PKT, packetText, parseAllPackets, pktLine } from "./pktline";
const PRIVATE_PREFIX = "refs/gitfor/";
const ZERO_SHA = "0".repeat(40);
/** Whether `name` is a ref clients must never see: base commits bridged into a fork for its pull requests. */
export function isPrivateRef(name: string): boolean {
return name.startsWith(PRIVATE_PREFIX);
}
function refsOf(lines: string[]): Map<string, string> {
const refs = new Map<string, string>();
for (const line of lines) {
const [sha, name] = (line.split("\0")[0] ?? "").split(" ");
if (sha && name) refs.set(name, sha);
}
return refs;
}
/** Points `symref=HEAD:...` in a v0 capability list at the configured default branch. */
function withDefaultHead(caps: string, branchRef: string): string {
const others = caps.split(" ").filter((cap) => cap !== "" && !cap.startsWith("symref=HEAD:"));
return [...others, `symref=HEAD:${branchRef}`].join(" ");
}
/**
* Rewrites a v0 upload-pack advertisement:
* - removes `refs/gitfor/*`. Capabilities ride on the first ref line, so they move to the next kept ref
* (or to a `capabilities^{}` placeholder when none is left);
* - points HEAD at `defaultBranch`, because Artifacts' own HEAD never follows the repository setting.
*/
export function filterAdvertisement(body: Uint8Array, defaultBranch?: string): Uint8Array<ArrayBuffer> {
const packets = parseAllPackets(body);
const texts = packets.map((packet) => (packet.kind === "data" ? (packetText(packet) ?? "") : ""));
const refs = refsOf(texts.filter((line) => line && !line.startsWith("#")));
const branchRef = defaultBranch ? `refs/heads/${defaultBranch}` : null;
const headSha = branchRef ? refs.get(branchRef) : undefined;
const out: Uint8Array[] = [];
let pendingCaps: string | null = null;
let sawRefs = false;