makePatch.js 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.logPatchSequenceError = exports.makePatch = void 0;
  7. const chalk_1 = __importDefault(require("chalk"));
  8. const console_1 = __importDefault(require("console"));
  9. const fs_1 = require("fs");
  10. const fs_extra_1 = require("fs-extra");
  11. const rimraf_1 = require("rimraf");
  12. const tmp_1 = require("tmp");
  13. const zlib_1 = require("zlib");
  14. const applyPatches_1 = require("./applyPatches");
  15. const createIssue_1 = require("./createIssue");
  16. const filterFiles_1 = require("./filterFiles");
  17. const getPackageResolution_1 = require("./getPackageResolution");
  18. const getPackageVersion_1 = require("./getPackageVersion");
  19. const hash_1 = require("./hash");
  20. const PackageDetails_1 = require("./PackageDetails");
  21. const parse_1 = require("./patch/parse");
  22. const patchFs_1 = require("./patchFs");
  23. const path_1 = require("./path");
  24. const resolveRelativeFileDependencies_1 = require("./resolveRelativeFileDependencies");
  25. const spawnSafe_1 = require("./spawnSafe");
  26. const stateFile_1 = require("./stateFile");
  27. function printNoPackageFoundError(packageName, packageJsonPath) {
  28. console_1.default.log(`No such package ${packageName}
  29. File not found: ${packageJsonPath}`);
  30. }
  31. function makePatch({ packagePathSpecifier, appPath, packageManager, includePaths, excludePaths, patchDir, createIssue, mode, }) {
  32. var _a, _b, _c, _d, _e;
  33. const packageDetails = PackageDetails_1.getPatchDetailsFromCliString(packagePathSpecifier);
  34. if (!packageDetails) {
  35. console_1.default.log("No such package", packagePathSpecifier);
  36. return;
  37. }
  38. const state = stateFile_1.getPatchApplicationState(packageDetails);
  39. const isRebasing = (_a = state === null || state === void 0 ? void 0 : state.isRebasing) !== null && _a !== void 0 ? _a : false;
  40. // If we are rebasing and no patches have been applied, --append is the only valid option because
  41. // there are no previous patches to overwrite/update
  42. if (isRebasing &&
  43. (state === null || state === void 0 ? void 0 : state.patches.filter((p) => p.didApply).length) === 0 &&
  44. mode.type === "overwrite_last") {
  45. mode = { type: "append", name: "initial" };
  46. }
  47. if (isRebasing && state) {
  48. stateFile_1.verifyAppliedPatches({ appPath, patchDir, state });
  49. }
  50. if (mode.type === "overwrite_last" &&
  51. isRebasing &&
  52. (state === null || state === void 0 ? void 0 : state.patches.length) === 0) {
  53. mode = { type: "append", name: "initial" };
  54. }
  55. const existingPatches = patchFs_1.getGroupedPatches(patchDir).pathSpecifierToPatchFiles[packageDetails.pathSpecifier] || [];
  56. // apply all existing patches if appending
  57. // otherwise apply all but the last
  58. const previouslyAppliedPatches = state === null || state === void 0 ? void 0 : state.patches.filter((p) => p.didApply);
  59. const patchesToApplyBeforeDiffing = isRebasing
  60. ? mode.type === "append"
  61. ? existingPatches.slice(0, previouslyAppliedPatches.length)
  62. : state.patches[state.patches.length - 1].didApply
  63. ? existingPatches.slice(0, previouslyAppliedPatches.length - 1)
  64. : existingPatches.slice(0, previouslyAppliedPatches.length)
  65. : mode.type === "append"
  66. ? existingPatches
  67. : existingPatches.slice(0, -1);
  68. if (createIssue && mode.type === "append") {
  69. console_1.default.log("--create-issue is not compatible with --append.");
  70. process.exit(1);
  71. }
  72. if (createIssue && isRebasing) {
  73. console_1.default.log("--create-issue is not compatible with rebasing.");
  74. process.exit(1);
  75. }
  76. const numPatchesAfterCreate = mode.type === "append" || existingPatches.length === 0
  77. ? existingPatches.length + 1
  78. : existingPatches.length;
  79. const vcs = createIssue_1.getPackageVCSDetails(packageDetails);
  80. const canCreateIssue = !isRebasing &&
  81. createIssue_1.shouldRecommendIssue(vcs) &&
  82. numPatchesAfterCreate === 1 &&
  83. mode.type !== "append";
  84. const appPackageJson = require(path_1.join(appPath, "package.json"));
  85. const packagePath = path_1.join(appPath, packageDetails.path);
  86. const packageJsonPath = path_1.join(packagePath, "package.json");
  87. if (!fs_extra_1.existsSync(packageJsonPath)) {
  88. printNoPackageFoundError(packagePathSpecifier, packageJsonPath);
  89. process.exit(1);
  90. }
  91. const tmpRepo = tmp_1.dirSync({ unsafeCleanup: true });
  92. const tmpRepoPackagePath = path_1.join(tmpRepo.name, packageDetails.path);
  93. const tmpRepoNpmRoot = tmpRepoPackagePath.slice(0, -`/node_modules/${packageDetails.name}`.length);
  94. const tmpRepoPackageJsonPath = path_1.join(tmpRepoNpmRoot, "package.json");
  95. try {
  96. const patchesDir = path_1.resolve(path_1.join(appPath, patchDir));
  97. console_1.default.info(chalk_1.default.grey("•"), "Creating temporary folder");
  98. // make a blank package.json
  99. fs_extra_1.mkdirpSync(tmpRepoNpmRoot);
  100. fs_extra_1.writeFileSync(tmpRepoPackageJsonPath, JSON.stringify({
  101. dependencies: {
  102. [packageDetails.name]: getPackageResolution_1.getPackageResolution({
  103. packageDetails,
  104. packageManager,
  105. appPath,
  106. }),
  107. },
  108. resolutions: resolveRelativeFileDependencies_1.resolveRelativeFileDependencies(appPath, appPackageJson.resolutions || {}),
  109. }));
  110. const packageVersion = getPackageVersion_1.getPackageVersion(path_1.join(path_1.resolve(packageDetails.path), "package.json"));
  111. [".npmrc", ".yarnrc", ".yarn"].forEach((rcFile) => {
  112. const rcPath = path_1.join(appPath, rcFile);
  113. if (fs_extra_1.existsSync(rcPath)) {
  114. fs_extra_1.copySync(rcPath, path_1.join(tmpRepo.name, rcFile), { dereference: true });
  115. }
  116. });
  117. if (packageManager === "yarn") {
  118. console_1.default.info(chalk_1.default.grey("•"), `Installing ${packageDetails.name}@${packageVersion} with yarn`);
  119. try {
  120. // try first without ignoring scripts in case they are required
  121. // this works in 99.99% of cases
  122. spawnSafe_1.spawnSafeSync(`yarn`, ["install", "--ignore-engines"], {
  123. cwd: tmpRepoNpmRoot,
  124. logStdErrOnError: false,
  125. });
  126. }
  127. catch (e) {
  128. // try again while ignoring scripts in case the script depends on
  129. // an implicit context which we haven't reproduced
  130. spawnSafe_1.spawnSafeSync(`yarn`, ["install", "--ignore-engines", "--ignore-scripts"], {
  131. cwd: tmpRepoNpmRoot,
  132. });
  133. }
  134. }
  135. else {
  136. console_1.default.info(chalk_1.default.grey("•"), `Installing ${packageDetails.name}@${packageVersion} with npm`);
  137. try {
  138. // try first without ignoring scripts in case they are required
  139. // this works in 99.99% of cases
  140. spawnSafe_1.spawnSafeSync(`npm`, ["i", "--force"], {
  141. cwd: tmpRepoNpmRoot,
  142. logStdErrOnError: false,
  143. stdio: "ignore",
  144. });
  145. }
  146. catch (e) {
  147. // try again while ignoring scripts in case the script depends on
  148. // an implicit context which we haven't reproduced
  149. spawnSafe_1.spawnSafeSync(`npm`, ["i", "--ignore-scripts", "--force"], {
  150. cwd: tmpRepoNpmRoot,
  151. stdio: "ignore",
  152. });
  153. }
  154. }
  155. const git = (...args) => spawnSafe_1.spawnSafeSync("git", args, {
  156. cwd: tmpRepo.name,
  157. env: Object.assign(Object.assign({}, process.env), { HOME: tmpRepo.name }),
  158. maxBuffer: 1024 * 1024 * 100,
  159. });
  160. // remove nested node_modules just to be safe
  161. rimraf_1.sync(path_1.join(tmpRepoPackagePath, "node_modules"));
  162. // remove .git just to be safe
  163. rimraf_1.sync(path_1.join(tmpRepoPackagePath, ".git"));
  164. // remove patch-package state file
  165. rimraf_1.sync(path_1.join(tmpRepoPackagePath, stateFile_1.STATE_FILE_NAME));
  166. // commit the package
  167. console_1.default.info(chalk_1.default.grey("•"), "Diffing your files with clean files");
  168. fs_extra_1.writeFileSync(path_1.join(tmpRepo.name, ".gitignore"), "!/node_modules\n\n");
  169. git("init");
  170. git("config", "--local", "user.name", "patch-package");
  171. git("config", "--local", "user.email", "patch@pack.age");
  172. // remove ignored files first
  173. filterFiles_1.removeIgnoredFiles(tmpRepoPackagePath, includePaths, excludePaths);
  174. for (const patchDetails of patchesToApplyBeforeDiffing) {
  175. if (!applyPatches_1.applyPatch({
  176. patchDetails,
  177. patchDir,
  178. patchFilePath: path_1.join(appPath, patchDir, patchDetails.patchFilename),
  179. reverse: false,
  180. cwd: tmpRepo.name,
  181. bestEffort: false,
  182. })) {
  183. // TODO: add better error message once --rebase is implemented
  184. console_1.default.log(`Failed to apply patch ${patchDetails.patchFilename} to ${packageDetails.pathSpecifier}`);
  185. process.exit(1);
  186. }
  187. }
  188. git("add", "-f", packageDetails.path);
  189. git("commit", "--allow-empty", "-m", "init");
  190. // replace package with user's version
  191. rimraf_1.sync(tmpRepoPackagePath);
  192. // pnpm installs packages as symlinks, copySync would copy only the symlink
  193. fs_extra_1.copySync(fs_extra_1.realpathSync(packagePath), tmpRepoPackagePath);
  194. // remove nested node_modules just to be safe
  195. rimraf_1.sync(path_1.join(tmpRepoPackagePath, "node_modules"));
  196. // remove .git just to be safe
  197. rimraf_1.sync(path_1.join(tmpRepoPackagePath, ".git"));
  198. // remove patch-package state file
  199. rimraf_1.sync(path_1.join(tmpRepoPackagePath, stateFile_1.STATE_FILE_NAME));
  200. // also remove ignored files like before
  201. filterFiles_1.removeIgnoredFiles(tmpRepoPackagePath, includePaths, excludePaths);
  202. // stage all files
  203. git("add", "-f", packageDetails.path);
  204. // get diff of changes
  205. const diffResult = git("diff", "--cached", "--no-color", "--ignore-space-at-eol", "--no-ext-diff", "--src-prefix=a/", "--dst-prefix=b/");
  206. if (diffResult.stdout.length === 0) {
  207. console_1.default.log(`⁉️ Not creating patch file for package '${packagePathSpecifier}'`);
  208. console_1.default.log(`⁉️ There don't appear to be any changes.`);
  209. if (isRebasing && mode.type === "overwrite_last") {
  210. console_1.default.log("\n💡 To remove a patch file, delete it and then reinstall node_modules from scratch.");
  211. }
  212. process.exit(1);
  213. return;
  214. }
  215. try {
  216. parse_1.parsePatchFile(diffResult.stdout.toString());
  217. }
  218. catch (e) {
  219. if (e.message.includes("Unexpected file mode string: 120000")) {
  220. console_1.default.log(`
  221. ⛔️ ${chalk_1.default.red.bold("ERROR")}
  222. Your changes involve creating symlinks. patch-package does not yet support
  223. symlinks.
  224. ️Please use ${chalk_1.default.bold("--include")} and/or ${chalk_1.default.bold("--exclude")} to narrow the scope of your patch if
  225. this was unintentional.
  226. `);
  227. }
  228. else {
  229. const outPath = "./patch-package-error.json.gz";
  230. fs_extra_1.writeFileSync(outPath, zlib_1.gzipSync(JSON.stringify({
  231. error: { message: e.message, stack: e.stack },
  232. patch: diffResult.stdout.toString(),
  233. })));
  234. console_1.default.log(`
  235. ⛔️ ${chalk_1.default.red.bold("ERROR")}
  236. patch-package was unable to read the patch-file made by git. This should not
  237. happen.
  238. A diagnostic file was written to
  239. ${outPath}
  240. Please attach it to a github issue
  241. https://github.com/ds300/patch-package/issues/new?title=New+patch+parse+failed&body=Please+attach+the+diagnostic+file+by+dragging+it+into+here+🙏
  242. Note that this diagnostic file will contain code from the package you were
  243. attempting to patch.
  244. `);
  245. }
  246. process.exit(1);
  247. return;
  248. }
  249. // maybe delete existing
  250. if (mode.type === "append" && !isRebasing && existingPatches.length === 1) {
  251. // if we are appending to an existing patch that doesn't have a sequence number let's rename it
  252. const prevPatch = existingPatches[0];
  253. if (prevPatch.sequenceNumber === undefined) {
  254. const newFileName = createPatchFileName({
  255. packageDetails,
  256. packageVersion,
  257. sequenceNumber: 1,
  258. sequenceName: (_b = prevPatch.sequenceName) !== null && _b !== void 0 ? _b : "initial",
  259. });
  260. const oldPath = path_1.join(appPath, patchDir, prevPatch.patchFilename);
  261. const newPath = path_1.join(appPath, patchDir, newFileName);
  262. fs_1.renameSync(oldPath, newPath);
  263. prevPatch.sequenceNumber = 1;
  264. prevPatch.patchFilename = newFileName;
  265. prevPatch.sequenceName = (_c = prevPatch.sequenceName) !== null && _c !== void 0 ? _c : "initial";
  266. }
  267. }
  268. const lastPatch = existingPatches[state ? state.patches.length - 1 : existingPatches.length - 1];
  269. const sequenceName = mode.type === "append" ? mode.name : lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceName;
  270. const sequenceNumber = mode.type === "append"
  271. ? ((_d = lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceNumber) !== null && _d !== void 0 ? _d : 0) + 1
  272. : lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceNumber;
  273. const patchFileName = createPatchFileName({
  274. packageDetails,
  275. packageVersion,
  276. sequenceName,
  277. sequenceNumber,
  278. });
  279. const patchPath = path_1.join(patchesDir, patchFileName);
  280. if (!fs_extra_1.existsSync(path_1.dirname(patchPath))) {
  281. // scoped package
  282. fs_extra_1.mkdirSync(path_1.dirname(patchPath));
  283. }
  284. // if we are inserting a new patch into a sequence we most likely need to update the sequence numbers
  285. if (isRebasing && mode.type === "append") {
  286. const patchesToNudge = existingPatches.slice(state.patches.length);
  287. if (sequenceNumber === undefined) {
  288. throw new Error("sequenceNumber is undefined while rebasing");
  289. }
  290. if (((_e = patchesToNudge[0]) === null || _e === void 0 ? void 0 : _e.sequenceNumber) !== undefined &&
  291. patchesToNudge[0].sequenceNumber <= sequenceNumber) {
  292. let next = sequenceNumber + 1;
  293. for (const p of patchesToNudge) {
  294. const newName = createPatchFileName({
  295. packageDetails,
  296. packageVersion,
  297. sequenceName: p.sequenceName,
  298. sequenceNumber: next++,
  299. });
  300. console_1.default.log("Renaming", chalk_1.default.bold(p.patchFilename), "to", chalk_1.default.bold(newName));
  301. const oldPath = path_1.join(appPath, patchDir, p.patchFilename);
  302. const newPath = path_1.join(appPath, patchDir, newName);
  303. fs_1.renameSync(oldPath, newPath);
  304. }
  305. }
  306. }
  307. fs_extra_1.writeFileSync(patchPath, diffResult.stdout);
  308. console_1.default.log(`${chalk_1.default.green("✔")} Created file ${path_1.join(patchDir, patchFileName)}\n`);
  309. const prevState = patchesToApplyBeforeDiffing.map((p) => ({
  310. patchFilename: p.patchFilename,
  311. didApply: true,
  312. patchContentHash: hash_1.hashFile(path_1.join(appPath, patchDir, p.patchFilename)),
  313. }));
  314. const nextState = [
  315. ...prevState,
  316. {
  317. patchFilename: patchFileName,
  318. didApply: true,
  319. patchContentHash: hash_1.hashFile(patchPath),
  320. },
  321. ];
  322. // if any patches come after this one we just made, we should reapply them
  323. let didFailWhileFinishingRebase = false;
  324. if (isRebasing) {
  325. const currentPatches = patchFs_1.getGroupedPatches(path_1.join(appPath, patchDir))
  326. .pathSpecifierToPatchFiles[packageDetails.pathSpecifier];
  327. const previouslyUnappliedPatches = currentPatches.slice(nextState.length);
  328. if (previouslyUnappliedPatches.length) {
  329. console_1.default.log(`Fast forwarding...`);
  330. for (const patch of previouslyUnappliedPatches) {
  331. const patchFilePath = path_1.join(appPath, patchDir, patch.patchFilename);
  332. if (!applyPatches_1.applyPatch({
  333. patchDetails: patch,
  334. patchDir,
  335. patchFilePath,
  336. reverse: false,
  337. cwd: process.cwd(),
  338. bestEffort: false,
  339. })) {
  340. didFailWhileFinishingRebase = true;
  341. logPatchSequenceError({ patchDetails: patch });
  342. nextState.push({
  343. patchFilename: patch.patchFilename,
  344. didApply: false,
  345. patchContentHash: hash_1.hashFile(patchFilePath),
  346. });
  347. break;
  348. }
  349. else {
  350. console_1.default.log(` ${chalk_1.default.green("✔")} ${patch.patchFilename}`);
  351. nextState.push({
  352. patchFilename: patch.patchFilename,
  353. didApply: true,
  354. patchContentHash: hash_1.hashFile(patchFilePath),
  355. });
  356. }
  357. }
  358. }
  359. }
  360. if (isRebasing || numPatchesAfterCreate > 1) {
  361. stateFile_1.savePatchApplicationState({
  362. packageDetails,
  363. patches: nextState,
  364. isRebasing: didFailWhileFinishingRebase,
  365. });
  366. }
  367. else {
  368. stateFile_1.clearPatchApplicationState(packageDetails);
  369. }
  370. if (canCreateIssue) {
  371. if (createIssue) {
  372. createIssue_1.openIssueCreationLink({
  373. packageDetails,
  374. patchFileContents: diffResult.stdout.toString(),
  375. packageVersion,
  376. });
  377. }
  378. else {
  379. createIssue_1.maybePrintIssueCreationPrompt(vcs, packageDetails, packageManager);
  380. }
  381. }
  382. }
  383. catch (e) {
  384. console_1.default.log(e);
  385. throw e;
  386. }
  387. finally {
  388. tmpRepo.removeCallback();
  389. }
  390. }
  391. exports.makePatch = makePatch;
  392. function createPatchFileName({ packageDetails, packageVersion, sequenceNumber, sequenceName, }) {
  393. const packageNames = packageDetails.packageNames
  394. .map((name) => name.replace(/\//g, "+"))
  395. .join("++");
  396. const nameAndVersion = `${packageNames}+${packageVersion}`;
  397. const num = sequenceNumber === undefined
  398. ? ""
  399. : `+${sequenceNumber.toString().padStart(3, "0")}`;
  400. const name = !sequenceName ? "" : `+${sequenceName}`;
  401. return `${nameAndVersion}${num}${name}.patch`;
  402. }
  403. function logPatchSequenceError({ patchDetails, }) {
  404. console_1.default.log(`
  405. ${chalk_1.default.red.bold("⛔ ERROR")}
  406. Failed to apply patch file ${chalk_1.default.bold(patchDetails.patchFilename)}.
  407. If this patch file is no longer useful, delete it and run
  408. ${chalk_1.default.bold(`patch-package`)}
  409. To partially apply the patch (if possible) and output a log of errors to fix, run
  410. ${chalk_1.default.bold(`patch-package --partial`)}
  411. After which you should make any required changes inside ${patchDetails.path}, and finally run
  412. ${chalk_1.default.bold(`patch-package ${patchDetails.pathSpecifier}`)}
  413. to update the patch file.
  414. `);
  415. }
  416. exports.logPatchSequenceError = logPatchSequenceError;
  417. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFrZVBhdGNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ha2VQYXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxrREFBeUI7QUFDekIsc0RBQTZCO0FBQzdCLDJCQUErQjtBQUMvQix1Q0FPaUI7QUFDakIsbUNBQXVDO0FBQ3ZDLDZCQUE2QjtBQUM3QiwrQkFBK0I7QUFDL0IsaURBQTJDO0FBQzNDLCtDQUtzQjtBQUV0QiwrQ0FBa0Q7QUFDbEQsaUVBQTZEO0FBQzdELDJEQUF1RDtBQUN2RCxpQ0FBaUM7QUFDakMscURBSXlCO0FBQ3pCLHlDQUE4QztBQUM5Qyx1Q0FBNkM7QUFDN0MsaUNBQStDO0FBQy9DLHVGQUFtRjtBQUNuRiwyQ0FBMkM7QUFDM0MsMkNBT29CO0FBRXBCLFNBQVMsd0JBQXdCLENBQy9CLFdBQW1CLEVBQ25CLGVBQXVCO0lBRXZCLGlCQUFPLENBQUMsR0FBRyxDQUNULG1CQUFtQixXQUFXOztvQkFFZCxlQUFlLEVBQUUsQ0FDbEMsQ0FBQTtBQUNILENBQUM7QUFFRCxTQUFnQixTQUFTLENBQUMsRUFDeEIsb0JBQW9CLEVBQ3BCLE9BQU8sRUFDUCxjQUFjLEVBQ2QsWUFBWSxFQUNaLFlBQVksRUFDWixRQUFRLEVBQ1IsV0FBVyxFQUNYLElBQUksR0FVTDs7SUFDQyxNQUFNLGNBQWMsR0FBRyw2Q0FBNEIsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO0lBRXpFLElBQUksQ0FBQyxjQUFjLEVBQUU7UUFDbkIsaUJBQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsb0JBQW9CLENBQUMsQ0FBQTtRQUNwRCxPQUFNO0tBQ1A7SUFFRCxNQUFNLEtBQUssR0FBRyxvQ0FBd0IsQ0FBQyxjQUFjLENBQUMsQ0FBQTtJQUN0RCxNQUFNLFVBQVUsR0FBRyxNQUFBLEtBQUssYUFBTCxLQUFLLHVCQUFMLEtBQUssQ0FBRSxVQUFVLG1DQUFJLEtBQUssQ0FBQTtJQUU3QyxpR0FBaUc7SUFDakcsb0RBQW9E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QUFDOzswREFHckMsWUFBWSxDQUFDLElBQ2Y7O0lBRUUsZUFBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsWUFBWSxDQUFDLGFBQWEsRUFBRSxDQUFDOzs7Q0FHNUQsQ0FBQyxDQUFBO0FBQ0YsQ0FBQztBQTFCRCxzREEwQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCJcbmltcG9ydCBjb25zb2xlIGZyb20gXCJjb25zb2xlXCJcbmltcG9ydCB7IHJlbmFtZVN5bmMgfSBmcm9tIFwiZnNcIlxuaW1wb3J0IHtcbiAgY29weVN5bmMsXG4gIGV4aXN0c1N5bmMsXG4gIG1rZGlycFN5bmMsXG4gIG1rZGlyU3luYyxcbiAgcmVhbHBhdGhTeW5jLFxuICB3cml0ZUZpbGVTeW5jLFxufSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgc3luYyBhcyByaW1yYWYgfSBmcm9tIFwicmltcmFmXCJcbmltcG9ydCB7IGRpclN5bmMgfSBmcm9tIFwidG1wXCJcbmltcG9ydCB7IGd6aXBTeW5jIH0gZnJvbSBcInpsaWJcIlxuaW1wb3J0IHsgYXBwbHlQYXRjaCB9IGZyb20gXCIuL2FwcGx5UGF0Y2hlc1wiXG5pbXBvcnQge1xuICBnZXRQYWNrYWdlVkNTRGV0YWlscyxcbiAgbWF5YmVQcmludElzc3VlQ3JlYXRpb25Qcm9tcHQsXG4gIG9wZW5Jc3N1ZUNyZWF0aW9uTGluayxcbiAgc2hvdWxkUmVjb21tZW5kSXNzdWUsXG59IGZyb20gXCIuL2NyZWF0ZUlzc3VlXCJcbmltcG9ydCB7IFBhY2thZ2VNYW5hZ2VyIH0gZnJvbSBcIi4vZGV0ZWN0UGFja2FnZU1hbmFnZXJcIlxuaW1wb3J0IHsgcmVtb3ZlSWdub3JlZEZpbGVzIH0gZnJvbSBcIi4vZmlsdGVyRmlsZXNcIlxuaW1wb3J0IHsgZ2V0UGFja2FnZVJlc29sdXRpb24gfSBmcm9tIFwiLi9nZXRQYWNrYWdlUmVzb2x1dGlvblwiXG5pbXBvcnQgeyBnZXRQYWNrYWdlVmVyc2lvbiB9IGZyb20gXCIuL2dldFBhY2thZ2VWZXJzaW9uXCJcbmltcG9ydCB7IGhhc2hGaWxlIH0gZnJvbSBcIi4vaGFzaFwiXG5pbXBvcnQge1xuICBnZXRQYXRjaERldGFpbHNGcm9tQ2xpU3RyaW5nLFxuICBQYWNrYWdlRGV0YWlscyxcbiAgUGF0Y2hlZFBhY2thZ2VEZXRhaWxzLFxufSBmcm9tIFwiLi9QYWNrYWdlRGV0YWlsc1wiXG5pbXBvcnQgeyBwYXJzZVBhdGNoRmlsZSB9IGZyb20gXCIuL3BhdGNoL3BhcnNlXCJcbmltcG9ydCB7IGdldEdyb3VwZWRQYXRjaGVzIH0gZnJvbSBcIi4vcGF0Y2hGc1wiXG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luLCByZXNvbHZlIH0gZnJvbSBcIi4vcGF0aFwiXG5pbXBvcnQgeyByZXNvbHZlUmVsYXRpdmVGaWxlRGVwZW5kZW5jaWVzIH0gZnJvbSBcIi4vcmVzb2x2ZVJlbGF0aXZlRmlsZURlcGVuZGVuY2llc1wiXG5pbXBvcnQgeyBzcGF3blNhZmVTeW5jIH0gZnJvbSBcIi4vc3Bhd25TYWZlXCJcbmltcG9ydCB7XG4gIGNsZWFyUGF0Y2hBcHBsaWNhdGlvblN0YXRlLFxuICBnZXRQYXRjaEFwcGxpY2F0aW9uU3RhdGUsXG4gIFBhdGNoU3RhdGUsXG4gIHNhdmVQYXRjaEFwcGxpY2F0aW9uU3RhdGUsXG4gIFNUQVRFX0ZJTEVfTkFNRSxcbiAgdmVyaWZ5QXBwbGllZFBhdGNoZXMsXG59IGZyb20gXCIuL3N0YXRlRmlsZVwiXG5cbmZ1bmN0aW9uIHByaW50Tm9QYWNrYWdlRm91bmRFcnJvcihcbiAgcGFja2FnZU5hbWU6IHN0cmluZyxcbiAgcGFja2FnZUpzb25QYXRoOiBzdHJpbmcsXG4pIHtcbiAgY29uc29sZS5sb2coXG4gICAgYE5vIHN1Y2ggcGFja2FnZSAke3BhY2thZ2VOYW1lfVxuXG4gIEZpbGUgbm90IGZvdW5kOiAke3BhY2thZ2VKc29uUGF0aH1gLFxuICApXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYWtlUGF0Y2goe1xuICBwYWNrYWdlUGF0aFNwZWNpZmllcixcbiAgYXBwUGF0aCxcbiAgcGFja2FnZU1hbmFnZXIsXG4gIGluY2x1ZGVQYXRocyxcbiAgZXhjbHVkZVBhdGhzLFxuICBwYXRjaERpcixcbiAgY3JlYXRlSXNzdWUsXG4gIG1vZGUsXG59OiB7XG4gIHBhY2thZ2VQYXRoU3BlY2lmaWVyOiBzdHJpbmdcbiAgYXBwUGF0aDogc3RyaW5nXG4gIHBhY2thZ2VNYW5hZ2VyOiBQYWNrYWdlTWFuYWdlclxuICBpbmNsdWRlUGF0aHM6IFJlZ0V4cFxuICBleGNsdWRlUGF0aHM6IFJlZ0V4cFxuICBwYXRjaERpcjogc3RyaW5nXG4gIGNyZWF0ZUlzc3VlOiBib29sZWFuXG4gIG1vZGU6IHsgdHlwZTogXCJvdmVyd3JpdGVfbGFzdFwiIH0gfCB7IHR5cGU6IFwiYXBwZW5kXCI7IG5hbWU/OiBzdHJpbmcgfVxufSkge1xuICBjb25zdCBwYWNrYWdlRGV0YWlscyA9IGdldFBhdGNoRGV0YWlsc0Zyb21DbGlTdHJpbmcocGFja2FnZVBhdGhTcGVjaWZpZXIpXG5cbiAgaWYgKCFwYWNrYWdlRGV0YWlscykge1xuICAgIGNvbnNvbGUubG9nKFwiTm8gc3VjaCBwYWNrYWdlXCIsIHBhY2thZ2VQYXRoU3BlY2lmaWVyKVxuICAgIHJldHVyblxuICB9XG5cbiAgY29uc3Qgc3RhdGUgPSBnZXRQYXRjaEFwcGxpY2F0aW9uU3RhdGUocGFja2FnZURldGFpbHMpXG4gIGNvbnN0IGlzUmViYXNpbmcgPSBzdGF0ZT8uaXNSZWJhc2luZyA/PyBmYWxzZVxuXG4gIC8vIElmIHdlIGFyZSByZWJhc2luZyBhbmQgbm8gcGF0Y2hlcyBoYXZlIGJlZW4gYXBwbGllZCwgLS1hcHBlbmQgaXMgdGhlIG9ubHkgdmFsaWQgb3B0aW9uIGJlY2F1c2VcbiAgLy8gdGhlcmUgYXJlIG5vIHByZXZpb3VzIHBhdGNoZXMgdG8gb3ZlcndyaXRlL3VwZGF0ZVxuICBpZiAoXG4gICAgaXNSZWJhc2luZyAmJlxuICAgIHN0YXRlPy5wYXRjaGVzLmZpbHRlcigocCkgPT4gcC5kaWRBcHBseSkubGVuZ3RoID09PSAwICYmXG4gICAgbW9kZS50eXBlID09PSBcIm92ZXJ3cml0ZV9sYXN0XCJcbiAgKSB7XG4gICAgbW9kZSA9IHsgdHlwZTogXCJhcHBlbmRcIiwgbmFtZTogXCJpbml0aWFsXCIgfVxuICB9XG5cbiAgaWYgKGlzUmViYXNpbmcgJiYgc3RhdGUpIHtcbiAgICB2ZXJpZnlBcHBsaWVkUGF0Y2hlcyh7IGFwcFBhdGgsIHBhdGNoRGlyLCBzdGF0ZSB9KVxuICB9XG5cbiAgaWYgKFxuICAgIG1vZGUudHlwZSA9PT0gXCJvdmVyd3JpdGVfbGFzdFwiICYmXG4gICAgaXNSZWJhc2luZyAmJlxuICAgIHN0YXRlPy5wYXRjaGVzLmxlbmd0aCA9PT0gMFxuICApIHtcbiAgICBtb2RlID0geyB0eXBlOiBcImFwcGVuZFwiLCBuYW1lOiBcImluaXRpYWxcIiB9XG4gIH1cblxuICBjb25zdCBleGlzdGluZ1BhdGNoZXMgPVxuICAgIGdldEdyb3VwZWRQYXRjaGVzKHBhdGNoRGlyKS5wYXRoU3BlY2lmaWVyVG9QYXRjaEZpbGVzW1xuICAgICAgcGFja2FnZURldGFpbHMucGF0aFNwZWNpZmllclxuICAgIF0gfHwgW11cblxuICAvLyBhcHBseSBhbGwgZXhpc3RpbmcgcGF0Y2hlcyBpZiBhcHBlbmRpbmdcbiAgLy8gb3RoZXJ3aXNlIGFwcGx5IGFsbCBidXQgdGhlIGxhc3RcbiAgY29uc3QgcHJldmlvdXNseUFwcGxpZWRQYXRjaGVzID0gc3RhdGU/LnBhdGNoZXMuZmlsdGVyKChwKSA9PiBwLmRpZEFwcGx5KVxuICBjb25zdCBwYXRjaGVzVG9BcHBseUJlZm9yZURpZmZpbmc6IFBhdGNoZWRQYWNrYWdlRGV0YWlsc1tdID0gaXNSZWJhc2luZ1xuICAgID8gbW9kZS50eXBlID09PSBcImFwcGVuZFwiXG4gICAgICA/IGV4aXN0aW5nUGF0Y2hlcy5zbGljZSgwLCBwcmV2aW91c2x5QXBwbGllZFBhdGNoZXMhLmxlbmd0aClcbiAgICAgIDogc3RhdGUhLnBhdGNoZXNbc3RhdGUhLnBhdGNoZXMubGVuZ3RoIC0gMV0uZGlkQXBwbHlcbiAgICAgID8gZXhpc3RpbmdQYXRjaGVzLnNsaWNlKDAsIHByZXZpb3VzbHlBcHBsaWVkUGF0Y2hlcyEubGVuZ3RoIC0gMSlcbiAgICAgIDogZXhpc3RpbmdQYXRjaGVzLnNsaWNlKDAsIHByZXZpb3VzbHlBcHBsaWVkUGF0Y2hlcyEubGVuZ3RoKVxuICAgIDogbW9kZS50eXBlID09PSBcImFwcGVuZFwiXG4gICAgPyBleGlzdGluZ1BhdGNoZXNcbiAgICA6IGV4aXN0aW5nUGF0Y2hlcy5zbGljZSgwLCAtMSlcblxuICBpZiAoY3JlYXRlSXNzdWUgJiYgbW9kZS50eXBlID09PSBcImFwcGVuZFwiKSB7XG4gICAgY29uc29sZS5sb2coXCItLWNyZWF0ZS1pc3N1ZSBpcyBub3QgY29tcGF0aWJsZSB3aXRoIC0tYXBwZW5kLlwiKVxuICAgIHByb2Nlc3MuZXhpdCgxKVxuICB9XG5cbiAgaWYgKGNyZWF0ZUlzc3VlICYmIGlzUmViYXNpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhcIi0tY3JlYXRlLWlzc3VlIGlzIG5vdCBjb21wYXRpYmxlIHdpdGggcmViYXNpbmcuXCIpXG4gICAgcHJvY2Vzcy5leGl0KDEpXG4gIH1cblxuICBjb25zdCBudW1QYXRjaGVzQWZ0ZXJDcmVhdGUgPVxuICAgIG1vZGUudHlwZSA9PT0gXCJhcHBlbmRcIiB8fCBleGlzdGluZ1BhdGNoZXMubGVuZ3RoID09PSAwXG4gICAgICA/IGV4aXN0aW5nUGF0Y2hlcy5sZW5ndGggKyAxXG4gICAgICA6IGV4aXN0aW5nUGF0Y2hlcy5sZW5ndGhcbiAgY29uc3QgdmNzID0gZ2V0UGFja2FnZVZDU0RldGFpbHMocGFja2FnZURldGFpbHMpXG4gIGNvbnN0IGNhbkNyZWF0ZUlzc3VlID1cbiAgICAhaXNSZWJhc2luZyAmJlxuICAgIHNob3VsZFJlY29tbWVuZElzc3VlKHZjcykgJiZcbiAgICBudW1QYXRjaGVzQWZ0ZXJDcmVhdGUgPT09IDEgJiZcbiAgICBtb2RlLnR5cGUgIT09IFwiYXBwZW5kXCJcblxuICBjb25zdCBhcHBQYWNrYWdlSnNvbiA9IHJlcXVpcmUoam9pbihhcHBQYXRoLCBcInBhY2thZ2UuanNvblwiKSlcbiAgY29uc3QgcGFja2FnZVBhdGggPSBqb2luKGFwcFBhdGgsIHBhY2thZ2VEZXRhaWxzLnBhdGgpXG4gIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IGpvaW4ocGFja2FnZVBhdGgsIFwicGFja2FnZS5qc29uXCIpXG5cbiAgaWYgKCFleGlzdHNTeW5jKHBhY2thZ2VKc29uUGF0aCkpIHtcbiAgICBwcmludE5vUGFja2FnZUZvdW5kRXJyb3IocGFja2FnZVBhdGhTcGVjaWZpZXIsIHBhY2thZ2VKc29uUGF0aClcbiAgICBwcm9jZXNzLmV4aXQoMSlcbiAgfVxuXG4gIGNvbnN0IHRtcFJlcG8gPSBkaXJTeW5jKHsgdW5zYWZlQ2xlYW51cDogdHJ1ZSB9KVxuICBjb25zdCB0bXBSZXBvUGFja2FnZVBhdGggPSBqb2luKHRtcFJlcG8ubmFtZSwgcGFja2FnZURldGFpbHMucGF0aClcbiAgY29uc3QgdG1wUmVwb05wbVJvb3QgPSB0bXBSZXBvUGFja2FnZVBhdGguc2xpY2UoXG4gICAgMCxcbiAgICAtYC9ub2RlX21vZHVsZXMvJHtwYWNrYWdlRGV0YWlscy5uYW1lfWAubGVuZ3RoLFxuICApXG5cbiAgY29uc3QgdG1wUmVwb1BhY2thZ2VKc29uUGF0aCA9IGpvaW4odG1wUmVwb05wbVJvb3QsIFwicGFja2FnZS5qc29uXCIpXG5cbiAgdHJ5IHtcbiAgICBjb25zdCBwYXRjaGVzRGlyID0gcmVzb2x2ZShqb2luKGFwcFBhdGgsIHBhdGNoRGlyKSlcblxuICAgIGNvbnNvbGUuaW5mbyhjaGFsay5ncmV5KFwi4oCiXCIpLCBcIkNyZWF0aW5nIHRlbXBvcmFyeSBmb2xkZXJcIilcblxuICAgIC8vIG1ha2UgYSBibGFuayBwYWNrYWdlLmpzb25cbiAgICBta2RpcnBTeW5jKHRtcFJlcG9OcG1Sb290KVxuICAgIHdyaXRlRmlsZVN5bmMoXG4gICAgICB0bXBSZXBvUGFja2FnZUpzb25QYXRoLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBkZXBlbmRlbmNpZXM6IHtcbiAgICAgICAgICBbcGFja2FnZURldGFpbHMubmFtZV06IGdldFBhY2thZ2VSZXNvbHV0aW9uKHtcbiAgICAgICAgICAgIHBhY2thZ2VEZXRhaWxzLFxuICAgICAgICAgICAgcGFja2FnZU1hbmFnZXIsXG4gICAgICAgICAgICBhcHBQYXRoLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9LFxuICAgICAgICByZXNvbHV0aW9uczogcmVzb2x2ZVJlbGF0aXZlRmlsZURlcGVuZGVuY2llcyhcbiAgICAgICAgICBhcHBQYXRoLFxuICAgICAgICAgIGFwcFBhY2thZ2VKc29uLnJlc29sdXRpb25zIHx8IHt9LFxuICAgICAgICApLFxuICAgICAgfSksXG4gICAgKVxuXG4gICAgY29uc3QgcGFja2FnZVZlcnNpb24gPSBnZXRQYWNrYWdlVmVyc2lvbihcbiAgICAgIGpvaW4ocmVzb2x2ZShwYWNrYWdlRGV0YWlscy5wYXRoKSwgXCJwYWNrYWdlLmpzb25cIiksXG4gICAgKVxuXG4gICAgLy8gY29weSAubnBtcmMvLnlhcm5yYyBpbiBjYXNlIHBhY2thZ2VzIGFyZSBob3N0ZWQgaW4gcHJpdmF0ZSByZWdpc3RyeVxuICAgIC8vIGNvcHkgLnlhcm4gZGlyZWN0b3J5IGFzIHdlbGwgdG8gZW5zdXJlIGluc3RhbGxhdGlvbnMgd29yayBpbiB5YXJuIDJcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6YWxpZ25cbiAgICA7W1wiLm5wbXJjXCIsIFwiLnlhcm5yY1wiLCBcIi55YXJuXCJdLmZvckVhY2goKHJjRmlsZSkgPT4ge1xuICAgICAgY29uc3QgcmNQYXRoID0gam9pbihhcHBQYXRoLCByY0ZpbGUpXG4gICAgICBpZiAoZXhpc3RzU3luYyhyY1BhdGgpKSB7XG4gICAgICAgIGNvcHlTeW5jKHJjUGF0aCwgam9pbih0bXBSZXBvLm5hbWUsIHJjRmlsZSksIHsgZGVyZWZlcmVuY2U6IHRydWUgfSlcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgaWYgKHBhY2thZ2VNYW5hZ2VyID09PSBcInlhcm5cIikge1xuICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICBjaGFsay5ncmV5KFwi4oCiXCIpLFxuICAgICAgICBgSW5zdGFsbGluZyAke3BhY2thZ2VEZXRhaWxzLm5hbWV9QCR7cGFja2FnZVZlcnNpb259IHdpdGggeWFybmAsXG4gICAgICApXG4gICAgICB0cnkge1xuICAgICAgICAvLyB0cnkgZmlyc3Qgd2l0aG91dCBpZ25vcmluZyBzY3JpcHRzIGluIGNhc2UgdGhleSBhcmUgcmVxdWlyZWRcbiAgICAgICAgLy8gdGhpcyB3b3JrcyBpbiA5OS45OSUgb2YgY2FzZXNcbiAgICAgICAgc3Bhd25TYWZlU3luYyhgeWFybmAsIFtcImluc3RhbGxcIiwgXCItLWlnbm9yZS1lbmdpbmVzXCJdLCB7XG4gICAgICAgICAgY3dkOiB0bXBSZXBvTnBtUm9vdCxcbiAgICAgICAgICBsb2dTdGRFcnJPbkVycm9yOiBmYWxzZSxcbiAgICAgICAgfSlcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gdHJ5IGFnYWluIHdoaWxlIGlnbm9yaW5nIHNjcmlwdHMgaW4gY2FzZSB0aGUgc2NyaXB0IGRlcGVuZHMgb25cbiAgICAgICAgLy8gYW4gaW1wbGljaXQgY29udGV4dCB3aGljaCB3ZSBoYXZlbid0IHJlcHJvZHVjZWRcbiAgICAgICAgc3Bhd25TYWZlU3luYyhcbiAgICAgICAgICBgeWFybmAsXG4gICAgICAgICAgW1wiaW5zdGFsbFwiLCBcIi0taWdub3JlLWVuZ2luZXNcIiwgXCItLWlnbm9yZS1zY3JpcHRzXCJdLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGN3ZDogdG1wUmVwb05wbVJvb3QsXG4gICAgICAgICAgfSxcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgIGNoYWxrLmdyZXkoXCLigKJcIiksXG4gICAgICAgIGBJbnN0YWxsaW5nICR7cGFja2FnZURldGFpbHMubmFtZX1AJHtwYWNrYWdlVmVyc2lvbn0gd2l0aCBucG1gLFxuICAgICAgKVxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gdHJ5IGZpcnN0IHdpdGhvdXQgaWdub3Jpbmcgc2NyaXB0cyBpbiBjYXNlIHRoZXkgYXJlIHJlcXVpcmVkXG4gICAgICAgIC8vIHRoaXMgd29ya3MgaW4gOTkuOTklIG9mIGNhc2VzXG4gICAgICAgIHNwYXduU2FmZVN5bmMoYG5wbWAsIFtcImlcIiwgXCItLWZvcmNlXCJdLCB7XG4gICAgICAgICAgY3dkOiB0bXBSZXBvTnBtUm9vdCxcbiAgICAgICAgICBsb2dTdGRFcnJPbkVycm9yOiBmYWxzZSxcbiAgICAgICAgICBzdGRpbzogXCJpZ25vcmVcIixcbiAgICAgICAgfSlcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gdHJ5IGFnYWluIHdoaWxlIGlnbm9yaW5nIHNjcmlwdHMgaW4gY2FzZSB0aGUgc2NyaXB0IGRlcGVuZHMgb25cbiAgICAgICAgLy8gYW4gaW1wbGljaXQgY29udGV4dCB3aGljaCB3ZSBoYXZlbid0IHJlcHJvZHVjZWRcbiAgICAgICAgc3Bhd25TYWZlU3luYyhgbnBtYCwgW1wiaVwiLCBcIi0taWdub3JlLXNjcmlwdHNcIiwgXCItLWZvcmNlXCJdLCB7XG4gICAgICAgICAgY3dkOiB0bXBSZXBvTnBtUm9vdCxcbiAgICAgICAgICBzdGRpbzogXCJpZ25vcmVcIixcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBnaXQgPSAoLi4uYXJnczogc3RyaW5nW10pID0+XG4gICAgICBzcGF3blNhZmVTeW5jKFwiZ2l0XCIsIGFyZ3MsIHtcbiAgICAgICAgY3dkOiB0bXBSZXBvLm5hbWUsXG4gICAgICAgIGVudjogeyAuLi5wcm9jZXNzLmVudiwgSE9NRTogdG1wUmVwby5uYW1lIH0sXG4gICAgICAgIG1heEJ1ZmZlcjogMTAyNCAqIDEwMjQgKiAxMDAsXG4gICAgICB9KVxuXG4gICAgLy8gcmVtb3ZlIG5lc3RlZCBub2RlX21vZHVsZXMganVzdCB0byBiZSBzYWZlXG4gICAgcmltcmFmKGpvaW4odG1wUmVwb1BhY2thZ2VQYXRoLCBcIm5vZGVfbW9kdWxlc1wiKSlcbiAgICAvLyByZW1vdmUgLmdpdCBqdXN0IHRvIGJlIHNhZmVcbiAgICByaW1yYWYoam9pbih0bXBSZXBvUGFja2FnZVBhdGgsIFwiLmdpdFwiKSlcbiAgICAvLyByZW1vdmUgcGF0Y2gtcGFja2FnZSBzdGF0ZSBmaWxlXG4gICAgcmltcmFmKGpvaW4odG1wUmVwb1BhY2thZ2VQYXRoLCBTVEFURV9GSUxFX05BTUUpKVxuXG4gICAgLy8gY29tbWl0IHRoZSBwYWNrYWdlXG4gICAgY29uc29sZS5pbmZvKGNoYWxrLmdyZXkoXCLigKJcIiksIFwiRGlmZmluZyB5b3VyIGZpbGVzIHdpdGggY2xlYW4gZmlsZXNcIilcbiAgICB3cml0ZUZpbGVTeW5jKGpvaW4odG1wUmVwby5uYW1lLCBcIi5naXRpZ25vcmVcIiksIFwiIS9ub2RlX21vZHVsZXNcXG5cXG5cIilcbiAgICBnaXQoXCJpbml0XCIpXG4gICAgZ2l0KFwiY29uZmlnXCIsIFwiLS1sb2NhbFwiLCBcInVzZXIubmFtZVwiLCBcInBhdGNoLXBhY2thZ2VcIilcbiAgICBnaXQoXCJjb25maWdcIiwgXCItLWxvY2FsXCIsIFwidXNlci5lbWFpbFwiLCBcInBhdGNoQHBhY2suYWdlXCIpXG5cbiAgICAvLyByZW1vdmUgaWdub3JlZCBmaWxlcyBmaXJzdFxuICAgIHJlbW92ZUlnbm9yZWRGaWxlcyh0bXBSZXBvUGFja2FnZVBhdGgsIGluY2x1ZGVQYXRocywgZXhjbHVkZVBhdGhzKVxuXG4gICAgZm9yIChjb25zdCBwYXRjaERldGFpbHMgb2YgcGF0Y2hlc1RvQXBwbHlCZWZvcmVEaWZmaW5nKSB7XG4gICAgICBpZiAoXG4gICAgICAgICFhcHBseVBhdGNoKHtcbiAgICAgICAgICBwYXRjaERldGFpbHMsXG4gICAgICAgICAgcGF0Y2hEaXIsXG4gICAgICAgICAgcGF0Y2hGaWxlUGF0aDogam9pbihhcHBQYXRoLCBwYXRjaERpciwgcGF0Y2hEZXRhaWxzLnBhdGNoRmlsZW5hbWUpLFxuICAgICAgICAgIHJldmVyc2U6IGZhbHNlLFxuICAgICAgICAgIGN3ZDogdG1wUmVwby5uYW1lLFxuICAgICAgICAgIGJlc3RFZmZvcnQ6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKSB7XG4gICAgICAgIC8vIFRPRE86IGFkZCBiZXR0ZXIgZXJyb3IgbWVzc2FnZSBvbmNlIC0tcmViYXNlIGlzIGltcGxlbWVudGVkXG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBGYWlsZWQgdG8gYXBwbHkgcGF0Y2ggJHtwYXRjaERldGFpbHMucGF0Y2hGaWxlbmFtZX0gdG8gJHtwYWNrYWdlRGV0YWlscy5wYXRoU3BlY2lmaWVyfWAsXG4gICAgICAgIClcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpXG4gICAgICB9XG4gICAgfVxuICAgIGdpdChcImFkZFwiLCBcIi1mXCIsIHBhY2thZ2VEZXRhaWxzLnBhdGgpXG4gICAgZ2l0KFwiY29tbWl0XCIsIFwiLS1hbGxvdy1lbXB0eVwiLCBcIi1tXCIsIFwiaW5pdFwiKVxuXG4gICAgLy8gcmVwbGFjZSBwYWNrYWdlIHdpdGggdXNlcidzIHZlcnNpb25cbiAgICByaW1yYWYodG1wUmVwb1BhY2thZ2VQYXRoKVxuXG4gICAgLy8gcG5wbSBpbnN0YWxscyBwYWNrYWdlcyBhcyBzeW1saW5rcywgY29weVN5bmMgd291bGQgY29weSBvbmx5IHRoZSBzeW1saW5rXG4gICAgY29weVN5bmMocmVhbHBhdGhTeW5jKHBhY2thZ2VQYXRoKSwgdG1wUmVwb1BhY2thZ2VQYXRoKVxuXG4gICAgLy8gcmVtb3ZlIG5lc3RlZCBub2RlX21vZHVsZXMganVzdCB0byBiZSBzYWZlXG4gICAgcmltcmFmKGpvaW4odG1wUmVwb1BhY2thZ2VQYXRoLCBcIm5vZGVfbW9kdWxlc1wiKSlcbiAgICAvLyByZW1vdmUgLmdpdCBqdXN0IHRvIGJlIHNhZmVcbiAgICByaW1yYWYoam9pbih0bXBSZXBvUGFja2FnZVBhdGgsIFwiLmdpdFwiKSlcbiAgICAvLyByZW1vdmUgcGF0Y2gtcGFja2FnZSBzdGF0ZSBmaWxlXG4gICAgcmltcmFmKGpvaW4odG1wUmVwb1BhY2thZ2VQYXRoLCBTVEFURV9GSUxFX05BTUUpKVxuXG4gICAgLy8gYWxzbyByZW1vdmUgaWdub3JlZCBmaWxlcyBsaWtlIGJlZm9yZVxuICAgIHJlbW92ZUlnbm9yZWRGaWxlcyh0bXBSZXBvUGFja2FnZVBhdGgsIGluY2x1ZGVQYXRocywgZXhjbHVkZVBhdGhzKVxuXG4gICAgLy8gc3RhZ2UgYWxsIGZpbGVzXG4gICAgZ2l0KFwiYWRkXCIsIFwiLWZcIiwgcGFja2FnZURldGFpbHMucGF0aClcblxuICAgIC8vIGdldCBkaWZmIG9mIGNoYW5nZXNcbiAgICBjb25zdCBkaWZmUmVzdWx0ID0gZ2l0KFxuICAgICAgXCJkaWZmXCIsXG4gICAgICBcIi0tY2FjaGVkXCIsXG4gICAgICBcIi0tbm8tY29sb3JcIixcbiAgICAgIFwiLS1pZ25vcmUtc3BhY2UtYXQtZW9sXCIsXG4gICAgICBcIi0tbm8tZXh0LWRpZmZcIixcbiAgICAgIFwiLS1zcmMtcHJlZml4PWEvXCIsXG4gICAgICBcIi0tZHN0LXByZWZpeD1iL1wiLFxuICAgIClcblxuICAgIGlmIChkaWZmUmVzdWx0LnN0ZG91dC5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBg4oGJ77iPICBOb3QgY3JlYXRpbmcgcGF0Y2ggZmlsZSBmb3IgcGFja2FnZSAnJHtwYWNrYWdlUGF0aFNwZWNpZmllcn0nYCxcbiAgICAgIClcbiAgICAgIGNvbnNvbGUubG9nKGDigYnvuI8gIFRoZXJlIGRvbid0IGFwcGVhciB0byBiZSBhbnkgY2hhbmdlcy5gKVxuICAgICAgaWYgKGlzUmViYXNpbmcgJiYgbW9kZS50eXBlID09PSBcIm92ZXJ3cml0ZV9sYXN0XCIpIHtcbiAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgXCJcXG7wn5KhIFRvIHJlbW92ZSBhIHBhdGNoIGZpbGUsIGRlbGV0ZSBpdCBhbmQgdGhlbiByZWluc3RhbGwgbm9kZV9tb2R1bGVzIGZyb20gc2NyYXRjaC5cIixcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgcHJvY2Vzcy5leGl0KDEpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgcGFyc2VQYXRjaEZpbGUoZGlmZlJlc3VsdC5zdGRvdXQudG9TdHJpbmcoKSlcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoXG4gICAgICAgIChlIGFzIEVycm9yKS5tZXNzYWdlLmluY2x1ZGVzKFwiVW5leHBlY3RlZCBmaWxlIG1vZGUgc3RyaW5nOiAxMjAwMDBcIilcbiAgICAgICkge1xuICAgICAgICBjb25zb2xlLmxvZyhgXG7im5TvuI8gJHtjaGFsay5yZWQuYm9sZChcIkVSUk9SXCIpfVxuXG4gIFlvdXIgY2hhbmdlcyBpbnZvbHZlIGNyZWF0aW5nIHN5bWxpbmtzLiBwYXRjaC1wYWNrYWdlIGRvZXMgbm90IHlldCBzdXBwb3J0XG4gIHN5bWxpbmtzLlxuICBcbiAg77iPUGxlYXNlIHVzZSAke2NoYWxrLmJvbGQoXCItLWluY2x1ZGVcIil9IGFuZC9vciAke2NoYWxrLmJvbGQoXG4gICAgICAgICAgXCItLWV4Y2x1ZGVcIixcbiAgICAgICAgKX0gdG8gbmFycm93IHRoZSBzY29wZSBvZiB5b3VyIHBhdGNoIGlmXG4gIHRoaXMgd2FzIHVuaW50ZW50aW9uYWwuXG5gKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3Qgb3V0UGF0aCA9IFwiLi9wYXRjaC1wYWNrYWdlLWVycm9yLmpzb24uZ3pcIlxuICAgICAgICB3cml0ZUZpbGVTeW5jKFxuICAgICAgICAgIG91dFBhdGgsXG4gICAgICAgICAgZ3ppcFN5bmMoXG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIGVycm9yOiB7IG1lc3NhZ2U6IGUubWVzc2FnZSwgc3RhY2s6IGUuc3RhY2sgfSxcbiAgICAgICAgICAgICAgcGF0Y2g6IGRpZmZSZXN1bHQuc3Rkb3V0LnRvU3RyaW5nKCksXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApLFxuICAgICAgICApXG4gICAgICAgIGNvbnNvbGUubG9nKGBcbuKblO+4jyAke2NoYWxrLnJlZC5ib2xkKFwiRVJST1JcIil9XG4gICAgICAgIFxuICBwYXRjaC1wYWNrYWdlIHdhcyB1bmFibGUgdG8gcmVhZCB0aGUgcGF0Y2gtZmlsZSBtYWRlIGJ5IGdpdC4gVGhpcyBzaG91bGQgbm90XG4gIGhhcHBlbi5cbiAgXG4gIEEgZGlhZ25vc3RpYyBmaWxlIHdhcyB3cml0dGVuIHRvXG4gIFxuICAgICR7b3V0UGF0aH1cbiAgXG4gIFBsZWFzZSBhdHRhY2ggaXQgdG8gYSBnaXRodWIgaXNzdWVcbiAgXG4gICAgaHR0cHM6Ly9naXRodWIuY29tL2RzMzAwL3BhdGNoLXBhY2thZ2UvaXNzdWVzL25ldz90aXRsZT1OZXcrcGF0Y2grcGFyc2UrZmFpbGVkJmJvZHk9UGxlYXNlK2F0dGFjaCt0aGUrZGlhZ25vc3RpYytmaWxlK2J5K2RyYWdnaW5nK2l0K2ludG8raGVyZSvwn5mPXG4gIFxuICBOb3RlIHRoYXQgdGhpcyBkaWFnbm9zdGljIGZpbGUgd2lsbCBjb250YWluIGNvZGUgZnJvbSB0aGUgcGFja2FnZSB5b3Ugd2VyZVxuICBhdHRlbXB0aW5nIHRvIHBhdGNoLlxuXG5gKVxuICAgICAgfVxuICAgICAgcHJvY2Vzcy5leGl0KDEpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBtYXliZSBkZWxldGUgZXhpc3RpbmdcbiAgICBpZiAobW9kZS50eXBlID09PSBcImFwcGVuZFwiICYmICFpc1JlYmFzaW5nICYmIGV4aXN0aW5nUGF0Y2hlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgIC8vIGlmIHdlIGFyZSBhcHBlbmRpbmcgdG8gYW4gZXhpc3RpbmcgcGF0Y2ggdGhhdCBkb2Vzbid0IGhhdmUgYSBzZXF1ZW5jZSBudW1iZXIgbGV0J3MgcmVuYW1lIGl0XG4gICAgICBjb25zdCBwcmV2UGF0Y2ggPSBleGlzdGluZ1BhdGNoZXNbMF1cbiAgICAgIGlmIChwcmV2UGF0Y2guc2VxdWVuY2VOdW1iZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCBuZXdGaWxlTmFtZSA9IGNyZWF0ZVBhdGNoRmlsZU5hbWUoe1xuICAgICAgICAgIHBhY2thZ2VEZXRhaWxzLFxuICAgICAgICAgIHBhY2thZ2VWZXJzaW9uLFxuICAgICAgICAgIHNlcXVlbmNlTnVtYmVyOiAxLFxuICAgICAgICAgIHNlcXVlbmNlTmFtZTogcHJldlBhdGNoLnNlcXVlbmNlTmFtZSA/PyBcImluaXRpYWxcIixcbiAgICAgICAgfSlcbiAgICAgICAgY29uc3Qgb2xkUGF0aCA9IGpvaW4oYXBwUGF0aCwgcGF0Y2hEaXIsIHByZXZQYXRjaC5wYXRjaEZpbGVuYW1lKVxuICAgICAgICBjb25zdCBuZXdQYXRoID0gam9pbihhcHBQYXRoLCBwYXRjaERpciwgbmV3RmlsZU5hbWUpXG4gICAgICAgIHJlbmFtZVN5bmMob2xkUGF0aCwgbmV3UGF0aClcbiAgICAgICAgcHJldlBhdGNoLnNlcXVlbmNlTnVtYmVyID0gMVxuICAgICAgICBwcmV2UGF0Y2gucGF0Y2hGaWxlbmFtZSA9IG5ld0ZpbGVOYW1lXG4gICAgICAgIHByZXZQYXRjaC5zZXF1ZW5jZU5hbWUgPSBwcmV2UGF0Y2guc2VxdWVuY2VOYW1lID8/IFwiaW5pdGlhbFwiXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbGFzdFBhdGNoID0gZXhpc3RpbmdQYXRjaGVzW1xuICAgICAgc3RhdGUgPyBzdGF0ZS5wYXRjaGVzLmxlbmd0aCAtIDEgOiBleGlzdGluZ1BhdGNoZXMubGVuZ3RoIC0gMVxuICAgIF0gYXMgUGF0Y2hlZFBhY2thZ2VEZXRhaWxzIHwgdW5kZWZpbmVkXG4gICAgY29uc3Qgc2VxdWVuY2VOYW1lID1cbiAgICAgIG1vZGUudHlwZSA9PT0gXCJhcHBlbmRcIiA/IG1vZGUubmFtZSA6IGxhc3RQYXRjaD8uc2VxdWVuY2VOYW1lXG4gICAgY29uc3Qgc2VxdWVuY2VOdW1iZXIgPVxuICAgICAgbW9kZS50eXBlID09PSBcImFwcGVuZFwiXG4gICAgICAgID8gKGxhc3RQYXRjaD8uc2VxdWVuY2VOdW1iZXIgPz8gMCkgKyAxXG4gICAgICAgIDogbGFzdFBhdGNoPy5zZXF1ZW5jZU51bWJlclxuXG4gICAgY29uc3QgcGF0Y2hGaWxlTmFtZSA9IGNyZWF0ZVBhdGNoRmlsZU5hbWUoe1xuICAgICAgcGFja2FnZURldGFpbHMsXG4gICAgICBwYWNrYWdlVmVyc2lvbixcbiAgICAgIHNlcXVlbmNlTmFtZSxcbiAgICAgIHNlcXVlbmNlTnVtYmVyLFxuICAgIH0pXG5cbiAgICBjb25zdCBwYXRjaFBhdGggPSBqb2luKHBhdGNoZXNEaXIsIHBhdGNoRmlsZU5hbWUpXG4gICAgaWYgKCFleGlzdHNTeW5jKGRpcm5hbWUocGF0Y2hQYXRoKSkpIHtcbiAgICAgIC8vIHNjb3BlZCBwYWNrYWdlXG4gICAgICBta2RpclN5bmMoZGlybmFtZShwYXRjaFBhdGgpKVxuICAgIH1cblxuICAgIC8vIGlmIHdlIGFyZSBpbnNlcnRpbmcgYSBuZXcgcGF0Y2ggaW50byBhIHNlcXVlbmNlIHdlIG1vc3QgbGlrZWx5IG5lZWQgdG8gdXBkYXRlIHRoZSBzZXF1ZW5jZSBudW1iZXJzXG4gICAgaWYgKGlzUmViYXNpbmcgJiYgbW9kZS50eXBlID09PSBcImFwcGVuZFwiKSB7XG4gICAgICBjb25zdCBwYXRjaGVzVG9OdWRnZSA9IGV4aXN0aW5nUGF0Y2hlcy5zbGljZShzdGF0ZSEucGF0Y2hlcy5sZW5ndGgpXG4gICAgICBpZiAoc2VxdWVuY2VOdW1iZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZXF1ZW5jZU51bWJlciBpcyB1bmRlZmluZWQgd2hpbGUgcmViYXNpbmdcIilcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgcGF0Y2hlc1RvTnVkZ2VbMF0/LnNlcXVlbmNlTnVtYmVyICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgcGF0Y2hlc1RvTnVkZ2VbMF0uc2VxdWVuY2VOdW1iZXIgPD0gc2VxdWVuY2VOdW1iZXJcbiAgICAgICkge1xuICAgICAgICBsZXQgbmV4dCA9IHNlcXVlbmNlTnVtYmVyICsgMVxuICAgICAgICBmb3IgKGNvbnN0IHAgb2YgcGF0Y2hlc1RvTnVkZ2UpIHtcbiAgICAgICAgICBjb25zdCBuZXdOYW1lID0gY3JlYXRlUGF0Y2hGaWxlTmFtZSh7XG4gICAgICAgICAgICBwYWNrYWdlRGV0YWlscyxcbiAgICAgICAgICAgIHBhY2thZ2VWZXJzaW9uLFxuICAgICAgICAgICAgc2VxdWVuY2VOYW1lOiBwLnNlcXVlbmNlTmFtZSxcbiAgICAgICAgICAgIHNlcXVlbmNlTnVtYmVyOiBuZXh0KyssXG4gICAgICAgICAgfSlcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIFwiUmVuYW1pbmdcIixcbiAgICAgICAgICAgIGNoYWxrLmJvbGQocC5wYXRjaEZpbGVuYW1lKSxcbiAgICAgICAgICAgIFwidG9cIixcbiAgICAgICAgICAgIGNoYWxrLmJvbGQobmV3TmFtZSksXG4gICAgICAgICAgKVxuICAgICAgICAgIGNvbnN0IG9sZFBhdGggPSBqb2luKGFwcFBhdGgsIHBhdGNoRGlyLCBwLnBhdGNoRmlsZW5hbWUpXG4gICAgICAgICAgY29uc3QgbmV3UGF0aCA9IGpvaW4oYXBwUGF0aCwgcGF0Y2hEaXIsIG5ld05hbWUpXG4gICAgICAgICAgcmVuYW1lU3luYyhvbGRQYXRoLCBuZXdQYXRoKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgd3JpdGVGaWxlU3luYyhwYXRjaFBhdGgsIGRpZmZSZXN1bHQuc3Rkb3V0KVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYCR7Y2hhbGsuZ3JlZW4oXCLinJRcIil9IENyZWF0ZWQgZmlsZSAke2pvaW4ocGF0Y2hEaXIsIHBhdGNoRmlsZU5hbWUpfVxcbmAsXG4gICAgKVxuXG4gICAgY29uc3QgcHJldlN0YXRlOiBQYXRjaFN0YXRlW10gPSBwYXRjaGVzVG9BcHBseUJlZm9yZURpZmZpbmcubWFwKFxuICAgICAgKHApOiBQYXRjaFN0YXRlID0+ICh7XG4gICAgICAgIHBhdGNoRmlsZW5hbWU6IHAucGF0Y2hGaWxlbmFtZSxcbiAgICAgICAgZGlkQXBwbHk6IHRydWUsXG4gICAgICAgIHBhdGNoQ29udGVudEhhc2g6IGhhc2hGaWxlKGpvaW4oYXBwUGF0aCwgcGF0Y2hEaXIsIHAucGF0Y2hGaWxlbmFtZSkpLFxuICAgICAgfSksXG4gICAgKVxuICAgIGNvbnN0IG5leHRTdGF0ZTogUGF0Y2hTdGF0ZVtdID0gW1xuICAgICAgLi4ucHJldlN0YXRlLFxuICAgICAge1xuICAgICAgICBwYXRjaEZpbGVuYW1lOiBwYXRjaEZpbGVOYW1lLFxuICAgICAgICBkaWRBcHBseTogdHJ1ZSxcbiAgICAgICAgcGF0Y2hDb250ZW50SGFzaDogaGFzaEZpbGUocGF0Y2hQYXRoKSxcbiAgICAgIH0sXG4gICAgXVxuXG4gICAgLy8gaWYgYW55IHBhdGNoZXMgY29tZSBhZnRlciB0aGlzIG9uZSB3ZSBqdXN0IG1hZGUsIHdlIHNob3VsZCByZWFwcGx5IHRoZW1cbiAgICBsZXQgZGlkRmFpbFdoaWxlRmluaXNoaW5nUmViYXNlID0gZmFsc2VcbiAgICBpZiAoaXNSZWJhc2luZykge1xuICAgICAgY29uc3QgY3VycmVudFBhdGNoZXMgPSBnZXRHcm91cGVkUGF0Y2hlcyhqb2luKGFwcFBhdGgsIHBhdGNoRGlyKSlcbiAgICAgICAgLnBhdGhTcGVjaWZpZXJUb1BhdGNoRmlsZXNbcGFja2FnZURldGFpbHMucGF0aFNwZWNpZmllcl1cblxuICAgICAgY29uc3QgcHJldmlvdXNseVVuYXBwbGllZFBhdGNoZXMgPSBjdXJyZW50UGF0Y2hlcy5zbGljZShuZXh0U3RhdGUubGVuZ3RoKVxuICAgICAgaWYgKHByZXZpb3VzbHlVbmFwcGxpZWRQYXRjaGVzLmxlbmd0aCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgRmFzdCBmb3J3YXJkaW5nLi4uYClcbiAgICAgICAgZm9yIChjb25zdCBwYXRjaCBvZiBwcmV2aW91c2x5VW5hcHBsaWVkUGF0Y2hlcykge1xuICAgICAgICAgIGNvbnN0IHBhdGNoRmlsZVBhdGggPSBqb2luKGFwcFBhdGgsIHBhdGNoRGlyLCBwYXRjaC5wYXRjaEZpbGVuYW1lKVxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICFhcHBseVBhdGNoKHtcbiAgICAgICAgICAgICAgcGF0Y2hEZXRhaWxzOiBwYXRjaCxcbiAgICAgICAgICAgICAgcGF0Y2hEaXIsXG4gICAgICAgICAgICAgIHBhdGNoRmlsZVBhdGgsXG4gICAgICAgICAgICAgIHJldmVyc2U6IGZhbHNlLFxuICAgICAgICAgICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgICAgICAgICAgIGJlc3RFZmZvcnQ6IGZhbHNlLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGRpZEZhaWxXaGlsZUZpbmlzaGluZ1JlYmFzZSA9IHRydWVcbiAgICAgICAgICAgIGxvZ1BhdGNoU2VxdWVuY2VFcnJvcih7IHBhdGNoRGV0YWlsczogcGF0Y2ggfSlcbiAgICAgICAgICAgIG5leHRTdGF0ZS5wdXNoKHtcbiAgICAgICAgICAgICAgcGF0Y2hGaWxlbmFtZTogcGF0Y2gucGF0Y2hGaWxlbmFtZSxcbiAgICAgICAgICAgICAgZGlkQXBwbHk6IGZhbHNlLFxuICAgICAgICAgICAgICBwYXRjaENvbnRlbnRIYXNoOiBoYXNoRmlsZShwYXRjaEZpbGVQYXRoKSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgICAke2NoYWxrLmdyZWVuKFwi4pyUXCIpfSAke3BhdGNoLnBhdGNoRmlsZW5hbWV9YClcbiAgICAgICAgICAgIG5leHRTdGF0ZS5wdXNoKHtcbiAgICAgICAgICAgICAgcGF0Y2hGaWxlbmFtZTogcGF0Y2gucGF0Y2hGaWxlbmFtZSxcbiAgICAgICAgICAgICAgZGlkQXBwbHk6IHRydWUsXG4gICAgICAgICAgICAgIHBhdGNoQ29udGVudEhhc2g6IGhhc2hGaWxlKHBhdGNoRmlsZVBhdGgpLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaXNSZWJhc2luZyB8fCBudW1QYXRjaGVzQWZ0ZXJDcmVhdGUgPiAxKSB7XG4gICAgICBzYXZlUGF0Y2hBcHBsaWNhdGlvblN0YXRlKHtcbiAgICAgICAgcGFja2FnZURldGFpbHMsXG4gICAgICAgIHBhdGNoZXM6IG5leHRTdGF0ZSxcbiAgICAgICAgaXNSZWJhc2luZzogZGlkRmFpbFdoaWxlRmluaXNoaW5nUmViYXNlLFxuICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgY2xlYXJQYXRjaEFwcGxpY2F0aW9uU3RhdGUocGFja2FnZURldGFpbHMpXG4gICAgfVxuXG4gICAgaWYgKGNhbkNyZWF0ZUlzc3VlKSB7XG4gICAgICBpZiAoY3JlYXRlSXNzdWUpIHtcbiAgICAgICAgb3Blbklzc3VlQ3JlYXRpb25MaW5rKHtcbiAgICAgICAgICBwYWNrYWdlRGV0YWlscyxcbiAgICAgICAgICBwYXRjaEZpbGVDb250ZW50czogZGlmZlJlc3VsdC5zdGRvdXQudG9TdHJpbmcoKSxcbiAgICAgICAgICBwYWNrYWdlVmVyc2lvbixcbiAgICAgICAgfSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1heWJlUHJpbnRJc3N1ZUNyZWF0aW9uUHJvbXB0KHZjcywgcGFja2FnZURldGFpbHMsIHBhY2thZ2VNYW5hZ2VyKVxuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGNvbnNvbGUubG9nKGUpXG4gICAgdGhyb3cgZVxuICB9IGZpbmFsbHkge1xuICAgIHRtcFJlcG8ucmVtb3ZlQ2FsbGJhY2soKVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBhdGNoRmlsZU5hbWUoe1xuICBwYWNrYWdlRGV0YWlscyxcbiAgcGFja2FnZVZlcnNpb24sXG4gIHNlcXVlbmNlTnVtYmVyLFxuICBzZXF1ZW5jZU5hbWUsXG59OiB7XG4gIHBhY2thZ2VEZXRhaWxzOiBQYWNrYWdlRGV0YWlsc1xuICBwYWNrYWdlVmVyc2lvbjogc3RyaW5nXG4gIHNlcXVlbmNlTnVtYmVyPzogbnVtYmVyXG4gIHNlcXVlbmNlTmFtZT86IHN0cmluZ1xufSkge1xuICBjb25zdCBwYWNrYWdlTmFtZXMgPSBwYWNrYWdlRGV0YWlscy5wYWNrYWdlTmFtZXNcbiAgICAubWFwKChuYW1lKSA9PiBuYW1lLnJlcGxhY2UoL1xcLy9nLCBcIitcIikpXG4gICAgLmpvaW4oXCIrK1wiKVxuXG4gIGNvbnN0IG5hbWVBbmRWZXJzaW9uID0gYCR7cGFja2FnZU5hbWVzfSske3BhY2thZ2VWZXJzaW9ufWBcbiAgY29uc3QgbnVtID1cbiAgICBzZXF1ZW5jZU51bWJlciA9PT0gdW5kZWZpbmVkXG4gICAgICA/IFwiXCJcbiAgICAgIDogYCske3NlcXVlbmNlTnVtYmVyLnRvU3RyaW5nKCkucGFkU3RhcnQoMywgXCIwXCIpfWBcbiAgY29uc3QgbmFtZSA9ICFzZXF1ZW5jZU5hbWUgPyBcIlwiIDogYCske3NlcXVlbmNlTmFtZX1gXG5cbiAgcmV0dXJuIGAke25hbWVBbmRWZXJzaW9ufSR7bnVtfSR7bmFtZX0ucGF0Y2hgXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dQYXRjaFNlcXVlbmNlRXJyb3Ioe1xuICBwYXRjaERldGFpbHMsXG59OiB7XG4gIHBhdGNoRGV0YWlsczogUGF0Y2hlZFBhY2thZ2VEZXRhaWxzXG59KSB7XG4gIGNvbnNvbGUubG9nKGBcbiR7Y2hhbGsucmVkLmJvbGQoXCLim5QgRVJST1JcIil9XG5cbkZhaWxlZCB0byBhcHBseSBwYXRjaCBmaWxlICR7Y2hhbGsuYm9sZChwYXRjaERldGFpbHMucGF0Y2hGaWxlbmFtZSl9LlxuXG5JZiB0aGlzIHBhdGNoIGZpbGUgaXMgbm8gbG9uZ2VyIHVzZWZ1bCwgZGVsZXRlIGl0IGFuZCBydW5cblxuICAke2NoYWxrLmJvbGQoYHBhdGNoLXBhY2thZ2VgKX1cblxuVG8gcGFydGlhbGx5IGFwcGx5IHRoZSBwYXRjaCAoaWYgcG9zc2libGUpIGFuZCBvdXRwdXQgYSBsb2cgb2YgZXJyb3JzIHRvIGZpeCwgcnVuXG5cbiAgJHtjaGFsay5ib2xkKGBwYXRjaC1wYWNrYWdlIC0tcGFydGlhbGApfVxuXG5BZnRlciB3aGljaCB5b3Ugc2hvdWxkIG1ha2UgYW55IHJlcXVpcmVkIGNoYW5nZXMgaW5zaWRlICR7XG4gICAgcGF0Y2hEZXRhaWxzLnBhdGhcbiAgfSwgYW5kIGZpbmFsbHkgcnVuXG5cbiAgJHtjaGFsay5ib2xkKGBwYXRjaC1wYWNrYWdlICR7cGF0Y2hEZXRhaWxzLnBhdGhTcGVjaWZpZXJ9YCl9XG5cbnRvIHVwZGF0ZSB0aGUgcGF0Y2ggZmlsZS5cbmApXG59XG4iXX0=