UNPKG

gitlab-ci-local

Version:

Tired of pushing to test your .gitlab-ci.yml?

247 lines 46.2 kB
import chalk from "chalk"; import { Utils } from "./utils.js"; import { Executor } from "./executor.js"; import fs from "fs-extra"; import { AssertionError } from "assert"; export class Commander { static async runPipeline(argv, parser, writeStreams) { const jobs = parser.jobs; const stages = parser.stages; let potentialStarters = [...jobs.values()]; potentialStarters = potentialStarters.filter(j => j.when !== "never"); potentialStarters = potentialStarters.filter(j => j.when !== "manual" || argv.manual.includes(j.name)); await Executor.runLoop(argv, jobs, stages, potentialStarters); await Commander.printReport({ cwd: argv.cwd, showTimestamps: argv.showTimestamps, stateDir: argv.stateDir, writeStreams: writeStreams, jobs: jobs, stages: stages, jobNamePad: parser.jobNamePad, }); } static async runJobsInStage(argv, parser, writeStreams) { const jobs = parser.jobs.filter(j => j.stage === argv.stage); const stages = parser.stages; let potentialStarters = [...jobs.values()]; potentialStarters = potentialStarters.filter(j => j.when !== "never"); potentialStarters = potentialStarters.filter(j => j.when !== "manual" || argv.manual.includes(j.name)); potentialStarters = potentialStarters.filter(j => j.stage === argv.stage); await Executor.runLoop(argv, jobs, stages, potentialStarters); await Commander.printReport({ cwd: argv.cwd, showTimestamps: argv.showTimestamps, stateDir: argv.stateDir, writeStreams: writeStreams, jobs: jobs, stages: stages, jobNamePad: parser.jobNamePad, }); } static async runJobs(argv, parser, writeStreams) { const needs = argv.needs || argv.onlyNeeds; const jobArgs = argv.job; const jobs = parser.jobs; const stages = parser.stages; const potentialStarters = []; const jobSet = needs ? new Set(jobs) : new Set(); jobArgs.forEach(jobArgName => { const baseJobs = jobs.filter(j => j.baseName == jobArgName || j.name === jobArgName); for (const b of baseJobs) { jobSet.add(b); if (needs) { potentialStarters.push(...Executor.getPastToWaitFor(jobs, stages, b, argv.manual)); } potentialStarters.push(b); } }); if (potentialStarters.length === 0) { throw new AssertionError({ message: chalk `{blueBright ${jobArgs.join(",")}} could not be found` }); } const starters = argv.onlyNeeds ? potentialStarters.filter(p => !jobArgs.includes(p.name)) : potentialStarters; await Executor.runLoop(argv, Array.from(jobSet), stages, starters); await Commander.printReport({ cwd: argv.cwd, showTimestamps: argv.showTimestamps, stateDir: argv.stateDir, writeStreams: writeStreams, jobs: jobs, stages: stages, jobNamePad: parser.jobNamePad, }); } static async printReport({ cwd, stateDir, showTimestamps, writeStreams, jobs, stages, jobNamePad }) { writeStreams.stdout("\n"); const renderDuration = (duration) => showTimestamps ? ` [${duration.padStart(7)}]` : ""; const preScripts = { successful: [], failed: [], warned: [], }; const afterScripts = { warned: [], }; for (const job of jobs.values()) { if (job.started && job.afterScriptsExitCode !== 0) { afterScripts.warned.push(job); } } for (const job of jobs.values()) { if (!job.started) { continue; } if (job.jobStatus === "success") { preScripts.successful.push(job); } else if (job.jobStatus === "warning") { preScripts.warned.push(job); } else { preScripts.failed.push(job); } } if (preScripts.successful.length !== 0) { preScripts.successful.sort((a, b) => stages.indexOf(a.stage) - stages.indexOf(b.stage)); preScripts.successful.forEach(({ argv, coveragePercent, name, prettyDuration }) => { let prefix = ""; if (argv.childPipelineDepth > 0) prefix = `[${argv.variable.GCL_TRIGGERER}] -> `; const namePad = name.padEnd(jobNamePad); writeStreams.stdout(chalk `{black.bgGreenBright PASS }${renderDuration(prettyDuration)} {blueBright ${prefix}${namePad}}`); if (coveragePercent) { writeStreams.stdout(chalk ` ${coveragePercent}% {grey coverage}`); } writeStreams.stdout("\n"); }); } if (preScripts.warned.length !== 0) { preScripts.warned.sort((a, b) => stages.indexOf(a.stage) - stages.indexOf(b.stage)); for (const { name, prettyDuration } of preScripts.warned) { const namePad = name.padEnd(jobNamePad); const safeName = Utils.safeDockerString(name); writeStreams.stdout(chalk `{black.bgYellowBright WARN }${renderDuration(prettyDuration)} {blueBright ${namePad}} pre_script\n`); const outputLog = await fs.readFile(`${cwd}/${stateDir}/output/${safeName}.log`, "utf8"); for (const line of outputLog.split(/\r?\n/).filter(j => !j.includes("[32m$ ")).filter(j => j !== "").slice(-3)) { writeStreams.stdout(chalk ` {yellow >} ${line}\n`); } } } if (afterScripts.warned.length !== 0) { afterScripts.warned.sort((a, b) => stages.indexOf(a.stage) - stages.indexOf(b.stage)); afterScripts.warned.forEach(({ name, prettyDuration }) => { const namePad = name.padEnd(jobNamePad); writeStreams.stdout(chalk `{black.bgYellowBright WARN }${renderDuration(prettyDuration)} {blueBright ${namePad}} after_script\n`); }); } if (preScripts.failed.length !== 0) { preScripts.failed.sort((a, b) => stages.indexOf(a.stage) - stages.indexOf(b.stage)); for (const { name, prettyDuration } of preScripts.failed) { const namePad = name.padEnd(jobNamePad); const safeName = Utils.safeDockerString(name); writeStreams.stdout(chalk `{black.bgRed FAIL }${renderDuration(prettyDuration)} {blueBright ${namePad}}\n`); const outputLog = await fs.readFile(`${cwd}/${stateDir}/output/${safeName}.log`, "utf8"); for (const line of outputLog.split(/\r?\n/).filter(j => !j.includes("[32m$ ")).filter(j => j !== "").slice(-3)) { writeStreams.stdout(chalk ` {red >} ${line}\n`); } } } for (const job of preScripts.successful) { const e = job.environment; if (e == null) { continue; } const name = e.name; const url = e.url; writeStreams.stdout(chalk `{blueBright ${job.name}} environment: \{ name: {bold ${name}}`); if (url != null) { writeStreams.stdout(chalk `, url: {bold ${url}}`); } writeStreams.stdout(" }\n"); } } static runList(parser, writeStreams, listAll) { const stages = parser.stages; let jobs = [...parser.jobs.values()]; jobs.sort((a, b) => { return stages.indexOf(a.stage) - stages.indexOf(b.stage); }); let whenPadEnd = 4; jobs.forEach(j => whenPadEnd = Math.max(j.when.length, whenPadEnd)); let stagePadEnd = 5; stages.forEach(s => stagePadEnd = Math.max(s.length, stagePadEnd)); let descriptionPadEnd = 11; jobs.forEach(j => descriptionPadEnd = Math.max(j.description.length, descriptionPadEnd)); const jobNamePad = parser.jobNamePad; if (!listAll) { jobs = jobs.filter(j => j.when !== "never"); } writeStreams.stdout(chalk `{grey ${"name".padEnd(jobNamePad)} ${"description".padEnd(descriptionPadEnd)}} `); writeStreams.stdout(chalk `{grey ${"stage".padEnd(stagePadEnd)} ${"when".padEnd(whenPadEnd)}} `); writeStreams.stdout(chalk `{grey allow_failure needs}\n`); const renderLine = (job) => { const needs = job.needs?.filter(n => !n.project && !n.pipeline).map(n => n.job); const allowFailure = job.allowFailure ? "true " : "false "; let jobLine = chalk `{blueBright ${job.name.padEnd(jobNamePad)}} ${job.description.padEnd(descriptionPadEnd)} `; jobLine += chalk `{yellow ${job.stage.padEnd(stagePadEnd)}} ${job.when.padEnd(whenPadEnd)} ${allowFailure.padEnd(11)}`; if (needs) { jobLine += chalk ` [{blueBright ${needs}}]`; } writeStreams.stdout(`${jobLine}\n`); }; jobs.forEach((job) => renderLine(job)); } static runJson(parser, writeStreams) { const jobs = [...parser.jobs.values()]; const json = []; jobs.forEach((job) => { json.push({ name: job.name, description: job.description, stage: job.stage, when: job.when, allow_failure: job.allowFailure, needs: job.needs?.filter(n => !n.project && !n.pipeline), ...job.rules ? { rules: job.rules } : {}, }); }); writeStreams.stdout(`${JSON.stringify(json, null, 2)}\n`); } static runCsv(parser, writeStreams, all) { const stages = parser.stages; let jobs = [...parser.jobs.values()]; jobs.sort((a, b) => { return stages.indexOf(a.stage) - stages.indexOf(b.stage); }); if (!all) { jobs = jobs.filter(j => j.when !== "never"); } writeStreams.stdout("name;description;stage;when;allowFailure;needs\n"); jobs.forEach((job) => { const needs = job.needs?.filter(n => !n.project && !n.pipeline).map(n => n.job).join(",") ?? []; writeStreams.stdout(`${job.name};"${job.description}";${job.stage};${job.when};${job.allowFailure ? "true" : "false"};[${needs}]\n`); }); } static validateDependencyChain(parser) { const allJobs = parser.jobs; // This is only the jobs that will actually run const activeJobs = allJobs.filter(j => j.when !== "never"); const stages = parser.stages; // This will throw an assertion errror if the dependency chain is broken due to needs keyword on specific events without having to run the full pipeline Executor.getStartCandidates(allJobs, stages, activeJobs, []); const activeJobNames = new Set(activeJobs.map(job => job.name)); // This willl throw an assertion error if the dependency chain is broken due to dependencies keyword (a job depending on artifacts from a job that will never run) without having to run the full pipeline for (const job of activeJobs) { if (job.dependencies) { for (const dependency of job.dependencies) { if (!activeJobNames.has(dependency)) { throw new AssertionError({ message: chalk `{blueBright ${dependency}} is when:never, but its depended on by {blueBright ${job.name}}` }); } } } } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWFuZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29tbWFuZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUcxQixPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBRWpDLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDdkMsT0FBTyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRTFCLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFFdEMsTUFBTSxPQUFPLFNBQVM7SUFFbEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUUsSUFBVSxFQUFFLE1BQWMsRUFBRSxZQUEwQjtRQUM1RSxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQ3pCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFFN0IsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDM0MsaUJBQWlCLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxPQUFPLENBQUMsQ0FBQztRQUN0RSxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN2RyxNQUFNLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUM5RCxNQUFNLFNBQVMsQ0FBQyxXQUFXLENBQUM7WUFDeEIsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO1lB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QUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO3dCQUNsQyxNQUFNLElBQUksY0FBYyxDQUFDLEVBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQSxlQUFlLFVBQVUsdURBQXVELEdBQUcsQ0FBQyxJQUFJLEdBQUcsRUFBQyxDQUFDLENBQUM7b0JBQzFJLENBQUM7Z0JBQ0wsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IHtKb2J9IGZyb20gXCIuL2pvYi5qc1wiO1xuaW1wb3J0IHtQYXJzZXJ9IGZyb20gXCIuL3BhcnNlci5qc1wiO1xuaW1wb3J0IHtVdGlsc30gZnJvbSBcIi4vdXRpbHMuanNcIjtcbmltcG9ydCB7V3JpdGVTdHJlYW1zfSBmcm9tIFwiLi93cml0ZS1zdHJlYW1zLmpzXCI7XG5pbXBvcnQge0V4ZWN1dG9yfSBmcm9tIFwiLi9leGVjdXRvci5qc1wiO1xuaW1wb3J0IGZzIGZyb20gXCJmcy1leHRyYVwiO1xuaW1wb3J0IHtBcmd2fSBmcm9tIFwiLi9hcmd2LmpzXCI7XG5pbXBvcnQge0Fzc2VydGlvbkVycm9yfSBmcm9tIFwiYXNzZXJ0XCI7XG5cbmV4cG9ydCBjbGFzcyBDb21tYW5kZXIge1xuXG4gICAgc3RhdGljIGFzeW5jIHJ1blBpcGVsaW5lIChhcmd2OiBBcmd2LCBwYXJzZXI6IFBhcnNlciwgd3JpdGVTdHJlYW1zOiBXcml0ZVN0cmVhbXMpIHtcbiAgICAgICAgY29uc3Qgam9icyA9IHBhcnNlci5qb2JzO1xuICAgICAgICBjb25zdCBzdGFnZXMgPSBwYXJzZXIuc3RhZ2VzO1xuXG4gICAgICAgIGxldCBwb3RlbnRpYWxTdGFydGVycyA9IFsuLi5qb2JzLnZhbHVlcygpXTtcbiAgICAgICAgcG90ZW50aWFsU3RhcnRlcnMgPSBwb3RlbnRpYWxTdGFydGVycy5maWx0ZXIoaiA9PiBqLndoZW4gIT09IFwibmV2ZXJcIik7XG4gICAgICAgIHBvdGVudGlhbFN0YXJ0ZXJzID0gcG90ZW50aWFsU3RhcnRlcnMuZmlsdGVyKGogPT4gai53aGVuICE9PSBcIm1hbnVhbFwiIHx8IGFyZ3YubWFudWFsLmluY2x1ZGVzKGoubmFtZSkpO1xuICAgICAgICBhd2FpdCBFeGVjdXRvci5ydW5Mb29wKGFyZ3YsIGpvYnMsIHN0YWdlcywgcG90ZW50aWFsU3RhcnRlcnMpO1xuICAgICAgICBhd2FpdCBDb21tYW5kZXIucHJpbnRSZXBvcnQoe1xuICAgICAgICAgICAgY3dkOiBhcmd2LmN3ZCxcbiAgICAgICAgICAgIHNob3dUaW1lc3RhbXBzOiBhcmd2LnNob3dUaW1lc3RhbXBzLFxuICAgICAgICAgICAgc3RhdGVEaXI6IGFyZ3Yuc3RhdGVEaXIsXG4gICAgICAgICAgICB3cml0ZVN0cmVhbXM6IHdyaXRlU3RyZWFtcyxcbiAgICAgICAgICAgIGpvYnM6IGpvYnMsXG4gICAgICAgICAgICBzdGFnZXM6IHN0YWdlcyxcbiAgICAgICAgICAgIGpvYk5hbWVQYWQ6IHBhcnNlci5qb2JOYW1lUGFkLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgYXN5bmMgcnVuSm9ic0luU3RhZ2UgKGFyZ3Y6IEFyZ3YsIHBhcnNlcjogUGFyc2VyLCB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcykge1xuICAgICAgICBjb25zdCBqb2JzID0gcGFyc2VyLmpvYnMuZmlsdGVyKGogPT4gai5zdGFnZSA9PT0gYXJndi5zdGFnZSk7XG4gICAgICAgIGNvbnN0IHN0YWdlcyA9IHBhcnNlci5zdGFnZXM7XG5cbiAgICAgICAgbGV0IHBvdGVudGlhbFN0YXJ0ZXJzID0gWy4uLmpvYnMudmFsdWVzKCldO1xuICAgICAgICBwb3RlbnRpYWxTdGFydGVycyA9IHBvdGVudGlhbFN0YXJ0ZXJzLmZpbHRlcihqID0+IGoud2hlbiAhPT0gXCJuZXZlclwiKTtcbiAgICAgICAgcG90ZW50aWFsU3RhcnRlcnMgPSBwb3RlbnRpYWxTdGFydGVycy5maWx0ZXIoaiA9PiBqLndoZW4gIT09IFwibWFudWFsXCIgfHwgYXJndi5tYW51YWwuaW5jbHVkZXMoai5uYW1lKSk7XG4gICAgICAgIHBvdGVudGlhbFN0YXJ0ZXJzID0gcG90ZW50aWFsU3RhcnRlcnMuZmlsdGVyKGogPT4gai5zdGFnZSA9PT0gYXJndi5zdGFnZSk7XG4gICAgICAgIGF3YWl0IEV4ZWN1dG9yLnJ1bkxvb3AoYXJndiwgam9icywgc3RhZ2VzLCBwb3RlbnRpYWxTdGFydGVycyk7XG4gICAgICAgIGF3YWl0IENvbW1hbmRlci5wcmludFJlcG9ydCh7XG4gICAgICAgICAgICBjd2Q6IGFyZ3YuY3dkLFxuICAgICAgICAgICAgc2hvd1RpbWVzdGFtcHM6IGFyZ3Yuc2hvd1RpbWVzdGFtcHMsXG4gICAgICAgICAgICBzdGF0ZURpcjogYXJndi5zdGF0ZURpcixcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtczogd3JpdGVTdHJlYW1zLFxuICAgICAgICAgICAgam9iczogam9icyxcbiAgICAgICAgICAgIHN0YWdlczogc3RhZ2VzLFxuICAgICAgICAgICAgam9iTmFtZVBhZDogcGFyc2VyLmpvYk5hbWVQYWQsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBydW5Kb2JzIChhcmd2OiBBcmd2LCBwYXJzZXI6IFBhcnNlciwgd3JpdGVTdHJlYW1zOiBXcml0ZVN0cmVhbXMpIHtcbiAgICAgICAgY29uc3QgbmVlZHMgPSBhcmd2Lm5lZWRzIHx8IGFyZ3Yub25seU5lZWRzO1xuICAgICAgICBjb25zdCBqb2JBcmdzID0gYXJndi5qb2I7XG4gICAgICAgIGNvbnN0IGpvYnMgPSBwYXJzZXIuam9icztcbiAgICAgICAgY29uc3Qgc3RhZ2VzID0gcGFyc2VyLnN0YWdlcztcblxuICAgICAgICBjb25zdCBwb3RlbnRpYWxTdGFydGVyczogSm9iW10gPSBbXTtcbiAgICAgICAgY29uc3Qgam9iU2V0ID0gbmVlZHMgPyBuZXcgU2V0KGpvYnMpIDogbmV3IFNldDxKb2I+KCk7XG4gICAgICAgIGpvYkFyZ3MuZm9yRWFjaChqb2JBcmdOYW1lID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJhc2VKb2JzID0gam9icy5maWx0ZXIoaiA9PiBqLmJhc2VOYW1lID09IGpvYkFyZ05hbWUgfHwgai5uYW1lID09PSBqb2JBcmdOYW1lKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYiBvZiBiYXNlSm9icykge1xuICAgICAgICAgICAgICAgIGpvYlNldC5hZGQoYik7XG4gICAgICAgICAgICAgICAgaWYgKG5lZWRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvdGVudGlhbFN0YXJ0ZXJzLnB1c2goLi4uRXhlY3V0b3IuZ2V0UGFzdFRvV2FpdEZvcihqb2JzLCBzdGFnZXMsIGIsIGFyZ3YubWFudWFsKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBvdGVudGlhbFN0YXJ0ZXJzLnB1c2goYik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChwb3RlbnRpYWxTdGFydGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogY2hhbGtge2JsdWVCcmlnaHQgJHtqb2JBcmdzLmpvaW4oXCIsXCIpfX0gY291bGQgbm90IGJlIGZvdW5kYH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3RhcnRlcnMgPSBhcmd2Lm9ubHlOZWVkcyA/XG4gICAgICAgICAgICBwb3RlbnRpYWxTdGFydGVycy5maWx0ZXIocCA9PiAham9iQXJncy5pbmNsdWRlcyhwLm5hbWUpKSA6XG4gICAgICAgICAgICBwb3RlbnRpYWxTdGFydGVycztcblxuICAgICAgICBhd2FpdCBFeGVjdXRvci5ydW5Mb29wKGFyZ3YsIEFycmF5LmZyb20oam9iU2V0KSwgc3RhZ2VzLCBzdGFydGVycyk7XG4gICAgICAgIGF3YWl0IENvbW1hbmRlci5wcmludFJlcG9ydCh7XG4gICAgICAgICAgICBjd2Q6IGFyZ3YuY3dkLFxuICAgICAgICAgICAgc2hvd1RpbWVzdGFtcHM6IGFyZ3Yuc2hvd1RpbWVzdGFtcHMsXG4gICAgICAgICAgICBzdGF0ZURpcjogYXJndi5zdGF0ZURpcixcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtczogd3JpdGVTdHJlYW1zLFxuICAgICAgICAgICAgam9iczogam9icyxcbiAgICAgICAgICAgIHN0YWdlczogc3RhZ2VzLFxuICAgICAgICAgICAgam9iTmFtZVBhZDogcGFyc2VyLmpvYk5hbWVQYWQsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBwcmludFJlcG9ydCAoe2N3ZCwgc3RhdGVEaXIsIHNob3dUaW1lc3RhbXBzLCB3cml0ZVN0cmVhbXMsIGpvYnMsIHN0YWdlcywgam9iTmFtZVBhZH06IHtcbiAgICAgICAgY3dkOiBzdHJpbmc7XG4gICAgICAgIHNob3dUaW1lc3RhbXBzOiBib29sZWFuO1xuICAgICAgICBzdGF0ZURpcjogc3RyaW5nO1xuICAgICAgICB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcztcbiAgICAgICAgam9iczogUmVhZG9ubHlBcnJheTxKb2I+O1xuICAgICAgICBzdGFnZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICAgICAgICBqb2JOYW1lUGFkOiBudW1iZXI7XG4gICAgfSkge1xuXG4gICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoXCJcXG5cIik7XG5cbiAgICAgICAgY29uc3QgcmVuZGVyRHVyYXRpb24gPSAoZHVyYXRpb246IHN0cmluZykgPT4gc2hvd1RpbWVzdGFtcHMgPyBgIFske2R1cmF0aW9uLnBhZFN0YXJ0KDcpfV1gIDogXCJcIjtcblxuICAgICAgICBjb25zdCBwcmVTY3JpcHRzOiB7c3VjY2Vzc2Z1bDogSm9iW107IGZhaWxlZDogSm9iW107IHdhcm5lZDogSm9iW119ID0ge1xuICAgICAgICAgICAgc3VjY2Vzc2Z1bDogW10sXG4gICAgICAgICAgICBmYWlsZWQ6IFtdLFxuICAgICAgICAgICAgd2FybmVkOiBbXSxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgYWZ0ZXJTY3JpcHRzOiB7d2FybmVkOiBKb2JbXX0gPSB7XG4gICAgICAgICAgICB3YXJuZWQ6IFtdLFxuICAgICAgICB9O1xuXG4gICAgICAgIGZvciAoY29uc3Qgam9iIG9mIGpvYnMudmFsdWVzKCkpIHtcbiAgICAgICAgICAgIGlmIChqb2Iuc3RhcnRlZCAmJiBqb2IuYWZ0ZXJTY3JpcHRzRXhpdENvZGUgIT09IDApIHtcbiAgICAgICAgICAgICAgICBhZnRlclNjcmlwdHMud2FybmVkLnB1c2goam9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoY29uc3Qgam9iIG9mIGpvYnMudmFsdWVzKCkpIHtcbiAgICAgICAgICAgIGlmICgham9iLnN0YXJ0ZWQpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGpvYi5qb2JTdGF0dXMgPT09IFwic3VjY2Vzc1wiKSB7XG4gICAgICAgICAgICAgICAgcHJlU2NyaXB0cy5zdWNjZXNzZnVsLnB1c2goam9iKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoam9iLmpvYlN0YXR1cyA9PT0gXCJ3YXJuaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBwcmVTY3JpcHRzLndhcm5lZC5wdXNoKGpvYik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHByZVNjcmlwdHMuZmFpbGVkLnB1c2goam9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwcmVTY3JpcHRzLnN1Y2Nlc3NmdWwubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICBwcmVTY3JpcHRzLnN1Y2Nlc3NmdWwuc29ydCgoYSwgYikgPT4gc3RhZ2VzLmluZGV4T2YoYS5zdGFnZSkgLSBzdGFnZXMuaW5kZXhPZihiLnN0YWdlKSk7XG4gICAgICAgICAgICBwcmVTY3JpcHRzLnN1Y2Nlc3NmdWwuZm9yRWFjaCgoe2FyZ3YsIGNvdmVyYWdlUGVyY2VudCwgbmFtZSwgcHJldHR5RHVyYXRpb259KSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IHByZWZpeCA9IFwiXCI7XG4gICAgICAgICAgICAgICAgaWYgKGFyZ3YuY2hpbGRQaXBlbGluZURlcHRoID4gMCkgcHJlZml4ID0gYFske2FyZ3YudmFyaWFibGUuR0NMX1RSSUdHRVJFUn1dIC0+IGA7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBuYW1lUGFkID0gbmFtZS5wYWRFbmQoam9iTmFtZVBhZCk7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2B7YmxhY2suYmdHcmVlbkJyaWdodCAgUEFTUyB9JHtyZW5kZXJEdXJhdGlvbihwcmV0dHlEdXJhdGlvbil9IHtibHVlQnJpZ2h0ICR7cHJlZml4fSR7bmFtZVBhZH19YCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvdmVyYWdlUGVyY2VudCkge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCAke2NvdmVyYWdlUGVyY2VudH0lIHtncmV5IGNvdmVyYWdlfWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KFwiXFxuXCIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJlU2NyaXB0cy53YXJuZWQubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICBwcmVTY3JpcHRzLndhcm5lZC5zb3J0KChhLCBiKSA9PiBzdGFnZXMuaW5kZXhPZihhLnN0YWdlKSAtIHN0YWdlcy5pbmRleE9mKGIuc3RhZ2UpKTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qge25hbWUsIHByZXR0eUR1cmF0aW9ufSBvZiBwcmVTY3JpcHRzLndhcm5lZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5hbWVQYWQgPSBuYW1lLnBhZEVuZChqb2JOYW1lUGFkKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzYWZlTmFtZSA9IFV0aWxzLnNhZmVEb2NrZXJTdHJpbmcobmFtZSk7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2B7YmxhY2suYmdZZWxsb3dCcmlnaHQgIFdBUk4gfSR7cmVuZGVyRHVyYXRpb24ocHJldHR5RHVyYXRpb24pfSB7Ymx1ZUJyaWdodCAke25hbWVQYWR9fSAgcHJlX3NjcmlwdFxcbmApO1xuICAgICAgICAgICAgICAgIGNvbnN0IG91dHB1dExvZyA9IGF3YWl0IGZzLnJlYWRGaWxlKGAke2N3ZH0vJHtzdGF0ZURpcn0vb3V0cHV0LyR7c2FmZU5hbWV9LmxvZ2AsIFwidXRmOFwiKTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2Ygb3V0cHV0TG9nLnNwbGl0KC9cXHI/XFxuLykuZmlsdGVyKGogPT4gIWouaW5jbHVkZXMoXCJbMzJtJCBcIikpLmZpbHRlcihqID0+IGogIT09IFwiXCIpLnNsaWNlKC0zKSkge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCAge3llbGxvdyA+fSAke2xpbmV9XFxuYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFmdGVyU2NyaXB0cy53YXJuZWQubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICBhZnRlclNjcmlwdHMud2FybmVkLnNvcnQoKGEsIGIpID0+IHN0YWdlcy5pbmRleE9mKGEuc3RhZ2UpIC0gc3RhZ2VzLmluZGV4T2YoYi5zdGFnZSkpO1xuICAgICAgICAgICAgYWZ0ZXJTY3JpcHRzLndhcm5lZC5mb3JFYWNoKCh7bmFtZSwgcHJldHR5RHVyYXRpb259KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmFtZVBhZCA9IG5hbWUucGFkRW5kKGpvYk5hbWVQYWQpO1xuICAgICAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtge2JsYWNrLmJnWWVsbG93QnJpZ2h0ICBXQVJOIH0ke3JlbmRlckR1cmF0aW9uKHByZXR0eUR1cmF0aW9uKX0ge2JsdWVCcmlnaHQgJHtuYW1lUGFkfX0gIGFmdGVyX3NjcmlwdFxcbmApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJlU2NyaXB0cy5mYWlsZWQubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICBwcmVTY3JpcHRzLmZhaWxlZC5zb3J0KChhLCBiKSA9PiBzdGFnZXMuaW5kZXhPZihhLnN0YWdlKSAtIHN0YWdlcy5pbmRleE9mKGIuc3RhZ2UpKTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qge25hbWUsIHByZXR0eUR1cmF0aW9ufSBvZiBwcmVTY3JpcHRzLmZhaWxlZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5hbWVQYWQgPSBuYW1lLnBhZEVuZChqb2JOYW1lUGFkKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzYWZlTmFtZSA9IFV0aWxzLnNhZmVEb2NrZXJTdHJpbmcobmFtZSk7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2B7YmxhY2suYmdSZWQgIEZBSUwgfSR7cmVuZGVyRHVyYXRpb24ocHJldHR5RHVyYXRpb24pfSB7Ymx1ZUJyaWdodCAke25hbWVQYWR9fVxcbmApO1xuICAgICAgICAgICAgICAgIGNvbnN0IG91dHB1dExvZyA9IGF3YWl0IGZzLnJlYWRGaWxlKGAke2N3ZH0vJHtzdGF0ZURpcn0vb3V0cHV0LyR7c2FmZU5hbWV9LmxvZ2AsIFwidXRmOFwiKTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2Ygb3V0cHV0TG9nLnNwbGl0KC9cXHI/XFxuLykuZmlsdGVyKGogPT4gIWouaW5jbHVkZXMoXCJbMzJtJCBcIikpLmZpbHRlcihqID0+IGogIT09IFwiXCIpLnNsaWNlKC0zKSkge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCAge3JlZCA+fSAke2xpbmV9XFxuYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBqb2Igb2YgcHJlU2NyaXB0cy5zdWNjZXNzZnVsKSB7XG4gICAgICAgICAgICBjb25zdCBlID0gam9iLmVudmlyb25tZW50O1xuICAgICAgICAgICAgaWYgKGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbmFtZSA9IGUubmFtZTtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IGUudXJsO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2B7Ymx1ZUJyaWdodCAke2pvYi5uYW1lfX0gZW52aXJvbm1lbnQ6IFxceyBuYW1lOiB7Ym9sZCAke25hbWV9fWApO1xuICAgICAgICAgICAgaWYgKHVybCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2AsIHVybDoge2JvbGQgJHt1cmx9fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChcIiB9XFxuXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIHJ1bkxpc3QgKHBhcnNlcjogUGFyc2VyLCB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcywgbGlzdEFsbDogYm9vbGVhbikge1xuICAgICAgICBjb25zdCBzdGFnZXMgPSBwYXJzZXIuc3RhZ2VzO1xuICAgICAgICBsZXQgam9icyA9IFsuLi5wYXJzZXIuam9icy52YWx1ZXMoKV07XG4gICAgICAgIGpvYnMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHN0YWdlcy5pbmRleE9mKGEuc3RhZ2UpIC0gc3RhZ2VzLmluZGV4T2YoYi5zdGFnZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCB3aGVuUGFkRW5kID0gNDtcbiAgICAgICAgam9icy5mb3JFYWNoKGogPT4gd2hlblBhZEVuZCA9IE1hdGgubWF4KGoud2hlbi5sZW5ndGgsIHdoZW5QYWRFbmQpKTtcblxuICAgICAgICBsZXQgc3RhZ2VQYWRFbmQgPSA1O1xuICAgICAgICBzdGFnZXMuZm9yRWFjaChzID0+IHN0YWdlUGFkRW5kID0gTWF0aC5tYXgocy5sZW5ndGgsIHN0YWdlUGFkRW5kKSk7XG5cbiAgICAgICAgbGV0IGRlc2NyaXB0aW9uUGFkRW5kID0gMTE7XG4gICAgICAgIGpvYnMuZm9yRWFjaChqID0+IGRlc2NyaXB0aW9uUGFkRW5kID0gTWF0aC5tYXgoai5kZXNjcmlwdGlvbi5sZW5ndGgsIGRlc2NyaXB0aW9uUGFkRW5kKSk7XG5cbiAgICAgICAgY29uc3Qgam9iTmFtZVBhZCA9IHBhcnNlci5qb2JOYW1lUGFkO1xuXG4gICAgICAgIGlmICghbGlzdEFsbCkge1xuICAgICAgICAgICAgam9icyA9IGpvYnMuZmlsdGVyKGogPT4gai53aGVuICE9PSBcIm5ldmVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2B7Z3JleSAke1wibmFtZVwiLnBhZEVuZChqb2JOYW1lUGFkKX0gICR7XCJkZXNjcmlwdGlvblwiLnBhZEVuZChkZXNjcmlwdGlvblBhZEVuZCl9fSAgYCk7XG4gICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtge2dyZXkgJHtcInN0YWdlXCIucGFkRW5kKHN0YWdlUGFkRW5kKX0gICR7XCJ3aGVuXCIucGFkRW5kKHdoZW5QYWRFbmQpfX0gIGApO1xuICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYHtncmV5IGFsbG93X2ZhaWx1cmUgIG5lZWRzfVxcbmApO1xuXG4gICAgICAgIGNvbnN0IHJlbmRlckxpbmUgPSAoam9iOiBKb2IpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5lZWRzID0gam9iLm5lZWRzPy5maWx0ZXIobiA9PiAhbi5wcm9qZWN0ICYmICFuLnBpcGVsaW5lKS5tYXAobiA9PiBuLmpvYik7XG4gICAgICAgICAgICBjb25zdCBhbGxvd0ZhaWx1cmUgPSBqb2IuYWxsb3dGYWlsdXJlID8gXCJ0cnVlIFwiIDogXCJmYWxzZSBcIjtcbiAgICAgICAgICAgIGxldCBqb2JMaW5lID0gY2hhbGtge2JsdWVCcmlnaHQgJHtqb2IubmFtZS5wYWRFbmQoam9iTmFtZVBhZCl9fSAgJHtqb2IuZGVzY3JpcHRpb24ucGFkRW5kKGRlc2NyaXB0aW9uUGFkRW5kKX0gIGA7XG4gICAgICAgICAgICBqb2JMaW5lICs9IGNoYWxrYHt5ZWxsb3cgJHtqb2Iuc3RhZ2UucGFkRW5kKHN0YWdlUGFkRW5kKX19ICAke2pvYi53aGVuLnBhZEVuZCh3aGVuUGFkRW5kKX0gICR7YWxsb3dGYWlsdXJlLnBhZEVuZCgxMSl9YDtcbiAgICAgICAgICAgIGlmIChuZWVkcykge1xuICAgICAgICAgICAgICAgIGpvYkxpbmUgKz0gY2hhbGtgICAgIFt7Ymx1ZUJyaWdodCAke25lZWRzfX1dYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoYCR7am9iTGluZX1cXG5gKTtcbiAgICAgICAgfTtcblxuICAgICAgICBqb2JzLmZvckVhY2goKGpvYikgPT4gcmVuZGVyTGluZShqb2IpKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgcnVuSnNvbiAocGFyc2VyOiBQYXJzZXIsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKSB7XG4gICAgICAgIGNvbnN0IGpvYnMgPSBbLi4ucGFyc2VyLmpvYnMudmFsdWVzKCldO1xuICAgICAgICBjb25zdCBqc29uOiBhbnlbXSA9IFtdO1xuXG4gICAgICAgIGpvYnMuZm9yRWFjaCgoam9iKSA9PiB7XG4gICAgICAgICAgICBqc29uLnB1c2goe1xuICAgICAgICAgICAgICAgIG5hbWU6IGpvYi5uYW1lLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBqb2IuZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgc3RhZ2U6IGpvYi5zdGFnZSxcbiAgICAgICAgICAgICAgICB3aGVuOiBqb2Iud2hlbixcbiAgICAgICAgICAgICAgICBhbGxvd19mYWlsdXJlOiBqb2IuYWxsb3dGYWlsdXJlLFxuICAgICAgICAgICAgICAgIG5lZWRzOiBqb2IubmVlZHM/LmZpbHRlcihuID0+ICFuLnByb2plY3QgJiYgIW4ucGlwZWxpbmUpLFxuICAgICAgICAgICAgICAgIC4uLmpvYi5ydWxlcyA/IHtydWxlczogam9iLnJ1bGVzfSA6IHt9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoYCR7SlNPTi5zdHJpbmdpZnkoanNvbiwgbnVsbCwgMil9XFxuYCk7XG4gICAgfVxuXG4gICAgc3RhdGljIHJ1bkNzdiAocGFyc2VyOiBQYXJzZXIsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBhbGw6IGJvb2xlYW4pIHtcbiAgICAgICAgY29uc3Qgc3RhZ2VzID0gcGFyc2VyLnN0YWdlcztcbiAgICAgICAgbGV0IGpvYnMgPSBbLi4ucGFyc2VyLmpvYnMudmFsdWVzKCldO1xuICAgICAgICBqb2JzLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBzdGFnZXMuaW5kZXhPZihhLnN0YWdlKSAtIHN0YWdlcy5pbmRleE9mKGIuc3RhZ2UpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoIWFsbCkge1xuICAgICAgICAgICAgam9icyA9IGpvYnMuZmlsdGVyKGogPT4gai53aGVuICE9PSBcIm5ldmVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChcIm5hbWU7ZGVzY3JpcHRpb247c3RhZ2U7d2hlbjthbGxvd0ZhaWx1cmU7bmVlZHNcXG5cIik7XG4gICAgICAgIGpvYnMuZm9yRWFjaCgoam9iKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBuZWVkcyA9IGpvYi5uZWVkcz8uZmlsdGVyKG4gPT4gIW4ucHJvamVjdCAmJiAhbi5waXBlbGluZSkubWFwKG4gPT4gbi5qb2IpLmpvaW4oXCIsXCIpID8/IFtdO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChgJHtqb2IubmFtZX07XCIke2pvYi5kZXNjcmlwdGlvbn1cIjske2pvYi5zdGFnZX07JHtqb2Iud2hlbn07JHtqb2IuYWxsb3dGYWlsdXJlID8gXCJ0cnVlXCIgOiBcImZhbHNlXCJ9O1ske25lZWRzfV1cXG5gKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3RhdGljIHZhbGlkYXRlRGVwZW5kZW5jeUNoYWluIChwYXJzZXI6IFBhcnNlcikge1xuICAgICAgICBjb25zdCBhbGxKb2JzID0gcGFyc2VyLmpvYnM7XG4gICAgICAgIC8vIFRoaXMgaXMgb25seSB0aGUgam9icyB0aGF0IHdpbGwgYWN0dWFsbHkgcnVuXG4gICAgICAgIGNvbnN0IGFjdGl2ZUpvYnMgPSBhbGxKb2JzLmZpbHRlcihqID0+IGoud2hlbiAhPT0gXCJuZXZlclwiKTtcbiAgICAgICAgY29uc3Qgc3RhZ2VzID0gcGFyc2VyLnN0YWdlcztcbiAgICAgICAgLy8gVGhpcyB3aWxsIHRocm93IGFuIGFzc2VydGlvbiBlcnJyb3IgaWYgdGhlIGRlcGVuZGVuY3kgY2hhaW4gaXMgYnJva2VuIGR1ZSB0byBuZWVkcyBrZXl3b3JkIG9uIHNwZWNpZmljIGV2ZW50cyB3aXRob3V0IGhhdmluZyB0byBydW4gdGhlIGZ1bGwgcGlwZWxpbmVcbiAgICAgICAgRXhlY3V0b3IuZ2V0U3RhcnRDYW5kaWRhdGVzKGFsbEpvYnMsIHN0YWdlcywgYWN0aXZlSm9icywgW10pO1xuXG4gICAgICAgIGNvbnN0IGFjdGl2ZUpvYk5hbWVzID0gbmV3IFNldChhY3RpdmVKb2JzLm1hcChqb2IgPT4gam9iLm5hbWUpKTtcbiAgICAgICAgLy8gVGhpcyB3aWxsbCB0aHJvdyBhbiBhc3NlcnRpb24gZXJyb3IgaWYgdGhlIGRlcGVuZGVuY3kgY2hhaW4gaXMgYnJva2VuIGR1ZSB0byBkZXBlbmRlbmNpZXMga2V5d29yZCAoYSBqb2IgZGVwZW5kaW5nIG9uIGFydGlmYWN0cyBmcm9tIGEgam9iIHRoYXQgd2lsbCBuZXZlciBydW4pIHdpdGhvdXQgaGF2aW5nIHRvIHJ1biB0aGUgZnVsbCBwaXBlbGluZVxuICAgICAgICBmb3IgKGNvbnN0IGpvYiBvZiBhY3RpdmVKb2JzKSB7XG4gICAgICAgICAgICBpZiAoam9iLmRlcGVuZGVuY2llcykge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBqb2IuZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghYWN0aXZlSm9iTmFtZXMuaGFzKGRlcGVuZGVuY3kpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3Ioe21lc3NhZ2U6IGNoYWxrYHtibHVlQnJpZ2h0ICR7ZGVwZW5kZW5jeX19IGlzIHdoZW46bmV2ZXIsIGJ1dCBpdHMgZGVwZW5kZWQgb24gYnkge2JsdWVCcmlnaHQgJHtqb2IubmFtZX19YH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuIl19