API/api.medcify.app/node_modules/js-git/mixins/walkers.js

153 lines
3.8 KiB
JavaScript
Raw Normal View History

2022-09-26 06:11:44 +00:00
var modes = require('../lib/modes.js');
module.exports = function (repo) {
repo.logWalk = logWalk; // (ref) => stream<commit>
repo.treeWalk = treeWalk; // (treeHash) => stream<object>
};
module.exports.walk = walk;
function logWalk(ref, callback) {
if (!callback) return logWalk.bind(this, ref);
var last, seen = {};
var repo = this;
if (!repo.readRef) return onShallow();
return repo.readRef("shallow", onShallow);
function onShallow(err, shallow) {
last = shallow;
resolveRef(repo, ref, onHash);
}
function onHash(err, hash) {
if (err) return callback(err);
return repo.loadAs("commit", hash, function (err, commit) {
if (commit === undefined) return callback(err);
commit.hash = hash;
seen[hash] = true;
return callback(null, walk(commit, scan, loadKey, compare));
});
}
function scan(commit) {
if (last === commit) return [];
return commit.parents.filter(function (hash) {
return !seen[hash];
});
}
function loadKey(hash, callback) {
return repo.loadAs("commit", hash, function (err, commit) {
if (!commit) return callback(err || new Error("Missing commit " + hash));
commit.hash = hash;
if (hash === last) commit.last = true;
return callback(null, commit);
});
}
}
function compare(commit, other) {
return commit.author.date < other.author.date;
}
function treeWalk(hash, callback) {
if (!callback) return treeWalk.bind(this, hash);
var repo = this;
return repo.loadAs("tree", hash, onTree);
function onTree(err, body) {
if (!body) return callback(err || new Error("Missing tree " + hash));
var tree = {
mode: modes.tree,
hash: hash,
body: body,
path: "/"
};
return callback(null, walk(tree, treeScan, treeLoadKey, treeCompare));
}
function treeLoadKey(entry, callback) {
if (entry.mode !== modes.tree) return callback(null, entry);
var type = modes.toType(entry.mode);
return repo.loadAs(type, entry.hash, function (err, body) {
if (err) return callback(err);
entry.body = body;
return callback(null, entry);
});
}
}
function treeScan(object) {
if (object.mode !== modes.tree) return [];
var tree = object.body;
return Object.keys(tree).map(function (name) {
var entry = tree[name];
var path = object.path + name;
if (entry.mode === modes.tree) path += "/";
return {
mode: entry.mode,
hash: entry.hash,
path: path
};
});
}
function treeCompare(first, second) {
return first.path < second.path;
}
function resolveRef(repo, hashish, callback) {
if (/^[0-9a-f]{40}$/.test(hashish)) {
return callback(null, hashish);
}
repo.readRef(hashish, function (err, hash) {
if (!hash) return callback(err || new Error("Bad ref " + hashish));
callback(null, hash);
});
}
function walk(seed, scan, loadKey, compare) {
var queue = [seed];
var working = 0, error, cb;
return {read: read, abort: abort};
function read(callback) {
if (!callback) return read;
if (cb) return callback(new Error("Only one read at a time"));
if (working) { cb = callback; return; }
var item = queue.shift();
if (!item) return callback();
try { scan(item).forEach(onKey); }
catch (err) { return callback(err); }
return callback(null, item);
}
function abort(callback) { return callback(); }
function onError(err) {
if (cb) {
var callback = cb; cb = null;
return callback(err);
}
error = err;
}
function onKey(key) {
working++;
loadKey(key, onItem);
}
function onItem(err, item) {
working--;
if (err) return onError(err);
var index = queue.length;
while (index && compare(item, queue[index - 1])) index--;
queue.splice(index, 0, item);
if (!working && cb) {
var callback = cb; cb = null;
return read(callback);
}
}
}