projen
Version:
CDK for software projects
291 lines โข 37.9 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 parseConflictJSON = require("parse-conflict-json");
const common_1 = require("./common");
const logging = require("./logging");
const tasks_1 = require("./util/tasks");
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.95.2" };
/**
* 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1ydW50aW1lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Rhc2stcnVudGltZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLGlEQUF3RDtBQUN4RCwyQkFBd0Q7QUFDeEQsK0JBQThDO0FBQzlDLDZCQUE2QjtBQUM3QiwrQkFBOEI7QUFDOUIsaUNBQXdDO0FBQ3hDLHlEQUF5RDtBQUN6RCxxQ0FBc0M7QUFDdEMscUNBQXFDO0FBRXJDLHdDQUFpRDtBQUVqRCxNQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7QUFDeEIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDO0FBQ3pCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxXQUFXLEdBQUcsQ0FBQztBQUU5Qzs7R0FFRztBQUNILE1BQWEsV0FBVztJQW1CdEIsWUFBWSxPQUFlO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBQSxjQUFPLEVBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEMsTUFBTSxZQUFZLEdBQUcsSUFBQSxXQUFJLEVBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDbkUsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFBLGVBQVUsRUFBQyxZQUFZLENBQUM7WUFDdEMsQ0FBQyxDQUFDLGlCQUFpQixDQUNmLElBQUEsaUJBQVksRUFBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLEVBQ25DLFNBQVMsRUFDVCxRQUFRLENBQ1Q7WUFDSCxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBVyxLQUFLO1FBQ2QsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLFdBQVcsQ0FBQyxJQUFZO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMs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Q0FBQztRQUMvRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUM3QixJQUFBLFdBQUksRUFBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLEdBQUcsT0FBTyxVQUFVLENBQUMsQ0FDOUMsQ0FBQztRQUNGLE9BQU8sSUFBSSxPQUFPLENBQUMsUUFBUSxNQUFNLE9BQU8sR0FBRyxDQUFDO0lBQzlDLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNwYXduT3B0aW9ucywgc3Bhd25TeW5jIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYywgc3RhdFN5bmMgfSBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4sIHJlc29sdmUgfSBmcm9tIFwicGF0aFwiO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgZm9ybWF0IH0gZnJvbSBcInV0aWxcIjtcbmltcG9ydCB7IGdyYXksIHVuZGVybGluZSB9IGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0ICogYXMgcGFyc2VDb25mbGljdEpTT04gZnJvbSBcInBhcnNlLWNvbmZsaWN0LWpzb25cIjtcbmltcG9ydCB7IFBST0pFTl9ESVIgfSBmcm9tIFwiLi9jb21tb25cIjtcbmltcG9ydCAqIGFzIGxvZ2dpbmcgZnJvbSBcIi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgVGFza3NNYW5pZmVzdCwgVGFza1NwZWMsIFRhc2tTdGVwIH0gZnJvbSBcIi4vdGFzay1tb2RlbFwiO1xuaW1wb3J0IHsgbWFrZUNyb3NzUGxhdGZvcm0gfSBmcm9tIFwiLi91dGlsL3Rhc2tzXCI7XG5cbmNvbnN0IEVOVl9UUklNX0xFTiA9IDIwO1xuY29uc3QgQVJHU19NQVJLRVIgPSBcIiRAXCI7XG5jb25zdCBRVU9URURfQVJHU19NQVJLRVIgPSBgXCIke0FSR1NfTUFSS0VSfVwiYDtcblxuLyoqXG4gKiBUaGUgcnVudGltZSBjb21wb25lbnQgb2YgdGhlIHRhc2tzIGVuZ2luZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFRhc2tSdW50aW1lIHtcbiAgLyoqXG4gICAqIFRoZSBwcm9qZWN0LXJlbGF0aXZlIHBhdGggb2YgdGhlIHRhc2tzIG1hbmlmZXN0IGZpbGUuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE1BTklGRVNUX0ZJTEUgPSBwYXRoLnBvc2l4LmpvaW4oXG4gICAgUFJPSkVOX0RJUixcbiAgICBcInRhc2tzLmpzb25cIlxuICApO1xuXG4gIC8qKlxuICAgKiBUaGUgY29udGVudHMgb2YgdGFza3MuanNvblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG1hbmlmZXN0OiBUYXNrc01hbmlmZXN0O1xuXG4gIC8qKlxuICAgKiBUaGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhlIHByb2plY3QgYW5kIHRoZSBjd2QgZm9yIGV4ZWN1dGluZyB0YXNrcy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB3b3JrZGlyOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Iod29ya2Rpcjogc3RyaW5nKSB7XG4gICAgdGhpcy53b3JrZGlyID0gcmVzb2x2ZSh3b3JrZGlyKTtcbiAgICBjb25zdCBtYW5pZmVzdFBhdGggPSBqb2luKHRoaXMud29ya2RpciwgVGFza1J1bnRpbWUuTUFOSUZFU1RfRklMRSk7XG4gICAgdGhpcy5tYW5pZmVzdCA9IGV4aXN0c1N5bmMobWFuaWZlc3RQYXRoKVxuICAgICAgPyBwYXJzZUNvbmZsaWN0SlNPTihcbiAgICAgICAgICByZWFkRmlsZVN5bmMobWFuaWZlc3RQYXRoLCBcInV0Zi04XCIpLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICBcInRoZWlyc1wiXG4gICAgICAgIClcbiAgICAgIDogeyB0YXNrczoge30gfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdGFza3MgaW4gdGhpcyBwcm9qZWN0LlxuICAgKi9cbiAgcHVibGljIGdldCB0YXNrcygpOiBUYXNrU3BlY1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLm1hbmlmZXN0LnRhc2tzID8/IHt9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kIGEgdGFzayBieSBuYW1lLCBvciBgdW5kZWZpbmVkYCBpZiBub3QgZm91bmQuXG4gICAqL1xuICBwdWJsaWMgdHJ5RmluZFRhc2sobmFtZTogc3RyaW5nKTogVGFza1NwZWMgfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5tYW5pZmVzdC50YXNrcykge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubWFuaWZlc3QudGFza3NbbmFtZV07XG4gIH1cblxuICAvKipcbiAgICogUnVucyB0aGUgdGFzay5cbiAgICogQHBhcmFtIG5hbWUgVGhlIHRhc2sgbmFtZS5cbiAgICovXG4gIHB1YmxpYyBydW5UYXNrKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBwYXJlbnRzOiBzdHJpbmdbXSA9IFtdLFxuICAgIGFyZ3M6IEFycmF5PHN0cmluZyB8IG51bWJlcj4gPSBbXSxcbiAgICBlbnY6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9ID0ge31cbiAgKSB7XG4gICAgY29uc3QgdGFzayA9IHRoaXMudHJ5RmluZFRhc2sobmFtZSk7XG4gICAgaWYgKCF0YXNrKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCBmaW5kIGNvbW1hbmQgJHt0YXNrfWApO1xuICAgIH1cblxuICAgIG5ldyBSdW5UYXNrKHRoaXMsIHRhc2ssIHBhcmVudHMsIGFyZ3MsIGVudik7XG4gIH1cbn1cblxuY2xhc3MgUnVuVGFzayB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZW52OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfCB1bmRlZmluZWQgfSA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IHBhcmVudHM6IHN0cmluZ1tdO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgd29ya2Rpcjogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcnVudGltZTogVGFza1J1bnRpbWUsXG4gICAgcHJpdmF0ZSByZWFkb25seSB0YXNrOiBUYXNrU3BlYyxcbiAgICBwYXJlbnRzOiBzdHJpbmdbXSA9IFtdLFxuICAgIGFyZ3M6IEFycmF5PHN0cmluZyB8IG51bWJlcj4gPSBbXSxcbiAgICBlbnZQYXJhbTogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fVxuICApIHtcbiAgICB0aGlzLndvcmtkaXIgPSB0YXNrLmN3ZCA/PyB0aGlzLnJ1bnRpbWUud29ya2RpcjtcblxuICAgIHRoaXMucGFyZW50cyA9IHBhcmVudHM7XG5cbiAgICBpZiAoIXRhc2suc3RlcHMgfHwgdGFzay5zdGVwcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMubG9nRGVidWcoZ3JheShcIk5vIGFjdGlvbnMgaGF2ZSBiZWVuIHNwZWNpZmllZCBmb3IgdGhpcyB0YXNrLlwiKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5lbnYgPSB0aGlzLnJlc29sdmVFbnZpcm9ubWVudChlbnZQYXJhbSwgcGFyZW50cyk7XG5cbiAgICBjb25zdCBlbnZsb2dzID0gW107XG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXModGhpcy5lbnYpKSB7XG4gICAgICBjb25zdCB2diA9IHYgPz8gXCJcIjtcbiAgICAgIGNvbnN0IHRyaW1tZWQgPVxuICAgICAgICB2di5sZW5ndGggPiBFTlZfVFJJTV9MRU4gPyB2di5zdWJzdHIoMCwgRU5WX1RSSU1fTEVOKSArIFwiLi4uXCIgOiB2djtcbiAgICAgIGVudmxvZ3MucHVzaChgJHtrfT0ke3RyaW1tZWR9YCk7XG4gICAgfVxuXG4gICAgaWYgKGVudmxvZ3MubGVuZ3RoKSB7XG4gICAgICB0aGlzLmxvZ0RlYnVnKGdyYXkoYCR7dW5kZXJsaW5lKFwiZW52XCIpfTogJHtlbnZsb2dzLmpvaW4oXCIgXCIpfWApKTtcbiAgICB9XG5cbiAgICAvLyBldmFsdWF0ZSBjb25kaXRpb25cbiAgICBpZiAoIXRoaXMuZXZhbENvbmRpdGlvbih0YXNrKSkge1xuICAgICAgdGhpcy5sb2coXCJjb25kaXRpb24gZXhpdGVkIHdpdGggbm9uLXplcm8gLSBza2lwcGluZ1wiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB2ZXJpZnkgd2UgcmVxdWlyZWQgZW52aXJvbm1lbnQgdmFyaWFibGVzIGFyZSBkZWZpbmVkXG4gICAgY29uc3QgbWVyZ2VkID0geyAuLi5wcm9jZXNzLmVudiwgLi4udGhpcy5lbnYgfTtcbiAgICBjb25zdCBtaXNzaW5nID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgdGFzay5yZXF1aXJlZEVudiA/PyBbXSkge1xuICAgICAgaWYgKCEobmFtZSBpbiBtZXJnZWQpKSB7XG4gICAgICAgIG1pc3NpbmcucHVzaChuYW1lKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobWlzc2luZy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBtaXNzaW5nIHJlcXVpcmVkIGVudmlyb25tZW50IHZhcmlhYmxlczogJHttaXNzaW5nLmpvaW4oXCIsXCIpfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBzdGVwIG9mIHRhc2suc3RlcHMpIHtcbiAgICAgIC8vIGV2YWx1YXRlIHN0ZXAgY29uZGl0aW9uXG4gICAgICBpZiAoIXRoaXMuZXZhbENvbmRpdGlvbihzdGVwKSkge1xuICAgICAgICB0aGlzLmxvZyhcImNvbmRpdGlvbiBleGl0ZWQgd2l0aCBub24temVybyAtIHNraXBwaW5nXCIpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYXJnc0xpc3Q6IHN0cmluZ1tdID0gW1xuICAgICAgICAuLi4oc3RlcC5hcmdzIHx8IFtdKSxcbiAgICAgICAgLi4uKHN0ZXAucmVjZWl2ZUFyZ3MgPyBhcmdzIDogW10pLFxuICAgICAgXS5tYXAoKGEpID0+IGEudG9TdHJpbmcoKSk7XG5cbiAgICAgIGlmIChzdGVwLnNheSkge1xuICAgICAgICBsb2dnaW5nLmluZm8odGhpcy5mbXRMb2coc3RlcC5zYXkpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN0ZXAuc3Bhd24pIHtcbiAgICAgICAgdGhpcy5ydW50aW1lLnJ1blRhc2soXG4gICAgICAgICAgc3RlcC5zcGF3bixcbiAgICAgICAgICBbLi4udGhpcy5wYXJlbnRzLCB0aGlzLnRhc2submFtZV0sXG4gICAgICAgICAgYXJnc0xpc3QsXG4gICAgICAgICAgc3RlcC5lbnZcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXhlY3MgPSBzdGVwLmV4ZWMgPyBbc3RlcC5leGVjXSA6IFtdO1xuXG4gICAgICAvLyBQYXJzZSBzdGVwLXNwZWNpZmljIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICAgICAgY29uc3QgZW52ID0gdGhpcy5ldmFsRW52aXJvbm1lbnQoc3RlcC5lbnYgPz8ge30pO1xuXG4gICAgICBpZiAoc3RlcC5idWlsdGluKSB7XG4gICAgICAgIGV4ZWNzLnB1c2godGhpcy5yZW5kZXJCdWlsdGluKHN0ZXAuYnVpbHRpbikpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGV4ZWMgb2YgZXhlY3MpIHtcbiAgICAgICAgbGV0IGhhc0Vycm9yID0gZmFsc2U7XG5cbiAgICAgICAgbGV0IGNvbW1hbmQgPSBtYWtlQ3Jvc3NQbGF0Zm9ybShleGVjKTtcblxuICAgICAgICBpZiAoY29tbWFuZC5pbmNsdWRlcyhRVU9URURfQVJHU19NQVJLRVIpKSB7XG4gICAgICAgICAgLy8gUG9vcmx5IGltaXRhdGUgYmFzaCBxdW90ZWQgdmFyaWFibGUgZXhwYW5zaW9uLiBJZiBcIiRAXCIgaXMgZW5jb3VudGVyZWQgaW4gYmFzaCwgZWxlbWVudHMgb2YgdGhlIGFyZyBhcnJheVxuICAgICAgICAgIC8vIHRoYXQgY29udGFpbiB3aGl0ZXNwYWNlIHdpbGwgYmUgc2luZ2xlIHF1b3RlZCAoJ2FyZycpLiBUaGlzIHByZXNlcnZlcyB3aGl0ZXNwYWNlIGluIHRoaW5ncyBsaWtlIGZpbGVuYW1lcy5cbiAgICAgICAgICAvLyBJbWl0YXRlIHRoYXQgYmVoYXZpb3IgaGVyZSBieSBzaW5nbGUgcXVvdGluZyBldmVyeSBlbGVtZW50IG9mIHRoZSBhcmcgYXJyYXkgd2hlbiBhIHF1b3RlZCBhcmcgbWFya2VyIChcIiRAXCIpXG4gICAgICAgICAgLy8gaXMgZW5jb3VudGVyZWQuXG4gICAgICAgICAgY29tbWFuZCA9IGNvbW1hbmQucmVwbGFjZShcbiAgICAgICAgICAgIFFVT1RFRF9BUkdTX01BUktFUixcbiAgICAgICAgICAgIGFyZ3NMaXN0Lm1hcCgoYXJnKSA9PiBgJyR7YXJnfSdgKS5qb2luKFwiIFwiKVxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoY29tbWFuZC5pbmNsdWRlcyhBUkdTX01BUktFUikpIHtcbiAgICAgICAgICBjb21tYW5kID0gY29tbWFuZC5yZXBsYWNlKEFSR1NfTUFSS0VSLCBhcmdzTGlzdC5qb2luKFwiIFwiKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29tbWFuZCA9IFtjb21tYW5kLCAuLi5hcmdzTGlzdF0uam9pbihcIiBcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjd2QgPSBzdGVwLmN3ZDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLnNoZWxsKHtcbiAgICAgICAgICAgIGNvbW1hbmQsXG4gICAgICAgICAgICBjd2QsXG4gICAgICAgICAgICBleHRyYUVudjogZW52LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGhhc0Vycm9yID0gcmVzdWx0LnN0YXR1cyAhPT0gMDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGVycm9yICdzaHgnIHdpbGwgdGhyb3dcbiAgICAgICAgICBpZiAoKGUgYXMgYW55KT8ubWVzc2FnZT8uc3RhcnRzV2l0aChcIm5vbi16ZXJvIGV4aXQgY29kZTpcIikpIHtcbiAgICAgICAgICAgIGhhc0Vycm9yID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgVGFzayBcIiR7XG4gICAgICAgICAgICAgIHRoaXMuZnVsbG5hbWVcbiAgICAgICAgICAgIH1cIiBmYWlsZWQgd2hlbiBleGVjdXRpbmcgXCIke2NvbW1hbmR9XCIgKGN3ZDogJHtyZXNvbHZlKFxuICAgICAgICAgICAgICBjd2QgPz8gdGhpcy53b3JrZGlyXG4gICAgICAgICAgICApfSlgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIGEgdGFzayBzaG91bGQgYmUgZXhlY3V0ZWQgYmFzZWQgb24gXCJjb25kaXRpb25cIi5cbiAgICpcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgdGFzayBzaG91bGQgYmUgZXhlY3V0ZWQgb3IgZmFsc2UgaWYgdGhlIGNvbmRpdGlvblxuICAgKiBldmFsdWF0ZXMgdG8gZmFsc2UgKGV4aXRzIHdpdGggbm9uLXplcm8pLCBpbmRpY2F0aW5nIHRoYXQgdGhlIHRhc2sgc2hvdWxkXG4gICAqIGJlIHNraXBwZWQuXG4gICAqL1xuICBwcml2YXRlIGV2YWxDb25kaXRpb24odGFza09yU3RlcDogVGFza1NwZWMgfCBUYXNrU3RlcCkge1xuICAgIC8vIG5vIGNvbmRpdGlvbiwgY2Fycnkgb25cbiAgICBpZiAoIXRhc2tPclN0ZXAuY29uZGl0aW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLmxvZyhncmF5KGAke3VuZGVybGluZShcImNvbmRpdGlvblwiKX06ICR7dGFza09yU3RlcC5jb25kaXRpb259YCkpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuc2hlbGwoe1xuICAgICAgY29tbWFuZDogdGFza09yU3RlcC5jb25kaXRpb24sXG4gICAgICBsb2dwcmVmaXg6IFwiY29uZGl0aW9uOiBcIixcbiAgICAgIHF1aWV0OiB0cnVlLFxuICAgIH0pO1xuICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZXMgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZyb20gc2hlbGwgY29tbWFuZHMgKGUuZy4gYCQoeHgpYClcbiAgICovXG4gIHByaXZhdGUgZXZhbEVudmlyb25tZW50KGVudjogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0pIHtcbiAgICBjb25zdCBvdXRwdXQ6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9ID0ge307XG5cbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhlbnYgPz8ge30pKSB7XG4gICAgICBpZiAoU3RyaW5nKHZhbHVlKS5zdGFydHNXaXRoKFwiJChcIikgJiYgU3RyaW5nKHZhbHVlKS5lbmRzV2l0aChcIilcIikpIHtcbiAgICAgICAgY29uc3QgcXVlcnkgPSB2YWx1ZS5zdWJzdHJpbmcoMiwgdmFsdWUubGVuZ3RoIC0gMSk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuc2hlbGxFdmFsKHsgY29tbWFuZDogcXVlcnkgfSk7XG4gICAgICAgIGlmIChyZXN1bHQuc3RhdHVzICE9PSAwKSB7XG4gICAgICAgICAgY29uc3QgZXJyb3IgPSByZXN1bHQuZXJyb3JcbiAgICAgICAgICAgID8gcmVzdWx0LmVycm9yLnN0YWNrXG4gICAgICAgICAgICA6IHJlc3VsdC5zdGRlcnI/LnRvU3RyaW5nKCkgPz8gXCJ1bmtub3duIGVycm9yXCI7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYHVuYWJsZSB0byBldmFsdWF0ZSBlbnZpcm9ubWVudCB2YXJpYWJsZSAke2tleX09JHt2YWx1ZX06ICR7ZXJyb3J9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgb3V0cHV0W2tleV0gPSByZXN1bHQuc3Rkb3V0LnRvU3RyaW5nKFwidXRmLThcIikudHJpbSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0W2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXJzIHRoZSBydW50aW1lIGVudmlyb25tZW50IGZvciBhIHRhc2suIE5hbWVseSwgaXQgc3VwcG9ydHMgdGhpcyBzeW50YXhcbiAgICogYCQoeHgpYCBmb3IgYWxsb3dpbmcgZW52aXJvbm1lbnQgdG8gYmUgZXZhbHVhdGVkIGJ5IGV4ZWN1dGluZyBhIHNoZWxsXG4gICAqIGNvbW1hbmQgYW5kIG9idGFpbmluZyBpdHMgcmVzdWx0LlxuICAgKi9cbiAgcHJpdmF0ZSByZXNvbHZlRW52aXJvbm1lbnQoXG4gICAgZW52UGFyYW06IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9LFxuICAgIHBhcmVudHM6IHN0cmluZ1tdXG4gICkge1xuICAgIGxldCBlbnYgPSB0aGlzLnJ1bnRpbWUubWFuaWZlc3QuZW52ID8/IHt9O1xuXG4gICAgLy8gYWRkIGVudiBmcm9tIGFsbCBwYXJlbnQgdGFza3Mgb25lIGJ5IG9uZVxuICAgIGZvciAoY29uc3QgcGFyZW50IG9mIHBhcmVudHMpIHtcbiAgICAgIGVudiA9IHtcbiAgICAgICAgLi4uZW52LFxuICAgICAgICAuLi4odGhpcy5ydW50aW1lLnRyeUZpbmRUYXNrKHBhcmVudCk/LmVudiA/PyB7fSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIGFwcGx5IHRhc2sgZW52aXJvbm1lbnQsIHRoZW4gdGhlIHNwZWNpZmljIGVudiBsYXN0XG4gICAgZW52ID0ge1xuICAgICAgLi4uZW52LFxuICAgICAgLi4uKHRoaXMudGFzay5lbnYgPz8ge30pLFxuICAgICAgLi4uZW52UGFyYW0sXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLmV2YWxFbnZpcm9ubWVudChlbnYgPz8ge30pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFwiZnVsbCBuYW1lXCIgb2YgdGhlIHRhc2sgd2hpY2ggaW5jbHVkZXMgYWxsIGl0J3MgcGFyZW50IHRhc2sgbmFtZXMgY29uY2F0ZW5hdGVkIGJ5IGNoZXZyb25zLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgZnVsbG5hbWUoKSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLnBhcmVudHMsIHRoaXMudGFzay5uYW1lXS5qb2luKFwiIMK7IFwiKTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgbG9nZ2luZy52ZXJib3NlKHRoaXMuZm10TG9nKC4uLmFyZ3MpKTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nRGVidWcoLi4uYXJnczogYW55W10pIHtcbiAgICBsb2dnaW5nLmRlYnVnKHRoaXMuZm10TG9nKC4uLmFyZ3MpKTtcbiAgfVxuXG4gIHByaXZhdGUgZm10TG9nKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgcmV0dXJuIGZvcm1hdChgJHt1bmRlcmxpbmUodGhpcy5mdWxsbmFtZSl9IHxgLCAuLi5hcmdzKTtcbiAgfVxuXG4gIHByaXZhdGUgc2hlbGwob3B0aW9uczogU2hlbGxPcHRpb25zKSB7XG4gICAgY29uc3QgcXVpZXQgPSBvcHRpb25zLnF1aWV0ID8/IGZhbHNlO1xuICAgIGlmICghcXVpZXQpIHtcbiAgICAgIGNvbnN0IGxvZyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG5cbiAgICAgIGlmIChvcHRpb25zLmxvZ3ByZWZpeCkge1xuICAgICAgICBsb2cucHVzaChvcHRpb25zLmxvZ3ByZWZpeCk7XG4gICAgICB9XG5cbiAgICAgIGxvZy5wdXNoKG9wdGlvbnMuY29tbWFuZCk7XG5cbiAgICAgIGlmIChvcHRpb25zLmN3ZCkge1xuICAgICAgICBsb2cucHVzaChgKGN3ZDogJHtvcHRpb25zLmN3ZH0pYCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubG9nKGxvZy5qb2luKFwiIFwiKSk7XG4gICAgfVxuXG4gICAgY29uc3QgY3dkID0gb3B0aW9ucy5jd2QgPz8gdGhpcy53b3JrZGlyO1xuICAgIGlmICghZXhpc3RzU3luYyhjd2QpIHx8ICFzdGF0U3luYyhjd2QpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYGludmFsaWQgd29ya2RpciAoY3dkKTogJHtjd2R9IG11c3QgYmUgYW4gZXhpc3RpbmcgZGlyZWN0b3J5YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3Bhd25TeW5jKG9wdGlvbnMuY29tbWFuZCwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIGN3ZCxcbiAgICAgIHNoZWxsOiB0cnVlLFxuICAgICAgc3RkaW86IFwiaW5oZXJpdFwiLFxuICAgICAgZW52OiB7XG4gICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICAuLi50aGlzLmVudixcbiAgICAgICAgLi4ub3B0aW9ucy5leHRyYUVudixcbiAgICAgIH0sXG4gICAgICAuLi5vcHRpb25zLnNwYXduT3B0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2hlbGxFdmFsKG9wdGlvbnM6IFNoZWxsT3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLnNoZWxsKHtcbiAgICAgIHF1aWV0OiB0cnVlLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHNwYXduT3B0aW9uczoge1xuICAgICAgICBzdGRpbzogW1wiaW5oZXJpdFwiLCBcInBpcGVcIiwgXCJpbmhlcml0XCJdLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyQnVpbHRpbihidWlsdGluOiBzdHJpbmcpIHtcbiAgICBjb25zdCBtb2R1bGVSb290ID0gZGlybmFtZShyZXF1aXJlLnJlc29sdmUoXCIuLi9wYWNrYWdlLmpzb25cIikpO1xuICAgIGNvbnN0IHByb2dyYW0gPSByZXF1aXJlLnJlc29sdmUoXG4gICAgICBqb2luKG1vZHVsZVJvb3QsIFwibGliXCIsIGAke2J1aWx0aW59LnRhc2suanNgKVxuICAgICk7XG4gICAgcmV0dXJuIGBcIiR7cHJvY2Vzcy5leGVjUGF0aH1cIiBcIiR7cHJvZ3JhbX1cImA7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFNoZWxsT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNvbW1hbmQ6IHN0cmluZztcbiAgLyoqXG4gICAqIEBkZWZhdWx0IC0gcHJvamVjdCBkaXJcbiAgICovXG4gIHJlYWRvbmx5IGN3ZD86IHN0cmluZztcbiAgcmVhZG9ubHkgbG9ncHJlZml4Pzogc3RyaW5nO1xuICByZWFkb25seSBzcGF3bk9wdGlvbnM/OiBTcGF3bk9wdGlvbnM7XG4gIC8qKiBAZGVmYXVsdCBmYWxzZSAqL1xuICByZWFkb25seSBxdWlldD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGV4dHJhRW52PzogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkIH07XG59XG4iXX0=