gitlab-ci-local 4.65.1 → 4.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/mutex.js DELETED
@@ -1,20 +0,0 @@
1
- export class Mutex {
2
- static locks = new Set();
3
- static async waitForLock(key) {
4
- return new Promise((resolve) => {
5
- const intervalKey = setInterval(() => {
6
- if (!Mutex.locks.has(key)) {
7
- clearInterval(intervalKey);
8
- return resolve();
9
- }
10
- }, 10);
11
- });
12
- }
13
- static async exclusive(key, cb) {
14
- await Mutex.waitForLock(key);
15
- Mutex.locks.add(key);
16
- await cb();
17
- Mutex.locks.delete(key);
18
- }
19
- }
20
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXV0ZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtdXRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLE9BQU8sS0FBSztJQUVOLE1BQU0sQ0FBVSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUVsQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBRSxHQUFXO1FBQ3pDLE9BQU8sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNqQyxNQUFNLFdBQVcsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO2dCQUNqQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDeEIsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO29CQUMzQixPQUFPLE9BQU8sRUFBRSxDQUFDO2dCQUNyQixDQUFDO1lBQ0wsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ1gsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUUsR0FBVyxFQUFFLEVBQXVCO1FBQ3hELE1BQU0sS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM3QixLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNyQixNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ1gsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBNdXRleCB7XG5cbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBsb2NrcyA9IG5ldyBTZXQoKTtcblxuICAgIHByaXZhdGUgc3RhdGljIGFzeW5jIHdhaXRGb3JMb2NrIChrZXk6IHN0cmluZykge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGludGVydmFsS2V5ID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghTXV0ZXgubG9ja3MuaGFzKGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbEtleSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgMTApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgYXN5bmMgZXhjbHVzaXZlIChrZXk6IHN0cmluZywgY2I6ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgICAgICAgYXdhaXQgTXV0ZXgud2FpdEZvckxvY2soa2V5KTtcbiAgICAgICAgTXV0ZXgubG9ja3MuYWRkKGtleSk7XG4gICAgICAgIGF3YWl0IGNiKCk7XG4gICAgICAgIE11dGV4LmxvY2tzLmRlbGV0ZShrZXkpO1xuICAgIH1cblxufVxuIl19
package/src/parallel.js DELETED
@@ -1,46 +0,0 @@
1
- import assert from "assert";
2
- import deepExtend from "deep-extend";
3
- export function isPlainParallel(jobData) {
4
- return Number.isInteger(jobData.parallel);
5
- }
6
- export function matrixVariablesList(jobData, jobName) {
7
- if (isPlainParallel(jobData)) {
8
- return Array(jobData.parallel).fill(null);
9
- }
10
- if (jobData?.parallel?.matrix == null) {
11
- return [null];
12
- }
13
- assert(Array.isArray(jobData.parallel.matrix), `${jobName} parallel.matrix is not an array`);
14
- const matrixVariables = [];
15
- // Expand string value to array of values
16
- for (const m of jobData.parallel.matrix) {
17
- for (const [key, value] of Object.entries(m)) {
18
- m[key] = Array.isArray(value) ? value : [value];
19
- }
20
- }
21
- // Generate variables in while loop by expanding the matrix
22
- const deep = deepExtend({}, jobData);
23
- for (const m of deep.parallel.matrix) {
24
- let i = 0;
25
- let inner = [];
26
- while (Object.keys(m).length > 0 && i < 100) {
27
- const keys = Object.keys(m);
28
- const key = keys[0];
29
- const values = m[key];
30
- delete m[key];
31
- const innerClone = inner.length > 0 ? [...inner] : [{}];
32
- inner = [];
33
- for (const clone of innerClone) {
34
- for (const v of values) {
35
- const matrixVariable = { ...clone };
36
- matrixVariable[key] = v;
37
- inner.push(matrixVariable);
38
- }
39
- }
40
- i++;
41
- }
42
- matrixVariables.push(...inner);
43
- }
44
- return matrixVariables;
45
- }
46
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyYWxsZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwYXJhbGxlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxVQUFVLE1BQU0sYUFBYSxDQUFDO0FBRXJDLE1BQU0sVUFBVSxlQUFlLENBQUUsT0FBWTtJQUN6QyxPQUFPLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRCxNQUFNLFVBQVUsbUJBQW1CLENBQUUsT0FBWSxFQUFFLE9BQWU7SUFDOUQsSUFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUMzQixPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFDRCxJQUFJLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3BDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNsQixDQUFDO0lBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxHQUFHLE9BQU8sa0NBQWtDLENBQUMsQ0FBQztJQUU3RixNQUFNLGVBQWUsR0FBOEIsRUFBRSxDQUFDO0lBRXRELHlDQUF5QztJQUN6QyxLQUFLLE1BQU0sQ0FBQyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdEMsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMzQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BELENBQUM7SUFDTCxDQUFDO0lBRUQsMkRBQTJEO0lBQzNELE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDckMsS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVWLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNmLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUMxQyxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwQixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdEIsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFZCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3hELEtBQUssR0FBRyxFQUFFLENBQUM7WUFFWCxLQUFLLE1BQU0sS0FBSyxJQUFJLFVBQVUsRUFBRSxDQUFDO2dCQUM3QixLQUFLLE1BQU0sQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDO29CQUNyQixNQUFNLGNBQWMsR0FBNEIsRUFBQyxHQUFHLEtBQUssRUFBQyxDQUFDO29CQUMzRCxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUN4QixLQUFLLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUMvQixDQUFDO1lBQ0wsQ0FBQztZQUNELENBQUMsRUFBRSxDQUFDO1FBQ1IsQ0FBQztRQUNELGVBQWUsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsT0FBTyxlQUFlLENBQUM7QUFDM0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IGRlZXBFeHRlbmQgZnJvbSBcImRlZXAtZXh0ZW5kXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1BsYWluUGFyYWxsZWwgKGpvYkRhdGE6IGFueSkge1xuICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKGpvYkRhdGEucGFyYWxsZWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0cml4VmFyaWFibGVzTGlzdCAoam9iRGF0YTogYW55LCBqb2JOYW1lOiBzdHJpbmcpOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfVtdIHwgbnVsbFtdIHtcbiAgICBpZiAoaXNQbGFpblBhcmFsbGVsKGpvYkRhdGEpKSB7XG4gICAgICAgIHJldHVybiBBcnJheShqb2JEYXRhLnBhcmFsbGVsKS5maWxsKG51bGwpO1xuICAgIH1cbiAgICBpZiAoam9iRGF0YT8ucGFyYWxsZWw/Lm1hdHJpeCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBbbnVsbF07XG4gICAgfVxuICAgIGFzc2VydChBcnJheS5pc0FycmF5KGpvYkRhdGEucGFyYWxsZWwubWF0cml4KSwgYCR7am9iTmFtZX0gcGFyYWxsZWwubWF0cml4IGlzIG5vdCBhbiBhcnJheWApO1xuXG4gICAgY29uc3QgbWF0cml4VmFyaWFibGVzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfVtdID0gW107XG5cbiAgICAvLyBFeHBhbmQgc3RyaW5nIHZhbHVlIHRvIGFycmF5IG9mIHZhbHVlc1xuICAgIGZvciAoY29uc3QgbSBvZiBqb2JEYXRhLnBhcmFsbGVsLm1hdHJpeCkge1xuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhtKSkge1xuICAgICAgICAgICAgbVtrZXldID0gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFt2YWx1ZV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBHZW5lcmF0ZSB2YXJpYWJsZXMgaW4gd2hpbGUgbG9vcCBieSBleHBhbmRpbmcgdGhlIG1hdHJpeFxuICAgIGNvbnN0IGRlZXAgPSBkZWVwRXh0ZW5kKHt9LCBqb2JEYXRhKTtcbiAgICBmb3IgKGNvbnN0IG0gb2YgZGVlcC5wYXJhbGxlbC5tYXRyaXgpIHtcbiAgICAgICAgbGV0IGkgPSAwO1xuXG4gICAgICAgIGxldCBpbm5lciA9IFtdO1xuICAgICAgICB3aGlsZSAoT2JqZWN0LmtleXMobSkubGVuZ3RoID4gMCAmJiBpIDwgMTAwKSB7XG4gICAgICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMobSk7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSBrZXlzWzBdO1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gbVtrZXldO1xuICAgICAgICAgICAgZGVsZXRlIG1ba2V5XTtcblxuICAgICAgICAgICAgY29uc3QgaW5uZXJDbG9uZSA9IGlubmVyLmxlbmd0aCA+IDAgPyBbLi4uaW5uZXJdIDogW3t9XTtcbiAgICAgICAgICAgIGlubmVyID0gW107XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgY2xvbmUgb2YgaW5uZXJDbG9uZSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgdiBvZiB2YWx1ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF0cml4VmFyaWFibGU6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9ID0gey4uLmNsb25lfTtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4VmFyaWFibGVba2V5XSA9IHY7XG4gICAgICAgICAgICAgICAgICAgIGlubmVyLnB1c2gobWF0cml4VmFyaWFibGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgICAgICBtYXRyaXhWYXJpYWJsZXMucHVzaCguLi5pbm5lcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1hdHJpeFZhcmlhYmxlcztcbn1cbiJdfQ==
@@ -1,387 +0,0 @@
1
- import { Utils } from "./utils.js";
2
- import fs from "fs-extra";
3
- import assert, { AssertionError } from "assert";
4
- import chalk from "chalk-template";
5
- import { Parser } from "./parser.js";
6
- import axios from "axios";
7
- import path from "path";
8
- import semver from "semver";
9
- import { RE2JS } from "re2js";
10
- export class ParserIncludes {
11
- static count = 0;
12
- static resetCount() {
13
- this.count = 0;
14
- }
15
- static normalizeTriggerInclude(gitlabData, opts) {
16
- const { writeStreams } = opts;
17
- for (const [jobName, jobData] of Object.entries(gitlabData ?? {})) {
18
- if (typeof jobData.trigger?.include === "string") {
19
- jobData.trigger.include = [{
20
- local: jobData.trigger.include,
21
- }];
22
- }
23
- else if (jobData.trigger?.project) {
24
- writeStreams.memoStdout(chalk `{bgYellowBright WARN } The job: \`{blueBright ${jobName}}\` will be no-op. Multi-project pipeline is not supported by gitlab-ci-local\n`);
25
- }
26
- }
27
- }
28
- static async init(gitlabData, opts) {
29
- const { argv } = opts;
30
- this.count++;
31
- assert(this.count <= opts.maximumIncludes + 1, // 1st init call is not counted
32
- chalk `This GitLab CI configuration is invalid: Maximum of {blueBright ${opts.maximumIncludes}} nested includes are allowed!. This limit can be increased with the --maximum-includes cli flags.`);
33
- let includeDatas = [];
34
- const promises = [];
35
- const { stateDir, cwd, fetchIncludes, gitData, expandVariables } = opts;
36
- // cache the parsed component, because parseIncludeComponent is expensive and we would call it twice otherwise
37
- const componentParseCache = new Map();
38
- const include = this.expandInclude(gitlabData?.include, opts.variables);
39
- this.normalizeTriggerInclude(gitlabData, opts);
40
- // Find files to fetch from remote and place in .gitlab-ci-local/includes
41
- for (const [index, value] of include.entries()) {
42
- if (value["rules"]) {
43
- const include_rules = value["rules"];
44
- const rulesResult = Utils.getRulesResult({ argv, cwd, rules: include_rules, variables: opts.variables }, gitData);
45
- if (rulesResult.when === "never") {
46
- continue;
47
- }
48
- }
49
- if (value["file"]) {
50
- for (const fileValue of Array.isArray(value["file"]) ? value["file"] : [value["file"]]) {
51
- promises.push(this.downloadIncludeProjectFile(cwd, stateDir, value["project"], value["ref"] || "HEAD", fileValue, gitData, fetchIncludes));
52
- }
53
- }
54
- else if (value["template"]) {
55
- const { project, ref, file, domain } = this.covertTemplateToProjectFile(value["template"]);
56
- const url = `https://${domain}/${project}/-/raw/${ref}/${file}`;
57
- promises.push(this.downloadIncludeRemote(cwd, stateDir, url, fetchIncludes));
58
- }
59
- else if (value["remote"]) {
60
- promises.push(this.downloadIncludeRemote(cwd, stateDir, value["remote"], fetchIncludes));
61
- }
62
- else if (value["component"]) {
63
- const component = this.parseIncludeComponent(value["component"], gitData);
64
- componentParseCache.set(index, component);
65
- if (!component.isLocal) {
66
- promises.push(this.downloadIncludeComponent(cwd, stateDir, component.projectPath, component.ref, component.name, gitData, fetchIncludes));
67
- }
68
- }
69
- }
70
- await Promise.all(promises);
71
- for (const [index, value] of include.entries()) {
72
- if (value["rules"]) {
73
- const include_rules = value["rules"];
74
- const rulesResult = Utils.getRulesResult({ argv, cwd, rules: include_rules, variables: opts.variables }, gitData);
75
- if (rulesResult.when === "never") {
76
- continue;
77
- }
78
- }
79
- if (value["local"]) {
80
- validateIncludeLocal(value["local"]);
81
- const files = await resolveIncludeLocal(value["local"], cwd);
82
- if (files.length == 0) {
83
- throw new AssertionError({ message: `Local include file cannot be found ${value["local"]}` });
84
- }
85
- for (const localFile of files) {
86
- const content = await Parser.loadYaml(localFile, { inputs: value.inputs ?? {} }, expandVariables);
87
- includeDatas = includeDatas.concat(await this.init(content, opts));
88
- }
89
- }
90
- else if (value["project"]) {
91
- for (const fileValue of Array.isArray(value["file"]) ? value["file"] : [value["file"]]) {
92
- const fileDoc = await Parser.loadYaml(`${cwd}/${stateDir}/includes/${gitData.remote.host}/${value["project"]}/${value["ref"] || "HEAD"}/${fileValue}`, { inputs: value.inputs || {} }, expandVariables);
93
- // Expand local includes inside a "project"-like include
94
- fileDoc["include"] = this.expandInnerLocalIncludes(fileDoc["include"], value["project"], value["ref"], opts);
95
- includeDatas = includeDatas.concat(await this.init(fileDoc, opts));
96
- }
97
- }
98
- else if (value["component"]) {
99
- const component = componentParseCache.get(index);
100
- assert(component !== undefined, `Internal error, component parse cache missing entry [${index}]`);
101
- // Gitlab allows two different file paths to include a component
102
- const files = [`${component.name}.yml`, `${component.name}/template.yml`];
103
- let file = null;
104
- for (const f of files) {
105
- let searchPath = `${cwd}/${f}`;
106
- if (!component.isLocal) {
107
- searchPath = `${cwd}/${stateDir}/includes/${gitData.remote.host}/${component.projectPath}/${component.ref}/${f}`;
108
- }
109
- if (fs.existsSync(searchPath)) {
110
- file = searchPath;
111
- }
112
- }
113
- assert(file !== null, `This GitLab CI configuration is invalid: component: \`${value["component"]}\`. One of the files [${files}] must exist in \`${component.domain}` +
114
- (component.port ? `:${component.port}` : "") + `/${component.projectPath}\``);
115
- const fileDoc = await Parser.loadYaml(file, { inputs: value.inputs || {} }, expandVariables);
116
- // Expand local includes inside to a "project"-like include
117
- fileDoc["include"] = this.expandInnerLocalIncludes(fileDoc["include"], component.projectPath, component.ref, opts);
118
- includeDatas = includeDatas.concat(await this.init(fileDoc, opts));
119
- }
120
- else if (value["template"]) {
121
- const { project, ref, file, domain } = this.covertTemplateToProjectFile(value["template"]);
122
- const fsUrl = Utils.fsUrl(`https://${domain}/${project}/-/raw/${ref}/${file}`);
123
- const fileDoc = await Parser.loadYaml(`${cwd}/${stateDir}/includes/${fsUrl}`, { inputs: value.inputs || {} }, expandVariables);
124
- includeDatas = includeDatas.concat(await this.init(fileDoc, opts));
125
- }
126
- else if (value["remote"]) {
127
- const fsUrl = Utils.fsUrl(value["remote"]);
128
- const fileDoc = await Parser.loadYaml(`${cwd}/${stateDir}/includes/${fsUrl}`, { inputs: value.inputs || {} }, expandVariables);
129
- includeDatas = includeDatas.concat(await this.init(fileDoc, opts));
130
- }
131
- else {
132
- throw new AssertionError({ message: `Didn't understand include ${JSON.stringify(value)}` });
133
- }
134
- }
135
- includeDatas.push(gitlabData);
136
- return includeDatas;
137
- }
138
- static expandInclude(i, variables) {
139
- let include = i || [];
140
- if (include && include.length == null) {
141
- include = [i];
142
- }
143
- if (typeof include === "string") {
144
- include = [include];
145
- }
146
- for (const [index, entry] of Object.entries(include)) {
147
- if (typeof entry === "string" && (entry.startsWith("https:") || entry.startsWith("http:"))) {
148
- include[index] = { "remote": entry };
149
- }
150
- else if (typeof entry === "string") {
151
- include[index] = { "local": entry };
152
- }
153
- else {
154
- include[index] = entry;
155
- }
156
- }
157
- for (const entry of include) {
158
- for (const [key, value] of Object.entries(entry)) {
159
- if (Array.isArray(value)) {
160
- entry[key] = value.map((v) => Utils.expandText(v, variables));
161
- }
162
- else {
163
- entry[key] = Utils.expandText(value, variables);
164
- }
165
- }
166
- }
167
- return include;
168
- }
169
- static covertTemplateToProjectFile(template) {
170
- return {
171
- domain: "gitlab.com",
172
- project: "gitlab-org/gitlab",
173
- ref: "HEAD",
174
- file: `lib/gitlab/ci/templates/${template}`,
175
- };
176
- }
177
- static parseIncludeComponent(component, gitData) {
178
- assert(!component.includes("://"), `This GitLab CI configuration is invalid: component: \`${component}\` should not contain protocol`);
179
- const pattern = /(?<domain>[^/:\s]+)(:(?<port>\d+))?\/(?<projectPath>.+)\/(?<componentName>[^@]+)@(?<ref>.+)/; // https://regexr.com/7v7hm
180
- const gitRemoteMatch = pattern.exec(component);
181
- if (gitRemoteMatch?.groups == null)
182
- throw new Error(`This is a bug, please create a github issue if this is something you're expecting to work. input: ${component}`);
183
- const { domain, projectPath, port } = gitRemoteMatch.groups;
184
- let ref = gitRemoteMatch.groups["ref"];
185
- const isLocalComponent = projectPath === `${gitData.remote.group}/${gitData.remote.project}` && ref === gitData.commit.SHA;
186
- if (!isLocalComponent) {
187
- const semanticVersionRangesPattern = /^\d+(\.\d+)?$/;
188
- if (ref == "~latest" || semanticVersionRangesPattern.test(ref)) {
189
- // https://docs.gitlab.com/ci/components/#semantic-version-ranges
190
- let stdout;
191
- if (gitData.remote.schema == "git" || gitData.remote.schema == "ssh") {
192
- stdout = Utils.syncSpawn(["git", "ls-remote", "--tags", `git@${domain}:${projectPath}`]).stdout;
193
- }
194
- else {
195
- stdout = Utils.syncSpawn(["git", "ls-remote", "--tags", `${gitData.remote.schema}://${domain}:${port ?? 443}/${projectPath}.git`]).stdout;
196
- }
197
- assert(stdout);
198
- const tags = stdout
199
- .split("\n")
200
- .map((line) => {
201
- return line
202
- .split("\t")[1]
203
- .split("/")[2];
204
- });
205
- const _ref = resolveSemanticVersionRange(ref, tags);
206
- assert(_ref, `This GitLab CI configuration is invalid: component: \`${component}\` - The ref (${ref}) is invalid`);
207
- ref = _ref;
208
- }
209
- }
210
- return {
211
- domain: domain,
212
- port: port,
213
- projectPath: projectPath,
214
- name: `templates/${gitRemoteMatch.groups["componentName"]}`,
215
- ref: ref,
216
- isLocal: isLocalComponent,
217
- };
218
- }
219
- // Expand local includes inside to a "project"-like include
220
- static expandInnerLocalIncludes(fileIncludes, projectPath, ref, opts) {
221
- const { argv } = opts;
222
- const updatedIncludes = this.expandInclude(fileIncludes, opts.variables);
223
- updatedIncludes.forEach((inner, i) => {
224
- if (!inner["local"])
225
- return;
226
- if (inner["rules"]) {
227
- const rulesResult = Utils.getRulesResult({ argv, cwd: opts.cwd, variables: opts.variables, rules: inner["rules"] }, opts.gitData);
228
- if (rulesResult.when === "never") {
229
- return;
230
- }
231
- }
232
- updatedIncludes[i] = {
233
- project: projectPath,
234
- file: inner["local"].replace(/^\//, ""),
235
- ref: ref,
236
- inputs: inner.inputs || {},
237
- };
238
- });
239
- return updatedIncludes;
240
- }
241
- static async downloadIncludeRemote(cwd, stateDir, url, fetchIncludes) {
242
- const fsUrl = Utils.fsUrl(url);
243
- try {
244
- const target = `${cwd}/${stateDir}/includes/${fsUrl}`;
245
- if (await fs.pathExists(target) && !fetchIncludes)
246
- return;
247
- const axiosConfig = {
248
- headers: { "User-Agent": "gitlab-ci-local" },
249
- ...Utils.getAxiosProxyConfig(),
250
- };
251
- const res = await axios.get(url, axiosConfig);
252
- await fs.outputFile(target, res.data);
253
- }
254
- catch (e) {
255
- throw new AssertionError({ message: `Remote include could not be fetched ${url}\n${e}` });
256
- }
257
- }
258
- static async downloadIncludeProjectFile(cwd, stateDir, project, ref, file, gitData, fetchIncludes) {
259
- const remote = gitData.remote;
260
- const normalizedFile = file.replace(/^\/+/, "");
261
- let tmpDir = null;
262
- try {
263
- const target = `${stateDir}/includes/${remote.host}/${project}/${ref}`;
264
- if (await fs.pathExists(`${cwd}/${target}/${normalizedFile}`) && !fetchIncludes)
265
- return;
266
- if (remote.schema.startsWith("http")) {
267
- const ext = "tmp-" + Math.random();
268
- await fs.mkdirp(path.dirname(`${cwd}/${target}/${normalizedFile}`));
269
- tmpDir = `${cwd}/${target}.${ext}`;
270
- const gitCloneBranch = (ref === "HEAD") ? "" : `--branch ${ref}`;
271
- await Utils.bashMulti([
272
- `cd ${cwd}/${stateDir}`,
273
- `git clone ${gitCloneBranch} -n --depth=1 --filter=tree:0 ${remote.schema}://${remote.host}:${remote.port}/${project}.git ${tmpDir}`,
274
- `cd ${tmpDir}`,
275
- `git sparse-checkout set --no-cone ${normalizedFile}`,
276
- "git checkout",
277
- `cd ${cwd}/${stateDir}`,
278
- `cp ${tmpDir}/${normalizedFile} ${cwd}/${target}/${normalizedFile}`,
279
- ], cwd);
280
- }
281
- else {
282
- await fs.mkdirp(`${cwd}/${target}`);
283
- await Utils.bash(`set -eou pipefail; git archive --remote=ssh://git@${remote.host}:${remote.port}/${project}.git ${ref} ${normalizedFile} | tar -f - -xC ${target}/`, cwd);
284
- }
285
- }
286
- catch (e) {
287
- throw new AssertionError({ message: `Project include could not be fetched { project: ${project}, ref: ${ref}, file: ${normalizedFile} }\n${e}` });
288
- }
289
- finally {
290
- if (tmpDir !== null) {
291
- // always cleanup temporary directory (if created)
292
- await fs.rm(tmpDir, { recursive: true, force: true });
293
- }
294
- }
295
- }
296
- static async downloadIncludeComponent(cwd, stateDir, project, ref, componentName, gitData, fetchIncludes) {
297
- const remote = gitData.remote;
298
- const files = [`${componentName}.yml`, `${componentName}/template.yml`];
299
- let tmpDir = null;
300
- try {
301
- const target = `${stateDir}/includes/${remote.host}/${project}/${ref}`;
302
- if (!fetchIncludes && (await fs.pathExists(`${cwd}/${target}/${files[0]}`) || await fs.pathExists(`${cwd}/${target}/${files[1]}`)))
303
- return;
304
- if (remote.schema.startsWith("http")) {
305
- const ext = "tmp-" + Math.random();
306
- await fs.mkdirp(path.dirname(`${cwd}/${target}/templates`));
307
- tmpDir = `${cwd}/${target}.${ext}`;
308
- const gitCloneBranch = (ref === "HEAD") ? "" : `--branch ${ref}`;
309
- await Utils.bashMulti([
310
- `cd ${cwd}/${stateDir}`,
311
- `git clone ${gitCloneBranch} -n --depth=1 --filter=tree:0 ${remote.schema}://${remote.host}:${remote.port}/${project}.git ${tmpDir}`,
312
- `cd ${tmpDir}`,
313
- `git sparse-checkout set --no-cone ${files[0]} ${files[1]}`,
314
- "git checkout",
315
- `cd ${cwd}/${stateDir}`,
316
- `mkdir -p ${tmpDir}/templates`, // create templates subdir (if it doesn't exist), as the check out may not create it
317
- `cp -r ${tmpDir}/templates ${cwd}/${target}`,
318
- ], cwd);
319
- }
320
- else {
321
- // git archive fails if the paths do not exist, to work around this we use a wildcard "templates/component*.yml"
322
- // this resolves to either "templates/component.yml" or "templates/component/template.yml"
323
- // if both exist "templates/component.yml" will be pulled
324
- // Drawback: also pulls all other .yml files from templates/component/ directory
325
- const componentWildcard = `${componentName}*.yml`;
326
- await fs.mkdirp(`${cwd}/${target}`);
327
- await Utils.bash(`set -eou pipefail; git archive --remote=ssh://git@${remote.host}:${remote.port}/${project}.git ${ref} ${componentWildcard} | tar -f - -xC ${target}/`, cwd);
328
- }
329
- }
330
- catch (e) {
331
- throw new AssertionError({ message: `Component include could not be fetched { project: ${project}, ref: ${ref}, file: ${files} }\n${e}` });
332
- }
333
- finally {
334
- if (tmpDir !== null) {
335
- // always cleanup temporary directory (if created)
336
- await fs.rm(tmpDir, { recursive: true, force: true });
337
- }
338
- }
339
- }
340
- static memoLocalRepoFiles = (() => {
341
- const cache = new Map();
342
- return async (path) => {
343
- let result = cache.get(path);
344
- if (typeof result !== "undefined")
345
- return result;
346
- result = (await Utils.getTrackedFiles(path)).map(p => `${path}/${p}`);
347
- cache.set(path, result);
348
- return result;
349
- };
350
- })();
351
- }
352
- export function validateIncludeLocal(filePath) {
353
- assert(!filePath.startsWith("./"), `\`${filePath}\` for include:local is invalid. Gitlab does not support relative path (ie. cannot start with \`./\`).`);
354
- assert(!filePath.includes(".."), `\`${filePath}\` for include:local is invalid. Gitlab does not support directory traversal.`);
355
- }
356
- export function resolveSemanticVersionRange(range, gitTags) {
357
- /** sorted list of tags thats compliant to semantic version where index 0 is the latest */
358
- const sanitizedSemverTags = semver.rsort(gitTags.filter(s => semver.valid(s)));
359
- const found = sanitizedSemverTags.find(t => {
360
- if (range == "~latest") {
361
- const semverParsed = semver.parse(t);
362
- assert(semverParsed);
363
- return (semverParsed.prerelease.length == 0 && semverParsed.build.length == 0);
364
- }
365
- else {
366
- return semver.satisfies(t, range);
367
- }
368
- });
369
- return found;
370
- }
371
- export async function resolveIncludeLocal(pattern, cwd) {
372
- const repoFiles = await ParserIncludes.memoLocalRepoFiles(cwd);
373
- if (!pattern.startsWith("/"))
374
- pattern = `/${pattern}`; // Ensure pattern starts with `/`
375
- pattern = `${cwd}${pattern}`;
376
- // escape all special regex metacharacters
377
- pattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
378
- // `**` matches anything
379
- const anything = ".*?";
380
- pattern = pattern.replace(/\\\*\\\*/g, anything);
381
- // `*` matches anything except for `/`
382
- const anything_but_not_slash = "([^/])*?";
383
- pattern = pattern.replace(/\\\*/g, anything_but_not_slash);
384
- const re2js = RE2JS.compile(`^${pattern}`);
385
- return repoFiles.filter((f) => re2js.matches(f));
386
- }
387
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyLWluY2x1ZGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicGFyc2VyLWluY2x1ZGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDakMsT0FBTyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRzFCLE9BQU8sTUFBTSxFQUFFLEVBQUMsY0FBYyxFQUFDLE1BQU0sUUFBUSxDQUFDO0FBQzlDLE9BQU8sS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ25DLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDbkMsT0FBTyxLQUEyQixNQUFNLE9BQU8sQ0FBQztBQUNoRCxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxPQUFPLENBQUM7QUF1QjVCLE1BQU0sT0FBTyxjQUFjO0lBQ2YsTUFBTSxDQUFDLEtBQUssR0FBVyxDQUFDLENBQUM7SUFFakMsTUFBTSxDQUFDLFVBQVU7UUFDYixJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNuQixDQUFDO0lBRU8sTUFBTSxDQUFDLHVCQUF1QixDQUFFLFVBQWUsRUFBRSxJQUErQjtRQUNwRixNQUFNLEVBQUMsWUFBWSxFQUFDLEdBQUcsSUFBSSxDQUFDO1FBQzVCLEtBQUssTUFBTSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFNLFVBQVUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ3JFLElBQUksT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDL0MsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsQ0FBQzt3QkFDdkIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTztxQkFDakMs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dEMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQztBQUVELE1BQU0sQ0FBQyxLQUFLLFVBQVUsbUJBQW1CLENBQUUsT0FBZSxFQUFFLEdBQVc7SUFDbkUsTUFBTSxTQUFTLEdBQUcsTUFBTSxjQUFjLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFL0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDO1FBQUUsT0FBTyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUMsQ0FBQyxpQ0FBaUM7SUFDeEYsT0FBTyxHQUFHLEdBQUcsR0FBRyxHQUFHLE9BQU8sRUFBRSxDQUFDO0lBRTdCLDBDQUEwQztJQUMxQyxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUV6RCx3QkFBd0I7SUFDeEIsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3ZCLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUVqRCxzQ0FBc0M7SUFDdEMsTUFBTSxzQkFBc0IsR0FBRyxVQUFVLENBQUM7SUFDMUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLHNCQUFzQixDQUFDLENBQUM7SUFFM0QsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDM0MsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBTSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QXJndn0gZnJvbSBcIi4vYXJndi5qc1wiO1xuaW1wb3J0IHtVdGlsc30gZnJvbSBcIi4vdXRpbHMuanNcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnMtZXh0cmFcIjtcbmltcG9ydCB7V3JpdGVTdHJlYW1zfSBmcm9tIFwiLi93cml0ZS1zdHJlYW1zLmpzXCI7XG5pbXBvcnQge0dpdERhdGF9IGZyb20gXCIuL2dpdC1kYXRhLmpzXCI7XG5pbXBvcnQgYXNzZXJ0LCB7QXNzZXJ0aW9uRXJyb3J9IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGstdGVtcGxhdGVcIjtcbmltcG9ydCB7UGFyc2VyfSBmcm9tIFwiLi9wYXJzZXIuanNcIjtcbmltcG9ydCBheGlvcywge0F4aW9zUmVxdWVzdENvbmZpZ30gZnJvbSBcImF4aW9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHNlbXZlciBmcm9tIFwic2VtdmVyXCI7XG5pbXBvcnQge1JFMkpTfSBmcm9tIFwicmUyanNcIjtcblxudHlwZSBQYXJzZXJJbmNsdWRlc0luaXRPcHRpb25zID0ge1xuICAgIGFyZ3Y6IEFyZ3Y7XG4gICAgY3dkOiBzdHJpbmc7XG4gICAgc3RhdGVEaXI6IHN0cmluZztcbiAgICB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcztcbiAgICBnaXREYXRhOiBHaXREYXRhO1xuICAgIGZldGNoSW5jbHVkZXM6IGJvb2xlYW47XG4gICAgdmFyaWFibGVzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfTtcbiAgICBleHBhbmRWYXJpYWJsZXM6IGJvb2xlYW47XG4gICAgbWF4aW11bUluY2x1ZGVzOiBudW1iZXI7XG59O1xuXG50eXBlIFBhcnNlZENvbXBvbmVudCA9IHtcbiAgICBkb21haW46IHN0cmluZztcbiAgICBwb3J0OiBzdHJpbmc7XG4gICAgcHJvamVjdFBhdGg6IHN0cmluZztcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgcmVmOiBzdHJpbmc7XG4gICAgaXNMb2NhbDogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBjbGFzcyBQYXJzZXJJbmNsdWRlcyB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgY291bnQ6IG51bWJlciA9IDA7XG5cbiAgICBzdGF0aWMgcmVzZXRDb3VudCAoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIG5vcm1hbGl6ZVRyaWdnZXJJbmNsdWRlIChnaXRsYWJEYXRhOiBhbnksIG9wdHM6IFBhcnNlckluY2x1ZGVzSW5pdE9wdGlvbnMpIHtcbiAgICAgICAgY29uc3Qge3dyaXRlU3RyZWFtc30gPSBvcHRzO1xuICAgICAgICBmb3IgKGNvbnN0IFtqb2JOYW1lLCBqb2JEYXRhXSBvZiBPYmplY3QuZW50cmllczxhbnk+KGdpdGxhYkRhdGEgPz8ge30pKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGpvYkRhdGEudHJpZ2dlcj8uaW5jbHVkZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIGpvYkRhdGEudHJpZ2dlci5pbmNsdWRlID0gW3tcbiAgICAgICAgICAgICAgICAgICAgbG9jYWw6IGpvYkRhdGEudHJpZ2dlci5pbmNsdWRlLFxuICAgICAgICAgICAgICAgIH0gXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoam9iRGF0YS50cmlnZ2VyPy5wcm9qZWN0KSB7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLm1lbW9TdGRvdXQoY2hhbGtge2JnWWVsbG93QnJpZ2h0ICBXQVJOIH0gVGhlIGpvYjogXFxge2JsdWVCcmlnaHQgJHtqb2JOYW1lfX1cXGAgd2lsbCBiZSBuby1vcC4gTXVsdGktcHJvamVjdCBwaXBlbGluZSBpcyBub3Qgc3VwcG9ydGVkIGJ5IGdpdGxhYi1jaS1sb2NhbFxcbmApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGFzeW5jIGluaXQgKGdpdGxhYkRhdGE6IGFueSwgb3B0czogUGFyc2VySW5jbHVkZXNJbml0T3B0aW9ucyk6IFByb21pc2U8YW55W10+IHtcbiAgICAgICAgY29uc3Qge2FyZ3Z9ID0gb3B0cztcbiAgICAgICAgdGhpcy5jb3VudCsrO1xuICAgICAgICBhc3NlcnQoXG4gICAgICAgICAgICB0aGlzLmNvdW50IDw9IG9wdHMubWF4aW11bUluY2x1ZGVzICsgMSwgLy8gMXN0IGluaXQgY2FsbCBpcyBub3QgY291bnRlZFxuICAgICAgICAgICAgY2hhbGtgVGhpcyBHaXRMYWIgQ0kgY29uZmlndXJhdGlvbiBpcyBpbnZhbGlkOiBNYXhpbXVtIG9mIHtibHVlQnJpZ2h0ICR7b3B0cy5tYXhpbXVtSW5jbHVkZXN9fSBuZXN0ZWQgaW5jbHVkZXMgYXJlIGFsbG93ZWQhLiBUaGlzIGxpbWl0IGNhbiBiZSBpbmNyZWFzZWQgd2l0aCB0aGUgLS1tYXhpbXVtLWluY2x1ZGVzIGNsaSBmbGFncy5gLFxuICAgICAgICApO1xuICAgICAgICBsZXQgaW5jbHVkZURhdGFzOiBhbnlbXSA9IFtdO1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgICAgICBjb25zdCB7c3RhdGVEaXIsIGN3ZCwgZmV0Y2hJbmNsdWRlcywgZ2l0RGF0YSwgZXhwYW5kVmFyaWFibGVzfSA9IG9wdHM7XG4gICAgICAgIC8vIGNhY2hlIHRoZSBwYXJzZWQgY29tcG9uZW50LCBiZWNhdXNlIHBhcnNlSW5jbHVkZUNvbXBvbmVudCBpcyBleHBlbnNpdmUgYW5kIHdlIHdvdWxkIGNhbGwgaXQgdHdpY2Ugb3RoZXJ3aXNlXG4gICAgICAgIGNvbnN0IGNvbXBvbmVudFBhcnNlQ2FjaGUgPSBuZXcgTWFwPG51bWJlciwgUGFyc2VkQ29tcG9uZW50PigpO1xuXG4gICAgICAgIGNvbnN0IGluY2x1ZGUgPSB0aGlzLmV4cGFuZEluY2x1ZGUoZ2l0bGFiRGF0YT8uaW5jbHVkZSwgb3B0cy52YXJpYWJsZXMpO1xuXG4gICAgICAgIHRoaXMubm9ybWFsaXplVHJpZ2dlckluY2x1ZGUoZ2l0bGFiRGF0YSwgb3B0cyk7XG4gICAgICAgIC8vIEZpbmQgZmlsZXMgdG8gZmV0Y2ggZnJvbSByZW1vdGUgYW5kIHBsYWNlIGluIC5naXRsYWItY2ktbG9jYWwvaW5jbHVkZXNcbiAgICAgICAgZm9yIChjb25zdCBbaW5kZXgsIHZhbHVlXSBvZiBpbmNsdWRlLmVudHJpZXMoKSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlW1wicnVsZXNcIl0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbmNsdWRlX3J1bGVzID0gdmFsdWVbXCJydWxlc1wiXTtcbiAgICAgICAgICAgICAgICBjb25zdCBydWxlc1Jlc3VsdCA9IFV0aWxzLmdldFJ1bGVzUmVzdWx0KHthcmd2LCBjd2QsIHJ1bGVzOiBpbmNsdWRlX3J1bGVzLCB2YXJpYWJsZXM6IG9wdHMudmFyaWFibGVzfSwgZ2l0RGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKHJ1bGVzUmVzdWx0LndoZW4gPT09IFwibmV2ZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWVbXCJmaWxlXCJdKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWxlVmFsdWUgb2YgQXJyYXkuaXNBcnJheSh2YWx1ZVtcImZpbGVcIl0pID8gdmFsdWVbXCJmaWxlXCJdIDogW3ZhbHVlW1wiZmlsZVwiXV0pIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLmRvd25sb2FkSW5jbHVkZVByb2plY3RGaWxlKGN3ZCwgc3RhdGVEaXIsIHZhbHVlW1wicHJvamVjdFwiXSwgdmFsdWVbXCJyZWZcIl0gfHwgXCJIRUFEXCIsIGZpbGVWYWx1ZSwgZ2l0RGF0YSwgZmV0Y2hJbmNsdWRlcykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWVbXCJ0ZW1wbGF0ZVwiXSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHtwcm9qZWN0LCByZWYsIGZpbGUsIGRvbWFpbn0gPSB0aGlzLmNvdmVydFRlbXBsYXRlVG9Qcm9qZWN0RmlsZSh2YWx1ZVtcInRlbXBsYXRlXCJdKTtcbiAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBgaHR0cHM6Ly8ke2RvbWFpbn0vJHtwcm9qZWN0fS8tL3Jhdy8ke3JlZn0vJHtmaWxlfWA7XG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLmRvd25sb2FkSW5jbHVkZVJlbW90ZShjd2QsIHN0YXRlRGlyLCB1cmwsIGZldGNoSW5jbHVkZXMpKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWVbXCJyZW1vdGVcIl0pIHtcbiAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuZG93bmxvYWRJbmNsdWRlUmVtb3RlKGN3ZCwgc3RhdGVEaXIsIHZhbHVlW1wicmVtb3RlXCJdLCBmZXRjaEluY2x1ZGVzKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlW1wiY29tcG9uZW50XCJdKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29tcG9uZW50ID0gdGhpcy5wYXJzZUluY2x1ZGVDb21wb25lbnQodmFsdWVbXCJjb21wb25lbnRcIl0sIGdpdERhdGEpO1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudFBhcnNlQ2FjaGUuc2V0KGluZGV4LCBjb21wb25lbnQpO1xuICAgICAgICAgICAgICAgIGlmICghY29tcG9uZW50LmlzTG9jYWwpXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuZG93bmxvYWRJbmNsdWRlQ29tcG9uZW50KGN3ZCwgc3RhdGVEaXIsIGNvbXBvbmVudC5wcm9qZWN0UGF0aCwgY29tcG9uZW50LnJlZiwgY29tcG9uZW50Lm5hbWUsIGdpdERhdGEsIGZldGNoSW5jbHVkZXMpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcblxuICAgICAgICBmb3IgKGNvbnN0IFtpbmRleCwgdmFsdWVdIG9mIGluY2x1ZGUuZW50cmllcygpKSB7XG4gICAgICAgICAgICBpZiAodmFsdWVbXCJydWxlc1wiXSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGluY2x1ZGVfcnVsZXMgPSB2YWx1ZVtcInJ1bGVzXCJdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJ1bGVzUmVzdWx0ID0gVXRpbHMuZ2V0UnVsZXNSZXN1bHQoe2FyZ3YsIGN3ZCwgcnVsZXM6IGluY2x1ZGVfcnVsZXMsIHZhcmlhYmxlczogb3B0cy52YXJpYWJsZXN9LCBnaXREYXRhKTtcbiAgICAgICAgICAgICAgICBpZiAocnVsZXNSZXN1bHQud2hlbiA9PT0gXCJuZXZlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh2YWx1ZVtcImxvY2FsXCJdKSB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdGVJbmNsdWRlTG9jYWwodmFsdWVbXCJsb2NhbFwiXSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCByZXNvbHZlSW5jbHVkZUxvY2FsKHZhbHVlW1wibG9jYWxcIl0sIGN3ZCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpbGVzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogYExvY2FsIGluY2x1ZGUgZmlsZSBjYW5ub3QgYmUgZm91bmQgJHt2YWx1ZVtcImxvY2FsXCJdfWB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBsb2NhbEZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IFBhcnNlci5sb2FkWWFtbChsb2NhbEZpbGUsIHtpbnB1dHM6IHZhbHVlLmlucHV0cyA/PyB7fX0sIGV4cGFuZFZhcmlhYmxlcyk7XG4gICAgICAgICAgICAgICAgICAgIGluY2x1ZGVEYXRhcyA9IGluY2x1ZGVEYXRhcy5jb25jYXQoYXdhaXQgdGhpcy5pbml0KGNvbnRlbnQsIG9wdHMpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlW1wicHJvamVjdFwiXSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmlsZVZhbHVlIG9mIEFycmF5LmlzQXJyYXkodmFsdWVbXCJmaWxlXCJdKSA/IHZhbHVlW1wiZmlsZVwiXSA6IFt2YWx1ZVtcImZpbGVcIl1dKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVEb2MgPSBhd2FpdCBQYXJzZXIubG9hZFlhbWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBgJHtjd2R9LyR7c3RhdGVEaXJ9L2luY2x1ZGVzLyR7Z2l0RGF0YS5yZW1vdGUuaG9zdH0vJHt2YWx1ZVtcInByb2plY3RcIl19LyR7dmFsdWVbXCJyZWZcIl0gfHwgXCJIRUFEXCJ9LyR7ZmlsZVZhbHVlfWBcbiAgICAgICAgICAgICAgICAgICAgICAgICwge2lucHV0czogdmFsdWUuaW5wdXRzIHx8IHt9fVxuICAgICAgICAgICAgICAgICAgICAgICAgLCBleHBhbmRWYXJpYWJsZXMpO1xuICAgICAgICAgICAgICAgICAgICAvLyBFeHBhbmQgbG9jYWwgaW5jbHVkZXMgaW5zaWRlIGEgXCJwcm9qZWN0XCItbGlrZSBpbmNsdWRlXG4gICAgICAgICAgICAgICAgICAgIGZpbGVEb2NbXCJpbmNsdWRlXCJdID0gdGhpcy5leHBhbmRJbm5lckxvY2FsSW5jbHVkZXMoZmlsZURvY1tcImluY2x1ZGVcIl0sIHZhbHVlW1wicHJvamVjdFwiXSwgdmFsdWVbXCJyZWZcIl0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpbmNsdWRlRGF0YXMgPSBpbmNsdWRlRGF0YXMuY29uY2F0KGF3YWl0IHRoaXMuaW5pdChmaWxlRG9jLCBvcHRzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZVtcImNvbXBvbmVudFwiXSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudCA9IGNvbXBvbmVudFBhcnNlQ2FjaGUuZ2V0KGluZGV4KTtcbiAgICAgICAgICAgICAgICBhc3NlcnQoY29tcG9uZW50ICE9PSB1bmRlZmluZWQsIGBJbnRlcm5hbCBlcnJvciwgY29tcG9uZW50IHBhcnNlIGNhY2hlIG1pc3NpbmcgZW50cnkgWyR7aW5kZXh9XWApO1xuICAgICAgICAgICAgICAgIC8vIEdpdGxhYiBhbGxvd3MgdHdvIGRpZmZlcmVudCBmaWxlIHBhdGhzIHRvIGluY2x1ZGUgYSBjb21wb25lbnRcbiAgICAgICAgICAgICAgICBjb25zdCBmaWxlcyA9IFtgJHtjb21wb25lbnQubmFtZX0ueW1sYCwgYCR7Y29tcG9uZW50Lm5hbWV9L3RlbXBsYXRlLnltbGBdO1xuXG4gICAgICAgICAgICAgICAgbGV0IGZpbGUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZiBvZiBmaWxlcykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgc2VhcmNoUGF0aCA9IGAke2N3ZH0vJHtmfWA7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcG9uZW50LmlzTG9jYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXJjaFBhdGggPSBgJHtjd2R9LyR7c3RhdGVEaXJ9L2luY2x1ZGVzLyR7Z2l0RGF0YS5yZW1vdGUuaG9zdH0vJHtjb21wb25lbnQucHJvamVjdFBhdGh9LyR7Y29tcG9uZW50LnJlZn0vJHtmfWA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoc2VhcmNoUGF0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGUgPSBzZWFyY2hQYXRoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFzc2VydChmaWxlICE9PSBudWxsLCBgVGhpcyBHaXRMYWIgQ0kgY29uZmlndXJhdGlvbiBpcyBpbnZhbGlkOiBjb21wb25lbnQ6IFxcYCR7dmFsdWVbXCJjb21wb25lbnRcIl19XFxgLiBPbmUgb2YgdGhlIGZpbGVzIFske2ZpbGVzfV0gbXVzdCBleGlzdCBpbiBcXGAke2NvbXBvbmVudC5kb21haW59YCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY29tcG9uZW50LnBvcnQgPyBgOiR7Y29tcG9uZW50LnBvcnR9YCA6IFwiXCIpICsgYC8ke2NvbXBvbmVudC5wcm9qZWN0UGF0aH1cXGBgKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVEb2MgPSBhd2FpdCBQYXJzZXIubG9hZFlhbWwoZmlsZSwge2lucHV0czogdmFsdWUuaW5wdXRzIHx8IHt9fSwgZXhwYW5kVmFyaWFibGVzKTtcbiAgICAgICAgICAgICAgICAvLyBFeHBhbmQgbG9jYWwgaW5jbHVkZXMgaW5zaWRlIHRvIGEgXCJwcm9qZWN0XCItbGlrZSBpbmNsdWRlXG4gICAgICAgICAgICAgICAgZmlsZURvY1tcImluY2x1ZGVcIl0gPSB0aGlzLmV4cGFuZElubmVyTG9jYWxJbmNsdWRlcyhmaWxlRG9jW1wiaW5jbHVkZVwiXSwgY29tcG9uZW50LnByb2plY3RQYXRoLCBjb21wb25lbnQucmVmLCBvcHRzKTtcbiAgICAgICAgICAgICAgICBpbmNsdWRlRGF0YXMgPSBpbmNsdWRlRGF0YXMuY29uY2F0KGF3YWl0IHRoaXMuaW5pdChmaWxlRG9jLCBvcHRzKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlW1widGVtcGxhdGVcIl0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCB7cHJvamVjdCwgcmVmLCBmaWxlLCBkb21haW59ID0gdGhpcy5jb3ZlcnRUZW1wbGF0ZVRvUHJvamVjdEZpbGUodmFsdWVbXCJ0ZW1wbGF0ZVwiXSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZnNVcmwgPSBVdGlscy5mc1VybChgaHR0cHM6Ly8ke2RvbWFpbn0vJHtwcm9qZWN0fS8tL3Jhdy8ke3JlZn0vJHtmaWxlfWApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVEb2MgPSBhd2FpdCBQYXJzZXIubG9hZFlhbWwoXG4gICAgICAgICAgICAgICAgICAgIGAke2N3ZH0vJHtzdGF0ZURpcn0vaW5jbHVkZXMvJHtmc1VybH1gLCB7aW5wdXRzOiB2YWx1ZS5pbnB1dHMgfHwge319LCBleHBhbmRWYXJpYWJsZXMsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpbmNsdWRlRGF0YXMgPSBpbmNsdWRlRGF0YXMuY29uY2F0KGF3YWl0IHRoaXMuaW5pdChmaWxlRG9jLCBvcHRzKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlW1wicmVtb3RlXCJdKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZnNVcmwgPSBVdGlscy5mc1VybCh2YWx1ZVtcInJlbW90ZVwiXSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZURvYyA9IGF3YWl0IFBhcnNlci5sb2FkWWFtbChcbiAgICAgICAgICAgICAgICAgICAgYCR7Y3dkfS8ke3N0YXRlRGlyfS9pbmNsdWRlcy8ke2ZzVXJsfWAsIHtpbnB1dHM6IHZhbHVlLmlucHV0cyB8fCB7fX0sIGV4cGFuZFZhcmlhYmxlcyxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGluY2x1ZGVEYXRhcyA9IGluY2x1ZGVEYXRhcy5jb25jYXQoYXdhaXQgdGhpcy5pbml0KGZpbGVEb2MsIG9wdHMpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHttZXNzYWdlOiBgRGlkbid0IHVuZGVyc3RhbmQgaW5jbHVkZSAke0pTT04uc3RyaW5naWZ5KHZhbHVlKX1gfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpbmNsdWRlRGF0YXMucHVzaChnaXRsYWJEYXRhKTtcbiAgICAgICAgcmV0dXJuIGluY2x1ZGVEYXRhcztcbiAgICB9XG5cbiAgICBzdGF0aWMgZXhwYW5kSW5jbHVkZSAoaTogYW55LCB2YXJpYWJsZXM6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9KTogYW55W10ge1xuICAgICAgICBsZXQgaW5jbHVkZSA9IGkgfHwgW107XG4gICAgICAgIGlmIChpbmNsdWRlICYmIGluY2x1ZGUubGVuZ3RoID09IG51bGwpIHtcbiAgICAgICAgICAgIGluY2x1ZGUgPSBbIGkgXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGluY2x1ZGUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGluY2x1ZGUgPSBbaW5jbHVkZV07XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIE9iamVjdC5lbnRyaWVzKGluY2x1ZGUpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVudHJ5ID09PSBcInN0cmluZ1wiICYmIChlbnRyeS5zdGFydHNXaXRoKFwiaHR0cHM6XCIpIHx8IGVudHJ5LnN0YXJ0c1dpdGgoXCJodHRwOlwiKSkpIHtcbiAgICAgICAgICAgICAgICBpbmNsdWRlW2luZGV4XSA9IHtcInJlbW90ZVwiOiBlbnRyeX07XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBlbnRyeSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIGluY2x1ZGVbaW5kZXhdID0ge1wibG9jYWxcIjogZW50cnl9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbmNsdWRlW2luZGV4XSA9IGVudHJ5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGluY2x1ZGUpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGVudHJ5KSkge1xuICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBlbnRyeVtrZXldID0gdmFsdWUubWFwKCh2KSA9PiBVdGlscy5leHBhbmRUZXh0KHYsIHZhcmlhYmxlcykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVudHJ5W2tleV0gPSBVdGlscy5leHBhbmRUZXh0KHZhbHVlLCB2YXJpYWJsZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbmNsdWRlO1xuICAgIH1cblxuICAgIHN0YXRpYyBjb3ZlcnRUZW1wbGF0ZVRvUHJvamVjdEZpbGUgKHRlbXBsYXRlOiBzdHJpbmcpOiB7cHJvamVjdDogc3RyaW5nOyByZWY6IHN0cmluZzsgZmlsZTogc3RyaW5nOyBkb21haW46IHN0cmluZ30ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZG9tYWluOiBcImdpdGxhYi5jb21cIixcbiAgICAgICAgICAgIHByb2plY3Q6IFwiZ2l0bGFiLW9yZy9naXRsYWJcIixcbiAgICAgICAgICAgIHJlZjogXCJIRUFEXCIsXG4gICAgICAgICAgICBmaWxlOiBgbGliL2dpdGxhYi9jaS90ZW1wbGF0ZXMvJHt0ZW1wbGF0ZX1gLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHN0YXRpYyBwYXJzZUluY2x1ZGVDb21wb25lbnQgKGNvbXBvbmVudDogc3RyaW5nLCBnaXREYXRhOiBHaXREYXRhKTogUGFyc2VkQ29tcG9uZW50IHtcbiAgICAgICAgYXNzZXJ0KCFjb21wb25lbnQuaW5jbHVkZXMoXCI6Ly9cIiksIGBUaGlzIEdpdExhYiBDSSBjb25maWd1cmF0aW9uIGlzIGludmFsaWQ6IGNvbXBvbmVudDogXFxgJHtjb21wb25lbnR9XFxgIHNob3VsZCBub3QgY29udGFpbiBwcm90b2NvbGApO1xuICAgICAgICBjb25zdCBwYXR0ZXJuID0gLyg/PGRvbWFpbj5bXi86XFxzXSspKDooPzxwb3J0PlxcZCspKT9cXC8oPzxwcm9qZWN0UGF0aD4uKylcXC8oPzxjb21wb25lbnROYW1lPlteQF0rKUAoPzxyZWY+LispLzsgLy8gaHR0cHM6Ly9yZWdleHIuY29tLzd2N2htXG4gICAgICAgIGNvbnN0IGdpdFJlbW90ZU1hdGNoID0gcGF0dGVybi5leGVjKGNvbXBvbmVudCk7XG5cbiAgICAgICAgaWYgKGdpdFJlbW90ZU1hdGNoPy5ncm91cHMgPT0gbnVsbCkgdGhyb3cgbmV3IEVycm9yKGBUaGlzIGlzIGEgYnVnLCBwbGVhc2UgY3JlYXRlIGEgZ2l0aHViIGlzc3VlIGlmIHRoaXMgaXMgc29tZXRoaW5nIHlvdSdyZSBleHBlY3RpbmcgdG8gd29yay4gaW5wdXQ6ICR7Y29tcG9uZW50fWApO1xuXG4gICAgICAgIGNvbnN0IHtkb21haW4sIHByb2plY3RQYXRoLCBwb3J0fSA9IGdpdFJlbW90ZU1hdGNoLmdyb3VwcztcbiAgICAgICAgbGV0IHJlZiA9IGdpdFJlbW90ZU1hdGNoLmdyb3Vwc1tcInJlZlwiXTtcbiAgICAgICAgY29uc3QgaXNMb2NhbENvbXBvbmVudCA9IHByb2plY3RQYXRoID09PSBgJHtnaXREYXRhLnJlbW90ZS5ncm91cH0vJHtnaXREYXRhLnJlbW90ZS5wcm9qZWN0fWAgJiYgcmVmID09PSBnaXREYXRhLmNvbW1pdC5TSEE7XG5cbiAgICAgICAgaWYgKCFpc0xvY2FsQ29tcG9uZW50KSB7XG4gICAgICAgICAgICBjb25zdCBzZW1hbnRpY1ZlcnNpb25SYW5nZXNQYXR0ZXJuID0gL15cXGQrKFxcLlxcZCspPyQvO1xuICAgICAgICAgICAgaWYgKHJlZiA9PSBcIn5sYXRlc3RcIiB8fCBzZW1hbnRpY1ZlcnNpb25SYW5nZXNQYXR0ZXJuLnRlc3QocmVmKSkge1xuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2NpL2NvbXBvbmVudHMvI3NlbWFudGljLXZlcnNpb24tcmFuZ2VzXG4gICAgICAgICAgICAgICAgbGV0IHN0ZG91dDtcbiAgICAgICAgICAgICAgICBpZiAoZ2l0RGF0YS5yZW1vdGUuc2NoZW1hID09IFwiZ2l0XCIgfHwgZ2l0RGF0YS5yZW1vdGUuc2NoZW1hID09IFwic3NoXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3Rkb3V0ID0gVXRpbHMuc3luY1NwYXduKFtcImdpdFwiLCBcImxzLXJlbW90ZVwiLCBcIi0tdGFnc1wiLCBgZ2l0QCR7ZG9tYWlufToke3Byb2plY3RQYXRofWBdKS5zdGRvdXQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3Rkb3V0ID0gVXRpbHMuc3luY1NwYXduKFtcImdpdFwiLCBcImxzLXJlbW90ZVwiLCBcIi0tdGFnc1wiLCBgJHtnaXREYXRhLnJlbW90ZS5zY2hlbWF9Oi8vJHtkb21haW59OiR7cG9ydCA/PyA0NDN9LyR7cHJvamVjdFBhdGh9LmdpdGBdKS5zdGRvdXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFzc2VydChzdGRvdXQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRhZ3MgPSBzdGRvdXRcbiAgICAgICAgICAgICAgICAgICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoKGxpbmUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBsaW5lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNwbGl0KFwiXFx0XCIpWzFdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNwbGl0KFwiL1wiKVsyXTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29uc3QgX3JlZiA9IHJlc29sdmVTZW1hbnRpY1ZlcnNpb25SYW5nZShyZWYsIHRhZ3MpO1xuICAgICAgICAgICAgICAgIGFzc2VydChfcmVmLCBgVGhpcyBHaXRMYWIgQ0kgY29uZmlndXJhdGlvbiBpcyBpbnZhbGlkOiBjb21wb25lbnQ6IFxcYCR7Y29tcG9uZW50fVxcYCAtIFRoZSByZWYgKCR7cmVmfSkgaXMgaW52YWxpZGApO1xuICAgICAgICAgICAgICAgIHJlZiA9IF9yZWY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRvbWFpbjogZG9tYWluLFxuICAgICAgICAgICAgcG9ydDogcG9ydCxcbiAgICAgICAgICAgIHByb2plY3RQYXRoOiBwcm9qZWN0UGF0aCxcbiAgICAgICAgICAgIG5hbWU6IGB0ZW1wbGF0ZXMvJHtnaXRSZW1vdGVNYXRjaC5ncm91cHNbXCJjb21wb25lbnROYW1lXCJdfWAsXG4gICAgICAgICAgICByZWY6IHJlZixcbiAgICAgICAgICAgIGlzTG9jYWw6IGlzTG9jYWxDb21wb25lbnQsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRXhwYW5kIGxvY2FsIGluY2x1ZGVzIGluc2lkZSB0byBhIFwicHJvamVjdFwiLWxpa2UgaW5jbHVkZVxuICAgIHN0YXRpYyBleHBhbmRJbm5lckxvY2FsSW5jbHVkZXMgKGZpbGVJbmNsdWRlczogYW55LCBwcm9qZWN0UGF0aDogc3RyaW5nLCByZWY6IHN0cmluZywgb3B0czogUGFyc2VySW5jbHVkZXNJbml0T3B0aW9ucykge1xuICAgICAgICBjb25zdCB7YXJndn0gPSBvcHRzO1xuICAgICAgICBjb25zdCB1cGRhdGVkSW5jbHVkZXMgPSB0aGlzLmV4cGFuZEluY2x1ZGUoZmlsZUluY2x1ZGVzLCBvcHRzLnZhcmlhYmxlcyk7XG4gICAgICAgIHVwZGF0ZWRJbmNsdWRlcy5mb3JFYWNoKChpbm5lcjogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGlmICghaW5uZXJbXCJsb2NhbFwiXSkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKGlubmVyW1wicnVsZXNcIl0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBydWxlc1Jlc3VsdCA9IFV0aWxzLmdldFJ1bGVzUmVzdWx0KHthcmd2LCBjd2Q6IG9wdHMuY3dkLCB2YXJpYWJsZXM6IG9wdHMudmFyaWFibGVzLCBydWxlczogaW5uZXJbXCJydWxlc1wiXX0sIG9wdHMuZ2l0RGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKHJ1bGVzUmVzdWx0LndoZW4gPT09IFwibmV2ZXJcIikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdXBkYXRlZEluY2x1ZGVzW2ldID0ge1xuICAgICAgICAgICAgICAgIHByb2plY3Q6IHByb2plY3RQYXRoLFxuICAgICAgICAgICAgICAgIGZpbGU6IGlubmVyW1wibG9jYWxcIl0ucmVwbGFjZSgvXlxcLy8sIFwiXCIpLFxuICAgICAgICAgICAgICAgIHJlZjogcmVmLFxuICAgICAgICAgICAgICAgIGlucHV0czogaW5uZXIuaW5wdXRzIHx8IHt9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB1cGRhdGVkSW5jbHVkZXM7XG4gICAgfVxuXG4gICAgc3RhdGljIGFzeW5jIGRvd25sb2FkSW5jbHVkZVJlbW90ZSAoY3dkOiBzdHJpbmcsIHN0YXRlRGlyOiBzdHJpbmcsIHVybDogc3RyaW5nLCBmZXRjaEluY2x1ZGVzOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGZzVXJsID0gVXRpbHMuZnNVcmwodXJsKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGAke2N3ZH0vJHtzdGF0ZURpcn0vaW5jbHVkZXMvJHtmc1VybH1gO1xuICAgICAgICAgICAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHModGFyZ2V0KSAmJiAhZmV0Y2hJbmNsdWRlcykgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgYXhpb3NDb25maWc6IEF4aW9zUmVxdWVzdENvbmZpZyA9IHtcbiAgICAgICAgICAgICAgICBoZWFkZXJzOiB7XCJVc2VyLUFnZW50XCI6IFwiZ2l0bGFiLWNpLWxvY2FsXCJ9LFxuICAgICAgICAgICAgICAgIC4uLlV0aWxzLmdldEF4aW9zUHJveHlDb25maWcoKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBheGlvcy5nZXQodXJsLCBheGlvc0NvbmZpZyk7XG4gICAgICAgICAgICBhd2FpdCBmcy5vdXRwdXRGaWxlKHRhcmdldCwgcmVzLmRhdGEpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3Ioe21lc3NhZ2U6IGBSZW1vdGUgaW5jbHVkZSBjb3VsZCBub3QgYmUgZmV0Y2hlZCAke3VybH1cXG4ke2V9YH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGFzeW5jIGRvd25sb2FkSW5jbHVkZVByb2plY3RGaWxlIChjd2Q6IHN0cmluZywgc3RhdGVEaXI6IHN0cmluZywgcHJvamVjdDogc3RyaW5nLCByZWY6IHN0cmluZywgZmlsZTogc3RyaW5nLCBnaXREYXRhOiBHaXREYXRhLCBmZXRjaEluY2x1ZGVzOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHJlbW90ZSA9IGdpdERhdGEucmVtb3RlO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkRmlsZSA9IGZpbGUucmVwbGFjZSgvXlxcLysvLCBcIlwiKTtcbiAgICAgICAgbGV0IHRtcERpciA9IG51bGw7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBgJHtzdGF0ZURpcn0vaW5jbHVkZXMvJHtyZW1vdGUuaG9zdH0vJHtwcm9qZWN0fS8ke3JlZn1gO1xuICAgICAgICAgICAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoYCR7Y3dkfS8ke3RhcmdldH0vJHtub3JtYWxpemVkRmlsZX1gKSAmJiAhZmV0Y2hJbmNsdWRlcykgcmV0dXJuO1xuXG4gICAgICAgICAgICBpZiAocmVtb3RlLnNjaGVtYS5zdGFydHNXaXRoKFwiaHR0cFwiKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV4dCA9IFwidG1wLVwiICsgTWF0aC5yYW5kb20oKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBmcy5ta2RpcnAocGF0aC5kaXJuYW1lKGAke2N3ZH0vJHt0YXJnZXR9LyR7bm9ybWFsaXplZEZpbGV9YCkpO1xuICAgICAgICAgICAgICAgIHRtcERpciA9IGAke2N3ZH0vJHt0YXJnZXR9LiR7ZXh0fWA7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBnaXRDbG9uZUJyYW5jaCA9IChyZWYgPT09IFwiSEVBRFwiKSA/IFwiXCIgOiBgLS1icmFuY2ggJHtyZWZ9YDtcbiAgICAgICAgICAgICAgICBhd2FpdCBVdGlscy5iYXNoTXVsdGkoW1xuICAgICAgICAgICAgICAgICAgICBgY2QgJHtjd2R9LyR7c3RhdGVEaXJ9YCxcbiAgICAgICAgICAgICAgICAgICAgYGdpdCBjbG9uZSAke2dpdENsb25lQnJhbmNofSAtbiAtLWRlcHRoPTEgLS1maWx0ZXI9dHJlZTowICR7cmVtb3RlLnNjaGVtYX06Ly8ke3JlbW90ZS5ob3N0fToke3JlbW90ZS5wb3J0fS8ke3Byb2plY3R9LmdpdCAke3RtcERpcn1gLFxuICAgICAgICAgICAgICAgICAgICBgY2QgJHt0bXBEaXJ9YCxcbiAgICAgICAgICAgICAgICAgICAgYGdpdCBzcGFyc2UtY2hlY2tvdXQgc2V0IC0tbm8tY29uZSAke25vcm1hbGl6ZWRGaWxlfWAsXG4gICAgICAgICAgICAgICAgICAgIFwiZ2l0IGNoZWNrb3V0XCIsXG4gICAgICAgICAgICAgICAgICAgIGBjZCAke2N3ZH0vJHtzdGF0ZURpcn1gLFxuICAgICAgICAgICAgICAgICAgICBgY3AgJHt0bXBEaXJ9LyR7bm9ybWFsaXplZEZpbGV9ICR7Y3dkfS8ke3RhcmdldH0vJHtub3JtYWxpemVkRmlsZX1gLFxuICAgICAgICAgICAgICAgIF0sIGN3ZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IGZzLm1rZGlycChgJHtjd2R9LyR7dGFyZ2V0fWApO1xuICAgICAgICAgICAgICAgIGF3YWl0IFV0aWxzLmJhc2goYHNldCAtZW91IHBpcGVmYWlsOyBnaXQgYXJjaGl2ZSAtLXJlbW90ZT1zc2g6Ly9naXRAJHtyZW1vdGUuaG9zdH06JHtyZW1vdGUucG9ydH0vJHtwcm9qZWN0fS5naXQgJHtyZWZ9ICR7bm9ybWFsaXplZEZpbGV9IHwgdGFyIC1mIC0gLXhDICR7dGFyZ2V0fS9gLCBjd2QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3Ioe21lc3NhZ2U6IGBQcm9qZWN0IGluY2x1ZGUgY291bGQgbm90IGJlIGZldGNoZWQgeyBwcm9qZWN0OiAke3Byb2plY3R9LCByZWY6ICR7cmVmfSwgZmlsZTogJHtub3JtYWxpemVkRmlsZX0gfVxcbiR7ZX1gfSk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICBpZiAodG1wRGlyICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gYWx3YXlzIGNsZWFudXAgdGVtcG9yYXJ5IGRpcmVjdG9yeSAoaWYgY3JlYXRlZClcbiAgICAgICAgICAgICAgICBhd2FpdCBmcy5ybSh0bXBEaXIsIHtyZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzdGF0aWMgYXN5bmMgZG93bmxvYWRJbmNsdWRlQ29tcG9uZW50IChjd2Q6IHN0cmluZywgc3RhdGVEaXI6IHN0cmluZywgcHJvamVjdDogc3RyaW5nLCByZWY6IHN0cmluZywgY29tcG9uZW50TmFtZTogc3RyaW5nLCBnaXREYXRhOiBHaXREYXRhLCBmZXRjaEluY2x1ZGVzOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHJlbW90ZSA9IGdpdERhdGEucmVtb3RlO1xuICAgICAgICBjb25zdCBmaWxlcyA9IFtgJHtjb21wb25lbnROYW1lfS55bWxgLCBgJHtjb21wb25lbnROYW1lfS90ZW1wbGF0ZS55bWxgXTtcbiAgICAgICAgbGV0IHRtcERpciA9IG51bGw7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBgJHtzdGF0ZURpcn0vaW5jbHVkZXMvJHtyZW1vdGUuaG9zdH0vJHtwcm9qZWN0fS8ke3JlZn1gO1xuXG4gICAgICAgICAgICBpZiAoIWZldGNoSW5jbHVkZXMgJiYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoYCR7Y3dkfS8ke3RhcmdldH0vJHtmaWxlc1swXX1gKSB8fCBhd2FpdCBmcy5wYXRoRXhpc3RzKGAke2N3ZH0vJHt0YXJnZXR9LyR7ZmlsZXNbMV19YCkpKSByZXR1cm47XG5cbiAgICAgICAgICAgIGlmIChyZW1vdGUuc2NoZW1hLnN0YXJ0c1dpdGgoXCJodHRwXCIpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXh0ID0gXCJ0bXAtXCIgKyBNYXRoLnJhbmRvbSgpO1xuICAgICAgICAgICAgICAgIGF3YWl0IGZzLm1rZGlycChwYXRoLmRpcm5hbWUoYCR7Y3dkfS8ke3RhcmdldH0vdGVtcGxhdGVzYCkpO1xuICAgICAgICAgICAgICAgIHRtcERpciA9IGAke2N3ZH0vJHt0YXJnZXR9LiR7ZXh0fWA7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBnaXRDbG9uZUJyYW5jaCA9IChyZWYgPT09IFwiSEVBRFwiKSA/IFwiXCIgOiBgLS1icmFuY2ggJHtyZWZ9YDtcbiAgICAgICAgICAgICAgICBhd2FpdCBVdGlscy5iYXNoTXVsdGkoW1xuICAgICAgICAgICAgICAgICAgICBgY2QgJHtjd2R9LyR7c3RhdGVEaXJ9YCxcbiAgICAgICAgICAgICAgICAgICAgYGdpdCBjbG9uZSAke2dpdENsb25lQnJhbmNofSAtbiAtLWRlcHRoPTEgLS1maWx0ZXI9dHJlZTowICR7cmVtb3RlLnNjaGVtYX06Ly8ke3JlbW90ZS5ob3N0fToke3JlbW90ZS5wb3J0fS8ke3Byb2plY3R9LmdpdCAke3RtcERpcn1gLFxuICAgICAgICAgICAgICAgICAgICBgY2QgJHt0bXBEaXJ9YCxcbiAgICAgICAgICAgICAgICAgICAgYGdpdCBzcGFyc2UtY2hlY2tvdXQgc2V0IC0tbm8tY29uZSAke2ZpbGVzWzBdfSAke2ZpbGVzWzFdfWAsXG4gICAgICAgICAgICAgICAgICAgIFwiZ2l0IGNoZWNrb3V0XCIsXG4gICAgICAgICAgICAgICAgICAgIGBjZCAke2N3ZH0vJHtzdGF0ZURpcn1gLFxuICAgICAgICAgICAgICAgICAgICBgbWtkaXIgLXAgJHt0bXBEaXJ9L3RlbXBsYXRlc2AsIC8vIGNyZWF0ZSB0ZW1wbGF0ZXMgc3ViZGlyIChpZiBpdCBkb2Vzbid0IGV4aXN0KSwgYXMgdGhlIGNoZWNrIG91dCBtYXkgbm90IGNyZWF0ZSBpdFxuICAgICAgICAgICAgICAgICAgICBgY3AgLXIgJHt0bXBEaXJ9L3RlbXBsYXRlcyAke2N3ZH0vJHt0YXJnZXR9YCxcbiAgICAgICAgICAgICAgICBdLCBjd2QpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBnaXQgYXJjaGl2ZSBmYWlscyBpZiB0aGUgcGF0aHMgZG8gbm90IGV4aXN0LCB0byB3b3JrIGFyb3VuZCB0aGlzIHdlIHVzZSBhIHdpbGRjYXJkIFwidGVtcGxhdGVzL2NvbXBvbmVudCoueW1sXCJcbiAgICAgICAgICAgICAgICAvLyB0aGlzIHJlc29sdmVzIHRvIGVpdGhlciBcInRlbXBsYXRlcy9jb21wb25lbnQueW1sXCIgb3IgXCJ0ZW1wbGF0ZXMvY29tcG9uZW50L3RlbXBsYXRlLnltbFwiXG4gICAgICAgICAgICAgICAgLy8gaWYgYm90aCBleGlzdCBcInRlbXBsYXRlcy9jb21wb25lbnQueW1sXCIgd2lsbCBiZSBwdWxsZWRcbiAgICAgICAgICAgICAgICAvLyBEcmF3YmFjazogYWxzbyBwdWxscyBhbGwgb3RoZXIgLnltbCBmaWxlcyBmcm9tIHRlbXBsYXRlcy9jb21wb25lbnQvIGRpcmVjdG9yeVxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudFdpbGRjYXJkID0gYCR7Y29tcG9uZW50TmFtZX0qLnltbGA7XG4gICAgICAgICAgICAgICAgYXdhaXQgZnMubWtkaXJwKGAke2N3ZH0vJHt0YXJnZXR9YCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgVXRpbHMuYmFzaChgc2V0IC1lb3UgcGlwZWZhaWw7IGdpdCBhcmNoaXZlIC0tcmVtb3RlPXNzaDovL2dpdEAke3JlbW90ZS5ob3N0fToke3JlbW90ZS5wb3J0fS8ke3Byb2plY3R9LmdpdCAke3JlZn0gJHtjb21wb25lbnRXaWxkY2FyZH0gfCB0YXIgLWYgLSAteEMgJHt0YXJnZXR9L2AsIGN3ZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogYENvbXBvbmVudCBpbmNsdWRlIGNvdWxkIG5vdCBiZSBmZXRjaGVkIHsgcHJvamVjdDogJHtwcm9qZWN0fSwgcmVmOiAke3JlZn0sIGZpbGU6ICR7ZmlsZXN9IH1cXG4ke2V9YH0pO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgaWYgKHRtcERpciAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIGFsd2F5cyBjbGVhbnVwIHRlbXBvcmFyeSBkaXJlY3RvcnkgKGlmIGNyZWF0ZWQpXG4gICAgICAgICAgICAgICAgYXdhaXQgZnMucm0odG1wRGlyLCB7cmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZX0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIHJlYWRvbmx5IG1lbW9Mb2NhbFJlcG9GaWxlcyA9ICgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZ1tdPigpO1xuICAgICAgICByZXR1cm4gYXN5bmMgKHBhdGg6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGNhY2hlLmdldChwYXRoKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzdWx0ICE9PSBcInVuZGVmaW5lZFwiKSByZXR1cm4gcmVzdWx0O1xuXG4gICAgICAgICAgICByZXN1bHQgPSAoYXdhaXQgVXRpbHMuZ2V0VHJhY2tlZEZpbGVzKHBhdGgpKS5tYXAocCA9PiBgJHtwYXRofS8ke3B9YCk7XG4gICAgICAgICAgICBjYWNoZS5zZXQocGF0aCwgcmVzdWx0KTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgfSkoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlSW5jbHVkZUxvY2FsIChmaWxlUGF0aDogc3RyaW5nKSB7XG4gICAgYXNzZXJ0KCFmaWxlUGF0aC5zdGFydHNXaXRoKFwiLi9cIiksIGBcXGAke2ZpbGVQYXRofVxcYCBmb3IgaW5jbHVkZTpsb2NhbCBpcyBpbnZhbGlkLiBHaXRsYWIgZG9lcyBub3Qgc3VwcG9ydCByZWxhdGl2ZSBwYXRoIChpZS4gY2Fubm90IHN0YXJ0IHdpdGggXFxgLi9cXGApLmApO1xuICAgIGFzc2VydCghZmlsZVBhdGguaW5jbHVkZXMoXCIuLlwiKSwgYFxcYCR7ZmlsZVBhdGh9XFxgIGZvciBpbmNsdWRlOmxvY2FsIGlzIGludmFsaWQuIEdpdGxhYiBkb2VzIG5vdCBzdXBwb3J0IGRpcmVjdG9yeSB0cmF2ZXJzYWwuYCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlU2VtYW50aWNWZXJzaW9uUmFuZ2UgKHJhbmdlOiBzdHJpbmcsIGdpdFRhZ3M6IHN0cmluZ1tdKSB7XG4gICAgLyoqIHNvcnRlZCBsaXN0IG9mIHRhZ3MgdGhhdHMgY29tcGxpYW50IHRvIHNlbWFudGljIHZlcnNpb24gd2hlcmUgaW5kZXggMCBpcyB0aGUgbGF0ZXN0ICovXG4gICAgY29uc3Qgc2FuaXRpemVkU2VtdmVyVGFncyA9IHNlbXZlci5yc29ydChcbiAgICAgICAgZ2l0VGFncy5maWx0ZXIocyA9PiBzZW12ZXIudmFsaWQocykpLFxuICAgICk7XG5cbiAgICBjb25zdCBmb3VuZCA9IHNhbml0aXplZFNlbXZlclRhZ3MuZmluZCh0ID0+IHtcbiAgICAgICAgaWYgKHJhbmdlID09IFwifmxhdGVzdFwiKSB7XG4gICAgICAgICAgICBjb25zdCBzZW12ZXJQYXJzZWQgPSBzZW12ZXIucGFyc2UodCk7XG4gICAgICAgICAgICBhc3NlcnQoc2VtdmVyUGFyc2VkKTtcbiAgICAgICAgICAgIHJldHVybiAoc2VtdmVyUGFyc2VkLnByZXJlbGVhc2UubGVuZ3RoID09IDAgJiYgc2VtdmVyUGFyc2VkLmJ1aWxkLmxlbmd0aCA9PSAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBzZW12ZXIuc2F0aXNmaWVzKHQsIHJhbmdlKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBmb3VuZDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVJbmNsdWRlTG9jYWwgKHBhdHRlcm46IHN0cmluZywgY3dkOiBzdHJpbmcpIHtcbiAgICBjb25zdCByZXBvRmlsZXMgPSBhd2FpdCBQYXJzZXJJbmNsdWRlcy5tZW1vTG9jYWxSZXBvRmlsZXMoY3dkKTtcblxuICAgIGlmICghcGF0dGVybi5zdGFydHNXaXRoKFwiL1wiKSkgcGF0dGVybiA9IGAvJHtwYXR0ZXJufWA7IC8vIEVuc3VyZSBwYXR0ZXJuIHN0YXJ0cyB3aXRoIGAvYFxuICAgIHBhdHRlcm4gPSBgJHtjd2R9JHtwYXR0ZXJufWA7XG5cbiAgICAvLyBlc2NhcGUgYWxsIHNwZWNpYWwgcmVnZXggbWV0YWNoYXJhY3RlcnNcbiAgICBwYXR0ZXJuID0gcGF0dGVybi5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgXCJcXFxcJCZcIik7XG5cbiAgICAvLyBgKipgIG1hdGNoZXMgYW55dGhpbmdcbiAgICBjb25zdCBhbnl0aGluZyA9IFwiLio/XCI7XG4gICAgcGF0dGVybiA9IHBhdHRlcm4ucmVwbGFjZSgvXFxcXFxcKlxcXFxcXCovZywgYW55dGhpbmcpO1xuXG4gICAgLy8gYCpgIG1hdGNoZXMgYW55dGhpbmcgZXhjZXB0IGZvciBgL2BcbiAgICBjb25zdCBhbnl0aGluZ19idXRfbm90X3NsYXNoID0gXCIoW14vXSkqP1wiO1xuICAgIHBhdHRlcm4gPSBwYXR0ZXJuLnJlcGxhY2UoL1xcXFxcXCovZywgYW55dGhpbmdfYnV0X25vdF9zbGFzaCk7XG5cbiAgICBjb25zdCByZTJqcyA9IFJFMkpTLmNvbXBpbGUoYF4ke3BhdHRlcm59YCk7XG4gICAgcmV0dXJuIHJlcG9GaWxlcy5maWx0ZXIoKGY6IGFueSkgPT4gcmUyanMubWF0Y2hlcyhmKSk7XG59XG4iXX0=