@mjcctech/meteor-desktop
Version:
Build a Meteor's desktop client with hot code push.
384 lines (311 loc) • 49.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _runtime = _interopRequireDefault(require("regenerator-runtime/runtime"));
var _shelljs = _interopRequireDefault(require("shelljs"));
var _path = _interopRequireDefault(require("path"));
var _fs = _interopRequireDefault(require("fs"));
var _rimraf = _interopRequireDefault(require("rimraf"));
var _crossSpawn = _interopRequireDefault(require("cross-spawn"));
var _log = _interopRequireDefault(require("./log"));
var _defaultDependencies = _interopRequireDefault(require("./defaultDependencies"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// eslint-disable-next-line no-unused-vars
/**
* Promisfied rimraf.
*
* @param {string} dirPath - path to the dir to be deleted
* @param {number} delay - delay the task by ms
* @returns {Promise<any>}
*/
function removeDir(dirPath, delay = 0) {
return new Promise((resolve, reject) => {
setTimeout(() => {
(0, _rimraf.default)(dirPath, {
maxBusyTries: 100
}, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
}, delay);
});
}
/**
* Wrapper for electron-builder.
*/
class InstallerBuilder {
/**
* @param {MeteorDesktop} $ - context
*
* @constructor
*/
constructor($) {
this.log = new _log.default('electronBuilder');
this.$ = $;
this.firstPass = true;
this.lastRebuild = {};
this.currentContext = null;
this.installerDir = _path.default.join(this.$.env.options.output, this.$.env.paths.installerDir);
this.platforms = [];
}
async init() {
this.builder = await this.$.getDependency('electron-builder', _defaultDependencies.default['electron-builder']);
const appBuilder = await this.$.getDependency('app-builder-lib', _defaultDependencies.default['electron-builder'], false);
this.yarn = require(_path.default.join(appBuilder.path, 'out', 'util', 'yarn'));
this.getGypEnv = this.yarn.getGypEnv;
this.packageDependencies = require(_path.default.join(appBuilder.path, 'out', 'util', 'packageDependencies'));
}
/**
* Prepares the last rebuild object for electron-builder.
*
* @param {string} arch
* @param {string} platform
* @returns {Object}
*/
prepareLastRebuildObject(arch, platform = process.platform) {
const productionDeps = this.packageDependencies.createLazyProductionDeps(this.$.env.paths.electronApp.root);
this.lastRebuild = {
frameworkInfo: {
version: this.$.getElectronVersion(),
useCustomDist: true
},
platform,
arch,
productionDeps
};
return this.lastRebuild;
}
/**
* Calls npm rebuild from electron-builder.
* @param {string} arch
* @param {string} platform
* @param {boolean} install
* @returns {Promise}
*/
async installOrRebuild(arch, platform = process.platform, install = false) {
this.log.debug(`calling installOrRebuild from electron-builder for arch ${arch}`);
this.prepareLastRebuildObject(arch, platform);
await this.yarn.installOrRebuild(this.$.desktop.getSettings().builderOptions || {}, this.$.env.paths.electronApp.root, this.lastRebuild, install);
}
/**
* Callback invoked before build is made. Ensures that app.asar have the right rebuilt
* node_modules.
*
* @param {Object} context
* @returns {Promise}
*/
beforeBuild(context) {
this.currentContext = Object.assign({}, context);
return new Promise((resolve, reject) => {
const platformMatches = process.platform === context.platform.nodeName;
const rebuild = platformMatches && context.arch !== this.lastRebuild.arch;
if (!platformMatches) {
this.log.warn('skipping dependencies rebuild because platform is different, if you have native ' + 'node modules as your app dependencies you should od the build on the target platform only');
}
if (!rebuild) {
this.moveNodeModulesOut().catch(e => reject(e)).then(() => setTimeout(() => resolve(false), 2000)); // Timeout helps on Windows to clear the file locks.
} else {
// Lets rebuild the node_modules for different arch.
this.installOrRebuild(context.arch, context.platform.nodeName).catch(e => reject(e)).then(() => this.$.electronApp.installLocalNodeModules(context.arch)).catch(e => reject(e)).then(() => {
this.$.electronApp.scaffold.createAppRoot();
this.$.electronApp.scaffold.copySkeletonApp();
return this.$.electronApp.packSkeletonToAsar([this.$.env.paths.electronApp.meteorAsar, this.$.env.paths.electronApp.desktopAsar, this.$.env.paths.electronApp.extracted]);
}).catch(e => reject(e)).then(() => this.moveNodeModulesOut()).catch(e => reject(e)).then(() => resolve(false));
}
});
}
/**
* Callback to be invoked after packing. Restores node_modules to the .desktop-build.
* @returns {Promise}
*/
afterPack(context) {
this.platforms = this.platforms.filter(platform => platform !== context.electronPlatformName);
if (this.platforms.length !== 0) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
_shelljs.default.config.fatal = true;
if (this.$.utils.exists(this.$.env.paths.electronApp.extractedNodeModules)) {
this.log.debug('injecting extracted modules');
_shelljs.default.cp('-Rf', this.$.env.paths.electronApp.extractedNodeModules, _path.default.join(this.getPackagedAppPath(context), 'node_modules'));
}
this.log.debug('moving node_modules back'); // Move node_modules back.
try {
_shelljs.default.mv(this.$.env.paths.electronApp.tmpNodeModules, this.$.env.paths.electronApp.nodeModules);
} catch (e) {
reject(e);
return;
} finally {
_shelljs.default.config.reset();
}
if (this.firstPass) {
this.firstPass = false;
}
this.log.debug('node_modules moved back');
this.wait().catch(e => reject(e)).then(() => resolve());
});
}
/**
* This command kills orphaned MSBuild.exe processes.
* Sometime after native node_modules compilation they are still writing some logs,
* prevent node_modules from being deleted.
*/
killMSBuild() {
if (this.currentContext.platform.nodeName !== 'win32') {
return;
}
try {
const out = _crossSpawn.default.sync('wmic', ['process', 'where', 'caption="MSBuild.exe"', 'get', 'processid']).stdout.toString('utf-8').split('\n');
const regex = new RegExp(/(\d+)/, 'gm'); // No we will check for those with the matching params.
out.forEach(line => {
const match = regex.exec(line) || false;
if (match) {
this.log.debug(`killing MSBuild.exe at pid: ${match[1]}`);
_crossSpawn.default.sync('taskkill', ['/pid', match[1], '/f', '/t']);
}
regex.lastIndex = 0;
});
} catch (e) {
this.log.debug('kill MSBuild failed');
}
}
/**
* Returns the path to packaged app.
* @returns {string}
*/
getPackagedAppPath(context = {}) {
if (this.currentContext.platform.nodeName === 'darwin') {
return _path.default.join(this.installerDir, 'mac', `${context.packager.appInfo.productFilename}.app`, 'Contents', 'Resources', 'app');
}
const platformDir = `${this.currentContext.platform.nodeName === 'win32' ? 'win' : 'linux'}-${this.currentContext.arch === 'ia32' ? 'ia32-' : ''}unpacked`;
return _path.default.join(this.installerDir, platformDir, 'resources', 'app');
}
/**
* On Windows it waits for the app.asar in the packed app to be free (no file locks).
* @returns {*}
*/
wait() {
if (this.currentContext.platform.nodeName !== 'win32') {
return Promise.resolve();
}
const appAsarPath = _path.default.join(this.getPackagedAppPath(), 'app.asar');
let retries = 0;
const self = this;
return new Promise((resolve, reject) => {
function check() {
_fs.default.open(appAsarPath, 'r+', (err, fd) => {
retries += 1;
if (err) {
if (err.code !== 'ENOENT') {
self.log.debug(`waiting for app.asar to be readable, ${'code' in err ? `currently reading it returns ${err.code}` : ''}`);
if (retries < 6) {
setTimeout(() => check(), 4000);
} else {
reject(`file is locked: ${appAsarPath}`);
}
} else {
resolve();
}
} else {
_fs.default.closeSync(fd);
resolve();
}
});
}
check();
});
}
/**
* Prepares the target object passed to the electron-builder.
*
* @returns {Map<Platform, Map<Arch, Array<string>>>}
*/
prepareTargets() {
let arch = this.$.env.options.ia32 ? 'ia32' : 'x64';
arch = this.$.env.options.allArchs ? 'all' : arch;
const targets = [];
if (this.$.env.options.win) {
targets.push(this.builder.dependency.Platform.WINDOWS);
}
if (this.$.env.options.linux) {
targets.push(this.builder.dependency.Platform.LINUX);
}
if (this.$.env.options.mac) {
targets.push(this.builder.dependency.Platform.MAC);
}
if (targets.length === 0) {
if (this.$.env.os.isWindows) {
targets.push(this.builder.dependency.Platform.WINDOWS);
} else if (this.$.env.os.isLinux) {
targets.push(this.builder.dependency.Platform.LINUX);
} else {
targets.push(this.builder.dependency.Platform.MAC);
}
}
return this.builder.dependency.createTargets(targets, null, arch);
}
async build() {
const settings = this.$.desktop.getSettings();
if (!('builderOptions' in settings)) {
this.log.error('no builderOptions in settings.json, aborting');
process.exit(1);
}
const builderOptions = Object.assign({}, settings.builderOptions);
builderOptions.asar = false;
builderOptions.npmRebuild = true;
builderOptions.beforeBuild = this.beforeBuild.bind(this);
builderOptions.afterPack = this.afterPack.bind(this);
builderOptions.electronVersion = this.$.getElectronVersion();
builderOptions.directories = {
app: this.$.env.paths.electronApp.root,
output: _path.default.join(this.$.env.options.output, this.$.env.paths.installerDir)
};
if ('mac' in builderOptions && 'target' in builderOptions.mac) {
if (builderOptions.mac.target.includes('mas')) {
this.platforms = ['darwin', 'mas'];
}
}
try {
this.log.debug('calling build from electron-builder');
await this.builder.dependency.build(Object.assign({
targets: this.prepareTargets(),
config: builderOptions
}, settings.builderCliOptions));
if (this.$.utils.exists(this.$.env.paths.electronApp.extractedNodeModules)) {
_shelljs.default.rm('-rf', this.$.env.paths.electronApp.extractedNodeModules);
}
} catch (e) {
this.log.error('error while building installer: ', e);
}
}
/**
* Moves node_modules out of the app because while the app will be packaged
* we do not want it to be there.
* @returns {Promise<any>}
*/
moveNodeModulesOut() {
return new Promise((resolve, reject) => {
this.log.debug('moving node_modules out, because we have them already in' + ' app.asar');
this.killMSBuild();
removeDir(this.$.env.paths.electronApp.tmpNodeModules).catch(e => reject(e)).then(() => {
_shelljs.default.config.fatal = true;
_shelljs.default.config.verbose = true;
try {
_shelljs.default.mv(this.$.env.paths.electronApp.nodeModules, this.$.env.paths.electronApp.tmpNodeModules);
_shelljs.default.config.reset();
return this.wait();
} catch (e) {
_shelljs.default.config.reset();
return Promise.reject(e);
}
}).catch(e => reject(e)).then(() => removeDir(this.$.env.paths.electronApp.nodeModules, 1000)).catch(e => reject(e)).then(() => this.wait()).catch(reject).then(resolve);
});
}
}
exports.default = InstallerBuilder;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9lbGVjdHJvbkJ1aWxkZXIuanMiXSwibmFtZXMiOlsicmVtb3ZlRGlyIiwiZGlyUGF0aCIsImRlbGF5IiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJzZXRUaW1lb3V0IiwibWF4QnVzeVRyaWVzIiwiZXJyIiwiSW5zdGFsbGVyQnVpbGRlciIsImNvbnN0cnVjdG9yIiwiJCIsImxvZyIsIkxvZyIsImZpcnN0UGFzcyIsImxhc3RSZWJ1aWxkIiwiY3VycmVudENvbnRleHQiLCJpbnN0YWxsZXJEaXIiLCJwYXRoIiwiam9pbiIsImVudiIsIm9wdGlvbnMiLCJvdXRwdXQiLCJwYXRocyIsInBsYXRmb3JtcyIsImluaXQiLCJidWlsZGVyIiwiZ2V0RGVwZW5kZW5jeSIsImRlZmF1bHREZXBlbmRlbmNpZXMiLCJhcHBCdWlsZGVyIiwieWFybiIsInJlcXVpcmUiLCJnZXRHeXBFbnYiLCJwYWNrYWdlRGVwZW5kZW5jaWVzIiwicHJlcGFyZUxhc3RSZWJ1aWxkT2JqZWN0IiwiYXJjaCIsInBsYXRmb3JtIiwicHJvY2VzcyIsInByb2R1Y3Rpb25EZXBzIiwiY3JlYXRlTGF6eVByb2R1Y3Rpb25EZXBzIiwiZWxlY3Ryb25BcHAiLCJyb290IiwiZnJhbWV3b3JrSW5mbyIsInZlcnNpb24iLCJnZXRFbGVjdHJvblZlcnNpb24iLCJ1c2VDdXN0b21EaXN0IiwiaW5zdGFsbE9yUmVidWlsZCIsImluc3RhbGwiLCJkZWJ1ZyIsImRlc2t0b3AiLCJnZXRTZXR0aW5ncyIsImJ1aWxkZXJPcHRpb25zIiwiYmVmb3JlQnVpbGQiLCJjb250ZXh0IiwiT2JqZWN0IiwiYXNzaWduIiwicGxhdGZvcm1NYXRjaGVzIiwibm9kZU5hbWUiLCJyZWJ1aWxkIiwid2FybiIsIm1vdmVOb2RlTW9kdWxlc091dCIsImNhdGNoIiwiZSIsInRoZW4iLCJpbnN0YWxsTG9jYWxOb2RlTW9kdWxlcyIsInNjYWZmb2xkIiwiY3JlYXRlQXBwUm9vdCIsImNvcHlTa2VsZXRvbkFwcCIsInBhY2tTa2VsZXRvblRvQXNhciIsIm1ldGVvckFzYXIiLCJkZXNrdG9wQXNhciIsImV4dHJhY3RlZCIsImFmdGVyUGFjayIsImZpbHRlciIsImVsZWN0cm9uUGxhdGZvcm1OYW1lIiwibGVuZ3RoIiwic2hlbGwiLCJjb25maWciLCJmYXRhbCIsInV0aWxzIiwiZXhpc3RzIiwiZXh0cmFjdGVkTm9kZU1vZHVsZXMiLCJjcCIsImdldFBhY2thZ2VkQXBwUGF0aCIsIm12IiwidG1wTm9kZU1vZHVsZXMiLCJub2RlTW9kdWxlcyIsInJlc2V0Iiwid2FpdCIsImtpbGxNU0J1aWxkIiwib3V0Iiwic3Bhd24iLCJzeW5jIiwic3Rkb3V0IiwidG9TdHJpbmciLCJzcGxpdCIsInJlZ2V4IiwiUmVnRXhwIiwiZm9yRWFjaCIsImxpbmUiLCJtYXRjaCIsImV4ZWMiLCJsYXN0SW5kZXgiLCJwYWNrYWdlciIsImFwcEluZm8iLCJwcm9kdWN0RmlsZW5hbWUiLCJwbGF0Zm9ybURpciIsImFwcEFzYXJQYXRoIiwicmV0cmllcyIsInNlbGYiLCJjaGVjayIsImZzIiwib3BlbiIsImZkIiwiY29kZSIsImNsb3NlU3luYyIsInByZXBhcmVUYXJnZXRzIiwiaWEzMiIsImFsbEFyY2hzIiwidGFyZ2V0cyIsIndpbiIsInB1c2giLCJkZXBlbmRlbmN5IiwiUGxhdGZvcm0iLCJXSU5ET1dTIiwibGludXgiLCJMSU5VWCIsIm1hYyIsIk1BQyIsIm9zIiwiaXNXaW5kb3dzIiwiaXNMaW51eCIsImNyZWF0ZVRhcmdldHMiLCJidWlsZCIsInNldHRpbmdzIiwiZXJyb3IiLCJleGl0IiwiYXNhciIsIm5wbVJlYnVpbGQiLCJiaW5kIiwiZWxlY3Ryb25WZXJzaW9uIiwiZGlyZWN0b3JpZXMiLCJhcHAiLCJ0YXJnZXQiLCJpbmNsdWRlcyIsImJ1aWxkZXJDbGlPcHRpb25zIiwicm0iLCJ2ZXJib3NlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFSQTs7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Q0EsaUJBQU9wRixPQUFPLENBQUNFLE1BQVIsQ0FBZXlELENBQWYsQ0FBUDtBQUNIO0FBQ0osT0FoQkwsRUFpQktELEtBakJMLENBaUJXQyxDQUFDLElBQUl6RCxNQUFNLENBQUN5RCxDQUFELENBakJ0QixFQWtCS0MsSUFsQkwsQ0FrQlUsTUFBTS9ELFNBQVMsQ0FBQyxLQUFLVyxDQUFMLENBQU9TLEdBQVAsQ0FBV0csS0FBWCxDQUFpQmlCLFdBQWpCLENBQTZCOEMsV0FBOUIsRUFBMkMsSUFBM0MsQ0FsQnpCLEVBbUJLekIsS0FuQkwsQ0FtQldDLENBQUMsSUFBSXpELE1BQU0sQ0FBQ3lELENBQUQsQ0FuQnRCLEVBb0JLQyxJQXBCTCxDQW9CVSxNQUFNLEtBQUt5QixJQUFMLEVBcEJoQixFQXFCSzNCLEtBckJMLENBcUJXeEQsTUFyQlgsRUFzQkswRCxJQXRCTCxDQXNCVTNELE9BdEJWO0FBdUJILEtBM0JNLENBQVA7QUE0Qkg7O0FBdFdpQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuaW1wb3J0IHJlZ2VuZXJhdG9yUnVudGltZSBmcm9tICdyZWdlbmVyYXRvci1ydW50aW1lL3J1bnRpbWUnO1xuaW1wb3J0IHNoZWxsIGZyb20gJ3NoZWxsanMnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHJpbXJhZiBmcm9tICdyaW1yYWYnO1xuaW1wb3J0IHNwYXduIGZyb20gJ2Nyb3NzLXNwYXduJztcbmltcG9ydCBMb2cgZnJvbSAnLi9sb2cnO1xuaW1wb3J0IGRlZmF1bHREZXBlbmRlbmNpZXMgZnJvbSAnLi9kZWZhdWx0RGVwZW5kZW5jaWVzJztcblxuLyoqXG4gKiBQcm9taXNmaWVkIHJpbXJhZi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZGlyUGF0aCAtIHBhdGggdG8gdGhlIGRpciB0byBiZSBkZWxldGVkXG4gKiBAcGFyYW0ge251bWJlcn0gZGVsYXkgLSBkZWxheSB0aGUgdGFzayBieSBtc1xuICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAqL1xuZnVuY3Rpb24gcmVtb3ZlRGlyKGRpclBhdGgsIGRlbGF5ID0gMCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgcmltcmFmKGRpclBhdGgsIHtcbiAgICAgICAgICAgICAgICBtYXhCdXN5VHJpZXM6IDEwMFxuICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBkZWxheSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogV3JhcHBlciBmb3IgZWxlY3Ryb24tYnVpbGRlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSW5zdGFsbGVyQnVpbGRlciB7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtNZXRlb3JEZXNrdG9wfSAkIC0gY29udGV4dFxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoJCkge1xuICAgICAgICB0aGlzLmxvZyA9IG5ldyBMb2coJ2VsZWN0cm9uQnVpbGRlcicpO1xuICAgICAgICB0aGlzLiQgPSAkO1xuICAgICAgICB0aGlzLmZpcnN0UGFzcyA9IHRydWU7XG4gICAgICAgIHRoaXMubGFzdFJlYnVpbGQgPSB7fTtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29udGV4dCA9IG51bGw7XG4gICAgICAgIHRoaXMuaW5zdGFsbGVyRGlyID0gcGF0aC5qb2luKHRoaXMuJC5lbnYub3B0aW9ucy5vdXRwdXQsIHRoaXMuJC5lbnYucGF0aHMuaW5zdGFsbGVyRGlyKTtcbiAgICAgICAgdGhpcy5wbGF0Zm9ybXMgPSBbXTtcbiAgICB9XG5cbiAgICBhc3luYyBpbml0KCkge1xuICAgICAgICB0aGlzLmJ1aWxkZXIgPSBhd2FpdCB0aGlzLiQuZ2V0RGVwZW5kZW5jeSgnZWxlY3Ryb24tYnVpbGRlcicsIGRlZmF1bHREZXBlbmRlbmNpZXNbJ2VsZWN0cm9uLWJ1aWxkZXInXSk7XG4gICAgICAgIGNvbnN0IGFwcEJ1aWxkZXIgPSBhd2FpdCB0aGlzLiQuZ2V0RGVwZW5kZW5jeSgnYXBwLWJ1aWxkZXItbGliJywgZGVmYXVsdERlcGVuZGVuY2llc1snZWxlY3Ryb24tYnVpbGRlciddLCBmYWxzZSk7XG5cbiAgICAgICAgdGhpcy55YXJuID0gcmVxdWlyZShwYXRoLmpvaW4oYXBwQnVpbGRlci5wYXRoLCAnb3V0JywgJ3V0aWwnLCAneWFybicpKTtcbiAgICAgICAgdGhpcy5nZXRHeXBFbnYgPSB0aGlzLnlhcm4uZ2V0R3lwRW52O1xuICAgICAgICB0aGlzLnBhY2thZ2VEZXBlbmRlbmNpZXMgPSByZXF1aXJlKHBhdGguam9pbihhcHBCdWlsZGVyLnBhdGgsICdvdXQnLCAndXRpbCcsICdwYWNrYWdlRGVwZW5kZW5jaWVzJykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXBhcmVzIHRoZSBsYXN0IHJlYnVpbGQgb2JqZWN0IGZvciBlbGVjdHJvbi1idWlsZGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGFyY2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fVxuICAgICAqL1xuICAgIHByZXBhcmVMYXN0UmVidWlsZE9iamVjdChhcmNoLCBwbGF0Zm9ybSA9IHByb2Nlc3MucGxhdGZvcm0pIHtcbiAgICAgICAgY29uc3QgcHJvZHVjdGlvbkRlcHMgPSB0aGlzLnBhY2thZ2VEZXBlbmRlbmNpZXNcbiAgICAgICAgICAgIC5jcmVhdGVMYXp5UHJvZHVjdGlvbkRlcHModGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5yb290KTtcbiAgICAgICAgdGhpcy5sYXN0UmVidWlsZCA9IHtcbiAgICAgICAgICAgIGZyYW1ld29ya0luZm86IHsgdmVyc2lvbjogdGhpcy4kLmdldEVsZWN0cm9uVmVyc2lvbigpLCB1c2VDdXN0b21EaXN0OiB0cnVlIH0sXG4gICAgICAgICAgICBwbGF0Zm9ybSxcbiAgICAgICAgICAgIGFyY2gsXG4gICAgICAgICAgICBwcm9kdWN0aW9uRGVwc1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdGhpcy5sYXN0UmVidWlsZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxscyBucG0gcmVidWlsZCBmcm9tIGVsZWN0cm9uLWJ1aWxkZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGFyY2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGxhdGZvcm1cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGluc3RhbGxcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICBhc3luYyBpbnN0YWxsT3JSZWJ1aWxkKGFyY2gsIHBsYXRmb3JtID0gcHJvY2Vzcy5wbGF0Zm9ybSwgaW5zdGFsbCA9IGZhbHNlKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKGBjYWxsaW5nIGluc3RhbGxPclJlYnVpbGQgZnJvbSBlbGVjdHJvbi1idWlsZGVyIGZvciBhcmNoICR7YXJjaH1gKTtcbiAgICAgICAgdGhpcy5wcmVwYXJlTGFzdFJlYnVpbGRPYmplY3QoYXJjaCwgcGxhdGZvcm0pO1xuICAgICAgICBhd2FpdCB0aGlzLnlhcm4uaW5zdGFsbE9yUmVidWlsZCh0aGlzLiQuZGVza3RvcC5nZXRTZXR0aW5ncygpLmJ1aWxkZXJPcHRpb25zIHx8IHt9LFxuICAgICAgICAgICAgdGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5yb290LCB0aGlzLmxhc3RSZWJ1aWxkLCBpbnN0YWxsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxsYmFjayBpbnZva2VkIGJlZm9yZSBidWlsZCBpcyBtYWRlLiBFbnN1cmVzIHRoYXQgYXBwLmFzYXIgaGF2ZSB0aGUgcmlnaHQgcmVidWlsdFxuICAgICAqIG5vZGVfbW9kdWxlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0XG4gICAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAgICovXG4gICAgYmVmb3JlQnVpbGQoY29udGV4dCkge1xuICAgICAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gT2JqZWN0LmFzc2lnbih7fSwgY29udGV4dCk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwbGF0Zm9ybU1hdGNoZXMgPSBwcm9jZXNzLnBsYXRmb3JtID09PSBjb250ZXh0LnBsYXRmb3JtLm5vZGVOYW1lO1xuICAgICAgICAgICAgY29uc3QgcmVidWlsZCA9IHBsYXRmb3JtTWF0Y2hlcyAmJiBjb250ZXh0LmFyY2ggIT09IHRoaXMubGFzdFJlYnVpbGQuYXJjaDtcbiAgICAgICAgICAgIGlmICghcGxhdGZvcm1NYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2cud2Fybignc2tpcHBpbmcgZGVwZW5kZW5jaWVzIHJlYnVpbGQgYmVjYXVzZSBwbGF0Zm9ybSBpcyBkaWZmZXJlbnQsIGlmIHlvdSBoYXZlIG5hdGl2ZSAnICtcbiAgICAgICAgICAgICAgICAgICAgJ25vZGUgbW9kdWxlcyBhcyB5b3VyIGFwcCBkZXBlbmRlbmNpZXMgeW91IHNob3VsZCBvZCB0aGUgYnVpbGQgb24gdGhlIHRhcmdldCBwbGF0Zm9ybSBvbmx5Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghcmVidWlsZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubW92ZU5vZGVNb2R1bGVzT3V0KClcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUoZmFsc2UpLCAyMDAwKSk7XG4gICAgICAgICAgICAgICAgLy8gVGltZW91dCBoZWxwcyBvbiBXaW5kb3dzIHRvIGNsZWFyIHRoZSBmaWxlIGxvY2tzLlxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBMZXRzIHJlYnVpbGQgdGhlIG5vZGVfbW9kdWxlcyBmb3IgZGlmZmVyZW50IGFyY2guXG4gICAgICAgICAgICAgICAgdGhpcy5pbnN0YWxsT3JSZWJ1aWxkKGNvbnRleHQuYXJjaCwgY29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLiQuZWxlY3Ryb25BcHAuaW5zdGFsbExvY2FsTm9kZU1vZHVsZXMoY29udGV4dC5hcmNoKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZWxlY3Ryb25BcHAuc2NhZmZvbGQuY3JlYXRlQXBwUm9vdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4kLmVsZWN0cm9uQXBwLnNjYWZmb2xkLmNvcHlTa2VsZXRvbkFwcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuJC5lbGVjdHJvbkFwcC5wYWNrU2tlbGV0b25Ub0FzYXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLm1ldGVvckFzYXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZGVza3RvcEFzYXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLm1vdmVOb2RlTW9kdWxlc091dCgpKVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZSA9PiByZWplY3QoZSkpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoZmFsc2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgdG8gYmUgaW52b2tlZCBhZnRlciBwYWNraW5nLiBSZXN0b3JlcyBub2RlX21vZHVsZXMgdG8gdGhlIC5kZXNrdG9wLWJ1aWxkLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfVxuICAgICAqL1xuICAgIGFmdGVyUGFjayhjb250ZXh0KSB7XG4gICAgICAgIHRoaXMucGxhdGZvcm1zID0gdGhpcy5wbGF0Zm9ybXNcbiAgICAgICAgICAgIC5maWx0ZXIocGxhdGZvcm0gPT4gcGxhdGZvcm0gIT09IGNvbnRleHQuZWxlY3Ryb25QbGF0Zm9ybU5hbWUpO1xuICAgICAgICBpZiAodGhpcy5wbGF0Zm9ybXMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHNoZWxsLmNvbmZpZy5mYXRhbCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLiQudXRpbHMuZXhpc3RzKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkTm9kZU1vZHVsZXMpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoJ2luamVjdGluZyBleHRyYWN0ZWQgbW9kdWxlcycpO1xuICAgICAgICAgICAgICAgIHNoZWxsLmNwKFxuICAgICAgICAgICAgICAgICAgICAnLVJmJyxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5leHRyYWN0ZWROb2RlTW9kdWxlcyxcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5qb2luKHRoaXMuZ2V0UGFja2FnZWRBcHBQYXRoKGNvbnRleHQpLCAnbm9kZV9tb2R1bGVzJylcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmxvZy5kZWJ1ZygnbW92aW5nIG5vZGVfbW9kdWxlcyBiYWNrJyk7XG4gICAgICAgICAgICAvLyBNb3ZlIG5vZGVfbW9kdWxlcyBiYWNrLlxuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHNoZWxsLm12KFxuICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLnRtcE5vZGVNb2R1bGVzLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLm5vZGVNb2R1bGVzXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICBzaGVsbC5jb25maWcucmVzZXQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuZmlyc3RQYXNzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdFBhc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubG9nLmRlYnVnKCdub2RlX21vZHVsZXMgbW92ZWQgYmFjaycpO1xuXG4gICAgICAgICAgICB0aGlzLndhaXQoKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlID0+IHJlamVjdChlKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGNvbW1hbmQga2lsbHMgb3JwaGFuZWQgTVNCdWlsZC5leGUgcHJvY2Vzc2VzLlxuICAgICAqIFNvbWV0aW1lIGFmdGVyIG5hdGl2ZSBub2RlX21vZHVsZXMgY29tcGlsYXRpb24gdGhleSBhcmUgc3RpbGwgd3JpdGluZyBzb21lIGxvZ3MsXG4gICAgICogcHJldmVudCBub2RlX21vZHVsZXMgZnJvbSBiZWluZyBkZWxldGVkLlxuICAgICAqL1xuICAgIGtpbGxNU0J1aWxkKCkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50Q29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSAhPT0gJ3dpbjMyJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBvdXQgPSBzcGF3blxuICAgICAgICAgICAgICAgIC5zeW5jKFxuICAgICAgICAgICAgICAgICAgICAnd21pYycsXG4gICAgICAgICAgICAgICAgICAgIFsncHJvY2VzcycsICd3aGVyZScsICdjYXB0aW9uPVwiTVNCdWlsZC5leGVcIicsICdnZXQnLCAncHJvY2Vzc2lkJ11cbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLnN0ZG91dC50b1N0cmluZygndXRmLTgnKVxuICAgICAgICAgICAgICAgIC5zcGxpdCgnXFxuJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cCgvKFxcZCspLywgJ2dtJyk7XG4gICAgICAgICAgICAvLyBObyB3ZSB3aWxsIGNoZWNrIGZvciB0aG9zZSB3aXRoIHRoZSBtYXRjaGluZyBwYXJhbXMuXG4gICAgICAgICAgICBvdXQuZm9yRWFjaCgobGluZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gcmVnZXguZXhlYyhsaW5lKSB8fCBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoYGtpbGxpbmcgTVNCdWlsZC5leGUgYXQgcGlkOiAke21hdGNoWzFdfWApO1xuICAgICAgICAgICAgICAgICAgICBzcGF3bi5zeW5jKCd0YXNra2lsbCcsIFsnL3BpZCcsIG1hdGNoWzFdLCAnL2YnLCAnL3QnXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlZ2V4Lmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoJ2tpbGwgTVNCdWlsZCBmYWlsZWQnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHBhdGggdG8gcGFja2FnZWQgYXBwLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0UGFja2FnZWRBcHBQYXRoKGNvbnRleHQgPSB7fSkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50Q29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSA9PT0gJ2RhcndpbicpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXRoLmpvaW4oXG4gICAgICAgICAgICAgICAgdGhpcy5pbnN0YWxsZXJEaXIsXG4gICAgICAgICAgICAgICAgJ21hYycsXG4gICAgICAgICAgICAgICAgYCR7Y29udGV4dC5wYWNrYWdlci5hcHBJbmZvLnByb2R1Y3RGaWxlbmFtZX0uYXBwYCxcbiAgICAgICAgICAgICAgICAnQ29udGVudHMnLCAnUmVzb3VyY2VzJywgJ2FwcCdcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGxhdGZvcm1EaXIgPVxuICAgICAgICAgICAgYCR7dGhpcy5jdXJyZW50Q29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSA9PT0gJ3dpbjMyJyA/ICd3aW4nIDogJ2xpbnV4J30tJHt0aGlzLmN1cnJlbnRDb250ZXh0LmFyY2ggPT09ICdpYTMyJyA/ICdpYTMyLScgOiAnJ311bnBhY2tlZGA7XG4gICAgICAgIHJldHVybiBwYXRoLmpvaW4oXG4gICAgICAgICAgICB0aGlzLmluc3RhbGxlckRpcixcbiAgICAgICAgICAgIHBsYXRmb3JtRGlyLFxuICAgICAgICAgICAgJ3Jlc291cmNlcycsICdhcHAnXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gV2luZG93cyBpdCB3YWl0cyBmb3IgdGhlIGFwcC5hc2FyIGluIHRoZSBwYWNrZWQgYXBwIHRvIGJlIGZyZWUgKG5vIGZpbGUgbG9ja3MpLlxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHdhaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRDb250ZXh0LnBsYXRmb3JtLm5vZGVOYW1lICE9PSAnd2luMzInKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYXBwQXNhclBhdGggPSBwYXRoLmpvaW4oXG4gICAgICAgICAgICB0aGlzLmdldFBhY2thZ2VkQXBwUGF0aCgpLFxuICAgICAgICAgICAgJ2FwcC5hc2FyJ1xuICAgICAgICApO1xuICAgICAgICBsZXQgcmV0cmllcyA9IDA7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2soKSB7XG4gICAgICAgICAgICAgICAgZnMub3BlbihhcHBBc2FyUGF0aCwgJ3IrJywgKGVyciwgZmQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cmllcyArPSAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyLmNvZGUgIT09ICdFTk9FTlQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5sb2cuZGVidWcoYHdhaXRpbmcgZm9yIGFwcC5hc2FyIHRvIGJlIHJlYWRhYmxlLCAkeydjb2RlJyBpbiBlcnIgPyBgY3VycmVudGx5IHJlYWRpbmcgaXQgcmV0dXJucyAke2Vyci5jb2RlfWAgOiAnJ31gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmV0cmllcyA8IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBjaGVjaygpLCA0MDAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoYGZpbGUgaXMgbG9ja2VkOiAke2FwcEFzYXJQYXRofWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnMuY2xvc2VTeW5jKGZkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2hlY2soKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJlcGFyZXMgdGhlIHRhcmdldCBvYmplY3QgcGFzc2VkIHRvIHRoZSBlbGVjdHJvbi1idWlsZGVyLlxuICAgICAqXG4gICAgICogQHJldHVybnMge01hcDxQbGF0Zm9ybSwgTWFwPEFyY2gsIEFycmF5PHN0cmluZz4+Pn1cbiAgICAgKi9cbiAgICBwcmVwYXJlVGFyZ2V0cygpIHtcbiAgICAgICAgbGV0IGFyY2ggPSB0aGlzLiQuZW52Lm9wdGlvbnMuaWEzMiA/ICdpYTMyJyA6ICd4NjQnO1xuICAgICAgICBhcmNoID0gdGhpcy4kLmVudi5vcHRpb25zLmFsbEFyY2hzID8gJ2FsbCcgOiBhcmNoO1xuXG4gICAgICAgIGNvbnN0IHRhcmdldHMgPSBbXTtcblxuICAgICAgICBpZiAodGhpcy4kLmVudi5vcHRpb25zLndpbikge1xuICAgICAgICAgICAgdGFyZ2V0cy5wdXNoKHRoaXMuYnVpbGRlci5kZXBlbmRlbmN5LlBsYXRmb3JtLldJTkRPV1MpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLiQuZW52Lm9wdGlvbnMubGludXgpIHtcbiAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5MSU5VWCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuJC5lbnYub3B0aW9ucy5tYWMpIHtcbiAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5NQUMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRhcmdldHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBpZiAodGhpcy4kLmVudi5vcy5pc1dpbmRvd3MpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRzLnB1c2godGhpcy5idWlsZGVyLmRlcGVuZGVuY3kuUGxhdGZvcm0uV0lORE9XUyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuJC5lbnYub3MuaXNMaW51eCkge1xuICAgICAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5MSU5VWCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5NQUMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5jcmVhdGVUYXJnZXRzKHRhcmdldHMsIG51bGwsIGFyY2gpO1xuICAgIH1cblxuICAgIGFzeW5jIGJ1aWxkKCkge1xuICAgICAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuJC5kZXNrdG9wLmdldFNldHRpbmdzKCk7XG4gICAgICAgIGlmICghKCdidWlsZGVyT3B0aW9ucycgaW4gc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5lcnJvcihcbiAgICAgICAgICAgICAgICAnbm8gYnVpbGRlck9wdGlvbnMgaW4gc2V0dGluZ3MuanNvbiwgYWJvcnRpbmcnXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYnVpbGRlck9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBzZXR0aW5ncy5idWlsZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgYnVpbGRlck9wdGlvbnMuYXNhciA9IGZhbHNlO1xuICAgICAgICBidWlsZGVyT3B0aW9ucy5ucG1SZWJ1aWxkID0gdHJ1ZTtcblxuICAgICAgICBidWlsZGVyT3B0aW9ucy5iZWZvcmVCdWlsZCA9IHRoaXMuYmVmb3JlQnVpbGQuYmluZCh0aGlzKTtcbiAgICAgICAgYnVpbGRlck9wdGlvbnMuYWZ0ZXJQYWNrID0gdGhpcy5hZnRlclBhY2suYmluZCh0aGlzKTtcbiAgICAgICAgYnVpbGRlck9wdGlvbnMuZWxlY3Ryb25WZXJzaW9uID0gdGhpcy4kLmdldEVsZWN0cm9uVmVyc2lvbigpO1xuXG4gICAgICAgIGJ1aWxkZXJPcHRpb25zLmRpcmVjdG9yaWVzID0ge1xuICAgICAgICAgICAgYXBwOiB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLnJvb3QsXG4gICAgICAgICAgICBvdXRwdXQ6IHBhdGguam9pbih0aGlzLiQuZW52Lm9wdGlvbnMub3V0cHV0LCB0aGlzLiQuZW52LnBhdGhzLmluc3RhbGxlckRpcilcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoJ21hYycgaW4gYnVpbGRlck9wdGlvbnMgJiYgJ3RhcmdldCcgaW4gYnVpbGRlck9wdGlvbnMubWFjKSB7XG4gICAgICAgICAgICBpZiAoYnVpbGRlck9wdGlvbnMubWFjLnRhcmdldC5pbmNsdWRlcygnbWFzJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBsYXRmb3JtcyA9IFsnZGFyd2luJywgJ21hcyddO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMubG9nLmRlYnVnKCdjYWxsaW5nIGJ1aWxkIGZyb20gZWxlY3Ryb24tYnVpbGRlcicpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5idWlsZGVyLmRlcGVuZGVuY3kuYnVpbGQoT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgdGFyZ2V0czogdGhpcy5wcmVwYXJlVGFyZ2V0cygpLFxuICAgICAgICAgICAgICAgIGNvbmZpZzogYnVpbGRlck9wdGlvbnNcbiAgICAgICAgICAgIH0sIHNldHRpbmdzLmJ1aWxkZXJDbGlPcHRpb25zKSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLiQudXRpbHMuZXhpc3RzKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkTm9kZU1vZHVsZXMpKSB7XG4gICAgICAgICAgICAgICAgc2hlbGwucm0oJy1yZicsIHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkTm9kZU1vZHVsZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5lcnJvcignZXJyb3Igd2hpbGUgYnVpbGRpbmcgaW5zdGFsbGVyOiAnLCBlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vdmVzIG5vZGVfbW9kdWxlcyBvdXQgb2YgdGhlIGFwcCBiZWNhdXNlIHdoaWxlIHRoZSBhcHAgd2lsbCBiZSBwYWNrYWdlZFxuICAgICAqIHdlIGRvIG5vdCB3YW50IGl0IHRvIGJlIHRoZXJlLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAgICovXG4gICAgbW92ZU5vZGVNb2R1bGVzT3V0KCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoJ21vdmluZyBub2RlX21vZHVsZXMgb3V0LCBiZWNhdXNlIHdlIGhhdmUgdGhlbSBhbHJlYWR5IGluJyArXG4gICAgICAgICAgICAgICAgJyBhcHAuYXNhcicpO1xuICAgICAgICAgICAgdGhpcy5raWxsTVNCdWlsZCgpO1xuICAgICAgICAgICAgcmVtb3ZlRGlyKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAudG1wTm9kZU1vZHVsZXMpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc2hlbGwuY29uZmlnLmZhdGFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2hlbGwuY29uZmlnLnZlcmJvc2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2hlbGwubXYoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5ub2RlTW9kdWxlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLnRtcE5vZGVNb2R1bGVzXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2hlbGwuY29uZmlnLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy53YWl0KCk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoZWxsLmNvbmZpZy5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZSA9PiByZWplY3QoZSkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gcmVtb3ZlRGlyKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAubm9kZU1vZHVsZXMsIDEwMDApKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlID0+IHJlamVjdChlKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLndhaXQoKSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gocmVqZWN0KVxuICAgICAgICAgICAgICAgIC50aGVuKHJlc29sdmUpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG4iXX0=