1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = exports.fSError = exports.pkgFileName = exports.resourceNotAvailable = exports.noSuchFile = exports.fileExist = void 0;
|
7 |
|
8 | var _fs = _interopRequireDefault(require("fs"));
|
9 |
|
10 | var _path = _interopRequireDefault(require("path"));
|
11 |
|
12 | var _lodash = _interopRequireDefault(require("lodash"));
|
13 |
|
14 | var _mkdirp = _interopRequireDefault(require("mkdirp"));
|
15 |
|
16 | var _streams = require("@verdaccio/streams");
|
17 |
|
18 | var _fileLocking = require("@verdaccio/file-locking");
|
19 |
|
20 | var _lib = require("@verdaccio/commons-api/lib");
|
21 |
|
22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
23 |
|
24 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
25 |
|
26 | const fileExist = 'EEXISTS';
|
27 | exports.fileExist = fileExist;
|
28 | const noSuchFile = 'ENOENT';
|
29 | exports.noSuchFile = noSuchFile;
|
30 | const resourceNotAvailable = 'EAGAIN';
|
31 | exports.resourceNotAvailable = resourceNotAvailable;
|
32 | const pkgFileName = 'package.json';
|
33 | exports.pkgFileName = pkgFileName;
|
34 |
|
35 | const fSError = function (message, code = 409) {
|
36 | const err = (0, _lib.getCode)(code, message); // FIXME: we should return http-status codes here instead, future improvement
|
37 | // @ts-ignore
|
38 |
|
39 | err.code = message;
|
40 | return err;
|
41 | };
|
42 |
|
43 | exports.fSError = fSError;
|
44 |
|
45 | const tempFile = function (str) {
|
46 | return `${str}.tmp${String(Math.random()).substr(2)}`;
|
47 | };
|
48 |
|
49 | const renameTmp = function (src, dst, _cb) {
|
50 | const cb = err => {
|
51 | if (err) {
|
52 | _fs.default.unlink(src, () => {});
|
53 | }
|
54 |
|
55 | _cb(err);
|
56 | };
|
57 |
|
58 | if (process.platform !== 'win32') {
|
59 | return _fs.default.rename(src, dst, cb);
|
60 | } // windows can't remove opened file,
|
61 | // but it seem to be able to rename it
|
62 |
|
63 |
|
64 | const tmp = tempFile(dst);
|
65 |
|
66 | _fs.default.rename(dst, tmp, function (err) {
|
67 | _fs.default.rename(src, dst, cb);
|
68 |
|
69 | if (!err) {
|
70 | _fs.default.unlink(tmp, () => {});
|
71 | }
|
72 | });
|
73 | };
|
74 |
|
75 | class LocalFS {
|
76 | constructor(path, logger) {
|
77 | _defineProperty(this, "path", void 0);
|
78 |
|
79 | _defineProperty(this, "logger", void 0);
|
80 |
|
81 | this.path = path;
|
82 | this.logger = logger;
|
83 | }
|
84 | /**
|
85 | * This function allows to update the package thread-safely
|
86 | Algorithm:
|
87 | 1. lock package.json for writing
|
88 | 2. read package.json
|
89 | 3. updateFn(pkg, cb), and wait for cb
|
90 | 4. write package.json.tmp
|
91 | 5. move package.json.tmp package.json
|
92 | 6. callback(err?)
|
93 | * @param {*} name
|
94 | * @param {*} updateHandler
|
95 | * @param {*} onWrite
|
96 | * @param {*} transformPackage
|
97 | * @param {*} onEnd
|
98 | */
|
99 |
|
100 |
|
101 | updatePackage(name, updateHandler, onWrite, transformPackage, onEnd) {
|
102 | this._lockAndReadJSON(pkgFileName, (err, json) => {
|
103 | let locked = false;
|
104 | const self = this; // callback that cleans up lock first
|
105 |
|
106 | const unLockCallback = function (lockError) {
|
107 | // eslint-disable-next-line prefer-rest-params
|
108 | const _args = arguments;
|
109 |
|
110 | if (locked) {
|
111 | self._unlockJSON(pkgFileName, () => {
|
112 | // ignore any error from the unlock
|
113 | if (lockError !== null) {
|
114 | self.logger.trace({
|
115 | name,
|
116 | lockError
|
117 | }, '[local-storage/updatePackage/unLockCallback] file: @{name} lock has failed lockError: @{lockError}');
|
118 | }
|
119 |
|
120 | onEnd.apply(lockError, _args);
|
121 | });
|
122 | } else {
|
123 | self.logger.trace({
|
124 | name
|
125 | }, '[local-storage/updatePackage/unLockCallback] file: @{name} has been updated');
|
126 | onEnd(..._args);
|
127 | }
|
128 | };
|
129 |
|
130 | if (!err) {
|
131 | locked = true;
|
132 | this.logger.trace({
|
133 | name
|
134 | }, '[local-storage/updatePackage] file: @{name} has been locked');
|
135 | }
|
136 |
|
137 | if (_lodash.default.isNil(err) === false) {
|
138 | if (err.code === resourceNotAvailable) {
|
139 | return unLockCallback((0, _lib.getInternalError)('resource temporarily unavailable'));
|
140 | } else if (err.code === noSuchFile) {
|
141 | return unLockCallback((0, _lib.getNotFound)());
|
142 | } else {
|
143 | return unLockCallback(err);
|
144 | }
|
145 | }
|
146 |
|
147 | updateHandler(json, err => {
|
148 | if (err) {
|
149 | return unLockCallback(err);
|
150 | }
|
151 |
|
152 | onWrite(name, transformPackage(json), unLockCallback);
|
153 | });
|
154 | });
|
155 | }
|
156 |
|
157 | deletePackage(packageName, callback) {
|
158 | this.logger.debug({
|
159 | packageName
|
160 | }, '[local-storage/deletePackage] delete a package @{packageName}');
|
161 | return _fs.default.unlink(this._getStorage(packageName), callback);
|
162 | }
|
163 |
|
164 | removePackage(callback) {
|
165 | this.logger.debug({
|
166 | packageName: this.path
|
167 | }, '[local-storage/removePackage] remove a package: @{packageName}');
|
168 |
|
169 | _fs.default.rmdir(this._getStorage('.'), callback);
|
170 | }
|
171 |
|
172 | createPackage(name, value, cb) {
|
173 | this.logger.debug({
|
174 | packageName: name
|
175 | }, '[local-storage/createPackage] create a package: @{packageName}');
|
176 |
|
177 | this._createFile(this._getStorage(pkgFileName), this._convertToString(value), cb);
|
178 | }
|
179 |
|
180 | savePackage(name, value, cb) {
|
181 | this.logger.debug({
|
182 | packageName: name
|
183 | }, '[local-storage/savePackage] save a package: @{packageName}');
|
184 |
|
185 | this._writeFile(this._getStorage(pkgFileName), this._convertToString(value), cb);
|
186 | }
|
187 |
|
188 | readPackage(name, cb) {
|
189 | this.logger.debug({
|
190 | packageName: name
|
191 | }, '[local-storage/readPackage] read a package: @{packageName}');
|
192 |
|
193 | this._readStorageFile(this._getStorage(pkgFileName)).then(res => {
|
194 | try {
|
195 | const data = JSON.parse(res.toString('utf8'));
|
196 | this.logger.trace({
|
197 | packageName: name
|
198 | }, '[local-storage/readPackage/_readStorageFile] read a package succeed: @{packageName}');
|
199 | cb(null, data);
|
200 | } catch (err) {
|
201 | this.logger.trace({
|
202 | err
|
203 | }, '[local-storage/readPackage/_readStorageFile] error on read a package: @{err}');
|
204 | cb(err);
|
205 | }
|
206 | }, err => {
|
207 | this.logger.trace({
|
208 | err
|
209 | }, '[local-storage/readPackage/_readStorageFile] error on read a package: @{err}');
|
210 | return cb(err);
|
211 | });
|
212 | }
|
213 |
|
214 | writeTarball(name) {
|
215 | const uploadStream = new _streams.UploadTarball({});
|
216 | this.logger.debug({
|
217 | packageName: name
|
218 | }, '[local-storage/writeTarball] write a tarball for package: @{packageName}');
|
219 | let _ended = 0;
|
220 | uploadStream.on('end', function () {
|
221 | _ended = 1;
|
222 | });
|
223 |
|
224 | const pathName = this._getStorage(name);
|
225 |
|
226 | _fs.default.access(pathName, fileNotFound => {
|
227 | const exists = !fileNotFound;
|
228 |
|
229 | if (exists) {
|
230 | uploadStream.emit('error', fSError(fileExist));
|
231 | } else {
|
232 | const temporalName = _path.default.join(this.path, `${name}.tmp-${String(Math.random()).replace(/^0\./, '')}`);
|
233 |
|
234 | const file = _fs.default.createWriteStream(temporalName);
|
235 |
|
236 | const removeTempFile = () => _fs.default.unlink(temporalName, () => {});
|
237 |
|
238 | let opened = false;
|
239 | uploadStream.pipe(file);
|
240 |
|
241 | uploadStream.done = function () {
|
242 | const onend = function () {
|
243 | file.on('close', function () {
|
244 | renameTmp(temporalName, pathName, function (err) {
|
245 | if (err) {
|
246 | uploadStream.emit('error', err);
|
247 | } else {
|
248 | uploadStream.emit('success');
|
249 | }
|
250 | });
|
251 | });
|
252 | file.end();
|
253 | };
|
254 |
|
255 | if (_ended) {
|
256 | onend();
|
257 | } else {
|
258 | uploadStream.on('end', onend);
|
259 | }
|
260 | };
|
261 |
|
262 | uploadStream.abort = function () {
|
263 | if (opened) {
|
264 | opened = false;
|
265 | file.on('close', function () {
|
266 | removeTempFile();
|
267 | });
|
268 | } else {
|
269 | // if the file does not recieve any byte never is opened and has to be removed anyway.
|
270 | removeTempFile();
|
271 | }
|
272 |
|
273 | file.end();
|
274 | };
|
275 |
|
276 | file.on('open', function () {
|
277 | opened = true; // re-emitting open because it's handled in storage.js
|
278 |
|
279 | uploadStream.emit('open');
|
280 | });
|
281 | file.on('error', function (err) {
|
282 | uploadStream.emit('error', err);
|
283 | });
|
284 | }
|
285 | });
|
286 |
|
287 | return uploadStream;
|
288 | }
|
289 |
|
290 | readTarball(name) {
|
291 | const pathName = this._getStorage(name);
|
292 |
|
293 | this.logger.debug({
|
294 | packageName: name
|
295 | }, '[local-storage/readTarball] read a tarball for package: @{packageName}');
|
296 | const readTarballStream = new _streams.ReadTarball({});
|
297 |
|
298 | const readStream = _fs.default.createReadStream(pathName);
|
299 |
|
300 | readStream.on('error', function (err) {
|
301 | readTarballStream.emit('error', err);
|
302 | });
|
303 | readStream.on('open', function (fd) {
|
304 | _fs.default.fstat(fd, function (err, stats) {
|
305 | if (_lodash.default.isNil(err) === false) {
|
306 | return readTarballStream.emit('error', err);
|
307 | }
|
308 |
|
309 | readTarballStream.emit('content-length', stats.size);
|
310 | readTarballStream.emit('open');
|
311 | readStream.pipe(readTarballStream);
|
312 | });
|
313 | });
|
314 |
|
315 | readTarballStream.abort = function () {
|
316 | readStream.close();
|
317 | };
|
318 |
|
319 | return readTarballStream;
|
320 | }
|
321 |
|
322 | _createFile(name, contents, callback) {
|
323 | this.logger.trace({
|
324 | name
|
325 | }, '[local-storage/_createFile] create a new file: @{name}');
|
326 |
|
327 | _fs.default.open(name, 'wx', err => {
|
328 | if (err) {
|
329 | // native EEXIST used here to check exception on fs.open
|
330 | if (err.code === 'EEXIST') {
|
331 | this.logger.trace({
|
332 | name
|
333 | }, '[local-storage/_createFile] file cannot be created, it already exists: @{name}');
|
334 | return callback(fSError(fileExist));
|
335 | }
|
336 | }
|
337 |
|
338 | this._writeFile(name, contents, callback);
|
339 | });
|
340 | }
|
341 |
|
342 | _readStorageFile(name) {
|
343 | return new Promise((resolve, reject) => {
|
344 | this.logger.trace({
|
345 | name
|
346 | }, '[local-storage/_readStorageFile] read a file: @{name}');
|
347 |
|
348 | _fs.default.readFile(name, (err, data) => {
|
349 | if (err) {
|
350 | this.logger.trace({
|
351 | err
|
352 | }, '[local-storage/_readStorageFile] error on read the file: @{name}');
|
353 | reject(err);
|
354 | } else {
|
355 | this.logger.trace({
|
356 | name
|
357 | }, '[local-storage/_readStorageFile] read file succeed: @{name}');
|
358 | resolve(data);
|
359 | }
|
360 | });
|
361 | });
|
362 | }
|
363 |
|
364 | _convertToString(value) {
|
365 | return JSON.stringify(value, null, '\t');
|
366 | }
|
367 |
|
368 | _getStorage(fileName = '') {
|
369 | const storagePath = _path.default.join(this.path, fileName);
|
370 |
|
371 | return storagePath;
|
372 | }
|
373 |
|
374 | _writeFile(dest, data, cb) {
|
375 | const createTempFile = cb => {
|
376 | const tempFilePath = tempFile(dest);
|
377 |
|
378 | _fs.default.writeFile(tempFilePath, data, err => {
|
379 | if (err) {
|
380 | this.logger.trace({
|
381 | name: dest
|
382 | }, '[local-storage/_writeFile] new file: @{name} has been created');
|
383 | return cb(err);
|
384 | }
|
385 |
|
386 | this.logger.trace({
|
387 | name: dest
|
388 | }, '[local-storage/_writeFile] creating a new file: @{name}');
|
389 | renameTmp(tempFilePath, dest, cb);
|
390 | });
|
391 | };
|
392 |
|
393 | createTempFile(err => {
|
394 | if (err && err.code === noSuchFile) {
|
395 | (0, _mkdirp.default)(_path.default.dirname(dest), function (err) {
|
396 | if (err) {
|
397 | return cb(err);
|
398 | }
|
399 |
|
400 | createTempFile(cb);
|
401 | });
|
402 | } else {
|
403 | cb(err);
|
404 | }
|
405 | });
|
406 | }
|
407 |
|
408 | _lockAndReadJSON(name, cb) {
|
409 | const fileName = this._getStorage(name);
|
410 |
|
411 | (0, _fileLocking.readFile)(fileName, {
|
412 | lock: true,
|
413 | parse: true
|
414 | }, (err, res) => {
|
415 | if (err) {
|
416 | this.logger.trace({
|
417 | name
|
418 | }, '[local-storage/_lockAndReadJSON] read new file: @{name} has failed');
|
419 | return cb(err);
|
420 | }
|
421 |
|
422 | this.logger.trace({
|
423 | name
|
424 | }, '[local-storage/_lockAndReadJSON] file: @{name} read');
|
425 | return cb(null, res);
|
426 | });
|
427 | }
|
428 |
|
429 | _unlockJSON(name, cb) {
|
430 | (0, _fileLocking.unlockFile)(this._getStorage(name), cb);
|
431 | }
|
432 |
|
433 | }
|
434 |
|
435 | exports.default = LocalFS;
|
436 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9sb2NhbC1mcy50cyJdLCJuYW1lcyI6WyJmaWxlRXhpc3QiLCJub1N1Y2hGaWxlIiwicmVzb3VyY2VOb3RBdmFpbGFibGUiLCJwa2dGaWxlTmFtZSIsImZTRXJyb3IiLCJtZXNzYWdlIiwiY29kZSIsImVyciIsInRlbXBGaWxlIiwic3RyIiwiU3RyaW5nIiwiTWF0aCIsInJhbmRvbSIsInN1YnN0ciIsInJlbmFtZVRtcCIsInNyYyIsImRzdCIsIl9jYiIsImNiIiwiZnMiLCJ1bmxpbmsiLCJwcm9jZXNzIiwicGxhdGZvcm0iLCJyZW5hbWUiLCJ0bXAiLCJMb2NhbEZTIiwiY29uc3RydWN0b3IiLCJwYXRoIiwibG9nZ2VyIiwidXBkYXRlUGFja2FnZSIsIm5hbWUiLCJ1cGRhdGVIYW5kbGVyIiwib25Xcml0ZSIsInRyYW5zZm9ybVBhY2thZ2UiLCJvbkVuZCIsIl9sb2NrQW5kUmVhZEpTT04iLCJqc29uIiwibG9ja2VkIiwic2VsZiIsInVuTG9ja0NhbGxiYWNrIiwibG9ja0Vycm9yIiwiX2FyZ3MiLCJhcmd1bWVudHMiLCJfdW5sb2NrSlNPTiIsInRyYWNlIiwiYXBwbHkiLCJfIiwiaXNOaWwiLCJkZWxldGVQYWNrYWdlIiwicGFja2FnZU5hbWUiLCJjYWxsYmFjayIsImRlYnVnIiwiX2dldFN0b3JhZ2UiLCJyZW1vdmVQYWNrYWdlIiwicm1kaXIiLCJjcmVhdGVQYWNrYWdlIiwidmFsdWUiLCJfY3JlYXRlRmlsZSIsIl9jb252ZXJ0VG9TdHJpbmciLCJzYXZlUGFja2FnZSIsIl93cml0ZUZpbGUiLCJyZWFkUGFja2FnZSIsIl9yZWFkU3RvcmFnZUZpbGUiLCJ0aGVuIiwicmVzIiwiZGF0YSIsIkpTT04iLCJwYXJzZSIsInRvU3RyaW5nIiwid3JpdGVUYXJiYWxsIiwidXBsb2FkU3RyZWFtIiwiVXBsb2FkVGFyYmFsbCIsIl9lbmRlZCIsIm9uIiwicGF0aE5hbWUiLCJhY2Nlc3MiLCJmaWxlTm90Rm91bmQiLCJleGlzdHMiLCJlbWl0IiwidGVtcG9yYWxOYW1lIiwiam9pbiIsInJlcGxhY2UiLCJmaWxlIiwiY3JlYXRlV3JpdGVTdHJlYW0iLCJyZW1vdmVUZW1wRmlsZSIsIm9wZW5lZCIsInBpcGUiLCJkb25lIiwib25lbmQiLCJlbmQiLCJhYm9ydCIsInJlYWRUYXJiYWxsIiwicmVhZFRhcmJhbGxTdHJlYW0iLCJSZWFkVGFyYmFsbCIsInJlYWRTdHJlYW0iLCJjcmVhdGVSZWFkU3RyZWFtIiwiZmQiLCJmc3RhdCIsInN0YXRzIiwic2l6ZSIsImNsb3NlIiwiY29udGVudHMiLCJvcGVuIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJyZWFkRmlsZSIsInN0cmluZ2lmeSIsImZpbGVOYW1lIiwic3RvcmFnZVBhdGgiLCJkZXN0IiwiY3JlYXRlVGVtcEZpbGUiLCJ0ZW1wRmlsZVBhdGgiLCJ3cml0ZUZpbGUiLCJkaXJuYW1lIiwibG9jayJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOzs7Ozs7QUFFTyxNQUFNQSxTQUFTLEdBQUcsU0FBbEI7O0FBQ0EsTUFBTUMsVUFBVSxHQUFHLFFBQW5COztBQUNBLE1BQU1DLG9CQUFvQixHQUFHLFFBQTdCOztBQUNBLE1BQU1DLFdBQVcsR0FBRyxjQUFwQjs7O0FBRUEsTUFBTUMsT0FBTyxHQUFHLFVBQVNDLE9BQVQsRUFBMEJDLElBQUksR0FBRyxHQUFqQyxFQUFzRDtBQUMzRSxRQUFNQyxHQUFtQixHQUFHLGtCQUFRRCxJQUFSLEVBQWNELE9BQWQsQ0FBNUIsQ0FEMkUsQ0FFM0U7QUFDQTs7QUFDQUUsRUFBQUEsR0FBRyxDQUFDRCxJQUFKLEdBQVdELE9BQVg7QUFFQSxTQUFPRSxHQUFQO0FBQ0QsQ0FQTTs7OztBQVNQLE1BQU1DLFFBQVEsR0FBRyxVQUFTQyxHQUFULEVBQXNCO0FBQ3JDLFNBQVEsR0FBRUEsR0FBSSxPQUFNQyxNQUFNLENBQUNDLElBQUksQ0FBQ0MsTUFBTCxFQUFELENBQU4sQ0FBc0JDLE1BQXRCLENBQTZCLENB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LEVBRUU7QUFDRU8sTUFBQUEsSUFBSSxFQUFFLElBRFI7QUFFRWhELE1BQUFBLEtBQUssRUFBRTtBQUZULEtBRkYsRUFNRSxDQUFDNUQsR0FBRCxFQUFNeUQsR0FBTixLQUFjO0FBQ1osVUFBSXpELEdBQUosRUFBUztBQUNQLGFBQUtxQixNQUFMLENBQVlnQixLQUFaLENBQWtCO0FBQUVkLFVBQUFBO0FBQUYsU0FBbEIsRUFBNEIsb0VBQTVCO0FBRUEsZUFBT1osRUFBRSxDQUFDWCxHQUFELENBQVQ7QUFDRDs7QUFFRCxXQUFLcUIsTUFBTCxDQUFZZ0IsS0FBWixDQUFrQjtBQUFFZCxRQUFBQTtBQUFGLE9BQWxCLEVBQTRCLHFEQUE1QjtBQUNBLGFBQU9aLEVBQUUsQ0FBQyxJQUFELEVBQU84QyxHQUFQLENBQVQ7QUFDRCxLQWZIO0FBaUJEOztBQUVPckIsRUFBQUEsV0FBUixDQUFvQmIsSUFBcEIsRUFBa0NaLEVBQWxDLEVBQXNEO0FBQ3BELGlDQUFXLEtBQUtrQyxXQUFMLENBQWlCdEIsSUFBakIsQ0FBWCxFQUFtQ1osRUFBbkM7QUFDRDs7QUFyVjREIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IG1rZGlycCBmcm9tICdta2RpcnAnO1xuaW1wb3J0IHsgVXBsb2FkVGFyYmFsbCwgUmVhZFRhcmJhbGwgfSBmcm9tICdAdmVyZGFjY2lvL3N0cmVhbXMnO1xuaW1wb3J0IHsgdW5sb2NrRmlsZSwgcmVhZEZpbGUgfSBmcm9tICdAdmVyZGFjY2lvL2ZpbGUtbG9ja2luZyc7XG5pbXBvcnQgeyBDYWxsYmFjaywgTG9nZ2VyLCBQYWNrYWdlLCBJTG9jYWxQYWNrYWdlTWFuYWdlciwgSVVwbG9hZFRhcmJhbGwgfSBmcm9tICdAdmVyZGFjY2lvL3R5cGVzJztcbmltcG9ydCB7IGdldENvZGUsIGdldEludGVybmFsRXJyb3IsIGdldE5vdEZvdW5kLCBWZXJkYWNjaW9FcnJvciB9IGZyb20gJ0B2ZXJkYWNjaW8vY29tbW9ucy1hcGkvbGliJztcblxuZXhwb3J0IGNvbnN0IGZpbGVFeGlzdCA9ICdFRVhJU1RTJztcbmV4cG9ydCBjb25zdCBub1N1Y2hGaWxlID0gJ0VOT0VOVCc7XG5leHBvcnQgY29uc3QgcmVzb3VyY2VOb3RBdmFpbGFibGUgPSAnRUFHQUlOJztcbmV4cG9ydCBjb25zdCBwa2dGaWxlTmFtZSA9ICdwYWNrYWdlLmpzb24nO1xuXG5leHBvcnQgY29uc3QgZlNFcnJvciA9IGZ1bmN0aW9uKG1lc3NhZ2U6IHN0cmluZywgY29kZSA9IDQwOSk6IFZlcmRhY2Npb0Vycm9yIHtcbiAgY29uc3QgZXJyOiBWZXJkYWNjaW9FcnJvciA9IGdldENvZGUoY29kZSwgbWVzc2FnZSk7XG4gIC8vIEZJWE1FOiB3ZSBzaG91bGQgcmV0dXJuIGh0dHAtc3RhdHVzIGNvZGVzIGhlcmUgaW5zdGVhZCwgZnV0dXJlIGltcHJvdmVtZW50XG4gIC8vIEB0cy1pZ25vcmVcbiAgZXJyLmNvZGUgPSBtZXNzYWdlO1xuXG4gIHJldHVybiBlcnI7XG59O1xuXG5jb25zdCB0ZW1wRmlsZSA9IGZ1bmN0aW9uKHN0cik6IHN0cmluZyB7XG4gIHJldHVybiBgJHtzdHJ9LnRtcCR7U3RyaW5nKE1hdGgucmFuZG9tKCkpLnN1YnN0cigyKX1gO1xufTtcblxuY29uc3QgcmVuYW1lVG1wID0gZnVuY3Rpb24oc3JjLCBkc3QsIF9jYik6IHZvaWQge1xuICBjb25zdCBjYiA9IChlcnIpOiB2b2lkID0+IHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICBmcy51bmxpbmsoc3JjLCAoKSA9PiB7fSk7XG4gICAgfVxuICAgIF9jYihlcnIpO1xuICB9O1xuXG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtICE9PSAnd2luMzInKSB7XG4gICAgcmV0dXJuIGZzLnJlbmFtZShzcmMsIGRzdCwgY2IpO1xuICB9XG5cbiAgLy8gd2luZG93cyBjYW4ndCByZW1vdmUgb3BlbmVkIGZpbGUsXG4gIC8vIGJ1dCBpdCBzZWVtIHRvIGJlIGFibGUgdG8gcmVuYW1lIGl0XG4gIGNvbnN0IHRtcCA9IHRlbXBGaWxlKGRzdCk7XG4gIGZzLnJlbmFtZShkc3QsIHRtcCwgZnVuY3Rpb24oZXJyKSB7XG4gICAgZnMucmVuYW1lKHNyYywgZHN0LCBjYik7XG4gICAgaWYgKCFlcnIpIHtcbiAgICAgIGZzLnVubGluayh0bXAsICgpID0+IHt9KTtcbiAgICB9XG4gIH0pO1xufTtcblxuZXhwb3J0IHR5cGUgSUxvY2FsRlNQYWNrYWdlTWFuYWdlciA9IElMb2NhbFBhY2thZ2VNYW5hZ2VyICYgeyBwYXRoOiBzdHJpbmcgfTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTG9jYWxGUyBpbXBsZW1lbnRzIElMb2NhbEZTUGFja2FnZU1hbmFnZXIge1xuICBwdWJsaWMgcGF0aDogc3RyaW5nO1xuICBwdWJsaWMgbG9nZ2VyOiBMb2dnZXI7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHBhdGg6IHN0cmluZywgbG9nZ2VyOiBMb2dnZXIpIHtcbiAgICB0aGlzLnBhdGggPSBwYXRoO1xuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICB9XG5cbiAgLyoqXG4gICAgKiAgVGhpcyBmdW5jdGlvbiBhbGxvd3MgdG8gdXBkYXRlIHRoZSBwYWNrYWdlIHRocmVhZC1zYWZlbHlcbiAgICAgIEFsZ29yaXRobTpcbiAgICAgIDEuIGxvY2sgcGFja2FnZS5qc29uIGZvciB3cml0aW5nXG4gICAgICAyLiByZWFkIHBhY2thZ2UuanNvblxuICAgICAgMy4gdXBkYXRlRm4ocGtnLCBjYiksIGFuZCB3YWl0IGZvciBjYlxuICAgICAgNC4gd3JpdGUgcGFja2FnZS5qc29uLnRtcFxuICAgICAgNS4gbW92ZSBwYWNrYWdlLmpzb24udG1wIHBhY2thZ2UuanNvblxuICAgICAgNi4gY2FsbGJhY2soZXJyPylcbiAgICAqIEBwYXJhbSB7Kn0gbmFtZVxuICAgICogQHBhcmFtIHsqfSB1cGRhdGVIYW5kbGVyXG4gICAgKiBAcGFyYW0geyp9IG9uV3JpdGVcbiAgICAqIEBwYXJhbSB7Kn0gdHJhbnNmb3JtUGFja2FnZVxuICAgICogQHBhcmFtIHsqfSBvbkVuZFxuICAgICovXG4gIHB1YmxpYyB1cGRhdGVQYWNrYWdlKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICB1cGRhdGVIYW5kbGVyOiBDYWxsYmFjayxcbiAgICBvbldyaXRlOiBDYWxsYmFjayxcbiAgICB0cmFuc2Zvcm1QYWNrYWdlOiBGdW5jdGlvbixcbiAgICBvbkVuZDogQ2FsbGJhY2tcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5fbG9ja0FuZFJlYWRKU09OKHBrZ0ZpbGVOYW1lLCAoZXJyLCBqc29uKSA9PiB7XG4gICAgICBsZXQgbG9ja2VkID0gZmFsc2U7XG4gICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgIC8vIGNhbGxiYWNrIHRoYXQgY2xlYW5zIHVwIGxvY2sgZmlyc3RcbiAgICAgIGNvbnN0IHVuTG9ja0NhbGxiYWNrID0gZnVuY3Rpb24obG9ja0Vycm9yOiBFcnJvcik6IHZvaWQge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLXJlc3QtcGFyYW1zXG4gICAgICAgIGNvbnN0IF9hcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgIGlmIChsb2NrZWQpIHtcbiAgICAgICAgICBzZWxmLl91bmxvY2tKU09OKHBrZ0ZpbGVOYW1lLCAoKSA9PiB7XG4gICAgICAgICAgICAvLyBpZ25vcmUgYW55IGVycm9yIGZyb20gdGhlIHVubG9ja1xuICAgICAgICAgICAgaWYgKGxvY2tFcnJvciAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICBzZWxmLmxvZ2dlci50cmFjZShcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgICAgbG9ja0Vycm9yLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ1tsb2NhbC1zdG9yYWdlL3VwZGF0ZVBhY2thZ2UvdW5Mb2NrQ2FsbGJhY2tdIGZpbGU6IEB7bmFtZX0gbG9jayBoYXMgZmFpbGVkIGxvY2tFcnJvcjogQHtsb2NrRXJyb3J9J1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBvbkVuZC5hcHBseShsb2NrRXJyb3IsIF9hcmdzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZWxmLmxvZ2dlci50cmFjZSh7IG5hbWUgfSwgJ1tsb2NhbC1zdG9yYWdlL3VwZGF0ZVBhY2thZ2UvdW5Mb2NrQ2FsbGJhY2tdIGZpbGU6IEB7bmFtZX0gaGFzIGJlZW4gdXBkYXRlZCcpO1xuXG4gICAgICAgICAgb25FbmQoLi4uX2FyZ3MpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoIWVycikge1xuICAgICAgICBsb2NrZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmxvZ2dlci50cmFjZShcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgJ1tsb2NhbC1zdG9yYWdlL3VwZGF0ZVBhY2thZ2VdIGZpbGU6IEB7bmFtZX0gaGFzIGJlZW4gbG9ja2VkJ1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAoXy5pc05pbChlcnIpID09PSBmYWxzZSkge1xuICAgICAgICBpZiAoZXJyLmNvZGUgPT09IHJlc291cmNlTm90QXZhaWxhYmxlKSB7XG4gICAgICAgICAgcmV0dXJuIHVuTG9ja0NhbGxiYWNrKGdldEludGVybmFsRXJyb3IoJ3Jlc291cmNlIHRlbXBvcmFyaWx5IHVuYXZhaWxhYmxlJykpO1xuICAgICAgICB9IGVsc2UgaWYgKGVyci5jb2RlID09PSBub1N1Y2hGaWxlKSB7XG4gICAgICAgICAgcmV0dXJuIHVuTG9ja0NhbGxiYWNrKGdldE5vdEZvdW5kKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB1bkxvY2tDYWxsYmFjayhlcnIpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHVwZGF0ZUhhbmRsZXIoanNvbiwgZXJyID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJldHVybiB1bkxvY2tDYWxsYmFjayhlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgb25Xcml0ZShuYW1lLCB0cmFuc2Zvcm1QYWNrYWdlKGpzb24pLCB1bkxvY2tDYWxsYmFjayk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBkZWxldGVQYWNrYWdlKHBhY2thZ2VOYW1lOiBzdHJpbmcsIGNhbGxiYWNrOiAoZXJyOiBOb2RlSlMuRXJybm9FeGNlcHRpb24gfCBudWxsKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoeyBwYWNrYWdlTmFtZSB9LCAnW2xvY2FsLXN0b3JhZ2UvZGVsZXRlUGFja2FnZV0gZGVsZXRlIGEgcGFja2FnZSBAe3BhY2thZ2VOYW1lfScpO1xuXG4gICAgcmV0dXJuIGZzLnVubGluayh0aGlzLl9nZXRTdG9yYWdlKHBhY2thZ2VOYW1lKSwgY2FsbGJhY2spO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZVBhY2thZ2UoY2FsbGJhY2s6IChlcnI6IE5vZGVKUy5FcnJub0V4Y2VwdGlvbiB8IG51bGwpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1Zyh7IHBhY2thZ2VOYW1lOiB0aGlzLnBhdGggfSwgJ1tsb2NhbC1zdG9yYWdlL3JlbW92ZVBhY2thZ2VdIHJlbW92ZSBhIHBhY2thZ2U6IEB7cGFja2FnZU5hbWV9Jyk7XG5cbiAgICBmcy5ybWRpcih0aGlzLl9nZXRTdG9yYWdlKCcuJyksIGNhbGxiYWNrKTtcbiAgfVxuXG4gIHB1YmxpYyBjcmVhdGVQYWNrYWdlKG5hbWU6IHN0cmluZywgdmFsdWU6IFBhY2thZ2UsIGNiOiBDYWxsYmFjayk6IHZvaWQge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKHsgcGFja2FnZU5hbWU6IG5hbWUgfSwgJ1tsb2NhbC1zdG9yYWdlL2NyZWF0ZVBhY2thZ2VdIGNyZWF0ZSBhIHBhY2thZ2U6IEB7cGFja2FnZU5hbWV9Jyk7XG5cbiAgICB0aGlzLl9jcmVhdGVGaWxlKHRoaXMuX2dldFN0b3JhZ2UocGtnRmlsZU5hbWUpLCB0aGlzLl9jb252ZXJ0VG9TdHJpbmcodmFsdWUpLCBjYik7XG4gIH1cblxuICBwdWJsaWMgc2F2ZVBhY2thZ2UobmFtZTogc3RyaW5nLCB2YWx1ZTogUGFja2FnZSwgY2I6IENhbGxiYWNrKTogdm9pZCB7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoeyBwYWNrYWdlTmFtZTogbmFtZSB9LCAnW2xvY2FsLXN0b3JhZ2Uvc2F2ZVBhY2thZ2VdIHNhdmUgYSBwYWNrYWdlOiBAe3BhY2thZ2VOYW1lfScpO1xuXG4gICAgdGhpcy5fd3JpdGVGaWxlKHRoaXMuX2dldFN0b3JhZ2UocGtnRmlsZU5hbWUpLCB0aGlzLl9jb252ZXJ0VG9TdHJpbmcodmFsdWUpLCBjYik7XG4gIH1cblxuICBwdWJsaWMgcmVhZFBhY2thZ2UobmFtZTogc3RyaW5nLCBjYjogQ2FsbGJhY2spOiB2b2lkIHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1Zyh7IHBhY2thZ2VOYW1lOiBuYW1lIH0sICdbbG9jYWwtc3RvcmFnZS9yZWFkUGFja2FnZV0gcmVhZCBhIHBhY2thZ2U6IEB7cGFja2FnZU5hbWV9Jyk7XG5cbiAgICB0aGlzLl9yZWFkU3RvcmFnZUZpbGUodGhpcy5fZ2V0U3RvcmFnZShwa2dGaWxlTmFtZSkpLnRoZW4oXG4gICAgICByZXMgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGRhdGE6IGFueSA9IEpTT04ucGFyc2UocmVzLnRvU3RyaW5nKCd1dGY4JykpO1xuXG4gICAgICAgICAgdGhpcy5sb2dnZXIudHJhY2UoXG4gICAgICAgICAgICB7IHBhY2thZ2VOYW1lOiBuYW1lIH0sXG4gICAgICAgICAgICAnW2xvY2FsLXN0b3JhZ2UvcmVhZFBhY2thZ2UvX3JlYWRTdG9yYWdlRmlsZV0gcmVhZCBhIHBhY2thZ2Ugc3VjY2VlZDogQHtwYWNrYWdlTmFtZX0nXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjYihudWxsLCBkYXRhKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIudHJhY2UoeyBlcnIgfSwgJ1tsb2NhbC1zdG9yYWdlL3JlYWRQYWNrYWdlL19yZWFkU3RvcmFnZUZpbGVdIGVycm9yIG9uIHJlYWQgYSBwYWNrYWdlOiBAe2Vycn0nKTtcbiAgICAgICAgICBjYihlcnIpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZXJyID0+IHtcbiAgICAgICAgdGhpcy5sb2dnZXIudHJhY2UoeyBlcnIgfSwgJ1tsb2NhbC1zdG9yYWdlL3JlYWRQYWNrYWdlL19yZWFkU3RvcmFnZUZpbGVdIGVycm9yIG9uIHJlYWQgYSBwYWNrYWdlOiBAe2Vycn0nKTtcblxuICAgICAgICByZXR1cm4gY2IoZXJyKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcHVibGljIHdyaXRlVGFyYmFsbChuYW1lOiBzdHJpbmcpOiBJVXBsb2FkVGFyYmFsbCB7XG4gICAgY29uc3QgdXBsb2FkU3RyZWFtID0gbmV3IFVwbG9hZFRhcmJhbGwoe30pO1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgeyBwYWNrYWdlTmFtZTogbmFtZSB9LFxuICAgICAgJ1tsb2NhbC1zdG9yYWdlL3dyaXRlVGFyYmFsbF0gd3JpdGUgYSB0YXJiYWxsIGZvciBwYWNrYWdlOiBAe3BhY2thZ2VOYW1lfSdcbiAgICApO1xuXG4gICAgbGV0IF9lbmRlZCA9IDA7XG4gICAgdXBsb2FkU3RyZWFtLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgIF9lbmRlZCA9IDE7XG4gICAgfSk7XG5cbiAgICBjb25zdCBwYXRoTmFtZTogc3RyaW5nID0gdGhpcy5fZ2V0U3RvcmFnZShuYW1lKTtcblxuICAgIGZzLmFjY2VzcyhwYXRoTmFtZSwgZmlsZU5vdEZvdW5kID0+IHtcbiAgICAgIGNvbnN0IGV4aXN0cyA9ICFmaWxlTm90Rm91bmQ7XG4gICAgICBpZiAoZXhpc3RzKSB7XG4gICAgICAgIHVwbG9hZFN0cmVhbS5lbWl0KCdlcnJvcicsIGZTRXJyb3IoZmlsZUV4aXN0KSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB0ZW1wb3JhbE5hbWUgPSBwYXRoLmpvaW4odGhpcy5wYXRoLCBgJHtuYW1lfS50bXAtJHtTdHJpbmcoTWF0aC5yYW5kb20oKSkucmVwbGFjZSgvXjBcXC4vLCAnJyl9YCk7XG4gICAgICAgIGNvbnN0IGZpbGUgPSBmcy5jcmVhdGVXcml0ZVN0cmVhbSh0ZW1wb3JhbE5hbWUpO1xuICAgICAgICBjb25zdCByZW1vdmVUZW1wRmlsZSA9ICgpOiB2b2lkID0+IGZzLnVubGluayh0ZW1wb3JhbE5hbWUsICgpID0+IHt9KTtcbiAgICAgICAgbGV0IG9wZW5lZCA9IGZhbHNlO1xuICAgICAgICB1cGxvYWRTdHJlYW0ucGlwZShmaWxlKTtcblxuICAgICAgICB1cGxvYWRTdHJlYW0uZG9uZSA9IGZ1bmN0aW9uKCk6IHZvaWQge1xuICAgICAgICAgIGNvbnN0IG9uZW5kID0gZnVuY3Rpb24oKTogdm9pZCB7XG4gICAgICAgICAgICBmaWxlLm9uKCdjbG9zZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICByZW5hbWVUbXAodGVtcG9yYWxOYW1lLCBwYXRoTmFtZSwgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgdXBsb2FkU3RyZWFtLmVtaXQoJ2Vycm9yJywgZXJyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdXBsb2FkU3RyZWFtLmVtaXQoJ3N1Y2Nlc3MnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmaWxlLmVuZCgpO1xuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKF9lbmRlZCkge1xuICAgICAgICAgICAgb25lbmQoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXBsb2FkU3RyZWFtLm9uKCdlbmQnLCBvbmVuZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHVwbG9hZFN0cmVhbS5hYm9ydCA9IGZ1bmN0aW9uKCk6IHZvaWQge1xuICAgICAgICAgIGlmIChvcGVuZWQpIHtcbiAgICAgICAgICAgIG9wZW5lZCA9IGZhbHNlO1xuICAgICAgICAgICAgZmlsZS5vbignY2xvc2UnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgcmVtb3ZlVGVtcEZpbGUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBpZiB0aGUgZmlsZSBkb2VzIG5vdCByZWNpZXZlIGFueSBieXRlIG5ldmVyIGlzIG9wZW5lZCBhbmQgaGFzIHRvIGJlIHJlbW92ZWQgYW55d2F5LlxuICAgICAgICAgICAgcmVtb3ZlVGVtcEZpbGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZmlsZS5lbmQoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBmaWxlLm9uKCdvcGVuJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgb3BlbmVkID0gdHJ1ZTtcbiAgICAgICAgICAvLyByZS1lbWl0dGluZyBvcGVuIGJlY2F1c2UgaXQncyBoYW5kbGVkIGluIHN0b3JhZ2UuanNcbiAgICAgICAgICB1cGxvYWRTdHJlYW0uZW1pdCgnb3BlbicpO1xuICAgICAgICB9KTtcblxuICAgICAgICBmaWxlLm9uKCdlcnJvcicsIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgIHVwbG9hZFN0cmVhbS5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHVwbG9hZFN0cmVhbTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkVGFyYmFsbChuYW1lOiBzdHJpbmcpOiBSZWFkVGFyYmFsbCB7XG4gICAgY29uc3QgcGF0aE5hbWU6IHN0cmluZyA9IHRoaXMuX2dldFN0b3JhZ2UobmFtZSk7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoeyBwYWNrYWdlTmFtZTogbmFtZSB9LCAnW2xvY2FsLXN0b3JhZ2UvcmVhZFRhcmJhbGxdIHJlYWQgYSB0YXJiYWxsIGZvciBwYWNrYWdlOiBAe3BhY2thZ2VOYW1lfScpO1xuXG4gICAgY29uc3QgcmVhZFRhcmJhbGxTdHJlYW0gPSBuZXcgUmVhZFRhcmJhbGwoe30pO1xuXG4gICAgY29uc3QgcmVhZFN0cmVhbSA9IGZzLmNyZWF0ZVJlYWRTdHJlYW0ocGF0aE5hbWUpO1xuXG4gICAgcmVhZFN0cmVhbS5vbignZXJyb3InLCBmdW5jdGlvbihlcnIpIHtcbiAgICAgIHJlYWRUYXJiYWxsU3RyZWFtLmVtaXQoJ2Vycm9yJywgZXJyKTtcbiAgICB9KTtcblxuICAgIHJlYWRTdHJlYW0ub24oJ29wZW4nLCBmdW5jdGlvbihmZCkge1xuICAgICAgZnMuZnN0YXQoZmQsIGZ1bmN0aW9uKGVyciwgc3RhdHMpIHtcbiAgICAgICAgaWYgKF8uaXNOaWwoZXJyKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICByZXR1cm4gcmVhZFRhcmJhbGxTdHJlYW0uZW1pdCgnZXJyb3InLCBlcnIpO1xuICAgICAgICB9XG4gICAgICAgIHJlYWRUYXJiYWxsU3RyZWFtLmVtaXQoJ2NvbnRlbnQtbGVuZ3RoJywgc3RhdHMuc2l6ZSk7XG4gICAgICAgIHJlYWRUYXJiYWxsU3RyZWFtLmVtaXQoJ29wZW4nKTtcbiAgICAgICAgcmVhZFN0cmVhbS5waXBlKHJlYWRUYXJiYWxsU3RyZWFtKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgcmVhZFRhcmJhbGxTdHJlYW0uYWJvcnQgPSBmdW5jdGlvbigpOiB2b2lkIHtcbiAgICAgIHJlYWRTdHJlYW0uY2xvc2UoKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlYWRUYXJiYWxsU3RyZWFtO1xuICB9XG5cbiAgcHJpdmF0ZSBfY3JlYXRlRmlsZShuYW1lOiBzdHJpbmcsIGNvbnRlbnRzOiBhbnksIGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgIHRoaXMubG9nZ2VyLnRyYWNlKHsgbmFtZSB9LCAnW2xvY2FsLXN0b3JhZ2UvX2NyZWF0ZUZpbGVdIGNyZWF0ZSBhIG5ldyBmaWxlOiBAe25hbWV9Jyk7XG5cbiAgICBmcy5vcGVuKG5hbWUsICd3eCcsIGVyciA9PiB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIC8vIG5hdGl2ZSBFRVhJU1QgdXNlZCBoZXJlIHRvIGNoZWNrIGV4Y2VwdGlvbiBvbiBmcy5vcGVuXG4gICAgICAgIGlmIChlcnIuY29kZSA9PT0gJ0VFWElTVCcpIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci50cmFjZSh7IG5hbWUgfSwgJ1tsb2NhbC1zdG9yYWdlL19jcmVhdGVGaWxlXSBmaWxlIGNhbm5vdCBiZSBjcmVhdGVkLCBpdCBhbHJlYWR5IGV4aXN0czogQHtuYW1lfScpO1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhmU0Vycm9yKGZpbGVFeGlzdCkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3dyaXRlRmlsZShuYW1lLCBjb250ZW50cywgY2FsbGJhY2spO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVhZFN0b3JhZ2VGaWxlKG5hbWU6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIHRoaXMubG9nZ2VyLnRyYWNlKHsgbmFtZSB9LCAnW2xvY2FsLXN0b3JhZ2UvX3JlYWRTdG9yYWdlRmlsZV0gcmVhZCBhIGZpbGU6IEB7bmFtZX0nKTtcblxuICAgICAgZnMucmVhZEZpbGUobmFtZSwgKGVyciwgZGF0YSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIudHJhY2UoeyBlcnIgfSwgJ1tsb2NhbC1zdG9yYWdlL19yZWFkU3RvcmFnZUZpbGVdIGVycm9yIG9uIHJlYWQgdGhlIGZpbGU6IEB7bmFtZX0nKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci50cmFjZSh7IG5hbWUgfSwgJ1tsb2NhbC1zdG9yYWdlL19yZWFkU3RvcmFnZUZpbGVdIHJlYWQgZmlsZSBzdWNjZWVkOiBAe25hbWV9Jyk7XG5cbiAgICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbnZlcnRUb1N0cmluZyh2YWx1ZTogUGFja2FnZSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlLCBudWxsLCAnXFx0Jyk7XG4gIH1cblxuICBwcml2YXRlIF9nZXRTdG9yYWdlKGZpbGVOYW1lID0gJycpOiBzdHJpbmcge1xuICAgIGNvbnN0IHN0b3JhZ2VQYXRoOiBzdHJpbmcgPSBwYXRoLmpvaW4odGhpcy5wYXRoLCBmaWxlTmFtZSk7XG5cbiAgICByZXR1cm4gc3RvcmFnZVBhdGg7XG4gIH1cblxuICBwcml2YXRlIF93cml0ZUZpbGUoZGVzdDogc3RyaW5nLCBkYXRhOiBzdHJpbmcsIGNiOiBDYWxsYmFjayk6IHZvaWQge1xuICAgIGNvbnN0IGNyZWF0ZVRlbXBGaWxlID0gKGNiKTogdm9pZCA9PiB7XG4gICAgICBjb25zdCB0ZW1wRmlsZVBhdGggPSB0ZW1wRmlsZShkZXN0KTtcblxuICAgICAgZnMud3JpdGVGaWxlKHRlbXBGaWxlUGF0aCwgZGF0YSwgZXJyID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLnRyYWNlKHsgbmFtZTogZGVzdCB9LCAnW2xvY2FsLXN0b3JhZ2UvX3dyaXRlRmlsZV0gbmV3IGZpbGU6IEB7bmFtZX0gaGFzIGJlZW4gY3JlYXRlZCcpO1xuXG4gICAgICAgICAgcmV0dXJuIGNiKGVycik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxvZ2dlci50cmFjZSh7IG5hbWU6IGRlc3QgfSwgJ1tsb2NhbC1zdG9yYWdlL193cml0ZUZpbGVdIGNyZWF0aW5nIGEgbmV3IGZpbGU6IEB7bmFtZX0nKTtcbiAgICAgICAgcmVuYW1lVG1wKHRlbXBGaWxlUGF0aCwgZGVzdCwgY2IpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIGNyZWF0ZVRlbXBGaWxlKGVyciA9PiB7XG4gICAgICBpZiAoZXJyICYmIGVyci5jb2RlID09PSBub1N1Y2hGaWxlKSB7XG4gICAgICAgIG1rZGlycChwYXRoLmRpcm5hbWUoZGVzdCksIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHJldHVybiBjYihlcnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjcmVhdGVUZW1wRmlsZShjYik7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2IoZXJyKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvY2tBbmRSZWFkSlNPTihuYW1lOiBzdHJpbmcsIGNiOiBGdW5jdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IGZpbGVOYW1lOiBzdHJpbmcgPSB0aGlzLl9nZXRTdG9yYWdlKG5hbWUpO1xuXG4gICAgcmVhZEZpbGUoXG4gICAgICBmaWxlTmFtZSxcbiAgICAgIHtcbiAgICAgICAgbG9jazogdHJ1ZSxcbiAgICAgICAgcGFyc2U6IHRydWUsXG4gICAgICB9LFxuICAgICAgKGVyciwgcmVzKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci50cmFjZSh7IG5hbWUgfSwgJ1tsb2NhbC1zdG9yYWdlL19sb2NrQW5kUmVhZEpTT05dIHJlYWQgbmV3IGZpbGU6IEB7bmFtZX0gaGFzIGZhaWxlZCcpO1xuXG4gICAgICAgICAgcmV0dXJuIGNiKGVycik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxvZ2dlci50cmFjZSh7IG5hbWUgfSwgJ1tsb2NhbC1zdG9yYWdlL19sb2NrQW5kUmVhZEpTT05dIGZpbGU6IEB7bmFtZX0gcmVhZCcpO1xuICAgICAgICByZXR1cm4gY2IobnVsbCwgcmVzKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBfdW5sb2NrSlNPTihuYW1lOiBzdHJpbmcsIGNiOiBGdW5jdGlvbik6IHZvaWQge1xuICAgIHVubG9ja0ZpbGUodGhpcy5fZ2V0U3RvcmFnZShuYW1lKSwgY2IpO1xuICB9XG59XG4iXX0= |
\ | No newline at end of file |