semantifold 0.9.0 → 0.11.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 +6 -3
- package/bin/semantifold.js +6 -0
- package/build/bin/semantifold.d.ts +3 -0
- package/build/bin/semantifold.d.ts.map +1 -0
- package/build/bin/semantifold.js +5 -0
- package/build/index.d.ts +8 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +9 -1
- package/build/src/artifact-path.d.ts +16 -0
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +29 -3
- package/build/src/backends/c-check.d.ts +7 -0
- package/build/src/backends/c-check.d.ts.map +1 -0
- package/build/src/backends/c-check.js +65 -0
- package/build/src/backends/check-plan.d.ts +96 -0
- package/build/src/backends/check-plan.d.ts.map +1 -0
- package/build/src/backends/check-plan.js +135 -0
- package/build/src/backends/cpp-check.d.ts +7 -0
- package/build/src/backends/cpp-check.d.ts.map +1 -0
- package/build/src/backends/cpp-check.js +59 -0
- package/build/src/backends/csharp-check.d.ts +7 -0
- package/build/src/backends/csharp-check.d.ts.map +1 -0
- package/build/src/backends/csharp-check.js +125 -0
- package/build/src/backends/csharp.d.ts +1 -0
- package/build/src/backends/csharp.d.ts.map +1 -1
- package/build/src/backends/csharp.js +5 -4
- package/build/src/backends/dart-check.d.ts +7 -0
- package/build/src/backends/dart-check.d.ts.map +1 -0
- package/build/src/backends/dart-check.js +103 -0
- package/build/src/backends/dart.d.ts +2 -0
- package/build/src/backends/dart.d.ts.map +1 -1
- package/build/src/backends/dart.js +5 -5
- package/build/src/backends/go-check.d.ts +7 -0
- package/build/src/backends/go-check.d.ts.map +1 -0
- package/build/src/backends/go-check.js +77 -0
- package/build/src/backends/go.d.ts +1 -0
- package/build/src/backends/go.d.ts.map +1 -1
- package/build/src/backends/go.js +3 -3
- package/build/src/backends/java-check.d.ts +21 -0
- package/build/src/backends/java-check.d.ts.map +1 -0
- package/build/src/backends/java-check.js +73 -0
- package/build/src/backends/javascript-check.d.ts +7 -0
- package/build/src/backends/javascript-check.d.ts.map +1 -0
- package/build/src/backends/javascript-check.js +29 -0
- package/build/src/backends/kotlin-check.d.ts +7 -0
- package/build/src/backends/kotlin-check.d.ts.map +1 -0
- package/build/src/backends/kotlin-check.js +31 -0
- package/build/src/backends/kotlin.d.ts +1 -1
- package/build/src/backends/kotlin.js +2 -2
- package/build/src/backends/php-check.d.ts +7 -0
- package/build/src/backends/php-check.d.ts.map +1 -0
- package/build/src/backends/php-check.js +21 -0
- package/build/src/backends/program.d.ts +7 -0
- package/build/src/backends/program.d.ts.map +1 -1
- package/build/src/backends/program.js +16 -1
- package/build/src/backends/python-check.d.ts +7 -0
- package/build/src/backends/python-check.d.ts.map +1 -0
- package/build/src/backends/python-check.js +28 -0
- package/build/src/backends/ruby-check.d.ts +7 -0
- package/build/src/backends/ruby-check.d.ts.map +1 -0
- package/build/src/backends/ruby-check.js +21 -0
- package/build/src/backends/rust-check.d.ts +7 -0
- package/build/src/backends/rust-check.d.ts.map +1 -0
- package/build/src/backends/rust-check.js +65 -0
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +29 -1
- package/build/src/backends/swift-check.d.ts +7 -0
- package/build/src/backends/swift-check.d.ts.map +1 -0
- package/build/src/backends/swift-check.js +77 -0
- package/build/src/backends/typescript-check.d.ts +7 -0
- package/build/src/backends/typescript-check.d.ts.map +1 -0
- package/build/src/backends/typescript-check.js +33 -0
- package/build/src/backends/zig-check.d.ts +7 -0
- package/build/src/backends/zig-check.d.ts.map +1 -0
- package/build/src/backends/zig-check.js +70 -0
- package/build/src/diagnostic.d.ts +13 -1
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +14 -2
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +23 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +45 -4
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +54 -3
- package/build/src/frontends/program.d.ts +6 -0
- package/build/src/frontends/program.d.ts.map +1 -1
- package/build/src/frontends/program.js +9 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +55 -5
- package/build/src/language-registry.d.ts +54 -0
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +124 -10
- package/build/src/project-build.d.ts +172 -0
- package/build/src/project-build.d.ts.map +1 -0
- package/build/src/project-build.js +320 -0
- package/build/src/project-cli.d.ts +40 -0
- package/build/src/project-cli.d.ts.map +1 -0
- package/build/src/project-cli.js +145 -0
- package/build/src/project-manifest.d.ts +148 -0
- package/build/src/project-manifest.d.ts.map +1 -0
- package/build/src/project-manifest.js +432 -0
- package/build/src/project-reporter.d.ts +81 -0
- package/build/src/project-reporter.d.ts.map +1 -0
- package/build/src/project-reporter.js +293 -0
- package/build/src/project-snapshot.d.ts +129 -0
- package/build/src/project-snapshot.d.ts.map +1 -0
- package/build/src/project-snapshot.js +362 -0
- package/build/src/project-watch-reporter.d.ts +125 -0
- package/build/src/project-watch-reporter.d.ts.map +1 -0
- package/build/src/project-watch-reporter.js +280 -0
- package/build/src/project-watch.d.ts +133 -0
- package/build/src/project-watch.d.ts.map +1 -0
- package/build/src/project-watch.js +839 -0
- package/build/src/publication.d.ts +69 -5
- package/build/src/publication.d.ts.map +1 -1
- package/build/src/publication.js +246 -57
- package/build/src/semantic/effects.js +3 -1
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +11 -1
- package/build/src/semantic/types.d.ts +355 -4
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +92 -3
- package/build/src/semantic/validate.js +18 -1
- package/build/src/subprocess.d.ts +8 -0
- package/build/src/subprocess.d.ts.map +1 -1
- package/build/src/subprocess.js +50 -9
- package/build/src/target-check.d.ts +52 -0
- package/build/src/target-check.d.ts.map +1 -0
- package/build/src/target-check.js +796 -0
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +3 -3
- package/docs/adr-expression-breadth.md +186 -0
- package/docs/architecture.md +3 -1
- package/docs/c.md +4 -0
- package/docs/cpp.md +4 -0
- package/docs/dart.md +4 -0
- package/docs/generated-artifact-publication.md +11 -8
- package/docs/kotlin.md +2 -2
- package/docs/language-support.md +40 -6
- package/docs/parser-qualification.md +1 -1
- package/docs/project-build-cli.md +147 -0
- package/docs/project-watch.md +60 -0
- package/docs/rust.md +4 -0
- package/docs/swift.md +2 -0
- package/docs/testing.md +70 -3
- package/docs/watch-build-pipeline.md +39 -23
- package/docs/zig.md +2 -0
- package/examples/jsdoc-java-watch/expected-output.txt +3 -0
- package/examples/jsdoc-java-watch/semantifold.json +23 -0
- package/examples/jsdoc-java-watch/src/main.js +21 -0
- package/index.js +8 -0
- package/package.json +6 -1
- package/src/artifact-path.js +31 -2
- package/src/backends/c-check.js +80 -0
- package/src/backends/check-plan.js +147 -0
- package/src/backends/cpp-check.js +73 -0
- package/src/backends/csharp-check.js +139 -0
- package/src/backends/csharp.js +4 -3
- package/src/backends/dart-check.js +117 -0
- package/src/backends/dart.js +4 -4
- package/src/backends/go-check.js +89 -0
- package/src/backends/go.js +2 -2
- package/src/backends/java-check.js +77 -0
- package/src/backends/javascript-check.js +33 -0
- package/src/backends/kotlin-check.js +41 -0
- package/src/backends/kotlin.js +1 -1
- package/src/backends/php-check.js +23 -0
- package/src/backends/program.js +17 -0
- package/src/backends/python-check.js +30 -0
- package/src/backends/ruby-check.js +23 -0
- package/src/backends/rust-check.js +78 -0
- package/src/backends/shared.js +30 -0
- package/src/backends/swift-check.js +89 -0
- package/src/backends/typescript-check.js +37 -0
- package/src/backends/zig-check.js +81 -0
- package/src/diagnostic.js +9 -1
- package/src/frontends/java.js +24 -0
- package/src/frontends/javascript-typescript.js +49 -2
- package/src/frontends/php.js +61 -2
- package/src/frontends/program.js +9 -0
- package/src/frontends/ruby.js +62 -2
- package/src/language-registry.js +130 -9
- package/src/project-build.js +353 -0
- package/src/project-cli.js +155 -0
- package/src/project-manifest.js +479 -0
- package/src/project-reporter.js +320 -0
- package/src/project-snapshot.js +403 -0
- package/src/project-watch-reporter.js +303 -0
- package/src/project-watch.js +870 -0
- package/src/publication.js +275 -58
- package/src/semantic/effects.js +1 -0
- package/src/semantic/provenance.js +8 -0
- package/src/semantic/types.js +101 -2
- package/src/semantic/validate.js +26 -0
- package/src/subprocess.js +49 -8
- package/src/target-check.js +844 -0
- package/src/toolchains.js +3 -2
- package/tsconfig.json +1 -1
|
@@ -0,0 +1,796 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { lstat, mkdir, readdir, rm, rmdir } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { isDenseArray } from "./array.js";
|
|
5
|
+
import { createGeneratedArtifactSet } from "./artifacts.js";
|
|
6
|
+
import { SemantifoldDiagnostic } from "./diagnostic.js";
|
|
7
|
+
import { languageRegistry } from "./language-registry.js";
|
|
8
|
+
import { cancelledOwnedProcess, exceededOwnedDeadline, executeFileWithDeadline } from "./subprocess.js";
|
|
9
|
+
import { isSupportedTimeoutMs, maximumTimeoutMs } from "./timeout.js";
|
|
10
|
+
import { deterministicEnvironment } from "./toolchains.js";
|
|
11
|
+
const defaultTimeoutMs = 20_000;
|
|
12
|
+
const maximumOutputBytes = 1024 * 1024;
|
|
13
|
+
const identityPattern = /^[a-z][a-z0-9-]*$/u;
|
|
14
|
+
const mediaTypePattern = /^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+(?:;[\u0020-\u007e]+)?$/u;
|
|
15
|
+
const rolePattern = /^[a-z][a-z0-9-]*$/u;
|
|
16
|
+
const launchErrorCodes = new Set([
|
|
17
|
+
"E2BIG", "EACCES", "EAGAIN", "ELOOP", "EMFILE", "ENAMETOOLONG", "ENFILE", "ENOENT", "ENOEXEC", "ENOMEM",
|
|
18
|
+
"ENOTDIR", "ENOTSUP", "EPERM", "ETXTBSY"
|
|
19
|
+
]);
|
|
20
|
+
/** @type {WeakMap<TargetCheckRunner, {execute: typeof executeFileWithDeadline, now: () => number}>} */
|
|
21
|
+
const targetCheckRunnerDependencies = new WeakMap();
|
|
22
|
+
/**
|
|
23
|
+
* Creates and validates one target-owned developer check plan.
|
|
24
|
+
* @param {object} input - Exact staged target context.
|
|
25
|
+
* @param {import("./semantic/types.js").GeneratedArtifactSet} input.artifacts - Validated staged artifacts.
|
|
26
|
+
* @param {string} input.buildPath - Exact generation-scoped target build subtree.
|
|
27
|
+
* @param {string} input.projectId - Exact project identity.
|
|
28
|
+
* @param {string} input.sourcePath - Exact generation-scoped target source subtree.
|
|
29
|
+
* @param {string} input.targetId - Exact project target identity.
|
|
30
|
+
* @param {readonly import("./semantic/types.js").DiscoveredToolchain[]} input.tools - Discovered immutable tool records.
|
|
31
|
+
* @returns {import("./semantic/types.js").TargetCheckPlan} Validated immutable plan.
|
|
32
|
+
*/
|
|
33
|
+
export function createTargetCheckPlan(input) {
|
|
34
|
+
if (!isPlainObject(input) || !hasExactKeys(input, ["artifacts", "buildPath", "projectId", "sourcePath", "targetId", "tools"])) {
|
|
35
|
+
return invalidPlan("Target check planning requires only staged artifacts, candidate roots, identities, and tools.");
|
|
36
|
+
}
|
|
37
|
+
let artifacts;
|
|
38
|
+
try {
|
|
39
|
+
artifacts = createGeneratedArtifactSet(input.artifacts);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
return invalidPlan("Target check planning requires a valid generated artifact set.", "check", error);
|
|
43
|
+
}
|
|
44
|
+
const target = artifacts.target;
|
|
45
|
+
const record = languageRegistry.record(target);
|
|
46
|
+
const capability = record.check;
|
|
47
|
+
if (!capability.supported || typeof capability.factory != "function") {
|
|
48
|
+
throw new SemantifoldDiagnostic({
|
|
49
|
+
code: "UNSUPPORTED_TARGET_CHECK",
|
|
50
|
+
language: target,
|
|
51
|
+
message: "Registered target does not provide a developer check plan."
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (typeof input.projectId != "string" || !identityPattern.test(input.projectId) ||
|
|
55
|
+
typeof input.targetId != "string" || !identityPattern.test(input.targetId) ||
|
|
56
|
+
typeof input.sourcePath != "string" || !path.isAbsolute(input.sourcePath) ||
|
|
57
|
+
typeof input.buildPath != "string" || !path.isAbsolute(input.buildPath) ||
|
|
58
|
+
pathsOverlap(input.sourcePath, input.buildPath) || !isDenseArray(input.tools)) {
|
|
59
|
+
return invalidPlan("Target check planning received invalid identities, candidate roots, or tools.", target);
|
|
60
|
+
}
|
|
61
|
+
/** @type {import("./semantic/types.js").DiscoveredToolchain[]} */
|
|
62
|
+
const tools = [];
|
|
63
|
+
for (let index = 0; index < input.tools.length; index += 1) {
|
|
64
|
+
const tool = input.tools[index];
|
|
65
|
+
if (!isDiscoveredTool(tool) || !Object.isFrozen(tool) || !Object.isFrozen(tool.versionArguments)) {
|
|
66
|
+
return invalidPlan("Target check planning requires immutable discovered tool records.", target);
|
|
67
|
+
}
|
|
68
|
+
tools.push(tool);
|
|
69
|
+
}
|
|
70
|
+
if (tools.map(({ id }) => id).join("\0") != capability.toolchains.join("\0")) {
|
|
71
|
+
return invalidPlan("Target check planning tools must exactly match the target-declared developer-check toolchains.", target);
|
|
72
|
+
}
|
|
73
|
+
const context = Object.freeze({
|
|
74
|
+
artifacts,
|
|
75
|
+
buildPath: input.buildPath,
|
|
76
|
+
projectId: input.projectId,
|
|
77
|
+
sourcePath: input.sourcePath,
|
|
78
|
+
targetId: input.targetId,
|
|
79
|
+
tools: Object.freeze(tools)
|
|
80
|
+
});
|
|
81
|
+
let plan;
|
|
82
|
+
try {
|
|
83
|
+
plan = capability.factory(context);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error instanceof SemantifoldDiagnostic)
|
|
87
|
+
throw error;
|
|
88
|
+
return invalidPlan("Target check plan factory failed.", target, error);
|
|
89
|
+
}
|
|
90
|
+
const validated = validateTargetCheckPlan(plan);
|
|
91
|
+
const expectedArtifacts = new Set(context.artifacts.artifacts.map(artifact => path.join(context.sourcePath, artifact.path)));
|
|
92
|
+
if (validated.projectId != context.projectId || validated.targetId != context.targetId ||
|
|
93
|
+
validated.target != target || validated.sourcePath != context.sourcePath || validated.buildPath != context.buildPath ||
|
|
94
|
+
validated.artifactPaths.length != expectedArtifacts.size || validated.artifactPaths.some(artifact => !expectedArtifacts.has(artifact))) {
|
|
95
|
+
return invalidPlan("Target check plan changed its validated candidate context.", target);
|
|
96
|
+
}
|
|
97
|
+
return validated;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Owns ordered check subprocesses and settles only after each child closes.
|
|
101
|
+
*/
|
|
102
|
+
export class TargetCheckRunner {
|
|
103
|
+
/**
|
|
104
|
+
* Runs one already-staged immutable plan without executing generated application code.
|
|
105
|
+
* @param {import("./semantic/types.js").TargetCheckPlan} plan - Target-owned plan.
|
|
106
|
+
* @param {{onStage?: (result: import("./semantic/types.js").TargetCheckStageResult) => void, signal?: AbortSignal, timeoutMs?: number}} [options] - Lifecycle controls.
|
|
107
|
+
* @returns {Promise<import("./semantic/types.js").TargetCheckResult>} Successful check evidence and output metadata.
|
|
108
|
+
*/
|
|
109
|
+
async run(plan, options = {}) {
|
|
110
|
+
const validated = validateTargetCheckPlan(plan);
|
|
111
|
+
const dependencies = targetCheckRunnerDependencies.get(this) ?? {
|
|
112
|
+
execute: executeFileWithDeadline,
|
|
113
|
+
now: () => performance.now()
|
|
114
|
+
};
|
|
115
|
+
if (!isPlainObject(options) || options.onStage !== undefined && typeof options.onStage != "function" ||
|
|
116
|
+
options.signal !== undefined && !(options.signal instanceof AbortSignal)) {
|
|
117
|
+
return invalidPlan("Target check runner options are invalid.", validated.target);
|
|
118
|
+
}
|
|
119
|
+
const timeoutMs = options.timeoutMs === undefined ? defaultTimeoutMs : options.timeoutMs;
|
|
120
|
+
if (!isSupportedTimeoutMs(timeoutMs)) {
|
|
121
|
+
return invalidPlan(`Target check timeout must be from 1 through ${maximumTimeoutMs}ms.`, validated.target);
|
|
122
|
+
}
|
|
123
|
+
/** @type {import("./semantic/types.js").TargetCheckStageResult[]} */
|
|
124
|
+
const results = [];
|
|
125
|
+
/** @type {unknown} */
|
|
126
|
+
let stageFailure;
|
|
127
|
+
let stageFailed = false;
|
|
128
|
+
try {
|
|
129
|
+
for (const stage of validated.stages) {
|
|
130
|
+
const startedAt = dependencies.now();
|
|
131
|
+
/** @type {import("./semantic/types.js").TargetCheckStageResult} */
|
|
132
|
+
let stageResult;
|
|
133
|
+
if (options.signal?.aborted)
|
|
134
|
+
throw cancelledDiagnostic(stage, validated, 0);
|
|
135
|
+
try {
|
|
136
|
+
await prepareStage(stage, validated);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
throw preparationDiagnostic(error, stage, validated, elapsed(dependencies.now(), startedAt));
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const output = await dependencies.execute({
|
|
143
|
+
arguments: stage.argv,
|
|
144
|
+
cwd: stage.cwd,
|
|
145
|
+
environment: stage.environment,
|
|
146
|
+
executable: stage.executable,
|
|
147
|
+
maxBuffer: maximumOutputBytes,
|
|
148
|
+
signal: options.signal,
|
|
149
|
+
timeoutMs
|
|
150
|
+
});
|
|
151
|
+
stageResult = Object.freeze({
|
|
152
|
+
argv: stage.argv,
|
|
153
|
+
durationMs: elapsed(dependencies.now(), startedAt),
|
|
154
|
+
exitCode: 0,
|
|
155
|
+
signal: null,
|
|
156
|
+
stage: stage.stage,
|
|
157
|
+
stderr: output.stderr,
|
|
158
|
+
stdout: output.stdout,
|
|
159
|
+
tool: Object.freeze({
|
|
160
|
+
command: stage.tool.command,
|
|
161
|
+
executable: stage.tool.executable,
|
|
162
|
+
id: stage.tool.id,
|
|
163
|
+
source: stage.tool.source,
|
|
164
|
+
version: stage.tool.version
|
|
165
|
+
})
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
throw processDiagnostic(error, stage, validated, timeoutMs, elapsed(dependencies.now(), startedAt));
|
|
170
|
+
}
|
|
171
|
+
results.push(stageResult);
|
|
172
|
+
options.onStage?.(stageResult);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
stageFailed = true;
|
|
177
|
+
stageFailure = error;
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
await cleanupStageEnvironment(validated);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
const cleanup = cleanupDiagnostic(error, validated);
|
|
184
|
+
if (stageFailed && stageFailure instanceof Error)
|
|
185
|
+
throw preservePrimaryFailure(stageFailure, cleanup);
|
|
186
|
+
if (stageFailed)
|
|
187
|
+
throw new AggregateError([stageFailure, cleanup], "Target check failed and its owned transient environment could not be cleaned.", { cause: error });
|
|
188
|
+
throw cleanup;
|
|
189
|
+
}
|
|
190
|
+
if (stageFailed)
|
|
191
|
+
throw stageFailure;
|
|
192
|
+
const output = validated.stages.findLast(stage => stage.output !== null)?.output;
|
|
193
|
+
const outputs = output == null ? [] : await collectBuildOutputs(validated.buildPath, output);
|
|
194
|
+
return Object.freeze({
|
|
195
|
+
outputs: Object.freeze(outputs),
|
|
196
|
+
projectId: validated.projectId,
|
|
197
|
+
stages: Object.freeze(results),
|
|
198
|
+
target: validated.target,
|
|
199
|
+
targetId: validated.targetId
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Creates a runner with focused instance-owned dependencies.
|
|
205
|
+
* @param {{execute: typeof executeFileWithDeadline, now: () => number}} dependencies - Testable lifecycle collaborators.
|
|
206
|
+
* @returns {TargetCheckRunner} Runner.
|
|
207
|
+
*/
|
|
208
|
+
export function createTargetCheckRunner(dependencies) {
|
|
209
|
+
if (!isPlainObject(dependencies) || typeof dependencies.execute != "function" || typeof dependencies.now != "function") {
|
|
210
|
+
throw new TypeError("Invalid target check runner dependencies.");
|
|
211
|
+
}
|
|
212
|
+
const runner = new TargetCheckRunner();
|
|
213
|
+
targetCheckRunnerDependencies.set(runner, dependencies);
|
|
214
|
+
return runner;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Validates a complete immutable plan before any process starts.
|
|
218
|
+
* @param {unknown} candidate - Candidate plan.
|
|
219
|
+
* @returns {import("./semantic/types.js").TargetCheckPlan} Exact validated plan.
|
|
220
|
+
*/
|
|
221
|
+
export function validateTargetCheckPlan(candidate) {
|
|
222
|
+
if (!isPlainObject(candidate) || !Object.isFrozen(candidate) || !hasExactKeys(candidate, [
|
|
223
|
+
"artifactPaths", "buildPath", "mode", "projectId", "schema", "sourcePath", "stages", "target", "targetId", "version"
|
|
224
|
+
]))
|
|
225
|
+
return invalidPlan("Target check plan must be one immutable closed schema record.");
|
|
226
|
+
const target = typeof candidate.target == "string" ? candidate.target : "check";
|
|
227
|
+
const record = languageRegistry.record(target);
|
|
228
|
+
const capability = record.check;
|
|
229
|
+
if (!capability.supported || candidate.schema != "SemantifoldTargetCheckPlan" || candidate.version != 1 ||
|
|
230
|
+
candidate.mode != "developer-check" || typeof candidate.projectId != "string" || !identityPattern.test(candidate.projectId) ||
|
|
231
|
+
typeof candidate.targetId != "string" || !identityPattern.test(candidate.targetId) ||
|
|
232
|
+
typeof candidate.sourcePath != "string" || !path.isAbsolute(candidate.sourcePath) ||
|
|
233
|
+
typeof candidate.buildPath != "string" || !path.isAbsolute(candidate.buildPath) ||
|
|
234
|
+
pathsOverlap(candidate.sourcePath, candidate.buildPath)) {
|
|
235
|
+
return invalidPlan("Target check plan has invalid schema, mode, identity, target, or candidate roots.", target);
|
|
236
|
+
}
|
|
237
|
+
if (!isDenseArray(candidate.artifactPaths) || !Object.isFrozen(candidate.artifactPaths) || candidate.artifactPaths.length == 0 ||
|
|
238
|
+
!isDenseArray(candidate.stages) || !Object.isFrozen(candidate.stages) || candidate.stages.length == 0) {
|
|
239
|
+
return invalidPlan("Target check plan requires dense immutable artifact and stage vectors.", target);
|
|
240
|
+
}
|
|
241
|
+
const artifactPaths = new Set();
|
|
242
|
+
for (let index = 0; index < candidate.artifactPaths.length; index += 1) {
|
|
243
|
+
const artifactPath = candidate.artifactPaths[index];
|
|
244
|
+
if (typeof artifactPath != "string" || !ownedBy(candidate.sourcePath, artifactPath) || artifactPaths.has(artifactPath)) {
|
|
245
|
+
return invalidPlan("Every planned artifact must be a distinct absolute path inside the candidate source subtree.", target);
|
|
246
|
+
}
|
|
247
|
+
artifactPaths.add(artifactPath);
|
|
248
|
+
}
|
|
249
|
+
const plannedStageKinds = candidate.stages.map(stage => isPlainObject(stage) && typeof stage.stage == "string" ? stage.stage : "")
|
|
250
|
+
.filter((stage, index, stages) => index == 0 || stage != stages[index - 1]);
|
|
251
|
+
if (plannedStageKinds.join("\0") != capability.stages.join("\0")) {
|
|
252
|
+
return invalidPlan("Target check stages must exactly match the target-declared developer-check stages.", target);
|
|
253
|
+
}
|
|
254
|
+
const usedTools = new Set();
|
|
255
|
+
const referencedArtifactPaths = new Set();
|
|
256
|
+
for (let index = 0; index < candidate.stages.length; index += 1) {
|
|
257
|
+
const stage = candidate.stages[index];
|
|
258
|
+
if (!isPlainObject(stage) || !Object.isFrozen(stage) || !hasExactKeys(stage, [
|
|
259
|
+
"argv", "cwd", "environment", "environmentPaths", "executable", "inputHash", "inputs", "output", "pathArguments",
|
|
260
|
+
"stage", "tool", "transientPaths"
|
|
261
|
+
]) || typeof stage.stage != "string" || stage.stage == "execute" ||
|
|
262
|
+
!record.acceptance.stages.includes(/** @type {import("./semantic/types.js").AcceptanceStage} */ (stage.stage))) {
|
|
263
|
+
return invalidPlan("Target check stages must be immutable, ordered, declared, and non-executing.", target);
|
|
264
|
+
}
|
|
265
|
+
const request = /** @type {import("./semantic/types.js").TargetCheckStageRequest} */ (stage);
|
|
266
|
+
if (!isDiscoveredTool(request.tool) || !Object.isFrozen(request.tool) || !Object.isFrozen(request.tool.versionArguments) ||
|
|
267
|
+
request.executable != request.tool.executable || !capability.toolchains.includes(request.tool.id)) {
|
|
268
|
+
return invalidPlan(`Target check stage '${request.stage}' uses an invalid or undeclared tool.`, target);
|
|
269
|
+
}
|
|
270
|
+
usedTools.add(request.tool.id);
|
|
271
|
+
if (!isDenseArray(request.argv) || !Object.isFrozen(request.argv) ||
|
|
272
|
+
!request.argv.every(argument => typeof argument == "string" && !argument.includes("\0")) ||
|
|
273
|
+
!isDenseArray(request.pathArguments) || !Object.isFrozen(request.pathArguments)) {
|
|
274
|
+
return invalidPlan(`Target check stage '${request.stage}' requires a dense immutable shell-free argv.`, target);
|
|
275
|
+
}
|
|
276
|
+
if (!validEnvironment(request.environment)) {
|
|
277
|
+
return invalidPlan(`Target check stage '${request.stage}' requires an immutable deterministic environment.`, target);
|
|
278
|
+
}
|
|
279
|
+
if (!validEnvironmentPaths(request.environmentPaths, request.environment, candidate.sourcePath, candidate.buildPath, capability.toolchains, usedTools)) {
|
|
280
|
+
return invalidPlan(`Target check stage '${request.stage}' has invalid environment-path ownership.`, target);
|
|
281
|
+
}
|
|
282
|
+
if (typeof request.cwd != "string" || !ownedByEither(candidate.sourcePath, candidate.buildPath, request.cwd)) {
|
|
283
|
+
return invalidPlan(`Target check stage '${request.stage}' working directory escapes the candidate target subtrees.`, target);
|
|
284
|
+
}
|
|
285
|
+
if (request.output !== null && !validOutput(request.output, candidate.buildPath)) {
|
|
286
|
+
return invalidPlan(`Target check stage '${request.stage}' has invalid compiler-output ownership.`, target);
|
|
287
|
+
}
|
|
288
|
+
if (!validTransientPaths(request.transientPaths, candidate.sourcePath, candidate.buildPath, artifactPaths)) {
|
|
289
|
+
return invalidPlan(`Target check stage '${request.stage}' has invalid transient-path ownership.`, target);
|
|
290
|
+
}
|
|
291
|
+
if (request.stage == "restore" ? typeof request.inputHash != "string" || !/^[a-f0-9]{64}$/u.test(request.inputHash) : request.inputHash !== null) {
|
|
292
|
+
return invalidPlan(`Target check stage '${request.stage}' has invalid restore-input identity.`, target);
|
|
293
|
+
}
|
|
294
|
+
if (!isDenseArray(request.inputs) || !Object.isFrozen(request.inputs) || request.inputs.length == 0) {
|
|
295
|
+
return invalidPlan(`Target check stage '${request.stage}' requires immutable declared inputs.`, target);
|
|
296
|
+
}
|
|
297
|
+
const stageInputs = new Set();
|
|
298
|
+
for (let inputIndex = 0; inputIndex < request.inputs.length; inputIndex += 1) {
|
|
299
|
+
const inputPath = request.inputs[inputIndex];
|
|
300
|
+
if (typeof inputPath != "string" || stageInputs.has(inputPath) || !ownedByEither(candidate.sourcePath, candidate.buildPath, inputPath)) {
|
|
301
|
+
return invalidPlan(`Target check stage '${request.stage}' has invalid or duplicate declared inputs.`, target);
|
|
302
|
+
}
|
|
303
|
+
if (ownedBy(candidate.sourcePath, inputPath)) {
|
|
304
|
+
if (!artifactPaths.has(inputPath)) {
|
|
305
|
+
return invalidPlan(`Target check stage '${request.stage}' reads an undeclared staged artifact.`, target);
|
|
306
|
+
}
|
|
307
|
+
referencedArtifactPaths.add(inputPath);
|
|
308
|
+
}
|
|
309
|
+
stageInputs.add(inputPath);
|
|
310
|
+
}
|
|
311
|
+
const pathIndexes = new Set();
|
|
312
|
+
for (let pathIndex = 0; pathIndex < request.pathArguments.length; pathIndex += 1) {
|
|
313
|
+
const declaration = request.pathArguments[pathIndex];
|
|
314
|
+
if (!isPlainObject(declaration) || !Object.isFrozen(declaration) ||
|
|
315
|
+
!hasExactKeys(declaration, declaration.prefix === undefined ? ["index", "ownership"] : ["index", "ownership", "prefix"]) ||
|
|
316
|
+
typeof declaration.index != "number" || !Number.isInteger(declaration.index) || declaration.index < 0 ||
|
|
317
|
+
declaration.index >= request.argv.length ||
|
|
318
|
+
pathIndexes.has(declaration.index) || declaration.ownership != "source" && declaration.ownership != "build" ||
|
|
319
|
+
declaration.prefix !== undefined && (typeof declaration.prefix != "string" || declaration.prefix.length == 0 ||
|
|
320
|
+
declaration.prefix.includes("\0"))) {
|
|
321
|
+
return invalidPlan(`Target check stage '${request.stage}' has invalid path-argument ownership.`, target);
|
|
322
|
+
}
|
|
323
|
+
const rawArgument = request.argv[declaration.index];
|
|
324
|
+
const argument = declaration.prefix === undefined
|
|
325
|
+
? rawArgument
|
|
326
|
+
: rawArgument.startsWith(declaration.prefix)
|
|
327
|
+
? rawArgument.slice(declaration.prefix.length)
|
|
328
|
+
: "";
|
|
329
|
+
const root = declaration.ownership == "source" ? candidate.sourcePath : candidate.buildPath;
|
|
330
|
+
if (argument != root && !ownedBy(root, argument)) {
|
|
331
|
+
return invalidPlan(`Target check stage '${request.stage}' path argument escapes its candidate subtree.`, target);
|
|
332
|
+
}
|
|
333
|
+
pathIndexes.add(declaration.index);
|
|
334
|
+
}
|
|
335
|
+
for (let argumentIndex = 0; argumentIndex < request.argv.length; argumentIndex += 1) {
|
|
336
|
+
if (path.isAbsolute(request.argv[argumentIndex]) && !pathIndexes.has(argumentIndex)) {
|
|
337
|
+
return invalidPlan(`Target check stage '${request.stage}' contains an unowned absolute path argument.`, target);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (referencedArtifactPaths.size != artifactPaths.size) {
|
|
342
|
+
return invalidPlan("Target check plan must include every staged check artifact.", target);
|
|
343
|
+
}
|
|
344
|
+
if (capability.toolchains.some(toolchain => !usedTools.has(toolchain))) {
|
|
345
|
+
return invalidPlan("Target check plan omits a target-declared toolchain.", target);
|
|
346
|
+
}
|
|
347
|
+
return /** @type {import("./semantic/types.js").TargetCheckPlan} */ (candidate);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Collects every regular compiler output without following links.
|
|
351
|
+
* @param {string} buildPath - Exact owned build root.
|
|
352
|
+
* @param {import("./semantic/types.js").TargetCheckOutputOwnership} output - Output metadata.
|
|
353
|
+
* @returns {Promise<import("./semantic/types.js").PublicationBuildArtifactInput[]>} Ordered metadata.
|
|
354
|
+
*/
|
|
355
|
+
async function collectBuildOutputs(buildPath, output) {
|
|
356
|
+
/** @type {string[]} */
|
|
357
|
+
const files = [];
|
|
358
|
+
/** @type {{absolute: string, relative: string}[]} */
|
|
359
|
+
const pending = [{ absolute: buildPath, relative: "" }];
|
|
360
|
+
while (pending.length > 0) {
|
|
361
|
+
const current = /** @type {{absolute: string, relative: string}} */ (pending.pop());
|
|
362
|
+
let entries;
|
|
363
|
+
try {
|
|
364
|
+
entries = await readdir(current.absolute, { withFileTypes: true });
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
return outputFailure("Compiler output subtree could not be inspected.", error);
|
|
368
|
+
}
|
|
369
|
+
entries.sort((left, right) => left.name.localeCompare(right.name, "en"));
|
|
370
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
371
|
+
const entry = entries[index];
|
|
372
|
+
const relative = current.relative.length == 0 ? entry.name : `${current.relative}/${entry.name}`;
|
|
373
|
+
const absolute = path.join(current.absolute, entry.name);
|
|
374
|
+
if (entry.isDirectory())
|
|
375
|
+
pending.push({ absolute, relative });
|
|
376
|
+
else if (entry.isFile())
|
|
377
|
+
files.push(relative);
|
|
378
|
+
else
|
|
379
|
+
return outputFailure(`Compiler output '${relative}' is not a regular file or directory.`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
files.sort((left, right) => left.localeCompare(right, "en"));
|
|
383
|
+
for (const filename of files) {
|
|
384
|
+
try {
|
|
385
|
+
if (!(await lstat(path.join(buildPath, filename))).isFile()) {
|
|
386
|
+
return outputFailure(`Compiler output '${filename}' is not a regular file.`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
return outputFailure(`Compiler output '${filename}' could not be inspected.`, error);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return files.map(filename => Object.freeze({ mediaType: output.mediaType, path: filename, role: output.role }));
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Normalizes one child failure while retaining complete bounded output.
|
|
397
|
+
* @param {unknown} error - Opaque process failure.
|
|
398
|
+
* @param {import("./semantic/types.js").TargetCheckStageRequest} stage - Failed stage.
|
|
399
|
+
* @param {import("./semantic/types.js").TargetCheckPlan} plan - Plan context.
|
|
400
|
+
* @param {number} timeoutMs - Exact timeout.
|
|
401
|
+
* @param {number} durationMs - Observed duration.
|
|
402
|
+
* @returns {SemantifoldDiagnostic} Structured check failure.
|
|
403
|
+
*/
|
|
404
|
+
function processDiagnostic(error, stage, plan, timeoutMs, durationMs) {
|
|
405
|
+
const fields = processErrorFields(error);
|
|
406
|
+
const outputLimited = fields.nativeCode == "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
407
|
+
const cancelled = !outputLimited && cancelledOwnedProcess(error);
|
|
408
|
+
const timedOut = !outputLimited && !cancelled && exceededOwnedDeadline(error);
|
|
409
|
+
const launchFailure = fields.nativeCode != undefined && launchErrorCodes.has(fields.nativeCode);
|
|
410
|
+
const signaled = !outputLimited && !cancelled && !timedOut && fields.signal != undefined;
|
|
411
|
+
const code = outputLimited ? "TARGET_CHECK_OUTPUT_LIMIT" : cancelled ? "TARGET_CHECK_CANCELLED" : timedOut
|
|
412
|
+
? "TARGET_CHECK_TIMEOUT" : launchFailure ? "TARGET_CHECK_LAUNCH_FAILURE" : signaled
|
|
413
|
+
? "TARGET_CHECK_SIGNAL" : "TARGET_CHECK_NONZERO_EXIT";
|
|
414
|
+
const reason = outputLimited ? `exceeded the ${maximumOutputBytes}-byte output limit` : cancelled
|
|
415
|
+
? "was cancelled" : timedOut ? `timed out after ${timeoutMs}ms` : launchFailure
|
|
416
|
+
? `could not launch (${fields.nativeCode})` : signaled ? `closed after signal ${fields.signal}`
|
|
417
|
+
: fields.exitCode == undefined ? "failed after launch" : `exited nonzero (${fields.exitCode})`;
|
|
418
|
+
return new SemantifoldDiagnostic({
|
|
419
|
+
cause: outputLimited ? undefined : error instanceof Error ? error : undefined,
|
|
420
|
+
code,
|
|
421
|
+
durationMs,
|
|
422
|
+
executable: stage.executable,
|
|
423
|
+
exitCode: fields.exitCode,
|
|
424
|
+
language: plan.target,
|
|
425
|
+
message: `Target '${plan.targetId}' stage '${stage.stage}' ${reason} using '${stage.executable}' (${stage.tool.version}).`,
|
|
426
|
+
projectId: plan.projectId,
|
|
427
|
+
signal: fields.signal,
|
|
428
|
+
stage: stage.stage,
|
|
429
|
+
stderr: fields.stderr,
|
|
430
|
+
stdout: fields.stdout,
|
|
431
|
+
targetId: plan.targetId,
|
|
432
|
+
toolId: stage.tool.id,
|
|
433
|
+
version: stage.tool.version
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Creates target-owned environment directories before launch without touching source staging.
|
|
438
|
+
* @param {import("./semantic/types.js").TargetCheckStageRequest} stage - Validated stage.
|
|
439
|
+
* @param {import("./semantic/types.js").TargetCheckPlan} plan - Validated plan context.
|
|
440
|
+
* @returns {Promise<void>} Completion.
|
|
441
|
+
*/
|
|
442
|
+
async function prepareStage(stage, plan) {
|
|
443
|
+
for (const declaration of stage.environmentPaths) {
|
|
444
|
+
if (declaration.ownership == "build") {
|
|
445
|
+
await mkdir(stage.environment[declaration.name], { mode: 0o700, recursive: true });
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
for (const transientPath of stage.transientPaths) {
|
|
449
|
+
if (ownedBy(plan.buildPath, transientPath))
|
|
450
|
+
await mkdir(transientPath, { mode: 0o700, recursive: true });
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Removes only explicitly declared generation-owned transient cache/home directories after every child has closed.
|
|
455
|
+
* @param {import("./semantic/types.js").TargetCheckPlan} plan - Validated plan.
|
|
456
|
+
* @returns {Promise<void>} Completion.
|
|
457
|
+
*/
|
|
458
|
+
async function cleanupStageEnvironment(plan) {
|
|
459
|
+
const owned = new Set();
|
|
460
|
+
for (const stage of plan.stages) {
|
|
461
|
+
for (const declaration of stage.environmentPaths) {
|
|
462
|
+
if (declaration.ownership == "build")
|
|
463
|
+
owned.add(stage.environment[declaration.name]);
|
|
464
|
+
}
|
|
465
|
+
for (const transientPath of stage.transientPaths)
|
|
466
|
+
owned.add(transientPath);
|
|
467
|
+
}
|
|
468
|
+
const paths = [...owned].sort((left, right) => right.length - left.length || right.localeCompare(left, "en"));
|
|
469
|
+
for (const ownedPath of paths) {
|
|
470
|
+
await rm(ownedPath, { force: true, recursive: true });
|
|
471
|
+
await removeEmptyParents(path.dirname(ownedPath), ownedBy(plan.buildPath, ownedPath) ? plan.buildPath : plan.sourcePath);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Removes empty transient ancestors without ever removing the candidate build root.
|
|
476
|
+
* @param {string} candidate - First possible empty ancestor.
|
|
477
|
+
* @param {string} root - Exact retained candidate root.
|
|
478
|
+
* @returns {Promise<void>} Completion.
|
|
479
|
+
*/
|
|
480
|
+
async function removeEmptyParents(candidate, root) {
|
|
481
|
+
let current = candidate;
|
|
482
|
+
while (ownedBy(root, current)) {
|
|
483
|
+
if ((await readdir(current)).length > 0)
|
|
484
|
+
return;
|
|
485
|
+
await rmdir(current);
|
|
486
|
+
current = path.dirname(current);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Preserves cache/home preparation failures separately from tool launch or compilation.
|
|
491
|
+
* @param {unknown} error - Filesystem failure.
|
|
492
|
+
* @param {import("./semantic/types.js").TargetCheckStageRequest} stage - Failed stage.
|
|
493
|
+
* @param {import("./semantic/types.js").TargetCheckPlan} plan - Plan context.
|
|
494
|
+
* @param {number} durationMs - Observed duration.
|
|
495
|
+
* @returns {SemantifoldDiagnostic} Structured failure.
|
|
496
|
+
*/
|
|
497
|
+
function preparationDiagnostic(error, stage, plan, durationMs) {
|
|
498
|
+
return new SemantifoldDiagnostic({
|
|
499
|
+
cause: error instanceof Error ? error : undefined,
|
|
500
|
+
code: "TARGET_CHECK_PREPARATION_FAILURE",
|
|
501
|
+
durationMs,
|
|
502
|
+
executable: stage.executable,
|
|
503
|
+
language: plan.target,
|
|
504
|
+
message: `Target '${plan.targetId}' stage '${stage.stage}' could not prepare its owned cache/home directories.`,
|
|
505
|
+
projectId: plan.projectId,
|
|
506
|
+
stage: stage.stage,
|
|
507
|
+
stderr: "",
|
|
508
|
+
stdout: "",
|
|
509
|
+
targetId: plan.targetId,
|
|
510
|
+
toolId: stage.tool.id,
|
|
511
|
+
version: stage.tool.version
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Reports transient cache/home cleanup separately from native compiler diagnostics.
|
|
516
|
+
* @param {unknown} error - Filesystem failure.
|
|
517
|
+
* @param {import("./semantic/types.js").TargetCheckPlan} plan - Plan context.
|
|
518
|
+
* @returns {SemantifoldDiagnostic} Structured cleanup failure.
|
|
519
|
+
*/
|
|
520
|
+
function cleanupDiagnostic(error, plan) {
|
|
521
|
+
return new SemantifoldDiagnostic({
|
|
522
|
+
cause: error instanceof Error ? error : undefined,
|
|
523
|
+
code: "TARGET_CHECK_CLEANUP_FAILURE",
|
|
524
|
+
language: plan.target,
|
|
525
|
+
message: `Target '${plan.targetId}' could not remove its owned transient cache/home directories.`,
|
|
526
|
+
projectId: plan.projectId,
|
|
527
|
+
targetId: plan.targetId
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Retains the first plan/process diagnostic while attaching bounded cleanup evidence.
|
|
532
|
+
* @param {Error} primaryFailure - First check failure.
|
|
533
|
+
* @param {SemantifoldDiagnostic} cleanupFailure - Structured cleanup failure.
|
|
534
|
+
* @returns {Error} Original failure with cleanup evidence in its cause chain.
|
|
535
|
+
*/
|
|
536
|
+
function preservePrimaryFailure(primaryFailure, cleanupFailure) {
|
|
537
|
+
const causes = primaryFailure.cause instanceof Error ? [primaryFailure.cause, cleanupFailure] : [cleanupFailure];
|
|
538
|
+
Object.defineProperty(primaryFailure, "cause", {
|
|
539
|
+
configurable: true,
|
|
540
|
+
value: new AggregateError(causes, "Target check failed and its owned transient environment cleanup also failed."),
|
|
541
|
+
writable: true
|
|
542
|
+
});
|
|
543
|
+
return primaryFailure;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Creates a structured failure when cancellation precedes stage launch.
|
|
547
|
+
* @param {import("./semantic/types.js").TargetCheckStageRequest} stage - Cancelled stage.
|
|
548
|
+
* @param {import("./semantic/types.js").TargetCheckPlan} plan - Plan context.
|
|
549
|
+
* @param {number} durationMs - Observed duration.
|
|
550
|
+
* @returns {SemantifoldDiagnostic} Structured cancellation diagnostic.
|
|
551
|
+
*/
|
|
552
|
+
function cancelledDiagnostic(stage, plan, durationMs) {
|
|
553
|
+
return new SemantifoldDiagnostic({
|
|
554
|
+
code: "TARGET_CHECK_CANCELLED",
|
|
555
|
+
durationMs,
|
|
556
|
+
executable: stage.executable,
|
|
557
|
+
language: plan.target,
|
|
558
|
+
message: `Target '${plan.targetId}' stage '${stage.stage}' was cancelled before launch.`,
|
|
559
|
+
projectId: plan.projectId,
|
|
560
|
+
stage: stage.stage,
|
|
561
|
+
stderr: "",
|
|
562
|
+
stdout: "",
|
|
563
|
+
targetId: plan.targetId,
|
|
564
|
+
toolId: stage.tool.id,
|
|
565
|
+
version: stage.tool.version
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Extracts stable bounded child-process failure fields.
|
|
570
|
+
* @param {unknown} error - Opaque process rejection.
|
|
571
|
+
* @returns {{exitCode: number | undefined, nativeCode: string | undefined, signal: string | undefined, stderr: string, stdout: string}} Stable fields.
|
|
572
|
+
*/
|
|
573
|
+
function processErrorFields(error) {
|
|
574
|
+
if (!error || typeof error != "object")
|
|
575
|
+
return { exitCode: undefined, nativeCode: undefined, signal: undefined, stderr: "", stdout: "" };
|
|
576
|
+
const value = /** @type {Record<string, unknown>} */ (error);
|
|
577
|
+
return {
|
|
578
|
+
exitCode: typeof value.code == "number" ? value.code : undefined,
|
|
579
|
+
nativeCode: typeof value.code == "string" ? value.code : undefined,
|
|
580
|
+
signal: typeof value.signal == "string" ? value.signal : undefined,
|
|
581
|
+
stderr: typeof value.stderr == "string" ? value.stderr : "",
|
|
582
|
+
stdout: typeof value.stdout == "string" ? value.stdout : ""
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Checks the complete immutable discovered-tool shape consumed by a plan.
|
|
587
|
+
* @param {unknown} value - Candidate tool record.
|
|
588
|
+
* @returns {value is import("./semantic/types.js").DiscoveredToolchain} Whether the tool shape is valid.
|
|
589
|
+
*/
|
|
590
|
+
function isDiscoveredTool(value) {
|
|
591
|
+
return isPlainObject(value) && typeof value.id == "string" && typeof value.command == "string" &&
|
|
592
|
+
typeof value.executable == "string" && path.isAbsolute(value.executable) && !value.executable.includes("\0") &&
|
|
593
|
+
(value.source == "canonical" || value.source == "override") && typeof value.version == "string" && value.version.length > 0 &&
|
|
594
|
+
typeof value.versionOutput == "string" && isDenseArray(value.versionArguments) &&
|
|
595
|
+
value.versionArguments.every(argument => typeof argument == "string" && !argument.includes("\0"));
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Checks that an environment is immutable and already deterministic.
|
|
599
|
+
* @param {unknown} value - Candidate environment record.
|
|
600
|
+
* @returns {boolean} Whether the environment is normalized.
|
|
601
|
+
*/
|
|
602
|
+
function validEnvironment(value) {
|
|
603
|
+
if (!isPlainRecord(value) || !Object.isFrozen(value))
|
|
604
|
+
return false;
|
|
605
|
+
let normalized;
|
|
606
|
+
try {
|
|
607
|
+
normalized = deterministicEnvironment(/** @type {Readonly<Record<string, string>>} */ (value));
|
|
608
|
+
}
|
|
609
|
+
catch {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
const actual = Object.entries(value).sort(([left], [right]) => left.localeCompare(right, "en"));
|
|
613
|
+
const expected = Object.entries(normalized).sort(([left], [right]) => left.localeCompare(right, "en"));
|
|
614
|
+
return JSON.stringify(actual) == JSON.stringify(expected);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Checks every absolute non-PATH environment value against an explicit candidate-owned directory or discovered-tool declaration.
|
|
618
|
+
* @param {unknown} value - Candidate declarations.
|
|
619
|
+
* @param {Readonly<Record<string, string>>} environment - Validated deterministic environment.
|
|
620
|
+
* @param {string} sourcePath - Candidate source root.
|
|
621
|
+
* @param {string} buildPath - Candidate build root.
|
|
622
|
+
* @param {readonly string[]} toolchains - Target-declared toolchain IDs.
|
|
623
|
+
* @param {Set<string>} usedTools - Validated tools used by this plan.
|
|
624
|
+
* @returns {value is readonly import("./semantic/types.js").TargetCheckEnvironmentPath[]} Whether ownership is complete.
|
|
625
|
+
*/
|
|
626
|
+
function validEnvironmentPaths(value, environment, sourcePath, buildPath, toolchains, usedTools) {
|
|
627
|
+
if (!isDenseArray(value) || !Object.isFrozen(value))
|
|
628
|
+
return false;
|
|
629
|
+
const names = new Set();
|
|
630
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
631
|
+
const declaration = value[index];
|
|
632
|
+
if (!isPlainObject(declaration) || !Object.isFrozen(declaration) ||
|
|
633
|
+
!hasExactKeys(declaration, declaration.ownership == "tool" ? ["name", "ownership", "tool"] : ["name", "ownership"]) ||
|
|
634
|
+
typeof declaration.name != "string" || names.has(declaration.name))
|
|
635
|
+
return false;
|
|
636
|
+
const environmentPath = environment[declaration.name];
|
|
637
|
+
if (declaration.ownership == "tool") {
|
|
638
|
+
if (!isDiscoveredTool(declaration.tool) || !Object.isFrozen(declaration.tool) ||
|
|
639
|
+
!Object.isFrozen(declaration.tool.versionArguments) || !toolchains.includes(declaration.tool.id) ||
|
|
640
|
+
environmentPath != declaration.tool.executable)
|
|
641
|
+
return false;
|
|
642
|
+
usedTools.add(declaration.tool.id);
|
|
643
|
+
names.add(declaration.name);
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
if (declaration.ownership != "source" && declaration.ownership != "build")
|
|
647
|
+
return false;
|
|
648
|
+
const root = declaration.ownership == "source" ? sourcePath : buildPath;
|
|
649
|
+
if (typeof environmentPath != "string" || !ownedBy(root, environmentPath))
|
|
650
|
+
return false;
|
|
651
|
+
names.add(declaration.name);
|
|
652
|
+
}
|
|
653
|
+
for (const [name, environmentValue] of Object.entries(environment)) {
|
|
654
|
+
if (name != "PATH" && path.isAbsolute(environmentValue) && !names.has(name))
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
return true;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Checks generation-owned transient cache/intermediate directories.
|
|
661
|
+
* @param {unknown} value - Candidate path vector.
|
|
662
|
+
* @param {string} sourcePath - Candidate source root.
|
|
663
|
+
* @param {string} buildPath - Candidate build root.
|
|
664
|
+
* @param {Set<string>} artifactPaths - Exact staged artifact paths.
|
|
665
|
+
* @returns {value is readonly string[]} Whether paths are immutable distinct candidate descendants.
|
|
666
|
+
*/
|
|
667
|
+
function validTransientPaths(value, sourcePath, buildPath, artifactPaths) {
|
|
668
|
+
if (!isDenseArray(value) || !Object.isFrozen(value))
|
|
669
|
+
return false;
|
|
670
|
+
const paths = new Set();
|
|
671
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
672
|
+
const transientPath = value[index];
|
|
673
|
+
if (typeof transientPath != "string" || !ownedBy(sourcePath, transientPath) && !ownedBy(buildPath, transientPath) ||
|
|
674
|
+
paths.has(transientPath) || ownedBy(sourcePath, transientPath) && [...artifactPaths].some(artifactPath => transientPath == artifactPath || pathsOverlap(transientPath, artifactPath)))
|
|
675
|
+
return false;
|
|
676
|
+
paths.add(transientPath);
|
|
677
|
+
}
|
|
678
|
+
return true;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Checks compiler-output metadata against the owned build root.
|
|
682
|
+
* @param {unknown} value - Candidate output record.
|
|
683
|
+
* @param {string} buildPath - Exact candidate build root.
|
|
684
|
+
* @returns {boolean} Whether output ownership is valid.
|
|
685
|
+
*/
|
|
686
|
+
function validOutput(value, buildPath) {
|
|
687
|
+
return isPlainObject(value) && Object.isFrozen(value) && hasExactKeys(value, ["mediaType", "ownership", "path", "role"]) &&
|
|
688
|
+
value.ownership == "build" && value.path == buildPath && typeof value.mediaType == "string" &&
|
|
689
|
+
mediaTypePattern.test(value.mediaType) && typeof value.role == "string" && rolePattern.test(value.role);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Checks strict descendant ownership without accepting the root itself.
|
|
693
|
+
* @param {string} root - Absolute owned root.
|
|
694
|
+
* @param {string} candidate - Absolute candidate path.
|
|
695
|
+
* @returns {boolean} Whether the candidate is a strict descendant.
|
|
696
|
+
*/
|
|
697
|
+
function ownedBy(root, candidate) {
|
|
698
|
+
if (!path.isAbsolute(candidate))
|
|
699
|
+
return false;
|
|
700
|
+
const relative = path.relative(root, candidate);
|
|
701
|
+
return relative.length > 0 && !relative.startsWith(`..${path.sep}`) && relative != ".." && !path.isAbsolute(relative);
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Checks candidate ownership by either exact target subtree.
|
|
705
|
+
* @param {string} sourcePath - Exact source root.
|
|
706
|
+
* @param {string} buildPath - Exact build root.
|
|
707
|
+
* @param {string} candidate - Candidate working directory.
|
|
708
|
+
* @returns {boolean} Whether either target subtree owns the candidate.
|
|
709
|
+
*/
|
|
710
|
+
function ownedByEither(sourcePath, buildPath, candidate) {
|
|
711
|
+
return candidate == sourcePath || candidate == buildPath || ownedBy(sourcePath, candidate) || ownedBy(buildPath, candidate);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Checks whether two absolute roots overlap in either direction.
|
|
715
|
+
* @param {string} left - First root.
|
|
716
|
+
* @param {string} right - Second root.
|
|
717
|
+
* @returns {boolean} Whether the roots overlap.
|
|
718
|
+
*/
|
|
719
|
+
function pathsOverlap(left, right) {
|
|
720
|
+
return left == right || ownedBy(left, right) || ownedBy(right, left);
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Normalizes one monotonic duration observation.
|
|
724
|
+
* @param {number} endedAt - End observation.
|
|
725
|
+
* @param {number} startedAt - Start observation.
|
|
726
|
+
* @returns {number} Finite non-negative duration.
|
|
727
|
+
*/
|
|
728
|
+
function elapsed(endedAt, startedAt) {
|
|
729
|
+
const duration = endedAt - startedAt;
|
|
730
|
+
return Number.isFinite(duration) && duration >= 0 ? duration : 0;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Throws one compiler-output inspection diagnostic.
|
|
734
|
+
* @param {string} message - Failure detail.
|
|
735
|
+
* @param {unknown} [cause] - Optional underlying failure.
|
|
736
|
+
* @returns {never} Always throws.
|
|
737
|
+
*/
|
|
738
|
+
function outputFailure(message, cause) {
|
|
739
|
+
throw new SemantifoldDiagnostic({
|
|
740
|
+
cause: cause instanceof Error ? cause : undefined,
|
|
741
|
+
code: "TARGET_CHECK_OUTPUT_INVALID",
|
|
742
|
+
language: "check",
|
|
743
|
+
message
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Throws one invalid-plan diagnostic.
|
|
748
|
+
* @param {string} message - Failure detail.
|
|
749
|
+
* @param {string} [target] - Target diagnostic identity.
|
|
750
|
+
* @param {unknown} [cause] - Optional underlying failure.
|
|
751
|
+
* @returns {never} Always throws.
|
|
752
|
+
*/
|
|
753
|
+
function invalidPlan(message, target = "check", cause) {
|
|
754
|
+
throw new SemantifoldDiagnostic({
|
|
755
|
+
cause: cause instanceof Error ? cause : undefined,
|
|
756
|
+
code: "INVALID_TARGET_CHECK_PLAN",
|
|
757
|
+
language: target,
|
|
758
|
+
message
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Checks for an ordinary object-prototype record.
|
|
763
|
+
* @param {unknown} value - Candidate value.
|
|
764
|
+
* @returns {value is Record<string, unknown>} Whether the value is a plain object.
|
|
765
|
+
*/
|
|
766
|
+
function isPlainObject(value) {
|
|
767
|
+
return typeof value == "object" && value != null && !Array.isArray(value) && Object.getPrototypeOf(value) == Object.prototype;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Checks for an own-property string-data record with an ordinary or null prototype.
|
|
771
|
+
* @param {unknown} value - Candidate value.
|
|
772
|
+
* @returns {value is Record<string, unknown>} Whether the value is a plain data record.
|
|
773
|
+
*/
|
|
774
|
+
function isPlainRecord(value) {
|
|
775
|
+
if (typeof value != "object" || value == null || Array.isArray(value))
|
|
776
|
+
return false;
|
|
777
|
+
const prototype = Object.getPrototypeOf(value);
|
|
778
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
779
|
+
return false;
|
|
780
|
+
return Reflect.ownKeys(value).every(key => {
|
|
781
|
+
if (typeof key != "string")
|
|
782
|
+
return false;
|
|
783
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
784
|
+
return descriptor != undefined && descriptor.enumerable && "value" in descriptor && typeof descriptor.value == "string";
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Checks one closed object-key set.
|
|
789
|
+
* @param {Record<string, unknown>} value - Candidate record.
|
|
790
|
+
* @param {string[]} keys - Exact allowed keys.
|
|
791
|
+
* @returns {boolean} Whether the key sets match.
|
|
792
|
+
*/
|
|
793
|
+
function hasExactKeys(value, keys) {
|
|
794
|
+
return Object.keys(value).sort().join("\0") == [...keys].sort().join("\0");
|
|
795
|
+
}
|
|
796
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFyZ2V0LWNoZWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RhcmdldC1jaGVjay5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQTtBQUNqRSxPQUFPLElBQUksTUFBTSxXQUFXLENBQUE7QUFDNUIsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLFlBQVksQ0FBQTtBQUN2QyxPQUFPLEVBQUMsMEJBQTBCLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQTtBQUN6RCxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQTtBQUNyRCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQTtBQUN2RCxPQUFPLEVBQUMscUJBQXFCLEVBQUUscUJBQXFCLEVBQUUsdUJBQXVCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQTtBQUNyRyxPQUFPLEVBQUMsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFDbkUsT0FBTyxFQUFDLHdCQUF3QixFQUFDLE1BQU0saUJBQWlCLENBQUE7QUFFeEQsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUE7QUFDL0IsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFBO0FBQ3RDLE1BQU0sZUFBZSxHQUFHLG9CQUFvQixDQUFBO0FBQzVDLE1BQU0sZ0JBQWdCLEdBQUcsdUVBQXVFLENBQUE7QUFDaEcsTUFBTSxXQUFXLEdBQUcsb0JBQW9CLENBQUE7QUFDeEMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUMvQixPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxRQUFR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LFNBQVMsSUFBSSxVQUFVLENBQUMsVUFBVSxJQUFJLE9BQU8sSUFBSSxVQUFVLElBQUksT0FBTyxVQUFVLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQTtJQUN6SCxDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsWUFBWSxDQUFDLEtBQUssRUFBRSxJQUFJO0lBQy9CLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUM1RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7bHN0YXQsIG1rZGlyLCByZWFkZGlyLCBybSwgcm1kaXJ9IGZyb20gXCJub2RlOmZzL3Byb21pc2VzXCJcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHtpc0RlbnNlQXJyYXl9IGZyb20gXCIuL2FycmF5LmpzXCJcbmltcG9ydCB7Y3JlYXRlR2VuZXJhdGVkQXJ0aWZhY3RTZXR9IGZyb20gXCIuL2FydGlmYWN0cy5qc1wiXG5pbXBvcnQge1NlbWFudGlmb2xkRGlhZ25vc3RpY30gZnJvbSBcIi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2xhbmd1YWdlUmVnaXN0cnl9IGZyb20gXCIuL2xhbmd1YWdlLXJlZ2lzdHJ5LmpzXCJcbmltcG9ydCB7Y2FuY2VsbGVkT3duZWRQcm9jZXNzLCBleGNlZWRlZE93bmVkRGVhZGxpbmUsIGV4ZWN1dGVGaWxlV2l0aERlYWRsaW5lfSBmcm9tIFwiLi9zdWJwcm9jZXNzLmpzXCJcbmltcG9ydCB7aXNTdXBwb3J0ZWRUaW1lb3V0TXMsIG1heGltdW1UaW1lb3V0TXN9IGZyb20gXCIuL3RpbWVvdXQuanNcIlxuaW1wb3J0IHtkZXRlcm1pbmlzdGljRW52aXJvbm1lbnR9IGZyb20gXCIuL3Rvb2xjaGFpbnMuanNcIlxuXG5jb25zdCBkZWZhdWx0VGltZW91dE1zID0gMjBfMDAwXG5jb25zdCBtYXhpbXVtT3V0cHV0Qnl0ZXMgPSAxMDI0ICogMTAyNFxuY29uc3QgaWRlbnRpdHlQYXR0ZXJuID0gL15bYS16XVthLXowLTktXSokL3VcbmNvbnN0IG1lZGlhVHlwZVBhdHRlcm4gPSAvXltBLVphLXowLTkhIyQmXl8uKy1dK1xcL1tBLVphLXowLTkhIyQmXl8uKy1dKyg/OjtbXFx1MDAyMC1cXHUwMDdlXSspPyQvdVxuY29uc3Qgcm9sZVBhdHRlcm4gPSAvXlthLXpdW2EtejAtOS1dKiQvdVxuY29uc3QgbGF1bmNoRXJyb3JDb2RlcyA9IG5ldyBTZXQoW1xuICBcIkUyQklHXCIsIFwiRUFDQ0VTXCIsIFwiRUFHQUlOXCIsIFwiRUxPT1BcIiwgXCJFTUZJTEVcIiwgXCJFTkFNRVRPT0xPTkdcIiwgXCJFTkZJTEVcIiwgXCJFTk9FTlRcIiwgXCJFTk9FWEVDXCIsIFwiRU5PTUVNXCIsXG4gIFwiRU5PVERJUlwiLCBcIkVOT1RTVVBcIiwgXCJFUEVSTVwiLCBcIkVUWFRCU1lcIlxuXSlcbi8qKiBAdHlwZSB7V2Vha01hcDxUYXJnZXRDaGVja1J1bm5lciwge2V4ZWN1dGU6IHR5cGVvZiBleGVjdXRlRmlsZVdpdGhEZWFkbGluZSwgbm93OiAoKSA9PiBudW1iZXJ9Pn0gKi9cbmNvbnN0IHRhcmdldENoZWNrUnVubmVyRGVwZW5kZW5jaWVzID0gbmV3IFdlYWtNYXAoKVxuXG4vKipcbiAqIENyZWF0ZXMgYW5kIHZhbGlkYXRlcyBvbmUgdGFyZ2V0LW93bmVkIGRldmVsb3BlciBjaGVjayBwbGFuLlxuICogQHBhcmFtIHtvYmplY3R9IGlucHV0IC0gRXhhY3Qgc3RhZ2VkIHRhcmdldCBjb250ZXh0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRlZEFydGlmYWN0U2V0fSBpbnB1dC5hcnRpZmFjdHMgLSBWYWxpZGF0ZWQgc3RhZ2VkIGFydGlmYWN0cy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5idWlsZFBhdGggLSBFeGFjdCBnZW5lcmF0aW9uLXNjb3BlZCB0YXJnZXQgYnVpbGQgc3VidHJlZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5wcm9qZWN0SWQgLSBFeGFjdCBwcm9qZWN0IGlkZW50aXR5LlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0LnNvdXJjZVBhdGggLSBFeGFjdCBnZW5lcmF0aW9uLXNjb3BlZCB0YXJnZXQgc291cmNlIHN1YnRyZWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5wdXQudGFyZ2V0SWQgLSBFeGFjdCBwcm9qZWN0IHRhcmdldCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7cmVhZG9ubHkgaW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5EaXNjb3ZlcmVkVG9vbGNoYWluW119IGlucHV0LnRvb2xzIC0gRGlzY292ZXJlZCBpbW11dGFibGUgdG9vbCByZWNvcmRzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tQbGFufSBWYWxpZGF0ZWQgaW1tdXRhYmxlIHBsYW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUYXJnZXRDaGVja1BsYW4oaW5wdXQpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGlucHV0KSB8fCAhaGFzRXhhY3RLZXlzKGlucHV0LCBbXCJhcnRpZmFjdHNcIiwgXCJidWlsZFBhdGhcIiwgXCJwcm9qZWN0SWRcIiwgXCJzb3VyY2VQYXRoXCIsIFwidGFyZ2V0SWRcIiwgXCJ0b29sc1wiXSkpIHtcbiAgICByZXR1cm4gaW52YWxpZFBsYW4oXCJUYXJnZXQgY2hlY2sgcGxhbm5pbmcgcmVxdWlyZXMgb25seSBzdGFnZWQgYXJ0aWZhY3RzLCBjYW5kaWRhdGUgcm9vdHMsIGlkZW50aXRpZXMsIGFuZCB0b29scy5cIilcbiAgfVxuICBsZXQgYXJ0aWZhY3RzXG5cbiAgdHJ5IHtcbiAgICBhcnRpZmFjdHMgPSBjcmVhdGVHZW5lcmF0ZWRBcnRpZmFjdFNldChpbnB1dC5hcnRpZmFjdHMpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIGludmFsaWRQbGFuKFwiVGFyZ2V0IGNoZWNrIHBsYW5uaW5nIHJlcXVpcmVzIGEgdmFsaWQgZ2VuZXJhdGVkIGFydGlmYWN0IHNldC5cIiwgXCJjaGVja1wiLCBlcnJvcilcbiAgfVxuICBjb25zdCB0YXJnZXQgPSBhcnRpZmFjdHMudGFyZ2V0XG4gIGNvbnN0IHJlY29yZCA9IGxhbmd1YWdlUmVnaXN0cnkucmVjb3JkKHRhcmdldClcbiAgY29uc3QgY2FwYWJpbGl0eSA9IHJlY29yZC5jaGVja1xuXG4gIGlmICghY2FwYWJpbGl0eS5zdXBwb3J0ZWQgfHwgdHlwZW9mIGNhcGFiaWxpdHkuZmFjdG9yeSAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtcbiAgICAgIGNvZGU6IFwiVU5TVVBQT1JURURfVEFSR0VUX0NIRUNLXCIsXG4gICAgICBsYW5ndWFnZTogdGFyZ2V0LFxuICAgICAgbWVzc2FnZTogXCJSZWdpc3RlcmVkIHRhcmdldCBkb2VzIG5vdCBwcm92aWRlIGEgZGV2ZWxvcGVyIGNoZWNrIHBsYW4uXCJcbiAgICB9KVxuICB9XG4gIGlmICh0eXBlb2YgaW5wdXQucHJvamVjdElkICE9IFwic3RyaW5nXCIgfHwgIWlkZW50aXR5UGF0dGVybi50ZXN0KGlucHV0LnByb2plY3RJZCkgfHxcbiAgICB0eXBlb2YgaW5wdXQudGFyZ2V0SWQgIT0gXCJzdHJpbmdcIiB8fCAhaWRlbnRpdHlQYXR0ZXJuLnRlc3QoaW5wdXQudGFyZ2V0SWQpIHx8XG4gICAgdHlwZW9mIGlucHV0LnNvdXJjZVBhdGggIT0gXCJzdHJpbmdcIiB8fCAhcGF0aC5pc0Fic29sdXRlKGlucHV0LnNvdXJjZVBhdGgpIHx8XG4gICAgdHlwZW9mIGlucHV0LmJ1aWxkUGF0aCAhPSBcInN0cmluZ1wiIHx8ICFwYXRoLmlzQWJzb2x1dGUoaW5wdXQuYnVpbGRQYXRoKSB8fFxuICAgIHBhdGhzT3ZlcmxhcChpbnB1dC5zb3VyY2VQYXRoLCBpbnB1dC5idWlsZFBhdGgpIHx8ICFpc0RlbnNlQXJyYXkoaW5wdXQudG9vbHMpKSB7XG4gICAgcmV0dXJuIGludmFsaWRQbGFuKFwiVGFyZ2V0IGNoZWNrIHBsYW5uaW5nIHJlY2VpdmVkIGludmFsaWQgaWRlbnRpdGllcywgY2FuZGlkYXRlIHJvb3RzLCBvciB0b29scy5cIiwgdGFyZ2V0KVxuICB9XG4gIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5EaXNjb3ZlcmVkVG9vbGNoYWluW119ICovXG4gIGNvbnN0IHRvb2xzID0gW11cblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgaW5wdXQudG9vbHMubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgdG9vbCA9IGlucHV0LnRvb2xzW2luZGV4XVxuXG4gICAgaWYgKCFpc0Rpc2NvdmVyZWRUb29sKHRvb2wpIHx8ICFPYmplY3QuaXNGcm96ZW4odG9vbCkgfHwgIU9iamVjdC5pc0Zyb3plbih0b29sLnZlcnNpb25Bcmd1bWVudHMpKSB7XG4gICAgICByZXR1cm4gaW52YWxpZFBsYW4oXCJUYXJnZXQgY2hlY2sgcGxhbm5pbmcgcmVxdWlyZXMgaW1tdXRhYmxlIGRpc2NvdmVyZWQgdG9vbCByZWNvcmRzLlwiLCB0YXJnZXQpXG4gICAgfVxuICAgIHRvb2xzLnB1c2godG9vbClcbiAgfVxuICBpZiAodG9vbHMubWFwKCh7aWR9KSA9PiBpZCkuam9pbihcIlxcMFwiKSAhPSBjYXBhYmlsaXR5LnRvb2xjaGFpbnMuam9pbihcIlxcMFwiKSkge1xuICAgIHJldHVybiBpbnZhbGlkUGxhbihcIlRhcmdldCBjaGVjayBwbGFubmluZyB0b29scyBtdXN0IGV4YWN0bHkgbWF0Y2ggdGhlIHRhcmdldC1kZWNsYXJlZCBkZXZlbG9wZXItY2hlY2sgdG9vbGNoYWlucy5cIiwgdGFyZ2V0KVxuICB9XG4gIGNvbnN0IGNvbnRleHQgPSBPYmplY3QuZnJlZXplKHtcbiAgICBhcnRpZmFjdHMsXG4gICAgYnVpbGRQYXRoOiBpbnB1dC5idWlsZFBhdGgsXG4gICAgcHJvamVjdElkOiBpbnB1dC5wcm9qZWN0SWQsXG4gICAgc291cmNlUGF0aDogaW5wdXQuc291cmNlUGF0aCxcbiAgICB0YXJnZXRJZDogaW5wdXQudGFyZ2V0SWQsXG4gICAgdG9vbHM6IE9iamVjdC5mcmVlemUodG9vbHMpXG4gIH0pXG4gIGxldCBwbGFuXG5cbiAgdHJ5IHtcbiAgICBwbGFuID0gY2FwYWJpbGl0eS5mYWN0b3J5KGNvbnRleHQpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgU2VtYW50aWZvbGREaWFnbm9zdGljKSB0aHJvdyBlcnJvclxuICAgIHJldHVybiBpbnZhbGlkUGxhbihcIlRhcmdldCBjaGVjayBwbGFuIGZhY3RvcnkgZmFpbGVkLlwiLCB0YXJnZXQsIGVycm9yKVxuICB9XG4gIGNvbnN0IHZhbGlkYXRlZCA9IHZhbGlkYXRlVGFyZ2V0Q2hlY2tQbGFuKHBsYW4pXG4gIGNvbnN0IGV4cGVjdGVkQXJ0aWZhY3RzID0gbmV3IFNldChjb250ZXh0LmFydGlmYWN0cy5hcnRpZmFjdHMubWFwKGFydGlmYWN0ID0+IHBhdGguam9pbihjb250ZXh0LnNvdXJjZVBhdGgsIGFydGlmYWN0LnBhdGgpKSlcblxuICBpZiAodmFsaWRhdGVkLnByb2plY3RJZCAhPSBjb250ZXh0LnByb2plY3RJZCB8fCB2YWxpZGF0ZWQudGFyZ2V0SWQgIT0gY29udGV4dC50YXJnZXRJZCB8fFxuICAgIHZhbGlkYXRlZC50YXJnZXQgIT0gdGFyZ2V0IHx8IHZhbGlkYXRlZC5zb3VyY2VQYXRoICE9IGNvbnRleHQuc291cmNlUGF0aCB8fCB2YWxpZGF0ZWQuYnVpbGRQYXRoICE9IGNvbnRleHQuYnVpbGRQYXRoIHx8XG4gICAgdmFsaWRhdGVkLmFydGlmYWN0UGF0aHMubGVuZ3RoICE9IGV4cGVjdGVkQXJ0aWZhY3RzLnNpemUgfHwgdmFsaWRhdGVkLmFydGlmYWN0UGF0aHMuc29tZShhcnRpZmFjdCA9PiAhZXhwZWN0ZWRBcnRpZmFjdHMuaGFzKGFydGlmYWN0KSkpIHtcbiAgICByZXR1cm4gaW52YWxpZFBsYW4oXCJUYXJnZXQgY2hlY2sgcGxhbiBjaGFuZ2VkIGl0cyB2YWxpZGF0ZWQgY2FuZGlkYXRlIGNvbnRleHQuXCIsIHRhcmdldClcbiAgfVxuXG4gIHJldHVybiB2YWxpZGF0ZWRcbn1cblxuLyoqXG4gKiBPd25zIG9yZGVyZWQgY2hlY2sgc3VicHJvY2Vzc2VzIGFuZCBzZXR0bGVzIG9ubHkgYWZ0ZXIgZWFjaCBjaGlsZCBjbG9zZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBUYXJnZXRDaGVja1J1bm5lciB7XG4gIC8qKlxuICAgKiBSdW5zIG9uZSBhbHJlYWR5LXN0YWdlZCBpbW11dGFibGUgcGxhbiB3aXRob3V0IGV4ZWN1dGluZyBnZW5lcmF0ZWQgYXBwbGljYXRpb24gY29kZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlRhcmdldENoZWNrUGxhbn0gcGxhbiAtIFRhcmdldC1vd25lZCBwbGFuLlxuICAgKiBAcGFyYW0ge3tvblN0YWdlPzogKHJlc3VsdDogaW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UYXJnZXRDaGVja1N0YWdlUmVzdWx0KSA9PiB2b2lkLCBzaWduYWw/OiBBYm9ydFNpZ25hbCwgdGltZW91dE1zPzogbnVtYmVyfX0gW29wdGlvbnNdIC0gTGlmZWN5Y2xlIGNvbnRyb2xzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlRhcmdldENoZWNrUmVzdWx0Pn0gU3VjY2Vzc2Z1bCBjaGVjayBldmlkZW5jZSBhbmQgb3V0cHV0IG1ldGFkYXRhLlxuICAgKi9cbiAgYXN5bmMgcnVuKHBsYW4sIG9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHZhbGlkYXRlZCA9IHZhbGlkYXRlVGFyZ2V0Q2hlY2tQbGFuKHBsYW4pXG4gICAgY29uc3QgZGVwZW5kZW5jaWVzID0gdGFyZ2V0Q2hlY2tSdW5uZXJEZXBlbmRlbmNpZXMuZ2V0KHRoaXMpID8/IHtcbiAgICAgIGV4ZWN1dGU6IGV4ZWN1dGVGaWxlV2l0aERlYWRsaW5lLFxuICAgICAgbm93OiAoKSA9PiBwZXJmb3JtYW5jZS5ub3coKVxuICAgIH1cblxuICAgIGlmICghaXNQbGFpbk9iamVjdChvcHRpb25zKSB8fCBvcHRpb25zLm9uU3RhZ2UgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb3B0aW9ucy5vblN0YWdlICE9IFwiZnVuY3Rpb25cIiB8fFxuICAgICAgb3B0aW9ucy5zaWduYWwgIT09IHVuZGVmaW5lZCAmJiAhKG9wdGlvbnMuc2lnbmFsIGluc3RhbmNlb2YgQWJvcnRTaWduYWwpKSB7XG4gICAgICByZXR1cm4gaW52YWxpZFBsYW4oXCJUYXJnZXQgY2hlY2sgcnVubmVyIG9wdGlvbnMgYXJlIGludmFsaWQuXCIsIHZhbGlkYXRlZC50YXJnZXQpXG4gICAgfVxuICAgIGNvbnN0IHRpbWVvdXRNcyA9IG9wdGlvbnMudGltZW91dE1zID09PSB1bmRlZmluZWQgPyBkZWZhdWx0VGltZW91dE1zIDogb3B0aW9ucy50aW1lb3V0TXNcblxuICAgIGlmICghaXNTdXBwb3J0ZWRUaW1lb3V0TXModGltZW91dE1zKSkge1xuICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgdGltZW91dCBtdXN0IGJlIGZyb20gMSB0aHJvdWdoICR7bWF4aW11bVRpbWVvdXRNc31tcy5gLCB2YWxpZGF0ZWQudGFyZ2V0KVxuICAgIH1cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tTdGFnZVJlc3VsdFtdfSAqL1xuICAgIGNvbnN0IHJlc3VsdHMgPSBbXVxuICAgIC8qKiBAdHlwZSB7dW5rbm93bn0gKi9cbiAgICBsZXQgc3RhZ2VGYWlsdXJlXG4gICAgbGV0IHN0YWdlRmFpbGVkID0gZmFsc2VcblxuICAgIHRyeSB7XG4gICAgICBmb3IgKGNvbnN0IHN0YWdlIG9mIHZhbGlkYXRlZC5zdGFnZXMpIHtcbiAgICAgICAgY29uc3Qgc3RhcnRlZEF0ID0gZGVwZW5kZW5jaWVzLm5vdygpXG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UYXJnZXRDaGVja1N0YWdlUmVzdWx0fSAqL1xuICAgICAgICBsZXQgc3RhZ2VSZXN1bHRcblxuICAgICAgICBpZiAob3B0aW9ucy5zaWduYWw/LmFib3J0ZWQpIHRocm93IGNhbmNlbGxlZERpYWdub3N0aWMoc3RhZ2UsIHZhbGlkYXRlZCwgMClcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBwcmVwYXJlU3RhZ2Uoc3RhZ2UsIHZhbGlkYXRlZClcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBwcmVwYXJhdGlvbkRpYWdub3N0aWMoZXJyb3IsIHN0YWdlLCB2YWxpZGF0ZWQsIGVsYXBzZWQoZGVwZW5kZW5jaWVzLm5vdygpLCBzdGFydGVkQXQpKVxuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgZGVwZW5kZW5jaWVzLmV4ZWN1dGUoe1xuICAgICAgICAgICAgYXJndW1lbnRzOiBzdGFnZS5hcmd2LFxuICAgICAgICAgICAgY3dkOiBzdGFnZS5jd2QsXG4gICAgICAgICAgICBlbnZpcm9ubWVudDogc3RhZ2UuZW52aXJvbm1lbnQsXG4gICAgICAgICAgICBleGVjdXRhYmxlOiBzdGFnZS5leGVjdXRhYmxlLFxuICAgICAgICAgICAgbWF4QnVmZmVyOiBtYXhpbXVtT3V0cHV0Qnl0ZXMsXG4gICAgICAgICAgICBzaWduYWw6IG9wdGlvbnMuc2lnbmFsLFxuICAgICAgICAgICAgdGltZW91dE1zXG4gICAgICAgICAgfSlcbiAgICAgICAgICBzdGFnZVJlc3VsdCA9IE9iamVjdC5mcmVlemUoe1xuICAgICAgICAgICAgYXJndjogc3RhZ2UuYXJndixcbiAgICAgICAgICAgIGR1cmF0aW9uTXM6IGVsYXBzZWQoZGVwZW5kZW5jaWVzLm5vdygpLCBzdGFydGVkQXQpLFxuICAgICAgICAgICAgZXhpdENvZGU6IDAsXG4gICAgICAgICAgICBzaWduYWw6IG51bGwsXG4gICAgICAgICAgICBzdGFnZTogc3RhZ2Uuc3RhZ2UsXG4gICAgICAgICAgICBzdGRlcnI6IG91dHB1dC5zdGRlcnIsXG4gICAgICAgICAgICBzdGRvdXQ6IG91dHB1dC5zdGRvdXQsXG4gICAgICAgICAgICB0b29sOiBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgICAgICAgY29tbWFuZDogc3RhZ2UudG9vbC5jb21tYW5kLFxuICAgICAgICAgICAgICBleGVjdXRhYmxlOiBzdGFnZS50b29sLmV4ZWN1dGFibGUsXG4gICAgICAgICAgICAgIGlkOiBzdGFnZS50b29sLmlkLFxuICAgICAgICAgICAgICBzb3VyY2U6IHN0YWdlLnRvb2wuc291cmNlLFxuICAgICAgICAgICAgICB2ZXJzaW9uOiBzdGFnZS50b29sLnZlcnNpb25cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfSlcblxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHRocm93IHByb2Nlc3NEaWFnbm9zdGljKGVycm9yLCBzdGFnZSwgdmFsaWRhdGVkLCB0aW1lb3V0TXMsIGVsYXBzZWQoZGVwZW5kZW5jaWVzLm5vdygpLCBzdGFydGVkQXQpKVxuICAgICAgICB9XG4gICAgICAgIHJlc3VsdHMucHVzaChzdGFnZVJlc3VsdClcbiAgICAgICAgb3B0aW9ucy5vblN0YWdlPy4oc3RhZ2VSZXN1bHQpXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHN0YWdlRmFpbGVkID0gdHJ1ZVxuICAgICAgc3RhZ2VGYWlsdXJlID0gZXJyb3JcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGNsZWFudXBTdGFnZUVudmlyb25tZW50KHZhbGlkYXRlZClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3QgY2xlYW51cCA9IGNsZWFudXBEaWFnbm9zdGljKGVycm9yLCB2YWxpZGF0ZWQpXG5cbiAgICAgIGlmIChzdGFnZUZhaWxlZCAmJiBzdGFnZUZhaWx1cmUgaW5zdGFuY2VvZiBFcnJvcikgdGhyb3cgcHJlc2VydmVQcmltYXJ5RmFpbHVyZShzdGFnZUZhaWx1cmUsIGNsZWFudXApXG4gICAgICBpZiAoc3RhZ2VGYWlsZWQpIHRocm93IG5ldyBBZ2dyZWdhdGVFcnJvcihbc3RhZ2VGYWlsdXJlLCBjbGVhbnVwXSxcbiAgICAgICAgXCJUYXJnZXQgY2hlY2sgZmFpbGVkIGFuZCBpdHMgb3duZWQgdHJhbnNpZW50IGVudmlyb25tZW50IGNvdWxkIG5vdCBiZSBjbGVhbmVkLlwiLCB7Y2F1c2U6IGVycm9yfSlcbiAgICAgIHRocm93IGNsZWFudXBcbiAgICB9XG4gICAgaWYgKHN0YWdlRmFpbGVkKSB0aHJvdyBzdGFnZUZhaWx1cmVcbiAgICBjb25zdCBvdXRwdXQgPSB2YWxpZGF0ZWQuc3RhZ2VzLmZpbmRMYXN0KHN0YWdlID0+IHN0YWdlLm91dHB1dCAhPT0gbnVsbCk/Lm91dHB1dFxuICAgIGNvbnN0IG91dHB1dHMgPSBvdXRwdXQgPT0gbnVsbCA/IFtdIDogYXdhaXQgY29sbGVjdEJ1aWxkT3V0cHV0cyh2YWxpZGF0ZWQuYnVpbGRQYXRoLCBvdXRwdXQpXG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgICBvdXRwdXRzOiBPYmplY3QuZnJlZXplKG91dHB1dHMpLFxuICAgICAgcHJvamVjdElkOiB2YWxpZGF0ZWQucHJvamVjdElkLFxuICAgICAgc3RhZ2VzOiBPYmplY3QuZnJlZXplKHJlc3VsdHMpLFxuICAgICAgdGFyZ2V0OiB2YWxpZGF0ZWQudGFyZ2V0LFxuICAgICAgdGFyZ2V0SWQ6IHZhbGlkYXRlZC50YXJnZXRJZFxuICAgIH0pXG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgcnVubmVyIHdpdGggZm9jdXNlZCBpbnN0YW5jZS1vd25lZCBkZXBlbmRlbmNpZXMuXG4gKiBAcGFyYW0ge3tleGVjdXRlOiB0eXBlb2YgZXhlY3V0ZUZpbGVXaXRoRGVhZGxpbmUsIG5vdzogKCkgPT4gbnVtYmVyfX0gZGVwZW5kZW5jaWVzIC0gVGVzdGFibGUgbGlmZWN5Y2xlIGNvbGxhYm9yYXRvcnMuXG4gKiBAcmV0dXJucyB7VGFyZ2V0Q2hlY2tSdW5uZXJ9IFJ1bm5lci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVRhcmdldENoZWNrUnVubmVyKGRlcGVuZGVuY2llcykge1xuICBpZiAoIWlzUGxhaW5PYmplY3QoZGVwZW5kZW5jaWVzKSB8fCB0eXBlb2YgZGVwZW5kZW5jaWVzLmV4ZWN1dGUgIT0gXCJmdW5jdGlvblwiIHx8IHR5cGVvZiBkZXBlbmRlbmNpZXMubm93ICE9IFwiZnVuY3Rpb25cIikge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIHRhcmdldCBjaGVjayBydW5uZXIgZGVwZW5kZW5jaWVzLlwiKVxuICB9XG4gIGNvbnN0IHJ1bm5lciA9IG5ldyBUYXJnZXRDaGVja1J1bm5lcigpXG5cbiAgdGFyZ2V0Q2hlY2tSdW5uZXJEZXBlbmRlbmNpZXMuc2V0KHJ1bm5lciwgZGVwZW5kZW5jaWVzKVxuXG4gIHJldHVybiBydW5uZXJcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYSBjb21wbGV0ZSBpbW11dGFibGUgcGxhbiBiZWZvcmUgYW55IHByb2Nlc3Mgc3RhcnRzLlxuICogQHBhcmFtIHt1bmtub3dufSBjYW5kaWRhdGUgLSBDYW5kaWRhdGUgcGxhbi5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlRhcmdldENoZWNrUGxhbn0gRXhhY3QgdmFsaWRhdGVkIHBsYW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVRhcmdldENoZWNrUGxhbihjYW5kaWRhdGUpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGNhbmRpZGF0ZSkgfHwgIU9iamVjdC5pc0Zyb3plbihjYW5kaWRhdGUpIHx8ICFoYXNFeGFjdEtleXMoY2FuZGlkYXRlLCBbXG4gICAgXCJhcnRpZmFjdFBhdGhzXCIsIFwiYnVpbGRQYXRoXCIsIFwibW9kZVwiLCBcInByb2plY3RJZFwiLCBcInNjaGVtYVwiLCBcInNvdXJjZVBhdGhcIiwgXCJzdGFnZXNcIiwgXCJ0YXJnZXRcIiwgXCJ0YXJnZXRJZFwiLCBcInZlcnNpb25cIlxuICBdKSkgcmV0dXJuIGludmFsaWRQbGFuKFwiVGFyZ2V0IGNoZWNrIHBsYW4gbXVzdCBiZSBvbmUgaW1tdXRhYmxlIGNsb3NlZCBzY2hlbWEgcmVjb3JkLlwiKVxuICBjb25zdCB0YXJnZXQgPSB0eXBlb2YgY2FuZGlkYXRlLnRhcmdldCA9PSBcInN0cmluZ1wiID8gY2FuZGlkYXRlLnRhcmdldCA6IFwiY2hlY2tcIlxuICBjb25zdCByZWNvcmQgPSBsYW5ndWFnZVJlZ2lzdHJ5LnJlY29yZCh0YXJnZXQpXG4gIGNvbnN0IGNhcGFiaWxpdHkgPSByZWNvcmQuY2hlY2tcblxuICBpZiAoIWNhcGFiaWxpdHkuc3VwcG9ydGVkIHx8IGNhbmRpZGF0ZS5zY2hlbWEgIT0gXCJTZW1hbnRpZm9sZFRhcmdldENoZWNrUGxhblwiIHx8IGNhbmRpZGF0ZS52ZXJzaW9uICE9IDEgfHxcbiAgICBjYW5kaWRhdGUubW9kZSAhPSBcImRldmVsb3Blci1jaGVja1wiIHx8IHR5cGVvZiBjYW5kaWRhdGUucHJvamVjdElkICE9IFwic3RyaW5nXCIgfHwgIWlkZW50aXR5UGF0dGVybi50ZXN0KGNhbmRpZGF0ZS5wcm9qZWN0SWQpIHx8XG4gICAgdHlwZW9mIGNhbmRpZGF0ZS50YXJnZXRJZCAhPSBcInN0cmluZ1wiIHx8ICFpZGVudGl0eVBhdHRlcm4udGVzdChjYW5kaWRhdGUudGFyZ2V0SWQpIHx8XG4gICAgdHlwZW9mIGNhbmRpZGF0ZS5zb3VyY2VQYXRoICE9IFwic3RyaW5nXCIgfHwgIXBhdGguaXNBYnNvbHV0ZShjYW5kaWRhdGUuc291cmNlUGF0aCkgfHxcbiAgICB0eXBlb2YgY2FuZGlkYXRlLmJ1aWxkUGF0aCAhPSBcInN0cmluZ1wiIHx8ICFwYXRoLmlzQWJzb2x1dGUoY2FuZGlkYXRlLmJ1aWxkUGF0aCkgfHxcbiAgICBwYXRoc092ZXJsYXAoY2FuZGlkYXRlLnNvdXJjZVBhdGgsIGNhbmRpZGF0ZS5idWlsZFBhdGgpKSB7XG4gICAgcmV0dXJuIGludmFsaWRQbGFuKFwiVGFyZ2V0IGNoZWNrIHBsYW4gaGFzIGludmFsaWQgc2NoZW1hLCBtb2RlLCBpZGVudGl0eSwgdGFyZ2V0LCBvciBjYW5kaWRhdGUgcm9vdHMuXCIsIHRhcmdldClcbiAgfVxuICBpZiAoIWlzRGVuc2VBcnJheShjYW5kaWRhdGUuYXJ0aWZhY3RQYXRocykgfHwgIU9iamVjdC5pc0Zyb3plbihjYW5kaWRhdGUuYXJ0aWZhY3RQYXRocykgfHwgY2FuZGlkYXRlLmFydGlmYWN0UGF0aHMubGVuZ3RoID09IDAgfHxcbiAgICAhaXNEZW5zZUFycmF5KGNhbmRpZGF0ZS5zdGFnZXMpIHx8ICFPYmplY3QuaXNGcm96ZW4oY2FuZGlkYXRlLnN0YWdlcykgfHwgY2FuZGlkYXRlLnN0YWdlcy5sZW5ndGggPT0gMCkge1xuICAgIHJldHVybiBpbnZhbGlkUGxhbihcIlRhcmdldCBjaGVjayBwbGFuIHJlcXVpcmVzIGRlbnNlIGltbXV0YWJsZSBhcnRpZmFjdCBhbmQgc3RhZ2UgdmVjdG9ycy5cIiwgdGFyZ2V0KVxuICB9XG4gIGNvbnN0IGFydGlmYWN0UGF0aHMgPSBuZXcgU2V0KClcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgY2FuZGlkYXRlLmFydGlmYWN0UGF0aHMubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgYXJ0aWZhY3RQYXRoID0gY2FuZGlkYXRlLmFydGlmYWN0UGF0aHNbaW5kZXhdXG5cbiAgICBpZiAodHlwZW9mIGFydGlmYWN0UGF0aCAhPSBcInN0cmluZ1wiIHx8ICFvd25lZEJ5KGNhbmRpZGF0ZS5zb3VyY2VQYXRoLCBhcnRpZmFjdFBhdGgpIHx8IGFydGlmYWN0UGF0aHMuaGFzKGFydGlmYWN0UGF0aCkpIHtcbiAgICAgIHJldHVybiBpbnZhbGlkUGxhbihcIkV2ZXJ5IHBsYW5uZWQgYXJ0aWZhY3QgbXVzdCBiZSBhIGRpc3RpbmN0IGFic29sdXRlIHBhdGggaW5zaWRlIHRoZSBjYW5kaWRhdGUgc291cmNlIHN1YnRyZWUuXCIsIHRhcmdldClcbiAgICB9XG4gICAgYXJ0aWZhY3RQYXRocy5hZGQoYXJ0aWZhY3RQYXRoKVxuICB9XG4gIGNvbnN0IHBsYW5uZWRTdGFnZUtpbmRzID0gY2FuZGlkYXRlLnN0YWdlcy5tYXAoc3RhZ2UgPT4gaXNQbGFpbk9iamVjdChzdGFnZSkgJiYgdHlwZW9mIHN0YWdlLnN0YWdlID09IFwic3RyaW5nXCIgPyBzdGFnZS5zdGFnZSA6IFwiXCIpXG4gICAgLmZpbHRlcigoc3RhZ2UsIGluZGV4LCBzdGFnZXMpID0+IGluZGV4ID09IDAgfHwgc3RhZ2UgIT0gc3RhZ2VzW2luZGV4IC0gMV0pXG5cbiAgaWYgKHBsYW5uZWRTdGFnZUtpbmRzLmpvaW4oXCJcXDBcIikgIT0gY2FwYWJpbGl0eS5zdGFnZXMuam9pbihcIlxcMFwiKSkge1xuICAgIHJldHVybiBpbnZhbGlkUGxhbihcIlRhcmdldCBjaGVjayBzdGFnZXMgbXVzdCBleGFjdGx5IG1hdGNoIHRoZSB0YXJnZXQtZGVjbGFyZWQgZGV2ZWxvcGVyLWNoZWNrIHN0YWdlcy5cIiwgdGFyZ2V0KVxuICB9XG4gIGNvbnN0IHVzZWRUb29scyA9IG5ldyBTZXQoKVxuICBjb25zdCByZWZlcmVuY2VkQXJ0aWZhY3RQYXRocyA9IG5ldyBTZXQoKVxuXG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBjYW5kaWRhdGUuc3RhZ2VzLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIGNvbnN0IHN0YWdlID0gY2FuZGlkYXRlLnN0YWdlc1tpbmRleF1cbiAgICBpZiAoIWlzUGxhaW5PYmplY3Qoc3RhZ2UpIHx8ICFPYmplY3QuaXNGcm96ZW4oc3RhZ2UpIHx8ICFoYXNFeGFjdEtleXMoc3RhZ2UsIFtcbiAgICAgIFwiYXJndlwiLCBcImN3ZFwiLCBcImVudmlyb25tZW50XCIsIFwiZW52aXJvbm1lbnRQYXRoc1wiLCBcImV4ZWN1dGFibGVcIiwgXCJpbnB1dEhhc2hcIiwgXCJpbnB1dHNcIiwgXCJvdXRwdXRcIiwgXCJwYXRoQXJndW1lbnRzXCIsXG4gICAgICBcInN0YWdlXCIsIFwidG9vbFwiLCBcInRyYW5zaWVudFBhdGhzXCJcbiAgICBdKSB8fCB0eXBlb2Ygc3RhZ2Uuc3RhZ2UgIT0gXCJzdHJpbmdcIiB8fCBzdGFnZS5zdGFnZSA9PSBcImV4ZWN1dGVcIiB8fFxuICAgICAgIXJlY29yZC5hY2NlcHRhbmNlLnN0YWdlcy5pbmNsdWRlcygvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuQWNjZXB0YW5jZVN0YWdlfSAqLyAoc3RhZ2Uuc3RhZ2UpKSkge1xuICAgICAgcmV0dXJuIGludmFsaWRQbGFuKFwiVGFyZ2V0IGNoZWNrIHN0YWdlcyBtdXN0IGJlIGltbXV0YWJsZSwgb3JkZXJlZCwgZGVjbGFyZWQsIGFuZCBub24tZXhlY3V0aW5nLlwiLCB0YXJnZXQpXG4gICAgfVxuICAgIGNvbnN0IHJlcXVlc3QgPSAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tTdGFnZVJlcXVlc3R9ICovIChzdGFnZSlcblxuICAgIGlmICghaXNEaXNjb3ZlcmVkVG9vbChyZXF1ZXN0LnRvb2wpIHx8ICFPYmplY3QuaXNGcm96ZW4ocmVxdWVzdC50b29sKSB8fCAhT2JqZWN0LmlzRnJvemVuKHJlcXVlc3QudG9vbC52ZXJzaW9uQXJndW1lbnRzKSB8fFxuICAgICAgcmVxdWVzdC5leGVjdXRhYmxlICE9IHJlcXVlc3QudG9vbC5leGVjdXRhYmxlIHx8ICFjYXBhYmlsaXR5LnRvb2xjaGFpbnMuaW5jbHVkZXMocmVxdWVzdC50b29sLmlkKSkge1xuICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgc3RhZ2UgJyR7cmVxdWVzdC5zdGFnZX0nIHVzZXMgYW4gaW52YWxpZCBvciB1bmRlY2xhcmVkIHRvb2wuYCwgdGFyZ2V0KVxuICAgIH1cbiAgICB1c2VkVG9vbHMuYWRkKHJlcXVlc3QudG9vbC5pZClcbiAgICBpZiAoIWlzRGVuc2VBcnJheShyZXF1ZXN0LmFyZ3YpIHx8ICFPYmplY3QuaXNGcm96ZW4ocmVxdWVzdC5hcmd2KSB8fFxuICAgICAgIXJlcXVlc3QuYXJndi5ldmVyeShhcmd1bWVudCA9PiB0eXBlb2YgYXJndW1lbnQgPT0gXCJzdHJpbmdcIiAmJiAhYXJndW1lbnQuaW5jbHVkZXMoXCJcXDBcIikpIHx8XG4gICAgICAhaXNEZW5zZUFycmF5KHJlcXVlc3QucGF0aEFyZ3VtZW50cykgfHwgIU9iamVjdC5pc0Zyb3plbihyZXF1ZXN0LnBhdGhBcmd1bWVudHMpKSB7XG4gICAgICByZXR1cm4gaW52YWxpZFBsYW4oYFRhcmdldCBjaGVjayBzdGFnZSAnJHtyZXF1ZXN0LnN0YWdlfScgcmVxdWlyZXMgYSBkZW5zZSBpbW11dGFibGUgc2hlbGwtZnJlZSBhcmd2LmAsIHRhcmdldClcbiAgICB9XG4gICAgaWYgKCF2YWxpZEVudmlyb25tZW50KHJlcXVlc3QuZW52aXJvbm1lbnQpKSB7XG4gICAgICByZXR1cm4gaW52YWxpZFBsYW4oYFRhcmdldCBjaGVjayBzdGFnZSAnJHtyZXF1ZXN0LnN0YWdlfScgcmVxdWlyZXMgYW4gaW1tdXRhYmxlIGRldGVybWluaXN0aWMgZW52aXJvbm1lbnQuYCwgdGFyZ2V0KVxuICAgIH1cbiAgICBpZiAoIXZhbGlkRW52aXJvbm1lbnRQYXRocyhyZXF1ZXN0LmVudmlyb25tZW50UGF0aHMsIHJlcXVlc3QuZW52aXJvbm1lbnQsIGNhbmRpZGF0ZS5zb3VyY2VQYXRoLCBjYW5kaWRhdGUuYnVpbGRQYXRoLFxuICAgICAgY2FwYWJpbGl0eS50b29sY2hhaW5zLCB1c2VkVG9vbHMpKSB7XG4gICAgICByZXR1cm4gaW52YWxpZFBsYW4oYFRhcmdldCBjaGVjayBzdGFnZSAnJHtyZXF1ZXN0LnN0YWdlfScgaGFzIGludmFsaWQgZW52aXJvbm1lbnQtcGF0aCBvd25lcnNoaXAuYCwgdGFyZ2V0KVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHJlcXVlc3QuY3dkICE9IFwic3RyaW5nXCIgfHwgIW93bmVkQnlFaXRoZXIoY2FuZGlkYXRlLnNvdXJjZVBhdGgsIGNhbmRpZGF0ZS5idWlsZFBhdGgsIHJlcXVlc3QuY3dkKSkge1xuICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgc3RhZ2UgJyR7cmVxdWVzdC5zdGFnZX0nIHdvcmtpbmcgZGlyZWN0b3J5IGVzY2FwZXMgdGhlIGNhbmRpZGF0ZSB0YXJnZXQgc3VidHJlZXMuYCwgdGFyZ2V0KVxuICAgIH1cbiAgICBpZiAocmVxdWVzdC5vdXRwdXQgIT09IG51bGwgJiYgIXZhbGlkT3V0cHV0KHJlcXVlc3Qub3V0cHV0LCBjYW5kaWRhdGUuYnVpbGRQYXRoKSkge1xuICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgc3RhZ2UgJyR7cmVxdWVzdC5zdGFnZX0nIGhhcyBpbnZhbGlkIGNvbXBpbGVyLW91dHB1dCBvd25lcnNoaXAuYCwgdGFyZ2V0KVxuICAgIH1cbiAgICBpZiAoIXZhbGlkVHJhbnNpZW50UGF0aHMocmVxdWVzdC50cmFuc2llbnRQYXRocywgY2FuZGlkYXRlLnNvdXJjZVBhdGgsIGNhbmRpZGF0ZS5idWlsZFBhdGgsIGFydGlmYWN0UGF0aHMpKSB7XG4gICAgICByZXR1cm4gaW52YWxpZFBsYW4oYFRhcmdldCBjaGVjayBzdGFnZSAnJHtyZXF1ZXN0LnN0YWdlfScgaGFzIGludmFsaWQgdHJhbnNpZW50LXBhdGggb3duZXJzaGlwLmAsIHRhcmdldClcbiAgICB9XG4gICAgaWYgKHJlcXVlc3Quc3RhZ2UgPT0gXCJyZXN0b3JlXCIgPyB0eXBlb2YgcmVxdWVzdC5pbnB1dEhhc2ggIT0gXCJzdHJpbmdcIiB8fCAhL15bYS1mMC05XXs2NH0kL3UudGVzdChyZXF1ZXN0LmlucHV0SGFzaCkgOiByZXF1ZXN0LmlucHV0SGFzaCAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgc3RhZ2UgJyR7cmVxdWVzdC5zdGFnZX0nIGhhcyBpbnZhbGlkIHJlc3RvcmUtaW5wdXQgaWRlbnRpdHkuYCwgdGFyZ2V0KVxuICAgIH1cbiAgICBpZiAoIWlzRGVuc2VBcnJheShyZXF1ZXN0LmlucHV0cykgfHwgIU9iamVjdC5pc0Zyb3plbihyZXF1ZXN0LmlucHV0cykgfHwgcmVxdWVzdC5pbnB1dHMubGVuZ3RoID09IDApIHtcbiAgICAgIHJldHVybiBpbnZhbGlkUGxhbihgVGFyZ2V0IGNoZWNrIHN0YWdlICcke3JlcXVlc3Quc3RhZ2V9JyByZXF1aXJlcyBpbW11dGFibGUgZGVjbGFyZWQgaW5wdXRzLmAsIHRhcmdldClcbiAgICB9XG4gICAgY29uc3Qgc3RhZ2VJbnB1dHMgPSBuZXcgU2V0KClcblxuICAgIGZvciAobGV0IGlucHV0SW5kZXggPSAwOyBpbnB1dEluZGV4IDwgcmVxdWVzdC5pbnB1dHMubGVuZ3RoOyBpbnB1dEluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGlucHV0UGF0aCA9IHJlcXVlc3QuaW5wdXRzW2lucHV0SW5kZXhdXG5cbiAgICAgIGlmICh0eXBlb2YgaW5wdXRQYXRoICE9IFwic3RyaW5nXCIgfHwgc3RhZ2VJbnB1dHMuaGFzKGlucHV0UGF0aCkgfHwgIW93bmVkQnlFaXRoZXIoY2FuZGlkYXRlLnNvdXJjZVBhdGgsIGNhbmRpZGF0ZS5idWlsZFBhdGgsIGlucHV0UGF0aCkpIHtcbiAgICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgc3RhZ2UgJyR7cmVxdWVzdC5zdGFnZX0nIGhhcyBpbnZhbGlkIG9yIGR1cGxpY2F0ZSBkZWNsYXJlZCBpbnB1dHMuYCwgdGFyZ2V0KVxuICAgICAgfVxuICAgICAgaWYgKG93bmVkQnkoY2FuZGlkYXRlLnNvdXJjZVBhdGgsIGlucHV0UGF0aCkpIHtcbiAgICAgICAgaWYgKCFhcnRpZmFjdFBhdGhzLmhhcyhpbnB1dFBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgc3RhZ2UgJyR7cmVxdWVzdC5zdGFnZX0nIHJlYWRzIGFuIHVuZGVjbGFyZWQgc3RhZ2VkIGFydGlmYWN0LmAsIHRhcmdldClcbiAgICAgICAgfVxuICAgICAgICByZWZlcmVuY2VkQXJ0aWZhY3RQYXRocy5hZGQoaW5wdXRQYXRoKVxuICAgICAgfVxuICAgICAgc3RhZ2VJbnB1dHMuYWRkKGlucHV0UGF0aClcbiAgICB9XG4gICAgY29uc3QgcGF0aEluZGV4ZXMgPSBuZXcgU2V0KClcbiAgICBmb3IgKGxldCBwYXRoSW5kZXggPSAwOyBwYXRoSW5kZXggPCByZXF1ZXN0LnBhdGhBcmd1bWVudHMubGVuZ3RoOyBwYXRoSW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgZGVjbGFyYXRpb24gPSByZXF1ZXN0LnBhdGhBcmd1bWVudHNbcGF0aEluZGV4XVxuXG4gICAgICBpZiAoIWlzUGxhaW5PYmplY3QoZGVjbGFyYXRpb24pIHx8ICFPYmplY3QuaXNGcm96ZW4oZGVjbGFyYXRpb24pIHx8XG4gICAgICAgICFoYXNFeGFjdEtleXMoZGVjbGFyYXRpb24sIGRlY2xhcmF0aW9uLnByZWZpeCA9PT0gdW5kZWZpbmVkID8gW1wiaW5kZXhcIiwgXCJvd25lcnNoaXBcIl0gOiBbXCJpbmRleFwiLCBcIm93bmVyc2hpcFwiLCBcInByZWZpeFwiXSkgfHxcbiAgICAgICAgdHlwZW9mIGRlY2xhcmF0aW9uLmluZGV4ICE9IFwibnVtYmVyXCIgfHwgIU51bWJlci5pc0ludGVnZXIoZGVjbGFyYXRpb24uaW5kZXgpIHx8IGRlY2xhcmF0aW9uLmluZGV4IDwgMCB8fFxuICAgICAgICBkZWNsYXJhdGlvbi5pbmRleCA+PSByZXF1ZXN0LmFyZ3YubGVuZ3RoIHx8XG4gICAgICAgIHBhdGhJbmRleGVzLmhhcyhkZWNsYXJhdGlvbi5pbmRleCkgfHwgZGVjbGFyYXRpb24ub3duZXJzaGlwICE9IFwic291cmNlXCIgJiYgZGVjbGFyYXRpb24ub3duZXJzaGlwICE9IFwiYnVpbGRcIiB8fFxuICAgICAgICBkZWNsYXJhdGlvbi5wcmVmaXggIT09IHVuZGVmaW5lZCAmJiAodHlwZW9mIGRlY2xhcmF0aW9uLnByZWZpeCAhPSBcInN0cmluZ1wiIHx8IGRlY2xhcmF0aW9uLnByZWZpeC5sZW5ndGggPT0gMCB8fFxuICAgICAgICAgIGRlY2xhcmF0aW9uLnByZWZpeC5pbmNsdWRlcyhcIlxcMFwiKSkpIHtcbiAgICAgICAgcmV0dXJuIGludmFsaWRQbGFuKGBUYXJnZXQgY2hlY2sgc3RhZ2UgJyR7cmVxdWVzdC5zdGFnZX0nIGhhcyBpbnZhbGlkIHBhdGgtYXJndW1lbnQgb3duZXJzaGlwLmAsIHRhcmdldClcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJhd0FyZ3VtZW50ID0gcmVxdWVzdC5hcmd2W2RlY2xhcmF0aW9uLmluZGV4XVxuICAgICAgY29uc3QgYXJndW1lbnQgPSBkZWNsYXJhdGlvbi5wcmVmaXggPT09IHVuZGVmaW5lZFxuICAgICAgICA/IHJhd0FyZ3VtZW50XG4gICAgICAgIDogcmF3QXJndW1lbnQuc3RhcnRzV2l0aChkZWNsYXJhdGlvbi5wcmVmaXgpXG4gICAgICAgICAgPyByYXdBcmd1bWVudC5zbGljZShkZWNsYXJhdGlvbi5wcmVmaXgubGVuZ3RoKVxuICAgICAgICAgIDogXCJcIlxuICAgICAgY29uc3Qgcm9vdCA9IGRlY2xhcmF0aW9uLm93bmVyc2hpcCA9PSBcInNvdXJjZVwiID8gY2FuZGlkYXRlLnNvdXJjZVBhdGggOiBjYW5kaWRhdGUuYnVpbGRQYXRoXG5cbiAgICAgIGlmIChhcmd1bWVudCAhPSByb290ICYmICFvd25lZEJ5KHJvb3QsIGFyZ3VtZW50KSkge1xuICAgICAgICByZXR1cm4gaW52YWxpZFBsYW4oYFRhcmdldCBjaGVjayBzdGFnZSAnJHtyZXF1ZXN0LnN0YWdlfScgcGF0aCBhcmd1bWVudCBlc2NhcGVzIGl0cyBjYW5kaWRhdGUgc3VidHJlZS5gLCB0YXJnZXQpXG4gICAgICB9XG4gICAgICBwYXRoSW5kZXhlcy5hZGQoZGVjbGFyYXRpb24uaW5kZXgpXG4gICAgfVxuICAgIGZvciAobGV0IGFyZ3VtZW50SW5kZXggPSAwOyBhcmd1bWVudEluZGV4IDwgcmVxdWVzdC5hcmd2Lmxlbmd0aDsgYXJndW1lbnRJbmRleCArPSAxKSB7XG4gICAgICBpZiAocGF0aC5pc0Fic29sdXRlKHJlcXVlc3QuYXJndlthcmd1bWVudEluZGV4XSkgJiYgIXBhdGhJbmRleGVzLmhhcyhhcmd1bWVudEluZGV4KSkge1xuICAgICAgICByZXR1cm4gaW52YWxpZFBsYW4oYFRhcmdldCBjaGVjayBzdGFnZSAnJHtyZXF1ZXN0LnN0YWdlfScgY29udGFpbnMgYW4gdW5vd25lZCBhYnNvbHV0ZSBwYXRoIGFyZ3VtZW50LmAsIHRhcmdldClcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgaWYgKHJlZmVyZW5jZWRBcnRpZmFjdFBhdGhzLnNpemUgIT0gYXJ0aWZhY3RQYXRocy5zaXplKSB7XG4gICAgcmV0dXJuIGludmFsaWRQbGFuKFwiVGFyZ2V0IGNoZWNrIHBsYW4gbXVzdCBpbmNsdWRlIGV2ZXJ5IHN0YWdlZCBjaGVjayBhcnRpZmFjdC5cIiwgdGFyZ2V0KVxuICB9XG4gIGlmIChjYXBhYmlsaXR5LnRvb2xjaGFpbnMuc29tZSh0b29sY2hhaW4gPT4gIXVzZWRUb29scy5oYXModG9vbGNoYWluKSkpIHtcbiAgICByZXR1cm4gaW52YWxpZFBsYW4oXCJUYXJnZXQgY2hlY2sgcGxhbiBvbWl0cyBhIHRhcmdldC1kZWNsYXJlZCB0b29sY2hhaW4uXCIsIHRhcmdldClcbiAgfVxuXG4gIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tQbGFufSAqLyAoY2FuZGlkYXRlKVxufVxuXG4vKipcbiAqIENvbGxlY3RzIGV2ZXJ5IHJlZ3VsYXIgY29tcGlsZXIgb3V0cHV0IHdpdGhvdXQgZm9sbG93aW5nIGxpbmtzLlxuICogQHBhcmFtIHtzdHJpbmd9IGJ1aWxkUGF0aCAtIEV4YWN0IG93bmVkIGJ1aWxkIHJvb3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tPdXRwdXRPd25lcnNoaXB9IG91dHB1dCAtIE91dHB1dCBtZXRhZGF0YS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuUHVibGljYXRpb25CdWlsZEFydGlmYWN0SW5wdXRbXT59IE9yZGVyZWQgbWV0YWRhdGEuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNvbGxlY3RCdWlsZE91dHB1dHMoYnVpbGRQYXRoLCBvdXRwdXQpIHtcbiAgLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi9cbiAgY29uc3QgZmlsZXMgPSBbXVxuICAvKiogQHR5cGUge3thYnNvbHV0ZTogc3RyaW5nLCByZWxhdGl2ZTogc3RyaW5nfVtdfSAqL1xuICBjb25zdCBwZW5kaW5nID0gW3thYnNvbHV0ZTogYnVpbGRQYXRoLCByZWxhdGl2ZTogXCJcIn1dXG5cbiAgd2hpbGUgKHBlbmRpbmcubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGN1cnJlbnQgPSAvKiogQHR5cGUge3thYnNvbHV0ZTogc3RyaW5nLCByZWxhdGl2ZTogc3RyaW5nfX0gKi8gKHBlbmRpbmcucG9wKCkpXG4gICAgbGV0IGVudHJpZXNcblxuICAgIHRyeSB7XG4gICAgICBlbnRyaWVzID0gYXdhaXQgcmVhZGRpcihjdXJyZW50LmFic29sdXRlLCB7d2l0aEZpbGVUeXBlczogdHJ1ZX0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiBvdXRwdXRGYWlsdXJlKFwiQ29tcGlsZXIgb3V0cHV0IHN1YnRyZWUgY291bGQgbm90IGJlIGluc3BlY3RlZC5cIiwgZXJyb3IpXG4gICAgfVxuICAgIGVudHJpZXMuc29ydCgobGVmdCwgcmlnaHQpID0+IGxlZnQubmFtZS5sb2NhbGVDb21wYXJlKHJpZ2h0Lm5hbWUsIFwiZW5cIikpXG4gICAgZm9yIChsZXQgaW5kZXggPSBlbnRyaWVzLmxlbmd0aCAtIDE7IGluZGV4ID49IDA7IGluZGV4IC09IDEpIHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1tpbmRleF1cbiAgICAgIGNvbnN0IHJlbGF0aXZlID0gY3VycmVudC5yZWxhdGl2ZS5sZW5ndGggPT0gMCA/IGVudHJ5Lm5hbWUgOiBgJHtjdXJyZW50LnJlbGF0aXZlfS8ke2VudHJ5Lm5hbWV9YFxuICAgICAgY29uc3QgYWJzb2x1dGUgPSBwYXRoLmpvaW4oY3VycmVudC5hYnNvbHV0ZSwgZW50cnkubmFtZSlcblxuICAgICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHBlbmRpbmcucHVzaCh7YWJzb2x1dGUsIHJlbGF0aXZlfSlcbiAgICAgIGVsc2UgaWYgKGVudHJ5LmlzRmlsZSgpKSBmaWxlcy5wdXNoKHJlbGF0aXZlKVxuICAgICAgZWxzZSByZXR1cm4gb3V0cHV0RmFpbHVyZShgQ29tcGlsZXIgb3V0cHV0ICcke3JlbGF0aXZlfScgaXMgbm90IGEgcmVndWxhciBmaWxlIG9yIGRpcmVjdG9yeS5gKVxuICAgIH1cbiAgfVxuICBmaWxlcy5zb3J0KChsZWZ0LCByaWdodCkgPT4gbGVmdC5sb2NhbGVDb21wYXJlKHJpZ2h0LCBcImVuXCIpKVxuICBmb3IgKGNvbnN0IGZpbGVuYW1lIG9mIGZpbGVzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghKGF3YWl0IGxzdGF0KHBhdGguam9pbihidWlsZFBhdGgsIGZpbGVuYW1lKSkpLmlzRmlsZSgpKSB7XG4gICAgICAgIHJldHVybiBvdXRwdXRGYWlsdXJlKGBDb21waWxlciBvdXRwdXQgJyR7ZmlsZW5hbWV9JyBpcyBub3QgYSByZWd1bGFyIGZpbGUuYClcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIG91dHB1dEZhaWx1cmUoYENvbXBpbGVyIG91dHB1dCAnJHtmaWxlbmFtZX0nIGNvdWxkIG5vdCBiZSBpbnNwZWN0ZWQuYCwgZXJyb3IpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZpbGVzLm1hcChmaWxlbmFtZSA9PiBPYmplY3QuZnJlZXplKHttZWRpYVR5cGU6IG91dHB1dC5tZWRpYVR5cGUsIHBhdGg6IGZpbGVuYW1lLCByb2xlOiBvdXRwdXQucm9sZX0pKVxufVxuXG4vKipcbiAqIE5vcm1hbGl6ZXMgb25lIGNoaWxkIGZhaWx1cmUgd2hpbGUgcmV0YWluaW5nIGNvbXBsZXRlIGJvdW5kZWQgb3V0cHV0LlxuICogQHBhcmFtIHt1bmtub3dufSBlcnJvciAtIE9wYXF1ZSBwcm9jZXNzIGZhaWx1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tTdGFnZVJlcXVlc3R9IHN0YWdlIC0gRmFpbGVkIHN0YWdlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlRhcmdldENoZWNrUGxhbn0gcGxhbiAtIFBsYW4gY29udGV4dC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0TXMgLSBFeGFjdCB0aW1lb3V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGR1cmF0aW9uTXMgLSBPYnNlcnZlZCBkdXJhdGlvbi5cbiAqIEByZXR1cm5zIHtTZW1hbnRpZm9sZERpYWdub3N0aWN9IFN0cnVjdHVyZWQgY2hlY2sgZmFpbHVyZS5cbiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0RpYWdub3N0aWMoZXJyb3IsIHN0YWdlLCBwbGFuLCB0aW1lb3V0TXMsIGR1cmF0aW9uTXMpIHtcbiAgY29uc3QgZmllbGRzID0gcHJvY2Vzc0Vycm9yRmllbGRzKGVycm9yKVxuICBjb25zdCBvdXRwdXRMaW1pdGVkID0gZmllbGRzLm5hdGl2ZUNvZGUgPT0gXCJFUlJfQ0hJTERfUFJPQ0VTU19TVERJT19NQVhCVUZGRVJcIlxuICBjb25zdCBjYW5jZWxsZWQgPSAhb3V0cHV0TGltaXRlZCAmJiBjYW5jZWxsZWRPd25lZFByb2Nlc3MoZXJyb3IpXG4gIGNvbnN0IHRpbWVkT3V0ID0gIW91dHB1dExpbWl0ZWQgJiYgIWNhbmNlbGxlZCAmJiBleGNlZWRlZE93bmVkRGVhZGxpbmUoZXJyb3IpXG4gIGNvbnN0IGxhdW5jaEZhaWx1cmUgPSBmaWVsZHMubmF0aXZlQ29kZSAhPSB1bmRlZmluZWQgJiYgbGF1bmNoRXJyb3JDb2Rlcy5oYXMoZmllbGRzLm5hdGl2ZUNvZGUpXG4gIGNvbnN0IHNpZ25hbGVkID0gIW91dHB1dExpbWl0ZWQgJiYgIWNhbmNlbGxlZCAmJiAhdGltZWRPdXQgJiYgZmllbGRzLnNpZ25hbCAhPSB1bmRlZmluZWRcbiAgY29uc3QgY29kZSA9IG91dHB1dExpbWl0ZWQgPyBcIlRBUkdFVF9DSEVDS19PVVRQVVRfTElNSVRcIiA6IGNhbmNlbGxlZCA/IFwiVEFSR0VUX0NIRUNLX0NBTkNFTExFRFwiIDogdGltZWRPdXRcbiAgICA/IFwiVEFSR0VUX0NIRUNLX1RJTUVPVVRcIiA6IGxhdW5jaEZhaWx1cmUgPyBcIlRBUkdFVF9DSEVDS19MQVVOQ0hfRkFJTFVSRVwiIDogc2lnbmFsZWRcbiAgICAgID8gXCJUQVJHRVRfQ0hFQ0tfU0lHTkFMXCIgOiBcIlRBUkdFVF9DSEVDS19OT05aRVJPX0VYSVRcIlxuICBjb25zdCByZWFzb24gPSBvdXRwdXRMaW1pdGVkID8gYGV4Y2VlZGVkIHRoZSAke21heGltdW1PdXRwdXRCeXRlc30tYnl0ZSBvdXRwdXQgbGltaXRgIDogY2FuY2VsbGVkXG4gICAgPyBcIndhcyBjYW5jZWxsZWRcIiA6IHRpbWVkT3V0ID8gYHRpbWVkIG91dCBhZnRlciAke3RpbWVvdXRNc31tc2AgOiBsYXVuY2hGYWlsdXJlXG4gICAgICA/IGBjb3VsZCBub3QgbGF1bmNoICgke2ZpZWxkcy5uYXRpdmVDb2RlfSlgIDogc2lnbmFsZWQgPyBgY2xvc2VkIGFmdGVyIHNpZ25hbCAke2ZpZWxkcy5zaWduYWx9YFxuICAgICAgICA6IGZpZWxkcy5leGl0Q29kZSA9PSB1bmRlZmluZWQgPyBcImZhaWxlZCBhZnRlciBsYXVuY2hcIiA6IGBleGl0ZWQgbm9uemVybyAoJHtmaWVsZHMuZXhpdENvZGV9KWBcblxuICByZXR1cm4gbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgY2F1c2U6IG91dHB1dExpbWl0ZWQgPyB1bmRlZmluZWQgOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiB1bmRlZmluZWQsXG4gICAgY29kZSxcbiAgICBkdXJhdGlvbk1zLFxuICAgIGV4ZWN1dGFibGU6IHN0YWdlLmV4ZWN1dGFibGUsXG4gICAgZXhpdENvZGU6IGZpZWxkcy5leGl0Q29kZSxcbiAgICBsYW5ndWFnZTogcGxhbi50YXJnZXQsXG4gICAgbWVzc2FnZTogYFRhcmdldCAnJHtwbGFuLnRhcmdldElkfScgc3RhZ2UgJyR7c3RhZ2Uuc3RhZ2V9JyAke3JlYXNvbn0gdXNpbmcgJyR7c3RhZ2UuZXhlY3V0YWJsZX0nICgke3N0YWdlLnRvb2wudmVyc2lvbn0pLmAsXG4gICAgcHJvamVjdElkOiBwbGFuLnByb2plY3RJZCxcbiAgICBzaWduYWw6IGZpZWxkcy5zaWduYWwsXG4gICAgc3RhZ2U6IHN0YWdlLnN0YWdlLFxuICAgIHN0ZGVycjogZmllbGRzLnN0ZGVycixcbiAgICBzdGRvdXQ6IGZpZWxkcy5zdGRvdXQsXG4gICAgdGFyZ2V0SWQ6IHBsYW4udGFyZ2V0SWQsXG4gICAgdG9vbElkOiBzdGFnZS50b29sLmlkLFxuICAgIHZlcnNpb246IHN0YWdlLnRvb2wudmVyc2lvblxuICB9KVxufVxuXG4vKipcbiAqIENyZWF0ZXMgdGFyZ2V0LW93bmVkIGVudmlyb25tZW50IGRpcmVjdG9yaWVzIGJlZm9yZSBsYXVuY2ggd2l0aG91dCB0b3VjaGluZyBzb3VyY2Ugc3RhZ2luZy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UYXJnZXRDaGVja1N0YWdlUmVxdWVzdH0gc3RhZ2UgLSBWYWxpZGF0ZWQgc3RhZ2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tQbGFufSBwbGFuIC0gVmFsaWRhdGVkIHBsYW4gY29udGV4dC5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBDb21wbGV0aW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiBwcmVwYXJlU3RhZ2Uoc3RhZ2UsIHBsYW4pIHtcbiAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBzdGFnZS5lbnZpcm9ubWVudFBhdGhzKSB7XG4gICAgaWYgKGRlY2xhcmF0aW9uLm93bmVyc2hpcCA9PSBcImJ1aWxkXCIpIHtcbiAgICAgIGF3YWl0IG1rZGlyKHN0YWdlLmVudmlyb25tZW50W2RlY2xhcmF0aW9uLm5hbWVdLCB7bW9kZTogMG83MDAsIHJlY3Vyc2l2ZTogdHJ1ZX0pXG4gICAgfVxuICB9XG4gIGZvciAoY29uc3QgdHJhbnNpZW50UGF0aCBvZiBzdGFnZS50cmFuc2llbnRQYXRocykge1xuICAgIGlmIChvd25lZEJ5KHBsYW4uYnVpbGRQYXRoLCB0cmFuc2llbnRQYXRoKSkgYXdhaXQgbWtkaXIodHJhbnNpZW50UGF0aCwge21vZGU6IDBvNzAwLCByZWN1cnNpdmU6IHRydWV9KVxuICB9XG59XG5cbi8qKlxuICogUmVtb3ZlcyBvbmx5IGV4cGxpY2l0bHkgZGVjbGFyZWQgZ2VuZXJhdGlvbi1vd25lZCB0cmFuc2llbnQgY2FjaGUvaG9tZSBkaXJlY3RvcmllcyBhZnRlciBldmVyeSBjaGlsZCBoYXMgY2xvc2VkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlRhcmdldENoZWNrUGxhbn0gcGxhbiAtIFZhbGlkYXRlZCBwbGFuLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IENvbXBsZXRpb24uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNsZWFudXBTdGFnZUVudmlyb25tZW50KHBsYW4pIHtcbiAgY29uc3Qgb3duZWQgPSBuZXcgU2V0KClcblxuICBmb3IgKGNvbnN0IHN0YWdlIG9mIHBsYW4uc3RhZ2VzKSB7XG4gICAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBzdGFnZS5lbnZpcm9ubWVudFBhdGhzKSB7XG4gICAgICBpZiAoZGVjbGFyYXRpb24ub3duZXJzaGlwID09IFwiYnVpbGRcIikgb3duZWQuYWRkKHN0YWdlLmVudmlyb25tZW50W2RlY2xhcmF0aW9uLm5hbWVdKVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IHRyYW5zaWVudFBhdGggb2Ygc3RhZ2UudHJhbnNpZW50UGF0aHMpIG93bmVkLmFkZCh0cmFuc2llbnRQYXRoKVxuICB9XG4gIGNvbnN0IHBhdGhzID0gWy4uLm93bmVkXS5zb3J0KChsZWZ0LCByaWdodCkgPT4gcmlnaHQubGVuZ3RoIC0gbGVmdC5sZW5ndGggfHwgcmlnaHQubG9jYWxlQ29tcGFyZShsZWZ0LCBcImVuXCIpKVxuXG4gIGZvciAoY29uc3Qgb3duZWRQYXRoIG9mIHBhdGhzKSB7XG4gICAgYXdhaXQgcm0ob3duZWRQYXRoLCB7Zm9yY2U6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZX0pXG4gICAgYXdhaXQgcmVtb3ZlRW1wdHlQYXJlbnRzKHBhdGguZGlybmFtZShvd25lZFBhdGgpLCBvd25lZEJ5KHBsYW4uYnVpbGRQYXRoLCBvd25lZFBhdGgpID8gcGxhbi5idWlsZFBhdGggOiBwbGFuLnNvdXJjZVBhdGgpXG4gIH1cbn1cblxuLyoqXG4gKiBSZW1vdmVzIGVtcHR5IHRyYW5zaWVudCBhbmNlc3RvcnMgd2l0aG91dCBldmVyIHJlbW92aW5nIHRoZSBjYW5kaWRhdGUgYnVpbGQgcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjYW5kaWRhdGUgLSBGaXJzdCBwb3NzaWJsZSBlbXB0eSBhbmNlc3Rvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSByb290IC0gRXhhY3QgcmV0YWluZWQgY2FuZGlkYXRlIHJvb3QuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVtb3ZlRW1wdHlQYXJlbnRzKGNhbmRpZGF0ZSwgcm9vdCkge1xuICBsZXQgY3VycmVudCA9IGNhbmRpZGF0ZVxuXG4gIHdoaWxlIChvd25lZEJ5KHJvb3QsIGN1cnJlbnQpKSB7XG4gICAgaWYgKChhd2FpdCByZWFkZGlyKGN1cnJlbnQpKS5sZW5ndGggPiAwKSByZXR1cm5cbiAgICBhd2FpdCBybWRpcihjdXJyZW50KVxuICAgIGN1cnJlbnQgPSBwYXRoLmRpcm5hbWUoY3VycmVudClcbiAgfVxufVxuXG4vKipcbiAqIFByZXNlcnZlcyBjYWNoZS9ob21lIHByZXBhcmF0aW9uIGZhaWx1cmVzIHNlcGFyYXRlbHkgZnJvbSB0b29sIGxhdW5jaCBvciBjb21waWxhdGlvbi5cbiAqIEBwYXJhbSB7dW5rbm93bn0gZXJyb3IgLSBGaWxlc3lzdGVtIGZhaWx1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuVGFyZ2V0Q2hlY2tTdGFnZVJlcXVlc3R9IHN0YWdlIC0gRmFpbGVkIHN0YWdlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlRhcmdldENoZWNrUGxhbn0gcGxhbiAtIFBsYW4gY29udGV4dC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkdXJhdGlvbk1zIC0gT2JzZXJ2ZWQgZHVyYXRpb24uXG4gKiBAcmV0dXJucyB7U2VtYW50aWZvbGREaWFnbm9zdGljfSBTdHJ1Y3R1cmVkIGZhaWx1cmUuXG4gKi9cbmZ1bmN0aW9uIHByZXBhcmF0aW9uRGlhZ25vc3RpYyhlcnJvciwgc3RhZ2UsIHBsYW4sIGR1cmF0aW9uTXMpIHtcbiAgcmV0dXJuIG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgIGNhdXNlOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiB1bmRlZmluZWQsXG4gICAgY29kZTogXCJUQVJHRVRfQ0hFQ0tfUFJFUEFSQVRJT05fRkFJTFVSRVwiLFxuICAgIGR1cmF0aW9uTXMsXG4gICAgZXhlY3V0YWJsZTogc3RhZ2UuZXhlY3V0YWJsZSxcbiAgICBsYW5ndWFnZTogcGxhbi50YXJnZXQsXG4gICAgbWVzc2FnZTogYFRhcmdldCAnJHtwbGFuLnRhcmdldElkfScgc3RhZ2UgJyR7c3RhZ2Uuc3RhZ2V9JyBjb3VsZCBub3QgcHJlcGFyZSBpdHMgb3duZWQgY2FjaGUvaG9tZSBkaXJlY3Rvcmllcy5gLFxuICAgIHByb2plY3RJZDogcGxhbi5wcm9qZWN0SWQsXG4gICAgc3RhZ2U6IHN0YWdlLnN0YWdlLFxuICAgIHN0ZGVycjogXCJcIixcbiAgICBzdGRvdXQ6IFwiXCIsXG4gICAgdGFyZ2V0SWQ6IHBsYW4udGFyZ2V0SWQsXG4gICAgdG9vbElkOiBzdGFnZS50b29sLmlkLFxuICAgIHZlcnNpb246IHN0YWdlLnRvb2wudmVyc2lvblxuICB9KVxufVxuXG4vKipcbiAqIFJlcG9ydHMgdHJhbnNpZW50IGNhY2hlL2hvbWUgY2xlYW51cCBzZXBhcmF0ZWx5IGZyb20gbmF0aXZlIGNvbXBpbGVyIGRpYWdub3N0aWNzLlxuICogQHBhcmFtIHt1bmtub3dufSBlcnJvciAtIEZpbGVzeXN0ZW0gZmFpbHVyZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UYXJnZXRDaGVja1BsYW59IHBsYW4gLSBQbGFuIGNvbnRleHQuXG4gKiBAcmV0dXJucyB7U2VtYW50aWZvbGREaWFnbm9zdGljfSBTdHJ1Y3R1cmVkIGNsZWFudXAgZmFpbHVyZS5cbiAqL1xuZnVuY3Rpb24gY2xlYW51cERpYWdub3N0aWMoZXJyb3IsIHBsYW4pIHtcbiAgcmV0dXJuIG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgIGNhdXNlOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiB1bmRlZmluZWQsXG4gICAgY29kZTogXCJUQVJHRVRfQ0hFQ0tfQ0xFQU5VUF9GQUlMVVJFXCIsXG4gICAgbGFuZ3VhZ2U6IHBsYW4udGFyZ2V0LFxuICAgIG1lc3NhZ2U6IGBUYXJnZXQgJyR7cGxhbi50YXJnZXRJZH0nIGNvdWxkIG5vdCByZW1vdmUgaXRzIG93bmVkIHRyYW5zaWVudCBjYWNoZS9ob21lIGRpcmVjdG9yaWVzLmAsXG4gICAgcHJvamVjdElkOiBwbGFuLnByb2plY3RJZCxcbiAgICB0YXJnZXRJZDogcGxhbi50YXJnZXRJZFxuICB9KVxufVxuXG4vKipcbiAqIFJldGFpbnMgdGhlIGZpcnN0IHBsYW4vcHJvY2VzcyBkaWFnbm9zdGljIHdoaWxlIGF0dGFjaGluZyBib3VuZGVkIGNsZWFudXAgZXZpZGVuY2UuXG4gKiBAcGFyYW0ge0Vycm9yfSBwcmltYXJ5RmFpbHVyZSAtIEZpcnN0IGNoZWNrIGZhaWx1cmUuXG4gKiBAcGFyYW0ge1NlbWFudGlmb2xkRGlhZ25vc3RpY30gY2xlYW51cEZhaWx1cmUgLSBTdHJ1Y3R1cmVkIGNsZWFudXAgZmFpbHVyZS5cbiAqIEByZXR1cm5zIHtFcnJvcn0gT3JpZ2luYWwgZmFpbHVyZSB3aXRoIGNsZWFudXAgZXZpZGVuY2UgaW4gaXRzIGNhdXNlIGNoYWluLlxuICovXG5mdW5jdGlvbiBwcmVzZXJ2ZVByaW1hcnlGYWlsdXJlKHByaW1hcnlGYWlsdXJlLCBjbGVhbnVwRmFpbHVyZSkge1xuICBjb25zdCBjYXVzZXMgPSBwcmltYXJ5RmFpbHVyZS5jYXVzZSBpbnN0YW5jZW9mIEVycm9yID8gW3ByaW1hcnlGYWlsdXJlLmNhdXNlLCBjbGVhbnVwRmFpbHVyZV0gOiBbY2xlYW51cEZhaWx1cmVdXG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHByaW1hcnlGYWlsdXJlLCBcImNhdXNlXCIsIHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgdmFsdWU6IG5ldyBBZ2dyZWdhdGVFcnJvcihjYXVzZXMsIFwiVGFyZ2V0IGNoZWNrIGZhaWxlZCBhbmQgaXRzIG93bmVkIHRyYW5zaWVudCBlbnZpcm9ubWVudCBjbGVhbnVwIGFsc28gZmFpbGVkLlwiKSxcbiAgICB3cml0YWJsZTogdHJ1ZVxuICB9KVxuXG4gIHJldHVybiBwcmltYXJ5RmFpbHVyZVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBzdHJ1Y3R1cmVkIGZhaWx1cmUgd2hlbiBjYW5jZWxsYXRpb24gcHJlY2VkZXMgc3RhZ2UgbGF1bmNoLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlRhcmdldENoZWNrU3RhZ2VSZXF1ZXN0fSBzdGFnZSAtIENhbmNlbGxlZCBzdGFnZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UYXJnZXRDaGVja1BsYW59IHBsYW4gLSBQbGFuIGNvbnRleHQuXG4gKiBAcGFyYW0ge251bWJlcn0gZHVyYXRpb25NcyAtIE9ic2VydmVkIGR1cmF0aW9uLlxuICogQHJldHVybnMge1NlbWFudGlmb2xkRGlhZ25vc3RpY30gU3RydWN0dXJlZCBjYW5jZWxsYXRpb24gZGlhZ25vc3RpYy5cbiAqL1xuZnVuY3Rpb24gY2FuY2VsbGVkRGlhZ25vc3RpYyhzdGFnZSwgcGxhbiwgZHVyYXRpb25Ncykge1xuICByZXR1cm4gbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgY29kZTogXCJUQVJHRVRfQ0hFQ0tfQ0FOQ0VMTEVEXCIsXG4gICAgZHVyYXRpb25NcyxcbiAgICBleGVjdXRhYmxlOiBzdGFnZS5leGVjdXRhYmxlLFxuICAgIGxhbmd1YWdlOiBwbGFuLnRhcmdldCxcbiAgICBtZXNzYWdlOiBgVGFyZ2V0ICcke3BsYW4udGFyZ2V0SWR9JyBzdGFnZSAnJHtzdGFnZS5zdGFnZX0nIHdhcyBjYW5jZWxsZWQgYmVmb3JlIGxhdW5jaC5gLFxuICAgIHByb2plY3RJZDogcGxhbi5wcm9qZWN0SWQsXG4gICAgc3RhZ2U6IHN0YWdlLnN0YWdlLFxuICAgIHN0ZGVycjogXCJcIixcbiAgICBzdGRvdXQ6IFwiXCIsXG4gICAgdGFyZ2V0SWQ6IHBsYW4udGFyZ2V0SWQsXG4gICAgdG9vbElkOiBzdGFnZS50b29sLmlkLFxuICAgIHZlcnNpb246IHN0YWdlLnRvb2wudmVyc2lvblxuICB9KVxufVxuXG4vKipcbiAqIEV4dHJhY3RzIHN0YWJsZSBib3VuZGVkIGNoaWxkLXByb2Nlc3MgZmFpbHVyZSBmaWVsZHMuXG4gKiBAcGFyYW0ge3Vua25vd259IGVycm9yIC0gT3BhcXVlIHByb2Nlc3MgcmVqZWN0aW9uLlxuICogQHJldHVybnMge3tleGl0Q29kZTogbnVtYmVyIHwgdW5kZWZpbmVkLCBuYXRpdmVDb2RlOiBzdHJpbmcgfCB1bmRlZmluZWQsIHNpZ25hbDogc3RyaW5nIHwgdW5kZWZpbmVkLCBzdGRlcnI6IHN0cmluZywgc3Rkb3V0OiBzdHJpbmd9fSBTdGFibGUgZmllbGRzLlxuICovXG5mdW5jdGlvbiBwcm9jZXNzRXJyb3JGaWVsZHMoZXJyb3IpIHtcbiAgaWYgKCFlcnJvciB8fCB0eXBlb2YgZXJyb3IgIT0gXCJvYmplY3RcIikgcmV0dXJuIHtleGl0Q29kZTogdW5kZWZpbmVkLCBuYXRpdmVDb2RlOiB1bmRlZmluZWQsIHNpZ25hbDogdW5kZWZpbmVkLCBzdGRlcnI6IFwiXCIsIHN0ZG91dDogXCJcIn1cbiAgY29uc3QgdmFsdWUgPSAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSAqLyAoZXJyb3IpXG5cbiAgcmV0dXJuIHtcbiAgICBleGl0Q29kZTogdHlwZW9mIHZhbHVlLmNvZGUgPT0gXCJudW1iZXJcIiA/IHZhbHVlLmNvZGUgOiB1bmRlZmluZWQsXG4gICAgbmF0aXZlQ29kZTogdHlwZW9mIHZhbHVlLmNvZGUgPT0gXCJzdHJpbmdcIiA/IHZhbHVlLmNvZGUgOiB1bmRlZmluZWQsXG4gICAgc2lnbmFsOiB0eXBlb2YgdmFsdWUuc2lnbmFsID09IFwic3RyaW5nXCIgPyB2YWx1ZS5zaWduYWwgOiB1bmRlZmluZWQsXG4gICAgc3RkZXJyOiB0eXBlb2YgdmFsdWUuc3RkZXJyID09IFwic3RyaW5nXCIgPyB2YWx1ZS5zdGRlcnIgOiBcIlwiLFxuICAgIHN0ZG91dDogdHlwZW9mIHZhbHVlLnN0ZG91dCA9PSBcInN0cmluZ1wiID8gdmFsdWUuc3Rkb3V0IDogXCJcIlxuICB9XG59XG5cbi8qKlxuICogQ2hlY2tzIHRoZSBjb21wbGV0ZSBpbW11dGFibGUgZGlzY292ZXJlZC10b29sIHNoYXBlIGNvbnN1bWVkIGJ5IGEgcGxhbi5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBDYW5kaWRhdGUgdG9vbCByZWNvcmQuXG4gKiBAcmV0dXJucyB7dmFsdWUgaXMgaW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5EaXNjb3ZlcmVkVG9vbGNoYWlufSBXaGV0aGVyIHRoZSB0b29sIHNoYXBlIGlzIHZhbGlkLlxuICovXG5mdW5jdGlvbiBpc0Rpc2NvdmVyZWRUb29sKHZhbHVlKSB7XG4gIHJldHVybiBpc1BsYWluT2JqZWN0KHZhbHVlKSAmJiB0eXBlb2YgdmFsdWUuaWQgPT0gXCJzdHJpbmdcIiAmJiB0eXBlb2YgdmFsdWUuY29tbWFuZCA9PSBcInN0cmluZ1wiICYmXG4gICAgdHlwZW9mIHZhbHVlLmV4ZWN1dGFibGUgPT0gXCJzdHJpbmdcIiAmJiBwYXRoLmlzQWJzb2x1dGUodmFsdWUuZXhlY3V0YWJsZSkgJiYgIXZhbHVlLmV4ZWN1dGFibGUuaW5jbHVkZXMoXCJcXDBcIikgJiZcbiAgICAodmFsdWUuc291cmNlID09IFwiY2Fub25pY2FsXCIgfHwgdmFsdWUuc291cmNlID09IFwib3ZlcnJpZGVcIikgJiYgdHlwZW9mIHZhbHVlLnZlcnNpb24gPT0gXCJzdHJpbmdcIiAmJiB2YWx1ZS52ZXJzaW9uLmxlbmd0aCA+IDAgJiZcbiAgICB0eXBlb2YgdmFsdWUudmVyc2lvbk91dHB1dCA9PSBcInN0cmluZ1wiICYmIGlzRGVuc2VBcnJheSh2YWx1ZS52ZXJzaW9uQXJndW1lbnRzKSAmJlxuICAgIHZhbHVlLnZlcnNpb25Bcmd1bWVudHMuZXZlcnkoYXJndW1lbnQgPT4gdHlwZW9mIGFyZ3VtZW50ID09IFwic3RyaW5nXCIgJiYgIWFyZ3VtZW50LmluY2x1ZGVzKFwiXFwwXCIpKVxufVxuXG4vKipcbiAqIENoZWNrcyB0aGF0IGFuIGVudmlyb25tZW50IGlzIGltbXV0YWJsZSBhbmQgYWxyZWFkeSBkZXRlcm1pbmlzdGljLlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIENhbmRpZGF0ZSBlbnZpcm9ubWVudCByZWNvcmQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgZW52aXJvbm1lbnQgaXMgbm9ybWFsaXplZC5cbiAqL1xuZnVuY3Rpb24gdmFsaWRFbnZpcm9ubWVudCh2YWx1ZSkge1xuICBpZiAoIWlzUGxhaW5SZWNvcmQodmFsdWUpIHx8ICFPYmplY3QuaXNGcm96ZW4odmFsdWUpKSByZXR1cm4gZmFsc2VcbiAgbGV0IG5vcm1hbGl6ZWRcblxuICB0cnkge1xuICAgIG5vcm1hbGl6ZWQgPSBkZXRlcm1pbmlzdGljRW52aXJvbm1lbnQoLyoqIEB0eXBlIHtSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+Pn0gKi8gKHZhbHVlKSlcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgY29uc3QgYWN0dWFsID0gT2JqZWN0LmVudHJpZXModmFsdWUpLnNvcnQoKFtsZWZ0XSwgW3JpZ2h0XSkgPT4gbGVmdC5sb2NhbGVDb21wYXJlKHJpZ2h0LCBcImVuXCIpKVxuICBjb25zdCBleHBlY3RlZCA9IE9iamVjdC5lbnRyaWVzKG5vcm1hbGl6ZWQpLnNvcnQoKFtsZWZ0XSwgW3JpZ2h0XSkgPT4gbGVmdC5sb2NhbGVDb21wYXJlKHJpZ2h0LCBcImVuXCIpKVxuXG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShhY3R1YWwpID09IEpTT04uc3RyaW5naWZ5KGV4cGVjdGVkKVxufVxuXG4vKipcbiAqIENoZWNrcyBldmVyeSBhYnNvbHV0ZSBub24tUEFUSCBlbnZpcm9ubWVudCB2YWx1ZSBhZ2FpbnN0IGFuIGV4cGxpY2l0IGNhbmRpZGF0ZS1vd25lZCBkaXJlY3Rvcnkgb3IgZGlzY292ZXJlZC10b29sIGRlY2xhcmF0aW9uLlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIENhbmRpZGF0ZSBkZWNsYXJhdGlvbnMuXG4gKiBAcGFyYW0ge1JlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHN0cmluZz4+fSBlbnZpcm9ubWVudCAtIFZhbGlkYXRlZCBkZXRlcm1pbmlzdGljIGVudmlyb25tZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZVBhdGggLSBDYW5kaWRhdGUgc291cmNlIHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gYnVpbGRQYXRoIC0gQ2FuZGlkYXRlIGJ1aWxkIHJvb3QuXG4gKiBAcGFyYW0ge3JlYWRvbmx5IHN0cmluZ1tdfSB0b29sY2hhaW5zIC0gVGFyZ2V0LWRlY2xhcmVkIHRvb2xjaGFpbiBJRHMuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSB1c2VkVG9vbHMgLSBWYWxpZGF0ZWQgdG9vbHMgdXNlZCBieSB0aGlzIHBsYW4uXG4gKiBAcmV0dXJucyB7dmFsdWUgaXMgcmVhZG9ubHkgaW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UYXJnZXRDaGVja0Vudmlyb25tZW50UGF0aFtdfSBXaGV0aGVyIG93bmVyc2hpcCBpcyBjb21wbGV0ZS5cbiAqL1xuZnVuY3Rpb24gdmFsaWRFbnZpcm9ubWVudFBhdGhzKHZhbHVlLCBlbnZpcm9ubWVudCwgc291cmNlUGF0aCwgYnVpbGRQYXRoLCB0b29sY2hhaW5zLCB1c2VkVG9vbHMpIHtcbiAgaWYgKCFpc0RlbnNlQXJyYXkodmFsdWUpIHx8ICFPYmplY3QuaXNGcm96ZW4odmFsdWUpKSByZXR1cm4gZmFsc2VcbiAgY29uc3QgbmFtZXMgPSBuZXcgU2V0KClcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdmFsdWUubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgZGVjbGFyYXRpb24gPSB2YWx1ZVtpbmRleF1cblxuICAgIGlmICghaXNQbGFpbk9iamVjdChkZWNsYXJhdGlvbikgfHwgIU9iamVjdC5pc0Zyb3plbihkZWNsYXJhdGlvbikgfHxcbiAgICAgICFoYXNFeGFjdEtleXMoZGVjbGFyYXRpb24sIGRlY2xhcmF0aW9uLm93bmVyc2hpcCA9PSBcInRvb2xcIiA/IFtcIm5hbWVcIiwgXCJvd25lcnNoaXBcIiwgXCJ0b29sXCJdIDogW1wibmFtZVwiLCBcIm93bmVyc2hpcFwiXSkgfHxcbiAgICAgIHR5cGVvZiBkZWNsYXJhdGlvbi5uYW1lICE9IFwic3RyaW5nXCIgfHwgbmFtZXMuaGFzKGRlY2xhcmF0aW9uLm5hbWUpKSByZXR1cm4gZmFsc2VcbiAgICBjb25zdCBlbnZpcm9ubWVudFBhdGggPSBlbnZpcm9ubWVudFtkZWNsYXJhdGlvbi5uYW1lXVxuXG4gICAgaWYgKGRlY2xhcmF0aW9uLm93bmVyc2hpcCA9PSBcInRvb2xcIikge1xuICAgICAgaWYgKCFpc0Rpc2NvdmVyZWRUb29sKGRlY2xhcmF0aW9uLnRvb2wpIHx8ICFPYmplY3QuaXNGcm96ZW4oZGVjbGFyYXRpb24udG9vbCkgfHxcbiAgICAgICAgIU9iamVjdC5pc0Zyb3plbihkZWNsYXJhdGlvbi50b29sLnZlcnNpb25Bcmd1bWVudHMpIHx8ICF0b29sY2hhaW5zLmluY2x1ZGVzKGRlY2xhcmF0aW9uLnRvb2wuaWQpIHx8XG4gICAgICAgIGVudmlyb25tZW50UGF0aCAhPSBkZWNsYXJhdGlvbi50b29sLmV4ZWN1dGFibGUpIHJldHVybiBmYWxzZVxuICAgICAgdXNlZFRvb2xzLmFkZChkZWNsYXJhdGlvbi50b29sLmlkKVxuICAgICAgbmFtZXMuYWRkKGRlY2xhcmF0aW9uLm5hbWUpXG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBpZiAoZGVjbGFyYXRpb24ub3duZXJzaGlwICE9IFwic291cmNlXCIgJiYgZGVjbGFyYXRpb24ub3duZXJzaGlwICE9IFwiYnVpbGRcIikgcmV0dXJuIGZhbHNlXG4gICAgY29uc3Qgcm9vdCA9IGRlY2xhcmF0aW9uLm93bmVyc2hpcCA9PSBcInNvdXJjZVwiID8gc291cmNlUGF0aCA6IGJ1aWxkUGF0aFxuXG4gICAgaWYgKHR5cGVvZiBlbnZpcm9ubWVudFBhdGggIT0gXCJzdHJpbmdcIiB8fCAhb3duZWRCeShyb290LCBlbnZpcm9ubWVudFBhdGgpKSByZXR1cm4gZmFsc2VcbiAgICBuYW1lcy5hZGQoZGVjbGFyYXRpb24ubmFtZSlcbiAgfVxuICBmb3IgKGNvbnN0IFtuYW1lLCBlbnZpcm9ubWVudFZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhlbnZpcm9ubWVudCkpIHtcbiAgICBpZiAobmFtZSAhPSBcIlBBVEhcIiAmJiBwYXRoLmlzQWJzb2x1dGUoZW52aXJvbm1lbnRWYWx1ZSkgJiYgIW5hbWVzLmhhcyhuYW1lKSkgcmV0dXJuIGZhbHNlXG4gIH1cblxuICByZXR1cm4gdHJ1ZVxufVxuXG4vKipcbiAqIENoZWNrcyBnZW5lcmF0aW9uLW93bmVkIHRyYW5zaWVudCBjYWNoZS9pbnRlcm1lZGlhdGUgZGlyZWN0b3JpZXMuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gQ2FuZGlkYXRlIHBhdGggdmVjdG9yLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZVBhdGggLSBDYW5kaWRhdGUgc291cmNlIHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gYnVpbGRQYXRoIC0gQ2FuZGlkYXRlIGJ1aWxkIHJvb3QuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSBhcnRpZmFjdFBhdGhzIC0gRXhhY3Qgc3RhZ2VkIGFydGlmYWN0IHBhdGhzLlxuICogQHJldHVybnMge3ZhbHVlIGlzIHJlYWRvbmx5IHN0cmluZ1tdfSBXaGV0aGVyIHBhdGhzIGFyZSBpbW11dGFibGUgZGlzdGluY3QgY2FuZGlkYXRlIGRlc2NlbmRhbnRzLlxuICovXG5mdW5jdGlvbiB2YWxpZFRyYW5zaWVudFBhdGhzKHZhbHVlLCBzb3VyY2VQYXRoLCBidWlsZFBhdGgsIGFydGlmYWN0UGF0aHMpIHtcbiAgaWYgKCFpc0RlbnNlQXJyYXkodmFsdWUpIHx8ICFPYmplY3QuaXNGcm96ZW4odmFsdWUpKSByZXR1cm4gZmFsc2VcbiAgY29uc3QgcGF0aHMgPSBuZXcgU2V0KClcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdmFsdWUubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgdHJhbnNpZW50UGF0aCA9IHZhbHVlW2luZGV4XVxuXG4gICAgaWYgKHR5cGVvZiB0cmFuc2llbnRQYXRoICE9IFwic3RyaW5nXCIgfHwgIW93bmVkQnkoc291cmNlUGF0aCwgdHJhbnNpZW50UGF0aCkgJiYgIW93bmVkQnkoYnVpbGRQYXRoLCB0cmFuc2llbnRQYXRoKSB8fFxuICAgICAgcGF0aHMuaGFzKHRyYW5zaWVudFBhdGgpIHx8IG93bmVkQnkoc291cmNlUGF0aCwgdHJhbnNpZW50UGF0aCkgJiYgWy4uLmFydGlmYWN0UGF0aHNdLnNvbWUoYXJ0aWZhY3RQYXRoID0+XG4gICAgICAgIHRyYW5zaWVudFBhdGggPT0gYXJ0aWZhY3RQYXRoIHx8IHBhdGhzT3ZlcmxhcCh0cmFuc2llbnRQYXRoLCBhcnRpZmFjdFBhdGgpKSkgcmV0dXJuIGZhbHNlXG4gICAgcGF0aHMuYWRkKHRyYW5zaWVudFBhdGgpXG4gIH1cblxuICByZXR1cm4gdHJ1ZVxufVxuXG4vKipcbiAqIENoZWNrcyBjb21waWxlci1vdXRwdXQgbWV0YWRhdGEgYWdhaW5zdCB0aGUgb3duZWQgYnVpbGQgcm9vdC5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBDYW5kaWRhdGUgb3V0cHV0IHJlY29yZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBidWlsZFBhdGggLSBFeGFjdCBjYW5kaWRhdGUgYnVpbGQgcm9vdC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIG91dHB1dCBvd25lcnNoaXAgaXMgdmFsaWQuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkT3V0cHV0KHZhbHVlLCBidWlsZFBhdGgpIHtcbiAgcmV0dXJuIGlzUGxhaW5PYmplY3QodmFsdWUpICYmIE9iamVjdC5pc0Zyb3plbih2YWx1ZSkgJiYgaGFzRXhhY3RLZXlzKHZhbHVlLCBbXCJtZWRpYVR5cGVcIiwgXCJvd25lcnNoaXBcIiwgXCJwYXRoXCIsIFwicm9sZVwiXSkgJiZcbiAgICB2YWx1ZS5vd25lcnNoaXAgPT0gXCJidWlsZFwiICYmIHZhbHVlLnBhdGggPT0gYnVpbGRQYXRoICYmIHR5cGVvZiB2YWx1ZS5tZWRpYVR5cGUgPT0gXCJzdHJpbmdcIiAmJlxuICAgIG1lZGlhVHlwZVBhdHRlcm4udGVzdCh2YWx1ZS5tZWRpYVR5cGUpICYmIHR5cGVvZiB2YWx1ZS5yb2xlID09IFwic3RyaW5nXCIgJiYgcm9sZVBhdHRlcm4udGVzdCh2YWx1ZS5yb2xlKVxufVxuXG4vKipcbiAqIENoZWNrcyBzdHJpY3QgZGVzY2VuZGFudCBvd25lcnNoaXAgd2l0aG91dCBhY2NlcHRpbmcgdGhlIHJvb3QgaXRzZWxmLlxuICogQHBhcmFtIHtzdHJpbmd9IHJvb3QgLSBBYnNvbHV0ZSBvd25lZCByb290LlxuICogQHBhcmFtIHtzdHJpbmd9IGNhbmRpZGF0ZSAtIEFic29sdXRlIGNhbmRpZGF0ZSBwYXRoLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGNhbmRpZGF0ZSBpcyBhIHN0cmljdCBkZXNjZW5kYW50LlxuICovXG5mdW5jdGlvbiBvd25lZEJ5KHJvb3QsIGNhbmRpZGF0ZSkge1xuICBpZiAoIXBhdGguaXNBYnNvbHV0ZShjYW5kaWRhdGUpKSByZXR1cm4gZmFsc2VcbiAgY29uc3QgcmVsYXRpdmUgPSBwYXRoLnJlbGF0aXZlKHJvb3QsIGNhbmRpZGF0ZSlcblxuICByZXR1cm4gcmVsYXRpdmUubGVuZ3RoID4gMCAmJiAhcmVsYXRpdmUuc3RhcnRzV2l0aChgLi4ke3BhdGguc2VwfWApICYmIHJlbGF0aXZlICE9IFwiLi5cIiAmJiAhcGF0aC5pc0Fic29sdXRlKHJlbGF0aXZlKVxufVxuXG4vKipcbiAqIENoZWNrcyBjYW5kaWRhdGUgb3duZXJzaGlwIGJ5IGVpdGhlciBleGFjdCB0YXJnZXQgc3VidHJlZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2VQYXRoIC0gRXhhY3Qgc291cmNlIHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gYnVpbGRQYXRoIC0gRXhhY3QgYnVpbGQgcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjYW5kaWRhdGUgLSBDYW5kaWRhdGUgd29ya2luZyBkaXJlY3RvcnkuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciBlaXRoZXIgdGFyZ2V0IHN1YnRyZWUgb3ducyB0aGUgY2FuZGlkYXRlLlxuICovXG5mdW5jdGlvbiBvd25lZEJ5RWl0aGVyKHNvdXJjZVBhdGgsIGJ1aWxkUGF0aCwgY2FuZGlkYXRlKSB7XG4gIHJldHVybiBjYW5kaWRhdGUgPT0gc291cmNlUGF0aCB8fCBjYW5kaWRhdGUgPT0gYnVpbGRQYXRoIHx8IG93bmVkQnkoc291cmNlUGF0aCwgY2FuZGlkYXRlKSB8fCBvd25lZEJ5KGJ1aWxkUGF0aCwgY2FuZGlkYXRlKVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHR3byBhYnNvbHV0ZSByb290cyBvdmVybGFwIGluIGVpdGhlciBkaXJlY3Rpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gbGVmdCAtIEZpcnN0IHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmlnaHQgLSBTZWNvbmQgcm9vdC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSByb290cyBvdmVybGFwLlxuICovXG5mdW5jdGlvbiBwYXRoc092ZXJsYXAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPT0gcmlnaHQgfHwgb3duZWRCeShsZWZ0LCByaWdodCkgfHwgb3duZWRCeShyaWdodCwgbGVmdClcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIG9uZSBtb25vdG9uaWMgZHVyYXRpb24gb2JzZXJ2YXRpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kZWRBdCAtIEVuZCBvYnNlcnZhdGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydGVkQXQgLSBTdGFydCBvYnNlcnZhdGlvbi5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IEZpbml0ZSBub24tbmVnYXRpdmUgZHVyYXRpb24uXG4gKi9cbmZ1bmN0aW9uIGVsYXBzZWQoZW5kZWRBdCwgc3RhcnRlZEF0KSB7XG4gIGNvbnN0IGR1cmF0aW9uID0gZW5kZWRBdCAtIHN0YXJ0ZWRBdFxuXG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUoZHVyYXRpb24pICYmIGR1cmF0aW9uID49IDAgPyBkdXJhdGlvbiA6IDBcbn1cblxuLyoqXG4gKiBUaHJvd3Mgb25lIGNvbXBpbGVyLW91dHB1dCBpbnNwZWN0aW9uIGRpYWdub3N0aWMuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIEZhaWx1cmUgZGV0YWlsLlxuICogQHBhcmFtIHt1bmtub3dufSBbY2F1c2VdIC0gT3B0aW9uYWwgdW5kZXJseWluZyBmYWlsdXJlLlxuICogQHJldHVybnMge25ldmVyfSBBbHdheXMgdGhyb3dzLlxuICovXG5mdW5jdGlvbiBvdXRwdXRGYWlsdXJlKG1lc3NhZ2UsIGNhdXNlKSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgIGNhdXNlOiBjYXVzZSBpbnN0YW5jZW9mIEVycm9yID8gY2F1c2UgOiB1bmRlZmluZWQsXG4gICAgY29kZTogXCJUQVJHRVRfQ0hFQ0tfT1VUUFVUX0lOVkFMSURcIixcbiAgICBsYW5ndWFnZTogXCJjaGVja1wiLFxuICAgIG1lc3NhZ2VcbiAgfSlcbn1cblxuLyoqXG4gKiBUaHJvd3Mgb25lIGludmFsaWQtcGxhbiBkaWFnbm9zdGljLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBGYWlsdXJlIGRldGFpbC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbdGFyZ2V0XSAtIFRhcmdldCBkaWFnbm9zdGljIGlkZW50aXR5LlxuICogQHBhcmFtIHt1bmtub3dufSBbY2F1c2VdIC0gT3B0aW9uYWwgdW5kZXJseWluZyBmYWlsdXJlLlxuICogQHJldHVybnMge25ldmVyfSBBbHdheXMgdGhyb3dzLlxuICovXG5mdW5jdGlvbiBpbnZhbGlkUGxhbihtZXNzYWdlLCB0YXJnZXQgPSBcImNoZWNrXCIsIGNhdXNlKSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgIGNhdXNlOiBjYXVzZSBpbnN0YW5jZW9mIEVycm9yID8gY2F1c2UgOiB1bmRlZmluZWQsXG4gICAgY29kZTogXCJJTlZBTElEX1RBUkdFVF9DSEVDS19QTEFOXCIsXG4gICAgbGFuZ3VhZ2U6IHRhcmdldCxcbiAgICBtZXNzYWdlXG4gIH0pXG59XG5cbi8qKlxuICogQ2hlY2tzIGZvciBhbiBvcmRpbmFyeSBvYmplY3QtcHJvdG90eXBlIHJlY29yZC5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBDYW5kaWRhdGUgdmFsdWUuXG4gKiBAcmV0dXJucyB7dmFsdWUgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj59IFdoZXRoZXIgdGhlIHZhbHVlIGlzIGEgcGxhaW4gb2JqZWN0LlxuICovXG5mdW5jdGlvbiBpc1BsYWluT2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gXCJvYmplY3RcIiAmJiB2YWx1ZSAhPSBudWxsICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpID09IE9iamVjdC5wcm90b3R5cGVcbn1cblxuLyoqXG4gKiBDaGVja3MgZm9yIGFuIG93bi1wcm9wZXJ0eSBzdHJpbmctZGF0YSByZWNvcmQgd2l0aCBhbiBvcmRpbmFyeSBvciBudWxsIHByb3RvdHlwZS5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBDYW5kaWRhdGUgdmFsdWUuXG4gKiBAcmV0dXJucyB7dmFsdWUgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj59IFdoZXRoZXIgdGhlIHZhbHVlIGlzIGEgcGxhaW4gZGF0YSByZWNvcmQuXG4gKi9cbmZ1bmN0aW9uIGlzUGxhaW5SZWNvcmQodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPSBcIm9iamVjdFwiIHx8IHZhbHVlID09IG51bGwgfHwgQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiBmYWxzZVxuICBjb25zdCBwcm90b3R5cGUgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpXG5cbiAgaWYgKHByb3RvdHlwZSAhPT0gT2JqZWN0LnByb3RvdHlwZSAmJiBwcm90b3R5cGUgIT09IG51bGwpIHJldHVybiBmYWxzZVxuICByZXR1cm4gUmVmbGVjdC5vd25LZXlzKHZhbHVlKS5ldmVyeShrZXkgPT4ge1xuICAgIGlmICh0eXBlb2Yga2V5ICE9IFwic3RyaW5nXCIpIHJldHVybiBmYWxzZVxuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHZhbHVlLCBrZXkpXG5cbiAgICByZXR1cm4gZGVzY3JpcHRvciAhPSB1bmRlZmluZWQgJiYgZGVzY3JpcHRvci5lbnVtZXJhYmxlICYmIFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yICYmIHR5cGVvZiBkZXNjcmlwdG9yLnZhbHVlID09IFwic3RyaW5nXCJcbiAgfSlcbn1cblxuLyoqXG4gKiBDaGVja3Mgb25lIGNsb3NlZCBvYmplY3Qta2V5IHNldC5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IHZhbHVlIC0gQ2FuZGlkYXRlIHJlY29yZC5cbiAqIEBwYXJhbSB7c3RyaW5nW119IGtleXMgLSBFeGFjdCBhbGxvd2VkIGtleXMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUga2V5IHNldHMgbWF0Y2guXG4gKi9cbmZ1bmN0aW9uIGhhc0V4YWN0S2V5cyh2YWx1ZSwga2V5cykge1xuICByZXR1cm4gT2JqZWN0LmtleXModmFsdWUpLnNvcnQoKS5qb2luKFwiXFwwXCIpID09IFsuLi5rZXlzXS5zb3J0KCkuam9pbihcIlxcMFwiKVxufVxuIl19
|