Code coverage report for src/commitizen/adapter.js

Statements: 93.81% (91 / 97)      Branches: 87.76% (43 / 49)      Functions: 100% (11 / 11)      Lines: 91.67% (66 / 72)      Ignored: 20 statements, 1 function, 14 branches     

All files » src/commitizen/ » adapter.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187    1         48       4   1   1   1   1   1   1   1   1   1   1 1 1 1 1 1 1                             1   11               11 11 11 11 11 11   11           1     12     12 12 12   12 12 48   48 48   48 14             12 12       12           12           1     11     11 11                 1 11           1 12           1   3     2   2 2                   1 6     6     6     3 3     1   4   2      
'use strict';
 
Object.defineProperty(exports, '__esModule', {
  value: true
});
// istanbul ignore next
 
var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { Eif (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
 
// istanbul ignore next
 
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
 
var _path = require('path');
 
var _path2 = _interopRequireDefault(_path);
 
var _fs = require('fs');
 
var _fs2 = _interopRequireDefault(_fs);
 
var _findNodeModules = require('find-node-modules');
 
var _findNodeModules2 = _interopRequireDefault(_findNodeModules);
 
var _lodash = require('lodash');
 
var _lodash2 = _interopRequireDefault(_lodash);
 
var _commonUtil = require('../common/util');
 
exports.addPathToAdapterConfig = addPathToAdapterConfig;
exports.getNearestNodeModulesDirectory = getNearestNodeModulesDirectory;
exports.getNearestProjectRootDirectory = getNearestProjectRootDirectory;
exports.getNpmInstallStringMappings = getNpmInstallStringMappings;
exports.getPrompter = getPrompter;
exports.generateNpmInstallAdapterCommand = generateNpmInstallAdapterCommand;
exports.resolveAdapterPath = resolveAdapterPath;
 
/**
 * ADAPTER
 * 
 * Adapter is generally responsible for actually installing adapters to an 
 * end user's project. It does not perform checks to determine if there is
 * a previous commitizen adapter installed or if the proper fields were
 * provided. It defers that responsibility to init. 
 */
 
/**
 * Modifies the package.json, sets config.commitizen.path to the path of the adapter
 * Must be passed an absolute path to the cli's root
 */
function addPathToAdapterConfig(sh, cliPath, repoPath, adapterNpmName) {
 
  var commitizenAdapterConfig = {
    config: {
      commitizen: {
        path: './node_modules/' + adapterNpmName
      }
    }
  };
 
  var packageJsonPath = _path2['default'].join(getNearestProjectRootDirectory(), 'package.json');
  var packageJsonString = _fs2['default'].readFileSync(packageJsonPath);
  var packageJsonContent = JSON.parse(packageJsonString);
  var newPackageJsonContent = '';
  Eif (_lodash2['default'].get(packageJsonContent, 'config.commitizen.path') !== adapterNpmName) {
    newPackageJsonContent = _lodash2['default'].merge(packageJsonContent, commitizenAdapterConfig);
  }
  _fs2['default'].writeFileSync(packageJsonPath, JSON.stringify(newPackageJsonContent));
}
 
/**
 * Generates an npm install command given a map of strings and a package name
 */
function generateNpmInstallAdapterCommand(stringMappings, adapterNpmName) {
 
  // Start with an initial npm install command
  var installAdapterCommand = 'npm install ' + adapterNpmName;
 
  // Append the neccesary arguments to it based on user preferences
  var _iteratorNormalCompletion = true;
  var _didIteratorError = false;
  var _iteratorError = undefined;
 
  try {
    for (var _iterator = stringMappings.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
      var _step$value = _slicedToArray(_step.value, 2);
 
      var key = _step$value[0];
      var value = _step$value[1];
 
      if (value) {
        installAdapterCommand = installAdapterCommand + ' ' + value;
      }
    }
  } catch (err) {
    _didIteratorError = true;
    _iteratorError = err;
  } finally {
    try {
      Iif (!_iteratorNormalCompletion && _iterator['return']) {
        _iterator['return']();
      }
    } finally {
      Iif (_didIteratorError) {
        throw _iteratorError;
      }
    }
  }
 
  return installAdapterCommand;
}
 
/**
 * Gets the nearest npm_modules directory
 */
function getNearestNodeModulesDirectory(options) {
 
  // Get the nearest node_modules directories to the current working directory
  var nodeModulesDirectories = (0, _findNodeModules2['default'])(options);
 
  // Make sure we find a node_modules folder
  Eif (nodeModulesDirectories && nodeModulesDirectories.length > 0) {
    return nodeModulesDirectories[0];
  } else {
    console.error('Error: Could not locate node_modules in your project\'s root directory. Did you forget to npm init or npm install?');
  }
}
 
/**
 * Gets the nearest project root directory
 */
function getNearestProjectRootDirectory(options) {
  return _path2['default'].join(process.cwd(), getNearestNodeModulesDirectory(options), '/../');
}
 
/**
 * Gets a map of arguments where the value is the corresponding npm strings
 */
function getNpmInstallStringMappings(save, saveDev, saveExact, force) {
  return new Map().set('save', save && !saveDev ? '--save' : undefined).set('saveDev', saveDev ? '--save-dev' : undefined).set('saveExact', saveExact ? '--save-exact' : undefined).set('force', force ? '--force' : undefined);
}
 
/**
 * Gets the prompter from an adapter given an adapter path
 */
function getPrompter(adapterPath) {
  // We need to handle directories and files, so resolve the parh first
  var resolvedAdapterPath = resolveAdapterPath(adapterPath);
 
  // Load the adapter
  var adapter = require(resolvedAdapterPath);
 
  Eif (adapter && adapter.prompter && (0, _commonUtil.isFunction)(adapter.prompter)) {
    return adapter.prompter;
  } else {
    throw "Could not find prompter method in the provided adapter module: " + adapterPath;
  }
}
 
/**
 * Given a path, which can be a directory or file, will
 * return a located adapter path or will throw.
 */
function resolveAdapterPath(inboundAdapterPath) {
  var outboundAdapterPath = undefined;
 
  // Try to open the provided path
  try {
 
    // If we're given a directory, append index.js
    if (_fs2['default'].lstatSync(inboundAdapterPath).isDirectory()) {
 
      // Modify the path and make sure the modified path exists
      outboundAdapterPath = _path2['default'].join(inboundAdapterPath, 'index.js');
      _fs2['default'].lstatSync(outboundAdapterPath);
    } else {
      // The file exists and is a file, so just return it
      outboundAdapterPath = inboundAdapterPath;
    }
    return outboundAdapterPath;
  } catch (err) {
    throw err;
  }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3RyYXZpcy9idWlsZC9jb21taXRpemVuL2N6LWNsaS9zcmMvY29tbWl0aXplbi9hZGFwdGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7b0JBQWlCLE1BQU07Ozs7a0JBQ1IsSUFBSTs7OzsrQkFDUyxtQkFBbUI7Ozs7c0JBQ2pDLFFBQVE7Ozs7MEJBRUcsZ0JBQWdCOztRQUd2QyxzQkFBc0IsR0FBdEIsc0JBQXNCO1FBQ3RCLDhCQUE4QixHQUE5Qiw4QkFBOEI7UUFDOUIsOEJBQThCLEdBQTlCLDhCQUE4QjtRQUM5QiwyQkFBMkIsR0FBM0IsMkJBQTJCO1FBQzNCLFdBQVcsR0FBWCxXQUFXO1FBQ1gsZ0NBQWdDLEdBQWhDLGdDQUFnQztRQUNoQyxrQkFBa0IsR0FBbEIsa0JBQWtCOzs7Ozs7Ozs7Ozs7Ozs7QUFnQnBCLFNBQVMsc0JBQXNCLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFOztBQUVyRSxNQUFJLHVCQUF1QixHQUFHO0FBQzVCLFVBQU0sRUFBRTtBQUNOLGdCQUFVLEVBQUU7QUFDVixZQUFJLHNCQUFvQixjQUFjLEFBQUU7T0FDekM7S0FDRjtHQUNGLENBQUM7O0FBRUYsTUFBSSxlQUFlLEdBQUcsa0JBQUssSUFBSSxDQUFDLDhCQUE4QixFQUFFLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDbEYsTUFBSSxpQkFBaUIsR0FBRyxnQkFBRyxZQUFZLENBQUMsZUFBZSxDQUFDLENBQUM7QUFDekQsTUFBSSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFDdkQsTUFBSSxxQkFBcUIsR0FBRyxFQUFFLENBQUM7QUFDL0IsTUFBRyxvQkFBRSxHQUFHLENBQUMsa0JBQWtCLEVBQUMsd0JBQXdCLENBQUMsS0FBSyxjQUFjLEVBQUU7QUFDeEUseUJBQXFCLEdBQUcsb0JBQUUsS0FBSyxDQUFDLGtCQUFrQixFQUFFLHVCQUF1QixDQUFDLENB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aXplbi9hZGFwdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IGZpbmROb2RlTW9kdWxlcyBmcm9tICdmaW5kLW5vZGUtbW9kdWxlcyc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuXG5pbXBvcnQge2lzRnVuY3Rpb259IGZyb20gJy4uL2NvbW1vbi91dGlsJztcblxuZXhwb3J0IHtcbiAgYWRkUGF0aFRvQWRhcHRlckNvbmZpZyxcbiAgZ2V0TmVhcmVzdE5vZGVNb2R1bGVzRGlyZWN0b3J5LFxuICBnZXROZWFyZXN0UHJvamVjdFJvb3REaXJlY3RvcnksXG4gIGdldE5wbUluc3RhbGxTdHJpbmdNYXBwaW5ncyxcbiAgZ2V0UHJvbXB0ZXIsXG4gIGdlbmVyYXRlTnBtSW5zdGFsbEFkYXB0ZXJDb21tYW5kLFxuICByZXNvbHZlQWRhcHRlclBhdGhcbn07XG5cbi8qKlxuICogQURBUFRFUlxuICogXG4gKiBBZGFwdGVyIGlzIGdlbmVyYWxseSByZXNwb25zaWJsZSBmb3IgYWN0dWFsbHkgaW5zdGFsbGluZyBhZGFwdGVycyB0byBhbiBcbiAqIGVuZCB1c2VyJ3MgcHJvamVjdC4gSXQgZG9lcyBub3QgcGVyZm9ybSBjaGVja3MgdG8gZGV0ZXJtaW5lIGlmIHRoZXJlIGlzXG4gKiBhIHByZXZpb3VzIGNvbW1pdGl6ZW4gYWRhcHRlciBpbnN0YWxsZWQgb3IgaWYgdGhlIHByb3BlciBmaWVsZHMgd2VyZVxuICogcHJvdmlkZWQuIEl0IGRlZmVycyB0aGF0IHJlc3BvbnNpYmlsaXR5IHRvIGluaXQuIFxuICovXG5cbi8qKlxuICogTW9kaWZpZXMgdGhlIHBhY2thZ2UuanNvbiwgc2V0cyBjb25maWcuY29tbWl0aXplbi5wYXRoIHRvIHRoZSBwYXRoIG9mIHRoZSBhZGFwdGVyXG4gKiBNdXN0IGJlIHBhc3NlZCBhbiBhYnNvbHV0ZSBwYXRoIHRvIHRoZSBjbGkncyByb290XG4gKi9cbmZ1bmN0aW9uIGFkZFBhdGhUb0FkYXB0ZXJDb25maWcoc2gsIGNsaVBhdGgsIHJlcG9QYXRoLCBhZGFwdGVyTnBtTmFtZSkge1xuICBcbiAgbGV0IGNvbW1pdGl6ZW5BZGFwdGVyQ29uZmlnID0ge1xuICAgIGNvbmZpZzoge1xuICAgICAgY29tbWl0aXplbjoge1xuICAgICAgICBwYXRoOiBgLi9ub2RlX21vZHVsZXMvJHthZGFwdGVyTnBtTmFtZX1gXG4gICAgICB9XG4gICAgfVxuICB9O1xuICBcbiAgbGV0IHBhY2thZ2VKc29uUGF0aCA9IHBhdGguam9pbihnZXROZWFyZXN0UHJvamVjdFJvb3REaXJlY3RvcnkoKSwgJ3BhY2thZ2UuanNvbicpO1xuICBsZXQgcGFja2FnZUpzb25TdHJpbmcgPSBmcy5yZWFkRmlsZVN5bmMocGFja2FnZUpzb25QYXRoKTtcbiAgbGV0IHBhY2thZ2VKc29uQ29udGVudCA9IEpTT04ucGFyc2UocGFja2FnZUpzb25TdHJpbmcpO1xuICBsZXQgbmV3UGFja2FnZUpzb25Db250ZW50ID0gJyc7XG4gIGlmKF8uZ2V0KHBhY2thZ2VKc29uQ29udGVudCwnY29uZmlnLmNvbW1pdGl6ZW4ucGF0aCcpICE9PSBhZGFwdGVyTnBtTmFtZSkge1xuICAgIG5ld1BhY2thZ2VKc29uQ29udGVudCA9IF8ubWVyZ2UocGFja2FnZUpzb25Db250ZW50LCBjb21taXRpemVuQWRhcHRlckNvbmZpZyk7XG4gIH1cbiAgZnMud3JpdGVGaWxlU3luYyhwYWNrYWdlSnNvblBhdGgsIEpTT04uc3RyaW5naWZ5KG5ld1BhY2thZ2VKc29uQ29udGVudCkpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhbiBucG0gaW5zdGFsbCBjb21tYW5kIGdpdmVuIGEgbWFwIG9mIHN0cmluZ3MgYW5kIGEgcGFja2FnZSBuYW1lXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlTnBtSW5zdGFsbEFkYXB0ZXJDb21tYW5kKHN0cmluZ01hcHBpbmdzLCBhZGFwdGVyTnBtTmFtZSkge1xuIFxuICAvLyBTdGFydCB3aXRoIGFuIGluaXRpYWwgbnBtIGluc3RhbGwgY29tbWFuZFxuICBsZXQgaW5zdGFsbEFkYXB0ZXJDb21tYW5kID0gYG5wbSBpbnN0YWxsICR7YWRhcHRlck5wbU5hbWV9YDtcbiAgXG4gIC8vIEFwcGVuZCB0aGUgbmVjY2VzYXJ5IGFyZ3VtZW50cyB0byBpdCBiYXNlZCBvbiB1c2VyIHByZWZlcmVuY2VzXG4gIGZvcihsZXQgW2tleSwgdmFsdWVdIG9mIHN0cmluZ01hcHBpbmdzLmVudHJpZXMoKSkge1xuICAgIGlmKHZhbHVlKSB7XG4gICAgICBpbnN0YWxsQWRhcHRlckNvbW1hbmQgPSBpbnN0YWxsQWRhcHRlckNvbW1hbmQgKyAnICcgKyB2YWx1ZTtcbiAgICB9XG4gIH1cbiAgXG4gIHJldHVybiBpbnN0YWxsQWRhcHRlckNvbW1hbmQ7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgbmVhcmVzdCBucG1fbW9kdWxlcyBkaXJlY3RvcnlcbiAqL1xuZnVuY3Rpb24gZ2V0TmVhcmVzdE5vZGVNb2R1bGVzRGlyZWN0b3J5KG9wdGlvbnMpIHtcbiAgXG4gIC8vIEdldCB0aGUgbmVhcmVzdCBub2RlX21vZHVsZXMgZGlyZWN0b3JpZXMgdG8gdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnlcbiAgbGV0IG5vZGVNb2R1bGVzRGlyZWN0b3JpZXMgPSBmaW5kTm9kZU1vZHVsZXMob3B0aW9ucyk7XG4gIFxuICAgLy8gTWFrZSBzdXJlIHdlIGZpbmQgYSBub2RlX21vZHVsZXMgZm9sZGVyXG4gIGlmKG5vZGVNb2R1bGVzRGlyZWN0b3JpZXMgJiYgbm9kZU1vZHVsZXNEaXJlY3Rvcmllcy5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIG5vZGVNb2R1bGVzRGlyZWN0b3JpZXNbMF07XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcihgRXJyb3I6IENvdWxkIG5vdCBsb2NhdGUgbm9kZV9tb2R1bGVzIGluIHlvdXIgcHJvamVjdCdzIHJvb3QgZGlyZWN0b3J5LiBEaWQgeW91IGZvcmdldCB0byBucG0gaW5pdCBvciBucG0gaW5zdGFsbD9gKVxuICB9XG59XG5cbi8qKlxuICogR2V0cyB0aGUgbmVhcmVzdCBwcm9qZWN0IHJvb3QgZGlyZWN0b3J5XG4gKi9cbmZ1bmN0aW9uIGdldE5lYXJlc3RQcm9qZWN0Um9vdERpcmVjdG9yeShvcHRpb25zKSB7XG4gIHJldHVybiBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgZ2V0TmVhcmVzdE5vZGVNb2R1bGVzRGlyZWN0b3J5KG9wdGlvbnMpLCAnLy4uLycpO1xufVxuXG4vKipcbiAqIEdldHMgYSBtYXAgb2YgYXJndW1lbnRzIHdoZXJlIHRoZSB2YWx1ZSBpcyB0aGUgY29ycmVzcG9uZGluZyBucG0gc3RyaW5nc1xuICovXG5mdW5jdGlvbiBnZXROcG1JbnN0YWxsU3RyaW5nTWFwcGluZ3Moc2F2ZSwgc2F2ZURldiwgc2F2ZUV4YWN0LCBmb3JjZSkge1xuICByZXR1cm4gbmV3IE1hcCgpXG4gICAgLnNldCgnc2F2ZScsIChzYXZlICYmICFzYXZlRGV2KSA/ICctLXNhdmUnOnVuZGVmaW5lZClcbiAgICAuc2V0KCdzYXZlRGV2Jywgc2F2ZURldiA/ICctLXNhdmUtZGV2Jzp1bmRlZmluZWQpXG4gICAgLnNldCgnc2F2ZUV4YWN0Jywgc2F2ZUV4YWN0ID8gJy0tc2F2ZS1leGFjdCc6dW5kZWZpbmVkKVxuICAgIC5zZXQoJ2ZvcmNlJywgZm9yY2UgPyAnLS1mb3JjZSc6dW5kZWZpbmVkKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBwcm9tcHRlciBmcm9tIGFuIGFkYXB0ZXIgZ2l2ZW4gYW4gYWRhcHRlciBwYXRoXG4gKi9cbmZ1bmN0aW9uIGdldFByb21wdGVyKGFkYXB0ZXJQYXRoKSB7XG4gIC8vIFdlIG5lZWQgdG8gaGFuZGxlIGRpcmVjdG9yaWVzIGFuZCBmaWxlcywgc28gcmVzb2x2ZSB0aGUgcGFyaCBmaXJzdFxuICBsZXQgcmVzb2x2ZWRBZGFwdGVyUGF0aCA9IHJlc29sdmVBZGFwdGVyUGF0aChhZGFwdGVyUGF0aCk7XG5cbiAgLy8gTG9hZCB0aGUgYWRhcHRlclxuICBsZXQgYWRhcHRlciA9IHJlcXVpcmUocmVzb2x2ZWRBZGFwdGVyUGF0aCk7XG4gIFxuICBpZihhZGFwdGVyICYmIGFkYXB0ZXIucHJvbXB0ZXIgJiYgaXNGdW5jdGlvbihhZGFwdGVyLnByb21wdGVyKSkge1xuICAgICByZXR1cm4gYWRhcHRlci5wcm9tcHRlcjsgXG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgXCJDb3VsZCBub3QgZmluZCBwcm9tcHRlciBtZXRob2QgaW4gdGhlIHByb3ZpZGVkIGFkYXB0ZXIgbW9kdWxlOiBcIiArIGFkYXB0ZXJQYXRoO1xuICB9XG59XG5cbi8qKlxuICogR2l2ZW4gYSBwYXRoLCB3aGljaCBjYW4gYmUgYSBkaXJlY3Rvcnkgb3IgZmlsZSwgd2lsbFxuICogcmV0dXJuIGEgbG9jYXRlZCBhZGFwdGVyIHBhdGggb3Igd2lsbCB0aHJvdy5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZUFkYXB0ZXJQYXRoKGluYm91bmRBZGFwdGVyUGF0aCkge1xuICBsZXQgb3V0Ym91bmRBZGFwdGVyUGF0aDtcbiAgXG4gIC8vIFRyeSB0byBvcGVuIHRoZSBwcm92aWRlZCBwYXRoXG4gIHRyeSB7XG4gICAgXG4gICAgLy8gSWYgd2UncmUgZ2l2ZW4gYSBkaXJlY3RvcnksIGFwcGVuZCBpbmRleC5qcyBcbiAgICBpZihmcy5sc3RhdFN5bmMoaW5ib3VuZEFkYXB0ZXJQYXRoKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBcbiAgICAgIC8vIE1vZGlmeSB0aGUgcGF0aCBhbmQgbWFrZSBzdXJlIHRoZSBtb2RpZmllZCBwYXRoIGV4aXN0c1xuICAgICAgb3V0Ym91bmRBZGFwdGVyUGF0aCA9IHBhdGguam9pbihpbmJvdW5kQWRhcHRlclBhdGgsICdpbmRleC5qcycpO1xuICAgICAgZnMubHN0YXRTeW5jKG91dGJvdW5kQWRhcHRlclBhdGgpOyBcbiAgICAgIFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBUaGUgZmlsZSBleGlzdHMgYW5kIGlzIGEgZmlsZSwgc28ganVzdCByZXR1cm4gaXRcbiAgICAgIG91dGJvdW5kQWRhcHRlclBhdGggPSBpbmJvdW5kQWRhcHRlclBhdGg7XG4gICAgfVxuICAgIHJldHVybiBvdXRib3VuZEFkYXB0ZXJQYXRoO1xuICAgIFxuICB9IGNhdGNoKGVycikge1xuICAgIHRocm93IGVycjtcbiAgfVxuICBcbn0iXX0=