UNPKG

projen

Version:

CDK for software projects

466 lines • 72.2 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpgradeDependenciesSchedule = exports.UpgradeDependencies = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const component_1 = require("../component");
const dependencies_1 = require("../dependencies");
const github_1 = require("../github");
const util_1 = require("./util");
const constants_1 = require("../github/constants");
const util_2 = require("../github/private/util");
const workflow_actions_1 = require("../github/workflow-actions");
const workflows_model_1 = require("../github/workflows-model");
const javascript_1 = require("../javascript");
const release_1 = require("../release");
const name_1 = require("../util/name");
const CREATE_PATCH_STEP_ID = "create_patch";
const PATCH_CREATED_OUTPUT = "patch_created";
/**
 * Upgrade node project dependencies.
 */
class UpgradeDependencies extends component_1.Component {
    static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.javascript.UpgradeDependencies", version: "0.104.8" };
    /**
     * The workflows that execute the upgrades. One workflow per branch.
     */
    workflows = [];
    project;
    options;
    pullRequestTitle;
    /**
     * Container definitions for the upgrade workflow.
     */
    containerOptions;
    /**
     * The upgrade task.
     */
    upgradeTask;
    /**
     * A task run after the upgrade task.
     */
    postUpgradeTask;
    gitIdentity;
    postBuildSteps;
    permissions;
    depTypes;
    upgradeTarget;
    satisfyPeerDependencies;
    includeDeprecatedVersions;
    constructor(project, options = {}) {
        super(project);
        this.project = project;
        this.options = options;
        // Validate cooldown
        if (options.cooldown !== undefined &&
            (!Number.isInteger(options.cooldown) || options.cooldown < 0)) {
            throw new Error("The 'cooldown' option must be a non-negative integer representing days");
        }
        // Yarn classic doesn't support cooldown
        if (options.cooldown && (0, util_1.isYarnClassic)(project.package.packageManager)) {
            throw new Error("The 'cooldown' option is not supported with yarn classic. " +
                "Consider using npm, pnpm, bun, or yarn berry instead.");
        }
        this.depTypes = this.options.types ?? [
            dependencies_1.DependencyType.BUILD,
            dependencies_1.DependencyType.BUNDLED,
            dependencies_1.DependencyType.DEVENV,
            dependencies_1.DependencyType.PEER,
            dependencies_1.DependencyType.RUNTIME,
            dependencies_1.DependencyType.TEST,
            dependencies_1.DependencyType.OPTIONAL,
        ];
        this.upgradeTarget = this.options.target ?? "minor";
        this.satisfyPeerDependencies = this.options.satisfyPeerDependencies ?? true;
        this.includeDeprecatedVersions =
            this.options.includeDeprecatedVersions ?? false;
        this.pullRequestTitle = options.pullRequestTitle ?? "upgrade dependencies";
        this.gitIdentity =
            options.workflowOptions?.gitIdentity ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER;
        this.permissions = {
            contents: workflows_model_1.JobPermission.READ,
            ...options.workflowOptions?.permissions,
        };
        this.postBuildSteps = [];
        this.containerOptions = options.workflowOptions?.container;
        this.postUpgradeTask =
            project.tasks.tryFind("post-upgrade") ??
                project.tasks.addTask("post-upgrade", {
                    description: "Runs after upgrading dependencies",
                });
        const taskEnv = { CI: "0" };
        // Yarn berry treats any non-empty CI value as truthy and auto-enables
        // immutable installs. Explicitly disable it so yarn dlx/up can modify
        // the lockfile during upgrades.
        if ((0, util_1.isYarnBerry)(project.package.packageManager)) {
            taskEnv.YARN_ENABLE_IMMUTABLE_INSTALLS = "false";
        }
        // Set yarn berry cooldown via environment variable, expects minutes
        if (options.cooldown && (0, util_1.isYarnBerry)(project.package.packageManager)) {
            taskEnv.YARN_NPM_MINIMAL_AGE_GATE = String(daysToMinutes(options.cooldown));
        }
        // Set npm cooldown date via environment variable (calculated at runtime), expects a date in ISO format
        if (options.cooldown && (0, util_1.isNpm)(project.package.packageManager)) {
            taskEnv.NPM_CONFIG_BEFORE = `$(node -p "new Date(Date.now()-${daysToMilliseconds(options.cooldown)}).toISOString()")`;
        }
        this.upgradeTask = project.addTask(options.taskName ?? "upgrade", {
            // this task should not run in CI mode because its designed to
            // update package.json and lock files.
            env: taskEnv,
            description: this.pullRequestTitle,
            steps: { toJSON: () => this.renderTaskSteps() },
        });
        this.upgradeTask.lock(); // this task is a lazy value, so make it readonly
        // always use the GitHub of the root project - there can only be one
        const github = github_1.GitHub.of(project.root);
        if (this.upgradeTask && github && (options.workflow ?? true)) {
            if (options.workflowOptions?.branches) {
                for (const branch of options.workflowOptions.branches) {
                    this.workflows.push(this.createWorkflow(this.upgradeTask, github, branch));
                }
            }
            else if (release_1.Release.of(project)) {
                const release = release_1.Release.of(project);
                release._forEachBranch((branch) => {
                    this.workflows.push(this.createWorkflow(this.upgradeTask, github, branch));
                });
            }
            else {
                // represents the default repository branch.
                // just like not specifying anything.
                const defaultBranch = undefined;
                this.workflows.push(this.createWorkflow(this.upgradeTask, github, defaultBranch));
            }
        }
    }
    /**
     * Add steps to execute a successful build.
     * @param steps workflow steps
     */
    addPostBuildSteps(...steps) {
        this.postBuildSteps.push(...steps);
    }
    renderTaskSteps() {
        const steps = new Array();
        // Package Manager upgrade should always include all deps
        const includeForPackageManagerUpgrade = this.buildDependencyList(true);
        if (includeForPackageManagerUpgrade.length === 0) {
            return [{ execArgs: ["echo", "No dependencies to upgrade."] }];
        }
        // Removing `npm-check-updates` from our dependency tree because it depends on a package
        // that uses an npm-specific feature that causes an invalid dependency tree when using Yarn 1.
        // See https://github.com/projen/projen/pull/3136 for more details.
        const includeForNcu = this.buildDependencyList(false);
        // bump versions in package.json
        if (includeForNcu.length) {
            const ncuCommand = this.buildNcuCommand(includeForNcu, {
                upgrade: true,
                target: this.upgradeTarget,
            });
            steps.push({ execArgs: ncuCommand });
        }
        // run "yarn/npm install" to update the lockfile and install any deps (such as projen)
        steps.push({ exec: this.project.package.installAndUpdateLockfileCommand });
        // run upgrade command to upgrade transitive deps as well
        steps.push({
            execArgs: this.renderUpgradePackagesCommand(includeForPackageManagerUpgrade),
        });
        // If we have a packages deduplication task, run it now.
        if (this.project.package.dedupeTask) {
            steps.push({ spawn: this.project.package.dedupeTask.name });
        }
        // run "projen" to give projen a chance to update dependencies (it will also run "yarn install")
        steps.push({ exec: this.project.projenCommand });
        steps.push({ spawn: this.postUpgradeTask.name });
        return steps;
    }
    /**
     * Build npm-check-updates command with common options.
     */
    buildNcuCommand(includePackages, options = {}) {
        const command = [
            ...(0, util_1.executeCommandPriorInstallation)(this.project.package.packageManager),
            "npm-check-updates@20",
        ];
        if (options.upgrade) {
            command.push("--upgrade");
        }
        if (options.target) {
            command.push(`--target=${options.target}`);
        }
        if (options.format) {
            command.push(`--format=${options.format}`);
        }
        if (options.removeRange) {
            command.push("--removeRange");
        }
        if (this.options.cooldown) {
            command.push(`--cooldown=${this.options.cooldown}`);
        }
        command.push(`--${this.satisfyPeerDependencies ? "peer" : "no-peer"}`);
        command.push(`--${this.includeDeprecatedVersions ? "deprecated" : "no-deprecated"}`);
        command.push(`--dep=${this.renderNcuDependencyTypes(this.depTypes)}`);
        command.push(`--filter=${includePackages.join(",")}`);
        return command;
    }
    /**
     * Render projen dependencies types to a list of ncu compatible types
     */
    renderNcuDependencyTypes(types) {
        return Array.from(new Set(types
            .map((type) => {
            switch (type) {
                case dependencies_1.DependencyType.PEER:
                    return "peer";
                case dependencies_1.DependencyType.RUNTIME:
                    return "prod";
                case dependencies_1.DependencyType.OPTIONAL:
                    return "optional";
                case dependencies_1.DependencyType.TEST:
                case dependencies_1.DependencyType.DEVENV:
                case dependencies_1.DependencyType.BUILD:
                    return "dev";
                case dependencies_1.DependencyType.BUNDLED:
                    return "prod";
                default:
                    return false;
            }
        })
            .filter((type) => Boolean(type)))).join(",");
    }
    /**
     * Render a package manager specific command to upgrade all requested dependencies.
     */
    renderUpgradePackagesCommand(include) {
        function upgradePackages(command, cooldownFlag) {
            return () => {
                const parts = [...command, ...include];
                if (cooldownFlag) {
                    parts.push(cooldownFlag);
                }
                return parts;
            };
        }
        const packageManager = this.project.package.packageManager;
        const cooldown = this.options.cooldown;
        let lazy = undefined;
        switch (packageManager) {
            case javascript_1.NodePackageManager.YARN:
            case javascript_1.NodePackageManager.YARN_CLASSIC:
                lazy = upgradePackages(["yarn", "upgrade"]);
                break;
            case javascript_1.NodePackageManager.YARN2:
            case javascript_1.NodePackageManager.YARN_BERRY:
                // Yarn Berry cooldown set via task env
                lazy = upgradePackages(["yarn", "up", "-R"]);
                break;
            case javascript_1.NodePackageManager.NPM:
                // npm cooldown set via NPM_CONFIG_BEFORE env
                lazy = upgradePackages(["npm", "update"]);
                break;
            case javascript_1.NodePackageManager.PNPM:
                // pnpm expects minutes
                lazy = upgradePackages(["pnpm", "update"], cooldown !== undefined
                    ? `--config.minimum-release-age=${daysToMinutes(cooldown)}`
                    : undefined);
                break;
            case javascript_1.NodePackageManager.BUN:
                // bun expects seconds
                lazy = upgradePackages(["bun", "update"], cooldown
                    ? `--minimum-release-age=${daysToSeconds(cooldown)}`
                    : undefined);
                break;
            default:
                throw new Error(`unexpected package manager ${packageManager}`);
        }
        // return a lazy function so that dependencies include ones that were
        // added post project instantiation (i.e using project.addDeps)
        return lazy;
    }
    buildDependencyList(includeDependenciesWithConstraint) {
        return Array.from(new Set(this.options.include ??
            this.filterDependencies(includeDependenciesWithConstraint)));
    }
    filterDependencies(includeConstraint) {
        const dependencies = [];
        const deps = this.project.deps.all
            // remove those that have a constraint version (unless includeConstraint is true)
            .filter((d) => includeConstraint ||
            this.packageCanBeUpgradedInPackageJson(d.version))
            // remove override dependencies
            .filter((d) => d.type !== dependencies_1.DependencyType.OVERRIDE);
        for (const type of this.depTypes) {
            dependencies.push(...deps
                .filter((d) => d.type === type)
                .filter((d) => !(this.options.exclude ?? []).includes(d.name)));
        }
        return dependencies.map((d) => d.name);
    }
    /**
     * Projen can alter a package's version in package.json when either the version is omitted, or set to "*".
     * Otherwise, the exact version selected is placed in the package.json file and upgrading is handled through the package manager
     * rather than npm-check-updates.
     *
     * @param version semver from DependencyCoordinates.version, may be undefined
     * @returns whether the version is the default versioning behavior
     */
    packageCanBeUpgradedInPackageJson(version) {
        // No version means "latest"
        return !version || version === "*";
    }
    createWorkflow(task, github, branch) {
        const schedule = this.options.workflowOptions?.schedule ??
            UpgradeDependenciesSchedule.DAILY;
        const taskBranchName = `${task.name}${branch ? `-${branch.replace(/\//g, "-")}` : ""}`;
        const workflowName = (0, name_1.workflowNameForProject)(taskBranchName, this.project);
        const workflow = github.addWorkflow(workflowName);
        const triggers = {
            workflowDispatch: {},
            schedule: schedule.cron.length > 0
                ? schedule.cron.map((e) => ({ cron: e }))
                : undefined,
        };
        workflow.on(triggers);
        const upgrade = this.createUpgrade(task, github, branch);
        const pr = this.createPr(workflow, upgrade);
        const jobs = {};
        jobs[upgrade.jobId] = upgrade.job;
        jobs[pr.jobId] = pr.job;
        workflow.addJobs(jobs);
        return workflow;
    }
    createUpgrade(task, github, branch) {
        const with_ = {
            ...(branch ? { ref: branch } : {}),
            ...(github.downloadLfs ? { lfs: true } : {}),
            ...(github.checkoutSubmodules !== github_1.CheckoutSubmodules.DISABLED
                ? { submodules: github.checkoutSubmodules }
                : {}),
        };
        const steps = [
            github_1.WorkflowSteps.checkout({ with: with_ }),
            ...this.project.renderWorkflowSetup({ mutable: false }),
            {
                name: "Upgrade dependencies",
                run: this.project.runTaskCommand(task),
                workingDirectory: this.project.parent
                    ? (0, util_2.projectPathRelativeToRepoRoot)(this.project)
                    : undefined,
            },
        ];
        steps.push(...this.postBuildSteps);
        steps.push(...workflow_actions_1.WorkflowActions.uploadGitPatch({
            stepId: CREATE_PATCH_STEP_ID,
            outputName: PATCH_CREATED_OUTPUT,
        }));
        return {
            job: {
                name: "Upgrade",
                container: this.containerOptions,
                permissions: this.permissions,
                env: this.options.workflowOptions?.env,
                ...github.runsOnConfig(this.options.workflowOptions),
                steps: steps,
                outputs: {
                    [PATCH_CREATED_OUTPUT]: {
                        stepId: CREATE_PATCH_STEP_ID,
                        outputName: PATCH_CREATED_OUTPUT,
                    },
                },
            },
            jobId: "upgrade",
            ref: branch,
        };
    }
    createPr(workflow, upgrade) {
        const credentials = this.options.workflowOptions?.projenCredentials ??
            workflow.projenCredentials;
        const semanticCommit = this.options.semanticCommit ?? "chore";
        // createPr is only called from createWorkflow, which is only reachable
        // once the constructor has already confirmed the root project has GitHub
        // enabled - so this is always defined.
        const github = github_1.GitHub.of(this.project.root);
        return {
            job: github_1.WorkflowJobs.pullRequestFromPatch({
                patch: {
                    jobId: upgrade.jobId,
                    outputName: PATCH_CREATED_OUTPUT,
                    ref: upgrade.ref,
                },
                workflowName: workflow.name,
                credentials,
                ...github.runsOnConfig(this.options.workflowOptions),
                pullRequestTitle: `${semanticCommit}(deps): ${this.pullRequestTitle}`,
                pullRequestDescription: this.options.pullRequestDescription ??
                    "Upgrades project dependencies.",
                gitIdentity: this.gitIdentity,
                assignees: this.options.workflowOptions?.assignees,
                labels: this.options.workflowOptions?.labels,
                signoff: this.options.signoff,
            }),
            jobId: "pr",
        };
    }
}
exports.UpgradeDependencies = UpgradeDependencies;
/**
 * How often to check for new versions and raise pull requests for version upgrades.
 */
class UpgradeDependenciesSchedule {
    cron;
    static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.javascript.UpgradeDependenciesSchedule", version: "0.104.8" };
    /**
     * Disables automatic upgrades.
     */
    static NEVER = new UpgradeDependenciesSchedule([]);
    /**
     * At 00:00.
     */
    static DAILY = new UpgradeDependenciesSchedule(["0 0 * * *"]);
    /**
     * At 00:00 on every day-of-week from Monday through Friday.
     */
    static WEEKDAY = new UpgradeDependenciesSchedule([
        "0 0 * * 1-5",
    ]);
    /**
     * At 00:00 on Monday.
     */
    static WEEKLY = new UpgradeDependenciesSchedule([
        "0 0 * * 1",
    ]);
    /**
     * At 00:00 on day-of-month 1.
     */
    static MONTHLY = new UpgradeDependenciesSchedule([
        "0 0 1 * *",
    ]);
    /**
     * Create a schedule from a raw cron expression.
     */
    static expressions(cron) {
        return new UpgradeDependenciesSchedule(cron);
    }
    constructor(cron) {
        this.cron = cron;
    }
}
exports.UpgradeDependenciesSchedule = UpgradeDependenciesSchedule;
/**
 * Convert days to minutes.
 */
function daysToMinutes(days) {
    return days * 1440;
}
/**
 * Convert days to seconds.
 */
function daysToSeconds(days) {
    return days * 86400;
}
/**
 * Convert days to milliseconds.
 */
function daysToMilliseconds(days) {
    return days * 86400000;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBncmFkZS1kZXBlbmRlbmNpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvamF2YXNjcmlwdC91cGdyYWRlLWRlcGVuZGVuY2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsNENBQXlDO0FBQ3pDLGtEQUFpRDtBQU9qRCxzQ0FLbUI7QUFDbkIsaUNBS2dCO0FBQ2hCLG1EQUFrRTtBQUNsRSxpREFBdUU7QUFDdkUsaUVBQTZEO0FBTTdELCtEQUEwRDtBQUUxRCw4Q0FBbUQ7QUFDbkQsd0NBQXFDO0FBSXJDLHVDQUFzRDtBQUV0RCxNQUFNLG9CQUFvQixHQUFHLGNBQWMsQ0FBQztBQUM1QyxNQUFNLG9CQUFvQixHQUFHLGVBQWUsQ0FBQztBQTJJN0M7O0dBRUc7QUFDSCxNQUFhLG1CQUFvQixTQUFRLHFCQUFTOztJQUNoRDs7T0FFRztJQUNhLFNBQVMsR0FBcUIsRUFBRSxDQUFDO0lBRWpDLE9BQU8sQ0FBYztJQUVwQixPQUFPLENBQTZCO0lBQ3BDLGdCQUFnQixDQUFTO0lBRTFDOztPQUVHO0lBQ0ksZ0JBQWdCLENBQW9CO0lBRTNDOztPQUVHO0lBQ2EsV0FBVyxDQUFPO0lBRWxDOztPQUVHO0lBQ2EsZUFBZSxDQUFPO0lBRXJCLFdBQVcsQ0FBYztJQUN6QixjQUFjLENBQVk7SUFDMUIsV0FBVyxDQUFpQjtJQUM1QixRQUFRLENBQW1CO0lBQzNCLGFBQWEsQ0FBUztJQUN0Qix1QkFBdUIsQ0FBVTtJQUNqQyx5QkFBeUIsQ0FBVTtJQUVwRCxZQUFZLE9BQW9CLEVBQUUsVUFBc0MsRUFBRTtRQUN4RSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFZixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUV2QixvQkFBb0I7UUFDcEIsSUFDRSxPQUFPLENBQUMsUUFBUSxLQUFLLFNBQVM7WUFDOUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxT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OztHQUVHO0FBQ0gsTUFBYSwyQkFBMkI7SUF1Q0Y7O0lBdENwQzs7T0FFRztJQUNJLE1BQU0sQ0FBVSxLQUFLLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUVuRTs7T0FFRztJQUNJLE1BQU0sQ0FBVSxLQUFLLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFFOUU7O09BRUc7SUFDSSxNQUFNLENBQVUsT0FBTyxHQUFHLElBQUksMkJBQTJCLENBQUM7UUFDL0QsYUFBYTtLQUNkLENBQUMsQ0FBQztJQUVIOztPQUVHO0lBQ0ksTUFBTSxDQUFVLE1BQU0sR0FBRyxJQUFJLDJCQUEyQixDQUFDO1FBQzlELFdBQVc7S0FDWixDQUFDLENBQUM7SUFFSDs7T0FFRztJQUNJLE1BQU0sQ0FBVSxPQUFPLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQztRQUMvRCxXQUFXO0tBQ1osQ0FBQyxDQUFDO0lBRUg7O09BRUc7SUFDSSxNQUFNLENBQUMsV0FBVyxDQUFDLElBQWM7UUFDdEMsT0FBTyxJQUFJLDJCQUEyQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFRCxZQUFvQyxJQUFjO1FBQWQsU0FBSSxHQUFKLElBQUksQ0FBVTtJQUFHLENBQUM7O0FBdkN4RCxrRUF3Q0M7QUFFRDs7R0FFRztBQUNILFNBQVMsYUFBYSxDQUFDLElBQVk7SUFDakMsT0FBTyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ3JCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsYUFBYSxDQUFDLElBQVk7SUFDakMsT0FBTyxJQUFJLEdBQUcsS0FBSyxDQUFDO0FBQ3RCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsa0JBQWtCLENBQUMsSUFBWTtJQUN0QyxPQUFPLElBQUksR0FBRyxRQUFRLENBQUM7QUFDekIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gXCIuLi9jb21wb25lbnRcIjtcbmltcG9ydCB7IERlcGVuZGVuY3lUeXBlIH0gZnJvbSBcIi4uL2RlcGVuZGVuY2llc1wiO1xuaW1wb3J0IHR5cGUge1xuICBHaXRodWJDcmVkZW50aWFscyxcbiAgR2l0aHViV29ya2Zsb3csXG4gIEdpdElkZW50aXR5LFxuICB3b3JrZmxvd3MsXG59IGZyb20gXCIuLi9naXRodWJcIjtcbmltcG9ydCB7XG4gIENoZWNrb3V0U3VibW9kdWxlcyxcbiAgR2l0SHViLFxuICBXb3JrZmxvd0pvYnMsXG4gIFdvcmtmbG93U3RlcHMsXG59IGZyb20gXCIuLi9naXRodWJcIjtcbmltcG9ydCB7XG4gIGlzWWFybkNsYXNzaWMsXG4gIGlzWWFybkJlcnJ5LFxuICBpc05wbSxcbiAgZXhlY3V0ZUNvbW1hbmRQcmlvckluc3RhbGxhdGlvbixcbn0gZnJvbSBcIi4vdXRpbFwiO1xuaW1wb3J0IHsgREVGQVVMVF9HSVRIVUJfQUNUSU9OU19VU0VSIH0gZnJvbSBcIi4uL2dpdGh1Yi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHByb2plY3RQYXRoUmVsYXRpdmVUb1JlcG9Sb290IH0gZnJvbSBcIi4uL2dpdGh1Yi9wcml2YXRlL3V0aWxcIjtcbmltcG9ydCB7IFdvcmtmbG93QWN0aW9ucyB9IGZyb20gXCIuLi9naXRodWIvd29ya2Zsb3ctYWN0aW9uc1wiO1xuaW1wb3J0IHR5cGUge1xuICBDb250YWluZXJPcHRpb25zLFxuICBKb2JTdGVwLFxuICBKb2JQZXJtaXNzaW9ucyxcbn0gZnJvbSBcIi4uL2dpdGh1Yi93b3JrZmxvd3MtbW9kZWxcIjtcbmltcG9ydCB7IEpvYlBlcm1pc3Npb24gfSBmcm9tIFwiLi4vZ2l0aHViL3dvcmtmbG93cy1tb2RlbFwiO1xuaW1wb3J0IHR5cGUgeyBOb2RlUHJvamVjdCB9IGZyb20gXCIuLi9qYXZhc2NyaXB0XCI7XG5pbXBvcnQgeyBOb2RlUGFja2FnZU1hbmFnZXIgfSBmcm9tIFwiLi4vamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgUmVsZWFzZSB9IGZyb20gXCIuLi9yZWxlYXNlXCI7XG5pbXBvcnQgdHlwZSB7IEdyb3VwUnVubmVyT3B0aW9ucyB9IGZyb20gXCIuLi9ydW5uZXItb3B0aW9uc1wiO1xuaW1wb3J0IHR5cGUgeyBUYXNrIH0gZnJvbSBcIi4uL3Rhc2tcIjtcbmltcG9ydCB0eXBlIHsgVGFza1N0ZXAgfSBmcm9tIFwiLi4vdGFzay1tb2RlbFwiO1xuaW1wb3J0IHsgd29ya2Zsb3dOYW1lRm9yUHJvamVjdCB9IGZyb20gXCIuLi91dGlsL25hbWVcIjtcblxuY29uc3QgQ1JFQVRFX1BBVENIX1NURVBfSUQgPSBcImNyZWF0ZV9wYXRjaFwiO1xuY29uc3QgUEFUQ0hfQ1JFQVRFRF9PVVRQVVQgPSBcInBhdGNoX2NyZWF0ZWRcIjtcblxuLyoqXG4gKiBPcHRpb25zIGZvciBgVXBncmFkZURlcGVuZGVuY2llc2AuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVXBncmFkZURlcGVuZGVuY2llc09wdGlvbnMge1xuICAvKipcbiAgICogTGlzdCBvZiBwYWNrYWdlIG5hbWVzIHRvIGV4Y2x1ZGUgZHVyaW5nIHRoZSB1cGdyYWRlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vdGhpbmcgaXMgZXhjbHVkZWQuXG4gICAqL1xuICByZWFkb25seSBleGNsdWRlPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIExpc3Qgb2YgcGFja2FnZSBuYW1lcyB0byBpbmNsdWRlIGR1cmluZyB0aGUgdXBncmFkZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBFdmVyeXRoaW5nIGlzIGluY2x1ZGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5jbHVkZT86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHRoZSB0YXJnZXQgdmVyc2lvbiB0byB1cGdyYWRlIGRlcGVuZGVuY2llcyB0by5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vcmFpbmVvcnNoaW5lL25wbS1jaGVjay11cGRhdGVzI3RhcmdldFxuICAgKlxuICAgKiBAZGVmYXVsdCBcIm1pbm9yXCJcbiAgICovXG4gIHJlYWRvbmx5IHRhcmdldD86IHN0cmluZztcblxuICAvKipcbiAgICogQ2hlY2sgcGVlciBkZXBlbmRlbmNpZXMgb2YgaW5zdGFsbGVkIHBhY2thZ2VzIGFuZCBmaWx0ZXIgdXBkYXRlcyB0byBjb21wYXRpYmxlIHZlcnNpb25zLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGUgdXBncmFkZSB3b3JrZmxvdyB3aWxsIGFkaGVyZSB0byB2ZXJzaW9uIGNvbnN0cmFpbnRzIGZyb20gcGVlciBkZXBlbmRlbmNpZXMuXG4gICAqIFNvbWV0aW1lcyB0aGlzIGlzIG5vdCBkZXNpcmFibGUgYW5kIGNhbiBiZSBkaXNhYmxlZC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vcmFpbmVvcnNoaW5lL25wbS1jaGVjay11cGRhdGVzI3BlZXJcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgc2F0aXNmeVBlZXJEZXBlbmRlbmNpZXM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJbmNsdWRlIGRlcHJlY2F0ZWQgcGFja2FnZXMuXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIGRlcHJlY2F0ZWQgdmVyc2lvbnMgd2lsbCBiZSBleGNsdWRlZCBmcm9tIHVwZ3JhZGVzLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9yYWluZW9yc2hpbmUvbnBtLWNoZWNrLXVwZGF0ZXM/dGFiPXJlYWRtZS1vdi1maWxlI29wdGlvbnNcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGluY2x1ZGVEZXByZWNhdGVkVmVyc2lvbnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJbmNsdWRlIGEgZ2l0aHViIHdvcmtmbG93IGZvciBjcmVhdGluZyBQUidzIHRoYXQgdXBncmFkZXMgdGhlXG4gICAqIHJlcXVpcmVkIGRlcGVuZGVuY2llcywgZWl0aGVyIGJ5IG1hbnVhbCBkaXNwYXRjaCwgb3IgYnkgYSBzY2hlZHVsZS5cbiAgICpcbiAgICogSWYgdGhpcyBpcyBgZmFsc2VgLCBvbmx5IGEgbG9jYWwgcHJvamVuIHRhc2sgaXMgY3JlYXRlZCwgd2hpY2ggY2FuIGJlIGV4ZWN1dGVkIG1hbnVhbGx5IHRvXG4gICAqIHVwZ3JhZGUgdGhlIGRlcGVuZGVuY2llcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0cnVlIGZvciByb290IHByb2plY3RzLCBmYWxzZSBmb3Igc3VicHJvamVjdHMuXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvdz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIHRoZSBnaXRodWIgd29ya2Zsb3cuIE9ubHkgYXBwbGllcyBpZiBgd29ya2Zsb3dgIGlzIHRydWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZGVmYXVsdCBvcHRpb25zLlxuICAgKi9cbiAgcmVhZG9ubHkgd29ya2Zsb3dPcHRpb25zPzogVXBncmFkZURlcGVuZGVuY2llc1dvcmtmbG93T3B0aW9ucztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIHRhc2sgdGhhdCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAqIFRoaXMgd2lsbCBhbHNvIGJlIHRoZSB3b3JrZmxvdyBuYW1lLlxuICAgKlxuICAgKiBAZGVmYXVsdCBcInVwZ3JhZGVcIi5cbiAgICovXG4gIHJlYWRvbmx5IHRhc2tOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaXRsZSBvZiB0aGUgcHVsbCByZXF1ZXN0IHRvIHVzZSAoc2hvdWxkIGJlIGFsbCBsb3dlci1jYXNlKS5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJ1cGdyYWRlIGRlcGVuZGVuY2llc1wiXG4gICAqL1xuICByZWFkb25seSBwdWxsUmVxdWVzdFRpdGxlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZXNjcmlwdGlvbiBvZiBkZXBlbmRlbmN5IHVwZ3JhZGUgcHVsbCByZXF1ZXN0cy5cbiAgICpcbiAgICogQWxzbyBpbmNsdWRlZCBpbiB0aGUgY29tbWl0IG1lc3NhZ2UuIFRyYWlsaW5nIHdoaXRlc3BhY2UgaXMgcmVtb3ZlZCBhbmQgYVxuICAgKiBwZXJpb2QgaXMgYXBwZW5kZWQgaWYgdGhlcmUgaXMgbm8gZmluYWwgcGVyaW9kLiBFbXB0eSBvciB3aGl0ZXNwYWNlLW9ubHlcbiAgICogc3RyaW5ncyBwcm9kdWNlIGEgc2luZ2xlIHBlcmlvZCBiZWZvcmUgdGhlIHdvcmtmbG93IGRldGFpbHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwiVXBncmFkZXMgcHJvamVjdCBkZXBlbmRlbmNpZXMuXCJcbiAgICovXG4gIHJlYWRvbmx5IHB1bGxSZXF1ZXN0RGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZW1hbnRpYyBjb21taXQgdHlwZS5cbiAgICpcbiAgICogQGRlZmF1bHQgJ2Nob3JlJ1xuICAgKi9cbiAgcmVhZG9ubHkgc2VtYW50aWNDb21taXQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFkZCBTaWduZWQtb2ZmLWJ5IGxpbmUgYnkgdGhlIGNvbW1pdHRlciBhdCB0aGUgZW5kIG9mIHRoZSBjb21taXQgbG9nIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNpZ25vZmY/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IHdoaWNoIGRlcGVuZGVuY3kgdHlwZXMgdGhlIHVwZ3JhZGUgc2hvdWxkIG9wZXJhdGUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQWxsIGRlcGVuZGVuY3kgdHlwZXMuXG4gICAqL1xuICByZWFkb25seSB0eXBlcz86IERlcGVuZGVuY3lUeXBlW107XG5cbiAgLyoqXG4gICAqIEV4Y2x1ZGUgcGFja2FnZSB2ZXJzaW9ucyBwdWJsaXNoZWQgd2l0aGluIHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIGRheXMuXG4gICAqXG4gICAqIFRoaXMgbWF5IHByb3ZpZGUgc29tZSBwcm90ZWN0aW9uIGFnYWluc3Qgc3VwcGx5IGNoYWluIGF0dGFja3MsIHNpbXBseSBieSBhdm9pZGluZ1xuICAgKiBuZXdseSBwdWJsaXNoZWQgcGFja2FnZXMgdGhhdCBtYXkgYmUgbWFsaWNpb3VzLiBJdCBnaXZlcyB0aGUgZWNvc3lzdGVtIG1vcmUgdGltZVxuICAgKiB0byBkZXRlY3QgbWFsaWNpb3VzIHBhY2thZ2VzLiBIb3dldmVyIGl0IGNvbWVzIGF0IHRoZSBjb3N0IG9mIHVwZGF0aW5nIG90aGVyXG4gICAqIHBhY2thZ2VzIHNsb3dlciwgd2hpY2ggbWlnaHQgYWxzbyBjb250YWluIHZ1bG5lcmFiaWxpdGllcyBvciBidWdzIGluIG5lZWQgb2YgYSBmaXguXG4gICAqXG4gICAqIFRoZSBjb29sZG93biBwZXJpb2QgYXBwbGllcyB0byBib3RoIG5wbS1jaGVjay11cGRhdGVzIGRpc2NvdmVyeVxuICAgKiBhbmQgdGhlIHBhY2thZ2UgbWFuYWdlciB1cGRhdGUgY29tbWFuZC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vcmFpbmVvcnNoaW5lL25wbS1jaGVjay11cGRhdGVzI2Nvb2xkb3duXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLm5wbWpzLmNvbS9jbGkvdjExL2NvbW1hbmRzL25wbS11cGRhdGUjYmVmb3JlXG4gICAqIEBzZWUgaHR0cHM6Ly9wbnBtLmlvL3NldHRpbmdzI21pbmltdW1yZWxlYXNlYWdlXG4gICAqIEBzZWUgaHR0cHM6Ly9idW4uY29tL2RvY3MvcG0vY2xpL2luc3RhbGwjbWluaW11bS1yZWxlYXNlLWFnZVxuICAgKiBAc2VlIGh0dHBzOi8veWFybnBrZy5jb20vY29uZmlndXJhdGlvbi95YXJucmMjbnBtTWluaW1hbEFnZUdhdGVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBjb29sZG93biBwZXJpb2QuXG4gICAqL1xuICByZWFkb25seSBjb29sZG93bj86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBVcGdyYWRlIG5vZGUgcHJvamVjdCBkZXBlbmRlbmNpZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBVcGdyYWRlRGVwZW5kZW5jaWVzIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFRoZSB3b3JrZmxvd3MgdGhhdCBleGVjdXRlIHRoZSB1cGdyYWRlcy4gT25lIHdvcmtmbG93IHBlciBicmFuY2guXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgd29ya2Zsb3dzOiBHaXRodWJXb3JrZmxvd1tdID0gW107XG5cbiAgcHVibGljIHJlYWRvbmx5IHByb2plY3Q6IE5vZGVQcm9qZWN0O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogVXBncmFkZURlcGVuZGVuY2llc09wdGlvbnM7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHVsbFJlcXVlc3RUaXRsZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDb250YWluZXIgZGVmaW5pdGlvbnMgZm9yIHRoZSB1cGdyYWRlIHdvcmtmbG93LlxuICAgKi9cbiAgcHVibGljIGNvbnRhaW5lck9wdGlvbnM/OiBDb250YWluZXJPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBUaGUgdXBncmFkZSB0YXNrLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHVwZ3JhZGVUYXNrOiBUYXNrO1xuXG4gIC8qKlxuICAgKiBBIHRhc2sgcnVuIGFmdGVyIHRoZSB1cGdyYWRlIHRhc2suXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcG9zdFVwZ3JhZGVUYXNrOiBUYXNrO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZ2l0SWRlbnRpdHk6IEdpdElkZW50aXR5O1xuICBwcml2YXRlIHJlYWRvbmx5IHBvc3RCdWlsZFN0ZXBzOiBKb2JTdGVwW107XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVybWlzc2lvbnM6IEpvYlBlcm1pc3Npb25zO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlcFR5cGVzOiBEZXBlbmRlbmN5VHlwZVtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHVwZ3JhZGVUYXJnZXQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBzYXRpc2Z5UGVlckRlcGVuZGVuY2llczogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmNsdWRlRGVwcmVjYXRlZFZlcnNpb25zOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IE5vZGVQcm9qZWN0LCBvcHRpb25zOiBVcGdyYWRlRGVwZW5kZW5jaWVzT3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG5cbiAgICB0aGlzLnByb2plY3QgPSBwcm9qZWN0O1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgICAvLyBWYWxpZGF0ZSBjb29sZG93blxuICAgIGlmIChcbiAgICAgIG9wdGlvbnMuY29vbGRvd24gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKCFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMuY29vbGRvd24pIHx8IG9wdGlvbnMuY29vbGRvd24gPCAwKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlRoZSAnY29vbGRvd24nIG9wdGlvbiBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIgcmVwcmVzZW50aW5nIGRheXNcIixcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gWWFybiBjbGFzc2ljIGRvZXNuJ3Qgc3VwcG9ydCBjb29sZG93blxuICAgIGlmIChvcHRpb25zLmNvb2xkb3duICYmIGlzWWFybkNsYXNzaWMocHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlRoZSAnY29vbGRvd24nIG9wdGlvbiBpcyBub3Qgc3VwcG9ydGVkIHdpdGggeWFybiBjbGFzc2ljLiBcIiArXG4gICAgICAgICAgXCJDb25zaWRlciB1c2luZyBucG0sIHBucG0sIGJ1biwgb3IgeWFybiBiZXJyeSBpbnN0ZWFkLlwiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmRlcFR5cGVzID0gdGhpcy5vcHRpb25zLnR5cGVzID8/IFtcbiAgICAgIERlcGVuZGVuY3lUeXBlLkJVSUxELFxuICAgICAgRGVwZW5kZW5jeVR5cGUuQlVORExFRCxcbiAgICAgIERlcGVuZGVuY3lUeXBlLkRFVkVOVixcbiAgICAgIERlcGVuZGVuY3lUeXBlLlBFRVIsXG4gICAgICBEZXBlbmRlbmN5VHlwZS5SVU5USU1FLFxuICAgICAgRGVwZW5kZW5jeVR5cGUuVEVTVCxcbiAgICAgIERlcGVuZGVuY3lUeXBlLk9QVElPTkFMLFxuICAgIF07XG4gICAgdGhpcy51cGdyYWRlVGFyZ2V0ID0gdGhpcy5vcHRpb25zLnRhcmdldCA/PyBcIm1pbm9yXCI7XG4gICAgdGhpcy5zYXRpc2Z5UGVlckRlcGVuZGVuY2llcyA9IHRoaXMub3B0aW9ucy5zYXRpc2Z5UGVlckRlcGVuZGVuY2llcyA/PyB0cnVlO1xuICAgIHRoaXMuaW5jbHVkZURlcHJlY2F0ZWRWZXJzaW9ucyA9XG4gICAgICB0aGlzLm9wdGlvbnMuaW5jbHVkZURlcHJlY2F0ZWRWZXJzaW9ucyA/PyBmYWxzZTtcbiAgICB0aGlzLnB1bGxSZXF1ZXN0VGl0bGUgPSBvcHRpb25zLnB1bGxSZXF1ZXN0VGl0bGUgPz8gXCJ1cGdyYWRlIGRlcGVuZGVuY2llc1wiO1xuICAgIHRoaXMuZ2l0SWRlbnRpdHkgPVxuICAgICAgb3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LmdpdElkZW50aXR5ID8/IERFRkFVTFRfR0lUSFVCX0FDVElPTlNfVVNFUjtcbiAgICB0aGlzLnBlcm1pc3Npb25zID0ge1xuICAgICAgY29udGVudHM6IEpvYlBlcm1pc3Npb24uUkVBRCxcbiAgICAgIC4uLm9wdGlvbnMud29ya2Zsb3dPcHRpb25zPy5wZXJtaXNzaW9ucyxcbiAgICB9O1xuICAgIHRoaXMucG9zdEJ1aWxkU3RlcHMgPSBbXTtcbiAgICB0aGlzLmNvbnRhaW5lck9wdGlvbnMgPSBvcHRpb25zLndvcmtmbG93T3B0aW9ucz8uY29udGFpbmVyO1xuXG4gICAgdGhpcy5wb3N0VXBncmFkZVRhc2sgPVxuICAgICAgcHJvamVjdC50YXNrcy50cnlGaW5kKFwicG9zdC11cGdyYWRlXCIpID8/XG4gICAgICBwcm9qZWN0LnRhc2tzLmFkZFRhc2soXCJwb3N0LXVwZ3JhZGVcIiwge1xuICAgICAgICBkZXNjcmlwdGlvbjogXCJSdW5zIGFmdGVyIHVwZ3JhZGluZyBkZXBlbmRlbmNpZXNcIixcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgdGFza0VudjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHsgQ0k6IFwiMFwiIH07XG5cbiAgICAvLyBZYXJuIGJlcnJ5IHRyZWF0cyBhbnkgbm9uLWVtcHR5IENJIHZhbHVlIGFzIHRydXRoeSBhbmQgYXV0by1lbmFibGVzXG4gICAgLy8gaW1tdXRhYmxlIGluc3RhbGxzLiBFeHBsaWNpdGx5IGRpc2FibGUgaXQgc28geWFybiBkbHgvdXAgY2FuIG1vZGlmeVxuICAgIC8vIHRoZSBsb2NrZmlsZSBkdXJpbmcgdXBncmFkZXMuXG4gICAgaWYgKGlzWWFybkJlcnJ5KHByb2plY3QucGFja2FnZS5wYWNrYWdlTWFuYWdlcikpIHtcbiAgICAgIHRhc2tFbnYuWUFSTl9FTkFCTEVfSU1NVVRBQkxFX0lOU1RBTExTID0gXCJmYWxzZVwiO1xuICAgIH1cblxuICAgIC8vIFNldCB5YXJuIGJlcnJ5IGNvb2xkb3duIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZSwgZXhwZWN0cyBtaW51dGVzXG4gICAgaWYgKG9wdGlvbnMuY29vbGRvd24gJiYgaXNZYXJuQmVycnkocHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyKSkge1xuICAgICAgdGFza0Vudi5ZQVJOX05QTV9NSU5JTUFMX0FHRV9HQVRFID0gU3RyaW5nKFxuICAgICAgICBkYXlzVG9NaW51dGVzKG9wdGlvbnMuY29vbGRvd24pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBTZXQgbnBtIGNvb2xkb3duIGRhdGUgdmlhIGVudmlyb25tZW50IHZhcmlhYmxlIChjYWxjdWxhdGVkIGF0IHJ1bnRpbWUpLCBleHBlY3RzIGEgZGF0ZSBpbiBJU08gZm9ybWF0XG4gICAgaWYgKG9wdGlvbnMuY29vbGRvd24gJiYgaXNOcG0ocHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyKSkge1xuICAgICAgdGFza0Vudi5OUE1fQ09ORklHX0JFRk9SRSA9IGAkKG5vZGUgLXAgXCJuZXcgRGF0ZShEYXRlLm5vdygpLSR7ZGF5c1RvTWlsbGlzZWNvbmRzKFxuICAgICAgICBvcHRpb25zLmNvb2xkb3duLFxuICAgICAgKX0pLnRvSVNPU3RyaW5nKClcIilgO1xuICAgIH1cblxuICAgIHRoaXMudXBncmFkZVRhc2sgPSBwcm9qZWN0LmFkZFRhc2sob3B0aW9ucy50YXNrTmFtZSA/PyBcInVwZ3JhZGVcIiwge1xuICAgICAgLy8gdGhpcyB0YXNrIHNob3VsZCBub3QgcnVuIGluIENJIG1vZGUgYmVjYXVzZSBpdHMgZGVzaWduZWQgdG9cbiAgICAgIC8vIHVwZGF0ZSBwYWNrYWdlLmpzb24gYW5kIGxvY2sgZmlsZXMuXG4gICAgICBlbnY6IHRhc2tFbnYsXG4gICAgICBkZXNjcmlwdGlvbjogdGhpcy5wdWxsUmVxdWVzdFRpdGxlLFxuICAgICAgc3RlcHM6IHsgdG9KU09OOiAoKSA9PiB0aGlzLnJlbmRlclRhc2tTdGVwcygpIH0gYXMgYW55LFxuICAgIH0pO1xuICAgIHRoaXMudXBncmFkZVRhc2subG9jaygpOyAvLyB0aGlzIHRhc2sgaXMgYSBsYXp5IHZhbHVlLCBzbyBtYWtlIGl0IHJlYWRvbmx5XG5cbiAgICAvLyBhbHdheXMgdXNlIHRoZSBHaXRIdWIgb2YgdGhlIHJvb3QgcHJvamVjdCAtIHRoZXJlIGNhbiBvbmx5IGJlIG9uZVxuICAgIGNvbnN0IGdpdGh1YiA9IEdpdEh1Yi5vZihwcm9qZWN0LnJvb3QpO1xuXG4gICAgaWYgKHRoaXMudXBncmFkZVRhc2sgJiYgZ2l0aHViICYmIChvcHRpb25zLndvcmtmbG93ID8/IHRydWUpKSB7XG4gICAgICBpZiAob3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LmJyYW5jaGVzKSB7XG4gICAgICAgIGZvciAoY29uc3QgYnJhbmNoIG9mIG9wdGlvbnMud29ya2Zsb3dPcHRpb25zLmJyYW5jaGVzKSB7XG4gICAgICAgICAgdGhpcy53b3JrZmxvd3MucHVzaChcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlV29ya2Zsb3codGhpcy51cGdyYWRlVGFzaywgZ2l0aHViLCBicmFuY2gpLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoUmVsZWFzZS5vZihwcm9qZWN0KSkge1xuICAgICAgICBjb25zdCByZWxlYXNlID0gUmVsZWFzZS5vZihwcm9qZWN0KSE7XG4gICAgICAgIHJlbGVhc2UuX2ZvckVhY2hCcmFuY2goKGJyYW5jaDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgdGhpcy53b3JrZmxvd3MucHVzaChcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlV29ya2Zsb3codGhpcy51cGdyYWRlVGFzaywgZ2l0aHViLCBicmFuY2gpLFxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVwcmVzZW50cyB0aGUgZGVmYXVsdCByZXBvc2l0b3J5IGJyYW5jaC5cbiAgICAgICAgLy8ganVzdCBsaWtlIG5vdCBzcGVjaWZ5aW5nIGFueXRoaW5nLlxuICAgICAgICBjb25zdCBkZWZhdWx0QnJhbmNoID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLndvcmtmbG93cy5wdXNoKFxuICAgICAgICAgIHRoaXMuY3JlYXRlV29ya2Zsb3codGhpcy51cGdyYWRlVGFzaywgZ2l0aHViLCBkZWZhdWx0QnJhbmNoKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIHN0ZXBzIHRvIGV4ZWN1dGUgYSBzdWNjZXNzZnVsIGJ1aWxkLlxuICAgKiBAcGFyYW0gc3RlcHMgd29ya2Zsb3cgc3RlcHNcbiAgICovXG4gIHB1YmxpYyBhZGRQb3N0QnVpbGRTdGVwcyguLi5zdGVwczogSm9iU3RlcFtdKSB7XG4gICAgdGhpcy5wb3N0QnVpbGRTdGVwcy5wdXNoKC4uLnN0ZXBzKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyVGFza1N0ZXBzKCk6IFRhc2tTdGVwW10ge1xuICAgIGNvbnN0IHN0ZXBzID0gbmV3IEFycmF5PFRhc2tTdGVwPigpO1xuXG4gICAgLy8gUGFja2FnZSBNYW5hZ2VyIHVwZ3JhZGUgc2hvdWxkIGFsd2F5cyBpbmNsdWRlIGFsbCBkZXBzXG4gICAgY29uc3QgaW5jbHVkZUZvclBhY2thZ2VNYW5hZ2VyVXBncmFkZSA9IHRoaXMuYnVpbGREZXBlbmRlbmN5TGlzdCh0cnVlKTtcbiAgICBpZiAoaW5jbHVkZUZvclBhY2thZ2VNYW5hZ2VyVXBncmFkZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBbeyBleGVjQXJnczogW1wiZWNob1wiLCBcIk5vIGRlcGVuZGVuY2llcyB0byB1cGdyYWRlLlwiXSB9XTtcbiAgICB9XG5cbiAgICAvLyBSZW1vdmluZyBgbnBtLWNoZWNrLXVwZGF0ZXNgIGZyb20gb3VyIGRlcGVuZGVuY3kgdHJlZSBiZWNhdXNlIGl0IGRlcGVuZHMgb24gYSBwYWNrYWdlXG4gICAgLy8gdGhhdCB1c2VzIGFuIG5wbS1zcGVjaWZpYyBmZWF0dXJlIHRoYXQgY2F1c2VzIGFuIGludmFsaWQgZGVwZW5kZW5jeSB0cmVlIHdoZW4gdXNpbmcgWWFybiAxLlxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vcHJvamVuL3Byb2plbi9wdWxsLzMxMzYgZm9yIG1vcmUgZGV0YWlscy5cbiAgICBjb25zdCBpbmNsdWRlRm9yTmN1ID0gdGhpcy5idWlsZERlcGVuZGVuY3lMaXN0KGZhbHNlKTtcblxuICAgIC8vIGJ1bXAgdmVyc2lvbnMgaW4gcGFja2FnZS5qc29uXG4gICAgaWYgKGluY2x1ZGVGb3JOY3UubGVuZ3RoKSB7XG4gICAgICBjb25zdCBuY3VDb21tYW5kID0gdGhpcy5idWlsZE5jdUNvbW1hbmQoaW5jbHVkZUZvck5jdSwge1xuICAgICAgICB1cGdyYWRlOiB0cnVlLFxuICAgICAgICB0YXJnZXQ6IHRoaXMudXBncmFkZVRhcmdldCxcbiAgICAgIH0pO1xuICAgICAgc3RlcHMucHVzaCh7IGV4ZWNBcmdzOiBuY3VDb21tYW5kIH0pO1xuICAgIH1cblxuICAgIC8vIHJ1biBcInlhcm4vbnBtIGluc3RhbGxcIiB0byB1cGRhdGUgdGhlIGxvY2tmaWxlIGFuZCBpbnN0YWxsIGFueSBkZXBzIChzdWNoIGFzIHByb2plbilcbiAgICBzdGVwcy5wdXNoKHsgZXhlYzogdGhpcy5wcm9qZWN0LnBhY2thZ2UuaW5zdGFsbEFuZFVwZGF0ZUxvY2tmaWxlQ29tbWFuZCB9KTtcblxuICAgIC8vIHJ1biB1cGdyYWRlIGNvbW1hbmQgdG8gdXBncmFkZSB0cmFuc2l0aXZlIGRlcHMgYXMgd2VsbFxuICAgIHN0ZXBzLnB1c2goe1xuICAgICAgZXhlY0FyZ3M6IHRoaXMucmVuZGVyVXBncmFkZVBhY2thZ2VzQ29tbWFuZChcbiAgICAgICAgaW5jbHVkZUZvclBhY2thZ2VNYW5hZ2VyVXBncmFkZSxcbiAgICAgICksXG4gICAgfSk7XG5cbiAgICAvLyBJZiB3ZSBoYXZlIGEgcGFja2FnZXMgZGVkdXBsaWNhdGlvbiB0YXNrLCBydW4gaXQgbm93LlxuICAgIGlmICh0aGlzLnByb2plY3QucGFja2FnZS5kZWR1cGVUYXNrKSB7XG4gICAgICBzdGVwcy5wdXNoKHsgc3Bhd246IHRoaXMucHJvamVjdC5wYWNrYWdlLmRlZHVwZVRhc2submFtZSB9KTtcbiAgICB9XG5cbiAgICAvLyBydW4gXCJwcm9qZW5cIiB0byBnaXZlIHByb2plbiBhIGNoYW5jZSB0byB1cGRhdGUgZGVwZW5kZW5jaWVzIChpdCB3aWxsIGFsc28gcnVuIFwieWFybiBpbnN0YWxsXCIpXG4gICAgc3RlcHMucHVzaCh7IGV4ZWM6IHRoaXMucHJvamVjdC5wcm9qZW5Db21tYW5kIH0pO1xuICAgIHN0ZXBzLnB1c2goeyBzcGF3bjogdGhpcy5wb3N0VXBncmFkZVRhc2submFtZSB9KTtcblxuICAgIHJldHVybiBzdGVwcztcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBucG0tY2hlY2stdXBkYXRlcyBjb21tYW5kIHdpdGggY29tbW9uIG9wdGlvbnMuXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkTmN1Q29tbWFuZChcbiAgICBpbmNsdWRlUGFja2FnZXM6IHN0cmluZ1tdLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIHVwZ3JhZGU/OiBib29sZWFuO1xuICAgICAgdGFyZ2V0Pzogc3RyaW5nO1xuICAgICAgZm9ybWF0Pzogc3RyaW5nO1xuICAgICAgcmVtb3ZlUmFuZ2U/OiBib29sZWFuO1xuICAgIH0gPSB7fSxcbiAgKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGNvbW1hbmQgPSBbXG4gICAgICAuLi5leGVjdXRlQ29tbWFuZFByaW9ySW5zdGFsbGF0aW9uKHRoaXMucHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyKSxcbiAgICAgIFwibnBtLWNoZWNrLXVwZGF0ZXNAMjBcIixcbiAgICBdO1xuXG4gICAgaWYgKG9wdGlvbnMudXBncmFkZSkge1xuICAgICAgY29tbWFuZC5wdXNoKFwiLS11cGdyYWRlXCIpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy50YXJnZXQpIHtcbiAgICAgIGNvbW1hbmQucHVzaChgLS10YXJnZXQ9JHtvcHRpb25zLnRhcmdldH1gKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuZm9ybWF0KSB7XG4gICAgICBjb21tYW5kLnB1c2goYC0tZm9ybWF0PSR7b3B0aW9ucy5mb3JtYXR9YCk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnJlbW92ZVJhbmdlKSB7XG4gICAgICBjb21tYW5kLnB1c2goXCItLXJlbW92ZVJhbmdlXCIpO1xuICAgIH1cbiAgICBpZiAodGhpcy5vcHRpb25zLmNvb2xkb3duKSB7XG4gICAgICBjb21tYW5kLnB1c2goYC0tY29vbGRvd249JHt0aGlzLm9wdGlvbnMuY29vbGRvd259YCk7XG4gICAgfVxuXG4gICAgY29tbWFuZC5wdXNoKGAtLSR7dGhpcy5zYXRpc2Z5UGVlckRlcGVuZGVuY2llcyA/IFwicGVlclwiIDogXCJuby1wZWVyXCJ9YCk7XG4gICAgY29tbWFuZC5wdXNoKFxuICAgICAgYC0tJHt0aGlzLmluY2x1ZGVEZXByZWNhdGVkVmVyc2lvbnMgPyBcImRlcHJlY2F0ZWRcIiA6IFwibm8tZGVwcmVjYXRlZFwifWAsXG4gICAgKTtcbiAgICBjb21tYW5kLnB1c2goYC0tZGVwPSR7dGhpcy5yZW5kZXJOY3VEZXBlbmRlbmN5VHlwZXModGhpcy5kZXBUeXBlcyl9YCk7XG4gICAgY29tbWFuZC5wdXNoKGAtLWZpbHRlcj0ke2luY2x1ZGVQYWNrYWdlcy5qb2luKFwiLFwiKX1gKTtcblxuICAgIHJldHVybiBjb21tYW5kO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciBwcm9qZW4gZGVwZW5kZW5jaWVzIHR5cGVzIHRvIGEgbGlzdCBvZiBuY3UgY29tcGF0aWJsZSB0eXBlc1xuICAgKi9cbiAgcHJpdmF0ZSByZW5kZXJOY3VEZXBlbmRlbmN5VHlwZXModHlwZXM6IERlcGVuZGVuY3lUeXBlW10pIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoXG4gICAgICAgIHR5cGVzXG4gICAgICAgICAgLm1hcCgodHlwZSkgPT4ge1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgIGNhc2UgRGVwZW5kZW5jeVR5cGUuUEVFUjpcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJwZWVyXCI7XG4gICAgICAgICAgICAgIGNhc2UgRGVwZW5kZW5jeVR5cGUuUlVOVElNRTpcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJwcm9kXCI7XG4gICAgICAgICAgICAgIGNhc2UgRGVwZW5kZW5jeVR5cGUuT1BUSU9OQUw6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwib3B0aW9uYWxcIjtcblxuICAgICAgICAgICAgICBjYXNlIERlcGVuZGVuY3lUeXBlLlRFU1Q6XG4gICAgICAgICAgICAgIGNhc2UgRGVwZW5kZW5jeVR5cGUuREVWRU5WOlxuICAgICAgICAgICAgICBjYXNlIERlcGVuZGVuY3lUeXBlLkJVSUxEOlxuICAgICAgICAgICAgICAgIHJldHVybiBcImRldlwiO1xuXG4gICAgICAgICAgICAgIGNhc2UgRGVwZW5kZW5jeVR5cGUuQlVORExFRDpcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJwcm9kXCI7XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmZpbHRlcigodHlwZSkgPT4gQm9vbGVhbih0eXBlKSksXG4gICAgICApLFxuICAgICkuam9pbihcIixcIik7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIGEgcGFja2FnZSBtYW5hZ2VyIHNwZWNpZmljIGNvbW1hbmQgdG8gdXBncmFkZSBhbGwgcmVxdWVzdGVkIGRlcGVuZGVuY2llcy5cbiAgICovXG4gIHByaXZhdGUgcmVuZGVyVXBncmFkZVBhY2thZ2VzQ29tbWFuZChpbmNsdWRlOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgICBmdW5jdGlvbiB1cGdyYWRlUGFja2FnZXMoY29tbWFuZDogc3RyaW5nW10sIGNvb2xkb3duRmxhZz86IHN0cmluZykge1xuICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgY29uc3QgcGFydHMgPSBbLi4uY29tbWFuZCwgLi4uaW5jbHVkZV07XG4gICAgICAgIGlmIChjb29sZG93bkZsYWcpIHtcbiAgICAgICAgICBwYXJ0cy5wdXNoKGNvb2xkb3duRmxhZyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhcnRzO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBwYWNrYWdlTWFuYWdlciA9IHRoaXMucHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyO1xuICAgIGNvbnN0IGNvb2xkb3duID0gdGhpcy5vcHRpb25zLmNvb2xkb3duO1xuXG4gICAgbGV0IGxhenkgPSB1bmRlZmluZWQ7XG4gICAgc3dpdGNoIChwYWNrYWdlTWFuYWdlcikge1xuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuWUFSTjpcbiAgICAgIGNhc2UgTm9kZVBhY2thZ2VNYW5hZ2VyLllBUk5fQ0xBU1NJQzpcbiAgICAgICAgbGF6eSA9IHVwZ3JhZGVQYWNrYWdlcyhbXCJ5YXJuXCIsIFwidXBncmFkZVwiXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuWUFSTjI6XG4gICAgICBjYXNlIE5vZGVQYWNrYWdlTWFuYWdlci5ZQVJOX0JFUlJZOlxuICAgICAgICAvLyBZYXJuIEJlcnJ5IGNvb2xkb3duIHNldCB2aWEgdGFzayBlbnZcbiAgICAgICAgbGF6eSA9IHVwZ3JhZGVQYWNrYWdlcyhbXCJ5YXJuXCIsIFwidXBcIiwgXCItUlwiXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuTlBNOlxuICAgICAgICAvLyBucG0gY29vbGRvd24gc2V0IHZpYSBOUE1fQ09ORklHX0JFRk9SRSBlbnZcbiAgICAgICAgbGF6eSA9IHVwZ3JhZGVQYWNrYWdlcyhbXCJucG1cIiwgXCJ1cGRhdGVcIl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTm9kZVBhY2thZ2VNYW5hZ2VyLlBOUE06XG4gICAgICAgIC8vIHBucG0gZXhwZWN0cyBtaW51dGVzXG4gICAgICAgIGxhenkgPSB1cGdyYWRlUGFja2FnZXMoXG4gICAgICAgICAgW1wicG5wbVwiLCBcInVwZGF0ZVwiXSxcbiAgICAgICAgICBjb29sZG93biAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IGAtLWNvbmZpZy5taW5pbXVtLXJlbGVhc2UtYWdlPSR7ZGF5c1RvTWludXRlcyhjb29sZG93bil9YFxuICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuQlVOOlxuICAgICAgICAvLyBidW4gZXhwZWN0cyBzZWNvbmRzXG4gICAgICAgIGxhenkgPSB1cGdyYWRlUGFja2FnZXMoXG4gICAgICAgICAgW1wiYnVuXCIsIFwidXBkYXRlXCJdLFxuICAgICAgICAgIGNvb2xkb3duXG4gICAgICAgICAgICA/IGAtLW1pbmltdW0tcmVsZWFzZS1hZ2U9JHtkYXlzVG9TZWNvbmRzKGNvb2xkb3duKX1gXG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuZXhwZWN0ZWQgcGFja2FnZSBtYW5hZ2VyICR7cGFja2FnZU1hbmFnZXJ9YCk7XG4gICAgfVxuXG4gICAgLy8gcmV0dXJuIGEgbGF6eSBmdW5jdGlvbiBzbyB0aGF0IGRlcGVuZGVuY2llcyBpbmNsdWRlIG9uZXMgdGhhdCB3ZXJlXG4gICAgLy8gYWRkZWQgcG9zdCBwcm9qZWN0IGluc3RhbnRpYXRpb24gKGkuZSB1c2luZyBwcm9qZWN0LmFkZERlcHMpXG4gICAgcmV0dXJuIGxhenkgYXMgdW5rbm93biBhcyBzdHJpbmdbXTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGREZXBlbmRlbmN5TGlzdChpbmNsdWRlRGVwZW5kZW5jaWVzV2l0aENvbnN0cmFpbnQ6IGJvb2xlYW4pIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoXG4gICAgICAgIHRoaXMub3B0aW9ucy5pbmNsdWRlID8/XG4gICAgICAgICAgdGhpcy5maWx0ZXJEZXBlbmRlbmNpZXMoaW5jbHVkZURlcGVuZGVuY2llc1dpdGhDb25zdHJhaW50KSxcbiAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZmlsdGVyRGVwZW5kZW5jaWVzKGluY2x1ZGVDb25zdHJhaW50OiBib29sZWFuKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IFtdO1xuXG4gICAgY29uc3QgZGVwcyA9IHRoaXMucHJvamVjdC5kZXBzLmFsbFxuICAgICAgLy8gcmVtb3ZlIHRob3NlIHRoYXQgaGF2ZSBhIGNvbnN0cmFpbnQgdmVyc2lvbiAodW5sZXNzIGluY2x1ZGVDb25zdHJhaW50IGlzIHRydWUpXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoZCkgPT5cbiAgICAgICAgICBpbmNsdWRlQ29uc3RyYWludCB8fFxuICAgICAgICAgIHRoaXMucGFja2FnZUNhbkJlVXBncmFkZWRJblBhY2thZ2VKc29uKGQudmVyc2lvbiksXG4gICAgICApXG4gICAgICAvLyByZW1vdmUgb3ZlcnJpZGUgZGVwZW5kZW5jaWVzXG4gICAgICAuZmlsdGVyKChkKSA9PiBkLnR5cGUgIT09IERlcGVuZGVuY3lUeXBlLk9WRVJSSURFKTtcblxuICAgIGZvciAoY29uc3QgdHlwZSBvZiB0aGlzLmRlcFR5cGVzKSB7XG4gICAgICBkZXBlbmRlbmNpZXMucHVzaChcbiAgICAgICAgLi4uZGVwc1xuICAgICAgICAgIC5maWx0ZXIoKGQpID0+IGQudHlwZSA9PT0gdHlwZSlcbiAgICAgICAgICAuZmlsdGVyKChkKSA9PiAhKHRoaXMub3B0aW9ucy5leGNsdWRlID8/IFtdKS5pbmNsdWRlcyhkLm5hbWUpKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlcGVuZGVuY2llcy5tYXAoKGQpID0+IGQubmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJvamVuIGNhbiBhbHRlciBhIHBhY2thZ2UncyB2ZXJzaW9uIGluIHBhY2thZ2UuanNvbiB3aGVuIGVpdGhlciB0aGUgdmVyc2lvbiBpcyBvbWl0dGVkLCBvciBzZXQgdG8gXCIqXCIuXG4gICAqIE90aGVyd2lzZSwgdGhlIGV4YWN0IHZlcnNpb24gc2VsZWN0ZWQgaXMgcGxhY2VkIGluIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBhbmQgdXBncmFkaW5nIGlzIGhhbmRsZWQgdGhyb3VnaCB0aGUgcGFja2FnZSBtYW5hZ2VyXG4gICAqIHJhdGhlciB0aGFuIG5wbS1jaGVjay11cGRhdGVzLlxuICAgKlxuICAgKiBAcGFyYW0gdmVyc2lvbiBzZW12ZXIgZnJvbSBEZXBlbmRlbmN5Q29vcmRpbmF0ZXMudmVyc2lvbiwgbWF5IGJlIHVuZGVmaW5lZFxuICAgKiBAcmV0dXJucyB3aGV0aGVyIHRoZSB2ZXJzaW9uIGlzIHRoZSBkZWZhdWx0IHZlcnNpb25pbmcgYmVoYXZpb3JcbiAgICovXG4gIHByaXZhdGUgcGFja2FnZUNhbkJlVXBncmFkZWRJblBhY2thZ2VKc29uKFxuICAgIHZlcnNpb246IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgKTogYm9vbGVhbiB7XG4gICAgLy8gTm8gdmVyc2lvbiBtZWFucyBcImxhdGVzdFwiXG4gICAgcmV0dXJuICF2ZXJzaW9uIHx8IHZlcnNpb24gPT09IFwiKlwiO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVXb3JrZmxvdyhcbiAgICB0YXNrOiBUYXNrLFxuICAgIGdpdGh1YjogR2l0SHViLFxuICAgIGJyYW5jaD86IHN0cmluZyxcbiAgKTogR2l0aHViV29ya2Zsb3cge1xuICAgIGNvbnN0IHNjaGVkdWxlID1cbiAgICAgIHRoaXMub3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LnNjaGVkdWxlID8/XG4gICAgICBVcGdyYWRlRGVwZW5kZW5jaWVzU2NoZWR1bGUuREFJTFk7XG5cbiAgICBjb25zdCB0YXNrQnJhbmNoTmFtZSA9IGAke3Rhc2submFtZX0ke1xuICAgICAgYnJhbmNoID8gYC0ke2JyYW5jaC5yZXBsYWNlKC9cXC8vZywgXCItXCIpfWAgOiBcIlwiXG4gICAgfWA7XG4gICAgY29uc3Qgd29ya2Zsb3dOYW1lID0gd29ya2Zsb3dOYW1lRm9yUHJvamVjdCh0YXNrQnJhbmNoTmFtZSwgdGhpcy5wcm9qZWN0KTtcblxuICAgIGNvbnN0IHdvcmtmbG93ID0gZ2l0aHViLmFkZFdvcmtmbG93KHdvcmtmbG93TmFtZSk7XG4gICAgY29uc3QgdHJpZ2dlcnM6IHdvcmtmbG93cy5UcmlnZ2VycyA9IHtcbiAgICAgIHdvcmtmbG93RGlzcGF0Y2g6IHt9LFxuICAgICAgc2NoZWR1bGU6XG4gICAgICAgIHNjaGVkdWxlLmNyb24ubGVuZ3RoID4gMFxuICAgICAgICAgID8gc2NoZWR1bGUuY3Jvbi5tYXAoKGUpID0+ICh7IGNyb246IGUgfSkpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgICB3b3JrZmxvdy5vbih0cmlnZ2Vycyk7XG5cbiAgICBjb25zdCB1cGdyYWRlID0gdGhpcy5jcmVhdGVVcGdyYWRlKHRhc2ssIGdpdGh1YiwgYnJhbmNoKTtcbiAgICBjb25zdCBwciA9IHRoaXMuY3JlYXRlUHIod29ya2Zsb3csIHVwZ3JhZGUpO1xuXG4gICAgY29uc3Qgam9iczogUmVjb3JkPHN0cmluZywgd29ya2Zsb3dzLkpvYj4gPSB7fTtcbiAgICBqb2JzW3VwZ3JhZGUuam9iSWRdID0gdXBncmFkZS5qb2I7XG4gICAgam9ic1twci5qb2JJZF0gPSBwci5qb2I7XG5cbiAgICB3b3JrZmxvdy5hZGRKb2JzKGpvYnMpO1xuICAgIHJldHVybiB3b3JrZmxvdztcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVXBncmFkZSh0YXNrOiBUYXNrLCBnaXRodWI6IEdpdEh1YiwgYnJhbmNoPzogc3RyaW5nKTogVXBncmFkZSB7XG4gICAgY29uc3Qgd2l0aF8gPSB7XG4gICAgICAuLi4oYnJhbmNoID8geyByZWY6IGJyYW5jaCB9IDoge30pLFxuICAgICAgLi4uKGdpdGh1Yi5kb3dubG9hZExmcyA/IHsgbGZzOiB0cnVlIH0gOiB7fSksXG4gICAgICAuLi4oZ2l0aHViLmNoZWNrb3V0U3VibW9kdWxlcyAhPT0gQ2hlY2tvdXRTdWJtb2R1bGVzLkRJU0FCTEVEXG4gICAgICAgID8geyBzdWJtb2R1bGVzOiBnaXRodWIuY2hlY2tvdXRTdWJtb2R1bGVzIH1cbiAgICAgICAgOiB7fSksXG4gICAgfTtcblxuICAgIGNvbnN0IHN0ZXBzOiB3b3JrZmxvd3MuSm9iU3RlcFtdID0gW1xuICAgICAgV29ya2Zsb3dTdGVwcy5jaGVja291dCh7IHdpdGg6IHdpdGhfIH0pLFxuICAgICAgLi4udGhpcy5wcm9qZWN0LnJlbmRlcldvcmtmbG93U2V0dXAoeyBtdXRhYmxlOiBmYWxzZSB9KSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJVcGdyYWRlIGRlcGVuZGVuY2llc1wiLFxuICAgICAgICBydW46IHRoaXMucHJvamVjdC5ydW5UYXNrQ29tbWFuZCh0YXNrKSxcbiAgICAgICAgd29ya2luZ0RpcmVjdG9yeTogdGhpcy5wcm9qZWN0LnBhcmVudFxuICAgICAgICAgID8gcHJvamVjdFBhdGhSZWxhdGl2ZVRvUmVwb1Jvb3QodGhpcy5wcm9qZWN0KVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgc3RlcHMucHVzaCguLi50aGlzLnBvc3RCdWlsZFN0ZXBzKTtcbiAgICBzdGVwcy5wdXNoKFxuICAgICAgLi4uV29ya2Zsb3dBY3Rpb25zLnVwbG9hZEdpdFBhdGNoKHtcbiAgICAgICAgc3RlcElkOiBDUkVBVEVfUEFUQ0hfU1RFUF9JRCxcbiAgICAgICAgb3V0cHV0TmFtZTogUEFUQ0hfQ1JFQVRFRF9PVVRQVVQsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGpvYjoge1xuICAgICAgICBuYW1lOiBcIlVwZ3JhZGVcIixcbiAgICAgICAgY29udGFpbmVyOiB0aGlzLmNvbnRhaW5lck9wdGlvbnMsXG4gICAgICAgIHBlcm1pc3Npb25zOiB0aGlzLnBlcm1pc3Npb25zLFxuICAgICAgICBlbnY6IHRoaXMub3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LmVudixcbiAgICAgICAgLi4uZ2l0aHViLnJ1bnNPbkNvbmZpZyh0aGlzLm9wdGlvbnMud29ya2Zsb3dPcHRpb25zKSxcbiAgICAgICAgc3RlcHM6IHN0ZXBzLFxuICAgICAgICBvdXRwdXRzOiB7XG4gICAgICAgICAgW1BBVENIX0NSRUFURURfT1VUUFVUXToge1xuICAgICAgICAgICAgc3RlcElkOiBDUkVBVEVfUEFUQ0hfU1RFUF9JRCxcbiAgICAgICAgICAgIG91dHB1dE5hbWU6IFBBVENIX0NSRUFURURfT1VUUFVULFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgam9iSWQ6IFwidXBncmFkZVwiLFxuICAgICAgcmVmOiBicmFuY2gsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUHIod29ya2Zsb3c6IEdpdGh1YldvcmtmbG93LCB1cGdyYWRlOiBVcGdyYWRlKTogUFIge1xuICAgIGNvbnN0IGNyZWRlbnRpYWxzID1cbiAgICAgIHRoaXMub3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LnByb2plbkNyZWRlbnRpYWxzID8/XG4gICAgICB3b3JrZmxvdy5wcm9qZW5DcmVkZW50aWFscztcblxuICAgIGNvbnN0IHNlbWFudGljQ29tbWl0ID0gdGhpcy5vcHRpb25zLnNlbWFudGljQ29tbWl0ID8/IFwiY2hvcmVcIjtcblxuICAgIC8vIGNyZWF0ZVByIGlzIG9ubHkgY2FsbGVkIGZyb20gY3JlYXRlV29ya2Zsb3csIHdoaWNoIGlzIG9ubHkgcmVhY2hhYmxlXG4gICAgLy8gb25jZSB0aGUgY29uc3RydWN0b3IgaGFzIGFscmVhZHkgY29uZmlybWVkIHRoZSByb290IHByb2plY3QgaGFzIEdpdEh1YlxuICAgIC8vIGVuYWJsZWQgLSBzbyB0aGlzIGlzIGFsd2F5cyBkZWZpbmVkLlxuICAgIGNvbnN0IGdpdGh1YiA9IEdpdEh1Yi5vZih0aGlzLnByb2plY3Qucm9vdCkhO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGpvYjogV29ya2Zsb3dKb2JzLnB1bGxSZXF1ZXN0RnJvbVBhdGNoKHtcbiAgICAgICAgcGF0Y2g6IHtcbiAgICAgICAgICBqb2JJZDogdXBncmFkZS5qb2JJZCxcbiAgICAgICAgICBvdXRwdXROYW1lOiBQQVRDSF9DUkVBVEVEX09VVFBVVCxcbiAgICAgICAgICByZWY6IHVwZ3JhZGUucmVmLFxuICAgICAgICB9LFxuICAgICAgICB3b3JrZmxvd05hbWU6IHdvcmtmbG93Lm5hbWUsXG4gICAgICAgIGNyZWRlbnRpYWxzLFxuICAgICAgICAuLi5naXRodWIucnVuc09uQ29uZmlnKHRoaXMub3B0aW9ucy53b3JrZmxvd09wdGlvbnMpLFxuICAgICAgICBwdWxsUmVxdWVzdFRpdGxlOiBgJHtzZW1hbnRpY0NvbW1pdH0oZGVwcyk6ICR7dGhpcy5wdWxsUmVxdWVzdFRpdGxlfWAsXG4gICAgICAgIHB1bGxSZXF1ZXN0RGVzY3JpcHRpb246XG4gICAgICAgICAgdGhpcy5vcHRpb25zLnB1bGxSZXF1ZXN0RGVzY3JpcHRpb24gPz9cbiAgICAgICAgICBcIlVwZ3JhZGVzIHByb2plY3QgZGVwZW5kZW5jaWVzLlwiLFxuICAgICAgICBnaXRJZGVudGl0eTogdGhpcy5naXRJZGVudGl0eSxcbiAgICAgICAgYXNzaWduZWVzOiB0aGlzLm9wdGlvbnMud29ya2Zsb3dPcHRpb25zPy5hc3NpZ25lZXMsXG4gICAgICAgIGxhYmVsczogdGhpcy5vcHRpb25zLndvcmtmbG93T3B0aW9ucz8ubGFiZWxzLFxuICAgICAgICBzaWdub2ZmOiB0aGlzLm9wdGlvbnMuc2lnbm9mZixcbiAgICAgIH0pLFxuICAgICAgam9iSWQ6IFwicHJcIixcbiAgICB9O1xuICB9XG59XG5cbmludGVyZmFjZSBVcGdyYWRlIHtcbiAgcmVhZG9ubHkgcmVmPzogc3RyaW5nO1xuICByZWFkb25seSBqb2I6IHdvcmtmbG93cy5Kb2I7XG4gIHJlYWRvbmx5IGpvYklkOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBQUiB7XG4gIHJlYWRvbmx5IGpvYjogd29ya2Zsb3dzLkpvYjtcbiAgcmVhZG9ubHkgam9iSWQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgVXBncmFkZURlcGVuZGVuY2llcy53b3JrZmxvd09wdGlvbnNgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFVwZ3JhZGVEZXBlbmRlbmNpZXNXb3JrZmxvd09wdGlvbnMge1xuICAvKipcbiAgICogU2NoZWR1bGUgdG8gcnVuIG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBVcGdyYWRlRGVwZW5kZW5jaWVzU2NoZWR1bGUuREFJTFlcbiAgICovXG4gIHJlYWRvbmx5IHNjaGVkdWxlPzogVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlO1xuXG4gIC8qKlxuICAgKiBDaG9vc2UgYSBtZXRob2QgZm9yIGF1dGhlbnRpY2F0aW5nIHdpdGggR2l0SHViIGZvciBjcmVhdGluZyB0aGUgUFIuXG4gICAqXG4gICAqIFdoZW4gdXNpbmcgdGhlIGRlZmF1bHQgZ2l0aHViIHRva2VuLCBQUidzIGNyZWF0ZWQgYnkgdGhpcyB3b3JrZmxvd1xuICAgKiB3aWxsIG5vdCB0cmlnZ2VyIGFueSBzdWJzZXF1ZW50IHdvcmtmbG93cyAoaS5lIHRoZSBidWlsZCB3b3JrZmxvdyksIHNvXG4gICAqIHByb2plbiByZXF1aXJlcyBBUEkgYWNjZXNzIHRvIGJlIHByb3ZpZGVkIHRocm91Z2ggZS5nLiBhIHBlcnNvbmFsXG4gICAqIGFjY2VzcyB0b2tlbiBvciBvdGhlciBtZXRob2QuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3BldGVyLWV2YW5zL2NyZWF0ZS1wdWxsLXJlcXVlc3QvaXNzdWVzLzQ4XG4gICAqIEBkZWZhdWx0IC0gcGVyc29uYWwgYWNjZXNzIHRva2VuIG5hbWVkIFBST0pFTl9HSVRIVUJfVE9LRU5cbiAgICovXG4gIHJlYWRvbmx5IHByb2plbkNyZWRlbnRpYWxzPzogR2l0aHViQ3JlZGVudGlhbHM7XG5cbiAgLyoqXG4gICAqIExhYmVscyB0byBhcHBseSBvbiB0aGUgUFIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gbGFiZWxzLlxuICAgKi9cbiAgcmVhZG9ubHkgbGFiZWxzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEFzc2lnbmVlcyB0byBhZGQgb24gdGhlIFBSLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGFzc2lnbmVlc1xuICAgKi9cbiAgcmVhZG9ubHkgYXNzaWduZWVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEpvYiBjb250YWluZXIgb3B0aW9ucy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZWZhdWx0c1xuICAgKi9cbiAgcmVhZG9ubHkgY29udGFpbmVyPzogd29ya2Zsb3dzLkNvbnRhaW5lck9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIExpc3Qgb2YgYnJhbmNoZXMgdG8gY3JlYXRlIFBSJ3MgZm9yLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEFsbCByZWxlYXNlIGJyYW5jaGVzIGNvbmZpZ3VyZWQgZm9yIHRoZSBwcm9qZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgYnJhbmNoZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGdpdCBpZGVudGl0eSB0byB1c2UgZm9yIGNvbW1pdHMuXG4gICAqIEBkZWZhdWx0IC0gZGVmYXVsdCBHaXRIdWIgQWN0aW9ucyB1c2VyXG4gICAqL1xuICByZWFkb25seSBnaXRJZGVudGl0eT86IEdpdElkZW50aXR5O1xuXG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIHNlbGVjdGlvbiBsYWJlbHNcbiAgICogQGRlZmF1bHQgW1widWJ1bnR1LWxhdGVzdFwiXVxuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgYnkgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbj86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIEdyb3VwIHNlbGVjdGlvbiBvcHRpb25zXG4gICAqIEBkZXNjcmlwdGlvbiBEZWZpbmVzIGEgdGFyZ2V0IFJ1bm5lciBHcm91cCBieSBuYW1lIGFuZC9vciBsYWJlbHNcbiAgICogQHRocm93cyB7RXJyb3J9IGlmIGJvdGggYHJ1bnNPbmAgYW5kIGBydW5zT25Hcm91cGAgYXJlIHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgcnVuc09uR3JvdXA/OiBHcm91cFJ1bm5lck9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFBlcm1pc3Npb25zIGdyYW50ZWQgdG8gdGhlIHVwZ3JhZGUgam9iXG4gICAqIFRvIGxpbWl0IGpvYiBwZXJtaXNzaW9ucyBmb3IgYGNvbnRlbnRzYCwgdGhlIGRlc2lyZWQgcGVybWlzc2lvbnMgaGF2ZSB0byBiZSBleHBsaWNpdGx5IHNldCwgZS5nLjogYHsgY29udGVudHM6IEpvYlBlcm1pc3Npb24uTk9ORSB9YFxuICAgKiBAZGVmYXVsdCBgeyBjb250ZW50czogSm9iUGVybWlzc2lvbi5SRUFEIH1gXG4gICAqL1xuICByZWFkb25seSBwZXJtaXNzaW9ucz86IEpvYlBlcm1pc3Npb25zO1xuXG4gIC8qKlxuICAgKiBCdWlsZCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgZm9yIHRoZSB1cGdyYWRlIGpvYi5cbiAgICpcbiAgICogQGRlZmF1bHQge31cbiAgICovXG4gIHJlYWRvbmx5IGVudj86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG59XG5cbi8qKlxuICogSG93IG9mdGVuIHRvIGNoZWNrIGZvciBuZXcgdmVyc2lvbnMgYW5kIHJhaXNlIHB1bGwgcmVxdWVzdHMgZm9yIHZlcnNpb24gdXBncmFkZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBVcGdyYWRlRGVwZW5kZW5jaWVzU2NoZWR1bGUge1xuICAvKipcbiAgICogRGlzYWJsZXMgYXV0b21hdGljIHVwZ3JhZGVzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBORVZFUiA9IG5ldyBVcGdyYWRlRGVwZW5kZW5jaWVzU2NoZWR1bGUoW10pO1xuXG4gIC8qKlxuICAgKiBBdCAwMDowMC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREFJTFkgPSBuZXcgVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlKFtcIjAgMCAqICogKlwiXSk7XG5cbiAgLyoqXG4gICAqIEF0IDAwOjAwIG9uIGV2ZXJ5IGRheS1vZi13ZWVrIGZyb20gTW9uZGF5IHRocm91Z2ggRnJpZGF5LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBXRUVLREFZID0gbmV3IFVwZ3JhZGVEZXBlbmRlbmNpZXNTY2hlZHVsZShbXG4gICAgXCIwIDAgKiAqIDEtNVwiLFxuICBdKTtcblxuICAvKipcbiAgICogQXQgMDA6MDAgb24gTW9uZGF5LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBXRUVLTFkgPSBuZXcgVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlKFtcbiAgICBcIjAgMCAqICogMVwiLFxuICBdKTtcblxuICAvKipcbiAgICogQXQgMDA6MDAgb24gZGF5LW9mLW1vbnRoIDEuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE1PTlRITFkgPSBuZXcgVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlKFtcbiAgICBcIjAgMCAxICogKlwiLFxuICBdKTtcblxuICAvKipcbiAgICogQ3JlYXRlIGEgc2NoZWR1bGUgZnJvbSBhIHJhdyBjcm9uIGV4cHJlc3Npb24uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGV4cHJlc3Npb25zKGNyb246IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIG5ldyBVcGdyYWRlRGVwZW5kZW5jaWVzU2NoZWR1bGUoY3Jvbik7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBjcm9uOiBzdHJpbmdbXSkge31cbn1cblxuLyoqXG4gKiBDb252ZXJ0IGRheXMgdG8gbWludXRlcy5cbiAqL1xuZnVuY3Rpb24gZGF5c1RvTWludXRlcyhkYXlzOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gZGF5cyAqIDE0NDA7XG59XG5cbi8qKlxuICogQ29udmVydCBkYXlzIHRvIHNlY29uZHMuXG4gKi9cbmZ1bmN0aW9uIGRheXNUb1NlY29uZHMoZGF5czogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIGRheXMgKiA4NjQwMDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGRheXMgdG8gbWlsbGlzZWNvbmRzLlxuICovXG5mdW5jdGlvbiBkYXlzVG9NaWxsaXNlY29uZHMoZGF5czogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIGRheXMgKiA4NjQwMDAwMDtcbn1cbiJdfQ==