aws-cdk
Version:
AWS CDK CLI, the command line tool for CDK apps
279 lines • 40.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.execProgram = execProgram;
exports.createAssembly = createAssembly;
exports.prepareDefaultEnvironment = prepareDefaultEnvironment;
exports.prepareContext = prepareContext;
exports.guessExecutable = guessExecutable;
exports.spaceAvailableForContext = spaceAvailableForContext;
const childProcess = require("child_process");
const os = require("os");
const path = require("path");
const util_1 = require("util");
const cxschema = require("@aws-cdk/cloud-assembly-schema");
const cxapi = require("@aws-cdk/cx-api");
const fs = require("fs-extra");
const semver = require("semver");
const api_1 = require("../../../../@aws-cdk/tmp-toolkit-helpers/src/api");
const private_1 = require("../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private");
const tree_1 = require("../../api/tree");
const user_configuration_1 = require("../../cli/user-configuration");
const version_1 = require("../../cli/version");
const util_2 = require("../../util");
const rwlock_1 = require("../util/rwlock");
/** Invokes the cloud executable and returns JSON output */
async function execProgram(aws, ioHelper, config) {
const debugFn = (msg) => ioHelper.notify(private_1.IO.DEFAULT_ASSEMBLY_DEBUG.msg(msg));
const env = await prepareDefaultEnvironment(aws, debugFn);
const context = await prepareContext(config.settings, config.context.all, env, debugFn);
const build = config.settings.get(['build']);
if (build) {
await exec(build);
}
const app = config.settings.get(['app']);
if (!app) {
throw new api_1.ToolkitError(`--app is required either in command-line, in ${user_configuration_1.PROJECT_CONFIG} or in ${user_configuration_1.USER_DEFAULTS}`);
}
// bypass "synth" if app points to a cloud assembly
if (await fs.pathExists(app) && (await fs.stat(app)).isDirectory()) {
await debugFn('--app points to a cloud assembly, so we bypass synth');
// Acquire a read lock on this directory
const lock = await new rwlock_1.RWLock(app).acquireRead();
return { assembly: createAssembly(app), lock };
}
const commandLine = await guessExecutable(app, debugFn);
const outdir = config.settings.get(['output']);
if (!outdir) {
throw new api_1.ToolkitError('unexpected: --output is required');
}
if (typeof outdir !== 'string') {
throw new api_1.ToolkitError(`--output takes a string, got ${JSON.stringify(outdir)}`);
}
try {
await fs.mkdirp(outdir);
}
catch (error) {
throw new api_1.ToolkitError(`Could not create output directory ${outdir} (${error.message})`);
}
await debugFn(`outdir: ${outdir}`);
env[cxapi.OUTDIR_ENV] = outdir;
// Acquire a lock on the output directory
const writerLock = await new rwlock_1.RWLock(outdir).acquireWrite();
try {
// Send version information
env[cxapi.CLI_ASM_VERSION_ENV] = cxschema.Manifest.version();
env[cxapi.CLI_VERSION_ENV] = (0, version_1.versionNumber)();
await debugFn((0, util_1.format)('env:', env));
const envVariableSizeLimit = os.platform() === 'win32' ? 32760 : 131072;
const [smallContext, overflow] = (0, util_2.splitBySize)(context, spaceAvailableForContext(env, envVariableSizeLimit));
// Store the safe part in the environment variable
env[cxapi.CONTEXT_ENV] = JSON.stringify(smallContext);
// If there was any overflow, write it to a temporary file
let contextOverflowLocation;
if (Object.keys(overflow ?? {}).length > 0) {
const contextDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-context'));
contextOverflowLocation = path.join(contextDir, 'context-overflow.json');
fs.writeJSONSync(contextOverflowLocation, overflow);
env[cxapi.CONTEXT_OVERFLOW_LOCATION_ENV] = contextOverflowLocation;
}
await exec(commandLine.join(' '));
const assembly = createAssembly(outdir);
await contextOverflowCleanup(contextOverflowLocation, assembly, ioHelper);
return { assembly, lock: await writerLock.convertToReaderLock() };
}
catch (e) {
await writerLock.release();
throw e;
}
async function exec(commandAndArgs) {
try {
await new Promise((ok, fail) => {
// We use a slightly lower-level interface to:
//
// - Pass arguments in an array instead of a string, to get around a
// number of quoting issues introduced by the intermediate shell layer
// (which would be different between Linux and Windows).
//
// - Inherit stderr from controlling terminal. We don't use the captured value
// anyway, and if the subprocess is printing to it for debugging purposes the
// user gets to see it sooner. Plus, capturing doesn't interact nicely with some
// processes like Maven.
const proc = childProcess.spawn(commandAndArgs, {
stdio: ['ignore', 'inherit', 'inherit'],
detached: false,
shell: true,
env: {
...process.env,
...env,
},
});
proc.on('error', fail);
proc.on('exit', code => {
if (code === 0) {
return ok();
}
else {
return fail(new api_1.ToolkitError(`Subprocess exited with error ${code}`));
}
});
});
}
catch (e) {
await debugFn(`failed command: ${commandAndArgs}`);
throw e;
}
}
}
/**
* Creates an assembly with error handling
*/
function createAssembly(appDir) {
try {
return new cxapi.CloudAssembly(appDir, {
// We sort as we deploy
topoSort: false,
});
}
catch (error) {
if (error.message.includes(cxschema.VERSION_MISMATCH)) {
// this means the CLI version is too old.
// we instruct the user to upgrade.
throw new api_1.ToolkitError(`This CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version.\n(${error.message})`);
}
throw error;
}
}
/**
* If we don't have region/account defined in context, we fall back to the default SDK behavior
* where region is retrieved from ~/.aws/config and account is based on default credentials provider
* chain and then STS is queried.
*
* This is done opportunistically: for example, if we can't access STS for some reason or the region
* is not configured, the context value will be 'null' and there could failures down the line. In
* some cases, synthesis does not require region/account information at all, so that might be perfectly
* fine in certain scenarios.
*
* @param context The context key/value bash.
*/
async function prepareDefaultEnvironment(aws, debugFn) {
const env = {};
env[cxapi.DEFAULT_REGION_ENV] = aws.defaultRegion;
await debugFn(`Setting "${cxapi.DEFAULT_REGION_ENV}" environment variable to ${env[cxapi.DEFAULT_REGION_ENV]}`);
const accountId = (await aws.defaultAccount())?.accountId;
if (accountId) {
env[cxapi.DEFAULT_ACCOUNT_ENV] = accountId;
await debugFn(`Setting "${cxapi.DEFAULT_ACCOUNT_ENV}" environment variable to ${env[cxapi.DEFAULT_ACCOUNT_ENV]}`);
}
return env;
}
/**
* Settings related to synthesis are read from context.
* The merging of various configuration sources like cli args or cdk.json has already happened.
* We now need to set the final values to the context.
*/
async function prepareContext(settings, context, env, debugFn) {
const debugMode = settings.get(['debug']) ?? true;
if (debugMode) {
env.CDK_DEBUG = 'true';
}
const pathMetadata = settings.get(['pathMetadata']) ?? true;
if (pathMetadata) {
context[cxapi.PATH_METADATA_ENABLE_CONTEXT] = true;
}
const assetMetadata = settings.get(['assetMetadata']) ?? true;
if (assetMetadata) {
context[cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT] = true;
}
const versionReporting = settings.get(['versionReporting']) ?? true;
if (versionReporting) {
context[cxapi.ANALYTICS_REPORTING_ENABLED_CONTEXT] = true;
}
// We need to keep on doing this for framework version from before this flag was deprecated.
if (!versionReporting) {
context['aws:cdk:disable-version-reporting'] = true;
}
const stagingEnabled = settings.get(['staging']) ?? true;
if (!stagingEnabled) {
context[cxapi.DISABLE_ASSET_STAGING_CONTEXT] = true;
}
const bundlingStacks = settings.get(['bundlingStacks']) ?? ['**'];
context[cxapi.BUNDLING_STACKS] = bundlingStacks;
await debugFn((0, util_1.format)('context:', context));
return context;
}
/**
* Make sure the 'app' is an array
*
* If it's a string, split on spaces as a trivial way of tokenizing the command line.
*/
function appToArray(app) {
return typeof app === 'string' ? app.split(' ') : app;
}
/**
* Execute the given file with the same 'node' process as is running the current process
*/
function executeNode(scriptFile) {
return [process.execPath, scriptFile];
}
/**
* Mapping of extensions to command-line generators
*/
const EXTENSION_MAP = new Map([
['.js', executeNode],
]);
/**
* Guess the executable from the command-line argument
*
* Only do this if the file is NOT marked as executable. If it is,
* we'll defer to the shebang inside the file itself.
*
* If we're on Windows, we ALWAYS take the handler, since it's hard to
* verify if registry associations have or have not been set up for this
* file type, so we'll assume the worst and take control.
*/
async function guessExecutable(app, debugFn) {
const commandLine = appToArray(app);
if (commandLine.length === 1) {
let fstat;
try {
fstat = await fs.stat(commandLine[0]);
}
catch {
await debugFn(`Not a file: '${commandLine[0]}'. Using '${commandLine}' as command-line`);
return commandLine;
}
// eslint-disable-next-line no-bitwise
const isExecutable = (fstat.mode & fs.constants.X_OK) !== 0;
const isWindows = process.platform === 'win32';
const handler = EXTENSION_MAP.get(path.extname(commandLine[0]));
if (handler && (!isExecutable || isWindows)) {
return handler(commandLine[0]);
}
}
return commandLine;
}
async function contextOverflowCleanup(location, assembly, ioHelper) {
if (location) {
fs.removeSync(path.dirname(location));
const tree = await (0, tree_1.loadTree)(assembly, (msg) => ioHelper.notify(private_1.IO.DEFAULT_ASSEMBLY_TRACE.msg(msg)));
const frameworkDoesNotSupportContextOverflow = (0, tree_1.some)(tree, node => {
const fqn = node.constructInfo?.fqn;
const version = node.constructInfo?.version;
return (fqn === 'aws-cdk-lib.App' && version != null && semver.lte(version, '2.38.0'))
|| fqn === '@aws-cdk/core.App'; // v1
});
// We're dealing with an old version of the framework here. It is unaware of the temporary
// file, which means that it will ignore the context overflow.
if (frameworkDoesNotSupportContextOverflow) {
await ioHelper.notify(private_1.IO.DEFAULT_ASSEMBLY_WARN.msg('Part of the context could not be sent to the application. Please update the AWS CDK library to the latest version.'));
}
}
}
function spaceAvailableForContext(env, limit) {
const size = (value) => value != null ? Buffer.byteLength(value) : 0;
const usedSpace = Object.entries(env)
.map(([k, v]) => k === cxapi.CONTEXT_ENV ? size(k) : size(k) + size(v))
.reduce((a, b) => a + b, 0);
return Math.max(0, limit - usedSpace);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV4ZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUEwQkEsa0NBc0hDO0FBS0Qsd0NBY0M7QUFjRCw4REFnQkM7QUFPRCx3Q0F5Q0M7QUFxQ0QsMENBc0JDO0FBMEJELDREQVFDO0FBOVVELDhDQUE4QztBQUM5Qyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLCtCQUE4QjtBQUM5QiwyREFBMkQ7QUFDM0QseUNBQXlDO0FBQ3pDLCtCQUErQjtBQUMvQixpQ0FBaUM7QUFDakMsMEVBQWdGO0FBQ2hGLHlGQUFnRztBQUNoRyx5Q0FBZ0Q7QUFFaEQscUVBQTZFO0FBQzdFLCtDQUFrRDtBQUNsRCxxQ0FBeUM7QUFJekMsMkNBQXdDO0FBT3hDLDJEQUEyRDtBQUNwRCxLQUFLLFVBQVUsV0FBVyxDQUFDLEdBQWdCLEVBQUUsUUFBa0IsRUFBRSxNQUFxQjtJQUMzRixNQUFNLE9BQU8sR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxZQUFFLENBQUMsc0JBQXNCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDckYsTUFBTSxHQUFHLEdBQUcsTUFBTSx5QkFBeUIsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDMUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxjQUFjLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFeEYsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQzdDLElBQUksS0FBSyxFQUFFLENBQUM7UUFDVixNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNwQixDQUFDO0lBRUQsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLFFB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cG9ydCAqIGFzIGNoaWxkUHJvY2VzcyBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBmb3JtYXQgfSBmcm9tICd1dGlsJztcbmltcG9ydCAqIGFzIGN4c2NoZW1hIGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0ICogYXMgc2VtdmVyIGZyb20gJ3NlbXZlcic7XG5pbXBvcnQgeyBUb29sa2l0RXJyb3IgfSBmcm9tICcuLi8uLi8uLi8uLi9AYXdzLWNkay90bXAtdG9vbGtpdC1oZWxwZXJzL3NyYy9hcGknO1xuaW1wb3J0IHsgSU8sIHR5cGUgSW9IZWxwZXIgfSBmcm9tICcuLi8uLi8uLi8uLi9AYXdzLWNkay90bXAtdG9vbGtpdC1oZWxwZXJzL3NyYy9hcGkvaW8vcHJpdmF0ZSc7XG5pbXBvcnQgeyBsb2FkVHJlZSwgc29tZSB9IGZyb20gJy4uLy4uL2FwaS90cmVlJztcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uLy4uL2NsaS91c2VyLWNvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgUFJPSkVDVF9DT05GSUcsIFVTRVJfREVGQVVMVFMgfSBmcm9tICcuLi8uLi9jbGkvdXNlci1jb25maWd1cmF0aW9uJztcbmltcG9ydCB7IHZlcnNpb25OdW1iZXIgfSBmcm9tICcuLi8uLi9jbGkvdmVyc2lvbic7XG5pbXBvcnQgeyBzcGxpdEJ5U2l6ZSB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHR5cGUgeyBTZGtQcm92aWRlciB9IGZyb20gJy4uL2F3cy1hdXRoJztcbmltcG9ydCB0eXBlIHsgU2V0dGluZ3MgfSBmcm9tICcuLi9zZXR0aW5ncyc7XG5pbXBvcnQgdHlwZSB7IElMb2NrIH0gZnJvbSAnLi4vdXRpbC9yd2xvY2snO1xuaW1wb3J0IHsgUldMb2NrIH0gZnJvbSAnLi4vdXRpbC9yd2xvY2snO1xuXG5leHBvcnQgaW50ZXJmYWNlIEV4ZWNQcm9ncmFtUmVzdWx0IHtcbiAgcmVhZG9ubHkgYXNzZW1ibHk6IGN4YXBpLkNsb3VkQXNzZW1ibHk7XG4gIHJlYWRvbmx5IGxvY2s6IElMb2NrO1xufVxuXG4vKiogSW52b2tlcyB0aGUgY2xvdWQgZXhlY3V0YWJsZSBhbmQgcmV0dXJucyBKU09OIG91dHB1dCAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4ZWNQcm9ncmFtKGF3czogU2RrUHJvdmlkZXIsIGlvSGVscGVyOiBJb0hlbHBlciwgY29uZmlnOiBDb25maWd1cmF0aW9uKTogUHJvbWlzZTxFeGVjUHJvZ3JhbVJlc3VsdD4ge1xuICBjb25zdCBkZWJ1Z0ZuID0gKG1zZzogc3RyaW5nKSA9PiBpb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9BU1NFTUJMWV9ERUJVRy5tc2cobXNnKSk7XG4gIGNvbnN0IGVudiA9IGF3YWl0IHByZXBhcmVEZWZhdWx0RW52aXJvbm1lbnQoYXdzLCBkZWJ1Z0ZuKTtcbiAgY29uc3QgY29udGV4dCA9IGF3YWl0IHByZXBhcmVDb250ZXh0KGNvbmZpZy5zZXR0aW5ncywgY29uZmlnLmNvbnRleHQuYWxsLCBlbnYsIGRlYnVnRm4pO1xuXG4gIGNvbnN0IGJ1aWxkID0gY29uZmlnLnNldHRpbmdzLmdldChbJ2J1aWxkJ10pO1xuICBpZiAoYnVpbGQpIHtcbiAgICBhd2FpdCBleGVjKGJ1aWxkKTtcbiAgfVxuXG4gIGNvbnN0IGFwcCA9IGNvbmZpZy5zZXR0aW5ncy5nZXQoWydhcHAnXSk7XG4gIGlmICghYXBwKSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgLS1hcHAgaXMgcmVxdWlyZWQgZWl0aGVyIGluIGNvbW1hbmQtbGluZSwgaW4gJHtQUk9KRUNUX0NPTkZJR30gb3IgaW4gJHtVU0VSX0RFRkFVTFRTfWApO1xuICB9XG5cbiAgLy8gYnlwYXNzIFwic3ludGhcIiBpZiBhcHAgcG9pbnRzIHRvIGEgY2xvdWQgYXNzZW1ibHlcbiAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoYXBwKSAmJiAoYXdhaXQgZnMuc3RhdChhcHApKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgYXdhaXQgZGVidWdGbignLS1hcHAgcG9pbnRzIHRvIGEgY2xvdWQgYXNzZW1ibHksIHNvIHdlIGJ5cGFzcyBzeW50aCcpO1xuXG4gICAgLy8gQWNxdWlyZSBhIHJlYWQgbG9jayBvbiB0aGlzIGRpcmVjdG9yeVxuICAgIGNvbnN0IGxvY2sgPSBhd2FpdCBuZXcgUldMb2NrKGFwcCkuYWNxdWlyZVJlYWQoKTtcblxuICAgIHJldHVybiB7IGFzc2VtYmx5OiBjcmVhdGVBc3NlbWJseShhcHApLCBsb2NrIH07XG4gIH1cblxuICBjb25zdCBjb21tYW5kTGluZSA9IGF3YWl0IGd1ZXNzRXhlY3V0YWJsZShhcHAsIGRlYnVnRm4pO1xuXG4gIGNvbnN0IG91dGRpciA9IGNvbmZpZy5zZXR0aW5ncy5nZXQoWydvdXRwdXQnXSk7XG4gIGlmICghb3V0ZGlyKSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcigndW5leHBlY3RlZDogLS1vdXRwdXQgaXMgcmVxdWlyZWQnKTtcbiAgfVxuICBpZiAodHlwZW9mIG91dGRpciAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGAtLW91dHB1dCB0YWtlcyBhIHN0cmluZywgZ290ICR7SlNPTi5zdHJpbmdpZnkob3V0ZGlyKX1gKTtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IGZzLm1rZGlycChvdXRkaXIpO1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgQ291bGQgbm90IGNyZWF0ZSBvdXRwdXQgZGlyZWN0b3J5ICR7b3V0ZGlyfSAoJHtlcnJvci5tZXNzYWdlfSlgKTtcbiAgfVxuXG4gIGF3YWl0IGRlYnVnRm4oYG91dGRpcjogJHtvdXRkaXJ9YCk7XG4gIGVudltjeGFwaS5PVVRESVJfRU5WXSA9IG91dGRpcjtcblxuICAvLyBBY3F1aXJlIGEgbG9jayBvbiB0aGUgb3V0cHV0IGRpcmVjdG9yeVxuICBjb25zdCB3cml0ZXJMb2NrID0gYXdhaXQgbmV3IFJXTG9jayhvdXRkaXIpLmFjcXVpcmVXcml0ZSgpO1xuXG4gIHRyeSB7XG4gICAgLy8gU2VuZCB2ZXJzaW9uIGluZm9ybWF0aW9uXG4gICAgZW52W2N4YXBpLkNMSV9BU01fVkVSU0lPTl9FTlZdID0gY3hzY2hlbWEuTWFuaWZlc3QudmVyc2lvbigpO1xuICAgIGVudltjeGFwaS5DTElfVkVSU0lPTl9FTlZdID0gdmVyc2lvbk51bWJlcigpO1xuXG4gICAgYXdhaXQgZGVidWdGbihmb3JtYXQoJ2VudjonLCBlbnYpKTtcblxuICAgIGNvbnN0IGVudlZhcmlhYmxlU2l6ZUxpbWl0ID0gb3MucGxhdGZvcm0oKSA9PT0gJ3dpbjMyJyA/IDMyNzYwIDogMTMxMDcyO1xuICAgIGNvbnN0IFtzbWFsbENvbnRleHQsIG92ZXJmbG93XSA9IHNwbGl0QnlTaXplKGNvbnRleHQsIHNwYWNlQXZhaWxhYmxlRm9yQ29udGV4dChlbnYsIGVudlZhcmlhYmxlU2l6ZUxpbWl0KSk7XG5cbiAgICAvLyBTdG9yZSB0aGUgc2FmZSBwYXJ0IGluIHRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICAgIGVudltjeGFwaS5DT05URVhUX0VOVl0gPSBKU09OLnN0cmluZ2lmeShzbWFsbENvbnRleHQpO1xuXG4gICAgLy8gSWYgdGhlcmUgd2FzIGFueSBvdmVyZmxvdywgd3JpdGUgaXQgdG8gYSB0ZW1wb3JhcnkgZmlsZVxuICAgIGxldCBjb250ZXh0T3ZlcmZsb3dMb2NhdGlvbjtcbiAgICBpZiAoT2JqZWN0LmtleXMob3ZlcmZsb3cgPz8ge30pLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGNvbnRleHREaXIgPSBhd2FpdCBmcy5ta2R0ZW1wKHBhdGguam9pbihvcy50bXBkaXIoKSwgJ2Nkay1jb250ZXh0JykpO1xuICAgICAgY29udGV4dE92ZXJmbG93TG9jYXRpb24gPSBwYXRoLmpvaW4oY29udGV4dERpciwgJ2NvbnRleHQtb3ZlcmZsb3cuanNvbicpO1xuICAgICAgZnMud3JpdGVKU09OU3luYyhjb250ZXh0T3ZlcmZsb3dMb2NhdGlvbiwgb3ZlcmZsb3cpO1xuICAgICAgZW52W2N4YXBpLkNPTlRFWFRfT1ZFUkZMT1dfTE9DQVRJT05fRU5WXSA9IGNvbnRleHRPdmVyZmxvd0xvY2F0aW9uO1xuICAgIH1cblxuICAgIGF3YWl0IGV4ZWMoY29tbWFuZExpbmUuam9pbignICcpKTtcblxuICAgIGNvbnN0IGFzc2VtYmx5ID0gY3JlYXRlQXNzZW1ibHkob3V0ZGlyKTtcblxuICAgIGF3YWl0IGNvbnRleHRPdmVyZmxvd0NsZWFudXAoY29udGV4dE92ZXJmbG93TG9jYXRpb24sIGFzc2VtYmx5LCBpb0hlbHBlcik7XG5cbiAgICByZXR1cm4geyBhc3NlbWJseSwgbG9jazogYXdhaXQgd3JpdGVyTG9jay5jb252ZXJ0VG9SZWFkZXJMb2NrKCkgfTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGF3YWl0IHdyaXRlckxvY2sucmVsZWFzZSgpO1xuICAgIHRocm93IGU7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBleGVjKGNvbW1hbmRBbmRBcmdzOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKG9rLCBmYWlsKSA9PiB7XG4gICAgICAgIC8vIFdlIHVzZSBhIHNsaWdodGx5IGxvd2VyLWxldmVsIGludGVyZmFjZSB0bzpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gLSBQYXNzIGFyZ3VtZW50cyBpbiBhbiBhcnJheSBpbnN0ZWFkIG9mIGEgc3RyaW5nLCB0byBnZXQgYXJvdW5kIGFcbiAgICAgICAgLy8gICBudW1iZXIgb2YgcXVvdGluZyBpc3N1ZXMgaW50cm9kdWNlZCBieSB0aGUgaW50ZXJtZWRpYXRlIHNoZWxsIGxheWVyXG4gICAgICAgIC8vICAgKHdoaWNoIHdvdWxkIGJlIGRpZmZlcmVudCBiZXR3ZWVuIExpbnV4IGFuZCBXaW5kb3dzKS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gLSBJbmhlcml0IHN0ZGVyciBmcm9tIGNvbnRyb2xsaW5nIHRlcm1pbmFsLiBXZSBkb24ndCB1c2UgdGhlIGNhcHR1cmVkIHZhbHVlXG4gICAgICAgIC8vICAgYW55d2F5LCBhbmQgaWYgdGhlIHN1YnByb2Nlc3MgaXMgcHJpbnRpbmcgdG8gaXQgZm9yIGRlYnVnZ2luZyBwdXJwb3NlcyB0aGVcbiAgICAgICAgLy8gICB1c2VyIGdldHMgdG8gc2VlIGl0IHNvb25lci4gUGx1cywgY2FwdHVyaW5nIGRvZXNuJ3QgaW50ZXJhY3QgbmljZWx5IHdpdGggc29tZVxuICAgICAgICAvLyAgIHByb2Nlc3NlcyBsaWtlIE1hdmVuLlxuICAgICAgICBjb25zdCBwcm9jID0gY2hpbGRQcm9jZXNzLnNwYXduKGNvbW1hbmRBbmRBcmdzLCB7XG4gICAgICAgICAgc3RkaW86IFsnaWdub3JlJywgJ2luaGVyaXQnLCAnaW5oZXJpdCddLFxuICAgICAgICAgIGRldGFjaGVkOiBmYWxzZSxcbiAgICAgICAgICBzaGVsbDogdHJ1ZSxcbiAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICAgICAgLi4uZW52LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByb2Mub24oJ2Vycm9yJywgZmFpbCk7XG5cbiAgICAgICAgcHJvYy5vbignZXhpdCcsIGNvZGUgPT4ge1xuICAgICAgICAgIGlmIChjb2RlID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gb2soKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhaWwobmV3IFRvb2xraXRFcnJvcihgU3VicHJvY2VzcyBleGl0ZWQgd2l0aCBlcnJvciAke2NvZGV9YCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGF3YWl0IGRlYnVnRm4oYGZhaWxlZCBjb21tYW5kOiAke2NvbW1hbmRBbmRBcmdzfWApO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFzc2VtYmx5IHdpdGggZXJyb3IgaGFuZGxpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFzc2VtYmx5KGFwcERpcjogc3RyaW5nKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG5ldyBjeGFwaS5DbG91ZEFzc2VtYmx5KGFwcERpciwge1xuICAgICAgLy8gV2Ugc29ydCBhcyB3ZSBkZXBsb3lcbiAgICAgIHRvcG9Tb3J0OiBmYWxzZSxcbiAgICB9KTtcbiAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgIGlmIChlcnJvci5tZXNzYWdlLmluY2x1ZGVzKGN4c2NoZW1hLlZFUlNJT05fTUlTTUFUQ0gpKSB7XG4gICAgICAvLyB0aGlzIG1lYW5zIHRoZSBDTEkgdmVyc2lvbiBpcyB0b28gb2xkLlxuICAgICAgLy8gd2UgaW5zdHJ1Y3QgdGhlIHVzZXIgdG8gdXBncmFkZS5cbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoYFRoaXMgQ0RLIENMSSBpcyBub3QgY29tcGF0aWJsZSB3aXRoIHRoZSBDREsgbGlicmFyeSB1c2VkIGJ5IHlvdXIgYXBwbGljYXRpb24uIFBsZWFzZSB1cGdyYWRlIHRoZSBDTEkgdG8gdGhlIGxhdGVzdCB2ZXJzaW9uLlxcbigke2Vycm9yLm1lc3NhZ2V9KWApO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG4vKipcbiAqIElmIHdlIGRvbid0IGhhdmUgcmVnaW9uL2FjY291bnQgZGVmaW5lZCBpbiBjb250ZXh0LCB3ZSBmYWxsIGJhY2sgdG8gdGhlIGRlZmF1bHQgU0RLIGJlaGF2aW9yXG4gKiB3aGVyZSByZWdpb24gaXMgcmV0cmlldmVkIGZyb20gfi8uYXdzL2NvbmZpZyBhbmQgYWNjb3VudCBpcyBiYXNlZCBvbiBkZWZhdWx0IGNyZWRlbnRpYWxzIHByb3ZpZGVyXG4gKiBjaGFpbiBhbmQgdGhlbiBTVFMgaXMgcXVlcmllZC5cbiAqXG4gKiBUaGlzIGlzIGRvbmUgb3Bwb3J0dW5pc3RpY2FsbHk6IGZvciBleGFtcGxlLCBpZiB3ZSBjYW4ndCBhY2Nlc3MgU1RTIGZvciBzb21lIHJlYXNvbiBvciB0aGUgcmVnaW9uXG4gKiBpcyBub3QgY29uZmlndXJlZCwgdGhlIGNvbnRleHQgdmFsdWUgd2lsbCBiZSAnbnVsbCcgYW5kIHRoZXJlIGNvdWxkIGZhaWx1cmVzIGRvd24gdGhlIGxpbmUuIEluXG4gKiBzb21lIGNhc2VzLCBzeW50aGVzaXMgZG9lcyBub3QgcmVxdWlyZSByZWdpb24vYWNjb3VudCBpbmZvcm1hdGlvbiBhdCBhbGwsIHNvIHRoYXQgbWlnaHQgYmUgcGVyZmVjdGx5XG4gKiBmaW5lIGluIGNlcnRhaW4gc2NlbmFyaW9zLlxuICpcbiAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IGtleS92YWx1ZSBiYXNoLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJlcGFyZURlZmF1bHRFbnZpcm9ubWVudChcbiAgYXdzOiBTZGtQcm92aWRlcixcbiAgZGVidWdGbjogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTx7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9PiB7XG4gIGNvbnN0IGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHsgfTtcblxuICBlbnZbY3hhcGkuREVGQVVMVF9SRUdJT05fRU5WXSA9IGF3cy5kZWZhdWx0UmVnaW9uO1xuICBhd2FpdCBkZWJ1Z0ZuKGBTZXR0aW5nIFwiJHtjeGFwaS5ERUZBVUxUX1JFR0lPTl9FTlZ9XCIgZW52aXJvbm1lbnQgdmFyaWFibGUgdG8gJHtlbnZbY3hhcGkuREVGQVVMVF9SRUdJT05fRU5WXX1gKTtcblxuICBjb25zdCBhY2NvdW50SWQgPSAoYXdhaXQgYXdzLmRlZmF1bHRBY2NvdW50KCkpPy5hY2NvdW50SWQ7XG4gIGlmIChhY2NvdW50SWQpIHtcbiAgICBlbnZbY3hhcGkuREVGQVVMVF9BQ0NPVU5UX0VOVl0gPSBhY2NvdW50SWQ7XG4gICAgYXdhaXQgZGVidWdGbihgU2V0dGluZyBcIiR7Y3hhcGkuREVGQVVMVF9BQ0NPVU5UX0VOVn1cIiBlbnZpcm9ubWVudCB2YXJpYWJsZSB0byAke2VudltjeGFwaS5ERUZBVUxUX0FDQ09VTlRfRU5WXX1gKTtcbiAgfVxuXG4gIHJldHVybiBlbnY7XG59XG5cbi8qKlxuICogU2V0dGluZ3MgcmVsYXRlZCB0byBzeW50aGVzaXMgYXJlIHJlYWQgZnJvbSBjb250ZXh0LlxuICogVGhlIG1lcmdpbmcgb2YgdmFyaW91cyBjb25maWd1cmF0aW9uIHNvdXJjZXMgbGlrZSBjbGkgYXJncyBvciBjZGsuanNvbiBoYXMgYWxyZWFkeSBoYXBwZW5lZC5cbiAqIFdlIG5vdyBuZWVkIHRvIHNldCB0aGUgZmluYWwgdmFsdWVzIHRvIHRoZSBjb250ZXh0LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJlcGFyZUNvbnRleHQoXG4gIHNldHRpbmdzOiBTZXR0aW5ncyxcbiAgY29udGV4dDoge1trZXk6IHN0cmluZ106IGFueX0sXG4gIGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCB1bmRlZmluZWR9LFxuICBkZWJ1Z0ZuOiAobXNnOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4sXG4pIHtcbiAgY29uc3QgZGVidWdNb2RlOiBib29sZWFuID0gc2V0dGluZ3MuZ2V0KFsnZGVidWcnXSkgPz8gdHJ1ZTtcbiAgaWYgKGRlYnVnTW9kZSkge1xuICAgIGVudi5DREtfREVCVUcgPSAndHJ1ZSc7XG4gIH1cblxuICBjb25zdCBwYXRoTWV0YWRhdGE6IGJvb2xlYW4gPSBzZXR0aW5ncy5nZXQoWydwYXRoTWV0YWRhdGEnXSkgPz8gdHJ1ZTtcbiAgaWYgKHBhdGhNZXRhZGF0YSkge1xuICAgIGNvbnRleHRbY3hhcGkuUEFUSF9NRVRBREFUQV9FTkFCTEVfQ09OVEVYVF0gPSB0cnVlO1xuICB9XG5cbiAgY29uc3QgYXNzZXRNZXRhZGF0YTogYm9vbGVhbiA9IHNldHRpbmdzLmdldChbJ2Fzc2V0TWV0YWRhdGEnXSkgPz8gdHJ1ZTtcbiAgaWYgKGFzc2V0TWV0YWRhdGEpIHtcbiAgICBjb250ZXh0W2N4YXBpLkFTU0VUX1JFU09VUkNFX01FVEFEQVRBX0VOQUJMRURfQ09OVEVYVF0gPSB0cnVlO1xuICB9XG5cbiAgY29uc3QgdmVyc2lvblJlcG9ydGluZzogYm9vbGVhbiA9IHNldHRpbmdzLmdldChbJ3ZlcnNpb25SZXBvcnRpbmcnXSkgPz8gdHJ1ZTtcbiAgaWYgKHZlcnNpb25SZXBvcnRpbmcpIHtcbiAgICBjb250ZXh0W2N4YXBpLkFOQUxZVElDU19SRVBPUlRJTkdfRU5BQkxFRF9DT05URVhUXSA9IHRydWU7XG4gIH1cbiAgLy8gV2UgbmVlZCB0byBrZWVwIG9uIGRvaW5nIHRoaXMgZm9yIGZyYW1ld29yayB2ZXJzaW9uIGZyb20gYmVmb3JlIHRoaXMgZmxhZyB3YXMgZGVwcmVjYXRlZC5cbiAgaWYgKCF2ZXJzaW9uUmVwb3J0aW5nKSB7XG4gICAgY29udGV4dFsnYXdzOmNkazpkaXNhYmxlLXZlcnNpb24tcmVwb3J0aW5nJ10gPSB0cnVlO1xuICB9XG5cbiAgY29uc3Qgc3RhZ2luZ0VuYWJsZWQgPSBzZXR0aW5ncy5nZXQoWydzdGFnaW5nJ10pID8/IHRydWU7XG4gIGlmICghc3RhZ2luZ0VuYWJsZWQpIHtcbiAgICBjb250ZXh0W2N4YXBpLkRJU0FCTEVfQVNTRVRfU1RBR0lOR19DT05URVhUXSA9IHRydWU7XG4gIH1cblxuICBjb25zdCBidW5kbGluZ1N0YWNrcyA9IHNldHRpbmdzLmdldChbJ2J1bmRsaW5nU3RhY2tzJ10pID8/IFsnKionXTtcbiAgY29udGV4dFtjeGFwaS5CVU5ETElOR19TVEFDS1NdID0gYnVuZGxpbmdTdGFja3M7XG5cbiAgYXdhaXQgZGVidWdGbihmb3JtYXQoJ2NvbnRleHQ6JywgY29udGV4dCkpO1xuXG4gIHJldHVybiBjb250ZXh0O1xufVxuXG4vKipcbiAqIE1ha2Ugc3VyZSB0aGUgJ2FwcCcgaXMgYW4gYXJyYXlcbiAqXG4gKiBJZiBpdCdzIGEgc3RyaW5nLCBzcGxpdCBvbiBzcGFjZXMgYXMgYSB0cml2aWFsIHdheSBvZiB0b2tlbml6aW5nIHRoZSBjb21tYW5kIGxpbmUuXG4gKi9cbmZ1bmN0aW9uIGFwcFRvQXJyYXkoYXBwOiBhbnkpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcHAgPT09ICdzdHJpbmcnID8gYXBwLnNwbGl0KCcgJykgOiBhcHA7XG59XG5cbnR5cGUgQ29tbWFuZEdlbmVyYXRvciA9IChmaWxlOiBzdHJpbmcpID0+IHN0cmluZ1tdO1xuXG4vKipcbiAqIEV4ZWN1dGUgdGhlIGdpdmVuIGZpbGUgd2l0aCB0aGUgc2FtZSAnbm9kZScgcHJvY2VzcyBhcyBpcyBydW5uaW5nIHRoZSBjdXJyZW50IHByb2Nlc3NcbiAqL1xuZnVuY3Rpb24gZXhlY3V0ZU5vZGUoc2NyaXB0RmlsZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gW3Byb2Nlc3MuZXhlY1BhdGgsIHNjcmlwdEZpbGVdO1xufVxuXG4vKipcbiAqIE1hcHBpbmcgb2YgZXh0ZW5zaW9ucyB0byBjb21tYW5kLWxpbmUgZ2VuZXJhdG9yc1xuICovXG5jb25zdCBFWFRFTlNJT05fTUFQID0gbmV3IE1hcDxzdHJpbmcsIENvbW1hbmRHZW5lcmF0b3I+KFtcbiAgWycuanMnLCBleGVjdXRlTm9kZV0sXG5dKTtcblxuLyoqXG4gKiBHdWVzcyB0aGUgZXhlY3V0YWJsZSBmcm9tIHRoZSBjb21tYW5kLWxpbmUgYXJndW1lbnRcbiAqXG4gKiBPbmx5IGRvIHRoaXMgaWYgdGhlIGZpbGUgaXMgTk9UIG1hcmtlZCBhcyBleGVjdXRhYmxlLiBJZiBpdCBpcyxcbiAqIHdlJ2xsIGRlZmVyIHRvIHRoZSBzaGViYW5nIGluc2lkZSB0aGUgZmlsZSBpdHNlbGYuXG4gKlxuICogSWYgd2UncmUgb24gV2luZG93cywgd2UgQUxXQVlTIHRha2UgdGhlIGhhbmRsZXIsIHNpbmNlIGl0J3MgaGFyZCB0b1xuICogdmVyaWZ5IGlmIHJlZ2lzdHJ5IGFzc29jaWF0aW9ucyBoYXZlIG9yIGhhdmUgbm90IGJlZW4gc2V0IHVwIGZvciB0aGlzXG4gKiBmaWxlIHR5cGUsIHNvIHdlJ2xsIGFzc3VtZSB0aGUgd29yc3QgYW5kIHRha2UgY29udHJvbC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGd1ZXNzRXhlY3V0YWJsZShhcHA6IHN0cmluZywgZGVidWdGbjogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+KSB7XG4gIGNvbnN0IGNvbW1hbmRMaW5lID0gYXBwVG9BcnJheShhcHApO1xuICBpZiAoY29tbWFuZExpbmUubGVuZ3RoID09PSAxKSB7XG4gICAgbGV0IGZzdGF0O1xuXG4gICAgdHJ5IHtcbiAgICAgIGZzdGF0ID0gYXdhaXQgZnMuc3RhdChjb21tYW5kTGluZVswXSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBhd2FpdCBkZWJ1Z0ZuKGBOb3QgYSBmaWxlOiAnJHtjb21tYW5kTGluZVswXX0nLiBVc2luZyAnJHtjb21tYW5kTGluZX0nIGFzIGNvbW1hbmQtbGluZWApO1xuICAgICAgcmV0dXJuIGNvbW1hbmRMaW5lO1xuICAgIH1cblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgY29uc3QgaXNFeGVjdXRhYmxlID0gKGZzdGF0Lm1vZGUgJiBmcy5jb25zdGFudHMuWF9PSykgIT09IDA7XG4gICAgY29uc3QgaXNXaW5kb3dzID0gcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJztcblxuICAgIGNvbnN0IGhhbmRsZXIgPSBFWFRFTlNJT05fTUFQLmdldChwYXRoLmV4dG5hbWUoY29tbWFuZExpbmVbMF0pKTtcbiAgICBpZiAoaGFuZGxlciAmJiAoIWlzRXhlY3V0YWJsZSB8fCBpc1dpbmRvd3MpKSB7XG4gICAgICByZXR1cm4gaGFuZGxlcihjb21tYW5kTGluZVswXSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBjb21tYW5kTGluZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29udGV4dE92ZXJmbG93Q2xlYW51cChcbiAgbG9jYXRpb246IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgYXNzZW1ibHk6IGN4YXBpLkNsb3VkQXNzZW1ibHksXG4gIGlvSGVscGVyOiBJb0hlbHBlcixcbikge1xuICBpZiAobG9jYXRpb24pIHtcbiAgICBmcy5yZW1vdmVTeW5jKHBhdGguZGlybmFtZShsb2NhdGlvbikpO1xuXG4gICAgY29uc3QgdHJlZSA9IGF3YWl0IGxvYWRUcmVlKGFzc2VtYmx5LCAobXNnOiBzdHJpbmcpID0+IGlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX0FTU0VNQkxZX1RSQUNFLm1zZyhtc2cpKSk7XG4gICAgY29uc3QgZnJhbWV3b3JrRG9lc05vdFN1cHBvcnRDb250ZXh0T3ZlcmZsb3cgPSBzb21lKHRyZWUsIG5vZGUgPT4ge1xuICAgICAgY29uc3QgZnFuID0gbm9kZS5jb25zdHJ1Y3RJbmZvPy5mcW47XG4gICAgICBjb25zdCB2ZXJzaW9uID0gbm9kZS5jb25zdHJ1Y3RJbmZvPy52ZXJzaW9uO1xuICAgICAgcmV0dXJuIChmcW4gPT09ICdhd3MtY2RrLWxpYi5BcHAnICYmIHZlcnNpb24gIT0gbnVsbCAmJiBzZW12ZXIubHRlKHZlcnNpb24sICcyLjM4LjAnKSlcbiAgICAgICAgfHwgZnFuID09PSAnQGF3cy1jZGsvY29yZS5BcHAnOyAvLyB2MVxuICAgIH0pO1xuXG4gICAgLy8gV2UncmUgZGVhbGluZyB3aXRoIGFuIG9sZCB2ZXJzaW9uIG9mIHRoZSBmcmFtZXdvcmsgaGVyZS4gSXQgaXMgdW5hd2FyZSBvZiB0aGUgdGVtcG9yYXJ5XG4gICAgLy8gZmlsZSwgd2hpY2ggbWVhbnMgdGhhdCBpdCB3aWxsIGlnbm9yZSB0aGUgY29udGV4dCBvdmVyZmxvdy5cbiAgICBpZiAoZnJhbWV3b3JrRG9lc05vdFN1cHBvcnRDb250ZXh0T3ZlcmZsb3cpIHtcbiAgICAgIGF3YWl0IGlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX0FTU0VNQkxZX1dBUk4ubXNnKCdQYXJ0IG9mIHRoZSBjb250ZXh0IGNvdWxkIG5vdCBiZSBzZW50IHRvIHRoZSBhcHBsaWNhdGlvbi4gUGxlYXNlIHVwZGF0ZSB0aGUgQVdTIENESyBsaWJyYXJ5IHRvIHRoZSBsYXRlc3QgdmVyc2lvbi4nKSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzcGFjZUF2YWlsYWJsZUZvckNvbnRleHQoZW52OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9LCBsaW1pdDogbnVtYmVyKSB7XG4gIGNvbnN0IHNpemUgPSAodmFsdWU6IHN0cmluZykgPT4gdmFsdWUgIT0gbnVsbCA/IEJ1ZmZlci5ieXRlTGVuZ3RoKHZhbHVlKSA6IDA7XG5cbiAgY29uc3QgdXNlZFNwYWNlID0gT2JqZWN0LmVudHJpZXMoZW52KVxuICAgIC5tYXAoKFtrLCB2XSkgPT4gayA9PT0gY3hhcGkuQ09OVEVYVF9FTlYgPyBzaXplKGspIDogc2l6ZShrKSArIHNpemUodikpXG4gICAgLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xuXG4gIHJldHVybiBNYXRoLm1heCgwLCBsaW1pdCAtIHVzZWRTcGFjZSk7XG59XG4iXX0=
;