gitlab-ci-local
Version:
Tired of pushing to test your .gitlab-ci.yml?
143 lines • 29.6 kB
JavaScript
import fs from "fs-extra";
import * as yaml from "js-yaml";
import chalk from "chalk";
import assert from "assert";
import { Utils } from "./utils.js";
import dotenv from "dotenv";
import deepExtend from "deep-extend";
export class VariablesFromFiles {
static async init(argv, writeStreams, gitData) {
const cwd = argv.cwd;
const stateDir = argv.stateDir;
const homeDir = argv.home;
const remoteVariables = argv.remoteVariables;
const autoCompleting = argv.autoCompleting;
const homeVariablesFile = `${homeDir}/${stateDir}/variables.yml`;
const variables = {};
let remoteFileData = {};
let homeFileData = {};
if (remoteVariables && !autoCompleting) {
for (let i = 0; i < remoteVariables.length; i++) {
const match = /(?<url>git@.*?)=(?<file>.*?)=(?<ref>.*)/.exec(remoteVariables[i]);
assert(match != null, "--remote-variables is malformed use 'git@gitlab.com:firecow/example.git=gitlab-variables.yml=master' syntax");
const url = match.groups?.url;
const file = match.groups?.file;
const ref = match.groups?.ref;
const res = await Utils.bash(`set -eou pipefail; git archive --remote=${url} ${ref} ${file} | tar -xO ${file}`, cwd);
const loadedYaml = yaml.load(`${res.stdout}`);
// Check if loadedYaml is an object
if (typeof loadedYaml === "object" && loadedYaml !== null) {
remoteFileData = deepExtend(remoteFileData, loadedYaml);
}
}
}
if (await fs.pathExists(homeVariablesFile)) {
homeFileData = yaml.load(await fs.readFile(homeVariablesFile, "utf8"), { schema: yaml.FAILSAFE_SCHEMA });
}
const unpack = (v) => {
if (typeof v === "string") {
const catchAll = { values: {}, type: null };
catchAll.values = {};
catchAll.values["*"] = v;
return catchAll;
}
else {
v.type = v.type ?? "variable";
}
return v;
};
const addToVariables = async (key, val, scopePriority, isDotEnv = false) => {
const { type, values } = unpack(val);
for (const [matcher, content] of Object.entries(values)) {
assert(typeof content == "string", `${key}.${matcher} content must be text or multiline text`);
if (isDotEnv || type === "variable" || (type === null && !/^[/~]/.exec(content))) {
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replace(/\*/g, ".*")}$`, "g");
variables[key] = variables[key] ?? { type: "variable", environments: [] };
variables[key].environments.push({ content, regexp, regexpPriority: matcher.length, scopePriority });
}
else if (type === null && /^[/~]/.exec(content)) {
const fileSource = content.replace(/^~\/(.*)/, `${homeDir}/$1`);
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replace(/\*/g, ".*")}$`, "g");
variables[key] = variables[key] ?? { type: "file", environments: [] };
if (fs.existsSync(fileSource)) {
variables[key].environments.push({ content, regexp, regexpPriority: matcher.length, scopePriority, fileSource });
}
else {
variables[key].environments.push({ content: `warn: ${key} is pointing to invalid path\n`, regexp, regexpPriority: matcher.length, scopePriority });
}
}
else if (type === "file") {
const regexp = matcher === "*" ? /.*/g : new RegExp(`^${matcher.replace(/\*/g, ".*")}$`, "g");
variables[key] = variables[key] ?? { type: "file", environments: [] };
variables[key].environments.push({ content, regexp, regexpPriority: matcher.length, scopePriority });
}
else {
assert(false, `${key} was not handled properly`);
}
}
};
const addVariableFileToVariables = async (fileData, filePriority) => {
for (const [globalKey, globalEntry] of Object.entries(fileData?.global ?? {})) {
await addToVariables(globalKey, globalEntry, 1 + filePriority);
}
const groupUrl = `${gitData.remote.host}/${gitData.remote.group}/`;
for (const [groupKey, groupEntries] of Object.entries(fileData?.group ?? {})) {
if (!groupUrl.includes(this.normalizeProjectKey(groupKey, writeStreams)))
continue;
assert(groupEntries != null, "groupEntries cannot be null/undefined");
assert(Utils.isObject(groupEntries), "group entries in variable files must be an object");
for (const [k, v] of Object.entries(groupEntries)) {
await addToVariables(k, v, 2 + filePriority);
}
}
const projectUrl = `${gitData.remote.host}/${gitData.remote.group}/${gitData.remote.project}.git`;
for (const [projectKey, projectEntries] of Object.entries(fileData?.project ?? [])) {
if (!projectUrl.includes(this.normalizeProjectKey(projectKey, writeStreams)))
continue;
assert(projectEntries != null, "projectEntries cannot be null/undefined");
assert(Utils.isObject(projectEntries), "project entries in variable files must be an object");
for (const [k, v] of Object.entries(projectEntries)) {
await addToVariables(k, v, 3 + filePriority);
}
}
};
await addVariableFileToVariables(remoteFileData, 0);
await addVariableFileToVariables(homeFileData, 10);
const projectVariablesFile = `${argv.cwd}/${argv.variablesFile}`;
if (fs.existsSync(projectVariablesFile)) {
let isDotEnvFormat = false;
const projectVariablesFileRawContent = await fs.readFile(projectVariablesFile, "utf8");
let projectVariablesFileData;
try {
projectVariablesFileData = yaml.load(projectVariablesFileRawContent, { schema: yaml.FAILSAFE_SCHEMA }) ?? {};
if (typeof (projectVariablesFileData) === "string") {
isDotEnvFormat = true;
projectVariablesFileData = dotenv.parse(projectVariablesFileRawContent);
}
}
catch (e) {
if (e instanceof yaml.YAMLException) {
isDotEnvFormat = true;
projectVariablesFileData = dotenv.parse(projectVariablesFileRawContent);
}
}
assert(projectVariablesFileData != null, "projectEntries cannot be null/undefined");
assert(Utils.isObject(projectVariablesFileData), `${argv.cwd}/.gitlab-ci-local-variables.yml must contain an object`);
for (const [k, v] of Object.entries(projectVariablesFileData)) {
await addToVariables(k, v, 24, isDotEnvFormat);
}
}
for (const varObj of Object.values(variables)) {
varObj.environments.sort((a, b) => b.scopePriority - a.scopePriority);
varObj.environments.sort((a, b) => b.regexpPriority - a.regexpPriority);
}
return variables;
}
static normalizeProjectKey(key, writeStreams) {
if (!key.includes(":"))
return key;
writeStreams.stderr(chalk `{yellow WARNING: Interpreting '${key}' as '${key.replace(":", "/")}'}\n`);
return key.replace(":", "/");
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFyaWFibGVzLWZyb20tZmlsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ2YXJpYWJsZXMtZnJvbS1maWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDMUIsT0FBTyxLQUFLLElBQUksTUFBTSxTQUFTLENBQUM7QUFDaEMsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBRTFCLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ2pDLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLFVBQVUsTUFBTSxhQUFhLENBQUM7QUFhckMsTUFBTSxPQUFPLGtCQUFrQjtJQUUzQixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBRSxJQUFVLEVBQUUsWUFBMEIsRUFBRSxPQUFnQjtRQUN2RSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ3JCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDL0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUMxQixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQzdDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUM7UUFDM0MsTUFBTSxpQkFBaUIsR0FBRyxHQUFHLE9BQU8sSUFBSSxRQUFRLGdCQUFnQixDQUFDO1FBQ2pFLE1BQU0sU0FBUyxHQUFtQyxFQUFFLENBQUM7UUFDckQsSUFBSSxjQUFjLEdBQVEsRUFBRSxDQUFDO1FBQzdCLElBQUksWUFBWSxHQUFRLEVBQUUsQ0FBQztRQUUzQixJQUFJLGVBQWUsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3JDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQzlDLE1BQU0sS0FBSyxHQUFHLHlDQUF5QyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDakYsTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJLEVBQUUsNkdBQTZHLENBQUMsQ0FBQztnQkFDckksTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUM7Z0JBQzlCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDO2dCQUNoQyxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQztnQkFDOUIsTUFBTSxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxHQUFHLElBQUksR0FBRyxJQUFJLElBQUksY0FBYyxJQUFJLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDckgsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO2dCQUM5QyxtQ0FBbUM7Z0JBQ25DLElBQUksT0FBTyxVQUFVLEtBQUssUUFBUSxJQUFJLFVBQVUsS0FBSyxJQUFJLEVBQUUsQ0FBQztvQkFDeEQsY0FBYyxHQUFHLFVBQVUsQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQzVELENBQUM7WUFDTCxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztZQUN6QyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGVBQWUsRUFBQyxDQUFDLENBQUM7UUFDM0csQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBTSxFQUFtRCxFQUFFO1lBQ3ZFLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3hCLE1BQU0sUUFBUSxHQUFvRCxFQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBQyxDQUFDO2dCQUMzRixRQUFRLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztnQkFDckIsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3pCLE9BQU8sUUFBUSxDQUFDO1lBQ3BCLENBQUM7aUJBQU0sQ0FBQztnQkFDSixDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxJQUFJLElBQUksVUFBVSxDQUFDO1lBQ2xDLENBQUM7WUFDRCxPQUFPLENBQUMsQ0FBQztRQUNiLENBQUMsQ0FBQztRQUNGLE1BQU0sY0FBYyxHQUFHLEtBQUssRUFBRSxHQUFXLEVBQUUsR0FBUSxFQUFFLGFBQXFCLEVBQUUsUUFBUSxHQUFHLEtBQUssRUFBRSxFQUFFO1lBQzVGLE1BQU0sRUFBQyxJQUFJLEVBQUUsTUFBTSxFQUFDLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25DLEtBQUssTUFBTSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQ3RELE1BQU0sQ0FBQyxPQUFPLE9BQU8sSUFBSSxRQUFRLEVBQUUsR0FBRyxHQUFHLElBQUksT0FBTyx5Q0FBeUMsQ0FBQyxDQUFDO2dCQUMvRixJQUFJLFFBQVEsSUFBSSxJQUFJLEtBQUssVUFBVSxJQUFJLENBQUMsSUFBSSxLQUFLLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUMvRSxNQUFNLE1BQU0sR0FBRyxPQUFPLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztvQkFDOUYsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBQyxDQUFDO29CQUN4RSxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsYUFBYSxFQUFDLENBQUMsQ0FBQztnQkFDdkcsQ0FBQztxQkFBTSxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNoRCxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxHQUFHLE9BQU8sS0FBSyxDQUFDLENBQUM7b0JBQ2hFLE1BQU0sTUFBTSxHQUFHLE9BQU8sS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO29CQUM5RixTQUFTLENBQUMsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFDLENBQUM7b0JBQ3BFLElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO3dCQUM1QixTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBQyxDQUFDLENBQUM7b0JBQ25ILENBQUM7eUJBQU0sQ0FBQzt3QkFDSixTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFDLE9BQU8sRUFBRSxTQUFTLEdBQUcsZ0NBQWdDLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLGFBQWEsRUFBQyxDQUFDLENBQUM7b0JBQ3JKLENBQUM7Z0JBQ0wsQ0FBQztxQkFBTSxJQUFJLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztvQkFDekIsTUFBTSxNQUFNLEdBQUcsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7b0JBQzlGLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksRUFBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUMsQ0FBQztvQkFDcEUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLGFBQWEsRUFBQyxDQUFDLENBQUM7Z0JBQ3ZHLENBQUM7cUJBQU0sQ0FBQztvQkFDSixNQUFNLENBQUMsS0FBSyxFQUFFLEdBQUcsR0FBRywyQkFBMkIsQ0FBQyxDQUFDO2dCQUNyRCxDQUFDO1lBQ0wsQ0FBQztRQUNMLENBQUMsQ0FBQztRQUVGLE1BQU0sMEJBQTBCLEdBQUcsS0FBSyxFQUFFLFFBQWEsRUFBRSxZQUFvQixFQUFFLEVBQUU7WUFDN0UsS0FBSyxNQUFNLENBQUMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLE1BQU0sSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUM1RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsV0FBVyxFQUFFLENBQUMsR0FBRyxZQUFZLENBQUMsQ0FBQztZQUNuRSxDQUFDO1lBRUQsTUFBTSxRQUFRLEdBQUcsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxDQUFDO1lBQ25FLEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDM0UsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQztvQkFBRSxTQUFTO2dCQUNuRixNQUFNLENBQUMsWUFBWSxJQUFJLElBQUksRUFBRSx1Q0FBdUMsQ0FBQyxDQUFDO2dCQUN0RSxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsRUFBRSxtREFBbUQsQ0FBQyxDQUFDO2dCQUMxRixLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO29CQUNoRCxNQUFNLGNBQWMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsR0FBRyxZQUFZLENBQUMsQ0FBQztnQkFDakQsQ0FBQztZQUNMLENBQUM7WUFFRCxNQUFNLFVBQVUsR0FBRyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxNQUFNLENBQUM7WUFDbEcsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLGNBQWMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNqRixJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO29CQUFFLFNBQVM7Z0JBQ3ZGLE1BQU0sQ0FBQyxjQUFjLElBQUksSUFBSSxFQUFFLHlDQUF5QyxDQUFDLENBQUM7Z0JBQzFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxFQUFFLHFEQUFxRCxDQUFDLENBQUM7Z0JBQzlGLEtBQUssTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7b0JBQ2xELE1BQU0sY0FBYyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDO2dCQUNqRCxDQUFDO1lBQ0wsQ0FBQztRQUNMLENBQUMsQ0FBQztRQUVGLE1BQU0sMEJBQTBCLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3BELE1BQU0sMEJBQTBCLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRW5ELE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNqRSxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsRUFBRSxDQUFDO1lBQ3RDLElBQUksY0FBYyxHQUFHLEtBQUssQ0FBQztZQUMzQixNQUFNLDhCQUE4QixHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUN2RixJQUFJLHdCQUF3QixDQUFDO1lBQzdCLElBQUksQ0FBQztnQkFDRCx3QkFBd0IsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLDhCQUE4QixFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxlQUFlLEVBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFFM0csSUFBSSxPQUFNLENBQUMsd0JBQXdCLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztvQkFDaEQsY0FBYyxHQUFHLElBQUksQ0FBQztvQkFDdEIsd0JBQXdCLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO2dCQUM1RSxDQUFDO1lBQ0wsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1QsSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO29CQUNsQyxjQUFjLEdBQUcsSUFBSSxDQUFDO29CQUN0Qix3QkFBd0IsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7Z0JBQzVFLENBQUM7WUFDTCxDQUFDO1lBQ0QsTUFBTSxDQUFDLHdCQUF3QixJQUFJLElBQUksRUFBRSx5Q0FBeUMsQ0FBQyxDQUFDO1lBQ3BGLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLHdCQUF3QixDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyx3REFBd0QsQ0FBQyxDQUFDO1lBQ3RILEtBQUssTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLHdCQUF3QixDQUFDLEVBQUUsQ0FBQztnQkFDNUQsTUFBTSxjQUFjLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsY0FBYyxDQUFDLENBQUM7WUFDbkQsQ0FBQztRQUNMLENBQUM7UUFFRCxLQUFLLE1BQU0sTUFBTSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUM1QyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ3RFLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDNUUsQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxNQUFNLENBQUMsbUJBQW1CLENBQUUsR0FBVyxFQUFFLFlBQTBCO1FBQy9ELElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQztZQUFFLE9BQU8sR0FBRyxDQUFDO1FBQ25DLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLGtDQUFrQyxHQUFHLFNBQVMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BHLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDakMsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtXcml0ZVN0cmVhbXN9IGZyb20gXCIuL3dyaXRlLXN0cmVhbXMuanNcIjtcbmltcG9ydCB7R2l0RGF0YX0gZnJvbSBcIi4vZ2l0LWRhdGEuanNcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnMtZXh0cmFcIjtcbmltcG9ydCAqIGFzIHlhbWwgZnJvbSBcImpzLXlhbWxcIjtcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCB7QXJndn0gZnJvbSBcIi4vYXJndi5qc1wiO1xuaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5pbXBvcnQge1V0aWxzfSBmcm9tIFwiLi91dGlscy5qc1wiO1xuaW1wb3J0IGRvdGVudiBmcm9tIFwiZG90ZW52XCI7XG5pbXBvcnQgZGVlcEV4dGVuZCBmcm9tIFwiZGVlcC1leHRlbmRcIjtcblxuZXhwb3J0IGludGVyZmFjZSBDSUNEVmFyaWFibGUge1xuICAgIHR5cGU6IFwiZmlsZVwiIHwgXCJ2YXJpYWJsZVwiO1xuICAgIGVudmlyb25tZW50czoge1xuICAgICAgICBjb250ZW50OiBzdHJpbmc7XG4gICAgICAgIHJlZ2V4cDogUmVnRXhwO1xuICAgICAgICByZWdleHBQcmlvcml0eTogbnVtYmVyO1xuICAgICAgICBzY29wZVByaW9yaXR5OiBudW1iZXI7XG4gICAgICAgIGZpbGVTb3VyY2U/OiBzdHJpbmc7XG4gICAgfVtdO1xufVxuXG5leHBvcnQgY2xhc3MgVmFyaWFibGVzRnJvbUZpbGVzIHtcblxuICAgIHN0YXRpYyBhc3luYyBpbml0IChhcmd2OiBBcmd2LCB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcywgZ2l0RGF0YTogR2l0RGF0YSk6IFByb21pc2U8e1tuYW1lOiBzdHJpbmddOiBDSUNEVmFyaWFibGV9PiB7XG4gICAgICAgIGNvbnN0IGN3ZCA9IGFyZ3YuY3dkO1xuICAgICAgICBjb25zdCBzdGF0ZURpciA9IGFyZ3Yuc3RhdGVEaXI7XG4gICAgICAgIGNvbnN0IGhvbWVEaXIgPSBhcmd2LmhvbWU7XG4gICAgICAgIGNvbnN0IHJlbW90ZVZhcmlhYmxlcyA9IGFyZ3YucmVtb3RlVmFyaWFibGVzO1xuICAgICAgICBjb25zdCBhdXRvQ29tcGxldGluZyA9IGFyZ3YuYXV0b0NvbXBsZXRpbmc7XG4gICAgICAgIGNvbnN0IGhvbWVWYXJpYWJsZXNGaWxlID0gYCR7aG9tZURpcn0vJHtzdGF0ZURpcn0vdmFyaWFibGVzLnltbGA7XG4gICAgICAgIGNvbnN0IHZhcmlhYmxlczoge1tuYW1lOiBzdHJpbmddOiBDSUNEVmFyaWFibGV9ID0ge307XG4gICAgICAgIGxldCByZW1vdGVGaWxlRGF0YTogYW55ID0ge307XG4gICAgICAgIGxldCBob21lRmlsZURhdGE6IGFueSA9IHt9O1xuXG4gICAgICAgIGlmIChyZW1vdGVWYXJpYWJsZXMgJiYgIWF1dG9Db21wbGV0aW5nKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlbW90ZVZhcmlhYmxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gLyg/PHVybD5naXRALio/KT0oPzxmaWxlPi4qPyk9KD88cmVmPi4qKS8uZXhlYyhyZW1vdGVWYXJpYWJsZXNbaV0pO1xuICAgICAgICAgICAgICAgIGFzc2VydChtYXRjaCAhPSBudWxsLCBcIi0tcmVtb3RlLXZhcmlhYmxlcyBpcyBtYWxmb3JtZWQgdXNlICdnaXRAZ2l0bGFiLmNvbTpmaXJlY293L2V4YW1wbGUuZ2l0PWdpdGxhYi12YXJpYWJsZXMueW1sPW1hc3Rlcicgc3ludGF4XCIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHVybCA9IG1hdGNoLmdyb3Vwcz8udXJsO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGUgPSBtYXRjaC5ncm91cHM/LmZpbGU7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVmID0gbWF0Y2guZ3JvdXBzPy5yZWY7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgVXRpbHMuYmFzaChgc2V0IC1lb3UgcGlwZWZhaWw7IGdpdCBhcmNoaXZlIC0tcmVtb3RlPSR7dXJsfSAke3JlZn0gJHtmaWxlfSB8IHRhciAteE8gJHtmaWxlfWAsIGN3ZCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9hZGVkWWFtbCA9IHlhbWwubG9hZChgJHtyZXMuc3Rkb3V0fWApO1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGxvYWRlZFlhbWwgaXMgYW4gb2JqZWN0XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBsb2FkZWRZYW1sID09PSBcIm9iamVjdFwiICYmIGxvYWRlZFlhbWwgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3RlRmlsZURhdGEgPSBkZWVwRXh0ZW5kKHJlbW90ZUZpbGVEYXRhLCBsb2FkZWRZYW1sKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhob21lVmFyaWFibGVzRmlsZSkpIHtcbiAgICAgICAgICAgIGhvbWVGaWxlRGF0YSA9IHlhbWwubG9hZChhd2FpdCBmcy5yZWFkRmlsZShob21lVmFyaWFibGVzRmlsZSwgXCJ1dGY4XCIpLCB7c2NoZW1hOiB5YW1sLkZBSUxTQUZFX1NDSEVNQX0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdW5wYWNrID0gKHY6IGFueSk6IHt2YWx1ZXM6IGFueTsgdHlwZTogXCJmaWxlXCIgfCBcInZhcmlhYmxlXCIgfCBudWxsfSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHYgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjYXRjaEFsbDoge3ZhbHVlczogYW55OyB0eXBlOiBcImZpbGVcIiB8IFwidmFyaWFibGVcIiB8IG51bGx9ID0ge3ZhbHVlczoge30sIHR5cGU6IG51bGx9O1xuICAgICAgICAgICAgICAgIGNhdGNoQWxsLnZhbHVlcyA9IHt9O1xuICAgICAgICAgICAgICAgIGNhdGNoQWxsLnZhbHVlc1tcIipcIl0gPSB2O1xuICAgICAgICAgICAgICAgIHJldHVybiBjYXRjaEFsbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdi50eXBlID0gdi50eXBlID8/IFwidmFyaWFibGVcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBhZGRUb1ZhcmlhYmxlcyA9IGFzeW5jIChrZXk6IHN0cmluZywgdmFsOiBhbnksIHNjb3BlUHJpb3JpdHk6IG51bWJlciwgaXNEb3RFbnYgPSBmYWxzZSkgPT4ge1xuICAgICAgICAgICAgY29uc3Qge3R5cGUsIHZhbHVlc30gPSB1bnBhY2sodmFsKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgW21hdGNoZXIsIGNvbnRlbnRdIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlcykpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQodHlwZW9mIGNvbnRlbnQgPT0gXCJzdHJpbmdcIiwgYCR7a2V5fS4ke21hdGNoZXJ9IGNvbnRlbnQgbXVzdCBiZSB0ZXh0IG9yIG11bHRpbGluZSB0ZXh0YCk7XG4gICAgICAgICAgICAgICAgaWYgKGlzRG90RW52IHx8IHR5cGUgPT09IFwidmFyaWFibGVcIiB8fCAodHlwZSA9PT0gbnVsbCAmJiAhL15bL35dLy5leGVjKGNvbnRlbnQpKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWdleHAgPSBtYXRjaGVyID09PSBcIipcIiA/IC8uKi9nIDogbmV3IFJlZ0V4cChgXiR7bWF0Y2hlci5yZXBsYWNlKC9cXCovZywgXCIuKlwiKX0kYCwgXCJnXCIpO1xuICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZXNba2V5XSA9IHZhcmlhYmxlc1trZXldID8/IHt0eXBlOiBcInZhcmlhYmxlXCIsIGVudmlyb25tZW50czogW119O1xuICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZXNba2V5XS5lbnZpcm9ubWVudHMucHVzaCh7Y29udGVudCwgcmVnZXhwLCByZWdleHBQcmlvcml0eTogbWF0Y2hlci5sZW5ndGgsIHNjb3BlUHJpb3JpdHl9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IG51bGwgJiYgL15bL35dLy5leGVjKGNvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVTb3VyY2UgPSBjb250ZW50LnJlcGxhY2UoL15+XFwvKC4qKS8sIGAke2hvbWVEaXJ9LyQxYCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2V4cCA9IG1hdGNoZXIgPT09IFwiKlwiID8gLy4qL2cgOiBuZXcgUmVnRXhwKGBeJHttYXRjaGVyLnJlcGxhY2UoL1xcKi9nLCBcIi4qXCIpfSRgLCBcImdcIik7XG4gICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlc1trZXldID0gdmFyaWFibGVzW2tleV0gPz8ge3R5cGU6IFwiZmlsZVwiLCBlbnZpcm9ubWVudHM6IFtdfTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoZmlsZVNvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlc1trZXldLmVudmlyb25tZW50cy5wdXNoKHtjb250ZW50LCByZWdleHAsIHJlZ2V4cFByaW9yaXR5OiBtYXRjaGVyLmxlbmd0aCwgc2NvcGVQcmlvcml0eSwgZmlsZVNvdXJjZX0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGVzW2tleV0uZW52aXJvbm1lbnRzLnB1c2goe2NvbnRlbnQ6IGB3YXJuOiAke2tleX0gaXMgcG9pbnRpbmcgdG8gaW52YWxpZCBwYXRoXFxuYCwgcmVnZXhwLCByZWdleHBQcmlvcml0eTogbWF0Y2hlci5sZW5ndGgsIHNjb3BlUHJpb3JpdHl9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCJmaWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVnZXhwID0gbWF0Y2hlciA9PT0gXCIqXCIgPyAvLiovZyA6IG5ldyBSZWdFeHAoYF4ke21hdGNoZXIucmVwbGFjZSgvXFwqL2csIFwiLipcIil9JGAsIFwiZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyaWFibGVzW2tleV0gPSB2YXJpYWJsZXNba2V5XSA/PyB7dHlwZTogXCJmaWxlXCIsIGVudmlyb25tZW50czogW119O1xuICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZXNba2V5XS5lbnZpcm9ubWVudHMucHVzaCh7Y29udGVudCwgcmVnZXhwLCByZWdleHBQcmlvcml0eTogbWF0Y2hlci5sZW5ndGgsIHNjb3BlUHJpb3JpdHl9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoZmFsc2UsIGAke2tleX0gd2FzIG5vdCBoYW5kbGVkIHByb3Blcmx5YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGFkZFZhcmlhYmxlRmlsZVRvVmFyaWFibGVzID0gYXN5bmMgKGZpbGVEYXRhOiBhbnksIGZpbGVQcmlvcml0eTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtnbG9iYWxLZXksIGdsb2JhbEVudHJ5XSBvZiBPYmplY3QuZW50cmllcyhmaWxlRGF0YT8uZ2xvYmFsID8/IHt9KSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGFkZFRvVmFyaWFibGVzKGdsb2JhbEtleSwgZ2xvYmFsRW50cnksIDEgKyBmaWxlUHJpb3JpdHkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBncm91cFVybCA9IGAke2dpdERhdGEucmVtb3RlLmhvc3R9LyR7Z2l0RGF0YS5yZW1vdGUuZ3JvdXB9L2A7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtncm91cEtleSwgZ3JvdXBFbnRyaWVzXSBvZiBPYmplY3QuZW50cmllcyhmaWxlRGF0YT8uZ3JvdXAgPz8ge30pKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFncm91cFVybC5pbmNsdWRlcyh0aGlzLm5vcm1hbGl6ZVByb2plY3RLZXkoZ3JvdXBLZXksIHdyaXRlU3RyZWFtcykpKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBhc3NlcnQoZ3JvdXBFbnRyaWVzICE9IG51bGwsIFwiZ3JvdXBFbnRyaWVzIGNhbm5vdCBiZSBudWxsL3VuZGVmaW5lZFwiKTtcbiAgICAgICAgICAgICAgICBhc3NlcnQoVXRpbHMuaXNPYmplY3QoZ3JvdXBFbnRyaWVzKSwgXCJncm91cCBlbnRyaWVzIGluIHZhcmlhYmxlIGZpbGVzIG11c3QgYmUgYW4gb2JqZWN0XCIpO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKGdyb3VwRW50cmllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgYWRkVG9WYXJpYWJsZXMoaywgdiwgMiArIGZpbGVQcmlvcml0eSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBwcm9qZWN0VXJsID0gYCR7Z2l0RGF0YS5yZW1vdGUuaG9zdH0vJHtnaXREYXRhLnJlbW90ZS5ncm91cH0vJHtnaXREYXRhLnJlbW90ZS5wcm9qZWN0fS5naXRgO1xuICAgICAgICAgICAgZm9yIChjb25zdCBbcHJvamVjdEtleSwgcHJvamVjdEVudHJpZXNdIG9mIE9iamVjdC5lbnRyaWVzKGZpbGVEYXRhPy5wcm9qZWN0ID8/IFtdKSkge1xuICAgICAgICAgICAgICAgIGlmICghcHJvamVjdFVybC5pbmNsdWRlcyh0aGlzLm5vcm1hbGl6ZVByb2plY3RLZXkocHJvamVjdEtleSwgd3JpdGVTdHJlYW1zKSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGFzc2VydChwcm9qZWN0RW50cmllcyAhPSBudWxsLCBcInByb2plY3RFbnRyaWVzIGNhbm5vdCBiZSBudWxsL3VuZGVmaW5lZFwiKTtcbiAgICAgICAgICAgICAgICBhc3NlcnQoVXRpbHMuaXNPYmplY3QocHJvamVjdEVudHJpZXMpLCBcInByb2plY3QgZW50cmllcyBpbiB2YXJpYWJsZSBmaWxlcyBtdXN0IGJlIGFuIG9iamVjdFwiKTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhwcm9qZWN0RW50cmllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgYWRkVG9WYXJpYWJsZXMoaywgdiwgMyArIGZpbGVQcmlvcml0eSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGFkZFZhcmlhYmxlRmlsZVRvVmFyaWFibGVzKHJlbW90ZUZpbGVEYXRhLCAwKTtcbiAgICAgICAgYXdhaXQgYWRkVmFyaWFibGVGaWxlVG9WYXJpYWJsZXMoaG9tZUZpbGVEYXRhLCAxMCk7XG5cbiAgICAgICAgY29uc3QgcHJvamVjdFZhcmlhYmxlc0ZpbGUgPSBgJHthcmd2LmN3ZH0vJHthcmd2LnZhcmlhYmxlc0ZpbGV9YDtcbiAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMocHJvamVjdFZhcmlhYmxlc0ZpbGUpKSB7XG4gICAgICAgICAgICBsZXQgaXNEb3RFbnZGb3JtYXQgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnN0IHByb2plY3RWYXJpYWJsZXNGaWxlUmF3Q29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKHByb2plY3RWYXJpYWJsZXNGaWxlLCBcInV0ZjhcIik7XG4gICAgICAgICAgICBsZXQgcHJvamVjdFZhcmlhYmxlc0ZpbGVEYXRhO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBwcm9qZWN0VmFyaWFibGVzRmlsZURhdGEgPSB5YW1sLmxvYWQocHJvamVjdFZhcmlhYmxlc0ZpbGVSYXdDb250ZW50LCB7c2NoZW1hOiB5YW1sLkZBSUxTQUZFX1NDSEVNQX0pID8/IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZihwcm9qZWN0VmFyaWFibGVzRmlsZURhdGEpID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzRG90RW52Rm9ybWF0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvamVjdFZhcmlhYmxlc0ZpbGVEYXRhID0gZG90ZW52LnBhcnNlKHByb2plY3RWYXJpYWJsZXNGaWxlUmF3Q29udGVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgeWFtbC5ZQU1MRXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzRG90RW52Rm9ybWF0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvamVjdFZhcmlhYmxlc0ZpbGVEYXRhID0gZG90ZW52LnBhcnNlKHByb2plY3RWYXJpYWJsZXNGaWxlUmF3Q29udGVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXNzZXJ0KHByb2plY3RWYXJpYWJsZXNGaWxlRGF0YSAhPSBudWxsLCBcInByb2plY3RFbnRyaWVzIGNhbm5vdCBiZSBudWxsL3VuZGVmaW5lZFwiKTtcbiAgICAgICAgICAgIGFzc2VydChVdGlscy5pc09iamVjdChwcm9qZWN0VmFyaWFibGVzRmlsZURhdGEpLCBgJHthcmd2LmN3ZH0vLmdpdGxhYi1jaS1sb2NhbC12YXJpYWJsZXMueW1sIG11c3QgY29udGFpbiBhbiBvYmplY3RgKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHByb2plY3RWYXJpYWJsZXNGaWxlRGF0YSkpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBhZGRUb1ZhcmlhYmxlcyhrLCB2LCAyNCwgaXNEb3RFbnZGb3JtYXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCB2YXJPYmogb2YgT2JqZWN0LnZhbHVlcyh2YXJpYWJsZXMpKSB7XG4gICAgICAgICAgICB2YXJPYmouZW52aXJvbm1lbnRzLnNvcnQoKGEsIGIpID0+IGIuc2NvcGVQcmlvcml0eSAtIGEuc2NvcGVQcmlvcml0eSk7XG4gICAgICAgICAgICB2YXJPYmouZW52aXJvbm1lbnRzLnNvcnQoKGEsIGIpID0+IGIucmVnZXhwUHJpb3JpdHkgLSBhLnJlZ2V4cFByaW9yaXR5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YXJpYWJsZXM7XG4gICAgfVxuXG4gICAgc3RhdGljIG5vcm1hbGl6ZVByb2plY3RLZXkgKGtleTogc3RyaW5nLCB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcyk6IHN0cmluZyB7XG4gICAgICAgIGlmICgha2V5LmluY2x1ZGVzKFwiOlwiKSkgcmV0dXJuIGtleTtcbiAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93IFdBUk5JTkc6IEludGVycHJldGluZyAnJHtrZXl9JyBhcyAnJHtrZXkucmVwbGFjZShcIjpcIiwgXCIvXCIpfSd9XFxuYCk7XG4gICAgICAgIHJldHVybiBrZXkucmVwbGFjZShcIjpcIiwgXCIvXCIpO1xuICAgIH1cbn1cbiJdfQ==