UNPKG

@mjcctech/meteor-desktop

Version:

Build a Meteor's desktop client with hot code push.

328 lines (271 loc) 29.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.exists = exists; exports.rmWithRetries = rmWithRetries; exports.readDir = readDir; exports.getFileList = getFileList; exports.readAndGetFileHash = readAndGetFileHash; exports.computeHashForHashesSet = computeHashForHashesSet; exports.readAndHashFiles = readAndHashFiles; exports.readFilesAndComputeHash = readFilesAndComputeHash; exports.symlinkExists = symlinkExists; exports.default = void 0; var _path = _interopRequireDefault(require("path")); var _fs = _interopRequireDefault(require("fs")); var _crypto = _interopRequireDefault(require("crypto")); var _shelljs = _interopRequireDefault(require("shelljs")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* eslint-disable consistent-return */ /** * Exists * @param {string} pathToCheck * @returns {boolean} */ function exists(pathToCheck) { try { _fs.default.accessSync(pathToCheck); return true; } catch (e) { return false; } } /** * Simple wrapper for shelljs.rm with additional retries in case of failure. * It is useful when something is concurrently reading the dir you want to remove. */ function rmWithRetries(...args) { let retries = 0; return new Promise((resolve, reject) => { function rm(...rmArgs) { try { _shelljs.default.config.fatal = true; _shelljs.default.rm(...rmArgs); _shelljs.default.config.reset(); resolve(); } catch (e) { retries += 1; if (retries < 5) { setTimeout(() => { rm(...rmArgs); }, 100); } else { _shelljs.default.config.reset(); reject(e); } } } rm(...args); }); } function readDir(dir, callback) { if (!callback) { return new Promise((resolve, reject) => { readDir(dir, (err, data, stats) => { if (err) { reject(err); } else { resolve({ data, stats }); } }); }); } let list = []; let allStats = {}; _fs.default.readdir(dir, (err, files) => { if (err) { return callback(err); } let pending = files.length; if (!pending) { return callback(null, list, allStats); } files.forEach(file => { const filePath = _path.default.join(dir, file); _fs.default.stat(filePath, (_err, stats) => { if (_err) { return callback(_err); } if (stats.isDirectory()) { readDir(filePath, (__err, res, _allStats) => { if (__err) { return callback(__err); } list = list.concat(res); allStats = Object.assign(allStats, _allStats); pending -= 1; if (!pending) { return callback(null, list, allStats); } }); } else { list.push(filePath); allStats[filePath] = { size: stats.size, dates: [stats.birthtime.getTime(), stats.ctime.getTime(), stats.mtime.getTime()] }; pending -= 1; if (!pending) { return callback(null, list, allStats); } } }); }); }); } /** * Returns a file list from a directory. * @param {string} dir - dir path * @param {boolean} sort - whether to apply sort * @returns {Promise<Array>} */ function getFileList(dir, sort = false) { return new Promise((resolve, reject) => { readDir(dir, (error, files) => { if (error) { reject(error); return; } // eslint-disable-next-line no-param-reassign let resultantFilesList; if (sort) { const stripLength = dir.substr(0, 2) === './' ? dir.length - 1 : dir.length + 1; let pathsUnified = files.map(pth => pth.substr(stripLength).replace(/[\\/]/gm, '-')); const temporaryIndex = {}; files.forEach((file, i) => { temporaryIndex[pathsUnified[i]] = file; }); pathsUnified = pathsUnified.sort(); const filesSorted = []; pathsUnified.forEach(key => { filesSorted.push(temporaryIndex[key]); }); resultantFilesList = filesSorted; } else { resultantFilesList = files; } resolve(resultantFilesList); }); }); } /** * Returns file's hash. * @param {string} file - file path * @param {boolean} returnFileContents - include file contents in the resultant object * @returns {Promise<Object>} */ function readAndGetFileHash(file, returnFileContents = false) { return new Promise((resolve, reject) => { _fs.default.readFile(file, (err, data) => { if (err) { reject(err); return; } const hash = _crypto.default.createHash('sha1'); hash.update(data); const returnObject = { hash: hash.digest('hex') }; if (returnFileContents) { returnObject.contents = data.toString('utf8'); } resolve(returnObject); }); }); } /** * Calculates a hash from objects values in specified order. * @param {Array} orderOfKeys * @param {Object} hashSet * @param {Function} keyFilter * @returns {string} */ function computeHashForHashesSet(orderOfKeys, hashSet, keyFilter = key => key) { const hash = _crypto.default.createHash('sha1'); const hashesJoined = orderOfKeys.reduce( // eslint-disable-next-line no-param-reassign,no-return-assign (tmpHash, key) => (tmpHash += hashSet[keyFilter(key)], tmpHash), ''); hash.update(hashesJoined); return hash.digest('hex'); } /** * Reads files from disk and computes hashes for them. * @param {Array} files - array with file paths * @returns {Promise<Object>} */ function readAndHashFiles(files, fileFilter) { const fileHashes = {}; const fileContents = {}; const promises = []; function readSingleFile(file) { return new Promise((resolve, reject) => { readAndGetFileHash(file, file.endsWith('.js') && !file.endsWith('.test.js')).then(result => { let fileName = file; if (fileFilter) { fileName = fileFilter(fileName); } fileHashes[fileName] = result.hash; if (result.contents) { fileContents[fileName] = result.contents; } resolve(); }).catch(reject); }); } files.forEach(file => { promises.push(readSingleFile(file)); }); return new Promise((resolve, reject) => { Promise.all(promises).then(() => { resolve({ files, fileContents, fileHashes }); }).catch(reject); }); } /** * Reads files from .desktop and computes a version hash. * * @param {string} dir - path * @param {Function} fileFilter * @returns {Promise<Object>} */ function readFilesAndComputeHash(dir, fileFilter) { return new Promise((resolve, reject) => { getFileList(dir, true).catch(reject).then(files => readAndHashFiles(files, fileFilter)).catch(reject).then(result => { // eslint-disable-next-line no-param-reassign result.hash = computeHashForHashesSet(result.files, result.fileHashes, fileFilter); resolve(result); }); }); } /** * Symlink exists * @param {string} pathToCheck * @returns {boolean} */ function symlinkExists(pathToCheck) { try { _fs.default.readlinkSync(pathToCheck); return true; } catch (e) { return false; } } var _default = { getFileList, rmWithRetries, exists, readDir, readAndGetFileHash, computeHashForHashesSet, readAndHashFiles, readFilesAndComputeHash, symlinkExists }; exports.default = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi91dGlscy5qcyJdLCJuYW1lcyI6WyJleGlzdHMiLCJwYXRoVG9DaGVjayIsImZzIiwiYWNjZXNzU3luYyIsImUiLCJybVdpdGhSZXRyaWVzIiwiYXJncyIsInJldHJpZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsInJtIiwicm1BcmdzIiwic2hlbGwiLCJjb25maWciLCJmYXRhbCIsInJlc2V0Iiwic2V0VGltZW91dCIsInJlYWREaXIiLCJkaXIiLCJjYWxsYmFjayIsImVyciIsImRhdGEiLCJzdGF0cyIsImxpc3QiLCJhbGxTdGF0cyIsInJlYWRkaXIiLCJmaWxlcyIsInBlbmRpbmciLCJsZW5ndGgiLCJmb3JFYWNoIiwiZmlsZSIsImZpbGVQYXRoIiwicGF0aCIsImpvaW4iLCJzdGF0IiwiX2VyciIsImlzRGlyZWN0b3J5IiwiX19lcnIiLCJyZXMiLCJfYWxsU3RhdHMiLCJjb25jYXQiLCJPYmplY3QiLCJhc3NpZ24iLCJwdXNoIiwic2l6ZSIsImRhdGVzIiwiYmlydGh0aW1lIiwiZ2V0VGltZSIsImN0aW1lIiwibXRpbWUiLCJnZXRGaWxlTGlzdCIsInNvcnQiLCJlcnJvciIsInJlc3VsdGFudEZpbGVzTGlzdCIsInN0cmlwTGVuZ3RoIiwic3Vic3RyIiwicGF0aHNVbmlmaWVkIiwibWFwIiwicHRoIiwicmVwbGFjZSIsInRlbXBvcmFyeUluZGV4IiwiaSIsImZpbGVzU29ydGVkIiwia2V5IiwicmVhZEFuZEdldEZpbGVIYXNoIiwicmV0dXJuRmlsZUNvbnRlbnRzIiwicmVhZEZpbGUiLCJoYXNoIiwiY3J5cHRvIiwiY3JlYXRlSGFzaCIsInVwZGF0ZSIsInJldHVybk9iamVjdCIsImRpZ2VzdCIsImNvbnRlbnRzIiwidG9TdHJpbmciLCJjb21wdXRlSGFzaEZvckhhc2hlc1NldCIsIm9yZGVyT2ZLZXlzIiwiaGFzaFNldCIsImtleUZpbHRlciIsImhhc2hlc0pvaW5lZCIsInJlZHVjZSIsInRtcEhhc2giLCJyZWFkQW5kSGFzaEZpbGVzIiwiZmlsZUZpbHRlciIsImZpbGVIYXNoZXMiLCJmaWxlQ29udGVudHMiLCJwcm9taXNlcyIsInJlYWRTaW5nbGVGaWxlIiwiZW5kc1dpdGgiLCJ0aGVuIiwicmVzdWx0IiwiZmlsZU5hbWUiLCJjYXRjaCIsImFsbCIsInJlYWRGaWxlc0FuZENvbXB1dGVIYXNoIiwic3ltbGlua0V4aXN0cyIsInJlYWRsaW5rU3luYyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBSkE7O0FBTUE7Ozs7O0FBS08sU0FBU0EsTUFBVCxDQUFnQkMsV0FBaEIsRUFBNkI7QUFDaEMsTUFBSTtBQUNBQyxnQkFBR0MsVUFBSCxDQUFjRixXQUFkOztBQUNBLFdBQU8sSUFBUDtBQUNILEdBSEQsQ0FHRSxPQUFPRyxDQUFQLEVBQVU7QUFDUixXQUFPLEtBQVA7QUFDSDtBQUNKO0FBRUQ7Ozs7OztBQUlPLFNBQVNDLGFBQVQsQ0FBdUIsR0FBR0MsSUFBMUIsRUFBZ0M7QUFDbkMsTUFBSUMsT0FBTyxHQUFHLENBQWQ7QUFDQSxTQUFPLElBQUlDLE9BQUosQ0FBWSxDQUFDQyxPQUFELEVBQVVDLE1BQVYsS0FBcUI7QUFDcEMsYUFBU0MsRUFBVCxDQUFZLEdBQUdDLE1BQWYsRUFBdUI7QUFDbkIsVUFBSTtBQUNBQyx5QkFBTUMsTUFBTixDQUFhQyxLQUFiLEdBQXFCLElBQXJCOztBQUNBRix5QkFBTUYsRUFBTixDQUFTLEdBQUdDLE1BQVo7O0FBQ0FDLHlCQUFNQyxNQUFOLENBQWFFLEtBQWI7O0FBQ0FQLFFBQUFBLE9BQU87QUFDVixPQUxELENBS0UsT0FBT0wsQ0FBUCxFQUFVO0FBQ1JHLFFBQUFBLE9BQU8sSUFBSSxDQUFYOztBQUNBLFlBQUlBLE9BQU8sR0FBRyxDQUFkLEVBQWlCO0FBQ2JVLFVBQUFBLFVBQVUsQ0FBQyxNQUFNO0FBQ2JOLFlBQUFBLEVBQUUsQ0FBQyxHQUFHQyxNQUFKLENBQUY7QUFDSCxXQUZTLEVBRVAsR0FGTyxDQUFWO0FBR0gsU0FKRCxN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R0tTLEtBSEwsQ0FHV25GLE1BSFgsRUFJS2dGLElBSkwsQ0FJV0MsTUFBRCxJQUFZO0FBQ2Q7QUFDQUEsTUFBQUEsTUFBTSxDQUFDdkIsSUFBUCxHQUFjUSx1QkFBdUIsQ0FBQ2UsTUFBTSxDQUFDaEUsS0FBUixFQUFlZ0UsTUFBTSxDQUFDTixVQUF0QixFQUFrQ0QsVUFBbEMsQ0FBckM7QUFDQTNFLE1BQUFBLE9BQU8sQ0FBQ2tGLE1BQUQsQ0FBUDtBQUNILEtBUkw7QUFTSCxHQVZNLENBQVA7QUFXSDtBQUVEOzs7Ozs7O0FBS08sU0FBU0ssYUFBVCxDQUF1Qi9GLFdBQXZCLEVBQW9DO0FBQ3ZDLE1BQUk7QUFDQUMsZ0JBQUcrRixZQUFILENBQWdCaEcsV0FBaEI7O0FBQ0EsV0FBTyxJQUFQO0FBQ0gsR0FIRCxDQUdFLE9BQU9HLENBQVAsRUFBVTtBQUNSLFdBQU8sS0FBUDtBQUNIO0FBQ0o7O2VBR2M7QUFDWCtDLEVBQUFBLFdBRFc7QUFFWDlDLEVBQUFBLGFBRlc7QUFHWEwsRUFBQUEsTUFIVztBQUlYa0IsRUFBQUEsT0FKVztBQUtYK0MsRUFBQUEsa0JBTFc7QUFNWFcsRUFBQUEsdUJBTlc7QUFPWE8sRUFBQUEsZ0JBUFc7QUFRWFksRUFBQUEsdUJBUlc7QUFTWEMsRUFBQUE7QUFUVyxDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgY29uc2lzdGVudC1yZXR1cm4gKi9cbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCBzaGVsbCBmcm9tICdzaGVsbGpzJztcblxuLyoqXG4gKiBFeGlzdHNcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoVG9DaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleGlzdHMocGF0aFRvQ2hlY2spIHtcbiAgICB0cnkge1xuICAgICAgICBmcy5hY2Nlc3NTeW5jKHBhdGhUb0NoZWNrKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuXG4vKipcbiAqIFNpbXBsZSB3cmFwcGVyIGZvciBzaGVsbGpzLnJtIHdpdGggYWRkaXRpb25hbCByZXRyaWVzIGluIGNhc2Ugb2YgZmFpbHVyZS5cbiAqIEl0IGlzIHVzZWZ1bCB3aGVuIHNvbWV0aGluZyBpcyBjb25jdXJyZW50bHkgcmVhZGluZyB0aGUgZGlyIHlvdSB3YW50IHRvIHJlbW92ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJtV2l0aFJldHJpZXMoLi4uYXJncykge1xuICAgIGxldCByZXRyaWVzID0gMDtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBmdW5jdGlvbiBybSguLi5ybUFyZ3MpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgc2hlbGwuY29uZmlnLmZhdGFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzaGVsbC5ybSguLi5ybUFyZ3MpO1xuICAgICAgICAgICAgICAgIHNoZWxsLmNvbmZpZy5yZXNldCgpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXRyaWVzICs9IDE7XG4gICAgICAgICAgICAgICAgaWYgKHJldHJpZXMgPCA1KSB7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm0oLi4ucm1BcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgMTAwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzaGVsbC5jb25maWcucmVzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBybSguLi5hcmdzKTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWREaXIoZGlyLCBjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHJlYWREaXIoZGlyLCAoZXJyLCBkYXRhLCBzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh7IGRhdGEsIHN0YXRzIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgbGV0IGxpc3QgPSBbXTtcbiAgICBsZXQgYWxsU3RhdHMgPSB7fTtcblxuICAgIGZzLnJlYWRkaXIoZGlyLCAoZXJyLCBmaWxlcykgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcGVuZGluZyA9IGZpbGVzLmxlbmd0aDtcbiAgICAgICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgbGlzdCwgYWxsU3RhdHMpO1xuICAgICAgICB9XG4gICAgICAgIGZpbGVzLmZvckVhY2goKGZpbGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKGRpciwgZmlsZSk7XG4gICAgICAgICAgICBmcy5zdGF0KGZpbGVQYXRoLCAoX2Vyciwgc3RhdHMpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoX2Vycikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soX2Vycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzdGF0cy5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWREaXIoZmlsZVBhdGgsIChfX2VyciwgcmVzLCBfYWxsU3RhdHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfX2Vycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhfX2Vycik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0ID0gbGlzdC5jb25jYXQocmVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbFN0YXRzID0gT2JqZWN0LmFzc2lnbihhbGxTdGF0cywgX2FsbFN0YXRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmcgLT0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcGVuZGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBsaXN0LCBhbGxTdGF0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3QucHVzaChmaWxlUGF0aCk7XG4gICAgICAgICAgICAgICAgICAgIGFsbFN0YXRzW2ZpbGVQYXRoXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IHN0YXRzLnNpemUsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRzLmJpcnRodGltZS5nZXRUaW1lKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHMuY3RpbWUuZ2V0VGltZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRzLm10aW1lLmdldFRpbWUoKVxuICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nIC09IDE7XG4gICAgICAgICAgICAgICAgICAgIGlmICghcGVuZGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGxpc3QsIGFsbFN0YXRzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZmlsZSBsaXN0IGZyb20gYSBkaXJlY3RvcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGlyIC0gZGlyIHBhdGhcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gc29ydCAtIHdoZXRoZXIgdG8gYXBwbHkgc29ydFxuICogQHJldHVybnMge1Byb21pc2U8QXJyYXk+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmlsZUxpc3QoZGlyLCBzb3J0ID0gZmFsc2UpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICByZWFkRGlyKGRpciwgKGVycm9yLCBmaWxlcykgPT4ge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICAgICAgICAgIGxldCByZXN1bHRhbnRGaWxlc0xpc3Q7XG5cbiAgICAgICAgICAgIGlmIChzb3J0KSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyaXBMZW5ndGggPSAoZGlyLnN1YnN0cigwLCAyKSA9PT0gJy4vJykgPyBkaXIubGVuZ3RoIC0gMSA6IGRpci5sZW5ndGggKyAxO1xuICAgICAgICAgICAgICAgIGxldCBwYXRoc1VuaWZpZWQgPSBmaWxlcy5tYXAoKHB0aCA9PiBwdGguc3Vic3RyKHN0cmlwTGVuZ3RoKS5yZXBsYWNlKC9bXFxcXC9dL2dtLCAnLScpKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgdGVtcG9yYXJ5SW5kZXggPSB7fTtcbiAgICAgICAgICAgICAgICBmaWxlcy5mb3JFYWNoKChmaWxlLCBpKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBvcmFyeUluZGV4W3BhdGhzVW5pZmllZFtpXV0gPSBmaWxlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHBhdGhzVW5pZmllZCA9IHBhdGhzVW5pZmllZC5zb3J0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZXNTb3J0ZWQgPSBbXTtcbiAgICAgICAgICAgICAgICBwYXRoc1VuaWZpZWQuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVzU29ydGVkLnB1c2godGVtcG9yYXJ5SW5kZXhba2V5XSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0YW50RmlsZXNMaXN0ID0gZmlsZXNTb3J0ZWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdGFudEZpbGVzTGlzdCA9IGZpbGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHRhbnRGaWxlc0xpc3QpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGZpbGUncyBoYXNoLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGUgLSBmaWxlIHBhdGhcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gcmV0dXJuRmlsZUNvbnRlbnRzIC0gaW5jbHVkZSBmaWxlIGNvbnRlbnRzIGluIHRoZSByZXN1bHRhbnQgb2JqZWN0XG4gKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZEFuZEdldEZpbGVIYXNoKGZpbGUsIHJldHVybkZpbGVDb250ZW50cyA9IGZhbHNlKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZnMucmVhZEZpbGUoZmlsZSwgKGVyciwgZGF0YSkgPT4ge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGhhc2ggPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMScpO1xuICAgICAgICAgICAgaGFzaC51cGRhdGUoZGF0YSk7XG4gICAgICAgICAgICBjb25zdCByZXR1cm5PYmplY3QgPSB7IGhhc2g6IGhhc2guZGlnZXN0KCdoZXgnKSB9O1xuICAgICAgICAgICAgaWYgKHJldHVybkZpbGVDb250ZW50cykge1xuICAgICAgICAgICAgICAgIHJldHVybk9iamVjdC5jb250ZW50cyA9IGRhdGEudG9TdHJpbmcoJ3V0ZjgnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc29sdmUocmV0dXJuT2JqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlcyBhIGhhc2ggZnJvbSBvYmplY3RzIHZhbHVlcyBpbiBzcGVjaWZpZWQgb3JkZXIuXG4gKiBAcGFyYW0ge0FycmF5fSBvcmRlck9mS2V5c1xuICogQHBhcmFtIHtPYmplY3R9IGhhc2hTZXRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGtleUZpbHRlclxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVIYXNoRm9ySGFzaGVzU2V0KG9yZGVyT2ZLZXlzLCBoYXNoU2V0LCBrZXlGaWx0ZXIgPSBrZXkgPT4ga2V5KSB7XG4gICAgY29uc3QgaGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGExJyk7XG4gICAgY29uc3QgaGFzaGVzSm9pbmVkID0gb3JkZXJPZktleXMucmVkdWNlKFxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ24sbm8tcmV0dXJuLWFzc2lnblxuICAgICAgICAodG1wSGFzaCwga2V5KSA9PiAodG1wSGFzaCArPSBoYXNoU2V0W2tleUZpbHRlcihrZXkpXSwgdG1wSGFzaCksICcnXG4gICAgKTtcbiAgICBoYXNoLnVwZGF0ZShoYXNoZXNKb2luZWQpO1xuICAgIHJldHVybiBoYXNoLmRpZ2VzdCgnaGV4Jyk7XG59XG5cblxuLyoqXG4gKiBSZWFkcyBmaWxlcyBmcm9tIGRpc2sgYW5kIGNvbXB1dGVzIGhhc2hlcyBmb3IgdGhlbS5cbiAqIEBwYXJhbSB7QXJyYXl9IGZpbGVzIC0gYXJyYXkgd2l0aCBmaWxlIHBhdGhzXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZEFuZEhhc2hGaWxlcyhmaWxlcywgZmlsZUZpbHRlcikge1xuICAgIGNvbnN0IGZpbGVIYXNoZXMgPSB7fTtcbiAgICBjb25zdCBmaWxlQ29udGVudHMgPSB7fTtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gcmVhZFNpbmdsZUZpbGUoZmlsZSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcmVhZEFuZEdldEZpbGVIYXNoKGZpbGUsIGZpbGUuZW5kc1dpdGgoJy5qcycpICYmICFmaWxlLmVuZHNXaXRoKCcudGVzdC5qcycpKVxuICAgICAgICAgICAgICAgIC50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZpbGVOYW1lID0gZmlsZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGVGaWx0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVOYW1lID0gZmlsZUZpbHRlcihmaWxlTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZmlsZUhhc2hlc1tmaWxlTmFtZV0gPSByZXN1bHQuaGFzaDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5jb250ZW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlsZUNvbnRlbnRzW2ZpbGVOYW1lXSA9IHJlc3VsdC5jb250ZW50cztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gocmVqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZmlsZXMuZm9yRWFjaCgoZmlsZSkgPT4ge1xuICAgICAgICBwcm9taXNlcy5wdXNoKHJlYWRTaW5nbGVGaWxlKGZpbGUpKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoeyBmaWxlcywgZmlsZUNvbnRlbnRzLCBmaWxlSGFzaGVzIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChyZWplY3QpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlYWRzIGZpbGVzIGZyb20gLmRlc2t0b3AgYW5kIGNvbXB1dGVzIGEgdmVyc2lvbiBoYXNoLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBkaXIgLSBwYXRoXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmaWxlRmlsdGVyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZEZpbGVzQW5kQ29tcHV0ZUhhc2goZGlyLCBmaWxlRmlsdGVyKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZ2V0RmlsZUxpc3QoZGlyLCB0cnVlKVxuICAgICAgICAgICAgLmNhdGNoKHJlamVjdClcbiAgICAgICAgICAgIC50aGVuKGZpbGVzID0+IHJlYWRBbmRIYXNoRmlsZXMoZmlsZXMsIGZpbGVGaWx0ZXIpKVxuICAgICAgICAgICAgLmNhdGNoKHJlamVjdClcbiAgICAgICAgICAgIC50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICAgICAgICAgICAgICByZXN1bHQuaGFzaCA9IGNvbXB1dGVIYXNoRm9ySGFzaGVzU2V0KHJlc3VsdC5maWxlcywgcmVzdWx0LmZpbGVIYXNoZXMsIGZpbGVGaWx0ZXIpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUocmVzdWx0KTtcbiAgICAgICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFN5bWxpbmsgZXhpc3RzXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aFRvQ2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3ltbGlua0V4aXN0cyhwYXRoVG9DaGVjaykge1xuICAgIHRyeSB7XG4gICAgICAgIGZzLnJlYWRsaW5rU3luYyhwYXRoVG9DaGVjayk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuXG5leHBvcnQgZGVmYXVsdCB7XG4gICAgZ2V0RmlsZUxpc3QsXG4gICAgcm1XaXRoUmV0cmllcyxcbiAgICBleGlzdHMsXG4gICAgcmVhZERpcixcbiAgICByZWFkQW5kR2V0RmlsZUhhc2gsXG4gICAgY29tcHV0ZUhhc2hGb3JIYXNoZXNTZXQsXG4gICAgcmVhZEFuZEhhc2hGaWxlcyxcbiAgICByZWFkRmlsZXNBbmRDb21wdXRlSGFzaCxcbiAgICBzeW1saW5rRXhpc3RzXG59O1xuIl19