@psync/patch-package 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,251 @@
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.executeEffects = void 0;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = require("path");
9
+ const assertNever_1 = require("../assertNever");
10
+ const executeEffects = (effects, { dryRun, bestEffort, errors, cwd, }) => {
11
+ const inCwd = (path) => (cwd ? (0, path_1.join)(cwd, path) : path);
12
+ const humanReadable = (path) => (0, path_1.relative)(process.cwd(), inCwd(path));
13
+ effects.forEach((eff) => {
14
+ switch (eff.type) {
15
+ case "file deletion":
16
+ if (dryRun) {
17
+ if (!fs_extra_1.default.existsSync(inCwd(eff.path))) {
18
+ throw new Error("Trying to delete file that doesn't exist: " +
19
+ humanReadable(eff.path));
20
+ }
21
+ }
22
+ else {
23
+ // TODO: integrity checks
24
+ try {
25
+ fs_extra_1.default.unlinkSync(inCwd(eff.path));
26
+ }
27
+ catch (e) {
28
+ if (bestEffort) {
29
+ errors?.push(`Failed to delete file ${eff.path}`);
30
+ }
31
+ else {
32
+ throw e;
33
+ }
34
+ }
35
+ }
36
+ break;
37
+ case "rename":
38
+ if (dryRun) {
39
+ // TODO: see what patch files look like if moving to exising path
40
+ if (!fs_extra_1.default.existsSync(inCwd(eff.fromPath))) {
41
+ throw new Error("Trying to move file that doesn't exist: " +
42
+ humanReadable(eff.fromPath));
43
+ }
44
+ }
45
+ else {
46
+ try {
47
+ fs_extra_1.default.moveSync(inCwd(eff.fromPath), inCwd(eff.toPath));
48
+ }
49
+ catch (e) {
50
+ if (bestEffort) {
51
+ errors?.push(`Failed to rename file ${eff.fromPath} to ${eff.toPath}`);
52
+ }
53
+ else {
54
+ throw e;
55
+ }
56
+ }
57
+ }
58
+ break;
59
+ case "file creation":
60
+ if (dryRun) {
61
+ if (fs_extra_1.default.existsSync(inCwd(eff.path))) {
62
+ throw new Error("Trying to create file that already exists: " +
63
+ humanReadable(eff.path));
64
+ }
65
+ // todo: check file contents matches
66
+ }
67
+ else {
68
+ const fileContents = eff.hunk
69
+ ? eff.hunk.parts[0].lines.join("\n") +
70
+ (eff.hunk.parts[0].noNewlineAtEndOfFile ? "" : "\n")
71
+ : "";
72
+ const path = inCwd(eff.path);
73
+ try {
74
+ fs_extra_1.default.ensureDirSync((0, path_1.dirname)(path));
75
+ fs_extra_1.default.writeFileSync(path, fileContents, { mode: eff.mode });
76
+ }
77
+ catch (e) {
78
+ if (bestEffort) {
79
+ errors?.push(`Failed to create new file ${eff.path}`);
80
+ }
81
+ else {
82
+ throw e;
83
+ }
84
+ }
85
+ }
86
+ break;
87
+ case "patch":
88
+ applyPatch(eff, { dryRun, cwd, bestEffort, errors });
89
+ break;
90
+ case "mode change":
91
+ const currentMode = fs_extra_1.default.statSync(inCwd(eff.path)).mode;
92
+ if (((isExecutable(eff.newMode) && isExecutable(currentMode)) ||
93
+ (!isExecutable(eff.newMode) && !isExecutable(currentMode))) &&
94
+ dryRun) {
95
+ console.log(`Mode change is not required for file ${humanReadable(eff.path)}`);
96
+ }
97
+ fs_extra_1.default.chmodSync(inCwd(eff.path), eff.newMode);
98
+ break;
99
+ default:
100
+ (0, assertNever_1.assertNever)(eff);
101
+ }
102
+ });
103
+ };
104
+ exports.executeEffects = executeEffects;
105
+ function isExecutable(fileMode) {
106
+ // tslint:disable-next-line:no-bitwise
107
+ return (fileMode & 64) > 0;
108
+ }
109
+ const trimRight = (s) => s.replace(/\s+$/, "");
110
+ function linesAreEqual(a, b) {
111
+ return trimRight(a) === trimRight(b);
112
+ }
113
+ /**
114
+ * How does noNewLineAtEndOfFile work?
115
+ *
116
+ * if you remove the newline from a file that had one without editing other bits:
117
+ *
118
+ * it creates an insertion/removal pair where the insertion has \ No new line at end of file
119
+ *
120
+ * if you edit a file that didn't have a new line and don't add one:
121
+ *
122
+ * both insertion and deletion have \ No new line at end of file
123
+ *
124
+ * if you edit a file that didn't have a new line and add one:
125
+ *
126
+ * deletion has \ No new line at end of file
127
+ * but not insertion
128
+ *
129
+ * if you edit a file that had a new line and leave it in:
130
+ *
131
+ * neither insetion nor deletion have the annoation
132
+ *
133
+ */
134
+ function applyPatch({ hunks, path }, { dryRun, cwd, bestEffort, errors, }) {
135
+ path = cwd ? (0, path_1.resolve)(cwd, path) : path;
136
+ // modifying the file in place
137
+ const fileContents = fs_extra_1.default.readFileSync(path).toString();
138
+ const mode = fs_extra_1.default.statSync(path).mode;
139
+ const fileLines = fileContents.split(/\n/);
140
+ const result = [];
141
+ for (const hunk of hunks) {
142
+ let fuzzingOffset = 0;
143
+ while (true) {
144
+ const modifications = evaluateHunk(hunk, fileLines, fuzzingOffset);
145
+ if (modifications) {
146
+ result.push(modifications);
147
+ break;
148
+ }
149
+ fuzzingOffset =
150
+ fuzzingOffset < 0 ? fuzzingOffset * -1 : fuzzingOffset * -1 - 1;
151
+ if (Math.abs(fuzzingOffset) > 20) {
152
+ const message = `Cannot apply hunk ${hunks.indexOf(hunk)} for file ${(0, path_1.relative)(process.cwd(), path)}\n\`\`\`diff\n${hunk.source}\n\`\`\`\n`;
153
+ if (bestEffort) {
154
+ errors?.push(message);
155
+ break;
156
+ }
157
+ else {
158
+ throw new Error(message);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ if (dryRun) {
164
+ return;
165
+ }
166
+ let diffOffset = 0;
167
+ for (const modifications of result) {
168
+ for (const modification of modifications) {
169
+ switch (modification.type) {
170
+ case "splice":
171
+ fileLines.splice(modification.index + diffOffset, modification.numToDelete, ...modification.linesToInsert);
172
+ diffOffset +=
173
+ modification.linesToInsert.length - modification.numToDelete;
174
+ break;
175
+ case "pop":
176
+ fileLines.pop();
177
+ break;
178
+ case "push":
179
+ fileLines.push(modification.line);
180
+ break;
181
+ default:
182
+ (0, assertNever_1.assertNever)(modification);
183
+ }
184
+ }
185
+ }
186
+ try {
187
+ fs_extra_1.default.writeFileSync(path, fileLines.join("\n"), { mode });
188
+ }
189
+ catch (e) {
190
+ if (bestEffort) {
191
+ errors?.push(`Failed to write file ${path}`);
192
+ }
193
+ else {
194
+ throw e;
195
+ }
196
+ }
197
+ }
198
+ function evaluateHunk(hunk, fileLines, fuzzingOffset) {
199
+ const result = [];
200
+ let contextIndex = hunk.header.original.start - 1 + fuzzingOffset;
201
+ // do bounds checks for index
202
+ if (contextIndex < 0) {
203
+ return null;
204
+ }
205
+ if (fileLines.length - contextIndex < hunk.header.original.length) {
206
+ return null;
207
+ }
208
+ for (const part of hunk.parts) {
209
+ switch (part.type) {
210
+ case "deletion":
211
+ case "context":
212
+ for (const line of part.lines) {
213
+ const originalLine = fileLines[contextIndex];
214
+ if (!linesAreEqual(originalLine, line)) {
215
+ return null;
216
+ }
217
+ contextIndex++;
218
+ }
219
+ if (part.type === "deletion") {
220
+ result.push({
221
+ type: "splice",
222
+ index: contextIndex - part.lines.length,
223
+ numToDelete: part.lines.length,
224
+ linesToInsert: [],
225
+ });
226
+ if (part.noNewlineAtEndOfFile) {
227
+ result.push({
228
+ type: "push",
229
+ line: "",
230
+ });
231
+ }
232
+ }
233
+ break;
234
+ case "insertion":
235
+ result.push({
236
+ type: "splice",
237
+ index: contextIndex,
238
+ numToDelete: 0,
239
+ linesToInsert: part.lines,
240
+ });
241
+ if (part.noNewlineAtEndOfFile) {
242
+ result.push({ type: "pop" });
243
+ }
244
+ break;
245
+ default:
246
+ (0, assertNever_1.assertNever)(part.type);
247
+ }
248
+ }
249
+ return result;
250
+ }
251
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGF0Y2gvYXBwbHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsd0RBQXlCO0FBQ3pCLCtCQUF1RDtBQUV2RCxnREFBNEM7QUFFckMsTUFBTSxjQUFjLEdBQUcsQ0FDNUIsT0FBd0IsRUFDeEIsRUFDRSxNQUFNLEVBQ04sVUFBVSxFQUNWLE1BQU0sRUFDTixHQUFHLEdBQ3VFLEVBQzVFLEVBQUU7SUFDRixNQUFNLEtBQUssR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUEsV0FBSSxFQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDOUQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUFDLElBQUEsZUFBUSxFQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUM1RSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDdEIsUUFBUSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDakIsS0FBSyxlQUFlO2dCQUNsQixJQUFJLE1BQU0sRUFBRSxDQUFDO29CQUNYLElBQUksQ0FBQyxrQkFBRSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQzt3QkFDcEMsTUFBTSxJQUFJLEtBQUssQ0FDYiw0Q0FBNEM7NEJBQzFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQzFCLENBQUE7b0JBQ0gsQ0FBQztnQkFDSCxDQUFDO3FCQUFNLENBQUM7b0JBQ04seUJBQXlCO29CQUN6QixJQUFJLENBQUM7d0JBQ0gsa0JBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJ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RSxJQUFBLHlCQUFXLEVBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxNQUFNLENBQUE7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gXCJmcy1leHRyYVwiXHJcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4sIHJlbGF0aXZlLCByZXNvbHZlIH0gZnJvbSBcInBhdGhcIlxyXG5pbXBvcnQgeyBQYXJzZWRQYXRjaEZpbGUsIEZpbGVQYXRjaCwgSHVuayB9IGZyb20gXCIuL3BhcnNlXCJcclxuaW1wb3J0IHsgYXNzZXJ0TmV2ZXIgfSBmcm9tIFwiLi4vYXNzZXJ0TmV2ZXJcIlxyXG5cclxuZXhwb3J0IGNvbnN0IGV4ZWN1dGVFZmZlY3RzID0gKFxyXG4gIGVmZmVjdHM6IFBhcnNlZFBhdGNoRmlsZSxcclxuICB7XHJcbiAgICBkcnlSdW4sXHJcbiAgICBiZXN0RWZmb3J0LFxyXG4gICAgZXJyb3JzLFxyXG4gICAgY3dkLFxyXG4gIH06IHsgZHJ5UnVuOiBib29sZWFuOyBjd2Q/OiBzdHJpbmc7IGVycm9ycz86IHN0cmluZ1tdOyBiZXN0RWZmb3J0OiBib29sZWFuIH0sXHJcbikgPT4ge1xyXG4gIGNvbnN0IGluQ3dkID0gKHBhdGg6IHN0cmluZykgPT4gKGN3ZCA/IGpvaW4oY3dkLCBwYXRoKSA6IHBhdGgpXHJcbiAgY29uc3QgaHVtYW5SZWFkYWJsZSA9IChwYXRoOiBzdHJpbmcpID0+IHJlbGF0aXZlKHByb2Nlc3MuY3dkKCksIGluQ3dkKHBhdGgpKVxyXG4gIGVmZmVjdHMuZm9yRWFjaCgoZWZmKSA9PiB7XHJcbiAgICBzd2l0Y2ggKGVmZi50eXBlKSB7XHJcbiAgICAgIGNhc2UgXCJmaWxlIGRlbGV0aW9uXCI6XHJcbiAgICAgICAgaWYgKGRyeVJ1bikge1xyXG4gICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGluQ3dkKGVmZi5wYXRoKSkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxyXG4gICAgICAgICAgICAgIFwiVHJ5aW5nIHRvIGRlbGV0ZSBmaWxlIHRoYXQgZG9lc24ndCBleGlzdDogXCIgK1xyXG4gICAgICAgICAgICAgICAgaHVtYW5SZWFkYWJsZShlZmYucGF0aCksXHJcbiAgICAgICAgICAgIClcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gVE9ETzogaW50ZWdyaXR5IGNoZWNrc1xyXG4gICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgZnMudW5saW5rU3luYyhpbkN3ZChlZmYucGF0aCkpXHJcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGlmIChiZXN0RWZmb3J0KSB7XHJcbiAgICAgICAgICAgICAgZXJyb3JzPy5wdXNoKGBGYWlsZWQgdG8gZGVsZXRlIGZpbGUgJHtlZmYucGF0aH1gKVxyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIHRocm93IGVcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBicmVha1xyXG4gICAgICBjYXNlIFwicmVuYW1lXCI6XHJcbiAgICAgICAgaWYgKGRyeVJ1bikge1xyXG4gICAgICAgICAgLy8gVE9ETzogc2VlIHdoYXQgcGF0Y2ggZmlsZXMgbG9vayBsaWtlIGlmIG1vdmluZyB0byBleGlzaW5nIHBhdGhcclxuICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhpbkN3ZChlZmYuZnJvbVBhdGgpKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgICAgICAgICAgXCJUcnlpbmcgdG8gbW92ZSBmaWxlIHRoYXQgZG9lc24ndCBleGlzdDogXCIgK1xyXG4gICAgICAgICAgICAgICAgaHVtYW5SZWFkYWJsZShlZmYuZnJvbVBhdGgpLFxyXG4gICAgICAgICAgICApXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGZzLm1vdmVTeW5jKGluQ3dkKGVmZi5mcm9tUGF0aCksIGluQ3dkKGVmZi50b1BhdGgpKVxyXG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICBpZiAoYmVzdEVmZm9ydCkge1xyXG4gICAgICAgICAgICAgIGVycm9ycz8ucHVzaChcclxuICAgICAgICAgICAgICAgIGBGYWlsZWQgdG8gcmVuYW1lIGZpbGUgJHtlZmYuZnJvbVBhdGh9IHRvICR7ZWZmLnRvUGF0aH1gLFxyXG4gICAgICAgICAgICAgIClcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICB0aHJvdyBlXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgY2FzZSBcImZpbGUgY3JlYXRpb25cIjpcclxuICAgICAgICBpZiAoZHJ5UnVuKSB7XHJcbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhpbkN3ZChlZmYucGF0aCkpKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICAgICAgICBcIlRyeWluZyB0byBjcmVhdGUgZmlsZSB0aGF0IGFscmVhZHkgZXhpc3RzOiBcIiArXHJcbiAgICAgICAgICAgICAgICBodW1hblJlYWRhYmxlKGVmZi5wYXRoKSxcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgLy8gdG9kbzogY2hlY2sgZmlsZSBjb250ZW50cyBtYXRjaGVzXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnN0IGZpbGVDb250ZW50cyA9IGVmZi5odW5rXHJcbiAgICAgICAgICAgID8gZWZmLmh1bmsucGFydHNbMF0ubGluZXMuam9pbihcIlxcblwiKSArXHJcbiAgICAgICAgICAgICAgKGVmZi5odW5rLnBhcnRzWzBdLm5vTmV3bGluZUF0RW5kT2ZGaWxlID8gXCJcIiA6IFwiXFxuXCIpXHJcbiAgICAgICAgICAgIDogXCJcIlxyXG4gICAgICAgICAgY29uc3QgcGF0aCA9IGluQ3dkKGVmZi5wYXRoKVxyXG4gICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgZnMuZW5zdXJlRGlyU3luYyhkaXJuYW1lKHBhdGgpKVxyXG4gICAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGgsIGZpbGVDb250ZW50cywgeyBtb2RlOiBlZmYubW9kZSB9KVxyXG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICBpZiAoYmVzdEVmZm9ydCkge1xyXG4gICAgICAgICAgICAgIGVycm9ycz8ucHVzaChgRmFpbGVkIHRvIGNyZWF0ZSBuZXcgZmlsZSAke2VmZi5wYXRofWApXHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgdGhyb3cgZVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgXCJwYXRjaFwiOlxyXG4gICAgICAgIGFwcGx5UGF0Y2goZWZmLCB7IGRyeVJ1biwgY3dkLCBiZXN0RWZmb3J0LCBlcnJvcnMgfSlcclxuICAgICAgICBicmVha1xyXG4gICAgICBjYXNlIFwibW9kZSBjaGFuZ2VcIjpcclxuICAgICAgICBjb25zdCBjdXJyZW50TW9kZSA9IGZzLnN0YXRTeW5jKGluQ3dkKGVmZi5wYXRoKSkubW9kZVxyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgICgoaXNFeGVjdXRhYmxlKGVmZi5uZXdNb2RlKSAmJiBpc0V4ZWN1dGFibGUoY3VycmVudE1vZGUpKSB8fFxyXG4gICAgICAgICAgICAoIWlzRXhlY3V0YWJsZShlZmYubmV3TW9kZSkgJiYgIWlzRXhlY3V0YWJsZShjdXJyZW50TW9kZSkpKSAmJlxyXG4gICAgICAgICAgZHJ5UnVuXHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICBjb25zb2xlLmxvZyhcclxuICAgICAgICAgICAgYE1vZGUgY2hhbmdlIGlzIG5vdCByZXF1aXJlZCBmb3IgZmlsZSAke2h1bWFuUmVhZGFibGUoZWZmLnBhdGgpfWAsXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZzLmNobW9kU3luYyhpbkN3ZChlZmYucGF0aCksIGVmZi5uZXdNb2RlKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgYXNzZXJ0TmV2ZXIoZWZmKVxyXG4gICAgfVxyXG4gIH0pXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGlzRXhlY3V0YWJsZShmaWxlTW9kZTogbnVtYmVyKSB7XHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWJpdHdpc2VcclxuICByZXR1cm4gKGZpbGVNb2RlICYgMGIwMDFfMDAwXzAwMCkgPiAwXHJcbn1cclxuXHJcbmNvbnN0IHRyaW1SaWdodCA9IChzOiBzdHJpbmcpID0+IHMucmVwbGFjZSgvXFxzKyQvLCBcIlwiKVxyXG5mdW5jdGlvbiBsaW5lc0FyZUVxdWFsKGE6IHN0cmluZywgYjogc3RyaW5nKSB7XHJcbiAgcmV0dXJuIHRyaW1SaWdodChhKSA9PT0gdHJpbVJpZ2h0KGIpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBIb3cgZG9lcyBub05ld0xpbmVBdEVuZE9mRmlsZSB3b3JrP1xyXG4gKlxyXG4gKiBpZiB5b3UgcmVtb3ZlIHRoZSBuZXdsaW5lIGZyb20gYSBmaWxlIHRoYXQgaGFkIG9uZSB3aXRob3V0IGVkaXRpbmcgb3RoZXIgYml0czpcclxuICpcclxuICogICAgaXQgY3JlYXRlcyBhbiBpbnNlcnRpb24vcmVtb3ZhbCBwYWlyIHdoZXJlIHRoZSBpbnNlcnRpb24gaGFzIFxcIE5vIG5ldyBsaW5lIGF0IGVuZCBvZiBmaWxlXHJcbiAqXHJcbiAqIGlmIHlvdSBlZGl0IGEgZmlsZSB0aGF0IGRpZG4ndCBoYXZlIGEgbmV3IGxpbmUgYW5kIGRvbid0IGFkZCBvbmU6XHJcbiAqXHJcbiAqICAgIGJvdGggaW5zZXJ0aW9uIGFuZCBkZWxldGlvbiBoYXZlIFxcIE5vIG5ldyBsaW5lIGF0IGVuZCBvZiBmaWxlXHJcbiAqXHJcbiAqIGlmIHlvdSBlZGl0IGEgZmlsZSB0aGF0IGRpZG4ndCBoYXZlIGEgbmV3IGxpbmUgYW5kIGFkZCBvbmU6XHJcbiAqXHJcbiAqICAgIGRlbGV0aW9uIGhhcyBcXCBObyBuZXcgbGluZSBhdCBlbmQgb2YgZmlsZVxyXG4gKiAgICBidXQgbm90IGluc2VydGlvblxyXG4gKlxyXG4gKiBpZiB5b3UgZWRpdCBhIGZpbGUgdGhhdCBoYWQgYSBuZXcgbGluZSBhbmQgbGVhdmUgaXQgaW46XHJcbiAqXHJcbiAqICAgIG5laXRoZXIgaW5zZXRpb24gbm9yIGRlbGV0aW9uIGhhdmUgdGhlIGFubm9hdGlvblxyXG4gKlxyXG4gKi9cclxuXHJcbmZ1bmN0aW9uIGFwcGx5UGF0Y2goXHJcbiAgeyBodW5rcywgcGF0aCB9OiBGaWxlUGF0Y2gsXHJcbiAge1xyXG4gICAgZHJ5UnVuLFxyXG4gICAgY3dkLFxyXG4gICAgYmVzdEVmZm9ydCxcclxuICAgIGVycm9ycyxcclxuICB9OiB7IGRyeVJ1bjogYm9vbGVhbjsgY3dkPzogc3RyaW5nOyBiZXN0RWZmb3J0OiBib29sZWFuOyBlcnJvcnM/OiBzdHJpbmdbXSB9LFxyXG4pOiB2b2lkIHtcclxuICBwYXRoID0gY3dkID8gcmVzb2x2ZShjd2QsIHBhdGgpIDogcGF0aFxyXG4gIC8vIG1vZGlmeWluZyB0aGUgZmlsZSBpbiBwbGFjZVxyXG4gIGNvbnN0IGZpbGVDb250ZW50cyA9IGZzLnJlYWRGaWxlU3luYyhwYXRoKS50b1N0cmluZygpXHJcbiAgY29uc3QgbW9kZSA9IGZzLnN0YXRTeW5jKHBhdGgpLm1vZGVcclxuXHJcbiAgY29uc3QgZmlsZUxpbmVzOiBzdHJpbmdbXSA9IGZpbGVDb250ZW50cy5zcGxpdCgvXFxuLylcclxuXHJcbiAgY29uc3QgcmVzdWx0OiBNb2RpZmljYXRpb25bXVtdID0gW11cclxuXHJcbiAgZm9yIChjb25zdCBodW5rIG9mIGh1bmtzKSB7XHJcbiAgICBsZXQgZnV6emluZ09mZnNldCA9IDBcclxuICAgIHdoaWxlICh0cnVlKSB7XHJcbiAgICAgIGNvbnN0IG1vZGlmaWNhdGlvbnMgPSBldmFsdWF0ZUh1bmsoaHVuaywgZmlsZUxpbmVzLCBmdXp6aW5nT2Zmc2V0KVxyXG4gICAgICBpZiAobW9kaWZpY2F0aW9ucykge1xyXG4gICAgICAgIHJlc3VsdC5wdXNoKG1vZGlmaWNhdGlvbnMpXHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgfVxyXG5cclxuICAgICAgZnV6emluZ09mZnNldCA9XHJcbiAgICAgICAgZnV6emluZ09mZnNldCA8IDAgPyBmdXp6aW5nT2Zmc2V0ICogLTEgOiBmdXp6aW5nT2Zmc2V0ICogLTEgLSAxXHJcblxyXG4gICAgICBpZiAoTWF0aC5hYnMoZnV6emluZ09mZnNldCkgPiAyMCkge1xyXG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgQ2Fubm90IGFwcGx5IGh1bmsgJHtodW5rcy5pbmRleE9mKFxyXG4gICAgICAgICAgaHVuayxcclxuICAgICAgICApfSBmb3IgZmlsZSAke3JlbGF0aXZlKHByb2Nlc3MuY3dkKCksIHBhdGgpfVxcblxcYFxcYFxcYGRpZmZcXG4ke1xyXG4gICAgICAgICAgaHVuay5zb3VyY2VcclxuICAgICAgICB9XFxuXFxgXFxgXFxgXFxuYFxyXG5cclxuICAgICAgICBpZiAoYmVzdEVmZm9ydCkge1xyXG4gICAgICAgICAgZXJyb3JzPy5wdXNoKG1lc3NhZ2UpXHJcbiAgICAgICAgICBicmVha1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSlcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmIChkcnlSdW4pIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgbGV0IGRpZmZPZmZzZXQgPSAwXHJcblxyXG4gIGZvciAoY29uc3QgbW9kaWZpY2F0aW9ucyBvZiByZXN1bHQpIHtcclxuICAgIGZvciAoY29uc3QgbW9kaWZpY2F0aW9uIG9mIG1vZGlmaWNhdGlvbnMpIHtcclxuICAgICAgc3dpdGNoIChtb2RpZmljYXRpb24udHlwZSkge1xyXG4gICAgICAgIGNhc2UgXCJzcGxpY2VcIjpcclxuICAgICAgICAgIGZpbGVMaW5lcy5zcGxpY2UoXHJcbiAgICAgICAgICAgIG1vZGlmaWNhdGlvbi5pbmRleCArIGRpZmZPZmZzZXQsXHJcbiAgICAgICAgICAgIG1vZGlmaWNhdGlvbi5udW1Ub0RlbGV0ZSxcclxuICAgICAgICAgICAgLi4ubW9kaWZpY2F0aW9uLmxpbmVzVG9JbnNlcnQsXHJcbiAgICAgICAgICApXHJcbiAgICAgICAgICBkaWZmT2Zmc2V0ICs9XHJcbiAgICAgICAgICAgIG1vZGlmaWNhdGlvbi5saW5lc1RvSW5zZXJ0Lmxlbmd0aCAtIG1vZGlmaWNhdGlvbi5udW1Ub0RlbGV0ZVxyXG4gICAgICAgICAgYnJlYWtcclxuICAgICAgICBjYXNlIFwicG9wXCI6XHJcbiAgICAgICAgICBmaWxlTGluZXMucG9wKClcclxuICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgY2FzZSBcInB1c2hcIjpcclxuICAgICAgICAgIGZpbGVMaW5lcy5wdXNoKG1vZGlmaWNhdGlvbi5saW5lKVxyXG4gICAgICAgICAgYnJlYWtcclxuICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgYXNzZXJ0TmV2ZXIobW9kaWZpY2F0aW9uKVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0cnkge1xyXG4gICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLCBmaWxlTGluZXMuam9pbihcIlxcblwiKSwgeyBtb2RlIH0pXHJcbiAgfSBjYXRjaCAoZSkge1xyXG4gICAgaWYgKGJlc3RFZmZvcnQpIHtcclxuICAgICAgZXJyb3JzPy5wdXNoKGBGYWlsZWQgdG8gd3JpdGUgZmlsZSAke3BhdGh9YClcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IGVcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmludGVyZmFjZSBQdXNoIHtcclxuICB0eXBlOiBcInB1c2hcIlxyXG4gIGxpbmU6IHN0cmluZ1xyXG59XHJcbmludGVyZmFjZSBQb3Age1xyXG4gIHR5cGU6IFwicG9wXCJcclxufVxyXG5pbnRlcmZhY2UgU3BsaWNlIHtcclxuICB0eXBlOiBcInNwbGljZVwiXHJcbiAgaW5kZXg6IG51bWJlclxyXG4gIG51bVRvRGVsZXRlOiBudW1iZXJcclxuICBsaW5lc1RvSW5zZXJ0OiBzdHJpbmdbXVxyXG59XHJcblxyXG50eXBlIE1vZGlmaWNhdGlvbiA9IFB1c2ggfCBQb3AgfCBTcGxpY2VcclxuXHJcbmZ1bmN0aW9uIGV2YWx1YXRlSHVuayhcclxuICBodW5rOiBIdW5rLFxyXG4gIGZpbGVMaW5lczogc3RyaW5nW10sXHJcbiAgZnV6emluZ09mZnNldDogbnVtYmVyLFxyXG4pOiBNb2RpZmljYXRpb25bXSB8IG51bGwge1xyXG4gIGNvbnN0IHJlc3VsdDogTW9kaWZpY2F0aW9uW10gPSBbXVxyXG4gIGxldCBjb250ZXh0SW5kZXggPSBodW5rLmhlYWRlci5vcmlnaW5hbC5zdGFydCAtIDEgKyBmdXp6aW5nT2Zmc2V0XHJcbiAgLy8gZG8gYm91bmRzIGNoZWNrcyBmb3IgaW5kZXhcclxuICBpZiAoY29udGV4dEluZGV4IDwgMCkge1xyXG4gICAgcmV0dXJuIG51bGxcclxuICB9XHJcbiAgaWYgKGZpbGVMaW5lcy5sZW5ndGggLSBjb250ZXh0SW5kZXggPCBodW5rLmhlYWRlci5vcmlnaW5hbC5sZW5ndGgpIHtcclxuICAgIHJldHVybiBudWxsXHJcbiAgfVxyXG5cclxuICBmb3IgKGNvbnN0IHBhcnQgb2YgaHVuay5wYXJ0cykge1xyXG4gICAgc3dpdGNoIChwYXJ0LnR5cGUpIHtcclxuICAgICAgY2FzZSBcImRlbGV0aW9uXCI6XHJcbiAgICAgIGNhc2UgXCJjb250ZXh0XCI6XHJcbiAgICAgICAgZm9yIChjb25zdCBsaW5lIG9mIHBhcnQubGluZXMpIHtcclxuICAgICAgICAgIGNvbnN0IG9yaWdpbmFsTGluZSA9IGZpbGVMaW5lc1tjb250ZXh0SW5kZXhdXHJcbiAgICAgICAgICBpZiAoIWxpbmVzQXJlRXF1YWwob3JpZ2luYWxMaW5lLCBsaW5lKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgY29udGV4dEluZGV4KytcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwYXJ0LnR5cGUgPT09IFwiZGVsZXRpb25cIikge1xyXG4gICAgICAgICAgcmVzdWx0LnB1c2goe1xyXG4gICAgICAgICAgICB0eXBlOiBcInNwbGljZVwiLFxyXG4gICAgICAgICAgICBpbmRleDogY29udGV4dEluZGV4IC0gcGFydC5saW5lcy5sZW5ndGgsXHJcbiAgICAgICAgICAgIG51bVRvRGVsZXRlOiBwYXJ0LmxpbmVzLmxlbmd0aCxcclxuICAgICAgICAgICAgbGluZXNUb0luc2VydDogW10sXHJcbiAgICAgICAgICB9KVxyXG5cclxuICAgICAgICAgIGlmIChwYXJ0Lm5vTmV3bGluZUF0RW5kT2ZGaWxlKSB7XHJcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHtcclxuICAgICAgICAgICAgICB0eXBlOiBcInB1c2hcIixcclxuICAgICAgICAgICAgICBsaW5lOiBcIlwiLFxyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBicmVha1xyXG4gICAgICBjYXNlIFwiaW5zZXJ0aW9uXCI6XHJcbiAgICAgICAgcmVzdWx0LnB1c2goe1xyXG4gICAgICAgICAgdHlwZTogXCJzcGxpY2VcIixcclxuICAgICAgICAgIGluZGV4OiBjb250ZXh0SW5kZXgsXHJcbiAgICAgICAgICBudW1Ub0RlbGV0ZTogMCxcclxuICAgICAgICAgIGxpbmVzVG9JbnNlcnQ6IHBhcnQubGluZXMsXHJcbiAgICAgICAgfSlcclxuICAgICAgICBpZiAocGFydC5ub05ld2xpbmVBdEVuZE9mRmlsZSkge1xyXG4gICAgICAgICAgcmVzdWx0LnB1c2goeyB0eXBlOiBcInBvcFwiIH0pXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgYXNzZXJ0TmV2ZXIocGFydC50eXBlKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcbiJdfQ==