UNPKG

@unts/patch-package

Version:

Fix broken node modules with no fuss

454 lines (436 loc) 68.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.logPatchSequenceError = exports.makePatch = void 0; const fs_extra_1 = require("fs-extra"); const picocolors_1 = __importDefault(require("picocolors")); const tmp_1 = require("tmp"); const zlib_1 = require("zlib"); const applyPatches_1 = require("./applyPatches"); const createIssue_1 = require("./createIssue"); const filterFiles_1 = require("./filterFiles"); const getPackageResolution_1 = require("./getPackageResolution"); const getPackageVersion_1 = require("./getPackageVersion"); const hash_1 = require("./hash"); const PackageDetails_1 = require("./PackageDetails"); const parse_1 = require("./patch/parse"); const patchFs_1 = require("./patchFs"); const path_1 = require("./path"); const resolveRelativeFileDependencies_1 = require("./resolveRelativeFileDependencies"); const spawnSafe_1 = require("./spawnSafe"); const stateFile_1 = require("./stateFile"); function printNoPackageFoundError(packageName, packageJsonPath) { console.log(`No such package ${packageName} File not found: ${packageJsonPath}`); } function makePatch({ packagePathSpecifier, appPath, packageManager, includePaths, excludePaths, patchDir, createIssue, mode, }) { var _a, _b, _c, _d, _e, _f, _g; const packageDetails = (0, PackageDetails_1.getPatchDetailsFromCliString)(packagePathSpecifier); if (!packageDetails) { console.log("No such package", packagePathSpecifier); return; } const state = (0, stateFile_1.getPatchApplicationState)(packageDetails); const isRebasing = (_a = state === null || state === void 0 ? void 0 : state.isRebasing) !== null && _a !== void 0 ? _a : false; // If we are rebasing and no patches have been applied, --append is the only valid option because // there are no previous patches to overwrite/update if (isRebasing && (state === null || state === void 0 ? void 0 : state.patches.filter((p) => p.didApply).length) === 0 && mode.type === "overwrite_last") { mode = { type: "append", name: "initial" }; } if (isRebasing && state) { (0, stateFile_1.verifyAppliedPatches)({ appPath, patchDir, state }); } if (mode.type === "overwrite_last" && isRebasing && (state === null || state === void 0 ? void 0 : state.patches.length) === 0) { mode = { type: "append", name: "initial" }; } const existingPatches = (0, patchFs_1.getGroupedPatches)(patchDir).pathSpecifierToPatchFiles[packageDetails.pathSpecifier] || []; // apply all existing patches if appending // otherwise apply all but the last const previouslyAppliedPatches = state === null || state === void 0 ? void 0 : state.patches.filter((p) => p.didApply); const patchesToApplyBeforeDiffing = isRebasing ? mode.type === "append" ? existingPatches.slice(0, previouslyAppliedPatches.length) : state.patches[state.patches.length - 1].didApply ? existingPatches.slice(0, previouslyAppliedPatches.length - 1) : existingPatches.slice(0, previouslyAppliedPatches.length) : mode.type === "append" ? existingPatches : existingPatches.slice(0, -1); if (createIssue && mode.type === "append") { console.log("--create-issue is not compatible with --append."); process.exit(1); } if (createIssue && isRebasing) { console.log("--create-issue is not compatible with rebasing."); process.exit(1); } const numPatchesAfterCreate = mode.type === "append" || existingPatches.length === 0 ? existingPatches.length + 1 : existingPatches.length; const vcs = (0, createIssue_1.getPackageVCSDetails)(packageDetails); const canCreateIssue = !isRebasing && (0, createIssue_1.shouldRecommendIssue)(vcs) && numPatchesAfterCreate === 1 && mode.type !== "append"; const appPackageJson = require((0, path_1.join)(appPath, "package.json")); const packagePath = (0, path_1.join)(appPath, packageDetails.path); const packageJsonPath = (0, path_1.join)(packagePath, "package.json"); if (!(0, fs_extra_1.existsSync)(packageJsonPath)) { printNoPackageFoundError(packagePathSpecifier, packageJsonPath); process.exit(1); } const tmpRepo = (0, tmp_1.dirSync)({ unsafeCleanup: true }); const tmpRepoPackagePath = (0, path_1.join)(tmpRepo.name, packageDetails.path); const tmpRepoNpmRoot = tmpRepoPackagePath.slice(0, -`/node_modules/${packageDetails.name}`.length); const tmpRepoPackageJsonPath = (0, path_1.join)(tmpRepoNpmRoot, "package.json"); try { const patchesDir = (0, path_1.resolve)((0, path_1.join)(appPath, patchDir)); console.info(picocolors_1.default.gray("•"), "Creating temporary folder"); // make a blank package.json (0, fs_extra_1.mkdirpSync)(tmpRepoNpmRoot); (0, fs_extra_1.writeFileSync)(tmpRepoPackageJsonPath, JSON.stringify({ // support `corepack` enabled without `.yarn/releases` packageManager: appPackageJson.packageManager, dependencies: { [packageDetails.name]: (0, getPackageResolution_1.getPackageResolution)({ packageDetails, packageManager, appPath, }), }, resolutions: (0, resolveRelativeFileDependencies_1.resolveRelativeFileDependencies)(appPath, appPackageJson.resolutions || {}), })); const packageVersion = (0, getPackageVersion_1.getPackageVersion)((0, path_1.join)((0, path_1.resolve)(packageDetails.path), "package.json")); [ ".npmrc", ".yarnrc", ".yarnrc.yml", // don't include the whole `.yarn` directory which could contain huge `cache` ".yarn/plugins", ".yarn/releases", ].forEach((rcFile) => { const rcPath = (0, path_1.join)(appPath, rcFile); if ((0, fs_extra_1.existsSync)(rcPath)) { (0, fs_extra_1.copySync)(rcPath, (0, path_1.join)(tmpRepo.name, rcFile), { dereference: true }); } }); if (packageManager === "yarn") { console.info(picocolors_1.default.gray("•"), `Installing ${packageDetails.name}@${packageVersion} with yarn`); const yarnArgs = ["install"]; const yarnVersionCmd = (0, spawnSafe_1.spawnSafeSync)(`yarn`, ["--version"], { cwd: tmpRepoNpmRoot, logStdErrOnError: false, }); const isYarnV1 = yarnVersionCmd.stdout.toString().startsWith("1."); if (isYarnV1) { yarnArgs.push("--ignore-engines"); } try { // try first without ignoring scripts in case they are required // this works in 99.99% of cases (0, spawnSafe_1.spawnSafeSync)(`yarn`, yarnArgs, { cwd: tmpRepoNpmRoot, logStdErrOnError: false, }); } catch (e) { // try again while ignoring scripts in case the script depends on // an implicit context which we haven't reproduced (0, spawnSafe_1.spawnSafeSync)(`yarn`, [...yarnArgs, isYarnV1 ? "--ignore-scripts" : "--mode=skip-build"], { cwd: tmpRepoNpmRoot, }); } } else { console.info(picocolors_1.default.gray("•"), `Installing ${packageDetails.name}@${packageVersion} with npm`); try { // try first without ignoring scripts in case they are required // this works in 99.99% of cases (0, spawnSafe_1.spawnSafeSync)(`npm`, ["i", "--force"], { cwd: tmpRepoNpmRoot, logStdErrOnError: false, stdio: "ignore", }); } catch (e) { // try again while ignoring scripts in case the script depends on // an implicit context which we haven't reproduced (0, spawnSafe_1.spawnSafeSync)(`npm`, ["i", "--ignore-scripts", "--force"], { cwd: tmpRepoNpmRoot, stdio: "ignore", }); } } const git = (...args) => (0, spawnSafe_1.spawnSafeSync)("git", args, { cwd: tmpRepo.name, env: Object.assign(Object.assign({}, process.env), { HOME: tmpRepo.name }), maxBuffer: 1024 * 1024 * 100, }); // remove nested node_modules just to be safe (0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, "node_modules")); // remove .git just to be safe (0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, ".git")); // remove patch-package state file (0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, stateFile_1.STATE_FILE_NAME)); // commit the package console.info(picocolors_1.default.gray("•"), "Diffing your files with clean files"); (0, fs_extra_1.writeFileSync)((0, path_1.join)(tmpRepo.name, ".gitignore"), "!/node_modules\n\n"); git("init"); git("config", "--local", "user.name", "patch-package"); git("config", "--local", "user.email", "patch@pack.age"); // remove ignored files first (0, filterFiles_1.removeIgnoredFiles)(tmpRepoPackagePath, includePaths, excludePaths); for (const patchDetails of patchesToApplyBeforeDiffing) { if (!(0, applyPatches_1.applyPatch)({ patchDetails, patchDir, patchFilePath: (0, path_1.join)(appPath, patchDir, patchDetails.patchFilename), reverse: false, cwd: tmpRepo.name, bestEffort: false, })) { // TODO: add better error message once --rebase is implemented console.log(`Failed to apply patch ${patchDetails.patchFilename} to ${packageDetails.pathSpecifier}`); process.exit(1); } } git("add", "-f", packageDetails.path); git("commit", "--allow-empty", "-m", "init"); // replace package with user's version (0, fs_extra_1.removeSync)(tmpRepoPackagePath); // pnpm installs packages as symlinks, copySync would copy only the symlink (0, fs_extra_1.copySync)((0, fs_extra_1.realpathSync)(packagePath), tmpRepoPackagePath); // remove nested node_modules just to be safe (0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, "node_modules")); // remove .git just to be safe (0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, ".git")); // remove patch-package state file (0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, stateFile_1.STATE_FILE_NAME)); // also remove ignored files like before (0, filterFiles_1.removeIgnoredFiles)(tmpRepoPackagePath, includePaths, excludePaths); // stage all files git("add", "-f", packageDetails.path); // get diff of changes const diffResult = git("diff", "--cached", "--no-color", "--ignore-space-at-eol", "--no-ext-diff", "--src-prefix=a/", "--dst-prefix=b/"); if (diffResult.stdout.length === 0) { console.log(`⁉️ Not creating patch file for package '${packagePathSpecifier}'`); console.log(`⁉️ There don't appear to be any changes.`); if (isRebasing && mode.type === "overwrite_last") { console.log("\n💡 To remove a patch file, delete it and then reinstall node_modules from scratch."); } process.exit(1); return; } try { (0, parse_1.parsePatchFile)(diffResult.stdout.toString()); } catch (e) { const err = e; if (err.message.includes("Unexpected file mode string: 120000")) { console.log(` ⛔️ ${picocolors_1.default.red(picocolors_1.default.bold("ERROR"))} Your changes involve creating symlinks. patch-package does not yet support symlinks. ️Please use ${picocolors_1.default.bold("--include")} and/or ${picocolors_1.default.bold("--exclude")} to narrow the scope of your patch if this was unintentional. `); } else { const outPath = "./patch-package-error.json.gz"; (0, fs_extra_1.writeFileSync)(outPath, (0, zlib_1.gzipSync)(JSON.stringify({ error: { message: err.message, stack: err.stack }, patch: diffResult.stdout.toString(), }))); console.log(` ⛔️ ${picocolors_1.default.red(picocolors_1.default.bold("ERROR"))} patch-package was unable to read the patch-file made by git. This should not happen. A diagnostic file was written to ${outPath} Please attach it to a github issue https://github.com/ds300/patch-package/issues/new?title=New+patch+parse+failed&body=Please+attach+the+diagnostic+file+by+dragging+it+into+here+🙏 Note that this diagnostic file will contain code from the package you were attempting to patch. `); } process.exit(1); return; } // maybe delete existing if (mode.type === "append" && !isRebasing && existingPatches.length === 1) { // if we are appending to an existing patch that doesn't have a sequence number let's rename it const prevPatch = existingPatches[0]; if (prevPatch.sequenceNumber === undefined) { const newFileName = createPatchFileName({ packageDetails, packageVersion, sequenceNumber: 1, sequenceName: (_b = prevPatch.sequenceName) !== null && _b !== void 0 ? _b : "initial", }); const oldPath = (0, path_1.join)(appPath, patchDir, prevPatch.patchFilename); const newPath = (0, path_1.join)(appPath, patchDir, newFileName); (0, fs_extra_1.renameSync)(oldPath, newPath); prevPatch.sequenceNumber = 1; prevPatch.patchFilename = newFileName; prevPatch.sequenceName = (_c = prevPatch.sequenceName) !== null && _c !== void 0 ? _c : "initial"; } } const lastPatch = existingPatches[state ? state.patches.length - 1 : existingPatches.length - 1]; const sequenceName = mode.type === "append" ? mode.name : lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceName; const sequenceNumber = mode.type === "append" ? ((_d = lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceNumber) !== null && _d !== void 0 ? _d : 0) + 1 : lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceNumber; const patchFileName = createPatchFileName({ packageDetails, packageVersion, sequenceName, sequenceNumber, }); const patchPath = (0, path_1.join)(patchesDir, patchFileName); if (!(0, fs_extra_1.existsSync)((0, path_1.dirname)(patchPath))) { // scoped package (0, fs_extra_1.mkdirSync)((0, path_1.dirname)(patchPath)); } // if we are inserting a new patch into a sequence we most likely need to update the sequence numbers if (isRebasing && mode.type === "append") { const patchesToNudge = existingPatches.slice(state.patches.length); if (sequenceNumber === undefined) { throw new Error("sequenceNumber is undefined while rebasing"); } if (((_e = patchesToNudge[0]) === null || _e === void 0 ? void 0 : _e.sequenceNumber) !== undefined && patchesToNudge[0].sequenceNumber <= sequenceNumber) { let next = sequenceNumber + 1; for (const p of patchesToNudge) { const newName = createPatchFileName({ packageDetails, packageVersion, sequenceName: p.sequenceName, sequenceNumber: next++, }); console.log("Renaming", picocolors_1.default.bold(p.patchFilename), "to", picocolors_1.default.bold(newName)); const oldPath = (0, path_1.join)(appPath, patchDir, p.patchFilename); const newPath = (0, path_1.join)(appPath, patchDir, newName); (0, fs_extra_1.renameSync)(oldPath, newPath); } } } (0, fs_extra_1.writeFileSync)(patchPath, diffResult.stdout); console.log(`${picocolors_1.default.green("✔")} Created file ${(0, path_1.join)(patchDir, patchFileName)}\n`); const prevState = patchesToApplyBeforeDiffing.map((p) => ({ patchFilename: p.patchFilename, didApply: true, patchContentHash: (0, hash_1.hashFile)((0, path_1.join)(appPath, patchDir, p.patchFilename)), })); const nextState = [ ...prevState, { patchFilename: patchFileName, didApply: true, patchContentHash: (0, hash_1.hashFile)(patchPath), }, ]; // if any patches come after this one we just made, we should reapply them let didFailWhileFinishingRebase = false; if (isRebasing) { const currentPatches = (0, patchFs_1.getGroupedPatches)((0, path_1.join)(appPath, patchDir)) .pathSpecifierToPatchFiles[packageDetails.pathSpecifier]; const previouslyUnappliedPatches = currentPatches.slice(nextState.length); if (previouslyUnappliedPatches.length) { console.log(`Fast forwarding...`); for (const patch of previouslyUnappliedPatches) { const patchFilePath = (0, path_1.join)(appPath, patchDir, patch.patchFilename); if (!(0, applyPatches_1.applyPatch)({ patchDetails: patch, patchDir, patchFilePath, reverse: false, cwd: process.cwd(), bestEffort: false, })) { didFailWhileFinishingRebase = true; logPatchSequenceError({ patchDetails: patch }); nextState.push({ patchFilename: patch.patchFilename, didApply: false, patchContentHash: (0, hash_1.hashFile)(patchFilePath), }); break; } else { console.log(` ${picocolors_1.default.green("✔")} ${patch.patchFilename}`); nextState.push({ patchFilename: patch.patchFilename, didApply: true, patchContentHash: (0, hash_1.hashFile)(patchFilePath), }); } } } } if (isRebasing || numPatchesAfterCreate > 1) { (0, stateFile_1.savePatchApplicationState)({ packageDetails, patches: nextState, isRebasing: didFailWhileFinishingRebase, }); } else { (0, stateFile_1.clearPatchApplicationState)(packageDetails); } if (canCreateIssue) { if (createIssue) { (0, createIssue_1.openIssueCreationLink)({ packageDetails, patchFileContents: diffResult.stdout.toString(), packageVersion, patchPath, }); } else { (0, createIssue_1.maybePrintIssueCreationPrompt)(vcs, packageDetails, packageManager); } } } catch (e) { const err = e; // try to log more useful error message console.log(((_f = err.stderr) === null || _f === void 0 ? void 0 : _f.toString()) || ((_g = err.stdout) === null || _g === void 0 ? void 0 : _g.toString()) || e); throw e; } finally { tmpRepo.removeCallback(); } } exports.makePatch = makePatch; function createPatchFileName({ packageDetails, packageVersion, sequenceNumber, sequenceName, }) { const packageNames = packageDetails.packageNames .map((name) => name.replace(/\//g, "+")) .join("++"); const nameAndVersion = `${packageNames}+${packageVersion}`; const num = sequenceNumber === undefined ? "" : `+${sequenceNumber.toString().padStart(3, "0")}`; const name = !sequenceName ? "" : `+${sequenceName}`; return `${nameAndVersion}${num}${name}.patch`; } function logPatchSequenceError({ patchDetails, }) { console.log(` ${picocolors_1.default.red(picocolors_1.default.bold("⛔ ERROR"))} Failed to apply patch file ${picocolors_1.default.bold(patchDetails.patchFilename)}. If this patch file is no longer useful, delete it and run ${picocolors_1.default.bold(`patch-package`)} To partially apply the patch (if possible) and output a log of errors to fix, run ${picocolors_1.default.bold(`patch-package --partial`)} After which you should make any required changes inside ${patchDetails.path}, and finally run ${picocolors_1.default.bold(`patch-package ${patchDetails.pathSpecifier}`)} to update the patch file. `); } exports.logPatchSequenceError = logPatchSequenceError; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFrZVBhdGNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ha2VQYXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx1Q0FTaUI7QUFDakIsNERBQStCO0FBQy9CLDZCQUE2QjtBQUM3QiwrQkFBK0I7QUFDL0IsaURBQTJDO0FBQzNDLCtDQUtzQjtBQUV0QiwrQ0FBa0Q7QUFDbEQsaUVBQTZEO0FBQzdELDJEQUF1RDtBQUN2RCxpQ0FBaUM7QUFDakMscURBSXlCO0FBQ3pCLHlDQUE4QztBQUM5Qyx1Q0FBNkM7QUFDN0MsaUNBQStDO0FBQy9DLHVGQUFtRjtBQUNuRiwyQ0FBMkM7QUFDM0MsMkNBT29CO0FBRXBCLFNBQVMsd0JBQXdCLENBQy9CLFdBQW1CLEVBQ25CLGVBQXVCO0lBRXZCLE9BQU8sQ0FBQyxHQUFHLENBQ1QsbUJBQW1CLFdBQVc7O29CQUVkLGVBQWUsRUFBRSxDQUNsQyxDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQWdCLFNBQVMsQ0FBQyxFQUN4QixvQkFBb0IsRUFDcEIsT0FBTyxFQUNQLGNBQWMsRUFDZCxZQUFZLEVBQ1osWUFBWSxFQUNaLFFBQVEsRUFDUixXQUFXLEVBQ1gsSUFBSSxHQVVMOztJQUNDLE1BQU0sY0FBYyxHQUFHLElBQUEsNkNBQTRCLEVBQUMsb0JBQW9CLENBQUMsQ0FBQTtJQUV6RSxJQUFJLENBQUMsY0FBYyxFQUFFO1FBQ25CLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsb0JBQW9CLENBQUMsQ0FBQTtRQUNwRCxPQUFNO0tBQ1A7SUFFRCxNQUFNLEtBQUssR0FBRyxJQUFBLG9DQUF3QixFQUFDLGNBQWMsQ0FBQyxDQUFBO0lBQ3RELE1BQU0sVUFBVSxHQUFHLE1BQUEsS0FBSyxhQUFMLEtBQUssdUJBQUwsS0FBSyxDQUFFLFVBQVUsbUNBQUksS0FBSyxDQUFBO0lBRTdDLGlHQUFpRztJQUNqRyxvREFBb0Q7SUFDcEQsSUFDRSxVQUFVO1FBQ1YsQ0FBQSxLQUFL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LENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUM7Ozs7SUFJaEUsb0JBQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDOzs7O0lBSTVCLG9CQUFNLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDOzswREFHdEMsWUFBWSxDQUFDLElBQ2Y7O0lBRUUsb0JBQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLFlBQVksQ0FBQyxhQUFhLEVBQUUsQ0FBQzs7O0NBRzdELENBQUMsQ0FBQTtBQUNGLENBQUM7QUExQkQsc0RBMEJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgY29weVN5bmMsXG4gIGV4aXN0c1N5bmMsXG4gIG1rZGlycFN5bmMsXG4gIG1rZGlyU3luYyxcbiAgcmVhbHBhdGhTeW5jLFxuICByZW1vdmVTeW5jLFxuICByZW5hbWVTeW5jLFxuICB3cml0ZUZpbGVTeW5jLFxufSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IGNvbG9ycyBmcm9tIFwicGljb2NvbG9yc1wiXG5pbXBvcnQgeyBkaXJTeW5jIH0gZnJvbSBcInRtcFwiXG5pbXBvcnQgeyBnemlwU3luYyB9IGZyb20gXCJ6bGliXCJcbmltcG9ydCB7IGFwcGx5UGF0Y2ggfSBmcm9tIFwiLi9hcHBseVBhdGNoZXNcIlxuaW1wb3J0IHtcbiAgZ2V0UGFja2FnZVZDU0RldGFpbHMsXG4gIG1heWJlUHJpbnRJc3N1ZUNyZWF0aW9uUHJvbXB0LFxuICBvcGVuSXNzdWVDcmVhdGlvbkxpbmssXG4gIHNob3VsZFJlY29tbWVuZElzc3VlLFxufSBmcm9tIFwiLi9jcmVhdGVJc3N1ZVwiXG5pbXBvcnQgeyBQYWNrYWdlTWFuYWdlciB9IGZyb20gXCIuL2RldGVjdFBhY2thZ2VNYW5hZ2VyXCJcbmltcG9ydCB7IHJlbW92ZUlnbm9yZWRGaWxlcyB9IGZyb20gXCIuL2ZpbHRlckZpbGVzXCJcbmltcG9ydCB7IGdldFBhY2thZ2VSZXNvbHV0aW9uIH0gZnJvbSBcIi4vZ2V0UGFja2FnZVJlc29sdXRpb25cIlxuaW1wb3J0IHsgZ2V0UGFja2FnZVZlcnNpb24gfSBmcm9tIFwiLi9nZXRQYWNrYWdlVmVyc2lvblwiXG5pbXBvcnQgeyBoYXNoRmlsZSB9IGZyb20gXCIuL2hhc2hcIlxuaW1wb3J0IHtcbiAgZ2V0UGF0Y2hEZXRhaWxzRnJvbUNsaVN0cmluZyxcbiAgUGFja2FnZURldGFpbHMsXG4gIFBhdGNoZWRQYWNrYWdlRGV0YWlscyxcbn0gZnJvbSBcIi4vUGFja2FnZURldGFpbHNcIlxuaW1wb3J0IHsgcGFyc2VQYXRjaEZpbGUgfSBmcm9tIFwiLi9wYXRjaC9wYXJzZVwiXG5pbXBvcnQgeyBnZXRHcm91cGVkUGF0Y2hlcyB9IGZyb20gXCIuL3BhdGNoRnNcIlxuaW1wb3J0IHsgZGlybmFtZSwgam9pbiwgcmVzb2x2ZSB9IGZyb20gXCIuL3BhdGhcIlxuaW1wb3J0IHsgcmVzb2x2ZVJlbGF0aXZlRmlsZURlcGVuZGVuY2llcyB9IGZyb20gXCIuL3Jlc29sdmVSZWxhdGl2ZUZpbGVEZXBlbmRlbmNpZXNcIlxuaW1wb3J0IHsgc3Bhd25TYWZlU3luYyB9IGZyb20gXCIuL3NwYXduU2FmZVwiXG5pbXBvcnQge1xuICBjbGVhclBhdGNoQXBwbGljYXRpb25TdGF0ZSxcbiAgZ2V0UGF0Y2hBcHBsaWNhdGlvblN0YXRlLFxuICBQYXRjaFN0YXRlLFxuICBzYXZlUGF0Y2hBcHBsaWNhdGlvblN0YXRlLFxuICBTVEFURV9GSUxFX05BTUUsXG4gIHZlcmlmeUFwcGxpZWRQYXRjaGVzLFxufSBmcm9tIFwiLi9zdGF0ZUZpbGVcIlxuXG5mdW5jdGlvbiBwcmludE5vUGFja2FnZUZvdW5kRXJyb3IoXG4gIHBhY2thZ2VOYW1lOiBzdHJpbmcsXG4gIHBhY2thZ2VKc29uUGF0aDogc3RyaW5nLFxuKSB7XG4gIGNvbnNvbGUubG9nKFxuICAgIGBObyBzdWNoIHBhY2thZ2UgJHtwYWNrYWdlTmFtZX1cblxuICBGaWxlIG5vdCBmb3VuZDogJHtwYWNrYWdlSnNvblBhdGh9YCxcbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFrZVBhdGNoKHtcbiAgcGFja2FnZVBhdGhTcGVjaWZpZXIsXG4gIGFwcFBhdGgsXG4gIHBhY2thZ2VNYW5hZ2VyLFxuICBpbmNsdWRlUGF0aHMsXG4gIGV4Y2x1ZGVQYXRocyxcbiAgcGF0Y2hEaXIsXG4gIGNyZWF0ZUlzc3VlLFxuICBtb2RlLFxufToge1xuICBwYWNrYWdlUGF0aFNwZWNpZmllcjogc3RyaW5nXG4gIGFwcFBhdGg6IHN0cmluZ1xuICBwYWNrYWdlTWFuYWdlcjogUGFja2FnZU1hbmFnZXJcbiAgaW5jbHVkZVBhdGhzOiBSZWdFeHBcbiAgZXhjbHVkZVBhdGhzOiBSZWdFeHBcbiAgcGF0Y2hEaXI6IHN0cmluZ1xuICBjcmVhdGVJc3N1ZTogYm9vbGVhblxuICBtb2RlOiB7IHR5cGU6IFwib3ZlcndyaXRlX2xhc3RcIiB9IHwgeyB0eXBlOiBcImFwcGVuZFwiOyBuYW1lPzogc3RyaW5nIH1cbn0pIHtcbiAgY29uc3QgcGFja2FnZURldGFpbHMgPSBnZXRQYXRjaERldGFpbHNGcm9tQ2xpU3RyaW5nKHBhY2thZ2VQYXRoU3BlY2lmaWVyKVxuXG4gIGlmICghcGFja2FnZURldGFpbHMpIHtcbiAgICBjb25zb2xlLmxvZyhcIk5vIHN1Y2ggcGFja2FnZVwiLCBwYWNrYWdlUGF0aFNwZWNpZmllcilcbiAgICByZXR1cm5cbiAgfVxuXG4gIGNvbnN0IHN0YXRlID0gZ2V0UGF0Y2hBcHBsaWNhdGlvblN0YXRlKHBhY2thZ2VEZXRhaWxzKVxuICBjb25zdCBpc1JlYmFzaW5nID0gc3RhdGU/LmlzUmViYXNpbmcgPz8gZmFsc2VcblxuICAvLyBJZiB3ZSBhcmUgcmViYXNpbmcgYW5kIG5vIHBhdGNoZXMgaGF2ZSBiZWVuIGFwcGxpZWQsIC0tYXBwZW5kIGlzIHRoZSBvbmx5IHZhbGlkIG9wdGlvbiBiZWNhdXNlXG4gIC8vIHRoZXJlIGFyZSBubyBwcmV2aW91cyBwYXRjaGVzIHRvIG92ZXJ3cml0ZS91cGRhdGVcbiAgaWYgKFxuICAgIGlzUmViYXNpbmcgJiZcbiAgICBzdGF0ZT8ucGF0Y2hlcy5maWx0ZXIoKHApID0+IHAuZGlkQXBwbHkpLmxlbmd0aCA9PT0gMCAmJlxuICAgIG1vZGUudHlwZSA9PT0gXCJvdmVyd3JpdGVfbGFzdFwiXG4gICkge1xuICAgIG1vZGUgPSB7IHR5cGU6IFwiYXBwZW5kXCIsIG5hbWU6IFwiaW5pdGlhbFwiIH1cbiAgfVxuXG4gIGlmIChpc1JlYmFzaW5nICYmIHN0YXRlKSB7XG4gICAgdmVyaWZ5QXBwbGllZFBhdGNoZXMoeyBhcHBQYXRoLCBwYXRjaERpciwgc3RhdGUgfSlcbiAgfVxuXG4gIGlmIChcbiAgICBtb2RlLnR5cGUgPT09IFwib3ZlcndyaXRlX2xhc3RcIiAmJlxuICAgIGlzUmViYXNpbmcgJiZcbiAgICBzdGF0ZT8ucGF0Y2hlcy5sZW5ndGggPT09IDBcbiAgKSB7XG4gICAgbW9kZSA9IHsgdHlwZTogXCJhcHBlbmRcIiwgbmFtZTogXCJpbml0aWFsXCIgfVxuICB9XG5cbiAgY29uc3QgZXhpc3RpbmdQYXRjaGVzID1cbiAgICBnZXRHcm91cGVkUGF0Y2hlcyhwYXRjaERpcikucGF0aFNwZWNpZmllclRvUGF0Y2hGaWxlc1tcbiAgICAgIHBhY2thZ2VEZXRhaWxzLnBhdGhTcGVjaWZpZXJcbiAgICBdIHx8IFtdXG5cbiAgLy8gYXBwbHkgYWxsIGV4aXN0aW5nIHBhdGNoZXMgaWYgYXBwZW5kaW5nXG4gIC8vIG90aGVyd2lzZSBhcHBseSBhbGwgYnV0IHRoZSBsYXN0XG4gIGNvbnN0IHByZXZpb3VzbHlBcHBsaWVkUGF0Y2hlcyA9IHN0YXRlPy5wYXRjaGVzLmZpbHRlcigocCkgPT4gcC5kaWRBcHBseSlcbiAgY29uc3QgcGF0Y2hlc1RvQXBwbHlCZWZvcmVEaWZmaW5nOiBQYXRjaGVkUGFja2FnZURldGFpbHNbXSA9IGlzUmViYXNpbmdcbiAgICA/IG1vZGUudHlwZSA9PT0gXCJhcHBlbmRcIlxuICAgICAgPyBleGlzdGluZ1BhdGNoZXMuc2xpY2UoMCwgcHJldmlvdXNseUFwcGxpZWRQYXRjaGVzIS5sZW5ndGgpXG4gICAgICA6IHN0YXRlIS5wYXRjaGVzW3N0YXRlIS5wYXRjaGVzLmxlbmd0aCAtIDFdLmRpZEFwcGx5XG4gICAgICA/IGV4aXN0aW5nUGF0Y2hlcy5zbGljZSgwLCBwcmV2aW91c2x5QXBwbGllZFBhdGNoZXMhLmxlbmd0aCAtIDEpXG4gICAgICA6IGV4aXN0aW5nUGF0Y2hlcy5zbGljZSgwLCBwcmV2aW91c2x5QXBwbGllZFBhdGNoZXMhLmxlbmd0aClcbiAgICA6IG1vZGUudHlwZSA9PT0gXCJhcHBlbmRcIlxuICAgID8gZXhpc3RpbmdQYXRjaGVzXG4gICAgOiBleGlzdGluZ1BhdGNoZXMuc2xpY2UoMCwgLTEpXG5cbiAgaWYgKGNyZWF0ZUlzc3VlICYmIG1vZGUudHlwZSA9PT0gXCJhcHBlbmRcIikge1xuICAgIGNvbnNvbGUubG9nKFwiLS1jcmVhdGUtaXNzdWUgaXMgbm90IGNvbXBhdGlibGUgd2l0aCAtLWFwcGVuZC5cIilcbiAgICBwcm9jZXNzLmV4aXQoMSlcbiAgfVxuXG4gIGlmIChjcmVhdGVJc3N1ZSAmJiBpc1JlYmFzaW5nKSB7XG4gICAgY29uc29sZS5sb2coXCItLWNyZWF0ZS1pc3N1ZSBpcyBub3QgY29tcGF0aWJsZSB3aXRoIHJlYmFzaW5nLlwiKVxuICAgIHByb2Nlc3MuZXhpdCgxKVxuICB9XG5cbiAgY29uc3QgbnVtUGF0Y2hlc0FmdGVyQ3JlYXRlID1cbiAgICBtb2RlLnR5cGUgPT09IFwiYXBwZW5kXCIgfHwgZXhpc3RpbmdQYXRjaGVzLmxlbmd0aCA9PT0gMFxuICAgICAgPyBleGlzdGluZ1BhdGNoZXMubGVuZ3RoICsgMVxuICAgICAgOiBleGlzdGluZ1BhdGNoZXMubGVuZ3RoXG4gIGNvbnN0IHZjcyA9IGdldFBhY2thZ2VWQ1NEZXRhaWxzKHBhY2thZ2VEZXRhaWxzKVxuICBjb25zdCBjYW5DcmVhdGVJc3N1ZSA9XG4gICAgIWlzUmViYXNpbmcgJiZcbiAgICBzaG91bGRSZWNvbW1lbmRJc3N1ZSh2Y3MpICYmXG4gICAgbnVtUGF0Y2hlc0FmdGVyQ3JlYXRlID09PSAxICYmXG4gICAgbW9kZS50eXBlICE9PSBcImFwcGVuZFwiXG5cbiAgY29uc3QgYXBwUGFja2FnZUpzb24gPSByZXF1aXJlKGpvaW4oYXBwUGF0aCwgXCJwYWNrYWdlLmpzb25cIikpXG4gIGNvbnN0IHBhY2thZ2VQYXRoID0gam9pbihhcHBQYXRoLCBwYWNrYWdlRGV0YWlscy5wYXRoKVxuICBjb25zdCBwYWNrYWdlSnNvblBhdGggPSBqb2luKHBhY2thZ2VQYXRoLCBcInBhY2thZ2UuanNvblwiKVxuXG4gIGlmICghZXhpc3RzU3luYyhwYWNrYWdlSnNvblBhdGgpKSB7XG4gICAgcHJpbnROb1BhY2thZ2VGb3VuZEVycm9yKHBhY2thZ2VQYXRoU3BlY2lmaWVyLCBwYWNrYWdlSnNvblBhdGgpXG4gICAgcHJvY2Vzcy5leGl0KDEpXG4gIH1cblxuICBjb25zdCB0bXBSZXBvID0gZGlyU3luYyh7IHVuc2FmZUNsZWFudXA6IHRydWUgfSlcbiAgY29uc3QgdG1wUmVwb1BhY2thZ2VQYXRoID0gam9pbih0bXBSZXBvLm5hbWUsIHBhY2thZ2VEZXRhaWxzLnBhdGgpXG4gIGNvbnN0IHRtcFJlcG9OcG1Sb290ID0gdG1wUmVwb1BhY2thZ2VQYXRoLnNsaWNlKFxuICAgIDAsXG4gICAgLWAvbm9kZV9tb2R1bGVzLyR7cGFja2FnZURldGFpbHMubmFtZX1gLmxlbmd0aCxcbiAgKVxuXG4gIGNvbnN0IHRtcFJlcG9QYWNrYWdlSnNvblBhdGggPSBqb2luKHRtcFJlcG9OcG1Sb290LCBcInBhY2thZ2UuanNvblwiKVxuXG4gIHRyeSB7XG4gICAgY29uc3QgcGF0Y2hlc0RpciA9IHJlc29sdmUoam9pbihhcHBQYXRoLCBwYXRjaERpcikpXG5cbiAgICBjb25zb2xlLmluZm8oY29sb3JzLmdyYXkoXCLigKJcIiksIFwiQ3JlYXRpbmcgdGVtcG9yYXJ5IGZvbGRlclwiKVxuXG4gICAgLy8gbWFrZSBhIGJsYW5rIHBhY2thZ2UuanNvblxuICAgIG1rZGlycFN5bmModG1wUmVwb05wbVJvb3QpXG4gICAgd3JpdGVGaWxlU3luYyhcbiAgICAgIHRtcFJlcG9QYWNrYWdlSnNvblBhdGgsXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIC8vIHN1cHBvcnQgYGNvcmVwYWNrYCBlbmFibGVkIHdpdGhvdXQgYC55YXJuL3JlbGVhc2VzYFxuICAgICAgICBwYWNrYWdlTWFuYWdlcjogYXBwUGFja2FnZUpzb24ucGFja2FnZU1hbmFnZXIsXG4gICAgICAgIGRlcGVuZGVuY2llczoge1xuICAgICAgICAgIFtwYWNrYWdlRGV0YWlscy5uYW1lXTogZ2V0UGFja2FnZVJlc29sdXRpb24oe1xuICAgICAgICAgICAgcGFja2FnZURldGFpbHMsXG4gICAgICAgICAgICBwYWNrYWdlTWFuYWdlcixcbiAgICAgICAgICAgIGFwcFBhdGgsXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICAgIHJlc29sdXRpb25zOiByZXNvbHZlUmVsYXRpdmVGaWxlRGVwZW5kZW5jaWVzKFxuICAgICAgICAgIGFwcFBhdGgsXG4gICAgICAgICAgYXBwUGFja2FnZUpzb24ucmVzb2x1dGlvbnMgfHwge30sXG4gICAgICAgICksXG4gICAgICB9KSxcbiAgICApXG5cbiAgICBjb25zdCBwYWNrYWdlVmVyc2lvbiA9IGdldFBhY2thZ2VWZXJzaW9uKFxuICAgICAgam9pbihyZXNvbHZlKHBhY2thZ2VEZXRhaWxzLnBhdGgpLCBcInBhY2thZ2UuanNvblwiKSxcbiAgICApXG5cbiAgICAvLyBjb3B5IC5ucG1yYy8ueWFybnJjIGluIGNhc2UgcGFja2FnZXMgYXJlIGhvc3RlZCBpbiBwcml2YXRlIHJlZ2lzdHJ5XG4gICAgLy8gY29weSAueWFybiBkaXJlY3RvcnkgYXMgd2VsbCB0byBlbnN1cmUgaW5zdGFsbGF0aW9ucyB3b3JrIGluIHlhcm4gMlxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTphbGlnblxuICAgIDtbXG4gICAgICBcIi5ucG1yY1wiLFxuICAgICAgXCIueWFybnJjXCIsXG4gICAgICBcIi55YXJucmMueW1sXCIsXG4gICAgICAvLyBkb24ndCBpbmNsdWRlIHRoZSB3aG9sZSBgLnlhcm5gIGRpcmVjdG9yeSB3aGljaCBjb3VsZCBjb250YWluIGh1Z2UgYGNhY2hlYFxuICAgICAgXCIueWFybi9wbHVnaW5zXCIsXG4gICAgICBcIi55YXJuL3JlbGVhc2VzXCIsXG4gICAgXS5mb3JFYWNoKChyY0ZpbGUpID0+IHtcbiAgICAgIGNvbnN0IHJjUGF0aCA9IGpvaW4oYXBwUGF0aCwgcmNGaWxlKVxuICAgICAgaWYgKGV4aXN0c1N5bmMocmNQYXRoKSkge1xuICAgICAgICBjb3B5U3luYyhyY1Bh