1 | import assert from "assert";
|
2 | import { proxy as fgChildProxy } from "demurgos-foreground-child";
|
3 | import findUp from "find-up";
|
4 | import fs from "fs";
|
5 | import { fromSysPath, toSysPath } from "furi";
|
6 | import sysPath from "path";
|
7 | import Exclude from "test-exclude";
|
8 | import vinylFs from "vinyl-fs";
|
9 | import yargs from "yargs";
|
10 | import { asyncDonePromise } from "./async-done-promise";
|
11 | import { fromGlob } from "./filter";
|
12 | import { getText as defaultGetText, getTextSyncFromSourceStore } from "./get-text";
|
13 | import { createReporter, reportStream, reportVinyl } from "./report";
|
14 | import { DEFAULT_REGISTRY } from "./reporter-registry";
|
15 | import { spawnInspected } from "./spawn-inspected";
|
16 | import { processCovsToIstanbul } from "./to-istanbul";
|
17 | import { VERSION } from "./version";
|
18 | const DEFAULT_GLOBS = [
|
19 | ...Exclude.defaultExclude.map((pattern) => `!${pattern}`),
|
20 | "**/*",
|
21 | ];
|
22 | const DEFAULT_WATERMARKS = Object.freeze({
|
23 | lines: [80, 95],
|
24 | functions: [80, 95],
|
25 | branches: [80, 95],
|
26 | statements: [80, 95],
|
27 | });
|
28 | // TODO: Fix yargs type definition
|
29 | const ARG_PARSER = yargs();
|
30 | ARG_PARSER
|
31 | .scriptName("c88")
|
32 | .version(VERSION)
|
33 | .usage("$0 [opts] [script] [opts]")
|
34 | .locale("en")
|
35 | .option("reporter", {
|
36 | alias: "r",
|
37 | describe: "coverage reporter(s) to use",
|
38 | default: "text",
|
39 | })
|
40 | .option("match", {
|
41 | alias: "m",
|
42 | default: DEFAULT_GLOBS,
|
43 | // tslint:disable-next-line:max-line-length
|
44 | describe: "a list of specific files and directories that should be matched, glob patterns are supported.",
|
45 | })
|
46 | .option("coverage-directory", {
|
47 | default: "coverage",
|
48 | describe: "directory to output coverage JSON and reports",
|
49 | })
|
50 | .pkgConf("c88")
|
51 | .demandCommand(1)
|
52 | .epilog("visit https://git.io/vHysA for list of available reporters");
|
53 | // tslint:disable:whitespace
|
54 | /**
|
55 | * Executes the c88 CLI
|
56 | *
|
57 | * @param args CLI arguments
|
58 | * @param cwd Current working directory
|
59 | * @param proc Current process
|
60 | */
|
61 | export async function execCli(args, cwd, proc) {
|
62 | const action = await getAction(args, cwd);
|
63 | switch (action.action) {
|
64 | case "message":
|
65 | process.stderr.write(Buffer.from(action.message));
|
66 | return action.error === undefined ? 0 : 1;
|
67 | case "run":
|
68 | return execRunAction(action, cwd, proc);
|
69 | default:
|
70 | throw new Error(`AssertionError: Unexpected \`action\`: ${action.action}`);
|
71 | }
|
72 | }
|
73 | function resolveConfig(fileConfig, cliConfig) {
|
74 | return {
|
75 | command: cliConfig.command,
|
76 | reporters: cliConfig.reporters !== undefined ? cliConfig.reporters : ["text"],
|
77 | globs: cliConfig.globs !== undefined ? cliConfig.globs : DEFAULT_GLOBS,
|
78 | waterMarks: fileConfig.waterMarks !== undefined ? fileConfig.waterMarks : DEFAULT_WATERMARKS,
|
79 | coverageDir: cliConfig.coverageDir !== undefined ? cliConfig.coverageDir : "coverage",
|
80 | };
|
81 | }
|
82 | async function execRunAction({ config }, cwd, proc) {
|
83 | const file = config.command[0];
|
84 | const args = config.command.slice(1);
|
85 | const filter = fromGlob({ patterns: config.globs, base: fromSysPath(cwd) });
|
86 | const subProcessExit = deferPromise();
|
87 | async function onRootProcess(inspectedProc) {
|
88 | const closeFn = await fgChildProxy(proc, inspectedProc);
|
89 | if (closeFn.signal !== null) {
|
90 | subProcessExit.reject(new Error(`Process killed by signal: ${closeFn.signal}`));
|
91 | }
|
92 | else {
|
93 | subProcessExit.resolve(closeFn.code);
|
94 | }
|
95 | }
|
96 | let processCovs;
|
97 | try {
|
98 | processCovs = await spawnInspected(file, args, { filter, onRootProcess });
|
99 | }
|
100 | catch (err) {
|
101 | proc.stderr.write(Buffer.from(`${err.toString()}\n`));
|
102 | return 1;
|
103 | }
|
104 | const exitCode = await subProcessExit.promise;
|
105 | try {
|
106 | const reporter = createReporter(DEFAULT_REGISTRY, config.reporters, { waterMarks: config.waterMarks });
|
107 | const resolvedCoverageDir = sysPath.join(cwd, config.coverageDir);
|
108 | const coverageDir = fromSysPath(resolvedCoverageDir);
|
109 | await report(reporter, processCovs, proc.stdout, coverageDir);
|
110 | return exitCode;
|
111 | }
|
112 | catch (err) {
|
113 | proc.stderr.write(Buffer.from(err.toString() + "\n"));
|
114 | return Math.max(1, exitCode);
|
115 | }
|
116 | }
|
117 | export async function report(reporter, processCovs, outStream, outDir, getText = defaultGetText) {
|
118 | const { coverageMap, sources } = await processCovsToIstanbul(processCovs, getText);
|
119 | const getSourcesSync = getTextSyncFromSourceStore(sources);
|
120 | const tasks = [];
|
121 | if (reporter.reportStream !== undefined) {
|
122 | const stream = reportStream(reporter, coverageMap, getSourcesSync);
|
123 | tasks.push(pipeData(stream, outStream));
|
124 | }
|
125 | if (reporter.reportVinyl !== undefined) {
|
126 | const stream = reportVinyl(reporter, coverageMap, getSourcesSync)
|
127 | .pipe(vinylFs.dest(toSysPath(outDir.href)));
|
128 | tasks.push(asyncDonePromise(() => stream));
|
129 | }
|
130 | await Promise.all(tasks);
|
131 | }
|
132 | export async function getAction(args, cwd) {
|
133 | const parsed = parseArgs(args);
|
134 | if (parsed.action !== "run") {
|
135 | return parsed;
|
136 | }
|
137 | const fileConfig = await readConfigFile(cwd);
|
138 | return {
|
139 | action: "run",
|
140 | config: resolveConfig(fileConfig, parsed.config),
|
141 | };
|
142 | }
|
143 | export function parseArgs(args) {
|
144 | // The yargs pure API is kinda strange to use (apart from requiring a callback):
|
145 | // The error can either be defined, `undefined` or `null`.
|
146 | // If it is defined or `null`, then `output` should be a non-empty string
|
147 | // intended to be written to stderr. `parsed` is defined but it should be
|
148 | // ignored in this case.
|
149 | // If `err` is `undefined`, then `output` is an empty string and `parsed`
|
150 | // contains the succesfully parsed args.
|
151 | // tslint:disable:variable-name
|
152 | let _err;
|
153 | let _parsed;
|
154 | let _output;
|
155 | let isParsed = false;
|
156 | ARG_PARSER.parse(args, (err, parsed, output) => {
|
157 | _err = err;
|
158 | _parsed = parsed;
|
159 | _output = output;
|
160 | isParsed = true;
|
161 | });
|
162 | assert(isParsed);
|
163 | const err = _err;
|
164 | const parsed = _parsed;
|
165 | const output = _output;
|
166 | if (err === null) {
|
167 | // Successfully parsed
|
168 | return {
|
169 | action: "run",
|
170 | config: {
|
171 | command: parsed._,
|
172 | reporters: Array.isArray(parsed.reporter) ? parsed.reporter : [parsed.reporter],
|
173 | globs: parsed.match,
|
174 | },
|
175 | };
|
176 | }
|
177 | else {
|
178 | return { action: "message", message: output, error: err };
|
179 | }
|
180 | }
|
181 | async function readConfigFile(_cwd) {
|
182 | const configPath = findUp.sync([".c88rc", ".c88rc.json"]);
|
183 | if (configPath === undefined) {
|
184 | return Object.create(null);
|
185 | }
|
186 | return JSON.parse(fs.readFileSync(configPath, "UTF-8"));
|
187 | }
|
188 | function deferPromise() {
|
189 | let resolve;
|
190 | let reject;
|
191 | const promise = new Promise((res, rej) => {
|
192 | resolve = res;
|
193 | reject = rej;
|
194 | });
|
195 | return { resolve: resolve, reject: reject, promise };
|
196 | }
|
197 | function pipeData(src, dest) {
|
198 | return new Promise((resolve, reject) => {
|
199 | src.on("data", chunk => dest.write(chunk));
|
200 | src.on("error", reject);
|
201 | src.on("end", resolve);
|
202 | });
|
203 | }
|
204 |
|
205 | //# sourceMappingURL=data:application/json;charset=utf8;base64,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LFNBQVMsRUFBRTtRQUM1QixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDNUI7SUFDRCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBVUQsU0FBUyxZQUFZO0lBQ25CLElBQUksT0FBMkIsQ0FBQztJQUNoQyxJQUFJLE1BQTZCLENBQUM7SUFDbEMsTUFBTSxPQUFPLEdBQWUsSUFBSSxPQUFPLENBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDdEQsT0FBTyxHQUFHLEdBQUcsQ0FBQztRQUNkLE1BQU0sR0FBRyxHQUFHLENBQUM7SUFDZixDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sRUFBQyxPQUFPLEVBQUUsT0FBUSxFQUFFLE1BQU0sRUFBRSxNQUFPLEVBQUUsT0FBTyxFQUFDLENBQUM7QUFDdkQsQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLEdBQTBCLEVBQUUsSUFBMkI7SUFDdkUsT0FBTyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUMzQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUMzQyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN4QixHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN6QixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJmaWxlIjoiY2xpLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5pbXBvcnQgY3AgZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IENsb3NlRm4gYXMgRmdDbG9zZUZuLCBwcm94eSBhcyBmZ0NoaWxkUHJveHkgfSBmcm9tIFwiZGVtdXJnb3MtZm9yZWdyb3VuZC1jaGlsZFwiO1xuaW1wb3J0IGZpbmRVcCBmcm9tIFwiZmluZC11cFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgZnJvbVN5c1BhdGgsIHRvU3lzUGF0aCB9IGZyb20gXCJmdXJpXCI7XG5pbXBvcnQgc3lzUGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IEV4Y2x1ZGUgZnJvbSBcInRlc3QtZXhjbHVkZVwiO1xuaW1wb3J0IHVybE1vZCBmcm9tIFwidXJsXCI7XG5pbXBvcnQgdmlueWxGcyBmcm9tIFwidmlueWwtZnNcIjtcbmltcG9ydCB5YXJncyBmcm9tIFwieWFyZ3NcIjtcbmltcG9ydCB7IGFzeW5jRG9uZVByb21pc2UgfSBmcm9tIFwiLi9hc3luYy1kb25lLXByb21pc2VcIjtcbmltcG9ydCB7IENvdmVyYWdlRmlsdGVyLCBmcm9tR2xvYiB9IGZyb20gXCIuL2ZpbHRlclwiO1xuaW1wb3J0IHsgR2V0VGV4dCwgZ2V0VGV4dCBhcyBkZWZhdWx0R2V0VGV4dCwgR2V0VGV4dFN5bmMsIGdldFRleHRTeW5jRnJvbVNvdXJjZVN0b3JlIH0gZnJvbSBcIi4vZ2V0LXRleHRcIjtcbmltcG9ydCB7IGNyZWF0ZVJlcG9ydGVyLCByZXBvcnRTdHJlYW0sIHJlcG9ydFZpbnlsIH0gZnJvbSBcIi4vcmVwb3J0XCI7XG5pbXBvcnQgeyBSZXBvcnRlciwgU3RyZWFtUmVwb3J0ZXIsIFZpbnlsUmVwb3J0ZXIgfSBmcm9tIFwiLi9yZXBvcnRlclwiO1xuaW1wb3J0IHsgREVGQVVMVF9SRUdJU1RSWSB9IGZyb20gXCIuL3JlcG9ydGVyLXJlZ2lzdHJ5XCI7XG5pbXBvcnQgeyBSaWNoUHJvY2Vzc0Nvdiwgc3Bhd25JbnNwZWN0ZWQgfSBmcm9tIFwiLi9zcGF3bi1pbnNwZWN0ZWRcIjtcbmltcG9ydCB7IHByb2Nlc3NDb3ZzVG9Jc3RhbmJ1bCB9IGZyb20gXCIuL3RvLWlzdGFuYnVsXCI7XG5pbXBvcnQgeyBWRVJTSU9OIH0gZnJvbSBcIi4vdmVyc2lvblwiO1xuXG5jb25zdCBERUZBVUxUX0dMT0JTOiBSZWFkb25seUFycmF5PHN0cmluZz4gPSBbXG4gIC4uLig8c3RyaW5nW10+IEV4Y2x1ZGUuZGVmYXVsdEV4Y2x1ZGUubWFwKChwYXR0ZXJuOiBzdHJpbmcpID0+IGAhJHtwYXR0ZXJufWApKSxcbiAgXCIqKi8qXCIsXG5dO1xuXG5pbnRlcmZhY2UgV2F0ZXJtYXJrcyB7XG4gIGxpbmVzOiBbbnVtYmVyLCBudW1iZXJdO1xuICBmdW5jdGlvbnM6IFtudW1iZXIsIG51bWJlcl07XG4gIGJyYW5jaGVzOiBbbnVtYmVyLCBudW1iZXJdO1xuICBzdGF0ZW1lbnRzOiBbbnVtYmVyLCBudW1iZXJdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVDb25maWcge1xuICByZXBvcnRlcnM/OiBSZWFkb25seUFycmF5PHN0cmluZz47XG4gIGdsb2JzPzogUmVhZG9ubHlBcnJheTxzdHJpbmc+O1xuICBjb3ZlcmFnZURpcj86IHN0cmluZztcbiAgd2F0ZXJNYXJrcz86IFdhdGVybWFya3M7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpQ29uZmlnIHtcbiAgcmVwb3J0ZXJzPzogUmVhZG9ubHlBcnJheTxzdHJpbmc+O1xuICBnbG9icz86IFJlYWRvbmx5QXJyYXk8c3RyaW5nPjtcbiAgY292ZXJhZ2VEaXI/OiBzdHJpbmc7XG4gIGNvbW1hbmQ6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZENvbmZpZyB7XG4gIHJlcG9ydGVyczogUmVhZG9ubHlBcnJheTxzdHJpbmc+O1xuICBnbG9iczogUmVhZG9ubHlBcnJheTxzdHJpbmc+O1xuICBjb3ZlcmFnZURpcjogc3RyaW5nO1xuICB3YXRlck1hcmtzOiBXYXRlcm1hcmtzO1xuICBjb21tYW5kOiBSZWFkb25seUFycmF5PHN0cmluZz47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVzc2FnZUFjdGlvbiB7XG4gIGFjdGlvbjogXCJtZXNzYWdlXCI7XG4gIG1lc3NhZ2U6IHN0cmluZztcbiAgZXJyb3I/OiBFcnJvcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSdW5BY3Rpb24ge1xuICBhY3Rpb246IFwicnVuXCI7XG4gIGNvbmZpZzogUmVzb2x2ZWRDb25maWc7XG59XG5cbmV4cG9ydCB0eXBlIENsaUFjdGlvbiA9IE1lc3NhZ2VBY3Rpb24gfCBSdW5BY3Rpb247XG5cbmV4cG9ydCB0eXBlIFBhcnNlQXJnc1Jlc3VsdCA9IE1lc3NhZ2VBY3Rpb24gfCB7YWN0aW9uOiBcInJ1blwiOyBjb25maWc6IENsaUNvbmZpZ307XG5cbmNvbnN0IERFRkFVTFRfV0FURVJNQVJLUzogV2F0ZXJtYXJrcyA9IE9iamVjdC5mcmVlemUoe1xuICBsaW5lczogWzgwLCA5NV0gYXMgW251bWJlciwgbnVtYmVyXSxcbiAgZnVuY3Rpb25zOiBbODAsIDk1XSBhcyBbbnVtYmVyLCBudW1iZXJdLFxuICBicmFuY2hlczogWzgwLCA5NV0gYXMgW251bWJlciwgbnVtYmVyXSxcbiAgc3RhdGVtZW50czogWzgwLCA5NV0gYXMgW251bWJlciwgbnVtYmVyXSxcbn0pO1xuXG4vLyBUT0RPOiBGaXggeWFyZ3MgdHlwZSBkZWZpbml0aW9uXG5jb25zdCBBUkdfUEFSU0VSOiB5YXJncy5Bcmd2ID0geWFyZ3MoKSBhcyBhbnk7XG5cbkFSR19QQVJTRVJcbiAgLnNjcmlwdE5hbWUoXCJjODhcIilcbiAgLnZlcnNpb24oVkVSU0lPTilcbiAgLnVzYWdlKFwiJDAgW29wdHNdIFtzY3JpcHRdIFtvcHRzXVwiKVxuICAubG9jYWxlKFwiZW5cIilcbiAgLm9wdGlvbihcInJlcG9ydGVyXCIsIHtcbiAgICBhbGlhczogXCJyXCIsXG4gICAgZGVzY3JpYmU6IFwiY292ZXJhZ2UgcmVwb3J0ZXIocykgdG8gdXNlXCIsXG4gICAgZGVmYXVsdDogXCJ0ZXh0XCIsXG4gIH0pXG4gIC5vcHRpb24oXCJtYXRjaFwiLCB7XG4gICAgYWxpYXM6IFwibVwiLFxuICAgIGRlZmF1bHQ6IERFRkFVTFRfR0xPQlMsXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aFxuICAgIGRlc2NyaWJlOiBcImEgbGlzdCBvZiBzcGVjaWZpYyBmaWxlcyBhbmQgZGlyZWN0b3JpZXMgdGhhdCBzaG91bGQgYmUgbWF0Y2hlZCwgZ2xvYiBwYXR0ZXJucyBhcmUgc3VwcG9ydGVkLlwiLFxuICB9KVxuICAub3B0aW9uKFwiY292ZXJhZ2UtZGlyZWN0b3J5XCIsIHtcbiAgICBkZWZhdWx0OiBcImNvdmVyYWdlXCIsXG4gICAgZGVzY3JpYmU6IFwiZGlyZWN0b3J5IHRvIG91dHB1dCBjb3ZlcmFnZSBKU09OIGFuZCByZXBvcnRzXCIsXG4gIH0pXG4gIC5wa2dDb25mKFwiYzg4XCIpXG4gIC5kZW1hbmRDb21tYW5kKDEpXG4gIC5lcGlsb2coXCJ2aXNpdCBodHRwczovL2dpdC5pby92SHlzQSBmb3IgbGlzdCBvZiBhdmFpbGFibGUgcmVwb3J0ZXJzXCIpO1xuXG4vLyB0c2xpbnQ6ZGlzYWJsZTp3aGl0ZXNwYWNlXG5cbi8qKlxuICogRXhlY3V0ZXMgdGhlIGM4OCBDTElcbiAqXG4gKiBAcGFyYW0gYXJncyBDTEkgYXJndW1lbnRzXG4gKiBAcGFyYW0gY3dkIEN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnlcbiAqIEBwYXJhbSBwcm9jIEN1cnJlbnQgcHJvY2Vzc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY0NsaShhcmdzOiBzdHJpbmdbXSwgY3dkOiBzdHJpbmcsIHByb2M6IE5vZGVKUy5Qcm9jZXNzKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgY29uc3QgYWN0aW9uOiBDbGlBY3Rpb24gPSBhd2FpdCBnZXRBY3Rpb24oYXJncywgY3dkKTtcblxuICBzd2l0Y2ggKGFjdGlvbi5hY3Rpb24pIHtcbiAgICBjYXNlIFwibWVzc2FnZVwiOlxuICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoQnVmZmVyLmZyb20oYWN0aW9uLm1lc3NhZ2UpKTtcbiAgICAgIHJldHVybiBhY3Rpb24uZXJyb3IgPT09IHVuZGVmaW5lZCA/IDAgOiAxO1xuICAgIGNhc2UgXCJydW5cIjpcbiAgICAgIHJldHVybiBleGVjUnVuQWN0aW9uKGFjdGlvbiwgY3dkLCBwcm9jKTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBc3NlcnRpb25FcnJvcjogVW5leHBlY3RlZCBcXGBhY3Rpb25cXGA6ICR7KGFjdGlvbiBhcyBhbnkpLmFjdGlvbn1gKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZXNvbHZlQ29uZmlnKGZpbGVDb25maWc6IEZpbGVDb25maWcsIGNsaUNvbmZpZzogQ2xpQ29uZmlnKTogUmVzb2x2ZWRDb25maWcge1xuICByZXR1cm4ge1xuICAgIGNvbW1hbmQ6IGNsaUNvbmZpZy5jb21tYW5kLFxuICAgIHJlcG9ydGVyczogY2xpQ29uZmlnLnJlcG9ydGVycyAhPT0gdW5kZWZpbmVkID8gY2xpQ29uZmlnLnJlcG9ydGVycyA6IFtcInRleHRcIl0sXG4gICAgZ2xvYnM6IGNsaUNvbmZpZy5nbG9icyAhPT0gdW5kZWZpbmVkID8gY2xpQ29uZmlnLmdsb2JzIDogREVGQVVMVF9HTE9CUyxcbiAgICB3YXRlck1hcmtzOiBmaWxlQ29uZmlnLndhdGVyTWFya3MgIT09IHVuZGVmaW5lZCA/IGZpbGVDb25maWcud2F0ZXJNYXJrcyA6IERFRkFVTFRfV0FURVJNQVJLUyxcbiAgICBjb3ZlcmFnZURpcjogY2xpQ29uZmlnLmNvdmVyYWdlRGlyICE9PSB1bmRlZmluZWQgPyBjbGlDb25maWcuY292ZXJhZ2VEaXIgOiBcImNvdmVyYWdlXCIsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGV4ZWNSdW5BY3Rpb24oe2NvbmZpZ306IFJ1bkFjdGlvbiwgY3dkOiBzdHJpbmcsIHByb2M6IE5vZGVKUy5Qcm9jZXNzKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgY29uc3QgZmlsZTogc3RyaW5nID0gY29uZmlnLmNvbW1hbmRbMF07XG4gIGNvbnN0IGFyZ3M6IHN0cmluZ1tdID0gY29uZmlnLmNvbW1hbmQuc2xpY2UoMSk7XG4gIGNvbnN0IGZpbHRlcjogQ292ZXJhZ2VGaWx0ZXIgPSBmcm9tR2xvYih7cGF0dGVybnM6IGNvbmZpZy5nbG9icywgYmFzZTogZnJvbVN5c1BhdGgoY3dkKX0pO1xuXG4gIGNvbnN0IHN1YlByb2Nlc3NFeGl0OiBEZWZlcnJlZFByb21pc2U8bnVtYmVyPiA9IGRlZmVyUHJvbWlzZSgpO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIG9uUm9vdFByb2Nlc3MoaW5zcGVjdGVkUHJvYzogY3AuQ2hpbGRQcm9jZXNzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2xvc2VGbjogRmdDbG9zZUZuID0gYXdhaXQgZmdDaGlsZFByb3h5KHByb2MsIGluc3BlY3RlZFByb2MpO1xuICAgIGlmIChjbG9zZUZuLnNpZ25hbCAhPT0gbnVsbCkge1xuICAgICAgc3ViUHJvY2Vzc0V4aXQucmVqZWN0KG5ldyBFcnJvcihgUHJvY2VzcyBraWxsZWQgYnkgc2lnbmFsOiAke2Nsb3NlRm4uc2lnbmFsfWApKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3ViUHJvY2Vzc0V4aXQucmVzb2x2ZShjbG9zZUZuLmNvZGUhKTtcbiAgICB9XG4gIH1cblxuICBsZXQgcHJvY2Vzc0NvdnM6IFJpY2hQcm9jZXNzQ292W107XG4gIHRyeSB7XG4gICAgcHJvY2Vzc0NvdnMgPSBhd2FpdCBzcGF3bkluc3BlY3RlZChmaWxlLCBhcmdzLCB7ZmlsdGVyLCBvblJvb3RQcm9jZXNzfSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHByb2Muc3RkZXJyLndyaXRlKEJ1ZmZlci5mcm9tKGAke2Vyci50b1N0cmluZygpfVxcbmApKTtcbiAgICByZXR1cm4gMTtcbiAgfVxuICBjb25zdCBleGl0Q29kZTogbnVtYmVyID0gYXdhaXQgc3ViUHJvY2Vzc0V4aXQucHJvbWlzZTtcblxuICB0cnkge1xuICAgIGNvbnN0IHJlcG9ydGVyOiBSZXBvcnRlciA9IGNyZWF0ZVJlcG9ydGVyKERFRkFVTFRfUkVHSVNUUlksIGNvbmZpZy5yZXBvcnRlcnMsIHt3YXRlck1hcmtzOiBjb25maWcud2F0ZXJNYXJrc30pO1xuICAgIGNvbnN0IHJlc29sdmVkQ292ZXJhZ2VEaXI6IHN0cmluZyA9IHN5c1BhdGguam9pbihjd2QsIGNvbmZpZy5jb3ZlcmFnZURpcik7XG4gICAgY29uc3QgY292ZXJhZ2VEaXI6IHVybE1vZC5VUkwgPSBmcm9tU3lzUGF0aChyZXNvbHZlZENvdmVyYWdlRGlyKTtcbiAgICBhd2FpdCByZXBvcnQocmVwb3J0ZXIsIHByb2Nlc3NDb3ZzLCBwcm9jLnN0ZG91dCwgY292ZXJhZ2VEaXIpO1xuICAgIHJldHVybiBleGl0Q29kZTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcHJvYy5zdGRlcnIud3JpdGUoQnVmZmVyLmZyb20oZXJyLnRvU3RyaW5nKCkgKyBcIlxcblwiKSk7XG4gICAgcmV0dXJuIE1hdGgubWF4KDEsIGV4aXRDb2RlKTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVwb3J0KFxuICByZXBvcnRlcjogUmVwb3J0ZXIsXG4gIHByb2Nlc3NDb3ZzOiBSZWFkb25seUFycmF5PFJpY2hQcm9jZXNzQ292PixcbiAgb3V0U3RyZWFtOiBOb2RlSlMuV3JpdGFibGVTdHJlYW0sXG4gIG91dERpcjogUmVhZG9ubHk8dXJsTW9kLlVSTD4sXG4gIGdldFRleHQ6IEdldFRleHQgPSBkZWZhdWx0R2V0VGV4dCxcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7Y292ZXJhZ2VNYXAsIHNvdXJjZXN9ID0gYXdhaXQgcHJvY2Vzc0NvdnNUb0lzdGFuYnVsKHByb2Nlc3NDb3ZzLCBnZXRUZXh0KTtcbiAgY29uc3QgZ2V0U291cmNlc1N5bmM6IEdldFRleHRTeW5jID0gZ2V0VGV4dFN5bmNGcm9tU291cmNlU3RvcmUoc291cmNlcyk7XG5cbiAgY29uc3QgdGFza3M6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuICBpZiAocmVwb3J0ZXIucmVwb3J0U3RyZWFtICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCBzdHJlYW06IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSA9IHJlcG9ydFN0cmVhbShyZXBvcnRlciBhcyBTdHJlYW1SZXBvcnRlciwgY292ZXJhZ2VNYXAsIGdldFNvdXJjZXNTeW5jKTtcbiAgICB0YXNrcy5wdXNoKHBpcGVEYXRhKHN0cmVhbSwgb3V0U3RyZWFtKSk7XG4gIH1cbiAgaWYgKHJlcG9ydGVyLnJlcG9ydFZpbnlsICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCBzdHJlYW06IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSA9IHJlcG9ydFZpbnlsKHJlcG9ydGVyIGFzIFZpbnlsUmVwb3J0ZXIsIGNvdmVyYWdlTWFwLCBnZXRTb3VyY2VzU3luYylcbiAgICAgIC5waXBlKHZpbnlsRnMuZGVzdCh0b1N5c1BhdGgob3V0RGlyLmhyZWYpKSk7XG4gICAgdGFza3MucHVzaChhc3luY0RvbmVQcm9taXNlKCgpID0+IHN0cmVhbSkpO1xuICB9XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGwodGFza3MpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QWN0aW9uKGFyZ3M6IHN0cmluZ1tdLCBjd2Q6IHN0cmluZyk6IFByb21pc2U8Q2xpQWN0aW9uPiB7XG4gIGNvbnN0IHBhcnNlZDogUGFyc2VBcmdzUmVzdWx0ID0gcGFyc2VBcmdzKGFyZ3MpO1xuICBpZiAocGFyc2VkLmFjdGlvbiAhPT0gXCJydW5cIikge1xuICAgIHJldHVybiBwYXJzZWQ7XG4gIH1cbiAgY29uc3QgZmlsZUNvbmZpZzogRmlsZUNvbmZpZyA9IGF3YWl0IHJlYWRDb25maWdGaWxlKGN3ZCk7XG4gIHJldHVybiB7XG4gICAgYWN0aW9uOiBcInJ1blwiLFxuICAgIGNvbmZpZzogcmVzb2x2ZUNvbmZpZyhmaWxlQ29uZmlnLCBwYXJzZWQuY29uZmlnKSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQXJncyhhcmdzOiBzdHJpbmdbXSk6IFBhcnNlQXJnc1Jlc3VsdCB7XG4gIC8vIFRoZSB5YXJncyBwdXJlIEFQSSBpcyBraW5kYSBzdHJhbmdlIHRvIHVzZSAoYXBhcnQgZnJvbSByZXF1aXJpbmcgYSBjYWxsYmFjayk6XG4gIC8vIFRoZSBlcnJvciBjYW4gZWl0aGVyIGJlIGRlZmluZWQsIGB1bmRlZmluZWRgIG9yIGBudWxsYC5cbiAgLy8gSWYgaXQgaXMgZGVmaW5lZCBvciBgbnVsbGAsIHRoZW4gYG91dHB1dGAgc2hvdWxkIGJlIGEgbm9uLWVtcHR5IHN0cmluZ1xuICAvLyBpbnRlbmRlZCB0byBiZSB3cml0dGVuIHRvIHN0ZGVyci4gYHBhcnNlZGAgaXMgZGVmaW5lZCBidXQgaXQgc2hvdWxkIGJlXG4gIC8vIGlnbm9yZWQgaW4gdGhpcyBjYXNlLlxuICAvLyBJZiBgZXJyYCBpcyBgdW5kZWZpbmVkYCwgdGhlbiBgb3V0cHV0YCBpcyBhbiBlbXB0eSBzdHJpbmcgYW5kIGBwYXJzZWRgXG4gIC8vIGNvbnRhaW5zIHRoZSBzdWNjZXNmdWxseSBwYXJzZWQgYXJncy5cbiAgLy8gdHNsaW50OmRpc2FibGU6dmFyaWFibGUtbmFtZVxuICBsZXQgX2VycjogRXJyb3IgfCB1bmRlZmluZWQgfCBudWxsO1xuICBsZXQgX3BhcnNlZDogYW55O1xuICBsZXQgX291dHB1dDogc3RyaW5nO1xuICBsZXQgaXNQYXJzZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQVJHX1BBUlNFUi5wYXJzZShhcmdzLCAoZXJyOiBFcnJvciB8IHVuZGVmaW5lZCB8IG51bGwsIHBhcnNlZDogYW55LCBvdXRwdXQ6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgIF9lcnIgPSBlcnI7XG4gICAgX3BhcnNlZCA9IHBhcnNlZDtcbiAgICBfb3V0cHV0ID0gb3V0cHV0O1xuICAgIGlzUGFyc2VkID0gdHJ1ZTtcbiAgfSk7XG4gIGFzc2VydChpc1BhcnNlZCk7XG4gIGNvbnN0IGVycjogRXJyb3IgfCB1bmRlZmluZWQgfCBudWxsID0gX2VyciE7XG4gIGNvbnN0IHBhcnNlZDogYW55ID0gX3BhcnNlZCE7XG4gIGNvbnN0IG91dHB1dDogc3RyaW5nID0gX291dHB1dCE7XG4gIGlmIChlcnIgPT09IG51bGwpIHtcbiAgICAvLyBTdWNjZXNzZnVsbHkgcGFyc2VkXG4gICAgcmV0dXJuIHtcbiAgICAgIGFjdGlvbjogXCJydW5cIixcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBjb21tYW5kOiBwYXJzZWQuXyxcbiAgICAgICAgcmVwb3J0ZXJzOiBBcnJheS5pc0FycmF5KHBhcnNlZC5yZXBvcnRlcikgPyBwYXJzZWQucmVwb3J0ZXIgOiBbcGFyc2VkLnJlcG9ydGVyXSxcbiAgICAgICAgZ2xvYnM6IHBhcnNlZC5tYXRjaCxcbiAgICAgIH0sXG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4ge2FjdGlvbjogXCJtZXNzYWdlXCIsIG1lc3NhZ2U6IG91dHB1dCwgZXJyb3I6IGVycn07XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZENvbmZpZ0ZpbGUoX2N3ZDogc3RyaW5nKTogUHJvbWlzZTxGaWxlQ29uZmlnPiB7XG4gIGNvbnN0IGNvbmZpZ1BhdGg6IHN0cmluZyB8IHVuZGVmaW5lZCA9IGZpbmRVcC5zeW5jKFtcIi5jODhyY1wiLCBcIi5jODhyYy5qc29uXCJdKTtcbiAgaWYgKGNvbmZpZ1BhdGggPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB9XG4gIHJldHVybiBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjb25maWdQYXRoLCBcIlVURi04XCIpKTtcbn1cblxuaW50ZXJmYWNlIERlZmVycmVkUHJvbWlzZTxUPiB7XG4gIHByb21pc2U6IFByb21pc2U8VD47XG5cbiAgcmVzb2x2ZSh2YWx1ZTogVCk6IHZvaWQ7XG5cbiAgcmVqZWN0KHJlYXNvbjogYW55KTogdm9pZDtcbn1cblxuZnVuY3Rpb24gZGVmZXJQcm9taXNlPFQ+KCk6IERlZmVycmVkUHJvbWlzZTxUPiB7XG4gIGxldCByZXNvbHZlOiAodmFsdWU6IFQpID0+IHZvaWQ7XG4gIGxldCByZWplY3Q6IChyZWFzb246IGFueSkgPT4gdm9pZDtcbiAgY29uc3QgcHJvbWlzZTogUHJvbWlzZTxUPiA9IG5ldyBQcm9taXNlPFQ+KChyZXMsIHJlaikgPT4ge1xuICAgIHJlc29sdmUgPSByZXM7XG4gICAgcmVqZWN0ID0gcmVqO1xuICB9KTtcbiAgcmV0dXJuIHtyZXNvbHZlOiByZXNvbHZlISwgcmVqZWN0OiByZWplY3QhLCBwcm9taXNlfTtcbn1cblxuZnVuY3Rpb24gcGlwZURhdGEoc3JjOiBOb2RlSlMuUmVhZGFibGVTdHJlYW0sIGRlc3Q6IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHNyYy5vbihcImRhdGFcIiwgY2h1bmsgPT4gZGVzdC53cml0ZShjaHVuaykpO1xuICAgIHNyYy5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgc3JjLm9uKFwiZW5kXCIsIHJlc29sdmUpO1xuICB9KTtcbn1cbiJdLCJzb3VyY2VSb290IjoiIn0=
|