UNPKG

projen

Version:

CDK for software projects

689 lines • 92.4 kB
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.TaskRuntime = void 0;
exports.systemShell = systemShell;
const child_process = __importStar(require("child_process"));
const fs_1 = require("fs");
const path_1 = require("path");
const path = __importStar(require("path"));
const util_1 = require("util");
const chalk_1 = require("chalk");
const common_1 = require("../common");
const logging = __importStar(require("../logging"));
const dax_1 = require("../util/dax");
const exec_1 = require("../util/exec");
// avoids a (false positive) esbuild warning about incorrect imports.
// `?.default ?? module` keeps this working both as a plain CommonJS require and
// when the dependency is interop-wrapped inside the bundled run-task.cjs (where
// `require(...)` may yield `{ default: fn }` instead of the function). See
// projen#4407 ("parseConflictJSON is not a function" after eject).
// eslint-disable-next-line @typescript-eslint/no-require-imports
const parseConflictJSONModule = require("parse-conflict-json");
const parseConflictJSON = parseConflictJSONModule?.default ?? parseConflictJSONModule;
const ENV_TRIM_LEN = 20;
const ARGS_MARKER = "$@";
const QUOTED_ARGS_MARKER = `"${ARGS_MARKER}"`;
/**
 * Renders args for splicing into a string command, escaped for whichever shell
 * will parse that command.
 *
 * Everything except `cmd.exe` gets POSIX single-quoting, which survives dax's
 * built-in shell and any POSIX shell losslessly. `cmd.exe` has no single-quote
 * syntax, so it keeps the double-quoted form.
 */
function escapeArgsFor(shell, args) {
    return isCmdExe(shell)
        ? args.map(quoteArgCmd).join(" ")
        : (0, dax_1.escapeCommand)(args);
}
/**
 * Whether a resolved shell means the host's `cmd.exe`: the only target that
 * cannot parse POSIX quoting.
 */
function isCmdExe(shell) {
    return shell === "system" && process.platform === "win32";
}
/**
 * Double-quotes a single argument for `cmd.exe`, escaping the characters that
 * stay special inside double quotes. Note that `cmd.exe` itself has no in-quote
 * escape - `\"` is understood by the receiving program's argv parser, not by the
 * shell - and `%VAR%` still expands, so not every value can be passed verbatim.
 */
function quoteArgCmd(arg) {
    return '"' + arg.replace(/(["$`\\])/g, "\\$1") + '"';
}
/**
 * dax's built-in cross-platform shell only implements a subset of POSIX shell
 * syntax and throws a terse `Not implemented: ...` for the rest. Rewrite those
 * into a short, actionable error that points at the system-shell escape hatch;
 * pass every other error through unchanged.
 */
function enrichBuiltinShellError(error, command) {
    const message = error instanceof Error ? error.message : String(error);
    if (!/Not implemented:/.test(message)) {
        /* v8 ignore next */
        return error;
    }
    const commandLine = Array.isArray(command) ? command.join(" ") : command;
    return new Error("projen's built-in shell can't run this command:\n" +
        `  ${commandLine}\n` +
        "To use your system's shell instead, set this task to TaskShell.system().");
}
/**
 * The runtime component of the tasks engine.
 */
class TaskRuntime {
    /**
     * The project-relative path of the tasks manifest file.
     */
    static MANIFEST_FILE = path.posix.join(common_1.PROJEN_DIR, "tasks.json");
    /**
     * One-shot entrypoint for the standalone task runner.
     *
     * Creates a runtime rooted at the current working directory, runs the named
     * task, and converts any failure into a non-zero process exit code. This is
     * the single line invoked by the bundled `scripts/run-task.cjs` that
     * "projen eject" emits, which keeps the generated bundle footer trivial.
     *
     * @param name The name of the task to run. Defaults to `process.argv[2]`.
     */
    static async main(name = process.argv[2]) {
        try {
            await new TaskRuntime(".").runTask(name);
        }
        catch (e) {
            console.error(e?.stack ?? String(e));
            process.exit(1);
        }
    }
    /**
     * The contents of tasks.json
     */
    _manifest = { tasks: {} };
    /**
     * The raw contents of the currently loaded manifest, used to detect changes
     * on disk so the runtime can reload a regenerated manifest mid-run.
     */
    _identity;
    /**
     * The root directory of the project and the cwd for executing tasks.
     */
    workdir;
    constructor(workdir) {
        this.workdir = (0, path_1.resolve)(workdir);
        // Perform the initial load. This also verifies the manifest's schema
        // version.
        this.reloadManifestIfChanged();
    }
    /**
     * The contents of tasks.json
     */
    get manifest() {
        return this._manifest;
    }
    /**
     * The absolute path of the tasks manifest file.
     */
    get manifestPath() {
        return (0, path_1.join)(this.workdir, TaskRuntime.MANIFEST_FILE);
    }
    /**
     * 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.
     */
    async runTask(name, parents = [], args = [], env = {}, options = {}) {
        // A previously executed task (most importantly the "default"/synth task,
        // which `build` spawns first) may have regenerated `.projen/tasks.json`.
        // Pick up any such changes before resolving and running this task so we
        // never execute a stale, in-memory definition.
        this.reloadManifestIfChanged();
        const task = this.tryFindTask(name);
        if (!task) {
            throw new Error(`cannot find command ${name}`);
        }
        const runner = new RunTask(this, task, parents, args, env);
        return options.captureOutput ? runner.runCapturingOutput() : runner.run();
    }
    /**
     * Re-reads the tasks manifest from disk if its contents changed since it was
     * last loaded, verifying its schema version along the way.
     *
     * Change detection compares the raw file contents, so an unchanged manifest
     * is not re-verified or re-adopted.
     */
    reloadManifestIfChanged() {
        if (!(0, fs_1.existsSync)(this.manifestPath)) {
            // No manifest on disk: treat as an empty project (legacy behavior).
            this._manifest = { tasks: {} };
            this._identity = undefined;
            return;
        }
        const raw = (0, fs_1.readFileSync)(this.manifestPath, "utf-8");
        if (raw === this._identity) {
            return; // unchanged since the last load
        }
        const manifest = parseConflictJSON(raw, undefined, "theirs");
        // A previously loaded manifest means this is a *reload* (e.g. the
        // "default"/synth task regenerated the file mid-run), as opposed to the
        // initial load performed by the constructor.
        const isReload = this._identity !== undefined;
        this.verifyManifest(manifest);
        this._manifest = manifest;
        this._identity = raw;
        if (isReload) {
            logging.debug(`${TaskRuntime.MANIFEST_FILE} changed on disk; successfully loaded the new tasks manifest.`);
        }
    }
    /**
     * Validates a freshly read manifest:
     *
     * - Legacy manifests (no `manifestVersion`) are accepted as-is for backwards
     *   compatibility.
     * - Manifests from a newer projen (a higher `manifestVersion`) are accepted
     *   with a warning, since this runtime may not understand the schema.
     */
    verifyManifest(manifest) {
        // Backwards compatibility: manifests generated before versioning carry no
        // version.
        if (manifest.manifestVersion === undefined) {
            return;
        }
        if (manifest.manifestVersion > common_1.TASKS_MANIFEST_VERSION) {
            logging.warn(`${TaskRuntime.MANIFEST_FILE} was generated by a newer version of projen ` +
                `(manifest version ${manifest.manifestVersion}, this projen supports up to ${common_1.TASKS_MANIFEST_VERSION}). ` +
                `Some tasks may not behave as expected; consider upgrading projen.`);
        }
    }
}
exports.TaskRuntime = TaskRuntime;
class RunTask {
    runtime;
    task;
    args;
    envParam;
    env = {};
    parents;
    workdir;
    // When set, every step's stdout is captured and accumulated (for a spawned
    // task whose aggregate output the caller wants).
    captureAll = false;
    captured = [];
    // `outputEnv` captures, propagated to spawned subtasks (exec/builtin steps
    // see them via `this.env`).
    capturedEnv = {};
    constructor(runtime, task, parents = [], args = [], envParam = {}) {
        this.runtime = runtime;
        this.task = task;
        this.args = args;
        this.envParam = envParam;
        this.workdir = task.cwd ?? this.runtime.workdir;
        this.parents = parents;
    }
    /**
     * Runs the task, capturing and returning the trimmed, newline-joined stdout
     * of all its steps (and any nested spawned tasks) in execution order.
     */
    async runCapturingOutput() {
        this.captureAll = true;
        await this.run();
        return this.captured.join("\n").trim();
    }
    /**
     * Records a step's captured (trimmed) stdout: into `outputEnv` for later
     * steps (and propagated to spawned subtasks), and into the run's aggregate
     * output when capturing everything.
     */
    recordCapture(outputEnv, value) {
        if (outputEnv) {
            this.env[outputEnv] = value;
            this.capturedEnv[outputEnv] = value;
        }
        if (this.captureAll) {
            this.captured.push(value);
        }
    }
    /**
     * Executes the task. This was previously done in the constructor, but is now
     * an async method since shell execution is asynchronous (e.g. dax on
     * Windows).
     */
    async run() {
        const { task, args, parents } = this;
        if (!task.steps || task.steps.length === 0) {
            this.logDebug((0, chalk_1.gray)("No actions have been specified for this task."));
            return;
        }
        this.env = await this.resolveEnvironment(this.envParam, parents, this.resolveShell());
        const envlogs = [];
        for (const [k, v] of Object.entries(this.env)) {
            const vv = v ?? "";
            const trimmed = vv.length > ENV_TRIM_LEN ? vv.substring(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 (!(await this.evalCondition(task, this.resolveShell()))) {
            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) {
            const stepShell = this.resolveShell(step);
            // evaluate step condition
            if (!(await this.evalCondition(step, stepShell))) {
                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) {
                const capture = this.captureAll || !!step.outputEnv;
                const output = await this.runtime.runTask(step.spawn, [...this.parents, this.task.name], argsList, { ...this.capturedEnv, ...step.env }, { captureOutput: capture });
                if (typeof output === "string") {
                    this.recordCapture(step.outputEnv, output);
                }
            }
            const execs = step.exec ? [step.exec] : [];
            // Parse step-specific environment variables
            const env = await this.evalEnvironment(step.env ?? {}, stepShell);
            if (step.builtin) {
                execs.push(this.renderBuiltin(step.builtin));
            }
            // `execArgs` is an explicit argv (the program followed by its arguments).
            // It is handed to `shell()` as an array rather than a rendered string, so
            // it runs without a shell and every element is passed through verbatim -
            // which is what lets callers avoid thinking about quoting. Fixed/received
            // args are spliced in wherever a `$@` marker element appears (mirroring
            // the string `exec` behavior), or appended at the end if there is none.
            if (step.execArgs) {
                const argv = [];
                let placed = false;
                for (const element of step.execArgs) {
                    if (element === ARGS_MARKER) {
                        argv.push(...argsList);
                        placed = true;
                    }
                    else {
                        argv.push(element);
                    }
                }
                if (!placed) {
                    argv.push(...argsList);
                }
                execs.push(argv);
            }
            for (const exec of execs) {
                let command = exec;
                // A string command is a shell line: splice task args in per the `$@`
                // marker rules. An `execArgs` argv already carries its args, untouched.
                if (typeof command === "string") {
                    if (command.includes(QUOTED_ARGS_MARKER)) {
                        // `"$@"`: splice each arg in as a separate verbatim word (like
                        // bash's quoted `"$@"`), so whitespace and metacharacters survive.
                        command = command.replace(QUOTED_ARGS_MARKER, escapeArgsFor(stepShell, argsList));
                    }
                    else if (command.includes(ARGS_MARKER)) {
                        command = command.replace(ARGS_MARKER, argsList.join(" "));
                    }
                    else {
                        command = [command, ...argsList].join(" ");
                    }
                }
                const cwd = step.cwd;
                const capture = this.captureAll || !!step.outputEnv;
                // A thrown error (e.g. spawn failure) propagates; a non-zero exit is
                // reported via `result.status`.
                const result = await this.shell({
                    command,
                    cwd,
                    extraEnv: env,
                    shell: stepShell,
                    captureOutput: capture,
                });
                if (result.status !== 0) {
                    throw new Error(`Task "${this.fullname}" failed when executing "${Array.isArray(command) ? command.join(" ") : command}" (cwd: ${(0, path_1.resolve)(cwd ?? this.workdir)})`);
                }
                if (capture) {
                    const stdout = result.stdout?.toString("utf-8").trim() ?? "";
                    this.recordCapture(step.outputEnv, stdout);
                }
            }
        }
    }
    /**
     * 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.
     */
    async evalCondition(taskOrStep, shell) {
        // no condition, carry on
        if (!taskOrStep.condition) {
            return true;
        }
        this.log((0, chalk_1.gray)(`${(0, chalk_1.underline)("condition")}: ${taskOrStep.condition}`));
        const result = await this.shell({
            command: taskOrStep.condition,
            quiet: true,
            shell,
        });
        if (result.status === 0) {
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * Evaluates environment variables from shell commands (e.g. `$(xx)`)
     */
    async evalEnvironment(env, shell) {
        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 = await this.shell({
                    command: query,
                    quiet: true,
                    captureOutput: true,
                    shell,
                });
                if (result.status !== 0) {
                    const error = result.error
                        ? result.error.stack
                        : result.stderr?.toString().trim() ||
                            result.stdout?.toString().trim() ||
                            `command exited with code ${result.status}`;
                    logging.warn(this.fmtLog(`${(0, chalk_1.underline)(key)}: unable to evaluate "${query}". Environment variable will be skipped. Check that the command exists and runs successfully.`));
                    logging.warn(this.fmtLog(`${(0, chalk_1.underline)(key)}: ${error}`));
                }
                else {
                    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.
     */
    async resolveEnvironment(envParam, parents, shell) {
        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, shell);
    }
    /**
     * Resolves the shell for a step's command (or the task's, when no step is
     * given): step, then task, then project default, then "projen".
     */
    resolveShell(step) {
        return (step?.shell ?? this.task.shell ?? this.runtime.manifest.shell ?? "projen");
    }
    /**
     * 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);
    }
    async shell(options) {
        const quiet = options.quiet ?? false;
        if (!quiet) {
            const log = new Array();
            log.push(Array.isArray(options.command)
                ? options.command.join(" ")
                : 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`);
        }
        // The resolved shell is one of:
        // - "projen" (default): dax's in-process cross-platform shell, so POSIX-style
        //   task syntax (`mkdir -p`, `&&`, `$VAR`, ...) works the same everywhere.
        // - "system": the host's native shell (`/bin/sh`, or `cmd.exe` on Windows).
        // - an argv, e.g. ["bash","-c"]: a shell invocation with the command appended
        //   as its final argument.
        const shell = options.shell ?? "projen";
        if (typeof shell === "string" && shell !== "projen" && shell !== "system") {
            throw new Error(`unknown built-in shell ${JSON.stringify(shell)}; use the built-in "projen" or "system" shells, or a TaskShell.command([...]) invocation`);
        }
        const capture = options.captureOutput ?? false;
        // Quiet captures (`$(...)`, conditions) stay silent; visible captures
        // (`outputEnv`) stream live while still buffering.
        const stream = capture && !quiet;
        const command = options.command;
        const env = {
            ...process.env,
            ...this.env,
            ...options.extraEnv,
        };
        // "system": the host-native engine. A string command runs through the OS
        // shell; an `execArgs` argv is spawned directly (shell-free), so the real
        // binary runs with no dax built-ins. (Only `$(...)`/condition eval captures,
        // and those always pass a string, so an array command never needs capture.)
        if (shell === "system") {
            if (Array.isArray(command)) {
                const [program, ...args] = command;
                try {
                    (0, exec_1.tool)(program).run(args, { cwd, env, inheritStdio: true });
                    return { status: 0 };
                }
                catch (e) {
                    if (typeof e?.status === "number") {
                        return { status: e.status };
                    }
                    throw e;
                }
            }
            return systemShell(command, { cwd, env, capture, stream });
        }
        // Otherwise run through dax: the "projen" shell or an explicit invocation.
        const builder = this.buildDaxCommand(command, shell);
        // `inheritPiped` streams and buffers; `piped` buffers quietly. stderr is
        // buffered only for quiet captures, so it can surface in errors.
        const stdoutMode = capture
            ? stream
                ? "inheritPiped"
                : "piped"
            : "inherit";
        const stderrMode = capture && !stream ? "piped" : "inherit";
        let result;
        try {
            result = await builder
                .cwd(cwd)
                .env(env)
                .stdout(stdoutMode)
                .stderr(stderrMode)
                .noThrow();
        }
        catch (e) {
            // dax's in-process shell throws a terse `Not implemented: ...` for shell
            // syntax it does not support (e.g. `$(...)` command substitution); turn
            // that into an actionable error that points at the system-shell escape
            // hatch. Other errors pass through unchanged.
            throw enrichBuiltinShellError(e, command);
        }
        return {
            status: result.code,
            stdout: capture ? Buffer.from(result.stdoutBytes) : null,
            stderr: capture && !stream ? Buffer.from(result.stderrBytes) : null,
        };
    }
    /**
     * Builds the dax command for the "projen" shell or an explicit invocation.
     * (The "system" shell is handled host-side, not here.) `command` is a shell
     * line (string) or an `execArgs` argv (string[]); `shell` is `"projen"` or an
     * invocation argv such as `["bash", "-c"]`.
     */
    buildDaxCommand(command, shell) {
        // An invocation (e.g. ["bash","-c"], ["npx","--no","-c"]): append the
        // command as its final argument. A string is appended as-is; an `execArgs`
        // argv is rendered to a quoted command line so the shell re-parses the same
        // argv. That rendering assumes a POSIX-style shell, which is what such an
        // invocation is (`bash -c`, `sh -c`, `npx -c`, ...).
        if (Array.isArray(shell)) {
            const [program, ...flags] = shell;
            const commandLine = Array.isArray(command)
                ? (0, dax_1.escapeCommand)(command)
                : command;
            return (0, dax_1.$) `${program} ${[...flags, commandLine]}`;
        }
        // The built-in "projen" shell (dax).
        return Array.isArray(command)
            ? // execArgs: shell-free argv (each element escaped; `.cmd` shims resolved).
                (0, dax_1.$) `${command[0]} ${command.slice(1)}`
            : // string command, parsed in-process by dax's cross-platform shell.
                dax_1.$.raw `${command}`;
    }
    renderBuiltin(builtin) {
        // Locate projen's package root by walking up from this module's directory
        // until we find a package.json. This works whether the code runs from the
        // compiled file (lib/cli/task-runtime.js) or from the bundled run-task.cjs
        // (lib/run-task.cjs), which live at different depths - so a hard-coded
        // relative path to package.json would be wrong in one of the two cases.
        let moduleRoot = __dirname;
        while (!(0, fs_1.existsSync)((0, path_1.join)(moduleRoot, "package.json"))) {
            const parent = (0, path_1.dirname)(moduleRoot);
            if (parent === moduleRoot) {
                throw new Error("unable to locate the projen package root");
            }
            moduleRoot = parent;
        }
        const program = require.resolve((0, path_1.join)(moduleRoot, "lib", `${builtin}.task.js`));
        return `"${process.execPath}" "${program}"`;
    }
}
/**
 * Runs a command line through the operating system's native shell.
 *
 * Calls the OS shell via `child_process` with `shell: true`.
 * This backs the `system` task shell, which lets a user opt out of the built-in
 * cross-platform shell and use the host's native shell instead:
 * `/bin/sh`on POSIX and `cmd.exe` on Windows.
 *
 * Never throws for a non-zero exit (that is reported via `status`);
 * a spawn failure is reported via `error`. The caller supplies the full `env`.
 */
function systemShell(command, options) {
    logging.debug(`${command} (cwd: ${options.cwd})`);
    const result = child_process.spawnSync(command, {
        cwd: options.cwd,
        shell: true,
        maxBuffer: exec_1.MAX_BUFFER,
        env: options.env,
        // Quiet capture buffers stderr for error messages. Streamed capture
        // inherits stderr and re-emits buffered stdout afterwards, since spawnSync
        // can't both show and buffer the same stream at once.
        stdio: options.capture
            ? options.stream
                ? ["inherit", "pipe", "inherit"]
                : ["inherit", "pipe", "pipe"]
            : "inherit",
    });
    if (options.capture && options.stream && result.stdout) {
        process.stdout.write(result.stdout);
    }
    return {
        status: result.status,
        stdout: result.stdout ?? null,
        stderr: result.stderr ?? null,
        error: result.error,
    };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1ydW50aW1lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS90YXNrLXJ1bnRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBdTBCQSxrQ0FpQ0M7QUF4MkJELDZEQUErQztBQUMvQywyQkFBd0Q7QUFDeEQsK0JBQThDO0FBQzlDLDJDQUE2QjtBQUM3QiwrQkFBOEI7QUFDOUIsaUNBQXdDO0FBQ3hDLHNDQUErRDtBQUMvRCxvREFBc0M7QUFFdEMscUNBQStDO0FBQy9DLHVDQUFnRDtBQUVoRCxxRUFBcUU7QUFDckUsZ0ZBQWdGO0FBQ2hGLGdGQUFnRjtBQUNoRiwyRUFBMkU7QUFDM0UsbUVBQW1FO0FBQ25FLGlFQUFpRTtBQUNqRSxNQUFNLHVCQUF1QixHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0FBQy9ELE1BQU0saUJBQWlCLEdBQ3JCLHVCQUF1QixFQUFFLE9BQU8sSUFBSSx1QkFBdUIsQ0FBQztBQUU5RCxNQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7QUFDeEIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDO0FBQ3pCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxXQUFXLEdBQUcsQ0FBQztBQUU5Qzs7Ozs7OztHQU9HO0FBQ0gsU0FBUyxhQUFhLENBQUMsS0FBd0IsRUFBRSxJQUFjO0lBQzdELE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQztRQUNwQixDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxJQUFBLG1CQUFhLEVBQUMsSUFBSSxDQUFDLENBQUM7QUFDMUIsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsUUFBUSxDQUFDLEtBQXdCO0lBQ3hDLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sQ0FBQztBQUM1RCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLFdBQVcsQ0FBQyxHQUFXO0lBQzlCLE9BQU8sR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUN2RCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLHVCQUF1QixDQUM5QixLQUFjLEVBQ2QsT0FBMEI7SUFFMUIsTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN0QyxvQkFBb0I7UUFDcEIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0lBQ3pFLE9BQU8sSUFBSSxLQUFLLENBQ2QsbURBQW1EO1FBQ2pELEtBQUssV0FBVyxJQUFJO1FBQ3BCLDBFQUEwRSxDQUM3RSxDQUFDO0FBQ0osQ0FBQztBQThCRDs7R0FFRztBQUNILE1BQWEsV0FBVztJQUN0Qjs7T0FFRztJQUNJLE1BQU0sQ0FBVSxhQUFhLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQ3BELG1CQUFVLEVBQ1YsWUFBWSxDQUNiLENBQUM7SUFFRjs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFlLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxTQUFTLEdBQWtCLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBRWpEOzs7T0FHRztJQUNLLFNBQVMsQ0FBVTtJQUUzQjs7T0FFRztJQUNhLE9BQU8sQ0FBUztJQUVoQyxZQUFZLE9BQWU7UUFDekIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFBLGNBQU8sRUFBQyxPQUFPLENBQUMsQ0FBQztRQUNoQyxxRUFBcUU7UUFDckUsV0FBVztRQUNYLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsUUFBUTtRQUNqQixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDeEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBWSxZQUFZO1FBQ3RCLE9BQU8sSUFBQSxXQUFJLEVBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBVyxLQUFLO1FBQ2QsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLFdBQVcsQ0FBQyxJQUFZO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3pCLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7O09BR0c7SUFDSSxLQUFLLENBQUMsT0FBTyxDQUNsQixJQUFZLEVBQ1osVUFBb0IsRUFBRSxFQUN0QixPQUErQixFQUFFLEVBQ2pDLE1BQWtDLEVBQUUsRUFDcEMsVUFBdUMsRUFBRTtRQUV6Qyx5RUFBeUU7UUFDekUseUVBQXlFO1FBQ3pFLHdFQUF3RTtRQUN4RSwrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7UUFFL0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDVixNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFFRCxNQUFNLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDM0QsT0FBTyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzVFLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSyx1QkFBdUI7UUFDN0IsSUFBSSxDQUFDLElBQUEsZUFBVSxFQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQ25DLG9FQUFvRTtZQUNwRSxJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1lBQzNCLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxHQUFHLEdBQUcsSUFBQSxpQkFBWSxFQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDckQsSUFBSSxHQUFHLEtBQUssSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzNCLE9BQU8sQ0FBQyxnQ0FBZ0M7UUFDMUMsQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFrQixpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRTVFLGtFQUFrRTtRQUNsRSx3RUFBd0U7UUFDeEUsNkNBQTZDO1FBQzdDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDO1FBRTlDLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUM7UUFDMUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxHQUFHLENBQUM7UUFFckIsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLE9BQU8sQ0FBQyxLQUFLLENBQ1gsR0FBRyxXQUFXLENBQUMsYUFBYSwrREFBK0QsQ0FDNUYsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNLLGNBQWMsQ0FBQyxRQUF1QjtRQUM1QywwRUFBMEU7UUFDMUUsV0FBVztRQUNYLElBQUksUUFBUSxDQUFDLGVBQWUsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMzQyxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksUUFBUSxDQUFDLGVBQWUsR0FBRywrQkFBc0IsRUFBRSxDQUFDO1lBQ3RELE9BQU8sQ0FBQyxJQUFJLENBQ1YsR0FBRyxXQUFXLENBQUMsYUFBYSw4Q0FBOEM7Z0JBQ3hFLHFCQUFxQixRQUFRLENBQUMsZUFBZSxnQ0FBZ0MsK0JBQXNCLEtBQUs7Z0JBQ3hHLG1FQUFtRSxDQUN0RSxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7O0FBeEtILGtDQXlLQztBQUVELE1BQU0sT0FBTztJQWdCUTtJQUNBO0lBRUE7SUFDQTtJQW5CWCxHQUFHLEdBQTJDLEVBQUUsQ0FBQztJQUN4QyxPQUFPLENBQVc7SUFFbEIsT0FBTyxDQUFTO0lBRWpDLDJFQUEyRTtJQUMzRSxpREFBaUQ7SUFDekMsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUNWLFFBQVEsR0FBYSxFQUFFLENBQUM7SUFFekMsMkVBQTJFO0lBQzNFLDRCQUE0QjtJQUNYLFdBQVcsR0FBK0IsRUFBRSxDQUFDO0lBRTlELFlBQ21CLE9BQW9CLEVBQ3BCLElBQWMsRUFDL0IsVUFBb0IsRUFBRSxFQUNMLE9BQStCLEVBQUUsRUFDakMsV0FBdUMsRUFBRTtRQUp6QyxZQUFPLEdBQVAsT0FBTyxDQUFhO1FBQ3BCLFNBQUksR0FBSixJQUFJLENBQVU7UUFFZCxTQUFJLEdBQUosSUFBSSxDQUE2QjtRQUNqQyxhQUFRLEdBQVIsUUFBUSxDQUFpQztRQUUxRCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDaEQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxrQkFBa0I7UUFDN0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsTUFBTSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN6QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGFBQWEsQ0FBQyxTQUE2QixFQUFFLEtBQWE7UUFDaEUsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSyxDQUFDO1lBQzVCLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQ3RDLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLLENBQUMsR0FBRztRQUNkLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQztRQUVyQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUEsWUFBSSxFQUFDLCtDQUErQyxDQUFDLENBQUMsQ0FBQztZQUNyRSxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQ3RDLElBQUksQ0FBQyxRQUFRLEVBQ2IsT0FBTyxFQUNQLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FDcEIsQ0FBQztRQUVGLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNuQixLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM5QyxNQUFNLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ25CLE1BQU0sT0FBTyxHQUNYLEVBQUUsQ0FBQyxNQUFNLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxZQUFZLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN4RSxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDbEMsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBQSxZQUFJLEVBQUMsR0FBRyxJQUFBLGlCQUFTLEVBQUMsS0FBSyxDQUFDLEtBQUssT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNuRSxDQUFDO1FBRUQscUJBQXFCO1FBQ3JCLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzNELElBQUksQ0FBQyxHQUFHLENBQUMsMkNBQTJDLENBQUMsQ0FBQztZQUN0RCxPQUFPO1FBQ1QsQ0FBQztRQUVELHVEQUF1RDtRQUN2RCxNQUFNLE1BQU0sR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUMvQyxNQUFNLE9BQU8sR0FBRyxJQUFJLEtBQUssRUFBVSxDQUFDO1FBQ3BDLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLFdBQVcsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUMxQyxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQztnQkFDdEIsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNyQixDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN2QixNQUFNLElBQUksS0FBSyxDQUNiLDJDQUEyQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQy9ELENBQUM7UUFDSixDQUFDO1FBRUQsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDOUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUUxQywwQkFBMEI7WUFDMUIsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ2pELElBQUksQ0FBQyxHQUFHLENBQUMsMkNBQTJDLENBQUMsQ0FBQztnQkFDdEQsU0FBUztZQUNYLENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBYTtnQkFDekIsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUNwQixHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDbEMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBRTNCLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNiLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUN0QyxDQUFDO1lBRUQsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDcEQsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FDdkMsSUFBSSxDQUFDLEtBQUssRUFDVixDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUNqQyxRQUFRLEVBQ1IsRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQ3BDLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxDQUMzQixDQUFDO2dCQUNGLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7b0JBQy9CLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDN0MsQ0FBQztZQUNILENBQUM7WUFFRCxNQUFNLEtBQUssR0FBNkIsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUVyRSw0Q0FBNEM7WUFDNUMsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBRWxFLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNqQixLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDL0MsQ0FBQztZQUVELDBFQUEwRTtZQUMxRSwwRUFBMEU7WUFDMUUseUVBQXlFO1lBQ3pFLDBFQUEwRTtZQUMxRSx3RUFBd0U7WUFDeEUsd0VBQXdFO1lBQ3hFLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNsQixNQUFNLElBQUksR0FBYSxFQUFFLENBQUM7Z0JBQzFCLElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQztnQkFDbkIsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQ3BDLElBQUksT0FBTyxLQUFLLFdBQVcsRUFBRSxDQUFDO3dCQUM1QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUM7d0JBQ3ZCLE1BQU0sR0FBRyxJQUFJLENBQUM7b0JBQ2hCLENBQUM7eUJBQU0sQ0FBQzt3QkFDTixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO29CQUNyQixDQUFDO2dCQUNILENBQUM7Z0JBQ0QsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQztnQkFDekIsQ0FBQztnQkFDRCxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ25CLENBQUM7WUFFRCxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUN6QixJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUM7Z0JBRW5CLHFFQUFxRTtnQkFDckUsd0VBQXdFO2dCQUN4RSxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUNoQyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDO3dCQUN6QywrREFBK0Q7d0JBQy9ELG1FQUFtRTt3QkFDbkUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQ3ZCLGtCQUFrQixFQUNsQixhQUFhLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUNuQyxDQUFDO29CQUNKLENBQUM7eUJBQU0sSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7d0JBQ3pDLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQzdELENBQUM7eUJBQU0sQ0FBQzt3QkFDTixPQUFPLEdBQUcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQzdDLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO2dCQUNyQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNwRCxxRUFBcUU7Z0JBQ3JFLGdDQUFnQztnQkFDaEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDO29CQUM5QixPQUFPO29CQUNQLEdBQUc7b0JBQ0gsUUFBUSxFQUFFLEdBQUc7b0JBQ2IsS0FBSyxFQUFFLFNBQVM7b0JBQ2hCLGFBQWEsRUFBRSxPQUFPO2lCQUN2QixDQUFDLENBQUM7Z0JBQ0gsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUN4QixNQUFNLElBQUksS0FBSyxDQUNiLFNBQVMsSUFBSSxDQUFDLFFBQVEsNEJBQ3BCLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQy9DLFdBQVcsSUFBQSxjQUFPLEVBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUMzQyxDQUFDO2dCQUNKLENBQUM7Z0JBQ0QsSUFBSSxPQUFPLEVBQUUsQ0FBQztvQkFDWixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUM7b0JBQzdELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDN0MsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNLLEtBQUssQ0FBQyxhQUFhLENBQ3pCLFVBQStCLEVBQy9CLEtBQXdCO1FBRXhCLHlCQUF5QjtRQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzFCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELElBQUksQ0FBQyxHQUFHLENBQUMsSUFBQSxZQUFJLEVBQUMsR0FBRyxJQUFBLGlCQUFTLEVBQUMsV0FBVyxDQUFDLEtBQUssVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNyRSxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUM7WUFDOUIsT0FBTyxFQUFFLFVBQVUsQ0FBQyxTQUFTO1lBQzdCLEtBQUssRUFBRSxJQUFJO1lBQ1gsS0FBSztTQUNOLENBQUMsQ0FBQztRQUNILElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLGVBQWUsQ0FDM0IsR0FBK0IsRUFDL0IsS0FBd0I7UUFFeEIsTUFBTSxNQUFNLEdBQTJDLEVBQUUsQ0FBQztRQUUxRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUNyRCxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNsRSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNuRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUM7b0JBQzlCLE9BQU8sRUFBRSxLQUFLO29CQUNkLEtBQUssRUFBRSxJQUFJO29CQUNYLGFBQWEsRUFBRSxJQUFJO29CQUNuQixLQUFLO2lCQUNOLENBQUMsQ0FBQztnQkFDSCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQ3hCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLO3dCQUN4QixDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLO3dCQUNwQixDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUU7NEJBQ2hDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQUMsSUFBSSxFQUFFOzRCQUNoQyw0QkFBNEIsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUVoRCxPQUFPLENBQUMsSUFBSSxDQUNWLElBQUksQ0FBQyxNQUFNLENBQ1QsR0FBRyxJQUFBLGlCQUFTLEVBQUMsR0FBRyxDQUFDLHlCQUF5QixLQUFLLCtGQUErRixDQUMvSSxDQUNGLENBQUM7b0JBQ0YsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBQSxpQkFBUyxFQUFDLEdBQUcsQ0FBQyxLQUFLLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDM0QsQ0FBQztxQkFBTSxDQUFDO29CQUNOLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUM7Z0JBQzlELENBQUM7WUFDSCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUN0QixDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssS0FBSyxDQUFDLGtCQUFrQixDQUM5QixRQUFvQyxFQUNwQyxPQUFpQixFQUNqQixLQUF3QjtRQUV4QixJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDO1FBRTFDLDJDQUEyQztRQUMzQyxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzdCLEdBQUcsR0FBRztnQkFDSixHQUFHLEdBQUc7Z0JBQ04sR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsSUFBSSxFQUFFLENBQUM7YUFDakQsQ0FBQztRQUNKLENBQUM7UUFFRCxxREFBcUQ7UUFDckQsR0FBRyxHQUFHO1lBQ0osR0FBRyxHQUFHO1lBQ04sR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQztZQUN4QixHQUFHLFFBQVE7U0FDWixDQUFDO1FBRUYsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssWUFBWSxDQUFDLElBQWU7UUFDbEMsT0FBTyxDQUNMLElBQUksRUFBRSxLQUFLLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FDMUUsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVksUUFBUTtRQUNsQixPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFTyxHQUFHLENBQUMsR0FBRyxJQUFXO1FBQ3hCLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVPLFFBQVEsQ0FBQyxHQUFHLElBQVc7UUFDN0IsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRU8sTUFBTSxDQUFDLEdBQUcsSUFBVztRQUMzQixPQUFPLElBQUEsYUFBTSxFQUFDLEdBQUcsSUFBQSxpQkFBUyxFQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVPLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBcUI7UUFDdkMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUM7UUFDckMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxHQUFHLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztZQUVoQyxHQUFHLENBQUMsSUFBSSxDQUNOLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztnQkFDNUIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztnQkFDM0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLENBQUM7WUFFRixJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDaEIsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLE9BQU8sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQ3BDLENBQUM7WUFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMxQixDQUFDO1FBRUQsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxJQUFBLGVBQVUsRUFBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUEsYUFBUSxFQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDckQsTUFBTSxJQUFJLEtBQUssQ0FDYiwwQkFBMEIsR0FBRyxnQ0FBZ0MsQ0FDOUQsQ0FBQztRQUNKLENBQUM7UUFFRCxnQ0FBZ0M7UUFDaEMsOEVBQThFO1FBQzlFLDJFQUEyRTtRQUMzRSw0RUFBNEU7UUFDNUUsOEVBQThFO1FBQzlFLDJCQUEyQjtRQUMzQixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQztRQUN4QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMxRSxNQUFNLElBQUksS0FBSyxDQUNiLDBCQUEwQixJQUFJLENBQUMsU0FBUyxDQUN0QyxLQUFLLENBQ04sMEZBQTBGLENBQzVGLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLGFBQWEsSUFBSSxLQUFLLENBQUM7UUFDL0Msc0VBQXNFO1FBQ3RFLG1EQUFtRDtRQUNuRCxNQUFNLE1BQU0sR0FBRyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7UUFFakMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUNoQyxNQUFNLEdBQUcsR0FBRztZQUNWLEdBQUcsT0FBTyxDQUFDLEdBQUc7WUFDZCxHQUFHLElBQUksQ0FBQyxHQUFHO1lBQ1gsR0FBRyxPQUFPLENBQUMsUUFBUTtTQUNwQixDQUFDO1FBRUYseUVBQXlFO1FBQ3pFLDBFQUEwRTtRQUMxRSw2RUFBNkU7UUFDN0UsNEVBQTRFO1FBQzVFLElBQUksS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3ZCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUMzQixNQUFNLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDO2dCQUNuQyxJQUFJLENBQUM7b0JBQ0gsSUFBQSxXQUFJLEVBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQzFELE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZCLENBQUM7Z0JBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztvQkFDaEIsSUFBSSxPQUFPLENBQUMsRUFBRSxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7d0JBQ2xDLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUM5QixDQUFDO29CQUNELE1BQU0sQ0FBQyxDQUFDO2dCQUNWLENBQUM7WUFDSCxDQUFDO1lBQ0QsT0FBTyxXQUFXLENBQUMsT0FBTyxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBRUQsMkVBQTJFO1FBQzNFLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXJELHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsTUFBTSxVQUFVLEdBQUcsT0FBTztZQUN4QixDQUFDLENBQUMsTUFBTTtnQkFDTixDQUFDLENBQUMsY0FBYztnQkFDaEIsQ0FBQyxDQUFDLE9BQU87WUFDWCxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ2QsTUFBTSxVQUFVLEdBQUcsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUU1RCxJQUFJLE1BQU0sQ0FBQztRQUNYLElBQUksQ0FBQztZQUNILE1BQU0sR0FBRyxNQUFNLE9BQU87aUJBQ25CLEdBQUcsQ0FBQyxHQUFHLENBQUM7aUJBQ1IsR0FBRyxDQUFDLEdBQUcsQ0FBQztpQkFDUixNQUFNLENBQUMsVUFBVSxDQUFDO2lCQUNsQixNQUFNLENBQUMsVUFBVSxDQUFDO2lCQUNsQixPQUFPLEVBQUUsQ0FBQztRQUNmLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gseUVBQXlFO1lBQ3pFLHdFQUF3RTtZQUN4RSx1RUFBdUU7WUFDdkUsOENBQThDO1lBQzlDLE1BQU0sdUJBQXVCLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzVDLENBQUM7UUFFRCxPQUFPO1lBQ0wsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJO1lBQ25CLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO1lBQ3hELE1BQU0sRUFBRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO1NBQ3BFLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxlQUFlLENBQ3JCLE9BQTBCLEVBQzFCLEtBQXdCO1FBRXhCLHNFQUFzRTtRQUN0RSwyRUFBMkU7UUFDM0UsNEVBQTRFO1FBQzVFLDBFQUEwRTtRQUMxRSxxREFBcUQ7UUFDckQsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDekIsTUFBTSxDQUFDLE9BQU8sRUFBRSxHQUFHLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUNsQyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztnQkFDeEMsQ0FBQyxDQUFDLElBQUEsbUJBQWEsRUFBQyxPQUFPLENBQUM7Z0JBQ3hCLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDWixPQUFPLElBQUEsT0FBQyxFQUFBLEdBQUcsT0FBTyxJQUFJLENBQUMsR0FBRyxLQUFLLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQztRQUNsRCxDQUFDO1FBRUQscUNBQXFDO1FBQ3JDLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7WUFDM0IsQ0FBQyxDQUFDLDJFQUEyRTtnQkFDM0UsSUFBQSxPQUFDLEVBQUEsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUN0QyxDQUFDLENBQUMsbUVBQW1FO2dCQUNuRSxPQUFDLENBQUMsR0FBRyxDQUFBLEdBQUcsT0FBTyxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVPLGFBQWEsQ0FBQyxPQUFlO1FBQ25DLDBFQUEwRTtRQUMxRSwwRUFBMEU7UUFDMUUsMkVBQTJFO1FBQzNFLHVFQUF1RTtRQUN2RSx3RUFBd0U7UUFDeEUsSUFBSSxVQUFVLEdBQUcsU0FBUyxDQUFDO1FBQzNCLE9BQU8sQ0FBQyxJQUFBLGVBQVUsRUFBQyxJQUFBLFdBQUksRUFBQyxVQUFVLEVBQUUsY0FBYyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3JELE1BQU0sTUFBTSxHQUFHLElBQUEsY0FBTyxFQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ25DLElBQUksTUFBTSxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7WUFDOUQsQ0FBQztZQUNELFVBQVUsR0FBRyxNQUFNLENBQUM7UUFDdEIsQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQzdCLElBQUEsV0FBSSxFQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsR0FBRyxPQUFPLFVBQVUsQ0FBQyxDQUM5QyxDQUFDO1FBQ0YsT0FBTyxJQUFJLE9BQU8sQ0FBQyxRQUFRLE1BQU0sT0FBTyxHQUFHLENBQUM7SUFDOUMsQ0FBQztDQUNGO0FBNkNEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFnQixXQUFXLENBQ3pCLE9BQWUsRUFDZixPQUtDO0lBRUQsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sVUFBVSxPQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUNsRCxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRTtRQUM5QyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7UUFDaEIsS0FBSyxFQUFFLElBQUk7UUFDWCxTQUFTLEVBQUUsaUJBQVU7UUFDckIsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHO1FBQ2hCLG9FQUFvRTtRQUNwRSwyRUFBMkU7UUFDM0Usc0RBQXNEO1FBQ3RELEtBQUssRUFBRSxPQUFPLENBQUMsT0FBTztZQUNwQixDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU07Z0JBQ2QsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLE1BQU0sRUFBRSxTQUFTLENBQUM7Z0JBQ2hDLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDO1lBQy9CLENBQUMsQ0FBQyxTQUFTO0tBQ2QsQ0FBQyxDQUFDO0lBQ0gsSUFBSSxPQUFPLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3ZELE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBQ0QsT0FBTztRQUNMLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtRQUNyQixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sSUFBSSxJQUFJO1FBQzdCLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxJQUFJLElBQUk7UUFDN0IsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLO0tBQ3BCLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2hpbGRfcHJvY2VzcyBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCBzdGF0U3luYyB9IGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgZGlybmFtZSwgam9pbiwgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBmb3JtYXQgfSBmcm9tIFwidXRpbFwiO1xuaW1wb3J0IHsgZ3JheSwgdW5kZXJsaW5lIH0gZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgeyBQUk9KRU5fRElSLCBUQVNLU19NQU5JRkVTVF9WRVJTSU9OIH0gZnJvbSBcIi4uL2NvbW1vblwiO1xuaW1wb3J0ICogYXMgbG9nZ2luZyBmcm9tIFwiLi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHR5cGUgeyBUYXNrc01hbmlmZXN0LCBUYXNrU3BlYywgVGFza1N0ZXAgfSBmcm9tIFwiLi4vdGFzay1tb2RlbFwiO1xuaW1wb3J0IHsgJCwgZXNjYXBlQ29tbWFuZCB9IGZyb20gXCIuLi91dGlsL2RheFwiO1xuaW1wb3J0IHsgTUFYX0JVRkZFUiwgdG9vbCB9IGZyb20gXCIuLi91dGlsL2V4ZWNcIjtcblxuLy8gYXZvaWRzIGEgKGZhbHNlIHBvc2l0aXZlKSBlc2J1aWxkIHdhcm5pbmcgYWJvdXQgaW5jb3JyZWN0IGltcG9ydHMuXG4vLyBgPy5kZWZhdWx0ID8/IG1vZHVsZWAga2VlcHMgdGhpcyB3b3JraW5nIGJvdGggYXMgYSBwbGFpbiBDb21tb25KUyByZXF1aXJlIGFuZFxuLy8gd2hlbiB0aGUgZGVwZW5kZW5jeSBpcyBpbnRlcm9wLXdyYXBwZWQgaW5zaWRlIHRoZSBidW5kbGVkIHJ1bi10YXNrLmNqcyAod2hlcmVcbi8vIGByZXF1aXJlKC4uLilgIG1heSB5aWVsZCBgeyBkZWZhdWx0OiBmbiB9YCBpbnN0ZWFkIG9mIHRoZSBmdW5jdGlvbikuIFNlZVxuLy8gcHJvamVuIzQ0MDcgKFwicGFyc2VDb25mbGljdEpTT04gaXMgbm90IGEgZnVuY3Rpb25cIiBhZnRlciBlamVjdCkuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuY29uc3QgcGFyc2VDb25mbGljdEpTT05Nb2R1bGUgPSByZXF1aXJlKFwicGFyc2UtY29uZmxpY3QtanNvblwiKTtcbmNvbnN0IHBhcnNlQ29uZmxpY3RKU09OID1cbiAgcGFyc2VDb25mbGljdEpTT05Nb2R1bGU/LmRlZmF1bHQgPz8gcGFyc2VDb25mbGljdEpTT05Nb2R1bGU7XG5cbmNvbnN0IEVOVl9UUklNX0xFTiA9IDIwO1xuY29uc3QgQVJHU19NQVJLRVIgPSBcIiRAXCI7XG5jb25zdCBRVU9URURfQVJHU19NQVJLRVIgPSBgXCIke0FSR1NfTUFSS0VSfVwiYDtcblxuLyoqXG4gKiBSZW5kZXJzIGFyZ3MgZm9yIHNwbGljaW5nIGludG8gYSBzdHJpbmcgY29tbWFuZCwgZXNjYXBlZCBmb3Igd2hpY2hldmVyIHNoZWxsXG4gKiB3aWxsIHBhcnNlIHRoYXQgY29tbWFuZC5cbiAqXG4gKiBFdmVyeXRoaW5nIGV4Y2VwdCBgY21kLmV4ZWAgZ2V0cyBQT1NJWCBzaW5nbGUtcXVvdGluZywgd2hpY2ggc3Vydml2ZXMgZGF4J3NcbiAqIGJ1aWx0LWluIHNoZWxsIGFuZCBhbnkgUE9TSVggc2hlbGwgbG9zc2xlc3NseS4gYGNtZC5leGVgIGhhcyBubyBzaW5nbGUtcXVvdGVcbiAqIHN5bnRheCwgc28gaXQga2VlcHMgdGhlIGRvdWJsZS1xdW90ZWQgZm9ybS5cbiAqL1xuZnVuY3Rpb24gZXNjYXBlQXJnc0ZvcihzaGVsbDogc3RyaW5nIHwgc3RyaW5nW10sIGFyZ3M6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIGlzQ21kRXhlKHNoZWxsKVxuICAgID8gYXJncy5tYXAocXVvdGVBcmdDbWQpLmpvaW4oXCIgXCIpXG4gICAgOiBlc2NhcGVDb21tYW5kKGFyZ3MpO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYSByZXNvbHZlZCBzaGVsbCBtZWFucyB0aGUgaG9zdCdzIGBjbWQuZXhlYDogdGhlIG9ubHkgdGFyZ2V0IHRoYXRcbiAqIGNhbm5vdCBwYXJzZSBQT1NJWCBxdW90aW5nLlxuICovXG5mdW5jdGlvbiBpc0NtZEV4ZShzaGVsbDogc3RyaW5nIHwgc3RyaW5nW10pOiBib29sZWFuIHtcbiAgcmV0dXJuIHNoZWxsID09PSBcInN5c3RlbVwiICYmIHByb2Nlc3MucGxhdGZvcm0gPT09IFwid2luMzJcIjtcbn1cblxuLyoqXG4gKiBEb3VibGUtcXVvdGVzIGEgc2luZ2xlIGFyZ3VtZW50IGZvciBgY21kLmV4ZWAsIGVzY2FwaW5nIHRoZSBjaGFyYWN0ZXJzIHRoYXRcbiAqIHN0YXkgc3BlY2lhbCBpbnNpZGUgZG91YmxlIHF1b3Rlcy4gTm90ZSB0aGF0IGBjbWQuZXhlYCBpdHNlbGYgaGFzIG5vIGluLXF1b3RlXG4gKiBlc2NhcGUgLSBgXFxcImAgaXMgdW5kZXJzdG9vZCBieSB0aGUgcmVjZWl2aW5nIHByb2dyYW0ncyBhcmd2IHBhcnNlciwgbm90IGJ5IHRoZVxuICogc2hlbGwgLSBhbmQgYCVWQVIlYCBzdGlsbCBleHBhbmRzLCBzbyBub3QgZXZlcnkgdmFsdWUgY2FuIGJlIHBhc3NlZCB2ZXJiYXRpbS5cbiAqL1xuZnVuY3Rpb24gcXVvdGVBcmdDbWQoYXJnOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gJ1wiJyArIGFyZy5yZXBsYWNlKC8oW1wiJGBcXFxcXSkvZywgXCJcXFxcJDFcIikgKyAnXCInO1xufVxuXG4vKipcbiAqIGRheCdzIGJ1aWx0LWluIGNyb3NzLXBsYXRmb3JtIHNoZWxsIG9ubHkgaW1wbGVtZW50cyBhIHN1YnNldCBvZiBQT1NJWCBzaGVsbFxuICogc3ludGF4IGFuZCB0aHJvd3MgYSB0ZXJzZSBgTm90IGltcGxlbWVudGVkOiAuLi5gIGZvciB0aGUgcmVzdC4gUmV3cml0ZSB0aG9zZVxuICogaW50byBhIHNob3J0LCBhY3Rpb25hYmxlIGVycm9yIHRoYXQgcG9pbnRzIGF0IHRoZSBzeXN0ZW0tc2hlbGwgZXNjYXBlIGhhdGNoO1xuICogcGFzcyBldmVyeSBvdGhlciBlcnJvciB0aHJvdWdoIHVuY2hhbmdlZC5cbiAqL1xuZnVuY3Rpb24gZW5yaWNoQnVpbHRpblNoZWxsRXJyb3IoXG4gIGVycm9yOiB1bmtub3duLFxuICBjb21tYW5kOiBzdHJpbmcgfCBzdHJpbmdbXSxcbik6IHVua25vd24ge1xuICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuICBpZiAoIS9Ob3QgaW1wbGVtZW50ZWQ6Ly50ZXN0KG1lc3NhZ2UpKSB7XG4gICAgLyogdjggaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gZXJyb3I7XG4gIH1cblxuICBjb25zdCBjb21tYW5kTGluZSA9IEFycmF5LmlzQXJyYXkoY29tbWFuZCkgPyBjb21tYW5kLmpvaW4oXCIgXCIpIDogY29tbWFuZDtcbiAgcmV0dXJuIG5ldyBFcnJvcihcbiAgICBcInByb2plbidzIGJ1aWx0LWluIHNoZWxsIGNhbid0IHJ1biB0aGlzIGNvbW1hbmQ6XFxuXCIgK1xuICAgICAgYCAgJHtjb21tYW5kTGluZX1cXG5gICtcbiAgICAgIFwiVG8gdXNlIHlvdXIgc3lzdGVtJ3Mgc2hlbGwgaW5zdGVhZCwgc2V0IHRoaXMgdGFzayB0byBUYXNrU2hlbGwuc3lzdGVtKCkuXCIsXG4gICk7XG59XG5cbi8qKlxuICogTm9ybWFsaXplZCByZXN1bHQgb2YgYHNoZWxsKClgIChhIHN1YnNldCBvZiBub2RlJ3MgYFNwYXduU3luY1JldHVybnNgKS5cbiAqL1xuaW50ZXJmYWNlIFNoZWxsUmVzdWx0IHtcbiAgLyoqXG4gICAqIFRoZSBleGl0IGNvZGUgb2YgdGhlIGNvbW1hbmQsIG9yIGBudWxsYCBpZiB0aGUgcHJvY2VzcyB3YXMgdGVybWluYXRlZCBieSBhXG4gICAqIHNpZ25hbCBvciBuZXZlciBzcGF3bmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdHVzOiBudW1iZXIgfCBudWxsO1xuXG4gIC8qKlxuICAgKiBDYXB0dXJlZCBzdGRvdXQuIE9ubHkgcG9wdWxhdGVkIHdoZW4gc3Rkb3V0IGlzIHBpcGVkIChlLmcuIHdoZW4gZXZhbHVhdGluZ1xuICAgKiBlbnZpcm9ubWVudCB2YXJpYWJsZXMpOyBgbnVsbGAvYHVuZGVmaW5lZGAgd2hlbiBzdGRpbyBpcyBpbmhlcml0ZWQuXG4gICAqL1xuICByZWFkb25seSBzdGRvdXQ/OiBCdWZmZXIgfCBudWxsO1xuXG4gIC8qKlxuICAgKiBDYXB0dXJlZCBzdGRlcnIuIFNlZSBgc3Rkb3V0YC5cbiAgICovXG4gIHJlYWRvbmx5IHN0ZGVycj86IEJ1ZmZlciB8IG51bGw7XG5cbiAgLyoqXG4gICAqIEFuIGVycm9yIHJhaXNlZCB3aGlsZSBhdHRlbXB0aW5nIHRvIHNwYXduIHRoZSBjb21tYW5kIChub3QgYSBub24temVybyBleGl0XG4gICAqIGNvZGUsIHdoaWNoIGlzIHJlcG9ydGVkIHZpYSBgc3RhdHVzYCkuXG4gICAqL1xuICByZWFkb25seSBlcnJvcj86IEVycm9yO1xufVxuXG4vKipcbiAqIFRoZSBydW50aW1lIGNvbXBvbmVudCBvZiB0aGUgdGFza3MgZW5naW5lLlxuICovXG5leHBvcnQgY2xhc3MgVGFza1J1bnRpbWUge1xuICAvKipcbiAgICogVGhlIHByb2plY3QtcmVsYXRpdmUgcGF0aCBvZiB0aGUgdGFza3MgbWFuaWZlc3QgZmlsZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTUFOSUZFU1RfRklMRSA9IHBhdGgucG9zaXguam9pbihcbiAgICBQUk9KRU5fRElSLFxuICAgIFwidGFza3MuanNvblwiLFxuICApO1xuXG4gIC8qKlxuICAgKiBPbmUtc2hvdCBlbnRyeXBvaW50IGZvciB0aGUgc3RhbmRhbG9uZSB0YXNrIHJ1bm5lci5cbiAgICpcbiAgICogQ3JlYXRlcyBhIHJ1bnRpbWUgcm9vdGVkIGF0IHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LCBydW5zIHRoZSBuYW1lZFxuICAgKiB0YXNrLCBhbmQgY29udmVydHMgYW55IGZhaWx1cmUgaW50byBhIG5vbi16ZXJvIHByb2Nlc3MgZXhpdCBjb2RlLiBUaGlzIGlzXG4gICAqIHRoZSBzaW5nbGUgbGluZSBpbnZva2VkIGJ5IHRoZSBidW5kbGVkIGBzY3JpcHRzL3J1bi10YXNrLmNqc2AgdGhhdFxuICAgKiBcInByb2plbiBlamVjdFwiIGVtaXRzLCB3aGljaCBrZWVwcyB0aGUgZ2VuZXJhdGVkIGJ1bmRsZSBmb290ZXIgdHJpdmlhbC5cbiAgICpcbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIHRhc2sgdG8gcnVuLiBEZWZhdWx0cyB0byBgcHJvY2Vzcy5hcmd2WzJdYC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgbWFpbihuYW1lOiBzdHJpbmcgPSBwcm9jZXNzLmFyZ3ZbMl0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgbmV3IFRhc2tSdW50aW1lKFwiLlwiKS5ydW5UYXNrKG5hbWUpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcihlPy5zdGFjayA/PyBTdHJpbmcoZSkpO1xuICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY29udGVudHMgb2YgdGFza3MuanNvblxuICAgKi9cbiAgcHJpdmF0ZSBfbWFuaWZlc3Q6IFRhc2tzTWFuaWZlc3QgPSB7IHRhc2tzOiB7fSB9O1xuXG4gIC8qKlxuICAgKiBUaGUgcmF3IGNvbnRlbnRzIG9mIHRoZSBjdXJyZW50bHkgbG9hZGVkIG1hbmlmZXN0LCB1c2VkIHRvIGRldGVjdCBjaGFuZ2VzXG4gICAqIG9uIGRpc2sgc28gdGhlIHJ1bnRpbWUgY2FuIHJlbG9hZCBhIHJlZ2VuZXJhdGVkIG1hbmlmZXN0IG1pZC1ydW4uXG4gICAqL1xuICBwcml2YXRlIF9pZGVudGl0eT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoZSBwcm9qZWN0IGFuZCB0aGUgY3dkIGZvciBleGVjdXRpbmcgdGFza3MuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgd29ya2Rpcjogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHdvcmtkaXI6IHN0cmluZykge1xuICAgIHRoaXMud29ya2RpciA9IHJlc29sdmUod29ya2Rpcik7XG4gICAgLy8gUGVyZm9ybSB0aGUgaW5pdGlhbCBsb2FkLiBUaGlzIGFsc28gdmVyaWZpZXMgdGhlIG1hbmlmZXN0J3Mgc2NoZW1hXG4gICAgLy8gdmVyc2lvbi5cbiAgICB0aGlzLnJlbG9hZE1hbmlmZXN0SWZDaGFuZ2VkKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNvbnRlbnRzIG9mIHRhc2tzLmpzb25cbiAgICovXG4gIHB1YmxpYyBnZXQgbWFuaWZlc3QoKTogVGFza3NNYW5pZmVzdCB7XG4gICAgcmV0dXJuIHRoaXMuX21hbmlmZXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBhYnNvbHV0ZSBwYXRoIG9mIHRoZSB0YXNrcyBtYW5pZmVzdCBmaWxlLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgbWFuaWZlc3RQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGpvaW4odGhpcy53b3JrZGlyLCBUYXNrUnVudGltZS5NQU5JRkVTVF9GSUxFKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdGFza3MgaW4gdGhpcyBwcm9qZWN0LlxuICAgKi9cbiAgcHVibGljIGdldCB0YXNrcygpOiBUYXNrU3BlY1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLm1hbmlmZXN0LnRhc2tzID8/IHt9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kIGEgdGFzayBieSBuYW1lLCBvciBgdW5kZWZpbmVkYCBpZiBub3QgZm91bmQuXG4gICAqL1xuICBwdWJsaWMgdHJ5RmluZFRhc2sobmFtZTogc3RyaW5nKTogVGFza1NwZWMgfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5tYW5pZmVzdC50YXNrcykge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubWFuaWZlc3QudGFza3NbbmFtZV07XG4gIH1cblxuICAvKipcbiAgICogUnVucyB0aGUgdGFzay5cbiAgICogQHBhcmFtIG5hbWUgVGhlIHRhc2sgbmFtZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBydW5UYXNrKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBwYXJlbnRzOiBzdHJpbmdbXSA9IFtdLFxuICAgIGFyZ3M6IEFycmF5PHN0cmluZyB8IG51bWJlcj4gPSBbXSxcbiAgICBlbnY6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9ID0ge30sXG4gICAgb3B0aW9uczogeyBjYXB0dXJlT3V0cHV0PzogYm9vbGVhbiB9ID0ge30sXG4gICk6IFByb21pc2U8c3RyaW5nIHwgdm9pZD4ge1xuICAgIC8vIEEgcHJldmlvdXNseSBleGVjdXRlZCB0YXNrIChtb3N0IGltcG9ydGFudGx5IHRoZSBcImRlZmF1bHRcIi9zeW50aCB0YXNrLFxuICAgIC8vIHdoaWNoIGBidWlsZGAgc3Bhd25zIGZpcnN0KSBtYXkgaGF2ZSByZWdlbmVyYXRlZCBgLnByb2plbi90YXNrcy5qc29uYC5cbiAgICAvLyBQaWNrIHVwIGFueSBzdWNoIGNoYW5nZXMgYmVmb3JlIHJlc29sdmluZyBhbmQgcnVubmluZyB0aGlzIHRhc2sgc28gd2VcbiAgICAvLyBuZXZlciBleGVjdXRlIGEgc3RhbGUsIGluLW1lbW9yeSBkZWZpbml0aW9uLlxuICAgIHRoaXMucmVsb2FkTWFuaWZlc3RJZkNoYW5nZWQoKTtcblxuICAgIGNvbnN0IHRhc2sgPSB0aGlzLnRyeUZpbmRUYXNrKG5hbWUpO1xuICAgIGlmICghdGFzaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgZmluZCBjb21tYW5kICR7bmFtZX1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBydW5uZXIgPSBuZXcgUnVuVGFzayh0aGlzLCB0YXNrLCBwYXJlbnRzLCBhcmdzLCBlbnYpO1xuICAgIHJldHVybiBvcHRpb25zLmNhcHR1cmVPdXRwdXQgPyBydW5uZXIucnVuQ2FwdHVyaW5nT3V0cHV0KCkgOiBydW5uZXIucnVuKCk7XG4gIH1cblxuICAvKipcbiAgICogUmUtcmVhZHMgdGhlIHRhc2tzIG1hbmlmZXN0IGZyb20gZGlzayBpZiBpdHMgY29udGVudHMgY2hhbmdlZCBzaW5jZSBpdCB3YXNcbiAgICogbGFzdCBsb2FkZWQsIHZlcmlmeWluZyBpdHMgc2NoZW1hIHZlcnNpb24gYWxvbmcgdGhlIHdheS5cbiAgICpcbiAgICogQ2hhbmdlIGRldGVjdGlvbiBjb21wYXJlcyB0aGUgcmF3IGZpbGUgY29udGVudHMsIHNvIGFuIHVuY2hhbmdlZCBtYW5pZmVzdFxuICAgKiBpcyBub3QgcmUtdmVyaWZpZWQgb3IgcmUtYWRvcHRlZC5cbiAgICovXG4gIHByaXZhdGUgcmVsb2FkTWFuaWZlc3RJZkNoYW5nZWQoKTogdm9pZCB7XG4gICAgaWYgKCFleGlzdHNTeW5jKHRoaXMubWFuaWZlc3RQYXRoKSkge1xuICAgICAgLy8gTm8gbWFuaWZlc3Qgb24gZGlzazogdHJlYXQgYXMgYW4gZW1wdHkgcHJvamVjdCAobGVnYWN5IGJlaGF2aW9yKS5cbiAgICAgIHRoaXMuX21hbmlmZXN0ID0geyB0YXNrczoge30gfTtcbiAgICAgIHRoaXMuX2lkZW50aXR5ID0gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJhdyA9IHJlYWRGaWxlU3luYyh0aGlzLm1hbmlmZXN0UGF0aCwgXCJ1dGYtOFwiKTtcbiAgICBpZiAocmF3ID09PSB0aGlzLl9pZGVudGl0eSkge1xuICAgICAgcmV0dXJuOyAvLyB1bmNoYW5nZWQgc2luY2UgdGhlIGxhc3QgbG9hZFxuICAgIH1cblxuICAgIGNvbnN0IG1hbmlmZXN0OiBUYXNrc01hbmlmZXN0ID0gcGFyc2VDb25mbGljdEpTT04ocmF3LCB1bmRlZmluZWQsIFwidGhlaXJzXCIpO1xuXG4gICAgLy8gQSBwcmV2aW91c2x5IGxvYWRlZCBtYW5pZmVzdCBtZWFucyB0aGlzIGlzIGEgKnJlbG9hZCogKGUuZy4gdGhlXG4gICAgLy8gXCJkZWZhdWx0XCIvc3ludGggdGFzayByZWdlbmVyYXRlZCB0aGUgZmlsZSBtaWQtcnVuKSwgYXMgb3Bwb3NlZCB0byB0aGVcbiAgICAvLyBpbml0aWFsIGxvYWQgcGVyZm9ybWVkIGJ5IHRoZSBjb25zdHJ1Y3Rvci5cbiAgICBjb25zdCBpc1JlbG9hZCA9IHRoaXMuX2lkZW50aXR5ICE9PSB1bmRlZmluZWQ7XG5cbiAgICB0aGlzLnZlcmlmeU1hbmlmZXN0KG1hbmlmZXN0KTtcbiAgICB0aGlzLl9tYW5pZmVzdCA9IG1hbmlmZXN0O1xuICAgIHRoaXMuX2lkZW50aXR5ID0gcmF3O1xuXG4gICAgaWYgKGlzUmVsb2FkKSB7XG4gICAgICBsb2dnaW5nLmRlYnVnKFxuICAgICAgICBgJHtUYXNrUnVudGltZS5NQU5JRkVTVF9GSUxFfSBjaGFuZ2VkIG9uIGRpc2s7IHN1Y2Nlc3NmdWxseSBsb2FkZWQgdGhlIG5ldyB0YXNrcyBtYW5pZmVzdC5gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgZnJlc2hseSByZWFkIG1hbmlmZXN0OlxuICAgKlxuICAgKiAtIExlZ2FjeSBtYW5pZmVzdHMgKG5vIGBtYW5pZmVzdFZlcnNpb25gKSBhcmUgYWNjZXB0ZWQgYXMtaXMgZm9yIGJhY2t3YXJkc1xuICAgKiAgIGNvbXBhdGliaWxpdHkuXG4gICAqIC0gTWFuaWZlc3RzIGZyb20gYSBuZXdlciBwcm9qZW4gKGEgaGlnaGVyIGBtYW5pZmVzdFZlcnNpb25gKSBhcmUgYWNjZXB0ZWRcbiAgICogICB3aXRoIGEgd2FybmluZywgc2luY2UgdGhpcyBydW50aW1lIG1heSBub3QgdW5kZXJzdGFuZCB0aGUgc2NoZW1hLlxuICAgKi9cbiAgcHJpdmF0ZSB2ZXJpZnlNYW5pZmVzdChtYW5pZmVzdDogVGFza3NNYW5pZmVzdCk6IHZvaWQge1xuICAgIC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5OiBtYW5pZmVzdHMgZ2VuZXJhdGVkIGJlZm9yZSB2ZXJzaW9uaW5nIGNhcnJ5IG5vXG4gICAgLy8gdmVyc2lvbi5cbiAgICBpZiAobWFuaWZlc3QubWFuaWZlc3RWZXJzaW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAobWFuaWZlc3QubWFuaWZlc3RWZXJzaW9uID4gVEFTS1NfTUFOSUZFU1RfVkVSU0lPTikge1xuICAgICAgbG9nZ2luZy53YXJuKFxuICAgICAgICBgJHtUYXNrUnVudGltZS5NQU5JRkVTVF9GSUxFfSB3YXMgZ2VuZXJhdGVkIGJ5IGEgbmV3ZXIgdmVyc2lvbiBvZiBwcm9qZW4gYCArXG4gICAgICAgICAgYChtYW5pZmVzdCB2ZXJzaW9uICR7bWFuaWZlc3QubWFuaWZlc3RWZXJzaW9ufSwgdGhpcyBwcm9qZW4gc3VwcG9ydHMgdXAgdG8gJHtUQVNLU19NQU5JRkVTVF9WRVJTSU9OfSkuIGAgK1xuICAgICAgICAgIGBTb21lIHRhc2tzIG1heSBub3QgYmVoYXZlIGFzIGV4cGVjdGVkOyBjb25zaWRlciB1cGdyYWRpbmcgcHJvamVuLmAsXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBSdW5UYXNrIHtcbiAgcHJpdmF0ZSBlbnY6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgcGFyZW50czogc3RyaW5nW107XG5cbiAgcHJpdmF0ZSByZWFkb25seSB3b3JrZGlyOiBzdHJpbmc7XG5cbiAgLy8gV2hlbiBzZXQsIGV2ZXJ5IHN0ZXAncyBzdGRvdXQgaXMgY2FwdHVyZWQgYW5kIGFjY3VtdWxhdGVkIChmb3IgYSBzcGF3bmVkXG4gIC8vIHRhc2sgd2hvc2UgYWdncmVnYXRlIG91dHB1dCB0aGUgY2FsbGVyIHdhbnRzKS5cbiAgcHJpdmF0ZSBjYXB0dXJlQWxsID0gZmFsc2U7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FwdHVyZWQ6IHN0cmluZ1tdID0gW107XG5cbiAgLy8gYG91dHB1dEVudmAgY2FwdHVyZXMsIHByb3BhZ2F0ZWQgdG8gc3Bhd25lZCBzdWJ0YXNrcyAoZXhlYy9idWlsdGluIHN0ZXBzXG4gIC8vIHNlZSB0aGVtIHZpYSBgdGhpcy5lbnZgKS5cbiAgcHJpdmF0ZSByZWFkb25seSBjYXB0dXJlZEVudjogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJ1bnRpbWU6IFRhc2tSdW50aW1lLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdGFzazogVGFza1NwZWMsXG4gICAgcGFyZW50czogc3RyaW5nW10gPSBbXSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFyZ3M6IEFycmF5PHN0cmluZyB8IG51bWJlcj4gPSBbXSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGVudlBhcmFtOiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9LFxuICApIHtcbiAgICB0aGlzLndvcmtkaXIgPSB0YXNrLmN3ZCA/PyB0aGlzLnJ1bnRpbWUud29ya2RpcjtcbiAgICB0aGlzLnBhcmVudHMgPSBwYXJlbnRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgdGhlIHRhc2ssIGNhcHR1cmluZyBhbmQgcmV0dXJuaW5nIHRoZSB0cmltbWVkLCBuZXdsaW5lLWpvaW5lZCBzdGRvdXRcbiAgICogb2YgYWxsIGl0cyBzdGVwcyAoYW5kIGFueSBuZXN0ZWQgc3Bhd25lZCB0YXNrcykgaW4gZXhlY3V0aW9uIG9yZGVyLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJ1bkNhcHR1cmluZ091dHB1dCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHRoaXMuY2FwdHVyZUFsbCA9IHRydWU7XG4gICAgYXdhaXQgdGhpcy5ydW4oKTtcbiAgICByZXR1cm4gdGhpcy5jYXB0dXJlZC5qb2luKFwiXFxuXCIpLnRyaW0oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNvcmRzIGEgc3RlcCdzIGNhcHR1cmVkICh0cmltbWVkKSBzdGRvdXQ6IGludG8gYG91dHB1dEVudmAgZm9yIGxhdGVyXG4gICAqIHN0ZXBzIChhbmQgcHJvcGFnYXRlZCB0byBzcGF3bmVkIHN1YnRhc2tzKSwgYW5kIGludG8gdGhlIHJ1bidzIGFnZ3JlZ2F0ZVxuICAgKiBvdXRwdXQgd2hlbiBjYXB0dXJpbmcgZXZlcnl0aGluZy5cbiAgICovXG4gIHByaXZhdGUgcmVjb3JkQ2FwdHVyZShvdXRwdXRFbnY6IHN0cmluZyB8IHVuZGVmaW5lZCwgdmFsdWU6IHN0cmluZykge1xuICAgIGlmIChvdXRwdXRFbnYpIHtcbiAgICAgIHRoaXMuZW52W291dHB1dEVudl0gPSB2YWx1ZTtcbiAgICAgIHRoaXMuY2FwdHVyZWRFbnZbb3V0cHV0RW52XSA9IHZhbHVlO1xuICAgIH1cbiAgICBpZiAodGhpcy5jYXB0dXJlQWxsKSB7XG4gICAgICB0aGlzLmNhcHR1cmVkLnB1c2godmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyB0aGUgdGFzay4gVGhpcyB3YXMgcHJldmlvdXNseSBkb25lIGluIHRoZSBjb25zdHJ1Y3RvciwgYnV0IGlzIG5vd1xuICAgKiBhbiBhc3luYyBtZXRob2Qgc2luY2Ugc2hlbGwgZXhlY3V0aW9uIGlzIGFzeW5jaHJvbm91cyAoZS5nLiBkYXggb25cbiAgICogV2luZG93cykuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcnVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgdGFzaywgYXJncywgcGFyZW50cyB9ID0gdGhpcztcblxuICAgIGlmICghdGFzay5zdGVwcyB8fCB0YXNrLnN0ZXBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5sb2dEZWJ1ZyhncmF5KFwiTm8gYWN0aW9ucyBoYXZlIGJlZW4gc3BlY2lmaWVkIGZvciB0aGlzIHRhc2suXCIpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmVudiA9IGF3YWl0IHRoaXMucmVzb2x2ZUVudmlyb25tZW50KFxuICAgICAgdGhpcy5lbnZQYXJhbSxcbiAgICAgIHBhcmVudHMsXG4gICAgICB0aGlzLnJlc29sdmVTaGVsbCgpLFxuICAgICk7XG5cbiAgICBjb25zdCBlbnZsb2dzID0gW107XG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXModGhpcy5lbnYpKSB7XG4gICAgICBjb25zdCB2diA9IHYgPz8gXCJcIjtcbiAgICAgIGNvbnN0IHRyaW1tZWQgPVxuICAgICAgICB2di5sZW5ndGggPiBFTlZfVFJJTV9MRU4gPyB2di5zdWJzdHJpbmcoMCwgRU5WX1RSSU1fTEVOKSArIFwiLi4uXCIgOiB2djtcbiAgICAgIGVudmxvZ3MucHVzaChgJHtrfT0ke3RyaW1tZWR9YCk7XG4gICAgfVxuXG4gICAgaWYgKGVudmxvZ3MubGVuZ3RoKSB7XG4gICAgICB0aGlzLmxvZ0RlYnVnKGdyYXkoYCR7dW5kZXJsaW5lKFwiZW52XCIpfTogJHtlbnZsb2dzLmpvaW4oXCIgXCIpfWApKTtcbiAgICB9XG5cbiAgICAvLyBldmFsdWF0ZSBjb25kaXRpb25cbiAgICBpZiAoIShhd2FpdCB0aGlzLmV2YWxDb25kaXRpb24odGFzaywgdGhpcy5yZXNvbHZlU2hlbGwoKSkpKSB7XG4gICAgICB0aGlzLmxvZyhcImNvbmRpdGlvbiBleGl0ZWQgd2l0aCBub24temVybyAtIHNraXBwaW5nXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIHZlcmlmeSB3ZSByZXF1aXJlZCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYXJlIGRlZmluZWRcbiAgICBjb25zdCBtZXJnZWQgPSB7IC4uLnByb2Nlc3MuZW52LCAuLi50aGlzLmVudiB9O1xuICAgIGNvbnN0IG1pc3NpbmcgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3QgbmFtZSBvZiB0YXNrLnJlcXVpcmVkRW52ID8/IFtdKSB7XG4gICAgICBpZiAoIShuYW1lIGluIG1lcmdlZCkpIHtcbiAgICAgICAgbWlzc2luZy5wdXNoKG5hbWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtaXNzaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYG1pc3NpbmcgcmVxdWlyZWQgZW52aXJvbm1lbnQgdmFyaWFibGVzOiAke21pc3Npbmcuam9pbihcIixcIil9YCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBzdGVwIG9mIHRhc2suc3RlcHMpIHtcbiAgICAgIGNvbnN0IHN0ZXBTaGVsbCA9IHRoaXMucmVzb2x2ZVNoZWxsKHN0ZXApO1xuXG4gICAgICAvLyBldmFsdWF0ZSBzdGVwIGNvbmRpdGlvblxuICAgICAgaWYgKCEoYXdhaXQgdGhpcy5ldmFsQ29uZGl0aW9uKHN0ZXAsIHN0ZXBTaGVsbCkpKSB7XG4gICAgICAgIHRoaXMubG9nKFwiY29uZGl0aW9uIGV4aXRlZCB3aXRoIG5vbi16ZXJvIC0gc2tpcHBpbmdcIik7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBhcmdzTGlzdDogc3RyaW5nW10gPSBbXG4gICAgICAgIC4uLihzdGVwLmFyZ3MgfHwgW10pLFxuICAgICAgICAuLi4oc3RlcC5yZWNlaXZlQXJncyA/IGFyZ3MgOiBbXSksXG4gICAgICBdLm1hcCgoYSkgPT4gYS50b1N0cmluZygpKTtcblxuICAgICAgaWYgKHN0ZXAuc2F5KSB7XG4gICAgICAgIGxvZ2dpbmcuaW5mbyh0aGlzLmZtdExvZyhzdGVwLnNheSkpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3RlcC5zcGF3bikge1xuICAgICAgICBjb25zdCBjYXB0dXJlID0gdGhpcy5jYXB0dXJlQWxsIHx8ICEhc3RlcC5vdXRwdXRFbnY7XG4gICAgICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IHRoaXMucnVudGltZS5ydW5UYXNrKFxuICAgICAgICAgIHN0ZXAuc3Bhd24sXG4gICAgICAgICAgWy4uLnRoaXMucGFyZW50cywgdGhpcy50YXNrLm5hbWVdLFxuICAgICAgICAgIGFyZ3NMaXN0LFxuICAgICAgICAgIHsgLi4udGhpcy5jYXB0dXJlZEVudiwgLi4uc3RlcC5lbnYgfSxcbiAgICAgICAgICB7IGNhcHR1cmVPdXRwdXQ6IGNhcHR1cmUgfSxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHR5cGVvZiBvdXRwdXQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICB0aGlzLnJlY29yZENhcHR1cmUoc3RlcC5vdXRwdXRFbnYsIG91dHB1dCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgZXhlY3M6IEFycmF5PHN0cmluZyB8IHN0cmluZ1tdPiA9IHN0ZXAuZXhlYyA/IFtzdGVwLmV4ZWNdIDogW107XG5cbiAgICAgIC8vIFBhcnNlIHN0ZXAtc3BlY2lmaWMgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAgICBjb25zdCBlbnYgPSBhd2FpdCB0aGlzLmV2YWxFbnZpcm9ubWVudChzdGVwLmVudiA/PyB7fSwgc3RlcFNoZWxsKTtcblxuICAgICAgaWYgKHN0ZXAuYnVpbHRpbikge1xuICAgICAgICBleGVjcy5wdXNoKHRoaXMucmVuZGVyQnVpbHRpbihzdGVwLmJ1aWx0aW4pKTtcbiAgICAgIH1cblxuICAgICAgLy8gYGV4ZWNBcmdzYCBpcyBhbiBleHBsaWNpdCBhcmd2ICh0aGUgcHJvZ3JhbSBmb2xsb3dlZCBieSBpdHMgYXJndW1lbnRzKS5cbiAgICAgIC8vIEl0IGlzIGhhbmRlZCB0byBgc2hlbGwoKWAgYXMgYW4gYXJyYXkgcmF0aGVyIHRoYW4gYSByZW5kZXJlZCBzdHJpbmcsIHNvXG4gICAgICAvLyBpdCBydW5zIHdpdGhvdXQgYSBzaGVsbCBhbmQgZXZlcnkgZWxlbWVudCBpcyBwYXNzZWQgdGhyb3VnaCB2ZXJiYXRpbSAtXG4gICAgICAvLyB3aGljaCBpcyB3aGF0IGxldHMgY2FsbGVycyBhdm9pZCB0aGlua2luZyBhYm91dCBxdW90aW5nLiBGaXhlZC9yZWNlaXZlZFxuICAgICAgLy8gYXJncyBhcmUgc3BsaWNlZCBpbiB3aGVyZXZlciBhIGAkQGAgbWFya2VyIGVsZW1lbnQgYXBwZWFycyAobWlycm9yaW5nXG4gICAgICAvLyB0aGUgc3RyaW5nIGBleGVjYCBiZWhhdmlvciksIG9yIGFwcGVuZGVkIGF0IHRoZSBlbmQgaWYgdGhlcmUgaXMgbm9uZS5cbiAgICAgIGlmIChzdGVwLmV4ZWNBcmdzKSB7XG4gICAgICAgIGNvbnN0IGFyZ3Y6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGxldCBwbGFjZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHN0ZXAuZXhlY0FyZ3MpIHtcbiAgICAgICAgICBpZiAoZWxlbWVudCA9PT0gQVJHU19NQVJLRVIpIHtcbiAgICAgICAgICAgIGFyZ3YucHVzaCguLi5hcmdzTGlzdCk7XG4gICAgICAgICAgICBwbGFjZWQgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcmd2LnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghcGxhY2VkKSB7XG4gICAgICAgICAgYXJndi5wdXNoKC4uLmFyZ3NMaXN0KTtcbiAgICAgICAgfVxuICAgICAgICBleGVjcy5wdXNoKGFyZ3YpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGV4ZWMgb2YgZXhlY3MpIHtcbiAgICAgICAgbGV0IGNvbW1hbmQgPSBleGVjO1xuXG4gICAgICAgIC8vIEEgc3RyaW5nIGNvbW1hbmQgaXMgYSBzaGVsbCBsaW5lOiBzcGxpY2UgdGFzayBhcmdzIGluIHBlciB0aGUgYCRAYFxuICAgICAgICAvLyBtYXJrZXIgcnVsZXMuIEFuIGBleGVjQXJnc2AgYXJndiBhbHJlYWR5IGNhcnJpZXMgaXRzIGFyZ3MsIHVudG91Y2hlZC5cbiAgICAgICAgaWYgKHR5cGVvZiBjb21tYW5kID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgaWYgKGNvbW1hbmQuaW5jbHVkZXMoUVVPVEVEX0FSR1NfTUFSS0VSKSkge1xuICAgICAgICAgICAgLy8gYFwiJEBcImA6IHNwbGljZSBlYWNoIGFyZyBpbiBhcyBhIHNlcGFyYXRlIHZlcmJhdGltIHdvcmQgKGxpa2VcbiAgICAgICAgICAgIC8vIGJhc2gncyBxdW90ZWQgYFwiJEBcImApLCBzbyB3aGl0ZXNwYWNlIGFuZCBtZXRhY2hhcmFjdGVycyBzdXJ2aXZlLlxuICAgICAgICAgICAgY29tbWFuZCA9IGNvbW1hbmQucmVwbGFjZShcbiAgICAgICAgICAgICAgUVVPVEVEX0FSR1NfTUFSS0VSLFxuICAgICAgICAgICAgICBlc2NhcGVBcmdzRm9yKHN0ZXBTaGVsbCwgYXJnc0xpc3QpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNvbW1hbmQuaW5jbHVkZXMoQVJHU19NQVJLRVIpKSB7XG4gICAgICAgICAgICBjb21tYW5kID0gY29tbWFuZC5yZXBsYWNlKEFSR1NfTUFSS0VSLCBhcmdzTGlzdC5qb2luKFwiIFwiKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbW1hbmQgPSBbY29tbWFuZCwgLi4uYXJnc0xpc3RdLmpvaW4oXCIgXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN3ZCA9IHN0ZXAuY3dkO1xuICAgICAgICBjb25zdCBjYXB0dXJlID0gdGhpcy5jYXB0dXJlQWxsIHx8ICEhc3RlcC5vdXRwdXRFbnY7XG4gICAgICAgIC8vIEEgdGhyb3duIGVycm9yIChlLmcuIHNwYXduIGZhaWx1cmUpIHByb3BhZ2F0ZXM7IGEgbm9uLXplcm8gZXhpdCBpc1xuICAgICAgICAvLyByZXBvcnRlZCB2aWEgYHJlc3VsdC5zdGF0dXNgLlxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnNoZWxsKHtcbiAgICAgICAgICBjb21tYW5kLFxuICAgICAgICAgIGN3ZCxcbiAgICAgICAgICBleHRyYUVudjogZW52LFxuICAgICAgICAgIHNoZWxsOiBzdGVwU2hlbGwsXG4gICAgICAgICAgY2FwdHVyZU91dHB1dDogY2FwdHVyZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQuc3RhdHVzICE9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFRhc2sgXCIke3RoaXMuZnVsbG5hbWV9XCIgZmFpbGVkIHdoZW4gZXhlY3V0aW5nIFwiJHtcbiAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjb21tYW5kKSA/IGNvbW1hbmQuam9pbihcIiBcIikgOiBjb21tYW5kXG4gICAgICAgICAgICB9XCIgKGN3ZDogJHtyZXNvbHZlKGN3ZCA/PyB0aGlzLndvcmtkaXIpfSlgLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNhcHR1cmUpIHtcbiAgICAgICAgICBjb25zdCBzdGRvdXQgPSByZXN1bHQuc3Rkb3V0Py50b1N0cmluZyhcInV0Zi04XCIpLnRyaW0oKSA/PyBcIlwiO1xuICAgICAgICAgIHRoaXMucmVjb3JkQ2FwdHVyZShzdGVwLm91dHB1dEVudiwgc3Rkb3V0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIGEgdGFzayBzaG91bGQgYmUgZXhlY3V0ZWQgYmFzZWQgb24gXCJjb25kaXRpb25cIi5cbiAgICpcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgdGFzayBzaG91bGQgYmUgZXhlY3V0ZWQgb3IgZmFsc2UgaWYgdGhlIGNvbmRpdGlvblxuICAgKiBldmFsdWF0ZXMgdG8gZmFsc2UgKGV4aXRzIHdpdGggbm9uLXplcm8pLCBpbmRpY2F0aW5nIHRoYXQgdGhlIHRhc2sgc2hvdWxkXG4gICAqIGJlIHNraXBwZWQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGV2YWxDb25kaXRpb24oXG4gICAgdGFza09yU3RlcDogVGFza1NwZWMgfCBUYXNrU3RlcCxcbiAgICBzaGVsbDogc3RyaW5nIHwgc3RyaW5nW10sXG4gICkge1xuICAgIC8vIG5vIGNvbmRpdGlvbiwgY2Fycnkgb25cbiAgICBpZiAoIXRhc2tPclN0ZXAuY29uZGl0aW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLmxvZyhncmF5KGAke3VuZGVybGluZShcImNvbmRpdGlvblwiKX06ICR7dGFza09yU3RlcC5jb25kaXRpb259YCkpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc2hlbGwoe1xuICAgICAgY29tbWFuZDogdGFza09yU3RlcC5jb25kaXRpb24sXG4gICAgICBxdWlldDogdHJ1ZSxcbiAgICAgIHNoZWxsLFxuICAgIH0pO1xuICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZXMgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZyb20gc2hlbGwgY29tbWFuZHMgKGUuZy4gYCQoeHgpYClcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZXZhbEVudmlyb25tZW50KFxuICAgIGVudjogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICAgc2hlbGw6IHN0cmluZyB8IHN0cmluZ1tdLFxuICApIHtcbiAgICBjb25zdCBvdXRwdXQ6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9ID0ge307XG5cbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhlbnYgPz8ge30pKSB7XG4gICAgICBpZiAoU3RyaW5nKHZhbHVlKS5zdGFydHNXaXRoKFwiJChcIikgJiYgU3RyaW5nKHZhbHVlKS5lbmRzV2l0aChcIilcIikpIHtcbiAgICAgICAgY29uc3QgcXVlcnkgPSB2YWx1ZS5zdWJzdHJpbmcoMiwgdmFsdWUubGVuZ3RoIC0gMSk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc2hlbGwoe1xuICAgICAgICAgIGNvbW1hbmQ6IHF1ZXJ5LFxuICAgICAgICAgIHF1aWV0OiB0cnVlLFxuICAgICAgICAgIGNhcHR1cmVPdXRwdXQ6IHRydWUsXG4gICAgICAgICAgc2hlbGwsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyAhPT0gMCkge1xuICAgICAgICAgIGNvbnN0IGVycm9yID0gcmVzdWx0LmVycm9yXG4gICAgICAgICAgICA/IHJlc3VsdC5lcnJvci5zdGFja1xuICAgICAgICAgICAgOiByZXN1bHQuc3RkZXJyPy50b1N0cmluZygpLnRyaW0oKSB8fFxuICAgICAgICAgICAgICByZXN1bHQuc3Rkb3V0Py50b1N0cmluZygpLnRyaW0oKSB8fFxuICAgICAgICAgICAgICBgY29tbWFuZCBleGl0ZWQgd2l0aCBjb2RlICR7cmVzdWx0LnN0YXR1c31gO1xuXG4gICAgICAgICAgbG9nZ2luZy53YXJuKFxuICAgICAgICAgICAgdGhpcy5mbXRMb2coXG4gICAgICAgICAgICAgIGAke3VuZGVybGluZShrZXkpfTogdW5hYmxlIHRvIGV2YWx1YXRlIFwiJHtxdWVyeX1cIi4gRW52aXJvbm1lbnQgdmFyaWFibGUgd2lsbCBiZSBza2lwcGVkLiBDaGVjayB0aGF0IHRoZSBjb21tYW5kIGV4aXN0cyBhbmQgcnVucyBzdWNjZXNzZnVsbHkuYCxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKTtcbiAgICAgICAgICBsb2dnaW5nLndhcm4odGhpcy5mbXRMb2coYCR7dW5kZXJsaW5lKGtleSl9OiAke2Vycm9yfWApKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvdXRwdXRba2V5XSA9IHJlc3VsdC5zdGRvdXQ/LnRvU3RyaW5nKFwidXRmLThcIikudHJpbSgpID8/IFwiXCI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dFtrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVycyB0aGUgcnVudGltZSBlbnZpcm9ubWVudCBmb3IgYSB0YXNrLiBOYW1lbHksIGl0IHN1cHBvcnRzIHRoaXMgc3ludGF4XG4gICAqIGAkKHh4KWAgZm9yIGFsbG93aW5nIGVudmlyb25tZW50IHRvIGJlIGV2YWx1YXRlZCBieSBleGVjdXRpbmcgYSBzaGVsbFxuICAgKiBjb21tYW5kIGFuZCBvYnRhaW5pbmcgaXRzIHJlc3VsdC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVzb2x2ZUVudmlyb25tZW50KFxuICAgIGVudlBhcmFtOiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgICBwYXJlbnRzOiBzdHJpbmdbXSxcbiAgICBzaGVsbDogc3RyaW5nIHwgc3RyaW5nW10sXG4gICkge1xuICAgIGxldCBlbnYgPSB0aGlzLnJ1bnRpbWUubWFuaWZlc3QuZW52ID8/IHt9O1xuXG4gICAgLy8gYWRkIGVudiBmcm9tIGFsbCBwYXJlbnQgdGFza3Mgb25lIGJ5IG9uZVxuICAgIGZvciAoY29uc3QgcGFyZW50IG9mIHBhcmVudHMpIHtcbiAgICAgIGVudiA9IHtcbiAgICAgICAgLi4uZW52LFxuICAgICAgICAuLi4odGhpcy5ydW50aW1lLnRyeUZpbmRUYXNrKHBhcmVudCk/LmVudiA/PyB7fSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIGFwcGx5IHRhc2sgZW52aXJvbm1lbnQsIHRoZW4gdGhlIHNwZWNpZmljIGVudiBsYXN0XG4gICAgZW52ID0ge1xuICAgICAgLi4uZW52LFxuICAgICAgLi4uKHRoaXMudGFzay5lbnYgPz8ge30pLFxuICAgICAgLi4uZW52UGFyYW0sXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLmV2YWxFbnZpcm9ubWVudChlbnYsIHNoZWxsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgc2hlbGwgZm9yIGEgc3RlcCdzIGNvbW1hbmQgKG9yIHRoZSB0YXNrJ3MsIHdoZW4gbm8gc3RlcCBpc1xuICAgKiBnaXZlbik6IHN0ZXAsIHRoZW4gdGFzaywgdGhlbiBwcm9qZWN0IGRlZmF1bHQsIHRoZW4gXCJwcm9qZW5cIi5cbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZVNoZWxsKHN0ZXA/OiBUYXNrU3RlcCk6IHN0cmluZyB8IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gKFxuICAgICAgc3RlcD8uc2hlbGwgPz8gdGhpcy50YXNrLnNoZWxsID8/IHRoaXMucnVudGltZS5tYW5pZmVzdC5zaGVsbCA/PyBcInByb2plblwiXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBcImZ1bGwgbmFtZVwiIG9mIHRoZSB0YXNrIHdoaWNoIGluY2x1ZGVzIGFsbCBpdCdzIHBhcmVudCB0YXNrIG5hbWVzIGNvbmNhdGVuYXRlZCBieSBjaGV2cm9ucy5cbiAgICovXG4gIHByaXZhdGUgZ2V0IGZ1bGxuYW1lKCkge1xuICAgIHJldHVybiBbLi4udGhpcy5wYXJlbnRzLCB0aGlzLnRhc2submFtZV0uam9pbihcIiDCuyBcIik7XG4gIH1cblxuICBwcml2YXRlIGxvZyguLi5hcmdzOiBhbnlbXSkge1xuICAgIGxvZ2dpbmcudmVyYm9zZSh0aGlzLmZtdExvZyguLi5hcmdzKSk7XG4gIH1cblxuICBwcml2YXRlIGxvZ0RlYnVnKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgbG9nZ2luZy5kZWJ1Zyh0aGlzLmZtdExvZyguLi5hcmdzKSk7XG4gIH1cblxuICBwcml2YXRlIGZtdExvZyguLi5hcmdzOiBhbnlbXSkge1xuICAgIHJldHVybiBmb3JtYXQoYCR7dW5kZXJsaW5lKHRoaXMuZnVsbG5hbWUpfSB8YCwgLi4uYXJncyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNoZWxsKG9wdGlvbnM6IFNoZWxsT3B0aW9ucyk6IFByb21pc2U8U2hlbGxSZXN1bHQ+IHtcbiAgICBjb25zdCBxdWlldCA9IG9wdGlvbnMucXVpZXQgPz8gZmFsc2U7XG4gICAgaWYgKCFxdWlldCkge1xuICAgICAgY29uc3QgbG9nID0gbmV3IEFycmF5PHN0cmluZz4oKTtcblxuICAgICAgbG9nLnB1c2goXG4gICAgICAgIEFycmF5LmlzQXJyYXkob3B0aW9ucy5jb21tYW5kKVxuICAgICAgICAgID8gb3B0aW9ucy5jb21tYW5kLmpvaW4oXCIgXCIpXG4gICAgICAgICAgOiBvcHRpb25zLmNvbW1hbmQsXG4gICAgICApO1xuXG4gICAgICBpZiAob3B0aW9ucy5jd2QpIHtcbiAgICAgICAgbG9nLnB1c2goYChjd2Q6ICR7b3B0aW9ucy5jd2R9KWApO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxvZyhsb2cuam9pbihcIiBcIikpO1xuICAgIH1cblxuICAgIGNvbnN0IGN3ZCA9IG9wdGlvbnMuY3dkID8/IHRoaXMud29ya2RpcjtcbiAgICBpZiAoIWV4aXN0c1N5bmMoY3dkKSB8fCAhc3RhdFN5bmMoY3dkKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBpbnZhbGlkIHdvcmtkaXIgKGN3ZCk6ICR7Y3dkfSBtdXN0IGJlIGFuIGV4aXN0aW5nIGRpcmVjdG9yeWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFRoZSByZXNvbHZlZCBzaGVsbCBpcyBvbmUgb2Y6XG4gICAgLy8gLSBcInByb2plblwiIChkZWZhdWx0KTogZGF4J3MgaW4tcHJvY2VzcyBjcm9zcy1wbGF0Zm9ybSBzaGVsbCwgc28gUE9TSVgtc3R5bGVcbiAgICAvLyAgIHRhc2sgc3ludGF4IChgbWtkaXIgLXBgLCBgJiZgLCBgJFZBUmAsIC4uLikgd29ya3MgdGhlIHNhbWUgZXZlcnl3aGVyZS5cbiAgICAvLyAtIFwic3lzdGVtXCI6IHRoZSBob3N0J3MgbmF0aXZlIHNoZWxsIChgL2Jpbi9zaGAsIG9yIGBjbWQuZXhlYCBvbiBXaW5kb3dzKS5cbiAgICAvLyAtIGFuIGFyZ3YsIGUuZy4gW1wiYmFzaFwiLFwiLWNcIl06IGEgc2hlbGwgaW52b2NhdGlvbiB3aXRoIHRoZSBjb21tYW5kIGFwcGVuZGVkXG4gICAgLy8gICBhcyBpdHMgZmluYWwgYXJndW1lbnQuXG4gICAgY29uc3Qgc2hlbGwgPSBvcHRpb25zLnNoZWxsID8/IFwicHJvamVuXCI7XG4gICAgaWYgKHR5cGVvZiBzaGVsbCA9PT0gXCJzdHJpbmdcIiAmJiBzaGVsbCAhPT0gXCJwcm9qZW5cIiAmJiBzaGVsbCAhPT0gXCJzeXN0ZW1cIikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgdW5rbm93biBidWlsdC1pbiBzaGVsbCAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIHNoZWxsLFxuICAgICAgICApfTsgdXNlIHRoZSBidWlsdC1pbiBcInByb2plblwiIG9yIFwic3lzdGVtXCIgc2hlbGxzLCBvciBhIFRhc2tTaGVsbC5jb21tYW5kKFsuLi5dKSBpbnZvY2F0aW9uYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgY2FwdHVyZSA9IG9wdGlvbnMuY2FwdHVyZU91dHB1dCA/PyBmYWxzZTtcbiAgICAvLyBRdWlldCBjYXB0dXJlcyAoYCQoLi4uKWAsIGNvbmRpdGlvbnMpIHN0YXkgc2lsZW50OyB2aXNpYmxlIGNhcHR1cmVzXG4gICAgLy8gKGBvdXRwdXRFbnZgKSBzdHJlYW0gbGl2ZSB3aGlsZSBzdGlsbCBidWZmZXJpbmcuXG4gICAgY29uc3Qgc3RyZWFtID0gY2FwdHVyZSAmJiAhcXVpZXQ7XG5cbiAgICBjb25zdCBjb21tYW5kID0gb3B0aW9ucy5jb21tYW5kO1xuICAgIGNvbnN0IGVudiA9IHtcbiAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgLi4udGhpcy5lbnYsXG4gICAgICAuLi5vcHRpb25zLmV4dHJhRW52LFxuICAgIH07XG5cbiAgICAvLyBcInN5c3RlbVwiOiB0aGUgaG9zdC1uYXRpdmUgZW5naW5lLiBBIHN0cmluZyBjb21tYW5kIHJ1bnMgdGhyb3VnaCB0aGUgT1NcbiAgICAvLyBzaGVsbDsgYW4gYGV4ZWNBcmdzYCBhcmd2IGlzIHNwYXduZWQgZGlyZWN0bHkgKHNoZWxsLWZyZWUpLCBzbyB0aGUgcmVhbFxuICAgIC8vIGJpbmFyeSBydW5zIHdpdGggbm8gZGF4IGJ1aWx0LWlucy4gKE9ubHkgYCQoLi4uKWAvY29uZGl0aW9uIGV2YWwgY2FwdHVyZXMsXG4gICAgLy8gYW5kIHRob3NlIGFsd2F5cyBwYXNzIGEgc3RyaW5nLCBzbyBhbiBhcnJheSBjb21tYW5kIG5ldmVyIG5lZWRzIGNhcHR1cmUuKVxuICAgIGlmIChzaGVsbCA9PT0gXCJzeXN0ZW1cIikge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29tbWFuZCkpIHtcbiAgICAgICAgY29uc3QgW3Byb2dyYW0sIC4uLmFyZ3NdID0gY29tbWFuZDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0b29sKHByb2dyYW0pLnJ1bihhcmdzLCB7IGN3ZCwgZW52LCBpbmhlcml0U3RkaW86IHRydWUgfSk7XG4gICAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiAwIH07XG4gICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZT8uc3RhdHVzID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IGUuc3RhdHVzIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBzeXN0ZW1TaGVsbChjb21tYW5kLCB7IGN3ZCwgZW52LCBjYXB0dXJlLCBzdHJlYW0gfSk7XG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlIHJ1biB0aHJvdWdoIGRheDogdGhlIFwicHJvamVuXCIgc2hlbGwgb3IgYW4gZXhwbGljaXQgaW52b2NhdGlvbi5cbiAgICBjb25zdCBidWlsZGVyID0gdGhpcy5idWlsZERheENvbW1hbmQoY29tbWFuZCwgc2hlbGwpO1xuXG4gICAgLy8gYGluaGVyaXRQaXBlZGAgc3RyZWFtcyBhbmQgYnVmZmVyczsgYHBpcGVkYCBidWZmZXJzIHF1aWV0bHkuIHN0ZGVyciBpc1xuICAgIC8vIGJ1ZmZlcmVkIG9ubHkgZm9yIHF1aWV0IGNhcHR1cmVzLCBzbyBpdCBjYW4gc3VyZmFjZSBpbiBlcnJvcnMuXG4gICAgY29uc3Qgc3Rkb3V0TW9kZSA9IGNhcHR1cmVcbiAgICAgID8gc3RyZWFtXG4gICAgICAgID8gXCJpbmhlcml0UGlwZWRcIlxuICAgICAgICA6IFwicGlwZWRcIlxuICAgICAgOiBcImluaGVyaXRcIjtcbiAgICBjb25zdCBzdGRlcnJNb2RlID0gY2FwdHVyZSAmJiAhc3RyZWFtID8gXCJwaXBlZFwiIDogXCJpbmhlcml0XCI7XG5cbiAgICBsZXQgcmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCBidWlsZGVyXG4gICAgICAgIC5jd2QoY3dkKVxuICAgICAgICAuZW52KGVudilcbiAgICAgICAgLnN0ZG91dChzdGRvdXRNb2RlKVxuICAgICAgICAuc3RkZXJyKHN0ZGVyck1vZGUpXG4gICAgICAgIC5ub1Rocm93KCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gZGF4J3MgaW4tcHJvY2VzcyBzaGVsbCB0aHJvd3MgYSB0ZXJzZSBgTm90IGltcGxlbWVudGVkOiAuLi5gIGZvciBzaGVsbFxuICAgICAgLy8gc3ludGF4IGl0IGRvZXMgbm90IHN1cHBvcnQgKGUuZy4gYCQoLi4uKWAgY29tbWFuZCBzdWJzdGl0dXRpb24pOyB0dXJuXG4gICAgICAvLyB0aGF0IGludG8gYW4gYWN0aW9uYWJsZSBlcnJvciB0aGF0IHBvaW50cyBhdCB0aGUgc3lzdGVtLXNoZWxsIGVzY2FwZVxuICAgICAgLy8gaGF0Y2guIE90aGVyIGVycm9ycyBwYXNzIHRocm91Z2ggdW5jaGFuZ2VkLlxuICAgICAgdGhyb3cgZW5yaWNoQnVpbHRpblNoZWxsRXJyb3IoZSwgY29tbWFuZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogcmVzdWx0LmNvZGUsXG4gICAgICBzdGRvdXQ6IGNhcHR1cmUgPyBCdWZmZXIuZnJvbShyZXN1bHQuc3Rkb3V0Qnl0ZXMpIDogbnVsbCxcbiAgICAgIHN0ZGVycjogY2FwdHVyZSAmJiAhc3RyZWFtID8gQnVmZmVyLmZyb20ocmVzdWx0LnN0ZGVyckJ5dGVzKSA6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGRheCBjb21tYW5kIGZvciB0aGUgXCJwcm9qZW5cIiBzaGVsbCBvciBhbiBleHBsaWNpdCBpbnZvY2F0aW9uLlxuICAgKiAoVGhlIFwic3lzdGVtXCIgc2hlbGwgaXMgaGFuZGxlZCBob3N0LXNpZGUsIG5vdCBoZXJlLikgYGNvbW1hbmRgIGlzIGEgc2hlbGxcbiAgICogbGluZSAoc3RyaW5nKSBvciBhbiBgZXhlY0FyZ3NgIGFyZ3YgKHN0cmluZ1tdKTsgYHNoZWxsYCBpcyBgXCJwcm9qZW5cImAgb3IgYW5cbiAgICogaW52b2NhdGlvbiBhcmd2IHN1Y2ggYXMgYFtcImJhc2hcIiwgXCItY1wiXWAuXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkRGF4Q29tbWFuZChcbiAgICBjb21tYW5kOiBzdHJpbmcgfCBzdHJpbmdbXSxcbiAgICBzaGVsbDogc3RyaW5nIHwgc3RyaW5nW10sXG4gICkge1xuICAgIC8vIEFuIGludm9jYXRpb24gKGUuZy4gW1wiYmFzaFwiLFwiLWNcIl0sIFtcIm5weFwiLFwiLS1ub1wiLFwiLWNcIl0pOiBhcHBlbmQgdGhlXG4gICAgLy8gY29tbWFuZCBhcyBpdHMgZmluYWwgYXJndW1lbnQuIEEgc3RyaW5nIGlzIGFwcGVuZGVkIGFzLWlzOyBhbiBgZXhlY0FyZ3NgXG4gICAgLy8gYXJndiBpcyByZW5kZXJlZCB0byBhIHF1b3RlZCBjb21tYW5kIGxpbmUgc28gdGhlIHNoZWxsIHJlLXBhcnNlcyB0aGUgc2FtZVxuICAgIC8vIGFyZ3YuIFRoYXQgcmVuZGVyaW5nIGFzc3VtZXMgYSBQT1NJWC1zdHlsZSBzaGVsbCwgd2hpY2ggaXMgd2hhdCBzdWNoIGFuXG4gICAgLy8gaW52b2NhdGlvbiBpcyAoYGJhc2ggLWNgLCBgc2ggLWNgLCBgbnB4IC1jYCwgLi4uKS5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShzaGVsbCkpIHtcbiAgICAgIGNvbnN0IFtwcm9ncmFtLCAuLi5mbGFnc10gPSBzaGVsbDtcbiAgICAgIGNvbnN0IGNvbW1hbmRMaW5lID0gQXJyYXkuaXNBcnJheShjb21tYW5kKVxuICAgICAgICA/IGVzY2FwZUNvbW1hbmQoY29tbWFuZClcbiAgICAgICAgOiBjb21tYW5kO1xuICAgICAgcmV0dXJuICRgJHtwcm9ncmFtfSAke1suLi5mbGFncywgY29tbWFuZExpbmVdfWA7XG4gICAgfVxuXG4gICAgLy8gVGhlIGJ1aWx0LWluIFwicHJvamVuXCIgc2hlbGwgKGRheCkuXG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoY29tbWFuZClcbiAgICAgID8gLy8gZXhlY0FyZ3M6IHNoZWxsLWZyZWUgYXJndiAoZWFjaCBlbGVtZW50IGVzY2FwZWQ7IGAuY21kYCBzaGltcyByZXNvbHZlZCkuXG4gICAgICAgICRgJHtjb21tYW5kWzBdfSAke2NvbW1hbmQuc2xpY2UoMSl9YFxuICAgICAgOiAvLyBzdHJpbmcgY29tbWFuZCwgcGFyc2VkIGluLXByb2Nlc3MgYnkgZGF4J3MgY3Jvc3MtcGxhdGZvcm0gc2hlbGwuXG4gICAgICAgICQucmF3YCR7Y29tbWFuZH1gO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJCdWlsdGluKGJ1aWx0aW46IHN0cmluZykge1xuICAgIC8vIExvY2F0ZSBwcm9qZW4ncyBwYWNrYWdlIHJvb3QgYnkgd2Fsa2luZyB1cCBmcm9tIHRoaXMgbW9kdWxlJ3MgZGlyZWN0b3J5XG4gICAgLy8gdW50aWwgd2UgZmluZCBhIHBhY2thZ2UuanNvbi4gVGhpcyB3b3JrcyB3aGV0aGVyIHRoZSBjb2RlIHJ1bnMgZnJvbSB0aGVcbiAgICAvLyBjb21waWxlZCBmaWxlIChsaWIvY2xpL3Rhc2stcnVudGltZS5qcykgb3IgZnJvbSB0aGUgYnVuZGxlZCBydW4tdGFzay5janNcbiAgICAvLyAobGliL3J1bi10YXNrLmNqcyksIHdoaWNoIGxpdmUgYXQgZGlmZmVyZW50IGRlcHRocyAtIHNvIGEgaGFyZC1jb2RlZFxuICAgIC8vIHJlbGF0aXZlIHBhdGggdG8gcGFja2FnZS5qc29uIHdvdWxkIGJlIHdyb25nIGluIG9uZSBvZiB0aGUgdHdvIGNhc2VzLlxuICAgIGxldCBtb2R1bGVSb290ID0gX19kaXJuYW1lO1xuICAgIHdoaWxlICghZXhpc3RzU3luYyhqb2luKG1vZHVsZVJvb3QsIFwicGFja2FnZS5qc29uXCIpKSkge1xuICAgICAgY29uc3QgcGFyZW50ID0gZGlybmFtZShtb2R1bGVSb290KTtcbiAgICAgIGlmIChwYXJlbnQgPT09IG1vZHVsZVJvb3QpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidW5hYmxlIHRvIGxvY2F0ZSB0aGUgcHJvamVuIHBhY2thZ2Ugcm9vdFwiKTtcbiAgICAgIH1cbiAgICAgIG1vZHVsZVJvb3QgPSBwYXJlbnQ7XG4gICAgfVxuICAgIGNvbnN0IHByb2dyYW0gPSByZXF1aXJlLnJlc29sdmUoXG4gICAgICBqb2luKG1vZHVsZVJvb3QsIFwibGliXCIsIGAke2J1aWx0aW59LnRhc2suanNgKSxcbiAgICApO1xuICAgIHJldHVybiBgXCIke3Byb2Nlc3MuZXhlY1BhdGh9XCIgXCIke3Byb2dyYW19XCJgO1xuICB9XG59XG5cbmludGVyZmFjZSBTaGVsbE9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGNvbW1hbmQgdG8gcnVuLiBBIHN0cmluZyBpcyBleGVjdXRlZCBhcyBhIHNoZWxsIGNvbW1hbmQgbGluZTsgYVxuICAgKiBzdHJpbmcgYXJyYXkgaXMgYW4gZXhwbGljaXQgYXJndiAocHJvZ3JhbSArIGFyZ3VtZW50cykgZXhlY3V0ZWQgd2l0aG91dCBhXG4gICAqIHNoZWxsLlxuICAgKi9cbiAgcmVhZG9ubHkgY29tbWFuZDogc3RyaW5nIHwgc3RyaW5nW107XG4gIC8qKlxuICAgKiBAZGVmYXVsdCAtIHByb2plY3QgZGlyXG4gICAqL1xuICByZWFkb25seSBjd2Q/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBDYXB0dXJlIHN0ZG91dC9zdGRlcnIgKHNvIHRoZSBjYWxsZXIgY2FuIHJlYWQgdGhlbSBmcm9tIHRoZSByZXN1bHQpXG4gICAqIGluc3RlYWQgb2YgaW5oZXJpdGluZyB0aGUgcGFyZW50J3Mgc3RyZWFtcy5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGNhcHR1cmVPdXRwdXQ/OiBib29sZWFuO1xuICAvKiogQGRlZmF1bHQgZmFsc2UgKi9cbiAgcmVhZG9ubHkgcXVpZXQ/OiBib29sZWFuO1xuICByZWFkb25seSBleHRyYUVudj86IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9O1xuICAvKipcbiAgICogVGhlIHJlc29sdmVkIHNoZWxsIHRvIGludGVycHJldCB0aGUgY29tbWFuZCAoZS5nLiBcInByb2plblwiLCBcImJhc2ggLWNcIikuXG4gICAqIEBkZWZhdWx0IFwicHJvamVuXCJcbiAgICovXG4gIHJlYWRvbmx5IHNoZWxsPzogc3RyaW5nIHwgc3RyaW5nW107XG59XG5cbi8qKlxuICogTm9ybWFsaXplZCByZXN1bHQgb2YgcnVubmluZyBhIGNvbW1hbmQgdGhyb3VnaCB0aGUgc3lzdGVtIHNoZWxsIChhIHN1YnNldCBvZlxuICogbm9kZSdzIGBTcGF3blN5bmNSZXR1cm5zYCkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3lzdGVtU2hlbGxSZXN1bHQge1xuICAvKiogRXhpdCBjb2RlLCBvciBgbnVsbGAgaWYgdGVybWluYXRlZCBieSBhIHNpZ25hbCBvciBuZXZlciBzcGF3bmVkLiAqL1xuICByZWFkb25seSBzdGF0dXM6IG51bWJlciB8IG51bGw7XG4gIC8qKiBDYXB0dXJlZCBzdGRvdXQsIG9yIGBudWxsYCB3aGVuIHN0ZG91dCB3YXMgaW5oZXJpdGVkLiAqL1xuICByZWFkb25seSBzdGRvdXQ6IEJ1ZmZlciB8IG51bGw7XG4gIC8qKiBDYXB0dXJlZCBzdGRlcnIsIG9yIGBudWxsYCB3aGVuIHN0ZGVyciB3YXMgaW5oZXJpdGVkLiAqL1xuICByZWFkb25seSBzdGRlcnI6IEJ1ZmZlciB8IG51bGw7XG4gIC8qKiBBbiBlcnJvciByYWlzZWQgd2hpbGUgYXR0ZW1wdGluZyB0byBzcGF3biAobm90IGEgbm9uLXplcm8gZXhpdCkuICovXG4gIHJlYWRvbmx5IGVycm9yPzogRXJyb3I7XG59XG5cbi8qKlxuICogUnVucyBhIGNvbW1hbmQgbGluZSB0aHJvdWdoIHRoZSBvcGVyYXRpbmcgc3lzdGVtJ3MgbmF0aXZlIHNoZWxsLlxuICpcbiAqIENhbGxzIHRoZSBPUyBzaGVsbCB2aWEgYGNoaWxkX3Byb2Nlc3NgIHdpdGggYHNoZWxsOiB0cnVlYC5cbiAqIFRoaXMgYmFja3MgdGhlIGBzeXN0ZW1gIHRhc2sgc2hlbGwsIHdoaWNoIGxldHMgYSB1c2VyIG9wdCBvdXQgb2YgdGhlIGJ1aWx0LWluXG4gKiBjcm9zcy1wbGF0Zm9ybSBzaGVsbCBhbmQgdXNlIHRoZSBob3N0J3MgbmF0aXZlIHNoZWxsIGluc3RlYWQ6XG4gKiBgL2Jpbi9zaGBvbiBQT1NJWCBhbmQgYGNtZC5leGVgIG9uIFdpbmRvd3MuXG4gKlxuICogTmV2ZXIgdGhyb3dzIGZvciBhIG5vbi16ZXJvIGV4aXQgKHRoYXQgaXMgcmVwb3J0ZWQgdmlhIGBzdGF0dXNgKTtcbiAqIGEgc3Bhd24gZmFpbHVyZSBpcyByZXBvcnRlZCB2aWEgYGVycm9yYC4gVGhlIGNhbGxlciBzdXBwbGllcyB0aGUgZnVsbCBgZW52YC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN5c3RlbVNoZWxsKFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIG9wdGlvbnM6IHtcbiAgICBjd2Q6IHN0cmluZztcbiAgICBlbnY/OiBOb2RlSlMuUHJvY2Vzc0VudjtcbiAgICBjYXB0dXJlPzogYm9vbGVhbjtcbiAgICBzdHJlYW0/OiBib29sZWFuO1xuICB9LFxuKTogU3lzdGVtU2hlbGxSZXN1bHQge1xuICBsb2dnaW5nLmRlYnVnKGAke2NvbW1hbmR9IChjd2Q6ICR7b3B0aW9ucy5jd2R9KWApO1xuICBjb25zdCByZXN1bHQgPSBjaGlsZF9wcm9jZXNzLnNwYXduU3luYyhjb21tYW5kLCB7XG4gICAgY3dkOiBvcHRpb25zLmN3ZCxcbiAgICBzaGVsbDogdHJ1ZSxcbiAgICBtYXhCdWZmZXI6IE1BWF9CVUZGRVIsXG4gICAgZW52OiBvcHRpb25zLmVudixcbiAgICAvLyBRdWlldCBjYXB0dXJlIGJ1ZmZlcnMgc3RkZXJyIGZvciBlcnJvciBtZXNzYWdlcy4gU3RyZWFtZWQgY2FwdHVyZVxuICAgIC8vIGluaGVyaXRzIHN0ZGVyciBhbmQgcmUtZW1pdHMgYnVmZmVyZWQgc3Rkb3V0IGFmdGVyd2FyZHMsIHNpbmNlIHNwYXduU3luY1xuICAgIC8vIGNhbid0IGJvdGggc2hvdyBhbmQgYnVmZmVyIHRoZSBzYW1lIHN0cmVhbSBhdCBvbmNlLlxuICAgIHN0ZGlvOiBvcHRpb25zLmNhcHR1cmVcbiAgICAgID8gb3B0aW9ucy5zdHJlYW1cbiAgICAgICAgPyBbXCJpbmhlcml0XCIsIFwicGlwZVwiLCBcImluaGVyaXRcIl1cbiAgICAgICAgOiBbXCJpbmhlcml0XCIsIFwicGlwZVwiLCBcInBpcGVcIl1cbiAgICAgIDogXCJpbmhlcml0XCIsXG4gIH0pO1xuICBpZiAob3B0aW9ucy5jYXB0dXJlICYmIG9wdGlvbnMuc3RyZWFtICYmIHJlc3VsdC5zdGRvdXQpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShyZXN1bHQuc3Rkb3V0KTtcbiAgfVxuICByZXR1cm4ge1xuICAgIHN0YXR1czogcmVzdWx0LnN0YXR1cyxcbiAgICBzdGRvdXQ6IHJlc3VsdC5zdGRvdXQgPz8gbnVsbCxcbiAgICBzdGRlcnI6IHJlc3VsdC5zdGRlcnIgPz8gbnVsbCxcbiAgICBlcnJvcjogcmVzdWx0LmVycm9yLFxuICB9O1xufVxuIl19