UNPKG

projen

Version:

CDK for software projects

395 lines • 43.2 kB
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90YXNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSx1Q0FBaUM7QUE2RGpDOzs7R0FHRztBQUNILE1BQWEsSUFBSTs7SUFDZjs7T0FFRztJQUNhLElBQUksQ0FBUztJQUVaLFdBQVcsQ0FBVztJQUN0QixNQUFNLENBQWE7SUFDbkIsSUFBSSxDQUE2QjtJQUMxQyxJQUFJLENBQXNCO0lBQzFCLE1BQU0sQ0FBeUI7SUFFdEIsV0FBVyxDQUFZO0lBQ2hDLE9BQU8sQ0FBVTtJQUNqQixZQUFZLENBQVU7SUFFOUIsWUFBWSxJQUFZLEVBQUUsUUFBcUIsRUFBRTtRQUMvQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7UUFDdEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzVELElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUN0QixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDMUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUU1QixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUVyQyxJQUFJLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsUUFBUSxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7UUFDNUQsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDakMsTUFBTSxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO1FBQzNELENBQUM7UUFFRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3BFLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxJQUFJO1FBQ1QsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDdEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBVyxHQUFHO1FBQ1osT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ25CLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsR0FBRyxDQUFDLEdBQXVCO1FBQ3BDLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBVyxLQUFLO1FBQ2QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsS0FBSyxDQUFDLEtBQTRCO1FBQzNDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsV0FBVztRQUNwQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBVyxXQUFXLENBQUMsSUFBd0I7UUFDN0MsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7SUFDM0IsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQVcsU0FBUztRQUNsQixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLFlBQVksQ0FBQyxHQUFHLFNBQW1CO1FBQ3hDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxPQUFnQixFQUFFLFVBQTJCLEVBQUU7UUFDMUQsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMvQixPQUFPO1FBQ1QsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3RCLENBQUM7UUFFRCxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1osSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDOUIsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLFFBQVEsQ0FBQyxHQUFHLEtBQWlCO1FBQ2xDLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksSUFBSSxDQUFDLE9BQWUsRUFBRSxVQUEyQixFQUFFO1FBQ3hELElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7T0FhRztJQUNJLFFBQVEsQ0FBQyxPQUFpQixFQUFFLFVBQTJCLEVBQUU7UUFDOUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLEVBQUU7WUFDMUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQztTQUNuRCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNJLE9BQU8sQ0FBQyxJQUFZO1FBQ3pCLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksR0FBRyxDQUFDLE9BQWUsRUFBRSxVQUEyQixFQUFFO1FBQ3ZELElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLE9BQWEsRUFBRSxVQUEyQixFQUFFO1FBQ3ZELElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFO1lBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDO1NBQ3JELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksWUFBWSxDQUFDLEdBQUcsS0FBaUI7UUFDdEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFdBQVcsQ0FBQyxPQUFlLEVBQUUsVUFBMkIsRUFBRTtRQUMvRCxJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRTtZQUNoQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDO1NBQy9DLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSSxZQUFZLENBQUMsT0FBYSxFQUFFLFVBQTJCLEVBQUU7UUFDOUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUU7WUFDakMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUM7U0FDckQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFVBQVUsQ0FBQyxPQUFlLEVBQUUsVUFBMkIsRUFBRTtRQUM5RCxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRTtZQUMvQixJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDO1NBQzlDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSyxVQUFVLENBQ2hCLElBQThEO1FBRTlELE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFDaEMsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDNUQsQ0FBQztJQUVPLFVBQVUsQ0FBQyxNQUFjLEVBQUUsS0FBaUI7UUFDbEQsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLE1BQU0sS0FBSyxDQUFDLENBQUM7WUFDdEMsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFTyxhQUFhLENBQUMsTUFBYyxFQUFFLEtBQWlCO1FBQ3JELElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUV0QixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUNoQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxNQUFNLEtBQUssQ0FBQyxDQUFDO1lBQ3RDLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksR0FBRyxDQUFDLElBQVksRUFBRSxLQUFhO1FBQ3BDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFXLE9BQU87UUFDaEIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ25CLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsS0FBSztRQUNkLHFFQUFxRTtRQUNyRSw2REFBNkQ7UUFDN0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDaEMsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBQ0QsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxVQUFVLENBQUMsS0FBYSxFQUFFLEdBQUcsS0FBaUI7UUFDbkQsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzNDLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxLQUFLLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUM3RCxNQUFNLElBQUksS0FBSyxDQUNiLGdDQUFnQyxLQUFLLGFBQWEsSUFBSSxDQUFDLElBQUksZ0RBQWdELElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQy9ILENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksVUFBVSxDQUFDLEtBQWEsRUFBRSxJQUFjO1FBQzdDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUV0QixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUNoQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUN6QyxPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQ2IsK0JBQStCLEtBQUssYUFBYSxJQUFJLENBQUMsSUFBSSw0QkFBNEIsQ0FDdkYsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQztJQUM1QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksVUFBVSxDQUFDLEtBQWE7UUFDN0IsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQzFDLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLEtBQUssQ0FDYiwrQkFBK0IsS0FBSyxhQUFhLElBQUksQ0FBQyxJQUFJLDRCQUE0QixDQUN2RixDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLFdBQVc7UUFDaEIseUNBQXlDO1FBQ3pDLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FDdkMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2YsR0FBRyxJQUFJO1lBQ1AsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ2pELENBQUMsRUFDRixFQUFFLENBQ0gsQ0FBQztRQUVGLHlDQUF5QztRQUN6QyxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDdEMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3pCLE9BQU8sQ0FBQyxDQUFDLEdBQUc7b0JBQ1YsQ0FBQyxDQUFDO3dCQUNFLEdBQUcsQ0FBQzt3QkFDSixHQUFHLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUM1QixDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7NEJBQ2YsR0FBRyxJQUFJOzRCQUNQLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzt5QkFDOUMsQ0FBQyxFQUNGLEVBQUUsQ0FDSDtxQkFDRjtvQkFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ1IsQ0FBQyxDQUFDO1lBQ0osQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7UUFFaEIsT0FBTztZQUNMLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNmLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztZQUM3QixHQUFHLEVBQUUsR0FBRztZQUNSLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztZQUM3QixLQUFLLEVBQUUsS0FBSztZQUNaLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUk7WUFDZCxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUU7U0FDOUIsQ0FBQztJQUNKLENBQUM7SUFFTyxjQUFjO1FBQ3BCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsU0FBUyxJQUFJLENBQUMsSUFBSSx5QkFBeUIsQ0FBQyxDQUFDO1FBQy9ELENBQUM7SUFDSCxDQUFDO0lBRU8sZ0JBQWdCLENBQUMscUJBQTZCO1FBQ3BELElBQUEsY0FBSSxFQUNGLFVBQVUscUJBQXFCLFVBQVUsSUFBSSxDQUFDLElBQUksa0VBQWtFLENBQ3JILENBQUM7SUFDSixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssWUFBWSxDQUFDLElBQVksRUFBRSxLQUFVO1FBQzNDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNyRCxJQUFBLGNBQUksRUFDRixzREFBc0QsSUFBSSw4QkFBOEIsQ0FDekYsQ0FBQztZQUNGLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQzs7QUExY0gsb0JBMmNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgd2FybiB9IGZyb20gXCIuL2xvZ2dpbmdcIjtcbmltcG9ydCB0eXBlIHtcbiAgVGFza0NvbW1vbk9wdGlvbnMsXG4gIFRhc2tTcGVjLFxuICBUYXNrU3RlcCxcbiAgVGFza1N0ZXBPcHRpb25zLFxufSBmcm9tIFwiLi90YXNrLW1vZGVsXCI7XG5pbXBvcnQgdHlwZSB7IFRhc2tTaGVsbCB9IGZyb20gXCIuL3Rhc2stc2hlbGxcIjtcblxuZXhwb3J0IGludGVyZmFjZSBUYXNrT3B0aW9ucyBleHRlbmRzIFRhc2tDb21tb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFNoZWxsIGNvbW1hbmQgdG8gZXhlY3V0ZSBhcyB0aGUgZmlyc3QgY29tbWFuZCBvZiB0aGUgdGFzay5cbiAgICpcbiAgICogQSBzaW5nbGUgc2hlbGwgc3RyaW5nLCBzbyBvbmx5IHBhc3MgdHJ1c3RlZCBpbnB1dDogYW4gaW50ZXJwb2xhdGVkIHZhbHVlIGlzXG4gICAqIGludGVycHJldGVkIGJ5IHRoZSBzaGVsbCB0b28uIFVzZSBgZXhlY0FyZ3NgIGZvciBhcmd1bWVudHMgeW91IGRpZCBub3Qgd3JpdGVcbiAgICogbGl0ZXJhbGx5LlxuICAgKlxuICAgKiBNdXR1YWxseSBleGNsdXNpdmUgd2l0aCBgZXhlY0FyZ3NgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGFkZCBzdGVwcyB1c2luZyBgdGFzay5leGVjKGNvbW1hbmQpYCBvciBgdGFzay5zcGF3bihzdWJ0YXNrKWBcbiAgICovXG4gIHJlYWRvbmx5IGV4ZWM/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNoZWxsIGNvbW1hbmQgdG8gZXhlY3V0ZSBhcyB0aGUgZmlyc3QgY29tbWFuZCBvZiB0aGUgdGFzaywgcHJvdmlkZWQgYXMgYVxuICAgKiBsaXN0IG9mIHRoZSBwcm9ncmFtIGZvbGxvd2VkIGJ5IGl0cyBhcmd1bWVudHMgKGFuIFwiYXJndlwiKS5cbiAgICpcbiAgICogQSBjb252ZW5pZW50IGFsdGVybmF0aXZlIHRvIGBleGVjYDogYXJndW1lbnRzIHdpdGggc3BhY2VzIG9yIHNwZWNpYWxcbiAgICogY2hhcmFjdGVycyBhcmUgcGFzc2VkIHRocm91Z2ggYXMtaXMsIHdpdGggbm8gcXVvdGluZyBuZWVkZWQuIFRoZSBlbGVtZW50c1xuICAgKiBhcmUgbm90IHJ1biB0aHJvdWdoIGEgc2hlbGwsIHNvIGVudmlyb25tZW50IHZhcmlhYmxlcyAoYCRGT09gKSBhcmUgbm90XG4gICAqIGV4cGFuZGVkIGFuZCBvdGhlciBzaGVsbCBmZWF0dXJlcyBhcmUgdW5hdmFpbGFibGUuXG4gICAqIEBzZWUgVGFza1N0ZXAuZXhlY0FyZ3NcbiAgICpcbiAgICogTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGV4ZWNgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGFkZCBzdGVwcyB1c2luZyBgdGFzay5leGVjQXJncyhhcmdzKWAsIGB0YXNrLmV4ZWMoY29tbWFuZClgIG9yIGB0YXNrLnNwYXduKHN1YnRhc2spYFxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY0FyZ3M/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTGlzdCBvZiB0YXNrIHN0ZXBzIHRvIHJ1bi5cbiAgICovXG4gIHJlYWRvbmx5IHN0ZXBzPzogVGFza1N0ZXBbXTtcblxuICAvKipcbiAgICogU2hvdWxkIHRoZSBwcm92aWRlZCBgZXhlY2Agc2hlbGwgY29tbWFuZCByZWNlaXZlIGFyZ3MgcGFzc2VkIHRvIHRoZSB0YXNrLlxuICAgKiBAc2VlIHtAbGluayBUYXNrU3RlcE9wdGlvbnMucmVjZWl2ZUFyZ3N9XG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSByZWNlaXZlQXJncz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNob3VsZCB0aGUgcHJvdmlkZWQgYGV4ZWNgIHNoZWxsIGNvbW1hbmQgcmVjZWl2ZSBmaXhlZCBhcmdzLlxuICAgKiBAc2VlIHtAbGluayBUYXNrU3RlcE9wdGlvbnMuYXJnc31cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byB0aGUgc3RlcFxuICAgKi9cbiAgcmVhZG9ubHkgYXJncz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIEEgdGFzayB0aGF0IGNhbiBiZSBwZXJmb3JtZWQgb24gdGhlIHByb2plY3QuIE1vZGVsZWQgYXMgYSBzZXJpZXMgb2Ygc2hlbGxcbiAqIGNvbW1hbmRzIGFuZCBzdWJ0YXNrcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFRhc2sge1xuICAvKipcbiAgICogVGFzayBuYW1lLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IF9jb25kaXRpb25zOiBzdHJpbmdbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBfc3RlcHM6IFRhc2tTdGVwW107XG4gIHByaXZhdGUgcmVhZG9ubHkgX2VudjogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH07XG4gIHByaXZhdGUgX2N3ZD86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfc2hlbGw/OiBUYXNrU2hlbGwgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSByZWFkb25seSByZXF1aXJlZEVudj86IHN0cmluZ1tdO1xuICBwcml2YXRlIF9sb2NrZWQ6IGJvb2xlYW47XG4gIHByaXZhdGUgX2Rlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgcHJvcHM6IFRhc2tPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgIHRoaXMuX2Rlc2NyaXB0aW9uID0gcHJvcHMuZGVzY3JpcHRpb247XG4gICAgdGhpcy5fY29uZGl0aW9ucyA9IHByb3BzLmNvbmRpdGlvbiA/IFtwcm9wcy5jb25kaXRpb25dIDogW107XG4gICAgdGhpcy5fY3dkID0gcHJvcHMuY3dkO1xuICAgIHRoaXMuX3NoZWxsID0gcHJvcHMuc2hlbGw7XG4gICAgdGhpcy5fbG9ja2VkID0gZmFsc2U7XG4gICAgdGhpcy5fZW52ID0gcHJvcHMuZW52ID8/IHt9O1xuXG4gICAgdGhpcy5fc3RlcHMgPSBwcm9wcy5zdGVwcyA/PyBbXTtcbiAgICB0aGlzLnJlcXVpcmVkRW52ID0gcHJvcHMucmVxdWlyZWRFbnY7XG5cbiAgICBpZiAocHJvcHMuZXhlYyAmJiBwcm9wcy5zdGVwcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY2Fubm90IHNwZWNpZnkgYm90aCBleGVjIGFuZCBzdGVwc1wiKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuZXhlY0FyZ3MgJiYgcHJvcHMuc3RlcHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImNhbm5vdCBzcGVjaWZ5IGJvdGggZXhlY0FyZ3MgYW5kIHN0ZXBzXCIpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5leGVjICYmIHByb3BzLmV4ZWNBcmdzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjYW5ub3Qgc3BlY2lmeSBib3RoIGV4ZWMgYW5kIGV4ZWNBcmdzXCIpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5leGVjKSB7XG4gICAgICB0aGlzLmV4ZWMocHJvcHMuZXhlYywgeyByZWNlaXZlQXJnczogcHJvcHMucmVjZWl2ZUFyZ3MgfSk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmV4ZWNBcmdzKSB7XG4gICAgICB0aGlzLmV4ZWNBcmdzKHByb3BzLmV4ZWNBcmdzLCB7IHJlY2VpdmVBcmdzOiBwcm9wcy5yZWNlaXZlQXJncyB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRm9yYmlkIGFkZGl0aW9uYWwgY2hhbmdlcyB0byB0aGlzIHRhc2suXG4gICAqL1xuICBwdWJsaWMgbG9jaygpIHtcbiAgICB0aGlzLl9sb2NrZWQgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGZvciB0aGlzIHRhc2suXG4gICAqL1xuICBwdWJsaWMgZ2V0IGN3ZCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9jd2Q7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgd29ya2luZyBkaXJlY3RvcnkgZm9yIHRoaXMgdGFzay5cbiAgICovXG4gIHB1YmxpYyBzZXQgY3dkKGN3ZDogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fY3dkID0gY3dkO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzaGVsbCB1c2VkIHRvIHJ1biB0aGlzIHRhc2sncyBjb21tYW5kcywgb3IgYHVuZGVmaW5lZGAgd2hlbiBpbmhlcml0aW5nXG4gICAqIHRoZSBidWlsdC1pbiBkZWZhdWx0IHNoZWxsLlxuICAgKiBAc2VlIHtAbGluayBUYXNrQ29tbW9uT3B0aW9ucy5zaGVsbH1cbiAgICovXG4gIHB1YmxpYyBnZXQgc2hlbGwoKTogVGFza1NoZWxsIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fc2hlbGw7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgc2hlbGwgdXNlZCB0byBydW4gdGhpcyB0YXNrJ3MgY29tbWFuZHMuXG4gICAqL1xuICBwdWJsaWMgc2V0IHNoZWxsKHNoZWxsOiBUYXNrU2hlbGwgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9zaGVsbCA9IHNoZWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGRlc2NyaXB0aW9uIG9mIHRoaXMgdGFzay5cbiAgICovXG4gIHB1YmxpYyBnZXQgZGVzY3JpcHRpb24oKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fZGVzY3JpcHRpb247XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZGVzY3JpcHRpb24gb2YgdGhpcyB0YXNrLlxuICAgKi9cbiAgcHVibGljIHNldCBkZXNjcmlwdGlvbihkZXNjOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9kZXNjcmlwdGlvbiA9IGRlc2M7XG4gIH1cblxuICAvKipcbiAgICogQSBjb21tYW5kIHRvIGV4ZWN1dGUgd2hpY2ggZGV0ZXJtaW5lcyBpZiB0aGUgdGFzayBzaG91bGQgYmUgc2tpcHBlZC4gSWYgaXRcbiAgICogcmV0dXJucyBhIHplcm8gZXhpdCBjb2RlLCB0aGUgdGFzayB3aWxsIG5vdCBiZSBleGVjdXRlZC5cbiAgICovXG4gIHB1YmxpYyBnZXQgY29uZGl0aW9uKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuX2NvbmRpdGlvbnM/Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NvbmRpdGlvbnMuam9pbihcIiAmJiBcIik7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgY29tbWFuZCB0byBleGVjdXRlIHdoaWNoIGRldGVybWluZXMgaWYgdGhlIHRhc2sgc2hvdWxkIGJlIHNraXBwZWQuXG4gICAqXG4gICAqIElmIGEgY29uZGl0aW9uIGFscmVhZHkgZXhpc3RzLCB0aGUgbmV3IGNvbmRpdGlvbiB3aWxsIGJlIGFwcGVuZGVkIHdpdGggYCAmJiBgIGRlbGltaXRlci5cbiAgICogQHBhcmFtIGNvbmRpdGlvbiBUaGUgY29tbWFuZCB0byBleGVjdXRlLlxuICAgKiBAc2VlIHtAbGluayBUYXNrLmNvbmRpdGlvbn1cbiAgICovXG4gIHB1YmxpYyBhZGRDb25kaXRpb24oLi4uY29uZGl0aW9uOiBzdHJpbmdbXSk6IHZvaWQge1xuICAgIHRoaXMuX2NvbmRpdGlvbnMucHVzaCguLi5jb25kaXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSB0YXNrIHNvIGl0IG5vIGxvbmdlciBoYXMgYW55IGNvbW1hbmRzLlxuICAgKiBAcGFyYW0gY29tbWFuZCB0aGUgZmlyc3QgY29tbWFuZCB0byBhZGQgdG8gdGhlIHRhc2sgYWZ0ZXIgaXQgd2FzIGNsZWFyZWQuXG4gICAqL1xuICBwdWJsaWMgcmVzZXQoY29tbWFuZD86IHN0cmluZywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLmFzc2VydFVubG9ja2VkKCk7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICB0aGlzLndhcm5Gb3JMYXp5VmFsdWUoXCJyZXNldFwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aGlsZSAodGhpcy5fc3RlcHMubGVuZ3RoKSB7XG4gICAgICB0aGlzLl9zdGVwcy5zaGlmdCgpO1xuICAgIH1cblxuICAgIGlmIChjb21tYW5kKSB7XG4gICAgICB0aGlzLmV4ZWMoY29tbWFuZCwgb3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgc3RlcHMgdG8gdGhpcyB0YXNrLiBUaGlzIGlzIGEgZ2VuZXJpYyBtZXRob2QgdGhhdCBhY2NlcHRzIGFueVxuICAgKiB0YXNrIHN0ZXAgKGV4ZWMsIHNwYXduLCBzYXksIGJ1aWx0aW4pLlxuICAgKlxuICAgKiBAcGFyYW0gc3RlcHMgVGhlIHN0ZXBzIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBhZGRTdGVwcyguLi5zdGVwczogVGFza1N0ZXBbXSkge1xuICAgIHRoaXMuX3B1c2hTdGVwcyhcImFkZFN0ZXBzXCIsIHN0ZXBzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyBhIHNoZWxsIGNvbW1hbmRcbiAgICogQHBhcmFtIGNvbW1hbmQgU2hlbGwgY29tbWFuZFxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zXG4gICAqL1xuICBwdWJsaWMgZXhlYyhjb21tYW5kOiBzdHJpbmcsIG9wdGlvbnM6IFRhc2tTdGVwT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fcHVzaFN0ZXBzKFwiZXhlY1wiLCBbdGhpcy5yZW5kZXJTdGVwKHsgZXhlYzogY29tbWFuZCwgLi4ub3B0aW9ucyB9KV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGVzIGEgY29tbWFuZCBwcm92aWRlZCBhcyBhIGxpc3Qgb2YgdGhlIHByb2dyYW0gZm9sbG93ZWQgYnkgaXRzXG4gICAqIGFyZ3VtZW50cyAoYW4gXCJhcmd2XCIpLlxuICAgKlxuICAgKiBBIGNvbnZlbmllbnQgYWx0ZXJuYXRpdmUgdG8gYFRhc2suZXhlY2A6IGFyZ3VtZW50cyB3aXRoIHNwYWNlcyBvclxuICAgKiBzcGVjaWFsIGNoYXJhY3RlcnMgYXJlIHBhc3NlZCB0aHJvdWdoIGFzLWlzLCB3aXRoIG5vIHF1b3RpbmcgbmVlZGVkLiBUaGVcbiAgICogZWxlbWVudHMgYXJlIG5vdCBydW4gdGhyb3VnaCBhIHNoZWxsLCBzbyBlbnZpcm9ubWVudCB2YXJpYWJsZXMgKGAkRk9PYCkgYXJlXG4gICAqIG5vdCBleHBhbmRlZCBhbmQgb3RoZXIgc2hlbGwgZmVhdHVyZXMgYXJlIHVuYXZhaWxhYmxlLlxuICAgKlxuICAgKiBAZXhhbXBsZSB0YXNrLmV4ZWNBcmdzKFtcImVjaG9cIiwgXCJoZWxsbyB3b3JsZFwiXSk7XG4gICAqXG4gICAqIEBwYXJhbSBjb21tYW5kIFRoZSBwcm9ncmFtIGZvbGxvd2VkIGJ5IGl0cyBhcmd1bWVudHMuXG4gICAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBleGVjQXJncyhjb21tYW5kOiBzdHJpbmdbXSwgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl9wdXNoU3RlcHMoXCJleGVjQXJnc1wiLCBbXG4gICAgICB0aGlzLnJlbmRlclN0ZXAoeyBleGVjQXJnczogY29tbWFuZCwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGEgYnVpbHRpbiB0YXNrLlxuICAgKlxuICAgKiBCdWlsdGluIHRhc2tzIGFyZSBwcm9ncmFtcyBidW5kbGVkIGFzIHBhcnQgb2YgcHJvamVuIGl0c2VsZiBhbmQgdXNlZCBhc1xuICAgKiBoZWxwZXJzIGZvciB2YXJpb3VzIGNvbXBvbmVudHMuXG4gICAqXG4gICAqIEluIHRoZSBmdXR1cmUgd2Ugc2hvdWxkIHN1cHBvcnQgYnVpbHQtaW4gdGFza3MgZnJvbSBleHRlcm5hbCBtb2R1bGVzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgYnVpbHRpbiB0YXNrIHRvIGV4ZWN1dGUgKGUuZy5cbiAgICogYHJlbGVhc2UvcmVzb2x2ZS12ZXJzaW9uYCkuXG4gICAqL1xuICBwdWJsaWMgYnVpbHRpbihuYW1lOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9wdXNoU3RlcHMoXCJidWlsdGluXCIsIFt7IGJ1aWx0aW46IG5hbWUgfV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNheSBzb21ldGhpbmcuXG4gICAqIEBwYXJhbSBtZXNzYWdlIFlvdXIgbWVzc2FnZVxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zXG4gICAqL1xuICBwdWJsaWMgc2F5KG1lc3NhZ2U6IHN0cmluZywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl9wdXNoU3RlcHMoXCJzYXlcIiwgW3RoaXMucmVuZGVyU3RlcCh7IHNheTogbWVzc2FnZSwgLi4ub3B0aW9ucyB9KV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwYXducyBhIHN1Yi10YXNrLlxuICAgKiBAcGFyYW0gc3VidGFzayBUaGUgc3VidGFzayB0byBleGVjdXRlLlxuICAgKi9cbiAgcHVibGljIHNwYXduKHN1YnRhc2s6IFRhc2ssIG9wdGlvbnM6IFRhc2tTdGVwT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fcHVzaFN0ZXBzKFwic3Bhd25cIiwgW1xuICAgICAgdGhpcy5yZW5kZXJTdGVwKHsgc3Bhd246IHN1YnRhc2submFtZSwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIHN0ZXBzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhpcyB0YXNrLlxuICAgKlxuICAgKiBAcGFyYW0gc3RlcHMgVGhlIHN0ZXBzIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kU3RlcHMoLi4uc3RlcHM6IFRhc2tTdGVwW10pIHtcbiAgICB0aGlzLl91bnNoaWZ0U3RlcHMoXCJwcmVwZW5kU3RlcHNcIiwgc3RlcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBjb21tYW5kIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHRhc2suXG4gICAqIEBwYXJhbSBjb21tYW5kIFRoZSBjb21tYW5kIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kRXhlYyhjb21tYW5kOiBzdHJpbmcsIG9wdGlvbnM6IFRhc2tTdGVwT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fdW5zaGlmdFN0ZXBzKFwicHJlcGVuZEV4ZWNcIiwgW1xuICAgICAgdGhpcy5yZW5kZXJTdGVwKHsgZXhlYzogY29tbWFuZCwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgc3Bhd24gaW5zdHJ1Y3Rpb24gYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdGFzay5cbiAgICogQHBhcmFtIHN1YnRhc2sgVGhlIHN1YnRhc2sgdG8gZXhlY3V0ZS5cbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kU3Bhd24oc3VidGFzazogVGFzaywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl91bnNoaWZ0U3RlcHMoXCJwcmVwZW5kU3Bhd25cIiwgW1xuICAgICAgdGhpcy5yZW5kZXJTdGVwKHsgc3Bhd246IHN1YnRhc2submFtZSwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXlzIHNvbWV0aGluZyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB0YXNrLlxuICAgKiBAcGFyYW0gbWVzc2FnZSBZb3VyIG1lc3NhZ2VcbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kU2F5KG1lc3NhZ2U6IHN0cmluZywgb3B0aW9uczogVGFza1N0ZXBPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLl91bnNoaWZ0U3RlcHMoXCJwcmVwZW5kU2F5XCIsIFtcbiAgICAgIHRoaXMucmVuZGVyU3RlcCh7IHNheTogbWVzc2FnZSwgLi4ub3B0aW9ucyB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXJzIHN0ZXAgb3B0aW9ucyAod2l0aCBhIHtAbGluayBUYXNrU2hlbGx9KSB0byB0aGUgbWFuaWZlc3RcbiAgICoge0BsaW5rIFRhc2tTdGVwfSBmb3JtLCB3aGVyZSBgc2hlbGxgIGlzIGl0cyBgc3RyaW5nIHwgc3RyaW5nW11gIHJlbmRlcmluZy5cbiAgICovXG4gIHByaXZhdGUgcmVuZGVyU3RlcChcbiAgICBzdGVwOiB7IHJlYWRvbmx5IHNoZWxsPzogVGFza1NoZWxsIH0gJiBPbWl0PFRhc2tTdGVwLCBcInNoZWxsXCI+LFxuICApOiBUYXNrU3RlcCB7XG4gICAgY29uc3QgeyBzaGVsbCwgLi4ucmVzdCB9ID0gc3RlcDtcbiAgICByZXR1cm4gc2hlbGwgPyB7IC4uLnJlc3QsIHNoZWxsOiBzaGVsbC5fcmVuZGVyKCkgfSA6IHJlc3Q7XG4gIH1cblxuICBwcml2YXRlIF9wdXNoU3RlcHMobWV0aG9kOiBzdHJpbmcsIHN0ZXBzOiBUYXNrU3RlcFtdKSB7XG4gICAgdGhpcy5hc3NlcnRVbmxvY2tlZCgpO1xuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMuX3N0ZXBzKSkge1xuICAgICAgdGhpcy53YXJuRm9yTGF6eVZhbHVlKGAke21ldGhvZH0gdG9gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGVwcy5wdXNoKC4uLnN0ZXBzKTtcbiAgfVxuXG4gIHByaXZhdGUgX3Vuc2hpZnRTdGVwcyhtZXRob2Q6IHN0cmluZywgc3RlcHM6IFRhc2tTdGVwW10pIHtcbiAgICB0aGlzLmFzc2VydFVubG9ja2VkKCk7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICB0aGlzLndhcm5Gb3JMYXp5VmFsdWUoYCR7bWV0aG9kfSB0b2ApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX3N0ZXBzLnVuc2hpZnQoLi4uc3RlcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUgdG8gdGhpcyB0YXNrLlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdmFyaWFibGVcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZS4gSWYgdGhlIHZhbHVlIGlzIHN1cnJvdW5kZWQgYnkgYCQoKWAsIHdlIHdpbGxcbiAgICogZXZhbHVhdGUgaXQgd2l0aGluIGEgc3Vic2hlbGwgYW5kIHVzZSB0aGUgcmVzdWx0IGFzIHRoZSB2YWx1ZSBvZiB0aGVcbiAgICogZW52aXJvbm1lbnQgdmFyaWFibGUuXG4gICAqL1xuICBwdWJsaWMgZW52KG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuYXNzZXJ0VW5sb2NrZWQoKTtcbiAgICB0aGlzLl9lbnZbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIHRhc2sgbGV2ZWxcbiAgICovXG4gIHB1YmxpYyBnZXQgZW52VmFycygpOiBSZWFkb25seTx7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfT4ge1xuICAgIHJldHVybiB0aGlzLl9lbnY7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBpbW11dGFibGUgY29weSBvZiBhbGwgdGhlIHN0ZXAgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHRhc2suXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0ZXBzKCk6IFRhc2tTdGVwW10ge1xuICAgIC8vIElmIHRoZSBsaXN0IG9mIHN0ZXBzIGlzIGEgTGF6eSB2YWx1ZSwgd2UgY2FuJ3Qga25vdyB3aGF0IHRoZSBzdGVwc1xuICAgIC8vIGFyZSB1bnRpbCBzeW50aGVzaXMgb2NjdXJzLCBzbyBqdXN0IHJldHVybiBhbiBlbXB0eSBhcnJheS5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHJldHVybiBbLi4udGhpcy5fc3RlcHNdO1xuICB9XG5cbiAgLyoqXG4gICAqIEluc2VydCBvbmUgb3IgbW9yZSBzdGVwcyBhdCBhIGdpdmVuIGluZGV4XG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBTdGVwcyB3aWxsIGJlIGluc2VydGVkIGJlZm9yZSB0aGlzIGluZGV4LiBNYXkgYmUgbmVnYXRpdmUgdG9cbiAgICogY291bnQgYmFja3dhcmRzIGZyb20gdGhlIGVuZCwgb3IgbWF5IGJlIGA9PSBzdGVwcygpLmxlbmd0aGAgdG8gaW5zZXJ0IGF0IHRoZSBlbmQuXG4gICAqIEBwYXJhbSBzdGVwcyBUaGUgc3RlcHMgdG8gaW5zZXJ0XG4gICAqL1xuICBwdWJsaWMgaW5zZXJ0U3RlcChpbmRleDogbnVtYmVyLCAuLi5zdGVwczogVGFza1N0ZXBbXSk6IHZvaWQge1xuICAgIHRoaXMuYXNzZXJ0VW5sb2NrZWQoKTtcblxuICAgIGlmICghQXJyYXkuaXNBcnJheSh0aGlzLl9zdGVwcykpIHtcbiAgICAgIHRoaXMud2FybkZvckxhenlWYWx1ZShcImluc2VydCBzdGVwcyBpbnRvXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChpbmRleCA8IC10aGlzLl9zdGVwcy5sZW5ndGggfHwgaW5kZXggPiB0aGlzLnN0ZXBzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ2Fubm90IGluc2VydCBzdGVwcyBhdCBpbmRleCAke2luZGV4fSBmb3IgdGFzayAke3RoaXMubmFtZX0gYmVjYXVzZSB0aGUgaW5kZXggaXMgb3V0IG9mIGJvdW5kcyBmb3Igc2l6ZSAke3RoaXMuc3RlcHMubGVuZ3RofWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuX3N0ZXBzLnNwbGljZShpbmRleCwgMCwgLi4uc3RlcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHN0ZXAgdG8gZWRpdFxuICAgKiBAcGFyYW0gc3RlcCBUaGUgbmV3IHN0ZXAgdG8gcmVwbGFjZSB0aGUgb2xkIG9uZSBlbnRpcmVseSwgaXQgaXMgbm90IG1lcmdlZCB3aXRoIHRoZSBvbGQgc3RlcFxuICAgKi9cbiAgcHVibGljIHVwZGF0ZVN0ZXAoaW5kZXg6IG51bWJlciwgc3RlcDogVGFza1N0ZXApOiB2b2lkIHtcbiAgICB0aGlzLmFzc2VydFVubG9ja2VkKCk7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpKSB7XG4gICAgICB0aGlzLndhcm5Gb3JMYXp5VmFsdWUoXCJ1cGRhdGUgc3RlcCBmb3JcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmdTdGVwID0gdGhpcy5fc3RlcHNbaW5kZXhdO1xuICAgIGlmICghZXhpc3RpbmdTdGVwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgdXBkYXRlIHN0ZXAgYXQgaW5kZXggJHtpbmRleH0gZm9yIHRhc2sgJHt0aGlzLm5hbWV9IGJlY2F1c2UgaXQgZG9lcyBub3QgZXhpc3RgLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGVwc1tpbmRleF0gPSBzdGVwO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHN0ZXAgdG8gcmVtb3ZlXG4gICAqL1xuICBwdWJsaWMgcmVtb3ZlU3RlcChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5hc3NlcnRVbmxvY2tlZCgpO1xuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMuX3N0ZXBzKSkge1xuICAgICAgdGhpcy53YXJuRm9yTGF6eVZhbHVlKFwicmVtb3ZlIHN0ZXAgZnJvbVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZ1N0ZXAgPSB0aGlzLl9zdGVwc1tpbmRleF07XG4gICAgaWYgKCFleGlzdGluZ1N0ZXApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYENhbm5vdCByZW1vdmUgc3RlcCBhdCBpbmRleCAke2luZGV4fSBmb3IgdGFzayAke3RoaXMubmFtZX0gYmVjYXVzZSBpdCBkb2VzIG5vdCBleGlzdGAsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuX3N0ZXBzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVycyBhIHRhc2sgc3BlYyBpbnRvIHRoZSBtYW5pZmVzdC5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3JlbmRlclNwZWMoKTogVGFza1NwZWMge1xuICAgIC8vIEVuc3VyZSB0YXNrLWxldmVsIGVudiB2YXJzIGFyZSBzdHJpbmdzXG4gICAgY29uc3QgZW52ID0gT2JqZWN0LmtleXModGhpcy5fZW52KS5yZWR1Y2UoXG4gICAgICAocHJldiwgY3VycikgPT4gKHtcbiAgICAgICAgLi4ucHJldixcbiAgICAgICAgW2N1cnJdOiB0aGlzLmdldEVudlN0cmluZyhjdXJyLCB0aGlzLl9lbnZbY3Vycl0pLFxuICAgICAgfSksXG4gICAgICB7fSxcbiAgICApO1xuXG4gICAgLy8gRW5zdXJlIHN0ZXAtbGV2ZWwgZW52IHZhcnMgYXJlIHN0cmluZ3NcbiAgICBjb25zdCBzdGVwcyA9IEFycmF5LmlzQXJyYXkodGhpcy5fc3RlcHMpXG4gICAgICA/IFsuLi50aGlzLl9zdGVwc10ubWFwKChzKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHMuZW52XG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAuLi5zLFxuICAgICAgICAgICAgICAgIGVudjogT2JqZWN0LmtleXMocy5lbnYpLnJlZHVjZShcbiAgICAgICAgICAgICAgICAgIChwcmV2LCBjdXJyKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAuLi5wcmV2LFxuICAgICAgICAgICAgICAgICAgICBbY3Vycl06IHRoaXMuZ2V0RW52U3RyaW5nKGN1cnIsIHMuZW52IVtjdXJyXSksXG4gICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDogcztcbiAgICAgICAgfSlcbiAgICAgIDogdGhpcy5fc3RlcHM7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IHRoaXMuZGVzY3JpcHRpb24sXG4gICAgICBlbnY6IGVudixcbiAgICAgIHJlcXVpcmVkRW52OiB0aGlzLnJlcXVpcmVkRW52LFxuICAgICAgc3RlcHM6IHN0ZXBzLFxuICAgICAgY29uZGl0aW9uOiB0aGlzLmNvbmRpdGlvbixcbiAgICAgIGN3ZDogdGhpcy5fY3dkLFxuICAgICAgc2hlbGw6IHRoaXMuX3NoZWxsPy5fcmVuZGVyKCksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXNzZXJ0VW5sb2NrZWQoKSB7XG4gICAgaWYgKHRoaXMuX2xvY2tlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUYXNrIFwiJHt0aGlzLm5hbWV9XCIgaXMgbG9ja2VkIGZvciBjaGFuZ2VzYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB3YXJuRm9yTGF6eVZhbHVlKGFjdGlvbkJlaW5nVW5kZXJ0YWtlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgd2FybihcbiAgICAgIGBDYW5ub3QgJHthY3Rpb25CZWluZ1VuZGVydGFrZW59IHRhc2sgXCIke3RoaXMubmFtZX1cIiBiZWNhdXNlIGl0IGlzIGEgbGF6eSB2YWx1ZSwgdHJ5IHVzaW5nIHRoZSBwcmVTeW50aGVzaXplIHBoYXNlLmAsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmUgdGhhdCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYXJlIHBlcnNpc3RlZCBhcyBzdHJpbmdzXG4gICAqIHRvIHByZXZlbnQgdHlwZSBlcnJvcnMgd2hlbiBwYXJzaW5nIGZyb20gdGFza3MuanNvbiBpbiBmdXR1cmVcbiAgICovXG4gIHByaXZhdGUgZ2V0RW52U3RyaW5nKG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgd2FybihcbiAgICAgICAgYFJlY2VpdmVkIG5vbi1zdHJpbmcgdmFsdWUgZm9yIGVudmlyb25tZW50IHZhcmlhYmxlICR7bmFtZX0uIFZhbHVlIHdpbGwgYmUgc3RyaW5naWZpZWQuYCxcbiAgICAgICk7XG4gICAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxufVxuIl19