projen
Version:
CDK for software projects
395 lines • 43.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Task = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const logging_1 = require("./logging");
/**
* A task that can be performed on the project. Modeled as a series of shell
* commands and subtasks.
*/
class Task {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.Task", version: "0.103.12" };
/**
* Task name.
*/
name;
_conditions;
_steps;
_env;
_cwd;
_shell;
requiredEnv;
_locked;
_description;
constructor(name, props = {}) {
this.name = name;
this._description = props.description;
this._conditions = props.condition ? [props.condition] : [];
this._cwd = props.cwd;
this._shell = props.shell;
this._locked = false;
this._env = props.env ?? {};
this._steps = props.steps ?? [];
this.requiredEnv = props.requiredEnv;
if (props.exec && props.steps) {
throw new Error("cannot specify both exec and steps");
}
if (props.execArgs && props.steps) {
throw new Error("cannot specify both execArgs and steps");
}
if (props.exec && props.execArgs) {
throw new Error("cannot specify both exec and execArgs");
}
if (props.exec) {
this.exec(props.exec, { receiveArgs: props.receiveArgs });
}
if (props.execArgs) {
this.execArgs(props.execArgs, { receiveArgs: props.receiveArgs });
}
}
/**
* Forbid additional changes to this task.
*/
lock() {
this._locked = true;
}
/**
* Returns the working directory for this task.
*/
get cwd() {
return this._cwd;
}
/**
* Sets the working directory for this task.
*/
set cwd(cwd) {
this._cwd = cwd;
}
/**
* The shell used to run this task's commands, or `undefined` when inheriting
* the built-in default shell.
* @see {@link TaskCommonOptions.shell}
*/
get shell() {
return this._shell;
}
/**
* Sets the shell used to run this task's commands.
*/
set shell(shell) {
this._shell = shell;
}
/**
* Returns the description of this task.
*/
get description() {
return this._description;
}
/**
* Sets the description of this task.
*/
set description(desc) {
this._description = desc;
}
/**
* A command to execute which determines if the task should be skipped. If it
* returns a zero exit code, the task will not be executed.
*/
get condition() {
if (this._conditions?.length) {
return this._conditions.join(" && ");
}
return undefined;
}
/**
* Add a command to execute which determines if the task should be skipped.
*
* If a condition already exists, the new condition will be appended with ` && ` delimiter.
* @param condition The command to execute.
* @see {@link Task.condition}
*/
addCondition(...condition) {
this._conditions.push(...condition);
}
/**
* Reset the task so it no longer has any commands.
* @param command the first command to add to the task after it was cleared.
*/
reset(command, options = {}) {
this.assertUnlocked();
if (!Array.isArray(this._steps)) {
this.warnForLazyValue("reset");
return;
}
while (this._steps.length) {
this._steps.shift();
}
if (command) {
this.exec(command, options);
}
}
/**
* Adds steps to this task. This is a generic method that accepts any
* task step (exec, spawn, say, builtin).
*
* @param steps The steps to add.
*/
addSteps(...steps) {
this._pushSteps("addSteps", steps);
}
/**
* Executes a shell command
* @param command Shell command
* @param options Options
*/
exec(command, options = {}) {
this._pushSteps("exec", [this.renderStep({ exec: command, ...options })]);
}
/**
* Executes a command provided as a list of the program followed by its
* arguments (an "argv").
*
* A convenient alternative to `Task.exec`: arguments with spaces or
* special characters are passed through as-is, with no quoting needed. The
* elements are not run through a shell, so environment variables (`$FOO`) are
* not expanded and other shell features are unavailable.
*
* @example task.execArgs(["echo", "hello world"]);
*
* @param command The program followed by its arguments.
* @param options Options
*/
execArgs(command, options = {}) {
this._pushSteps("execArgs", [
this.renderStep({ execArgs: command, ...options }),
]);
}
/**
* Execute a builtin task.
*
* Builtin tasks are programs bundled as part of projen itself and used as
* helpers for various components.
*
* In the future we should support built-in tasks from external modules.
*
* @param name The name of the builtin task to execute (e.g.
* `release/resolve-version`).
*/
builtin(name) {
this._pushSteps("builtin", [{ builtin: name }]);
}
/**
* Say something.
* @param message Your message
* @param options Options
*/
say(message, options = {}) {
this._pushSteps("say", [this.renderStep({ say: message, ...options })]);
}
/**
* Spawns a sub-task.
* @param subtask The subtask to execute.
*/
spawn(subtask, options = {}) {
this._pushSteps("spawn", [
this.renderStep({ spawn: subtask.name, ...options }),
]);
}
/**
* Adds steps at the beginning of this task.
*
* @param steps The steps to add.
*/
prependSteps(...steps) {
this._unshiftSteps("prependSteps", steps);
}
/**
* Adds a command at the beginning of the task.
* @param command The command to add.
*/
prependExec(command, options = {}) {
this._unshiftSteps("prependExec", [
this.renderStep({ exec: command, ...options }),
]);
}
/**
* Adds a spawn instruction at the beginning of the task.
* @param subtask The subtask to execute.
*/
prependSpawn(subtask, options = {}) {
this._unshiftSteps("prependSpawn", [
this.renderStep({ spawn: subtask.name, ...options }),
]);
}
/**
* Says something at the beginning of the task.
* @param message Your message
*/
prependSay(message, options = {}) {
this._unshiftSteps("prependSay", [
this.renderStep({ say: message, ...options }),
]);
}
/**
* Renders step options (with a {@link TaskShell}) to the manifest
* {@link TaskStep} form, where `shell` is its `string | string[]` rendering.
*/
renderStep(step) {
const { shell, ...rest } = step;
return shell ? { ...rest, shell: shell._render() } : rest;
}
_pushSteps(method, steps) {
this.assertUnlocked();
if (!Array.isArray(this._steps)) {
this.warnForLazyValue(`${method} to`);
return;
}
this._steps.push(...steps);
}
_unshiftSteps(method, steps) {
this.assertUnlocked();
if (!Array.isArray(this._steps)) {
this.warnForLazyValue(`${method} to`);
return;
}
this._steps.unshift(...steps);
}
/**
* Adds an environment variable to this task.
* @param name The name of the variable
* @param value The value. If the value is surrounded by `$()`, we will
* evaluate it within a subshell and use the result as the value of the
* environment variable.
*/
env(name, value) {
this.assertUnlocked();
this._env[name] = value;
}
/**
* Returns all environment variables in the task level
*/
get envVars() {
return this._env;
}
/**
* Returns an immutable copy of all the step specifications of the task.
*/
get steps() {
// If the list of steps is a Lazy value, we can't know what the steps
// are until synthesis occurs, so just return an empty array.
if (!Array.isArray(this._steps)) {
return [];
}
return [...this._steps];
}
/**
* Insert one or more steps at a given index
*
* @param index Steps will be inserted before this index. May be negative to
* count backwards from the end, or may be `== steps().length` to insert at the end.
* @param steps The steps to insert
*/
insertStep(index, ...steps) {
this.assertUnlocked();
if (!Array.isArray(this._steps)) {
this.warnForLazyValue("insert steps into");
return;
}
if (index < -this._steps.length || index > this.steps.length) {
throw new Error(`Cannot insert steps at index ${index} for task ${this.name} because the index is out of bounds for size ${this.steps.length}`);
}
this._steps.splice(index, 0, ...steps);
}
/**
*
* @param index The index of the step to edit
* @param step The new step to replace the old one entirely, it is not merged with the old step
*/
updateStep(index, step) {
this.assertUnlocked();
if (!Array.isArray(this._steps)) {
this.warnForLazyValue("update step for");
return;
}
const existingStep = this._steps[index];
if (!existingStep) {
throw new Error(`Cannot update step at index ${index} for task ${this.name} because it does not exist`);
}
this._steps[index] = step;
}
/**
*
* @param index The index of the step to remove
*/
removeStep(index) {
this.assertUnlocked();
if (!Array.isArray(this._steps)) {
this.warnForLazyValue("remove step from");
return;
}
const existingStep = this._steps[index];
if (!existingStep) {
throw new Error(`Cannot remove step at index ${index} for task ${this.name} because it does not exist`);
}
this._steps.splice(index, 1);
}
/**
* Renders a task spec into the manifest.
*
* @internal
*/
_renderSpec() {
// Ensure task-level env vars are strings
const env = Object.keys(this._env).reduce((prev, curr) => ({
...prev,
[curr]: this.getEnvString(curr, this._env[curr]),
}), {});
// Ensure step-level env vars are strings
const steps = Array.isArray(this._steps)
? [...this._steps].map((s) => {
return s.env
? {
...s,
env: Object.keys(s.env).reduce((prev, curr) => ({
...prev,
[curr]: this.getEnvString(curr, s.env[curr]),
}), {}),
}
: s;
})
: this._steps;
return {
name: this.name,
description: this.description,
env: env,
requiredEnv: this.requiredEnv,
steps: steps,
condition: this.condition,
cwd: this._cwd,
shell: this._shell?._render(),
};
}
assertUnlocked() {
if (this._locked) {
throw new Error(`Task "${this.name}" is locked for changes`);
}
}
warnForLazyValue(actionBeingUndertaken) {
(0, logging_1.warn)(`Cannot ${actionBeingUndertaken} task "${this.name}" because it is a lazy value, try using the preSynthesize phase.`);
}
/**
* Ensure that environment variables are persisted as strings
* to prevent type errors when parsing from tasks.json in future
*/
getEnvString(name, value) {
if (typeof value !== "string" && value !== undefined) {
(0, logging_1.warn)(`Received non-string value for environment variable ${name}. Value will be stringified.`);
return String(value);
}
else {
return value;
}
}
}
exports.Task = Task;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90YXNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSx1Q0FBaUM7QUE2RGpDOzs7R0FHRztBQUNILE1BQWEsSUFBSTs7SUFDZjs7T0FFRztJQUNhLElBQUksQ0FBUztJQUVaLFdBQVcsQ0FBVztJQUN0QixNQUFNLENBQWE7SUFDbkIsSUFBSSxDQUE2QjtJQUMxQyxJQUFJLENBQXNCO0lBQzFCLE1BQU0sQ0FBeUI7SUFFdEIsV0FBVyxDQUFZO0lBQ2hDLE9BQU8sQ0FBVTtJQUNqQixZQUFZLENBQVU7SUFFOUIsWUFBWSxJQUFZLEVBQUUsUUFBcUIsRUFBRTtRQUMvQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7UUFDdEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzVELElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUN0QixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDMUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUU1QixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUVyQyxJQUFJLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMs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SSxDQUFDLElBQUksa0VBQWtFLENBQ3JILENBQUM7SUFDSixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssWUFBWSxDQUFDLElBQVksRUFBRSxLQUFVO1FBQzNDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNyRCxJQUFBLGNBQUksRUFDRixzREFBc0QsSUFBSSw4QkFBOEIsQ0FDekYsQ0FBQztZQUNGLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQzs7QUExY0gsb0JBMmNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgd2FybiB9IGZyb20gXCIuL2xvZ2dpbmdcIjtcbmltcG9ydCB0eXBlIHtcbiAgVGFza0NvbW1vbk9wdGlvbnMsXG4gIFRhc2tTcGVjLFxuICBUYXNrU3RlcCxcbiAgVGFza1N0ZXBPcHRpb25zLFxufSBmcm9tIFwiLi90YXNrLW1vZGVsXCI7XG5pbXBvcnQgdHlwZSB7IFRhc2tTaGVsbCB9IGZyb20gXCIuL3Rhc2stc2hlbGxcIjtcblxuZXhwb3J0IGludGVyZmFjZSBUYXNrT3B0aW9ucyBleHRlbmRzIFRhc2tDb21tb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFNoZWxsIGNvbW1hbmQgdG8gZXhlY3V0ZSBhcyB0aGUgZmlyc3QgY29tbWFuZCBvZiB0aGUgdGFzay5cbiAgICpcbiAgICogQSBzaW5nbGUgc2hlbGwgc3RyaW5nLCBzbyBvbmx5IHBhc3MgdHJ1c3RlZCBpbnB1dDogYW4gaW50ZXJwb2xhdGVkIHZhbHVlIGlzXG4gICAqIGludGVycHJldGVkIGJ5IHRoZSBzaGVsbCB0b28uIFVzZSBgZXhlY0FyZ3NgIGZvciBhcmd1bWVudHMgeW91IGRpZCBub3Qgd3JpdGVcbiAgICogbGl0ZXJhbGx5LlxuICAgKlxuICAgKiBNdXR1YWxseSBleGNsdXNpdmUgd2l0aCBgZXhlY0FyZ3NgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGFkZCBzdGVwcyB1c2luZyBgdGFzay5leGVjKGNvbW1hbmQpYCBvciBgdGFzay5zcGF3bihzdWJ0YXNrKWBcbiAgICovXG4gIHJlYWRvbmx5IGV4ZWM/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNoZWxsIGNvbW1hbmQgdG8gZXhlY3V0ZSBhcyB0aGUgZmlyc3QgY29tbWFuZCBvZiB0aGUgdGFzaywgcHJvdmlkZWQgYXMgYVxuICAgKiBsaXN0IG9mIHRoZSBwcm9ncmFtIGZvbGxvd2VkIGJ5IGl0cyBhcmd1bWVudHMgKGFuIFwiYXJndlwiKS5cbiAgICpcbiAgICogQSBjb252ZW5pZW50IGFsdGVybmF0aXZlIHRvIGBleGVjYDogYXJndW1lbnRzIHdpdGggc3BhY2VzIG9yIHNwZWNpYWxcbiAgICogY2hhcmFjdGVycyBhcmUgcGFzc2VkIHRocm91Z2ggYXMtaXMsIHdpdGggbm8gcXVvdGluZyBuZWVkZWQuIFRoZSBlbGVtZW50c1xuICAgKiBhcmUgbm90IHJ1biB0aHJvdWdoIGEgc2hlbGwsIHNvIGVudmlyb25tZW50IHZhcmlhYmxlcyAoYCRGT09gKSBhcmUgbm90XG4gICAqIGV4cGFuZGVkIGFuZCBvdGhlciBzaGVsbCBmZWF0dXJlcyBhcmUgdW5hdmFpbGFibGUuXG4gICAqIEBzZWUgVGFza1N0ZXAuZXhlY0FyZ3NcbiAgICpcbiAgICogTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGV4ZWNgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGFkZCBzdGVwcyB1c2luZyBgdGFzay5leGVjQXJncyhhcmdzKWAsIGB0YXNrLmV4ZWMoY29tbWFuZClgIG9yIGB0YXNrLnNwYXduKHN1YnRhc2spYFxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY0FyZ3M/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTGlzdCBvZiB0YXNrIHN0ZXBzIHRvIHJ1bi5cbiAgICovXG4gIHJlYWRvbmx5IHN0ZXBzPzogVGFza1N0ZXBbXTtcblxuICAvKipcbiAgICogU2hvdWxkIHRoZSBwcm92aWRlZCBgZXhlY2Agc2hlbGwgY29tbWFuZCByZWNlaXZlIGFyZ3MgcGFzc2VkIHRvIHRoZSB0YXNrLlxuICAgKiBAc2VlIHtAbGluayBUYXNrU3RlcE9wdGlvbnMucmVjZWl2ZUFyZ3N9XG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSByZWNlaXZlQXJncz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNob3VsZCB0aGUgcHJvdmlkZWQgYGV4ZWNgIHNoZWxsIGNvbW1hbmQgcmVjZWl2ZSBmaXhlZCBhcmdzLlxuICAgKiBAc2VlIHtAbGluayBUYXNrU3RlcE9wdGlvbnMuYXJnc31cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byB0aGUgc3RlcFxuICAgKi9cbiAgcmVhZG9ubHkgYXJncz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIEEgdGFzayB0aGF0IGNhbiBiZSBwZXJmb3JtZWQgb24gdGhlIHByb2plY3QuIE1vZGVsZWQgYXMgYSBzZXJpZXMgb2Ygc2hlbGxcbiAqIGNvbW1hbmRzIGFuZCBzdWJ0YXNrcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFRhc2sge1xuICAvKipcbiAgICogVGFzayBuYW1lLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IF9jb25kaXRpb25zOiBzdHJpbmdbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBfc3RlcHM6IFRhc2tTdGVwW107XG4gIHByaXZhdGUgcmVhZG9ubHkgX2VudjogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH07XG4gIHByaXZhdGUgX2N3ZD86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfc2hlbGw/OiBUYXNrU2hlbGwgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSByZWFkb25seSByZXF1aXJlZEVudj86IHN0cmluZ1tdO1xuICBwcml2YXRlIF9sb2NrZWQ6IGJvb2xlYW47XG4gIHByaXZhdGUgX2Rlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgcHJvcHM6IFRhc2tPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgIHRoaXMuX2Rlc2NyaXB0aW9uID0gcHJvcHMuZGVzY3JpcHRpb247XG4gICAgdGhpcy5fY29uZGl0aW9ucyA9IHByb3BzLmNvbmRpdGlvbiA/IFtwcm9wcy5jb25kaXRpb25dIDogW107XG4gICAgdGhpcy5fY3dkID0gcHJvcHMuY3dkO1xuICAgIHRoaXMuX3NoZWxsID0gcHJvcHMuc2hlbGw7XG4gICAgdGhpcy5fbG9ja2VkID0gZmFsc2U7XG4gICAgdGhpcy5fZW52ID0gcHJvcHMuZW52ID8/IHt9O1xuXG4gICAgdGhpcy5fc3RlcHMgPSBwcm9wcy5zdGVwcyA/PyBbXTtcbiAgICB0aGlzLnJlcXVpcmVkRW52ID0gcHJvcHMucmVxdWlyZWRFbnY7XG5cbiAgICBpZiAocHJvcHMuZXhlYyAmJiBwcm9wcy5zdGVwcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY2Fubm90IHNwZWNpZnkgYm90aCBleGVjIGFuZCBzdGVwc1wiKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuZXhlY0FyZ3MgJiYgcHJvcHMuc3RlcHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImNhbm5vdCBzcGVjaWZ5IGJvdGggZXhlY0FyZ3MgYW5kIHN0ZXBzXCIpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5leGVjICYmIHByb3BzLmV4ZWNBcmdzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjYW5ub3Qgc3BlY2lmeSBib3RoIGV4ZWMgYW5kIGV4ZWNBcmdzXCIpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5leGVjKSB7XG4gICAgICB0aGlzLmV4ZWMocHJvcHMuZXhlYywgeyByZWNlaXZlQXJnczogcHJvcHMucmVjZWl2ZUFyZ3MgfSk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmV4ZWNBcmdzKSB7XG4gICAgICB0aGlzLmV4ZWNBcmdzKHByb3BzLmV4ZWNBcmdzLCB7IHJlY2VpdmVBcmdzOiBwcm9wcy5yZWNlaXZlQXJncyB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRm9yYmlkIGFkZGl0aW9uYWwgY2hhbmdlcyB0byB0aGlzIHRhc2suXG4gICAqL1xuICBwdWJsaWMgbG9jaygpIHtcbiAgICB0aGlzLl9sb2NrZWQgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGZvciB0aGlzIHRhc2suXG4gICAqL1xuICBwdWJsaWMgZ2V0IGN3ZCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9jd2Q7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgd29ya2luZyBkaXJlY3RvcnkgZm9yIHRoaXMgdGFzay5cbiAgICovXG4gIHB1YmxpYyBzZXQgY3dkKGN3ZDogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fY3dkID0gY3dkO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzaGVsbCB1c2VkIHRvIHJ1biB0aGlzIHRhc2sncyBjb21tYW5kcywgb3IgYHVuZGVmaW5lZGAgd2hlbiBpbmhlcml0aW5nXG4gICAqIHRoZSBidWlsdC1pbiBkZWZhdWx0IHNoZWxsLlxuICAgKiBAc2VlIHtAbGluayBUYXNrQ29tbW9uT3B0aW9ucy5zaGVsbH1cbiAgICovXG4gIHB1YmxpYyBnZXQgc2hlbGwoKTogVGFza1NoZWxsIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fc2hlbGw7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgc2hlbGwgdXNlZCB0byBydW4gdGhpcyB0YXNrJ3MgY29tbWFuZHMuXG4gICAqL1xuICBwdWJsaWMgc2V0IHNoZWxsKHNoZWxsOiBUYXNrU2hlbGwgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9zaGVsbCA9IHNoZWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGRlc2NyaXB0aW9uIG9mIHRoaXMgdGFzay5cbiAgICovXG4gIHB1YmxpYyBnZXQgZGVzY3JpcHRpb24oKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fZGVzY3JpcHRpb247XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZGVzY3JpcHRpb24gb2YgdGhpcyB0YXNrLlxuICAgKi9cbiAgcHVibGljIHNldCBkZXNjcmlwdGlvbihkZXNjOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9kZXNjcmlwdGlvbiA9IGRlc2M7XG4gIH1cblxuICAvKipcbiAgICogQSBjb21tYW5kIHRvIGV4ZWN1dGUgd2hpY2ggZGV0ZXJtaW5lcyBpZiB0aGUgdGFzayBzaG91bGQgYmUgc2tpcHBlZC4gSWYgaXRcbiAgICogcmV0dXJucyBhIHplcm8gZXhpdCBjb2RlLCB0aGUgdGFzayB3aWxsIG5vdCBiZSBleGVjdXRlZC5cbiAgICovXG4gIHB1YmxpYyBnZXQgY29uZGl0aW9uKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuX2NvbmRpdGlvbnM/Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbmRpdGlvbnMuam9pbihcIiAmJiBcIik7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgY29tbWFuZCB0byBleGVjdXRlIHdoaWNoIGRldGVybWluZXMgaWYgdGhlIHRhc2sgc2hvdWxkIGJlIHNraXBwZWQuXG4gICAqXG4gICAqIElmIGEgY29uZGl0aW9uIGFscmVhZHkgZXhpc3RzLCB0aGUgbmV3IGNvbmRpdGlvbiB3aWxsIGJlIGFwcGVuZGVkIHdpdGggYCAmJiBgIGRlbGltaXRlci5cbiAgICogQHBhcmFtIGNvbmRpdGlvbiBUaGUgY29tbWFuZCB0byBleGVjdXRlLlxuICAgKiBAc2VlIHtAbGluayBUYXNrLmNvbmRpdGlvbn1cbiAgICovXG4gIHB1YmxpYyBhZGRDb25kaXRpb24oLi4uY29uZGl0aW9uOiBzdHJpbmdbXSk6IHZvaWQge1xuICAgIHRoaXMuX2NvbmRpdGlvbnMucHVzaCguLi5jb25kaXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSB0YXNrIHNvIGl0IG5vIGxvbmdlciBoYXMgYW55IGNvbW1hbmRzLlxuICAgKiBAcGFyYW0gY29tbWFuZCB0aGUgZmlyc3QgY29tbWFuZCB0byBhZGQgdG8gdGhlIHRhc2sgYWZ0ZXIgaXQgd2FzIGNsZWFyZWQuXG4gICAqL1xuICBwdWJsaWMgcmVzZXQoY29tbWFuZD86IHN0cmluZywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLmFzc2VydFVubG9ja2VkKCk7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICB0aGlzLndhcm5Gb3JMYXp5VmFsdWUoXCJyZXNldFwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aGlsZSAodGhpcy5fc3RlcHMubGVuZ3RoKSB7XG4gICAgICB0aGlzLl9zdGVwcy5zaGlmdCgpO1xuICAgIH1cblxuICAgIGlmIChjb21tYW5kKSB7XG4gICAgICB0aGlzLmV4ZWMoY29tbWFuZCwgb3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgc3RlcHMgdG8gdGhpcyB0YXNrLiBUaGlzIGlzIGEgZ2VuZXJpYyBtZXRob2QgdGhhdCBhY2NlcHRzIGFueVxuICAgKiB0YXNrIHN0ZXAgKGV4ZWMsIHNwYXduLCBzYXksIGJ1aWx0aW4pLlxuICAgKlxuICAgKiBAcGFyYW0gc3RlcHMgVGhlIHN0ZXBzIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBhZGRTdGVwcyguLi5zdGVwczogVGFza1N0ZXBbXSkge1xuICAgIHRoaXMuX3B1c2hTdGVwcyhcImFkZFN0ZXBzXCIsIHN0ZXBzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyBhIHNoZWxsIGNvbW1hbmRcbiAgICogQHBhcmFtIGNvbW1hbmQgU2hlbGwgY29tbWFuZFxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zXG4gICAqL1xuICBwdWJsaWMgZXhlYyhjb21tYW5kOiBzdHJpbmcsIG9wdGlvbnM6IFRhc2tTdGVwT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fcHVzaFN0ZXBzKFwiZXhlY1wiLCBbdGhpcy5yZW5kZXJTdGVwKHsgZXhlYzogY29tbWFuZCwgLi4ub3B0aW9ucyB9KV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGVzIGEgY29tbWFuZCBwcm92aWRlZCBhcyBhIGxpc3Qgb2YgdGhlIHByb2dyYW0gZm9sbG93ZWQgYnkgaXRzXG4gICAqIGFyZ3VtZW50cyAoYW4gXCJhcmd2XCIpLlxuICAgKlxuICAgKiBBIGNvbnZlbmllbnQgYWx0ZXJuYXRpdmUgdG8gYFRhc2suZXhlY2A6IGFyZ3VtZW50cyB3aXRoIHNwYWNlcyBvclxuICAgKiBzcGVjaWFsIGNoYXJhY3RlcnMgYXJlIHBhc3NlZCB0aHJvdWdoIGFzLWlzLCB3aXRoIG5vIHF1b3RpbmcgbmVlZGVkLiBUaGVcbiAgICogZWxlbWVudHMgYXJlIG5vdCBydW4gdGhyb3VnaCBhIHNoZWxsLCBzbyBlbnZpcm9ubWVudCB2YXJpYWJsZXMgKGAkRk9PYCkgYXJlXG4gICAqIG5vdCBleHBhbmRlZCBhbmQgb3RoZXIgc2hlbGwgZmVhdHVyZXMgYXJlIHVuYXZhaWxhYmxlLlxuICAgKlxuICAgKiBAZXhhbXBsZSB0YXNrLmV4ZWNBcmdzKFtcImVjaG9cIiwgXCJoZWxsbyB3b3JsZFwiXSk7XG4gICAqXG4gICAqIEBwYXJhbSBjb21tYW5kIFRoZSBwcm9ncmFtIGZvbGxvd2VkIGJ5IGl0cyBhcmd1bWVudHMuXG4gICAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBleGVjQXJncyhjb21tYW5kOiBzdHJpbmdbXSwgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl9wdXNoU3RlcHMoXCJleGVjQXJnc1wiLCBbXG4gICAgICB0aGlzLnJlbmRlclN0ZXAoeyBleGVjQXJnczogY29tbWFuZCwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGEgYnVpbHRpbiB0YXNrLlxuICAgKlxuICAgKiBCdWlsdGluIHRhc2tzIGFyZSBwcm9ncmFtcyBidW5kbGVkIGFzIHBhcnQgb2YgcHJvamVuIGl0c2VsZiBhbmQgdXNlZCBhc1xuICAgKiBoZWxwZXJzIGZvciB2YXJpb3VzIGNvbXBvbmVudHMuXG4gICAqXG4gICAqIEluIHRoZSBmdXR1cmUgd2Ugc2hvdWxkIHN1cHBvcnQgYnVpbHQtaW4gdGFza3MgZnJvbSBleHRlcm5hbCBtb2R1bGVzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgYnVpbHRpbiB0YXNrIHRvIGV4ZWN1dGUgKGUuZy5cbiAgICogYHJlbGVhc2UvcmVzb2x2ZS12ZXJzaW9uYCkuXG4gICAqL1xuICBwdWJsaWMgYnVpbHRpbihuYW1lOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9wdXNoU3RlcHMoXCJidWlsdGluXCIsIFt7IGJ1aWx0aW46IG5hbWUgfV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNheSBzb21ldGhpbmcuXG4gICAqIEBwYXJhbSBtZXNzYWdlIFlvdXIgbWVzc2FnZVxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zXG4gICAqL1xuICBwdWJsaWMgc2F5KG1lc3NhZ2U6IHN0cmluZywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl9wdXNoU3RlcHMoXCJzYXlcIiwgW3RoaXMucmVuZGVyU3RlcCh7IHNheTogbWVzc2FnZSwgLi4ub3B0aW9ucyB9KV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwYXducyBhIHN1Yi10YXNrLlxuICAgKiBAcGFyYW0gc3VidGFzayBUaGUgc3VidGFzayB0byBleGVjdXRlLlxuICAgKi9cbiAgcHVibGljIHNwYXduKHN1YnRhc2s6IFRhc2ssIG9wdGlvbnM6IFRhc2tTdGVwT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fcHVzaFN0ZXBzKFwic3Bhd25cIiwgW1xuICAgICAgdGhpcy5yZW5kZXJTdGVwKHsgc3Bhd246IHN1YnRhc2submFtZSwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIHN0ZXBzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhpcyB0YXNrLlxuICAgKlxuICAgKiBAcGFyYW0gc3RlcHMgVGhlIHN0ZXBzIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kU3RlcHMoLi4uc3RlcHM6IFRhc2tTdGVwW10pIHtcbiAgICB0aGlzLl91bnNoaWZ0U3RlcHMoXCJwcmVwZW5kU3RlcHNcIiwgc3RlcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBjb21tYW5kIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHRhc2suXG4gICAqIEBwYXJhbSBjb21tYW5kIFRoZSBjb21tYW5kIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kRXhlYyhjb21tYW5kOiBzdHJpbmcsIG9wdGlvbnM6IFRhc2tTdGVwT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fdW5zaGlmdFN0ZXBzKFwicHJlcGVuZEV4ZWNcIiwgW1xuICAgICAgdGhpcy5yZW5kZXJTdGVwKHsgZXhlYzogY29tbWFuZCwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgc3Bhd24gaW5zdHJ1Y3Rpb24gYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdGFzay5cbiAgICogQHBhcmFtIHN1YnRhc2sgVGhlIHN1YnRhc2sgdG8gZXhlY3V0ZS5cbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kU3Bhd24oc3VidGFzazogVGFzaywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl91bnNoaWZ0U3RlcHMoXCJwcmVwZW5kU3Bhd25cIiwgW1xuICAgICAgdGhpcy5yZW5kZXJTdGVwKHsgc3Bhd246IHN1YnRhc2submFtZSwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXlzIHNvbWV0aGluZyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB0YXNrLlxuICAgKiBAcGFyYW0gbWVzc2FnZSBZb3VyIG1lc3NhZ2VcbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kU2F5KG1lc3NhZ2U6IHN0cmluZywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl91bnNoaWZ0U3RlcHMoXCJwcmVwZW5kU2F5XCIsIFtcbiAgICAgIHRoaXMucmVuZGVyU3RlcCh7IHNheTogbWVzc2FnZSwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXJzIHN0ZXAgb3B0aW9ucyAod2l0aCBhIHtAbGluayBUYXNrU2hlbGx9KSB0byB0aGUgbWFuaWZlc3RcbiAgICoge0BsaW5rIFRhc2tTdGVwfSBmb3JtLCB3aGVyZSBgc2hlbGxgIGlzIGl0cyBgc3RyaW5nIHwgc3RyaW5nW11gIHJlbmRlcmluZy5cbiAgICovXG4gIHByaXZhdGUgcmVuZGVyU3RlcChcbiAgICBzdGVwOiB7IHJlYWRvbmx5IHNoZWxsPzogVGFza1NoZWxsIH0gJiBPbWl0PFRhc2tTdGVwLCBcInNoZWxsXCI+LFxuICApOiBUYXNrU3RlcCB7XG4gICAgY29uc3QgeyBzaGVsbCwgLi4ucmVzdCB9ID0gc3RlcDtcbiAgICByZXR1cm4gc2hlbGwgPyB7IC4uLnJlc3QsIHNoZWxsOiBzaGVsbC5fcmVuZGVyKCkgfSA6IHJlc3Q7XG4gIH1cblxuICBwcml2YXRlIF9wdXNoU3RlcHMobWV0aG9kOiBzdHJpbmcsIHN0ZXBzOiBUYXNrU3RlcFtdKSB7XG4gICAgdGhpcy5hc3NlcnRVbmxvY2tlZCgpO1xuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMuX3N0ZXBzKSkge1xuICAgICAgdGhpcy53YXJuRm9yTGF6eVZhbHVlKGAke21ldGhvZH0gdG9gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGVwcy5wdXNoKC4uLnN0ZXBzKTtcbiAgfVxuXG4gIHByaXZhdGUgX3Vuc2hpZnRTdGVwcyhtZXRob2Q6IHN0cmluZywgc3RlcHM6IFRhc2tTdGVwW10pIHtcbiAgICB0aGlzLmFzc2VydFVubG9ja2VkKCk7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICB0aGlzLndhcm5Gb3JMYXp5VmFsdWUoYCR7bWV0aG9kfSB0b2ApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX3N0ZXBzLnVuc2hpZnQoLi4uc3RlcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUgdG8gdGhpcyB0YXNrLlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdmFyaWFibGVcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZS4gSWYgdGhlIHZhbHVlIGlzIHN1cnJvdW5kZWQgYnkgYCQoKWAsIHdlIHdpbGxcbiAgICogZXZhbHVhdGUgaXQgd2l0aGluIGEgc3Vic2hlbGwgYW5kIHVzZSB0aGUgcmVzdWx0IGFzIHRoZSB2YWx1ZSBvZiB0aGVcbiAgICogZW52aXJvbm1lbnQgdmFyaWFibGUuXG4gICAqL1xuICBwdWJsaWMgZW52KG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuYXNzZXJ0VW5sb2NrZWQoKTtcbiAgICB0aGlzLl9lbnZbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIHRhc2sgbGV2ZWxcbiAgICovXG4gIHB1YmxpYyBnZXQgZW52VmFycygpOiBSZWFkb25seTx7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfT4ge1xuICAgIHJldHVybiB0aGlzLl9lbnY7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBpbW11dGFibGUgY29weSBvZiBhbGwgdGhlIHN0ZXAgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHRhc2suXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0ZXBzKCk6IFRhc2tTdGVwW10ge1xuICAgIC8vIElmIHRoZSBsaXN0IG9mIHN0ZXBzIGlzIGEgTGF6eSB2YWx1ZSwgd2UgY2FuJ3Qga25vdyB3aGF0IHRoZSBzdGVwc1xuICAgIC8vIGFyZSB1bnRpbCBzeW50aGVzaXMgb2NjdXJzLCBzbyBqdXN0IHJldHVybiBhbiBlbXB0eSBhcnJheS5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHJldHVybiBbLi4udGhpcy5fc3RlcHNdO1xuICB9XG5cbiAgLyoqXG4gICAqIEluc2VydCBvbmUgb3IgbW9yZSBzdGVwcyBhdCBhIGdpdmVuIGluZGV4XG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBTdGVwcyB3aWxsIGJlIGluc2VydGVkIGJlZm9yZSB0aGlzIGluZGV4LiBNYXkgYmUgbmVnYXRpdmUgdG9cbiAgICogY291bnQgYmFja3dhcmRzIGZyb20gdGhlIGVuZCwgb3IgbWF5IGJlIGA9PSBzdGVwcygpLmxlbmd0aGAgdG8gaW5zZXJ0IGF0IHRoZSBlbmQuXG4gICAqIEBwYXJhbSBzdGVwcyBUaGUgc3RlcHMgdG8gaW5zZXJ0XG4gICAqL1xuICBwdWJsaWMgaW5zZXJ0U3RlcChpbmRleDogbnVtYmVyLCAuLi5zdGVwczogVGFza1N0ZXBbXSk6IHZvaWQge1xuICAgIHRoaXMuYXNzZXJ0VW5sb2NrZWQoKTtcblxuICAgIGlmICghQXJyYXkuaXNBcnJheSh0aGlzLl9zdGVwcykpIHtcbiAgICAgIHRoaXMud2FybkZvckxhenlWYWx1ZShcImluc2VydCBzdGVwcyBpbnRvXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChpbmRleCA8IC10aGlzLl9zdGVwcy5sZW5ndGggfHwgaW5kZXggPiB0aGlzLnN0ZXBzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ2Fubm90IGluc2VydCBzdGVwcyBhdCBpbmRleCAke2luZGV4fSBmb3IgdGFzayAke3RoaXMubmFtZX0gYmVjYXVzZSB0aGUgaW5kZXggaXMgb3V0IG9mIGJvdW5kcyBmb3Igc2l6ZSAke3RoaXMuc3RlcHMubGVuZ3RofWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuX3N0ZXBzLnNwbGljZShpbmRleCwgMCwgLi4uc3RlcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHN0ZXAgdG8gZWRpdFxuICAgKiBAcGFyYW0gc3RlcCBUaGUgbmV3IHN0ZXAgdG8gcmVwbGFjZSB0aGUgb2xkIG9uZSBlbnRpcmVseSwgaXQgaXMgbm90IG1lcmdlZCB3aXRoIHRoZSBvbGQgc3RlcFxuICAgKi9cbiAgcHVibGljIHVwZGF0ZVN0ZXAoaW5kZXg6IG51bWJlciwgc3RlcDogVGFza1N0ZXApOiB2b2lkIHtcbiAgICB0aGlzLmFzc2VydFVubG9ja2VkKCk7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICB0aGlzLndhcm5Gb3JMYXp5VmFsdWUoXCJ1cGRhdGUgc3RlcCBmb3JcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmdTdGVwID0gdGhpcy5fc3RlcHNbaW5kZXhdO1xuICAgIGlmICghZXhpc3RpbmdTdGVwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgdXBkYXRlIHN0ZXAgYXQgaW5kZXggJHtpbmRleH0gZm9yIHRhc2sgJHt0aGlzLm5hbWV9IGJlY2F1c2UgaXQgZG9lcyBub3QgZXhpc3RgLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGVwc1tpbmRleF0gPSBzdGVwO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHN0ZXAgdG8gcmVtb3ZlXG4gICAqL1xuICBwdWJsaWMgcmVtb3ZlU3RlcChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5hc3NlcnRVbmxvY2tlZCgpO1xuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMuX3N0ZXBzKSkge1xuICAgICAgdGhpcy53YXJuRm9yTGF6eVZhbHVlKFwicmVtb3ZlIHN0ZXAgZnJvbVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZ1N0ZXAgPSB0aGlzLl9zdGVwc1tpbmRleF07XG4gICAgaWYgKCFleGlzdGluZ1N0ZXApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYENhbm5vdCByZW1vdmUgc3RlcCBhdCBpbmRleCAke2luZGV4fSBmb3IgdGFzayAke3RoaXMubmFtZX0gYmVjYXVzZSBpdCBkb2VzIG5vdCBleGlzdGAsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuX3N0ZXBzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVycyBhIHRhc2sgc3BlYyBpbnRvIHRoZSBtYW5pZmVzdC5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3JlbmRlclNwZWMoKTogVGFza1NwZWMge1xuICAgIC8vIEVuc3VyZSB0YXNrLWxldmVsIGVudiB2YXJzIGFyZSBzdHJpbmdzXG4gICAgY29uc3QgZW52ID0gT2JqZWN0LmtleXModGhpcy5fZW52KS5yZWR1Y2UoXG4gICAgICAocHJldiwgY3VycikgPT4gKHtcbiAgICAgICAgLi4ucHJldixcbiAgICAgICAgW2N1cnJdOiB0aGlzLmdldEVudlN0cmluZyhjdXJyLCB0aGlzLl9lbnZbY3Vycl0pLFxuICAgICAgfSksXG4gICAgICB7fSxcbiAgICApO1xuXG4gICAgLy8gRW5zdXJlIHN0ZXAtbGV2ZWwgZW52IHZhcnMgYXJlIHN0cmluZ3NcbiAgICBjb25zdCBzdGVwcyA9IEFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpXG4gICAgICA/IFsuLi50aGlzLl9zdGVwc10ubWFwKChzKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHMuZW52XG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAuLi5zLFxuICAgICAgICAgICAgICAgIGVudjogT2JqZWN0LmtleXMocy5lbnYpLnJlZHVjZShcbiAgICAgICAgICAgICAgICAgIChwcmV2LCBjdXJyKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAuLi5wcmV2LFxuICAgICAgICAgICAgICAgICAgICBbY3Vycl06IHRoaXMuZ2V0RW52U3RyaW5nKGN1cnIsIHMuZW52IVtjdXJyXSksXG4gICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDogcztcbiAgICAgICAgfSlcbiAgICAgIDogdGhpcy5fc3RlcHM7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IHRoaXMuZGVzY3JpcHRpb24sXG4gICAgICBlbnY6IGVudixcbiAgICAgIHJlcXVpcmVkRW52OiB0aGlzLnJlcXVpcmVkRW52LFxuICAgICAgc3RlcHM6IHN0ZXBzLFxuICAgICAgY29uZGl0aW9uOiB0aGlzLmNvbmRpdGlvbixcbiAgICAgIGN3ZDogdGhpcy5fY3dkLFxuICAgICAgc2hlbGw6IHRoaXMuX3NoZWxsPy5fcmVuZGVyKCksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXNzZXJ0VW5sb2NrZWQoKSB7XG4gICAgaWYgKHRoaXMuX2xvY2tlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUYXNrIFwiJHt0aGlzLm5hbWV9XCIgaXMgbG9ja2VkIGZvciBjaGFuZ2VzYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB3YXJuRm9yTGF6eVZhbHVlKGFjdGlvbkJlaW5nVW5kZXJ0YWtlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgd2FybihcbiAgICAgIGBDYW5ub3QgJHthY3Rpb25CZWluZ1VuZGVydGFrZW59IHRhc2sgXCIke3RoaXMubmFtZX1cIiBiZWNhdXNlIGl0IGlzIGEgbGF6eSB2YWx1ZSwgdHJ5IHVzaW5nIHRoZSBwcmVTeW50aGVzaXplIHBoYXNlLmAsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmUgdGhhdCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYXJlIHBlcnNpc3RlZCBhcyBzdHJpbmdzXG4gICAqIHRvIHByZXZlbnQgdHlwZSBlcnJvcnMgd2hlbiBwYXJzaW5nIGZyb20gdGFza3MuanNvbiBpbiBmdXR1cmVcbiAgICovXG4gIHByaXZhdGUgZ2V0RW52U3RyaW5nKG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgd2FybihcbiAgICAgICAgYFJlY2VpdmVkIG5vbi1zdHJpbmcgdmFsdWUgZm9yIGVudmlyb25tZW50IHZhcmlhYmxlICR7bmFtZX0uIFZhbHVlIHdpbGwgYmUgc3RyaW5naWZpZWQuYCxcbiAgICAgICk7XG4gICAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxufVxuIl19