gitlab-ci-local
Version:
Tired of pushing to test your .gitlab-ci.yml?
279 lines • 38 kB
JavaScript
import assert from "assert";
import fs from "fs-extra";
import * as dotenv from "dotenv";
import * as path from "path";
import camelCase from "camelcase";
import { Utils } from "./utils.js";
import chalk from "chalk";
async function isInGitRepository() {
try {
await Utils.spawn(["git", "rev-parse", "--is-inside-work-tree"]);
return true;
}
catch (err) {
return false;
}
}
async function gitRootPath() {
const { stdout } = await Utils.spawn(["git", "rev-parse", "--show-toplevel"]);
return stdout;
}
export class Argv {
static default = {
"variablesFile": ".gitlab-ci-local-variables.yml",
"evaluateRuleChanges": true,
"ignoreSchemaPaths": [],
};
map = new Map();
writeStreams;
async fallbackCwd(args) {
if (args.cwd !== undefined || args.file !== undefined)
return;
if (fs.existsSync(`${process.cwd()}/.gitlab-ci.yml`))
return;
if (!(await isInGitRepository()))
return;
this.writeStreams?.stderr(chalk `{yellow .gitlab-ci.yml not found in cwd, falling back to git root directory}\n`);
this.map.set("cwd", path.relative(process.cwd(), await gitRootPath()));
}
static async build(args, writeStreams) {
const argv = new Argv(args, writeStreams);
await argv.fallbackCwd(args);
argv.injectDotenv(`${argv.home}/.gitlab-ci-local/.env`, args);
argv.injectDotenv(`${argv.cwd}/.gitlab-ci-local-env`, args);
if (!argv.shellExecutorNoImage && argv.shellIsolation) {
writeStreams?.stderr(chalk `{black.bgYellowBright WARN } --shell-isolation does not work with --no-shell-executor-no-image\n`);
}
if (argv.defaultImageExplicitlySet && argv.shellIsolation) {
writeStreams?.stderr(chalk `{black.bgYellowBright WARN } --default-image does not work with --shell-isolation=true\n`);
}
if (argv.defaultImageExplicitlySet && argv.shellExecutorNoImage) {
writeStreams?.stderr(chalk `{black.bgYellowBright WARN } --default-image does not work with --shell-executor-no-image=true\n`);
}
if (argv.defaultImageExplicitlySet && argv.forceShellExecutor) {
writeStreams?.stderr(chalk `{black.bgYellowBright WARN } --default-image does not work with --force-shell-executor=true\n`);
}
return argv;
}
constructor(argv, writeStreams) {
if (argv.noColor) {
chalk.level = 0;
}
this.writeStreams = writeStreams;
for (const [key, value] of Object.entries(argv)) {
this.map.set(key, value);
}
}
injectDotenv(potentialDotenvFilepath, argv) {
if (fs.existsSync(potentialDotenvFilepath)) {
const config = dotenv.parse(fs.readFileSync(potentialDotenvFilepath));
for (const [key, value] of Object.entries(config)) {
const argKey = camelCase(key);
// Special handle KEY=VALUE variable keys
if (argKey === "variable") {
let currentVal = argv[argKey];
if (currentVal == null) {
currentVal = [];
this.map.set(argKey, currentVal);
}
if (!Array.isArray(currentVal)) {
continue;
}
for (const pair of value.split(" ")) {
currentVal.unshift(pair);
}
}
else if (argv[argKey] == null) {
// Work around `dotenv.parse` limitation https://github.com/motdotla/dotenv/issues/51#issuecomment-552559070
if (value === "true")
this.map.set(argKey, true);
else if (value === "false")
this.map.set(argKey, false);
else if (value === "null")
this.map.set(argKey, null);
else if (!isNaN(Number(value)))
this.map.set(argKey, Number(value));
else
this.map.set(argKey, value);
}
}
}
}
get cwd() {
let cwd = this.map.get("cwd") ?? ".";
assert(typeof cwd != "object", "--cwd option cannot be an array");
assert(!path.isAbsolute(cwd), "Please use relative path for the --cwd option");
cwd = path.normalize(`${process.cwd()}/${cwd}`);
cwd = cwd.replace(/\/$/, "");
assert(fs.pathExistsSync(cwd), `${cwd} is not a directory`);
return cwd;
}
get variablesFile() {
return this.map.get("variablesFile") ?? Argv.default.variablesFile;
}
get evaluateRuleChanges() {
return this.map.get("evaluateRuleChanges") ?? Argv.default.evaluateRuleChanges;
}
get file() {
return this.map.get("file") ?? ".gitlab-ci.yml";
}
get stateDir() {
return (this.map.get("stateDir") ?? ".gitlab-ci-local").replace(/\/$/, "");
}
get home() {
return (this.map.get("home") ?? process.env.HOME ?? "").replace(/\/$/, "");
}
get volume() {
const val = this.map.get("volume") ?? [];
return typeof val == "string" ? val.split(" ") : val;
}
get network() {
const val = this.map.get("network") ?? [];
return typeof val == "string" ? val.split(" ") : val;
}
get extraHost() {
const val = this.map.get("extraHost") ?? [];
return typeof val == "string" ? val.split(" ") : val;
}
get ignoreSchemaPaths() {
return this.map.get("ignoreSchemaPaths") ?? Argv.default.ignoreSchemaPaths;
}
get pullPolicy() {
return this.map.get("pullPolicy") ?? "if-not-present";
}
get remoteVariables() {
return this.map.get("remoteVariables");
}
get variable() {
const val = this.map.get("variable");
const variables = {};
const pairs = typeof val == "string" ? val.split(" ") : val;
(pairs ?? []).forEach((variablePair) => {
const exec = /(?<key>\w*?)(=)(?<value>(.|\n|\r)*)/.exec(variablePair);
if (exec?.groups?.key) {
variables[exec.groups.key] = exec?.groups?.value;
}
});
return variables;
}
get unsetVariables() {
return this.map.get("unsetVariable") ?? [];
}
get manual() {
const val = this.map.get("manual") ?? [];
return typeof val == "string" ? val.split(" ") : val;
}
get job() {
return this.map.get("job") ?? [];
}
get autoCompleting() {
return this.map.get("autoCompleting") ?? false;
}
get cleanup() {
return this.map.get("cleanup") ?? true;
}
get quiet() {
return this.map.get("quiet") ?? false;
}
get umask() {
// TODO: default to false in 5.x.x
return this.map.get("umask") ?? true;
}
get privileged() {
return this.map.get("privileged") ?? false;
}
get ulimit() {
const ulimit = this.map.get("ulimit");
if (!ulimit)
return null;
return ulimit;
}
get needs() {
return this.map.get("needs") ?? false;
}
get onlyNeeds() {
return this.map.get("onlyNeeds") ?? false;
}
get stage() {
return this.map.get("stage") ?? null;
}
get completion() {
return this.map.get("completion") ?? false;
}
get list() {
return this.map.get("list") ?? false;
}
get listAll() {
return this.map.get("listAll") ?? false;
}
get listJson() {
return this.map.get("listJson") ?? false;
}
get listCsv() {
return this.map.get("listCsv") ?? false;
}
get listCsvAll() {
return this.map.get("listCsvAll") ?? false;
}
get preview() {
return this.map.get("preview") ?? false;
}
get shellIsolation() {
// TODO: default to true in 5.x.x
return this.map.get("shellIsolation") ?? false;
}
get fetchIncludes() {
return this.map.get("fetchIncludes") ?? false;
}
get mountCache() {
return this.map.get("mountCache") ?? false;
}
get artifactsToSource() {
// TODO: default to false in 5.x.x
return this.map.get("artifactsToSource") ?? true;
}
get showTimestamps() {
return this.map.get("timestamps") ?? false;
}
get maxJobNamePadding() {
return this.map.get("maxJobNamePadding") ?? null;
}
get containerMacAddress() {
return this.map.get("containerMacAddress") ?? null;
}
get containerEmulate() {
return this.map.get("containerEmulate") ?? null;
}
get concurrency() {
const concurrency = this.map.get("concurrency");
if (!concurrency)
return null;
return Number(concurrency);
}
get containerExecutable() {
return this.map.get("containerExecutable") ?? "docker";
}
get jsonSchemaValidation() {
return this.map.get("jsonSchemaValidation") ?? true;
}
get shellExecutorNoImage() {
// TODO: default to false in 5.x.x
return this.map.get("shellExecutorNoImage") ?? true;
}
get forceShellExecutor() {
return this.map.get("forceShellExecutor") ?? false;
}
get defaultImage() {
return this.map.get("defaultImage") ?? "docker.io/ruby:3.1";
}
get defaultImageExplicitlySet() {
return this.map.get("defaultImage") ?? false;
}
get maximumIncludes() {
return this.map.get("maximumIncludes") ?? 150; // https://docs.gitlab.com/ee/administration/settings/continuous_integration.html#maximum-includes
}
get childPipelineDepth() {
return this.map.get("childPipelineDepth");
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJndi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFyZ3YudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUMxQixPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLFNBQVMsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFDLEtBQUssRUFBQyxNQUFNLFlBQVksQ0FBQztBQUVqQyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFMUIsS0FBSyxVQUFVLGlCQUFpQjtJQUM1QixJQUFJLENBQUM7UUFDRCxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLHVCQUF1QixDQUFDLENBQUMsQ0FBQztRQUNqRSxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBQUMsT0FBTyxHQUFRLEVBQUUsQ0FBQztRQUNoQixPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSxXQUFXO0lBQ3RCLE1BQU0sRUFBQyxNQUFNLEVBQUMsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUM1RSxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBRUQsTUFBTSxPQUFPLElBQUk7SUFDYixNQUFNLENBQVUsT0FBTyxHQUFHO1FBQ3RCLGVBQWUsRUFBRSxnQ0FBZ0M7UUFDakQscUJBQXFCLEVBQUUsSUFBSTtRQUMzQixtQkFBbUIsRUFBRSxFQUFFO0tBQzFCLENBQUM7SUFFRixHQUFHLEdBQXFCLElBQUksR0FBRyxFQUFlLENBQUM7SUFDOUIsWUFBWSxDQUEyQjtJQUVoRCxLQUFLLENBQUMsV0FBVyxDQUFF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RyxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDOUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmcy1leHRyYVwiO1xuaW1wb3J0ICogYXMgZG90ZW52IGZyb20gXCJkb3RlbnZcIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBjYW1lbENhc2UgZnJvbSBcImNhbWVsY2FzZVwiO1xuaW1wb3J0IHtVdGlsc30gZnJvbSBcIi4vdXRpbHMuanNcIjtcbmltcG9ydCB7V3JpdGVTdHJlYW1zfSBmcm9tIFwiLi93cml0ZS1zdHJlYW1zLmpzXCI7XG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5cbmFzeW5jIGZ1bmN0aW9uIGlzSW5HaXRSZXBvc2l0b3J5ICgpIHtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbXCJnaXRcIiwgXCJyZXYtcGFyc2VcIiwgXCItLWlzLWluc2lkZS13b3JrLXRyZWVcIl0pO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBnaXRSb290UGF0aCAoKSB7XG4gICAgY29uc3Qge3N0ZG91dH0gPSBhd2FpdCBVdGlscy5zcGF3bihbXCJnaXRcIiwgXCJyZXYtcGFyc2VcIiwgXCItLXNob3ctdG9wbGV2ZWxcIl0pO1xuICAgIHJldHVybiBzdGRvdXQ7XG59XG5cbmV4cG9ydCBjbGFzcyBBcmd2IHtcbiAgICBzdGF0aWMgcmVhZG9ubHkgZGVmYXVsdCA9IHtcbiAgICAgICAgXCJ2YXJpYWJsZXNGaWxlXCI6IFwiLmdpdGxhYi1jaS1sb2NhbC12YXJpYWJsZXMueW1sXCIsXG4gICAgICAgIFwiZXZhbHVhdGVSdWxlQ2hhbmdlc1wiOiB0cnVlLFxuICAgICAgICBcImlnbm9yZVNjaGVtYVBhdGhzXCI6IFtdLFxuICAgIH07XG5cbiAgICBtYXA6IE1hcDxzdHJpbmcsIGFueT4gPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgd3JpdGVTdHJlYW1zOiBXcml0ZVN0cmVhbXMgfCB1bmRlZmluZWQ7XG5cbiAgICBwcml2YXRlIGFzeW5jIGZhbGxiYWNrQ3dkIChhcmdzOiBhbnkpIHtcbiAgICAgICAgaWYgKGFyZ3MuY3dkICE9PSB1bmRlZmluZWQgfHwgYXJncy5maWxlICE9PSB1bmRlZmluZWQpIHJldHVybjtcbiAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoYCR7cHJvY2Vzcy5jd2QoKX0vLmdpdGxhYi1jaS55bWxgKSkgcmV0dXJuO1xuICAgICAgICBpZiAoIShhd2FpdCBpc0luR2l0UmVwb3NpdG9yeSgpKSkgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMud3JpdGVTdHJlYW1zPy5zdGRlcnIoY2hhbGtge3llbGxvdyAuZ2l0bGFiLWNpLnltbCBub3QgZm91bmQgaW4gY3dkLCBmYWxsaW5nIGJhY2sgdG8gZ2l0IHJvb3QgZGlyZWN0b3J5fVxcbmApO1xuICAgICAgICB0aGlzLm1hcC5zZXQoXCJjd2RcIiwgcGF0aC5yZWxhdGl2ZShwcm9jZXNzLmN3ZCgpLCBhd2FpdCBnaXRSb290UGF0aCgpKSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGFzeW5jIGJ1aWxkIChhcmdzOiBhbnksIHdyaXRlU3RyZWFtcz86IFdyaXRlU3RyZWFtcykge1xuICAgICAgICBjb25zdCBhcmd2ID0gbmV3IEFyZ3YoYXJncywgd3JpdGVTdHJlYW1zKTtcbiAgICAgICAgYXdhaXQgYXJndi5mYWxsYmFja0N3ZChhcmdzKTtcblxuICAgICAgICBhcmd2LmluamVjdERvdGVudihgJHthcmd2LmhvbWV9Ly5naXRsYWItY2ktbG9jYWwvLmVudmAsIGFyZ3MpO1xuICAgICAgICBhcmd2LmluamVjdERvdGVudihgJHthcmd2LmN3ZH0vLmdpdGxhYi1jaS1sb2NhbC1lbnZgLCBhcmdzKTtcblxuICAgICAgICBpZiAoIWFyZ3Yuc2hlbGxFeGVjdXRvck5vSW1hZ2UgJiYgYXJndi5zaGVsbElzb2xhdGlvbikge1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zPy5zdGRlcnIoY2hhbGtge2JsYWNrLmJnWWVsbG93QnJpZ2h0ICBXQVJOIH0gLS1zaGVsbC1pc29sYXRpb24gZG9lcyBub3Qgd29yayB3aXRoIC0tbm8tc2hlbGwtZXhlY3V0b3Itbm8taW1hZ2VcXG5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhcmd2LmRlZmF1bHRJbWFnZUV4cGxpY2l0bHlTZXQgJiYgYXJndi5zaGVsbElzb2xhdGlvbikge1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zPy5zdGRlcnIoY2hhbGtge2JsYWNrLmJnWWVsbG93QnJpZ2h0ICBXQVJOIH0gLS1kZWZhdWx0LWltYWdlIGRvZXMgbm90IHdvcmsgd2l0aCAtLXNoZWxsLWlzb2xhdGlvbj10cnVlXFxuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXJndi5kZWZhdWx0SW1hZ2VFeHBsaWNpdGx5U2V0ICYmIGFyZ3Yuc2hlbGxFeGVjdXRvck5vSW1hZ2UpIHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcz8uc3RkZXJyKGNoYWxrYHtibGFjay5iZ1llbGxvd0JyaWdodCAgV0FSTiB9IC0tZGVmYXVsdC1pbWFnZSBkb2VzIG5vdCB3b3JrIHdpdGggLS1zaGVsbC1leGVjdXRvci1uby1pbWFnZT10cnVlXFxuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXJndi5kZWZhdWx0SW1hZ2VFeHBsaWNpdGx5U2V0ICYmIGFyZ3YuZm9yY2VTaGVsbEV4ZWN1dG9yKSB7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXM/LnN0ZGVycihjaGFsa2B7YmxhY2suYmdZZWxsb3dCcmlnaHQgIFdBUk4gfSAtLWRlZmF1bHQtaW1hZ2UgZG9lcyBub3Qgd29yayB3aXRoIC0tZm9yY2Utc2hlbGwtZXhlY3V0b3I9dHJ1ZVxcbmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFyZ3Y7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3RvciAoYXJndjogYW55LCB3cml0ZVN0cmVhbXM/OiBXcml0ZVN0cmVhbXMpIHtcbiAgICAgICAgaWYgKGFyZ3Yubm9Db2xvcikge1xuICAgICAgICAgICAgY2hhbGsubGV2ZWwgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMud3JpdGVTdHJlYW1zID0gd3JpdGVTdHJlYW1zO1xuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhhcmd2KSkge1xuICAgICAgICAgICAgdGhpcy5tYXAuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbmplY3REb3RlbnYgKHBvdGVudGlhbERvdGVudkZpbGVwYXRoOiBzdHJpbmcsIGFyZ3Y6IGFueSkge1xuICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhwb3RlbnRpYWxEb3RlbnZGaWxlcGF0aCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZyA9IGRvdGVudi5wYXJzZShmcy5yZWFkRmlsZVN5bmMocG90ZW50aWFsRG90ZW52RmlsZXBhdGgpKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbmZpZykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhcmdLZXkgPSBjYW1lbENhc2Uoa2V5KTtcblxuICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgaGFuZGxlIEtFWT1WQUxVRSB2YXJpYWJsZSBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKGFyZ0tleSA9PT0gXCJ2YXJpYWJsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjdXJyZW50VmFsID0gYXJndlthcmdLZXldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudFZhbCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50VmFsID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcC5zZXQoYXJnS2V5LCBjdXJyZW50VmFsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY3VycmVudFZhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcGFpciBvZiB2YWx1ZS5zcGxpdChcIiBcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRWYWwudW5zaGlmdChwYWlyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYXJndlthcmdLZXldID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV29yayBhcm91bmQgYGRvdGVudi5wYXJzZWAgbGltaXRhdGlvbiBodHRwczovL2dpdGh1Yi5jb20vbW90ZG90bGEvZG90ZW52L2lzc3Vlcy81MSNpc3N1ZWNvbW1lbnQtNTUyNTU5MDcwXG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gXCJ0cnVlXCIpIHRoaXMubWFwLnNldChhcmdLZXksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh2YWx1ZSA9PT0gXCJmYWxzZVwiKSB0aGlzLm1hcC5zZXQoYXJnS2V5LCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlID09PSBcIm51bGxcIikgdGhpcy5tYXAuc2V0KGFyZ0tleSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFpc05hTihOdW1iZXIodmFsdWUpKSkgdGhpcy5tYXAuc2V0KGFyZ0tleSwgTnVtYmVyKHZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgdGhpcy5tYXAuc2V0KGFyZ0tleSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldCBjd2QgKCk6IHN0cmluZyB7XG4gICAgICAgIGxldCBjd2QgPSB0aGlzLm1hcC5nZXQoXCJjd2RcIikgPz8gXCIuXCI7XG4gICAgICAgIGFzc2VydCh0eXBlb2YgY3dkICE9IFwib2JqZWN0XCIsIFwiLS1jd2Qgb3B0aW9uIGNhbm5vdCBiZSBhbiBhcnJheVwiKTtcbiAgICAgICAgYXNzZXJ0KCFwYXRoLmlzQWJzb2x1dGUoY3dkKSwgXCJQbGVhc2UgdXNlIHJlbGF0aXZlIHBhdGggZm9yIHRoZSAtLWN3ZCBvcHRpb25cIik7XG4gICAgICAgIGN3ZCA9IHBhdGgubm9ybWFsaXplKGAke3Byb2Nlc3MuY3dkKCl9LyR7Y3dkfWApO1xuICAgICAgICBjd2QgPSBjd2QucmVwbGFjZSgvXFwvJC8sIFwiXCIpO1xuICAgICAgICBhc3NlcnQoZnMucGF0aEV4aXN0c1N5bmMoY3dkKSwgYCR7Y3dkfSBpcyBub3QgYSBkaXJlY3RvcnlgKTtcbiAgICAgICAgcmV0dXJuIGN3ZDtcbiAgICB9XG5cbiAgICBnZXQgdmFyaWFibGVzRmlsZSAoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcInZhcmlhYmxlc0ZpbGVcIikgPz8gQXJndi5kZWZhdWx0LnZhcmlhYmxlc0ZpbGU7XG4gICAgfVxuXG4gICAgZ2V0IGV2YWx1YXRlUnVsZUNoYW5nZXMgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwiZXZhbHVhdGVSdWxlQ2hhbmdlc1wiKSA/PyBBcmd2LmRlZmF1bHQuZXZhbHVhdGVSdWxlQ2hhbmdlcztcbiAgICB9XG5cbiAgICBnZXQgZmlsZSAoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcImZpbGVcIikgPz8gXCIuZ2l0bGFiLWNpLnltbFwiO1xuICAgIH1cblxuICAgIGdldCBzdGF0ZURpciAoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLm1hcC5nZXQoXCJzdGF0ZURpclwiKSA/PyBcIi5naXRsYWItY2ktbG9jYWxcIikucmVwbGFjZSgvXFwvJC8sIFwiXCIpO1xuICAgIH1cblxuICAgIGdldCBob21lICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gKHRoaXMubWFwLmdldChcImhvbWVcIikgPz8gcHJvY2Vzcy5lbnYuSE9NRSA/PyBcIlwiKS5yZXBsYWNlKC9cXC8kLywgXCJcIik7XG4gICAgfVxuXG4gICAgZ2V0IHZvbHVtZSAoKTogc3RyaW5nW10ge1xuICAgICAgICBjb25zdCB2YWwgPSB0aGlzLm1hcC5nZXQoXCJ2b2x1bWVcIikgPz8gW107XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsID09IFwic3RyaW5nXCIgPyB2YWwuc3BsaXQoXCIgXCIpIDogdmFsO1xuICAgIH1cblxuICAgIGdldCBuZXR3b3JrICgpOiBzdHJpbmdbXSB7XG4gICAgICAgIGNvbnN0IHZhbCA9IHRoaXMubWFwLmdldChcIm5ldHdvcmtcIikgPz8gW107XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsID09IFwic3RyaW5nXCIgPyB2YWwuc3BsaXQoXCIgXCIpIDogdmFsO1xuICAgIH1cblxuICAgIGdldCBleHRyYUhvc3QgKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgY29uc3QgdmFsID0gdGhpcy5tYXAuZ2V0KFwiZXh0cmFIb3N0XCIpID8/IFtdO1xuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbCA9PSBcInN0cmluZ1wiID8gdmFsLnNwbGl0KFwiIFwiKSA6IHZhbDtcbiAgICB9XG5cbiAgICBnZXQgaWdub3JlU2NoZW1hUGF0aHMgKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcImlnbm9yZVNjaGVtYVBhdGhzXCIpID8/IEFyZ3YuZGVmYXVsdC5pZ25vcmVTY2hlbWFQYXRocztcbiAgICB9XG5cbiAgICBnZXQgcHVsbFBvbGljeSAoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcInB1bGxQb2xpY3lcIikgPz8gXCJpZi1ub3QtcHJlc2VudFwiO1xuICAgIH1cblxuICAgIGdldCByZW1vdGVWYXJpYWJsZXMgKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJyZW1vdGVWYXJpYWJsZXNcIik7XG4gICAgfVxuXG4gICAgZ2V0IHZhcmlhYmxlICgpOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSB7XG4gICAgICAgIGNvbnN0IHZhbCA9IHRoaXMubWFwLmdldChcInZhcmlhYmxlXCIpO1xuICAgICAgICBjb25zdCB2YXJpYWJsZXM6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9ID0ge307XG4gICAgICAgIGNvbnN0IHBhaXJzID0gdHlwZW9mIHZhbCA9PSBcInN0cmluZ1wiID8gdmFsLnNwbGl0KFwiIFwiKSA6IHZhbDtcbiAgICAgICAgKHBhaXJzID8/IFtdKS5mb3JFYWNoKCh2YXJpYWJsZVBhaXI6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXhlYyA9IC8oPzxrZXk+XFx3Kj8pKD0pKD88dmFsdWU+KC58XFxufFxccikqKS8uZXhlYyh2YXJpYWJsZVBhaXIpO1xuICAgICAgICAgICAgaWYgKGV4ZWM/Lmdyb3Vwcz8ua2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyaWFibGVzW2V4ZWMuZ3JvdXBzLmtleV0gPSBleGVjPy5ncm91cHM/LnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHZhcmlhYmxlcztcbiAgICB9XG5cbiAgICBnZXQgdW5zZXRWYXJpYWJsZXMgKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcInVuc2V0VmFyaWFibGVcIikgPz8gW107XG4gICAgfVxuXG4gICAgZ2V0IG1hbnVhbCAoKTogc3RyaW5nW10ge1xuICAgICAgICBjb25zdCB2YWwgPSB0aGlzLm1hcC5nZXQoXCJtYW51YWxcIikgPz8gW107XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsID09IFwic3RyaW5nXCIgPyB2YWwuc3BsaXQoXCIgXCIpIDogdmFsO1xuICAgIH1cblxuICAgIGdldCBqb2IgKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcImpvYlwiKSA/PyBbXTtcbiAgICB9XG5cbiAgICBnZXQgYXV0b0NvbXBsZXRpbmcgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwiYXV0b0NvbXBsZXRpbmdcIikgPz8gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0IGNsZWFudXAgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwiY2xlYW51cFwiKSA/PyB0cnVlO1xuICAgIH1cblxuICAgIGdldCBxdWlldCAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJxdWlldFwiKSA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgdW1hc2sgKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBUT0RPOiBkZWZhdWx0IHRvIGZhbHNlIGluIDUueC54XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJ1bWFza1wiKSA/PyB0cnVlO1xuICAgIH1cblxuICAgIGdldCBwcml2aWxlZ2VkICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcInByaXZpbGVnZWRcIikgPz8gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0IHVsaW1pdCAoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIGNvbnN0IHVsaW1pdCA9IHRoaXMubWFwLmdldChcInVsaW1pdFwiKTtcbiAgICAgICAgaWYgKCF1bGltaXQpIHJldHVybiBudWxsO1xuICAgICAgICByZXR1cm4gdWxpbWl0O1xuICAgIH1cblxuICAgIGdldCBuZWVkcyAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJuZWVkc1wiKSA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgb25seU5lZWRzICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcIm9ubHlOZWVkc1wiKSA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgc3RhZ2UgKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwic3RhZ2VcIikgPz8gbnVsbDtcbiAgICB9XG5cbiAgICBnZXQgY29tcGxldGlvbiAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJjb21wbGV0aW9uXCIpID8/IGZhbHNlO1xuICAgIH1cblxuICAgIGdldCBsaXN0ICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcImxpc3RcIikgPz8gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0IGxpc3RBbGwgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwibGlzdEFsbFwiKSA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgbGlzdEpzb24gKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwibGlzdEpzb25cIikgPz8gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0IGxpc3RDc3YgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwibGlzdENzdlwiKSA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgbGlzdENzdkFsbCAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJsaXN0Q3N2QWxsXCIpID8/IGZhbHNlO1xuICAgIH1cblxuICAgIGdldCBwcmV2aWV3ICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcInByZXZpZXdcIikgPz8gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0IHNoZWxsSXNvbGF0aW9uICgpOiBib29sZWFuIHtcbiAgICAgICAgLy8gVE9ETzogZGVmYXVsdCB0byB0cnVlIGluIDUueC54XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJzaGVsbElzb2xhdGlvblwiKSA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgZmV0Y2hJbmNsdWRlcyAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJmZXRjaEluY2x1ZGVzXCIpID8/IGZhbHNlO1xuICAgIH1cblxuICAgIGdldCBtb3VudENhY2hlICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcIm1vdW50Q2FjaGVcIikgPz8gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0IGFydGlmYWN0c1RvU291cmNlICgpOiBib29sZWFuIHtcbiAgICAgICAgLy8gVE9ETzogZGVmYXVsdCB0byBmYWxzZSBpbiA1LngueFxuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwiYXJ0aWZhY3RzVG9Tb3VyY2VcIikgPz8gdHJ1ZTtcbiAgICB9XG5cbiAgICBnZXQgc2hvd1RpbWVzdGFtcHMgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwidGltZXN0YW1wc1wiKSA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgbWF4Sm9iTmFtZVBhZGRpbmcgKCk6IG51bWJlciB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwibWF4Sm9iTmFtZVBhZGRpbmdcIikgPz8gbnVsbDtcbiAgICB9XG5cbiAgICBnZXQgY29udGFpbmVyTWFjQWRkcmVzcyAoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJjb250YWluZXJNYWNBZGRyZXNzXCIpID8/IG51bGw7XG4gICAgfVxuXG4gICAgZ2V0IGNvbnRhaW5lckVtdWxhdGUgKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwiY29udGFpbmVyRW11bGF0ZVwiKSA/PyBudWxsO1xuICAgIH1cblxuICAgIGdldCBjb25jdXJyZW5jeSAoKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgICAgIGNvbnN0IGNvbmN1cnJlbmN5ID0gdGhpcy5tYXAuZ2V0KFwiY29uY3VycmVuY3lcIik7XG4gICAgICAgIGlmICghY29uY3VycmVuY3kpIHJldHVybiBudWxsO1xuICAgICAgICByZXR1cm4gTnVtYmVyKGNvbmN1cnJlbmN5KTtcbiAgICB9XG5cbiAgICBnZXQgY29udGFpbmVyRXhlY3V0YWJsZSAoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcImNvbnRhaW5lckV4ZWN1dGFibGVcIikgPz8gXCJkb2NrZXJcIjtcbiAgICB9XG5cbiAgICBnZXQganNvblNjaGVtYVZhbGlkYXRpb24gKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwianNvblNjaGVtYVZhbGlkYXRpb25cIikgPz8gdHJ1ZTtcbiAgICB9XG5cbiAgICBnZXQgc2hlbGxFeGVjdXRvck5vSW1hZ2UgKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBUT0RPOiBkZWZhdWx0IHRvIGZhbHNlIGluIDUueC54XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJzaGVsbEV4ZWN1dG9yTm9JbWFnZVwiKSA/PyB0cnVlO1xuICAgIH1cblxuICAgIGdldCBmb3JjZVNoZWxsRXhlY3V0b3IgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KFwiZm9yY2VTaGVsbEV4ZWN1dG9yXCIpID8/IGZhbHNlO1xuICAgIH1cblxuICAgIGdldCBkZWZhdWx0SW1hZ2UgKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJkZWZhdWx0SW1hZ2VcIikgPz8gXCJkb2NrZXIuaW8vcnVieTozLjFcIjtcbiAgICB9XG5cbiAgICBnZXQgZGVmYXVsdEltYWdlRXhwbGljaXRseVNldCAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcC5nZXQoXCJkZWZhdWx0SW1hZ2VcIikgPz8gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2V0IG1heGltdW1JbmNsdWRlcyAoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcIm1heGltdW1JbmNsdWRlc1wiKSA/PyAxNTA7IC8vIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL2FkbWluaXN0cmF0aW9uL3NldHRpbmdzL2NvbnRpbnVvdXNfaW50ZWdyYXRpb24uaHRtbCNtYXhpbXVtLWluY2x1ZGVzXG4gICAgfVxuXG4gICAgZ2V0IGNoaWxkUGlwZWxpbmVEZXB0aCAoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwLmdldChcImNoaWxkUGlwZWxpbmVEZXB0aFwiKTtcbiAgICB9XG59XG4iXX0=