projen
Version:
CDK for software projects
293 lines โข 38.3 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TaskRuntime = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const path_1 = require("path");
const path = require("path");
const util_1 = require("util");
const chalk_1 = require("chalk");
const common_1 = require("./common");
const logging = require("./logging");
const tasks_1 = require("./util/tasks");
// avoids a (false positive) esbuild warning about incorrect imports
// eslint-disable-next-line @typescript-eslint/no-require-imports
const parseConflictJSON = require("parse-conflict-json");
const ENV_TRIM_LEN = 20;
const ARGS_MARKER = "$@";
const QUOTED_ARGS_MARKER = `"${ARGS_MARKER}"`;
/**
* The runtime component of the tasks engine.
*/
class TaskRuntime {
constructor(workdir) {
this.workdir = (0, path_1.resolve)(workdir);
const manifestPath = (0, path_1.join)(this.workdir, TaskRuntime.MANIFEST_FILE);
this.manifest = (0, fs_1.existsSync)(manifestPath)
? parseConflictJSON((0, fs_1.readFileSync)(manifestPath, "utf-8"), undefined, "theirs")
: { tasks: {} };
}
/**
* The tasks in this project.
*/
get tasks() {
return Object.values(this.manifest.tasks ?? {});
}
/**
* Find a task by name, or `undefined` if not found.
*/
tryFindTask(name) {
if (!this.manifest.tasks) {
return undefined;
}
return this.manifest.tasks[name];
}
/**
* Runs the task.
* @param name The task name.
*/
runTask(name, parents = [], args = [], env = {}) {
const task = this.tryFindTask(name);
if (!task) {
throw new Error(`cannot find command ${task}`);
}
new RunTask(this, task, parents, args, env);
}
}
exports.TaskRuntime = TaskRuntime;
_a = JSII_RTTI_SYMBOL_1;
TaskRuntime[_a] = { fqn: "projen.TaskRuntime", version: "0.99.16" };
/**
* The project-relative path of the tasks manifest file.
*/
TaskRuntime.MANIFEST_FILE = path.posix.join(common_1.PROJEN_DIR, "tasks.json");
class RunTask {
constructor(runtime, task, parents = [], args = [], envParam = {}) {
this.runtime = runtime;
this.task = task;
this.env = {};
this.workdir = task.cwd ?? this.runtime.workdir;
this.parents = parents;
if (!task.steps || task.steps.length === 0) {
this.logDebug((0, chalk_1.gray)("No actions have been specified for this task."));
return;
}
this.env = this.resolveEnvironment(envParam, parents);
const envlogs = [];
for (const [k, v] of Object.entries(this.env)) {
const vv = v ?? "";
const trimmed = vv.length > ENV_TRIM_LEN ? vv.substr(0, ENV_TRIM_LEN) + "..." : vv;
envlogs.push(`${k}=${trimmed}`);
}
if (envlogs.length) {
this.logDebug((0, chalk_1.gray)(`${(0, chalk_1.underline)("env")}: ${envlogs.join(" ")}`));
}
// evaluate condition
if (!this.evalCondition(task)) {
this.log("condition exited with non-zero - skipping");
return;
}
// verify we required environment variables are defined
const merged = { ...process.env, ...this.env };
const missing = new Array();
for (const name of task.requiredEnv ?? []) {
if (!(name in merged)) {
missing.push(name);
}
}
if (missing.length > 0) {
throw new Error(`missing required environment variables: ${missing.join(",")}`);
}
for (const step of task.steps) {
// evaluate step condition
if (!this.evalCondition(step)) {
this.log("condition exited with non-zero - skipping");
continue;
}
const argsList = [
...(step.args || []),
...(step.receiveArgs ? args : []),
].map((a) => a.toString());
if (step.say) {
logging.info(this.fmtLog(step.say));
}
if (step.spawn) {
this.runtime.runTask(step.spawn, [...this.parents, this.task.name], argsList, step.env);
}
const execs = step.exec ? [step.exec] : [];
// Parse step-specific environment variables
const env = this.evalEnvironment(step.env ?? {});
if (step.builtin) {
execs.push(this.renderBuiltin(step.builtin));
}
for (const exec of execs) {
let hasError = false;
let command = (0, tasks_1.makeCrossPlatform)(exec);
if (command.includes(QUOTED_ARGS_MARKER)) {
// Poorly imitate bash quoted variable expansion. If "$@" is encountered in bash, elements of the arg array
// that contain whitespace will be single quoted ('arg'). This preserves whitespace in things like filenames.
// Imitate that behavior here by single quoting every element of the arg array when a quoted arg marker ("$@")
// is encountered.
command = command.replace(QUOTED_ARGS_MARKER, argsList.map((arg) => `'${arg}'`).join(" "));
}
else if (command.includes(ARGS_MARKER)) {
command = command.replace(ARGS_MARKER, argsList.join(" "));
}
else {
command = [command, ...argsList].join(" ");
}
const cwd = step.cwd;
try {
const result = this.shell({
command,
cwd,
extraEnv: env,
});
hasError = result.status !== 0;
}
catch (e) {
// This is the error 'shx' will throw
if (e?.message?.startsWith("non-zero exit code:")) {
hasError = true;
}
throw e;
}
if (hasError) {
throw new Error(`Task "${this.fullname}" failed when executing "${command}" (cwd: ${(0, path_1.resolve)(cwd ?? this.workdir)})`);
}
}
}
}
/**
* Determines if a task should be executed based on "condition".
*
* @returns true if the task should be executed or false if the condition
* evaluates to false (exits with non-zero), indicating that the task should
* be skipped.
*/
evalCondition(taskOrStep) {
// no condition, carry on
if (!taskOrStep.condition) {
return true;
}
this.log((0, chalk_1.gray)(`${(0, chalk_1.underline)("condition")}: ${taskOrStep.condition}`));
const result = this.shell({
command: taskOrStep.condition,
logprefix: "condition: ",
quiet: true,
});
if (result.status === 0) {
return true;
}
else {
return false;
}
}
/**
* Evaluates environment variables from shell commands (e.g. `$(xx)`)
*/
evalEnvironment(env) {
const output = {};
for (const [key, value] of Object.entries(env ?? {})) {
if (String(value).startsWith("$(") && String(value).endsWith(")")) {
const query = value.substring(2, value.length - 1);
const result = this.shellEval({ command: query });
if (result.status !== 0) {
const error = result.error
? result.error.stack
: (result.stderr?.toString() ?? "unknown error");
throw new Error(`unable to evaluate environment variable ${key}=${value}: ${error}`);
}
output[key] = result.stdout.toString("utf-8").trim();
}
else {
output[key] = value;
}
}
return output;
}
/**
* Renders the runtime environment for a task. Namely, it supports this syntax
* `$(xx)` for allowing environment to be evaluated by executing a shell
* command and obtaining its result.
*/
resolveEnvironment(envParam, parents) {
let env = this.runtime.manifest.env ?? {};
// add env from all parent tasks one by one
for (const parent of parents) {
env = {
...env,
...(this.runtime.tryFindTask(parent)?.env ?? {}),
};
}
// apply task environment, then the specific env last
env = {
...env,
...(this.task.env ?? {}),
...envParam,
};
return this.evalEnvironment(env ?? {});
}
/**
* Returns the "full name" of the task which includes all it's parent task names concatenated by chevrons.
*/
get fullname() {
return [...this.parents, this.task.name].join(" ยป ");
}
log(...args) {
logging.verbose(this.fmtLog(...args));
}
logDebug(...args) {
logging.debug(this.fmtLog(...args));
}
fmtLog(...args) {
return (0, util_1.format)(`${(0, chalk_1.underline)(this.fullname)} |`, ...args);
}
shell(options) {
const quiet = options.quiet ?? false;
if (!quiet) {
const log = new Array();
if (options.logprefix) {
log.push(options.logprefix);
}
log.push(options.command);
if (options.cwd) {
log.push(`(cwd: ${options.cwd})`);
}
this.log(log.join(" "));
}
const cwd = options.cwd ?? this.workdir;
if (!(0, fs_1.existsSync)(cwd) || !(0, fs_1.statSync)(cwd).isDirectory()) {
throw new Error(`invalid workdir (cwd): ${cwd} must be an existing directory`);
}
return (0, child_process_1.spawnSync)(options.command, {
...options,
cwd,
shell: true,
stdio: "inherit",
env: {
...process.env,
...this.env,
...options.extraEnv,
},
...options.spawnOptions,
});
}
shellEval(options) {
return this.shell({
quiet: true,
...options,
spawnOptions: {
stdio: ["inherit", "pipe", "inherit"],
},
});
}
renderBuiltin(builtin) {
const moduleRoot = (0, path_1.dirname)(require.resolve("../package.json"));
const program = require.resolve((0, path_1.join)(moduleRoot, "lib", `${builtin}.task.js`));
return `"${process.execPath}" "${program}"`;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1ydW50aW1lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Rhc2stcnVudGltZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLGlEQUF3RDtBQUN4RCwyQkFBd0Q7QUFDeEQsK0JBQThDO0FBQzlDLDZCQUE2QjtBQUM3QiwrQkFBOEI7QUFDOUIsaUNBQXdDO0FBQ3hDLHFDQUFzQztBQUN0QyxxQ0FBcUM7QUFFckMsd0NBQWlEO0FBRWpELG9FQUFvRTtBQUNwRSxpRUFBaUU7QUFDakUsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FBQztBQUV6RCxNQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7QUFDeEIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDO0FBQ3pCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxXQUFXLEdBQUcsQ0FBQztBQUU5Qzs7R0FFRztBQUNILE1BQWEsV0FBVztJQW1CdEIsWUFBWSxPQUFlO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBQSxjQUFPLEVBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEMsTUFBTSxZQUFZLEdBQUcsSUFBQSxXQUFJLEVBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDbkUsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFBLGVBQVUsRUFBQyxZQUFZLENBQUM7WUFDdEMsQ0FBQyxDQUFDLGlCQUFpQixDQUNmLElBQUEsaUJBQVksRUFBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLEVBQ25DLFNBQVMsRUFDVCxRQUFRLENBQ1Q7WUFDSCxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBVyxLQUFLO1FBQ2QsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2xE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UUFDbkMsTUFBTSxVQUFVLEdBQUcsSUFBQSxjQUFPLEVBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFDL0QsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FDN0IsSUFBQSxXQUFJLEVBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxHQUFHLE9BQU8sVUFBVSxDQUFDLENBQzlDLENBQUM7UUFDRixPQUFPLElBQUksT0FBTyxDQUFDLFFBQVEsTUFBTSxPQUFPLEdBQUcsQ0FBQztJQUM5QyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTcGF3bk9wdGlvbnMsIHNwYXduU3luYyB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHN0YXRTeW5jIH0gZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luLCByZXNvbHZlIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IGZvcm1hdCB9IGZyb20gXCJ1dGlsXCI7XG5pbXBvcnQgeyBncmF5LCB1bmRlcmxpbmUgfSBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCB7IFBST0pFTl9ESVIgfSBmcm9tIFwiLi9jb21tb25cIjtcbmltcG9ydCAqIGFzIGxvZ2dpbmcgZnJvbSBcIi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgVGFza3NNYW5pZmVzdCwgVGFza1NwZWMsIFRhc2tTdGVwIH0gZnJvbSBcIi4vdGFzay1tb2RlbFwiO1xuaW1wb3J0IHsgbWFrZUNyb3NzUGxhdGZvcm0gfSBmcm9tIFwiLi91dGlsL3Rhc2tzXCI7XG5cbi8vIGF2b2lkcyBhIChmYWxzZSBwb3NpdGl2ZSkgZXNidWlsZCB3YXJuaW5nIGFib3V0IGluY29ycmVjdCBpbXBvcnRzXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuY29uc3QgcGFyc2VDb25mbGljdEpTT04gPSByZXF1aXJlKFwicGFyc2UtY29uZmxpY3QtanNvblwiKTtcblxuY29uc3QgRU5WX1RSSU1fTEVOID0gMjA7XG5jb25zdCBBUkdTX01BUktFUiA9IFwiJEBcIjtcbmNvbnN0IFFVT1RFRF9BUkdTX01BUktFUiA9IGBcIiR7QVJHU19NQVJLRVJ9XCJgO1xuXG4vKipcbiAqIFRoZSBydW50aW1lIGNvbXBvbmVudCBvZiB0aGUgdGFza3MgZW5naW5lLlxuICovXG5leHBvcnQgY2xhc3MgVGFza1J1bnRpbWUge1xuICAvKipcbiAgICogVGhlIHByb2plY3QtcmVsYXRpdmUgcGF0aCBvZiB0aGUgdGFza3MgbWFuaWZlc3QgZmlsZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTUFOSUZFU1RfRklMRSA9IHBhdGgucG9zaXguam9pbihcbiAgICBQUk9KRU5fRElSLFxuICAgIFwidGFza3MuanNvblwiLFxuICApO1xuXG4gIC8qKlxuICAgKiBUaGUgY29udGVudHMgb2YgdGFza3MuanNvblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG1hbmlmZXN0OiBUYXNrc01hbmlmZXN0O1xuXG4gIC8qKlxuICAgKiBUaGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhlIHByb2plY3QgYW5kIHRoZSBjd2QgZm9yIGV4ZWN1dGluZyB0YXNrcy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB3b3JrZGlyOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Iod29ya2Rpcjogc3RyaW5nKSB7XG4gICAgdGhpcy53b3JrZGlyID0gcmVzb2x2ZSh3b3JrZGlyKTtcbiAgICBjb25zdCBtYW5pZmVzdFBhdGggPSBqb2luKHRoaXMud29ya2RpciwgVGFza1J1bnRpbWUuTUFOSUZFU1RfRklMRSk7XG4gICAgdGhpcy5tYW5pZmVzdCA9IGV4aXN0c1N5bmMobWFuaWZlc3RQYXRoKVxuICAgICAgPyBwYXJzZUNvbmZsaWN0SlNPTihcbiAgICAgICAgICByZWFkRmlsZVN5bmMobWFuaWZlc3RQYXRoLCBcInV0Zi04XCIpLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICBcInRoZWlyc1wiLFxuICAgICAgICApXG4gICAgICA6IHsgdGFza3M6IHt9IH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIHRhc2tzIGluIHRoaXMgcHJvamVjdC5cbiAgICovXG4gIHB1YmxpYyBnZXQgdGFza3MoKTogVGFza1NwZWNbXSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5tYW5pZmVzdC50YXNrcyA/PyB7fSk7XG4gIH1cblxuICAvKipcbiAgICogRmluZCBhIHRhc2sgYnkgbmFtZSwgb3IgYHVuZGVmaW5lZGAgaWYgbm90IGZvdW5kLlxuICAgKi9cbiAgcHVibGljIHRyeUZpbmRUYXNrKG5hbWU6IHN0cmluZyk6IFRhc2tTcGVjIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMubWFuaWZlc3QudGFza3MpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm1hbmlmZXN0LnRhc2tzW25hbWVdO1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgdGhlIHRhc2suXG4gICAqIEBwYXJhbSBuYW1lIFRoZSB0YXNrIG5hbWUuXG4gICAqL1xuICBwdWJsaWMgcnVuVGFzayhcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcGFyZW50czogc3RyaW5nW10gPSBbXSxcbiAgICBhcmdzOiBBcnJheTxzdHJpbmcgfCBudW1iZXI+ID0gW10sXG4gICAgZW52OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9LFxuICApIHtcbiAgICBjb25zdCB0YXNrID0gdGhpcy50cnlGaW5kVGFzayhuYW1lKTtcbiAgICBpZiAoIXRhc2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IGZpbmQgY29tbWFuZCAke3Rhc2t9YCk7XG4gICAgfVxuXG4gICAgbmV3IFJ1blRhc2sodGhpcywgdGFzaywgcGFyZW50cywgYXJncywgZW52KTtcbiAgfVxufVxuXG5jbGFzcyBSdW5UYXNrIHtcbiAgcHJpdmF0ZSByZWFkb25seSBlbnY6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgcGFyZW50czogc3RyaW5nW107XG5cbiAgcHJpdmF0ZSByZWFkb25seSB3b3JrZGlyOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBydW50aW1lOiBUYXNrUnVudGltZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRhc2s6IFRhc2tTcGVjLFxuICAgIHBhcmVudHM6IHN0cmluZ1tdID0gW10sXG4gICAgYXJnczogQXJyYXk8c3RyaW5nIHwgbnVtYmVyPiA9IFtdLFxuICAgIGVudlBhcmFtOiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9LFxuICApIHtcbiAgICB0aGlzLndvcmtkaXIgPSB0YXNrLmN3ZCA/PyB0aGlzLnJ1bnRpbWUud29ya2RpcjtcblxuICAgIHRoaXMucGFyZW50cyA9IHBhcmVudHM7XG5cbiAgICBpZiAoIXRhc2suc3RlcHMgfHwgdGFzay5zdGVwcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMubG9nRGVidWcoZ3JheShcIk5vIGFjdGlvbnMgaGF2ZSBiZWVuIHNwZWNpZmllZCBmb3IgdGhpcyB0YXNrLlwiKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5lbnYgPSB0aGlzLnJlc29sdmVFbnZpcm9ubWVudChlbnZQYXJhbSwgcGFyZW50cyk7XG5cbiAgICBjb25zdCBlbnZsb2dzID0gW107XG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXModGhpcy5lbnYpKSB7XG4gICAgICBjb25zdCB2diA9IHYgPz8gXCJcIjtcbiAgICAgIGNvbnN0IHRyaW1tZWQgPVxuICAgICAgICB2di5sZW5ndGggPiBFTlZfVFJJTV9MRU4gPyB2di5zdWJzdHIoMCwgRU5WX1RSSU1fTEVOKSArIFwiLi4uXCIgOiB2djtcbiAgICAgIGVudmxvZ3MucHVzaChgJHtrfT0ke3RyaW1tZWR9YCk7XG4gICAgfVxuXG4gICAgaWYgKGVudmxvZ3MubGVuZ3RoKSB7XG4gICAgICB0aGlzLmxvZ0RlYnVnKGdyYXkoYCR7dW5kZXJsaW5lKFwiZW52XCIpfTogJHtlbnZsb2dzLmpvaW4oXCIgXCIpfWApKTtcbiAgICB9XG5cbiAgICAvLyBldmFsdWF0ZSBjb25kaXRpb25cbiAgICBpZiAoIXRoaXMuZXZhbENvbmRpdGlvbih0YXNrKSkge1xuICAgICAgdGhpcy5sb2coXCJjb25kaXRpb24gZXhpdGVkIHdpdGggbm9uLXplcm8gLSBza2lwcGluZ1wiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB2ZXJpZnkgd2UgcmVxdWlyZWQgZW52aXJvbm1lbnQgdmFyaWFibGVzIGFyZSBkZWZpbmVkXG4gICAgY29uc3QgbWVyZ2VkID0geyAuLi5wcm9jZXNzLmVudiwgLi4udGhpcy5lbnYgfTtcbiAgICBjb25zdCBtaXNzaW5nID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgdGFzay5yZXF1aXJlZEVudiA/PyBbXSkge1xuICAgICAgaWYgKCEobmFtZSBpbiBtZXJnZWQpKSB7XG4gICAgICAgIG1pc3NpbmcucHVzaChuYW1lKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobWlzc2luZy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBtaXNzaW5nIHJlcXVpcmVkIGVudmlyb25tZW50IHZhcmlhYmxlczogJHttaXNzaW5nLmpvaW4oXCIsXCIpfWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgc3RlcCBvZiB0YXNrLnN0ZXBzKSB7XG4gICAgICAvLyBldmFsdWF0ZSBzdGVwIGNvbmRpdGlvblxuICAgICAgaWYgKCF0aGlzLmV2YWxDb25kaXRpb24oc3RlcCkpIHtcbiAgICAgICAgdGhpcy5sb2coXCJjb25kaXRpb24gZXhpdGVkIHdpdGggbm9uLXplcm8gLSBza2lwcGluZ1wiKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFyZ3NMaXN0OiBzdHJpbmdbXSA9IFtcbiAgICAgICAgLi4uKHN0ZXAuYXJncyB8fCBbXSksXG4gICAgICAgIC4uLihzdGVwLnJlY2VpdmVBcmdzID8gYXJncyA6IFtdKSxcbiAgICAgIF0ubWFwKChhKSA9PiBhLnRvU3RyaW5nKCkpO1xuXG4gICAgICBpZiAoc3RlcC5zYXkpIHtcbiAgICAgICAgbG9nZ2luZy5pbmZvKHRoaXMuZm10TG9nKHN0ZXAuc2F5KSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGVwLnNwYXduKSB7XG4gICAgICAgIHRoaXMucnVudGltZS5ydW5UYXNrKFxuICAgICAgICAgIHN0ZXAuc3Bhd24sXG4gICAgICAgICAgWy4uLnRoaXMucGFyZW50cywgdGhpcy50YXNrLm5hbWVdLFxuICAgICAgICAgIGFyZ3NMaXN0LFxuICAgICAgICAgIHN0ZXAuZW52LFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBleGVjcyA9IHN0ZXAuZXhlYyA/IFtzdGVwLmV4ZWNdIDogW107XG5cbiAgICAgIC8vIFBhcnNlIHN0ZXAtc3BlY2lmaWMgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAgICBjb25zdCBlbnYgPSB0aGlzLmV2YWxFbnZpcm9ubWVudChzdGVwLmVudiA/PyB7fSk7XG5cbiAgICAgIGlmIChzdGVwLmJ1aWx0aW4pIHtcbiAgICAgICAgZXhlY3MucHVzaCh0aGlzLnJlbmRlckJ1aWx0aW4oc3RlcC5idWlsdGluKSk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgZXhlYyBvZiBleGVjcykge1xuICAgICAgICBsZXQgaGFzRXJyb3IgPSBmYWxzZTtcblxuICAgICAgICBsZXQgY29tbWFuZCA9IG1ha2VDcm9zc1BsYXRmb3JtKGV4ZWMpO1xuXG4gICAgICAgIGlmIChjb21tYW5kLmluY2x1ZGVzKFFVT1RFRF9BUkdTX01BUktFUikpIHtcbiAgICAgICAgICAvLyBQb29ybHkgaW1pdGF0ZSBiYXNoIHF1b3RlZCB2YXJpYWJsZSBleHBhbnNpb24uIElmIFwiJEBcIiBpcyBlbmNvdW50ZXJlZCBpbiBiYXNoLCBlbGVtZW50cyBvZiB0aGUgYXJnIGFycmF5XG4gICAgICAgICAgLy8gdGhhdCBjb250YWluIHdoaXRlc3BhY2Ugd2lsbCBiZSBzaW5nbGUgcXVvdGVkICgnYXJnJykuIFRoaXMgcHJlc2VydmVzIHdoaXRlc3BhY2UgaW4gdGhpbmdzIGxpa2UgZmlsZW5hbWVzLlxuICAgICAgICAgIC8vIEltaXRhdGUgdGhhdCBiZWhhdmlvciBoZXJlIGJ5IHNpbmdsZSBxdW90aW5nIGV2ZXJ5IGVsZW1lbnQgb2YgdGhlIGFyZyBhcnJheSB3aGVuIGEgcXVvdGVkIGFyZyBtYXJrZXIgKFwiJEBcIilcbiAgICAgICAgICAvLyBpcyBlbmNvdW50ZXJlZC5cbiAgICAgICAgICBjb21tYW5kID0gY29tbWFuZC5yZXBsYWNlKFxuICAgICAgICAgICAgUVVPVEVEX0FSR1NfTUFSS0VSLFxuICAgICAgICAgICAgYXJnc0xpc3QubWFwKChhcmcpID0+IGAnJHthcmd9J2ApLmpvaW4oXCIgXCIpLFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoY29tbWFuZC5pbmNsdWRlcyhBUkdTX01BUktFUikpIHtcbiAgICAgICAgICBjb21tYW5kID0gY29tbWFuZC5yZXBsYWNlKEFSR1NfTUFSS0VSLCBhcmdzTGlzdC5qb2luKFwiIFwiKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29tbWFuZCA9IFtjb21tYW5kLCAuLi5hcmdzTGlzdF0uam9pbihcIiBcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjd2QgPSBzdGVwLmN3ZDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLnNoZWxsKHtcbiAgICAgICAgICAgIGNvbW1hbmQsXG4gICAgICAgICAgICBjd2QsXG4gICAgICAgICAgICBleHRyYUVudjogZW52LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGhhc0Vycm9yID0gcmVzdWx0LnN0YXR1cyAhPT0gMDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGVycm9yICdzaHgnIHdpbGwgdGhyb3dcbiAgICAgICAgICBpZiAoKGUgYXMgYW55KT8ubWVzc2FnZT8uc3RhcnRzV2l0aChcIm5vbi16ZXJvIGV4aXQgY29kZTpcIikpIHtcbiAgICAgICAgICAgIGhhc0Vycm9yID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgVGFzayBcIiR7XG4gICAgICAgICAgICAgIHRoaXMuZnVsbG5hbWVcbiAgICAgICAgICAgIH1cIiBmYWlsZWQgd2hlbiBleGVjdXRpbmcgXCIke2NvbW1hbmR9XCIgKGN3ZDogJHtyZXNvbHZlKFxuICAgICAgICAgICAgICBjd2QgPz8gdGhpcy53b3JrZGlyLFxuICAgICAgICAgICAgKX0pYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgaWYgYSB0YXNrIHNob3VsZCBiZSBleGVjdXRlZCBiYXNlZCBvbiBcImNvbmRpdGlvblwiLlxuICAgKlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSB0YXNrIHNob3VsZCBiZSBleGVjdXRlZCBvciBmYWxzZSBpZiB0aGUgY29uZGl0aW9uXG4gICAqIGV2YWx1YXRlcyB0byBmYWxzZSAoZXhpdHMgd2l0aCBub24temVybyksIGluZGljYXRpbmcgdGhhdCB0aGUgdGFzayBzaG91bGRcbiAgICogYmUgc2tpcHBlZC5cbiAgICovXG4gIHByaXZhdGUgZXZhbENvbmRpdGlvbih0YXNrT3JTdGVwOiBUYXNrU3BlYyB8IFRhc2tTdGVwKSB7XG4gICAgLy8gbm8gY29uZGl0aW9uLCBjYXJyeSBvblxuICAgIGlmICghdGFza09yU3RlcC5jb25kaXRpb24pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHRoaXMubG9nKGdyYXkoYCR7dW5kZXJsaW5lKFwiY29uZGl0aW9uXCIpfTogJHt0YXNrT3JTdGVwLmNvbmRpdGlvbn1gKSk7XG4gICAgY29uc3QgcmVzdWx0ID0gdGhpcy5zaGVsbCh7XG4gICAgICBjb21tYW5kOiB0YXNrT3JTdGVwLmNvbmRpdGlvbixcbiAgICAgIGxvZ3ByZWZpeDogXCJjb25kaXRpb246IFwiLFxuICAgICAgcXVpZXQ6IHRydWUsXG4gICAgfSk7XG4gICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09IDApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2YWx1YXRlcyBlbnZpcm9ubWVudCB2YXJpYWJsZXMgZnJvbSBzaGVsbCBjb21tYW5kcyAoZS5nLiBgJCh4eClgKVxuICAgKi9cbiAgcHJpdmF0ZSBldmFsRW52aXJvbm1lbnQoZW52OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfSkge1xuICAgIGNvbnN0IG91dHB1dDogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkIH0gPSB7fTtcblxuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGVudiA/PyB7fSkpIHtcbiAgICAgIGlmIChTdHJpbmcodmFsdWUpLnN0YXJ0c1dpdGgoXCIkKFwiKSAmJiBTdHJpbmcodmFsdWUpLmVuZHNXaXRoKFwiKVwiKSkge1xuICAgICAgICBjb25zdCBxdWVyeSA9IHZhbHVlLnN1YnN0cmluZygyLCB2YWx1ZS5sZW5ndGggLSAxKTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5zaGVsbEV2YWwoeyBjb21tYW5kOiBxdWVyeSB9KTtcbiAgICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgIT09IDApIHtcbiAgICAgICAgICBjb25zdCBlcnJvciA9IHJlc3VsdC5lcnJvclxuICAgICAgICAgICAgPyByZXN1bHQuZXJyb3Iuc3RhY2tcbiAgICAgICAgICAgIDogKHJlc3VsdC5zdGRlcnI/LnRvU3RyaW5nKCkgPz8gXCJ1bmtub3duIGVycm9yXCIpO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGB1bmFibGUgdG8gZXZhbHVhdGUgZW52aXJvbm1lbnQgdmFyaWFibGUgJHtrZXl9PSR7dmFsdWV9OiAke2Vycm9yfWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBvdXRwdXRba2V5XSA9IHJlc3VsdC5zdGRvdXQudG9TdHJpbmcoXCJ1dGYtOFwiKS50cmltKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvdXRwdXRba2V5XSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlcnMgdGhlIHJ1bnRpbWUgZW52aXJvbm1lbnQgZm9yIGEgdGFzay4gTmFtZWx5LCBpdCBzdXBwb3J0cyB0aGlzIHN5bnRheFxuICAgKiBgJCh4eClgIGZvciBhbGxvd2luZyBlbnZpcm9ubWVudCB0byBiZSBldmFsdWF0ZWQgYnkgZXhlY3V0aW5nIGEgc2hlbGxcbiAgICogY29tbWFuZCBhbmQgb2J0YWluaW5nIGl0cyByZXN1bHQuXG4gICAqL1xuICBwcml2YXRlIHJlc29sdmVFbnZpcm9ubWVudChcbiAgICBlbnZQYXJhbTogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICAgcGFyZW50czogc3RyaW5nW10sXG4gICkge1xuICAgIGxldCBlbnYgPSB0aGlzLnJ1bnRpbWUubWFuaWZlc3QuZW52ID8/IHt9O1xuXG4gICAgLy8gYWRkIGVudiBmcm9tIGFsbCBwYXJlbnQgdGFza3Mgb25lIGJ5IG9uZVxuICAgIGZvciAoY29uc3QgcGFyZW50IG9mIHBhcmVudHMpIHtcbiAgICAgIGVudiA9IHtcbiAgICAgICAgLi4uZW52LFxuICAgICAgICAuLi4odGhpcy5ydW50aW1lLnRyeUZpbmRUYXNrKHBhcmVudCk/LmVudiA/PyB7fSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIGFwcGx5IHRhc2sgZW52aXJvbm1lbnQsIHRoZW4gdGhlIHNwZWNpZmljIGVudiBsYXN0XG4gICAgZW52ID0ge1xuICAgICAgLi4uZW52LFxuICAgICAgLi4uKHRoaXMudGFzay5lbnYgPz8ge30pLFxuICAgICAgLi4uZW52UGFyYW0sXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLmV2YWxFbnZpcm9ubWVudChlbnYgPz8ge30pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFwiZnVsbCBuYW1lXCIgb2YgdGhlIHRhc2sgd2hpY2ggaW5jbHVkZXMgYWxsIGl0J3MgcGFyZW50IHRhc2sgbmFtZXMgY29uY2F0ZW5hdGVkIGJ5IGNoZXZyb25zLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgZnVsbG5hbWUoKSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLnBhcmVudHMsIHRoaXMudGFzay5uYW1lXS5qb2luKFwiIMK7IFwiKTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgbG9nZ2luZy52ZXJib3NlKHRoaXMuZm10TG9nKC4uLmFyZ3MpKTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nRGVidWcoLi4uYXJnczogYW55W10pIHtcbiAgICBsb2dnaW5nLmRlYnVnKHRoaXMuZm10TG9nKC4uLmFyZ3MpKTtcbiAgfVxuXG4gIHByaXZhdGUgZm10TG9nKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgcmV0dXJuIGZvcm1hdChgJHt1bmRlcmxpbmUodGhpcy5mdWxsbmFtZSl9IHxgLCAuLi5hcmdzKTtcbiAgfVxuXG4gIHByaXZhdGUgc2hlbGwob3B0aW9uczogU2hlbGxPcHRpb25zKSB7XG4gICAgY29uc3QgcXVpZXQgPSBvcHRpb25zLnF1aWV0ID8/IGZhbHNlO1xuICAgIGlmICghcXVpZXQpIHtcbiAgICAgIGNvbnN0IGxvZyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG5cbiAgICAgIGlmIChvcHRpb25zLmxvZ3ByZWZpeCkge1xuICAgICAgICBsb2cucHVzaChvcHRpb25zLmxvZ3ByZWZpeCk7XG4gICAgICB9XG5cbiAgICAgIGxvZy5wdXNoKG9wdGlvbnMuY29tbWFuZCk7XG5cbiAgICAgIGlmIChvcHRpb25zLmN3ZCkge1xuICAgICAgICBsb2cucHVzaChgKGN3ZDogJHtvcHRpb25zLmN3ZH0pYCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubG9nKGxvZy5qb2luKFwiIFwiKSk7XG4gICAgfVxuXG4gICAgY29uc3QgY3dkID0gb3B0aW9ucy5jd2QgPz8gdGhpcy53b3JrZGlyO1xuICAgIGlmICghZXhpc3RzU3luYyhjd2QpIHx8ICFzdGF0U3luYyhjd2QpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYGludmFsaWQgd29ya2RpciAoY3dkKTogJHtjd2R9IG11c3QgYmUgYW4gZXhpc3RpbmcgZGlyZWN0b3J5YCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNwYXduU3luYyhvcHRpb25zLmNvbW1hbmQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBjd2QsXG4gICAgICBzaGVsbDogdHJ1ZSxcbiAgICAgIHN0ZGlvOiBcImluaGVyaXRcIixcbiAgICAgIGVudjoge1xuICAgICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgICAgLi4udGhpcy5lbnYsXG4gICAgICAgIC4uLm9wdGlvbnMuZXh0cmFFbnYsXG4gICAgICB9LFxuICAgICAgLi4ub3B0aW9ucy5zcGF3bk9wdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNoZWxsRXZhbChvcHRpb25zOiBTaGVsbE9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy5zaGVsbCh7XG4gICAgICBxdWlldDogdHJ1ZSxcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBzcGF3bk9wdGlvbnM6IHtcbiAgICAgICAgc3RkaW86IFtcImluaGVyaXRcIiwgXCJwaXBlXCIsIFwiaW5oZXJpdFwiXSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlckJ1aWx0aW4oYnVpbHRpbjogc3RyaW5nKSB7XG4gICAgY29uc3QgbW9kdWxlUm9vdCA9IGRpcm5hbWUocmVxdWlyZS5yZXNvbHZlKFwiLi4vcGFja2FnZS5qc29uXCIpKTtcbiAgICBjb25zdCBwcm9ncmFtID0gcmVxdWlyZS5yZXNvbHZlKFxuICAgICAgam9pbihtb2R1bGVSb290LCBcImxpYlwiLCBgJHtidWlsdGlufS50YXNrLmpzYCksXG4gICAgKTtcbiAgICByZXR1cm4gYFwiJHtwcm9jZXNzLmV4ZWNQYXRofVwiIFwiJHtwcm9ncmFtfVwiYDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgU2hlbGxPcHRpb25zIHtcbiAgcmVhZG9ubHkgY29tbWFuZDogc3RyaW5nO1xuICAvKipcbiAgICogQGRlZmF1bHQgLSBwcm9qZWN0IGRpclxuICAgKi9cbiAgcmVhZG9ubHkgY3dkPzogc3RyaW5nO1xuICByZWFkb25seSBsb2dwcmVmaXg/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNwYXduT3B0aW9ucz86IFNwYXduT3B0aW9ucztcbiAgLyoqIEBkZWZhdWx0IGZhbHNlICovXG4gIHJlYWRvbmx5IHF1aWV0PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZXh0cmFFbnY/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfCB1bmRlZmluZWQgfTtcbn1cbiJdfQ==