@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
88 lines • 12.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.fingerprint = void 0;
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const options_1 = require("./options");
const utils_1 = require("./utils");
const BUFFER_SIZE = 8 * 1024;
const CTRL_SOH = '\x01';
const CTRL_SOT = '\x02';
const CTRL_ETX = '\x03';
/**
* Produces fingerprint based on the contents of a single file or an entire directory tree.
*
* The fingerprint will also include:
* 1. An extra string if defined in `options.extra`.
* 2. The set of exclude patterns, if defined in `options.exclude`
* 3. The symlink follow mode value.
*
* @param fileOrDirectory The directory or file to fingerprint
* @param options Fingerprinting options
*/
function fingerprint(fileOrDirectory, options = {}) {
const hash = crypto.createHash('sha256');
_hashField(hash, 'options.extra', options.extraHash || '');
const follow = options.follow || options_1.SymlinkFollowMode.EXTERNAL;
_hashField(hash, 'options.follow', follow);
const rootDirectory = fs.statSync(fileOrDirectory).isDirectory()
? fileOrDirectory
: path.dirname(fileOrDirectory);
const exclude = options.exclude || [];
if (exclude.length) {
_hashField(hash, 'options.exclude', JSON.stringify(exclude));
}
const isDir = fs.statSync(fileOrDirectory).isDirectory();
_processFileOrDirectory(fileOrDirectory, isDir);
return hash.digest('hex');
function _processFileOrDirectory(symbolicPath, isRootDir = false, realPath = symbolicPath) {
if (!isRootDir && utils_1.shouldExclude(exclude, symbolicPath)) {
return;
}
const stat = fs.lstatSync(realPath);
const relativePath = path.relative(fileOrDirectory, symbolicPath);
if (stat.isSymbolicLink()) {
const linkTarget = fs.readlinkSync(realPath);
const resolvedLinkTarget = path.resolve(path.dirname(realPath), linkTarget);
if (utils_1.shouldFollow(follow, rootDirectory, resolvedLinkTarget)) {
_processFileOrDirectory(symbolicPath, false, resolvedLinkTarget);
}
else {
_hashField(hash, `link:${relativePath}`, linkTarget);
}
}
else if (stat.isFile()) {
_hashField(hash, `file:${relativePath}`, _contentFingerprint(realPath, stat));
}
else if (stat.isDirectory()) {
for (const item of fs.readdirSync(realPath).sort()) {
_processFileOrDirectory(path.join(symbolicPath, item), false, path.join(realPath, item));
}
}
else {
throw new Error(`Unable to hash ${symbolicPath}: it is neither a file nor a directory`);
}
}
}
exports.fingerprint = fingerprint;
function _contentFingerprint(file, stat) {
const hash = crypto.createHash('sha256');
const buffer = Buffer.alloc(BUFFER_SIZE);
// eslint-disable-next-line no-bitwise
const fd = fs.openSync(file, fs.constants.O_DSYNC | fs.constants.O_RDONLY | fs.constants.O_SYNC);
try {
let read = 0;
while ((read = fs.readSync(fd, buffer, 0, BUFFER_SIZE, null)) !== 0) {
hash.update(buffer.slice(0, read));
}
}
finally {
fs.closeSync(fd);
}
return `${stat.size}:${hash.digest('hex')}`;
}
function _hashField(hash, header, value) {
hash.update(CTRL_SOH).update(header).update(CTRL_SOT).update(value).update(CTRL_ETX);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmluZ2VycHJpbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJmaW5nZXJwcmludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpQ0FBaUM7QUFDakMseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qix1Q0FBa0U7QUFDbEUsbUNBQXNEO0FBRXRELE1BQU0sV0FBVyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7QUFDN0IsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDO0FBQ3hCLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQztBQUN4QixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUM7QUFFeEI7Ozs7Ozs7Ozs7R0FVRztBQUNILFNBQWdCLFdBQVcsQ0FBQyxlQUF1QixFQUFFLFVBQThCLEVBQUc7SUFDcEYsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6QyxVQUFVLENBQUMsSUFBSSxFQUFFLGVBQWUsRUFBRSxPQUFPLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzNELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLElBQUksMkJBQWlCLENBQUMsUUFBUSxDQUFDO0lBQzVELFVBQVUsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFFM0MsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxXQUFXLEVBQUU7UUFDOUQsQ0FBQyxDQUFDLGVBQWU7UUFDakIsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDbEMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUM7SUFDdEMsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFO1FBQ2xCLFVBQVUsQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMs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LENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDcEM7S0FDRjtZQUFTO1FBQ1IsRUFBRSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztLQUNsQjtJQUNELE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUM5QyxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsSUFBaUIsRUFBRSxNQUFjLEVBQUUsS0FBaUM7SUFDdEYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDdkYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IEZpbmdlcnByaW50T3B0aW9ucywgU3ltbGlua0ZvbGxvd01vZGUgfSBmcm9tICcuL29wdGlvbnMnO1xuaW1wb3J0IHsgc2hvdWxkRXhjbHVkZSwgc2hvdWxkRm9sbG93IH0gZnJvbSAnLi91dGlscyc7XG5cbmNvbnN0IEJVRkZFUl9TSVpFID0gOCAqIDEwMjQ7XG5jb25zdCBDVFJMX1NPSCA9ICdcXHgwMSc7XG5jb25zdCBDVFJMX1NPVCA9ICdcXHgwMic7XG5jb25zdCBDVFJMX0VUWCA9ICdcXHgwMyc7XG5cbi8qKlxuICogUHJvZHVjZXMgZmluZ2VycHJpbnQgYmFzZWQgb24gdGhlIGNvbnRlbnRzIG9mIGEgc2luZ2xlIGZpbGUgb3IgYW4gZW50aXJlIGRpcmVjdG9yeSB0cmVlLlxuICpcbiAqIFRoZSBmaW5nZXJwcmludCB3aWxsIGFsc28gaW5jbHVkZTpcbiAqIDEuIEFuIGV4dHJhIHN0cmluZyBpZiBkZWZpbmVkIGluIGBvcHRpb25zLmV4dHJhYC5cbiAqIDIuIFRoZSBzZXQgb2YgZXhjbHVkZSBwYXR0ZXJucywgaWYgZGVmaW5lZCBpbiBgb3B0aW9ucy5leGNsdWRlYFxuICogMy4gVGhlIHN5bWxpbmsgZm9sbG93IG1vZGUgdmFsdWUuXG4gKlxuICogQHBhcmFtIGZpbGVPckRpcmVjdG9yeSBUaGUgZGlyZWN0b3J5IG9yIGZpbGUgdG8gZmluZ2VycHJpbnRcbiAqIEBwYXJhbSBvcHRpb25zIEZpbmdlcnByaW50aW5nIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmdlcnByaW50KGZpbGVPckRpcmVjdG9yeTogc3RyaW5nLCBvcHRpb25zOiBGaW5nZXJwcmludE9wdGlvbnMgPSB7IH0pIHtcbiAgY29uc3QgaGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKTtcbiAgX2hhc2hGaWVsZChoYXNoLCAnb3B0aW9ucy5leHRyYScsIG9wdGlvbnMuZXh0cmFIYXNoIHx8ICcnKTtcbiAgY29uc3QgZm9sbG93ID0gb3B0aW9ucy5mb2xsb3cgfHwgU3ltbGlua0ZvbGxvd01vZGUuRVhURVJOQUw7XG4gIF9oYXNoRmllbGQoaGFzaCwgJ29wdGlvbnMuZm9sbG93JywgZm9sbG93KTtcblxuICBjb25zdCByb290RGlyZWN0b3J5ID0gZnMuc3RhdFN5bmMoZmlsZU9yRGlyZWN0b3J5KS5pc0RpcmVjdG9yeSgpXG4gICAgPyBmaWxlT3JEaXJlY3RvcnlcbiAgICA6IHBhdGguZGlybmFtZShmaWxlT3JEaXJlY3RvcnkpO1xuICBjb25zdCBleGNsdWRlID0gb3B0aW9ucy5leGNsdWRlIHx8IFtdO1xuICBpZiAoZXhjbHVkZS5sZW5ndGgpIHtcbiAgICBfaGFzaEZpZWxkKGhhc2gsICdvcHRpb25zLmV4Y2x1ZGUnLCBKU09OLnN0cmluZ2lmeShleGNsdWRlKSk7XG4gIH1cbiAgY29uc3QgaXNEaXIgPSBmcy5zdGF0U3luYyhmaWxlT3JEaXJlY3RvcnkpLmlzRGlyZWN0b3J5KCk7XG4gIF9wcm9jZXNzRmlsZU9yRGlyZWN0b3J5KGZpbGVPckRpcmVjdG9yeSwgaXNEaXIpO1xuXG4gIHJldHVybiBoYXNoLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgZnVuY3Rpb24gX3Byb2Nlc3NGaWxlT3JEaXJlY3Rvcnkoc3ltYm9saWNQYXRoOiBzdHJpbmcsIGlzUm9vdERpcjogYm9vbGVhbiA9IGZhbHNlLCByZWFsUGF0aCA9IHN5bWJvbGljUGF0aCkge1xuICAgIGlmICghaXNSb290RGlyICYmIHNob3VsZEV4Y2x1ZGUoZXhjbHVkZSwgc3ltYm9saWNQYXRoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN0YXQgPSBmcy5sc3RhdFN5bmMocmVhbFBhdGgpO1xuICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IHBhdGgucmVsYXRpdmUoZmlsZU9yRGlyZWN0b3J5LCBzeW1ib2xpY1BhdGgpO1xuXG4gICAgaWYgKHN0YXQuaXNTeW1ib2xpY0xpbmsoKSkge1xuICAgICAgY29uc3QgbGlua1RhcmdldCA9IGZzLnJlYWRsaW5rU3luYyhyZWFsUGF0aCk7XG4gICAgICBjb25zdCByZXNvbHZlZExpbmtUYXJnZXQgPSBwYXRoLnJlc29sdmUocGF0aC5kaXJuYW1lKHJlYWxQYXRoKSwgbGlua1RhcmdldCk7XG4gICAgICBpZiAoc2hvdWxkRm9sbG93KGZvbGxvdywgcm9vdERpcmVjdG9yeSwgcmVzb2x2ZWRMaW5rVGFyZ2V0KSkge1xuICAgICAgICBfcHJvY2Vzc0ZpbGVPckRpcmVjdG9yeShzeW1ib2xpY1BhdGgsIGZhbHNlLCByZXNvbHZlZExpbmtUYXJnZXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgX2hhc2hGaWVsZChoYXNoLCBgbGluazoke3JlbGF0aXZlUGF0aH1gLCBsaW5rVGFyZ2V0KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHN0YXQuaXNGaWxlKCkpIHtcbiAgICAgIF9oYXNoRmllbGQoaGFzaCwgYGZpbGU6JHtyZWxhdGl2ZVBhdGh9YCwgX2NvbnRlbnRGaW5nZXJwcmludChyZWFsUGF0aCwgc3RhdCkpO1xuICAgIH0gZWxzZSBpZiAoc3RhdC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgZnMucmVhZGRpclN5bmMocmVhbFBhdGgpLnNvcnQoKSkge1xuICAgICAgICBfcHJvY2Vzc0ZpbGVPckRpcmVjdG9yeShwYXRoLmpvaW4oc3ltYm9saWNQYXRoLCBpdGVtKSwgZmFsc2UsIHBhdGguam9pbihyZWFsUGF0aCwgaXRlbSkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBoYXNoICR7c3ltYm9saWNQYXRofTogaXQgaXMgbmVpdGhlciBhIGZpbGUgbm9yIGEgZGlyZWN0b3J5YCk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9jb250ZW50RmluZ2VycHJpbnQoZmlsZTogc3RyaW5nLCBzdGF0OiBmcy5TdGF0cyk6IHN0cmluZyB7XG4gIGNvbnN0IGhhc2ggPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2Jyk7XG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhCVUZGRVJfU0laRSk7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gIGNvbnN0IGZkID0gZnMub3BlblN5bmMoZmlsZSwgZnMuY29uc3RhbnRzLk9fRFNZTkMgfCBmcy5jb25zdGFudHMuT19SRE9OTFkgfCBmcy5jb25zdGFudHMuT19TWU5DKTtcbiAgdHJ5IHtcbiAgICBsZXQgcmVhZCA9IDA7XG4gICAgd2hpbGUgKChyZWFkID0gZnMucmVhZFN5bmMoZmQsIGJ1ZmZlciwgMCwgQlVGRkVSX1NJWkUsIG51bGwpKSAhPT0gMCkge1xuICAgICAgaGFzaC51cGRhdGUoYnVmZmVyLnNsaWNlKDAsIHJlYWQpKTtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgZnMuY2xvc2VTeW5jKGZkKTtcbiAgfVxuICByZXR1cm4gYCR7c3RhdC5zaXplfToke2hhc2guZGlnZXN0KCdoZXgnKX1gO1xufVxuXG5mdW5jdGlvbiBfaGFzaEZpZWxkKGhhc2g6IGNyeXB0by5IYXNoLCBoZWFkZXI6IHN0cmluZywgdmFsdWU6IHN0cmluZyB8IEJ1ZmZlciB8IERhdGFWaWV3KSB7XG4gIGhhc2gudXBkYXRlKENUUkxfU09IKS51cGRhdGUoaGVhZGVyKS51cGRhdGUoQ1RSTF9TT1QpLnVwZGF0ZSh2YWx1ZSkudXBkYXRlKENUUkxfRVRYKTtcbn1cbiJdfQ==