settings.js
  1  "use strict";
  2  Object.defineProperty(exports, "__esModule", { value: true });
  3  exports.Settings = exports.Context = exports.Configuration = exports.Command = exports.TRANSIENT_CONTEXT_KEY = exports.USER_DEFAULTS = exports.PROJECT_CONTEXT = exports.PROJECT_CONFIG = void 0;
  4  const os = require("os");
  5  const fs_path = require("path");
  6  const fs = require("fs-extra");
  7  const logging_1 = require("./logging");
  8  const util = require("./util");
  9  exports.PROJECT_CONFIG = 'cdk.json';
 10  exports.PROJECT_CONTEXT = 'cdk.context.json';
 11  exports.USER_DEFAULTS = '~/.cdk.json';
 12  /**
 13   * If a context value is an object with this key set to a truthy value, it won't be saved to cdk.context.json
 14   */
 15  exports.TRANSIENT_CONTEXT_KEY = '$dontSaveContext';
 16  const CONTEXT_KEY = 'context';
 17  var Command;
 18  (function (Command) {
 19      Command["LS"] = "ls";
 20      Command["LIST"] = "list";
 21      Command["DIFF"] = "diff";
 22      Command["BOOTSTRAP"] = "bootstrap";
 23      Command["DEPLOY"] = "deploy";
 24      Command["DESTROY"] = "destroy";
 25      Command["SYNTHESIZE"] = "synthesize";
 26      Command["SYNTH"] = "synth";
 27      Command["METADATA"] = "metadata";
 28      Command["INIT"] = "init";
 29      Command["VERSION"] = "version";
 30  })(Command = exports.Command || (exports.Command = {}));
 31  const BUNDLING_COMMANDS = [
 32      Command.DEPLOY,
 33      Command.DIFF,
 34      Command.SYNTH,
 35      Command.SYNTHESIZE,
 36  ];
 37  /**
 38   * All sources of settings combined
 39   */
 40  class Configuration {
 41      constructor(props = {}) {
 42          this.props = props;
 43          this.settings = new Settings();
 44          this.context = new Context();
 45          this.defaultConfig = new Settings({
 46              versionReporting: true,
 47              pathMetadata: true,
 48              output: 'cdk.out',
 49          });
 50          this.loaded = false;
 51          this.commandLineArguments = props.commandLineArguments
 52              ? Settings.fromCommandLineArguments(props.commandLineArguments)
 53              : new Settings();
 54          this.commandLineContext = this.commandLineArguments.subSettings([CONTEXT_KEY]).makeReadOnly();
 55      }
 56      get projectConfig() {
 57          if (!this._projectConfig) {
 58              throw new Error('#load has not been called yet!');
 59          }
 60          return this._projectConfig;
 61      }
 62      get projectContext() {
 63          if (!this._projectContext) {
 64              throw new Error('#load has not been called yet!');
 65          }
 66          return this._projectContext;
 67      }
 68      /**
 69       * Load all config
 70       */
 71      async load() {
 72          var _a;
 73          const userConfig = await loadAndLog(exports.USER_DEFAULTS);
 74          this._projectConfig = await loadAndLog(exports.PROJECT_CONFIG);
 75          this._projectContext = await loadAndLog(exports.PROJECT_CONTEXT);
 76          const readUserContext = (_a = this.props.readUserContext) !== null && _a !== void 0 ? _a : true;
 77          const contextSources = [
 78              this.commandLineContext,
 79              this.projectConfig.subSettings([CONTEXT_KEY]).makeReadOnly(),
 80              this.projectContext,
 81          ];
 82          if (readUserContext) {
 83              contextSources.push(userConfig.subSettings([CONTEXT_KEY]).makeReadOnly());
 84          }
 85          this.context = new Context(...contextSources);
 86          // Build settings from what's left
 87          this.settings = this.defaultConfig
 88              .merge(userConfig)
 89              .merge(this.projectConfig)
 90              .merge(this.commandLineArguments)
 91              .makeReadOnly();
 92          logging_1.debug('merged settings:', this.settings.all);
 93          this.loaded = true;
 94          return this;
 95      }
 96      /**
 97       * Save the project context
 98       */
 99      async saveContext() {
100          if (!this.loaded) {
101              return this;
102          } // Avoid overwriting files with nothing
103          await this.projectContext.save(exports.PROJECT_CONTEXT);
104          return this;
105      }
106  }
107  exports.Configuration = Configuration;
108  async function loadAndLog(fileName) {
109      const ret = new Settings();
110      await ret.load(fileName);
111      if (!ret.empty) {
112          logging_1.debug(fileName + ':', JSON.stringify(ret.all, undefined, 2));
113      }
114      return ret;
115  }
116  /**
117   * Class that supports overlaying property bags
118   *
119   * Reads come from the first property bag that can has the given key,
120   * writes go to the first property bag that is not readonly. A write
121   * will remove the value from all property bags after the first
122   * writable one.
123   */
124  class Context {
125      constructor(...bags) {
126          this.bags = bags.length > 0 ? bags : [new Settings()];
127      }
128      get keys() {
129          return Object.keys(this.all);
130      }
131      has(key) {
132          return this.keys.indexOf(key) > -1;
133      }
134      get all() {
135          let ret = new Settings();
136          // In reverse order so keys to the left overwrite keys to the right of them
137          for (const bag of [...this.bags].reverse()) {
138              ret = ret.merge(bag);
139          }
140          return ret.all;
141      }
142      get(key) {
143          for (const bag of this.bags) {
144              const v = bag.get([key]);
145              if (v !== undefined) {
146                  return v;
147              }
148          }
149          return undefined;
150      }
151      set(key, value) {
152          for (const bag of this.bags) {
153              if (bag.readOnly) {
154                  continue;
155              }
156              // All bags past the first one have the value erased
157              bag.set([key], value);
158              value = undefined;
159          }
160      }
161      unset(key) {
162          this.set(key, undefined);
163      }
164      clear() {
165          for (const key of this.keys) {
166              this.unset(key);
167          }
168      }
169  }
170  exports.Context = Context;
171  /**
172   * A single bag of settings
173   */
174  class Settings {
175      constructor(settings = {}, readOnly = false) {
176          this.settings = settings;
177          this.readOnly = readOnly;
178      }
179      /**
180       * Parse Settings out of CLI arguments.
181       *
182       * CLI arguments in must be accessed in the CLI code via
183       * `configuration.settings.get(['argName'])` instead of via `args.argName`.
184       *
185       * The advantage is that they can be configured via `cdk.json` and
186       * `$HOME/.cdk.json`. Arguments not listed below and accessed via this object
187       * can only be specified on the command line.
188       *
189       * @param argv the received CLI arguments.
190       * @returns a new Settings object.
191       */
192      static fromCommandLineArguments(argv) {
193          var _a;
194          const context = this.parseStringContextListToObject(argv);
195          const tags = this.parseStringTagsListToObject(expectStringList(argv.tags));
196          // Determine bundling stacks
197          let bundlingStacks;
198          if (BUNDLING_COMMANDS.includes(argv._[0])) {
199              // If we deploy, diff or synth a list of stacks exclusively we skip
200              // bundling for all other stacks.
201              bundlingStacks = argv.exclusively
202                  ? (_a = argv.STACKS) !== null && _a !== void 0 ? _a : ['*'] : ['*'];
203          }
204          else { // Skip bundling for all stacks
205              bundlingStacks = [];
206          }
207          return new Settings({
208              app: argv.app,
209              browser: argv.browser,
210              context,
211              debug: argv.debug,
212              tags,
213              language: argv.language,
214              pathMetadata: argv.pathMetadata,
215              assetMetadata: argv.assetMetadata,
216              profile: argv.profile,
217              plugin: argv.plugin,
218              requireApproval: argv.requireApproval,
219              toolkitStackName: argv.toolkitStackName,
220              toolkitBucket: {
221                  bucketName: argv.bootstrapBucketName,
222                  kmsKeyId: argv.bootstrapKmsKeyId,
223              },
224              versionReporting: argv.versionReporting,
225              staging: argv.staging,
226              output: argv.output,
227              outputsFile: argv.outputsFile,
228              progress: argv.progress,
229              bundlingStacks,
230              lookups: argv.lookups,
231              rollback: argv.rollback,
232          });
233      }
234      static mergeAll(...settings) {
235          let ret = new Settings();
236          for (const setting of settings) {
237              ret = ret.merge(setting);
238          }
239          return ret;
240      }
241      static parseStringContextListToObject(argv) {
242          const context = {};
243          for (const assignment of (argv.context || [])) {
244              const parts = assignment.split(/=(.*)/, 2);
245              if (parts.length === 2) {
246                  logging_1.debug('CLI argument context: %s=%s', parts[0], parts[1]);
247                  if (parts[0].match(/^aws:.+/)) {
248                      throw new Error(`User-provided context cannot use keys prefixed with 'aws:', but ${parts[0]} was provided.`);
249                  }
250                  context[parts[0]] = parts[1];
251              }
252              else {
253                  logging_1.warning('Context argument is not an assignment (key=value): %s', assignment);
254              }
255          }
256          return context;
257      }
258      /**
259       * Parse tags out of arguments
260       *
261       * Return undefined if no tags were provided, return an empty array if only empty
262       * strings were provided
263       */
264      static parseStringTagsListToObject(argTags) {
265          if (argTags === undefined) {
266              return undefined;
267          }
268          if (argTags.length === 0) {
269              return undefined;
270          }
271          const nonEmptyTags = argTags.filter(t => t !== '');
272          if (nonEmptyTags.length === 0) {
273              return [];
274          }
275          const tags = [];
276          for (const assignment of nonEmptyTags) {
277              const parts = assignment.split('=', 2);
278              if (parts.length === 2) {
279                  logging_1.debug('CLI argument tags: %s=%s', parts[0], parts[1]);
280                  tags.push({
281                      Key: parts[0],
282                      Value: parts[1],
283                  });
284              }
285              else {
286                  logging_1.warning('Tags argument is not an assignment (key=value): %s', assignment);
287              }
288          }
289          return tags.length > 0 ? tags : undefined;
290      }
291      async load(fileName) {
292          if (this.readOnly) {
293              throw new Error(`Can't load ${fileName}: settings object is readonly`);
294          }
295          this.settings = {};
296          const expanded = expandHomeDir(fileName);
297          if (await fs.pathExists(expanded)) {
298              this.settings = await fs.readJson(expanded);
299          }
300          // See https://github.com/aws/aws-cdk/issues/59
301          this.prohibitContextKey('default-account', fileName);
302          this.prohibitContextKey('default-region', fileName);
303          this.warnAboutContextKey('aws:', fileName);
304          return this;
305      }
306      async save(fileName) {
307          const expanded = expandHomeDir(fileName);
308          await fs.writeJson(expanded, stripTransientValues(this.settings), { spaces: 2 });
309          return this;
310      }
311      get all() {
312          return this.get([]);
313      }
314      merge(other) {
315          return new Settings(util.deepMerge(this.settings, other.settings));
316      }
317      subSettings(keyPrefix) {
318          return new Settings(this.get(keyPrefix) || {}, false);
319      }
320      makeReadOnly() {
321          return new Settings(this.settings, true);
322      }
323      clear() {
324          if (this.readOnly) {
325              throw new Error('Cannot clear(): settings are readonly');
326          }
327          this.settings = {};
328      }
329      get empty() {
330          return Object.keys(this.settings).length === 0;
331      }
332      get(path) {
333          return util.deepClone(util.deepGet(this.settings, path));
334      }
335      set(path, value) {
336          if (this.readOnly) {
337              throw new Error(`Can't set ${path}: settings object is readonly`);
338          }
339          if (path.length === 0) {
340              // deepSet can't handle this case
341              this.settings = value;
342          }
343          else {
344              util.deepSet(this.settings, path, value);
345          }
346          return this;
347      }
348      unset(path) {
349          this.set(path, undefined);
350      }
351      prohibitContextKey(key, fileName) {
352          if (!this.settings.context) {
353              return;
354          }
355          if (key in this.settings.context) {
356              // eslint-disable-next-line max-len
357              throw new Error(`The 'context.${key}' key was found in ${fs_path.resolve(fileName)}, but it is no longer supported. Please remove it.`);
358          }
359      }
360      warnAboutContextKey(prefix, fileName) {
361          if (!this.settings.context) {
362              return;
363          }
364          for (const contextKey of Object.keys(this.settings.context)) {
365              if (contextKey.startsWith(prefix)) {
366                  // eslint-disable-next-line max-len
367                  logging_1.warning(`A reserved context key ('context.${prefix}') key was found in ${fs_path.resolve(fileName)}, it might cause surprising behavior and should be removed.`);
368              }
369          }
370      }
371  }
372  exports.Settings = Settings;
373  function expandHomeDir(x) {
374      if (x.startsWith('~')) {
375          return fs_path.join(os.homedir(), x.substr(1));
376      }
377      return x;
378  }
379  /**
380   * Return all context value that are not transient context values
381   */
382  function stripTransientValues(obj) {
383      const ret = {};
384      for (const [key, value] of Object.entries(obj)) {
385          if (!isTransientValue(value)) {
386              ret[key] = value;
387          }
388      }
389      return ret;
390  }
391  /**
392   * Return whether the given value is a transient context value
393   *
394   * Values that are objects with a magic key set to a truthy value are considered transient.
395   */
396  function isTransientValue(value) {
397      return typeof value === 'object' && value !== null && value[exports.TRANSIENT_CONTEXT_KEY];
398  }
399  function expectStringList(x) {
400      if (x === undefined) {
401          return undefined;
402      }
403      if (!Array.isArray(x)) {
404          throw new Error(`Expected array, got '${x}'`);
405      }
406      const nonStrings = x.filter(e => typeof e !== 'string');
407      if (nonStrings.length > 0) {
408          throw new Error(`Expected list of strings, found ${nonStrings}`);
409      }
410      return x;
411  }
412  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0dGluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5QkFBeUI7QUFDekIsZ0NBQWdDO0FBQ2hDLCtCQUErQjtBQUUvQix1Q0FBMkM7QUFDM0MsK0JBQStCO0FBSWxCLFFBQUEsY0FBYyxHQUFHLFVBQVUsQ0FBQztBQUM1QixRQUFBLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQztBQUNyQyxRQUFBLGFBQWEsR0FBRyxhQUFhLENBQUM7QUFFM0M7O0dBRUc7QUFDVSxRQUFBLHFCQUFxQixHQUFHLGtCQUFrQixDQUFDO0FBRXhELE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQztBQUU5QixJQUFZLE9BWVg7QUFaRCxXQUFZLE9BQU87SUFDakIsb0JBQVMsQ0FBQTtJQUNULHdCQUFhLENBQUE7SUFDYix3QkFBYSxDQUFBO0lBQ2Isa0NBQXVCLENBQUE7SUFDdkIsNEJBQWlCLENBQUE7SUFDakIsOEJBQW1CLENBQUE7SUFDbkIsb0NBQXlCLENBQUE7SUFDekIsMEJBQWUsQ0FBQTtJQUNmLGdDQUFxQixDQUFBO0lBQ3JCLHdCQUFhLENBQUE7SUFDYiw4QkFBbUIsQ0FBQTtBQUNyQixDQUFDLEVBWlcsT0FBTyxHQUFQLGVBQU8sS0FBUCxlQUFPLFFBWWxCO0FBRUQsTUFBTSxpQkFBaUIsR0FBRztJQUN4QixPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxJQUFJO0lBQ1osT0FBTyxDQUFDLEtBQUs7SUFDYixPQUFPLENBQUMsVUFBVTtDQUNuQixDQUFDO0FBMEJGOztHQUVHO0FBQ0gsTUFBYSxhQUFhO0lBZ0J4QixZQUE2QixRQUE0QixFQUFFO1FBQTlCLFVBQUssR0FBTCxLQUFLLENBQXlCO1FBZnBELGFBQVEsR0FBRyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQzFCLFlBQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBRWYsa0JBQWEsR0FBRyxJQUFJLFFBQVEsQ0FBQztZ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LCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBmc19wYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IHsgVGFnIH0gZnJvbSAnLi9jZGstdG9vbGtpdCc7XG5pbXBvcnQgeyBkZWJ1Zywgd2FybmluZyB9IGZyb20gJy4vbG9nZ2luZyc7XG5pbXBvcnQgKiBhcyB1dGlsIGZyb20gJy4vdXRpbCc7XG5cbmV4cG9ydCB0eXBlIFNldHRpbmdzTWFwID0ge1trZXk6IHN0cmluZ106IGFueX07XG5cbmV4cG9ydCBjb25zdCBQUk9KRUNUX0NPTkZJRyA9ICdjZGsuanNvbic7XG5leHBvcnQgY29uc3QgUFJPSkVDVF9DT05URVhUID0gJ2Nkay5jb250ZXh0Lmpzb24nO1xuZXhwb3J0IGNvbnN0IFVTRVJfREVGQVVMVFMgPSAnfi8uY2RrLmpzb24nO1xuXG4vKipcbiAqIElmIGEgY29udGV4dCB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCB0aGlzIGtleSBzZXQgdG8gYSB0cnV0aHkgdmFsdWUsIGl0IHdvbid0IGJlIHNhdmVkIHRvIGNkay5jb250ZXh0Lmpzb25cbiAqL1xuZXhwb3J0IGNvbnN0IFRSQU5TSUVOVF9DT05URVhUX0tFWSA9ICckZG9udFNhdmVDb250ZXh0JztcblxuY29uc3QgQ09OVEVYVF9LRVkgPSAnY29udGV4dCc7XG5cbmV4cG9ydCBlbnVtIENvbW1hbmQge1xuICBMUyA9ICdscycsXG4gIExJU1QgPSAnbGlzdCcsXG4gIERJRkYgPSAnZGlmZicsXG4gIEJPT1RTVFJBUCA9ICdib290c3RyYXAnLFxuICBERVBMT1kgPSAnZGVwbG95JyxcbiAgREVTVFJPWSA9ICdkZXN0cm95JyxcbiAgU1lOVEhFU0laRSA9ICdzeW50aGVzaXplJyxcbiAgU1lOVEggPSAnc3ludGgnLFxuICBNRVRBREFUQSA9ICdtZXRhZGF0YScsXG4gIElOSVQgPSAnaW5pdCcsXG4gIFZFUlNJT04gPSAndmVyc2lvbicsXG59XG5cbmNvbnN0IEJVTkRMSU5HX0NPTU1BTkRTID0gW1xuICBDb21tYW5kLkRFUExPWSxcbiAgQ29tbWFuZC5ESUZGLFxuICBDb21tYW5kLlNZTlRILFxuICBDb21tYW5kLlNZTlRIRVNJWkUsXG5dO1xuXG5leHBvcnQgdHlwZSBBcmd1bWVudHMgPSB7XG4gIHJlYWRvbmx5IF86IFtDb21tYW5kLCAuLi5zdHJpbmdbXV07XG4gIHJlYWRvbmx5IGV4Y2x1c2l2ZWx5PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgU1RBQ0tTPzogc3RyaW5nW107XG4gIHJlYWRvbmx5IGxvb2t1cHM/OiBib29sZWFuO1xuICByZWFkb25seSBbbmFtZTogc3RyaW5nXTogdW5rbm93bjtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29uZmlndXJhdGlvblByb3BzIHtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gcGFzc2VkIHZpYSBjb21tYW5kIGxpbmUgYXJndW1lbnRzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm90aGluZyBwYXNzZWRcbiAgICovXG4gIHJlYWRvbmx5IGNvbW1hbmRMaW5lQXJndW1lbnRzPzogQXJndW1lbnRzO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0byB1c2UgY29udGV4dCBmcm9tIGAuY2RrLmpzb25gIGluIHVzZXIgaG9tZSBkaXJlY3RvcnlcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVhZFVzZXJDb250ZXh0PzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBbGwgc291cmNlcyBvZiBzZXR0aW5ncyBjb21iaW5lZFxuICovXG5leHBvcnQgY2xhc3MgQ29uZmlndXJhdGlvbiB7XG4gIHB1YmxpYyBzZXR0aW5ncyA9IG5ldyBTZXR0aW5ncygpO1xuICBwdWJsaWMgY29udGV4dCA9IG5ldyBDb250ZXh0KCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRDb25maWcgPSBuZXcgU2V0dGluZ3Moe1xuICAgIHZlcnNpb25SZXBvcnRpbmc6IHRydWUsXG4gICAgcGF0aE1ldGFkYXRhOiB0cnVlLFxuICAgIG91dHB1dDogJ2Nkay5vdXQnLFxuICB9KTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvbW1hbmRMaW5lQXJndW1lbnRzOiBTZXR0aW5ncztcbiAgcHJpdmF0ZSByZWFkb25seSBjb21tYW5kTGluZUNvbnRleHQ6IFNldHRpbmdzO1xuICBwcml2YXRlIF9wcm9qZWN0Q29uZmlnPzogU2V0dGluZ3M7XG4gIHByaXZhdGUgX3Byb2plY3RDb250ZXh0PzogU2V0dGluZ3M7XG4gIHByaXZhdGUgbG9hZGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwcm9wczogQ29uZmlndXJhdGlvblByb3BzID0ge30pIHtcbiAgICB0aGlzLmNvbW1hbmRMaW5lQXJndW1lbnRzID0gcHJvcHMuY29tbWFuZExpbmVBcmd1bWVudHNcbiAgICAgID8gU2V0dGluZ3MuZnJvbUNvbW1hbmRMaW5lQXJndW1lbnRzKHByb3BzLmNvbW1hbmRMaW5lQXJndW1lbnRzKVxuICAgICAgOiBuZXcgU2V0dGluZ3MoKTtcbiAgICB0aGlzLmNvbW1hbmRMaW5lQ29udGV4dCA9IHRoaXMuY29tbWFuZExpbmVBcmd1bWVudHMuc3ViU2V0dGluZ3MoW0NPTlRFWFRfS0VZXSkubWFrZVJlYWRPbmx5KCk7XG4gIH1cblxuICBwcml2YXRlIGdldCBwcm9qZWN0Q29uZmlnKCkge1xuICAgIGlmICghdGhpcy5fcHJvamVjdENvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCcjbG9hZCBoYXMgbm90IGJlZW4gY2FsbGVkIHlldCEnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3Byb2plY3RDb25maWc7XG4gIH1cblxuICBwcml2YXRlIGdldCBwcm9qZWN0Q29udGV4dCgpIHtcbiAgICBpZiAoIXRoaXMuX3Byb2plY3RDb250ZXh0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJyNsb2FkIGhhcyBub3QgYmVlbiBjYWxsZWQgeWV0IScpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcHJvamVjdENvbnRleHQ7XG4gIH1cblxuICAvKipcbiAgICogTG9hZCBhbGwgY29uZmlnXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbG9hZCgpOiBQcm9taXNlPHRoaXM+IHtcbiAgICBjb25zdCB1c2VyQ29uZmlnID0gYXdhaXQgbG9hZEFuZExvZyhVU0VSX0RFRkFVTFRTKTtcbiAgICB0aGlzLl9wcm9qZWN0Q29uZmlnID0gYXdhaXQgbG9hZEFuZExvZyhQUk9KRUNUX0NPTkZJRyk7XG4gICAgdGhpcy5fcHJvamVjdENvbnRleHQgPSBhd2FpdCBsb2FkQW5kTG9nKFBST0pFQ1RfQ09OVEVYVCk7XG5cbiAgICBjb25zdCByZWFkVXNlckNvbnRleHQgPSB0aGlzLnByb3BzLnJlYWRVc2VyQ29udGV4dCA/PyB0cnVlO1xuXG4gICAgY29uc3QgY29udGV4dFNvdXJjZXMgPSBbXG4gICAgICB0aGlzLmNvbW1hbmRMaW5lQ29udGV4dCxcbiAgICAgIHRoaXMucHJvamVjdENvbmZpZy5zdWJTZXR0aW5ncyhbQ09OVEVYVF9LRVldKS5tYWtlUmVhZE9ubHkoKSxcbiAgICAgIHRoaXMucHJvamVjdENvbnRleHQsXG4gICAgXTtcbiAgICBpZiAocmVhZFVzZXJDb250ZXh0KSB7XG4gICAgICBjb250ZXh0U291cmNlcy5wdXNoKHVzZXJDb25maWcuc3ViU2V0dGluZ3MoW0NPTlRFWFRfS0VZXSkubWFrZVJlYWRPbmx5KCkpO1xuICAgIH1cblxuICAgIHRoaXMuY29udGV4dCA9IG5ldyBDb250ZXh0KC4uLmNvbnRleHRTb3VyY2VzKTtcblxuICAgIC8vIEJ1aWxkIHNldHRpbmdzIGZyb20gd2hhdCdzIGxlZnRcbiAgICB0aGlzLnNldHRpbmdzID0gdGhpcy5kZWZhdWx0Q29uZmlnXG4gICAgICAubWVyZ2UodXNlckNvbmZpZylcbiAgICAgIC5tZXJnZSh0aGlzLnByb2plY3RDb25maWcpXG4gICAgICAubWVyZ2UodGhpcy5jb21tYW5kTGluZUFyZ3VtZW50cylcbiAgICAgIC5tYWtlUmVhZE9ubHkoKTtcblxuICAgIGRlYnVnKCdtZXJnZWQgc2V0dGluZ3M6JywgdGhpcy5zZXR0aW5ncy5hbGwpO1xuXG4gICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSB0aGUgcHJvamVjdCBjb250ZXh0XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc2F2ZUNvbnRleHQoKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgaWYgKCF0aGlzLmxvYWRlZCkgeyByZXR1cm4gdGhpczsgfSAvLyBBdm9pZCBvdmVyd3JpdGluZyBmaWxlcyB3aXRoIG5vdGhpbmdcblxuICAgIGF3YWl0IHRoaXMucHJvamVjdENvbnRleHQuc2F2ZShQUk9KRUNUX0NPTlRFWFQpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZEFuZExvZyhmaWxlTmFtZTogc3RyaW5nKTogUHJvbWlzZTxTZXR0aW5ncz4ge1xuICBjb25zdCByZXQgPSBuZXcgU2V0dGluZ3MoKTtcbiAgYXdhaXQgcmV0LmxvYWQoZmlsZU5hbWUpO1xuICBpZiAoIXJldC5lbXB0eSkge1xuICAgIGRlYnVnKGZpbGVOYW1lICsgJzonLCBKU09OLnN0cmluZ2lmeShyZXQuYWxsLCB1bmRlZmluZWQsIDIpKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIENsYXNzIHRoYXQgc3VwcG9ydHMgb3ZlcmxheWluZyBwcm9wZXJ0eSBiYWdzXG4gKlxuICogUmVhZHMgY29tZSBmcm9tIHRoZSBmaXJzdCBwcm9wZXJ0eSBiYWcgdGhhdCBjYW4gaGFzIHRoZSBnaXZlbiBrZXksXG4gKiB3cml0ZXMgZ28gdG8gdGhlIGZpcnN0IHByb3BlcnR5IGJhZyB0aGF0IGlzIG5vdCByZWFkb25seS4gQSB3cml0ZVxuICogd2lsbCByZW1vdmUgdGhlIHZhbHVlIGZyb20gYWxsIHByb3BlcnR5IGJhZ3MgYWZ0ZXIgdGhlIGZpcnN0XG4gKiB3cml0YWJsZSBvbmUuXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250ZXh0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBiYWdzOiBTZXR0aW5nc1tdO1xuXG4gIGNvbnN0cnVjdG9yKC4uLmJhZ3M6IFNldHRpbmdzW10pIHtcbiAgICB0aGlzLmJhZ3MgPSBiYWdzLmxlbmd0aCA+IDAgPyBiYWdzIDogW25ldyBTZXR0aW5ncygpXTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQga2V5cygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuYWxsKTtcbiAgfVxuXG4gIHB1YmxpYyBoYXMoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5rZXlzLmluZGV4T2Yoa2V5KSA+IC0xO1xuICB9XG5cbiAgcHVibGljIGdldCBhbGwoKToge1trZXk6IHN0cmluZ106IGFueX0ge1xuICAgIGxldCByZXQgPSBuZXcgU2V0dGluZ3MoKTtcblxuICAgIC8vIEluIHJldmVyc2Ugb3JkZXIgc28ga2V5cyB0byB0aGUgbGVmdCBvdmVyd3JpdGUga2V5cyB0byB0aGUgcmlnaHQgb2YgdGhlbVxuICAgIGZvciAoY29uc3QgYmFnIG9mIFsuLi50aGlzLmJhZ3NdLnJldmVyc2UoKSkge1xuICAgICAgcmV0ID0gcmV0Lm1lcmdlKGJhZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldC5hbGw7XG4gIH1cblxuICBwdWJsaWMgZ2V0KGtleTogc3RyaW5nKTogYW55IHtcbiAgICBmb3IgKGNvbnN0IGJhZyBvZiB0aGlzLmJhZ3MpIHtcbiAgICAgIGNvbnN0IHYgPSBiYWcuZ2V0KFtrZXldKTtcbiAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIHsgcmV0dXJuIHY7IH1cbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHB1YmxpYyBzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgICBmb3IgKGNvbnN0IGJhZyBvZiB0aGlzLmJhZ3MpIHtcbiAgICAgIGlmIChiYWcucmVhZE9ubHkpIHsgY29udGludWU7IH1cblxuICAgICAgLy8gQWxsIGJhZ3MgcGFzdCB0aGUgZmlyc3Qgb25lIGhhdmUgdGhlIHZhbHVlIGVyYXNlZFxuICAgICAgYmFnLnNldChba2V5XSwgdmFsdWUpO1xuICAgICAgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHVuc2V0KGtleTogc3RyaW5nKSB7XG4gICAgdGhpcy5zZXQoa2V5LCB1bmRlZmluZWQpO1xuICB9XG5cbiAgcHVibGljIGNsZWFyKCkge1xuICAgIGZvciAoY29uc3Qga2V5IG9mIHRoaXMua2V5cykge1xuICAgICAgdGhpcy51bnNldChrZXkpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEEgc2luZ2xlIGJhZyBvZiBzZXR0aW5nc1xuICovXG5leHBvcnQgY2xhc3MgU2V0dGluZ3Mge1xuXG4gIC8qKlxuICAgKiBQYXJzZSBTZXR0aW5ncyBvdXQgb2YgQ0xJIGFyZ3VtZW50cy5cbiAgICpcbiAgICogQ0xJIGFyZ3VtZW50cyBpbiBtdXN0IGJlIGFjY2Vzc2VkIGluIHRoZSBDTEkgY29kZSB2aWFcbiAgICogYGNvbmZpZ3VyYXRpb24uc2V0dGluZ3MuZ2V0KFsnYXJnTmFtZSddKWAgaW5zdGVhZCBvZiB2aWEgYGFyZ3MuYXJnTmFtZWAuXG4gICAqXG4gICAqIFRoZSBhZHZhbnRhZ2UgaXMgdGhhdCB0aGV5IGNhbiBiZSBjb25maWd1cmVkIHZpYSBgY2RrLmpzb25gIGFuZFxuICAgKiBgJEhPTUUvLmNkay5qc29uYC4gQXJndW1lbnRzIG5vdCBsaXN0ZWQgYmVsb3cgYW5kIGFjY2Vzc2VkIHZpYSB0aGlzIG9iamVjdFxuICAgKiBjYW4gb25seSBiZSBzcGVjaWZpZWQgb24gdGhlIGNvbW1hbmQgbGluZS5cbiAgICpcbiAgICogQHBhcmFtIGFyZ3YgdGhlIHJlY2VpdmVkIENMSSBhcmd1bWVudHMuXG4gICAqIEByZXR1cm5zIGEgbmV3IFNldHRpbmdzIG9iamVjdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUNvbW1hbmRMaW5lQXJndW1lbnRzKGFyZ3Y6IEFyZ3VtZW50cyk6IFNldHRpbmdzIHtcbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5wYXJzZVN0cmluZ0NvbnRleHRMaXN0VG9PYmplY3QoYXJndik7XG4gICAgY29uc3QgdGFncyA9IHRoaXMucGFyc2VTdHJpbmdUYWdzTGlzdFRvT2JqZWN0KGV4cGVjdFN0cmluZ0xpc3QoYXJndi50YWdzKSk7XG5cbiAgICAvLyBEZXRlcm1pbmUgYnVuZGxpbmcgc3RhY2tzXG4gICAgbGV0IGJ1bmRsaW5nU3RhY2tzOiBzdHJpbmdbXTtcbiAgICBpZiAoQlVORExJTkdfQ09NTUFORFMuaW5jbHVkZXMoYXJndi5fWzBdKSkge1xuICAgIC8vIElmIHdlIGRlcGxveSwgZGlmZiBvciBzeW50aCBhIGxpc3Qgb2Ygc3RhY2tzIGV4Y2x1c2l2ZWx5IHdlIHNraXBcbiAgICAvLyBidW5kbGluZyBmb3IgYWxsIG90aGVyIHN0YWNrcy5cbiAgICAgIGJ1bmRsaW5nU3RhY2tzID0gYXJndi5leGNsdXNpdmVseVxuICAgICAgICA/IGFyZ3YuU1RBQ0tTID8/IFsnKiddXG4gICAgICAgIDogWycqJ107XG4gICAgfSBlbHNlIHsgLy8gU2tpcCBidW5kbGluZyBmb3IgYWxsIHN0YWNrc1xuICAgICAgYnVuZGxpbmdTdGFja3MgPSBbXTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFNldHRpbmdzKHtcbiAgICAgIGFwcDogYXJndi5hcHAsXG4gICAgICBicm93c2VyOiBhcmd2LmJyb3dzZXIsXG4gICAgICBjb250ZXh0LFxuICAgICAgZGVidWc6IGFyZ3YuZGVidWcsXG4gICAgICB0YWdzLFxuICAgICAgbGFuZ3VhZ2U6IGFyZ3YubGFuZ3VhZ2UsXG4gICAgICBwYXRoTWV0YWRhdGE6IGFyZ3YucGF0aE1ldGFkYXRhLFxuICAgICAgYXNzZXRNZXRhZGF0YTogYXJndi5hc3NldE1ldGFkYXRhLFxuICAgICAgcHJvZmlsZTogYXJndi5wcm9maWxlLFxuICAgICAgcGx1Z2luOiBhcmd2LnBsdWdpbixcbiAgICAgIHJlcXVpcmVBcHByb3ZhbDogYXJndi5yZXF1aXJlQXBwcm92YWwsXG4gICAgICB0b29sa2l0U3RhY2tOYW1lOiBhcmd2LnRvb2xraXRTdGFja05hbWUsXG4gICAgICB0b29sa2l0QnVja2V0OiB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IGFyZ3YuYm9vdHN0cmFwQnVja2V0TmFtZSxcbiAgICAgICAga21zS2V5SWQ6IGFyZ3YuYm9vdHN0cmFwS21zS2V5SWQsXG4gICAgICB9LFxuICAgICAgdmVyc2lvblJlcG9ydGluZzogYXJndi52ZXJzaW9uUmVwb3J0aW5nLFxuICAgICAgc3RhZ2luZzogYXJndi5zdGFnaW5nLFxuICAgICAgb3V0cHV0OiBhcmd2Lm91dHB1dCxcbiAgICAgIG91dHB1dHNGaWxlOiBhcmd2Lm91dHB1dHNGaWxlLFxuICAgICAgcHJvZ3Jlc3M6IGFyZ3YucHJvZ3Jlc3MsXG4gICAgICBidW5kbGluZ1N0YWNrcyxcbiAgICAgIGxvb2t1cHM6IGFyZ3YubG9va3VwcyxcbiAgICAgIHJvbGxiYWNrOiBhcmd2LnJvbGxiYWNrLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBtZXJnZUFsbCguLi5zZXR0aW5nczogU2V0dGluZ3NbXSk6IFNldHRpbmdzIHtcbiAgICBsZXQgcmV0ID0gbmV3IFNldHRpbmdzKCk7XG4gICAgZm9yIChjb25zdCBzZXR0aW5nIG9mIHNldHRpbmdzKSB7XG4gICAgICByZXQgPSByZXQubWVyZ2Uoc2V0dGluZyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVN0cmluZ0NvbnRleHRMaXN0VG9PYmplY3QoYXJndjogQXJndW1lbnRzKTogYW55IHtcbiAgICBjb25zdCBjb250ZXh0OiBhbnkgPSB7fTtcblxuICAgIGZvciAoY29uc3QgYXNzaWdubWVudCBvZiAoKGFyZ3YgYXMgYW55KS5jb250ZXh0IHx8IFtdKSkge1xuICAgICAgY29uc3QgcGFydHMgPSBhc3NpZ25tZW50LnNwbGl0KC89KC4qKS8sIDIpO1xuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICBkZWJ1ZygnQ0xJIGFyZ3VtZW50IGNvbnRleHQ6ICVzPSVzJywgcGFydHNbMF0sIHBhcnRzWzFdKTtcbiAgICAgICAgaWYgKHBhcnRzWzBdLm1hdGNoKC9eYXdzOi4rLykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVzZXItcHJvdmlkZWQgY29udGV4dCBjYW5ub3QgdXNlIGtleXMgcHJlZml4ZWQgd2l0aCAnYXdzOicsIGJ1dCAke3BhcnRzWzBdfSB3YXMgcHJvdmlkZWQuYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGV4dFtwYXJ0c1swXV0gPSBwYXJ0c1sxXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHdhcm5pbmcoJ0NvbnRleHQgYXJndW1lbnQgaXMgbm90IGFuIGFzc2lnbm1lbnQgKGtleT12YWx1ZSk6ICVzJywgYXNzaWdubWVudCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb250ZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIHRhZ3Mgb3V0IG9mIGFyZ3VtZW50c1xuICAgKlxuICAgKiBSZXR1cm4gdW5kZWZpbmVkIGlmIG5vIHRhZ3Mgd2VyZSBwcm92aWRlZCwgcmV0dXJuIGFuIGVtcHR5IGFycmF5IGlmIG9ubHkgZW1wdHlcbiAgICogc3RyaW5ncyB3ZXJlIHByb3ZpZGVkXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBwYXJzZVN0cmluZ1RhZ3NMaXN0VG9PYmplY3QoYXJnVGFnczogc3RyaW5nW10gfCB1bmRlZmluZWQpOiBUYWdbXSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKGFyZ1RhZ3MgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gICAgaWYgKGFyZ1RhZ3MubGVuZ3RoID09PSAwKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgICBjb25zdCBub25FbXB0eVRhZ3MgPSBhcmdUYWdzLmZpbHRlcih0ID0+IHQgIT09ICcnKTtcbiAgICBpZiAobm9uRW1wdHlUYWdzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gW107IH1cblxuICAgIGNvbnN0IHRhZ3M6IFRhZ1tdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGFzc2lnbm1lbnQgb2Ygbm9uRW1wdHlUYWdzKSB7XG4gICAgICBjb25zdCBwYXJ0cyA9IGFzc2lnbm1lbnQuc3BsaXQoJz0nLCAyKTtcbiAgICAgIGlmIChwYXJ0cy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgZGVidWcoJ0NMSSBhcmd1bWVudCB0YWdzOiAlcz0lcycsIHBhcnRzWzBdLCBwYXJ0c1sxXSk7XG4gICAgICAgIHRhZ3MucHVzaCh7XG4gICAgICAgICAgS2V5OiBwYXJ0c1swXSxcbiAgICAgICAgICBWYWx1ZTogcGFydHNbMV0sXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2FybmluZygnVGFncyBhcmd1bWVudCBpcyBub3QgYW4gYXNzaWdubWVudCAoa2V5PXZhbHVlKTogJXMnLCBhc3NpZ25tZW50KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRhZ3MubGVuZ3RoID4gMCA/IHRhZ3MgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNldHRpbmdzOiBTZXR0aW5nc01hcCA9IHt9LCBwdWJsaWMgcmVhZG9ubHkgcmVhZE9ubHkgPSBmYWxzZSkge31cblxuICBwdWJsaWMgYXN5bmMgbG9hZChmaWxlTmFtZTogc3RyaW5nKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgbG9hZCAke2ZpbGVOYW1lfTogc2V0dGluZ3Mgb2JqZWN0IGlzIHJlYWRvbmx5YCk7XG4gICAgfVxuICAgIHRoaXMuc2V0dGluZ3MgPSB7fTtcblxuICAgIGNvbnN0IGV4cGFuZGVkID0gZXhwYW5kSG9tZURpcihmaWxlTmFtZSk7XG4gICAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoZXhwYW5kZWQpKSB7XG4gICAgICB0aGlzLnNldHRpbmdzID0gYXdhaXQgZnMucmVhZEpzb24oZXhwYW5kZWQpO1xuICAgIH1cblxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvaXNzdWVzLzU5XG4gICAgdGhpcy5wcm9oaWJpdENvbnRleHRLZXkoJ2RlZmF1bHQtYWNjb3VudCcsIGZpbGVOYW1lKTtcbiAgICB0aGlzLnByb2hpYml0Q29udGV4dEtleSgnZGVmYXVsdC1yZWdpb24nLCBmaWxlTmFtZSk7XG4gICAgdGhpcy53YXJuQWJvdXRDb250ZXh0S2V5KCdhd3M6JywgZmlsZU5hbWUpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgc2F2ZShmaWxlTmFtZTogc3RyaW5nKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgY29uc3QgZXhwYW5kZWQgPSBleHBhbmRIb21lRGlyKGZpbGVOYW1lKTtcbiAgICBhd2FpdCBmcy53cml0ZUpzb24oZXhwYW5kZWQsIHN0cmlwVHJhbnNpZW50VmFsdWVzKHRoaXMuc2V0dGluZ3MpLCB7IHNwYWNlczogMiB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYWxsKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFtdKTtcbiAgfVxuXG4gIHB1YmxpYyBtZXJnZShvdGhlcjogU2V0dGluZ3MpOiBTZXR0aW5ncyB7XG4gICAgcmV0dXJuIG5ldyBTZXR0aW5ncyh1dGlsLmRlZXBNZXJnZSh0aGlzLnNldHRpbmdzLCBvdGhlci5zZXR0aW5ncykpO1xuICB9XG5cbiAgcHVibGljIHN1YlNldHRpbmdzKGtleVByZWZpeDogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gbmV3IFNldHRpbmdzKHRoaXMuZ2V0KGtleVByZWZpeCkgfHwge30sIGZhbHNlKTtcbiAgfVxuXG4gIHB1YmxpYyBtYWtlUmVhZE9ubHkoKTogU2V0dGluZ3Mge1xuICAgIHJldHVybiBuZXcgU2V0dGluZ3ModGhpcy5zZXR0aW5ncywgdHJ1ZSk7XG4gIH1cblxuICBwdWJsaWMgY2xlYXIoKSB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNsZWFyKCk6IHNldHRpbmdzIGFyZSByZWFkb25seScpO1xuICAgIH1cbiAgICB0aGlzLnNldHRpbmdzID0ge307XG4gIH1cblxuICBwdWJsaWMgZ2V0IGVtcHR5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnNldHRpbmdzKS5sZW5ndGggPT09IDA7XG4gIH1cblxuICBwdWJsaWMgZ2V0KHBhdGg6IHN0cmluZ1tdKTogYW55IHtcbiAgICByZXR1cm4gdXRpbC5kZWVwQ2xvbmUodXRpbC5kZWVwR2V0KHRoaXMuc2V0dGluZ3MsIHBhdGgpKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXQocGF0aDogc3RyaW5nW10sIHZhbHVlOiBhbnkpOiBTZXR0aW5ncyB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3Qgc2V0ICR7cGF0aH06IHNldHRpbmdzIG9iamVjdCBpcyByZWFkb25seWApO1xuICAgIH1cbiAgICBpZiAocGF0aC5sZW5ndGggPT09IDApIHtcbiAgICAgIC8vIGRlZXBTZXQgY2FuJ3QgaGFuZGxlIHRoaXMgY2FzZVxuICAgICAgdGhpcy5zZXR0aW5ncyA9IHZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB1dGlsLmRlZXBTZXQodGhpcy5zZXR0aW5ncywgcGF0aCwgdmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyB1bnNldChwYXRoOiBzdHJpbmdbXSkge1xuICAgIHRoaXMuc2V0KHBhdGgsIHVuZGVmaW5lZCk7XG4gIH1cblxuICBwcml2YXRlIHByb2hpYml0Q29udGV4dEtleShrZXk6IHN0cmluZywgZmlsZU5hbWU6IHN0cmluZykge1xuICAgIGlmICghdGhpcy5zZXR0aW5ncy5jb250ZXh0KSB7IHJldHVybjsgfVxuICAgIGlmIChrZXkgaW4gdGhpcy5zZXR0aW5ncy5jb250ZXh0KSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgJ2NvbnRleHQuJHtrZXl9JyBrZXkgd2FzIGZvdW5kIGluICR7ZnNfcGF0aC5yZXNvbHZlKGZpbGVOYW1lKX0sIGJ1dCBpdCBpcyBubyBsb25nZXIgc3VwcG9ydGVkLiBQbGVhc2UgcmVtb3ZlIGl0LmApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgd2FybkFib3V0Q29udGV4dEtleShwcmVmaXg6IHN0cmluZywgZmlsZU5hbWU6IHN0cmluZykge1xuICAgIGlmICghdGhpcy5zZXR0aW5ncy5jb250ZXh0KSB7IHJldHVybjsgfVxuICAgIGZvciAoY29uc3QgY29udGV4dEtleSBvZiBPYmplY3Qua2V5cyh0aGlzLnNldHRpbmdzLmNvbnRleHQpKSB7XG4gICAgICBpZiAoY29udGV4dEtleS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgICAgd2FybmluZyhgQSByZXNlcnZlZCBjb250ZXh0IGtleSAoJ2NvbnRleHQuJHtwcmVmaXh9Jykga2V5IHdhcyBmb3VuZCBpbiAke2ZzX3BhdGgucmVzb2x2ZShmaWxlTmFtZSl9LCBpdCBtaWdodCBjYXVzZSBzdXJwcmlzaW5nIGJlaGF2aW9yIGFuZCBzaG91bGQgYmUgcmVtb3ZlZC5gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZXhwYW5kSG9tZURpcih4OiBzdHJpbmcpIHtcbiAgaWYgKHguc3RhcnRzV2l0aCgnficpKSB7XG4gICAgcmV0dXJuIGZzX3BhdGguam9pbihvcy5ob21lZGlyKCksIHguc3Vic3RyKDEpKTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuLyoqXG4gKiBSZXR1cm4gYWxsIGNvbnRleHQgdmFsdWUgdGhhdCBhcmUgbm90IHRyYW5zaWVudCBjb250ZXh0IHZhbHVlc1xuICovXG5mdW5jdGlvbiBzdHJpcFRyYW5zaWVudFZhbHVlcyhvYmo6IHtba2V5OiBzdHJpbmddOiBhbnl9KSB7XG4gIGNvbnN0IHJldDogYW55ID0ge307XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHtcbiAgICBpZiAoIWlzVHJhbnNpZW50VmFsdWUodmFsdWUpKSB7XG4gICAgICByZXRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIHRoZSBnaXZlbiB2YWx1ZSBpcyBhIHRyYW5zaWVudCBjb250ZXh0IHZhbHVlXG4gKlxuICogVmFsdWVzIHRoYXQgYXJlIG9iamVjdHMgd2l0aCBhIG1hZ2ljIGtleSBzZXQgdG8gYSB0cnV0aHkgdmFsdWUgYXJlIGNvbnNpZGVyZWQgdHJhbnNpZW50LlxuICovXG5mdW5jdGlvbiBpc1RyYW5zaWVudFZhbHVlKHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgKHZhbHVlIGFzIGFueSlbVFJBTlNJRU5UX0NPTlRFWFRfS0VZXTtcbn1cblxuZnVuY3Rpb24gZXhwZWN0U3RyaW5nTGlzdCh4OiB1bmtub3duKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICBpZiAoeCA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgaWYgKCFBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhcnJheSwgZ290ICcke3h9J2ApO1xuICB9XG4gIGNvbnN0IG5vblN0cmluZ3MgPSB4LmZpbHRlcihlID0+IHR5cGVvZiBlICE9PSAnc3RyaW5nJyk7XG4gIGlmIChub25TdHJpbmdzLmxlbmd0aCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGxpc3Qgb2Ygc3RyaW5ncywgZm91bmQgJHtub25TdHJpbmdzfWApO1xuICB9XG4gIHJldHVybiB4O1xufVxuIl19