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/README.md +20 -19
- package/dist/index.js +340 -0
- package/dist/index.js.map +480 -0
- package/package.json +26 -80
- package/src/argv.js +0 -307
- package/src/commander.js +0 -247
- package/src/data-expander.js +0 -220
- package/src/executor.js +0 -104
- package/src/git-data.js +0 -168
- package/src/gitlab-preset.js +0 -24
- package/src/global.js +0 -40
- package/src/handler.js +0 -119
- package/src/index.js +0 -364
- package/src/job.js +0 -1463
- package/src/mutex.js +0 -20
- package/src/parallel.js +0 -46
- package/src/parser-includes.js +0 -387
- package/src/parser.js +0 -357
- package/src/predefined-variables.js +0 -67
- package/src/producers.js +0 -42
- package/src/schema/index.js +0 -19
- package/src/schema/schema.js +0 -3190
- package/src/schema-error.js +0 -114
- package/src/state.js +0 -22
- package/src/utils.js +0 -485
- package/src/validator.js +0 -151
- package/src/variables-from-files.js +0 -143
- package/src/write-streams.js +0 -51
package/src/utils.js
DELETED
|
@@ -1,485 +0,0 @@
|
|
|
1
|
-
import "./global.js";
|
|
2
|
-
import { RE2JS } from "re2js";
|
|
3
|
-
import chalk from "chalk-template";
|
|
4
|
-
import { Job } from "./job.js";
|
|
5
|
-
import { needsComplex } from "./data-expander.js";
|
|
6
|
-
import fs from "fs-extra";
|
|
7
|
-
import checksum from "checksum";
|
|
8
|
-
import base64url from "base64url";
|
|
9
|
-
import execa from "execa";
|
|
10
|
-
import assert from "assert";
|
|
11
|
-
import { GitData } from "./git-data.js";
|
|
12
|
-
import { globbySync } from "globby";
|
|
13
|
-
import micromatch from "micromatch";
|
|
14
|
-
import path from "path";
|
|
15
|
-
export class Utils {
|
|
16
|
-
static bashMulti(scripts, cwd = process.cwd()) {
|
|
17
|
-
return execa(scripts.join(" && \\"), { shell: "bash", cwd });
|
|
18
|
-
}
|
|
19
|
-
static bash(shellScript, cwd = process.cwd()) {
|
|
20
|
-
return execa(shellScript, { shell: "bash", cwd });
|
|
21
|
-
}
|
|
22
|
-
static spawn(cmdArgs, cwd = process.cwd()) {
|
|
23
|
-
return execa(cmdArgs[0], cmdArgs.slice(1), { cwd });
|
|
24
|
-
}
|
|
25
|
-
static syncSpawn(cmdArgs, cwd = process.cwd()) {
|
|
26
|
-
return execa.sync(cmdArgs[0], cmdArgs.slice(1), { cwd });
|
|
27
|
-
}
|
|
28
|
-
static fsUrl(url) {
|
|
29
|
-
return url.replace(/^https:\/\//g, "").replace(/^http:\/\//g, "");
|
|
30
|
-
}
|
|
31
|
-
static safeDockerString(jobName) {
|
|
32
|
-
return jobName.replace(/[^\w-]+/g, (match) => {
|
|
33
|
-
return base64url.encode(match);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
static safeBashString(s) {
|
|
37
|
-
return `'${s.replace(/'/g, "'\"'\"'")}'`; // replaces `'` with `'"'"'`
|
|
38
|
-
}
|
|
39
|
-
static forEachRealJob(gitlabData, callback) {
|
|
40
|
-
for (const [jobName, jobData] of Object.entries(gitlabData)) {
|
|
41
|
-
if (Job.illegalJobNames.has(jobName) || jobName[0].startsWith(".")) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
callback(jobName, jobData);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
static getJobNamesFromPreviousStages(jobs, stages, currentJob) {
|
|
48
|
-
const jobNames = [];
|
|
49
|
-
const currentStageIndex = stages.indexOf(currentJob.stage);
|
|
50
|
-
jobs.forEach(job => {
|
|
51
|
-
const stageIndex = stages.indexOf(job.stage);
|
|
52
|
-
if (stageIndex < currentStageIndex) {
|
|
53
|
-
jobNames.push(job.name);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
return jobNames;
|
|
57
|
-
}
|
|
58
|
-
static async getCoveragePercent(cwd, stateDir, coverageRegex, jobName) {
|
|
59
|
-
const content = await fs.readFile(`${cwd}/${stateDir}/output/${jobName}.log`, "utf8");
|
|
60
|
-
const regex = RE2JS.compile(coverageRegex
|
|
61
|
-
.replace(/^\//, "")
|
|
62
|
-
.replace(/\/$/, ""), RE2JS.MULTILINE);
|
|
63
|
-
const matches = Array.from(content.matchAllRE2JS(regex));
|
|
64
|
-
if (matches.length === 0)
|
|
65
|
-
return "0";
|
|
66
|
-
const lastMatch = matches[matches.length - 1];
|
|
67
|
-
const digits = /\d+(?:\.\d+)?/.exec(lastMatch[1] ?? lastMatch[0] ?? "");
|
|
68
|
-
if (!digits)
|
|
69
|
-
return "0";
|
|
70
|
-
return digits[0] ?? "0";
|
|
71
|
-
}
|
|
72
|
-
static printJobNames(stream, job, i, arr) {
|
|
73
|
-
if (i === arr.length - 1) {
|
|
74
|
-
stream(chalk `{blueBright ${job.name}}`);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
stream(chalk `{blueBright ${job.name}}, `);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
static expandTextWith(text, expandWith) {
|
|
81
|
-
if (typeof text !== "string") {
|
|
82
|
-
return text;
|
|
83
|
-
}
|
|
84
|
-
return text.replace(/(\$\$)|\$\{([a-zA-Z_]\w*)}|\$([a-zA-Z_]\w*)/g, // https://regexr.com/7s4ka
|
|
85
|
-
(_match, escape, var1, var2) => {
|
|
86
|
-
if (typeof escape !== "undefined") {
|
|
87
|
-
return expandWith.unescape;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
const name = var1 || var2;
|
|
91
|
-
assert(name, "unexpected unset capture group");
|
|
92
|
-
return `${expandWith.variable(name)}`;
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
static expandText(text, envs) {
|
|
97
|
-
return this.expandTextWith(text, {
|
|
98
|
-
unescape: "$",
|
|
99
|
-
variable: (name) => envs[name] ?? "",
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
static expandVariables(variables) {
|
|
103
|
-
const _variables = { ...variables }; // copy by value to prevent mutating the original input
|
|
104
|
-
let expandedAnyVariables, i = 0;
|
|
105
|
-
do {
|
|
106
|
-
assert(i < 100, "Recursive variable expansion reached 100 iterations");
|
|
107
|
-
expandedAnyVariables = false;
|
|
108
|
-
for (const [k, v] of Object.entries(_variables)) {
|
|
109
|
-
const envsWithoutSelf = { ..._variables };
|
|
110
|
-
delete envsWithoutSelf[k];
|
|
111
|
-
// If the $$'s are converted to single $'s now, then the next
|
|
112
|
-
// iteration, they might be interpreted as _variables, even
|
|
113
|
-
// though they were *explicitly* escaped. To work around this,
|
|
114
|
-
// leave the '$$'s as the same value, then only unescape them at
|
|
115
|
-
// the very end.
|
|
116
|
-
_variables[k] = Utils.expandTextWith(v, {
|
|
117
|
-
unescape: "$$",
|
|
118
|
-
variable: (name) => envsWithoutSelf[name] ?? "",
|
|
119
|
-
});
|
|
120
|
-
expandedAnyVariables ||= _variables[k] !== v;
|
|
121
|
-
}
|
|
122
|
-
i++;
|
|
123
|
-
} while (expandedAnyVariables);
|
|
124
|
-
return _variables;
|
|
125
|
-
}
|
|
126
|
-
static unscape$$Variables(variables) {
|
|
127
|
-
for (const [k, v] of Object.entries(variables)) {
|
|
128
|
-
variables[k] = Utils.expandText(v, {});
|
|
129
|
-
}
|
|
130
|
-
return variables;
|
|
131
|
-
}
|
|
132
|
-
static findEnvMatchedVariables(variables, fileVariablesDir, environment) {
|
|
133
|
-
const envMatchedVariables = {};
|
|
134
|
-
for (const [k, v] of Object.entries(variables)) {
|
|
135
|
-
for (const entry of v.environments) {
|
|
136
|
-
if (environment?.name.match(entry.regexp) || entry.regexp.source === ".*") {
|
|
137
|
-
if (fileVariablesDir != null && v.type === "file" && !entry.fileSource) {
|
|
138
|
-
envMatchedVariables[k] = `${fileVariablesDir}/${k}`;
|
|
139
|
-
fs.mkdirpSync(`${fileVariablesDir}`);
|
|
140
|
-
fs.writeFileSync(`${fileVariablesDir}/${k}`, entry.content);
|
|
141
|
-
}
|
|
142
|
-
else if (fileVariablesDir != null && v.type === "file" && entry.fileSource) {
|
|
143
|
-
envMatchedVariables[k] = `${fileVariablesDir}/${k}`;
|
|
144
|
-
fs.mkdirpSync(`${fileVariablesDir}`);
|
|
145
|
-
fs.copyFileSync(entry.fileSource, `${fileVariablesDir}/${k}`);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
envMatchedVariables[k] = entry.content;
|
|
149
|
-
}
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return envMatchedVariables;
|
|
155
|
-
}
|
|
156
|
-
static getRulesResult(opt, gitData, jobWhen = "on_success", jobAllowFailure = false) {
|
|
157
|
-
let when = "never";
|
|
158
|
-
const { evaluateRuleChanges } = opt.argv;
|
|
159
|
-
// optional manual jobs allowFailure defaults to true https://docs.gitlab.com/ee/ci/jobs/job_control.html#types-of-manual-jobs
|
|
160
|
-
let allowFailure = jobWhen === "manual" ? true : jobAllowFailure;
|
|
161
|
-
let ruleVariable;
|
|
162
|
-
let ruleNeeds;
|
|
163
|
-
for (const rule of opt.rules) {
|
|
164
|
-
if (!Utils.evaluateRuleIf(rule.if, opt.variables))
|
|
165
|
-
continue;
|
|
166
|
-
if (!Utils.evaluateRuleExist(opt.cwd, rule.exists))
|
|
167
|
-
continue;
|
|
168
|
-
if (evaluateRuleChanges && !Utils.evaluateRuleChanges(gitData.branches.default, rule.changes, opt.cwd))
|
|
169
|
-
continue;
|
|
170
|
-
when = rule.when ? rule.when : jobWhen;
|
|
171
|
-
allowFailure = rule.allow_failure ?? allowFailure;
|
|
172
|
-
ruleVariable = rule.variables;
|
|
173
|
-
ruleNeeds = rule.needs?.map((n) => needsComplex(n));
|
|
174
|
-
break; // Early return, will not evaluate the remaining rules
|
|
175
|
-
}
|
|
176
|
-
return { when, allowFailure, variables: ruleVariable, needs: ruleNeeds };
|
|
177
|
-
}
|
|
178
|
-
static evaluateRuleIf(ruleIf, envs) {
|
|
179
|
-
if (ruleIf === undefined)
|
|
180
|
-
return true;
|
|
181
|
-
let evalStr = ruleIf;
|
|
182
|
-
const flagsToBinary = (flags) => {
|
|
183
|
-
let binary = 0;
|
|
184
|
-
if (flags.includes("i")) {
|
|
185
|
-
binary |= RE2JS.CASE_INSENSITIVE;
|
|
186
|
-
}
|
|
187
|
-
if (flags.includes("s")) {
|
|
188
|
-
binary |= RE2JS.DOTALL;
|
|
189
|
-
}
|
|
190
|
-
if (flags.includes("m")) {
|
|
191
|
-
binary |= RE2JS.MULTILINE;
|
|
192
|
-
}
|
|
193
|
-
return binary;
|
|
194
|
-
};
|
|
195
|
-
// Expand all variables
|
|
196
|
-
evalStr = this.expandTextWith(evalStr, {
|
|
197
|
-
unescape: JSON.stringify("$"),
|
|
198
|
-
variable: (name) => JSON.stringify(envs[name] ?? null).replaceAll("\\\\", "\\"),
|
|
199
|
-
});
|
|
200
|
-
const expandedEvalStr = evalStr;
|
|
201
|
-
// Scenario when RHS is a <regex>
|
|
202
|
-
// https://regexr.com/85sjo
|
|
203
|
-
const pattern1 = /\s*(?<operator>(?:=~)|(?:!~))\s*\/(?<rhs>.*?[^\\])\/(?<flags>[igmsuy]*)(\s|$|\))/g;
|
|
204
|
-
evalStr = evalStr.replace(pattern1, (_, operator, rhs, flags, remainingTokens) => {
|
|
205
|
-
let _operator;
|
|
206
|
-
switch (operator) {
|
|
207
|
-
case "=~":
|
|
208
|
-
_operator = "!=";
|
|
209
|
-
break;
|
|
210
|
-
case "!~":
|
|
211
|
-
_operator = "==";
|
|
212
|
-
break;
|
|
213
|
-
default:
|
|
214
|
-
throw operator;
|
|
215
|
-
}
|
|
216
|
-
const _rhs = JSON.stringify(rhs); // JSON.stringify for escaping `"`
|
|
217
|
-
const containsNonEscapedSlash = /(?<!\\)\//.test(_rhs);
|
|
218
|
-
const assertMsg = [
|
|
219
|
-
"Error attempting to evaluate the following rules:",
|
|
220
|
-
" rules:",
|
|
221
|
-
` - if: '${expandedEvalStr}'`,
|
|
222
|
-
"as rhs contains unescaped quote",
|
|
223
|
-
];
|
|
224
|
-
assert(!containsNonEscapedSlash, assertMsg.join("\n"));
|
|
225
|
-
const flagsBinary = flagsToBinary(flags);
|
|
226
|
-
return `.matchRE2JS(RE2JS.compile(${_rhs}, ${flagsBinary})) ${_operator} null${remainingTokens}`;
|
|
227
|
-
});
|
|
228
|
-
// Scenario when RHS is surrounded by single/double-quotes
|
|
229
|
-
// https://regexr.com/85t0g
|
|
230
|
-
const pattern2 = /\s*(?<operator>=~|!~)\s*(["'])(?<rhs>(?:\\.|[^\\])*?)\2/g;
|
|
231
|
-
evalStr = evalStr.replace(pattern2, (_, operator, __, rhs) => {
|
|
232
|
-
let _operator;
|
|
233
|
-
switch (operator) {
|
|
234
|
-
case "=~":
|
|
235
|
-
_operator = "!=";
|
|
236
|
-
break;
|
|
237
|
-
case "!~":
|
|
238
|
-
_operator = "==";
|
|
239
|
-
break;
|
|
240
|
-
default:
|
|
241
|
-
throw operator;
|
|
242
|
-
}
|
|
243
|
-
const assertMsg = [
|
|
244
|
-
"RHS (${rhs}) must be a regex pattern. Do not rely on this behavior!",
|
|
245
|
-
"Refer to https://docs.gitlab.com/ee/ci/jobs/job_rules.html#unexpected-behavior-from-regular-expression-matching-with- for more info...",
|
|
246
|
-
];
|
|
247
|
-
assert((/\/(.*)\/(\w*)/.test(rhs)), assertMsg.join("\n"));
|
|
248
|
-
const regex = /\/(?<pattern>.*)\/(?<flags>[igmsuy]*)/;
|
|
249
|
-
const _rhs = rhs.replace(regex, (_, pattern, flags) => {
|
|
250
|
-
const flagsBinary = flagsToBinary(flags);
|
|
251
|
-
return `RE2JS.compile("${pattern}", ${flagsBinary})`;
|
|
252
|
-
});
|
|
253
|
-
return `.matchRE2JS(${_rhs}) ${_operator} null`;
|
|
254
|
-
});
|
|
255
|
-
evalStr = evalStr.replace(/null.matchRE2JS\(.+?\)\s*!=\s*null/g, "false");
|
|
256
|
-
evalStr = evalStr.replace(/null.matchRE2JS\(.+?\)\s*==\s*null/g, "true");
|
|
257
|
-
evalStr = evalStr.trim();
|
|
258
|
-
let res;
|
|
259
|
-
try {
|
|
260
|
-
global.RE2JS = RE2JS; // Assign RE2JS to the global object
|
|
261
|
-
res = (0, eval)(evalStr); // https://esbuild.github.io/content-types/#direct-eval
|
|
262
|
-
delete global.RE2JS; // Cleanup
|
|
263
|
-
}
|
|
264
|
-
catch {
|
|
265
|
-
const assertMsg = [
|
|
266
|
-
"Error attempting to evaluate the following rules:",
|
|
267
|
-
" rules:",
|
|
268
|
-
` - if: '${expandedEvalStr}'`,
|
|
269
|
-
"as",
|
|
270
|
-
"```javascript",
|
|
271
|
-
`${evalStr}`,
|
|
272
|
-
"```",
|
|
273
|
-
];
|
|
274
|
-
assert(false, assertMsg.join("\n"));
|
|
275
|
-
}
|
|
276
|
-
return Boolean(res);
|
|
277
|
-
}
|
|
278
|
-
static evaluateRuleExist(cwd, ruleExists) {
|
|
279
|
-
if (ruleExists === undefined)
|
|
280
|
-
return true;
|
|
281
|
-
// Normalize rules:exists:paths to rules:exists
|
|
282
|
-
if (!Array.isArray(ruleExists))
|
|
283
|
-
ruleExists = ruleExists.paths;
|
|
284
|
-
for (const pattern of ruleExists) {
|
|
285
|
-
if (pattern == "") {
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
if (globbySync(pattern, { dot: true, cwd }).length > 0) {
|
|
289
|
-
return true;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
static evaluateRuleChanges(defaultBranch, ruleChanges, cwd) {
|
|
295
|
-
if (ruleChanges === undefined)
|
|
296
|
-
return true;
|
|
297
|
-
// Normalize rules:changes:paths to rules:changes
|
|
298
|
-
if (!Array.isArray(ruleChanges))
|
|
299
|
-
ruleChanges = ruleChanges.paths;
|
|
300
|
-
// NOTE: https://docs.gitlab.com/ee/ci/yaml/#ruleschanges
|
|
301
|
-
// Glob patterns are interpreted with Ruby's [File.fnmatch](https://docs.ruby-lang.org/en/master/File.html#method-c-fnmatch)
|
|
302
|
-
// with the flags File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB.
|
|
303
|
-
return micromatch.some(GitData.changedFiles(`origin/${defaultBranch}`, cwd), ruleChanges, {
|
|
304
|
-
nonegate: true,
|
|
305
|
-
noextglob: true,
|
|
306
|
-
posix: false,
|
|
307
|
-
dot: true,
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
static isSubpath(lhs, rhs, cwd = process.cwd()) {
|
|
311
|
-
let absLhs = "";
|
|
312
|
-
if (path.isAbsolute(lhs)) {
|
|
313
|
-
absLhs = lhs;
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
absLhs = path.resolve(cwd, lhs);
|
|
317
|
-
}
|
|
318
|
-
let absRhs = "";
|
|
319
|
-
if (path.isAbsolute(rhs)) {
|
|
320
|
-
absRhs = rhs;
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
absRhs = path.resolve(cwd, rhs);
|
|
324
|
-
}
|
|
325
|
-
const relative = path.relative(absRhs, absLhs);
|
|
326
|
-
return !relative.startsWith("..");
|
|
327
|
-
}
|
|
328
|
-
static async rsyncTrackedFiles(cwd, stateDir, target) {
|
|
329
|
-
const time = process.hrtime();
|
|
330
|
-
await fs.mkdirp(`${cwd}/${stateDir}/builds/${target}`);
|
|
331
|
-
await Utils.bash(`rsync -a --delete-excluded --delete --exclude-from=<(git ls-files -o --directory | awk '{print "/"$0}') --exclude ${stateDir}/ ./ ${stateDir}/builds/${target}/`, cwd);
|
|
332
|
-
return { hrdeltatime: process.hrtime(time) };
|
|
333
|
-
}
|
|
334
|
-
static async checksumFiles(cwd, files) {
|
|
335
|
-
const promises = [];
|
|
336
|
-
files.forEach((file) => {
|
|
337
|
-
promises.push(new Promise((resolve, reject) => {
|
|
338
|
-
if (!fs.pathExistsSync(file))
|
|
339
|
-
resolve(path.relative(cwd, file)); // must use relative path here, so that checksum can be deterministic when running the unit tests
|
|
340
|
-
checksum.file(file, (err, hash) => {
|
|
341
|
-
if (err) {
|
|
342
|
-
return reject(err);
|
|
343
|
-
}
|
|
344
|
-
resolve(hash);
|
|
345
|
-
});
|
|
346
|
-
}));
|
|
347
|
-
});
|
|
348
|
-
const result = await Promise.all(promises);
|
|
349
|
-
return checksum(result.join(""));
|
|
350
|
-
}
|
|
351
|
-
static isObject(v) {
|
|
352
|
-
return Object.getPrototypeOf(v) === Object.prototype;
|
|
353
|
-
}
|
|
354
|
-
static switchStatementExhaustiveCheck(param) {
|
|
355
|
-
// https://dev.to/babak/exhaustive-type-checking-with-typescript-4l3f
|
|
356
|
-
throw new Error(`Unhandled case ${param}`);
|
|
357
|
-
}
|
|
358
|
-
static async dockerVolumeFileExists(containerExecutable, path, volume) {
|
|
359
|
-
try {
|
|
360
|
-
await Utils.spawn([containerExecutable, "run", "--rm", "-v", `${volume}:/mnt/vol`, "alpine", "ls", `/mnt/vol/${path}`]);
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
catch {
|
|
364
|
-
return false;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
static gclRegistryPrefix = "registry.gcl.local";
|
|
368
|
-
static async startDockerRegistry(argv) {
|
|
369
|
-
const gclRegistryCertVol = `${this.gclRegistryPrefix}.certs`;
|
|
370
|
-
const gclRegistryDataVol = `${this.gclRegistryPrefix}.data`;
|
|
371
|
-
const gclRegistryNet = `${this.gclRegistryPrefix}.net`;
|
|
372
|
-
// create cert volume
|
|
373
|
-
try {
|
|
374
|
-
await Utils.spawn(`${argv.containerExecutable} volume create ${gclRegistryCertVol}`.split(" "));
|
|
375
|
-
}
|
|
376
|
-
catch (err) {
|
|
377
|
-
if (err instanceof Error && !err.message.endsWith("already exists"))
|
|
378
|
-
throw err;
|
|
379
|
-
}
|
|
380
|
-
// create self-signed cert/key files for https support
|
|
381
|
-
if (!await this.dockerVolumeFileExists(argv.containerExecutable, `${this.gclRegistryPrefix}.crt`, gclRegistryCertVol)) {
|
|
382
|
-
const opensslArgs = [
|
|
383
|
-
"req", "-newkey", "rsa:4096", "-nodes", "-sha256",
|
|
384
|
-
"-keyout", `/certs/${this.gclRegistryPrefix}.key`,
|
|
385
|
-
"-x509", "-days", "365",
|
|
386
|
-
"-out", `/certs/${this.gclRegistryPrefix}.crt`,
|
|
387
|
-
"-subj", `/CN=${this.gclRegistryPrefix}`,
|
|
388
|
-
"-addext", `subjectAltName=DNS:${this.gclRegistryPrefix}`,
|
|
389
|
-
];
|
|
390
|
-
const generateCertsInPlace = [
|
|
391
|
-
argv.containerExecutable, "run", "--rm", "-v", `${gclRegistryCertVol}:/certs`, "--entrypoint", "sh", "alpine/openssl", "-c",
|
|
392
|
-
[
|
|
393
|
-
"openssl", ...opensslArgs,
|
|
394
|
-
"&&", "mkdir", "-p", `/certs/${this.gclRegistryPrefix}`,
|
|
395
|
-
"&&", "cp", `/certs/${this.gclRegistryPrefix}.crt`, `/certs/${this.gclRegistryPrefix}/ca.crt`,
|
|
396
|
-
].join(" "),
|
|
397
|
-
];
|
|
398
|
-
await Utils.spawn(generateCertsInPlace);
|
|
399
|
-
}
|
|
400
|
-
// create data volume
|
|
401
|
-
try {
|
|
402
|
-
await Utils.spawn([argv.containerExecutable, "volume", "create", gclRegistryDataVol]);
|
|
403
|
-
}
|
|
404
|
-
catch (err) {
|
|
405
|
-
if (err instanceof Error && !err.message.endsWith("already exists"))
|
|
406
|
-
throw err;
|
|
407
|
-
}
|
|
408
|
-
// create network
|
|
409
|
-
try {
|
|
410
|
-
await Utils.spawn([argv.containerExecutable, "network", "create", gclRegistryNet]);
|
|
411
|
-
}
|
|
412
|
-
catch (err) {
|
|
413
|
-
if (err instanceof Error && !err.message.includes("already exists"))
|
|
414
|
-
throw err;
|
|
415
|
-
}
|
|
416
|
-
await Utils.spawn([argv.containerExecutable, "rm", "-f", this.gclRegistryPrefix]);
|
|
417
|
-
await Utils.spawn([
|
|
418
|
-
argv.containerExecutable, "run", "-d", "--name", this.gclRegistryPrefix,
|
|
419
|
-
"--network", gclRegistryNet,
|
|
420
|
-
"--volume", `${gclRegistryDataVol}:/var/lib/registry`,
|
|
421
|
-
"--volume", `${gclRegistryCertVol}:/certs:ro`,
|
|
422
|
-
"-e", "REGISTRY_HTTP_ADDR=0.0.0.0:443",
|
|
423
|
-
"-e", `REGISTRY_HTTP_TLS_CERTIFICATE=/certs/${this.gclRegistryPrefix}.crt`,
|
|
424
|
-
"-e", `REGISTRY_HTTP_TLS_KEY=/certs/${this.gclRegistryPrefix}.key`,
|
|
425
|
-
"registry",
|
|
426
|
-
]);
|
|
427
|
-
try {
|
|
428
|
-
await execa(argv.containerExecutable, [
|
|
429
|
-
"run", "--rm",
|
|
430
|
-
"--network", gclRegistryNet,
|
|
431
|
-
"--entrypoint", "sh",
|
|
432
|
-
"curlimages/curl",
|
|
433
|
-
"-c", `until [ "$(curl -s -o /dev/null -k -w "%{http_code}" https://${this.gclRegistryPrefix}:443)" = "200" ]; do sleep 1; done;`,
|
|
434
|
-
], {
|
|
435
|
-
timeout: 4000,
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
catch (err) {
|
|
439
|
-
await this.stopDockerRegistry(argv.containerExecutable);
|
|
440
|
-
if (err.timedOut) {
|
|
441
|
-
throw "local docker registry port check timed out";
|
|
442
|
-
}
|
|
443
|
-
throw err;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
static async stopDockerRegistry(containerExecutable) {
|
|
447
|
-
await Utils.spawn([containerExecutable, "rm", "-f", this.gclRegistryPrefix]);
|
|
448
|
-
}
|
|
449
|
-
static async getTrackedFiles(cwd) {
|
|
450
|
-
const lsFilesRes = await Utils.bash("git ls-files --deduplicate", cwd);
|
|
451
|
-
if (lsFilesRes.exitCode != 0) {
|
|
452
|
-
throw new Error(`Failed to list tracked files in ${cwd}: ${lsFilesRes.stderr}`);
|
|
453
|
-
}
|
|
454
|
-
return lsFilesRes.stdout.split("\n");
|
|
455
|
-
}
|
|
456
|
-
static getAxiosProxyConfig() {
|
|
457
|
-
const proxyEnv = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
|
|
458
|
-
if (proxyEnv) {
|
|
459
|
-
const proxyUrl = new URL(proxyEnv);
|
|
460
|
-
return {
|
|
461
|
-
proxy: {
|
|
462
|
-
host: proxyUrl.hostname,
|
|
463
|
-
port: proxyUrl.port ? parseInt(proxyUrl.port, 10) : 8080,
|
|
464
|
-
protocol: proxyUrl.protocol.replace(":", ""),
|
|
465
|
-
},
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
return {};
|
|
469
|
-
}
|
|
470
|
-
static normalizeVariables(variable) {
|
|
471
|
-
if (variable === null) {
|
|
472
|
-
return ""; // variable's values are nullable
|
|
473
|
-
}
|
|
474
|
-
else if (Utils.isObject(variable)) {
|
|
475
|
-
if (variable["expand"] === false) {
|
|
476
|
-
return String(variable["value"]).replaceAll("$", () => "$$");
|
|
477
|
-
}
|
|
478
|
-
return String(variable["value"]);
|
|
479
|
-
}
|
|
480
|
-
else {
|
|
481
|
-
return String(variable);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sT0FBTyxDQUFDO0FBQzVCLE9BQU8sS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ25DLE9BQU8sRUFBQyxHQUFHLEVBQWdCLE1BQU0sVUFBVSxDQUFDO0FBQzVDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDMUIsT0FBTyxRQUFRLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sU0FBUyxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEtBQW1CLE1BQU0sT0FBTyxDQUFDO0FBQ3hDLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUU1QixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3RDLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFDbEMsT0FBTyxVQUFVLE1BQU0sWUFBWSxDQUFDO0FBRXBDLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQWV4QixNQUFNLE9BQU8sS0FBSztJQUNkLE1BQU0sQ0FBQyxTQUFTLENBQUUsT0FBaUIsRUFBRSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRTtRQUNwRCxPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUMsQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFFRCxNQUFNLENBQUMsSUFBSSxDQUFFLFdBQW1CLEVBQUUsR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUU7UUFDakQsT0FBTyxLQUFLLENBQUMsV0FBVyxFQUFFLEVBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVB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QzthQUNKLENBQUM7UUFDTixDQUFDO1FBQ0QsT0FBTyxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsTUFBTSxDQUFDLGtCQUFrQixDQUFFLFFBQWE7UUFDcEMsSUFBSSxRQUFRLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDcEIsT0FBTyxFQUFFLENBQUMsQ0FBQyxpQ0FBaUM7UUFDaEQsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2xDLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEtBQUssRUFBRSxDQUFDO2dCQUMvQixPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pFLENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNyQyxDQUFDO2FBQU0sQ0FBQztZQUNKLE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzVCLENBQUM7SUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFwiLi9nbG9iYWwuanNcIjtcbmltcG9ydCB7UkUySlN9IGZyb20gXCJyZTJqc1wiO1xuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsay10ZW1wbGF0ZVwiO1xuaW1wb3J0IHtKb2IsIEpvYlJ1bGUsIE5lZWR9IGZyb20gXCIuL2pvYi5qc1wiO1xuaW1wb3J0IHtuZWVkc0NvbXBsZXh9IGZyb20gXCIuL2RhdGEtZXhwYW5kZXIuanNcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnMtZXh0cmFcIjtcbmltcG9ydCBjaGVja3N1bSBmcm9tIFwiY2hlY2tzdW1cIjtcbmltcG9ydCBiYXNlNjR1cmwgZnJvbSBcImJhc2U2NHVybFwiO1xuaW1wb3J0IGV4ZWNhLCB7RXhlY2FFcnJvcn0gZnJvbSBcImV4ZWNhXCI7XG5pbXBvcnQgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCB7Q0lDRFZhcmlhYmxlfSBmcm9tIFwiLi92YXJpYWJsZXMtZnJvbS1maWxlcy5qc1wiO1xuaW1wb3J0IHtHaXREYXRhfSBmcm9tIFwiLi9naXQtZGF0YS5qc1wiO1xuaW1wb3J0IHtnbG9iYnlTeW5jfSBmcm9tIFwiZ2xvYmJ5XCI7XG5pbXBvcnQgbWljcm9tYXRjaCBmcm9tIFwibWljcm9tYXRjaFwiO1xuaW1wb3J0IHtBeGlvc1JlcXVlc3RDb25maWd9IGZyb20gXCJheGlvc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7QXJndn0gZnJvbSBcIi4vYXJndi5qc1wiO1xuXG50eXBlIFJ1bGVSZXN1bHRPcHQgPSB7XG4gICAgYXJndjogQXJndjtcbiAgICBjd2Q6IHN0cmluZztcbiAgICBydWxlczogSm9iUnVsZVtdO1xuICAgIHZhcmlhYmxlczoge1trZXk6IHN0cmluZ106IHN0cmluZ307XG59O1xuXG50eXBlIEV4cGFuZFdpdGggPSB7XG4gICAgdW5lc2NhcGU6IHN0cmluZztcbiAgICB2YXJpYWJsZTogKG5hbWU6IHN0cmluZykgPT4gc3RyaW5nO1xufTtcblxuZXhwb3J0IGNsYXNzIFV0aWxzIHtcbiAgICBzdGF0aWMgYmFzaE11bHRpIChzY3JpcHRzOiBzdHJpbmdbXSwgY3dkID0gcHJvY2Vzcy5jd2QoKSk6IFByb21pc2U8e3N0ZG91dDogc3RyaW5nOyBzdGRlcnI6IHN0cmluZzsgZXhpdENvZGU6IG51bWJlcn0+IHtcbiAgICAgICAgcmV0dXJuIGV4ZWNhKHNjcmlwdHMuam9pbihcIiAmJiBcXFxcXCIpLCB7c2hlbGw6IFwiYmFzaFwiLCBjd2R9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgYmFzaCAoc2hlbGxTY3JpcHQ6IHN0cmluZywgY3dkID0gcHJvY2Vzcy5jd2QoKSk6IFByb21pc2U8e3N0ZG91dDogc3RyaW5nOyBzdGRlcnI6IHN0cmluZzsgZXhpdENvZGU6IG51bWJlcn0+IHtcbiAgICAgICAgcmV0dXJuIGV4ZWNhKHNoZWxsU2NyaXB0LCB7c2hlbGw6IFwiYmFzaFwiLCBjd2R9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgc3Bhd24gKGNtZEFyZ3M6IHN0cmluZ1tdLCBjd2QgPSBwcm9jZXNzLmN3ZCgpKTogUHJvbWlzZTx7c3Rkb3V0OiBzdHJpbmc7IHN0ZGVycjogc3RyaW5nfT4ge1xuICAgICAgICByZXR1cm4gZXhlY2EoY21kQXJnc1swXSwgY21kQXJncy5zbGljZSgxKSwge2N3ZH0pO1xuICAgIH1cblxuICAgIHN0YXRpYyBzeW5jU3Bhd24gKGNtZEFyZ3M6IHN0cmluZ1tdLCBjd2QgPSBwcm9jZXNzLmN3ZCgpKToge3N0ZG91dDogc3RyaW5nOyBzdGRlcnI6IHN0cmluZ30ge1xuICAgICAgICByZXR1cm4gZXhlY2Euc3luYyhjbWRBcmdzWzBdLCBjbWRBcmdzLnNsaWNlKDEpLCB7Y3dkfSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGZzVXJsICh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB1cmwucmVwbGFjZSgvXmh0dHBzOlxcL1xcLy9nLCBcIlwiKS5yZXBsYWNlKC9eaHR0cDpcXC9cXC8vZywgXCJcIik7XG4gICAgfVxuXG4gICAgc3RhdGljIHNhZmVEb2NrZXJTdHJpbmcgKGpvYk5hbWU6IHN0cmluZykge1xuICAgICAgICByZXR1cm4gam9iTmFtZS5yZXBsYWNlKC9bXlxcdy1dKy9nLCAobWF0Y2gpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBiYXNlNjR1cmwuZW5jb2RlKG1hdGNoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3RhdGljIHNhZmVCYXNoU3RyaW5nIChzOiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIGAnJHtzLnJlcGxhY2UoLycvZywgXCInXFxcIidcXFwiJ1wiKX0nYDsgLy8gcmVwbGFjZXMgYCdgIHdpdGggYCdcIidcIidgXG4gICAgfVxuXG4gICAgc3RhdGljIGZvckVhY2hSZWFsSm9iIChnaXRsYWJEYXRhOiBhbnksIGNhbGxiYWNrOiAoam9iTmFtZTogc3RyaW5nLCBqb2JEYXRhOiBhbnkpID0+IHZvaWQpIHtcbiAgICAgICAgZm9yIChjb25zdCBbam9iTmFtZSwgam9iRGF0YV0gb2YgT2JqZWN0LmVudHJpZXM8YW55PihnaXRsYWJEYXRhKSkge1xuICAgICAgICAgICAgaWYgKEpvYi5pbGxlZ2FsSm9iTmFtZXMuaGFzKGpvYk5hbWUpIHx8IGpvYk5hbWVbMF0uc3RhcnRzV2l0aChcIi5cIikpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKGpvYk5hbWUsIGpvYkRhdGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGdldEpvYk5hbWVzRnJvbVByZXZpb3VzU3RhZ2VzIChqb2JzOiBSZWFkb25seUFycmF5PEpvYj4sIHN0YWdlczogcmVhZG9ubHkgc3RyaW5nW10sIGN1cnJlbnRKb2I6IEpvYikge1xuICAgICAgICBjb25zdCBqb2JOYW1lczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgY29uc3QgY3VycmVudFN0YWdlSW5kZXggPSBzdGFnZXMuaW5kZXhPZihjdXJyZW50Sm9iLnN0YWdlKTtcbiAgICAgICAgam9icy5mb3JFYWNoKGpvYiA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdGFnZUluZGV4ID0gc3RhZ2VzLmluZGV4T2Yoam9iLnN0YWdlKTtcbiAgICAgICAgICAgIGlmIChzdGFnZUluZGV4IDwgY3VycmVudFN0YWdlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICBqb2JOYW1lcy5wdXNoKGpvYi5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBqb2JOYW1lcztcbiAgICB9XG5cbiAgICBzdGF0aWMgYXN5bmMgZ2V0Q292ZXJhZ2VQZXJjZW50IChjd2Q6IHN0cmluZywgc3RhdGVEaXI6IHN0cmluZywgY292ZXJhZ2VSZWdleDogc3RyaW5nLCBqb2JOYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGAke2N3ZH0vJHtzdGF0ZURpcn0vb3V0cHV0LyR7am9iTmFtZX0ubG9nYCwgXCJ1dGY4XCIpO1xuXG4gICAgICAgIGNvbnN0IHJlZ2V4ID0gUkUySlMuY29tcGlsZShcbiAgICAgICAgICAgIGNvdmVyYWdlUmVnZXhcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXlxcLy8sIFwiXCIpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcLyQvLCBcIlwiKSxcbiAgICAgICAgICAgIFJFMkpTLk1VTFRJTElORSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgbWF0Y2hlcyA9IEFycmF5LmZyb20oY29udGVudC5tYXRjaEFsbFJFMkpTKHJlZ2V4KSk7XG4gICAgICAgIGlmIChtYXRjaGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFwiMFwiO1xuXG4gICAgICAgIGNvbnN0IGxhc3RNYXRjaCA9IG1hdGNoZXNbbWF0Y2hlcy5sZW5ndGggLSAxXTtcbiAgICAgICAgY29uc3QgZGlnaXRzID0gL1xcZCsoPzpcXC5cXGQrKT8vLmV4ZWMobGFzdE1hdGNoWzFdID8/IGxhc3RNYXRjaFswXSA/PyBcIlwiKTtcbiAgICAgICAgaWYgKCFkaWdpdHMpIHJldHVybiBcIjBcIjtcbiAgICAgICAgcmV0dXJuIGRpZ2l0c1swXSA/PyBcIjBcIjtcbiAgICB9XG5cbiAgICBzdGF0aWMgcHJpbnRKb2JOYW1lcyAoc3RyZWFtOiAodHh0OiBzdHJpbmcpID0+IHZvaWQsIGpvYjoge25hbWU6IHN0cmluZ30sIGk6IG51bWJlciwgYXJyOiB7bmFtZTogc3RyaW5nfVtdKSB7XG4gICAgICAgIGlmIChpID09PSBhcnIubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgc3RyZWFtKGNoYWxrYHtibHVlQnJpZ2h0ICR7am9iLm5hbWV9fWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RyZWFtKGNoYWxrYHtibHVlQnJpZ2h0ICR7am9iLm5hbWV9fSwgYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBleHBhbmRUZXh0V2l0aCAodGV4dDogYW55LCBleHBhbmRXaXRoOiBFeHBhbmRXaXRoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGV4dCAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKFxuICAgICAgICAgICAgLyhcXCRcXCQpfFxcJFxceyhbYS16QS1aX11cXHcqKX18XFwkKFthLXpBLVpfXVxcdyopL2csIC8vIGh0dHBzOi8vcmVnZXhyLmNvbS83czRrYVxuICAgICAgICAgICAgKF9tYXRjaCwgZXNjYXBlLCB2YXIxLCB2YXIyKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBlc2NhcGUgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGFuZFdpdGgudW5lc2NhcGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmFtZSA9IHZhcjEgfHwgdmFyMjtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KG5hbWUsIFwidW5leHBlY3RlZCB1bnNldCBjYXB0dXJlIGdyb3VwXCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYCR7ZXhwYW5kV2l0aC52YXJpYWJsZShuYW1lKX1gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgc3RhdGljIGV4cGFuZFRleHQgKHRleHQ6IGFueSwgZW52czoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwYW5kVGV4dFdpdGgodGV4dCwge1xuICAgICAgICAgICAgdW5lc2NhcGU6IFwiJFwiLFxuICAgICAgICAgICAgdmFyaWFibGU6IChuYW1lKSA9PiBlbnZzW25hbWVdID8/IFwiXCIsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0YXRpYyBleHBhbmRWYXJpYWJsZXMgKHZhcmlhYmxlczoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgY29uc3QgX3ZhcmlhYmxlcyA9IHsuLi52YXJpYWJsZXN9OyAvLyBjb3B5IGJ5IHZhbHVlIHRvIHByZXZlbnQgbXV0YXRpbmcgdGhlIG9yaWdpbmFsIGlucHV0XG4gICAgICAgIGxldCBleHBhbmRlZEFueVZhcmlhYmxlcywgaSA9IDA7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIGFzc2VydChpIDwgMTAwLCBcIlJlY3Vyc2l2ZSB2YXJpYWJsZSBleHBhbnNpb24gcmVhY2hlZCAxMDAgaXRlcmF0aW9uc1wiKTtcbiAgICAgICAgICAgIGV4cGFuZGVkQW55VmFyaWFibGVzID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhfdmFyaWFibGVzKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVudnNXaXRob3V0U2VsZiA9IHsuLi5fdmFyaWFibGVzfTtcbiAgICAgICAgICAgICAgICBkZWxldGUgZW52c1dpdGhvdXRTZWxmW2tdO1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSAkJCdzIGFyZSBjb252ZXJ0ZWQgdG8gc2luZ2xlICQncyBub3csIHRoZW4gdGhlIG5leHRcbiAgICAgICAgICAgICAgICAvLyBpdGVyYXRpb24sIHRoZXkgbWlnaHQgYmUgaW50ZXJwcmV0ZWQgYXMgX3ZhcmlhYmxlcywgZXZlblxuICAgICAgICAgICAgICAgIC8vIHRob3VnaCB0aGV5IHdlcmUgKmV4cGxpY2l0bHkqIGVzY2FwZWQuIFRvIHdvcmsgYXJvdW5kIHRoaXMsXG4gICAgICAgICAgICAgICAgLy8gbGVhdmUgdGhlICckJCdzIGFzIHRoZSBzYW1lIHZhbHVlLCB0aGVuIG9ubHkgdW5lc2NhcGUgdGhlbSBhdFxuICAgICAgICAgICAgICAgIC8vIHRoZSB2ZXJ5IGVuZC5cbiAgICAgICAgICAgICAgICBfdmFyaWFibGVzW2tdID0gVXRpbHMuZXhwYW5kVGV4dFdpdGgodiwge1xuICAgICAgICAgICAgICAgICAgICB1bmVzY2FwZTogXCIkJFwiLFxuICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZTogKG5hbWUpID0+IGVudnNXaXRob3V0U2VsZltuYW1lXSA/PyBcIlwiLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGV4cGFuZGVkQW55VmFyaWFibGVzIHx8PSBfdmFyaWFibGVzW2tdICE9PSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9IHdoaWxlIChleHBhbmRlZEFueVZhcmlhYmxlcyk7XG5cbiAgICAgICAgcmV0dXJuIF92YXJpYWJsZXM7XG4gICAgfVxuXG4gICAgc3RhdGljIHVuc2NhcGUkJFZhcmlhYmxlcyAodmFyaWFibGVzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSkge1xuICAgICAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyh2YXJpYWJsZXMpKSB7XG4gICAgICAgICAgICB2YXJpYWJsZXNba10gPSBVdGlscy5leHBhbmRUZXh0KHYsIHt9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YXJpYWJsZXM7XG4gICAgfVxuXG4gICAgc3RhdGljIGZpbmRFbnZNYXRjaGVkVmFyaWFibGVzICh2YXJpYWJsZXM6IHtbbmFtZTogc3RyaW5nXTogQ0lDRFZhcmlhYmxlfSwgZmlsZVZhcmlhYmxlc0Rpcj86IHN0cmluZywgZW52aXJvbm1lbnQ/OiB7bmFtZTogc3RyaW5nfSkge1xuICAgICAgICBjb25zdCBlbnZNYXRjaGVkVmFyaWFibGVzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyh2YXJpYWJsZXMpKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHYuZW52aXJvbm1lbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVudmlyb25tZW50Py5uYW1lLm1hdGNoKGVudHJ5LnJlZ2V4cCkgfHwgZW50cnkucmVnZXhwLnNvdXJjZSA9PT0gXCIuKlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlVmFyaWFibGVzRGlyICE9IG51bGwgJiYgdi50eXBlID09PSBcImZpbGVcIiAmJiAhZW50cnkuZmlsZVNvdXJjZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW52TWF0Y2hlZFZhcmlhYmxlc1trXSA9IGAke2ZpbGVWYXJpYWJsZXNEaXJ9LyR7a31gO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnMubWtkaXJwU3luYyhgJHtmaWxlVmFyaWFibGVzRGlyfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnMud3JpdGVGaWxlU3luYyhgJHtmaWxlVmFyaWFibGVzRGlyfS8ke2t9YCwgZW50cnkuY29udGVudCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZmlsZVZhcmlhYmxlc0RpciAhPSBudWxsICYmIHYudHlwZSA9PT0gXCJmaWxlXCIgJiYgZW50cnkuZmlsZVNvdXJjZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW52TWF0Y2hlZFZhcmlhYmxlc1trXSA9IGAke2ZpbGVWYXJpYWJsZXNEaXJ9LyR7a31gO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnMubWtkaXJwU3luYyhgJHtmaWxlVmFyaWFibGVzRGlyfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnMuY29weUZpbGVTeW5jKGVudHJ5LmZpbGVTb3VyY2UsIGAke2ZpbGVWYXJpYWJsZXNEaXJ9LyR7a31gKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudk1hdGNoZWRWYXJpYWJsZXNba10gPSBlbnRyeS5jb250ZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZW52TWF0Y2hlZFZhcmlhYmxlcztcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0UnVsZXNSZXN1bHQgKG9wdDogUnVsZVJlc3VsdE9wdCwgZ2l0RGF0YTogR2l0RGF0YSwgam9iV2hlbjogc3RyaW5nID0gXCJvbl9zdWNjZXNzXCIsIGpvYkFsbG93RmFpbHVyZTogYm9vbGVhbiB8IHtleGl0X2NvZGVzOiBudW1iZXIgfCBudW1iZXJbXX0gPSBmYWxzZSk6IHt3aGVuOiBzdHJpbmc7IGFsbG93RmFpbHVyZTogYm9vbGVhbiB8IHtleGl0X2NvZGVzOiBudW1iZXIgfCBudW1iZXJbXX07IHZhcmlhYmxlcz86IHtbbmFtZTogc3RyaW5nXTogc3RyaW5nfTsgbmVlZHM/OiBOZWVkW119IHtcbiAgICAgICAgbGV0IHdoZW4gPSBcIm5ldmVyXCI7XG4gICAgICAgIGNvbnN0IHtldmFsdWF0ZVJ1bGVDaGFuZ2VzfSA9IG9wdC5hcmd2O1xuXG4gICAgICAgIC8vIG9wdGlvbmFsIG1hbnVhbCBqb2JzIGFsbG93RmFpbHVyZSBkZWZhdWx0cyB0byB0cnVlIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL2NpL2pvYnMvam9iX2NvbnRyb2wuaHRtbCN0eXBlcy1vZi1tYW51YWwtam9ic1xuICAgICAgICBsZXQgYWxsb3dGYWlsdXJlID0gam9iV2hlbiA9PT0gXCJtYW51YWxcIiA/IHRydWUgOiBqb2JBbGxvd0ZhaWx1cmU7XG4gICAgICAgIGxldCBydWxlVmFyaWFibGU6IHtbbmFtZTogc3RyaW5nXTogc3RyaW5nfSB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHJ1bGVOZWVkczogTmVlZFtdIHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIGZvciAoY29uc3QgcnVsZSBvZiBvcHQucnVsZXMpIHtcbiAgICAgICAgICAgIGlmICghVXRpbHMuZXZhbHVhdGVSdWxlSWYocnVsZS5pZiwgb3B0LnZhcmlhYmxlcykpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKCFVdGlscy5ldmFsdWF0ZVJ1bGVFeGlzdChvcHQuY3dkLCBydWxlLmV4aXN0cykpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKGV2YWx1YXRlUnVsZUNoYW5nZXMgJiYgIVV0aWxzLmV2YWx1YXRlUnVsZUNoYW5nZXMoZ2l0RGF0YS5icmFuY2hlcy5kZWZhdWx0LCBydWxlLmNoYW5nZXMsIG9wdC5jd2QpKSBjb250aW51ZTtcblxuICAgICAgICAgICAgd2hlbiA9IHJ1bGUud2hlbiA/IHJ1bGUud2hlbiA6IGpvYldoZW47XG4gICAgICAgICAgICBhbGxvd0ZhaWx1cmUgPSBydWxlLmFsbG93X2ZhaWx1cmUgPz8gYWxsb3dGYWlsdXJlO1xuICAgICAgICAgICAgcnVsZVZhcmlhYmxlID0gcnVsZS52YXJpYWJsZXM7XG4gICAgICAgICAgICBydWxlTmVlZHMgPSBydWxlLm5lZWRzPy5tYXAoKG46IGFueSkgPT4gbmVlZHNDb21wbGV4KG4pKTtcblxuICAgICAgICAgICAgYnJlYWs7IC8vIEVhcmx5IHJldHVybiwgd2lsbCBub3QgZXZhbHVhdGUgdGhlIHJlbWFpbmluZyBydWxlc1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHt3aGVuLCBhbGxvd0ZhaWx1cmUsIHZhcmlhYmxlczogcnVsZVZhcmlhYmxlLCBuZWVkczogcnVsZU5lZWRzfTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZXZhbHVhdGVSdWxlSWYgKHJ1bGVJZjogc3RyaW5nIHwgdW5kZWZpbmVkLCBlbnZzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAocnVsZUlmID09PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuICAgICAgICBsZXQgZXZhbFN0ciA9IHJ1bGVJZjtcblxuICAgICAgICBjb25zdCBmbGFnc1RvQmluYXJ5ID0gKGZsYWdzOiBzdHJpbmcpOiBudW1iZXIgPT4ge1xuICAgICAgICAgICAgbGV0IGJpbmFyeSA9IDA7XG4gICAgICAgICAgICBpZiAoZmxhZ3MuaW5jbHVkZXMoXCJpXCIpKSB7XG4gICAgICAgICAgICAgICAgYmluYXJ5IHw9IFJFMkpTLkNBU0VfSU5TRU5TSVRJVkU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmxhZ3MuaW5jbHVkZXMoXCJzXCIpKSB7XG4gICAgICAgICAgICAgICAgYmluYXJ5IHw9IFJFMkpTLkRPVEFMTDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmbGFncy5pbmNsdWRlcyhcIm1cIikpIHtcbiAgICAgICAgICAgICAgICBiaW5hcnkgfD0gUkUySlMuTVVMVElMSU5FO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJpbmFyeTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBFeHBhbmQgYWxsIHZhcmlhYmxlc1xuICAgICAgICBldmFsU3RyID0gdGhpcy5leHBhbmRUZXh0V2l0aChldmFsU3RyLCB7XG4gICAgICAgICAgICB1bmVzY2FwZTogSlNPTi5zdHJpbmdpZnkoXCIkXCIpLFxuICAgICAgICAgICAgdmFyaWFibGU6IChuYW1lKSA9PiBKU09OLnN0cmluZ2lmeShlbnZzW25hbWVdID8/IG51bGwpLnJlcGxhY2VBbGwoXCJcXFxcXFxcXFwiLCBcIlxcXFxcIiksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBleHBhbmRlZEV2YWxTdHIgPSBldmFsU3RyO1xuXG4gICAgICAgIC8vIFNjZW5hcmlvIHdoZW4gUkhTIGlzIGEgPHJlZ2V4PlxuICAgICAgICAvLyBodHRwczovL3JlZ2V4ci5jb20vODVzam9cbiAgICAgICAgY29uc3QgcGF0dGVybjEgPSAvXFxzKig/PG9wZXJhdG9yPig/Oj1+KXwoPzohfikpXFxzKlxcLyg/PHJocz4uKj9bXlxcXFxdKVxcLyg/PGZsYWdzPltpZ21zdXldKikoXFxzfCR8XFwpKS9nO1xuICAgICAgICBldmFsU3RyID0gZXZhbFN0ci5yZXBsYWNlKHBhdHRlcm4xLCAoXywgb3BlcmF0b3IsIHJocywgZmxhZ3MsIHJlbWFpbmluZ1Rva2VucykgPT4ge1xuICAgICAgICAgICAgbGV0IF9vcGVyYXRvcjtcbiAgICAgICAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHtcbiAgICAgICAgICAgICAgICBjYXNlIFwiPX5cIjpcbiAgICAgICAgICAgICAgICAgICAgX29wZXJhdG9yID0gXCIhPVwiO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFwiIX5cIjpcbiAgICAgICAgICAgICAgICAgICAgX29wZXJhdG9yID0gXCI9PVwiO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBvcGVyYXRvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IF9yaHMgPSBKU09OLnN0cmluZ2lmeShyaHMpOyAvLyBKU09OLnN0cmluZ2lmeSBmb3IgZXNjYXBpbmcgYFwiYFxuICAgICAgICAgICAgY29uc3QgY29udGFpbnNOb25Fc2NhcGVkU2xhc2ggPSAvKD88IVxcXFwpXFwvLy50ZXN0KF9yaHMpO1xuICAgICAgICAgICAgY29uc3QgYXNzZXJ0TXNnID0gW1xuICAgICAgICAgICAgICAgIFwiRXJyb3IgYXR0ZW1wdGluZyB0byBldmFsdWF0ZSB0aGUgZm9sbG93aW5nIHJ1bGVzOlwiLFxuICAgICAgICAgICAgICAgIFwiICBydWxlczpcIixcbiAgICAgICAgICAgICAgICBgICAgIC0gaWY6ICcke2V4cGFuZGVkRXZhbFN0cn0nYCxcbiAgICAgICAgICAgICAgICBcImFzIHJocyBjb250YWlucyB1bmVzY2FwZWQgcXVvdGVcIixcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBhc3NlcnQoIWNvbnRhaW5zTm9uRXNjYXBlZFNsYXNoLCBhc3NlcnRNc2cuam9pbihcIlxcblwiKSk7XG4gICAgICAgICAgICBjb25zdCBmbGFnc0JpbmFyeSA9IGZsYWdzVG9CaW5hcnkoZmxhZ3MpO1xuICAgICAgICAgICAgcmV0dXJuIGAubWF0Y2hSRTJKUyhSRTJKUy5jb21waWxlKCR7X3Joc30sICR7ZmxhZ3NCaW5hcnl9KSkgJHtfb3BlcmF0b3J9IG51bGwke3JlbWFpbmluZ1Rva2Vuc31gO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTY2VuYXJpbyB3aGVuIFJIUyBpcyBzdXJyb3VuZGVkIGJ5IHNpbmdsZS9kb3VibGUtcXVvdGVzXG4gICAgICAgIC8vIGh0dHBzOi8vcmVnZXhyLmNvbS84NXQwZ1xuICAgICAgICBjb25zdCBwYXR0ZXJuMiA9IC9cXHMqKD88b3BlcmF0b3I+PX58IX4pXFxzKihbXCInXSkoPzxyaHM+KD86XFxcXC58W15cXFxcXSkqPylcXDIvZztcbiAgICAgICAgZXZhbFN0ciA9IGV2YWxTdHIucmVwbGFjZShwYXR0ZXJuMiwgKF8sIG9wZXJhdG9yLCBfXywgcmhzKSA9PiB7XG4gICAgICAgICAgICBsZXQgX29wZXJhdG9yO1xuICAgICAgICAgICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgICAgICAgICAgIGNhc2UgXCI9flwiOlxuICAgICAgICAgICAgICAgICAgICBfb3BlcmF0b3IgPSBcIiE9XCI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCIhflwiOlxuICAgICAgICAgICAgICAgICAgICBfb3BlcmF0b3IgPSBcIj09XCI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG9wZXJhdG9yO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBhc3NlcnRNc2cgPSBbXG4gICAgICAgICAgICAgICAgXCJSSFMgKCR7cmhzfSkgbXVzdCBiZSBhIHJlZ2V4IHBhdHRlcm4uIERvIG5vdCByZWx5IG9uIHRoaXMgYmVoYXZpb3IhXCIsXG4gICAgICAgICAgICAgICAgXCJSZWZlciB0byBodHRwczovL2RvY3MuZ2l0bGFiLmNvbS9lZS9jaS9qb2JzL2pvYl9ydWxlcy5odG1sI3VuZXhwZWN0ZWQtYmVoYXZpb3ItZnJvbS1yZWd1bGFyLWV4cHJlc3Npb24tbWF0Y2hpbmctd2l0aC0gZm9yIG1vcmUgaW5mby4uLlwiLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGFzc2VydCgoL1xcLyguKilcXC8oXFx3KikvLnRlc3QocmhzKSksIGFzc2VydE1zZy5qb2luKFwiXFxuXCIpKTtcblxuICAgICAgICAgICAgY29uc3QgcmVnZXggPSAvXFwvKD88cGF0dGVybj4uKilcXC8oPzxmbGFncz5baWdtc3V5XSopLztcbiAgICAgICAgICAgIGNvbnN0IF9yaHMgPSByaHMucmVwbGFjZShyZWdleCwgKF86IHN0cmluZywgcGF0dGVybjogc3RyaW5nLCBmbGFnczogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmxhZ3NCaW5hcnkgPSBmbGFnc1RvQmluYXJ5KGZsYWdzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYFJFMkpTLmNvbXBpbGUoXCIke3BhdHRlcm59XCIsICR7ZmxhZ3NCaW5hcnl9KWA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBgLm1hdGNoUkUySlMoJHtfcmhzfSkgJHtfb3BlcmF0b3J9IG51bGxgO1xuICAgICAgICB9KTtcblxuICAgICAgICBldmFsU3RyID0gZXZhbFN0ci5yZXBsYWNlKC9udWxsLm1hdGNoUkUySlNcXCguKz9cXClcXHMqIT1cXHMqbnVsbC9nLCBcImZhbHNlXCIpO1xuICAgICAgICBldmFsU3RyID0gZXZhbFN0ci5yZXBsYWNlKC9udWxsLm1hdGNoUkUySlNcXCguKz9cXClcXHMqPT1cXHMqbnVsbC9nLCBcInRydWVcIik7XG5cbiAgICAgICAgZXZhbFN0ciA9IGV2YWxTdHIudHJpbSgpO1xuXG4gICAgICAgIGxldCByZXM7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAoZ2xvYmFsIGFzIGFueSkuUkUySlMgPSBSRTJKUzsgLy8gQXNzaWduIFJFMkpTIHRvIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgICAgICAgICByZXMgPSAoMCwgZXZhbCkoZXZhbFN0cik7IC8vIGh0dHBzOi8vZXNidWlsZC5naXRodWIuaW8vY29udGVudC10eXBlcy8jZGlyZWN0LWV2YWxcbiAgICAgICAgICAgIGRlbGV0ZSAoZ2xvYmFsIGFzIGFueSkuUkUySlM7IC8vIENsZWFudXBcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICBjb25zdCBhc3NlcnRNc2cgPSBbXG4gICAgICAgICAgICAgICAgXCJFcnJvciBhdHRlbXB0aW5nIHRvIGV2YWx1YXRlIHRoZSBmb2xsb3dpbmcgcnVsZXM6XCIsXG4gICAgICAgICAgICAgICAgXCIgIHJ1bGVzOlwiLFxuICAgICAgICAgICAgICAgIGAgICAgLSBpZjogJyR7ZXhwYW5kZWRFdmFsU3RyfSdgLFxuICAgICAgICAgICAgICAgIFwiYXNcIixcbiAgICAgICAgICAgICAgICBcImBgYGphdmFzY3JpcHRcIixcbiAgICAgICAgICAgICAgICBgJHtldmFsU3RyfWAsXG4gICAgICAgICAgICAgICAgXCJgYGBcIixcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBhc3NlcnQoZmFsc2UsIGFzc2VydE1zZy5qb2luKFwiXFxuXCIpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQm9vbGVhbihyZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBldmFsdWF0ZVJ1bGVFeGlzdCAoY3dkOiBzdHJpbmcsIHJ1bGVFeGlzdHM6IHN0cmluZ1tdIHwge3BhdGhzOiBzdHJpbmdbXX0gfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKHJ1bGVFeGlzdHMgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgLy8gTm9ybWFsaXplIHJ1bGVzOmV4aXN0czpwYXRocyB0byBydWxlczpleGlzdHNcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHJ1bGVFeGlzdHMpKSBydWxlRXhpc3RzID0gcnVsZUV4aXN0cy5wYXRocztcblxuICAgICAgICBmb3IgKGNvbnN0IHBhdHRlcm4gb2YgcnVsZUV4aXN0cykge1xuICAgICAgICAgICAgaWYgKHBhdHRlcm4gPT0gXCJcIikge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdsb2JieVN5bmMocGF0dGVybiwge2RvdDogdHJ1ZSwgY3dkfSkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZXZhbHVhdGVSdWxlQ2hhbmdlcyAoZGVmYXVsdEJyYW5jaDogc3RyaW5nLCBydWxlQ2hhbmdlczogc3RyaW5nW10gfCB7cGF0aHM6IHN0cmluZ1tdfSB8IHVuZGVmaW5lZCwgY3dkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKHJ1bGVDaGFuZ2VzID09PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuXG4gICAgICAgIC8vIE5vcm1hbGl6ZSBydWxlczpjaGFuZ2VzOnBhdGhzIHRvIHJ1bGVzOmNoYW5nZXNcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHJ1bGVDaGFuZ2VzKSkgcnVsZUNoYW5nZXMgPSBydWxlQ2hhbmdlcy5wYXRocztcblxuICAgICAgICAvLyBOT1RFOiBodHRwczovL2RvY3MuZ2l0bGFiLmNvbS9lZS9jaS95YW1sLyNydWxlc2NoYW5nZXNcbiAgICAgICAgLy8gICBHbG9iIHBhdHRlcm5zIGFyZSBpbnRlcnByZXRlZCB3aXRoIFJ1YnkncyBbRmlsZS5mbm1hdGNoXShodHRwczovL2RvY3MucnVieS1sYW5nLm9yZy9lbi9tYXN0ZXIvRmlsZS5odG1sI21ldGhvZC1jLWZubWF0Y2gpXG4gICAgICAgIC8vICAgd2l0aCB0aGUgZmxhZ3MgRmlsZTo6Rk5NX1BBVEhOQU1FIHwgRmlsZTo6Rk5NX0RPVE1BVENIIHwgRmlsZTo6Rk5NX0VYVEdMT0IuXG4gICAgICAgIHJldHVybiBtaWNyb21hdGNoLnNvbWUoR2l0RGF0YS5jaGFuZ2VkRmlsZXMoYG9yaWdpbi8ke2RlZmF1bHRCcmFuY2h9YCwgY3dkKSwgcnVsZUNoYW5nZXMsIHtcbiAgICAgICAgICAgIG5vbmVnYXRlOiB0cnVlLFxuICAgICAgICAgICAgbm9leHRnbG9iOiB0cnVlLFxuICAgICAgICAgICAgcG9zaXg6IGZhbHNlLFxuICAgICAgICAgICAgZG90OiB0cnVlLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNTdWJwYXRoIChsaHM6IHN0cmluZywgcmhzOiBzdHJpbmcsIGN3ZDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKSkge1xuICAgICAgICBsZXQgYWJzTGhzID0gXCJcIjtcbiAgICAgICAgaWYgKHBhdGguaXNBYnNvbHV0ZShsaHMpKSB7XG4gICAgICAgICAgICBhYnNMaHMgPSBsaHM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhYnNMaHMgPSBwYXRoLnJlc29sdmUoY3dkLCBsaHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGFic1JocyA9IFwiXCI7XG4gICAgICAgIGlmIChwYXRoLmlzQWJzb2x1dGUocmhzKSkge1xuICAgICAgICAgICAgYWJzUmhzID0gcmhzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWJzUmhzID0gcGF0aC5yZXNvbHZlKGN3ZCwgcmhzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlbGF0aXZlID0gcGF0aC5yZWxhdGl2ZShhYnNSaHMsIGFic0xocyk7XG4gICAgICAgIHJldHVybiAhcmVsYXRpdmUuc3RhcnRzV2l0aChcIi4uXCIpO1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyByc3luY1RyYWNrZWRGaWxlcyAoY3dkOiBzdHJpbmcsIHN0YXRlRGlyOiBzdHJpbmcsIHRhcmdldDogc3RyaW5nKTogUHJvbWlzZTx7aHJkZWx0YXRpbWU6IFtudW1iZXIsIG51bWJlcl19PiB7XG4gICAgICAgIGNvbnN0IHRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgICAgICBhd2FpdCBmcy5ta2RpcnAoYCR7Y3dkfS8ke3N0YXRlRGlyfS9idWlsZHMvJHt0YXJnZXR9YCk7XG4gICAgICAgIGF3YWl0IFV0aWxzLmJhc2goYHJzeW5jIC1hIC0tZGVsZXRlLWV4Y2x1ZGVkIC0tZGVsZXRlIC0tZXhjbHVkZS1mcm9tPTwoZ2l0IGxzLWZpbGVzIC1vIC0tZGlyZWN0b3J5IHwgYXdrICd7cHJpbnQgXCIvXCIkMH0nKSAtLWV4Y2x1ZGUgJHtzdGF0ZURpcn0vIC4vICR7c3RhdGVEaXJ9L2J1aWxkcy8ke3RhcmdldH0vYCwgY3dkKTtcbiAgICAgICAgcmV0dXJuIHtocmRlbHRhdGltZTogcHJvY2Vzcy5ocnRpbWUodGltZSl9O1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBjaGVja3N1bUZpbGVzIChjd2Q6IHN0cmluZywgZmlsZXM6IHN0cmluZ1tdKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgY29uc3QgcHJvbWlzZXM6IFByb21pc2U8c3RyaW5nPltdID0gW107XG5cbiAgICAgICAgZmlsZXMuZm9yRWFjaCgoZmlsZSkgPT4ge1xuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEgZnMucGF0aEV4aXN0c1N5bmMoZmlsZSkpIHJlc29sdmUocGF0aC5yZWxhdGl2ZShjd2QsIGZpbGUpKTsgLy8gbXVzdCB1c2UgcmVsYXRpdmUgcGF0aCBoZXJlLCBzbyB0aGF0IGNoZWNrc3VtIGNhbiBiZSBkZXRlcm1pbmlzdGljIHdoZW4gcnVubmluZyB0aGUgdW5pdCB0ZXN0c1xuICAgICAgICAgICAgICAgIGNoZWNrc3VtLmZpbGUoZmlsZSwgKGVyciwgaGFzaCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShoYXNoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgICAgICByZXR1cm4gY2hlY2tzdW0ocmVzdWx0LmpvaW4oXCJcIikpO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc09iamVjdCAodjogYW55KSB7XG4gICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodikgPT09IE9iamVjdC5wcm90b3R5cGU7XG4gICAgfVxuXG4gICAgc3RhdGljIHN3aXRjaFN0YXRlbWVudEV4aGF1c3RpdmVDaGVjayAocGFyYW06IG5ldmVyKTogbmV2ZXIge1xuICAgICAgICAvLyBodHRwczovL2Rldi50by9iYWJhay9leGhhdXN0aXZlLXR5cGUtY2hlY2tpbmctd2l0aC10eXBlc2NyaXB0LTRsM2ZcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmhhbmRsZWQgY2FzZSAke3BhcmFtfWApO1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBkb2NrZXJWb2x1bWVGaWxlRXhpc3RzIChjb250YWluZXJFeGVjdXRhYmxlOiBzdHJpbmcsIHBhdGg6IHN0cmluZywgdm9sdW1lOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFtjb250YWluZXJFeGVjdXRhYmxlLCBcInJ1blwiLCBcIi0tcm1cIiwgXCItdlwiLCBgJHt2b2x1bWV9Oi9tbnQvdm9sYCwgXCJhbHBpbmVcIiwgXCJsc1wiLCBgL21udC92b2wvJHtwYXRofWBdKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBnY2xSZWdpc3RyeVByZWZpeDogc3RyaW5nID0gXCJyZWdpc3RyeS5nY2wubG9jYWxcIjtcbiAgICBzdGF0aWMgYXN5bmMgc3RhcnREb2NrZXJSZWdpc3RyeSAoYXJndjogQXJndik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBnY2xSZWdpc3RyeUNlcnRWb2wgPSBgJHt0aGlzLmdjbFJlZ2lzdHJ5UHJlZml4fS5jZXJ0c2A7XG4gICAgICAgIGNvbnN0IGdjbFJlZ2lzdHJ5RGF0YVZvbCA9IGAke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9LmRhdGFgO1xuICAgICAgICBjb25zdCBnY2xSZWdpc3RyeU5ldCA9IGAke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9Lm5ldGA7XG5cbiAgICAgICAgLy8gY3JlYXRlIGNlcnQgdm9sdW1lXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihgJHthcmd2LmNvbnRhaW5lckV4ZWN1dGFibGV9IHZvbHVtZSBjcmVhdGUgJHtnY2xSZWdpc3RyeUNlcnRWb2x9YC5zcGxpdChcIiBcIikpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiAhZXJyLm1lc3NhZ2UuZW5kc1dpdGgoXCJhbHJlYWR5IGV4aXN0c1wiKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgc2VsZi1zaWduZWQgY2VydC9rZXkgZmlsZXMgZm9yIGh0dHBzIHN1cHBvcnRcbiAgICAgICAgaWYgKCFhd2FpdCB0aGlzLmRvY2tlclZvbHVtZUZpbGVFeGlzdHMoYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBgJHt0aGlzLmdjbFJlZ2lzdHJ5UHJlZml4fS5jcnRgLCBnY2xSZWdpc3RyeUNlcnRWb2wpKSB7XG4gICAgICAgICAgICBjb25zdCBvcGVuc3NsQXJncyA9IFtcbiAgICAgICAgICAgICAgICBcInJlcVwiLCBcIi1uZXdrZXlcIiwgXCJyc2E6NDA5NlwiLCBcIi1ub2Rlc1wiLCBcIi1zaGEyNTZcIixcbiAgICAgICAgICAgICAgICBcIi1rZXlvdXRcIiwgYC9jZXJ0cy8ke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9LmtleWAsXG4gICAgICAgICAgICAgICAgXCIteDUwOVwiLCBcIi1kYXlzXCIsIFwiMzY1XCIsXG4gICAgICAgICAgICAgICAgXCItb3V0XCIsIGAvY2VydHMvJHt0aGlzLmdjbFJlZ2lzdHJ5UHJlZml4fS5jcnRgLFxuICAgICAgICAgICAgICAgIFwiLXN1YmpcIiwgYC9DTj0ke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9YCxcbiAgICAgICAgICAgICAgICBcIi1hZGRleHRcIiwgYHN1YmplY3RBbHROYW1lPUROUzoke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9YCxcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zdCBnZW5lcmF0ZUNlcnRzSW5QbGFjZSA9IFtcbiAgICAgICAgICAgICAgICBhcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwicnVuXCIsIFwiLS1ybVwiLCBcIi12XCIsIGAke2djbFJlZ2lzdHJ5Q2VydFZvbH06L2NlcnRzYCwgXCItLWVudHJ5cG9pbnRcIiwgXCJzaFwiLCBcImFscGluZS9vcGVuc3NsXCIsIFwiLWNcIixcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIFwib3BlbnNzbFwiLCAuLi5vcGVuc3NsQXJncyxcbiAgICAgICAgICAgICAgICAgICAgXCImJlwiLCBcIm1rZGlyXCIsIFwiLXBcIiwgYC9jZXJ0cy8ke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9YCxcbiAgICAgICAgICAgICAgICAgICAgXCImJlwiLCBcImNwXCIsIGAvY2VydHMvJHt0aGlzLmdjbFJlZ2lzdHJ5UHJlZml4fS5jcnRgLCBgL2NlcnRzLyR7dGhpcy5nY2xSZWdpc3RyeVByZWZpeH0vY2EuY3J0YCxcbiAgICAgICAgICAgICAgICBdLmpvaW4oXCIgXCIpLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKGdlbmVyYXRlQ2VydHNJblBsYWNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNyZWF0ZSBkYXRhIHZvbHVtZVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW2FyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJ2b2x1bWVcIiwgXCJjcmVhdGVcIiwgZ2NsUmVnaXN0cnlEYXRhVm9sXSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmICFlcnIubWVzc2FnZS5lbmRzV2l0aChcImFscmVhZHkgZXhpc3RzXCIpKVxuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNyZWF0ZSBuZXR3b3JrXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcIm5ldHdvcmtcIiwgXCJjcmVhdGVcIiwgZ2NsUmVnaXN0cnlOZXRdKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgRXJyb3IgJiYgIWVyci5tZXNzYWdlLmluY2x1ZGVzKFwiYWxyZWFkeSBleGlzdHNcIikpXG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW2FyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJybVwiLCBcIi1mXCIsIHRoaXMuZ2NsUmVnaXN0cnlQcmVmaXhdKTtcbiAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW1xuICAgICAgICAgICAgYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInJ1blwiLCBcIi1kXCIsIFwiLS1uYW1lXCIsIHRoaXMuZ2NsUmVnaXN0cnlQcmVmaXgsXG4gICAgICAgICAgICBcIi0tbmV0d29ya1wiLCBnY2xSZWdpc3RyeU5ldCxcbiAgICAgICAgICAgIFwiLS12b2x1bWVcIiwgYCR7Z2NsUmVnaXN0cnlEYXRhVm9sfTovdmFyL2xpYi9yZWdpc3RyeWAsXG4gICAgICAgICAgICBcIi0tdm9sdW1lXCIsIGAke2djbFJlZ2lzdHJ5Q2VydFZvbH06L2NlcnRzOnJvYCxcbiAgICAgICAgICAgIFwiLWVcIiwgXCJSRUdJU1RSWV9IVFRQX0FERFI9MC4wLjAuMDo0NDNcIixcbiAgICAgICAgICAgIFwiLWVcIiwgYFJFR0lTVFJZX0hUVFBfVExTX0NFUlRJRklDQVRFPS9jZXJ0cy8ke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9LmNydGAsXG4gICAgICAgICAgICBcIi1lXCIsIGBSRUdJU1RSWV9IVFRQX1RMU19LRVk9L2NlcnRzLyR7dGhpcy5nY2xSZWdpc3RyeVByZWZpeH0ua2V5YCxcbiAgICAgICAgICAgIFwicmVnaXN0cnlcIixcbiAgICAgICAgXSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IGV4ZWNhKGFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgW1xuICAgICAgICAgICAgICAgIFwicnVuXCIsIFwiLS1ybVwiLFxuICAgICAgICAgICAgICAgIFwiLS1uZXR3b3JrXCIsIGdjbFJlZ2lzdHJ5TmV0LFxuICAgICAgICAgICAgICAgIFwiLS1lbnRyeXBvaW50XCIsIFwic2hcIixcbiAgICAgICAgICAgICAgICBcImN1cmxpbWFnZXMvY3VybFwiLFxuICAgICAgICAgICAgICAgIFwiLWNcIiwgYHVudGlsIFsgXCIkKGN1cmwgLXMgLW8gL2Rldi9udWxsIC1rIC13IFwiJXtodHRwX2NvZGV9XCIgaHR0cHM6Ly8ke3RoaXMuZ2NsUmVnaXN0cnlQcmVmaXh9OjQ0MylcIiA9IFwiMjAwXCIgXTsgZG8gc2xlZXAgMTsgZG9uZTtgLFxuICAgICAgICAgICAgXSwge1xuICAgICAgICAgICAgICAgIHRpbWVvdXQ6IDQwMDAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnN0b3BEb2NrZXJSZWdpc3RyeShhcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUpO1xuICAgICAgICAgICAgaWYgKChlcnIgYXMgRXhlY2FFcnJvcikudGltZWRPdXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcImxvY2FsIGRvY2tlciByZWdpc3RyeSBwb3J0IGNoZWNrIHRpbWVkIG91dFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGFzeW5jIHN0b3BEb2NrZXJSZWdpc3RyeSAoY29udGFpbmVyRXhlY3V0YWJsZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFtjb250YWluZXJFeGVjdXRhYmxlLCBcInJtXCIsIFwiLWZcIiwgdGhpcy5nY2xSZWdpc3RyeVByZWZpeF0pO1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBnZXRUcmFja2VkRmlsZXMgKGN3ZDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgICBjb25zdCBsc0ZpbGVzUmVzID0gYXdhaXQgVXRpbHMuYmFzaChcImdpdCBscy1maWxlcyAtLWRlZHVwbGljYXRlXCIsIGN3ZCk7XG4gICAgICAgIGlmIChsc0ZpbGVzUmVzLmV4aXRDb2RlICE9IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxpc3QgdHJhY2tlZCBmaWxlcyBpbiAke2N3ZH06ICR7bHNGaWxlc1Jlcy5zdGRlcnJ9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxzRmlsZXNSZXMuc3Rkb3V0LnNwbGl0KFwiXFxuXCIpO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRBeGlvc1Byb3h5Q29uZmlnICgpOiBBeGlvc1JlcXVlc3RDb25maWcge1xuICAgICAgICBjb25zdCBwcm94eUVudiA9IHByb2Nlc3MuZW52LkhUVFBTX1BST1hZIHx8IHByb2Nlc3MuZW52LkhUVFBfUFJPWFk7XG4gICAgICAgIGlmIChwcm94eUVudikge1xuICAgICAgICAgICAgY29uc3QgcHJveHlVcmwgPSBuZXcgVVJMKHByb3h5RW52KTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgcHJveHk6IHtcbiAgICAgICAgICAgICAgICAgICAgaG9zdDogcHJveHlVcmwuaG9zdG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHBvcnQ6IHByb3h5VXJsLnBvcnQgPyBwYXJzZUludChwcm94eVVybC5wb3J0LCAxMCkgOiA4MDgwLFxuICAgICAgICAgICAgICAgICAgICBwcm90b2NvbDogcHJveHlVcmwucHJvdG9jb2wucmVwbGFjZShcIjpcIiwgXCJcIiksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIHN0YXRpYyBub3JtYWxpemVWYXJpYWJsZXMgKHZhcmlhYmxlOiBhbnkpIHtcbiAgICAgICAgaWYgKHZhcmlhYmxlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJcIjsgLy8gdmFyaWFibGUncyB2YWx1ZXMgYXJlIG51bGxhYmxlXG4gICAgICAgIH0gZWxzZSBpZiAoVXRpbHMuaXNPYmplY3QodmFyaWFibGUpKSB7XG4gICAgICAgICAgICBpZiAodmFyaWFibGVbXCJleHBhbmRcIl0gPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyh2YXJpYWJsZVtcInZhbHVlXCJdKS5yZXBsYWNlQWxsKFwiJFwiLCAoKSA9PiBcIiQkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFN0cmluZyh2YXJpYWJsZVtcInZhbHVlXCJdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmcodmFyaWFibGUpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19
|