|
|
|
"use strict";
|
|
|
|
|
|
|
|
const EventEmitter = require("events").EventEmitter; // eslint-disable-line fp/no-events
|
|
|
|
const path = require("path");
|
|
|
|
const fs = require("fs");
|
|
|
|
const async = require("async");
|
|
|
|
const Copier = require("recursive-tree-copy").Copier;
|
|
|
|
|
|
|
|
const safeGetEntries = (tree) => {
|
|
|
|
try {
|
|
|
|
return { "entries": tree.gitTree.entries() };
|
|
|
|
} catch (err) {
|
|
|
|
return { err };
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const gitToFsCopier = new Copier({
|
|
|
|
"concurrency": 4,
|
|
|
|
"copyLeaf": (entry, targetDir, callback) => {
|
|
|
|
const targetPath = path.join(targetDir, entry.name());
|
|
|
|
|
|
|
|
entry.getBlob((err, blob) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return fs.writeFile(targetPath, blob.content(), callback);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
"createTargetTree": (tree, targetDir, callback) => {
|
|
|
|
const targetSubdir = path.join(targetDir, tree.name);
|
|
|
|
|
|
|
|
fs.mkdir(targetSubdir, (err) => {
|
|
|
|
// Workaround for broken trees
|
|
|
|
if (err && err.code !== "EEXIST") {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(null, targetSubdir);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
"finalizeTargetTree": (targetSubdir, callback) => callback(),
|
|
|
|
"walkSourceTree": (tree) => {
|
|
|
|
const emitter = new EventEmitter();
|
|
|
|
|
|
|
|
process.nextTick(() => {
|
|
|
|
const { entries, err } = safeGetEntries(tree);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
return emitter.emit("error", err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return async.parallel(entries.map((entry) => (callback) => {
|
|
|
|
if (entry.isTree()) {
|
|
|
|
return entry.getTree((getTreeErr, subTree) => {
|
|
|
|
if (getTreeErr) {
|
|
|
|
return callback(getTreeErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
emitter.emit("tree", {
|
|
|
|
"gitTree": subTree,
|
|
|
|
"name": entry.name()
|
|
|
|
});
|
|
|
|
|
|
|
|
return callback();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry.isFile()) {
|
|
|
|
emitter.emit("leaf", entry);
|
|
|
|
|
|
|
|
return callback();
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback();
|
|
|
|
}), (parallelErr) => {
|
|
|
|
if (parallelErr) {
|
|
|
|
return emitter.emit("error", parallelErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return emitter.emit("done");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return emitter;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
exports.gitToFs = (commit, exportDir, callback) => commit.getTree((err, tree) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return gitToFsCopier.copy({
|
|
|
|
"gitTree": tree,
|
|
|
|
"name": "."
|
|
|
|
}, exportDir, callback);
|
|
|
|
});
|