UNPKG

@aws-cdk-testing/cli-integ

Version:

Integration tests for the AWS CDK CLI

228 lines 30.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ShellHelper = void 0; exports.shell = shell; exports.rimraf = rimraf; exports.addToShellPath = addToShellPath; const fs = require("fs"); const os = require("os"); const path = require("path"); const process_1 = require("./process"); /** * A shell command that does what you want * * Is platform-aware, handles errors nicely. */ async function shell(command, options = {}) { if (options.modEnv && options.env) { throw new Error('Use either env or modEnv but not both'); } const outputs = new Set(options.outputs); const writeToOutputs = (x) => { for (const outputStream of outputs) { outputStream.write(x); } }; // Always output the command writeToOutputs(`💻 ${command.join(' ')}\n`); const show = options.show ?? 'always'; const env = options.env ?? (options.modEnv ? { ...process.env, ...options.modEnv } : process.env); const tty = options.tty || (options.interact && options.interact.length > 0); // Coerce to `any` because `ShellOptions` contains custom properties // that don't exist in the underlying interfaces. We could either rebuild each options map, // or just pass through and let the underlying implemenation ignore what it doesn't know about. // We choose the lazy one. const spawnOptions = { ...options, env }; const child = tty ? process_1.Process.spawnTTY(command[0], command.slice(1), spawnOptions) : process_1.Process.spawn(command[0], command.slice(1), spawnOptions); // copy because we will be shifting it const remainingInteractions = [...(options.interact ?? [])]; return new Promise((resolve, reject) => { const stdout = new Array(); const stderr = new Array(); const lastLine = new LastLine(); child.onStdout(chunk => { if (show === 'always') { writeToOutputs(chunk.toString('utf-8')); } stdout.push(chunk); lastLine.append(chunk.toString('utf-8')); const interaction = remainingInteractions[0]; if (interaction) { if (interaction.prompt.test(lastLine.get())) { // subprocess expects a user input now. // first, shift the interactions to ensure the same interaction is not reused remainingInteractions.shift(); // then, reset the last line to prevent repeated matches caused by tty echoing lastLine.reset(); // now write the input with a slight delay to ensure // the child process has already started reading. const sendInput = () => { child.writeStdin(interaction.input + (interaction.end ?? os.EOL)); }; if (interaction.beforeInput) { void interaction.beforeInput() .catch((err) => { writeToOutputs(`\n[Prompt: ${interaction.prompt.toString()}] beforeInput hook failed!\n`); writeToOutputs(`${err}\n\n`); }) .finally(() => { setTimeout(sendInput, 500); }); } else { setTimeout(sendInput, 500); } } } }); if (tty && options.captureStderr === false) { // in a tty stderr goes to the same fd as stdout throw new Error('Cannot disable \'captureStderr\' in tty'); } if (!tty) { // in a tty stderr goes to the same fd as stdout, so onStdout // is sufficient. child.onStderr(chunk => { if (show === 'always') { writeToOutputs(chunk.toString('utf-8')); } if (options.captureStderr ?? true) { stderr.push(chunk); } }); } child.onError(reject); child.onExit(code => { const stderrOutput = Buffer.concat(stderr).toString('utf-8'); const stdoutOutput = Buffer.concat(stdout).toString('utf-8'); const out = (options.onlyStderr ? stderrOutput : stdoutOutput + stderrOutput).trim(); const logAndReject = (error) => { if (show === 'error') { writeToOutputs(`${out}\n`); } reject(error); }; if (remainingInteractions.length !== 0) { // regardless of the exit code, if we didn't consume all expected interactions we probably // did something wrong. logAndReject(new Error(`Expected more user interactions but subprocess exited with ${code}`)); return; } if (code === 0 || options.allowErrExit) { resolve(out); } else { logAndReject(new Error(`'${command.join(' ')}' exited with error code ${code}.`)); } }); }); } class ShellHelper { _cwd; _output; static fromContext(context) { return new ShellHelper(context.integTestDir, context.output); } constructor(_cwd, _output) { this._cwd = _cwd; this._output = _output; } get dockerConfigDir() { return path.join(this._cwd, '.docker'); } async shell(command, options = {}) { return shell(command, { outputs: [this._output], cwd: this._cwd, ...options, modEnv: { // give every shell its own docker config directory // so that parallel runs don't interfere with each other. DOCKER_CONFIG: this.dockerConfigDir, ...options.modEnv, }, }); } } exports.ShellHelper = ShellHelper; /** * rm -rf reimplementation, don't want to depend on an NPM package for this * * Returns `true` if everything got deleted, or `false` if some files could * not be deleted due to permissions issues. */ function rimraf(fsPath) { try { let success = true; const isDir = fs.lstatSync(fsPath).isDirectory(); if (isDir) { for (const file of fs.readdirSync(fsPath)) { success &&= rimraf(path.join(fsPath, file)); } fs.rmdirSync(fsPath); } else { fs.unlinkSync(fsPath); } return success; } catch (e) { // Can happen if some files got generated inside a Docker container and are now inadvertently owned by `root`. // We can't ever clean those up anymore, but since it only happens inside GitHub Actions containers we also don't care too much. if (e.code === 'EACCES' || e.code === 'ENOTEMPTY') { return false; } // Already gone if (e.code === 'ENOENT') { return true; } throw e; } } function addToShellPath(x) { const parts = process.env.PATH?.split(':') ?? []; if (!parts.includes(x)) { parts.unshift(x); } process.env.PATH = parts.join(':'); } /** * Accumulate text since the last line break (or beginning of string) it has seen in the chunks. * * Examples: * * - Chunks: ['one\n', 'two\n', three'] * - Last Line: 'three' * * - Chunks: ['one', 'two', '\nthree'] * - Last Line: 'three' * * - Chunks: ['one', 'two'] * - Last Line: 'onetwo' * * - Chunks: ['one', 'two', '\nthree', 'four'] * - Last Line: 'threefour' */ class LastLine { lastLine = ''; append(chunk) { const lines = chunk.split(os.EOL); if (lines.length === 1) { // chunk doesn't contain a new line so just append this.lastLine += lines[0]; } else { // chunk contains multiple lines so just override with the last one this.lastLine = lines[lines.length - 1]; } } get() { return this.lastLine; } reset() { this.lastLine = ''; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hlbGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzaGVsbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFhQSxzQkEySEM7QUFpSkQsd0JBNEJDO0FBRUQsd0NBUUM7QUE5VEQseUJBQXlCO0FBQ3pCLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFFN0IsdUNBQW9DO0FBR3BDOzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUsS0FBSyxDQUFDLE9BQWlCLEVBQUUsVUFBd0IsRUFBRTtJQUN2RSxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBUyxFQUFFLEVBQUU7UUFDbkMsS0FBSyxNQUFNLFlBQVksSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNuQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLENBQUM7SUFDSCxDQUFDLENBQUM7SUFFRiw0QkFBNEI7SUFDNUIsY0FBYyxDQUFDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxRQUFRLENBQUM7SUFFdEMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEcsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcs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SSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDckIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBjaGlsZF9wcm9jZXNzIGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgVGVzdENvbnRleHQgfSBmcm9tICcuL2ludGVnLXRlc3QnO1xuaW1wb3J0IHsgUHJvY2VzcyB9IGZyb20gJy4vcHJvY2Vzcyc7XG5pbXBvcnQgdHlwZSB7IFRlbXBvcmFyeURpcmVjdG9yeUNvbnRleHQgfSBmcm9tICcuL3dpdGgtdGVtcG9yYXJ5LWRpcmVjdG9yeSc7XG5cbi8qKlxuICogQSBzaGVsbCBjb21tYW5kIHRoYXQgZG9lcyB3aGF0IHlvdSB3YW50XG4gKlxuICogSXMgcGxhdGZvcm0tYXdhcmUsIGhhbmRsZXMgZXJyb3JzIG5pY2VseS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNoZWxsKGNvbW1hbmQ6IHN0cmluZ1tdLCBvcHRpb25zOiBTaGVsbE9wdGlvbnMgPSB7fSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmIChvcHRpb25zLm1vZEVudiAmJiBvcHRpb25zLmVudikge1xuICAgIHRocm93IG5ldyBFcnJvcignVXNlIGVpdGhlciBlbnYgb3IgbW9kRW52IGJ1dCBub3QgYm90aCcpO1xuICB9XG5cbiAgY29uc3Qgb3V0cHV0cyA9IG5ldyBTZXQob3B0aW9ucy5vdXRwdXRzKTtcbiAgY29uc3Qgd3JpdGVUb091dHB1dHMgPSAoeDogc3RyaW5nKSA9PiB7XG4gICAgZm9yIChjb25zdCBvdXRwdXRTdHJlYW0gb2Ygb3V0cHV0cykge1xuICAgICAgb3V0cHV0U3RyZWFtLndyaXRlKHgpO1xuICAgIH1cbiAgfTtcblxuICAvLyBBbHdheXMgb3V0cHV0IHRoZSBjb21tYW5kXG4gIHdyaXRlVG9PdXRwdXRzKGDwn5K7ICR7Y29tbWFuZC5qb2luKCcgJyl9XFxuYCk7XG4gIGNvbnN0IHNob3cgPSBvcHRpb25zLnNob3cgPz8gJ2Fsd2F5cyc7XG5cbiAgY29uc3QgZW52ID0gb3B0aW9ucy5lbnYgPz8gKG9wdGlvbnMubW9kRW52ID8geyAuLi5wcm9jZXNzLmVudiwgLi4ub3B0aW9ucy5tb2RFbnYgfSA6IHByb2Nlc3MuZW52KTtcbiAgY29uc3QgdHR5ID0gb3B0aW9ucy50dHkgfHwgKG9wdGlvbnMuaW50ZXJhY3QgJiYgb3B0aW9ucy5pbnRlcmFjdC5sZW5ndGggPiAwKTtcblxuICAvLyBDb2VyY2UgdG8gYGFueWAgYmVjYXVzZSBgU2hlbGxPcHRpb25zYCBjb250YWlucyBjdXN0b20gcHJvcGVydGllc1xuICAvLyB0aGF0IGRvbid0IGV4aXN0IGluIHRoZSB1bmRlcmx5aW5nIGludGVyZmFjZXMuIFdlIGNvdWxkIGVpdGhlciByZWJ1aWxkIGVhY2ggb3B0aW9ucyBtYXAsXG4gIC8vIG9yIGp1c3QgcGFzcyB0aHJvdWdoIGFuZCBsZXQgdGhlIHVuZGVybHlpbmcgaW1wbGVtZW5hdGlvbiBpZ25vcmUgd2hhdCBpdCBkb2Vzbid0IGtub3cgYWJvdXQuXG4gIC8vIFdlIGNob29zZSB0aGUgbGF6eSBvbmUuXG4gIGNvbnN0IHNwYXduT3B0aW9ucyA9IHsgLi4ub3B0aW9ucywgZW52IH0gYXMgYW55O1xuXG4gIGNvbnN0IGNoaWxkID0gdHR5XG4gICAgPyBQcm9jZXNzLnNwYXduVFRZKGNvbW1hbmRbMF0sIGNvbW1hbmQuc2xpY2UoMSksIHNwYXduT3B0aW9ucylcbiAgICA6IFByb2Nlc3Muc3Bhd24oY29tbWFuZFswXSwgY29tbWFuZC5zbGljZSgxKSwgc3Bhd25PcHRpb25zKTtcblxuICAvLyBjb3B5IGJlY2F1c2Ugd2Ugd2lsbCBiZSBzaGlmdGluZyBpdFxuICBjb25zdCByZW1haW5pbmdJbnRlcmFjdGlvbnMgPSBbLi4uKG9wdGlvbnMuaW50ZXJhY3QgPz8gW10pXTtcblxuICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3Qgc3Rkb3V0ID0gbmV3IEFycmF5PEJ1ZmZlcj4oKTtcbiAgICBjb25zdCBzdGRlcnIgPSBuZXcgQXJyYXk8QnVmZmVyPigpO1xuXG4gICAgY29uc3QgbGFzdExpbmUgPSBuZXcgTGFzdExpbmUoKTtcblxuICAgIGNoaWxkLm9uU3Rkb3V0KGNodW5rID0+IHtcbiAgICAgIGlmIChzaG93ID09PSAnYWx3YXlzJykge1xuICAgICAgICB3cml0ZVRvT3V0cHV0cyhjaHVuay50b1N0cmluZygndXRmLTgnKSk7XG4gICAgICB9XG4gICAgICBzdGRvdXQucHVzaChjaHVuayk7XG4gICAgICBsYXN0TGluZS5hcHBlbmQoY2h1bmsudG9TdHJpbmcoJ3V0Zi04JykpO1xuXG4gICAgICBjb25zdCBpbnRlcmFjdGlvbiA9IHJlbWFpbmluZ0ludGVyYWN0aW9uc1swXTtcbiAgICAgIGlmIChpbnRlcmFjdGlvbikge1xuICAgICAgICBpZiAoaW50ZXJhY3Rpb24ucHJvbXB0LnRlc3QobGFzdExpbmUuZ2V0KCkpKSB7XG4gICAgICAgICAgLy8gc3VicHJvY2VzcyBleHBlY3RzIGEgdXNlciBpbnB1dCBub3cuXG4gICAgICAgICAgLy8gZmlyc3QsIHNoaWZ0IHRoZSBpbnRlcmFjdGlvbnMgdG8gZW5zdXJlIHRoZSBzYW1lIGludGVyYWN0aW9uIGlzIG5vdCByZXVzZWRcbiAgICAgICAgICByZW1haW5pbmdJbnRlcmFjdGlvbnMuc2hpZnQoKTtcblxuICAgICAgICAgIC8vIHRoZW4sIHJlc2V0IHRoZSBsYXN0IGxpbmUgdG8gcHJldmVudCByZXBlYXRlZCBtYXRjaGVzIGNhdXNlZCBieSB0dHkgZWNob2luZ1xuICAgICAgICAgIGxhc3RMaW5lLnJlc2V0KCk7XG5cbiAgICAgICAgICAvLyBub3cgd3JpdGUgdGhlIGlucHV0IHdpdGggYSBzbGlnaHQgZGVsYXkgdG8gZW5zdXJlXG4gICAgICAgICAgLy8gdGhlIGNoaWxkIHByb2Nlc3MgaGFzIGFscmVhZHkgc3RhcnRlZCByZWFkaW5nLlxuICAgICAgICAgIGNvbnN0IHNlbmRJbnB1dCA9ICgpID0+IHtcbiAgICAgICAgICAgIGNoaWxkLndyaXRlU3RkaW4oaW50ZXJhY3Rpb24uaW5wdXQgKyAoaW50ZXJhY3Rpb24uZW5kID8/IG9zLkVPTCkpO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBpZiAoaW50ZXJhY3Rpb24uYmVmb3JlSW5wdXQpIHtcbiAgICAgICAgICAgIHZvaWQgaW50ZXJhY3Rpb24uYmVmb3JlSW5wdXQoKVxuICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIHdyaXRlVG9PdXRwdXRzKGBcXG5bUHJvbXB0OiAke2ludGVyYWN0aW9uLnByb21wdC50b1N0cmluZygpfV0gYmVmb3JlSW5wdXQgaG9vayBmYWlsZWQhXFxuYCk7XG4gICAgICAgICAgICAgICAgd3JpdGVUb091dHB1dHMoYCR7ZXJyfVxcblxcbmApO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChzZW5kSW5wdXQsIDUwMCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KHNlbmRJbnB1dCwgNTAwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0dHkgJiYgb3B0aW9ucy5jYXB0dXJlU3RkZXJyID09PSBmYWxzZSkge1xuICAgICAgLy8gaW4gYSB0dHkgc3RkZXJyIGdvZXMgdG8gdGhlIHNhbWUgZmQgYXMgc3Rkb3V0XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkaXNhYmxlIFxcJ2NhcHR1cmVTdGRlcnJcXCcgaW4gdHR5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCF0dHkpIHtcbiAgICAgIC8vIGluIGEgdHR5IHN0ZGVyciBnb2VzIHRvIHRoZSBzYW1lIGZkIGFzIHN0ZG91dCwgc28gb25TdGRvdXRcbiAgICAgIC8vIGlzIHN1ZmZpY2llbnQuXG4gICAgICBjaGlsZC5vblN0ZGVycihjaHVuayA9PiB7XG4gICAgICAgIGlmIChzaG93ID09PSAnYWx3YXlzJykge1xuICAgICAgICAgIHdyaXRlVG9PdXRwdXRzKGNodW5rLnRvU3RyaW5nKCd1dGYtOCcpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5jYXB0dXJlU3RkZXJyID8/IHRydWUpIHtcbiAgICAgICAgICBzdGRlcnIucHVzaChjaHVuayk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNoaWxkLm9uRXJyb3IocmVqZWN0KTtcblxuICAgIGNoaWxkLm9uRXhpdChjb2RlID0+IHtcbiAgICAgIGNvbnN0IHN0ZGVyck91dHB1dCA9IEJ1ZmZlci5jb25jYXQoc3RkZXJyKS50b1N0cmluZygndXRmLTgnKTtcbiAgICAgIGNvbnN0IHN0ZG91dE91dHB1dCA9IEJ1ZmZlci5jb25jYXQoc3Rkb3V0KS50b1N0cmluZygndXRmLTgnKTtcbiAgICAgIGNvbnN0IG91dCA9IChvcHRpb25zLm9ubHlTdGRlcnIgPyBzdGRlcnJPdXRwdXQgOiBzdGRvdXRPdXRwdXQgKyBzdGRlcnJPdXRwdXQpLnRyaW0oKTtcblxuICAgICAgY29uc3QgbG9nQW5kUmVqZWN0ID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICBpZiAoc2hvdyA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgIHdyaXRlVG9PdXRwdXRzKGAke291dH1cXG5gKTtcbiAgICAgICAgfVxuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfTtcblxuICAgICAgaWYgKHJlbWFpbmluZ0ludGVyYWN0aW9ucy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgLy8gcmVnYXJkbGVzcyBvZiB0aGUgZXhpdCBjb2RlLCBpZiB3ZSBkaWRuJ3QgY29uc3VtZSBhbGwgZXhwZWN0ZWQgaW50ZXJhY3Rpb25zIHdlIHByb2JhYmx5XG4gICAgICAgIC8vIGRpZCBzb21ldGhpbmcgd3JvbmcuXG4gICAgICAgIGxvZ0FuZFJlamVjdChuZXcgRXJyb3IoYEV4cGVjdGVkIG1vcmUgdXNlciBpbnRlcmFjdGlvbnMgYnV0IHN1YnByb2Nlc3MgZXhpdGVkIHdpdGggJHtjb2RlfWApKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoY29kZSA9PT0gMCB8fCBvcHRpb25zLmFsbG93RXJyRXhpdCkge1xuICAgICAgICByZXNvbHZlKG91dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dBbmRSZWplY3QobmV3IEVycm9yKGAnJHtjb21tYW5kLmpvaW4oJyAnKX0nIGV4aXRlZCB3aXRoIGVycm9yIGNvZGUgJHtjb2RlfS5gKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIE1vZGVscyBhIHNpbmdsZSB1c2VyIGludGVyYWN0aW9uIHdpdGggdGhlIHNoZWxsLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFVzZXJJbnRlcmFjdGlvbiB7XG4gIC8qKlxuICAgKiBUaGUgcHJvbXB0IHRvIGV4cGVjdC4gUmVnZXggbWF0Y2hlZCBhZ2FpbnN0IHRoZSBsYXN0IGxpbmUgaW5cbiAgICogdGhlIG91dHB1dCBiZWZvcmUgdGhlIHByb21wdCBpcyBkaXNwbGF5ZWQuXG4gICAqXG4gICAqIE1vc3QgY29tbW9ubHkgdGhpcyB3b3VsZCBiZSBhIHNpbXBsZSBzdHJpbmcgdG8gbWF0Y2ggZm9yIGluY2x1c2lvbi5cbiAgICpcbiAgICogRXhhbXBsZXM6XG4gICAqXG4gICAqIC0gUHJvY2VzcyBPdXRwdXQ6IFwiSGV5IHRoZXJlISBBcmUgeW91IHN1cmU/XCJcbiAgICogICBQcm9tcHQ6IC9BcmUgeW91IHN1cmU/L1xuICAgKiAgIE1hdGNoIChZZXMvTm8pOiBZZXNcbiAgICogICBSZWFzb246IFwiSGV5IHRoZXJlISBBcmUgeW91IHN1cmU/XCIgfiAvQXJlIHlvdSBzdXJlPy9cbiAgICpcbiAgICogLSBQcm9jZXNzIE91dHB1dDogXCJIZXkgdGhlcmUhXFxuQXJlIHlvdSBzdXJlP1wiXG4gICAqICAgUHJvbXB0OiAvQXJlIHlvdSBzdXJlPy9cbiAgICogICBNYXRjaCAoWWVzL05vKTogWWVzXG4gICAqICAgUmVhc29uOiBcIkFyZSB5b3Ugc3VyZT9cIiB+IC9BcmUgeW91IHN1cmU/L1xuICAgKlxuICAgKiAtIFByb2Nlc3MgT3V0cHV0OiBcIkFyZSB5b3Ugc3VyZT9cXG4ocmVtZW1iZXIgdGhpcyBpcyBkZXN0cnVjdGl2ZSlcIlxuICAgKiAgIFByb21wdDogL0FyZSB5b3Ugc3VyZT8vXG4gICAqICAgTWF0Y2ggKFllcy9Obyk6IE5vXG4gICAqICAgUmVhc29uOiBcIihyZW1lbWJlciB0aGlzIGlzIGRlc3RydWN0aXZlKVwiIOKJhCAvQXJlIHlvdSBzdXJlPy9cbiAgICpcbiAgICogLSBQcm9jZXNzIE91dHB1dDogXCJBcmUgeW91IHN1cmU/XFxuKHJlbWVtYmVyIHRoaXMgaXMgZGVzdHJ1Y3RpdmUpXCJcbiAgICogICBQcm9tcHQ6IC9yZW1lbWJlciB0aGlzIGlzIGRlc3RydWN0aXZlL1xuICAgKiAgIE1hdGNoIChZZXMvTm8pOiBZZXNcbiAgICogICBSZWFzb246IFwiKHJlbWVtYmVyIHRoaXMgaXMgZGVzdHJ1Y3RpdmUpXCIgfiAvcmVtZW1iZXIgdGhpcyBpcyBkZXN0cnVjdGl2ZS9cbiAgICpcbiAgICovXG4gIHJlYWRvbmx5IHByb21wdDogUmVnRXhwO1xuICAvKipcbiAgICogVGhlIGlucHV0IHRvIHByb3ZpZGUuXG4gICAqL1xuICByZWFkb25seSBpbnB1dDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc3RyaW5nIHRvIHNpZ25hbCB0aGUgZW5kIG9mIGlucHV0LlxuICAgKlxuICAgKiBAZGVmYXVsdCBvcy5FT0xcbiAgICovXG4gIHJlYWRvbmx5IGVuZD86IHN0cmluZztcblxuICAvKipcbiAgICogQW4gYXN5bmMgY2FsbGJhY2sgdG8gcnVuIGFmdGVyIHRoZSBwcm9tcHQgaXMgbWF0Y2hlZCBidXQgYmVmb3JlIHRoZSBpbnB1dCBpcyBzZW50LlxuICAgKiBVc2VmdWwgZm9yIHZlcmlmeWluZyBleHRlcm5hbCBzdGF0ZSB3aGlsZSB0aGUgcHJvY2VzcyBpcyBwYXVzZWQgYXQgYSBwcm9tcHQuXG4gICAqL1xuICByZWFkb25seSBiZWZvcmVJbnB1dD86ICgpID0+IFByb21pc2U8dm9pZD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2hlbGxPcHRpb25zIGV4dGVuZHMgY2hpbGRfcHJvY2Vzcy5TcGF3bk9wdGlvbnMge1xuICAvKipcbiAgICogUHJvcGVydGllcyB0byBhZGQgdG8gJ2VudidcbiAgICovXG4gIHJlYWRvbmx5IG1vZEVudj86IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD47XG5cbiAgLyoqXG4gICAqIERvbid0IGZhaWwgd2hlbiBleGl0aW5nIHdpdGggYW4gZXJyb3JcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGFsbG93RXJyRXhpdD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gY2FwdHVyZSBzdGRlcnJcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2FwdHVyZVN0ZGVycj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFBhc3Mgb3V0cHV0IGhlcmVcbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dHM/OiBOb2RlSlMuV3JpdGFibGVTdHJlYW1bXTtcblxuICAvKipcbiAgICogT25seSByZXR1cm4gc3RkZXJyLiBGb3IgZXhhbXBsZSwgdGhpcyBpcyB1c2VkIHRvIHZhbGlkYXRlXG4gICAqIHRoYXQgd2hlbiBDST10cnVlLCBhbGwgbG9ncyBhcmUgc2VudCB0byBzdGRvdXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBvbmx5U3RkZXJyPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRG9uJ3QgbG9nIHRvIHN0ZG91dFxuICAgKlxuICAgKiBAZGVmYXVsdCBhbHdheXNcbiAgICovXG4gIHJlYWRvbmx5IHNob3c/OiAnYWx3YXlzJyB8ICduZXZlcicgfCAnZXJyb3InO1xuXG4gIC8qKlxuICAgKiBQcm92aWRlIHVzZXIgaW50ZXJhY3Rpb24gdG8gcmVzcG9uZCB0byBzaGVsbCBwcm9tcHRzLlxuICAgKlxuICAgKiBPcmRlciBhbmQgY291bnQgc2hvdWxkIGNvcnJlc3BvbmQgdG8gdGhlIGV4cGVjdGVkIHByb21wdHMgaXNzdWVkIGJ5IHRoZSBzdWJwcm9jZXNzLlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJhY3Q/OiBVc2VySW50ZXJhY3Rpb25bXTtcblxuICAvKipcbiAgICogRm9yY2UgYSBUVFksIGV2ZW4gaWYgdGhlcmUgYXJlIG5vIGludGVyYWN0aW9uc1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgdHR5PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIFNoZWxsSGVscGVyIHtcbiAgcHVibGljIHN0YXRpYyBmcm9tQ29udGV4dChjb250ZXh0OiBUZXN0Q29udGV4dCAmIFRlbXBvcmFyeURpcmVjdG9yeUNvbnRleHQpIHtcbiAgICByZXR1cm4gbmV3IFNoZWxsSGVscGVyKGNvbnRleHQuaW50ZWdUZXN0RGlyLCBjb250ZXh0Lm91dHB1dCk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jd2Q6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9vdXRwdXQ6IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSkge1xuICB9XG5cbiAgcHVibGljIGdldCBkb2NrZXJDb25maWdEaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLl9jd2QsICcuZG9ja2VyJyk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgc2hlbGwoY29tbWFuZDogc3RyaW5nW10sIG9wdGlvbnM6IE9taXQ8U2hlbGxPcHRpb25zLCAnY3dkJyB8ICdvdXRwdXRzJz4gPSB7fSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHNoZWxsKGNvbW1hbmQsIHtcbiAgICAgIG91dHB1dHM6IFt0aGlzLl9vdXRwdXRdLFxuICAgICAgY3dkOiB0aGlzLl9jd2QsXG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgbW9kRW52OiB7XG4gICAgICAgIC8vIGdpdmUgZXZlcnkgc2hlbGwgaXRzIG93biBkb2NrZXIgY29uZmlnIGRpcmVjdG9yeVxuICAgICAgICAvLyBzbyB0aGF0IHBhcmFsbGVsIHJ1bnMgZG9uJ3QgaW50ZXJmZXJlIHdpdGggZWFjaCBvdGhlci5cbiAgICAgICAgRE9DS0VSX0NPTkZJRzogdGhpcy5kb2NrZXJDb25maWdEaXIsXG4gICAgICAgIC4uLm9wdGlvbnMubW9kRW52LFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIHJtIC1yZiByZWltcGxlbWVudGF0aW9uLCBkb24ndCB3YW50IHRvIGRlcGVuZCBvbiBhbiBOUE0gcGFja2FnZSBmb3IgdGhpc1xuICpcbiAqIFJldHVybnMgYHRydWVgIGlmIGV2ZXJ5dGhpbmcgZ290IGRlbGV0ZWQsIG9yIGBmYWxzZWAgaWYgc29tZSBmaWxlcyBjb3VsZFxuICogbm90IGJlIGRlbGV0ZWQgZHVlIHRvIHBlcm1pc3Npb25zIGlzc3Vlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJpbXJhZihmc1BhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIGxldCBzdWNjZXNzID0gdHJ1ZTtcbiAgICBjb25zdCBpc0RpciA9IGZzLmxzdGF0U3luYyhmc1BhdGgpLmlzRGlyZWN0b3J5KCk7XG5cbiAgICBpZiAoaXNEaXIpIHtcbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmcy5yZWFkZGlyU3luYyhmc1BhdGgpKSB7XG4gICAgICAgIHN1Y2Nlc3MgJiY9IHJpbXJhZihwYXRoLmpvaW4oZnNQYXRoLCBmaWxlKSk7XG4gICAgICB9XG4gICAgICBmcy5ybWRpclN5bmMoZnNQYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZnMudW5saW5rU3luYyhmc1BhdGgpO1xuICAgIH1cbiAgICByZXR1cm4gc3VjY2VzcztcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgLy8gQ2FuIGhhcHBlbiBpZiBzb21lIGZpbGVzIGdvdCBnZW5lcmF0ZWQgaW5zaWRlIGEgRG9ja2VyIGNvbnRhaW5lciBhbmQgYXJlIG5vdyBpbmFkdmVydGVudGx5IG93bmVkIGJ5IGByb290YC5cbiAgICAvLyBXZSBjYW4ndCBldmVyIGNsZWFuIHRob3NlIHVwIGFueW1vcmUsIGJ1dCBzaW5jZSBpdCBvbmx5IGhhcHBlbnMgaW5zaWRlIEdpdEh1YiBBY3Rpb25zIGNvbnRhaW5lcnMgd2UgYWxzbyBkb24ndCBjYXJlIHRvbyBtdWNoLlxuICAgIGlmIChlLmNvZGUgPT09ICdFQUNDRVMnIHx8IGUuY29kZSA9PT0gJ0VOT1RFTVBUWScpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBBbHJlYWR5IGdvbmVcbiAgICBpZiAoZS5jb2RlID09PSAnRU5PRU5UJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYWRkVG9TaGVsbFBhdGgoeDogc3RyaW5nKSB7XG4gIGNvbnN0IHBhcnRzID0gcHJvY2Vzcy5lbnYuUEFUSD8uc3BsaXQoJzonKSA/PyBbXTtcblxuICBpZiAoIXBhcnRzLmluY2x1ZGVzKHgpKSB7XG4gICAgcGFydHMudW5zaGlmdCh4KTtcbiAgfVxuXG4gIHByb2Nlc3MuZW52LlBBVEggPSBwYXJ0cy5qb2luKCc6Jyk7XG59XG5cbi8qKlxuICogQWNjdW11bGF0ZSB0ZXh0IHNpbmNlIHRoZSBsYXN0IGxpbmUgYnJlYWsgKG9yIGJlZ2lubmluZyBvZiBzdHJpbmcpIGl0IGhhcyBzZWVuIGluIHRoZSBjaHVua3MuXG4gKlxuICogRXhhbXBsZXM6XG4gKlxuICogLSBDaHVua3M6IFsnb25lXFxuJywgJ3R3b1xcbicsIHRocmVlJ11cbiAqIC0gTGFzdCBMaW5lOiAndGhyZWUnXG4gKlxuICogLSBDaHVua3M6IFsnb25lJywgJ3R3bycsICdcXG50aHJlZSddXG4gKiAtIExhc3QgTGluZTogJ3RocmVlJ1xuICpcbiAqIC0gQ2h1bmtzOiBbJ29uZScsICd0d28nXVxuICogLSBMYXN0IExpbmU6ICdvbmV0d28nXG4gKlxuICogLSBDaHVua3M6IFsnb25lJywgJ3R3bycsICdcXG50aHJlZScsICdmb3VyJ11cbiAqIC0gTGFzdCBMaW5lOiAndGhyZWVmb3VyJ1xuICovXG5jbGFzcyBMYXN0TGluZSB7XG4gIHByaXZhdGUgbGFzdExpbmU6IHN0cmluZyA9ICcnO1xuXG4gIHB1YmxpYyBhcHBlbmQoY2h1bms6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGxpbmVzID0gY2h1bmsuc3BsaXQob3MuRU9MKTtcbiAgICBpZiAobGluZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAvLyBjaHVuayBkb2Vzbid0IGNvbnRhaW4gYSBuZXcgbGluZSBzbyBqdXN0IGFwcGVuZFxuICAgICAgdGhpcy5sYXN0TGluZSArPSBsaW5lc1swXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gY2h1bmsgY29udGFpbnMgbXVsdGlwbGUgbGluZXMgc28ganVzdCBvdmVycmlkZSB3aXRoIHRoZSBsYXN0IG9uZVxuICAgICAgdGhpcy5sYXN0TGluZSA9IGxpbmVzW2xpbmVzLmxlbmd0aCAtIDFdO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5sYXN0TGluZTtcbiAgfVxuXG4gIHB1YmxpYyByZXNldCgpIHtcbiAgICB0aGlzLmxhc3RMaW5lID0gJyc7XG4gIH1cbn1cbiJdfQ==