UNPKG

26.9 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _promise = require('babel-runtime/core-js/promise');
8
9var _promise2 = _interopRequireDefault(_promise);
10
11var _regenerator = require('babel-runtime/regenerator');
12
13var _regenerator2 = _interopRequireDefault(_regenerator);
14
15var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
16
17var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
18
19var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
20
21var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
22
23var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
24
25var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
26
27var _createClass2 = require('babel-runtime/helpers/createClass');
28
29var _createClass3 = _interopRequireDefault(_createClass2);
30
31var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
32
33var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
34
35var _inherits2 = require('babel-runtime/helpers/inherits');
36
37var _inherits3 = _interopRequireDefault(_inherits2);
38
39var _cliEngineCommand = require('cli-engine-command');
40
41var _path = require('path');
42
43var _path2 = _interopRequireDefault(_path);
44
45var _rwlockfile = require('rwlockfile');
46
47var _rwlockfile2 = _interopRequireDefault(_rwlockfile);
48
49function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
50
51var _class = function (_Base) {
52 (0, _inherits3.default)(_class, _Base);
53
54 function _class() {
55 (0, _classCallCheck3.default)(this, _class);
56 return (0, _possibleConstructorReturn3.default)(this, (_class.__proto__ || (0, _getPrototypeOf2.default)(_class)).apply(this, arguments));
57 }
58
59 (0, _createClass3.default)(_class, [{
60 key: 'fetchManifest',
61 value: function () {
62 var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(channel) {
63 var url, manifest;
64 return _regenerator2.default.wrap(function _callee$(_context) {
65 while (1) {
66 switch (_context.prev = _context.next) {
67 case 0:
68 if (this.config.s3.host) {
69 _context.next = 2;
70 break;
71 }
72
73 throw new Error('S3 host not defined');
74
75 case 2:
76 _context.prev = 2;
77 url = 'https://' + this.config.s3.host + '/' + this.config.name + '/channels/' + channel + '/' + process.platform + '-' + process.arch;
78 _context.next = 6;
79 return this.http.get(url);
80
81 case 6:
82 manifest = _context.sent;
83 return _context.abrupt('return', manifest);
84
85 case 10:
86 _context.prev = 10;
87 _context.t0 = _context['catch'](2);
88
89 if (!(_context.t0.statusCode === 403)) {
90 _context.next = 14;
91 break;
92 }
93
94 throw new Error('HTTP 403: Invalid channel ' + channel);
95
96 case 14:
97 throw _context.t0;
98
99 case 15:
100 case 'end':
101 return _context.stop();
102 }
103 }
104 }, _callee, this, [[2, 10]]);
105 }));
106
107 function fetchManifest(_x) {
108 return _ref.apply(this, arguments);
109 }
110
111 return fetchManifest;
112 }()
113 }, {
114 key: 'update',
115 value: function () {
116 var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(manifest) {
117 var url, stream, dir, tmp;
118 return _regenerator2.default.wrap(function _callee2$(_context2) {
119 while (1) {
120 switch (_context2.prev = _context2.next) {
121 case 0:
122 if (this.config.s3.host) {
123 _context2.next = 2;
124 break;
125 }
126
127 throw new Error('S3 host not defined');
128
129 case 2:
130 url = 'https://' + this.config.s3.host + '/' + this.config.name + '/channels/' + manifest.channel + '/' + this.base(manifest) + '.tar.gz';
131 _context2.next = 5;
132 return this.http.stream(url);
133
134 case 5:
135 stream = _context2.sent;
136 dir = _path2.default.join(this.config.dirs.data, 'cli');
137 tmp = _path2.default.join(this.config.dirs.data, 'cli_tmp');
138 _context2.next = 10;
139 return this.extract(stream, tmp);
140
141 case 10:
142 _context2.next = 12;
143 return _rwlockfile2.default.write(this.updatelockfile, { skipOwnPid: true });
144
145 case 12:
146 this.fs.removeSync(dir);
147 this.fs.renameSync(_path2.default.join(tmp, this.base(manifest)), dir);
148 this.fs.removeSync(tmp);
149
150 case 15:
151 case 'end':
152 return _context2.stop();
153 }
154 }
155 }, _callee2, this);
156 }));
157
158 function update(_x2) {
159 return _ref2.apply(this, arguments);
160 }
161
162 return update;
163 }()
164 }, {
165 key: 'extract',
166 value: function extract(stream, dir) {
167 var _this2 = this;
168
169 var zlib = require('zlib');
170 var tar = require('tar-stream');
171
172 return new _promise2.default(function (resolve) {
173 _this2.fs.removeSync(dir);
174 var extract = tar.extract();
175 extract.on('entry', function (header, stream, next) {
176 var p = _path2.default.join(dir, header.name);
177 var opts = { mode: header.mode };
178 switch (header.type) {
179 case 'directory':
180 _this2.fs.mkdirpSync(p, opts);
181 next();
182 break;
183 case 'file':
184 stream.pipe(_this2.fs.createWriteStream(p, opts));
185 break;
186 case 'symlink':
187 // ignore symlinks since they will not work on windows
188 next();
189 break;
190 default:
191 throw new Error(header.type);
192 }
193 stream.resume();
194 stream.on('end', next);
195 });
196 extract.on('finish', resolve);
197 stream.pipe(zlib.createGunzip()).pipe(extract);
198 });
199 }
200 }, {
201 key: 'base',
202 value: function base(manifest) {
203 return this.config.name + '-v' + manifest.version + '-' + process.platform + '-' + process.arch;
204 }
205 }, {
206 key: 'restartCLI',
207 value: function () {
208 var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3() {
209 var _require, spawnSync, _spawnSync, status;
210
211 return _regenerator2.default.wrap(function _callee3$(_context3) {
212 while (1) {
213 switch (_context3.prev = _context3.next) {
214 case 0:
215 _context3.next = 2;
216 return _rwlockfile2.default.read(this.updatelockfile);
217
218 case 2:
219 _rwlockfile2.default.unreadSync(this.updatelockfile);
220 _require = require('child_process'), spawnSync = _require.spawnSync;
221
222 if (this.binPath) {
223 _context3.next = 6;
224 break;
225 }
226
227 return _context3.abrupt('return');
228
229 case 6:
230 _spawnSync = spawnSync(this.binPath, process.argv.slice(2), { stdio: 'inherit', shell: true }), status = _spawnSync.status;
231
232 this.exit(status);
233
234 case 8:
235 case 'end':
236 return _context3.stop();
237 }
238 }
239 }, _callee3, this);
240 }));
241
242 function restartCLI() {
243 return _ref3.apply(this, arguments);
244 }
245
246 return restartCLI;
247 }()
248 }, {
249 key: 'autoupdate',
250 value: function () {
251 var _ref4 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee4() {
252 var _this3 = this;
253
254 var fd, _require2, spawn;
255
256 return _regenerator2.default.wrap(function _callee4$(_context4) {
257 while (1) {
258 switch (_context4.prev = _context4.next) {
259 case 0:
260 _context4.prev = 0;
261
262 if (this.autoupdateNeeded) {
263 _context4.next = 3;
264 break;
265 }
266
267 return _context4.abrupt('return');
268
269 case 3:
270 this.fs.writeFileSync(this.autoupdatefile, '');
271
272 if (!this.config.updateDisabled) {
273 _context4.next = 7;
274 break;
275 }
276
277 _context4.next = 7;
278 return this.warnIfUpdateAvailable();
279
280 case 7:
281 _context4.next = 9;
282 return this.checkIfUpdating();
283
284 case 9:
285 fd = this.fs.openSync(this.autoupdatelogfile, 'a');
286
287 if (this.binPath) {
288 _context4.next = 12;
289 break;
290 }
291
292 return _context4.abrupt('return');
293
294 case 12:
295 _require2 = require('child_process'), spawn = _require2.spawn;
296
297 spawn(this.binPath, ['update'], { stdio: [null, fd, fd], detached: true }).on('error', function (e) {
298 return _this3.warn(e, 'autoupdate:');
299 });
300 _context4.next = 19;
301 break;
302
303 case 16:
304 _context4.prev = 16;
305 _context4.t0 = _context4['catch'](0);
306 this.warn(_context4.t0, 'autoupdate:');
307 case 19:
308 case 'end':
309 return _context4.stop();
310 }
311 }
312 }, _callee4, this, [[0, 16]]);
313 }));
314
315 function autoupdate() {
316 return _ref4.apply(this, arguments);
317 }
318
319 return autoupdate;
320 }()
321 }, {
322 key: 'warnIfUpdateAvailable',
323 value: function () {
324 var _ref5 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee5() {
325 var manifest, local, remote;
326 return _regenerator2.default.wrap(function _callee5$(_context5) {
327 while (1) {
328 switch (_context5.prev = _context5.next) {
329 case 0:
330 _context5.next = 2;
331 return this.fetchManifest(this.config.channel);
332
333 case 2:
334 manifest = _context5.sent;
335 local = this.config.version.split('.');
336 remote = manifest.version.split('.');
337
338 if (local[0] !== remote[0] || local[1] !== remote[1]) {
339 this.stderr.log(this.config.name + ': update available from ' + this.config.version + ' to ' + manifest.version);
340 }
341
342 case 6:
343 case 'end':
344 return _context5.stop();
345 }
346 }
347 }, _callee5, this);
348 }));
349
350 function warnIfUpdateAvailable() {
351 return _ref5.apply(this, arguments);
352 }
353
354 return warnIfUpdateAvailable;
355 }()
356 }, {
357 key: 'checkIfUpdating',
358 value: function () {
359 var _ref6 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee6() {
360 var lock;
361 return _regenerator2.default.wrap(function _callee6$(_context6) {
362 while (1) {
363 switch (_context6.prev = _context6.next) {
364 case 0:
365 lock = require('rwlockfile');
366 _context6.next = 3;
367 return lock.hasWriter(this.updatelockfile);
368
369 case 3:
370 if (!_context6.sent) {
371 _context6.next = 9;
372 break;
373 }
374
375 this.warn(this.config.name + ': warning: update in process');
376 _context6.next = 7;
377 return this.restartCLI();
378
379 case 7:
380 _context6.next = 11;
381 break;
382
383 case 9:
384 _context6.next = 11;
385 return lock.read(this.updatelockfile);
386
387 case 11:
388 case 'end':
389 return _context6.stop();
390 }
391 }
392 }, _callee6, this);
393 }));
394
395 function checkIfUpdating() {
396 return _ref6.apply(this, arguments);
397 }
398
399 return checkIfUpdating;
400 }()
401 }, {
402 key: 'autoupdatefile',
403 get: function get() {
404 return _path2.default.join(this.config.dirs.cache, 'autoupdate');
405 }
406 }, {
407 key: 'autoupdatelogfile',
408 get: function get() {
409 return _path2.default.join(this.config.dirs.cache, 'autoupdate.log');
410 }
411 }, {
412 key: 'updatelockfile',
413 get: function get() {
414 return _path2.default.join(this.config.dirs.cache, 'update.lock');
415 }
416 }, {
417 key: 'binPath',
418 get: function get() {
419 return process.env.CLI_BINPATH;
420 }
421 }, {
422 key: 'autoupdateNeeded',
423 get: function get() {
424 try {
425 var moment = require('moment');
426 var stat = this.fs.statSync(this.autoupdatefile);
427 return moment(stat.mtime).isBefore(moment().subtract(4, 'hours'));
428 } catch (err) {
429 if (err.code !== 'ENOENT') console.error(err.stack);
430 return true;
431 }
432 }
433 }]);
434 return _class;
435}(_cliEngineCommand.Base);
436/* globals
437 stream$Readable
438*/
439
440exports.default = _class;
441//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy91cGRhdGVyLmpzIl0sIm5hbWVzIjpbImNoYW5uZWwiLCJjb25maWciLCJzMyIsImhvc3QiLCJFcnJvciIsInVybCIsIm5hbWUiLCJwcm9jZXNzIiwicGxhdGZvcm0iLCJhcmNoIiwiaHR0cCIsImdldCIsIm1hbmlmZXN0Iiwic3RhdHVzQ29kZSIsImJhc2UiLCJzdHJlYW0iLCJkaXIiLCJqb2luIiwiZGlycyIsImRhdGEiLCJ0bXAiLCJleHRyYWN0Iiwid3JpdGUiLCJ1cGRhdGVsb2NrZmlsZSIsInNraXBPd25QaWQiLCJmcyIsInJlbW92ZVN5bmMiLCJyZW5hbWVTeW5jIiwiemxpYiIsInJlcXVpcmUiLCJ0YXIiLCJvbiIsImhlYWRlciIsIm5leHQiLCJwIiwib3B0cyIsIm1vZGUiLCJ0eXBlIiwibWtkaXJwU3luYyIsInBpcGUiLCJjcmVhdGVXcml0ZVN0cmVhbSIsInJlc3VtZSIsInJlc29sdmUiLCJjcmVhdGVHdW56aXAiLCJ2ZXJzaW9uIiwicmVhZCIsInVucmVhZFN5bmMiLCJzcGF3blN5bmMiLCJiaW5QYXRoIiwiYXJndiIsInNsaWNlIiwic3RkaW8iLCJzaGVsbCIsInN0YXR1cyIsImV4aXQiLCJhdXRvdXBkYXRlTmVlZGVkIiwid3JpdGVGaWxlU3luYyIsImF1dG91cGRhdGVmaWxlIiwidXBkYXRlRGlzYWJsZWQiLCJ3YXJuSWZVcGRhdGVBdmFpbGFibGUiLCJjaGVja0lmVXBkYXRpbmciLCJmZCIsIm9wZW5TeW5jIiwiYXV0b3VwZGF0ZWxvZ2ZpbGUiLCJzcGF3biIsImRldGFjaGVkIiwid2FybiIsImUiLCJmZXRjaE1hbmlmZXN0IiwibG9jYWwiLCJzcGxpdCIsInJlbW90ZSIsInN0ZGVyciIsImxvZyIsImxvY2siLCJoYXNXcml0ZXIiLCJyZXN0YXJ0Q0xJIiwiY2FjaGUiLCJlbnYiLCJDTElfQklOUEFUSCIsIm1vbWVudCIsInN0YXQiLCJzdGF0U3luYyIsIm10aW1lIiwiaXNCZWZvcmUiLCJzdWJ0cmFjdCIsImVyciIsImNv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QUwsQ0FBYSxLQUFLakUsTUFBTCxDQUFZSyxJQUF6Qjs7dUJBQ00sS0FBS3NFLFVBQUwsRTs7Ozs7Ozs7dUJBQ0tGLEtBQUs3QixJQUFMLENBQVUsS0FBS3RCLGNBQWYsQzs7Ozs7Ozs7Ozs7Ozs7Ozs7O3dCQXBIZTtBQUFFLGFBQU8sZUFBS04sSUFBTCxDQUFVLEtBQUtoQixNQUFMLENBQVlpQixJQUFaLENBQWlCMkQsS0FBM0IsRUFBa0MsWUFBbEMsQ0FBUDtBQUF3RDs7O3dCQUN2RDtBQUFFLGFBQU8sZUFBSzVELElBQUwsQ0FBVSxLQUFLaEIsTUFBTCxDQUFZaUIsSUFBWixDQUFpQjJELEtBQTNCLEVBQWtDLGdCQUFsQyxDQUFQO0FBQTREOzs7d0JBQ2pFO0FBQUUsYUFBTyxlQUFLNUQsSUFBTCxDQUFVLEtBQUtoQixNQUFMLENBQVlpQixJQUFaLENBQWlCMkQsS0FBM0IsRUFBa0MsYUFBbEMsQ0FBUDtBQUF5RDs7O3dCQUNqRTtBQUFFLGFBQU90RSxRQUFRdUUsR0FBUixDQUFZQyxXQUFuQjtBQUFnQzs7O3dCQTBFbEM7QUFDdEIsVUFBSTtBQUNGLFlBQU1DLFNBQVNuRCxRQUFRLFFBQVIsQ0FBZjtBQUNBLFlBQU1vRCxPQUFPLEtBQUt4RCxFQUFMLENBQVF5RCxRQUFSLENBQWlCLEtBQUt6QixjQUF0QixDQUFiO0FBQ0EsZUFBT3VCLE9BQU9DLEtBQUtFLEtBQVosRUFBbUJDLFFBQW5CLENBQTRCSixTQUFTSyxRQUFULENBQWtCLENBQWxCLEVBQXFCLE9BQXJCLENBQTVCLENBQVA7QUFDRCxPQUpELENBSUUsT0FBT0MsR0FBUCxFQUFZO0FBQ1osWUFBSUEsSUFBSUMsSUFBSixLQUFhLFFBQWpCLEVBQTJCQyxRQUFRQyxLQUFSLENBQWNILElBQUlJLEtBQWxCO0FBQzNCLGVBQU8sSUFBUDtBQUNEO0FBQ0Y7Ozs7QUFyR0giLCJmaWxlIjoidXBkYXRlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG4vKiBnbG9iYWxzXG4gICBzdHJlYW0kUmVhZGFibGVcbiovXG5cbmltcG9ydCB7QmFzZX0gZnJvbSAnY2xpLWVuZ2luZS1jb21tYW5kJ1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcbmltcG9ydCBsb2NrIGZyb20gJ3J3bG9ja2ZpbGUnXG5cbnR5cGUgTWFuaWZlc3QgPSB7XG4gIHZlcnNpb246IHN0cmluZyxcbiAgY2hhbm5lbDogc3RyaW5nLFxuICBzaGEyNTY6IHN0cmluZ1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBleHRlbmRzIEJhc2Uge1xuICBnZXQgYXV0b3VwZGF0ZWZpbGUgKCk6IHN0cmluZyB7IHJldHVybiBwYXRoLmpvaW4odGhpcy5jb25maWcuZGlycy5jYWNoZSwgJ2F1dG91cGRhdGUnKSB9XG4gIGdldCBhdXRvdXBkYXRlbG9nZmlsZSAoKTogc3RyaW5nIHsgcmV0dXJuIHBhdGguam9pbih0aGlzLmNvbmZpZy5kaXJzLmNhY2hlLCAnYXV0b3VwZGF0ZS5sb2cnKSB9XG4gIGdldCB1cGRhdGVsb2NrZmlsZSAoKTogc3RyaW5nIHsgcmV0dXJuIHBhdGguam9pbih0aGlzLmNvbmZpZy5kaXJzLmNhY2hlLCAndXBkYXRlLmxvY2snKSB9XG4gIGdldCBiaW5QYXRoICgpOiA/c3RyaW5nIHsgcmV0dXJuIHByb2Nlc3MuZW52LkNMSV9CSU5QQVRIIH1cblxuICBhc3luYyBmZXRjaE1hbmlmZXN0IChjaGFubmVsOiBzdHJpbmcpOiBQcm9taXNlPE1hbmlmZXN0PiB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5zMy5ob3N0KSB0aHJvdyBuZXcgRXJyb3IoJ1MzIGhvc3Qgbm90IGRlZmluZWQnKVxuICAgIHRyeSB7XG4gICAgICBsZXQgdXJsID0gYGh0dHBzOi8vJHt0aGlzLmNvbmZpZy5zMy5ob3N0fS8ke3RoaXMuY29uZmlnLm5hbWV9L2NoYW5uZWxzLyR7Y2hhbm5lbH0vJHtwcm9jZXNzLnBsYXRmb3JtfS0ke3Byb2Nlc3MuYXJjaH1gXG4gICAgICBsZXQgbWFuaWZlc3QgPSBhd2FpdCB0aGlzLmh0dHAuZ2V0KHVybClcbiAgICAgIHJldHVybiAoKG1hbmlmZXN0OiBhbnkpOiBQcm9taXNlPE1hbmlmZXN0PilcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChlcnIuc3RhdHVzQ29kZSA9PT0gNDAzKSB0aHJvdyBuZXcgRXJyb3IoYEhUVFAgNDAzOiBJbnZhbGlkIGNoYW5uZWwgJHtjaGFubmVsfWApXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gIH1cblxuICBhc3luYyB1cGRhdGUgKG1hbmlmZXN0OiBNYW5pZmVzdCkge1xuICAgIGlmICghdGhpcy5jb25maWcuczMuaG9zdCkgdGhyb3cgbmV3IEVycm9yKCdTMyBob3N0IG5vdCBkZWZpbmVkJylcbiAgICBsZXQgdXJsID0gYGh0dHBzOi8vJHt0aGlzLmNvbmZpZy5zMy5ob3N0fS8ke3RoaXMuY29uZmlnLm5hbWV9L2NoYW5uZWxzLyR7bWFuaWZlc3QuY2hhbm5lbH0vJHt0aGlzLmJhc2UobWFuaWZlc3QpfS50YXIuZ3pgXG4gICAgbGV0IHN0cmVhbSA9IGF3YWl0IHRoaXMuaHR0cC5zdHJlYW0odXJsKVxuICAgIGxldCBkaXIgPSBwYXRoLmpvaW4odGhpcy5jb25maWcuZGlycy5kYXRhLCAnY2xpJylcbiAgICBsZXQgdG1wID0gcGF0aC5qb2luKHRoaXMuY29uZmlnLmRpcnMuZGF0YSwgJ2NsaV90bXAnKVxuICAgIGF3YWl0IHRoaXMuZXh0cmFjdChzdHJlYW0sIHRtcClcbiAgICBhd2FpdCBsb2NrLndyaXRlKHRoaXMudXBkYXRlbG9ja2ZpbGUsIHtza2lwT3duUGlkOiB0cnVlfSlcbiAgICB0aGlzLmZzLnJlbW92ZVN5bmMoZGlyKVxuICAgIHRoaXMuZnMucmVuYW1lU3luYyhwYXRoLmpvaW4odG1wLCB0aGlzLmJhc2UobWFuaWZlc3QpKSwgZGlyKVxuICAgIHRoaXMuZnMucmVtb3ZlU3luYyh0bXApXG4gIH1cblxuICBleHRyYWN0IChzdHJlYW06IHN0cmVhbSRSZWFkYWJsZSwgZGlyOiBzdHJpbmcpIHtcbiAgICBjb25zdCB6bGliID0gcmVxdWlyZSgnemxpYicpXG4gICAgY29uc3QgdGFyID0gcmVxdWlyZSgndGFyLXN0cmVhbScpXG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLmZzLnJlbW92ZVN5bmMoZGlyKVxuICAgICAgbGV0IGV4dHJhY3QgPSB0YXIuZXh0cmFjdCgpXG4gICAgICBleHRyYWN0Lm9uKCdlbnRyeScsIChoZWFkZXIsIHN0cmVhbSwgbmV4dCkgPT4ge1xuICAgICAgICBsZXQgcCA9IHBhdGguam9pbihkaXIsIGhlYWRlci5uYW1lKVxuICAgICAgICBsZXQgb3B0cyA9IHttb2RlOiBoZWFkZXIubW9kZX1cbiAgICAgICAgc3dpdGNoIChoZWFkZXIudHlwZSkge1xuICAgICAgICAgIGNhc2UgJ2RpcmVjdG9yeSc6XG4gICAgICAgICAgICB0aGlzLmZzLm1rZGlycFN5bmMocCwgb3B0cylcbiAgICAgICAgICAgIG5leHQoKVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBjYXNlICdmaWxlJzpcbiAgICAgICAgICAgIHN0cmVhbS5waXBlKHRoaXMuZnMuY3JlYXRlV3JpdGVTdHJlYW0ocCwgb3B0cykpXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGNhc2UgJ3N5bWxpbmsnOlxuICAgICAgICAgICAgLy8gaWdub3JlIHN5bWxpbmtzIHNpbmNlIHRoZXkgd2lsbCBub3Qgd29yayBvbiB3aW5kb3dzXG4gICAgICAgICAgICBuZXh0KClcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgZGVmYXVsdDogdGhyb3cgbmV3IEVycm9yKGhlYWRlci50eXBlKVxuICAgICAgICB9XG4gICAgICAgIHN0cmVhbS5yZXN1bWUoKVxuICAgICAgICBzdHJlYW0ub24oJ2VuZCcsIG5leHQpXG4gICAgICB9KVxuICAgICAgZXh0cmFjdC5vbignZmluaXNoJywgcmVzb2x2ZSlcbiAgICAgIHN0cmVhbVxuICAgICAgLnBpcGUoemxpYi5jcmVhdGVHdW56aXAoKSlcbiAgICAgIC5waXBlKGV4dHJhY3QpXG4gICAgfSlcbiAgfVxuXG4gIGJhc2UgKG1hbmlmZXN0OiBNYW5pZmVzdCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMuY29uZmlnLm5hbWV9LXYke21hbmlmZXN0LnZlcnNpb259LSR7cHJvY2Vzcy5wbGF0Zm9ybX0tJHtwcm9jZXNzLmFyY2h9YFxuICB9XG5cbiAgYXN5bmMgcmVzdGFydENMSSAoKSB7XG4gICAgYXdhaXQgbG9jay5yZWFkKHRoaXMudXBkYXRlbG9ja2ZpbGUpXG4gICAgbG9jay51bnJlYWRTeW5jKHRoaXMudXBkYXRlbG9ja2ZpbGUpXG4gICAgY29uc3Qge3NwYXduU3luY30gPSByZXF1aXJlKCdjaGlsZF9wcm9jZXNzJylcbiAgICBpZiAoIXRoaXMuYmluUGF0aCkgcmV0dXJuXG4gICAgY29uc3Qge3N0YXR1c30gPSBzcGF3blN5bmModGhpcy5iaW5QYXRoLCBwcm9jZXNzLmFyZ3Yuc2xpY2UoMiksIHtzdGRpbzogJ2luaGVyaXQnLCBzaGVsbDogdHJ1ZX0pXG4gICAgdGhpcy5leGl0KHN0YXR1cylcbiAgfVxuXG4gIGdldCBhdXRvdXBkYXRlTmVlZGVkICgpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbW9tZW50ID0gcmVxdWlyZSgnbW9tZW50JylcbiAgICAgIGNvbnN0IHN0YXQgPSB0aGlzLmZzLnN0YXRTeW5jKHRoaXMuYXV0b3VwZGF0ZWZpbGUpXG4gICAgICByZXR1cm4gbW9tZW50KHN0YXQubXRpbWUpLmlzQmVmb3JlKG1vbWVudCgpLnN1YnRyYWN0KDQsICdob3VycycpKVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyci5jb2RlICE9PSAnRU5PRU5UJykgY29uc29sZS5lcnJvcihlcnIuc3RhY2spXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGF1dG91cGRhdGUgKCkge1xuICAgIHRyeSB7XG4gICAgICBpZiAoIXRoaXMuYXV0b3VwZGF0ZU5lZWRlZCkgcmV0dXJuXG4gICAgICB0aGlzLmZzLndyaXRlRmlsZVN5bmModGhpcy5hdXRvdXBkYXRlZmlsZSwgJycpXG4gICAgICBpZiAodGhpcy5jb25maWcudXBkYXRlRGlzYWJsZWQpIGF3YWl0IHRoaXMud2FybklmVXBkYXRlQXZhaWxhYmxlKClcbiAgICAgIGF3YWl0IHRoaXMuY2hlY2tJZlVwZGF0aW5nKClcbiAgICAgIGxldCBmZCA9IHRoaXMuZnMub3BlblN5bmModGhpcy5hdXRvdXBkYXRlbG9nZmlsZSwgJ2EnKVxuICAgICAgaWYgKCF0aGlzLmJpblBhdGgpIHJldHVyblxuICAgICAgY29uc3Qge3NwYXdufSA9IHJlcXVpcmUoJ2NoaWxkX3Byb2Nlc3MnKVxuICAgICAgc3Bhd24odGhpcy5iaW5QYXRoLCBbJ3VwZGF0ZSddLCB7c3RkaW86IFtudWxsLCBmZCwgZmRdLCBkZXRhY2hlZDogdHJ1ZX0pXG4gICAgICAub24oJ2Vycm9yJywgZSA9PiB0aGlzLndhcm4oZSwgJ2F1dG91cGRhdGU6JykpXG4gICAgfSBjYXRjaCAoZSkgeyB0aGlzLndhcm4oZSwgJ2F1dG91cGRhdGU6JykgfVxuICB9XG5cbiAgYXN5bmMgd2FybklmVXBkYXRlQXZhaWxhYmxlICgpIHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IHRoaXMuZmV0Y2hNYW5pZmVzdCh0aGlzLmNvbmZpZy5jaGFubmVsKVxuICAgIGxldCBsb2NhbCA9IHRoaXMuY29uZmlnLnZlcnNpb24uc3BsaXQoJy4nKVxuICAgIGxldCByZW1vdGUgPSBtYW5pZmVzdC52ZXJzaW9uLnNwbGl0KCcuJylcbiAgICBpZiAobG9jYWxbMF0gIT09IHJlbW90ZVswXSB8fCBsb2NhbFsxXSAhPT0gcmVtb3RlWzFdKSB7XG4gICAgICB0aGlzLnN0ZGVyci5sb2coYCR7dGhpcy5jb25maWcubmFtZX06IHVwZGF0ZSBhdmFpbGFibGUgZnJvbSAke3RoaXMuY29uZmlnLnZlcnNpb259IHRvICR7bWFuaWZlc3QudmVyc2lvbn1gKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGNoZWNrSWZVcGRhdGluZyAoKSB7XG4gICAgY29uc3QgbG9jayA9IHJlcXVpcmUoJ3J3bG9ja2ZpbGUnKVxuICAgIGlmIChhd2FpdCBsb2NrLmhhc1dyaXRlcih0aGlzLnVwZGF0ZWxvY2tmaWxlKSkge1xuICAgICAgdGhpcy53YXJuKGAke3RoaXMuY29uZmlnLm5hbWV9OiB3YXJuaW5nOiB1cGRhdGUgaW4gcHJvY2Vzc2ApXG4gICAgICBhd2FpdCB0aGlzLnJlc3RhcnRDTEkoKVxuICAgIH0gZWxzZSBhd2FpdCBsb2NrLnJlYWQodGhpcy51cGRhdGVsb2NrZmlsZSlcbiAgfVxufVxuIl19
\No newline at end of file