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/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