appium-adb
Version:
438 lines (351 loc) • 26.8 kB
JavaScript
;
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _appiumSupport = require('appium-support');
var _loggerJs = require('./logger.js');
var _loggerJs2 = _interopRequireDefault(_loggerJs);
var _admZip = require('adm-zip');
var _admZip2 = _interopRequireDefault(_admZip);
var _teen_process = require('teen_process');
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var rootDir = _path2['default'].resolve(__dirname, process.env.NO_PRECOMPILE ? '..' : '../..');
var androidPlatforms = ['android-4.2', 'android-17', 'android-4.3', 'android-18', 'android-4.4', 'android-19', 'android-L', 'android-20', 'android-5.0', 'android-21', 'android-22', 'android-MNC', 'android-23', 'android-6.0'];
function getDirectories(rootPath) {
var files, dirs, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, file, pathString;
return _regeneratorRuntime.async(function getDirectories$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(_appiumSupport.fs.readdir(rootPath));
case 2:
files = context$1$0.sent;
dirs = [];
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$1$0.prev = 7;
_iterator = _getIterator(files);
case 9:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
context$1$0.next = 19;
break;
}
file = _step.value;
pathString = _path2['default'].resolve(rootPath, file);
context$1$0.next = 14;
return _regeneratorRuntime.awrap(_appiumSupport.fs.lstat(pathString));
case 14:
if (!context$1$0.sent.isDirectory()) {
context$1$0.next = 16;
break;
}
dirs.push(file);
case 16:
_iteratorNormalCompletion = true;
context$1$0.next = 9;
break;
case 19:
context$1$0.next = 25;
break;
case 21:
context$1$0.prev = 21;
context$1$0.t0 = context$1$0['catch'](7);
_didIteratorError = true;
_iteratorError = context$1$0.t0;
case 25:
context$1$0.prev = 25;
context$1$0.prev = 26;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 28:
context$1$0.prev = 28;
if (!_didIteratorError) {
context$1$0.next = 31;
break;
}
throw _iteratorError;
case 31:
return context$1$0.finish(28);
case 32:
return context$1$0.finish(25);
case 33:
return context$1$0.abrupt('return', dirs.sort());
case 34:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 21, 25, 33], [26,, 28, 32]]);
}
function getAndroidPlatformAndPath() {
var androidHome, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, platform, platforms, platformPath;
return _regeneratorRuntime.async(function getAndroidPlatformAndPath$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
androidHome = process.env.ANDROID_HOME;
if (_lodash2['default'].isString(androidHome)) {
context$1$0.next = 4;
break;
}
_loggerJs2['default'].error("ANDROID_HOME was not exported!");
return context$1$0.abrupt('return', null);
case 4:
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
context$1$0.prev = 7;
_iterator2 = _getIterator(_lodash2['default'].clone(androidPlatforms).reverse());
case 9:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
context$1$0.next = 20;
break;
}
platform = _step2.value;
platforms = _path2['default'].resolve(androidHome, 'platforms');
platformPath = _path2['default'].resolve(platforms, platform);
context$1$0.next = 15;
return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(platformPath));
case 15:
if (!context$1$0.sent) {
context$1$0.next = 17;
break;
}
return context$1$0.abrupt('return', { platform: platform, platformPath: platformPath });
case 17:
_iteratorNormalCompletion2 = true;
context$1$0.next = 9;
break;
case 20:
context$1$0.next = 26;
break;
case 22:
context$1$0.prev = 22;
context$1$0.t0 = context$1$0['catch'](7);
_didIteratorError2 = true;
_iteratorError2 = context$1$0.t0;
case 26:
context$1$0.prev = 26;
context$1$0.prev = 27;
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
case 29:
context$1$0.prev = 29;
if (!_didIteratorError2) {
context$1$0.next = 32;
break;
}
throw _iteratorError2;
case 32:
return context$1$0.finish(29);
case 33:
return context$1$0.finish(26);
case 34:
return context$1$0.abrupt('return', null);
case 35:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 22, 26, 34], [27,, 29, 33]]);
}
function unzipFile(zipPath) {
var zip;
return _regeneratorRuntime.async(function unzipFile$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_loggerJs2['default'].debug('Unzipping ' + zipPath);
context$1$0.prev = 1;
context$1$0.next = 4;
return _regeneratorRuntime.awrap(assertZipArchive(zipPath));
case 4:
if (!_appiumSupport.system.isWindows()) {
context$1$0.next = 10;
break;
}
zip = new _admZip2['default'](zipPath);
zip.extractAllTo(_path2['default'].dirname(zipPath), true);
_loggerJs2['default'].debug("Unzip successful");
context$1$0.next = 13;
break;
case 10:
context$1$0.next = 12;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('unzip', ['-o', zipPath], { cwd: _path2['default'].dirname(zipPath) }));
case 12:
_loggerJs2['default'].debug("Unzip successful");
case 13:
context$1$0.next = 18;
break;
case 15:
context$1$0.prev = 15;
context$1$0.t0 = context$1$0['catch'](1);
throw new Error('Error occurred while unzipping. Original error: ' + context$1$0.t0.message);
case 18:
case 'end':
return context$1$0.stop();
}
}, null, this, [[1, 15]]);
}
function assertZipArchive(zipPath) {
var execOpts;
return _regeneratorRuntime.async(function assertZipArchive$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_loggerJs2['default'].debug('Testing zip archive: ' + zipPath);
if (!_appiumSupport.system.isWindows()) {
context$1$0.next = 11;
break;
}
context$1$0.next = 4;
return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(zipPath));
case 4:
if (!context$1$0.sent) {
context$1$0.next = 8;
break;
}
_loggerJs2['default'].debug("Zip archive tested clean");
context$1$0.next = 9;
break;
case 8:
throw new Error('Zip archive not present at ' + zipPath);
case 9:
context$1$0.next = 14;
break;
case 11:
execOpts = { cwd: _path2['default'].dirname(zipPath) };
context$1$0.next = 14;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('unzip', ['-tq', zipPath], execOpts));
case 14:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function getIMEListFromOutput(stdout) {
var engines = [];
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = _getIterator(stdout.split('\n')), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var line = _step3.value;
if (line.length > 0 && line[0] !== ' ') {
// remove newline and trailing colon, and add to the list
engines.push(line.trim().replace(/:$/, ''));
}
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3['return']) {
_iterator3['return']();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
return engines;
}
function getJavaForOs() {
var sep = _path2['default'].sep;
var java = '' + getJavaHome() + sep + 'bin' + sep + 'java';
if (_appiumSupport.system.isWindows()) {
java = java + '.exe';
}
return java;
}
function getJavaHome() {
if (process.env.JAVA_HOME) {
return process.env.JAVA_HOME;
}
throw new Error("JAVA_HOME is not set currently. Please set JAVA_HOME.");
}
/*
* Checks mShowingLockscreen in dumpsys output to determine if lock screen is showing
*/
function isShowingLockscreen(dumpsys) {
var m = /mShowingLockscreen=\w+/gi.exec(dumpsys);
var ret = m && m.length && m[0].split('=')[1] === 'true' || false;
return ret;
}
/*
* Checks mCurrentFocus in dumpsys output to determine if Keyguard is activated
*/
function isCurrentFocusOnKeyguard(dumpsys) {
var m = /mCurrentFocus.+Keyguard/gi.exec(dumpsys);
return m && m.length && m[0] ? true : false;
}
/*
* Checks mScreenOnFully in dumpsys output to determine if screen is showing
* Default is true
*/
function isScreenOnFully(dumpsys) {
var m = /mScreenOnFully=\w+/gi.exec(dumpsys);
return !m || // if information is missing we assume screen is fully on
m && m.length > 0 && m[0].split('=')[1] === 'true' || false;
}
function buildStartCmd(startAppOptions, apiLevel) {
var cmd = ['am', 'start', '-n', startAppOptions.pkg + '/' + startAppOptions.activity];
if (startAppOptions.stopApp && apiLevel >= 15) {
cmd.push('-S');
}
if (startAppOptions.action) {
cmd.push('-a', startAppOptions.action);
}
if (startAppOptions.category) {
cmd.push('-c', startAppOptions.category);
}
if (startAppOptions.flags) {
cmd.push('-f', startAppOptions.flags);
}
if (startAppOptions.optionalIntentArguments) {
cmd.push(startAppOptions.optionalIntentArguments);
}
return cmd;
}
// turns pkg.activity.name to .activity.name
// also turns activity.name to .activity.name
function getActivityRelativeName(pkgName, activityRelativeName) {
var relativeName = activityRelativeName;
// need to beware of namespaces with overlapping chars:
// com.foo.bar
// com.foo.barx
if (activityRelativeName.indexOf(pkgName + ".") === 0) {
relativeName = activityRelativeName.substring(pkgName.length);
}
if (relativeName[0] !== '.') {
relativeName = '.' + relativeName;
}
return relativeName;
}
exports.getDirectories = getDirectories;
exports.getAndroidPlatformAndPath = getAndroidPlatformAndPath;
exports.unzipFile = unzipFile;
exports.assertZipArchive = assertZipArchive;
exports.getIMEListFromOutput = getIMEListFromOutput;
exports.getJavaForOs = getJavaForOs;
exports.isShowingLockscreen = isShowingLockscreen;
exports.isCurrentFocusOnKeyguard = isCurrentFocusOnKeyguard;
exports.isScreenOnFully = isScreenOnFully;
exports.buildStartCmd = buildStartCmd;
exports.getActivityRelativeName = getActivityRelativeName;
exports.getJavaHome = getJavaHome;
exports.rootDir = rootDir;
exports.androidPlatforms = androidPlatforms;
// It is not a clean way to sort it, but in this case would work fine because
// we have numerics and alphanumeric
// will return some thing like this
// ["17.0.0", "18.0.1", "19.0.0", "19.0.1", "19.1.0", "20.0.0",
// "android-4.2.2", "android-4.3", "android-4.4"]
// get the latest platform and path
//# sourceMappingURL=data:application/json;base64,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TSxDQUFDLENBQUM7R0FDL0Q7QUFDRCxNQUFJLFlBQVksQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7QUFDM0IsZ0JBQVksU0FBTyxZQUFZLEFBQUUsQ0FBQztHQUNuQztBQUNELFNBQU8sWUFBWSxDQUFDO0NBQ3JCOztRQUVRLGNBQWMsR0FBZCxjQUFjO1FBQUUseUJBQXlCLEdBQXpCLHlCQUF5QjtRQUFFLFNBQVMsR0FBVCxTQUFTO1FBQUUsZ0JBQWdCLEdBQWhCLGdCQUFnQjtRQUN0RSxvQkFBb0IsR0FBcEIsb0JBQW9CO1FBQUUsWUFBWSxHQUFaLFlBQVk7UUFBRSxtQkFBbUIsR0FBbkIsbUJBQW1CO1FBQUUsd0JBQXdCLEdBQXhCLHdCQUF3QjtRQUNqRixlQUFlLEdBQWYsZUFBZTtRQUFFLGFBQWEsR0FBYixhQUFhO1FBQUUsdUJBQXVCLEdBQXZCLHVCQUF1QjtRQUFFLFdBQVcsR0FBWCxXQUFXO1FBQ3BFLE9BQU8sR0FBUCxPQUFPO1FBQUUsZ0JBQWdCLEdBQWhCLGdCQUFnQiIsImZpbGUiOiJsaWIvaGVscGVycy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgc3lzdGVtLCBmcyB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCBsb2cgZnJvbSAnLi9sb2dnZXIuanMnO1xuaW1wb3J0IEFkbVppcCBmcm9tICdhZG0temlwJztcbmltcG9ydCB7IGV4ZWMgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcblxuXG5jb25zdCByb290RGlyID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgcHJvY2Vzcy5lbnYuTk9fUFJFQ09NUElMRSA/ICcuLicgOiAnLi4vLi4nKTtcbmNvbnN0IGFuZHJvaWRQbGF0Zm9ybXMgPSBbJ2FuZHJvaWQtNC4yJywgJ2FuZHJvaWQtMTcnLCAnYW5kcm9pZC00LjMnLCAnYW5kcm9pZC0xOCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdhbmRyb2lkLTQuNCcsICdhbmRyb2lkLTE5JywgJ2FuZHJvaWQtTCcsICdhbmRyb2lkLTIwJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ2FuZHJvaWQtNS4wJywgJ2FuZHJvaWQtMjEnLCAnYW5kcm9pZC0yMicsICdhbmRyb2lkLU1OQycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdhbmRyb2lkLTIzJywgJ2FuZHJvaWQtNi4wJ107XG5cbmFzeW5jIGZ1bmN0aW9uIGdldERpcmVjdG9yaWVzIChyb290UGF0aCkge1xuICBsZXQgZmlsZXMgPSBhd2FpdCBmcy5yZWFkZGlyKHJvb3RQYXRoKTtcbiAgbGV0IGRpcnMgPSBbXTtcbiAgZm9yIChsZXQgZmlsZSBvZiBmaWxlcykge1xuICAgIGxldCBwYXRoU3RyaW5nID0gcGF0aC5yZXNvbHZlKHJvb3RQYXRoLCBmaWxlKTtcbiAgICBpZiAoKGF3YWl0IGZzLmxzdGF0KHBhdGhTdHJpbmcpKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBkaXJzLnB1c2goZmlsZSk7XG4gICAgfVxuICB9XG4gIC8vIEl0IGlzIG5vdCBhIGNsZWFuIHdheSB0byBzb3J0IGl0LCBidXQgaW4gdGhpcyBjYXNlIHdvdWxkIHdvcmsgZmluZSBiZWNhdXNlXG4gIC8vIHdlIGhhdmUgbnVtZXJpY3MgYW5kIGFscGhhbnVtZXJpY1xuICAvLyB3aWxsIHJldHVybiBzb21lIHRoaW5nIGxpa2UgdGhpc1xuICAvLyBbXCIxNy4wLjBcIiwgXCIxOC4wLjFcIiwgXCIxOS4wLjBcIiwgXCIxOS4wLjFcIiwgXCIxOS4xLjBcIiwgXCIyMC4wLjBcIixcbiAgLy8gIFwiYW5kcm9pZC00LjIuMlwiLCBcImFuZHJvaWQtNC4zXCIsIFwiYW5kcm9pZC00LjRcIl1cbiAgcmV0dXJuIGRpcnMuc29ydCgpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRBbmRyb2lkUGxhdGZvcm1BbmRQYXRoICgpIHtcbiAgY29uc3QgYW5kcm9pZEhvbWUgPSBwcm9jZXNzLmVudi5BTkRST0lEX0hPTUU7XG4gIGlmICghXy5pc1N0cmluZyhhbmRyb2lkSG9tZSkpIHtcbiAgICBsb2cuZXJyb3IoXCJBTkRST0lEX0hPTUUgd2FzIG5vdCBleHBvcnRlZCFcIik7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyBnZXQgdGhlIGxhdGVzdCBwbGF0Zm9ybSBhbmQgcGF0aFxuICBmb3IgKGxldCBwbGF0Zm9ybSBvZiBfLmNsb25lKGFuZHJvaWRQbGF0Zm9ybXMpLnJldmVyc2UoKSkge1xuICAgIGxldCBwbGF0Zm9ybXMgPSBwYXRoLnJlc29sdmUoYW5kcm9pZEhvbWUsICdwbGF0Zm9ybXMnKTtcbiAgICBsZXQgcGxhdGZvcm1QYXRoID0gcGF0aC5yZXNvbHZlKHBsYXRmb3JtcywgcGxhdGZvcm0pO1xuICAgIGlmIChhd2FpdCBmcy5leGlzdHMocGxhdGZvcm1QYXRoKSkge1xuICAgICAgcmV0dXJuIHtwbGF0Zm9ybSwgcGxhdGZvcm1QYXRofTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVuemlwRmlsZSAoemlwUGF0aCkge1xuICBsb2cuZGVidWcoYFVuemlwcGluZyAke3ppcFBhdGh9YCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgYXNzZXJ0WmlwQXJjaGl2ZSh6aXBQYXRoKTtcbiAgICBpZiAoc3lzdGVtLmlzV2luZG93cygpKSB7XG4gICAgICBsZXQgemlwID0gbmV3IEFkbVppcCh6aXBQYXRoKTtcbiAgICAgIHppcC5leHRyYWN0QWxsVG8ocGF0aC5kaXJuYW1lKHppcFBhdGgpLCB0cnVlKTtcbiAgICAgIGxvZy5kZWJ1ZyhcIlVuemlwIHN1Y2Nlc3NmdWxcIik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IGV4ZWMoJ3VuemlwJywgWyctbycsIHppcFBhdGhdLCB7Y3dkOiBwYXRoLmRpcm5hbWUoemlwUGF0aCl9KTtcbiAgICAgIGxvZy5kZWJ1ZyhcIlVuemlwIHN1Y2Nlc3NmdWxcIik7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBvY2N1cnJlZCB3aGlsZSB1bnppcHBpbmcuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBhc3NlcnRaaXBBcmNoaXZlICh6aXBQYXRoKSB7XG4gIGxvZy5kZWJ1ZyhgVGVzdGluZyB6aXAgYXJjaGl2ZTogJHt6aXBQYXRofWApO1xuICBpZiAoc3lzdGVtLmlzV2luZG93cygpKSB7XG4gICAgaWYgKGF3YWl0IGZzLmV4aXN0cyh6aXBQYXRoKSkge1xuICAgICAgbG9nLmRlYnVnKFwiWmlwIGFyY2hpdmUgdGVzdGVkIGNsZWFuXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFppcCBhcmNoaXZlIG5vdCBwcmVzZW50IGF0ICR7emlwUGF0aH1gKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgbGV0IGV4ZWNPcHRzID0ge2N3ZDogcGF0aC5kaXJuYW1lKHppcFBhdGgpfTtcbiAgICBhd2FpdCBleGVjKCd1bnppcCcsIFsnLXRxJywgemlwUGF0aF0sIGV4ZWNPcHRzKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRJTUVMaXN0RnJvbU91dHB1dCAoc3Rkb3V0KSB7XG4gIGxldCBlbmdpbmVzID0gW107XG4gIGZvciAobGV0IGxpbmUgb2Ygc3Rkb3V0LnNwbGl0KCdcXG4nKSkge1xuICAgIGlmIChsaW5lLmxlbmd0aCA+IDAgJiYgbGluZVswXSAhPT0gJyAnKSB7XG4gICAgICAvLyByZW1vdmUgbmV3bGluZSBhbmQgdHJhaWxpbmcgY29sb24sIGFuZCBhZGQgdG8gdGhlIGxpc3RcbiAgICAgIGVuZ2luZXMucHVzaChsaW5lLnRyaW0oKS5yZXBsYWNlKC86JC8sICcnKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBlbmdpbmVzO1xufVxuXG5mdW5jdGlvbiBnZXRKYXZhRm9yT3MgKCkge1xuICBjb25zdCBzZXAgPSBwYXRoLnNlcDtcbiAgbGV0IGphdmEgPSBgJHtnZXRKYXZhSG9tZSgpfSR7c2VwfWJpbiR7c2VwfWphdmFgO1xuICBpZiAoc3lzdGVtLmlzV2luZG93cygpKSB7XG4gICAgamF2YSA9IGphdmEgKyAnLmV4ZSc7XG4gIH1cbiAgcmV0dXJuIGphdmE7XG59XG5cbmZ1bmN0aW9uIGdldEphdmFIb21lICgpIHtcbiAgaWYgKHByb2Nlc3MuZW52LkpBVkFfSE9NRSkge1xuICAgIHJldHVybiBwcm9jZXNzLmVudi5KQVZBX0hPTUU7XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKFwiSkFWQV9IT01FIGlzIG5vdCBzZXQgY3VycmVudGx5LiBQbGVhc2Ugc2V0IEpBVkFfSE9NRS5cIik7XG59XG5cbi8qXG4gKiBDaGVja3MgbVNob3dpbmdMb2Nrc2NyZWVuIGluIGR1bXBzeXMgb3V0cHV0IHRvIGRldGVybWluZSBpZiBsb2NrIHNjcmVlbiBpcyBzaG93aW5nXG4gKi9cbmZ1bmN0aW9uIGlzU2hvd2luZ0xvY2tzY3JlZW4gKGR1bXBzeXMpIHtcbiAgbGV0IG0gPSAvbVNob3dpbmdMb2Nrc2NyZWVuPVxcdysvZ2kuZXhlYyhkdW1wc3lzKTtcbiAgbGV0IHJldCA9IChtICYmIG0ubGVuZ3RoICYmIG1bMF0uc3BsaXQoJz0nKVsxXSA9PT0gJ3RydWUnKSB8fCBmYWxzZTtcbiAgcmV0dXJuIHJldDtcbn1cblxuLypcbiAqIENoZWNrcyBtQ3VycmVudEZvY3VzIGluIGR1bXBzeXMgb3V0cHV0IHRvIGRldGVybWluZSBpZiBLZXlndWFyZCBpcyBhY3RpdmF0ZWRcbiAqL1xuZnVuY3Rpb24gaXNDdXJyZW50Rm9jdXNPbktleWd1YXJkIChkdW1wc3lzKSB7XG4gIGxldCBtID0gL21DdXJyZW50Rm9jdXMuK0tleWd1YXJkL2dpLmV4ZWMoZHVtcHN5cyk7XG4gIHJldHVybiAobSAmJiBtLmxlbmd0aCAmJiBtWzBdKSA/IHRydWUgOiBmYWxzZTtcbn1cblxuLypcbiAqIENoZWNrcyBtU2NyZWVuT25GdWxseSBpbiBkdW1wc3lzIG91dHB1dCB0byBkZXRlcm1pbmUgaWYgc2NyZWVuIGlzIHNob3dpbmdcbiAqIERlZmF1bHQgaXMgdHJ1ZVxuICovXG5mdW5jdGlvbiBpc1NjcmVlbk9uRnVsbHkgKGR1bXBzeXMpIHtcbiAgbGV0IG0gPSAvbVNjcmVlbk9uRnVsbHk9XFx3Ky9naS5leGVjKGR1bXBzeXMpO1xuICByZXR1cm4gIW0gfHwgLy8gaWYgaW5mb3JtYXRpb24gaXMgbWlzc2luZyB3ZSBhc3N1bWUgc2NyZWVuIGlzIGZ1bGx5IG9uXG4gICAgICAgICAobSAmJiBtLmxlbmd0aCA+IDAgJiYgbVswXS5zcGxpdCgnPScpWzFdID09PSAndHJ1ZScpIHx8IGZhbHNlO1xufVxuXG5mdW5jdGlvbiBidWlsZFN0YXJ0Q21kIChzdGFydEFwcE9wdGlvbnMsIGFwaUxldmVsKSB7XG4gIGxldCBjbWQgPSBbJ2FtJywgJ3N0YXJ0JywgJy1uJywgYCR7c3RhcnRBcHBPcHRpb25zLnBrZ30vJHtzdGFydEFwcE9wdGlvbnMuYWN0aXZpdHl9YF07XG4gIGlmIChzdGFydEFwcE9wdGlvbnMuc3RvcEFwcCAmJiBhcGlMZXZlbCA+PSAxNSkge1xuICAgIGNtZC5wdXNoKCctUycpO1xuICB9XG4gIGlmIChzdGFydEFwcE9wdGlvbnMuYWN0aW9uKSB7XG4gICAgY21kLnB1c2goJy1hJywgc3RhcnRBcHBPcHRpb25zLmFjdGlvbik7XG4gIH1cbiAgaWYgKHN0YXJ0QXBwT3B0aW9ucy5jYXRlZ29yeSkge1xuICAgIGNtZC5wdXNoKCctYycsIHN0YXJ0QXBwT3B0aW9ucy5jYXRlZ29yeSk7XG4gIH1cbiAgaWYgKHN0YXJ0QXBwT3B0aW9ucy5mbGFncykge1xuICAgIGNtZC5wdXNoKCctZicsIHN0YXJ0QXBwT3B0aW9ucy5mbGFncyk7XG4gIH1cbiAgaWYgKHN0YXJ0QXBwT3B0aW9ucy5vcHRpb25hbEludGVudEFyZ3VtZW50cykge1xuICAgIGNtZC5wdXNoKHN0YXJ0QXBwT3B0aW9ucy5vcHRpb25hbEludGVudEFyZ3VtZW50cyk7XG4gIH1cbiAgcmV0dXJuIGNtZDtcbn1cblxuLy8gdHVybnMgcGtnLmFjdGl2aXR5Lm5hbWUgdG8gLmFjdGl2aXR5Lm5hbWVcbi8vIGFsc28gdHVybnMgYWN0aXZpdHkubmFtZSB0byAuYWN0aXZpdHkubmFtZVxuZnVuY3Rpb24gZ2V0QWN0aXZpdHlSZWxhdGl2ZU5hbWUgKHBrZ05hbWUsIGFjdGl2aXR5UmVsYXRpdmVOYW1lKSB7XG4gIGxldCByZWxhdGl2ZU5hbWUgPSBhY3Rpdml0eVJlbGF0aXZlTmFtZTtcbiAgLy8gbmVlZCB0byBiZXdhcmUgb2YgbmFtZXNwYWNlcyB3aXRoIG92ZXJsYXBwaW5nIGNoYXJzOlxuICAvLyAgIGNvbS5mb28uYmFyXG4gIC8vICAgY29tLmZvby5iYXJ4XG4gIGlmIChhY3Rpdml0eVJlbGF0aXZlTmFtZS5pbmRleE9mKHBrZ05hbWUgKyBcIi5cIikgPT09IDApIHtcbiAgICByZWxhdGl2ZU5hbWUgPSBhY3Rpdml0eVJlbGF0aXZlTmFtZS5zdWJzdHJpbmcocGtnTmFtZS5sZW5ndGgpO1xuICB9XG4gIGlmIChyZWxhdGl2ZU5hbWVbMF0gIT09ICcuJykge1xuICAgIHJlbGF0aXZlTmFtZSA9IGAuJHtyZWxhdGl2ZU5hbWV9YDtcbiAgfVxuICByZXR1cm4gcmVsYXRpdmVOYW1lO1xufVxuXG5leHBvcnQgeyBnZXREaXJlY3RvcmllcywgZ2V0QW5kcm9pZFBsYXRmb3JtQW5kUGF0aCwgdW56aXBGaWxlLCBhc3NlcnRaaXBBcmNoaXZlLFxuICAgICAgICAgZ2V0SU1FTGlzdEZyb21PdXRwdXQsIGdldEphdmFGb3JPcywgaXNTaG93aW5nTG9ja3NjcmVlbiwgaXNDdXJyZW50Rm9jdXNPbktleWd1YXJkLFxuICAgICAgICAgaXNTY3JlZW5PbkZ1bGx5LCBidWlsZFN0YXJ0Q21kLCBnZXRBY3Rpdml0eVJlbGF0aXZlTmFtZSwgZ2V0SmF2YUhvbWUsXG4gICAgICAgICByb290RGlyLCBhbmRyb2lkUGxhdGZvcm1zIH07XG4iXX0=