chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
/**
* Git bundle file parsing: a text header (format marker, optional
* capabilities, prerequisites, refs) terminated by a blank line, followed by
* a complete packfile.
*/
const decoder = new TextDecoder();
/**
* @typedef {Object} ParsedBundle
* @property {2|3} version
* @property {Array<{sha: string, name: string}>} refs
* @property {string[]} prerequisites
* @property {Record<string, string>} capabilities
* @property {Uint8Array} pack - the complete packfile region
*/
/**
* @param {Uint8Array} bytes
* @returns {ParsedBundle}
*/
export function parseBundle(bytes) {
/** @type {Array<{sha: string, name: string}>} */
const refs = [];
/** @type {string[]} */
const prerequisites = [];
/** @type {Record<string, string>} */
const capabilities = {};
/** @type {2|3|null} */
let version = null;
let offset = 0;
let lineStart = 0;
let sawSignature = false;
while (offset < bytes.length) {
if (bytes[offset] !== 0x0a) {
offset++;
continue;
}
const line = decoder.decode(bytes.subarray(lineStart, offset));
offset++;
lineStart = offset;
if (!sawSignature) {
if (line === '# v2 git bundle') version = 2;
else if (line === '# v3 git bundle') version = 3;
else throw new Error('not a git bundle');
sawSignature = true;
continue;
}
if (line === '') break;
if (line.startsWith('@')) {
const eq = line.indexOf('=');
if (eq === -1) capabilities[line.slice(1)] = '';
else capabilities[line.slice(1, eq)] = line.slice(eq + 1);
continue;
}
if (line.startsWith('-')) {
prerequisites.push(line.slice(1).split(' ')[0]);
continue;
}
const space = line.indexOf(' ');
if (space === -1) throw new Error('malformed bundle ref line');
refs.push({ sha: line.slice(0, space), name: line.slice(space + 1) });
}
if (version === null) throw new Error('not a git bundle');
return {
version,
refs,
prerequisites,
capabilities,
pack: bytes.subarray(lineStart),
};
}