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
112 lines
3.1 KiB
JavaScript
2 years ago
|
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);
|
||
|
}
|