Swap-Aggregator-Subgraph/node_modules/fs-jetpack/lib/inspect_tree.js
2022-07-03 07:27:35 +05:30

184 lines
5.1 KiB
JavaScript

"use strict";
const crypto = require("crypto");
const pathUtil = require("path");
const inspect = require("./inspect");
const list = require("./list");
const validate = require("./utils/validate");
const validateInput = (methodName, path, options) => {
const methodSignature = `${methodName}(path, [options])`;
validate.argument(methodSignature, "path", path, ["string"]);
validate.options(methodSignature, "options", options, {
checksum: ["string"],
relativePath: ["boolean"],
times: ["boolean"],
symlinks: ["string"]
});
if (
options &&
options.checksum !== undefined &&
inspect.supportedChecksumAlgorithms.indexOf(options.checksum) === -1
) {
throw new Error(
`Argument "options.checksum" passed to ${methodSignature} must have one of values: ${inspect.supportedChecksumAlgorithms.join(
", "
)}`
);
}
if (
options &&
options.symlinks !== undefined &&
inspect.symlinkOptions.indexOf(options.symlinks) === -1
) {
throw new Error(
`Argument "options.symlinks" passed to ${methodSignature} must have one of values: ${inspect.symlinkOptions.join(
", "
)}`
);
}
};
const generateTreeNodeRelativePath = (parent, path) => {
if (!parent) {
return ".";
}
return `${parent.relativePath}/${pathUtil.basename(path)}`;
};
// Creates checksum of a directory by using
// checksums and names of all its children inside.
const checksumOfDir = (inspectList, algo) => {
const hash = crypto.createHash(algo);
inspectList.forEach(inspectObj => {
hash.update(inspectObj.name + inspectObj[algo]);
});
return hash.digest("hex");
};
// ---------------------------------------------------------
// Sync
// ---------------------------------------------------------
const inspectTreeNodeSync = (path, options, parent) => {
const treeBranch = inspect.sync(path, options);
if (treeBranch) {
if (options.relativePath) {
treeBranch.relativePath = generateTreeNodeRelativePath(parent, path);
}
if (treeBranch.type === "dir") {
treeBranch.size = 0;
treeBranch.children = list.sync(path).map(filename => {
const subBranchPath = pathUtil.join(path, filename);
const treeSubBranch = inspectTreeNodeSync(
subBranchPath,
options,
treeBranch
);
// Add together all childrens' size to get directory combined size.
treeBranch.size += treeSubBranch.size || 0;
return treeSubBranch;
});
if (options.checksum) {
treeBranch[options.checksum] = checksumOfDir(
treeBranch.children,
options.checksum
);
}
}
}
return treeBranch;
};
const inspectTreeSync = (path, options) => {
const opts = options || {};
return inspectTreeNodeSync(path, opts, undefined);
};
// ---------------------------------------------------------
// Async
// ---------------------------------------------------------
const inspectTreeNodeAsync = (path, options, parent) => {
return new Promise((resolve, reject) => {
const inspectAllChildren = treeBranch => {
return new Promise((resolve2, reject2) => {
list.async(path).then(children => {
const doNext = index => {
if (index === children.length) {
if (options.checksum) {
// We are done, but still have to calculate checksum of whole directory.
treeBranch[options.checksum] = checksumOfDir(
treeBranch.children,
options.checksum
);
}
resolve2();
} else {
const subPath = pathUtil.join(path, children[index]);
inspectTreeNodeAsync(subPath, options, treeBranch)
.then(treeSubBranch => {
children[index] = treeSubBranch;
treeBranch.size += treeSubBranch.size || 0;
doNext(index + 1);
})
.catch(reject2);
}
};
treeBranch.children = children;
treeBranch.size = 0;
doNext(0);
});
});
};
inspect
.async(path, options)
.then(treeBranch => {
if (!treeBranch) {
// Given path doesn't exist. We are done.
resolve(treeBranch);
} else {
if (options.relativePath) {
treeBranch.relativePath = generateTreeNodeRelativePath(
parent,
path
);
}
if (treeBranch.type !== "dir") {
resolve(treeBranch);
} else {
inspectAllChildren(treeBranch)
.then(() => {
resolve(treeBranch);
})
.catch(reject);
}
}
})
.catch(reject);
});
};
const inspectTreeAsync = (path, options) => {
const opts = options || {};
return inspectTreeNodeAsync(path, opts);
};
// ---------------------------------------------------------
// API
// ---------------------------------------------------------
exports.validateInput = validateInput;
exports.sync = inspectTreeSync;
exports.async = inspectTreeAsync;