@tricoteuses/assemblee
Version:
Retrieve, clean up & handle French Assemblée nationale's open data
249 lines (239 loc) • 34.5 kB
JavaScript
;
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.symbol.iterator.js");
require("core-js/modules/es.array.from.js");
require("core-js/modules/es.array.is-array.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.array.slice.js");
require("core-js/modules/es.date.to-string.js");
require("core-js/modules/es.function.name.js");
require("core-js/modules/es.regexp.to-string.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
require("core-js/modules/es.array.for-each.js");
require("core-js/modules/es.array.join.js");
require("core-js/modules/es.date.to-json.js");
require("core-js/modules/es.object.keys.js");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.string.replace.js");
var _commandLineArgs = _interopRequireDefault(require("command-line-args"));
var _fsExtra = _interopRequireDefault(require("fs-extra"));
var _path = _interopRequireDefault(require("path"));
var _deepObjectDiff = require("deep-object-diff");
var _datasets = require("../datasets");
var _file_systems = require("../file_systems");
var _cli_helpers = require("./shared/cli_helpers");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var diffedAmendments = [];
var newAmendments = [];
var optionsDefinitions = [_cli_helpers.silentOption, _cli_helpers.verboseOption, _cli_helpers.dataDirDefaultOption, {
alias: "m",
help: "Diff modes.",
name: "mode",
defaultValue: "merged",
type: String
}, {
alias: "p",
help: "Directory containing the previous dump of amendments",
name: "previous",
type: String
}, {
alias: "o",
help: "Output directory for diff files",
name: "output",
defaultValue: "./diff_outputs/",
type: String
}];
var options = (0, _commandLineArgs["default"])(optionsDefinitions);
function diffAmendements(dataDir) {
if (!options.previous) {
console.error("No previous data folder specified. You must provide one with the -p or --previous option. Exiting...");
process.exit();
}
if (!_fsExtra["default"].existsSync(options.output)) {
console.error("The output dir does not exists. You must provide an existing directory. Default directory is ./diff_outputs/");
process.exit();
}
var _iterator = _createForOfIteratorHelper(_datasets.datasets.amendements),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var dataset = _step.value;
switch (dataset.structure) {
case _datasets.DatasetStructure.SegmentedFiles:
{
var originalJsonDir = _path["default"].join(dataDir, dataset.filename);
if (!options.silent) {
console.log("Diffing ".concat(originalJsonDir, " folder..."));
}
var _iterator2 = _createForOfIteratorHelper((0, _file_systems.walkDir)(originalJsonDir)),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var amendementSplitPath = _step2.value;
var newFilePath = originalJsonDir + "/" + amendementSplitPath.join("/");
var newFile = JSON.parse(_fsExtra["default"].readFileSync(newFilePath).toLocaleString());
var oldFilePath = options.previous + dataset.filename + "/" + amendementSplitPath.join("/");
var oldFileExists = _fsExtra["default"].existsSync(oldFilePath);
if (!oldFileExists) {
// If file found does not exist in the previous dump
if (!options.silent) {
console.log("File did not exists previously. Guessing it's a new amendment. Adding to the diff list for new objects");
}
addToQueueForNewAmendments(newFile, amendementSplitPath);
continue;
}
// File already existed in previous dump
var oldFile = JSON.parse("{}");
try {
// Gather data of the file and retranscript as a Json object
oldFile = JSON.parse(_fsExtra["default"].readFileSync(oldFilePath).toLocaleString());
} catch (e) {
// Skip the process to the next iteration in case of corrupt JSON data
continue;
}
// Generate the diff beetween the two JSON objects (old & new dump)
var diff = (0, _deepObjectDiff.detailedDiff)(oldFile, newFile);
// If no changes beetween the two dumps
if (Object.keys(diff.added).length === 0 && Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) {
// Skip to next iteration as there is no need to generate a file
continue;
} else {
if (!options.silent) {
console.log("Changes found !");
}
addToQueueForDiffedAmendments(diff, amendementSplitPath);
}
break;
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
}
}
if (!options.silent) {
console.log("Generating output(s)");
}
generateDiffFiles();
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
/**
* General process for output of diffs.
* The script handles two different modes :
* - merged : Will output a single file for new amendements and a single file
* for updated amendements
* - splitted : Will output a single file for each amendments, either its new or updated.
*
*/
function generateDiffFiles() {
// Handles merged mode
if (options.mode === "merged") {
if (!options.silent) {
console.log("Generating merged files");
}
if (diffedAmendments.length > 0) {
if (!options.silent) {
console.log("Generating diffed amendments files");
}
_fsExtra["default"].writeFileSync(options.output + "amendements_XV_diffed.json", JSON.stringify(diffedAmendments), {
encoding: "utf8",
flag: "w"
});
} else {
if (!options.silent) {
console.log("No diff in the already existing amendments");
}
}
if (newAmendments.length > 0) {
if (!options.silent) {
console.log("Generating new amendments file");
}
_fsExtra["default"].writeFileSync(options.output + "amendements_XV_new.json", JSON.stringify(newAmendments), {
encoding: "utf8",
flag: "w"
});
} else {
if (!options.silent) {
console.log("No new amendement. Skipping file generation");
}
}
} else if (options.mode === "splitted") {
// Handles splitted mode
if (!options.silent) {
console.log("Generating separated files");
}
/**
* Process the copy action of the new and diffed amendments
*/
diffedAmendments.forEach(function (diffedAmendment) {
generateSingleDiffedAmendment(diffedAmendment);
});
newAmendments.forEach(function (newAmendment) {
generateSingleNewAmendment(newAmendment);
});
} else {
console.error("Unknown output mode. Aborting...");
process.exit();
}
}
// Pushes an amendment to the queue that will be processed to copy new amendments files
function addToQueueForNewAmendments(file, path) {
var amendment = {
path: path,
data: file
};
newAmendments.push(amendment);
}
// Pushes an amendment to the queue that will be processed to copy updated amendments files
function addToQueueForDiffedAmendments(diffedData, path) {
var amendment = {
path: path,
data: diffedData
};
diffedAmendments.push(amendment);
}
// generates a file with a copy of the new amendement
function generateSingleNewAmendment(newAmendment) {
newAmendment.path.shift();
var shortDir = _toConsumableArray(newAmendment.path);
shortDir.pop();
console.log(options.output + shortDir.join("/"));
_fsExtra["default"].mkdirSync(options.output + shortDir.join("/"), {
recursive: true
});
_fsExtra["default"].writeFileSync(options.output + newAmendment.path.join("/").replace(/(\.json)/, ".new$1"), JSON.stringify(newAmendment.data), {
encoding: "utf8",
flag: "w"
});
}
// generates a file with a copy of the modified data of the previously existing amendment;
function generateSingleDiffedAmendment(diffedAmendment) {
diffedAmendment.path.shift();
var shortDir = _toConsumableArray(diffedAmendment.path);
shortDir.pop();
_fsExtra["default"].mkdirSync(options.output + shortDir.join("/"), {
recursive: true
});
_fsExtra["default"].writeFileSync(options.output + diffedAmendment.path.join("/").replace(/(\.json)/, ".diff$1"), JSON.stringify(diffedAmendment.data), {
encoding: "utf8",
flag: "w"
});
}
diffAmendements(options.dataDir);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29tbWFuZExpbmVBcmdzIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZnNFeHRyYSIsIl9wYXRoIiwiX2RlZXBPYmplY3REaWZmIiwiX2RhdGFzZXRzIiwiX2ZpbGVfc3lzdGVtcyIsIl9jbGlfaGVscGVycyIsImUiLCJfX2VzTW9kdWxlIiwiX3RvQ29uc3VtYWJsZUFycmF5IiwiciIsIl9hcnJheVdpdGhvdXRIb2xlcyIsIl9pdGVyYWJsZVRvQXJyYXkiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJfbm9uSXRlcmFibGVTcHJlYWQiLCJUeXBlRXJyb3IiLCJTeW1ib2wiLCJpdGVyYXRvciIsIkFycmF5IiwiZnJvbSIsImlzQXJyYXkiLCJfYXJyYXlMaWtlVG9BcnJheSIsIl9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyIiwidCIsImxlbmd0aCIsIl9uIiwiRiIsInMiLCJuIiwiZG9uZSIsInZhbHVlIiwiZiIsIm8iLCJhIiwidSIsImNhbGwiLCJuZXh0IiwidG9TdHJpbmciLCJzbGljZSIsImNvbnN0cnVjdG9yIiwibmFtZSIsInRlc3QiLCJkaWZmZWRBbWVuZG1lbnRzIiwibmV3QW1lbmRtZW50cyIsIm9wdGlvbnNEZWZpbml0aW9ucyIsInNpbGVudE9wdGlvbiIsInZlcmJvc2VPcHRpb24iLCJkYXRhRGlyRGVmYXVsdE9wdGlvbiIsImFsaWFzIiwiaGVscCIsImRlZmF1bHRWYWx1ZSIsInR5cGUiLCJTdHJpbmciLCJvcHRpb25zIiwiY29tbWFuZExpbmVBcmdzIiwiZGlmZkFtZW5kZW1lbnRzIiwiZGF0YURpciIsInByZXZpb3VzIiwiY29uc29sZSIsImVycm9yIiwicHJvY2VzcyIsImV4aXQiLCJmcyIsImV4aXN0c1N5bmMiLCJvdXRwdXQiLCJfaXRlcmF0b3IiLCJkYXRhc2V0cyIsImFtZW5kZW1lbnRzIiwiX3N0ZXAiLCJkYXRhc2V0Iiwic3RydWN0dXJlIiwiRGF0YXNldFN0cnVjdHVyZSIsIlNlZ21lbnRlZEZpbGVzIiwib3JpZ2luYWxKc29uRGlyIiwicGF0aCIsImpvaW4iLCJmaWxlbmFtZSIsInNpbGVudCIsImxvZyIsImNvbmNhdCIsIl9pdGVyYXRvcjIiLCJ3YWxrRGlyIiwiX3N0ZXAyIiwiYW1lbmRlbWVudFNwbGl0UGF0aCIsIm5ld0ZpbGVQYXRoIiwibmV3RmlsZSIsIkpTT04iLCJwYXJzZSIsInJlYWRGaWxlU3luYyIsInRvTG9jYWxlU3RyaW5nIiwib2xkRmlsZVBhdGgiLCJvbGRGaWxlRXhpc3RzIiwiYWRkVG9RdWV1ZUZvck5ld0FtZW5kbWVudHMiLCJvbGRGaWxlIiwiZGlmZiIsImRldGFpbGVkRGlmZiIsIk9iamVjdCIsImtleXMiLCJhZGRlZCIsInVwZGF0ZWQiLCJkZWxldGVkIiwiYWRkVG9RdWV1ZUZvckRpZmZlZEFtZW5kbWVudHMiLCJlcnIiLCJnZW5lcmF0ZURpZmZGaWxlcyIsIm1vZGUiLCJ3cml0ZUZpbGVTeW5jIiwic3RyaW5naWZ5IiwiZW5jb2RpbmciLCJmbGFnIiwiZm9yRWFjaCIsImRpZmZlZEFtZW5kbWVudCIsImdlbmVyYXRlU2luZ2xlRGlmZmVkQW1lbmRtZW50IiwibmV3QW1lbmRtZW50IiwiZ2VuZXJhdGVTaW5nbGVOZXdBbWVuZG1lbnQiLCJmaWxlIiwiYW1lbmRtZW50IiwiZGF0YSIsInB1c2giLCJkaWZmZWREYXRhIiwic2hpZnQiLCJzaG9ydERpciIsInBvcCIsIm1rZGlyU3luYyIsInJlY3Vyc2l2ZSIsInJlcGxhY2UiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NyaXB0cy9kaWZmX2FtZW5kZW1lbnRzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjb21tYW5kTGluZUFyZ3MgZnJvbSBcImNvbW1hbmQtbGluZS1hcmdzXCJcbmltcG9ydCBmcyBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIlxuaW1wb3J0IHsgZGV0YWlsZWREaWZmIH0gZnJvbSBcImRlZXAtb2JqZWN0LWRpZmZcIlxuaW1wb3J0IHsgZGF0YXNldHMsIERhdGFzZXRTdHJ1Y3R1cmUgfSBmcm9tIFwiLi4vZGF0YXNldHNcIlxuaW1wb3J0IHsgd2Fsa0RpciB9IGZyb20gXCIuLi9maWxlX3N5c3RlbXNcIlxuaW1wb3J0IHtcbiAgc2lsZW50T3B0aW9uLFxuICB2ZXJib3NlT3B0aW9uLFxuICBkYXRhRGlyRGVmYXVsdE9wdGlvbixcbn0gZnJvbSBcIi4vc2hhcmVkL2NsaV9oZWxwZXJzXCJcbmNvbnN0IGRpZmZlZEFtZW5kbWVudHM6IEFycmF5PGFueT4gPSBbXVxuY29uc3QgbmV3QW1lbmRtZW50czogQXJyYXk8YW55PiA9IFtdXG5cbmNvbnN0IG9wdGlvbnNEZWZpbml0aW9ucyA9IFtcbiAgc2lsZW50T3B0aW9uLFxuICB2ZXJib3NlT3B0aW9uLFxuICBkYXRhRGlyRGVmYXVsdE9wdGlvbixcbiAge1xuICAgIGFsaWFzOiBcIm1cIixcbiAgICBoZWxwOiBcIkRpZmYgbW9kZXMuXCIsXG4gICAgbmFtZTogXCJtb2RlXCIsXG4gICAgZGVmYXVsdFZhbHVlOiBcIm1lcmdlZFwiLFxuICAgIHR5cGU6IFN0cmluZyxcbiAgfSxcbiAge1xuICAgIGFsaWFzOiBcInBcIixcbiAgICBoZWxwOiBcIkRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBwcmV2aW91cyBkdW1wIG9mIGFtZW5kbWVudHNcIixcbiAgICBuYW1lOiBcInByZXZpb3VzXCIsXG4gICAgdHlwZTogU3RyaW5nLFxuICB9LFxuICB7XG4gICAgYWxpYXM6IFwib1wiLFxuICAgIGhlbHA6IFwiT3V0cHV0IGRpcmVjdG9yeSBmb3IgZGlmZiBmaWxlc1wiLFxuICAgIG5hbWU6IFwib3V0cHV0XCIsXG4gICAgZGVmYXVsdFZhbHVlOiBcIi4vZGlmZl9vdXRwdXRzL1wiLFxuICAgIHR5cGU6IFN0cmluZyxcbiAgfSxcbl1cbmNvbnN0IG9wdGlvbnMgPSBjb21tYW5kTGluZUFyZ3Mob3B0aW9uc0RlZmluaXRpb25zKVxuXG5mdW5jdGlvbiBkaWZmQW1lbmRlbWVudHMoZGF0YURpcjogc3RyaW5nKSB7XG4gIGlmICghb3B0aW9ucy5wcmV2aW91cykge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBcIk5vIHByZXZpb3VzIGRhdGEgZm9sZGVyIHNwZWNpZmllZC4gWW91IG11c3QgcHJvdmlkZSBvbmUgd2l0aCB0aGUgLXAgb3IgLS1wcmV2aW91cyBvcHRpb24uIEV4aXRpbmcuLi5cIixcbiAgICApXG4gICAgcHJvY2Vzcy5leGl0KClcbiAgfVxuXG4gIGlmICghZnMuZXhpc3RzU3luYyhvcHRpb25zLm91dHB1dCkpIHtcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgXCJUaGUgb3V0cHV0IGRpciBkb2VzIG5vdCBleGlzdHMuIFlvdSBtdXN0IHByb3ZpZGUgYW4gZXhpc3RpbmcgZGlyZWN0b3J5LiBEZWZhdWx0IGRpcmVjdG9yeSBpcyAuL2RpZmZfb3V0cHV0cy9cIixcbiAgICApXG4gICAgcHJvY2Vzcy5leGl0KClcbiAgfVxuXG4gIGZvciAoY29uc3QgZGF0YXNldCBvZiBkYXRhc2V0cy5hbWVuZGVtZW50cykge1xuICAgIHN3aXRjaCAoZGF0YXNldC5zdHJ1Y3R1cmUpIHtcbiAgICAgIGNhc2UgRGF0YXNldFN0cnVjdHVyZS5TZWdtZW50ZWRGaWxlczoge1xuICAgICAgICBjb25zdCBvcmlnaW5hbEpzb25EaXI6IHN0cmluZyA9IHBhdGguam9pbihkYXRhRGlyLCBkYXRhc2V0LmZpbGVuYW1lKVxuICAgICAgICBpZiAoIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYERpZmZpbmcgJHtvcmlnaW5hbEpzb25EaXJ9IGZvbGRlci4uLmApXG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IGFtZW5kZW1lbnRTcGxpdFBhdGggb2Ygd2Fsa0RpcihvcmlnaW5hbEpzb25EaXIpKSB7XG4gICAgICAgICAgY29uc3QgbmV3RmlsZVBhdGggPVxuICAgICAgICAgICAgb3JpZ2luYWxKc29uRGlyICsgXCIvXCIgKyBhbWVuZGVtZW50U3BsaXRQYXRoLmpvaW4oXCIvXCIpXG4gICAgICAgICAgY29uc3QgbmV3RmlsZSA9IEpTT04ucGFyc2UoXG4gICAgICAgICAgICBmcy5yZWFkRmlsZVN5bmMobmV3RmlsZVBhdGgpLnRvTG9jYWxlU3RyaW5nKCksXG4gICAgICAgICAgKVxuXG4gICAgICAgICAgY29uc3Qgb2xkRmlsZVBhdGggPVxuICAgICAgICAgICAgb3B0aW9ucy5wcmV2aW91cyArXG4gICAgICAgICAgICBkYXRhc2V0LmZpbGVuYW1lICtcbiAgICAgICAgICAgIFwiL1wiICtcbiAgICAgICAgICAgIGFtZW5kZW1lbnRTcGxpdFBhdGguam9pbihcIi9cIilcbiAgICAgICAgICBjb25zdCBvbGRGaWxlRXhpc3RzID0gZnMuZXhpc3RzU3luYyhvbGRGaWxlUGF0aClcbiAgICAgICAgICBpZiAoIW9sZEZpbGVFeGlzdHMpIHtcbiAgICAgICAgICAgIC8vIElmIGZpbGUgZm91bmQgZG9lcyBub3QgZXhpc3QgaW4gdGhlIHByZXZpb3VzIGR1bXBcbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5zaWxlbnQpIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgXCJGaWxlIGRpZCBub3QgZXhpc3RzIHByZXZpb3VzbHkuIEd1ZXNzaW5nIGl0J3MgYSBuZXcgYW1lbmRtZW50LiBBZGRpbmcgdG8gdGhlIGRpZmYgbGlzdCBmb3IgbmV3IG9iamVjdHNcIixcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYWRkVG9RdWV1ZUZvck5ld0FtZW5kbWVudHMobmV3RmlsZSwgYW1lbmRlbWVudFNwbGl0UGF0aClcbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gRmlsZSBhbHJlYWR5IGV4aXN0ZWQgaW4gcHJldmlvdXMgZHVtcFxuICAgICAgICAgIGxldCBvbGRGaWxlOiBKU09OID0gSlNPTi5wYXJzZShcInt9XCIpXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEdhdGhlciBkYXRhIG9mIHRoZSBmaWxlIGFuZCByZXRyYW5zY3JpcHQgYXMgYSBKc29uIG9iamVjdFxuICAgICAgICAgICAgb2xkRmlsZSA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKG9sZEZpbGVQYXRoKS50b0xvY2FsZVN0cmluZygpKVxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIFNraXAgdGhlIHByb2Nlc3MgdG8gdGhlIG5leHQgaXRlcmF0aW9uIGluIGNhc2Ugb2YgY29ycnVwdCBKU09OIGRhdGFcbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gR2VuZXJhdGUgdGhlIGRpZmYgYmVldHdlZW4gdGhlIHR3byBKU09OIG9iamVjdHMgKG9sZCAmIG5ldyBkdW1wKVxuICAgICAgICAgIGNvbnN0IGRpZmY6IGFueSA9IGRldGFpbGVkRGlmZihvbGRGaWxlLCBuZXdGaWxlKVxuXG4gICAgICAgICAgLy8gSWYgbm8gY2hhbmdlcyBiZWV0d2VlbiB0aGUgdHdvIGR1bXBzXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgT2JqZWN0LmtleXMoZGlmZi5hZGRlZCkubGVuZ3RoID09PSAwICYmXG4gICAgICAgICAgICBPYmplY3Qua2V5cyhkaWZmLnVwZGF0ZWQpLmxlbmd0aCA9PT0gMCAmJlxuICAgICAgICAgICAgT2JqZWN0LmtleXMoZGlmZi5kZWxldGVkKS5sZW5ndGggPT09IDBcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIC8vIFNraXAgdG8gbmV4dCBpdGVyYXRpb24gYXMgdGhlcmUgaXMgbm8gbmVlZCB0byBnZW5lcmF0ZSBhIGZpbGVcbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5zaWxlbnQpIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJDaGFuZ2VzIGZvdW5kICFcIilcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFkZFRvUXVldWVGb3JEaWZmZWRBbWVuZG1lbnRzKGRpZmYsIGFtZW5kZW1lbnRTcGxpdFBhdGgpXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICBjb25zb2xlLmxvZyhcIkdlbmVyYXRpbmcgb3V0cHV0KHMpXCIpXG4gICAgfVxuXG4gICAgZ2VuZXJhdGVEaWZmRmlsZXMoKVxuICB9XG59XG5cbi8qKlxuICogR2VuZXJhbCBwcm9jZXNzIGZvciBvdXRwdXQgb2YgZGlmZnMuXG4gKiBUaGUgc2NyaXB0IGhhbmRsZXMgdHdvIGRpZmZlcmVudCBtb2RlcyA6XG4gKiAtIG1lcmdlZCA6IFdpbGwgb3V0cHV0IGEgc2luZ2xlIGZpbGUgZm9yIG5ldyBhbWVuZGVtZW50cyBhbmQgYSBzaW5nbGUgZmlsZVxuICogICAgICAgICAgICBmb3IgdXBkYXRlZCBhbWVuZGVtZW50c1xuICogLSBzcGxpdHRlZCA6IFdpbGwgb3V0cHV0IGEgc2luZ2xlIGZpbGUgZm9yIGVhY2ggYW1lbmRtZW50cywgZWl0aGVyIGl0cyBuZXcgb3IgdXBkYXRlZC5cbiAqXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlRGlmZkZpbGVzKCkge1xuICAvLyBIYW5kbGVzIG1lcmdlZCBtb2RlXG4gIGlmIChvcHRpb25zLm1vZGUgPT09IFwibWVyZ2VkXCIpIHtcbiAgICBpZiAoIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICBjb25zb2xlLmxvZyhcIkdlbmVyYXRpbmcgbWVyZ2VkIGZpbGVzXCIpXG4gICAgfVxuXG4gICAgaWYgKGRpZmZlZEFtZW5kbWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKCFvcHRpb25zLnNpbGVudCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcIkdlbmVyYXRpbmcgZGlmZmVkIGFtZW5kbWVudHMgZmlsZXNcIilcbiAgICAgIH1cbiAgICAgIGZzLndyaXRlRmlsZVN5bmMoXG4gICAgICAgIG9wdGlvbnMub3V0cHV0ICsgXCJhbWVuZGVtZW50c19YVl9kaWZmZWQuanNvblwiLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShkaWZmZWRBbWVuZG1lbnRzKSxcbiAgICAgICAgeyBlbmNvZGluZzogXCJ1dGY4XCIsIGZsYWc6IFwid1wiIH0sXG4gICAgICApXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghb3B0aW9ucy5zaWxlbnQpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJObyBkaWZmIGluIHRoZSBhbHJlYWR5IGV4aXN0aW5nIGFtZW5kbWVudHNcIilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobmV3QW1lbmRtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAoIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiR2VuZXJhdGluZyBuZXcgYW1lbmRtZW50cyBmaWxlXCIpXG4gICAgICB9XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKFxuICAgICAgICBvcHRpb25zLm91dHB1dCArIFwiYW1lbmRlbWVudHNfWFZfbmV3Lmpzb25cIixcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkobmV3QW1lbmRtZW50cyksXG4gICAgICAgIHsgZW5jb2Rpbmc6IFwidXRmOFwiLCBmbGFnOiBcIndcIiB9LFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiTm8gbmV3IGFtZW5kZW1lbnQuIFNraXBwaW5nIGZpbGUgZ2VuZXJhdGlvblwiKVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChvcHRpb25zLm1vZGUgPT09IFwic3BsaXR0ZWRcIikge1xuICAgIC8vIEhhbmRsZXMgc3BsaXR0ZWQgbW9kZVxuICAgIGlmICghb3B0aW9ucy5zaWxlbnQpIHtcbiAgICAgIGNvbnNvbGUubG9nKFwiR2VuZXJhdGluZyBzZXBhcmF0ZWQgZmlsZXNcIilcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIHRoZSBjb3B5IGFjdGlvbiBvZiB0aGUgbmV3IGFuZCBkaWZmZWQgYW1lbmRtZW50c1xuICAgICAqL1xuXG4gICAgZGlmZmVkQW1lbmRtZW50cy5mb3JFYWNoKChkaWZmZWRBbWVuZG1lbnQ6IGFueSkgPT4ge1xuICAgICAgZ2VuZXJhdGVTaW5nbGVEaWZmZWRBbWVuZG1lbnQoZGlmZmVkQW1lbmRtZW50KVxuICAgIH0pXG5cbiAgICBuZXdBbWVuZG1lbnRzLmZvckVhY2goKG5ld0FtZW5kbWVudDogYW55KSA9PiB7XG4gICAgICBnZW5lcmF0ZVNpbmdsZU5ld0FtZW5kbWVudChuZXdBbWVuZG1lbnQpXG4gICAgfSlcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKFwiVW5rbm93biBvdXRwdXQgbW9kZS4gQWJvcnRpbmcuLi5cIilcbiAgICBwcm9jZXNzLmV4aXQoKVxuICB9XG59XG5cbi8vIFB1c2hlcyBhbiBhbWVuZG1lbnQgdG8gdGhlIHF1ZXVlIHRoYXQgd2lsbCBiZSBwcm9jZXNzZWQgdG8gY29weSBuZXcgYW1lbmRtZW50cyBmaWxlc1xuZnVuY3Rpb24gYWRkVG9RdWV1ZUZvck5ld0FtZW5kbWVudHMoZmlsZTogYW55LCBwYXRoOiBhbnkpOiB2b2lkIHtcbiAgY29uc3QgYW1lbmRtZW50OiBhbnkgPSB7XG4gICAgcGF0aDogcGF0aCxcbiAgICBkYXRhOiBmaWxlLFxuICB9XG4gIG5ld0FtZW5kbWVudHMucHVzaChhbWVuZG1lbnQpXG59XG4vLyBQdXNoZXMgYW4gYW1lbmRtZW50IHRvIHRoZSBxdWV1ZSB0aGF0IHdpbGwgYmUgcHJvY2Vzc2VkIHRvIGNvcHkgdXBkYXRlZCBhbWVuZG1lbnRzIGZpbGVzXG5mdW5jdGlvbiBhZGRUb1F1ZXVlRm9yRGlmZmVkQW1lbmRtZW50cyhkaWZmZWREYXRhOiBhbnksIHBhdGg6IGFueSk6IHZvaWQge1xuICBjb25zdCBhbWVuZG1lbnQ6IGFueSA9IHtcbiAgICBwYXRoOiBwYXRoLFxuICAgIGRhdGE6IGRpZmZlZERhdGEsXG4gIH1cbiAgZGlmZmVkQW1lbmRtZW50cy5wdXNoKGFtZW5kbWVudClcbn1cblxuLy8gZ2VuZXJhdGVzIGEgZmlsZSB3aXRoIGEgY29weSBvZiB0aGUgbmV3IGFtZW5kZW1lbnRcbmZ1bmN0aW9uIGdlbmVyYXRlU2luZ2xlTmV3QW1lbmRtZW50KG5ld0FtZW5kbWVudDoge1xuICBwYXRoOiBBcnJheTxzdHJpbmc+XG4gIGRhdGE6IGFueVxufSkge1xuICBuZXdBbWVuZG1lbnQucGF0aC5zaGlmdCgpXG5cbiAgY29uc3Qgc2hvcnREaXI6IEFycmF5PGFueT4gPSBbLi4ubmV3QW1lbmRtZW50LnBhdGhdXG4gIHNob3J0RGlyLnBvcCgpXG4gIGNvbnNvbGUubG9nKG9wdGlvbnMub3V0cHV0ICsgc2hvcnREaXIuam9pbihcIi9cIikpXG4gIGZzLm1rZGlyU3luYyhvcHRpb25zLm91dHB1dCArIHNob3J0RGlyLmpvaW4oXCIvXCIpLCB7XG4gICAgcmVjdXJzaXZlOiB0cnVlLFxuICB9KVxuICBmcy53cml0ZUZpbGVTeW5jKFxuICAgIG9wdGlvbnMub3V0cHV0ICsgbmV3QW1lbmRtZW50LnBhdGguam9pbihcIi9cIikucmVwbGFjZSgvKFxcLmpzb24pLywgXCIubmV3JDFcIiksXG4gICAgSlNPTi5zdHJpbmdpZnkobmV3QW1lbmRtZW50LmRhdGEpLFxuICAgIHsgZW5jb2Rpbmc6IFwidXRmOFwiLCBmbGFnOiBcIndcIiB9LFxuICApXG59XG5cbi8vIGdlbmVyYXRlcyBhIGZpbGUgd2l0aCBhIGNvcHkgb2YgdGhlIG1vZGlmaWVkIGRhdGEgb2YgdGhlIHByZXZpb3VzbHkgZXhpc3RpbmcgYW1lbmRtZW50O1xuZnVuY3Rpb24gZ2VuZXJhdGVTaW5nbGVEaWZmZWRBbWVuZG1lbnQoZGlmZmVkQW1lbmRtZW50OiB7XG4gIHBhdGg6IEFycmF5PHN0cmluZz5cbiAgZGF0YTogYW55XG59KSB7XG4gIGRpZmZlZEFtZW5kbWVudC5wYXRoLnNoaWZ0KClcblxuICBjb25zdCBzaG9ydERpcjogQXJyYXk8YW55PiA9IFsuLi5kaWZmZWRBbWVuZG1lbnQucGF0aF1cbiAgc2hvcnREaXIucG9wKClcbiAgZnMubWtkaXJTeW5jKG9wdGlvbnMub3V0cHV0ICsgc2hvcnREaXIuam9pbihcIi9cIiksIHtcbiAgICByZWN1cnNpdmU6IHRydWUsXG4gIH0pXG5cbiAgZnMud3JpdGVGaWxlU3luYyhcbiAgICBvcHRpb25zLm91dHB1dCArXG4gICAgICBkaWZmZWRBbWVuZG1lbnQucGF0aC5qb2luKFwiL1wiKS5yZXBsYWNlKC8oXFwuanNvbikvLCBcIi5kaWZmJDFcIiksXG4gICAgSlNPTi5zdHJpbmdpZnkoZGlmZmVkQW1lbmRtZW50LmRhdGEpLFxuICAgIHsgZW5jb2Rpbmc6IFwidXRmOFwiLCBmbGFnOiBcIndcIiB9LFxuICApXG59XG5cbmRpZmZBbWVuZGVtZW50cyhvcHRpb25zLmRhdGFEaXIpXG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLElBQUFBLGdCQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxRQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRSxLQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRyxlQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxTQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxhQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxZQUFBLEdBQUFOLE9BQUE7QUFJNkIsU0FBQUQsdUJBQUFRLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxnQkFBQUEsQ0FBQTtBQUFBLFNBQUFFLG1CQUFBQyxDQUFBLFdBQUFDLGtCQUFBLENBQUFELENBQUEsS0FBQUUsZ0JBQUEsQ0FBQUYsQ0FBQSxLQUFBRywyQkFBQSxDQUFBSCxDQUFBLEtBQUFJLGtCQUFBO0FBQUEsU0FBQUEsbUJBQUEsY0FBQUMsU0FBQTtBQUFBLFNBQUFILGlCQUFBRixDQUFBLDhCQUFBTSxNQUFBLFlBQUFOLENBQUEsQ0FBQU0sTUFBQSxDQUFBQyxRQUFBLGFB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