@naandalist/patch-package
Version:
Fix broken node modules with no fuss
251 lines • 30.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeEffects = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = require("path");
const assertNever_1 = require("../assertNever");
const executeEffects = (effects, { dryRun, bestEffort, errors, cwd, }) => {
const inCwd = (path) => (cwd ? (0, path_1.join)(cwd, path) : path);
const humanReadable = (path) => (0, path_1.relative)(process.cwd(), inCwd(path));
effects.forEach((eff) => {
switch (eff.type) {
case "file deletion":
if (dryRun) {
if (!fs_extra_1.default.existsSync(inCwd(eff.path))) {
throw new Error("Trying to delete file that doesn't exist: " +
humanReadable(eff.path));
}
}
else {
// TODO: integrity checks
try {
fs_extra_1.default.unlinkSync(inCwd(eff.path));
}
catch (e) {
if (bestEffort) {
errors === null || errors === void 0 ? void 0 : errors.push(`Failed to delete file ${eff.path}`);
}
else {
throw e;
}
}
}
break;
case "rename":
if (dryRun) {
// TODO: see what patch files look like if moving to exising path
if (!fs_extra_1.default.existsSync(inCwd(eff.fromPath))) {
throw new Error("Trying to move file that doesn't exist: " +
humanReadable(eff.fromPath));
}
}
else {
try {
fs_extra_1.default.moveSync(inCwd(eff.fromPath), inCwd(eff.toPath));
}
catch (e) {
if (bestEffort) {
errors === null || errors === void 0 ? void 0 : errors.push(`Failed to rename file ${eff.fromPath} to ${eff.toPath}`);
}
else {
throw e;
}
}
}
break;
case "file creation":
if (dryRun) {
if (fs_extra_1.default.existsSync(inCwd(eff.path))) {
throw new Error("Trying to create file that already exists: " +
humanReadable(eff.path));
}
// todo: check file contents matches
}
else {
const fileContents = eff.hunk
? eff.hunk.parts[0].lines.join("\n") +
(eff.hunk.parts[0].noNewlineAtEndOfFile ? "" : "\n")
: "";
const path = inCwd(eff.path);
try {
fs_extra_1.default.ensureDirSync((0, path_1.dirname)(path));
fs_extra_1.default.writeFileSync(path, fileContents, { mode: eff.mode });
}
catch (e) {
if (bestEffort) {
errors === null || errors === void 0 ? void 0 : errors.push(`Failed to create new file ${eff.path}`);
}
else {
throw e;
}
}
}
break;
case "patch":
applyPatch(eff, { dryRun, cwd, bestEffort, errors });
break;
case "mode change":
const currentMode = fs_extra_1.default.statSync(inCwd(eff.path)).mode;
if (((isExecutable(eff.newMode) && isExecutable(currentMode)) ||
(!isExecutable(eff.newMode) && !isExecutable(currentMode))) &&
dryRun) {
console.log(`Mode change is not required for file ${humanReadable(eff.path)}`);
}
fs_extra_1.default.chmodSync(inCwd(eff.path), eff.newMode);
break;
default:
(0, assertNever_1.assertNever)(eff);
}
});
};
exports.executeEffects = executeEffects;
function isExecutable(fileMode) {
// tslint:disable-next-line:no-bitwise
return (fileMode & 64) > 0;
}
const trimRight = (s) => s.replace(/\s+$/, "");
function linesAreEqual(a, b) {
return trimRight(a) === trimRight(b);
}
/**
* How does noNewLineAtEndOfFile work?
*
* if you remove the newline from a file that had one without editing other bits:
*
* it creates an insertion/removal pair where the insertion has \ No new line at end of file
*
* if you edit a file that didn't have a new line and don't add one:
*
* both insertion and deletion have \ No new line at end of file
*
* if you edit a file that didn't have a new line and add one:
*
* deletion has \ No new line at end of file
* but not insertion
*
* if you edit a file that had a new line and leave it in:
*
* neither insetion nor deletion have the annoation
*
*/
function applyPatch({ hunks, path }, { dryRun, cwd, bestEffort, errors, }) {
path = cwd ? (0, path_1.resolve)(cwd, path) : path;
// modifying the file in place
const fileContents = fs_extra_1.default.readFileSync(path).toString();
const mode = fs_extra_1.default.statSync(path).mode;
const fileLines = fileContents.split(/\n/);
const result = [];
for (const hunk of hunks) {
let fuzzingOffset = 0;
while (true) {
const modifications = evaluateHunk(hunk, fileLines, fuzzingOffset);
if (modifications) {
result.push(modifications);
break;
}
fuzzingOffset =
fuzzingOffset < 0 ? fuzzingOffset * -1 : fuzzingOffset * -1 - 1;
if (Math.abs(fuzzingOffset) > 20) {
const message = `Cannot apply hunk ${hunks.indexOf(hunk)} for file ${(0, path_1.relative)(process.cwd(), path)}\n\`\`\`diff\n${hunk.source}\n\`\`\`\n`;
if (bestEffort) {
errors === null || errors === void 0 ? void 0 : errors.push(message);
break;
}
else {
throw new Error(message);
}
}
}
}
if (dryRun) {
return;
}
let diffOffset = 0;
for (const modifications of result) {
for (const modification of modifications) {
switch (modification.type) {
case "splice":
fileLines.splice(modification.index + diffOffset, modification.numToDelete, ...modification.linesToInsert);
diffOffset +=
modification.linesToInsert.length - modification.numToDelete;
break;
case "pop":
fileLines.pop();
break;
case "push":
fileLines.push(modification.line);
break;
default:
(0, assertNever_1.assertNever)(modification);
}
}
}
try {
fs_extra_1.default.writeFileSync(path, fileLines.join("\n"), { mode });
}
catch (e) {
if (bestEffort) {
errors === null || errors === void 0 ? void 0 : errors.push(`Failed to write file ${path}`);
}
else {
throw e;
}
}
}
function evaluateHunk(hunk, fileLines, fuzzingOffset) {
const result = [];
let contextIndex = hunk.header.original.start - 1 + fuzzingOffset;
// do bounds checks for index
if (contextIndex < 0) {
return null;
}
if (fileLines.length - contextIndex < hunk.header.original.length) {
return null;
}
for (const part of hunk.parts) {
switch (part.type) {
case "deletion":
case "context":
for (const line of part.lines) {
const originalLine = fileLines[contextIndex];
if (!linesAreEqual(originalLine, line)) {
return null;
}
contextIndex++;
}
if (part.type === "deletion") {
result.push({
type: "splice",
index: contextIndex - part.lines.length,
numToDelete: part.lines.length,
linesToInsert: [],
});
if (part.noNewlineAtEndOfFile) {
result.push({
type: "push",
line: "",
});
}
}
break;
case "insertion":
result.push({
type: "splice",
index: contextIndex,
numToDelete: 0,
linesToInsert: part.lines,
});
if (part.noNewlineAtEndOfFile) {
result.push({ type: "pop" });
}
break;
default:
(0, assertNever_1.assertNever)(part.type);
}
}
return result;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGF0Y2gvYXBwbHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsd0RBQXlCO0FBQ3pCLCtCQUF1RDtBQUV2RCxnREFBNEM7QUFFckMsTUFBTSxjQUFjLEdBQUcsQ0FDNUIsT0FBd0IsRUFDeEIsRUFDRSxNQUFNLEVBQ04sVUFBVSxFQUNWLE1BQU0sRUFDTixHQUFHLEdBQ3VFLEVBQzVFLEVBQUU7SUFDRixNQUFNLEtBQUssR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUEsV0FBSSxFQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDOUQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUFDLElBQUEsZUFBUSxFQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUM1RSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDdEIsUUFBUSxHQUFHLENBQUMsSUFBSSxFQUFFO1lBQ2hCLEtBQUssZUFBZTtnQkFDbEIsSUFBSSxNQUFNLEVBQUU7b0JBQ1YsSUFBSSxDQUFDLGtCQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRTt3QkFDbkMsTUFBTSxJQUFJLEtBQUssQ0FDYiw0Q0FBNEM7NEJBQzFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQzFCLENBQUE7cUJBQ0Y7aUJBQ0Y7cUJBQU07b0JBQ0wseUJBQXlCO29CQUN6QixJQUFJO3dCQUNGLGtCQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtxQkFDL0I7b0JBQUMsT0FB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LFFBQVE7d0JBQ2QsS0FBSyxFQUFFLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU07d0JBQ3ZDLFdBQVcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU07d0JBQzlCLGFBQWEsRUFBRSxFQUFFO3FCQUNsQixDQUFDLENBQUE7b0JBRUYsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUU7d0JBQzdCLE1BQU0sQ0FBQyxJQUFJLENBQUM7NEJBQ1YsSUFBSSxFQUFFLE1BQU07NEJBQ1osSUFBSSxFQUFFLEVBQUU7eUJBQ1QsQ0FBQyxDQUFBO3FCQUNIO2lCQUNGO2dCQUNELE1BQUs7WUFDUCxLQUFLLFdBQVc7Z0JBQ2QsTUFBTSxDQUFDLElBQUksQ0FBQztvQkFDVixJQUFJLEVBQUUsUUFBUTtvQkFDZCxLQUFLLEVBQUUsWUFBWTtvQkFDbkIsV0FBVyxFQUFFLENBQUM7b0JBQ2QsYUFBYSxFQUFFLElBQUksQ0FBQyxLQUFLO2lCQUMxQixDQUFDLENBQUE7Z0JBQ0YsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUU7b0JBQzdCLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtpQkFDN0I7Z0JBQ0QsTUFBSztZQUNQO2dCQUNFLElBQUEseUJBQVcsRUFBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7U0FDekI7S0FDRjtJQUVELE9BQU8sTUFBTSxDQUFBO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgZGlybmFtZSwgam9pbiwgcmVsYXRpdmUsIHJlc29sdmUgfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyBQYXJzZWRQYXRjaEZpbGUsIEZpbGVQYXRjaCwgSHVuayB9IGZyb20gXCIuL3BhcnNlXCJcbmltcG9ydCB7IGFzc2VydE5ldmVyIH0gZnJvbSBcIi4uL2Fzc2VydE5ldmVyXCJcblxuZXhwb3J0IGNvbnN0IGV4ZWN1dGVFZmZlY3RzID0gKFxuICBlZmZlY3RzOiBQYXJzZWRQYXRjaEZpbGUsXG4gIHtcbiAgICBkcnlSdW4sXG4gICAgYmVzdEVmZm9ydCxcbiAgICBlcnJvcnMsXG4gICAgY3dkLFxuICB9OiB7IGRyeVJ1bjogYm9vbGVhbjsgY3dkPzogc3RyaW5nOyBlcnJvcnM/OiBzdHJpbmdbXTsgYmVzdEVmZm9ydDogYm9vbGVhbiB9LFxuKSA9PiB7XG4gIGNvbnN0IGluQ3dkID0gKHBhdGg6IHN0cmluZykgPT4gKGN3ZCA/IGpvaW4oY3dkLCBwYXRoKSA6IHBhdGgpXG4gIGNvbnN0IGh1bWFuUmVhZGFibGUgPSAocGF0aDogc3RyaW5nKSA9PiByZWxhdGl2ZShwcm9jZXNzLmN3ZCgpLCBpbkN3ZChwYXRoKSlcbiAgZWZmZWN0cy5mb3JFYWNoKChlZmYpID0+IHtcbiAgICBzd2l0Y2ggKGVmZi50eXBlKSB7XG4gICAgICBjYXNlIFwiZmlsZSBkZWxldGlvblwiOlxuICAgICAgICBpZiAoZHJ5UnVuKSB7XG4gICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGluQ3dkKGVmZi5wYXRoKSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgXCJUcnlpbmcgdG8gZGVsZXRlIGZpbGUgdGhhdCBkb2Vzbid0IGV4aXN0OiBcIiArXG4gICAgICAgICAgICAgICAgaHVtYW5SZWFkYWJsZShlZmYucGF0aCksXG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFRPRE86IGludGVncml0eSBjaGVja3NcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZnMudW5saW5rU3luYyhpbkN3ZChlZmYucGF0aCkpXG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKGJlc3RFZmZvcnQpIHtcbiAgICAgICAgICAgICAgZXJyb3JzPy5wdXNoKGBGYWlsZWQgdG8gZGVsZXRlIGZpbGUgJHtlZmYucGF0aH1gKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSBcInJlbmFtZVwiOlxuICAgICAgICBpZiAoZHJ5UnVuKSB7XG4gICAgICAgICAgLy8gVE9ETzogc2VlIHdoYXQgcGF0Y2ggZmlsZXMgbG9vayBsaWtlIGlmIG1vdmluZyB0byBleGlzaW5nIHBhdGhcbiAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoaW5Dd2QoZWZmLmZyb21QYXRoKSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgXCJUcnlpbmcgdG8gbW92ZSBmaWxlIHRoYXQgZG9lc24ndCBleGlzdDogXCIgK1xuICAgICAgICAgICAgICAgIGh1bWFuUmVhZGFibGUoZWZmLmZyb21QYXRoKSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZzLm1vdmVTeW5jKGluQ3dkKGVmZi5mcm9tUGF0aCksIGluQ3dkKGVmZi50b1BhdGgpKVxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmIChiZXN0RWZmb3J0KSB7XG4gICAgICAgICAgICAgIGVycm9ycz8ucHVzaChcbiAgICAgICAgICAgICAgICBgRmFpbGVkIHRvIHJlbmFtZSBmaWxlICR7ZWZmLmZyb21QYXRofSB0byAke2VmZi50b1BhdGh9YCxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSBcImZpbGUgY3JlYXRpb25cIjpcbiAgICAgICAgaWYgKGRyeVJ1bikge1xuICAgICAgICAgIGlmIChmcy5leGlzdHNTeW5jKGluQ3dkKGVmZi5wYXRoKSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgXCJUcnlpbmcgdG8gY3JlYXRlIGZpbGUgdGhhdCBhbHJlYWR5IGV4aXN0czogXCIgK1xuICAgICAgICAgICAgICAgIGh1bWFuUmVhZGFibGUoZWZmLnBhdGgpLFxuICAgICAgICAgICAgKVxuICAgICAgICAgIH1cbiAgICAgICAgICAvLyB0b2RvOiBjaGVjayBmaWxlIGNvbnRlbnRzIG1hdGNoZXNcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBmaWxlQ29udGVudHMgPSBlZmYuaHVua1xuICAgICAgICAgICAgPyBlZmYuaHVuay5wYXJ0c1swXS5saW5lcy5qb2luKFwiXFxuXCIpICtcbiAgICAgICAgICAgICAgKGVmZi5odW5rLnBhcnRzWzBdLm5vTmV3bGluZUF0RW5kT2ZGaWxlID8gXCJcIiA6IFwiXFxuXCIpXG4gICAgICAgICAgICA6IFwiXCJcbiAgICAgICAgICBjb25zdCBwYXRoID0gaW5Dd2QoZWZmLnBhdGgpXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZzLmVuc3VyZURpclN5bmMoZGlybmFtZShwYXRoKSlcbiAgICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmMocGF0aCwgZmlsZUNvbnRlbnRzLCB7IG1vZGU6IGVmZi5tb2RlIH0pXG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKGJlc3RFZmZvcnQpIHtcbiAgICAgICAgICAgICAgZXJyb3JzPy5wdXNoKGBGYWlsZWQgdG8gY3JlYXRlIG5ldyBmaWxlICR7ZWZmLnBhdGh9YClcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgXCJwYXRjaFwiOlxuICAgICAgICBhcHBseVBhdGNoKGVmZiwgeyBkcnlSdW4sIGN3ZCwgYmVzdEVmZm9ydCwgZXJyb3JzIH0pXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlIFwibW9kZSBjaGFuZ2VcIjpcbiAgICAgICAgY29uc3QgY3VycmVudE1vZGUgPSBmcy5zdGF0U3luYyhpbkN3ZChlZmYucGF0aCkpLm1vZGVcbiAgICAgICAgaWYgKFxuICAgICAgICAgICgoaXNFeGVjdXRhYmxlKGVmZi5uZXdNb2RlKSAmJiBpc0V4ZWN1dGFibGUoY3VycmVudE1vZGUpKSB8fFxuICAgICAgICAgICAgKCFpc0V4ZWN1dGFibGUoZWZmLm5ld01vZGUpICYmICFpc0V4ZWN1dGFibGUoY3VycmVudE1vZGUpKSkgJiZcbiAgICAgICAgICBkcnlSdW5cbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICBgTW9kZSBjaGFuZ2UgaXMgbm90IHJlcXVpcmVkIGZvciBmaWxlICR7aHVtYW5SZWFkYWJsZShlZmYucGF0aCl9YCxcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAgZnMuY2htb2RTeW5jKGluQ3dkKGVmZi5wYXRoKSwgZWZmLm5ld01vZGUpXG4gICAgICAgIGJyZWFrXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBhc3NlcnROZXZlcihlZmYpXG4gICAgfVxuICB9KVxufVxuXG5mdW5jdGlvbiBpc0V4ZWN1dGFibGUoZmlsZU1vZGU6IG51bWJlcikge1xuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYml0d2lzZVxuICByZXR1cm4gKGZpbGVNb2RlICYgMGIwMDFfMDAwXzAwMCkgPiAwXG59XG5cbmNvbnN0IHRyaW1SaWdodCA9IChzOiBzdHJpbmcpID0+IHMucmVwbGFjZSgvXFxzKyQvLCBcIlwiKVxuZnVuY3Rpb24gbGluZXNBcmVFcXVhbChhOiBzdHJpbmcsIGI6IHN0cmluZykge1xuICByZXR1cm4gdHJpbVJpZ2h0KGEpID09PSB0cmltUmlnaHQoYilcbn1cblxuLyoqXG4gKiBIb3cgZG9lcyBub05ld0xpbmVBdEVuZE9mRmlsZSB3b3JrP1xuICpcbiAqIGlmIHlvdSByZW1vdmUgdGhlIG5ld2xpbmUgZnJvbSBhIGZpbGUgdGhhdCBoYWQgb25lIHdpdGhvdXQgZWRpdGluZyBvdGhlciBiaXRzOlxuICpcbiAqICAgIGl0IGNyZWF0ZXMgYW4gaW5zZXJ0aW9uL3JlbW92YWwgcGFpciB3aGVyZSB0aGUgaW5zZXJ0aW9uIGhhcyBcXCBObyBuZXcgbGluZSBhdCBlbmQgb2YgZmlsZVxuICpcbiAqIGlmIHlvdSBlZGl0IGEgZmlsZSB0aGF0IGRpZG4ndCBoYXZlIGEgbmV3IGxpbmUgYW5kIGRvbid0IGFkZCBvbmU6XG4gKlxuICogICAgYm90aCBpbnNlcnRpb24gYW5kIGRlbGV0aW9uIGhhdmUgXFwgTm8gbmV3IGxpbmUgYXQgZW5kIG9mIGZpbGVcbiAqXG4gKiBpZiB5b3UgZWRpdCBhIGZpbGUgdGhhdCBkaWRuJ3QgaGF2ZSBhIG5ldyBsaW5lIGFuZCBhZGQgb25lOlxuICpcbiAqICAgIGRlbGV0aW9uIGhhcyBcXCBObyBuZXcgbGluZSBhdCBlbmQgb2YgZmlsZVxuICogICAgYnV0IG5vdCBpbnNlcnRpb25cbiAqXG4gKiBpZiB5b3UgZWRpdCBhIGZpbGUgdGhhdCBoYWQgYSBuZXcgbGluZSBhbmQgbGVhdmUgaXQgaW46XG4gKlxuICogICAgbmVpdGhlciBpbnNldGlvbiBub3IgZGVsZXRpb24gaGF2ZSB0aGUgYW5ub2F0aW9uXG4gKlxuICovXG5cbmZ1bmN0aW9uIGFwcGx5UGF0Y2goXG4gIHsgaHVua3MsIHBhdGggfTogRmlsZVBhdGNoLFxuICB7XG4gICAgZHJ5UnVuLFxuICAgIGN3ZCxcbiAgICBiZXN0RWZmb3J0LFxuICAgIGVycm9ycyxcbiAgfTogeyBkcnlSdW46IGJvb2xlYW47IGN3ZD86IHN0cmluZzsgYmVzdEVmZm9ydDogYm9vbGVhbjsgZXJyb3JzPzogc3RyaW5nW10gfSxcbik6IHZvaWQge1xuICBwYXRoID0gY3dkID8gcmVzb2x2ZShjd2QsIHBhdGgpIDogcGF0aFxuICAvLyBtb2RpZnlpbmcgdGhlIGZpbGUgaW4gcGxhY2VcbiAgY29uc3QgZmlsZUNvbnRlbnRzID0gZnMucmVhZEZpbGVTeW5jKHBhdGgpLnRvU3RyaW5nKClcbiAgY29uc3QgbW9kZSA9IGZzLnN0YXRTeW5jKHBhdGgpLm1vZGVcblxuICBjb25zdCBmaWxlTGluZXM6IHN0cmluZ1tdID0gZmlsZUNvbnRlbnRzLnNwbGl0KC9cXG4vKVxuXG4gIGNvbnN0IHJlc3VsdDogTW9kaWZpY2F0aW9uW11bXSA9IFtdXG5cbiAgZm9yIChjb25zdCBodW5rIG9mIGh1bmtzKSB7XG4gICAgbGV0IGZ1enppbmdPZmZzZXQgPSAwXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IG1vZGlmaWNhdGlvbnMgPSBldmFsdWF0ZUh1bmsoaHVuaywgZmlsZUxpbmVzLCBmdXp6aW5nT2Zmc2V0KVxuICAgICAgaWYgKG1vZGlmaWNhdGlvbnMpIHtcbiAgICAgICAgcmVzdWx0LnB1c2gobW9kaWZpY2F0aW9ucylcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cblxuICAgICAgZnV6emluZ09mZnNldCA9XG4gICAgICAgIGZ1enppbmdPZmZzZXQgPCAwID8gZnV6emluZ09mZnNldCAqIC0xIDogZnV6emluZ09mZnNldCAqIC0xIC0gMVxuXG4gICAgICBpZiAoTWF0aC5hYnMoZnV6emluZ09mZnNldCkgPiAyMCkge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gYENhbm5vdCBhcHBseSBodW5rICR7aHVua3MuaW5kZXhPZihcbiAgICAgICAgICBodW5rLFxuICAgICAgICApfSBmb3IgZmlsZSAke3JlbGF0aXZlKHByb2Nlc3MuY3dkKCksIHBhdGgpfVxcblxcYFxcYFxcYGRpZmZcXG4ke1xuICAgICAgICAgIGh1bmsuc291cmNlXG4gICAgICAgIH1cXG5cXGBcXGBcXGBcXG5gXG5cbiAgICAgICAgaWYgKGJlc3RFZmZvcnQpIHtcbiAgICAgICAgICBlcnJvcnM/LnB1c2gobWVzc2FnZSlcbiAgICAgICAgICBicmVha1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKGRyeVJ1bikge1xuICAgIHJldHVyblxuICB9XG5cbiAgbGV0IGRpZmZPZmZzZXQgPSAwXG5cbiAgZm9yIChjb25zdCBtb2RpZmljYXRpb25zIG9mIHJlc3VsdCkge1xuICAgIGZvciAoY29uc3QgbW9kaWZpY2F0aW9uIG9mIG1vZGlmaWNhdGlvbnMpIHtcbiAgICAgIHN3aXRjaCAobW9kaWZpY2F0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSBcInNwbGljZVwiOlxuICAgICAgICAgIGZpbGVMaW5lcy5zcGxpY2UoXG4gICAgICAgICAgICBtb2RpZmljYXRpb24uaW5kZXggKyBkaWZmT2Zmc2V0LFxuICAgICAgICAgICAgbW9kaWZpY2F0aW9uLm51bVRvRGVsZXRlLFxuICAgICAgICAgICAgLi4ubW9kaWZpY2F0aW9uLmxpbmVzVG9JbnNlcnQsXG4gICAgICAgICAgKVxuICAgICAgICAgIGRpZmZPZmZzZXQgKz1cbiAgICAgICAgICAgIG1vZGlmaWNhdGlvbi5saW5lc1RvSW5zZXJ0Lmxlbmd0aCAtIG1vZGlmaWNhdGlvbi5udW1Ub0RlbGV0ZVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgXCJwb3BcIjpcbiAgICAgICAgICBmaWxlTGluZXMucG9wKClcbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIFwicHVzaFwiOlxuICAgICAgICAgIGZpbGVMaW5lcy5wdXNoKG1vZGlmaWNhdGlvbi5saW5lKVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgYXNzZXJ0TmV2ZXIobW9kaWZpY2F0aW9uKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRyeSB7XG4gICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLCBmaWxlTGluZXMuam9pbihcIlxcblwiKSwgeyBtb2RlIH0pXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoYmVzdEVmZm9ydCkge1xuICAgICAgZXJyb3JzPy5wdXNoKGBGYWlsZWQgdG8gd3JpdGUgZmlsZSAke3BhdGh9YClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZVxuICAgIH1cbiAgfVxufVxuXG5pbnRlcmZhY2UgUHVzaCB7XG4gIHR5cGU6IFwicHVzaFwiXG4gIGxpbmU6IHN0cmluZ1xufVxuaW50ZXJmYWNlIFBvcCB7XG4gIHR5cGU6IFwicG9wXCJcbn1cbmludGVyZmFjZSBTcGxpY2Uge1xuICB0eXBlOiBcInNwbGljZVwiXG4gIGluZGV4OiBudW1iZXJcbiAgbnVtVG9EZWxldGU6IG51bWJlclxuICBsaW5lc1RvSW5zZXJ0OiBzdHJpbmdbXVxufVxuXG50eXBlIE1vZGlmaWNhdGlvbiA9IFB1c2ggfCBQb3AgfCBTcGxpY2VcblxuZnVuY3Rpb24gZXZhbHVhdGVIdW5rKFxuICBodW5rOiBIdW5rLFxuICBmaWxlTGluZXM6IHN0cmluZ1tdLFxuICBmdXp6aW5nT2Zmc2V0OiBudW1iZXIsXG4pOiBNb2RpZmljYXRpb25bXSB8IG51bGwge1xuICBjb25zdCByZXN1bHQ6IE1vZGlmaWNhdGlvbltdID0gW11cbiAgbGV0IGNvbnRleHRJbmRleCA9IGh1bmsuaGVhZGVyLm9yaWdpbmFsLnN0YXJ0IC0gMSArIGZ1enppbmdPZmZzZXRcbiAgLy8gZG8gYm91bmRzIGNoZWNrcyBmb3IgaW5kZXhcbiAgaWYgKGNvbnRleHRJbmRleCA8IDApIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIGlmIChmaWxlTGluZXMubGVuZ3RoIC0gY29udGV4dEluZGV4IDwgaHVuay5oZWFkZXIub3JpZ2luYWwubGVuZ3RoKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGZvciAoY29uc3QgcGFydCBvZiBodW5rLnBhcnRzKSB7XG4gICAgc3dpdGNoIChwYXJ0LnR5cGUpIHtcbiAgICAgIGNhc2UgXCJkZWxldGlvblwiOlxuICAgICAgY2FzZSBcImNvbnRleHRcIjpcbiAgICAgICAgZm9yIChjb25zdCBsaW5lIG9mIHBhcnQubGluZXMpIHtcbiAgICAgICAgICBjb25zdCBvcmlnaW5hbExpbmUgPSBmaWxlTGluZXNbY29udGV4dEluZGV4XVxuICAgICAgICAgIGlmICghbGluZXNBcmVFcXVhbChvcmlnaW5hbExpbmUsIGxpbmUpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICAgIH1cbiAgICAgICAgICBjb250ZXh0SW5kZXgrK1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gXCJkZWxldGlvblwiKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICAgICAgdHlwZTogXCJzcGxpY2VcIixcbiAgICAgICAgICAgIGluZGV4OiBjb250ZXh0SW5kZXggLSBwYXJ0LmxpbmVzLmxlbmd0aCxcbiAgICAgICAgICAgIG51bVRvRGVsZXRlOiBwYXJ0LmxpbmVzLmxlbmd0aCxcbiAgICAgICAgICAgIGxpbmVzVG9JbnNlcnQ6IFtdLFxuICAgICAgICAgIH0pXG5cbiAgICAgICAgICBpZiAocGFydC5ub05ld2xpbmVBdEVuZE9mRmlsZSkge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICAgICAgICB0eXBlOiBcInB1c2hcIixcbiAgICAgICAgICAgICAgbGluZTogXCJcIixcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlIFwiaW5zZXJ0aW9uXCI6XG4gICAgICAgIHJlc3VsdC5wdXNoKHtcbiAgICAgICAgICB0eXBlOiBcInNwbGljZVwiLFxuICAgICAgICAgIGluZGV4OiBjb250ZXh0SW5kZXgsXG4gICAgICAgICAgbnVtVG9EZWxldGU6IDAsXG4gICAgICAgICAgbGluZXNUb0luc2VydDogcGFydC5saW5lcyxcbiAgICAgICAgfSlcbiAgICAgICAgaWYgKHBhcnQubm9OZXdsaW5lQXRFbmRPZkZpbGUpIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh7IHR5cGU6IFwicG9wXCIgfSlcbiAgICAgICAgfVxuICAgICAgICBicmVha1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYXNzZXJ0TmV2ZXIocGFydC50eXBlKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHRcbn1cbiJdfQ==