UNPKG

git-cat-file

Version:

A pure-JavaScript implementation of `git cat-file -p` for Node.js.

92 lines (74 loc) 2.35 kB
/** * https://github.com/kawanet/git-cat-file */ import type {GCF} from "../types/git-cat-file.d.ts" import {getFileMode} from "./file-mode.ts" import type {ObjStore} from "./obj-store.ts" export class Tree implements GCF.Tree { private readonly obj: GCF.IObject protected readonly store: ObjStore constructor(obj: GCF.IObject, store: ObjStore) { if (obj.type !== "tree") { throw new TypeError(`Invalid tree object: ${obj.oid} (${obj.type})`) } this.obj = obj this.store = store } getId(): string { return this.obj.oid } async getEntries(): Promise<GCF.Entry[]> { return parseTree(this.obj.data) } async getEntry(path: string): Promise<GCF.Entry> { let tree: GCF.Tree = this if (/\//.test(path)) { const names = path.split("/") path = names.pop() if (!path) path = names.pop() tree = await this.getTree(names.join("/")) } if (!tree) return const list = await tree.getEntries() return list.filter(item => item.name === path).shift() } async getTree(path: string): Promise<GCF.Tree> { let tree: Tree = this for (const name of path.split("/")) { if (!name) continue const entry = await tree.getEntry(name) if (!entry) return const obj = await this.store.getObject(entry.oid) if (!obj) return tree = new Tree(obj, this.store) } return tree } } function parseTree(data: Buffer): GCF.Entry[] { const list: GCF.Entry[] = [] let start = 0 let end: number const {length} = data while (start < length) { end = findZero(data, start) const line = data.slice(start, end - 1).toString() const [modeStr, name] = splitBySpace(line) const mode = getFileMode(modeStr) start = end + 20 const oid = data.slice(end, start).toString("hex") list.push({mode, name, oid}) } return list } function findZero(buf: Buffer, offset?: number): number { offset |= 0 while (buf[offset++]) { // nop } return offset } function splitBySpace(line: string): string[] { const sp = line.indexOf(" ") return [line.slice(0, sp), line.slice(sp + 1)] }