You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.1 KiB
JavaScript

import readdir from "readdir-enhanced";
import fs from "fs";
import crypto from "crypto";
import multimatch from "multimatch";
function applyExcludeFilter(stat, excludeFilters) {
// match exclude, return immediatley
if (excludeFilters.length > 0) {
// todo this could be a performance problem...
const pathWithFolderSlash = stat.path + (stat.isDirectory() ? "/" : "");
const excludeMatch = multimatch(pathWithFolderSlash, excludeFilters, { matchBase: true, dot: true });
if (excludeMatch.length > 0) {
return false;
}
}
return true;
}
/**
* @param algorithm : "md5" | "sha1" | "sha256" | "sha512"
*/
async function fileHash(filename, algorithm) {
return new Promise((resolve, reject) => {
// Algorithm depends on availability of OpenSSL on platform
// Another algorithms: "sha1", "md5", "sha256", "sha512" ...
let shasum = crypto.createHash(algorithm);
try {
let s = fs.createReadStream(filename);
s.on("data", function (data) {
shasum.update(data)
});
s.on("error", function (error) {
reject(error);
});
// making digest
s.on("end", function () {
const hash = shasum.digest("hex")
return resolve(hash);
});
}
catch (error) {
return reject("calc fail");
}
});
}
function createLocalState(localFiles, args) {
console.log(`Creating local state at ${args["local-dir"]}${args["state-name"]}`);
fs.writeFileSync(`${args["local-dir"]}${args["state-name"]}`, JSON.stringify(localFiles, undefined, 4), { encoding: "utf8" });
console.log("Local state created");
}
async function getLocalFiles(args) {
const files = await readdir.async(args["local-dir"], { deep: true, stats: true, sep: "/", filter: (stat) => applyExcludeFilter(stat, args.exclude) });
let records = [];
for (let stat of files) {
if (stat.isDirectory()) {
records.push({
type: "folder",
name: stat.path,
size: undefined
});
continue;
}
if (stat.isFile()) {
records.push({
type: "file",
name: stat.path,
size: stat.size,
hash: await fileHash(args["local-dir"] + stat.path, "sha256")
});
continue;
}
if (stat.isSymbolicLink()) {
console.warn("This script is currently unable to handle symbolic links - please add a feature request if you need this");
}
}
return {
description: 'Don\'t delete',
version: '1.0.0',
generatedTime: new Date().getTime(),
data: records
};
}
try {
const filename = ".generate-file-hash.json";
const _args = {
'local-dir': './',
'state-name': filename,
'exclude': [
'**/node_modules/**',
'**/.git*/**',
'**/.git*/**',
filename,
]
};
const localFiles = await getLocalFiles(_args);
createLocalState(localFiles, _args);
} catch (error) {
console.log(error);
}