@pando/git-remote-pando
Version:
git-remote-helper for pando
111 lines (110 loc) • 4.33 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = __importDefault(require("debug"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const shelljs_1 = __importDefault(require("shelljs"));
// tslint:disable-next-line:no-submodule-imports
const promise_1 = __importDefault(require("simple-git/promise"));
const smart_buffer_1 = require("smart-buffer");
const zlib_1 = __importDefault(require("zlib"));
const git = promise_1.default();
class GitHelper {
// OK
constructor(helper) {
this.helper = helper;
this.debug = debug_1.default('pando');
}
/***** core methods *****/
// OK
async collect(oid, mapping) {
this.debug('collecting', oid);
const cid = this.helper.ipld.shaToCid(oid);
if (mapping[cid])
return mapping;
const node = await this.load(oid);
if (node.gitType === 'commit') {
// node is a commit
const _mapping = await this.collect(this.helper.ipld.cidToSha(node.tree['/']), mapping);
return Object.assign({}, mapping, _mapping, { [cid]: node });
}
else if (Buffer.isBuffer(node)) {
// node is a blob
return Object.assign({}, mapping, { [cid]: node });
}
else {
// node is a tree
// tslint:disable-next-line:forin
for (const entry in node) {
const _mapping = await this.collect(this.helper.ipld.cidToSha(node[entry].hash['/']), mapping);
mapping = Object.assign({}, mapping, _mapping);
}
return Object.assign({}, mapping, { [cid]: node });
}
}
// OK
async download(oid) {
this.debug('downloading', oid);
if (await this.exists(oid))
return;
const cid = this.helper.ipld.shaToCid(oid);
const node = await this.helper.ipld.get(cid);
if (node.gitType === 'commit') {
// node is a commit
await this.download(this.helper.ipld.cidToSha(node.tree['/']));
for (const parent of node.parents) {
await this.download(this.helper.ipld.cidToSha(parent['/']));
}
await this.dump(oid, node);
}
else if (Buffer.isBuffer(node)) {
// node is a blob
await this.dump(oid, node);
}
else {
// node is a tree
// tslint:disable-next-line:forin
for (const entry in node) {
await this.download(await this.helper.ipld.cidToSha(node[entry].hash['/']));
}
await this.dump(oid, node);
}
}
/***** fs-related methods *****/
// OK
async exists(oid) {
// modify this function to rely on git cat-file -e $sha^{commit}
// see https://stackoverflow.com/questions/18515488/how-to-check-if-the-commit-exists-in-a-git-repository-by-its-sha-1
return fs_extra_1.default.pathExists(await this.path(oid));
}
// OK
async load(oid) {
const type = shelljs_1.default.exec(`git cat-file -t ${oid}`, { silent: true }).stdout.trim();
const size = shelljs_1.default.exec(`git cat-file -s ${oid}`, { silent: true }).stdout.trim();
const data = await git.binaryCatFile([type, oid]);
const raw = new smart_buffer_1.SmartBuffer();
raw.writeString(`${type} `);
raw.writeString(size);
raw.writeUInt8(0);
raw.writeBuffer(data);
return this.helper.ipld.deserialize(raw.toBuffer());
}
// OK
async dump(oid, node) {
const path = await this.path(oid);
const buffer = await this.helper.ipld.serialize(node);
await fs_extra_1.default.ensureFile(path);
fs_extra_1.default.writeFileSync(path, zlib_1.default.deflateSync(buffer));
}
/***** utility methods *****/
// OK
async path(oid) {
const subdirectory = oid.substring(0, 2);
const filename = oid.substring(2);
return path_1.default.join(this.helper.path, 'objects', subdirectory, filename);
}
}
exports.default = GitHelper;