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.

113 lines
3.2 KiB
JavaScript

2 years ago
import readdir from 'readdir-enhanced';
import fs from 'fs';
import crypto from 'crypto';
import multimatch from 'multimatch';
import { cfg } from './repo-config.js';
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 = [];
console.log(files.length, 'items');
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. Generate local",
version: '1.0.0',
generatedTime: new Date().getTime(),
generatedTimeString: new Date().toLocaleString(),
data: records,
};
}
try {
const [, , repoArg] = process.argv;
2 years ago
const options = Object.keys(cfg).join(' | ');
2 years ago
if (!repoArg) {
2 years ago
throw `error: Pls input repo: ${options}`;
2 years ago
}
2 years ago
const filename = `.ftp-deploy-sync-state.json`;
2 years ago
const _args = {
'local-dir': `./../${cfg[repoArg].folder}/`,
'state-name': filename,
'exclude': [filename, 'ftp-state/**'].concat(cfg[repoArg].exclude),
};
const localFiles = await getLocalFiles(_args);
createLocalState(localFiles, _args);
} catch (error) {
console.log(error);
}