@aws-cdk-testing/cli-integ
Version:
Integration tests for the AWS CDK CLI
215 lines • 28.6 kB
JavaScript
;
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.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.
setTimeout(() => {
child.writeStdin(interaction.input + (interaction.end ?? os.EOL));
}, 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 somethiing 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hlbGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzaGVsbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFhQSxzQkE4R0M7QUFxSUQsd0JBNEJDO0FBRUQsd0NBUUM7QUFyU0QseUJBQXlCO0FBQ3pCLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFFN0IsdUNBQW9DO0FBR3BDOzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUsS0FBSyxDQUFDLE9BQWlCLEVBQUUsVUFBd0IsRUFBRTtJQUN2RSxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBUyxFQUFFLEVBQUU7UUFDbkMsS0FBSyxNQUFNLFlBQVksSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNuQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLENBQUM7SUFDSCxDQUFDLENBQUM7SUFFRiw0QkFBNEI7SUFDNUIsY0FBYyxDQUFDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxRQUFRLENBQUM7SUFFdEMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEcsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLFFBQVEs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R0FBRyxDQUFDLENBQUM7QUFDckMsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxRQUFRO0lBQ0osUUFBUSxHQUFXLEVBQUUsQ0FBQztJQUV2QixNQUFNLENBQUMsS0FBYTtRQUN6QixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNsQyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdkIsa0RBQWtEO1lBQ2xELElBQUksQ0FBQyxRQUFRLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzVCLENBQUM7YUFBTSxDQUFDO1lBQ04sbUVBQW1FO1lBQ25FLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDMUMsQ0FBQztJQUNILENBQUM7SUFFTSxHQUFHO1FBQ1IsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFTSxLQUFLO1FBQ1YsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDckIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBjaGlsZF9wcm9jZXNzIGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgVGVzdENvbnRleHQgfSBmcm9tICcuL2ludGVnLXRlc3QnO1xuaW1wb3J0IHsgUHJvY2VzcyB9IGZyb20gJy4vcHJvY2Vzcyc7XG5pbXBvcnQgdHlwZSB7IFRlbXBvcmFyeURpcmVjdG9yeUNvbnRleHQgfSBmcm9tICcuL3dpdGgtdGVtcG9yYXJ5LWRpcmVjdG9yeSc7XG5cbi8qKlxuICogQSBzaGVsbCBjb21tYW5kIHRoYXQgZG9lcyB3aGF0IHlvdSB3YW50XG4gKlxuICogSXMgcGxhdGZvcm0tYXdhcmUsIGhhbmRsZXMgZXJyb3JzIG5pY2VseS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNoZWxsKGNvbW1hbmQ6IHN0cmluZ1tdLCBvcHRpb25zOiBTaGVsbE9wdGlvbnMgPSB7fSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmIChvcHRpb25zLm1vZEVudiAmJiBvcHRpb25zLmVudikge1xuICAgIHRocm93IG5ldyBFcnJvcignVXNlIGVpdGhlciBlbnYgb3IgbW9kRW52IGJ1dCBub3QgYm90aCcpO1xuICB9XG5cbiAgY29uc3Qgb3V0cHV0cyA9IG5ldyBTZXQob3B0aW9ucy5vdXRwdXRzKTtcbiAgY29uc3Qgd3JpdGVUb091dHB1dHMgPSAoeDogc3RyaW5nKSA9PiB7XG4gICAgZm9yIChjb25zdCBvdXRwdXRTdHJlYW0gb2Ygb3V0cHV0cykge1xuICAgICAgb3V0cHV0U3RyZWFtLndyaXRlKHgpO1xuICAgIH1cbiAgfTtcblxuICAvLyBBbHdheXMgb3V0cHV0IHRoZSBjb21tYW5kXG4gIHdyaXRlVG9PdXRwdXRzKGDwn5K7ICR7Y29tbWFuZC5qb2luKCcgJyl9XFxuYCk7XG4gIGNvbnN0IHNob3cgPSBvcHRpb25zLnNob3cgPz8gJ2Fsd2F5cyc7XG5cbiAgY29uc3QgZW52ID0gb3B0aW9ucy5lbnYgPz8gKG9wdGlvbnMubW9kRW52ID8geyAuLi5wcm9jZXNzLmVudiwgLi4ub3B0aW9ucy5tb2RFbnYgfSA6IHByb2Nlc3MuZW52KTtcbiAgY29uc3QgdHR5ID0gb3B0aW9ucy5pbnRlcmFjdCAmJiBvcHRpb25zLmludGVyYWN0Lmxlbmd0aCA+IDA7XG5cbiAgLy8gQ29lcmNlIHRvIGBhbnlgIGJlY2F1c2UgYFNoZWxsT3B0aW9uc2AgY29udGFpbnMgY3VzdG9tIHByb3BlcnRpZXNcbiAgLy8gdGhhdCBkb24ndCBleGlzdCBpbiB0aGUgdW5kZXJseWluZyBpbnRlcmZhY2VzLiBXZSBjb3VsZCBlaXRoZXIgcmVidWlsZCBlYWNoIG9wdGlvbnMgbWFwLFxuICAvLyBvciBqdXN0IHBhc3MgdGhyb3VnaCBhbmQgbGV0IHRoZSB1bmRlcmx5aW5nIGltcGxlbWVuYXRpb24gaWdub3JlIHdoYXQgaXQgZG9lc24ndCBrbm93IGFib3V0LlxuICAvLyBXZSBjaG9vc2UgdGhlIGxhenkgb25lLlxuICBjb25zdCBzcGF3bk9wdGlvbnMgPSB7IC4uLm9wdGlvbnMsIGVudiB9IGFzIGFueTtcblxuICBjb25zdCBjaGlsZCA9IHR0eVxuICAgID8gUHJvY2Vzcy5zcGF3blRUWShjb21tYW5kWzBdLCBjb21tYW5kLnNsaWNlKDEpLCBzcGF3bk9wdGlvbnMpXG4gICAgOiBQcm9jZXNzLnNwYXduKGNvbW1hbmRbMF0sIGNvbW1hbmQuc2xpY2UoMSksIHNwYXduT3B0aW9ucyk7XG5cbiAgLy8gY29weSBiZWNhdXNlIHdlIHdpbGwgYmUgc2hpZnRpbmcgaXRcbiAgY29uc3QgcmVtYWluaW5nSW50ZXJhY3Rpb25zID0gWy4uLihvcHRpb25zLmludGVyYWN0ID8/IFtdKV07XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlPHN0cmluZz4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IHN0ZG91dCA9IG5ldyBBcnJheTxCdWZmZXI+KCk7XG4gICAgY29uc3Qgc3RkZXJyID0gbmV3IEFycmF5PEJ1ZmZlcj4oKTtcblxuICAgIGNvbnN0IGxhc3RMaW5lID0gbmV3IExhc3RMaW5lKCk7XG5cbiAgICBjaGlsZC5vblN0ZG91dChjaHVuayA9PiB7XG4gICAgICBpZiAoc2hvdyA9PT0gJ2Fsd2F5cycpIHtcbiAgICAgICAgd3JpdGVUb091dHB1dHMoY2h1bmsudG9TdHJpbmcoJ3V0Zi04JykpO1xuICAgICAgfVxuICAgICAgc3Rkb3V0LnB1c2goY2h1bmspO1xuICAgICAgbGFzdExpbmUuYXBwZW5kKGNodW5rLnRvU3RyaW5nKCd1dGYtOCcpKTtcblxuICAgICAgY29uc3QgaW50ZXJhY3Rpb24gPSByZW1haW5pbmdJbnRlcmFjdGlvbnNbMF07XG4gICAgICBpZiAoaW50ZXJhY3Rpb24pIHtcbiAgICAgICAgaWYgKGludGVyYWN0aW9uLnByb21wdC50ZXN0KGxhc3RMaW5lLmdldCgpKSkge1xuICAgICAgICAgIC8vIHN1YnByb2Nlc3MgZXhwZWN0cyBhIHVzZXIgaW5wdXQgbm93LlxuICAgICAgICAgIC8vIGZpcnN0LCBzaGlmdCB0aGUgaW50ZXJhY3Rpb25zIHRvIGVuc3VyZSB0aGUgc2FtZSBpbnRlcmFjdGlvbiBpcyBub3QgcmV1c2VkXG4gICAgICAgICAgcmVtYWluaW5nSW50ZXJhY3Rpb25zLnNoaWZ0KCk7XG5cbiAgICAgICAgICAvLyB0aGVuLCByZXNldCB0aGUgbGFzdCBsaW5lIHRvIHByZXZlbnQgcmVwZWF0ZWQgbWF0Y2hlcyBjYXVzZWQgYnkgdHR5IGVjaG9pbmdcbiAgICAgICAgICBsYXN0TGluZS5yZXNldCgpO1xuXG4gICAgICAgICAgLy8gbm93IHdyaXRlIHRoZSBpbnB1dCB3aXRoIGEgc2xpZ2h0IGRlbGF5IHRvIGVuc3VyZVxuICAgICAgICAgIC8vIHRoZSBjaGlsZCBwcm9jZXNzIGhhcyBhbHJlYWR5IHN0YXJ0ZWQgcmVhZGluZy5cbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGNoaWxkLndyaXRlU3RkaW4oaW50ZXJhY3Rpb24uaW5wdXQgKyAoaW50ZXJhY3Rpb24uZW5kID8/IG9zLkVPTCkpO1xuICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0dHkgJiYgb3B0aW9ucy5jYXB0dXJlU3RkZXJyID09PSBmYWxzZSkge1xuICAgICAgLy8gaW4gYSB0dHkgc3RkZXJyIGdvZXMgdG8gdGhlIHNhbWUgZmQgYXMgc3Rkb3V0XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkaXNhYmxlIFxcJ2NhcHR1cmVTdGRlcnJcXCcgaW4gdHR5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCF0dHkpIHtcbiAgICAgIC8vIGluIGEgdHR5IHN0ZGVyciBnb2VzIHRvIHRoZSBzYW1lIGZkIGFzIHN0ZG91dCwgc28gb25TdGRvdXRcbiAgICAgIC8vIGlzIHN1ZmZpY2llbnQuXG4gICAgICBjaGlsZC5vblN0ZGVycihjaHVuayA9PiB7XG4gICAgICAgIGlmIChzaG93ID09PSAnYWx3YXlzJykge1xuICAgICAgICAgIHdyaXRlVG9PdXRwdXRzKGNodW5rLnRvU3RyaW5nKCd1dGYtOCcpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5jYXB0dXJlU3RkZXJyID8/IHRydWUpIHtcbiAgICAgICAgICBzdGRlcnIucHVzaChjaHVuayk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNoaWxkLm9uRXJyb3IocmVqZWN0KTtcblxuICAgIGNoaWxkLm9uRXhpdChjb2RlID0+IHtcbiAgICAgIGNvbnN0IHN0ZGVyck91dHB1dCA9IEJ1ZmZlci5jb25jYXQoc3RkZXJyKS50b1N0cmluZygndXRmLTgnKTtcbiAgICAgIGNvbnN0IHN0ZG91dE91dHB1dCA9IEJ1ZmZlci5jb25jYXQoc3Rkb3V0KS50b1N0cmluZygndXRmLTgnKTtcbiAgICAgIGNvbnN0IG91dCA9IChvcHRpb25zLm9ubHlTdGRlcnIgPyBzdGRlcnJPdXRwdXQgOiBzdGRvdXRPdXRwdXQgKyBzdGRlcnJPdXRwdXQpLnRyaW0oKTtcblxuICAgICAgY29uc3QgbG9nQW5kcmVqZWN0ID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICBpZiAoc2hvdyA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgIHdyaXRlVG9PdXRwdXRzKGAke291dH1cXG5gKTtcbiAgICAgICAgfVxuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfTtcblxuICAgICAgaWYgKHJlbWFpbmluZ0ludGVyYWN0aW9ucy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgLy8gcmVnYXJkbGVzcyBvZiB0aGUgZXhpdCBjb2RlLCBpZiB3ZSBkaWRuJ3QgY29uc3VtZSBhbGwgZXhwZWN0ZWQgaW50ZXJhY3Rpb25zIHdlIHByb2JhYmx5XG4gICAgICAgIC8vIGRpZCBzb21ldGhpaW5nIHdyb25nLlxuICAgICAgICBsb2dBbmRyZWplY3QobmV3IEVycm9yKGBFeHBlY3RlZCBtb3JlIHVzZXIgaW50ZXJhY3Rpb25zIGJ1dCBzdWJwcm9jZXNzIGV4aXRlZCB3aXRoICR7Y29kZX1gKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGNvZGUgPT09IDAgfHwgb3B0aW9ucy5hbGxvd0VyckV4aXQpIHtcbiAgICAgICAgcmVzb2x2ZShvdXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nQW5kcmVqZWN0KG5ldyBFcnJvcihgJyR7Y29tbWFuZC5qb2luKCcgJyl9JyBleGl0ZWQgd2l0aCBlcnJvciBjb2RlICR7Y29kZX0uYCkpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBNb2RlbHMgYSBzaW5nbGUgdXNlciBpbnRlcmFjdGlvbiB3aXRoIHRoZSBzaGVsbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVc2VySW50ZXJhY3Rpb24ge1xuICAvKipcbiAgICogVGhlIHByb21wdCB0byBleHBlY3QuIFJlZ2V4IG1hdGNoZWQgYWdhaW5zdCB0aGUgbGFzdCBsaW5lIGluXG4gICAqIHRoZSBvdXRwdXQgYmVmb3JlIHRoZSBwcm9tcHQgaXMgZGlzcGxheWVkLlxuICAgKlxuICAgKiBNb3N0IGNvbW1vbmx5IHRoaXMgd291bGQgYmUgYSBzaW1wbGUgc3RyaW5nIHRvIG1hdGNoIGZvciBpbmNsdXNpb24uXG4gICAqXG4gICAqIEV4YW1wbGVzOlxuICAgKlxuICAgKiAtIFByb2Nlc3MgT3V0cHV0OiBcIkhleSB0aGVyZSEgQXJlIHlvdSBzdXJlP1wiXG4gICAqICAgUHJvbXB0OiAvQXJlIHlvdSBzdXJlPy9cbiAgICogICBNYXRjaCAoWWVzL05vKTogWWVzXG4gICAqICAgUmVhc29uOiBcIkhleSB0aGVyZSEgQXJlIHlvdSBzdXJlP1wiIH4gL0FyZSB5b3Ugc3VyZT8vXG4gICAqXG4gICAqIC0gUHJvY2VzcyBPdXRwdXQ6IFwiSGV5IHRoZXJlIVxcbkFyZSB5b3Ugc3VyZT9cIlxuICAgKiAgIFByb21wdDogL0FyZSB5b3Ugc3VyZT8vXG4gICAqICAgTWF0Y2ggKFllcy9Obyk6IFllc1xuICAgKiAgIFJlYXNvbjogXCJBcmUgeW91IHN1cmU/XCIgfiAvQXJlIHlvdSBzdXJlPy9cbiAgICpcbiAgICogLSBQcm9jZXNzIE91dHB1dDogXCJBcmUgeW91IHN1cmU/XFxuKHJlbWVtYmVyIHRoaXMgaXMgZGVzdHJ1Y3RpdmUpXCJcbiAgICogICBQcm9tcHQ6IC9BcmUgeW91IHN1cmU/L1xuICAgKiAgIE1hdGNoIChZZXMvTm8pOiBOb1xuICAgKiAgIFJlYXNvbjogXCIocmVtZW1iZXIgdGhpcyBpcyBkZXN0cnVjdGl2ZSlcIiDiiYQgL0FyZSB5b3Ugc3VyZT8vXG4gICAqXG4gICAqIC0gUHJvY2VzcyBPdXRwdXQ6IFwiQXJlIHlvdSBzdXJlP1xcbihyZW1lbWJlciB0aGlzIGlzIGRlc3RydWN0aXZlKVwiXG4gICAqICAgUHJvbXB0OiAvcmVtZW1iZXIgdGhpcyBpcyBkZXN0cnVjdGl2ZS9cbiAgICogICBNYXRjaCAoWWVzL05vKTogWWVzXG4gICAqICAgUmVhc29uOiBcIihyZW1lbWJlciB0aGlzIGlzIGRlc3RydWN0aXZlKVwiIH4gL3JlbWVtYmVyIHRoaXMgaXMgZGVzdHJ1Y3RpdmUvXG4gICAqXG4gICAqL1xuICByZWFkb25seSBwcm9tcHQ6IFJlZ0V4cDtcbiAgLyoqXG4gICAqIFRoZSBpbnB1dCB0byBwcm92aWRlLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5wdXQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHN0cmluZyB0byBzaWduYWwgdGhlIGVuZCBvZiBpbnB1dC5cbiAgICpcbiAgICogQGRlZmF1bHQgb3MuRU9MXG4gICAqL1xuICByZWFkb25seSBlbmQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2hlbGxPcHRpb25zIGV4dGVuZHMgY2hpbGRfcHJvY2Vzcy5TcGF3bk9wdGlvbnMge1xuICAvKipcbiAgICogUHJvcGVydGllcyB0byBhZGQgdG8gJ2VudidcbiAgICovXG4gIHJlYWRvbmx5IG1vZEVudj86IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD47XG5cbiAgLyoqXG4gICAqIERvbid0IGZhaWwgd2hlbiBleGl0aW5nIHdpdGggYW4gZXJyb3JcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGFsbG93RXJyRXhpdD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gY2FwdHVyZSBzdGRlcnJcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2FwdHVyZVN0ZGVycj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFBhc3Mgb3V0cHV0IGhlcmVcbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dHM/OiBOb2RlSlMuV3JpdGFibGVTdHJlYW1bXTtcblxuICAvKipcbiAgICogT25seSByZXR1cm4gc3RkZXJyLiBGb3IgZXhhbXBsZSwgdGhpcyBpcyB1c2VkIHRvIHZhbGlkYXRlXG4gICAqIHRoYXQgd2hlbiBDST10cnVlLCBhbGwgbG9ncyBhcmUgc2VudCB0byBzdGRvdXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBvbmx5U3RkZXJyPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRG9uJ3QgbG9nIHRvIHN0ZG91dFxuICAgKlxuICAgKiBAZGVmYXVsdCBhbHdheXNcbiAgICovXG4gIHJlYWRvbmx5IHNob3c/OiAnYWx3YXlzJyB8ICduZXZlcicgfCAnZXJyb3InO1xuXG4gIC8qKlxuICAgKiBQcm92aWRlIHVzZXIgaW50ZXJhY3Rpb24gdG8gcmVzcG9uZCB0byBzaGVsbCBwcm9tcHRzLlxuICAgKlxuICAgKiBPcmRlciBhbmQgY291bnQgc2hvdWxkIGNvcnJlc3BvbmQgdG8gdGhlIGV4cGVjdGVkIHByb21wdHMgaXNzdWVkIGJ5IHRoZSBzdWJwcm9jZXNzLlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJhY3Q/OiBVc2VySW50ZXJhY3Rpb25bXTtcblxufVxuXG5leHBvcnQgY2xhc3MgU2hlbGxIZWxwZXIge1xuICBwdWJsaWMgc3RhdGljIGZyb21Db250ZXh0KGNvbnRleHQ6IFRlc3RDb250ZXh0ICYgVGVtcG9yYXJ5RGlyZWN0b3J5Q29udGV4dCkge1xuICAgIHJldHVybiBuZXcgU2hlbGxIZWxwZXIoY29udGV4dC5pbnRlZ1Rlc3REaXIsIGNvbnRleHQub3V0cHV0KTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2N3ZDogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX291dHB1dDogTm9kZUpTLldyaXRhYmxlU3RyZWFtKSB7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGRvY2tlckNvbmZpZ0RpcigpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKHRoaXMuX2N3ZCwgJy5kb2NrZXInKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzaGVsbChjb21tYW5kOiBzdHJpbmdbXSwgb3B0aW9uczogT21pdDxTaGVsbE9wdGlvbnMsICdjd2QnIHwgJ291dHB1dHMnPiA9IHt9KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gc2hlbGwoY29tbWFuZCwge1xuICAgICAgb3V0cHV0czogW3RoaXMuX291dHB1dF0sXG4gICAgICBjd2Q6IHRoaXMuX2N3ZCxcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBtb2RFbnY6IHtcbiAgICAgICAgLy8gZ2l2ZSBldmVyeSBzaGVsbCBpdHMgb3duIGRvY2tlciBjb25maWcgZGlyZWN0b3J5XG4gICAgICAgIC8vIHNvIHRoYXQgcGFyYWxsZWwgcnVucyBkb24ndCBpbnRlcmZlcmUgd2l0aCBlYWNoIG90aGVyLlxuICAgICAgICBET0NLRVJfQ09ORklHOiB0aGlzLmRvY2tlckNvbmZpZ0RpcixcbiAgICAgICAgLi4ub3B0aW9ucy5tb2RFbnYsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogcm0gLXJmIHJlaW1wbGVtZW50YXRpb24sIGRvbid0IHdhbnQgdG8gZGVwZW5kIG9uIGFuIE5QTSBwYWNrYWdlIGZvciB0aGlzXG4gKlxuICogUmV0dXJucyBgdHJ1ZWAgaWYgZXZlcnl0aGluZyBnb3QgZGVsZXRlZCwgb3IgYGZhbHNlYCBpZiBzb21lIGZpbGVzIGNvdWxkXG4gKiBub3QgYmUgZGVsZXRlZCBkdWUgdG8gcGVybWlzc2lvbnMgaXNzdWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmltcmFmKGZzUGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHRyeSB7XG4gICAgbGV0IHN1Y2Nlc3MgPSB0cnVlO1xuICAgIGNvbnN0IGlzRGlyID0gZnMubHN0YXRTeW5jKGZzUGF0aCkuaXNEaXJlY3RvcnkoKTtcblxuICAgIGlmIChpc0Rpcikge1xuICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGZzLnJlYWRkaXJTeW5jKGZzUGF0aCkpIHtcbiAgICAgICAgc3VjY2VzcyAmJj0gcmltcmFmKHBhdGguam9pbihmc1BhdGgsIGZpbGUpKTtcbiAgICAgIH1cbiAgICAgIGZzLnJtZGlyU3luYyhmc1BhdGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmcy51bmxpbmtTeW5jKGZzUGF0aCk7XG4gICAgfVxuICAgIHJldHVybiBzdWNjZXNzO1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAvLyBDYW4gaGFwcGVuIGlmIHNvbWUgZmlsZXMgZ290IGdlbmVyYXRlZCBpbnNpZGUgYSBEb2NrZXIgY29udGFpbmVyIGFuZCBhcmUgbm93IGluYWR2ZXJ0ZW50bHkgb3duZWQgYnkgYHJvb3RgLlxuICAgIC8vIFdlIGNhbid0IGV2ZXIgY2xlYW4gdGhvc2UgdXAgYW55bW9yZSwgYnV0IHNpbmNlIGl0IG9ubHkgaGFwcGVucyBpbnNpZGUgR2l0SHViIEFjdGlvbnMgY29udGFpbmVycyB3ZSBhbHNvIGRvbid0IGNhcmUgdG9vIG11Y2guXG4gICAgaWYgKGUuY29kZSA9PT0gJ0VBQ0NFUycgfHwgZS5jb2RlID09PSAnRU5PVEVNUFRZJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIEFscmVhZHkgZ29uZVxuICAgIGlmIChlLmNvZGUgPT09ICdFTk9FTlQnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRUb1NoZWxsUGF0aCh4OiBzdHJpbmcpIHtcbiAgY29uc3QgcGFydHMgPSBwcm9jZXNzLmVudi5QQVRIPy5zcGxpdCgnOicpID8/IFtdO1xuXG4gIGlmICghcGFydHMuaW5jbHVkZXMoeCkpIHtcbiAgICBwYXJ0cy51bnNoaWZ0KHgpO1xuICB9XG5cbiAgcHJvY2Vzcy5lbnYuUEFUSCA9IHBhcnRzLmpvaW4oJzonKTtcbn1cblxuLyoqXG4gKiBBY2N1bXVsYXRlIHRleHQgc2luY2UgdGhlIGxhc3QgbGluZSBicmVhayAob3IgYmVnaW5uaW5nIG9mIHN0cmluZykgaXQgaGFzIHNlZW4gaW4gdGhlIGNodW5rcy5cbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAtIENodW5rczogWydvbmVcXG4nLCAndHdvXFxuJywgdGhyZWUnXVxuICogLSBMYXN0IExpbmU6ICd0aHJlZSdcbiAqXG4gKiAtIENodW5rczogWydvbmUnLCAndHdvJywgJ1xcbnRocmVlJ11cbiAqIC0gTGFzdCBMaW5lOiAndGhyZWUnXG4gKlxuICogLSBDaHVua3M6IFsnb25lJywgJ3R3byddXG4gKiAtIExhc3QgTGluZTogJ29uZXR3bydcbiAqXG4gKiAtIENodW5rczogWydvbmUnLCAndHdvJywgJ1xcbnRocmVlJywgJ2ZvdXInXVxuICogLSBMYXN0IExpbmU6ICd0aHJlZWZvdXInXG4gKi9cbmNsYXNzIExhc3RMaW5lIHtcbiAgcHJpdmF0ZSBsYXN0TGluZTogc3RyaW5nID0gJyc7XG5cbiAgcHVibGljIGFwcGVuZChjaHVuazogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbGluZXMgPSBjaHVuay5zcGxpdChvcy5FT0wpO1xuICAgIGlmIChsaW5lcy5sZW5ndGggPT09IDEpIHtcbiAgICAgIC8vIGNodW5rIGRvZXNuJ3QgY29udGFpbiBhIG5ldyBsaW5lIHNvIGp1c3QgYXBwZW5kXG4gICAgICB0aGlzLmxhc3RMaW5lICs9IGxpbmVzWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBjaHVuayBjb250YWlucyBtdWx0aXBsZSBsaW5lcyBzbyBqdXN0IG92ZXJyaWRlIHdpdGggdGhlIGxhc3Qgb25lXG4gICAgICB0aGlzLmxhc3RMaW5lID0gbGluZXNbbGluZXMubGVuZ3RoIC0gMV07XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmxhc3RMaW5lO1xuICB9XG5cbiAgcHVibGljIHJlc2V0KCkge1xuICAgIHRoaXMubGFzdExpbmUgPSAnJztcbiAgfVxufVxuIl19