UNPKG

@tricoteuses/assemblee

Version:

Retrieve, clean up & handle French Assemblée nationale's open data

251 lines (250 loc) 35.1 kB
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } import fs from "fs-extra"; import commandLineArgs from "command-line-args"; import commandLineUsage from "command-line-usage"; import { load, getFiles, GetFileNotFoundError } from "../file_systems.mjs"; import { SchemaBugs } from "../../src/bugs/index.mjs"; import * as git from "../../src/git.mjs"; import { validDataset, getDatasets, getSchemas, datasetDirectorySchema, diffUpstream, masterUrl } from "../../src/datasets.mjs"; function parseArgs(argv) { const optionsDefinitions = [{ description: "pathname to the directory containing the dataset", defaultOption: true, name: "data", type: String }, { description: "pathname to the directory containing the HTML comptes rendus de seance", name: "cr", type: String }, { description: "pathname to the directory to commit", name: "commit", type: String }, { description: "only consider this bug", name: "bug", type: String }, { description: "pathname to the directory where the check outputs will be stored", name: "output", type: String }, { description: `dataset (possible values must include exactly one of ${getDatasets()})`, name: "dataset", type: String }, { description: `schema (possible values are ${getSchemas()})`, name: "schema", type: String }, { description: "directory in which bugs are found (default .)", name: "bugs-dir", type: String }, { description: "increase verbosity", name: "verbose", type: Boolean }, { description: "debug information", name: "debug", type: Boolean }, { description: "check", name: "check", type: Boolean }, { description: "fix", name: "fix", type: Boolean }, { name: "help", description: "Print this usage guide." }]; const sections = [{ header: "Cross check data consistency and fix problems", content: "" }, { header: "Options", optionList: optionsDefinitions }]; const options = commandLineArgs(optionsDefinitions, { argv: argv }); if (options.dataset) { if (!validDataset(options.dataset)) { console.error(`--dataset ${options.dataset}`); options.help = true; } } if (options.schema) { if (!getSchemas().includes(options.schema)) { console.error(`--schema ${options.schema}`); options.help = true; } } if (options.commit) { if (!fs.existsSync(options.commit)) { console.error(`${options.commit} does not exist`); options.help = true; } } if (options.debug) options.verbose = true; if ("help" in options) { const usage = commandLineUsage(sections); console.warn(usage); return null; } return options; } export class BugsHelper { constructor(options) { _defineProperty(this, "options", void 0); _defineProperty(this, "bugs", void 0); this.options = options; this.bugs = new SchemaBugs(this.options); } async check() { const analysis = {}; await this.bugs.preCheck(); if (this.options.verbose) console.log(`check ${this.options.data}`); for (const file of getFiles([this.options.data])) { const content = load(file); analysis[file] = await this.bugs.check(content, file); } await this.bugs.postCheck(analysis); await this.show(analysis); if (this.options.output) await this.store(analysis); return 0; } async show(analysis) { for (const filename of Object.keys(analysis)) { const bug = analysis[filename]; for (const name of Object.keys(bug)) { const result = bug[name]; if (result != null) { let log; if (result["status"] == "needs-fixing") { log = console.error; } else if (this.options.verbose) { log = console.log; } if (log != undefined) { log(`${name} finds ${filename} ${result["status"]}`); log(result["info"].join("\n")); } } } } } async store(analysis) { const name2reports = {}; for (const filename of Object.keys(analysis)) { const bug = analysis[filename]; for (const name of Object.keys(bug)) { if (!(name in name2reports)) name2reports[name] = {}; name2reports[name][filename] = bug[name]; } } for (const name of Object.keys(name2reports)) { const reports = name2reports[name]; const n = name.split("-")[1]; let lines = [`## Bug [${name}](https://git.en-root.org/tricoteuses/tricoteuses-assemblee-qa/issues/${Number(n)})`, `This report was created by the **check** function of [${name}](https://git.en-root.org/tricoteuses/tricoteuses-assemblee/-/blob/master/src/bugs/${name}.ts).`]; const status2lines = { "needs-fixing": [], "will-be-fixed": [], "already-fixed": [] }; for (const filename of Object.keys(reports)) { const report = reports[filename]; if (report == null || report["status"] == "ok") continue; if (!(report["status"] in status2lines)) console.error(`${filename} status ${report["status"]} unknown`); const status = report["status"]; let l = status2lines[status]; if (status == "will-be-fixed") l.push(`* ${diffUpstream(filename)}`);else l.push(`* ${masterUrl(filename)}`); for (const info of report["info"]) l.push(` * ${info}`); } for (const [status, label] of [["needs-fixing", "The following files must be fixed"], ["already-fixed", "The following files no longer need a fix"], ["will-be-fixed", "The following files have been successfully fixed"]]) { lines.push(`### ${label}`); lines = lines.concat(status2lines[status]); } const output = `${this.options.output}/${name}.md`; fs.writeFileSync(output, lines.join("\n"), { encoding: "utf8" }); } } async fix() { await this.bugs.preFix(); await this.bugs.fix(getFiles([this.options.data])); return 0; } async main() { if (this.options.check) return this.check();else return this.fix(); } } export async function checkoutFix(options) { const c = options.commit; if (c == undefined) return; const v = options.verbose; git.run(c, "checkout --quiet master", v); if (/tmp/.test(git.run(c, "branch", v))) git.run(c, "branch -D tmp", v); git.run(c, "checkout --quiet -b tmp master", v); if (/Merge bugfixes/.test(git.run(c, "log --oneline -1", v))) git.run(c, "revert --mainline 1 --no-edit HEAD", v); git.run(c, "merge --no-ff -m 'Merge upstream' upstream/uid", v); if (/bugfixes/.test(git.run(c, "branch", v))) git.run(c, "branch -D bugfixes", v); git.run(c, "checkout --quiet -b bugfixes", v); } export async function mergeFix(options) { const c = options.commit; if (c == undefined) return; const v = options.verbose; git.run(c, "checkout --quiet tmp", v); git.run(c, "merge --no-ff -m 'Merge bugfixes' bugfixes", v); git.run(c, "branch -D bugfixes", v); git.run(c, "checkout --quiet master", v); if (!git.test(c, "diff --quiet tmp master", v)) git.run(c, "merge --ff-only tmp", v); git.run(c, "branch -D tmp", v); } export async function main(argv) { const options = parseArgs(argv); if (options === null) return 1; let directorySchema = []; if (options.schema) { directorySchema = [[options.data, options.schema]]; } else if (options.dataset) { directorySchema = datasetDirectorySchema(options.dataset); } else { console.error("either --schema or --dataset is required"); return 1; } await checkoutFix(options); for (const d of directorySchema) { options.schema = d[1]; options.data = d[0]; if (options.debug) console.log(`working on ${options.data} with schema ${options.schema}`); let helper; try { helper = new BugsHelper(options); } catch (e) { if (!(e instanceof GetFileNotFoundError)) { throw e; } continue; } if (options.verbose) console.log(`working on files ${options.data} with schema ${options.schema}`); const status = await helper.main(); if (status != 0) return status; } await mergeFix(options); return 0; } /* istanbul ignore if */ if (process.argv[1].endsWith("bugs_helper.ts")) main(process.argv).then(exitCode => { process.exit(exitCode); }).catch(error => { console.error(error); process.exit(1); }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJmcyIsImNvbW1hbmRMaW5lQXJncyIsImNvbW1hbmRMaW5lVXNhZ2UiLCJsb2FkIiwiZ2V0RmlsZXMiLCJHZXRGaWxlTm90Rm91bmRFcnJvciIsIlNjaGVtYUJ1Z3MiLCJnaXQiLCJ2YWxpZERhdGFzZXQiLCJnZXREYXRhc2V0cyIsImdldFNjaGVtYXMiLCJkYXRhc2V0RGlyZWN0b3J5U2NoZW1hIiwiZGlmZlVwc3RyZWFtIiwibWFzdGVyVXJsIiwicGFyc2VBcmdzIiwiYXJndiIsIm9wdGlvbnNEZWZpbml0aW9ucyIsImRlc2NyaXB0aW9uIiwiZGVmYXVsdE9wdGlvbiIsIm5hbWUiLCJ0eXBlIiwiU3RyaW5nIiwiQm9vbGVhbiIsInNlY3Rpb25zIiwiaGVhZGVyIiwiY29udGVudCIsIm9wdGlvbkxpc3QiLCJvcHRpb25zIiwiZGF0YXNldCIsImNvbnNvbGUiLCJlcnJvciIsImhlbHAiLCJzY2hlbWEiLCJpbmNsdWRlcyIsImNvbW1pdCIsImV4aXN0c1N5bmMiLCJkZWJ1ZyIsInZlcmJvc2UiLCJ1c2FnZSIsIndhcm4iLCJCdWdzSGVscGVyIiwiY29uc3RydWN0b3IiLCJfZGVmaW5lUHJvcGVydHkiLCJidWdzIiwiY2hlY2siLCJhbmFseXNpcyIsInByZUNoZWNrIiwibG9nIiwiZGF0YSIsImZpbGUiLCJwb3N0Q2hlY2siLCJzaG93Iiwib3V0cHV0Iiwic3RvcmUiLCJmaWxlbmFtZSIsIk9iamVjdCIsImtleXMiLCJidWciLCJyZXN1bHQiLCJ1bmRlZmluZWQiLCJqb2luIiwibmFtZTJyZXBvcnRzIiwicmVwb3J0cyIsIm4iLCJzcGxpdCIsImxpbmVzIiwiTnVtYmVyIiwic3RhdHVzMmxpbmVzIiwicmVwb3J0Iiwic3RhdHVzIiwibCIsInB1c2giLCJpbmZvIiwibGFiZWwiLCJjb25jYXQiLCJ3cml0ZUZpbGVTeW5jIiwiZW5jb2RpbmciLCJmaXgiLCJwcmVGaXgiLCJtYWluIiwiY2hlY2tvdXRGaXgiLCJjIiwidiIsInJ1biIsInRlc3QiLCJtZXJnZUZpeCIsImRpcmVjdG9yeVNjaGVtYSIsImQiLCJoZWxwZXIiLCJlIiwicHJvY2VzcyIsImVuZHNXaXRoIiwidGhlbiIsImV4aXRDb2RlIiwiZXhpdCIsImNhdGNoIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmlwdHMvYnVnc19oZWxwZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gXCJmcy1leHRyYVwiXG5pbXBvcnQgY29tbWFuZExpbmVBcmdzIGZyb20gXCJjb21tYW5kLWxpbmUtYXJnc1wiXG5pbXBvcnQgY29tbWFuZExpbmVVc2FnZSBmcm9tIFwiY29tbWFuZC1saW5lLXVzYWdlXCJcbmltcG9ydCB7IGxvYWQsIGdldEZpbGVzLCBHZXRGaWxlTm90Rm91bmRFcnJvciB9IGZyb20gXCIuLi9maWxlX3N5c3RlbXNcIlxuaW1wb3J0IHsgU2NoZW1hQnVncyB9IGZyb20gXCIuLi8uLi9zcmMvYnVnc1wiXG5pbXBvcnQgKiBhcyBnaXQgZnJvbSBcIi4uLy4uL3NyYy9naXRcIlxuaW1wb3J0IHtcbiAgdmFsaWREYXRhc2V0LFxuICBnZXREYXRhc2V0cyxcbiAgZ2V0U2NoZW1hcyxcbiAgZGF0YXNldERpcmVjdG9yeVNjaGVtYSxcbiAgZGlmZlVwc3RyZWFtLFxuICBtYXN0ZXJVcmwsXG59IGZyb20gXCIuLi8uLi9zcmMvZGF0YXNldHNcIlxuXG5mdW5jdGlvbiBwYXJzZUFyZ3MoYXJndjogc3RyaW5nW10pOiBhbnkge1xuICBjb25zdCBvcHRpb25zRGVmaW5pdGlvbnMgPSBbXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwicGF0aG5hbWUgdG8gdGhlIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBkYXRhc2V0XCIsXG4gICAgICBkZWZhdWx0T3B0aW9uOiB0cnVlLFxuICAgICAgbmFtZTogXCJkYXRhXCIsXG4gICAgICB0eXBlOiBTdHJpbmcsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJwYXRobmFtZSB0byB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIEhUTUwgY29tcHRlcyByZW5kdXMgZGUgc2VhbmNlXCIsXG4gICAgICBuYW1lOiBcImNyXCIsXG4gICAgICB0eXBlOiBTdHJpbmcsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJwYXRobmFtZSB0byB0aGUgZGlyZWN0b3J5IHRvIGNvbW1pdFwiLFxuICAgICAgbmFtZTogXCJjb21taXRcIixcbiAgICAgIHR5cGU6IFN0cmluZyxcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIm9ubHkgY29uc2lkZXIgdGhpcyBidWdcIixcbiAgICAgIG5hbWU6IFwiYnVnXCIsXG4gICAgICB0eXBlOiBTdHJpbmcsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJwYXRobmFtZSB0byB0aGUgZGlyZWN0b3J5IHdoZXJlIHRoZSBjaGVjayBvdXRwdXRzIHdpbGwgYmUgc3RvcmVkXCIsXG4gICAgICBuYW1lOiBcIm91dHB1dFwiLFxuICAgICAgdHlwZTogU3RyaW5nLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IGBkYXRhc2V0IChwb3NzaWJsZSB2YWx1ZXMgbXVzdCBpbmNsdWRlIGV4YWN0bHkgb25lIG9mICR7Z2V0RGF0YXNldHMoKX0pYCxcbiAgICAgIG5hbWU6IFwiZGF0YXNldFwiLFxuICAgICAgdHlwZTogU3RyaW5nLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IGBzY2hlbWEgKHBvc3NpYmxlIHZhbHVlcyBhcmUgJHtnZXRTY2hlbWFzKCl9KWAsXG4gICAgICBuYW1lOiBcInNjaGVtYVwiLFxuICAgICAgdHlwZTogU3RyaW5nLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiZGlyZWN0b3J5IGluIHdoaWNoIGJ1Z3MgYXJlIGZvdW5kIChkZWZhdWx0IC4pXCIsXG4gICAgICBuYW1lOiBcImJ1Z3MtZGlyXCIsXG4gICAgICB0eXBlOiBTdHJpbmcsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJpbmNyZWFzZSB2ZXJib3NpdHlcIixcbiAgICAgIG5hbWU6IFwidmVyYm9zZVwiLFxuICAgICAgdHlwZTogQm9vbGVhbixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcImRlYnVnIGluZm9ybWF0aW9uXCIsXG4gICAgICBuYW1lOiBcImRlYnVnXCIsXG4gICAgICB0eXBlOiBCb29sZWFuLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiY2hlY2tcIixcbiAgICAgIG5hbWU6IFwiY2hlY2tcIixcbiAgICAgIHR5cGU6IEJvb2xlYW4sXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJmaXhcIixcbiAgICAgIG5hbWU6IFwiZml4XCIsXG4gICAgICB0eXBlOiBCb29sZWFuLFxuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogXCJoZWxwXCIsXG4gICAgICBkZXNjcmlwdGlvbjogXCJQcmludCB0aGlzIHVzYWdlIGd1aWRlLlwiLFxuICAgIH0sXG4gIF1cbiAgY29uc3Qgc2VjdGlvbnMgPSBbXG4gICAge1xuICAgICAgaGVhZGVyOiBcIkNyb3NzIGNoZWNrIGRhdGEgY29uc2lzdGVuY3kgYW5kIGZpeCBwcm9ibGVtc1wiLFxuICAgICAgY29udGVudDogXCJcIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGhlYWRlcjogXCJPcHRpb25zXCIsXG4gICAgICBvcHRpb25MaXN0OiBvcHRpb25zRGVmaW5pdGlvbnMsXG4gICAgfSxcbiAgXVxuICBjb25zdCBvcHRpb25zID0gY29tbWFuZExpbmVBcmdzKG9wdGlvbnNEZWZpbml0aW9ucywge1xuICAgIGFyZ3Y6IGFyZ3YsXG4gIH0pXG5cbiAgaWYgKG9wdGlvbnMuZGF0YXNldCkge1xuICAgIGlmICghdmFsaWREYXRhc2V0KG9wdGlvbnMuZGF0YXNldCkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYC0tZGF0YXNldCAke29wdGlvbnMuZGF0YXNldH1gKVxuICAgICAgb3B0aW9ucy5oZWxwID0gdHJ1ZVxuICAgIH1cbiAgfVxuXG4gIGlmIChvcHRpb25zLnNjaGVtYSkge1xuICAgIGlmICghZ2V0U2NoZW1hcygpLmluY2x1ZGVzKG9wdGlvbnMuc2NoZW1hKSkge1xuICAgICAgY29uc29sZS5lcnJvcihgLS1zY2hlbWEgJHtvcHRpb25zLnNjaGVtYX1gKVxuICAgICAgb3B0aW9ucy5oZWxwID0gdHJ1ZVxuICAgIH1cbiAgfVxuXG4gIGlmIChvcHRpb25zLmNvbW1pdCkge1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhvcHRpb25zLmNvbW1pdCkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYCR7b3B0aW9ucy5jb21taXR9IGRvZXMgbm90IGV4aXN0YClcbiAgICAgIG9wdGlvbnMuaGVscCA9IHRydWVcbiAgICB9XG4gIH1cblxuICBpZiAob3B0aW9ucy5kZWJ1Zykgb3B0aW9ucy52ZXJib3NlID0gdHJ1ZVxuXG4gIGlmIChcImhlbHBcIiBpbiBvcHRpb25zKSB7XG4gICAgY29uc3QgdXNhZ2UgPSBjb21tYW5kTGluZVVzYWdlKHNlY3Rpb25zKVxuICAgIGNvbnNvbGUud2Fybih1c2FnZSlcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIHJldHVybiBvcHRpb25zXG59XG5cbmV4cG9ydCBjbGFzcyBCdWdzSGVscGVyIHtcbiAgb3B0aW9uczogYW55XG4gIGJ1Z3M6IGFueVxuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IGFueSkge1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnNcbiAgICB0aGlzLmJ1Z3MgPSBuZXcgU2NoZW1hQnVncyh0aGlzLm9wdGlvbnMpXG4gIH1cblxuICBhc3luYyBjaGVjaygpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGFuYWx5c2lzOiBhbnkgPSB7fVxuICAgIGF3YWl0IHRoaXMuYnVncy5wcmVDaGVjaygpXG4gICAgaWYgKHRoaXMub3B0aW9ucy52ZXJib3NlKSBjb25zb2xlLmxvZyhgY2hlY2sgJHt0aGlzLm9wdGlvbnMuZGF0YX1gKVxuICAgIGZvciAoY29uc3QgZmlsZSBvZiBnZXRGaWxlcyhbdGhpcy5vcHRpb25zLmRhdGFdKSkge1xuICAgICAgY29uc3QgY29udGVudCA9IGxvYWQoZmlsZSlcbiAgICAgIGFuYWx5c2lzW2ZpbGVdID0gYXdhaXQgdGhpcy5idWdzLmNoZWNrKGNvbnRlbnQsIGZpbGUpXG4gICAgfVxuICAgIGF3YWl0IHRoaXMuYnVncy5wb3N0Q2hlY2soYW5hbHlzaXMpXG4gICAgYXdhaXQgdGhpcy5zaG93KGFuYWx5c2lzKVxuICAgIGlmICh0aGlzLm9wdGlvbnMub3V0cHV0KSBhd2FpdCB0aGlzLnN0b3JlKGFuYWx5c2lzKVxuICAgIHJldHVybiAwXG4gIH1cblxuICBhc3luYyBzaG93KGFuYWx5c2lzOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGZpbGVuYW1lIG9mIE9iamVjdC5rZXlzKGFuYWx5c2lzKSkge1xuICAgICAgY29uc3QgYnVnID0gYW5hbHlzaXNbZmlsZW5hbWVdXG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMoYnVnKSkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBidWdbbmFtZV1cbiAgICAgICAgaWYgKHJlc3VsdCAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IGxvZ1xuICAgICAgICAgIGlmIChyZXN1bHRbXCJzdGF0dXNcIl0gPT0gXCJuZWVkcy1maXhpbmdcIikge1xuICAgICAgICAgICAgbG9nID0gY29uc29sZS5lcnJvclxuICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgICAgICAgIGxvZyA9IGNvbnNvbGUubG9nXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChsb2cgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBsb2coYCR7bmFtZX0gZmluZHMgJHtmaWxlbmFtZX0gJHtyZXN1bHRbXCJzdGF0dXNcIl19YClcbiAgICAgICAgICAgIGxvZyhyZXN1bHRbXCJpbmZvXCJdLmpvaW4oXCJcXG5cIikpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc3RvcmUoYW5hbHlzaXM6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5hbWUycmVwb3J0czogYW55ID0ge31cbiAgICBmb3IgKGNvbnN0IGZpbGVuYW1lIG9mIE9iamVjdC5rZXlzKGFuYWx5c2lzKSkge1xuICAgICAgY29uc3QgYnVnID0gYW5hbHlzaXNbZmlsZW5hbWVdXG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMoYnVnKSkge1xuICAgICAgICBpZiAoIShuYW1lIGluIG5hbWUycmVwb3J0cykpIG5hbWUycmVwb3J0c1tuYW1lXSA9IHt9XG4gICAgICAgIG5hbWUycmVwb3J0c1tuYW1lXVtmaWxlbmFtZV0gPSBidWdbbmFtZV1cbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKG5hbWUycmVwb3J0cykpIHtcbiAgICAgIGNvbnN0IHJlcG9ydHMgPSBuYW1lMnJlcG9ydHNbbmFtZV1cbiAgICAgIGNvbnN0IG4gPSBuYW1lLnNwbGl0KFwiLVwiKVsxXVxuICAgICAgbGV0IGxpbmVzOiBhbnkgPSBbXG4gICAgICAgIGAjIyBCdWcgWyR7bmFtZX1dKGh0dHBzOi8vZ2l0LmVuLXJvb3Qub3JnL3RyaWNvdGV1c2VzL3RyaWNvdGV1c2VzLWFzc2VtYmxlZS1xYS9pc3N1ZXMvJHtOdW1iZXIoXG4gICAgICAgICAgbixcbiAgICAgICAgKX0pYCxcbiAgICAgICAgYFRoaXMgcmVwb3J0IHdhcyBjcmVhdGVkIGJ5IHRoZSAqKmNoZWNrKiogZnVuY3Rpb24gb2YgWyR7bmFtZX1dKGh0dHBzOi8vZ2l0LmVuLXJvb3Qub3JnL3RyaWNvdGV1c2VzL3RyaWNvdGV1c2VzLWFzc2VtYmxlZS8tL2Jsb2IvbWFzdGVyL3NyYy9idWdzLyR7bmFtZX0udHMpLmAsXG4gICAgICBdXG4gICAgICBjb25zdCBzdGF0dXMybGluZXM6IGFueSA9IHtcbiAgICAgICAgXCJuZWVkcy1maXhpbmdcIjogW10sXG4gICAgICAgIFwid2lsbC1iZS1maXhlZFwiOiBbXSxcbiAgICAgICAgXCJhbHJlYWR5LWZpeGVkXCI6IFtdLFxuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBmaWxlbmFtZSBvZiBPYmplY3Qua2V5cyhyZXBvcnRzKSkge1xuICAgICAgICBjb25zdCByZXBvcnQgPSByZXBvcnRzW2ZpbGVuYW1lXVxuICAgICAgICBpZiAocmVwb3J0ID09IG51bGwgfHwgcmVwb3J0W1wic3RhdHVzXCJdID09IFwib2tcIikgY29udGludWVcbiAgICAgICAgaWYgKCEocmVwb3J0W1wic3RhdHVzXCJdIGluIHN0YXR1czJsaW5lcykpXG4gICAgICAgICAgY29uc29sZS5lcnJvcihgJHtmaWxlbmFtZX0gc3RhdHVzICR7cmVwb3J0W1wic3RhdHVzXCJdfSB1bmtub3duYClcbiAgICAgICAgY29uc3Qgc3RhdHVzID0gcmVwb3J0W1wic3RhdHVzXCJdXG4gICAgICAgIGxldCBsID0gc3RhdHVzMmxpbmVzW3N0YXR1c11cbiAgICAgICAgaWYgKHN0YXR1cyA9PSBcIndpbGwtYmUtZml4ZWRcIikgbC5wdXNoKGAqICR7ZGlmZlVwc3RyZWFtKGZpbGVuYW1lKX1gKVxuICAgICAgICBlbHNlIGwucHVzaChgKiAke21hc3RlclVybChmaWxlbmFtZSl9YClcbiAgICAgICAgZm9yIChjb25zdCBpbmZvIG9mIHJlcG9ydFtcImluZm9cIl0pIGwucHVzaChgICAqICR7aW5mb31gKVxuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBbc3RhdHVzLCBsYWJlbF0gb2YgW1xuICAgICAgICBbXCJuZWVkcy1maXhpbmdcIiwgXCJUaGUgZm9sbG93aW5nIGZpbGVzIG11c3QgYmUgZml4ZWRcIl0sXG4gICAgICAgIFtcImFscmVhZHktZml4ZWRcIiwgXCJUaGUgZm9sbG93aW5nIGZpbGVzIG5vIGxvbmdlciBuZWVkIGEgZml4XCJdLFxuICAgICAgICBbXCJ3aWxsLWJlLWZpeGVkXCIsIFwiVGhlIGZvbGxvd2luZyBmaWxlcyBoYXZlIGJlZW4gc3VjY2Vzc2Z1bGx5IGZpeGVkXCJdLFxuICAgICAgXSkge1xuICAgICAgICBsaW5lcy5wdXNoKGAjIyMgJHtsYWJlbH1gKVxuICAgICAgICBsaW5lcyA9IGxpbmVzLmNvbmNhdChzdGF0dXMybGluZXNbc3RhdHVzXSlcbiAgICAgIH1cbiAgICAgIGNvbnN0IG91dHB1dCA9IGAke3RoaXMub3B0aW9ucy5vdXRwdXR9LyR7bmFtZX0ubWRgXG4gICAgICBmcy53cml0ZUZpbGVTeW5jKG91dHB1dCwgbGluZXMuam9pbihcIlxcblwiKSwge1xuICAgICAgICBlbmNvZGluZzogXCJ1dGY4XCIsXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZpeCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGF3YWl0IHRoaXMuYnVncy5wcmVGaXgoKVxuICAgIGF3YWl0IHRoaXMuYnVncy5maXgoZ2V0RmlsZXMoW3RoaXMub3B0aW9ucy5kYXRhXSkpXG4gICAgcmV0dXJuIDBcbiAgfVxuXG4gIGFzeW5jIG1haW4oKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBpZiAodGhpcy5vcHRpb25zLmNoZWNrKSByZXR1cm4gdGhpcy5jaGVjaygpXG4gICAgZWxzZSByZXR1cm4gdGhpcy5maXgoKVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjaGVja291dEZpeChvcHRpb25zOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYyA9IG9wdGlvbnMuY29tbWl0XG4gIGlmIChjID09IHVuZGVmaW5lZCkgcmV0dXJuXG4gIGNvbnN0IHYgPSBvcHRpb25zLnZlcmJvc2VcbiAgZ2l0LnJ1bihjLCBcImNoZWNrb3V0IC0tcXVpZXQgbWFzdGVyXCIsIHYpXG4gIGlmICgvdG1wLy50ZXN0KGdpdC5ydW4oYywgXCJicmFuY2hcIiwgdikpKSBnaXQucnVuKGMsIFwiYnJhbmNoIC1EIHRtcFwiLCB2KVxuICBnaXQucnVuKGMsIFwiY2hlY2tvdXQgLS1xdWlldCAtYiB0bXAgbWFzdGVyXCIsIHYpXG4gIGlmICgvTWVyZ2UgYnVnZml4ZXMvLnRlc3QoZ2l0LnJ1bihjLCBcImxvZyAtLW9uZWxpbmUgLTFcIiwgdikpKVxuICAgIGdpdC5ydW4oYywgXCJyZXZlcnQgLS1tYWlubGluZSAxIC0tbm8tZWRpdCBIRUFEXCIsIHYpXG4gIGdpdC5ydW4oYywgXCJtZXJnZSAtLW5vLWZmIC1tICdNZXJnZSB1cHN0cmVhbScgdXBzdHJlYW0vdWlkXCIsIHYpXG4gIGlmICgvYnVnZml4ZXMvLnRlc3QoZ2l0LnJ1bihjLCBcImJyYW5jaFwiLCB2KSkpXG4gICAgZ2l0LnJ1bihjLCBcImJyYW5jaCAtRCBidWdmaXhlc1wiLCB2KVxuICBnaXQucnVuKGMsIFwiY2hlY2tvdXQgLS1xdWlldCAtYiBidWdmaXhlc1wiLCB2KVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWVyZ2VGaXgob3B0aW9uczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGMgPSBvcHRpb25zLmNvbW1pdFxuICBpZiAoYyA9PSB1bmRlZmluZWQpIHJldHVyblxuICBjb25zdCB2ID0gb3B0aW9ucy52ZXJib3NlXG4gIGdpdC5ydW4oYywgXCJjaGVja291dCAtLXF1aWV0IHRtcFwiLCB2KVxuICBnaXQucnVuKGMsIFwibWVyZ2UgLS1uby1mZiAtbSAnTWVyZ2UgYnVnZml4ZXMnIGJ1Z2ZpeGVzXCIsIHYpXG4gIGdpdC5ydW4oYywgXCJicmFuY2ggLUQgYnVnZml4ZXNcIiwgdilcbiAgZ2l0LnJ1bihjLCBcImNoZWNrb3V0IC0tcXVpZXQgbWFzdGVyXCIsIHYpXG4gIGlmICghZ2l0LnRlc3QoYywgXCJkaWZmIC0tcXVpZXQgdG1wIG1hc3RlclwiLCB2KSlcbiAgICBnaXQucnVuKGMsIFwibWVyZ2UgLS1mZi1vbmx5IHRtcFwiLCB2KVxuICBnaXQucnVuKGMsIFwiYnJhbmNoIC1EIHRtcFwiLCB2KVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFpbihhcmd2OiBhbnkpOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCBvcHRpb25zID0gcGFyc2VBcmdzKGFyZ3YpXG4gIGlmIChvcHRpb25zID09PSBudWxsKSByZXR1cm4gMVxuICBsZXQgZGlyZWN0b3J5U2NoZW1hID0gW11cbiAgaWYgKG9wdGlvbnMuc2NoZW1hKSB7XG4gICAgZGlyZWN0b3J5U2NoZW1hID0gW1tvcHRpb25zLmRhdGEsIG9wdGlvbnMuc2NoZW1hXV1cbiAgfSBlbHNlIGlmIChvcHRpb25zLmRhdGFzZXQpIHtcbiAgICBkaXJlY3RvcnlTY2hlbWEgPSBkYXRhc2V0RGlyZWN0b3J5U2NoZW1hKG9wdGlvbnMuZGF0YXNldClcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKFwiZWl0aGVyIC0tc2NoZW1hIG9yIC0tZGF0YXNldCBpcyByZXF1aXJlZFwiKVxuICAgIHJldHVybiAxXG4gIH1cbiAgYXdhaXQgY2hlY2tvdXRGaXgob3B0aW9ucylcbiAgZm9yIChjb25zdCBkIG9mIGRpcmVjdG9yeVNjaGVtYSkge1xuICAgIG9wdGlvbnMuc2NoZW1hID0gZFsxXVxuICAgIG9wdGlvbnMuZGF0YSA9IGRbMF1cbiAgICBpZiAob3B0aW9ucy5kZWJ1ZylcbiAgICAgIGNvbnNvbGUubG9nKGB3b3JraW5nIG9uICR7b3B0aW9ucy5kYXRhfSB3aXRoIHNjaGVtYSAke29wdGlvbnMuc2NoZW1hfWApXG4gICAgbGV0IGhlbHBlclxuICAgIHRyeSB7XG4gICAgICBoZWxwZXIgPSBuZXcgQnVnc0hlbHBlcihvcHRpb25zKVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBHZXRGaWxlTm90Rm91bmRFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZVxuICAgICAgfVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMudmVyYm9zZSlcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBgd29ya2luZyBvbiBmaWxlcyAke29wdGlvbnMuZGF0YX0gd2l0aCBzY2hlbWEgJHtvcHRpb25zLnNjaGVtYX1gLFxuICAgICAgKVxuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGhlbHBlci5tYWluKClcbiAgICBpZiAoc3RhdHVzICE9IDApIHJldHVybiBzdGF0dXNcbiAgfVxuICBhd2FpdCBtZXJnZUZpeChvcHRpb25zKVxuICByZXR1cm4gMFxufVxuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbmlmIChwcm9jZXNzLmFyZ3ZbMV0uZW5kc1dpdGgoXCJidWdzX2hlbHBlci50c1wiKSlcbiAgbWFpbihwcm9jZXNzLmFyZ3YpXG4gICAgLnRoZW4oKGV4aXRDb2RlKSA9PiB7XG4gICAgICBwcm9jZXNzLmV4aXQoZXhpdENvZGUpXG4gICAgfSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICBjb25zb2xlLmVycm9yKGVycm9yKVxuICAgICAgcHJvY2Vzcy5leGl0KDEpXG4gICAgfSlcbiJdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsT0FBT0EsRUFBRSxNQUFNLFVBQVU7QUFDekIsT0FBT0MsZUFBZSxNQUFNLG1CQUFtQjtBQUMvQyxPQUFPQyxnQkFBZ0IsTUFBTSxvQkFBb0I7QUFBQSxTQUN4Q0MsSUFBSSxFQUFFQyxRQUFRLEVBQUVDLG9CQUFvQjtBQUFBLFNBQ3BDQyxVQUFVO0FBQUEsT0FDWixLQUFLQyxHQUFHO0FBQUEsU0FFYkMsWUFBWSxFQUNaQyxXQUFXLEVBQ1hDLFVBQVUsRUFDVkMsc0JBQXNCLEVBQ3RCQyxZQUFZLEVBQ1pDLFNBQVM7QUFHWCxTQUFTQyxTQUFTQSxDQUFDQyxJQUFjLEVBQU87RUFDdEMsTUFBTUMsa0JBQWtCLEdBQUcsQ0FDekI7SUFDRUMsV0FBVyxFQUFFLGtEQUFrRDtJQUMvREMsYUFBYSxFQUFFLElBQUk7SUFDbkJDLElBQUksRUFBRSxNQUFNO0lBQ1pDLElBQUksRUFBRUM7RUFDUixDQUFDLEVBQ0Q7SUFDRUosV0FBVyxFQUNULHdFQUF3RTtJQUMxRUUsSUFBSSxFQUFFLElBQUk7SUFDVkMsSUFBSSxFQUFFQztFQUNSLENBQUMs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