gitlab-ci-local 4.65.0 → 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/job.js
DELETED
|
@@ -1,1463 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk-template";
|
|
2
|
-
import * as dotenv from "dotenv";
|
|
3
|
-
import fs from "fs-extra";
|
|
4
|
-
import prettyHrtime from "pretty-hrtime";
|
|
5
|
-
import split2 from "split2";
|
|
6
|
-
import { Utils } from "./utils.js";
|
|
7
|
-
import assert, { AssertionError } from "assert";
|
|
8
|
-
import { Mutex } from "./mutex.js";
|
|
9
|
-
import execa from "execa";
|
|
10
|
-
import { GitlabRunnerCPUsPresetValue, GitlabRunnerMemoryPresetValue, GitlabRunnerPresetValues } from "./gitlab-preset.js";
|
|
11
|
-
import { handler } from "./handler.js";
|
|
12
|
-
import * as yaml from "js-yaml";
|
|
13
|
-
import { Parser } from "./parser.js";
|
|
14
|
-
import { resolveIncludeLocal, validateIncludeLocal } from "./parser-includes.js";
|
|
15
|
-
import { globbySync } from "globby";
|
|
16
|
-
import terminalLink from "terminal-link";
|
|
17
|
-
import * as crypto from "crypto";
|
|
18
|
-
import * as path from "path";
|
|
19
|
-
const GCL_SHELL_PROMPT_PLACEHOLDER = "<gclShellPromptPlaceholder>";
|
|
20
|
-
const isGlob = (str) => /[*?{}(|)[\]]/.test(str);
|
|
21
|
-
const dateFormatter = new Intl.DateTimeFormat(undefined, {
|
|
22
|
-
year: undefined,
|
|
23
|
-
month: undefined,
|
|
24
|
-
hour: "numeric",
|
|
25
|
-
minute: "numeric",
|
|
26
|
-
second: "numeric",
|
|
27
|
-
hour12: false,
|
|
28
|
-
});
|
|
29
|
-
export class Job {
|
|
30
|
-
generateJobId() {
|
|
31
|
-
return Math.floor(Math.random() * 1000000);
|
|
32
|
-
}
|
|
33
|
-
static illegalJobNames = new Set([
|
|
34
|
-
"include", "local_configuration", "image", "services",
|
|
35
|
-
"stages", "before_script", "default",
|
|
36
|
-
"after_script", "variables", "cache", "workflow", "page:deploy",
|
|
37
|
-
]);
|
|
38
|
-
argv;
|
|
39
|
-
name;
|
|
40
|
-
baseName;
|
|
41
|
-
dependencies;
|
|
42
|
-
environment;
|
|
43
|
-
jobId;
|
|
44
|
-
rules;
|
|
45
|
-
allowFailure;
|
|
46
|
-
when;
|
|
47
|
-
exists;
|
|
48
|
-
pipelineIid;
|
|
49
|
-
gitData;
|
|
50
|
-
inherit;
|
|
51
|
-
_dotenvVariables = {};
|
|
52
|
-
_prescriptsExitCode = null;
|
|
53
|
-
_afterScriptsExitCode = 0;
|
|
54
|
-
_coveragePercent = null;
|
|
55
|
-
_running = false;
|
|
56
|
-
_containerId = null;
|
|
57
|
-
_serviceNetworkId = null;
|
|
58
|
-
_longRunningSilentTimeout = -1;
|
|
59
|
-
_producers = null;
|
|
60
|
-
_jobNamePad = null;
|
|
61
|
-
_ciProjectDir = null;
|
|
62
|
-
_startTime;
|
|
63
|
-
_endTime;
|
|
64
|
-
_filesToRm = [];
|
|
65
|
-
_globalVariables = {};
|
|
66
|
-
_variables = {};
|
|
67
|
-
_containersToClean = [];
|
|
68
|
-
_containerVolumeNames = [];
|
|
69
|
-
jobData;
|
|
70
|
-
writeStreams;
|
|
71
|
-
constructor(opt) {
|
|
72
|
-
const jobData = opt.data;
|
|
73
|
-
const jobVariables = jobData.variables ?? {};
|
|
74
|
-
const variablesFromFiles = opt.variablesFromFiles;
|
|
75
|
-
const argv = opt.argv;
|
|
76
|
-
const cwd = argv.cwd;
|
|
77
|
-
const argvVariables = argv.variable;
|
|
78
|
-
const expandVariables = opt.expandVariables ?? true;
|
|
79
|
-
this.argv = argv;
|
|
80
|
-
this.writeStreams = opt.writeStreams;
|
|
81
|
-
this.gitData = opt.gitData;
|
|
82
|
-
this.name = opt.name;
|
|
83
|
-
this.baseName = opt.baseName;
|
|
84
|
-
this.jobId = this.generateJobId();
|
|
85
|
-
this.jobData = opt.data;
|
|
86
|
-
this.pipelineIid = opt.pipelineIid;
|
|
87
|
-
this._globalVariables = opt.globalVariables;
|
|
88
|
-
this.inherit = {};
|
|
89
|
-
this.inherit.variables = this.jobData.inherit?.variables ?? true;
|
|
90
|
-
this.when = jobData.when || "on_success";
|
|
91
|
-
this.exists = jobData.exists || [];
|
|
92
|
-
this.allowFailure = jobData.allow_failure ?? false;
|
|
93
|
-
this.dependencies = jobData.dependencies || null;
|
|
94
|
-
this.rules = jobData.rules || null;
|
|
95
|
-
this.environment = typeof jobData.environment === "string" ? { name: jobData.environment } : (jobData.environment ? { ...jobData.environment } : jobData.environment);
|
|
96
|
-
const matrixVariables = opt.matrixVariables ?? {};
|
|
97
|
-
const fileVariables = Utils.findEnvMatchedVariables(variablesFromFiles, this.fileVariablesDir);
|
|
98
|
-
const predefinedVariables = this._predefinedVariables(opt);
|
|
99
|
-
this._variables = { ...predefinedVariables, ...this.globalVariables, ...jobVariables, ...matrixVariables, ...fileVariables, ...argvVariables };
|
|
100
|
-
if (this.rules && expandVariables) {
|
|
101
|
-
const expanded = Utils.expandVariables(this._variables);
|
|
102
|
-
// Expand variables in rules:changes
|
|
103
|
-
this.rules.forEach((rule, ruleIdx, rules) => {
|
|
104
|
-
const changes = Array.isArray(rule.changes) ? rule.changes : rule.changes?.paths;
|
|
105
|
-
if (!changes) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
changes.forEach((change, changeIdx, changes) => {
|
|
109
|
-
changes[changeIdx] = Utils.expandText(change, expanded);
|
|
110
|
-
});
|
|
111
|
-
rules[ruleIdx].changes = changes;
|
|
112
|
-
});
|
|
113
|
-
// Expand variables in rules:exists
|
|
114
|
-
this.rules.forEach((rule, ruleIdx, rules) => {
|
|
115
|
-
const exists = Array.isArray(rule.exists) ? rule.exists : null;
|
|
116
|
-
if (!exists) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
exists.forEach((exist, existId, exists) => {
|
|
120
|
-
exists[existId] = Utils.expandText(exist, expanded);
|
|
121
|
-
});
|
|
122
|
-
rules[ruleIdx].exists = exists;
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
let ruleVariables;
|
|
126
|
-
// Set {when, allowFailure} based on rules result
|
|
127
|
-
if (this.rules) {
|
|
128
|
-
const ruleResult = Utils.getRulesResult({ argv, cwd, rules: this.rules, variables: this._variables }, this.gitData, this.when, this.allowFailure);
|
|
129
|
-
this.when = ruleResult.when;
|
|
130
|
-
this.allowFailure = ruleResult.allowFailure;
|
|
131
|
-
ruleVariables = ruleResult.variables;
|
|
132
|
-
if (ruleResult.needs) {
|
|
133
|
-
this.jobData["needs"] = ruleResult.needs;
|
|
134
|
-
}
|
|
135
|
-
this._variables = { ...this._variables, ...ruleVariables, ...argvVariables };
|
|
136
|
-
}
|
|
137
|
-
// Find environment matched variables
|
|
138
|
-
if (this.environment && expandVariables) {
|
|
139
|
-
const expanded = Utils.expandVariables(this._variables);
|
|
140
|
-
const envNameBeforeExpansion = this.environment.name;
|
|
141
|
-
this.environment.name = Utils.expandText(this.environment.name, expanded);
|
|
142
|
-
if (this.environment.name !== envNameBeforeExpansion) {
|
|
143
|
-
// Regenerate CI_ENVIRONMENT_SLUG based on env name if it changed after expansion
|
|
144
|
-
predefinedVariables["CI_ENVIRONMENT_SLUG"] = this._generateEnvironmentSlug(this.environment.name);
|
|
145
|
-
}
|
|
146
|
-
this.environment.url = Utils.expandText(this.environment.url, expanded);
|
|
147
|
-
}
|
|
148
|
-
const envMatchedVariables = Utils.findEnvMatchedVariables(variablesFromFiles, this.fileVariablesDir, this.environment);
|
|
149
|
-
const userDefinedVariables = { ...this.globalVariables, ...jobVariables, ...matrixVariables, ...ruleVariables, ...envMatchedVariables, ...argvVariables };
|
|
150
|
-
this.discourageOverridingOfPredefinedVariables(predefinedVariables, userDefinedVariables, argv.ignorePredefinedVars);
|
|
151
|
-
// Merge and expand after finding env matched variables
|
|
152
|
-
this._variables = { ...predefinedVariables, ...userDefinedVariables };
|
|
153
|
-
// Delete variables the user intentionally wants unset
|
|
154
|
-
for (const unsetVariable of argv.unsetVariables) {
|
|
155
|
-
delete this._variables[unsetVariable];
|
|
156
|
-
}
|
|
157
|
-
// Set GCL_PROJECT_DIR_ON_HOST if docker image
|
|
158
|
-
if (this.imageName(this._variables)) {
|
|
159
|
-
this._variables = { ...this._variables, ...{ GCL_PROJECT_DIR_ON_HOST: cwd } };
|
|
160
|
-
}
|
|
161
|
-
assert(this.scripts || this.trigger, chalk `{blueBright ${this.name}} must have script specified`);
|
|
162
|
-
assert(!(this.interactive && !this.argv.shellExecutorNoImage), chalk `${this.formattedJobName} @Interactive decorator cannot be used with --no-shell-executor-no-image`);
|
|
163
|
-
if (this.interactive && (this.when !== "manual" || this.imageName(this._variables) !== null)) {
|
|
164
|
-
throw new AssertionError({ message: `${this.formattedJobName} @Interactive decorator cannot have image: and must be when:manual` });
|
|
165
|
-
}
|
|
166
|
-
if (this.injectSSHAgent && this.imageName(this._variables) === null) {
|
|
167
|
-
throw new AssertionError({ message: `${this.formattedJobName} @InjectSSHAgent can only be used with image:` });
|
|
168
|
-
}
|
|
169
|
-
const expanded = Utils.expandVariables(this._variables);
|
|
170
|
-
for (const [i, c] of Object.entries(this.cache)) {
|
|
171
|
-
c.policy = Utils.expandText(c.policy, expanded);
|
|
172
|
-
assert(["pull", "push", "pull-push"].includes(c.policy), chalk `{blue ${this.name}} cache[${i}].policy is not 'pull', 'push' or 'pull-push'`);
|
|
173
|
-
assert(["on_success", "on_failure", "always"].includes(c.when), chalk `{blue ${this.name}} cache[${i}].when is not 'on_success', 'on_failure' or 'always'`);
|
|
174
|
-
assert(Array.isArray(c.paths), chalk `{blue ${this.name}} cache[${i}].paths must be array`);
|
|
175
|
-
}
|
|
176
|
-
for (const [i, s] of Object.entries(this.services)) {
|
|
177
|
-
assert(s.name, chalk `{blue ${this.name}} services[${i}].name is undefined`);
|
|
178
|
-
assert(!s.command || Array.isArray(s.command), chalk `{blue ${this.name}} services[${i}].command must be an array`);
|
|
179
|
-
assert(!s.entrypoint || Array.isArray(s.entrypoint), chalk `{blue ${this.name}} services[${i}].entrypoint must be an array`);
|
|
180
|
-
}
|
|
181
|
-
assert(!this.artifacts?.paths || Array.isArray(this.artifacts.paths), chalk `{blue ${this.name}} artifacts.paths must be an array`);
|
|
182
|
-
if (this.imageName(this._variables) && argv.mountCache) {
|
|
183
|
-
for (const c of this.cache) {
|
|
184
|
-
c.paths.forEach((p) => {
|
|
185
|
-
const path = Utils.expandText(p, expanded);
|
|
186
|
-
assert(!path.includes("*"), chalk `{blue ${this.name}} cannot have * in cache paths, when --mount-cache is enabled`);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Warn when overriding of predefined variables is detected
|
|
193
|
-
*/
|
|
194
|
-
discourageOverridingOfPredefinedVariables(predefinedVariables, userDefinedVariables, whiteListedPredefinedVariablesKeys) {
|
|
195
|
-
const predefinedVariablesKeys = Object.keys(predefinedVariables);
|
|
196
|
-
const userDefinedVariablesKeys = Object.keys(userDefinedVariables);
|
|
197
|
-
const overridingOfPredefinedVariables = userDefinedVariablesKeys.filter(ele => predefinedVariablesKeys.includes(ele) && !whiteListedPredefinedVariablesKeys.includes(ele));
|
|
198
|
-
if (overridingOfPredefinedVariables.length == 0) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
const linkToGitlab = "https://gitlab.com/gitlab-org/gitlab/-/blob/v17.7.1-ee/doc/ci/variables/predefined_variables.md?plain=1&ref_type=tags#L15-16";
|
|
202
|
-
this.writeStreams.memoStdout(chalk `
|
|
203
|
-
{bgYellowBright WARN } ${terminalLink("Avoid overriding predefined variables", linkToGitlab)} [{bold ${overridingOfPredefinedVariables}}] as it can cause the pipeline to behave unexpectedly.
|
|
204
|
-
If you know what you're doing and would like to suppress this warning, use one of the following methods:
|
|
205
|
-
\t• via cli options
|
|
206
|
-
\t\t• --ignore-predefined-vars ${overridingOfPredefinedVariables}
|
|
207
|
-
\t• via environment variable
|
|
208
|
-
\t\t• GCL_IGNORE_PREDEFINED_VARS=${overridingOfPredefinedVariables}
|
|
209
|
-
`);
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Get the predefinedVariables that's enriched with the additional info that's only available when constructing
|
|
213
|
-
*/
|
|
214
|
-
_predefinedVariables(opt) {
|
|
215
|
-
const argv = this.argv;
|
|
216
|
-
const cwd = argv.cwd;
|
|
217
|
-
const stateDir = this.argv.stateDir;
|
|
218
|
-
const gitData = this.gitData;
|
|
219
|
-
let ciBuildsDir;
|
|
220
|
-
if (this.jobData["image"]) {
|
|
221
|
-
ciBuildsDir = "/builds";
|
|
222
|
-
this.ciProjectDir = `${ciBuildsDir}/${gitData.remote.group}/${gitData.remote.project}`;
|
|
223
|
-
}
|
|
224
|
-
else if (argv.shellIsolation) {
|
|
225
|
-
ciBuildsDir = `${cwd}/${stateDir}/builds/${this.safeJobName}`;
|
|
226
|
-
this.ciProjectDir = ciBuildsDir;
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
ciBuildsDir = cwd;
|
|
230
|
-
this.ciProjectDir = ciBuildsDir;
|
|
231
|
-
}
|
|
232
|
-
const predefinedVariables = opt.predefinedVariables;
|
|
233
|
-
predefinedVariables["CI_JOB_ID"] = `${this.jobId}`;
|
|
234
|
-
predefinedVariables["CI_PIPELINE_ID"] = `${this.pipelineIid + 1000}`;
|
|
235
|
-
predefinedVariables["CI_PIPELINE_IID"] = `${this.pipelineIid}`;
|
|
236
|
-
predefinedVariables["CI_JOB_NAME"] = `${this.name}`;
|
|
237
|
-
predefinedVariables["CI_JOB_NAME_SLUG"] = `${this.name.replace(/[^a-z\d]+/ig, "-").replace(/^-/, "").slice(0, 63).replace(/-$/, "").toLowerCase()}`;
|
|
238
|
-
predefinedVariables["CI_JOB_STAGE"] = `${this.stage}`;
|
|
239
|
-
predefinedVariables["CI_BUILDS_DIR"] = ciBuildsDir;
|
|
240
|
-
predefinedVariables["CI_PROJECT_DIR"] = this.ciProjectDir;
|
|
241
|
-
predefinedVariables["CI_JOB_URL"] = `${predefinedVariables["CI_SERVER_URL"]}/${gitData.remote.group}/${gitData.remote.project}/-/jobs/${this.jobId}`; // Changes on rerun.
|
|
242
|
-
predefinedVariables["CI_PIPELINE_URL"] = `${predefinedVariables["CI_SERVER_URL"]}/${gitData.remote.group}/${gitData.remote.project}/pipelines/${this.pipelineIid}`;
|
|
243
|
-
predefinedVariables["CI_ENVIRONMENT_NAME"] = this.environment?.name ?? "";
|
|
244
|
-
predefinedVariables["CI_ENVIRONMENT_SLUG"] = this.environment?.name ? this._generateEnvironmentSlug(this.environment.name) : "";
|
|
245
|
-
predefinedVariables["CI_ENVIRONMENT_URL"] = this.environment?.url ?? "";
|
|
246
|
-
predefinedVariables["CI_ENVIRONMENT_TIER"] = this.environment?.deployment_tier ?? "";
|
|
247
|
-
predefinedVariables["CI_ENVIRONMENT_ACTION"] = this.environment?.action ?? "";
|
|
248
|
-
if (opt.nodeIndex !== null) {
|
|
249
|
-
predefinedVariables["CI_NODE_INDEX"] = `${opt.nodeIndex}`;
|
|
250
|
-
}
|
|
251
|
-
predefinedVariables["CI_NODE_TOTAL"] = `${opt.nodesTotal}`;
|
|
252
|
-
predefinedVariables["CI_REGISTRY"] = predefinedVariables["CI_REGISTRY"] = this.argv.registry ? Utils.gclRegistryPrefix : `local-registry.${this.gitData.remote.host}`;
|
|
253
|
-
predefinedVariables["CI_REGISTRY_IMAGE"] = `$CI_REGISTRY/${predefinedVariables["CI_PROJECT_PATH"].toLowerCase()}`;
|
|
254
|
-
return predefinedVariables;
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Generates a compliant slug for an environment name.
|
|
258
|
-
* See: https://gitlab.com/gitlab-org/gitlab/-/blob/fc31e7ac344e53ebae182ea1dca183bdc0e2ea71/lib/gitlab/slug/environment.rb
|
|
259
|
-
*
|
|
260
|
-
* The slug:
|
|
261
|
-
* - Contains only lowercase letters (a-z), numbers (0-9), and '-'.
|
|
262
|
-
* - Begins with a letter.
|
|
263
|
-
* - Has a maximum length of 24 characters.
|
|
264
|
-
* - Does not end with '-'.
|
|
265
|
-
*
|
|
266
|
-
* @param name The original environment name.
|
|
267
|
-
* @returns A compliant environment slug.
|
|
268
|
-
*/
|
|
269
|
-
_generateEnvironmentSlug(name) {
|
|
270
|
-
// 1. Lowercase, replace non-alphanumeric with '-', and squeeze repeating '-'
|
|
271
|
-
let slug = name
|
|
272
|
-
.toLowerCase()
|
|
273
|
-
.replace(/[^a-z0-9]/g, "-")
|
|
274
|
-
.replace(/-+/g, "-");
|
|
275
|
-
// 2. Must start with a letter
|
|
276
|
-
if (!/^[a-z]/.test(slug)) {
|
|
277
|
-
slug = `env-${slug}`;
|
|
278
|
-
}
|
|
279
|
-
// 3. If it's too long or was modified, shorten and add a hash suffix
|
|
280
|
-
if (slug.length > 24 || slug !== name) {
|
|
281
|
-
// Truncate to 17 chars (leaving room for '-' + 6-char hash)
|
|
282
|
-
slug = slug.slice(0, 17);
|
|
283
|
-
// Ensure it ends with a dash before adding the suffix
|
|
284
|
-
if (!slug.endsWith("-")) {
|
|
285
|
-
slug += "-";
|
|
286
|
-
}
|
|
287
|
-
// Create the 6-char suffix from a hash of the *original* name
|
|
288
|
-
const hexHash = crypto
|
|
289
|
-
.createHash("sha256")
|
|
290
|
-
.update(name)
|
|
291
|
-
.digest("hex");
|
|
292
|
-
// Use BigInt for safe conversion from hex -> base36
|
|
293
|
-
const suffix = BigInt(`0x${hexHash}`).toString(36).slice(-6);
|
|
294
|
-
return slug + suffix;
|
|
295
|
-
}
|
|
296
|
-
// 4. If it was short and unmodified, just ensure it doesn't end with '-'
|
|
297
|
-
return slug.replace(/-$/, "");
|
|
298
|
-
}
|
|
299
|
-
get jobStatus() {
|
|
300
|
-
if (this.preScriptsExitCode == null)
|
|
301
|
-
return "pending";
|
|
302
|
-
if (this.preScriptsExitCode == 0)
|
|
303
|
-
return "success";
|
|
304
|
-
let allowedExitCodes = [0];
|
|
305
|
-
const allowFailure = this.allowFailure;
|
|
306
|
-
switch (typeof allowFailure) {
|
|
307
|
-
case "boolean":
|
|
308
|
-
if (allowFailure) {
|
|
309
|
-
allowedExitCodes = [this.preScriptsExitCode];
|
|
310
|
-
}
|
|
311
|
-
break;
|
|
312
|
-
case "object":
|
|
313
|
-
if (!Array.isArray(allowFailure.exit_codes)) {
|
|
314
|
-
allowedExitCodes = [allowFailure.exit_codes];
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
allowedExitCodes = allowFailure.exit_codes;
|
|
318
|
-
}
|
|
319
|
-
break;
|
|
320
|
-
default:
|
|
321
|
-
throw new Error(`Unexpected type: ${typeof allowFailure}`);
|
|
322
|
-
}
|
|
323
|
-
return allowedExitCodes.includes(this.preScriptsExitCode) ? "warning" : "failed";
|
|
324
|
-
}
|
|
325
|
-
get artifactsToSource() {
|
|
326
|
-
if (this.jobData["gclArtifactsToSource"] != null)
|
|
327
|
-
return this.jobData["gclArtifactsToSource"];
|
|
328
|
-
return this.argv.artifactsToSource;
|
|
329
|
-
}
|
|
330
|
-
get prettyDuration() {
|
|
331
|
-
if (this._endTime) {
|
|
332
|
-
return prettyHrtime(this._endTime);
|
|
333
|
-
}
|
|
334
|
-
return this._startTime ?
|
|
335
|
-
prettyHrtime(process.hrtime(this._startTime)) :
|
|
336
|
-
"0 ms";
|
|
337
|
-
}
|
|
338
|
-
get formattedJobName() {
|
|
339
|
-
let prefix = "";
|
|
340
|
-
if (this.argv.childPipelineDepth > 0)
|
|
341
|
-
prefix = "\t".repeat(this.argv.childPipelineDepth) + `[${this.argv.variable.GCL_TRIGGERER}] -> `;
|
|
342
|
-
const timestampPrefix = this.argv.showTimestamps ?
|
|
343
|
-
`[${dateFormatter.format(new Date())} ${this.prettyDuration.padStart(7)}] ` :
|
|
344
|
-
"";
|
|
345
|
-
// [16:33:19 1.37 min] my-job > hello world
|
|
346
|
-
return chalk `${timestampPrefix}{blueBright ${prefix}${this.name.padEnd(this.jobNamePad)}}`;
|
|
347
|
-
}
|
|
348
|
-
get safeJobName() {
|
|
349
|
-
return Utils.safeDockerString(this.name);
|
|
350
|
-
}
|
|
351
|
-
get needs() {
|
|
352
|
-
return this.jobData["needs"] ?? null;
|
|
353
|
-
}
|
|
354
|
-
get buildVolumeName() {
|
|
355
|
-
return `gcl-${this.safeJobName}-${this.jobId}-build`;
|
|
356
|
-
}
|
|
357
|
-
get tmpVolumeName() {
|
|
358
|
-
return `gcl-${this.safeJobName}-${this.jobId}-tmp`;
|
|
359
|
-
}
|
|
360
|
-
get services() {
|
|
361
|
-
const services = [];
|
|
362
|
-
if (!this.jobData["services"])
|
|
363
|
-
return [];
|
|
364
|
-
for (const service of Object.values(this.jobData["services"])) {
|
|
365
|
-
const expanded = Utils.expandVariables({ ...this._variables, ...this._dotenvVariables, ...service["variables"] });
|
|
366
|
-
let serviceName = Utils.expandText(service["name"], expanded);
|
|
367
|
-
if (serviceName == "")
|
|
368
|
-
continue;
|
|
369
|
-
serviceName = serviceName.includes(":") ? serviceName : `${serviceName}:latest`;
|
|
370
|
-
services.push({
|
|
371
|
-
name: serviceName,
|
|
372
|
-
entrypoint: service["entrypoint"] ?? null,
|
|
373
|
-
command: service["command"] ?? null,
|
|
374
|
-
variables: expanded,
|
|
375
|
-
alias: Utils.expandText(service["alias"], expanded) ?? null,
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
return services;
|
|
379
|
-
}
|
|
380
|
-
set ciProjectDir(ciProjectDir) {
|
|
381
|
-
assert(this._ciProjectDir == null, "this._ciProjectDir can only be set once");
|
|
382
|
-
this._ciProjectDir = ciProjectDir;
|
|
383
|
-
}
|
|
384
|
-
get ciProjectDir() {
|
|
385
|
-
assert(this._ciProjectDir, "attempted to access this._ciProjectDir before it is initialized");
|
|
386
|
-
return this._ciProjectDir;
|
|
387
|
-
}
|
|
388
|
-
set jobNamePad(jobNamePad) {
|
|
389
|
-
assert(this._jobNamePad == null, "this._jobNamePad can only be set once");
|
|
390
|
-
this._jobNamePad = jobNamePad;
|
|
391
|
-
}
|
|
392
|
-
get jobNamePad() {
|
|
393
|
-
return this._jobNamePad ?? 0;
|
|
394
|
-
}
|
|
395
|
-
get producers() {
|
|
396
|
-
return this._producers;
|
|
397
|
-
}
|
|
398
|
-
set producers(producers) {
|
|
399
|
-
assert(this._producers == null, "this._producers can only be set once");
|
|
400
|
-
this._producers = producers;
|
|
401
|
-
}
|
|
402
|
-
get stage() {
|
|
403
|
-
return this.jobData["stage"] || "test";
|
|
404
|
-
}
|
|
405
|
-
get interactive() {
|
|
406
|
-
return this.jobData["gclInteractive"] || false;
|
|
407
|
-
}
|
|
408
|
-
get injectSSHAgent() {
|
|
409
|
-
return this.jobData["gclInjectSSHAgent"] || false;
|
|
410
|
-
}
|
|
411
|
-
get description() {
|
|
412
|
-
return this.jobData["gclDescription"] ?? "";
|
|
413
|
-
}
|
|
414
|
-
get artifacts() {
|
|
415
|
-
return this.jobData["artifacts"];
|
|
416
|
-
}
|
|
417
|
-
deleteArtifacts() {
|
|
418
|
-
delete this.jobData["artifacts"];
|
|
419
|
-
}
|
|
420
|
-
get cache() {
|
|
421
|
-
return this.jobData["cache"] || [];
|
|
422
|
-
}
|
|
423
|
-
async getUniqueCacheName(cwd, expanded, cacheIndex) {
|
|
424
|
-
const getCachePrefix = (index) => {
|
|
425
|
-
const prefix = this.jobData["cache"][index]["key"]["prefix"];
|
|
426
|
-
if (prefix) {
|
|
427
|
-
return `${index}_${Utils.expandText(prefix, expanded)}-`;
|
|
428
|
-
}
|
|
429
|
-
const filenames = this.jobData["cache"][index]["key"]["files"].map((p) => {
|
|
430
|
-
const expandP = Utils.expandText(p, expanded);
|
|
431
|
-
return expandP.split(".")[0];
|
|
432
|
-
}).join("_");
|
|
433
|
-
return `${index}_${filenames}-`;
|
|
434
|
-
};
|
|
435
|
-
const key = this.jobData["cache"][cacheIndex].key;
|
|
436
|
-
if (typeof key === "string" || key == null) {
|
|
437
|
-
return Utils.expandText(key ?? "default", expanded);
|
|
438
|
-
}
|
|
439
|
-
const files = key["files"].map((f) => {
|
|
440
|
-
let path = Utils.expandText(f, expanded);
|
|
441
|
-
if (path.startsWith(`${this.ciProjectDir}/`)) {
|
|
442
|
-
path = path.slice(`${this.ciProjectDir}/`.length);
|
|
443
|
-
}
|
|
444
|
-
return `${cwd}/${path}`;
|
|
445
|
-
});
|
|
446
|
-
return getCachePrefix(cacheIndex) + await Utils.checksumFiles(cwd, files);
|
|
447
|
-
}
|
|
448
|
-
get beforeScripts() {
|
|
449
|
-
const beforeScripts = this.jobData["before_script"] || [];
|
|
450
|
-
return typeof beforeScripts === "string" ? [beforeScripts] : beforeScripts;
|
|
451
|
-
}
|
|
452
|
-
get afterScripts() {
|
|
453
|
-
const afterScripts = this.jobData["after_script"] || [];
|
|
454
|
-
return typeof afterScripts === "string" ? [afterScripts] : afterScripts;
|
|
455
|
-
}
|
|
456
|
-
get scripts() {
|
|
457
|
-
const script = this.jobData["script"];
|
|
458
|
-
return typeof script === "string" ? [script] : script;
|
|
459
|
-
}
|
|
460
|
-
get trigger() {
|
|
461
|
-
return this.jobData["trigger"];
|
|
462
|
-
}
|
|
463
|
-
async startTriggerPipeline() {
|
|
464
|
-
this.writeStreams.memoStdout(chalk `{bgYellowBright WARN } downstream pipeline is experimental in gitlab-ci-local\n`);
|
|
465
|
-
await this.fetchTriggerInclude();
|
|
466
|
-
const variablesForDownstreamPipeline = Object.entries({ ...this.globalVariables, ...this.jobData.variables }).map(([key, value]) => `${key}=${value}`);
|
|
467
|
-
const gclTriggerer = this.argv.variable["GCL_TRIGGERER"] ?
|
|
468
|
-
`${this.argv.variable["GCL_TRIGGERER"]} -> ${this.name}` :
|
|
469
|
-
this.name;
|
|
470
|
-
await handler({
|
|
471
|
-
...Object.fromEntries(this.argv.map),
|
|
472
|
-
file: `${this.argv.stateDir}/includes/triggers/${this.name}.yml`,
|
|
473
|
-
variable: [
|
|
474
|
-
chalk `GCL_TRIGGERER=${gclTriggerer}`,
|
|
475
|
-
"CI_PIPELINE_SOURCE=parent_pipeline",
|
|
476
|
-
].concat(variablesForDownstreamPipeline),
|
|
477
|
-
}, this.writeStreams, [], this.argv.childPipelineDepth + 1);
|
|
478
|
-
}
|
|
479
|
-
get preScriptsExitCode() {
|
|
480
|
-
return this._prescriptsExitCode;
|
|
481
|
-
}
|
|
482
|
-
get afterScriptsExitCode() {
|
|
483
|
-
return this._afterScriptsExitCode;
|
|
484
|
-
}
|
|
485
|
-
get started() {
|
|
486
|
-
return this._running || this._prescriptsExitCode !== null;
|
|
487
|
-
}
|
|
488
|
-
get finished() {
|
|
489
|
-
return !this._running && this._prescriptsExitCode !== null;
|
|
490
|
-
}
|
|
491
|
-
get coveragePercent() {
|
|
492
|
-
return this._coveragePercent;
|
|
493
|
-
}
|
|
494
|
-
get fileVariablesDir() {
|
|
495
|
-
return `/tmp/gitlab-ci-local-file-variables-${this._variables["CI_PROJECT_PATH_SLUG"]}-${this.jobId}`;
|
|
496
|
-
}
|
|
497
|
-
get globalVariables() {
|
|
498
|
-
if (this.inherit.variables === false) {
|
|
499
|
-
return {};
|
|
500
|
-
}
|
|
501
|
-
else if (Array.isArray(this.inherit.variables)) {
|
|
502
|
-
const inheritVariables = this.inherit.variables;
|
|
503
|
-
return Object.fromEntries(Object.entries(this._globalVariables).filter(([k]) => inheritVariables.includes(k)));
|
|
504
|
-
}
|
|
505
|
-
return this._globalVariables;
|
|
506
|
-
}
|
|
507
|
-
async start() {
|
|
508
|
-
if (this.trigger) {
|
|
509
|
-
await this.startTriggerPipeline();
|
|
510
|
-
this._prescriptsExitCode = 0; // NOTE: so that `this.finished` will implicitly be set to true
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
513
|
-
this._running = true;
|
|
514
|
-
const argv = this.argv;
|
|
515
|
-
this._startTime = process.hrtime();
|
|
516
|
-
this._variables["CI_JOB_STARTED_AT"] = new Date().toISOString().split(".")[0] + "Z";
|
|
517
|
-
const writeStreams = this.writeStreams;
|
|
518
|
-
this._dotenvVariables = await this.initProducerReportsDotenvVariables(writeStreams, Utils.expandVariables(this._variables));
|
|
519
|
-
const expanded = Utils.unscape$$Variables(Utils.expandVariables({ ...this._variables, ...this._dotenvVariables }));
|
|
520
|
-
const imageName = this.imageName(expanded);
|
|
521
|
-
const helperImageName = argv.helperImage;
|
|
522
|
-
const safeJobName = this.safeJobName;
|
|
523
|
-
const outputLogFilePath = `${argv.cwd}/${argv.stateDir}/output/${safeJobName}.log`;
|
|
524
|
-
await fs.ensureFile(outputLogFilePath);
|
|
525
|
-
await fs.truncate(outputLogFilePath);
|
|
526
|
-
if (!this.interactive) {
|
|
527
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright starting} ${imageName ?? "shell"} ({yellow ${this.stage}})\n`);
|
|
528
|
-
}
|
|
529
|
-
if (imageName) {
|
|
530
|
-
await this.pullImage(writeStreams, imageName);
|
|
531
|
-
const buildVolumeName = this.buildVolumeName;
|
|
532
|
-
const tmpVolumeName = this.tmpVolumeName;
|
|
533
|
-
const fileVariablesDir = this.fileVariablesDir;
|
|
534
|
-
const volumePromises = [];
|
|
535
|
-
volumePromises.push(Utils.spawn([this.argv.containerExecutable, "volume", "create", `${buildVolumeName}`], argv.cwd));
|
|
536
|
-
volumePromises.push(Utils.spawn([this.argv.containerExecutable, "volume", "create", `${tmpVolumeName}`], argv.cwd));
|
|
537
|
-
this._containerVolumeNames.push(buildVolumeName);
|
|
538
|
-
this._containerVolumeNames.push(tmpVolumeName);
|
|
539
|
-
await Promise.all(volumePromises);
|
|
540
|
-
const time = process.hrtime();
|
|
541
|
-
this.refreshLongRunningSilentTimeout(writeStreams);
|
|
542
|
-
let chownOpt = "0:0";
|
|
543
|
-
let chmodOpt = "a+rw";
|
|
544
|
-
if (!this.argv.umask) {
|
|
545
|
-
const { stdout } = await Utils.spawn([this.argv.containerExecutable, "run", "--rm", "--entrypoint", "sh", imageName, "-c", "echo \"$(id -u):$(id -g)\""]);
|
|
546
|
-
chownOpt = stdout;
|
|
547
|
-
if (chownOpt == "0:0") {
|
|
548
|
-
chmodOpt = "g-w";
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
if (helperImageName) {
|
|
552
|
-
await this.pullImage(writeStreams, helperImageName);
|
|
553
|
-
}
|
|
554
|
-
const helperContainerArgs = [
|
|
555
|
-
this.argv.containerExecutable, "create", "--user=0:0",
|
|
556
|
-
`--volume=${buildVolumeName}:${this.ciProjectDir}`,
|
|
557
|
-
`--volume=${tmpVolumeName}:${this.fileVariablesDir}`,
|
|
558
|
-
];
|
|
559
|
-
if (this.argv.caFile) {
|
|
560
|
-
const caFilePath = path.isAbsolute(this.argv.caFile) ? this.argv.caFile : path.resolve(this.argv.cwd, this.argv.caFile);
|
|
561
|
-
if (await fs.pathExists(caFilePath)) {
|
|
562
|
-
helperContainerArgs.push(`--volume=${caFilePath}:/etc/ssl/certs/ca-certificates.crt:ro`);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
helperContainerArgs.push(`${helperImageName}`, "sh", "-c", `chown ${chownOpt} -R ${this.ciProjectDir} && chmod ${chmodOpt} -R ${this.ciProjectDir} && chown ${chownOpt} -R /tmp/ && chmod ${chmodOpt} -R /tmp/`);
|
|
566
|
-
const { stdout: containerId } = await Utils.spawn(helperContainerArgs, argv.cwd);
|
|
567
|
-
this._containersToClean.push(containerId);
|
|
568
|
-
if (await fs.pathExists(fileVariablesDir)) {
|
|
569
|
-
await Utils.spawn([this.argv.containerExecutable, "cp", `${fileVariablesDir}/.`, `${containerId}:${fileVariablesDir}`], argv.cwd);
|
|
570
|
-
this.refreshLongRunningSilentTimeout(writeStreams);
|
|
571
|
-
}
|
|
572
|
-
await Utils.spawn([this.argv.containerExecutable, "cp", `${argv.stateDir}/builds/.docker/.`, `${containerId}:${this.ciProjectDir}`], argv.cwd);
|
|
573
|
-
await Utils.spawn([this.argv.containerExecutable, "start", "--attach", containerId], argv.cwd);
|
|
574
|
-
await Utils.spawn([this.argv.containerExecutable, "rm", "-vf", containerId], argv.cwd);
|
|
575
|
-
const endTime = process.hrtime(time);
|
|
576
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright copied to ${this.argv.containerExecutable} volumes} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
577
|
-
}
|
|
578
|
-
if (this.services?.length) {
|
|
579
|
-
// `host` and `none` networks do not work with services because aliases only work for
|
|
580
|
-
// user defined networks.
|
|
581
|
-
for (const network of this.argv.network) {
|
|
582
|
-
if (["host", "none"].includes(network)) {
|
|
583
|
-
throw new AssertionError({ message: `Cannot add service network alias with network mode '${network}'` });
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
await this.createDockerNetwork(`gitlab-ci-local-${this.jobId}`);
|
|
587
|
-
await Promise.all(this.services.map(async (service, serviceIndex) => {
|
|
588
|
-
const serviceName = service.name;
|
|
589
|
-
await this.pullImage(writeStreams, serviceName);
|
|
590
|
-
const serviceContainerId = await this.startService(writeStreams, Utils.expandVariables({ ...expanded, ...service.variables }), service);
|
|
591
|
-
const serviceContainerLogFile = `${argv.cwd}/${argv.stateDir}/services-output/${this.safeJobName}/${serviceName}-${serviceIndex}.log`;
|
|
592
|
-
await this.serviceHealthCheck(writeStreams, service, serviceIndex, serviceContainerLogFile);
|
|
593
|
-
const { stdout, stderr } = await Utils.spawn([this.argv.containerExecutable, "logs", serviceContainerId]);
|
|
594
|
-
await fs.ensureFile(serviceContainerLogFile);
|
|
595
|
-
await fs.promises.writeFile(serviceContainerLogFile, `### stdout ###\n${stdout}\n### stderr ###\n${stderr}\n`);
|
|
596
|
-
}));
|
|
597
|
-
}
|
|
598
|
-
await this.execPreScripts(expanded);
|
|
599
|
-
if (this._prescriptsExitCode == null)
|
|
600
|
-
throw Error("this._prescriptsExitCode must be defined!");
|
|
601
|
-
await this.execAfterScripts(expanded);
|
|
602
|
-
this._running = false;
|
|
603
|
-
this._endTime = this._endTime ?? process.hrtime(this._startTime);
|
|
604
|
-
this.printFinishedString();
|
|
605
|
-
await this.copyCacheOut(this.writeStreams, expanded);
|
|
606
|
-
await this.copyArtifactsOut(this.writeStreams, expanded);
|
|
607
|
-
if (this.jobData["coverage"]) {
|
|
608
|
-
this._coveragePercent = await Utils.getCoveragePercent(argv.cwd, argv.stateDir, this.jobData["coverage"], safeJobName);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
async cleanupResources() {
|
|
612
|
-
clearTimeout(this._longRunningSilentTimeout);
|
|
613
|
-
if (!this.argv.cleanup)
|
|
614
|
-
return;
|
|
615
|
-
if (this._containersToClean.length > 0) {
|
|
616
|
-
try {
|
|
617
|
-
await Utils.spawn([this.argv.containerExecutable, "rm", "-vf", ...this._containersToClean]);
|
|
618
|
-
}
|
|
619
|
-
catch (e) {
|
|
620
|
-
assert(e instanceof Error, "e is not instanceof Error");
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
if (this._serviceNetworkId) {
|
|
624
|
-
try {
|
|
625
|
-
await Utils.spawn([this.argv.containerExecutable, "network", "rm", `${this._serviceNetworkId}`]);
|
|
626
|
-
}
|
|
627
|
-
catch (e) {
|
|
628
|
-
assert(e instanceof Error, "e is not instanceof Error");
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
if (this._containerVolumeNames.length > 0) {
|
|
632
|
-
try {
|
|
633
|
-
await Utils.spawn([this.argv.containerExecutable, "volume", "rm", ...this._containerVolumeNames]);
|
|
634
|
-
}
|
|
635
|
-
catch (e) {
|
|
636
|
-
assert(e instanceof Error, "e is not instanceof Error");
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
const rmPromises = [];
|
|
640
|
-
for (const file of this._filesToRm) {
|
|
641
|
-
rmPromises.push(fs.rm(file, { recursive: true, force: true }));
|
|
642
|
-
}
|
|
643
|
-
await Promise.all(rmPromises);
|
|
644
|
-
const fileVariablesDir = this.fileVariablesDir;
|
|
645
|
-
try {
|
|
646
|
-
await fs.rm(fileVariablesDir, { recursive: true, force: true });
|
|
647
|
-
}
|
|
648
|
-
catch (e) {
|
|
649
|
-
assert(e instanceof Error, "e is not instanceof Error");
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
generateInjectSSHAgentOptions() {
|
|
653
|
-
if (!this.injectSSHAgent) {
|
|
654
|
-
return "";
|
|
655
|
-
}
|
|
656
|
-
if (process.platform === "darwin" || /^darwin/.exec(process.env.OSTYPE ?? "")) {
|
|
657
|
-
return "--env SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock";
|
|
658
|
-
}
|
|
659
|
-
return `--env SSH_AUTH_SOCK=${process.env.SSH_AUTH_SOCK} -v ${process.env.SSH_AUTH_SOCK}:${process.env.SSH_AUTH_SOCK}`;
|
|
660
|
-
}
|
|
661
|
-
generateScriptCommands(scripts) {
|
|
662
|
-
let cmd = "";
|
|
663
|
-
scripts.forEach((script) => {
|
|
664
|
-
const split = script.split(/\r?\n/);
|
|
665
|
-
const multilineText = split.length > 1 ? " # collapsed multi-line command" : "";
|
|
666
|
-
const text = split[0]?.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/[$]/g, "\\$");
|
|
667
|
-
if (this.interactive) {
|
|
668
|
-
cmd += chalk `echo "{green $ ${text}${multilineText}}"\n`;
|
|
669
|
-
}
|
|
670
|
-
else {
|
|
671
|
-
// Print command echo'ed with $GCL_SHELL_PROMPT_PLACEHOLDER
|
|
672
|
-
cmd += `echo "${GCL_SHELL_PROMPT_PLACEHOLDER} ${text}${multilineText}"\n`;
|
|
673
|
-
}
|
|
674
|
-
// Execute actual script
|
|
675
|
-
cmd += `${script}\n`;
|
|
676
|
-
});
|
|
677
|
-
return cmd;
|
|
678
|
-
}
|
|
679
|
-
async mountCacheCmd(writeStreams, expanded) {
|
|
680
|
-
if (this.imageName(expanded) && !this.argv.mountCache)
|
|
681
|
-
return [];
|
|
682
|
-
const cmd = [];
|
|
683
|
-
for (const [index, c] of this.cache.entries()) {
|
|
684
|
-
const uniqueCacheName = await this.getUniqueCacheName(this.argv.cwd, expanded, index);
|
|
685
|
-
c.paths.forEach((p) => {
|
|
686
|
-
const path = Utils.expandText(p, expanded);
|
|
687
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright mounting cache} for path ${path}\n`);
|
|
688
|
-
const cacheMount = Utils.safeDockerString(`gcl-${expanded.CI_PROJECT_PATH_SLUG}-${uniqueCacheName}`);
|
|
689
|
-
cmd.push("-v", `${cacheMount}:${this.ciProjectDir}/${path}`);
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
return cmd;
|
|
693
|
-
}
|
|
694
|
-
async execPreScripts(expanded) {
|
|
695
|
-
const prescripts = this.beforeScripts.concat(this.scripts);
|
|
696
|
-
expanded["CI_JOB_STATUS"] = "running";
|
|
697
|
-
this._prescriptsExitCode = await this.execScripts(prescripts, expanded, "");
|
|
698
|
-
expanded["CI_JOB_STATUS"] = this._prescriptsExitCode === 0 ? "success" : "failed";
|
|
699
|
-
this.printExitedString(this._prescriptsExitCode);
|
|
700
|
-
}
|
|
701
|
-
async execAfterScripts(expanded) {
|
|
702
|
-
const message = "Running after script...";
|
|
703
|
-
this._afterScriptsExitCode = await this.execScripts(this.afterScripts, expanded, message);
|
|
704
|
-
this.printAfterScriptExitedString(this._afterScriptsExitCode);
|
|
705
|
-
}
|
|
706
|
-
async execScripts(scripts, expanded, message) {
|
|
707
|
-
const cwd = this.argv.cwd;
|
|
708
|
-
const stateDir = this.argv.stateDir;
|
|
709
|
-
const safeJobName = this.safeJobName;
|
|
710
|
-
const outputFilesPath = `${cwd}/${stateDir}/output/${safeJobName}.log`;
|
|
711
|
-
const buildVolumeName = this.buildVolumeName;
|
|
712
|
-
const tmpVolumeName = this.tmpVolumeName;
|
|
713
|
-
const imageName = this.imageName(expanded);
|
|
714
|
-
const writeStreams = this.writeStreams;
|
|
715
|
-
if (scripts.length === 0 || scripts[0] == null)
|
|
716
|
-
return 0;
|
|
717
|
-
if (message.length > 0)
|
|
718
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright ${message}}\n`);
|
|
719
|
-
await fs.remove(`${cwd}/${stateDir}/artifacts/${safeJobName}`);
|
|
720
|
-
// Copy git tracked files to build folder if shell isolation enabled.
|
|
721
|
-
if (!imageName && this.argv.shellIsolation) {
|
|
722
|
-
await Utils.rsyncTrackedFiles(cwd, stateDir, `${safeJobName}`);
|
|
723
|
-
}
|
|
724
|
-
if (this.interactive) {
|
|
725
|
-
let iCmd = "set -eo pipefail\n";
|
|
726
|
-
iCmd += this.generateScriptCommands(scripts);
|
|
727
|
-
const interactiveCp = execa(iCmd, {
|
|
728
|
-
cwd,
|
|
729
|
-
shell: "bash",
|
|
730
|
-
stdio: ["inherit", "inherit", "inherit"],
|
|
731
|
-
env: { ...expanded, ...process.env },
|
|
732
|
-
});
|
|
733
|
-
return new Promise((resolve, reject) => {
|
|
734
|
-
void interactiveCp.on("exit", (code) => resolve(code ?? 0));
|
|
735
|
-
void interactiveCp.on("error", (err) => reject(err));
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
if (this.argv.registry) {
|
|
739
|
-
expanded["CI_REGISTRY_USER"] = expanded["CI_REGISTRY_USER"] ?? `${Utils.gclRegistryPrefix}.user`;
|
|
740
|
-
expanded["CI_REGISTRY_PASSWORD"] = expanded["CI_REGISTRY_PASSWORD"] ?? `${Utils.gclRegistryPrefix}.password`;
|
|
741
|
-
}
|
|
742
|
-
this.refreshLongRunningSilentTimeout(writeStreams);
|
|
743
|
-
if (imageName && !this._containerId) {
|
|
744
|
-
let dockerCmd = `${this.argv.containerExecutable} create --interactive ${this.generateInjectSSHAgentOptions()} `;
|
|
745
|
-
if (this.argv.privileged) {
|
|
746
|
-
dockerCmd += "--privileged ";
|
|
747
|
-
}
|
|
748
|
-
for (const device of this.argv.device) {
|
|
749
|
-
dockerCmd += `--device ${device} `;
|
|
750
|
-
}
|
|
751
|
-
if (this.argv.ulimit !== null) {
|
|
752
|
-
dockerCmd += `--ulimit nofile=${this.argv.ulimit} `;
|
|
753
|
-
}
|
|
754
|
-
if (this.argv.umask) {
|
|
755
|
-
dockerCmd += "--user 0:0 ";
|
|
756
|
-
}
|
|
757
|
-
if (this.argv.userns != undefined) {
|
|
758
|
-
dockerCmd += `--userns=${this.argv.userns} `;
|
|
759
|
-
}
|
|
760
|
-
if (this.argv.containerMacAddress) {
|
|
761
|
-
dockerCmd += `--mac-address "${this.argv.containerMacAddress}" `;
|
|
762
|
-
}
|
|
763
|
-
const imageUser = this.imageUser(expanded);
|
|
764
|
-
if (imageUser) {
|
|
765
|
-
dockerCmd += `--user ${imageUser} `;
|
|
766
|
-
}
|
|
767
|
-
if (this.argv.containerEmulate) {
|
|
768
|
-
const runnerName = this.argv.containerEmulate;
|
|
769
|
-
if (!GitlabRunnerPresetValues.includes(runnerName)) {
|
|
770
|
-
throw new Error("Invalid gitlab runner to emulate.");
|
|
771
|
-
}
|
|
772
|
-
const memoryConfig = GitlabRunnerMemoryPresetValue[runnerName];
|
|
773
|
-
const cpuConfig = GitlabRunnerCPUsPresetValue[runnerName];
|
|
774
|
-
dockerCmd += `--memory=${memoryConfig}m `;
|
|
775
|
-
dockerCmd += `--kernel-memory=${memoryConfig}m `;
|
|
776
|
-
dockerCmd += `--cpus=${cpuConfig} `;
|
|
777
|
-
}
|
|
778
|
-
// host and none networks have to be specified using --network, since they cannot be used with
|
|
779
|
-
// `docker network connect`.
|
|
780
|
-
for (const network of this.argv.network) {
|
|
781
|
-
if (["host", "none"].includes(network)) {
|
|
782
|
-
dockerCmd += `--network ${network} `;
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
// The default podman network mode is not `bridge`, which means a `podman network connect` call will fail
|
|
786
|
-
// when connecting user defined networks. The workaround is to use a user defined network on container
|
|
787
|
-
// creation.
|
|
788
|
-
//
|
|
789
|
-
// See https://github.com/containers/podman/issues/19577
|
|
790
|
-
//
|
|
791
|
-
// This should not clash with the `host` and `none` networks above, since service creation should have
|
|
792
|
-
// failed when using `host` or `none` networks.
|
|
793
|
-
if (this._serviceNetworkId) {
|
|
794
|
-
// `build` alias: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27060
|
|
795
|
-
dockerCmd += `--network ${this._serviceNetworkId} --network-alias build `;
|
|
796
|
-
}
|
|
797
|
-
if (this.argv.registry) {
|
|
798
|
-
dockerCmd += `--network ${Utils.gclRegistryPrefix}.net `;
|
|
799
|
-
dockerCmd += `--volume ${Utils.gclRegistryPrefix}.certs:/etc/containers/certs.d:ro `;
|
|
800
|
-
dockerCmd += `--volume ${Utils.gclRegistryPrefix}.certs:/etc/docker/certs.d:ro `;
|
|
801
|
-
}
|
|
802
|
-
dockerCmd += `--volume ${buildVolumeName}:${this.ciProjectDir} `;
|
|
803
|
-
dockerCmd += `--volume ${tmpVolumeName}:${this.fileVariablesDir} `;
|
|
804
|
-
dockerCmd += `--workdir ${this.ciProjectDir} `;
|
|
805
|
-
for (const volume of this.argv.volume) {
|
|
806
|
-
dockerCmd += `--volume ${volume} `;
|
|
807
|
-
}
|
|
808
|
-
for (const extraHost of this.argv.extraHost) {
|
|
809
|
-
dockerCmd += `--add-host=${extraHost} `;
|
|
810
|
-
}
|
|
811
|
-
if (this.argv.caFile) {
|
|
812
|
-
const caFilePath = path.isAbsolute(this.argv.caFile) ? this.argv.caFile : path.resolve(this.argv.cwd, this.argv.caFile);
|
|
813
|
-
if (await fs.pathExists(caFilePath)) {
|
|
814
|
-
dockerCmd += `--volume ${caFilePath}:/etc/ssl/certs/ca-certificates.crt:ro `;
|
|
815
|
-
expanded["SSL_CERT_FILE"] = "/etc/ssl/certs/ca-certificates.crt";
|
|
816
|
-
expanded["SSL_CERT_DIR"] = "/etc/ssl/certs";
|
|
817
|
-
}
|
|
818
|
-
else {
|
|
819
|
-
writeStreams.stderr(chalk `{yellow WARNING: CA file not found: ${caFilePath}}\n`);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
for (const [key, val] of Object.entries(expanded)) {
|
|
823
|
-
// Replacing `'` with `'\''` to correctly handle single quotes(if `val` contains `'`) in shell commands
|
|
824
|
-
dockerCmd += ` -e '${key}=${val.toString().replace(/'/g, "'\\''")}' \\\n`;
|
|
825
|
-
}
|
|
826
|
-
if (this.imageEntrypoint) {
|
|
827
|
-
dockerCmd += `--entrypoint ${Utils.safeBashString(this.imageEntrypoint[0])} `;
|
|
828
|
-
}
|
|
829
|
-
dockerCmd += `${(await this.mountCacheCmd(writeStreams, expanded)).join(" ")} `;
|
|
830
|
-
dockerCmd += `${imageName} `;
|
|
831
|
-
if (this.imageEntrypoint?.length ?? 0 > 1) {
|
|
832
|
-
this.imageEntrypoint?.slice(1).forEach((e) => {
|
|
833
|
-
dockerCmd += `${Utils.safeBashString(e)} `;
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
dockerCmd += "sh -c \"\n";
|
|
837
|
-
dockerCmd += "if [ -x /usr/local/bin/bash ]; then\n";
|
|
838
|
-
dockerCmd += "\texec /usr/local/bin/bash \n";
|
|
839
|
-
dockerCmd += "elif [ -x /usr/bin/bash ]; then\n";
|
|
840
|
-
dockerCmd += "\texec /usr/bin/bash \n";
|
|
841
|
-
dockerCmd += "elif [ -x /bin/bash ]; then\n";
|
|
842
|
-
dockerCmd += "\texec /bin/bash \n";
|
|
843
|
-
dockerCmd += "elif [ -x /usr/local/bin/sh ]; then\n";
|
|
844
|
-
dockerCmd += "\texec /usr/local/bin/sh \n";
|
|
845
|
-
dockerCmd += "elif [ -x /usr/bin/sh ]; then\n";
|
|
846
|
-
dockerCmd += "\texec /usr/bin/sh \n";
|
|
847
|
-
dockerCmd += "elif [ -x /bin/sh ]; then\n";
|
|
848
|
-
dockerCmd += "\texec /bin/sh \n";
|
|
849
|
-
dockerCmd += "elif [ -x /busybox/sh ]; then\n";
|
|
850
|
-
dockerCmd += "\texec /busybox/sh \n";
|
|
851
|
-
dockerCmd += "else\n";
|
|
852
|
-
dockerCmd += "\techo shell not found\n";
|
|
853
|
-
dockerCmd += "\texit 1\n";
|
|
854
|
-
dockerCmd += "fi\n\"";
|
|
855
|
-
const { stdout: containerId } = await Utils.bash(dockerCmd, cwd);
|
|
856
|
-
for (const network of this.argv.network) {
|
|
857
|
-
// Special network names that do not work with `docker network connect`
|
|
858
|
-
if (["host", "none"].includes(network)) {
|
|
859
|
-
continue;
|
|
860
|
-
}
|
|
861
|
-
await Utils.spawn([this.argv.containerExecutable, "network", "connect", network, `${containerId}`]);
|
|
862
|
-
}
|
|
863
|
-
this._containerId = containerId;
|
|
864
|
-
this._containersToClean.push(this._containerId);
|
|
865
|
-
}
|
|
866
|
-
await this.copyCacheIn(writeStreams, expanded);
|
|
867
|
-
await this.copyArtifactsIn(writeStreams);
|
|
868
|
-
let cmd = "set -eo pipefail\n";
|
|
869
|
-
cmd += "exec 0< /dev/null\n";
|
|
870
|
-
if (!imageName && this.argv.shellIsolation) {
|
|
871
|
-
cmd += `cd ${stateDir}/builds/${safeJobName}/\n`;
|
|
872
|
-
}
|
|
873
|
-
if (imageName) {
|
|
874
|
-
cmd += `cd ${this.ciProjectDir} \n`;
|
|
875
|
-
if (expanded["CI_JOB_STATUS"] != "running") {
|
|
876
|
-
// Ensures the env `CI_JOB_STATUS` is passed to the after_script context
|
|
877
|
-
cmd += `export CI_JOB_STATUS=${expanded["CI_JOB_STATUS"]}\n`;
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
cmd += this.generateScriptCommands(scripts);
|
|
881
|
-
cmd += "exit 0\n";
|
|
882
|
-
const jobScriptFile = `${cwd}/${stateDir}/scripts/${safeJobName}_${this.jobId}`;
|
|
883
|
-
await fs.outputFile(jobScriptFile, cmd, "utf-8");
|
|
884
|
-
await fs.chmod(jobScriptFile, "0755");
|
|
885
|
-
this._filesToRm.push(jobScriptFile);
|
|
886
|
-
if (imageName) {
|
|
887
|
-
await Utils.spawn([this.argv.containerExecutable, "cp", `${stateDir}/scripts/${safeJobName}_${this.jobId}`, `${this._containerId}:/gcl-cmd`], cwd);
|
|
888
|
-
}
|
|
889
|
-
const cp = execa(this._containerId ? `${this.argv.containerExecutable} start --attach -i ${this._containerId}` : "bash", {
|
|
890
|
-
cwd,
|
|
891
|
-
shell: "bash",
|
|
892
|
-
env: imageName ? process.env : expanded,
|
|
893
|
-
});
|
|
894
|
-
// eslint-disable-next-line no-control-regex
|
|
895
|
-
const sectionRegex = /\x1b\[0Ksection_(start|end):(\d+):([^\s[]+)(?:\[[^\]]*\])?\r\x1b\[0K/;
|
|
896
|
-
const sectionStartTimes = new Map();
|
|
897
|
-
const outFunc = (line, stream, colorize) => {
|
|
898
|
-
this.refreshLongRunningSilentTimeout(writeStreams);
|
|
899
|
-
const m = sectionRegex.exec(line);
|
|
900
|
-
let isSection = false;
|
|
901
|
-
if (m) {
|
|
902
|
-
isSection = true;
|
|
903
|
-
if (m[1] === "start") {
|
|
904
|
-
sectionStartTimes.set(m[3], Date.now());
|
|
905
|
-
line = chalk `{cyanBright ${m[3]}_started}`;
|
|
906
|
-
}
|
|
907
|
-
else {
|
|
908
|
-
const elapsed = Date.now() - (sectionStartTimes.get(m[3]) ?? Date.now());
|
|
909
|
-
line = chalk `{cyanBright ${m[3]}} took {magenta ${elapsed}ms}`;
|
|
910
|
-
sectionStartTimes.delete(m[3]);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
stream(`${this.formattedJobName} `);
|
|
914
|
-
if (line.startsWith(GCL_SHELL_PROMPT_PLACEHOLDER)) {
|
|
915
|
-
// replace the GCL_SHELL_PROMPT_PLACEHOLDER with `$` and make the SHELL_PROMPT line green color
|
|
916
|
-
line = line.slice(GCL_SHELL_PROMPT_PLACEHOLDER.length);
|
|
917
|
-
line = chalk `{green $${line}}`;
|
|
918
|
-
}
|
|
919
|
-
else if (!isSection) {
|
|
920
|
-
stream(`${colorize(">")} `);
|
|
921
|
-
}
|
|
922
|
-
stream(`${line}\n`);
|
|
923
|
-
fs.appendFileSync(outputFilesPath, `${line}\n`);
|
|
924
|
-
};
|
|
925
|
-
const quiet = this.argv.quiet;
|
|
926
|
-
return await new Promise((resolve, reject) => {
|
|
927
|
-
if (!quiet) {
|
|
928
|
-
cp.stdout?.pipe(split2()).on("data", (e) => outFunc(e, writeStreams.stdout.bind(writeStreams), (s) => chalk `{greenBright ${s}}`));
|
|
929
|
-
cp.stderr?.pipe(split2()).on("data", (e) => outFunc(e, writeStreams.stderr.bind(writeStreams), (s) => chalk `{redBright ${s}}`));
|
|
930
|
-
}
|
|
931
|
-
void cp.on("exit", (code) => {
|
|
932
|
-
clearTimeout(this._longRunningSilentTimeout);
|
|
933
|
-
return resolve(code ?? 0);
|
|
934
|
-
});
|
|
935
|
-
void cp.on("error", (err) => {
|
|
936
|
-
clearTimeout(this._longRunningSilentTimeout);
|
|
937
|
-
return reject(err);
|
|
938
|
-
});
|
|
939
|
-
if (imageName) {
|
|
940
|
-
cp.stdin?.end(". /gcl-cmd");
|
|
941
|
-
}
|
|
942
|
-
else {
|
|
943
|
-
cp.stdin?.end(`./${stateDir}/scripts/${safeJobName}_${this.jobId}`);
|
|
944
|
-
}
|
|
945
|
-
});
|
|
946
|
-
}
|
|
947
|
-
imageName(vars = {}) {
|
|
948
|
-
if (this.argv.forceShellExecutor) {
|
|
949
|
-
return null;
|
|
950
|
-
}
|
|
951
|
-
const image = this.jobData["image"];
|
|
952
|
-
if (!image) {
|
|
953
|
-
if (this.argv.shellExecutorNoImage) {
|
|
954
|
-
return null;
|
|
955
|
-
}
|
|
956
|
-
else {
|
|
957
|
-
// https://docs.gitlab.com/ee/ci/runners/hosted_runners/linux.html#container-images
|
|
958
|
-
return this.argv.defaultImage;
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
const expanded = Utils.expandVariables(vars);
|
|
962
|
-
const imageName = Utils.expandText(image.name, expanded);
|
|
963
|
-
return imageName.includes(":") ? imageName : `${imageName}:latest`;
|
|
964
|
-
}
|
|
965
|
-
imageUser(vars = {}) {
|
|
966
|
-
const image = this.jobData["image"];
|
|
967
|
-
if (!image)
|
|
968
|
-
return null;
|
|
969
|
-
if (!image["docker"])
|
|
970
|
-
return null;
|
|
971
|
-
return Utils.expandText(image["docker"]["user"], vars);
|
|
972
|
-
}
|
|
973
|
-
get imageEntrypoint() {
|
|
974
|
-
const image = this.jobData["image"];
|
|
975
|
-
if (!image?.entrypoint) {
|
|
976
|
-
return null;
|
|
977
|
-
}
|
|
978
|
-
assert(Array.isArray(image.entrypoint), "image:entrypoint must be an array");
|
|
979
|
-
return image.entrypoint;
|
|
980
|
-
}
|
|
981
|
-
async validateCiDependencyProxyServerAuthentication(imageName) {
|
|
982
|
-
const CI_DEPENDENCY_PROXY_SERVER = this._variables["CI_DEPENDENCY_PROXY_SERVER"];
|
|
983
|
-
if (!imageName.startsWith(CI_DEPENDENCY_PROXY_SERVER)) {
|
|
984
|
-
return;
|
|
985
|
-
}
|
|
986
|
-
try {
|
|
987
|
-
await Utils.spawn([this.argv.containerExecutable, "login", CI_DEPENDENCY_PROXY_SERVER]);
|
|
988
|
-
}
|
|
989
|
-
catch (e) {
|
|
990
|
-
const errMsg = `Please authenticate to the Dependency Proxy (${CI_DEPENDENCY_PROXY_SERVER}) https://docs.gitlab.com/ee/user/packages/dependency_proxy/#authenticate-with-the-dependency-proxy`;
|
|
991
|
-
if (this.argv.containerExecutable == "docker") {
|
|
992
|
-
assert(!e.stderr.includes("Cannot perform an interactive login"), errMsg);
|
|
993
|
-
}
|
|
994
|
-
else if (this.argv.containerExecutable == "podman") {
|
|
995
|
-
assert(!e.stderr.includes("Username: Error: getting username and password: reading username: EOF"), errMsg);
|
|
996
|
-
}
|
|
997
|
-
throw e;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
async pullImage(writeStreams, imageToPull) {
|
|
1001
|
-
const pullPolicy = this.argv.pullPolicy;
|
|
1002
|
-
const actualPull = async () => {
|
|
1003
|
-
await this.validateCiDependencyProxyServerAuthentication(imageToPull);
|
|
1004
|
-
const time = process.hrtime();
|
|
1005
|
-
await Utils.spawn([this.argv.containerExecutable, "pull", imageToPull]);
|
|
1006
|
-
const endTime = process.hrtime(time);
|
|
1007
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright pulled} ${imageToPull} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
1008
|
-
this.refreshLongRunningSilentTimeout(writeStreams);
|
|
1009
|
-
};
|
|
1010
|
-
if (pullPolicy === "always") {
|
|
1011
|
-
await actualPull();
|
|
1012
|
-
return;
|
|
1013
|
-
}
|
|
1014
|
-
try {
|
|
1015
|
-
await Utils.spawn([this.argv.containerExecutable, "image", "inspect", imageToPull]);
|
|
1016
|
-
}
|
|
1017
|
-
catch {
|
|
1018
|
-
await actualPull();
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
async initProducerReportsDotenvVariables(writeStreams, expanded) {
|
|
1022
|
-
const cwd = this.argv.cwd;
|
|
1023
|
-
const stateDir = this.argv.stateDir;
|
|
1024
|
-
const producers = this.producers;
|
|
1025
|
-
let producerReportsEnvs = {};
|
|
1026
|
-
for (const producer of producers ?? []) {
|
|
1027
|
-
const producerDotenv = Utils.expandText(producer.dotenv, expanded);
|
|
1028
|
-
if (producerDotenv === null)
|
|
1029
|
-
continue;
|
|
1030
|
-
const safeProducerName = Utils.safeDockerString(producer.name);
|
|
1031
|
-
const dotenvFolder = `${cwd}/${stateDir}/artifacts/${safeProducerName}/.gitlab-ci-reports/dotenv/`;
|
|
1032
|
-
if (await fs.pathExists(dotenvFolder)) {
|
|
1033
|
-
const dotenvFiles = (await Utils.spawn(["find", ".", "-type", "f"], dotenvFolder)).stdout.split("\n");
|
|
1034
|
-
for (const dotenvFile of dotenvFiles) {
|
|
1035
|
-
if (dotenvFile == "")
|
|
1036
|
-
continue;
|
|
1037
|
-
const producerReportEnv = dotenv.parse(await fs.readFile(`${dotenvFolder}/${dotenvFile}`));
|
|
1038
|
-
producerReportsEnvs = { ...producerReportsEnvs, ...producerReportEnv };
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
else {
|
|
1042
|
-
writeStreams.stderr(chalk `${this.formattedJobName} {yellow reports.dotenv produced by '${producer.name}' could not be found}\n`);
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
return producerReportsEnvs;
|
|
1046
|
-
}
|
|
1047
|
-
async copyCacheIn(writeStreams, expanded) {
|
|
1048
|
-
if (this.argv.mountCache && this.imageName(expanded))
|
|
1049
|
-
return;
|
|
1050
|
-
if ((!this.imageName(expanded) && !this.argv.shellIsolation) || this.cache.length === 0)
|
|
1051
|
-
return;
|
|
1052
|
-
const cwd = this.argv.cwd;
|
|
1053
|
-
const stateDir = this.argv.stateDir;
|
|
1054
|
-
for (const [index, c] of this.cache.entries()) {
|
|
1055
|
-
if (!["pull", "pull-push"].includes(c.policy))
|
|
1056
|
-
return;
|
|
1057
|
-
const time = process.hrtime();
|
|
1058
|
-
const cacheName = await this.getUniqueCacheName(cwd, expanded, index);
|
|
1059
|
-
const cacheFolder = `${cwd}/${stateDir}/cache/${cacheName}`;
|
|
1060
|
-
if (!await fs.pathExists(cacheFolder)) {
|
|
1061
|
-
continue;
|
|
1062
|
-
}
|
|
1063
|
-
await Mutex.exclusive(cacheName, async () => {
|
|
1064
|
-
await this.copyIn(cacheFolder);
|
|
1065
|
-
});
|
|
1066
|
-
const endTime = process.hrtime(time);
|
|
1067
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright imported cache '${cacheName}'} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
async copyArtifactsIn(writeStreams) {
|
|
1071
|
-
if ((!this.imageName(this._variables) && !this.argv.shellIsolation) || (this.producers ?? []).length === 0)
|
|
1072
|
-
return;
|
|
1073
|
-
const cwd = this.argv.cwd;
|
|
1074
|
-
const stateDir = this.argv.stateDir;
|
|
1075
|
-
const time = process.hrtime();
|
|
1076
|
-
const promises = [];
|
|
1077
|
-
for (const producer of this.producers ?? []) {
|
|
1078
|
-
const producerSafeName = Utils.safeDockerString(producer.name);
|
|
1079
|
-
const artifactFolder = `${cwd}/${stateDir}/artifacts/${producerSafeName}`;
|
|
1080
|
-
if (!await fs.pathExists(artifactFolder)) {
|
|
1081
|
-
await fs.mkdirp(artifactFolder);
|
|
1082
|
-
}
|
|
1083
|
-
const readdir = await fs.readdir(artifactFolder);
|
|
1084
|
-
if (readdir.length === 0) {
|
|
1085
|
-
writeStreams.stderr(chalk `${this.formattedJobName} {yellow artifacts from {blueBright ${producerSafeName}} was empty}\n`);
|
|
1086
|
-
}
|
|
1087
|
-
promises.push(this.copyIn(artifactFolder));
|
|
1088
|
-
}
|
|
1089
|
-
await Promise.all(promises);
|
|
1090
|
-
const endTime = process.hrtime(time);
|
|
1091
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright imported artifacts} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
1092
|
-
}
|
|
1093
|
-
copyIn(source) {
|
|
1094
|
-
const safeJobName = this.safeJobName;
|
|
1095
|
-
if (!this.imageName(this._variables) && this.argv.shellIsolation) {
|
|
1096
|
-
return Utils.spawn(["rsync", "-a", `${source}/.`, `${this.argv.cwd}/${this.argv.stateDir}/builds/${safeJobName}`]);
|
|
1097
|
-
}
|
|
1098
|
-
return Utils.spawn([this.argv.containerExecutable, "cp", `${source}/.`, `${this._containerId}:${this.ciProjectDir}`]);
|
|
1099
|
-
}
|
|
1100
|
-
async copyCacheOut(writeStreams, expanded) {
|
|
1101
|
-
if (this.argv.mountCache && this.imageName(expanded))
|
|
1102
|
-
return;
|
|
1103
|
-
if ((!this.imageName(expanded) && !this.argv.shellIsolation) || this.cache.length === 0)
|
|
1104
|
-
return;
|
|
1105
|
-
const cwd = this.argv.cwd;
|
|
1106
|
-
const stateDir = this.argv.stateDir;
|
|
1107
|
-
const cachePath = this.imageName(expanded) ? "/cache" : "../../cache";
|
|
1108
|
-
let time, endTime;
|
|
1109
|
-
for (const [index, c] of this.cache.entries()) {
|
|
1110
|
-
if (!["push", "pull-push"].includes(c.policy))
|
|
1111
|
-
return;
|
|
1112
|
-
if ("on_success" === c.when && this.jobStatus !== "success")
|
|
1113
|
-
return;
|
|
1114
|
-
if ("on_failure" === c.when && this.jobStatus === "success")
|
|
1115
|
-
return;
|
|
1116
|
-
const cacheName = await this.getUniqueCacheName(cwd, expanded, index);
|
|
1117
|
-
let paths = "";
|
|
1118
|
-
for (const path of c.paths) {
|
|
1119
|
-
if (!Utils.isSubpath(path, this.argv.cwd, this.argv.cwd))
|
|
1120
|
-
continue;
|
|
1121
|
-
paths += " " + Utils.expandText(path, expanded).replace(`${expanded.CI_PROJECT_DIR}/`, "");
|
|
1122
|
-
}
|
|
1123
|
-
time = process.hrtime();
|
|
1124
|
-
let cmd = "shopt -s globstar nullglob dotglob\n";
|
|
1125
|
-
cmd += `mkdir -p ${Utils.safeBashString(cachePath + "/" + cacheName)}\n`;
|
|
1126
|
-
cmd += `rsync -Ra ${paths} ${Utils.safeBashString(cachePath + "/" + cacheName + "/.")} || true\n`;
|
|
1127
|
-
await Mutex.exclusive(cacheName, async () => {
|
|
1128
|
-
await this.copyOut(cmd, stateDir, "cache", []);
|
|
1129
|
-
});
|
|
1130
|
-
endTime = process.hrtime(time);
|
|
1131
|
-
for (const __path of c.paths) {
|
|
1132
|
-
const _path = Utils.expandText(__path, expanded);
|
|
1133
|
-
if (!Utils.isSubpath(_path, this.argv.cwd, this.argv.cwd)) {
|
|
1134
|
-
writeStreams.stdout(chalk `{yellow WARNING: processPath: artifact path is not a subpath of project directory: ${_path}}\n`);
|
|
1135
|
-
continue;
|
|
1136
|
-
}
|
|
1137
|
-
let path = _path;
|
|
1138
|
-
if (isGlob(path) && !path.endsWith("*")) {
|
|
1139
|
-
path = `${path}/**`;
|
|
1140
|
-
}
|
|
1141
|
-
let numOfFiles = globbySync(path, {
|
|
1142
|
-
dot: true,
|
|
1143
|
-
onlyFiles: false,
|
|
1144
|
-
cwd: `${this.argv.cwd}/${stateDir}/cache/${cacheName}`,
|
|
1145
|
-
}).length;
|
|
1146
|
-
if (numOfFiles == 0) {
|
|
1147
|
-
writeStreams.stdout(chalk `{yellow WARNING: ${path}: no matching files. Ensure that the artifact path is relative to the working directory}\n`);
|
|
1148
|
-
continue;
|
|
1149
|
-
}
|
|
1150
|
-
if (!isGlob(path))
|
|
1151
|
-
numOfFiles++; // add one because the pattern itself is a folder
|
|
1152
|
-
writeStreams.stdout(`${_path}: found ${numOfFiles} artifact files and directories\n`);
|
|
1153
|
-
}
|
|
1154
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright cache created in '${stateDir}/cache/${cacheName}'} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
async copyArtifactsOut(writeStreams, expanded) {
|
|
1158
|
-
// TODO: update the condition to support when:on_success / when:on_failure
|
|
1159
|
-
if (this.jobStatus !== "success" && this.artifacts?.when !== "always")
|
|
1160
|
-
return;
|
|
1161
|
-
if (!this.artifacts)
|
|
1162
|
-
return;
|
|
1163
|
-
if ((this.artifacts.paths?.length ?? 0) === 0 && this.artifacts.reports?.dotenv == null)
|
|
1164
|
-
return;
|
|
1165
|
-
const safeJobName = this.safeJobName;
|
|
1166
|
-
const cwd = this.argv.cwd;
|
|
1167
|
-
const stateDir = this.argv.stateDir;
|
|
1168
|
-
let artifactsPath;
|
|
1169
|
-
if (!this.argv.shellIsolation && !this.imageName(expanded)) {
|
|
1170
|
-
artifactsPath = `${stateDir}/artifacts`;
|
|
1171
|
-
}
|
|
1172
|
-
else if (this.imageName(expanded)) {
|
|
1173
|
-
artifactsPath = "/artifacts";
|
|
1174
|
-
}
|
|
1175
|
-
else {
|
|
1176
|
-
artifactsPath = "../../artifacts";
|
|
1177
|
-
}
|
|
1178
|
-
let time, endTime;
|
|
1179
|
-
let cpCmd = "shopt -s globstar nullglob dotglob\n";
|
|
1180
|
-
cpCmd += `mkdir -p ${artifactsPath}/${safeJobName}\n`;
|
|
1181
|
-
cpCmd += "rsync --exclude '.gitlab-ci-local/**' -Ra ";
|
|
1182
|
-
for (const artifactExcludePath of this.artifacts?.exclude ?? []) {
|
|
1183
|
-
const expandedPath = Utils.expandText(artifactExcludePath, expanded).replace(`${expanded.CI_PROJECT_DIR}/`, "");
|
|
1184
|
-
cpCmd += `--exclude '${expandedPath}' `;
|
|
1185
|
-
}
|
|
1186
|
-
for (const artifactPath of this.artifacts?.paths ?? []) {
|
|
1187
|
-
const expandedPath = Utils.expandText(artifactPath, expanded).replace(`${expanded.CI_PROJECT_DIR}/`, "");
|
|
1188
|
-
cpCmd += `${expandedPath} `;
|
|
1189
|
-
}
|
|
1190
|
-
cpCmd += `${artifactsPath}/${safeJobName}/. || true\n`;
|
|
1191
|
-
const reportDotenv = Utils.expandText(this.artifacts.reports?.dotenv ?? null, expanded);
|
|
1192
|
-
const reportDotenvs = (typeof reportDotenv === "string") ? // normalize to string[] for easier handling
|
|
1193
|
-
[reportDotenv] :
|
|
1194
|
-
reportDotenv;
|
|
1195
|
-
if (reportDotenvs != null) {
|
|
1196
|
-
reportDotenvs.forEach((reportDotenv) => {
|
|
1197
|
-
cpCmd += `mkdir -p ${artifactsPath}/${safeJobName}/.gitlab-ci-reports/dotenv\n`;
|
|
1198
|
-
cpCmd += `if [ -f ${reportDotenv} ]; then\n`;
|
|
1199
|
-
cpCmd += ` rsync -Ra ${reportDotenv} ${artifactsPath}/${safeJobName}/.gitlab-ci-reports/dotenv/.\n`;
|
|
1200
|
-
cpCmd += "fi\n";
|
|
1201
|
-
});
|
|
1202
|
-
}
|
|
1203
|
-
time = process.hrtime();
|
|
1204
|
-
const dockerCmdExtras = this.argv.mountCache ? await this.mountCacheCmd(writeStreams, expanded) : [];
|
|
1205
|
-
await this.copyOut(cpCmd, stateDir, "artifacts", dockerCmdExtras);
|
|
1206
|
-
endTime = process.hrtime(time);
|
|
1207
|
-
for (const reportDotenv of reportDotenvs ?? []) {
|
|
1208
|
-
if (await fs.pathExists(`${cwd}/${stateDir}/artifacts/${safeJobName}/.gitlab-ci-reports/dotenv/${reportDotenv}`))
|
|
1209
|
-
continue;
|
|
1210
|
-
writeStreams.stderr(chalk `${this.formattedJobName} {yellow artifact reports dotenv '${reportDotenv}' could not be found}\n`);
|
|
1211
|
-
}
|
|
1212
|
-
const readdir = await fs.readdir(`${cwd}/${stateDir}/artifacts/${safeJobName}`);
|
|
1213
|
-
if (readdir.length === 0) {
|
|
1214
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {yellow !! no artifacts was copied !!}\n`);
|
|
1215
|
-
}
|
|
1216
|
-
else {
|
|
1217
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright exported artifacts} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
1218
|
-
}
|
|
1219
|
-
if (this.artifactsToSource && (this.argv.shellIsolation || this.imageName(expanded))) {
|
|
1220
|
-
time = process.hrtime();
|
|
1221
|
-
await Utils.spawn(["rsync", "--exclude=/.gitlab-ci-reports/", "-a", `${cwd}/${stateDir}/artifacts/${safeJobName}/.`, cwd]);
|
|
1222
|
-
if (reportDotenv != null) {
|
|
1223
|
-
await Utils.spawn(["rsync", "-a", `${cwd}/${stateDir}/artifacts/${safeJobName}/.gitlab-ci-reports/dotenv/.`, cwd]);
|
|
1224
|
-
}
|
|
1225
|
-
endTime = process.hrtime(time);
|
|
1226
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright copied artifacts to cwd} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
async copyOut(cmd, stateDir, type, dockerCmdExtras) {
|
|
1230
|
-
const safeJobName = this.safeJobName;
|
|
1231
|
-
const buildVolumeName = this.buildVolumeName;
|
|
1232
|
-
const cwd = this.argv.cwd;
|
|
1233
|
-
const helperImageName = this.argv.helperImage;
|
|
1234
|
-
await fs.mkdirp(`${cwd}/${stateDir}/${type}`);
|
|
1235
|
-
if (this.imageName(this._variables)) {
|
|
1236
|
-
const { stdout: containerId } = await Utils.bash(`${this.argv.containerExecutable} create -i ${dockerCmdExtras.join(" ")} -v ${buildVolumeName}:${this.ciProjectDir} -w ${this.ciProjectDir} ${helperImageName} bash -c "${cmd.replace(/"/g, "\\\"")}"`, cwd);
|
|
1237
|
-
this._containersToClean.push(containerId);
|
|
1238
|
-
await Utils.spawn([this.argv.containerExecutable, "start", containerId, "--attach"]);
|
|
1239
|
-
await Utils.spawn([this.argv.containerExecutable, "cp", `${containerId}:/${type}/.`, `${stateDir}/${type}/.`], cwd);
|
|
1240
|
-
}
|
|
1241
|
-
else if (this.argv.shellIsolation) {
|
|
1242
|
-
await Utils.bash(`bash -eo pipefail -c "${cmd}"`, `${cwd}/${stateDir}/builds/${safeJobName}`);
|
|
1243
|
-
}
|
|
1244
|
-
else if (!this.argv.shellIsolation) {
|
|
1245
|
-
await Utils.bash(`bash -eo pipefail -c "${cmd}"`, `${cwd}`);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
refreshLongRunningSilentTimeout(writeStreams) {
|
|
1249
|
-
clearTimeout(this._longRunningSilentTimeout);
|
|
1250
|
-
this._longRunningSilentTimeout = setTimeout(() => {
|
|
1251
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {grey > still running...}\n`);
|
|
1252
|
-
this.refreshLongRunningSilentTimeout(writeStreams);
|
|
1253
|
-
}, 10000);
|
|
1254
|
-
}
|
|
1255
|
-
getFinishedString() {
|
|
1256
|
-
return chalk `${this.formattedJobName} {magentaBright finished} in {magenta ${this.prettyDuration}}`;
|
|
1257
|
-
}
|
|
1258
|
-
printFinishedString() {
|
|
1259
|
-
if (this.jobStatus !== "success")
|
|
1260
|
-
return;
|
|
1261
|
-
this.writeStreams.stdout(`${this.getFinishedString()}\n`);
|
|
1262
|
-
}
|
|
1263
|
-
printExitedString(code) {
|
|
1264
|
-
const writeStreams = this.writeStreams;
|
|
1265
|
-
const finishedStr = this.getFinishedString();
|
|
1266
|
-
// Won't print if jobStatus is "success" because that will be printed via the `printFinishedString()`
|
|
1267
|
-
if (this.jobStatus === "warning") {
|
|
1268
|
-
writeStreams.stderr(chalk `${finishedStr} {black.bgYellowBright WARN ${code.toString()} }\n`);
|
|
1269
|
-
}
|
|
1270
|
-
else if (this.jobStatus === "failed") {
|
|
1271
|
-
writeStreams.stderr(chalk `${finishedStr} {black.bgRed FAIL ${code.toString()} }\n`);
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
printAfterScriptExitedString(code) {
|
|
1275
|
-
const writeStreams = this.writeStreams;
|
|
1276
|
-
const finishedStr = this.getFinishedString();
|
|
1277
|
-
if (code !== 0) {
|
|
1278
|
-
writeStreams.stderr(chalk `${finishedStr} {black.bgYellowBright WARN ${code.toString()} } after_script\n`);
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
async createDockerNetwork(networkName) {
|
|
1282
|
-
const { stdout: networkId } = await Utils.spawn([this.argv.containerExecutable, "network", "create", `${networkName}`]);
|
|
1283
|
-
this._serviceNetworkId = networkId;
|
|
1284
|
-
}
|
|
1285
|
-
async startService(writeStreams, expanded, service) {
|
|
1286
|
-
const cwd = this.argv.cwd;
|
|
1287
|
-
let dockerCmd = `${this.argv.containerExecutable} create --interactive `;
|
|
1288
|
-
this.refreshLongRunningSilentTimeout(writeStreams);
|
|
1289
|
-
if (this.argv.umask) {
|
|
1290
|
-
dockerCmd += "--user 0:0 ";
|
|
1291
|
-
}
|
|
1292
|
-
if (this.argv.userns != undefined) {
|
|
1293
|
-
dockerCmd += `--userns=${this.argv.userns} `;
|
|
1294
|
-
}
|
|
1295
|
-
if (this.argv.privileged) {
|
|
1296
|
-
dockerCmd += "--privileged ";
|
|
1297
|
-
}
|
|
1298
|
-
for (const device of this.argv.device) {
|
|
1299
|
-
dockerCmd += `--device ${device} `;
|
|
1300
|
-
}
|
|
1301
|
-
if (this.argv.ulimit !== null) {
|
|
1302
|
-
dockerCmd += `--ulimit nofile=${this.argv.ulimit} `;
|
|
1303
|
-
}
|
|
1304
|
-
for (const volume of this.argv.volume) {
|
|
1305
|
-
dockerCmd += `--volume ${volume} `;
|
|
1306
|
-
}
|
|
1307
|
-
for (const extraHost of this.argv.extraHost) {
|
|
1308
|
-
dockerCmd += `--add-host=${extraHost} `;
|
|
1309
|
-
}
|
|
1310
|
-
if (this.argv.caFile) {
|
|
1311
|
-
const caFilePath = path.isAbsolute(this.argv.caFile) ? this.argv.caFile : path.resolve(this.argv.cwd, this.argv.caFile);
|
|
1312
|
-
if (await fs.pathExists(caFilePath)) {
|
|
1313
|
-
dockerCmd += `--volume ${caFilePath}:/etc/ssl/certs/ca-certificates.crt:ro `;
|
|
1314
|
-
expanded["SSL_CERT_FILE"] = "/etc/ssl/certs/ca-certificates.crt";
|
|
1315
|
-
expanded["SSL_CERT_DIR"] = "/etc/ssl/certs";
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
const serviceAlias = service.alias;
|
|
1319
|
-
const serviceName = service.name;
|
|
1320
|
-
const serviceNameWithoutVersion = serviceName.replace(/(.*)(:.*)/, "$1");
|
|
1321
|
-
const aliases = new Set();
|
|
1322
|
-
aliases.add(serviceNameWithoutVersion.replaceAll("/", "-"));
|
|
1323
|
-
aliases.add(serviceNameWithoutVersion.replaceAll("/", "__"));
|
|
1324
|
-
if (serviceAlias) {
|
|
1325
|
-
aliases.add(serviceAlias);
|
|
1326
|
-
}
|
|
1327
|
-
for (const [key, val] of Object.entries(expanded)) {
|
|
1328
|
-
// Replacing `'` with `'\''` to correctly handle single quotes(if `val` contains `'`) in shell commands
|
|
1329
|
-
dockerCmd += ` -e '${key}=${val.toString().replace(/'/g, "'\\''")}' \\\n`;
|
|
1330
|
-
}
|
|
1331
|
-
const serviceEntrypoint = service.entrypoint;
|
|
1332
|
-
if (serviceEntrypoint) {
|
|
1333
|
-
dockerCmd += `--entrypoint ${Utils.safeBashString(serviceEntrypoint[0])} `;
|
|
1334
|
-
}
|
|
1335
|
-
dockerCmd += `--volume ${this.buildVolumeName}:${this.ciProjectDir} `;
|
|
1336
|
-
dockerCmd += `--volume ${this.tmpVolumeName}:${this.fileVariablesDir} `;
|
|
1337
|
-
// The default podman network mode is not `bridge`, which means a `podman network connect` call will fail
|
|
1338
|
-
// when connecting user defined networks. The workaround is to use a user defined network on container
|
|
1339
|
-
// creation.
|
|
1340
|
-
//
|
|
1341
|
-
// See https://github.com/containers/podman/issues/19577
|
|
1342
|
-
dockerCmd += `--network ${this._serviceNetworkId} `;
|
|
1343
|
-
for (const alias of aliases) {
|
|
1344
|
-
dockerCmd += `--network-alias ${alias} `;
|
|
1345
|
-
}
|
|
1346
|
-
dockerCmd += `${serviceName} `;
|
|
1347
|
-
if (serviceEntrypoint?.length ?? 0 > 1) {
|
|
1348
|
-
serviceEntrypoint?.slice(1).forEach((e) => {
|
|
1349
|
-
dockerCmd += `${Utils.safeBashString(e)} `;
|
|
1350
|
-
});
|
|
1351
|
-
}
|
|
1352
|
-
(service.command ?? []).forEach((e) => dockerCmd += `"${e.replace(/\$/g, "\\$")}" `);
|
|
1353
|
-
const time = process.hrtime();
|
|
1354
|
-
const { stdout: containerId } = await Utils.bash(dockerCmd, cwd);
|
|
1355
|
-
this._containersToClean.push(containerId);
|
|
1356
|
-
for (const network of this.argv.network) {
|
|
1357
|
-
await Utils.spawn([this.argv.containerExecutable, "network", "connect", network, `${containerId}`]);
|
|
1358
|
-
}
|
|
1359
|
-
await Utils.spawn([this.argv.containerExecutable, "start", `${containerId}`]);
|
|
1360
|
-
const endTime = process.hrtime(time);
|
|
1361
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright started service image: ${serviceName} with aliases: ${Array.from(aliases).join(", ")}} in {magenta ${prettyHrtime(endTime)}}\n`);
|
|
1362
|
-
return containerId;
|
|
1363
|
-
}
|
|
1364
|
-
async serviceHealthCheck(writeStreams, service, serviceIndex, serviceContainerLogFile) {
|
|
1365
|
-
const serviceAlias = service.alias;
|
|
1366
|
-
const serviceName = service.name;
|
|
1367
|
-
const waitImageName = this.argv.waitImage;
|
|
1368
|
-
const { stdout } = await Utils.spawn([this.argv.containerExecutable, "image", "inspect", serviceName]);
|
|
1369
|
-
const imageInspect = JSON.parse(stdout);
|
|
1370
|
-
// Copied from the startService block. Important thing is that the aliases match
|
|
1371
|
-
const serviceNameWithoutVersion = serviceName.replace(/(.*)(:.*)/, "$1");
|
|
1372
|
-
const aliases = [serviceNameWithoutVersion.replaceAll("/", "-"), serviceNameWithoutVersion.replaceAll("/", "__")];
|
|
1373
|
-
if (serviceAlias) {
|
|
1374
|
-
aliases.push(serviceAlias);
|
|
1375
|
-
}
|
|
1376
|
-
const uniqueAlias = aliases[aliases.length - 1];
|
|
1377
|
-
if ((imageInspect[0]?.Config?.ExposedPorts ?? null) === null) {
|
|
1378
|
-
return writeStreams.stderr(chalk `${this.formattedJobName} {yellow Could not find exposed tcp ports ${serviceName}}\n`);
|
|
1379
|
-
}
|
|
1380
|
-
const time = process.hrtime();
|
|
1381
|
-
try {
|
|
1382
|
-
// Iterate over each port defined in the image, and try to connect to the alias
|
|
1383
|
-
await Promise.any(Object.keys(imageInspect[0].Config.ExposedPorts).map((port) => {
|
|
1384
|
-
if (!port.endsWith("/tcp"))
|
|
1385
|
-
return;
|
|
1386
|
-
const portNum = parseInt(port.replace("/tcp", ""));
|
|
1387
|
-
const containerName = `gcl-wait-for-it-${this.jobId}-${serviceIndex}-${portNum}`;
|
|
1388
|
-
const spawnCmd = [this.argv.containerExecutable, "run", "--rm", `--name=${containerName}`, "--network", `${this._serviceNetworkId}`, `${waitImageName}`, `${uniqueAlias}:${portNum}`, "-t", "30"];
|
|
1389
|
-
this._containersToClean.push(containerName);
|
|
1390
|
-
return Utils.spawn(spawnCmd);
|
|
1391
|
-
}));
|
|
1392
|
-
const endTime = process.hrtime(time);
|
|
1393
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {greenBright service image: ${serviceName} healthcheck passed in {green ${prettyHrtime(endTime)}}}\n`);
|
|
1394
|
-
}
|
|
1395
|
-
catch (e) {
|
|
1396
|
-
if (!(e instanceof AggregateError))
|
|
1397
|
-
throw e;
|
|
1398
|
-
e.errors.forEach((singleError) => {
|
|
1399
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {redBright service image: ${serviceName} healthcheck failed}\n`);
|
|
1400
|
-
singleError.message.split(/\r?\n/g).forEach((line) => {
|
|
1401
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {redBright ${line}}\n`);
|
|
1402
|
-
});
|
|
1403
|
-
writeStreams.stdout(chalk `${this.formattedJobName} {redBright also see (${serviceContainerLogFile})}\n`);
|
|
1404
|
-
});
|
|
1405
|
-
}
|
|
1406
|
-
finally {
|
|
1407
|
-
// Kill all wait-for-it containers, when one have been successful
|
|
1408
|
-
await Promise.allSettled(Object.keys(imageInspect[0].Config.ExposedPorts).map((port) => {
|
|
1409
|
-
if (!port.endsWith("/tcp"))
|
|
1410
|
-
return;
|
|
1411
|
-
const portNum = parseInt(port.replace("/tcp", ""));
|
|
1412
|
-
return Utils.spawn([this.argv.containerExecutable, "rm", "-vf", `gcl-wait-for-it-${this.jobId}-${serviceIndex}-${portNum}`]);
|
|
1413
|
-
}));
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
async fetchTriggerInclude() {
|
|
1417
|
-
const { cwd, stateDir } = this.argv;
|
|
1418
|
-
fs.mkdirpSync(`${cwd}/${stateDir}/includes/triggers`);
|
|
1419
|
-
let contents = {};
|
|
1420
|
-
for (const include of this.jobData.trigger?.include ?? []) {
|
|
1421
|
-
if (include["local"]) {
|
|
1422
|
-
const expandedInclude = Utils.expandText(include["local"], this._variables);
|
|
1423
|
-
validateIncludeLocal(expandedInclude);
|
|
1424
|
-
const files = await resolveIncludeLocal(expandedInclude, cwd);
|
|
1425
|
-
if (files.length == 0) {
|
|
1426
|
-
throw new AssertionError({ message: `Local include file \`${include["local"]}\` specified in \`.${this.name}\` cannot be found!` });
|
|
1427
|
-
}
|
|
1428
|
-
for (const file of files) {
|
|
1429
|
-
const content = await Parser.loadYaml(file, {});
|
|
1430
|
-
contents = {
|
|
1431
|
-
...contents,
|
|
1432
|
-
...content,
|
|
1433
|
-
};
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
else if (include["artifact"]) {
|
|
1437
|
-
const content = await Parser.loadYaml(`${cwd}/${stateDir}/artifacts/${include["job"]}/${include["artifact"]}`, {});
|
|
1438
|
-
contents = {
|
|
1439
|
-
...contents,
|
|
1440
|
-
...content,
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1443
|
-
else if (include["project"]) {
|
|
1444
|
-
this.writeStreams.memoStdout(chalk `{bgYellowBright WARN } \`{blueBright ${this.name}.trigger.include.*.project}\` will be no-op. It is currently not implemented\n`);
|
|
1445
|
-
}
|
|
1446
|
-
else if (include["template"]) {
|
|
1447
|
-
this.writeStreams.memoStdout(chalk `{bgYellowBright WARN } \`{blueBright ${this.name}.trigger.include.*.template}\` will be no-op. It is currently not implemented\n`);
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
const target = `${cwd}/${stateDir}/includes/triggers/${this.name}.yml`;
|
|
1451
|
-
fs.writeFileSync(target, yaml.dump(contents));
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
export async function cleanupJobResources(jobs) {
|
|
1455
|
-
if (!jobs)
|
|
1456
|
-
return;
|
|
1457
|
-
const promises = [];
|
|
1458
|
-
for (const job of jobs) {
|
|
1459
|
-
promises.push(job.cleanupResources());
|
|
1460
|
-
}
|
|
1461
|
-
await Promise.all(promises);
|
|
1462
|
-
}
|
|
1463
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiam9iLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ25DLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUMxQixPQUFPLFlBQVksTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFHakMsT0FBTyxNQUFNLEVBQUUsRUFBQyxjQUFjLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFDOUMsT0FBTyxFQUFDLEtBQUssRUFBQyxNQUFNLFlBQVksQ0FBQztBQUVqQyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFMUIsT0FBTyxFQUFDLDJCQUEyQixFQUFFLDZCQUE2QixFQUFFLHdCQUF3QixFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDeEgsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUNyQyxPQUFPLEtBQUssSUFBSSxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sYUFBYSxDQUFDO0FBQ25DLE9BQU8sRUFBQyxtQkFBbUIsRUFBRSxvQkFBb0IsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQy9FLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFDbEMsT0FBTyxZQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBRTdCLE1BQU0sNEJBQTRCLEdBQUcsNkJBQTZCLENBQUM7QUEwQ25FLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsSUFBSSxD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QkFDWCxHQUFHLE9BQU87aUJBQ2IsQ0FBQztZQUNOLENBQUM7aUJBQU0sSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFBLHlDQUF5QyxJQUFJLENBQUMsSUFBSSxnRkFBZ0YsQ0FBQyxDQUFDO1lBRTFLLENBQUM7aUJBQU0sSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztnQkFDN0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFBLHlDQUF5QyxJQUFJLENBQUMsSUFBSSxpRkFBaUYsQ0FBQyxDQUFDO1lBQzNLLENBQUM7UUFDTCxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsR0FBRyxHQUFHLElBQUksUUFBUSxzQkFBc0IsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDO1FBQ3ZFLEVBQUUsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNsRCxDQUFDOztBQUdMLE1BQU0sQ0FBQyxLQUFLLFVBQVUsbUJBQW1CLENBQUUsSUFBb0I7SUFDM0QsSUFBSSxDQUFDLElBQUk7UUFBRSxPQUFPO0lBQ2xCLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUNwQixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3JCLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ2hDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrLXRlbXBsYXRlXCI7XG5pbXBvcnQgKiBhcyBkb3RlbnYgZnJvbSBcImRvdGVudlwiO1xuaW1wb3J0IGZzIGZyb20gXCJmcy1leHRyYVwiO1xuaW1wb3J0IHByZXR0eUhydGltZSBmcm9tIFwicHJldHR5LWhydGltZVwiO1xuaW1wb3J0IHNwbGl0MiBmcm9tIFwic3BsaXQyXCI7XG5pbXBvcnQge1V0aWxzfSBmcm9tIFwiLi91dGlscy5qc1wiO1xuaW1wb3J0IHtXcml0ZVN0cmVhbXN9IGZyb20gXCIuL3dyaXRlLXN0cmVhbXMuanNcIjtcbmltcG9ydCB7R2l0RGF0YX0gZnJvbSBcIi4vZ2l0LWRhdGEuanNcIjtcbmltcG9ydCBhc3NlcnQsIHtBc3NlcnRpb25FcnJvcn0gZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHtNdXRleH0gZnJvbSBcIi4vbXV0ZXguanNcIjtcbmltcG9ydCB7QXJndn0gZnJvbSBcIi4vYXJndi5qc1wiO1xuaW1wb3J0IGV4ZWNhIGZyb20gXCJleGVjYVwiO1xuaW1wb3J0IHtDSUNEVmFyaWFibGV9IGZyb20gXCIuL3ZhcmlhYmxlcy1mcm9tLWZpbGVzLmpzXCI7XG5pbXBvcnQge0dpdGxhYlJ1bm5lckNQVXNQcmVzZXRWYWx1ZSwgR2l0bGFiUnVubmVyTWVtb3J5UHJlc2V0VmFsdWUsIEdpdGxhYlJ1bm5lclByZXNldFZhbHVlc30gZnJvbSBcIi4vZ2l0bGFiLXByZXNldC5qc1wiO1xuaW1wb3J0IHtoYW5kbGVyfSBmcm9tIFwiLi9oYW5kbGVyLmpzXCI7XG5pbXBvcnQgKiBhcyB5YW1sIGZyb20gXCJqcy15YW1sXCI7XG5pbXBvcnQge1BhcnNlcn0gZnJvbSBcIi4vcGFyc2VyLmpzXCI7XG5pbXBvcnQge3Jlc29sdmVJbmNsdWRlTG9jYWwsIHZhbGlkYXRlSW5jbHVkZUxvY2FsfSBmcm9tIFwiLi9wYXJzZXItaW5jbHVkZXMuanNcIjtcbmltcG9ydCB7Z2xvYmJ5U3luY30gZnJvbSBcImdsb2JieVwiO1xuaW1wb3J0IHRlcm1pbmFsTGluayBmcm9tIFwidGVybWluYWwtbGlua1wiO1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gXCJjcnlwdG9cIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcblxuY29uc3QgR0NMX1NIRUxMX1BST01QVF9QTEFDRUhPTERFUiA9IFwiPGdjbFNoZWxsUHJvbXB0UGxhY2Vob2xkZXI+XCI7XG5pbnRlcmZhY2UgSm9iT3B0aW9ucyB7XG4gICAgYXJndjogQXJndjtcbiAgICB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcztcbiAgICBkYXRhOiBhbnk7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGJhc2VOYW1lOiBzdHJpbmc7XG4gICAgcGlwZWxpbmVJaWQ6IG51bWJlcjtcbiAgICBnaXREYXRhOiBHaXREYXRhO1xuICAgIGdsb2JhbFZhcmlhYmxlczoge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9O1xuICAgIHZhcmlhYmxlc0Zyb21GaWxlczoge1tuYW1lOiBzdHJpbmddOiBDSUNEVmFyaWFibGV9O1xuICAgIHByZWRlZmluZWRWYXJpYWJsZXM6IHtbbmFtZTogc3RyaW5nXTogYW55fTtcbiAgICBtYXRyaXhWYXJpYWJsZXM6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9IHwgbnVsbDtcbiAgICBub2RlSW5kZXg6IG51bWJlciB8IG51bGw7XG4gICAgbm9kZXNUb3RhbDogbnVtYmVyO1xuICAgIGV4cGFuZFZhcmlhYmxlczogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIENhY2hlIHtcbiAgICBwb2xpY3k6IFwicHVsbFwiIHwgXCJwdWxsLXB1c2hcIiB8IFwicHVzaFwiO1xuICAgIGtleTogc3RyaW5nIHwge2ZpbGVzOiBzdHJpbmdbXX07XG4gICAgcGF0aHM6IHN0cmluZ1tdO1xuICAgIHdoZW46IFwib25fc3VjY2Vzc1wiIHwgXCJvbl9mYWlsdXJlXCIgfCBcImFsd2F5c1wiO1xufVxuXG5pbnRlcmZhY2UgU2VydmljZSB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGVudHJ5cG9pbnQ6IHN0cmluZ1tdIHwgbnVsbDtcbiAgICBjb21tYW5kOiBzdHJpbmdbXSB8IG51bGw7XG4gICAgYWxpYXM6IHN0cmluZyB8IG51bGw7XG4gICAgdmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ307XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmVlZCB7XG4gICAgam9iOiBzdHJpbmc7XG4gICAgYXJ0aWZhY3RzOiBib29sZWFuO1xuICAgIG9wdGlvbmFsPzogYm9vbGVhbjtcbiAgICByZWY/OiBzdHJpbmc7XG4gICAgcGlwZWxpbmU/OiBzdHJpbmc7XG4gICAgcHJvamVjdD86IHN0cmluZztcbn1cblxuY29uc3QgaXNHbG9iID0gKHN0cjogc3RyaW5nKSA9PiAvWyo/e30ofClbXFxdXS8udGVzdChzdHIpO1xuXG5jb25zdCBkYXRlRm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQodW5kZWZpbmVkLCB7XG4gICAgeWVhcjogdW5kZWZpbmVkLFxuICAgIG1vbnRoOiB1bmRlZmluZWQsXG4gICAgaG91cjogXCJudW1lcmljXCIsXG4gICAgbWludXRlOiBcIm51bWVyaWNcIixcbiAgICBzZWNvbmQ6IFwibnVtZXJpY1wiLFxuICAgIGhvdXIxMjogZmFsc2UsXG59KTtcblxuZXhwb3J0IHR5cGUgSm9iUnVsZSA9IHtcbiAgICBpZj86IHN0cmluZztcbiAgICB3aGVuPzogc3RyaW5nO1xuICAgIGNoYW5nZXM/OiBzdHJpbmdbXSB8IHtwYXRoczogc3RyaW5nW119O1xuICAgIGV4aXN0cz86IHN0cmluZ1tdO1xuICAgIGFsbG93X2ZhaWx1cmU/OiBib29sZWFuO1xuICAgIHZhcmlhYmxlcz86IHtbbmFtZTogc3RyaW5nXTogc3RyaW5nfTtcbiAgICBuZWVkcz86IGFueVtdO1xufTtcblxuZXhwb3J0IGNsYXNzIEpvYiB7XG4gICAgcHJpdmF0ZSBnZW5lcmF0ZUpvYklkICgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMDAwMCk7XG4gICAgfVxuXG4gICAgc3RhdGljIHJlYWRvbmx5IGlsbGVnYWxKb2JOYW1lcyA9IG5ldyBTZXQoW1xuICAgICAgICBcImluY2x1ZGVcIiwgXCJsb2NhbF9jb25maWd1cmF0aW9uXCIsIFwiaW1hZ2VcIiwgXCJzZXJ2aWNlc1wiLFxuICAgICAgICBcInN0YWdlc1wiLCBcImJlZm9yZV9zY3JpcHRcIiwgXCJkZWZhdWx0XCIsXG4gICAgICAgIFwiYWZ0ZXJfc2NyaXB0XCIsIFwidmFyaWFibGVzXCIsIFwiY2FjaGVcIiwgXCJ3b3JrZmxvd1wiLCBcInBhZ2U6ZGVwbG95XCIsXG4gICAgXSk7XG5cbiAgICByZWFkb25seSBhcmd2OiBBcmd2O1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgICByZWFkb25seSBiYXNlTmFtZTogc3RyaW5nO1xuICAgIHJlYWRvbmx5IGRlcGVuZGVuY2llczogc3RyaW5nW10gfCBudWxsO1xuICAgIHJlYWRvbmx5IGVudmlyb25tZW50Pzoge25hbWU6IHN0cmluZzsgdXJsOiBzdHJpbmcgfCBudWxsOyBkZXBsb3ltZW50X3RpZXI6IHN0cmluZyB8IG51bGw7IGFjdGlvbjogc3RyaW5nIHwgbnVsbH07XG4gICAgcmVhZG9ubHkgam9iSWQ6IG51bWJlcjtcbiAgICByZWFkb25seSBydWxlcz86IEpvYlJ1bGVbXTtcblxuICAgIHJlYWRvbmx5IGFsbG93RmFpbHVyZTogYm9vbGVhbiB8IHtcbiAgICAgICAgZXhpdF9jb2RlczogbnVtYmVyIHwgbnVtYmVyW107XG4gICAgfTtcbiAgICByZWFkb25seSB3aGVuOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgZXhpc3RzOiBzdHJpbmdbXTtcbiAgICByZWFkb25seSBwaXBlbGluZUlpZDogbnVtYmVyO1xuICAgIHJlYWRvbmx5IGdpdERhdGE6IEdpdERhdGE7XG4gICAgcmVhZG9ubHkgaW5oZXJpdDoge1xuICAgICAgICB2YXJpYWJsZXM/OiBib29sZWFuIHwgc3RyaW5nW107XG4gICAgfTtcblxuICAgIHByaXZhdGUgX2RvdGVudlZhcmlhYmxlczoge1trZXk6IHN0cmluZ106IHN0cmluZ30gPSB7fTtcbiAgICBwcml2YXRlIF9wcmVzY3JpcHRzRXhpdENvZGU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2FmdGVyU2NyaXB0c0V4aXRDb2RlID0gMDtcbiAgICBwcml2YXRlIF9jb3ZlcmFnZVBlcmNlbnQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX3J1bm5pbmcgPSBmYWxzZTtcbiAgICBwcml2YXRlIF9jb250YWluZXJJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfc2VydmljZU5ldHdvcmtJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfbG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0OiBOb2RlSlMuVGltZW91dCA9IC0xIGFzIGFueTtcbiAgICBwcml2YXRlIF9wcm9kdWNlcnM6IHtuYW1lOiBzdHJpbmc7IGRvdGVudjogc3RyaW5nIHwgbnVsbH1bXSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2pvYk5hbWVQYWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2NpUHJvamVjdERpcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfc3RhcnRUaW1lPzogW251bWJlciwgbnVtYmVyXTtcbiAgICBwcml2YXRlIF9lbmRUaW1lPzogW251bWJlciwgbnVtYmVyXTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2ZpbGVzVG9SbTogc3RyaW5nW10gPSBbXTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9nbG9iYWxWYXJpYWJsZXM6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9ID0ge307XG4gICAgcHJpdmF0ZSByZWFkb25seSBfdmFyaWFibGVzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSA9IHt9O1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NvbnRhaW5lcnNUb0NsZWFuOiBzdHJpbmdbXSA9IFtdO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NvbnRhaW5lclZvbHVtZU5hbWVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgam9iRGF0YTogYW55O1xuICAgIHByaXZhdGUgcmVhZG9ubHkgd3JpdGVTdHJlYW1zOiBXcml0ZVN0cmVhbXM7XG5cbiAgICBjb25zdHJ1Y3RvciAob3B0OiBKb2JPcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGpvYkRhdGEgPSBvcHQuZGF0YTtcbiAgICAgICAgY29uc3Qgam9iVmFyaWFibGVzID0gam9iRGF0YS52YXJpYWJsZXMgPz8ge307XG4gICAgICAgIGNvbnN0IHZhcmlhYmxlc0Zyb21GaWxlcyA9IG9wdC52YXJpYWJsZXNGcm9tRmlsZXM7XG4gICAgICAgIGNvbnN0IGFyZ3YgPSBvcHQuYXJndjtcbiAgICAgICAgY29uc3QgY3dkID0gYXJndi5jd2Q7XG4gICAgICAgIGNvbnN0IGFyZ3ZWYXJpYWJsZXMgPSBhcmd2LnZhcmlhYmxlO1xuICAgICAgICBjb25zdCBleHBhbmRWYXJpYWJsZXMgPSBvcHQuZXhwYW5kVmFyaWFibGVzID8/IHRydWU7XG5cbiAgICAgICAgdGhpcy5hcmd2ID0gYXJndjtcbiAgICAgICAgdGhpcy53cml0ZVN0cmVhbXMgPSBvcHQud3JpdGVTdHJlYW1zO1xuICAgICAgICB0aGlzLmdpdERhdGEgPSBvcHQuZ2l0RGF0YTtcbiAgICAgICAgdGhpcy5uYW1lID0gb3B0Lm5hbWU7XG4gICAgICAgIHRoaXMuYmFzZU5hbWUgPSBvcHQuYmFzZU5hbWU7XG4gICAgICAgIHRoaXMuam9iSWQgPSB0aGlzLmdlbmVyYXRlSm9iSWQoKTtcbiAgICAgICAgdGhpcy5qb2JEYXRhID0gb3B0LmRhdGE7XG4gICAgICAgIHRoaXMucGlwZWxpbmVJaWQgPSBvcHQucGlwZWxpbmVJaWQ7XG4gICAgICAgIHRoaXMuX2dsb2JhbFZhcmlhYmxlcyA9IG9wdC5nbG9iYWxWYXJpYWJsZXM7XG5cbiAgICAgICAgdGhpcy5pbmhlcml0ID0ge307XG4gICAgICAgIHRoaXMuaW5oZXJpdC52YXJpYWJsZXMgPSB0aGlzLmpvYkRhdGEuaW5oZXJpdD8udmFyaWFibGVzID8/IHRydWU7XG5cbiAgICAgICAgdGhpcy53aGVuID0gam9iRGF0YS53aGVuIHx8IFwib25fc3VjY2Vzc1wiO1xuICAgICAgICB0aGlzLmV4aXN0cyA9IGpvYkRhdGEuZXhpc3RzIHx8IFtdO1xuICAgICAgICB0aGlzLmFsbG93RmFpbHVyZSA9IGpvYkRhdGEuYWxsb3dfZmFpbHVyZSA/PyBmYWxzZTtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBqb2JEYXRhLmRlcGVuZGVuY2llcyB8fCBudWxsO1xuICAgICAgICB0aGlzLnJ1bGVzID0gam9iRGF0YS5ydWxlcyB8fCBudWxsO1xuICAgICAgICB0aGlzLmVudmlyb25tZW50ID0gdHlwZW9mIGpvYkRhdGEuZW52aXJvbm1lbnQgPT09IFwic3RyaW5nXCIgPyB7bmFtZTogam9iRGF0YS5lbnZpcm9ubWVudH0gOiAoam9iRGF0YS5lbnZpcm9ubWVudCA/IHsuLi5qb2JEYXRhLmVudmlyb25tZW50fSA6IGpvYkRhdGEuZW52aXJvbm1lbnQpO1xuXG4gICAgICAgIGNvbnN0IG1hdHJpeFZhcmlhYmxlcyA9IG9wdC5tYXRyaXhWYXJpYWJsZXMgPz8ge307XG4gICAgICAgIGNvbnN0IGZpbGVWYXJpYWJsZXMgPSBVdGlscy5maW5kRW52TWF0Y2hlZFZhcmlhYmxlcyh2YXJpYWJsZXNGcm9tRmlsZXMsIHRoaXMuZmlsZVZhcmlhYmxlc0Rpcik7XG4gICAgICAgIGNvbnN0IHByZWRlZmluZWRWYXJpYWJsZXMgPSB0aGlzLl9wcmVkZWZpbmVkVmFyaWFibGVzKG9wdCk7XG4gICAgICAgIHRoaXMuX3ZhcmlhYmxlcyA9IHsuLi5wcmVkZWZpbmVkVmFyaWFibGVzLCAuLi50aGlzLmdsb2JhbFZhcmlhYmxlcywgLi4uam9iVmFyaWFibGVzLCAuLi5tYXRyaXhWYXJpYWJsZXMsIC4uLmZpbGVWYXJpYWJsZXMsIC4uLmFyZ3ZWYXJpYWJsZXN9O1xuXG4gICAgICAgIGlmICh0aGlzLnJ1bGVzICYmIGV4cGFuZFZhcmlhYmxlcykge1xuICAgICAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKTtcblxuICAgICAgICAgICAgLy8gRXhwYW5kIHZhcmlhYmxlcyBpbiBydWxlczpjaGFuZ2VzXG4gICAgICAgICAgICB0aGlzLnJ1bGVzLmZvckVhY2goKHJ1bGUsIHJ1bGVJZHgsIHJ1bGVzKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2hhbmdlcyA9IEFycmF5LmlzQXJyYXkocnVsZS5jaGFuZ2VzKSA/IHJ1bGUuY2hhbmdlcyA6IHJ1bGUuY2hhbmdlcz8ucGF0aHM7XG4gICAgICAgICAgICAgICAgaWYgKCFjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjaGFuZ2VzLmZvckVhY2goKGNoYW5nZSwgY2hhbmdlSWR4LCBjaGFuZ2VzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZXNbY2hhbmdlSWR4XSA9IFV0aWxzLmV4cGFuZFRleHQoY2hhbmdlLCBleHBhbmRlZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcnVsZXNbcnVsZUlkeF0uY2hhbmdlcyA9IGNoYW5nZXM7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gRXhwYW5kIHZhcmlhYmxlcyBpbiBydWxlczpleGlzdHNcbiAgICAgICAgICAgIHRoaXMucnVsZXMuZm9yRWFjaCgocnVsZSwgcnVsZUlkeCwgcnVsZXMpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBleGlzdHMgPSBBcnJheS5pc0FycmF5KHJ1bGUuZXhpc3RzKSA/IHJ1bGUuZXhpc3RzIDogbnVsbDtcbiAgICAgICAgICAgICAgICBpZiAoIWV4aXN0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGV4aXN0cy5mb3JFYWNoKChleGlzdCwgZXhpc3RJZCwgZXhpc3RzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGV4aXN0c1tleGlzdElkXSA9IFV0aWxzLmV4cGFuZFRleHQoZXhpc3QsIGV4cGFuZGVkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBydWxlc1tydWxlSWR4XS5leGlzdHMgPSBleGlzdHM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBydWxlVmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30gfCB1bmRlZmluZWQ7XG4gICAgICAgIC8vIFNldCB7d2hlbiwgYWxsb3dGYWlsdXJlfSBiYXNlZCBvbiBydWxlcyByZXN1bHRcbiAgICAgICAgaWYgKHRoaXMucnVsZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJ1bGVSZXN1bHQgPSBVdGlscy5nZXRSdWxlc1Jlc3VsdCh7YXJndiwgY3dkLCBydWxlczogdGhpcy5ydWxlcywgdmFyaWFibGVzOiB0aGlzLl92YXJpYWJsZXN9LCB0aGlzLmdpdERhdGEsIHRoaXMud2hlbiwgdGhpcy5hbGxvd0ZhaWx1cmUpO1xuICAgICAgICAgICAgdGhpcy53aGVuID0gcnVsZVJlc3VsdC53aGVuO1xuICAgICAgICAgICAgdGhpcy5hbGxvd0ZhaWx1cmUgPSBydWxlUmVzdWx0LmFsbG93RmFpbHVyZTtcbiAgICAgICAgICAgIHJ1bGVWYXJpYWJsZXMgPSBydWxlUmVzdWx0LnZhcmlhYmxlcztcbiAgICAgICAgICAgIGlmIChydWxlUmVzdWx0Lm5lZWRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5qb2JEYXRhW1wibmVlZHNcIl0gPSBydWxlUmVzdWx0Lm5lZWRzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdmFyaWFibGVzID0gey4uLnRoaXMuX3ZhcmlhYmxlcywgLi4ucnVsZVZhcmlhYmxlcywgLi4uYXJndlZhcmlhYmxlc307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaW5kIGVudmlyb25tZW50IG1hdGNoZWQgdmFyaWFibGVzXG4gICAgICAgIGlmICh0aGlzLmVudmlyb25tZW50ICYmIGV4cGFuZFZhcmlhYmxlcykge1xuICAgICAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKTtcbiAgICAgICAgICAgIGNvbnN0IGVudk5hbWVCZWZvcmVFeHBhbnNpb24gPSB0aGlzLmVudmlyb25tZW50Lm5hbWU7XG4gICAgICAgICAgICB0aGlzLmVudmlyb25tZW50Lm5hbWUgPSBVdGlscy5leHBhbmRUZXh0KHRoaXMuZW52aXJvbm1lbnQubmFtZSwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQubmFtZSAhPT0gZW52TmFtZUJlZm9yZUV4cGFuc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlZ2VuZXJhdGUgQ0lfRU5WSVJPTk1FTlRfU0xVRyBiYXNlZCBvbiBlbnYgbmFtZSBpZiBpdCBjaGFuZ2VkIGFmdGVyIGV4cGFuc2lvblxuICAgICAgICAgICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9TTFVHXCJdID0gdGhpcy5fZ2VuZXJhdGVFbnZpcm9ubWVudFNsdWcodGhpcy5lbnZpcm9ubWVudC5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW52aXJvbm1lbnQudXJsID0gVXRpbHMuZXhwYW5kVGV4dCh0aGlzLmVudmlyb25tZW50LnVybCwgZXhwYW5kZWQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGVudk1hdGNoZWRWYXJpYWJsZXMgPSBVdGlscy5maW5kRW52TWF0Y2hlZFZhcmlhYmxlcyh2YXJpYWJsZXNGcm9tRmlsZXMsIHRoaXMuZmlsZVZhcmlhYmxlc0RpciwgdGhpcy5lbnZpcm9ubWVudCk7XG5cbiAgICAgICAgY29uc3QgdXNlckRlZmluZWRWYXJpYWJsZXMgPSB7Li4udGhpcy5nbG9iYWxWYXJpYWJsZXMsIC4uLmpvYlZhcmlhYmxlcywgLi4ubWF0cml4VmFyaWFibGVzLCAuLi5ydWxlVmFyaWFibGVzLCAuLi5lbnZNYXRjaGVkVmFyaWFibGVzLCAuLi5hcmd2VmFyaWFibGVzfTtcbiAgICAgICAgdGhpcy5kaXNjb3VyYWdlT3ZlcnJpZGluZ09mUHJlZGVmaW5lZFZhcmlhYmxlcyhwcmVkZWZpbmVkVmFyaWFibGVzLCB1c2VyRGVmaW5lZFZhcmlhYmxlcywgYXJndi5pZ25vcmVQcmVkZWZpbmVkVmFycyk7XG5cbiAgICAgICAgLy8gTWVyZ2UgYW5kIGV4cGFuZCBhZnRlciBmaW5kaW5nIGVudiBtYXRjaGVkIHZhcmlhYmxlc1xuICAgICAgICB0aGlzLl92YXJpYWJsZXMgPSB7Li4ucHJlZGVmaW5lZFZhcmlhYmxlcywgLi4udXNlckRlZmluZWRWYXJpYWJsZXN9O1xuICAgICAgICAvLyBEZWxldGUgdmFyaWFibGVzIHRoZSB1c2VyIGludGVudGlvbmFsbHkgd2FudHMgdW5zZXRcbiAgICAgICAgZm9yIChjb25zdCB1bnNldFZhcmlhYmxlIG9mIGFyZ3YudW5zZXRWYXJpYWJsZXMpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl92YXJpYWJsZXNbdW5zZXRWYXJpYWJsZV07XG4gICAgICAgIH1cbiAgICAgICAgLy8gU2V0IEdDTF9QUk9KRUNUX0RJUl9PTl9IT1NUIGlmIGRvY2tlciBpbWFnZVxuICAgICAgICBpZiAodGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSkge1xuICAgICAgICAgICAgdGhpcy5fdmFyaWFibGVzID0gey4uLnRoaXMuX3ZhcmlhYmxlcywgLi4ue0dDTF9QUk9KRUNUX0RJUl9PTl9IT1NUOiBjd2R9fTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFzc2VydCh0aGlzLnNjcmlwdHMgfHwgdGhpcy50cmlnZ2VyLCBjaGFsa2B7Ymx1ZUJyaWdodCAke3RoaXMubmFtZX19IG11c3QgaGF2ZSBzY3JpcHQgc3BlY2lmaWVkYCk7XG5cbiAgICAgICAgYXNzZXJ0KCEodGhpcy5pbnRlcmFjdGl2ZSAmJiAhdGhpcy5hcmd2LnNoZWxsRXhlY3V0b3JOb0ltYWdlKSwgY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IEBJbnRlcmFjdGl2ZSBkZWNvcmF0b3IgY2Fubm90IGJlIHVzZWQgd2l0aCAtLW5vLXNoZWxsLWV4ZWN1dG9yLW5vLWltYWdlYCk7XG5cbiAgICAgICAgaWYgKHRoaXMuaW50ZXJhY3RpdmUgJiYgKHRoaXMud2hlbiAhPT0gXCJtYW51YWxcIiB8fCB0aGlzLmltYWdlTmFtZSh0aGlzLl92YXJpYWJsZXMpICE9PSBudWxsKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHttZXNzYWdlOiBgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IEBJbnRlcmFjdGl2ZSBkZWNvcmF0b3IgY2Fubm90IGhhdmUgaW1hZ2U6IGFuZCBtdXN0IGJlIHdoZW46bWFudWFsYH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaW5qZWN0U1NIQWdlbnQgJiYgdGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHttZXNzYWdlOiBgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IEBJbmplY3RTU0hBZ2VudCBjYW4gb25seSBiZSB1c2VkIHdpdGggaW1hZ2U6YH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKTtcbiAgICAgICAgZm9yIChjb25zdCBbaSwgY10gb2YgT2JqZWN0LmVudHJpZXM8YW55Pih0aGlzLmNhY2hlKSkge1xuICAgICAgICAgICAgYy5wb2xpY3kgPSBVdGlscy5leHBhbmRUZXh0KGMucG9saWN5LCBleHBhbmRlZCk7XG4gICAgICAgICAgICBhc3NlcnQoW1wicHVsbFwiLCBcInB1c2hcIiwgXCJwdWxsLXB1c2hcIl0uaW5jbHVkZXMoYy5wb2xpY3kpLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IGNhY2hlWyR7aX1dLnBvbGljeSBpcyBub3QgJ3B1bGwnLCAncHVzaCcgb3IgJ3B1bGwtcHVzaCdgKTtcbiAgICAgICAgICAgIGFzc2VydChbXCJvbl9zdWNjZXNzXCIsIFwib25fZmFpbHVyZVwiLCBcImFsd2F5c1wiXS5pbmNsdWRlcyhjLndoZW4pLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IGNhY2hlWyR7aX1dLndoZW4gaXMgbm90ICdvbl9zdWNjZXNzJywgJ29uX2ZhaWx1cmUnIG9yICdhbHdheXMnYCk7XG4gICAgICAgICAgICBhc3NlcnQoQXJyYXkuaXNBcnJheShjLnBhdGhzKSwgY2hhbGtge2JsdWUgJHt0aGlzLm5hbWV9fSBjYWNoZVske2l9XS5wYXRocyBtdXN0IGJlIGFycmF5YCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IFtpLCBzXSBvZiBPYmplY3QuZW50cmllczxhbnk+KHRoaXMuc2VydmljZXMpKSB7XG4gICAgICAgICAgICBhc3NlcnQocy5uYW1lLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IHNlcnZpY2VzWyR7aX1dLm5hbWUgaXMgdW5kZWZpbmVkYCk7XG4gICAgICAgICAgICBhc3NlcnQoIXMuY29tbWFuZCB8fCBBcnJheS5pc0FycmF5KHMuY29tbWFuZCksIGNoYWxrYHtibHVlICR7dGhpcy5uYW1lfX0gc2VydmljZXNbJHtpfV0uY29tbWFuZCBtdXN0IGJlIGFuIGFycmF5YCk7XG4gICAgICAgICAgICBhc3NlcnQoIXMuZW50cnlwb2ludCB8fCBBcnJheS5pc0FycmF5KHMuZW50cnlwb2ludCksIGNoYWxrYHtibHVlICR7dGhpcy5uYW1lfX0gc2VydmljZXNbJHtpfV0uZW50cnlwb2ludCBtdXN0IGJlIGFuIGFycmF5YCk7XG4gICAgICAgIH1cblxuICAgICAgICBhc3NlcnQoIXRoaXMuYXJ0aWZhY3RzPy5wYXRocyB8fCBBcnJheS5pc0FycmF5KHRoaXMuYXJ0aWZhY3RzLnBhdGhzKSwgY2hhbGtge2JsdWUgJHt0aGlzLm5hbWV9fSBhcnRpZmFjdHMucGF0aHMgbXVzdCBiZSBhbiBhcnJheWApO1xuXG4gICAgICAgIGlmICh0aGlzLmltYWdlTmFtZSh0aGlzLl92YXJpYWJsZXMpICYmIGFyZ3YubW91bnRDYWNoZSkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBjIG9mIHRoaXMuY2FjaGUpIHtcbiAgICAgICAgICAgICAgICBjLnBhdGhzLmZvckVhY2goKHApID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGF0aCA9IFV0aWxzLmV4cGFuZFRleHQocCwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoIXBhdGguaW5jbHVkZXMoXCIqXCIpLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IGNhbm5vdCBoYXZlICogaW4gY2FjaGUgcGF0aHMsIHdoZW4gLS1tb3VudC1jYWNoZSBpcyBlbmFibGVkYCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAgV2FybiB3aGVuIG92ZXJyaWRpbmcgb2YgcHJlZGVmaW5lZCB2YXJpYWJsZXMgaXMgZGV0ZWN0ZWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGRpc2NvdXJhZ2VPdmVycmlkaW5nT2ZQcmVkZWZpbmVkVmFyaWFibGVzIChwcmVkZWZpbmVkVmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30sIHVzZXJEZWZpbmVkVmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30sIHdoaXRlTGlzdGVkUHJlZGVmaW5lZFZhcmlhYmxlc0tleXM6IHN0cmluZ1tdKSB7XG4gICAgICAgIGNvbnN0IHByZWRlZmluZWRWYXJpYWJsZXNLZXlzID0gT2JqZWN0LmtleXMocHJlZGVmaW5lZFZhcmlhYmxlcyk7XG4gICAgICAgIGNvbnN0IHVzZXJEZWZpbmVkVmFyaWFibGVzS2V5cyA9IE9iamVjdC5rZXlzKHVzZXJEZWZpbmVkVmFyaWFibGVzKTtcblxuICAgICAgICBjb25zdCBvdmVycmlkaW5nT2ZQcmVkZWZpbmVkVmFyaWFibGVzID0gdXNlckRlZmluZWRWYXJpYWJsZXNLZXlzLmZpbHRlcihlbGUgPT4gcHJlZGVmaW5lZFZhcmlhYmxlc0tleXMuaW5jbHVkZXMoZWxlKSAmJiAhd2hpdGVMaXN0ZWRQcmVkZWZpbmVkVmFyaWFibGVzS2V5cy5pbmNsdWRlcyhlbGUpKTtcbiAgICAgICAgaWYgKG92ZXJyaWRpbmdPZlByZWRlZmluZWRWYXJpYWJsZXMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGxpbmtUb0dpdGxhYiA9IFwiaHR0cHM6Ly9naXRsYWIuY29tL2dpdGxhYi1vcmcvZ2l0bGFiLy0vYmxvYi92MTcuNy4xLWVlL2RvYy9jaS92YXJpYWJsZXMvcHJlZGVmaW5lZF92YXJpYWJsZXMubWQ/cGxhaW49MSZyZWZfdHlwZT10YWdzI0wxNS0xNlwiO1xuICAgICAgICB0aGlzLndyaXRlU3RyZWFtcy5tZW1vU3Rkb3V0KGNoYWxrYFxue2JnWWVsbG93QnJpZ2h0ICBXQVJOIH0gJHt0ZXJtaW5hbExpbmsoXCJBdm9pZCBvdmVycmlkaW5nIHByZWRlZmluZWQgdmFyaWFibGVzXCIsIGxpbmtUb0dpdGxhYil9IFt7Ym9sZCAke292ZXJyaWRpbmdPZlByZWRlZmluZWRWYXJpYWJsZXN9fV0gYXMgaXQgY2FuIGNhdXNlIHRoZSBwaXBlbGluZSB0byBiZWhhdmUgdW5leHBlY3RlZGx5LlxuSWYgeW91IGtub3cgd2hhdCB5b3UncmUgZG9pbmcgYW5kIHdvdWxkIGxpa2UgdG8gc3VwcHJlc3MgdGhpcyB3YXJuaW5nLCB1c2Ugb25lIG9mIHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcblxcdOKAoiB2aWEgY2xpIG9wdGlvbnNcblxcdFxcdOKAoiAtLWlnbm9yZS1wcmVkZWZpbmVkLXZhcnMgJHtvdmVycmlkaW5nT2ZQcmVkZWZpbmVkVmFyaWFibGVzfVxuXFx04oCiIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZVxuXFx0XFx04oCiIEdDTF9JR05PUkVfUFJFREVGSU5FRF9WQVJTPSR7b3ZlcnJpZGluZ09mUHJlZGVmaW5lZFZhcmlhYmxlc31cbmApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgcHJlZGVmaW5lZFZhcmlhYmxlcyB0aGF0J3MgZW5yaWNoZWQgd2l0aCB0aGUgYWRkaXRpb25hbCBpbmZvIHRoYXQncyBvbmx5IGF2YWlsYWJsZSB3aGVuIGNvbnN0cnVjdGluZ1xuICAgICAqL1xuICAgIHByaXZhdGUgX3ByZWRlZmluZWRWYXJpYWJsZXMgKG9wdDogSm9iT3B0aW9ucykge1xuICAgICAgICBjb25zdCBhcmd2ID0gdGhpcy5hcmd2O1xuICAgICAgICBjb25zdCBjd2QgPSBhcmd2LmN3ZDtcbiAgICAgICAgY29uc3Qgc3RhdGVEaXIgPSB0aGlzLmFyZ3Yuc3RhdGVEaXI7XG4gICAgICAgIGNvbnN0IGdpdERhdGEgPSB0aGlzLmdpdERhdGE7XG5cbiAgICAgICAgbGV0IGNpQnVpbGRzRGlyOiBzdHJpbmc7XG4gICAgICAgIGlmICh0aGlzLmpvYkRhdGFbXCJpbWFnZVwiXSkge1xuICAgICAgICAgICAgY2lCdWlsZHNEaXIgPSBcIi9idWlsZHNcIjtcbiAgICAgICAgICAgIHRoaXMuY2lQcm9qZWN0RGlyID0gYCR7Y2lCdWlsZHNEaXJ9LyR7Z2l0RGF0YS5yZW1vdGUuZ3JvdXB9LyR7Z2l0RGF0YS5yZW1vdGUucHJvamVjdH1gO1xuICAgICAgICB9IGVsc2UgaWYgKGFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIGNpQnVpbGRzRGlyID0gYCR7Y3dkfS8ke3N0YXRlRGlyfS9idWlsZHMvJHt0aGlzLnNhZmVKb2JOYW1lfWA7XG4gICAgICAgICAgICB0aGlzLmNpUHJvamVjdERpciA9IGNpQnVpbGRzRGlyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2lCdWlsZHNEaXIgPSBjd2Q7XG4gICAgICAgICAgICB0aGlzLmNpUHJvamVjdERpciA9IGNpQnVpbGRzRGlyO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcHJlZGVmaW5lZFZhcmlhYmxlcyA9IG9wdC5wcmVkZWZpbmVkVmFyaWFibGVzO1xuXG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9KT0JfSURcIl0gPSBgJHt0aGlzLmpvYklkfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9QSVBFTElORV9JRFwiXSA9IGAke3RoaXMucGlwZWxpbmVJaWQgKyAxMDAwfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9QSVBFTElORV9JSURcIl0gPSBgJHt0aGlzLnBpcGVsaW5lSWlkfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9KT0JfTkFNRVwiXSA9IGAke3RoaXMubmFtZX1gO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfSk9CX05BTUVfU0xVR1wiXSA9IGAke3RoaXMubmFtZS5yZXBsYWNlKC9bXmEtelxcZF0rL2lnLCBcIi1cIikucmVwbGFjZSgvXi0vLCBcIlwiKS5zbGljZSgwLCA2MykucmVwbGFjZSgvLSQvLCBcIlwiKS50b0xvd2VyQ2FzZSgpfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9KT0JfU1RBR0VcIl0gPSBgJHt0aGlzLnN0YWdlfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9CVUlMRFNfRElSXCJdID0gY2lCdWlsZHNEaXI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9QUk9KRUNUX0RJUlwiXSA9IHRoaXMuY2lQcm9qZWN0RGlyO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfSk9CX1VSTFwiXSA9IGAke3ByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9TRVJWRVJfVVJMXCJdfS8ke2dpdERhdGEucmVtb3RlLmdyb3VwfS8ke2dpdERhdGEucmVtb3RlLnByb2plY3R9Ly0vam9icy8ke3RoaXMuam9iSWR9YDsgLy8gQ2hhbmdlcyBvbiByZXJ1bi5cbiAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX1BJUEVMSU5FX1VSTFwiXSA9IGAke3ByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9TRVJWRVJfVVJMXCJdfS8ke2dpdERhdGEucmVtb3RlLmdyb3VwfS8ke2dpdERhdGEucmVtb3RlLnByb2plY3R9L3BpcGVsaW5lcy8ke3RoaXMucGlwZWxpbmVJaWR9YDtcbiAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX0VOVklST05NRU5UX05BTUVcIl0gPSB0aGlzLmVudmlyb25tZW50Py5uYW1lID8/IFwiXCI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9TTFVHXCJdID0gdGhpcy5lbnZpcm9ubWVudD8ubmFtZSA/IHRoaXMuX2dlbmVyYXRlRW52aXJvbm1lbnRTbHVnKHRoaXMuZW52aXJvbm1lbnQubmFtZSkgOiBcIlwiO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfRU5WSVJPTk1FTlRfVVJMXCJdID0gdGhpcy5lbnZpcm9ubWVudD8udXJsID8/IFwiXCI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9USUVSXCJdID0gdGhpcy5lbnZpcm9ubWVudD8uZGVwbG95bWVudF90aWVyID8/IFwiXCI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9BQ1RJT05cIl0gPSB0aGlzLmVudmlyb25tZW50Py5hY3Rpb24gPz8gXCJcIjtcblxuICAgICAgICBpZiAob3B0Lm5vZGVJbmRleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX05PREVfSU5ERVhcIl0gPSBgJHtvcHQubm9kZUluZGV4fWA7XG4gICAgICAgIH1cbiAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX05PREVfVE9UQUxcIl0gPSBgJHtvcHQubm9kZXNUb3RhbH1gO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfUkVHSVNUUllcIl0gPSBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfUkVHSVNUUllcIl0gPSB0aGlzLmFyZ3YucmVnaXN0cnkgPyBVdGlscy5nY2xSZWdpc3RyeVByZWZpeCA6IGBsb2NhbC1yZWdpc3RyeS4ke3RoaXMuZ2l0RGF0YS5yZW1vdGUuaG9zdH1gO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfUkVHSVNUUllfSU1BR0VcIl0gPSBgJENJX1JFR0lTVFJZLyR7cHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX1BST0pFQ1RfUEFUSFwiXS50b0xvd2VyQ2FzZSgpfWA7XG4gICAgICAgIHJldHVybiBwcmVkZWZpbmVkVmFyaWFibGVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlcyBhIGNvbXBsaWFudCBzbHVnIGZvciBhbiBlbnZpcm9ubWVudCBuYW1lLlxuICAgICAqIFNlZTogaHR0cHM6Ly9naXRsYWIuY29tL2dpdGxhYi1vcmcvZ2l0bGFiLy0vYmxvYi9mYzMxZTdhYzM0NGU1M2ViYWUxODJlYTFkY2ExODNiZGMwZTJlYTcxL2xpYi9naXRsYWIvc2x1Zy9lbnZpcm9ubWVudC5yYlxuICAgICAqXG4gICAgICogVGhlIHNsdWc6XG4gICAgICogLSBDb250YWlucyBvbmx5IGxvd2VyY2FzZSBsZXR0ZXJzIChhLXopLCBudW1iZXJzICgwLTkpLCBhbmQgJy0nLlxuICAgICAqIC0gQmVnaW5zIHdpdGggYSBsZXR0ZXIuXG4gICAgICogLSBIYXMgYSBtYXhpbXVtIGxlbmd0aCBvZiAyNCBjaGFyYWN0ZXJzLlxuICAgICAqIC0gRG9lcyBub3QgZW5kIHdpdGggJy0nLlxuICAgICAqXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG9yaWdpbmFsIGVudmlyb25tZW50IG5hbWUuXG4gICAgICogQHJldHVybnMgQSBjb21wbGlhbnQgZW52aXJvbm1lbnQgc2x1Zy5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9nZW5lcmF0ZUVudmlyb25tZW50U2x1ZyAobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgLy8gMS4gTG93ZXJjYXNlLCByZXBsYWNlIG5vbi1hbHBoYW51bWVyaWMgd2l0aCAnLScsIGFuZCBzcXVlZXplIHJlcGVhdGluZyAnLSdcbiAgICAgICAgbGV0IHNsdWcgPSBuYW1lXG4gICAgICAgICAgICAudG9Mb3dlckNhc2UoKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1teYS16MC05XS9nLCBcIi1cIilcbiAgICAgICAgICAgIC5yZXBsYWNlKC8tKy9nLCBcIi1cIik7XG5cbiAgICAgICAgLy8gMi4gTXVzdCBzdGFydCB3aXRoIGEgbGV0dGVyXG4gICAgICAgIGlmICghL15bYS16XS8udGVzdChzbHVnKSkge1xuICAgICAgICAgICAgc2x1ZyA9IGBlbnYtJHtzbHVnfWA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAzLiBJZiBpdCdzIHRvbyBsb25nIG9yIHdhcyBtb2RpZmllZCwgc2hvcnRlbiBhbmQgYWRkIGEgaGFzaCBzdWZmaXhcbiAgICAgICAgaWYgKHNsdWcubGVuZ3RoID4gMjQgfHwgc2x1ZyAhPT0gbmFtZSkge1xuICAgICAgICAgICAgLy8gVHJ1bmNhdGUgdG8gMTcgY2hhcnMgKGxlYXZpbmcgcm9vbSBmb3IgJy0nICsgNi1jaGFyIGhhc2gpXG4gICAgICAgICAgICBzbHVnID0gc2x1Zy5zbGljZSgwLCAxNyk7XG5cbiAgICAgICAgICAgIC8vIEVuc3VyZSBpdCBlbmRzIHdpdGggYSBkYXNoIGJlZm9yZSBhZGRpbmcgdGhlIHN1ZmZpeFxuICAgICAgICAgICAgaWYgKCFzbHVnLmVuZHNXaXRoKFwiLVwiKSkge1xuICAgICAgICAgICAgICAgIHNsdWcgKz0gXCItXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSB0aGUgNi1jaGFyIHN1ZmZpeCBmcm9tIGEgaGFzaCBvZiB0aGUgKm9yaWdpbmFsKiBuYW1lXG4gICAgICAgICAgICBjb25zdCBoZXhIYXNoID0gY3J5cHRvXG4gICAgICAgICAgICAgICAgLmNyZWF0ZUhhc2goXCJzaGEyNTZcIilcbiAgICAgICAgICAgICAgICAudXBkYXRlKG5hbWUpXG4gICAgICAgICAgICAgICAgLmRpZ2VzdChcImhleFwiKTtcblxuICAgICAgICAgICAgLy8gVXNlIEJpZ0ludCBmb3Igc2FmZSBjb252ZXJzaW9uIGZyb20gaGV4IC0+IGJhc2UzNlxuICAgICAgICAgICAgY29uc3Qgc3VmZml4ID0gQmlnSW50KGAweCR7aGV4SGFzaH1gKS50b1N0cmluZygzNikuc2xpY2UoLTYpO1xuXG4gICAgICAgICAgICByZXR1cm4gc2x1ZyArIHN1ZmZpeDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDQuIElmIGl0IHdhcyBzaG9ydCBhbmQgdW5tb2RpZmllZCwganVzdCBlbnN1cmUgaXQgZG9lc24ndCBlbmQgd2l0aCAnLSdcbiAgICAgICAgcmV0dXJuIHNsdWcucmVwbGFjZSgvLSQvLCBcIlwiKTtcbiAgICB9XG5cbiAgICBnZXQgam9iU3RhdHVzICgpIHtcbiAgICAgICAgaWYgKHRoaXMucHJlU2NyaXB0c0V4aXRDb2RlID09IG51bGwpIHJldHVybiBcInBlbmRpbmdcIjtcbiAgICAgICAgaWYgKHRoaXMucHJlU2NyaXB0c0V4aXRDb2RlID09IDApIHJldHVybiBcInN1Y2Nlc3NcIjtcblxuICAgICAgICBsZXQgYWxsb3dlZEV4aXRDb2RlcyA9IFswXTtcbiAgICAgICAgY29uc3QgYWxsb3dGYWlsdXJlID0gdGhpcy5hbGxvd0ZhaWx1cmU7XG4gICAgICAgIHN3aXRjaCAodHlwZW9mIGFsbG93RmFpbHVyZSkge1xuICAgICAgICAgICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgICAgICAgICAgICBpZiAoYWxsb3dGYWlsdXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIGFsbG93ZWRFeGl0Q29kZXMgPSBbdGhpcy5wcmVTY3JpcHRzRXhpdENvZGVdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgICAgICAgICAgICBpZiAoISBBcnJheS5pc0FycmF5KGFsbG93RmFpbHVyZS5leGl0X2NvZGVzKSkge1xuICAgICAgICAgICAgICAgICAgICBhbGxvd2VkRXhpdENvZGVzID0gW2FsbG93RmFpbHVyZS5leGl0X2NvZGVzXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhbGxvd2VkRXhpdENvZGVzID0gYWxsb3dGYWlsdXJlLmV4aXRfY29kZXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgdHlwZTogICR7dHlwZW9mIGFsbG93RmFpbHVyZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhbGxvd2VkRXhpdENvZGVzLmluY2x1ZGVzKHRoaXMucHJlU2NyaXB0c0V4aXRDb2RlKSA/IFwid2FybmluZ1wiIDogXCJmYWlsZWRcIjtcbiAgICB9XG5cbiAgICBnZXQgYXJ0aWZhY3RzVG9Tb3VyY2UgKCkge1xuICAgICAgICBpZiAodGhpcy5qb2JEYXRhW1wiZ2NsQXJ0aWZhY3RzVG9Tb3VyY2VcIl0gIT0gbnVsbCkgcmV0dXJuIHRoaXMuam9iRGF0YVtcImdjbEFydGlmYWN0c1RvU291cmNlXCJdO1xuICAgICAgICByZXR1cm4gdGhpcy5hcmd2LmFydGlmYWN0c1RvU291cmNlO1xuICAgIH1cblxuICAgIGdldCBwcmV0dHlEdXJhdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLl9lbmRUaW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJldHR5SHJ0aW1lKHRoaXMuX2VuZFRpbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0YXJ0VGltZSA/XG4gICAgICAgICAgICBwcmV0dHlIcnRpbWUocHJvY2Vzcy5ocnRpbWUodGhpcy5fc3RhcnRUaW1lKSkgOlxuICAgICAgICAgICAgXCIwIG1zXCI7XG4gICAgfVxuXG4gICAgZ2V0IGZvcm1hdHRlZEpvYk5hbWUgKCkge1xuICAgICAgICBsZXQgcHJlZml4ID0gXCJcIjtcbiAgICAgICAgaWYgKHRoaXMuYXJndi5jaGlsZFBpcGVsaW5lRGVwdGggPiAwKSBwcmVmaXggPSBcIlxcdFwiLnJlcGVhdCh0aGlzLmFyZ3YuY2hpbGRQaXBlbGluZURlcHRoKSArIGBbJHt0aGlzLmFyZ3YudmFyaWFibGUuR0NMX1RSSUdHRVJFUn1dIC0+IGA7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcFByZWZpeCA9IHRoaXMuYXJndi5zaG93VGltZXN0YW1wcyA/XG4gICAgICAgICAgICBgWyR7ZGF0ZUZvcm1hdHRlci5mb3JtYXQobmV3IERhdGUoKSl9ICR7dGhpcy5wcmV0dHlEdXJhdGlvbi5wYWRTdGFydCg3KX1dIGAgOlxuICAgICAgICAgICAgXCJcIjtcblxuICAgICAgICAvLyBbMTY6MzM6MTkgMS4zNyBtaW5dIG15LWpvYiAgICAgPiBoZWxsbyB3b3JsZFxuICAgICAgICByZXR1cm4gY2hhbGtgJHt0aW1lc3RhbXBQcmVmaXh9e2JsdWVCcmlnaHQgJHtwcmVmaXh9JHt0aGlzLm5hbWUucGFkRW5kKHRoaXMuam9iTmFtZVBhZCl9fWA7XG4gICAgfVxuXG4gICAgZ2V0IHNhZmVKb2JOYW1lICgpIHtcbiAgICAgICAgcmV0dXJuIFV0aWxzLnNhZmVEb2NrZXJTdHJpbmcodGhpcy5uYW1lKTtcbiAgICB9XG5cbiAgICBnZXQgbmVlZHMgKCk6IE5lZWRbXSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5qb2JEYXRhW1wibmVlZHNcIl0gPz8gbnVsbDtcbiAgICB9XG5cbiAgICBnZXQgYnVpbGRWb2x1bWVOYW1lICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYGdjbC0ke3RoaXMuc2FmZUpvYk5hbWV9LSR7dGhpcy5qb2JJZH0tYnVpbGRgO1xuICAgIH1cblxuICAgIGdldCB0bXBWb2x1bWVOYW1lICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYGdjbC0ke3RoaXMuc2FmZUpvYk5hbWV9LSR7dGhpcy5qb2JJZH0tdG1wYDtcbiAgICB9XG5cbiAgICBnZXQgc2VydmljZXMgKCk6IFNlcnZpY2VbXSB7XG4gICAgICAgIGNvbnN0IHNlcnZpY2VzOiBTZXJ2aWNlW10gPSBbXTtcbiAgICAgICAgaWYgKCF0aGlzLmpvYkRhdGFbXCJzZXJ2aWNlc1wiXSkgcmV0dXJuIFtdO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc2VydmljZSBvZiBPYmplY3QudmFsdWVzPGFueT4odGhpcy5qb2JEYXRhW1wic2VydmljZXNcIl0pKSB7XG4gICAgICAgICAgICBjb25zdCBleHBhbmRlZCA9IFV0aWxzLmV4cGFuZFZhcmlhYmxlcyh7Li4udGhpcy5fdmFyaWFibGVzLCAuLi50aGlzLl9kb3RlbnZWYXJpYWJsZXMsIC4uLnNlcnZpY2VbXCJ2YXJpYWJsZXNcIl19KTtcbiAgICAgICAgICAgIGxldCBzZXJ2aWNlTmFtZSA9IFV0aWxzLmV4cGFuZFRleHQoc2VydmljZVtcIm5hbWVcIl0sIGV4cGFuZGVkKTtcbiAgICAgICAgICAgIGlmIChzZXJ2aWNlTmFtZSA9PSBcIlwiKSBjb250aW51ZTtcbiAgICAgICAgICAgIHNlcnZpY2VOYW1lID0gc2VydmljZU5hbWUuaW5jbHVkZXMoXCI6XCIpID8gc2VydmljZU5hbWUgOiBgJHtzZXJ2aWNlTmFtZX06bGF0ZXN0YDtcbiAgICAgICAgICAgIHNlcnZpY2VzLnB1c2goe1xuICAgICAgICAgICAgICAgIG5hbWU6IHNlcnZpY2VOYW1lLFxuICAgICAgICAgICAgICAgIGVudHJ5cG9pbnQ6IHNlcnZpY2VbXCJlbnRyeXBvaW50XCJdID8/IG51bGwsXG4gICAgICAgICAgICAgICAgY29tbWFuZDogc2VydmljZVtcImNvbW1hbmRcIl0gPz8gbnVsbCxcbiAgICAgICAgICAgICAgICB2YXJpYWJsZXM6IGV4cGFuZGVkLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBVdGlscy5leHBhbmRUZXh0KHNlcnZpY2VbXCJhbGlhc1wiXSwgZXhwYW5kZWQpID8/IG51bGwsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VydmljZXM7XG4gICAgfVxuXG4gICAgc2V0IGNpUHJvamVjdERpciAoY2lQcm9qZWN0RGlyOiBzdHJpbmcpIHtcbiAgICAgICAgYXNzZXJ0KHRoaXMuX2NpUHJvamVjdERpciA9PSBudWxsLCBcInRoaXMuX2NpUHJvamVjdERpciBjYW4gb25seSBiZSBzZXQgb25jZVwiKTtcbiAgICAgICAgdGhpcy5fY2lQcm9qZWN0RGlyID0gY2lQcm9qZWN0RGlyO1xuICAgIH1cbiAgICBnZXQgY2lQcm9qZWN0RGlyICgpIHtcbiAgICAgICAgYXNzZXJ0KHRoaXMuX2NpUHJvamVjdERpciwgXCJhdHRlbXB0ZWQgdG8gYWNjZXNzIHRoaXMuX2NpUHJvamVjdERpciBiZWZvcmUgaXQgaXMgaW5pdGlhbGl6ZWRcIik7XG4gICAgICAgIHJldHVybiB0aGlzLl9jaVByb2plY3REaXI7XG4gICAgfVxuXG4gICAgc2V0IGpvYk5hbWVQYWQgKGpvYk5hbWVQYWQ6IG51bWJlcikge1xuICAgICAgICBhc3NlcnQodGhpcy5fam9iTmFtZVBhZCA9PSBudWxsLCBcInRoaXMuX2pvYk5hbWVQYWQgY2FuIG9ubHkgYmUgc2V0IG9uY2VcIik7XG4gICAgICAgIHRoaXMuX2pvYk5hbWVQYWQgPSBqb2JOYW1lUGFkO1xuICAgIH1cblxuICAgIGdldCBqb2JOYW1lUGFkICgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fam9iTmFtZVBhZCA/PyAwO1xuICAgIH1cblxuICAgIGdldCBwcm9kdWNlcnMgKCk6IHtuYW1lOiBzdHJpbmc7IGRvdGVudjogc3RyaW5nIHwgbnVsbH1bXSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5fcHJvZHVjZXJzO1xuICAgIH1cblxuICAgIHNldCBwcm9kdWNlcnMgKHByb2R1Y2Vyczoge25hbWU6IHN0cmluZzsgZG90ZW52OiBzdHJpbmcgfCBudWxsfVtdIHwgbnVsbCkge1xuICAgICAgICBhc3NlcnQodGhpcy5fcHJvZHVjZXJzID09IG51bGwsIFwidGhpcy5fcHJvZHVjZXJzIGNhbiBvbmx5IGJlIHNldCBvbmNlXCIpO1xuICAgICAgICB0aGlzLl9wcm9kdWNlcnMgPSBwcm9kdWNlcnM7XG4gICAgfVxuXG4gICAgZ2V0IHN0YWdlICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5qb2JEYXRhW1wic3RhZ2VcIl0gfHwgXCJ0ZXN0XCI7XG4gICAgfVxuXG4gICAgZ2V0IGludGVyYWN0aXZlICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuam9iRGF0YVtcImdjbEludGVyYWN0aXZlXCJdIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIGdldCBpbmplY3RTU0hBZ2VudCAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmpvYkRhdGFbXCJnY2xJbmplY3RTU0hBZ2VudFwiXSB8fCBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgZGVzY3JpcHRpb24gKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLmpvYkRhdGFbXCJnY2xEZXNjcmlwdGlvblwiXSA/PyBcIlwiO1xuICAgIH1cblxuICAgIGdldCBhcnRpZmFjdHMgKCk6IHtwYXRoczogc3RyaW5nW107IGV4Y2x1ZGU/OiBzdHJpbmdbXTsgcmVwb3J0cz86IHtkb3RlbnY/OiBzdHJpbmd9OyB3aGVuPzogc3RyaW5nfSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5qb2JEYXRhW1wiYXJ0aWZhY3RzXCJdO1xuICAgIH1cblxuICAgIGRlbGV0ZUFydGlmYWN0cyAoKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmpvYkRhdGFbXCJhcnRpZmFjdHNcIl07XG4gICAgfVxuXG4gICAgZ2V0IGNhY2hlICgpOiBDYWNoZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuam9iRGF0YVtcImNhY2hlXCJdIHx8IFtdO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRVbmlxdWVDYWNoZU5hbWUgKGN3ZDogc3RyaW5nLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30sIGNhY2hlSW5kZXg6IG51bWJlcikge1xuICAgICAgICBjb25zdCBnZXRDYWNoZVByZWZpeCA9IChpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwcmVmaXggPSB0aGlzLmpvYkRhdGFbXCJjYWNoZVwiXVtpbmRleF1bXCJrZXlcIl1bXCJwcmVmaXhcIl07XG4gICAgICAgICAgICBpZiAocHJlZml4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke2luZGV4fV8ke1V0aWxzLmV4cGFuZFRleHQocHJlZml4LCBleHBhbmRlZCl9LWA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGZpbGVuYW1lcyA9IHRoaXMuam9iRGF0YVtcImNhY2hlXCJdW2luZGV4XVtcImtleVwiXVtcImZpbGVzXCJdLm1hcCgocDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXhwYW5kUCA9IFV0aWxzLmV4cGFuZFRleHQocCwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBleHBhbmRQLnNwbGl0KFwiLlwiKVswXTtcbiAgICAgICAgICAgIH0pLmpvaW4oXCJfXCIpO1xuICAgICAgICAgICAgcmV0dXJuIGAke2luZGV4fV8ke2ZpbGVuYW1lc30tYDtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBrZXkgPSB0aGlzLmpvYkRhdGFbXCJjYWNoZVwiXVtjYWNoZUluZGV4XS5rZXk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBrZXkgPT09IFwic3RyaW5nXCIgfHwga2V5ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBVdGlscy5leHBhbmRUZXh0KGtleSA/PyBcImRlZmF1bHRcIiwgZXhwYW5kZWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmlsZXMgPSBrZXlbXCJmaWxlc1wiXS5tYXAoKGY6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IHBhdGggPSBVdGlscy5leHBhbmRUZXh0KGYsIGV4cGFuZGVkKTtcbiAgICAgICAgICAgIGlmIChwYXRoLnN0YXJ0c1dpdGgoYCR7dGhpcy5jaVByb2plY3REaXJ9L2ApKSB7XG4gICAgICAgICAgICAgICAgcGF0aCA9IHBhdGguc2xpY2UoYCR7dGhpcy5jaVByb2plY3REaXJ9L2AubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBgJHtjd2R9LyR7cGF0aH1gO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGdldENhY2hlUHJlZml4KGNhY2hlSW5kZXgpICsgYXdhaXQgVXRpbHMuY2hlY2tzdW1GaWxlcyhjd2QsIGZpbGVzKTtcbiAgICB9XG5cbiAgICBnZXQgYmVmb3JlU2NyaXB0cyAoKTogc3RyaW5nW10ge1xuICAgICAgICBjb25zdCBiZWZvcmVTY3JpcHRzID0gdGhpcy5qb2JEYXRhW1wiYmVmb3JlX3NjcmlwdFwiXSB8fCBbXTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBiZWZvcmVTY3JpcHRzID09PSBcInN0cmluZ1wiID8gW2JlZm9yZVNjcmlwdHNdIDogYmVmb3JlU2NyaXB0cztcbiAgICB9XG5cbiAgICBnZXQgYWZ0ZXJTY3JpcHRzICgpOiBzdHJpbmdbXSB7XG4gICAgICAgIGNvbnN0IGFmdGVyU2NyaXB0cyA9IHRoaXMuam9iRGF0YVtcImFmdGVyX3NjcmlwdFwiXSB8fCBbXTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBhZnRlclNjcmlwdHMgPT09IFwic3RyaW5nXCIgPyBbYWZ0ZXJTY3JpcHRzXSA6IGFmdGVyU2NyaXB0cztcbiAgICB9XG5cbiAgICBnZXQgc2NyaXB0cyAoKTogc3RyaW5nW10ge1xuICAgICAgICBjb25zdCBzY3JpcHQgPSB0aGlzLmpvYkRhdGFbXCJzY3JpcHRcIl07XG4gICAgICAgIHJldHVybiB0eXBlb2Ygc2NyaXB0ID09PSBcInN0cmluZ1wiID8gW3NjcmlwdF0gOiBzY3JpcHQ7XG4gICAgfVxuXG4gICAgZ2V0IHRyaWdnZXIgKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLmpvYkRhdGFbXCJ0cmlnZ2VyXCJdO1xuICAgIH1cblxuICAgIGFzeW5jIHN0YXJ0VHJpZ2dlclBpcGVsaW5lICgpIHtcbiAgICAgICAgdGhpcy53cml0ZVN0cmVhbXMubWVtb1N0ZG91dChjaGFsa2B7YmdZZWxsb3dCcmlnaHQgIFdBUk4gfSBkb3duc3RyZWFtIHBpcGVsaW5lIGlzIGV4cGVyaW1lbnRhbCBpbiBnaXRsYWItY2ktbG9jYWxcXG5gKTtcbiAgICAgICAgYXdhaXQgdGhpcy5mZXRjaFRyaWdnZXJJbmNsdWRlKCk7XG4gICAgICAgIGNvbnN0IHZhcmlhYmxlc0ZvckRvd25zdHJlYW1QaXBlbGluZSA9IE9iamVjdC5lbnRyaWVzKHsuLi50aGlzLmdsb2JhbFZhcmlhYmxlcywgLi4udGhpcy5qb2JEYXRhLnZhcmlhYmxlc30pLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgJHtrZXl9PSR7dmFsdWV9YCk7XG5cbiAgICAgICAgY29uc3QgZ2NsVHJpZ2dlcmVyID0gdGhpcy5hcmd2LnZhcmlhYmxlW1wiR0NMX1RSSUdHRVJFUlwiXSA/XG4gICAgICAgICAgICBgJHt0aGlzLmFyZ3YudmFyaWFibGVbXCJHQ0xfVFJJR0dFUkVSXCJdfSAtPiAke3RoaXMubmFtZX1gIDpcbiAgICAgICAgICAgIHRoaXMubmFtZTtcbiAgICAgICAgYXdhaXQgaGFuZGxlcih7XG4gICAgICAgICAgICAuLi5PYmplY3QuZnJvbUVudHJpZXModGhpcy5hcmd2Lm1hcCksXG4gICAgICAgICAgICBmaWxlOiBgJHt0aGlzLmFyZ3Yuc3RhdGVEaXJ9L2luY2x1ZGVzL3RyaWdnZXJzLyR7dGhpcy5uYW1lfS55bWxgLFxuICAgICAgICAgICAgdmFyaWFibGU6IFtcbiAgICAgICAgICAgICAgICBjaGFsa2BHQ0xfVFJJR0dFUkVSPSR7Z2NsVHJpZ2dlcmVyfWAsXG4gICAgICAgICAgICAgICAgXCJDSV9QSVBFTElORV9TT1VSQ0U9cGFyZW50X3BpcGVsaW5lXCIsXG4gICAgICAgICAgICBdLmNvbmNhdCh2YXJpYWJsZXNGb3JEb3duc3RyZWFtUGlwZWxpbmUpLFxuICAgICAgICB9LCB0aGlzLndyaXRlU3RyZWFtcywgW10sIHRoaXMuYXJndi5jaGlsZFBpcGVsaW5lRGVwdGggKyAxKTtcbiAgICB9XG5cbiAgICBnZXQgcHJlU2NyaXB0c0V4aXRDb2RlICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZTtcbiAgICB9XG5cbiAgICBnZXQgYWZ0ZXJTY3JpcHRzRXhpdENvZGUgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWZ0ZXJTY3JpcHRzRXhpdENvZGU7XG4gICAgfVxuXG4gICAgZ2V0IHN0YXJ0ZWQgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcnVubmluZyB8fCB0aGlzLl9wcmVzY3JpcHRzRXhpdENvZGUgIT09IG51bGw7XG4gICAgfVxuXG4gICAgZ2V0IGZpbmlzaGVkICgpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLl9ydW5uaW5nICYmIHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSAhPT0gbnVsbDtcbiAgICB9XG5cbiAgICBnZXQgY292ZXJhZ2VQZXJjZW50ICgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvdmVyYWdlUGVyY2VudDtcbiAgICB9XG5cbiAgICBnZXQgZmlsZVZhcmlhYmxlc0RpciAoKSB7XG4gICAgICAgIHJldHVybiBgL3RtcC9naXRsYWItY2ktbG9jYWwtZmlsZS12YXJpYWJsZXMtJHt0aGlzLl92YXJpYWJsZXNbXCJDSV9QUk9KRUNUX1BBVEhfU0xVR1wiXX0tJHt0aGlzLmpvYklkfWA7XG4gICAgfVxuXG4gICAgZ2V0IGdsb2JhbFZhcmlhYmxlcyAoKSB7XG4gICAgICAgIGlmICh0aGlzLmluaGVyaXQudmFyaWFibGVzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5pbmhlcml0LnZhcmlhYmxlcykpIHtcbiAgICAgICAgICAgIGNvbnN0IGluaGVyaXRWYXJpYWJsZXMgPSB0aGlzLmluaGVyaXQudmFyaWFibGVzO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgICAgICAgICAgICBPYmplY3QuZW50cmllcyh0aGlzLl9nbG9iYWxWYXJpYWJsZXMpLmZpbHRlcigoW2tdKSA9PiBpbmhlcml0VmFyaWFibGVzLmluY2x1ZGVzKGspKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2dsb2JhbFZhcmlhYmxlcztcbiAgICB9XG5cbiAgICBhc3luYyBzdGFydCAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLnRyaWdnZXIpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc3RhcnRUcmlnZ2VyUGlwZWxpbmUoKTtcbiAgICAgICAgICAgIHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSA9IDA7IC8vIE5PVEU6IHNvIHRoYXQgYHRoaXMuZmluaXNoZWRgIHdpbGwgaW1wbGljaXRseSBiZSBzZXQgdG8gdHJ1ZVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcnVubmluZyA9IHRydWU7XG5cbiAgICAgICAgY29uc3QgYXJndiA9IHRoaXMuYXJndjtcbiAgICAgICAgdGhpcy5fc3RhcnRUaW1lID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgICAgICAgdGhpcy5fdmFyaWFibGVzW1wiQ0lfSk9CX1NUQVJURURfQVRcIl0gPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkuc3BsaXQoXCIuXCIpWzBdICsgXCJaXCI7XG4gICAgICAgIGNvbnN0IHdyaXRlU3RyZWFtcyA9IHRoaXMud3JpdGVTdHJlYW1zO1xuICAgICAgICB0aGlzLl9kb3RlbnZWYXJpYWJsZXMgPSBhd2FpdCB0aGlzLmluaXRQcm9kdWNlclJlcG9ydHNEb3RlbnZWYXJpYWJsZXMod3JpdGVTdHJlYW1zLCBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKSk7XG4gICAgICAgIGNvbnN0IGV4cGFuZGVkID0gVXRpbHMudW5zY2FwZSQkVmFyaWFibGVzKFV0aWxzLmV4cGFuZFZhcmlhYmxlcyh7Li4udGhpcy5fdmFyaWFibGVzLCAuLi50aGlzLl9kb3RlbnZWYXJpYWJsZXN9KSk7XG4gICAgICAgIGNvbnN0IGltYWdlTmFtZSA9IHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKTtcbiAgICAgICAgY29uc3QgaGVscGVySW1hZ2VOYW1lID0gYXJndi5oZWxwZXJJbWFnZTtcbiAgICAgICAgY29uc3Qgc2FmZUpvYk5hbWUgPSB0aGlzLnNhZmVKb2JOYW1lO1xuXG4gICAgICAgIGNvbnN0IG91dHB1dExvZ0ZpbGVQYXRoID0gYCR7YXJndi5jd2R9LyR7YXJndi5zdGF0ZURpcn0vb3V0cHV0LyR7c2FmZUpvYk5hbWV9LmxvZ2A7XG4gICAgICAgIGF3YWl0IGZzLmVuc3VyZUZpbGUob3V0cHV0TG9nRmlsZVBhdGgpO1xuICAgICAgICBhd2FpdCBmcy50cnVuY2F0ZShvdXRwdXRMb2dGaWxlUGF0aCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmludGVyYWN0aXZlKSB7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBzdGFydGluZ30gJHtpbWFnZU5hbWUgPz8gXCJzaGVsbFwifSAoe3llbGxvdyAke3RoaXMuc3RhZ2V9fSlcXG5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbWFnZU5hbWUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucHVsbEltYWdlKHdyaXRlU3RyZWFtcywgaW1hZ2VOYW1lKTtcblxuICAgICAgICAgICAgY29uc3QgYnVpbGRWb2x1bWVOYW1lID0gdGhpcy5idWlsZFZvbHVtZU5hbWU7XG4gICAgICAgICAgICBjb25zdCB0bXBWb2x1bWVOYW1lID0gdGhpcy50bXBWb2x1bWVOYW1lO1xuICAgICAgICAgICAgY29uc3QgZmlsZVZhcmlhYmxlc0RpciA9IHRoaXMuZmlsZVZhcmlhYmxlc0RpcjtcblxuICAgICAgICAgICAgY29uc3Qgdm9sdW1lUHJvbWlzZXMgPSBbXTtcbiAgICAgICAgICAgIHZvbHVtZVByb21pc2VzLnB1c2goVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInZvbHVtZVwiLCBcImNyZWF0ZVwiLCBgJHtidWlsZFZvbHVtZU5hbWV9YF0sIGFyZ3YuY3dkKSk7XG4gICAgICAgICAgICB2b2x1bWVQcm9taXNlcy5wdXNoKFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJ2b2x1bWVcIiwgXCJjcmVhdGVcIiwgYCR7dG1wVm9sdW1lTmFtZX1gXSwgYXJndi5jd2QpKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lclZvbHVtZU5hbWVzLnB1c2goYnVpbGRWb2x1bWVOYW1lKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lclZvbHVtZU5hbWVzLnB1c2godG1wVm9sdW1lTmFtZSk7XG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbCh2b2x1bWVQcm9taXNlcyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoTG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KHdyaXRlU3RyZWFtcyk7XG5cbiAgICAgICAgICAgIGxldCBjaG93bk9wdCA9IFwiMDowXCI7XG4gICAgICAgICAgICBsZXQgY2htb2RPcHQgPSBcImErcndcIjtcbiAgICAgICAgICAgIGlmICghdGhpcy5hcmd2LnVtYXNrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qge3N0ZG91dH0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwicnVuXCIsIFwiLS1ybVwiLCBcIi0tZW50cnlwb2ludFwiLCBcInNoXCIsIGltYWdlTmFtZSwgXCItY1wiLCBcImVjaG8gXFxcIiQoaWQgLXUpOiQoaWQgLWcpXFxcIlwiXSk7XG4gICAgICAgICAgICAgICAgY2hvd25PcHQgPSBzdGRvdXQ7XG4gICAgICAgICAgICAgICAgaWYgKGNob3duT3B0ID09IFwiMDowXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2htb2RPcHQgPSBcImctd1wiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChoZWxwZXJJbWFnZU5hbWUpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnB1bGxJbWFnZSh3cml0ZVN0cmVhbXMsIGhlbHBlckltYWdlTmFtZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGhlbHBlckNvbnRhaW5lckFyZ3MgPSBbXG4gICAgICAgICAgICAgICAgdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwiY3JlYXRlXCIsIFwiLS11c2VyPTA6MFwiLFxuICAgICAgICAgICAgICAgIGAtLXZvbHVtZT0ke2J1aWxkVm9sdW1lTmFtZX06JHt0aGlzLmNpUHJvamVjdERpcn1gLFxuICAgICAgICAgICAgICAgIGAtLXZvbHVtZT0ke3RtcFZvbHVtZU5hbWV9OiR7dGhpcy5maWxlVmFyaWFibGVzRGlyfWAsXG4gICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LmNhRmlsZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhRmlsZVBhdGggPSBwYXRoLmlzQWJzb2x1dGUodGhpcy5hcmd2LmNhRmlsZSkgPyB0aGlzLmFyZ3YuY2FGaWxlIDogcGF0aC5yZXNvbHZlKHRoaXMuYXJndi5jd2QsIHRoaXMuYXJndi5jYUZpbGUpO1xuICAgICAgICAgICAgICAgIGlmIChhd2FpdCBmcy5wYXRoRXhpc3RzKGNhRmlsZVBhdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlbHBlckNvbnRhaW5lckFyZ3MucHVzaChgLS12b2x1bWU9JHtjYUZpbGVQYXRofTovZXRjL3NzbC9jZXJ0cy9jYS1jZXJ0aWZpY2F0ZXMuY3J0OnJvYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBoZWxwZXJDb250YWluZXJBcmdzLnB1c2goYCR7aGVscGVySW1hZ2VOYW1lfWAsIFwic2hcIiwgXCItY1wiLCBgY2hvd24gJHtjaG93bk9wdH0gLVIgJHt0aGlzLmNpUHJvamVjdERpcn0gJiYgY2htb2QgJHtjaG1vZE9wdH0gLVIgJHt0aGlzLmNpUHJvamVjdERpcn0gJiYgY2hvd24gJHtjaG93bk9wdH0gLVIgL3RtcC8gJiYgY2htb2QgJHtjaG1vZE9wdH0gLVIgL3RtcC9gKTtcblxuICAgICAgICAgICAgY29uc3Qge3N0ZG91dDogY29udGFpbmVySWR9ID0gYXdhaXQgVXRpbHMuc3Bhd24oaGVscGVyQ29udGFpbmVyQXJncywgYXJndi5jd2QpO1xuICAgICAgICAgICAgdGhpcy5fY29udGFpbmVyc1RvQ2xlYW4ucHVzaChjb250YWluZXJJZCk7XG4gICAgICAgICAgICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhmaWxlVmFyaWFibGVzRGlyKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJjcFwiLCBgJHtmaWxlVmFyaWFibGVzRGlyfS8uYCwgYCR7Y29udGFpbmVySWR9OiR7ZmlsZVZhcmlhYmxlc0Rpcn1gXSwgYXJndi5jd2QpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVmcmVzaExvbmdSdW5uaW5nU2lsZW50VGltZW91dCh3cml0ZVN0cmVhbXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcImNwXCIsIGAke2FyZ3Yuc3RhdGVEaXJ9L2J1aWxkcy8uZG9ja2VyLy5gLCBgJHtjb250YWluZXJJZH06JHt0aGlzLmNpUHJvamVjdERpcn1gXSwgYXJndi5jd2QpO1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInN0YXJ0XCIsIFwiLS1hdHRhY2hcIiwgY29udGFpbmVySWRdLCBhcmd2LmN3ZCk7XG4gICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwicm1cIiwgXCItdmZcIiwgY29udGFpbmVySWRdLCBhcmd2LmN3ZCk7XG4gICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gcHJvY2Vzcy5ocnRpbWUodGltZSk7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBjb3BpZWQgdG8gJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gdm9sdW1lc30gaW4ge21hZ2VudGEgJHtwcmV0dHlIcnRpbWUoZW5kVGltZSl9fVxcbmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2VydmljZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gYGhvc3RgIGFuZCBgbm9uZWAgbmV0d29ya3MgZG8gbm90IHdvcmsgd2l0aCBzZXJ2aWNlcyBiZWNhdXNlIGFsaWFzZXMgb25seSB3b3JrIGZvclxuICAgICAgICAgICAgLy8gdXNlciBkZWZpbmVkIG5ldHdvcmtzLlxuICAgICAgICAgICAgZm9yIChjb25zdCBuZXR3b3JrIG9mIHRoaXMuYXJndi5uZXR3b3JrKSB7XG4gICAgICAgICAgICAgICAgaWYgKFtcImhvc3RcIiwgXCJub25lXCJdLmluY2x1ZGVzKG5ldHdvcmspKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogYENhbm5vdCBhZGQgc2VydmljZSBuZXR3b3JrIGFsaWFzIHdpdGggbmV0d29yayBtb2RlICcke25ldHdvcmt9J2B9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRG9ja2VyTmV0d29yayhgZ2l0bGFiLWNpLWxvY2FsLSR7dGhpcy5qb2JJZH1gKTtcblxuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2aWNlcy5tYXAoYXN5bmMgKHNlcnZpY2UsIHNlcnZpY2VJbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXJ2aWNlTmFtZSA9IHNlcnZpY2UubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wdWxsSW1hZ2Uod3JpdGVTdHJlYW1zLCBzZXJ2aWNlTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlcnZpY2VDb250YWluZXJJZCA9IGF3YWl0IHRoaXMuc3RhcnRTZXJ2aWNlKHdyaXRlU3RyZWFtcywgVXRpbHMuZXhwYW5kVmFyaWFibGVzKHsuLi5leHBhbmRlZCwgLi4uc2VydmljZS52YXJpYWJsZXN9KSwgc2VydmljZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlcnZpY2VDb250YWluZXJMb2dGaWxlID0gYCR7YXJndi5jd2R9LyR7YXJndi5zdGF0ZURpcn0vc2VydmljZXMtb3V0cHV0LyR7dGhpcy5zYWZlSm9iTmFtZX0vJHtzZXJ2aWNlTmFtZX0tJHtzZXJ2aWNlSW5kZXh9LmxvZ2A7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VydmljZUhlYWx0aENoZWNrKHdyaXRlU3RyZWFtcywgc2VydmljZSwgc2VydmljZUluZGV4LCBzZXJ2aWNlQ29udGFpbmVyTG9nRmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHtzdGRvdXQsIHN0ZGVycn0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwibG9nc1wiLCBzZXJ2aWNlQ29udGFpbmVySWRdKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZnMuZW5zdXJlRmlsZShzZXJ2aWNlQ29udGFpbmVyTG9nRmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGZzLnByb21pc2VzLndyaXRlRmlsZShzZXJ2aWNlQ29udGFpbmVyTG9nRmlsZSwgYCMjIyBzdGRvdXQgIyMjXFxuJHtzdGRvdXR9XFxuIyMjIHN0ZGVyciAjIyNcXG4ke3N0ZGVycn1cXG5gKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLmV4ZWNQcmVTY3JpcHRzKGV4cGFuZGVkKTtcbiAgICAgICAgaWYgKHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSA9PSBudWxsKSB0aHJvdyBFcnJvcihcInRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSBtdXN0IGJlIGRlZmluZWQhXCIpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuZXhlY0FmdGVyU2NyaXB0cyhleHBhbmRlZCk7XG5cbiAgICAgICAgdGhpcy5fcnVubmluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9lbmRUaW1lID0gdGhpcy5fZW5kVGltZSA/PyBwcm9jZXNzLmhydGltZSh0aGlzLl9zdGFydFRpbWUpO1xuICAgICAgICB0aGlzLnByaW50RmluaXNoZWRTdHJpbmcoKTtcblxuICAgICAgICBhd2FpdCB0aGlzLmNvcHlDYWNoZU91dCh0aGlzLndyaXRlU3RyZWFtcywgZXhwYW5kZWQpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvcHlBcnRpZmFjdHNPdXQodGhpcy53cml0ZVN0cmVhbXMsIGV4cGFuZGVkKTtcblxuICAgICAgICBpZiAodGhpcy5qb2JEYXRhW1wiY292ZXJhZ2VcIl0pIHtcbiAgICAgICAgICAgIHRoaXMuX2NvdmVyYWdlUGVyY2VudCA9IGF3YWl0IFV0aWxzLmdldENvdmVyYWdlUGVyY2VudChhcmd2LmN3ZCwgYXJndi5zdGF0ZURpciwgdGhpcy5qb2JEYXRhW1wiY292ZXJhZ2VcIl0sIHNhZmVKb2JOYW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGNsZWFudXBSZXNvdXJjZXMgKCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fbG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KTtcblxuICAgICAgICBpZiAoIXRoaXMuYXJndi5jbGVhbnVwKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInJtXCIsIFwiLXZmXCIsIC4uLnRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuXSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KGUgaW5zdGFuY2VvZiBFcnJvciwgXCJlIGlzIG5vdCBpbnN0YW5jZW9mIEVycm9yXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX3NlcnZpY2VOZXR3b3JrSWQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcIm5ldHdvcmtcIiwgXCJybVwiLCBgJHt0aGlzLl9zZXJ2aWNlTmV0d29ya0lkfWBdKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoZSBpbnN0YW5jZW9mIEVycm9yLCBcImUgaXMgbm90IGluc3RhbmNlb2YgRXJyb3JcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY29udGFpbmVyVm9sdW1lTmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwidm9sdW1lXCIsIFwicm1cIiwgLi4udGhpcy5fY29udGFpbmVyVm9sdW1lTmFtZXNdKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoZSBpbnN0YW5jZW9mIEVycm9yLCBcImUgaXMgbm90IGluc3RhbmNlb2YgRXJyb3JcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBybVByb21pc2VzID0gW107XG4gICAgICAgIGZvciAoY29uc3QgZmlsZSBvZiB0aGlzLl9maWxlc1RvUm0pIHtcbiAgICAgICAgICAgIHJtUHJvbWlzZXMucHVzaChmcy5ybShmaWxlLCB7cmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZX0pKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChybVByb21pc2VzKTtcblxuICAgICAgICBjb25zdCBmaWxlVmFyaWFibGVzRGlyID0gdGhpcy5maWxlVmFyaWFibGVzRGlyO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgZnMucm0oZmlsZVZhcmlhYmxlc0Rpciwge3JlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWV9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgYXNzZXJ0KGUgaW5zdGFuY2VvZiBFcnJvciwgXCJlIGlzIG5vdCBpbnN0YW5jZW9mIEVycm9yXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZUluamVjdFNTSEFnZW50T3B0aW9ucyAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pbmplY3RTU0hBZ2VudCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09IFwiZGFyd2luXCIgfHwgL15kYXJ3aW4vLmV4ZWMocHJvY2Vzcy5lbnYuT1NUWVBFID8/IFwiXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gXCItLWVudiBTU0hfQVVUSF9TT0NLPS9ydW4vaG9zdC1zZXJ2aWNlcy9zc2gtYXV0aC5zb2NrIC12IC9ydW4vaG9zdC1zZXJ2aWNlcy9zc2gtYXV0aC5zb2NrOi9ydW4vaG9zdC1zZXJ2aWNlcy9zc2gtYXV0aC5zb2NrXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGAtLWVudiBTU0hfQVVUSF9TT0NLPSR7cHJvY2Vzcy5lbnYuU1NIX0FVVEhfU09DS30gLXYgJHtwcm9jZXNzLmVudi5TU0hfQVVUSF9TT0NLfToke3Byb2Nlc3MuZW52LlNTSF9BVVRIX1NPQ0t9YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlU2NyaXB0Q29tbWFuZHMgKHNjcmlwdHM6IHN0cmluZ1tdKSB7XG4gICAgICAgIGxldCBjbWQgPSBcIlwiO1xuICAgICAgICBzY3JpcHRzLmZvckVhY2goKHNjcmlwdCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3BsaXQgPSBzY3JpcHQuc3BsaXQoL1xccj9cXG4vKTtcbiAgICAgICAgICAgIGNvbnN0IG11bHRpbGluZVRleHQgPSBzcGxpdC5sZW5ndGggPiAxID8gXCIgIyBjb2xsYXBzZWQgbXVsdGktbGluZSBjb21tYW5kXCIgOiBcIlwiO1xuICAgICAgICAgICAgY29uc3QgdGV4dCA9IHNwbGl0WzBdPy5yZXBsYWNlKC9cXFxcL2csIFwiXFxcXFxcXFxcIikucmVwbGFjZSgvXCIvZywgXCJcXFxcXFxcIlwiKS5yZXBsYWNlKC9bJF0vZywgXCJcXFxcJFwiKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmludGVyYWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgY21kICs9IGNoYWxrYGVjaG8gXCJ7Z3JlZW4gJCAke3RleHR9JHttdWx0aWxpbmVUZXh0fX1cIlxcbmA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFByaW50IGNvbW1hbmQgZWNobydlZCB3aXRoICRHQ0xfU0hFTExfUFJPTVBUX1BMQUNFSE9MREVSXG4gICAgICAgICAgICAgICAgY21kICs9IGBlY2hvIFwiJHtHQ0xfU0hFTExfUFJPTVBUX1BMQUNFSE9MREVSfSAke3RleHR9JHttdWx0aWxpbmVUZXh0fVwiXFxuYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgYWN0dWFsIHNjcmlwdFxuICAgICAgICAgICAgY21kICs9IGAke3NjcmlwdH1cXG5gO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNtZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIG1vdW50Q2FjaGVDbWQgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgaWYgKHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSAmJiAhdGhpcy5hcmd2Lm1vdW50Q2FjaGUpIHJldHVybiBbXTtcblxuICAgICAgICBjb25zdCBjbWQ6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGZvciAoY29uc3QgW2luZGV4LCBjXSBvZiB0aGlzLmNhY2hlLmVudHJpZXMoKSkge1xuICAgICAgICAgICAgY29uc3QgdW5pcXVlQ2FjaGVOYW1lID0gYXdhaXQgdGhpcy5nZXRVbmlxdWVDYWNoZU5hbWUodGhpcy5hcmd2LmN3ZCwgZXhwYW5kZWQsIGluZGV4KTtcbiAgICAgICAgICAgIGMucGF0aHMuZm9yRWFjaCgocCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhdGggPSBVdGlscy5leHBhbmRUZXh0KHAsIGV4cGFuZGVkKTtcbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBtb3VudGluZyBjYWNoZX0gZm9yIHBhdGggJHtwYXRofVxcbmApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhY2hlTW91bnQgPSBVdGlscy5zYWZlRG9ja2VyU3RyaW5nKGBnY2wtJHtleHBhbmRlZC5DSV9QUk9KRUNUX1BBVEhfU0xVR30tJHt1bmlxdWVDYWNoZU5hbWV9YCk7XG4gICAgICAgICAgICAgICAgY21kLnB1c2goXCItdlwiLCBgJHtjYWNoZU1vdW50fToke3RoaXMuY2lQcm9qZWN0RGlyfS8ke3BhdGh9YCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY21kO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZXhlY1ByZVNjcmlwdHMgKGV4cGFuZGVkOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBwcmVzY3JpcHRzID0gdGhpcy5iZWZvcmVTY3JpcHRzLmNvbmNhdCh0aGlzLnNjcmlwdHMpO1xuICAgICAgICBleHBhbmRlZFtcIkNJX0pPQl9TVEFUVVNcIl0gPSBcInJ1bm5pbmdcIjtcblxuICAgICAgICB0aGlzLl9wcmVzY3JpcHRzRXhpdENvZGUgPSBhd2FpdCB0aGlzLmV4ZWNTY3JpcHRzKHByZXNjcmlwdHMsIGV4cGFuZGVkLCBcIlwiKTtcbiAgICAgICAgZXhwYW5kZWRbXCJDSV9KT0JfU1RBVFVTXCJdID0gdGhpcy5fcHJlc2NyaXB0c0V4aXRDb2RlID09PSAwID8gXCJzdWNjZXNzXCIgOiBcImZhaWxlZFwiO1xuXG4gICAgICAgIHRoaXMucHJpbnRFeGl0ZWRTdHJpbmcodGhpcy5fcHJlc2NyaXB0c0V4aXRDb2RlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGV4ZWNBZnRlclNjcmlwdHMgKGV4cGFuZGVkOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gXCJSdW5uaW5nIGFmdGVyIHNjcmlwdC4uLlwiO1xuICAgICAgICB0aGlzLl9hZnRlclNjcmlwdHNFeGl0Q29kZSA9IGF3YWl0IHRoaXMuZXhlY1NjcmlwdHModGhpcy5hZnRlclNjcmlwdHMsIGV4cGFuZGVkLCBtZXNzYWdlKTtcblxuICAgICAgICB0aGlzLnByaW50QWZ0ZXJTY3JpcHRFeGl0ZWRTdHJpbmcodGhpcy5fYWZ0ZXJTY3JpcHRzRXhpdENvZGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZXhlY1NjcmlwdHMgKHNjcmlwdHM6IHN0cmluZ1tdLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30sIG1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgICAgIGNvbnN0IGN3ZCA9IHRoaXMuYXJndi5jd2Q7XG4gICAgICAgIGNvbnN0IHN0YXRlRGlyID0gdGhpcy5hcmd2LnN0YXRlRGlyO1xuICAgICAgICBjb25zdCBzYWZlSm9iTmFtZSA9IHRoaXMuc2FmZUpvYk5hbWU7XG4gICAgICAgIGNvbnN0IG91dHB1dEZpbGVzUGF0aCA9IGAke2N3ZH0vJHtzdGF0ZURpcn0vb3V0cHV0LyR7c2FmZUpvYk5hbWV9LmxvZ2A7XG4gICAgICAgIGNvbnN0IGJ1aWxkVm9sdW1lTmFtZSA9IHRoaXMuYnVpbGRWb2x1bWVOYW1lO1xuICAgICAgICBjb25zdCB0bXBWb2x1bWVOYW1lID0gdGhpcy50bXBWb2x1bWVOYW1lO1xuICAgICAgICBjb25zdCBpbWFnZU5hbWUgPSB0aGlzLmltYWdlTmFtZShleHBhbmRlZCk7XG4gICAgICAgIGNvbnN0IHdyaXRlU3RyZWFtcyA9IHRoaXMud3JpdGVTdHJlYW1zO1xuXG4gICAgICAgIGlmIChzY3JpcHRzLmxlbmd0aCA9PT0gMCB8fCBzY3JpcHRzWzBdID09IG51bGwpIHJldHVybiAwO1xuXG4gICAgICAgIGlmIChtZXNzYWdlLmxlbmd0aCA+IDApIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHttYWdlbnRhQnJpZ2h0ICR7bWVzc2FnZX19XFxuYCk7XG5cbiAgICAgICAgYXdhaXQgZnMucmVtb3ZlKGAke2N3ZH0vJHtzdGF0ZURpcn0vYXJ0aWZhY3RzLyR7c2FmZUpvYk5hbWV9YCk7XG5cbiAgICAgICAgLy8gQ29weSBnaXQgdHJhY2tlZCBmaWxlcyB0byBidWlsZCBmb2xkZXIgaWYgc2hlbGwgaXNvbGF0aW9uIGVuYWJsZWQuXG4gICAgICAgIGlmICghaW1hZ2VOYW1lICYmIHRoaXMuYXJndi5zaGVsbElzb2xhdGlvbikge1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMucnN5bmNUcmFja2VkRmlsZXMoY3dkLCBzdGF0ZURpciwgYCR7c2FmZUpvYk5hbWV9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgbGV0IGlDbWQgPSBcInNldCAtZW8gcGlwZWZhaWxcXG5cIjtcbiAgICAgICAgICAgIGlDbWQgKz0gdGhpcy5nZW5lcmF0ZVNjcmlwdENvbW1hbmRzKHNjcmlwdHMpO1xuXG4gICAgICAgICAgICBjb25zdCBpbnRlcmFjdGl2ZUNwID0gZXhlY2EoaUNtZCwge1xuICAgICAgICAgICAgICAgIGN3ZCxcbiAgICAgICAgICAgICAgICBzaGVsbDogXCJiYXNoXCIsXG4gICAgICAgICAgICAgICAgc3RkaW86IFtcImluaGVyaXRcIiwgXCJpbmhlcml0XCIsIFwiaW5oZXJpdFwiXSxcbiAgICAgICAgICAgICAgICBlbnY6IHsuLi5leHBhbmRlZCwgLi4ucHJvY2Vzcy5lbnZ9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8bnVtYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdm9pZCBpbnRlcmFjdGl2ZUNwLm9uKFwiZXhpdFwiLCAoY29kZSkgPT4gcmVzb2x2ZShjb2RlID8/IDApKTtcbiAgICAgICAgICAgICAgICB2b2lkIGludGVyYWN0aXZlQ3Aub24oXCJlcnJvclwiLCAoZXJyKSA9PiByZWplY3QoZXJyKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFyZ3YucmVnaXN0cnkpIHtcbiAgICAgICAgICAgIGV4cGFuZGVkW1wiQ0lfUkVHSVNUUllfVVNFUlwiXSA9IGV4cGFuZGVkW1wiQ0lfUkVHSVNUUllfVVNFUlwiXSA/PyBgJHtVdGlscy5nY2xSZWdpc3RyeVByZWZpeH0udXNlcmA7XG4gICAgICAgICAgICBleHBhbmRlZFtcIkNJX1JFR0lTVFJZX1BBU1NXT1JEXCJdID0gZXhwYW5kZWRbXCJDSV9SRUdJU1RSWV9QQVNTV09SRFwiXSA/PyBgJHtVdGlscy5nY2xSZWdpc3RyeVByZWZpeH0ucGFzc3dvcmRgO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZWZyZXNoTG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KHdyaXRlU3RyZWFtcyk7XG5cbiAgICAgICAgaWYgKGltYWdlTmFtZSAmJiAhdGhpcy5fY29udGFpbmVySWQpIHtcbiAgICAgICAgICAgIGxldCBkb2NrZXJDbWQgPSBgJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gY3JlYXRlIC0taW50ZXJhY3RpdmUgJHt0aGlzLmdlbmVyYXRlSW5qZWN0U1NIQWdlbnRPcHRpb25zKCl9IGA7XG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LnByaXZpbGVnZWQpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCItLXByaXZpbGVnZWQgXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgZGV2aWNlIG9mIHRoaXMuYXJndi5kZXZpY2UpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tZGV2aWNlICR7ZGV2aWNlfSBgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LnVsaW1pdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS11bGltaXQgbm9maWxlPSR7dGhpcy5hcmd2LnVsaW1pdH0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi51bWFzaykge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIi0tdXNlciAwOjAgXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmFyZ3YudXNlcm5zICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS11c2VybnM9JHt0aGlzLmFyZ3YudXNlcm5zfSBgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LmNvbnRhaW5lck1hY0FkZHJlc3MpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tbWFjLWFkZHJlc3MgXCIke3RoaXMuYXJndi5jb250YWluZXJNYWNBZGRyZXNzfVwiIGA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGltYWdlVXNlciA9IHRoaXMuaW1hZ2VVc2VyKGV4cGFuZGVkKTtcbiAgICAgICAgICAgIGlmIChpbWFnZVVzZXIpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdXNlciAke2ltYWdlVXNlcn0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi5jb250YWluZXJFbXVsYXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcnVubmVyTmFtZTogc3RyaW5nID0gdGhpcy5hcmd2LmNvbnRhaW5lckVtdWxhdGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIUdpdGxhYlJ1bm5lclByZXNldFZhbHVlcy5pbmNsdWRlcyhydW5uZXJOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGdpdGxhYiBydW5uZXIgdG8gZW11bGF0ZS5cIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgbWVtb3J5Q29uZmlnID0gR2l0bGFiUnVubmVyTWVtb3J5UHJlc2V0VmFsdWVbcnVubmVyTmFtZV07XG4gICAgICAgICAgICAgICAgY29uc3QgY3B1Q29uZmlnID0gR2l0bGFiUnVubmVyQ1BVc1ByZXNldFZhbHVlW3J1bm5lck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLW1lbW9yeT0ke21lbW9yeUNvbmZpZ31tIGA7XG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLWtlcm5lbC1tZW1vcnk9JHttZW1vcnlDb25maWd9bSBgO1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS1jcHVzPSR7Y3B1Q29uZmlnfSBgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBob3N0IGFuZCBub25lIG5ldHdvcmtzIGhhdmUgdG8gYmUgc3BlY2lmaWVkIHVzaW5nIC0tbmV0d29yaywgc2luY2UgdGhleSBjYW5ub3QgYmUgdXNlZCB3aXRoXG4gICAgICAgICAgICAvLyBgZG9ja2VyIG5ldHdvcmsgY29ubmVjdGAuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5ldHdvcmsgb2YgdGhpcy5hcmd2Lm5ldHdvcmspIHtcbiAgICAgICAgICAgICAgICBpZiAoW1wiaG9zdFwiLCBcIm5vbmVcIl0uaW5jbHVkZXMobmV0d29yaykpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLW5ldHdvcmsgJHtuZXR3b3JrfSBgO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRoZSBkZWZhdWx0IHBvZG1hbiBuZXR3b3JrIG1vZGUgaXMgbm90IGBicmlkZ2VgLCB3aGljaCBtZWFucyBhIGBwb2RtYW4gbmV0d29yayBjb25uZWN0YCBjYWxsIHdpbGwgZmFpbFxuICAgICAgICAgICAgLy8gd2hlbiBjb25uZWN0aW5nIHVzZXIgZGVmaW5lZCBuZXR3b3Jrcy4gVGhlIHdvcmthcm91bmQgaXMgdG8gdXNlIGEgdXNlciBkZWZpbmVkIG5ldHdvcmsgb24gY29udGFpbmVyXG4gICAgICAgICAgICAvLyBjcmVhdGlvbi5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2NvbnRhaW5lcnMvcG9kbWFuL2lzc3Vlcy8xOTU3N1xuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFRoaXMgc2hvdWxkIG5vdCBjbGFzaCB3aXRoIHRoZSBgaG9zdGAgYW5kIGBub25lYCBuZXR3b3JrcyBhYm92ZSwgc2luY2Ugc2VydmljZSBjcmVhdGlvbiBzaG91bGQgaGF2ZVxuICAgICAgICAgICAgLy8gZmFpbGVkIHdoZW4gdXNpbmcgYGhvc3RgIG9yIGBub25lYCBuZXR3b3Jrcy5cbiAgICAgICAgICAgIGlmICh0aGlzLl9zZXJ2aWNlTmV0d29ya0lkKSB7XG4gICAgICAgICAgICAgICAgLy8gYGJ1aWxkYCBhbGlhczogaHR0cHM6Ly9naXRsYWIuY29tL2dpdGxhYi1vcmcvZ2l0bGFiLXJ1bm5lci8tL2lzc3Vlcy8yNzA2MFxuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS1uZXR3b3JrICR7dGhpcy5fc2VydmljZU5ldHdvcmtJZH0gLS1uZXR3b3JrLWFsaWFzIGJ1aWxkIGA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmFyZ3YucmVnaXN0cnkpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tbmV0d29yayAke1V0aWxzLmdjbFJlZ2lzdHJ5UHJlZml4fS5uZXQgYDtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7VXRpbHMuZ2NsUmVnaXN0cnlQcmVmaXh9LmNlcnRzOi9ldGMvY29udGFpbmVycy9jZXJ0cy5kOnJvIGA7XG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLXZvbHVtZSAke1V0aWxzLmdjbFJlZ2lzdHJ5UHJlZml4fS5jZXJ0czovZXRjL2RvY2tlci9jZXJ0cy5kOnJvIGA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS12b2x1bWUgJHtidWlsZFZvbHVtZU5hbWV9OiR7dGhpcy5jaVByb2plY3REaXJ9IGA7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7dG1wVm9sdW1lTmFtZX06JHt0aGlzLmZpbGVWYXJpYWJsZXNEaXJ9IGA7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0td29ya2RpciAke3RoaXMuY2lQcm9qZWN0RGlyfSBgO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHZvbHVtZSBvZiB0aGlzLmFyZ3Yudm9sdW1lKSB7XG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLXZvbHVtZSAke3ZvbHVtZX0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChjb25zdCBleHRyYUhvc3Qgb2YgdGhpcy5hcmd2LmV4dHJhSG9zdCkge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS1hZGQtaG9zdD0ke2V4dHJhSG9zdH0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi5jYUZpbGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjYUZpbGVQYXRoID0gcGF0aC5pc0Fic29sdXRlKHRoaXMuYXJndi5jYUZpbGUpID8gdGhpcy5hcmd2LmNhRmlsZSA6IHBhdGgucmVzb2x2ZSh0aGlzLmFyZ3YuY3dkLCB0aGlzLmFyZ3YuY2FGaWxlKTtcbiAgICAgICAgICAgICAgICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhjYUZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7Y2FGaWxlUGF0aH06L2V0Yy9zc2wvY2VydHMvY2EtY2VydGlmaWNhdGVzLmNydDpybyBgO1xuICAgICAgICAgICAgICAgICAgICBleHBhbmRlZFtcIlNTTF9DRVJUX0ZJTEVcIl0gPSBcIi9ldGMvc3NsL2NlcnRzL2NhLWNlcnRpZmljYXRlcy5jcnRcIjtcbiAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWRbXCJTU0xfQ0VSVF9ESVJcIl0gPSBcIi9ldGMvc3NsL2NlcnRzXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93IFdBUk5JTkc6IENBIGZpbGUgbm90IGZvdW5kOiAke2NhRmlsZVBhdGh9fVxcbmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWxdIG9mIE9iamVjdC5lbnRyaWVzKGV4cGFuZGVkKSkge1xuICAgICAgICAgICAgICAgIC8vIFJlcGxhY2luZyBgJ2Agd2l0aCBgJ1xcJydgIHRvIGNvcnJlY3RseSBoYW5kbGUgc2luZ2xlIHF1b3RlcyhpZiBgdmFsYCBjb250YWlucyBgJ2ApIGluIHNoZWxsIGNvbW1hbmRzXG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAgIC1lICcke2tleX09JHt2YWwudG9TdHJpbmcoKS5yZXBsYWNlKC8nL2csIFwiJ1xcXFwnJ1wiKX0nIFxcXFxcXG5gO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5pbWFnZUVudHJ5cG9pbnQpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tZW50cnlwb2ludCAke1V0aWxzLnNhZmVCYXNoU3RyaW5nKHRoaXMuaW1hZ2VFbnRyeXBvaW50WzBdKX0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAkeyhhd2FpdCB0aGlzLm1vdW50Q2FjaGVDbWQod3JpdGVTdHJlYW1zLCBleHBhbmRlZCkpLmpvaW4oXCIgXCIpfSBgO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAke2ltYWdlTmFtZX0gYDtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaW1hZ2VFbnRyeXBvaW50Py5sZW5ndGggPz8gMCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmltYWdlRW50cnlwb2ludD8uc2xpY2UoMSkuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYCR7VXRpbHMuc2FmZUJhc2hTdHJpbmcoZSl9IGA7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcInNoIC1jIFxcXCJcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcImlmIFsgLXggL3Vzci9sb2NhbC9iaW4vYmFzaCBdOyB0aGVuXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJcXHRleGVjIC91c3IvbG9jYWwvYmluL2Jhc2ggXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJlbGlmIFsgLXggL3Vzci9iaW4vYmFzaCBdOyB0aGVuXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJcXHRleGVjIC91c3IvYmluL2Jhc2ggXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJlbGlmIFsgLXggL2Jpbi9iYXNoIF07IHRoZW5cXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4ZWMgL2Jpbi9iYXNoIFxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiZWxpZiBbIC14IC91c3IvbG9jYWwvYmluL3NoIF07IHRoZW5cXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4ZWMgL3Vzci9sb2NhbC9iaW4vc2ggXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJlbGlmIFsgLXggL3Vzci9iaW4vc2ggXTsgdGhlblxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiXFx0ZXhlYyAvdXNyL2Jpbi9zaCBcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcImVsaWYgWyAteCAvYmluL3NoIF07IHRoZW5cXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4ZWMgL2Jpbi9zaCBcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcImVsaWYgWyAteCAvYnVzeWJveC9zaCBdOyB0aGVuXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJcXHRleGVjIC9idXN5Ym94L3NoIFxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiZWxzZVxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiXFx0ZWNobyBzaGVsbCBub3QgZm91bmRcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4aXQgMVxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiZmlcXG5cXFwiXCI7XG5cbiAgICAgICAgICAgIGNvbnN0IHtzdGRvdXQ6IGNvbnRhaW5lcklkfSA9IGF3YWl0IFV0aWxzLmJhc2goZG9ja2VyQ21kLCBjd2QpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5ldHdvcmsgb2YgdGhpcy5hcmd2Lm5ldHdvcmspIHtcbiAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIG5ldHdvcmsgbmFtZXMgdGhhdCBkbyBub3Qgd29yayB3aXRoIGBkb2NrZXIgbmV0d29yayBjb25uZWN0YFxuICAgICAgICAgICAgICAgIGlmIChbXCJob3N0XCIsIFwibm9uZVwiXS5pbmNsdWRlcyhuZXR3b3JrKSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcIm5ldHdvcmtcIiwgXCJjb25uZWN0XCIsIG5ldHdvcmssIGAke2NvbnRhaW5lcklkfWBdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fY29udGFpbmVySWQgPSBjb250YWluZXJJZDtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLnB1c2godGhpcy5fY29udGFpbmVySWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5jb3B5Q2FjaGVJbih3cml0ZVN0cmVhbXMsIGV4cGFuZGVkKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jb3B5QXJ0aWZhY3RzSW4od3JpdGVTdHJlYW1zKTtcblxuICAgICAgICBsZXQgY21kID0gXCJzZXQgLWVvIHBpcGVmYWlsXFxuXCI7XG4gICAgICAgIGNtZCArPSBcImV4ZWMgMDwgL2Rldi9udWxsXFxuXCI7XG5cbiAgICAgICAgaWYgKCFpbWFnZU5hbWUgJiYgdGhpcy5hcmd2LnNoZWxsSXNvbGF0aW9uKSB7XG4gICAgICAgICAgICBjbWQgKz0gYGNkICR7c3RhdGVEaXJ9L2J1aWxkcy8ke3NhZmVKb2JOYW1lfS9cXG5gO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGltYWdlTmFtZSkge1xuICAgICAgICAgICAgY21kICs9IGBjZCAke3RoaXMuY2lQcm9qZWN0RGlyfSBcXG5gO1xuXG4gICAgICAgICAgICBpZiAoZXhwYW5kZWRbXCJDSV9KT0JfU1RBVFVTXCJdICE9IFwicnVubmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgLy8gRW5zdXJlcyB0aGUgZW52IGBDSV9KT0JfU1RBVFVTYCBpcyBwYXNzZWQgdG8gdGhlIGFmdGVyX3NjcmlwdCBjb250ZXh0XG4gICAgICAgICAgICAgICAgY21kICs9IGBleHBvcnQgQ0lfSk9CX1NUQVRVUz0ke2V4cGFuZGVkW1wiQ0lfSk9CX1NUQVRVU1wiXX1cXG5gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNtZCArPSB0aGlzLmdlbmVyYXRlU2NyaXB0Q29tbWFuZHMoc2NyaXB0cyk7XG5cbiAgICAgICAgY21kICs9IFwiZXhpdCAwXFxuXCI7XG5cbiAgICAgICAgY29uc3Qgam9iU2NyaXB0RmlsZSA9IGAke2N3ZH0vJHtzdGF0ZURpcn0vc2NyaXB0cy8ke3NhZmVKb2JOYW1lfV8ke3RoaXMuam9iSWR9YDtcbiAgICAgICAgYXdhaXQgZnMub3V0cHV0RmlsZShqb2JTY3JpcHRGaWxlLCBjbWQsIFwidXRmLThcIik7XG4gICAgICAgIGF3YWl0IGZzLmNobW9kKGpvYlNjcmlwdEZpbGUsIFwiMDc1NVwiKTtcbiAgICAgICAgdGhpcy5fZmlsZXNUb1JtLnB1c2goam9iU2NyaXB0RmlsZSk7XG5cbiAgICAgICAgaWYgKGltYWdlTmFtZSkge1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcImNwXCIsIGAke3N0YXRlRGlyfS9zY3JpcHRzLyR7c2FmZUpvYk5hbWV9XyR7dGhpcy5qb2JJZH1gLCBgJHt0aGlzLl9jb250YWluZXJJZH06L2djbC1jbWRgXSwgY3dkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNwID0gZXhlY2EodGhpcy5fY29udGFpbmVySWQgPyBgJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gc3RhcnQgLS1hdHRhY2ggLWkgJHt0aGlzLl9jb250YWluZXJJZH1gIDogXCJiYXNoXCIsIHtcbiAgICAgICAgICAgIGN3ZCxcbiAgICAgICAgICAgIHNoZWxsOiBcImJhc2hcIixcbiAgICAgICAgICAgIGVudjogaW1hZ2VOYW1lID8gcHJvY2Vzcy5lbnYgOiBleHBhbmRlZCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnRyb2wtcmVnZXhcbiAgICAgICAgY29uc3Qgc2VjdGlvblJlZ2V4ID0gL1xceDFiXFxbMEtzZWN0aW9uXyhzdGFydHxlbmQpOihcXGQrKTooW15cXHNbXSspKD86XFxbW15cXF1dKlxcXSk/XFxyXFx4MWJcXFswSy87XG4gICAgICAgIGNvbnN0IHNlY3Rpb25TdGFydFRpbWVzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICAgICAgICBjb25zdCBvdXRGdW5jID0gKGxpbmU6IHN0cmluZywgc3RyZWFtOiAodHh0OiBzdHJpbmcpID0+IHZvaWQsIGNvbG9yaXplOiAoc3RyOiBzdHJpbmcpID0+IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoTG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KHdyaXRlU3RyZWFtcyk7XG5cbiAgICAgICAgICAgIGNvbnN0IG0gPSBzZWN0aW9uUmVnZXguZXhlYyhsaW5lKTtcbiAgICAgICAgICAgIGxldCBpc1NlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChtKSB7XG4gICAgICAgICAgICAgICAgaXNTZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAobVsxXSA9PT0gXCJzdGFydFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb25TdGFydFRpbWVzLnNldChtWzNdLCBEYXRlLm5vdygpKTtcbiAgICAgICAgICAgICAgICAgICAgbGluZSA9IGNoYWxrYHtjeWFuQnJpZ2h0ICR7bVszXX1fc3RhcnRlZH1gO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVsYXBzZWQgPSBEYXRlLm5vdygpIC0gKHNlY3Rpb25TdGFydFRpbWVzLmdldChtWzNdKSA/PyBEYXRlLm5vdygpKTtcbiAgICAgICAgICAgICAgICAgICAgbGluZSA9IGNoYWxrYHtjeWFuQnJpZ2h0ICR7bVszXX19IHRvb2sge21hZ2VudGEgJHtlbGFwc2VkfW1zfWA7XG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb25TdGFydFRpbWVzLmRlbGV0ZShtWzNdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN0cmVhbShgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IGApO1xuICAgICAgICAgICAgaWYgKGxpbmUuc3RhcnRzV2l0aChHQ0xfU0hFTExfUFJPTVBUX1BMQUNFSE9MREVSKSkge1xuICAgICAgICAgICAgICAgIC8vIHJlcGxhY2UgdGhlIEdDTF9TSEVMTF9QUk9NUFRfUExBQ0VIT0xERVIgd2l0aCBgJGAgYW5kIG1ha2UgdGhlIFNIRUxMX1BST01QVCBsaW5lIGdyZWVuIGNvbG9yXG4gICAgICAgICAgICAgICAgbGluZSA9IGxpbmUuc2xpY2UoR0NMX1NIRUxMX1BST01QVF9QTEFDRUhPTERFUi5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGxpbmUgPSBjaGFsa2B7Z3JlZW4gJCR7bGluZX19YDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzU2VjdGlvbikge1xuICAgICAgICAgICAgICAgIHN0cmVhbShgJHtjb2xvcml6ZShcIj5cIil9IGApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RyZWFtKGAke2xpbmV9XFxuYCk7XG4gICAgICAgICAgICBmcy5hcHBlbmRGaWxlU3luYyhvdXRwdXRGaWxlc1BhdGgsIGAke2xpbmV9XFxuYCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcXVpZXQgPSB0aGlzLmFyZ3YucXVpZXQ7XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IG5ldyBQcm9taXNlPG51bWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFxdWlldCkge1xuICAgICAgICAgICAgICAgIGNwLnN0ZG91dD8ucGlwZShzcGxpdDIoKSkub24oXCJkYXRhXCIsIChlOiBzdHJpbmcpID0+IG91dEZ1bmMoZSwgd3JpdGVTdHJlYW1zLnN0ZG91dC5iaW5kKHdyaXRlU3RyZWFtcyksIChzKSA9PiBjaGFsa2B7Z3JlZW5CcmlnaHQgJHtzfX1gKSk7XG4gICAgICAgICAgICAgICAgY3Auc3RkZXJyPy5waXBlKHNwbGl0MigpKS5vbihcImRhdGFcIiwgKGU6IHN0cmluZykgPT4gb3V0RnVuYyhlLCB3cml0ZVN0cmVhbXMuc3RkZXJyLmJpbmQod3JpdGVTdHJlYW1zKSwgKHMpID0+IGNoYWxrYHtyZWRCcmlnaHQgJHtzfX1gKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2b2lkIGNwLm9uKFwiZXhpdFwiLCAoY29kZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGNvZGUgPz8gMCk7fSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB2b2lkIGNwLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoaW1hZ2VOYW1lKSB7XG4gICAgICAgICAgICAgICAgY3Auc3RkaW4/LmVuZChcIi4gL2djbC1jbWRcIik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNwLnN0ZGluPy5lbmQoYC4vJHtzdGF0ZURpcn0vc2NyaXB0cy8ke3NhZmVKb2JOYW1lfV8ke3RoaXMuam9iSWR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW1hZ2VOYW1lICh2YXJzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSA9IHt9KTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIGlmICh0aGlzLmFyZ3YuZm9yY2VTaGVsbEV4ZWN1dG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuam9iRGF0YVtcImltYWdlXCJdO1xuICAgICAgICBpZiAoIWltYWdlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LnNoZWxsRXhlY3V0b3JOb0ltYWdlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL2NpL3J1bm5lcnMvaG9zdGVkX3J1bm5lcnMvbGludXguaHRtbCNjb250YWluZXItaW1hZ2VzXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXJndi5kZWZhdWx0SW1hZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModmFycyk7XG4gICAgICAgIGNvbnN0IGltYWdlTmFtZSA9IFV0aWxzLmV4cGFuZFRleHQoaW1hZ2UubmFtZSwgZXhwYW5kZWQpO1xuICAgICAgICByZXR1cm4gaW1hZ2VOYW1lLmluY2x1ZGVzKFwiOlwiKSA/IGltYWdlTmFtZSA6IGAke2ltYWdlTmFtZX06bGF0ZXN0YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGltYWdlVXNlciAodmFyczoge1trZXk6IHN0cmluZ106IHN0cmluZ30gPSB7fSk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuam9iRGF0YVtcImltYWdlXCJdO1xuICAgICAgICBpZiAoIWltYWdlKSByZXR1cm4gbnVsbDtcbiAgICAgICAgaWYgKCFpbWFnZVtcImRvY2tlclwiXSkgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBVdGlscy5leHBhbmRUZXh0KGltYWdlW1wiZG9ja2VyXCJdW1widXNlclwiXSwgdmFycyk7XG4gICAgfVxuXG4gICAgZ2V0IGltYWdlRW50cnlwb2ludCAoKTogc3RyaW5nW10gfCBudWxsIHtcbiAgICAgICAgY29uc3QgaW1hZ2UgPSB0aGlzLmpvYkRhdGFbXCJpbWFnZVwiXTtcblxuICAgICAgICBpZiAoIWltYWdlPy5lbnRyeXBvaW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBhc3NlcnQoQXJyYXkuaXNBcnJheShpbWFnZS5lbnRyeXBvaW50KSwgXCJpbWFnZTplbnRyeXBvaW50IG11c3QgYmUgYW4gYXJyYXlcIik7XG4gICAgICAgIHJldHVybiBpbWFnZS5lbnRyeXBvaW50O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgdmFsaWRhdGVDaURlcGVuZGVuY3lQcm94eVNlcnZlckF1dGhlbnRpY2F0aW9uIChpbWFnZU5hbWU6IHN0cmluZykge1xuICAgICAgICBjb25zdCBDSV9ERVBFTkRFTkNZX1BST1hZX1NFUlZFUiA9IHRoaXMuX3ZhcmlhYmxlc1tcIkNJX0RFUEVOREVOQ1lfUFJPWFlfU0VSVkVSXCJdO1xuICAgICAgICBpZiAoIWltYWdlTmFtZS5zdGFydHNXaXRoKENJX0RFUEVOREVOQ1lfUFJPWFlfU0VSVkVSKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwibG9naW5cIiwgQ0lfREVQRU5ERU5DWV9QUk9YWV9TRVJWRVJdKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBjb25zdCBlcnJNc2cgPSBgUGxlYXNlIGF1dGhlbnRpY2F0ZSB0byB0aGUgRGVwZW5kZW5jeSBQcm94eSAoJHtDSV9ERVBFTkRFTkNZX1BST1hZX1NFUlZFUn0pIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL3VzZXIvcGFja2FnZXMvZGVwZW5kZW5jeV9wcm94eS8jYXV0aGVudGljYXRlLXdpdGgtdGhlLWRlcGVuZGVuY3ktcHJveHlgO1xuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlID09IFwiZG9ja2VyXCIpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoIWUuc3RkZXJyLmluY2x1ZGVzKFwiQ2Fubm90IHBlcmZvcm0gYW4gaW50ZXJhY3RpdmUgbG9naW5cIiksIGVyck1zZyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlID09IFwicG9kbWFuXCIpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoIWUuc3RkZXJyLmluY2x1ZGVzKFwiVXNlcm5hbWU6IEVycm9yOiBnZXR0aW5nIHVzZXJuYW1lIGFuZCBwYXNzd29yZDogcmVhZGluZyB1c2VybmFtZTogRU9GXCIpLCBlcnJNc2cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcHVsbEltYWdlICh3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcywgaW1hZ2VUb1B1bGw6IHN0cmluZykge1xuICAgICAgICBjb25zdCBwdWxsUG9saWN5ID0gdGhpcy5hcmd2LnB1bGxQb2xpY3k7XG4gICAgICAgIGNvbnN0IGFjdHVhbFB1bGwgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnZhbGlkYXRlQ2lEZXBlbmRlbmN5UHJveHlTZXJ2ZXJBdXRoZW50aWNhdGlvbihpbWFnZVRvUHVsbCk7XG4gICAgICAgICAgICBjb25zdCB0aW1lID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJwdWxsXCIsIGltYWdlVG9QdWxsXSk7XG4gICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gcHJvY2Vzcy5ocnRpbWUodGltZSk7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBwdWxsZWR9ICR7aW1hZ2VUb1B1bGx9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaExvbmdSdW5uaW5nU2lsZW50VGltZW91dCh3cml0ZVN0cmVhbXMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChwdWxsUG9saWN5ID09PSBcImFsd2F5c1wiKSB7XG4gICAgICAgICAgICBhd2FpdCBhY3R1YWxQdWxsKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJpbWFnZVwiLCBcImluc3BlY3RcIiwgaW1hZ2VUb1B1bGxdKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICBhd2FpdCBhY3R1YWxQdWxsKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGluaXRQcm9kdWNlclJlcG9ydHNEb3RlbnZWYXJpYWJsZXMgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgY29uc3Qgc3RhdGVEaXIgPSB0aGlzLmFyZ3Yuc3RhdGVEaXI7XG4gICAgICAgIGNvbnN0IHByb2R1Y2VycyA9IHRoaXMucHJvZHVjZXJzO1xuICAgICAgICBsZXQgcHJvZHVjZXJSZXBvcnRzRW52cyA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IHByb2R1Y2VyIG9mIHByb2R1Y2VycyA/PyBbXSkge1xuICAgICAgICAgICAgY29uc3QgcHJvZHVjZXJEb3RlbnYgPSBVdGlscy5leHBhbmRUZXh0KHByb2R1Y2VyLmRvdGVudiwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgaWYgKHByb2R1Y2VyRG90ZW52ID09PSBudWxsKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3Qgc2FmZVByb2R1Y2VyTmFtZSA9IFV0aWxzLnNhZmVEb2NrZXJTdHJpbmcocHJvZHVjZXIubmFtZSk7XG4gICAgICAgICAgICBjb25zdCBkb3RlbnZGb2xkZXIgPSBgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke3NhZmVQcm9kdWNlck5hbWV9Ly5naXRsYWItY2ktcmVwb3J0cy9kb3RlbnYvYDtcbiAgICAgICAgICAgIGlmIChhd2FpdCBmcy5wYXRoRXhpc3RzKGRvdGVudkZvbGRlcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkb3RlbnZGaWxlcyA9IChhd2FpdCBVdGlscy5zcGF3bihbXCJmaW5kXCIsIFwiLlwiLCBcIi10eXBlXCIsIFwiZlwiXSwgZG90ZW52Rm9sZGVyKSkuc3Rkb3V0LnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZG90ZW52RmlsZSBvZiBkb3RlbnZGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZG90ZW52RmlsZSA9PSBcIlwiKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJvZHVjZXJSZXBvcnRFbnYgPSBkb3RlbnYucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUoYCR7ZG90ZW52Rm9sZGVyfS8ke2RvdGVudkZpbGV9YCkpO1xuICAgICAgICAgICAgICAgICAgICBwcm9kdWNlclJlcG9ydHNFbnZzID0gey4uLnByb2R1Y2VyUmVwb3J0c0VudnMsIC4uLnByb2R1Y2VyUmVwb3J0RW52fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHt5ZWxsb3cgcmVwb3J0cy5kb3RlbnYgcHJvZHVjZWQgYnkgJyR7cHJvZHVjZXIubmFtZX0nIGNvdWxkIG5vdCBiZSBmb3VuZH1cXG5gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcm9kdWNlclJlcG9ydHNFbnZzO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weUNhY2hlSW4gKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgaWYgKHRoaXMuYXJndi5tb3VudENhY2hlICYmIHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSkgcmV0dXJuO1xuICAgICAgICBpZiAoKCF0aGlzLmltYWdlTmFtZShleHBhbmRlZCkgJiYgIXRoaXMuYXJndi5zaGVsbElzb2xhdGlvbikgfHwgdGhpcy5jYWNoZS5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgICAgICBjb25zdCBjd2QgPSB0aGlzLmFyZ3YuY3dkO1xuICAgICAgICBjb25zdCBzdGF0ZURpciA9IHRoaXMuYXJndi5zdGF0ZURpcjtcblxuICAgICAgICBmb3IgKGNvbnN0IFtpbmRleCwgY10gb2YgdGhpcy5jYWNoZS5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIGlmICghW1wicHVsbFwiLCBcInB1bGwtcHVzaFwiXS5pbmNsdWRlcyhjLnBvbGljeSkpIHJldHVybjtcblxuICAgICAgICAgICAgY29uc3QgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG4gICAgICAgICAgICBjb25zdCBjYWNoZU5hbWUgPSBhd2FpdCB0aGlzLmdldFVuaXF1ZUNhY2hlTmFtZShjd2QsIGV4cGFuZGVkLCBpbmRleCk7XG4gICAgICAgICAgICBjb25zdCBjYWNoZUZvbGRlciA9IGAke2N3ZH0vJHtzdGF0ZURpcn0vY2FjaGUvJHtjYWNoZU5hbWV9YDtcbiAgICAgICAgICAgIGlmICghYXdhaXQgZnMucGF0aEV4aXN0cyhjYWNoZUZvbGRlcikpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXdhaXQgTXV0ZXguZXhjbHVzaXZlKGNhY2hlTmFtZSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY29weUluKGNhY2hlRm9sZGVyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgaW1wb3J0ZWQgY2FjaGUgJyR7Y2FjaGVOYW1lfSd9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weUFydGlmYWN0c0luICh3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcykge1xuICAgICAgICBpZiAoKCF0aGlzLmltYWdlTmFtZSh0aGlzLl92YXJpYWJsZXMpICYmICF0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHx8ICh0aGlzLnByb2R1Y2VycyA/PyBbXSkubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgY29uc3Qgc3RhdGVEaXIgPSB0aGlzLmFyZ3Yuc3RhdGVEaXI7XG4gICAgICAgIGNvbnN0IHRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHByb2R1Y2VyIG9mIHRoaXMucHJvZHVjZXJzID8/IFtdKSB7XG4gICAgICAgICAgICBjb25zdCBwcm9kdWNlclNhZmVOYW1lID0gVXRpbHMuc2FmZURvY2tlclN0cmluZyhwcm9kdWNlci5uYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGFydGlmYWN0Rm9sZGVyID0gYCR7Y3dkfS8ke3N0YXRlRGlyfS9hcnRpZmFjdHMvJHtwcm9kdWNlclNhZmVOYW1lfWA7XG4gICAgICAgICAgICBpZiAoIWF3YWl0IGZzLnBhdGhFeGlzdHMoYXJ0aWZhY3RGb2xkZXIpKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZnMubWtkaXJwKGFydGlmYWN0Rm9sZGVyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVhZGRpciA9IGF3YWl0IGZzLnJlYWRkaXIoYXJ0aWZhY3RGb2xkZXIpO1xuICAgICAgICAgICAgaWYgKHJlYWRkaXIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge3llbGxvdyBhcnRpZmFjdHMgZnJvbSB7Ymx1ZUJyaWdodCAke3Byb2R1Y2VyU2FmZU5hbWV9fSB3YXMgZW1wdHl9XFxuYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5jb3B5SW4oYXJ0aWZhY3RGb2xkZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgIGNvbnN0IGVuZFRpbWUgPSBwcm9jZXNzLmhydGltZSh0aW1lKTtcbiAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgaW1wb3J0ZWQgYXJ0aWZhY3RzfSBpbiB7bWFnZW50YSAke3ByZXR0eUhydGltZShlbmRUaW1lKX19XFxuYCk7XG4gICAgfVxuXG4gICAgY29weUluIChzb3VyY2U6IHN0cmluZykge1xuICAgICAgICBjb25zdCBzYWZlSm9iTmFtZSA9IHRoaXMuc2FmZUpvYk5hbWU7XG4gICAgICAgIGlmICghdGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSAmJiB0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiBVdGlscy5zcGF3bihbXCJyc3luY1wiLCBcIi1hXCIsIGAke3NvdXJjZX0vLmAsIGAke3RoaXMuYXJndi5jd2R9LyR7dGhpcy5hcmd2LnN0YXRlRGlyfS9idWlsZHMvJHtzYWZlSm9iTmFtZX1gXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJjcFwiLCBgJHtzb3VyY2V9Ly5gLCBgJHt0aGlzLl9jb250YWluZXJJZH06JHt0aGlzLmNpUHJvamVjdERpcn1gXSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjb3B5Q2FjaGVPdXQgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgaWYgKHRoaXMuYXJndi5tb3VudENhY2hlICYmIHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSkgcmV0dXJuO1xuICAgICAgICBpZiAoKCF0aGlzLmltYWdlTmFtZShleHBhbmRlZCkgJiYgIXRoaXMuYXJndi5zaGVsbElzb2xhdGlvbikgfHwgdGhpcy5jYWNoZS5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgICAgICBjb25zdCBjd2QgPSB0aGlzLmFyZ3YuY3dkO1xuICAgICAgICBjb25zdCBzdGF0ZURpciA9IHRoaXMuYXJndi5zdGF0ZURpcjtcbiAgICAgICAgY29uc3QgY2FjaGVQYXRoID0gdGhpcy5pbWFnZU5hbWUoZXhwYW5kZWQpID8gXCIvY2FjaGVcIiA6IFwiLi4vLi4vY2FjaGVcIjtcblxuICAgICAgICBsZXQgdGltZSwgZW5kVGltZTtcbiAgICAgICAgZm9yIChjb25zdCBbaW5kZXgsIGNdIG9mIHRoaXMuY2FjaGUuZW50cmllcygpKSB7XG4gICAgICAgICAgICBpZiAoIVtcInB1c2hcIiwgXCJwdWxsLXB1c2hcIl0uaW5jbHVkZXMoYy5wb2xpY3kpKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoXCJvbl9zdWNjZXNzXCIgPT09IGMud2hlbiAmJiB0aGlzLmpvYlN0YXR1cyAhPT0gXCJzdWNjZXNzXCIpIHJldHVybjtcbiAgICAgICAgICAgIGlmIChcIm9uX2ZhaWx1cmVcIiA9PT0gYy53aGVuICYmIHRoaXMuam9iU3RhdHVzID09PSBcInN1Y2Nlc3NcIikgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgY2FjaGVOYW1lID0gYXdhaXQgdGhpcy5nZXRVbmlxdWVDYWNoZU5hbWUoY3dkLCBleHBhbmRlZCwgaW5kZXgpO1xuXG4gICAgICAgICAgICBsZXQgcGF0aHMgPSBcIlwiO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwYXRoIG9mIGMucGF0aHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIVV0aWxzLmlzU3VicGF0aChwYXRoLCB0aGlzLmFyZ3YuY3dkLCB0aGlzLmFyZ3YuY3dkKSkgY29udGludWU7XG5cbiAgICAgICAgICAgICAgICBwYXRocyArPSBcIiBcIiArIFV0aWxzLmV4cGFuZFRleHQocGF0aCwgZXhwYW5kZWQpLnJlcGxhY2UoYCR7ZXhwYW5kZWQuQ0lfUFJPSkVDVF9ESVJ9L2AsIFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aW1lID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgICAgICAgICAgIGxldCBjbWQgPSBcInNob3B0IC1zIGdsb2JzdGFyIG51bGxnbG9iIGRvdGdsb2JcXG5cIjtcbiAgICAgICAgICAgIGNtZCArPSBgbWtkaXIgLXAgJHtVdGlscy5zYWZlQmFzaFN0cmluZyhjYWNoZVBhdGggKyBcIi9cIiArIGNhY2hlTmFtZSl9XFxuYDtcbiAgICAgICAgICAgIGNtZCArPSBgcnN5bmMgLVJhICR7cGF0aHN9ICR7VXRpbHMuc2FmZUJhc2hTdHJpbmcoY2FjaGVQYXRoICsgXCIvXCIgKyBjYWNoZU5hbWUgKyBcIi8uXCIpfSB8fCB0cnVlXFxuYDtcblxuICAgICAgICAgICAgYXdhaXQgTXV0ZXguZXhjbHVzaXZlKGNhY2hlTmFtZSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY29weU91dChjbWQsIHN0YXRlRGlyLCBcImNhY2hlXCIsIFtdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IF9fcGF0aCBvZiBjLnBhdGhzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgX3BhdGggPSBVdGlscy5leHBhbmRUZXh0KF9fcGF0aCwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgICAgIGlmICghVXRpbHMuaXNTdWJwYXRoKF9wYXRoLCB0aGlzLmFyZ3YuY3dkLCB0aGlzLmFyZ3YuY3dkKSkge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYHt5ZWxsb3cgV0FSTklORzogcHJvY2Vzc1BhdGg6IGFydGlmYWN0IHBhdGggaXMgbm90IGEgc3VicGF0aCBvZiBwcm9qZWN0IGRpcmVjdG9yeTogJHtfcGF0aH19XFxuYCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBwYXRoID0gX3BhdGg7XG4gICAgICAgICAgICAgICAgaWYgKGlzR2xvYihwYXRoKSAmJiAhcGF0aC5lbmRzV2l0aChcIipcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aCA9IGAke3BhdGh9LyoqYDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgbnVtT2ZGaWxlcyA9IGdsb2JieVN5bmMocGF0aCwge1xuICAgICAgICAgICAgICAgICAgICBkb3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG9ubHlGaWxlczogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGN3ZDogYCR7dGhpcy5hcmd2LmN3ZH0vJHtzdGF0ZURpcn0vY2FjaGUvJHtjYWNoZU5hbWV9YCxcbiAgICAgICAgICAgICAgICB9KS5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBpZiAobnVtT2ZGaWxlcyA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtge3llbGxvdyBXQVJOSU5HOiAke3BhdGh9OiBubyBtYXRjaGluZyBmaWxlcy4gRW5zdXJlIHRoYXQgdGhlIGFydGlmYWN0IHBhdGggaXMgcmVsYXRpdmUgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5fVxcbmApO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzR2xvYihwYXRoKSkgbnVtT2ZGaWxlcysrOyAvLyBhZGQgb25lIGJlY2F1c2UgdGhlIHBhdHRlcm4gaXRzZWxmIGlzIGEgZm9sZGVyXG5cbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGAke19wYXRofTogZm91bmQgJHtudW1PZkZpbGVzfSBhcnRpZmFjdCBmaWxlcyBhbmQgZGlyZWN0b3JpZXNcXG5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHttYWdlbnRhQnJpZ2h0IGNhY2hlIGNyZWF0ZWQgaW4gJyR7c3RhdGVEaXJ9L2NhY2hlLyR7Y2FjaGVOYW1lfSd9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weUFydGlmYWN0c091dCAod3JpdGVTdHJlYW1zOiBXcml0ZVN0cmVhbXMsIGV4cGFuZGVkOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSkge1xuICAgICAgICAvLyBUT0RPOiB1cGRhdGUgdGhlIGNvbmRpdGlvbiB0byBzdXBwb3J0IHdoZW46b25fc3VjY2VzcyAvIHdoZW46b25fZmFpbHVyZVxuICAgICAgICBpZiAodGhpcy5qb2JTdGF0dXMgIT09IFwic3VjY2Vzc1wiICYmIHRoaXMuYXJ0aWZhY3RzPy53aGVuICE9PSBcImFsd2F5c1wiKSByZXR1cm47XG4gICAgICAgIGlmICghdGhpcy5hcnRpZmFjdHMpIHJldHVybjtcbiAgICAgICAgaWYgKCh0aGlzLmFydGlmYWN0cy5wYXRocz8ubGVuZ3RoID8/IDApID09PSAwICYmIHRoaXMuYXJ0aWZhY3RzLnJlcG9ydHM/LmRvdGVudiA9PSBudWxsKSByZXR1cm47XG5cbiAgICAgICAgY29uc3Qgc2FmZUpvYk5hbWUgPSB0aGlzLnNhZmVKb2JOYW1lO1xuICAgICAgICBjb25zdCBjd2QgPSB0aGlzLmFyZ3YuY3dkO1xuICAgICAgICBjb25zdCBzdGF0ZURpciA9IHRoaXMuYXJndi5zdGF0ZURpcjtcbiAgICAgICAgbGV0IGFydGlmYWN0c1BhdGg6IHN0cmluZztcblxuICAgICAgICBpZiAoIXRoaXMuYXJndi5zaGVsbElzb2xhdGlvbiAmJiAhdGhpcy5pbWFnZU5hbWUoZXhwYW5kZWQpKSB7XG4gICAgICAgICAgICBhcnRpZmFjdHNQYXRoID0gYCR7c3RhdGVEaXJ9L2FydGlmYWN0c2A7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5pbWFnZU5hbWUoZXhwYW5kZWQpKSB7XG4gICAgICAgICAgICBhcnRpZmFjdHNQYXRoID0gXCIvYXJ0aWZhY3RzXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcnRpZmFjdHNQYXRoID0gXCIuLi8uLi9hcnRpZmFjdHNcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0aW1lLCBlbmRUaW1lO1xuICAgICAgICBsZXQgY3BDbWQgPSBcInNob3B0IC1zIGdsb2JzdGFyIG51bGxnbG9iIGRvdGdsb2JcXG5cIjtcbiAgICAgICAgY3BDbWQgKz0gYG1rZGlyIC1wICR7YXJ0aWZhY3RzUGF0aH0vJHtzYWZlSm9iTmFtZX1cXG5gO1xuICAgICAgICBjcENtZCArPSBcInJzeW5jIC0tZXhjbHVkZSAnLmdpdGxhYi1jaS1sb2NhbC8qKicgLVJhIFwiO1xuICAgICAgICBmb3IgKGNvbnN0IGFydGlmYWN0RXhjbHVkZVBhdGggb2YgdGhpcy5hcnRpZmFjdHM/LmV4Y2x1ZGUgPz8gW10pIHtcbiAgICAgICAgICAgIGNvbnN0IGV4cGFuZGVkUGF0aCA9IFV0aWxzLmV4cGFuZFRleHQoYXJ0aWZhY3RFeGNsdWRlUGF0aCwgZXhwYW5kZWQpLnJlcGxhY2UoYCR7ZXhwYW5kZWQuQ0lfUFJPSkVDVF9ESVJ9L2AsIFwiXCIpO1xuICAgICAgICAgICAgY3BDbWQgKz0gYC0tZXhjbHVkZSAnJHtleHBhbmRlZFBhdGh9JyBgO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgYXJ0aWZhY3RQYXRoIG9mIHRoaXMuYXJ0aWZhY3RzPy5wYXRocyA/PyBbXSkge1xuICAgICAgICAgICAgY29uc3QgZXhwYW5kZWRQYXRoID0gVXRpbHMuZXhwYW5kVGV4dChhcnRpZmFjdFBhdGgsIGV4cGFuZGVkKS5yZXBsYWNlKGAke2V4cGFuZGVkLkNJX1BST0pFQ1RfRElSfS9gLCBcIlwiKTtcbiAgICAgICAgICAgIGNwQ21kICs9IGAke2V4cGFuZGVkUGF0aH0gYDtcbiAgICAgICAgfVxuICAgICAgICBjcENtZCArPSBgJHthcnRpZmFjdHNQYXRofS8ke3NhZmVKb2JOYW1lfS8uIHx8IHRydWVcXG5gO1xuICAgICAgICBjb25zdCByZXBvcnREb3RlbnYgPSBVdGlscy5leHBhbmRUZXh0KHRoaXMuYXJ0aWZhY3RzLnJlcG9ydHM/LmRvdGVudiA/PyBudWxsLCBleHBhbmRlZCk7XG4gICAgICAgIGNvbnN0IHJlcG9ydERvdGVudnM6IHN0cmluZ1tdIHwgbnVsbCA9ICh0eXBlb2YgcmVwb3J0RG90ZW52ID09PSBcInN0cmluZ1wiKSA/IC8vIG5vcm1hbGl6ZSB0byBzdHJpbmdbXSBmb3IgZWFzaWVyIGhhbmRsaW5nXG4gICAgICAgICAgICBbcmVwb3J0RG90ZW52XSA6XG4gICAgICAgICAgICByZXBvcnREb3RlbnY7XG4gICAgICAgIGlmIChyZXBvcnREb3RlbnZzICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJlcG9ydERvdGVudnMuZm9yRWFjaCgocmVwb3J0RG90ZW52KSA9PiB7XG4gICAgICAgICAgICAgICAgY3BDbWQgKz0gYG1rZGlyIC1wICR7YXJ0aWZhY3RzUGF0aH0vJHtzYWZlSm9iTmFtZX0vLmdpdGxhYi1jaS1yZXBvcnRzL2RvdGVudlxcbmA7XG4gICAgICAgICAgICAgICAgY3BDbWQgKz0gYGlmIFsgLWYgJHtyZXBvcnREb3RlbnZ9IF07IHRoZW5cXG5gO1xuICAgICAgICAgICAgICAgIGNwQ21kICs9IGAgIHJzeW5jIC1SYSAke3JlcG9ydERvdGVudn0gJHthcnRpZmFjdHNQYXRofS8ke3NhZmVKb2JOYW1lfS8uZ2l0bGFiLWNpLXJlcG9ydHMvZG90ZW52Ly5cXG5gO1xuICAgICAgICAgICAgICAgIGNwQ21kICs9IFwiZmlcXG5cIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG4gICAgICAgIGNvbnN0IGRvY2tlckNtZEV4dHJhcyA9IHRoaXMuYXJndi5tb3VudENhY2hlID8gYXdhaXQgdGhpcy5tb3VudENhY2hlQ21kKHdyaXRlU3RyZWFtcywgZXhwYW5kZWQpIDogW107XG4gICAgICAgIGF3YWl0IHRoaXMuY29weU91dChjcENtZCwgc3RhdGVEaXIsIFwiYXJ0aWZhY3RzXCIsIGRvY2tlckNtZEV4dHJhcyk7XG4gICAgICAgIGVuZFRpbWUgPSBwcm9jZXNzLmhydGltZSh0aW1lKTtcblxuICAgICAgICBmb3IgKGNvbnN0IHJlcG9ydERvdGVudiBvZiByZXBvcnREb3RlbnZzID8/IFtdKSB7XG4gICAgICAgICAgICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke3NhZmVKb2JOYW1lfS8uZ2l0bGFiLWNpLXJlcG9ydHMvZG90ZW52LyR7cmVwb3J0RG90ZW52fWApKSBjb250aW51ZTtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHt5ZWxsb3cgYXJ0aWZhY3QgcmVwb3J0cyBkb3RlbnYgJyR7cmVwb3J0RG90ZW52fScgY291bGQgbm90IGJlIGZvdW5kfVxcbmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVhZGRpciA9IGF3YWl0IGZzLnJlYWRkaXIoYCR7Y3dkfS8ke3N0YXRlRGlyfS9hcnRpZmFjdHMvJHtzYWZlSm9iTmFtZX1gKTtcbiAgICAgICAgaWYgKHJlYWRkaXIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7eWVsbG93ICEhIG5vIGFydGlmYWN0cyB3YXMgY29waWVkICEhfVxcbmApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgZXhwb3J0ZWQgYXJ0aWZhY3RzfSBpbiB7bWFnZW50YSAke3ByZXR0eUhydGltZShlbmRUaW1lKX19XFxuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5hcnRpZmFjdHNUb1NvdXJjZSAmJiAodGhpcy5hcmd2LnNoZWxsSXNvbGF0aW9uIHx8IHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSkpIHtcbiAgICAgICAgICAgIHRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW1wicnN5bmNcIiwgXCItLWV4Y2x1ZGU9Ly5naXRsYWItY2ktcmVwb3J0cy9cIiwgXCItYVwiLCBgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke3NhZmVKb2JOYW1lfS8uYCwgY3dkXSk7XG4gICAgICAgICAgICBpZiAocmVwb3J0RG90ZW52ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbXCJyc3luY1wiLCBcIi1hXCIsIGAke2N3ZH0vJHtzdGF0ZURpcn0vYXJ0aWZhY3RzLyR7c2FmZUpvYk5hbWV9Ly5naXRsYWItY2ktcmVwb3J0cy9kb3RlbnYvLmAsIGN3ZF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgY29waWVkIGFydGlmYWN0cyB0byBjd2R9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weU91dCAoY21kOiBzdHJpbmcsIHN0YXRlRGlyOiBzdHJpbmcsIHR5cGU6IFwiYXJ0aWZhY3RzXCIgfCBcImNhY2hlXCIsIGRvY2tlckNtZEV4dHJhczogc3RyaW5nW10pIHtcbiAgICAgICAgY29uc3Qgc2FmZUpvYk5hbWUgPSB0aGlzLnNhZmVKb2JOYW1lO1xuICAgICAgICBjb25zdCBidWlsZFZvbHVtZU5hbWUgPSB0aGlzLmJ1aWxkVm9sdW1lTmFtZTtcbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgY29uc3QgaGVscGVySW1hZ2VOYW1lID0gdGhpcy5hcmd2LmhlbHBlckltYWdlO1xuXG4gICAgICAgIGF3YWl0IGZzLm1rZGlycChgJHtjd2R9LyR7c3RhdGVEaXJ9LyR7dHlwZX1gKTtcblxuICAgICAgICBpZiAodGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSkge1xuICAgICAgICAgICAgY29uc3Qge3N0ZG91dDogY29udGFpbmVySWR9ID0gYXdhaXQgVXRpbHMuYmFzaChgJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gY3JlYXRlIC1pICR7ZG9ja2VyQ21kRXh0cmFzLmpvaW4oXCIgXCIpfSAtdiAke2J1aWxkVm9sdW1lTmFtZX06JHt0aGlzLmNpUHJvamVjdERpcn0gLXcgJHt0aGlzLmNpUHJvamVjdERpcn0gJHtoZWxwZXJJbWFnZU5hbWV9IGJhc2ggLWMgXCIke2NtZC5yZXBsYWNlKC9cIi9nLCBcIlxcXFxcXFwiXCIpfVwiYCwgY3dkKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLnB1c2goY29udGFpbmVySWQpO1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInN0YXJ0XCIsIGNvbnRhaW5lcklkLCBcIi0tYXR0YWNoXCJdKTtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJjcFwiLCBgJHtjb250YWluZXJJZH06LyR7dHlwZX0vLmAsIGAke3N0YXRlRGlyfS8ke3R5cGV9Ly5gXSwgY3dkKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLmJhc2goYGJhc2ggLWVvIHBpcGVmYWlsIC1jIFwiJHtjbWR9XCJgLCBgJHtjd2R9LyR7c3RhdGVEaXJ9L2J1aWxkcy8ke3NhZmVKb2JOYW1lfWApO1xuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLmJhc2goYGJhc2ggLWVvIHBpcGVmYWlsIC1jIFwiJHtjbWR9XCJgLCBgJHtjd2R9YCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJlZnJlc2hMb25nUnVubmluZ1NpbGVudFRpbWVvdXQgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQpO1xuICAgICAgICB0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHtncmV5ID4gc3RpbGwgcnVubmluZy4uLn1cXG5gKTtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaExvbmdSdW5uaW5nU2lsZW50VGltZW91dCh3cml0ZVN0cmVhbXMpO1xuICAgICAgICB9LCAxMDAwMCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRGaW5pc2hlZFN0cmluZyAoKSB7XG4gICAgICAgIHJldHVybiBjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgZmluaXNoZWR9IGluIHttYWdlbnRhICR7dGhpcy5wcmV0dHlEdXJhdGlvbn19YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByaW50RmluaXNoZWRTdHJpbmcgKCkge1xuICAgICAgICBpZiAodGhpcy5qb2JTdGF0dXMgIT09IFwic3VjY2Vzc1wiKSByZXR1cm47XG4gICAgICAgIHRoaXMud3JpdGVTdHJlYW1zLnN0ZG91dChgJHt0aGlzLmdldEZpbmlzaGVkU3RyaW5nKCl9XFxuYCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcmludEV4aXRlZFN0cmluZyAoY29kZTogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IHdyaXRlU3RyZWFtcyA9IHRoaXMud3JpdGVTdHJlYW1zO1xuICAgICAgICBjb25zdCBmaW5pc2hlZFN0ciA9IHRoaXMuZ2V0RmluaXNoZWRTdHJpbmcoKTtcblxuICAgICAgICAvLyBXb24ndCBwcmludCBpZiBqb2JTdGF0dXMgaXMgXCJzdWNjZXNzXCIgYmVjYXVzZSB0aGF0IHdpbGwgYmUgcHJpbnRlZCB2aWEgdGhlIGBwcmludEZpbmlzaGVkU3RyaW5nKClgXG4gICAgICAgIGlmICh0aGlzLmpvYlN0YXR1cyA9PT0gXCJ3YXJuaW5nXCIpIHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoXG4gICAgICAgICAgICAgICAgY2hhbGtgJHtmaW5pc2hlZFN0cn0ge2JsYWNrLmJnWWVsbG93QnJpZ2h0ICBXQVJOICR7Y29kZS50b1N0cmluZygpfSB9XFxuYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5qb2JTdGF0dXMgPT09IFwiZmFpbGVkXCIpIHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoXG4gICAgICAgICAgICAgICAgY2hhbGtgJHtmaW5pc2hlZFN0cn0ge2JsYWNrLmJnUmVkICBGQUlMICR7Y29kZS50b1N0cmluZygpfSB9XFxuYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHByaW50QWZ0ZXJTY3JpcHRFeGl0ZWRTdHJpbmcgKGNvZGU6IG51bWJlcikge1xuICAgICAgICBjb25zdCB3cml0ZVN0cmVhbXMgPSB0aGlzLndyaXRlU3RyZWFtcztcbiAgICAgICAgY29uc3QgZmluaXNoZWRTdHIgPSB0aGlzLmdldEZpbmlzaGVkU3RyaW5nKCk7XG5cbiAgICAgICAgaWYgKGNvZGUgIT09IDApIHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoXG4gICAgICAgICAgICAgICAgY2hhbGtgJHtmaW5pc2hlZFN0cn0ge2JsYWNrLmJnWWVsbG93QnJpZ2h0ICBXQVJOICR7Y29kZS50b1N0cmluZygpfSB9IGFmdGVyX3NjcmlwdFxcbmAsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVEb2NrZXJOZXR3b3JrIChuZXR3b3JrTmFtZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHtzdGRvdXQ6IG5ldHdvcmtJZH0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwibmV0d29ya1wiLCBcImNyZWF0ZVwiLCBgJHtuZXR3b3JrTmFtZX1gXSk7XG4gICAgICAgIHRoaXMuX3NlcnZpY2VOZXR3b3JrSWQgPSBuZXR3b3JrSWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBzdGFydFNlcnZpY2UgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30sIHNlcnZpY2U6IFNlcnZpY2UpIHtcbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgbGV0IGRvY2tlckNtZCA9IGAke3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlfSBjcmVhdGUgLS1pbnRlcmFjdGl2ZSBgO1xuICAgICAgICB0aGlzLnJlZnJlc2hMb25nUnVubmluZ1NpbGVudFRpbWVvdXQod3JpdGVTdHJlYW1zKTtcblxuICAgICAgICBpZiAodGhpcy5hcmd2LnVtYXNrKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCItLXVzZXIgMDowIFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYXJndi51c2VybnMgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdXNlcm5zPSR7dGhpcy5hcmd2LnVzZXJuc30gYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFyZ3YucHJpdmlsZWdlZCkge1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiLS1wcml2aWxlZ2VkIFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBkZXZpY2Ugb2YgdGhpcy5hcmd2LmRldmljZSkge1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLWRldmljZSAke2RldmljZX0gYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFyZ3YudWxpbWl0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdWxpbWl0IG5vZmlsZT0ke3RoaXMuYXJndi51bGltaXR9IGA7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IHZvbHVtZSBvZiB0aGlzLmFyZ3Yudm9sdW1lKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7dm9sdW1lfSBgO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBleHRyYUhvc3Qgb2YgdGhpcy5hcmd2LmV4dHJhSG9zdCkge1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLWFkZC1ob3N0PSR7ZXh0cmFIb3N0fSBgO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYXJndi5jYUZpbGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGNhRmlsZVBhdGggPSBwYXRoLmlzQWJzb2x1dGUodGhpcy5hcmd2LmNhRmlsZSkgPyB0aGlzLmFyZ3YuY2FGaWxlIDogcGF0aC5yZXNvbHZlKHRoaXMuYXJndi5jd2QsIHRoaXMuYXJndi5jYUZpbGUpO1xuICAgICAgICAgICAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoY2FGaWxlUGF0aCkpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7Y2FGaWxlUGF0aH06L2V0Yy9zc2wvY2VydHMvY2EtY2VydGlmaWNhdGVzLmNydDpybyBgO1xuICAgICAgICAgICAgICAgIGV4cGFuZGVkW1wiU1NMX0NFUlRfRklMRVwiXSA9IFwiL2V0Yy9zc2wvY2VydHMvY2EtY2VydGlmaWNhdGVzLmNydFwiO1xuICAgICAgICAgICAgICAgIGV4cGFuZGVkW1wiU1NMX0NFUlRfRElSXCJdID0gXCIvZXRjL3NzbC9jZXJ0c1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2VydmljZUFsaWFzID0gc2VydmljZS5hbGlhcztcbiAgICAgICAgY29uc3Qgc2VydmljZU5hbWUgPSBzZXJ2aWNlLm5hbWU7XG4gICAgICAgIGNvbnN0IHNlcnZpY2VOYW1lV2l0aG91dFZlcnNpb24gPSBzZXJ2aWNlTmFtZS5yZXBsYWNlKC8oLiopKDouKikvLCBcIiQxXCIpO1xuICAgICAgICBjb25zdCBhbGlhc2VzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICAgIGFsaWFzZXMuYWRkKHNlcnZpY2VOYW1lV2l0aG91dFZlcnNpb24ucmVwbGFjZUFsbChcIi9cIiwgXCItXCIpKTtcbiAgICAgICAgYWxpYXNlcy5hZGQoc2VydmljZU5hbWVXaXRob3V0VmVyc2lvbi5yZXBsYWNlQWxsKFwiL1wiLCBcIl9fXCIpKTtcbiAgICAgICAgaWYgKHNlcnZpY2VBbGlhcykge1xuICAgICAgICAgICAgYWxpYXNlcy5hZGQoc2VydmljZUFsaWFzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBPYmplY3QuZW50cmllcyhleHBhbmRlZCkpIHtcbiAgICAgICAgICAgIC8vIFJlcGxhY2luZyBgJ2Agd2l0aCBgJ1xcJydgIHRvIGNvcnJlY3RseSBoYW5kbGUgc2luZ2xlIHF1b3RlcyhpZiBgdmFsYCBjb250YWlucyBgJ2ApIGluIHNoZWxsIGNvbW1hbmRzXG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYCAgLWUgJyR7a2V5fT0ke3ZhbC50b1N0cmluZygpLnJlcGxhY2UoLycvZywgXCInXFxcXCcnXCIpfScgXFxcXFxcbmA7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzZXJ2aWNlRW50cnlwb2ludCA9IHNlcnZpY2UuZW50cnlwb2ludDtcbiAgICAgICAgaWYgKHNlcnZpY2VFbnRyeXBvaW50KSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tZW50cnlwb2ludCAke1V0aWxzLnNhZmVCYXNoU3RyaW5nKHNlcnZpY2VFbnRyeXBvaW50WzBdKX0gYDtcbiAgICAgICAgfVxuICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7dGhpcy5idWlsZFZvbHVtZU5hbWV9OiR7dGhpcy5jaVByb2plY3REaXJ9IGA7XG4gICAgICAgIGRvY2tlckNtZCArPSBgLS12b2x1bWUgJHt0aGlzLnRtcFZvbHVtZU5hbWV9OiR7dGhpcy5maWxlVmFyaWFibGVzRGlyfSBgO1xuXG4gICAgICAgIC8vIFRoZSBkZWZhdWx0IHBvZG1hbiBuZXR3b3JrIG1vZGUgaXMgbm90IGBicmlkZ2VgLCB3aGljaCBtZWFucyBhIGBwb2RtYW4gbmV0d29yayBjb25uZWN0YCBjYWxsIHdpbGwgZmFpbFxuICAgICAgICAvLyB3aGVuIGNvbm5lY3RpbmcgdXNlciBkZWZpbmVkIG5ldHdvcmtzLiBUaGUgd29ya2Fyb3VuZCBpcyB0byB1c2UgYSB1c2VyIGRlZmluZWQgbmV0d29yayBvbiBjb250YWluZXJcbiAgICAgICAgLy8gY3JlYXRpb24uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vY29udGFpbmVycy9wb2RtYW4vaXNzdWVzLzE5NTc3XG4gICAgICAgIGRvY2tlckNtZCArPSBgLS1uZXR3b3JrICR7dGhpcy5fc2VydmljZU5ldHdvcmtJZH0gYDtcbiAgICAgICAgZm9yIChjb25zdCBhbGlhcyBvZiBhbGlhc2VzKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tbmV0d29yay1hbGlhcyAke2FsaWFzfSBgO1xuICAgICAgICB9XG5cbiAgICAgICAgZG9ja2VyQ21kICs9IGAke3NlcnZpY2VOYW1lfSBgO1xuXG4gICAgICAgIGlmIChzZXJ2aWNlRW50cnlwb2ludD8ubGVuZ3RoID8/IDAgPiAxKSB7XG4gICAgICAgICAgICBzZXJ2aWNlRW50cnlwb2ludD8uc2xpY2UoMSkuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgJHtVdGlscy5zYWZlQmFzaFN0cmluZyhlKX0gYDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIChzZXJ2aWNlLmNvbW1hbmQgPz8gW10pLmZvckVhY2goKGUpID0+IGRvY2tlckNtZCArPSBgXCIke2UucmVwbGFjZSgvXFwkL2csIFwiXFxcXCRcIil9XCIgYCk7XG5cbiAgICAgICAgY29uc3QgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG5cbiAgICAgICAgY29uc3Qge3N0ZG91dDogY29udGFpbmVySWR9ID0gYXdhaXQgVXRpbHMuYmFzaChkb2NrZXJDbWQsIGN3ZCk7XG4gICAgICAgIHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLnB1c2goY29udGFpbmVySWQpO1xuXG4gICAgICAgIGZvciAoY29uc3QgbmV0d29yayBvZiB0aGlzLmFyZ3YubmV0d29yaykge1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcIm5ldHdvcmtcIiwgXCJjb25uZWN0XCIsIG5ldHdvcmssIGAke2NvbnRhaW5lcklkfWBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJzdGFydFwiLCBgJHtjb250YWluZXJJZH1gXSk7XG5cbiAgICAgICAgY29uc3QgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBzdGFydGVkIHNlcnZpY2UgaW1hZ2U6ICR7c2VydmljZU5hbWV9IHdpdGggYWxpYXNlczogJHtBcnJheS5mcm9tKGFsaWFzZXMpLmpvaW4oXCIsIFwiKX19IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVySWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBzZXJ2aWNlSGVhbHRoQ2hlY2sgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBzZXJ2aWNlOiBTZXJ2aWNlLCBzZXJ2aWNlSW5kZXg6IG51bWJlciwgc2VydmljZUNvbnRhaW5lckxvZ0ZpbGU6IHN0cmluZykge1xuICAgICAgICBjb25zdCBzZXJ2aWNlQWxpYXMgPSBzZXJ2aWNlLmFsaWFzO1xuICAgICAgICBjb25zdCBzZXJ2aWNlTmFtZSA9IHNlcnZpY2UubmFtZTtcbiAgICAgICAgY29uc3Qgd2FpdEltYWdlTmFtZSA9IHRoaXMuYXJndi53YWl0SW1hZ2U7XG5cbiAgICAgICAgY29uc3Qge3N0ZG91dH0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwiaW1hZ2VcIiwgXCJpbnNwZWN0XCIsIHNlcnZpY2VOYW1lXSk7XG4gICAgICAgIGNvbnN0IGltYWdlSW5zcGVjdCA9IEpTT04ucGFyc2Uoc3Rkb3V0KTtcblxuICAgICAgICAvLyBDb3BpZWQgZnJvbSB0aGUgc3RhcnRTZXJ2aWNlIGJsb2NrLiBJbXBvcnRhbnQgdGhpbmcgaXMgdGhhdCB0aGUgYWxpYXNlcyBtYXRjaFxuICAgICAgICBjb25zdCBzZXJ2aWNlTmFtZVdpdGhvdXRWZXJzaW9uID0gc2VydmljZU5hbWUucmVwbGFjZSgvKC4qKSg6LiopLywgXCIkMVwiKTtcbiAgICAgICAgY29uc3QgYWxpYXNlcyA9IFtzZXJ2aWNlTmFtZVdpdGhvdXRWZXJzaW9uLnJlcGxhY2VBbGwoXCIvXCIsIFwiLVwiKSwgc2VydmljZU5hbWVXaXRob3V0VmVyc2lvbi5yZXBsYWNlQWxsKFwiL1wiLCBcIl9fXCIpXTtcbiAgICAgICAgaWYgKHNlcnZpY2VBbGlhcykge1xuICAgICAgICAgICAgYWxpYXNlcy5wdXNoKHNlcnZpY2VBbGlhcyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB1bmlxdWVBbGlhcyA9IGFsaWFzZXNbYWxpYXNlcy5sZW5ndGggLSAxXTtcblxuICAgICAgICBpZiAoKGltYWdlSW5zcGVjdFswXT8uQ29uZmlnPy5FeHBvc2VkUG9ydHMgPz8gbnVsbCkgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZVN0cmVhbXMuc3RkZXJyKGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7eWVsbG93IENvdWxkIG5vdCBmaW5kIGV4cG9zZWQgdGNwIHBvcnRzICR7c2VydmljZU5hbWV9fVxcbmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBJdGVyYXRlIG92ZXIgZWFjaCBwb3J0IGRlZmluZWQgaW4gdGhlIGltYWdlLCBhbmQgdHJ5IHRvIGNvbm5lY3QgdG8gdGhlIGFsaWFzXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFueShPYmplY3Qua2V5cyhpbWFnZUluc3BlY3RbMF0uQ29uZmlnLkV4cG9zZWRQb3J0cykubWFwKChwb3J0KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFwb3J0LmVuZHNXaXRoKFwiL3RjcFwiKSkgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvcnROdW0gPSBwYXJzZUludChwb3J0LnJlcGxhY2UoXCIvdGNwXCIsIFwiXCIpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjb250YWluZXJOYW1lID0gYGdjbC13YWl0LWZvci1pdC0ke3RoaXMuam9iSWR9LSR7c2VydmljZUluZGV4fS0ke3BvcnROdW19YDtcbiAgICAgICAgICAgICAgICBjb25zdCBzcGF3bkNtZCA9IFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJydW5cIiwgXCItLXJtXCIsIGAtLW5hbWU9JHtjb250YWluZXJOYW1lfWAsIFwiLS1uZXR3b3JrXCIsIGAke3RoaXMuX3NlcnZpY2VOZXR3b3JrSWR9YCwgYCR7d2FpdEltYWdlTmFtZX1gLCBgJHt1bmlxdWVBbGlhc306JHtwb3J0TnVtfWAsIFwiLXRcIiwgXCIzMFwiXTtcbiAgICAgICAgICAgICAgICB0aGlzLl9jb250YWluZXJzVG9DbGVhbi5wdXNoKGNvbnRhaW5lck5hbWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBVdGlscy5zcGF3bihzcGF3bkNtZCk7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gcHJvY2Vzcy5ocnRpbWUodGltZSk7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7Z3JlZW5CcmlnaHQgc2VydmljZSBpbWFnZTogJHtzZXJ2aWNlTmFtZX0gaGVhbHRoY2hlY2sgcGFzc2VkIGluIHtncmVlbiAke3ByZXR0eUhydGltZShlbmRUaW1lKX19fVxcbmApO1xuICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBBZ2dyZWdhdGVFcnJvcikpIHRocm93IGU7XG4gICAgICAgICAgICBlLmVycm9ycy5mb3JFYWNoKChzaW5nbGVFcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7cmVkQnJpZ2h0IHNlcnZpY2UgaW1hZ2U6ICR7c2VydmljZU5hbWV9IGhlYWx0aGNoZWNrIGZhaWxlZH1cXG5gKTtcbiAgICAgICAgICAgICAgICBzaW5nbGVFcnJvci5tZXNzYWdlLnNwbGl0KC9cXHI/XFxuL2cpLmZvckVhY2goKGxpbmU6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7cmVkQnJpZ2h0ICAgJHtsaW5lfX1cXG5gKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7cmVkQnJpZ2h0IGFsc28gc2VlICgke3NlcnZpY2VDb250YWluZXJMb2dGaWxlfSl9XFxuYCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIC8vIEtpbGwgYWxsIHdhaXQtZm9yLWl0IGNvbnRhaW5lcnMsIHdoZW4gb25lIGhhdmUgYmVlbiBzdWNjZXNzZnVsXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoT2JqZWN0LmtleXMoaW1hZ2VJbnNwZWN0WzBdLkNvbmZpZy5FeHBvc2VkUG9ydHMpLm1hcCgocG9ydCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghcG9ydC5lbmRzV2l0aChcIi90Y3BcIikpIHJldHVybjtcbiAgICAgICAgICAgICAgICBjb25zdCBwb3J0TnVtID0gcGFyc2VJbnQocG9ydC5yZXBsYWNlKFwiL3RjcFwiLCBcIlwiKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJybVwiLCBcIi12ZlwiLCBgZ2NsLXdhaXQtZm9yLWl0LSR7dGhpcy5qb2JJZH0tJHtzZXJ2aWNlSW5kZXh9LSR7cG9ydE51bX1gXSk7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGZldGNoVHJpZ2dlckluY2x1ZGUgKCkge1xuICAgICAgICBjb25zdCB7Y3dkLCBzdGF0ZURpcn0gPSB0aGlzLmFyZ3Y7XG5cbiAgICAgICAgZnMubWtkaXJwU3luYyhgJHtjd2R9LyR7c3RhdGVEaXJ9L2luY2x1ZGVzL3RyaWdnZXJzYCk7XG5cbiAgICAgICAgbGV0IGNvbnRlbnRzOiBhbnkgPSB7fTtcblxuICAgICAgICBmb3IgKGNvbnN0IGluY2x1ZGUgb2YgdGhpcy5qb2JEYXRhLnRyaWdnZXI/LmluY2x1ZGUgPz8gW10pIHtcbiAgICAgICAgICAgIGlmIChpbmNsdWRlW1wibG9jYWxcIl0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHBhbmRlZEluY2x1ZGUgPSBVdGlscy5leHBhbmRUZXh0KGluY2x1ZGVbXCJsb2NhbFwiXSwgdGhpcy5fdmFyaWFibGVzKTtcbiAgICAgICAgICAgICAgICB2YWxpZGF0ZUluY2x1ZGVMb2NhbChleHBhbmRlZEluY2x1ZGUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcmVzb2x2ZUluY2x1ZGVMb2NhbChleHBhbmRlZEluY2x1ZGUsIGN3ZCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpbGVzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogYExvY2FsIGluY2x1ZGUgZmlsZSBcXGAke2luY2x1ZGVbXCJsb2NhbFwiXX1cXGAgc3BlY2lmaWVkIGluIFxcYC4ke3RoaXMubmFtZX1cXGAgY2Fubm90IGJlIGZvdW5kIWB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IFBhcnNlci5sb2FkWWFtbChmaWxlLCB7fSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uY29udGVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jb250ZW50LFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZVtcImFydGlmYWN0XCJdKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IFBhcnNlci5sb2FkWWFtbChgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke2luY2x1ZGVbXCJqb2JcIl19LyR7aW5jbHVkZVtcImFydGlmYWN0XCJdfWAsIHt9KTtcbiAgICAgICAgICAgICAgICBjb250ZW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgLi4uY29udGVudHMsXG4gICAgICAgICAgICAgICAgICAgIC4uLmNvbnRlbnQsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZVtcInByb2plY3RcIl0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLndyaXRlU3RyZWFtcy5tZW1vU3Rkb3V0KGNoYWxrYHtiZ1llbGxvd0JyaWdodCAgV0FSTiB9IFxcYHtibHVlQnJpZ2h0ICR7dGhpcy5uYW1lfS50cmlnZ2VyLmluY2x1ZGUuKi5wcm9qZWN0fVxcYCB3aWxsIGJlIG5vLW9wLiBJdCBpcyBjdXJyZW50bHkgbm90IGltcGxlbWVudGVkXFxuYCk7XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZVtcInRlbXBsYXRlXCJdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53cml0ZVN0cmVhbXMubWVtb1N0ZG91dChjaGFsa2B7YmdZZWxsb3dCcmlnaHQgIFdBUk4gfSBcXGB7Ymx1ZUJyaWdodCAke3RoaXMubmFtZX0udHJpZ2dlci5pbmNsdWRlLioudGVtcGxhdGV9XFxgIHdpbGwgYmUgbm8tb3AuIEl0IGlzIGN1cnJlbnRseSBub3QgaW1wbGVtZW50ZWRcXG5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0YXJnZXQgPSBgJHtjd2R9LyR7c3RhdGVEaXJ9L2luY2x1ZGVzL3RyaWdnZXJzLyR7dGhpcy5uYW1lfS55bWxgO1xuICAgICAgICBmcy53cml0ZUZpbGVTeW5jKHRhcmdldCwgeWFtbC5kdW1wKGNvbnRlbnRzKSk7XG4gICAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xlYW51cEpvYlJlc291cmNlcyAoam9icz86IEl0ZXJhYmxlPEpvYj4pIHtcbiAgICBpZiAoIWpvYnMpIHJldHVybjtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgIGZvciAoY29uc3Qgam9iIG9mIGpvYnMpIHtcbiAgICAgICAgcHJvbWlzZXMucHVzaChqb2IuY2xlYW51cFJlc291cmNlcygpKTtcbiAgICB9XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xufVxuIl19
|