git-cat-file
Version:
Pure JavaScript `git cat-file -p` for node.js
55 lines (54 loc) • 1.94 kB
JavaScript
;
/**
* https://github.com/kawanet/git-cat-file
*
* @see https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.readPackIndex = void 0;
const fs_1 = require("fs");
const toHex = (buf) => buf.toString("hex").replace(/(\w.)(?=\w)/g, "$1 ");
async function readPackIndex(path) {
path = path.replace(/\.pack$/, ".idx");
if (!/\.idx$/.test(path))
throw TypeError(`Invalid pack index file: ${path}`);
const data = await fs_1.promises.readFile(path);
return parsePackIndex(data);
}
exports.readPackIndex = readPackIndex;
async function parsePackIndex(data) {
// validate header
const headByte = data.slice(0, 4);
const head = headByte.toString("latin1");
if (head !== "\xFFtOc")
throw TypeError(`Invalid header: ${toHex(headByte)}`);
// validate version number
const version = data.readUInt32BE(4);
if (version !== 2)
throw TypeError(`Invalid version number: ${version}`);
let oidIdx = 8 + 4 * 256;
// total objects count
const total = data.readUInt32BE(oidIdx - 4);
// console.warn(`found: ${total} packed objects`);
const oidLast = oidIdx + 20 * total;
let table4Idx = oidLast + 4 * total;
let table8Idx = table4Idx + 4 * total;
const packIndex = {};
while (oidIdx < oidLast) {
const end = oidIdx + 20;
const oid = data.slice(oidIdx, end).toString("hex");
let pos = data.readUInt32BE(table4Idx);
table4Idx += 4;
if (pos & 0x80000000) {
// console.warn(pos.toString(16));
const high = data.readUInt32BE(table8Idx);
table8Idx += 4;
const low = data.readUInt32BE(table8Idx);
table8Idx += 4;
pos = high * 0x100000000 + low;
}
packIndex[oid] = pos;
oidIdx = end;
}
return packIndex;
}