UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

376 lines 54.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.printAvailableTemplates = exports.availableInitLanguages = exports.availableInitTemplates = exports.InitTemplate = exports.cliInit = void 0; const childProcess = require("child_process"); const path = require("path"); const cxapi = require("@aws-cdk/cx-api"); const chalk = require("chalk"); const fs = require("fs-extra"); const init_hooks_1 = require("./init-hooks"); const logging_1 = require("./logging"); const directories_1 = require("./util/directories"); const version_range_1 = require("./util/version-range"); /* eslint-disable @typescript-eslint/no-var-requires */ // Packages don't have @types module // eslint-disable-next-line @typescript-eslint/no-require-imports const camelCase = require('camelcase'); // eslint-disable-next-line @typescript-eslint/no-require-imports const decamelize = require('decamelize'); /** * Initialize a CDK package in the current directory */ async function cliInit(options) { const canUseNetwork = options.canUseNetwork ?? true; const generateOnly = options.generateOnly ?? false; const workDir = options.workDir ?? process.cwd(); if (!options.type && !options.language) { await printAvailableTemplates(); return; } const type = options.type || 'default'; // "default" is the default type (and maps to "app") const template = (await availableInitTemplates()).find(t => t.hasName(type)); if (!template) { await printAvailableTemplates(options.language); throw new Error(`Unknown init template: ${type}`); } if (!options.language && template.languages.length === 1) { const language = template.languages[0]; (0, logging_1.warning)(`No --language was provided, but '${type}' supports only '${language}', so defaulting to --language=${language}`); } if (!options.language) { (0, logging_1.print)(`Available languages for ${chalk.green(type)}: ${template.languages.map(l => chalk.blue(l)).join(', ')}`); throw new Error('No language was selected'); } await initializeProject(template, options.language, canUseNetwork, generateOnly, workDir, options.stackName); } exports.cliInit = cliInit; /** * Returns the name of the Python executable for this OS */ function pythonExecutable() { let python = 'python3'; if (process.platform === 'win32') { python = 'python'; } return python; } const INFO_DOT_JSON = 'info.json'; class InitTemplate { static async fromName(templatesDir, name) { const basePath = path.join(templatesDir, name); const languages = (await listDirectory(basePath)); const info = await fs.readJson(path.join(basePath, INFO_DOT_JSON)); return new InitTemplate(basePath, name, languages, info); } constructor(basePath, name, languages, info) { this.basePath = basePath; this.name = name; this.languages = languages; this.aliases = new Set(); this.description = info.description; for (const alias of info.aliases || []) { this.aliases.add(alias); } } /** * @param name the name that is being checked * @returns ``true`` if ``name`` is the name of this template or an alias of it. */ hasName(name) { return name === this.name || this.aliases.has(name); } /** * Creates a new instance of this ``InitTemplate`` for a given language to a specified folder. * * @param language the language to instantiate this template with * @param targetDirectory the directory where the template is to be instantiated into */ async install(language, targetDirectory, stackName) { if (this.languages.indexOf(language) === -1) { (0, logging_1.error)(`The ${chalk.blue(language)} language is not supported for ${chalk.green(this.name)} ` + `(it supports: ${this.languages.map(l => chalk.blue(l)).join(', ')})`); throw new Error(`Unsupported language: ${language}`); } const projectInfo = { name: decamelize(path.basename(path.resolve(targetDirectory))), stackName, }; const sourceDirectory = path.join(this.basePath, language); await this.installFiles(sourceDirectory, targetDirectory, language, projectInfo); await this.applyFutureFlags(targetDirectory); await (0, init_hooks_1.invokeBuiltinHooks)({ targetDirectory, language, templateName: this.name }, { substitutePlaceholdersIn: async (...fileNames) => { for (const fileName of fileNames) { const fullPath = path.join(targetDirectory, fileName); const template = await fs.readFile(fullPath, { encoding: 'utf-8' }); await fs.writeFile(fullPath, this.expand(template, language, projectInfo)); } }, placeholder: (ph) => this.expand(`%${ph}%`, language, projectInfo), }); } async installFiles(sourceDirectory, targetDirectory, language, project) { for (const file of await fs.readdir(sourceDirectory)) { const fromFile = path.join(sourceDirectory, file); const toFile = path.join(targetDirectory, this.expand(file, language, project)); if ((await fs.stat(fromFile)).isDirectory()) { await fs.mkdir(toFile); await this.installFiles(fromFile, toFile, language, project); continue; } else if (file.match(/^.*\.template\.[^.]+$/)) { await this.installProcessed(fromFile, toFile.replace(/\.template(\.[^.]+)$/, '$1'), language, project); continue; } else if (file.match(/^.*\.hook\.(d.)?[^.]+$/)) { // Ignore continue; } else { await fs.copy(fromFile, toFile); } } } async installProcessed(templatePath, toFile, language, project) { const template = await fs.readFile(templatePath, { encoding: 'utf-8' }); await fs.writeFile(toFile, this.expand(template, language, project)); } expand(template, language, project) { // eslint-disable-next-line @typescript-eslint/no-require-imports const manifest = require(path.join((0, directories_1.rootDir)(), 'package.json')); const MATCH_VER_BUILD = /\+[a-f0-9]+$/; // Matches "+BUILD" in "x.y.z-beta+BUILD" const cdkVersion = manifest.version.replace(MATCH_VER_BUILD, ''); let constructsVersion = manifest.devDependencies.constructs.replace(MATCH_VER_BUILD, ''); switch (language) { case 'java': case 'csharp': case 'fsharp': constructsVersion = (0, version_range_1.rangeFromSemver)(constructsVersion, 'bracket'); break; case 'python': constructsVersion = (0, version_range_1.rangeFromSemver)(constructsVersion, 'pep'); break; } return template.replace(/%name%/g, project.name) .replace(/%stackname%/, project.stackName ?? '%name.PascalCased%Stack') .replace(/%PascalNameSpace%/, project.stackName ? camelCase(project.stackName + 'Stack', { pascalCase: true }) : '%name.PascalCased%') .replace(/%PascalStackProps%/, project.stackName ? (camelCase(project.stackName, { pascalCase: true }) + 'StackProps') : 'StackProps') .replace(/%name\.camelCased%/g, camelCase(project.name)) .replace(/%name\.PascalCased%/g, camelCase(project.name, { pascalCase: true })) .replace(/%cdk-version%/g, cdkVersion) .replace(/%constructs-version%/g, constructsVersion) .replace(/%cdk-home%/g, (0, directories_1.cdkHomeDir)()) .replace(/%name\.PythonModule%/g, project.name.replace(/-/g, '_')) .replace(/%python-executable%/g, pythonExecutable()) .replace(/%name\.StackName%/g, project.name.replace(/[^A-Za-z0-9-]/g, '-')); } /** * Adds context variables to `cdk.json` in the generated project directory to * enable future behavior for new projects. */ async applyFutureFlags(projectDir) { const cdkJson = path.join(projectDir, 'cdk.json'); if (!await fs.pathExists(cdkJson)) { return; } const config = await fs.readJson(cdkJson); config.context = { ...config.context, ...cxapi.NEW_PROJECT_CONTEXT, }; await fs.writeJson(cdkJson, config, { spaces: 2 }); } } exports.InitTemplate = InitTemplate; async function availableInitTemplates() { return new Promise(async (resolve) => { try { const templatesDir = path.join((0, directories_1.rootDir)(), 'lib', 'init-templates'); const templateNames = await listDirectory(templatesDir); const templates = new Array(); for (const templateName of templateNames) { templates.push(await InitTemplate.fromName(templatesDir, templateName)); } resolve(templates); } catch { resolve([]); } }); } exports.availableInitTemplates = availableInitTemplates; async function availableInitLanguages() { return new Promise(async (resolve) => { const templates = await availableInitTemplates(); const result = new Set(); for (const template of templates) { for (const language of template.languages) { result.add(language); } } resolve([...result]); }); } exports.availableInitLanguages = availableInitLanguages; /** * @param dirPath is the directory to be listed. * @returns the list of file or directory names contained in ``dirPath``, excluding any dot-file, and sorted. */ async function listDirectory(dirPath) { return (await fs.readdir(dirPath)) .filter(p => !p.startsWith('.')) .filter(p => !(p === 'LICENSE')) // if, for some reason, the temp folder for the hook doesn't get deleted we don't want to display it in this list .filter(p => !(p === INFO_DOT_JSON)) .sort(); } async function printAvailableTemplates(language) { (0, logging_1.print)('Available templates:'); for (const template of await availableInitTemplates()) { if (language && template.languages.indexOf(language) === -1) { continue; } (0, logging_1.print)(`* ${chalk.green(template.name)}: ${template.description}`); const languageArg = language ? chalk.bold(language) : template.languages.length > 1 ? `[${template.languages.map(t => chalk.bold(t)).join('|')}]` : chalk.bold(template.languages[0]); (0, logging_1.print)(` └─ ${chalk.blue(`cdk init ${chalk.bold(template.name)} --language=${languageArg}`)}`); } } exports.printAvailableTemplates = printAvailableTemplates; async function initializeProject(template, language, canUseNetwork, generateOnly, workDir, stackName) { await assertIsEmptyDirectory(workDir); (0, logging_1.print)(`Applying project template ${chalk.green(template.name)} for ${chalk.blue(language)}`); await template.install(language, workDir, stackName); if (await fs.pathExists('README.md')) { (0, logging_1.print)(chalk.green(await fs.readFile('README.md', { encoding: 'utf-8' }))); } if (!generateOnly) { await initializeGitRepository(workDir); await postInstall(language, canUseNetwork, workDir); } (0, logging_1.print)('✅ All done!'); } async function assertIsEmptyDirectory(workDir) { const files = await fs.readdir(workDir); if (files.filter(f => !f.startsWith('.')).length !== 0) { throw new Error('`cdk init` cannot be run in a non-empty directory!'); } } async function initializeGitRepository(workDir) { if (await isInGitRepository(workDir)) { return; } (0, logging_1.print)('Initializing a new git repository...'); try { await execute('git', ['init'], { cwd: workDir }); await execute('git', ['add', '.'], { cwd: workDir }); await execute('git', ['commit', '--message="Initial commit"', '--no-gpg-sign'], { cwd: workDir }); } catch { (0, logging_1.warning)('Unable to initialize git repository for your project.'); } } async function postInstall(language, canUseNetwork, workDir) { switch (language) { case 'javascript': return postInstallJavascript(canUseNetwork, workDir); case 'typescript': return postInstallTypescript(canUseNetwork, workDir); case 'java': return postInstallJava(canUseNetwork, workDir); case 'python': return postInstallPython(workDir); } } async function postInstallJavascript(canUseNetwork, cwd) { return postInstallTypescript(canUseNetwork, cwd); } async function postInstallTypescript(canUseNetwork, cwd) { const command = 'npm'; if (!canUseNetwork) { (0, logging_1.warning)(`Please run '${command} install'!`); return; } (0, logging_1.print)(`Executing ${chalk.green(`${command} install`)}...`); try { await execute(command, ['install'], { cwd }); } catch (e) { (0, logging_1.warning)(`${command} install failed: ` + e.message); } } async function postInstallJava(canUseNetwork, cwd) { const mvnPackageWarning = 'Please run \'mvn package\'!'; if (!canUseNetwork) { (0, logging_1.warning)(mvnPackageWarning); return; } (0, logging_1.print)('Executing \'mvn package\''); try { await execute('mvn', ['package'], { cwd }); } catch { (0, logging_1.warning)('Unable to package compiled code as JAR'); (0, logging_1.warning)(mvnPackageWarning); } } async function postInstallPython(cwd) { const python = pythonExecutable(); (0, logging_1.warning)(`Please run '${python} -m venv .venv'!`); (0, logging_1.print)(`Executing ${chalk.green('Creating virtualenv...')}`); try { await execute(python, ['-m venv', '.venv'], { cwd }); } catch { (0, logging_1.warning)('Unable to create virtualenv automatically'); (0, logging_1.warning)(`Please run '${python} -m venv .venv'!`); } } /** * @param dir a directory to be checked * @returns true if ``dir`` is within a git repository. */ async function isInGitRepository(dir) { while (true) { if (await fs.pathExists(path.join(dir, '.git'))) { return true; } if (isRoot(dir)) { return false; } dir = path.dirname(dir); } } /** * @param dir a directory to be checked. * @returns true if ``dir`` is the root of a filesystem. */ function isRoot(dir) { return path.dirname(dir) === dir; } /** * Executes `command`. STDERR is emitted in real-time. * * If command exits with non-zero exit code, an exceprion is thrown and includes * the contents of STDOUT. * * @returns STDOUT (if successful). */ async function execute(cmd, args, { cwd }) { const child = childProcess.spawn(cmd, args, { cwd, shell: true, stdio: ['ignore', 'pipe', 'inherit'] }); let stdout = ''; child.stdout.on('data', chunk => stdout += chunk.toString()); return new Promise((ok, fail) => { child.once('error', err => fail(err)); child.once('exit', status => { if (status === 0) { return ok(stdout); } else { process.stderr.write(stdout); return fail(new Error(`${cmd} exited with status ${status}`)); } }); }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImluaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsOENBQThDO0FBQzlDLDZCQUE2QjtBQUM3Qix5Q0FBeUM7QUFDekMsK0JBQStCO0FBQy9CLCtCQUErQjtBQUMvQiw2Q0FBa0Q7QUFDbEQsdUNBQWtEO0FBQ2xELG9EQUF5RDtBQUN6RCx3REFBdUQ7QUFFdkQsdURBQXVELENBQUMsb0NBQW9DO0FBQzVGLGlFQUFpRTtBQUNqRSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDdkMsaUVBQWlFO0FBQ2pFLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQVd6Qzs7R0FFRztBQUNJLEtBQUssVUFBVSxPQUFPLENBQUMsT0FBdUI7SUFDbkQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUM7SUFDcEQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksSUFBSSxLQUFLLENBQUM7SUFDbkQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDakQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFO1FBQ3RDLE1BQU0sdUJBQXVCLEVBQUUsQ0FBQztRQUNoQyxPQUFPO0tBQ1I7SUFFRCxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxJQUFJLFNBQVMsQ0FBQyxDQUFDLG9EQUFvRDtJQUU1RixNQUFNLFFBQVEsR0FBRyxDQUFDLE1BQU0sc0JBQXNCLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSyxDQUFDLENBQUMsQ0FBQztJQUM5RSxJQUFJLENBQUMsUUFBUSxFQUFFO1FBQ2IsTUFBTSx1QkFBdUIsQ0FB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ImltcG9ydCAqIGFzIGNoaWxkUHJvY2VzcyBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0ICogYXMgY2hhbGsgZnJvbSAnY2hhbGsnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IHsgaW52b2tlQnVpbHRpbkhvb2tzIH0gZnJvbSAnLi9pbml0LWhvb2tzJztcbmltcG9ydCB7IGVycm9yLCBwcmludCwgd2FybmluZyB9IGZyb20gJy4vbG9nZ2luZyc7XG5pbXBvcnQgeyBjZGtIb21lRGlyLCByb290RGlyIH0gZnJvbSAnLi91dGlsL2RpcmVjdG9yaWVzJztcbmltcG9ydCB7IHJhbmdlRnJvbVNlbXZlciB9IGZyb20gJy4vdXRpbC92ZXJzaW9uLXJhbmdlJztcblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlcyAqLyAvLyBQYWNrYWdlcyBkb24ndCBoYXZlIEB0eXBlcyBtb2R1bGVcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG5jb25zdCBjYW1lbENhc2UgPSByZXF1aXJlKCdjYW1lbGNhc2UnKTtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG5jb25zdCBkZWNhbWVsaXplID0gcmVxdWlyZSgnZGVjYW1lbGl6ZScpO1xuXG5leHBvcnQgaW50ZXJmYWNlIENsaUluaXRPcHRpb25zIHtcbiAgcmVhZG9ubHkgdHlwZT86IHN0cmluZztcbiAgcmVhZG9ubHkgbGFuZ3VhZ2U/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNhblVzZU5ldHdvcms/OiBib29sZWFuO1xuICByZWFkb25seSBnZW5lcmF0ZU9ubHk/OiBib29sZWFuO1xuICByZWFkb25seSB3b3JrRGlyPzogc3RyaW5nO1xuICByZWFkb25seSBzdGFja05hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBhIENESyBwYWNrYWdlIGluIHRoZSBjdXJyZW50IGRpcmVjdG9yeVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xpSW5pdChvcHRpb25zOiBDbGlJbml0T3B0aW9ucykge1xuICBjb25zdCBjYW5Vc2VOZXR3b3JrID0gb3B0aW9ucy5jYW5Vc2VOZXR3b3JrID8/IHRydWU7XG4gIGNvbnN0IGdlbmVyYXRlT25seSA9IG9wdGlvbnMuZ2VuZXJhdGVPbmx5ID8/IGZhbHNlO1xuICBjb25zdCB3b3JrRGlyID0gb3B0aW9ucy53b3JrRGlyID8/IHByb2Nlc3MuY3dkKCk7XG4gIGlmICghb3B0aW9ucy50eXBlICYmICFvcHRpb25zLmxhbmd1YWdlKSB7XG4gICAgYXdhaXQgcHJpbnRBdmFpbGFibGVUZW1wbGF0ZXMoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB0eXBlID0gb3B0aW9ucy50eXBlIHx8ICdkZWZhdWx0JzsgLy8gXCJkZWZhdWx0XCIgaXMgdGhlIGRlZmF1bHQgdHlwZSAoYW5kIG1hcHMgdG8gXCJhcHBcIilcblxuICBjb25zdCB0ZW1wbGF0ZSA9IChhd2FpdCBhdmFpbGFibGVJbml0VGVtcGxhdGVzKCkpLmZpbmQodCA9PiB0Lmhhc05hbWUodHlwZSEpKTtcbiAgaWYgKCF0ZW1wbGF0ZSkge1xuICAgIGF3YWl0IHByaW50QXZhaWxhYmxlVGVtcGxhdGVzKG9wdGlvbnMubGFuZ3VhZ2UpO1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBpbml0IHRlbXBsYXRlOiAke3R5cGV9YCk7XG4gIH1cbiAgaWYgKCFvcHRpb25zLmxhbmd1YWdlICYmIHRlbXBsYXRlLmxhbmd1YWdlcy5sZW5ndGggPT09IDEpIHtcbiAgICBjb25zdCBsYW5ndWFnZSA9IHRlbXBsYXRlLmxhbmd1YWdlc1swXTtcbiAgICB3YXJuaW5nKGBObyAtLWxhbmd1YWdlIHdhcyBwcm92aWRlZCwgYnV0ICcke3R5cGV9JyBzdXBwb3J0cyBvbmx5ICcke2xhbmd1YWdlfScsIHNvIGRlZmF1bHRpbmcgdG8gLS1sYW5ndWFnZT0ke2xhbmd1YWdlfWApO1xuICB9XG4gIGlmICghb3B0aW9ucy5sYW5ndWFnZSkge1xuICAgIHByaW50KGBBdmFpbGFibGUgbGFuZ3VhZ2VzIGZvciAke2NoYWxrLmdyZWVuKHR5cGUpfTogJHt0ZW1wbGF0ZS5sYW5ndWFnZXMubWFwKGwgPT4gY2hhbGsuYmx1ZShsKSkuam9pbignLCAnKX1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGxhbmd1YWdlIHdhcyBzZWxlY3RlZCcpO1xuICB9XG5cbiAgYXdhaXQgaW5pdGlhbGl6ZVByb2plY3QodGVtcGxhdGUsIG9wdGlvbnMubGFuZ3VhZ2UsIGNhblVzZU5ldHdvcmssIGdlbmVyYXRlT25seSwgd29ya0Rpciwgb3B0aW9ucy5zdGFja05hbWUpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIG5hbWUgb2YgdGhlIFB5dGhvbiBleGVjdXRhYmxlIGZvciB0aGlzIE9TXG4gKi9cbmZ1bmN0aW9uIHB5dGhvbkV4ZWN1dGFibGUoKSB7XG4gIGxldCBweXRob24gPSAncHl0aG9uMyc7XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgcHl0aG9uID0gJ3B5dGhvbic7XG4gIH1cbiAgcmV0dXJuIHB5dGhvbjtcbn1cbmNvbnN0IElORk9fRE9UX0pTT04gPSAnaW5mby5qc29uJztcblxuZXhwb3J0IGNsYXNzIEluaXRUZW1wbGF0ZSB7XG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgZnJvbU5hbWUodGVtcGxhdGVzRGlyOiBzdHJpbmcsIG5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IGJhc2VQYXRoID0gcGF0aC5qb2luKHRlbXBsYXRlc0RpciwgbmFtZSk7XG4gICAgY29uc3QgbGFuZ3VhZ2VzID0gKGF3YWl0IGxpc3REaXJlY3RvcnkoYmFzZVBhdGgpKTtcbiAgICBjb25zdCBpbmZvID0gYXdhaXQgZnMucmVhZEpzb24ocGF0aC5qb2luKGJhc2VQYXRoLCBJTkZPX0RPVF9KU09OKSk7XG4gICAgcmV0dXJuIG5ldyBJbml0VGVtcGxhdGUoYmFzZVBhdGgsIG5hbWUsIGxhbmd1YWdlcywgaW5mbyk7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgZGVzY3JpcHRpb246IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGFsaWFzZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGJhc2VQYXRoOiBzdHJpbmcsXG4gICAgcHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZyxcbiAgICBwdWJsaWMgcmVhZG9ubHkgbGFuZ3VhZ2VzOiBzdHJpbmdbXSxcbiAgICBpbmZvOiBhbnkpIHtcbiAgICB0aGlzLmRlc2NyaXB0aW9uID0gaW5mby5kZXNjcmlwdGlvbjtcbiAgICBmb3IgKGNvbnN0IGFsaWFzIG9mIGluZm8uYWxpYXNlcyB8fCBbXSkge1xuICAgICAgdGhpcy5hbGlhc2VzLmFkZChhbGlhcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBuYW1lIHRoZSBuYW1lIHRoYXQgaXMgYmVpbmcgY2hlY2tlZFxuICAgKiBAcmV0dXJucyBgYHRydWVgYCBpZiBgYG5hbWVgYCBpcyB0aGUgbmFtZSBvZiB0aGlzIHRlbXBsYXRlIG9yIGFuIGFsaWFzIG9mIGl0LlxuICAgKi9cbiAgcHVibGljIGhhc05hbWUobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIG5hbWUgPT09IHRoaXMubmFtZSB8fCB0aGlzLmFsaWFzZXMuaGFzKG5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhpcyBgYEluaXRUZW1wbGF0ZWBgIGZvciBhIGdpdmVuIGxhbmd1YWdlIHRvIGEgc3BlY2lmaWVkIGZvbGRlci5cbiAgICpcbiAgICogQHBhcmFtIGxhbmd1YWdlICAgIHRoZSBsYW5ndWFnZSB0byBpbnN0YW50aWF0ZSB0aGlzIHRlbXBsYXRlIHdpdGhcbiAgICogQHBhcmFtIHRhcmdldERpcmVjdG9yeSB0aGUgZGlyZWN0b3J5IHdoZXJlIHRoZSB0ZW1wbGF0ZSBpcyB0byBiZSBpbnN0YW50aWF0ZWQgaW50b1xuICAgKi9cbiAgcHVibGljIGFzeW5jIGluc3RhbGwobGFuZ3VhZ2U6IHN0cmluZywgdGFyZ2V0RGlyZWN0b3J5OiBzdHJpbmcsIHN0YWNrTmFtZT86IHN0cmluZykge1xuICAgIGlmICh0aGlzLmxhbmd1YWdlcy5pbmRleE9mKGxhbmd1YWdlKSA9PT0gLTEpIHtcbiAgICAgIGVycm9yKGBUaGUgJHtjaGFsay5ibHVlKGxhbmd1YWdlKX0gbGFuZ3VhZ2UgaXMgbm90IHN1cHBvcnRlZCBmb3IgJHtjaGFsay5ncmVlbih0aGlzLm5hbWUpfSBgXG4gICAgICAgICAgKyBgKGl0IHN1cHBvcnRzOiAke3RoaXMubGFuZ3VhZ2VzLm1hcChsID0+IGNoYWxrLmJsdWUobCkpLmpvaW4oJywgJyl9KWApO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBsYW5ndWFnZTogJHtsYW5ndWFnZX1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9qZWN0SW5mbzogUHJvamVjdEluZm8gPSB7XG4gICAgICBuYW1lOiBkZWNhbWVsaXplKHBhdGguYmFzZW5hbWUocGF0aC5yZXNvbHZlKHRhcmdldERpcmVjdG9yeSkpKSxcbiAgICAgIHN0YWNrTmFtZSxcbiAgICB9O1xuXG4gICAgY29uc3Qgc291cmNlRGlyZWN0b3J5ID0gcGF0aC5qb2luKHRoaXMuYmFzZVBhdGgsIGxhbmd1YWdlKTtcblxuICAgIGF3YWl0IHRoaXMuaW5zdGFsbEZpbGVzKHNvdXJjZURpcmVjdG9yeSwgdGFyZ2V0RGlyZWN0b3J5LCBsYW5ndWFnZSwgcHJvamVjdEluZm8pO1xuICAgIGF3YWl0IHRoaXMuYXBwbHlGdXR1cmVGbGFncyh0YXJnZXREaXJlY3RvcnkpO1xuICAgIGF3YWl0IGludm9rZUJ1aWx0aW5Ib29rcyh7IHRhcmdldERpcmVjdG9yeSwgbGFuZ3VhZ2UsIHRlbXBsYXRlTmFtZTogdGhpcy5uYW1lIH0sIHtcbiAgICAgIHN1YnN0aXR1dGVQbGFjZWhvbGRlcnNJbjogYXN5bmMgKC4uLmZpbGVOYW1lczogc3RyaW5nW10pID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBmaWxlTmFtZSBvZiBmaWxlTmFtZXMpIHtcbiAgICAgICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbih0YXJnZXREaXJlY3RvcnksIGZpbGVOYW1lKTtcbiAgICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IGF3YWl0IGZzLnJlYWRGaWxlKGZ1bGxQYXRoLCB7IGVuY29kaW5nOiAndXRmLTgnIH0pO1xuICAgICAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShmdWxsUGF0aCwgdGhpcy5leHBhbmQodGVtcGxhdGUsIGxhbmd1YWdlLCBwcm9qZWN0SW5mbykpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgcGxhY2Vob2xkZXI6IChwaDogc3RyaW5nKSA9PiB0aGlzLmV4cGFuZChgJSR7cGh9JWAsIGxhbmd1YWdlLCBwcm9qZWN0SW5mbyksXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluc3RhbGxGaWxlcyhzb3VyY2VEaXJlY3Rvcnk6IHN0cmluZywgdGFyZ2V0RGlyZWN0b3J5OiBzdHJpbmcsIGxhbmd1YWdlOiBzdHJpbmcsIHByb2plY3Q6IFByb2plY3RJbmZvKSB7XG4gICAgZm9yIChjb25zdCBmaWxlIG9mIGF3YWl0IGZzLnJlYWRkaXIoc291cmNlRGlyZWN0b3J5KSkge1xuICAgICAgY29uc3QgZnJvbUZpbGUgPSBwYXRoLmpvaW4oc291cmNlRGlyZWN0b3J5LCBmaWxlKTtcbiAgICAgIGNvbnN0IHRvRmlsZSA9IHBhdGguam9pbih0YXJnZXREaXJlY3RvcnksIHRoaXMuZXhwYW5kKGZpbGUsIGxhbmd1YWdlLCBwcm9qZWN0KSk7XG4gICAgICBpZiAoKGF3YWl0IGZzLnN0YXQoZnJvbUZpbGUpKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgIGF3YWl0IGZzLm1rZGlyKHRvRmlsZSk7XG4gICAgICAgIGF3YWl0IHRoaXMuaW5zdGFsbEZpbGVzKGZyb21GaWxlLCB0b0ZpbGUsIGxhbmd1YWdlLCBwcm9qZWN0KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IGVsc2UgaWYgKGZpbGUubWF0Y2goL14uKlxcLnRlbXBsYXRlXFwuW14uXSskLykpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pbnN0YWxsUHJvY2Vzc2VkKGZyb21GaWxlLCB0b0ZpbGUucmVwbGFjZSgvXFwudGVtcGxhdGUoXFwuW14uXSspJC8sICckMScpLCBsYW5ndWFnZSwgcHJvamVjdCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfSBlbHNlIGlmIChmaWxlLm1hdGNoKC9eLipcXC5ob29rXFwuKGQuKT9bXi5dKyQvKSkge1xuICAgICAgICAvLyBJZ25vcmVcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBmcy5jb3B5KGZyb21GaWxlLCB0b0ZpbGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5zdGFsbFByb2Nlc3NlZCh0ZW1wbGF0ZVBhdGg6IHN0cmluZywgdG9GaWxlOiBzdHJpbmcsIGxhbmd1YWdlOiBzdHJpbmcsIHByb2plY3Q6IFByb2plY3RJbmZvKSB7XG4gICAgY29uc3QgdGVtcGxhdGUgPSBhd2FpdCBmcy5yZWFkRmlsZSh0ZW1wbGF0ZVBhdGgsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSk7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHRvRmlsZSwgdGhpcy5leHBhbmQodGVtcGxhdGUsIGxhbmd1YWdlLCBwcm9qZWN0KSk7XG4gIH1cblxuICBwcml2YXRlIGV4cGFuZCh0ZW1wbGF0ZTogc3RyaW5nLCBsYW5ndWFnZTogc3RyaW5nLCBwcm9qZWN0OiBQcm9qZWN0SW5mbykge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3QgbWFuaWZlc3QgPSByZXF1aXJlKHBhdGguam9pbihyb290RGlyKCksICdwYWNrYWdlLmpzb24nKSk7XG4gICAgY29uc3QgTUFUQ0hfVkVSX0JVSUxEID0gL1xcK1thLWYwLTldKyQvOyAvLyBNYXRjaGVzIFwiK0JVSUxEXCIgaW4gXCJ4Lnkuei1iZXRhK0JVSUxEXCJcbiAgICBjb25zdCBjZGtWZXJzaW9uID0gbWFuaWZlc3QudmVyc2lvbi5yZXBsYWNlKE1BVENIX1ZFUl9CVUlMRCwgJycpO1xuICAgIGxldCBjb25zdHJ1Y3RzVmVyc2lvbiA9IG1hbmlmZXN0LmRldkRlcGVuZGVuY2llcy5jb25zdHJ1Y3RzLnJlcGxhY2UoTUFUQ0hfVkVSX0JVSUxELCAnJyk7XG4gICAgc3dpdGNoIChsYW5ndWFnZSkge1xuICAgICAgY2FzZSAnamF2YSc6XG4gICAgICBjYXNlICdjc2hhcnAnOlxuICAgICAgY2FzZSAnZnNoYXJwJzpcbiAgICAgICAgY29uc3RydWN0c1ZlcnNpb24gPSByYW5nZUZyb21TZW12ZXIoY29uc3RydWN0c1ZlcnNpb24sICdicmFja2V0Jyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncHl0aG9uJzpcbiAgICAgICAgY29uc3RydWN0c1ZlcnNpb24gPSByYW5nZUZyb21TZW12ZXIoY29uc3RydWN0c1ZlcnNpb24sICdwZXAnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiB0ZW1wbGF0ZS5yZXBsYWNlKC8lbmFtZSUvZywgcHJvamVjdC5uYW1lKVxuICAgICAgLnJlcGxhY2UoLyVzdGFja25hbWUlLywgcHJvamVjdC5zdGFja05hbWUgPz8gJyVuYW1lLlBhc2NhbENhc2VkJVN0YWNrJylcbiAgICAgIC5yZXBsYWNlKC8lUGFzY2FsTmFtZVNwYWNlJS8sIHByb2plY3Quc3RhY2tOYW1lID8gY2FtZWxDYXNlKHByb2plY3Quc3RhY2tOYW1lICsgJ1N0YWNrJywgeyBwYXNjYWxDYXNlOiB0cnVlIH0pIDogJyVuYW1lLlBhc2NhbENhc2VkJScpXG4gICAgICAucmVwbGFjZSgvJVBhc2NhbFN0YWNrUHJvcHMlLywgcHJvamVjdC5zdGFja05hbWUgPyAoY2FtZWxDYXNlKHByb2plY3Quc3RhY2tOYW1lLCB7IHBhc2NhbENhc2U6IHRydWUgfSkgKyAnU3RhY2tQcm9wcycpIDogJ1N0YWNrUHJvcHMnKVxuICAgICAgLnJlcGxhY2UoLyVuYW1lXFwuY2FtZWxDYXNlZCUvZywgY2FtZWxDYXNlKHByb2plY3QubmFtZSkpXG4gICAgICAucmVwbGFjZSgvJW5hbWVcXC5QYXNjYWxDYXNlZCUvZywgY2FtZWxDYXNlKHByb2plY3QubmFtZSwgeyBwYXNjYWxDYXNlOiB0cnVlIH0pKVxuICAgICAgLnJlcGxhY2UoLyVjZGstdmVyc2lvbiUvZywgY2RrVmVyc2lvbilcbiAgICAgIC5yZXBsYWNlKC8lY29uc3RydWN0cy12ZXJzaW9uJS9nLCBjb25zdHJ1Y3RzVmVyc2lvbilcbiAgICAgIC5yZXBsYWNlKC8lY2RrLWhvbWUlL2csIGNka0hvbWVEaXIoKSlcbiAgICAgIC5yZXBsYWNlKC8lbmFtZVxcLlB5dGhvbk1vZHVsZSUvZywgcHJvamVjdC5uYW1lLnJlcGxhY2UoLy0vZywgJ18nKSlcbiAgICAgIC5yZXBsYWNlKC8lcHl0aG9uLWV4ZWN1dGFibGUlL2csIHB5dGhvbkV4ZWN1dGFibGUoKSlcbiAgICAgIC5yZXBsYWNlKC8lbmFtZVxcLlN0YWNrTmFtZSUvZywgcHJvamVjdC5uYW1lLnJlcGxhY2UoL1teQS1aYS16MC05LV0vZywgJy0nKSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBjb250ZXh0IHZhcmlhYmxlcyB0byBgY2RrLmpzb25gIGluIHRoZSBnZW5lcmF0ZWQgcHJvamVjdCBkaXJlY3RvcnkgdG9cbiAgICogZW5hYmxlIGZ1dHVyZSBiZWhhdmlvciBmb3IgbmV3IHByb2plY3RzLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBhcHBseUZ1dHVyZUZsYWdzKHByb2plY3REaXI6IHN0cmluZykge1xuICAgIGNvbnN0IGNka0pzb24gPSBwYXRoLmpvaW4ocHJvamVjdERpciwgJ2Nkay5qc29uJyk7XG4gICAgaWYgKCFhd2FpdCBmcy5wYXRoRXhpc3RzKGNka0pzb24pKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlnID0gYXdhaXQgZnMucmVhZEpzb24oY2RrSnNvbik7XG4gICAgY29uZmlnLmNvbnRleHQgPSB7XG4gICAgICAuLi5jb25maWcuY29udGV4dCxcbiAgICAgIC4uLmN4YXBpLk5FV19QUk9KRUNUX0NPTlRFWFQsXG4gICAgfTtcblxuICAgIGF3YWl0IGZzLndyaXRlSnNvbihjZGtKc29uLCBjb25maWcsIHsgc3BhY2VzOiAyIH0pO1xuICB9XG59XG5cbmludGVyZmFjZSBQcm9qZWN0SW5mbyB7XG4gIC8qKiBUaGUgdmFsdWUgdXNlZCBmb3IgJW5hbWUlICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgc3RhY2tOYW1lPzogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXZhaWxhYmxlSW5pdFRlbXBsYXRlcygpOiBQcm9taXNlPEluaXRUZW1wbGF0ZVtdPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyByZXNvbHZlID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdGVtcGxhdGVzRGlyID0gcGF0aC5qb2luKHJvb3REaXIoKSwgJ2xpYicsICdpbml0LXRlbXBsYXRlcycpO1xuICAgICAgY29uc3QgdGVtcGxhdGVOYW1lcyA9IGF3YWl0IGxpc3REaXJlY3RvcnkodGVtcGxhdGVzRGlyKTtcbiAgICAgIGNvbnN0IHRlbXBsYXRlcyA9IG5ldyBBcnJheTxJbml0VGVtcGxhdGU+KCk7XG4gICAgICBmb3IgKGNvbnN0IHRlbXBsYXRlTmFtZSBvZiB0ZW1wbGF0ZU5hbWVzKSB7XG4gICAgICAgIHRlbXBsYXRlcy5wdXNoKGF3YWl0IEluaXRUZW1wbGF0ZS5mcm9tTmFtZSh0ZW1wbGF0ZXNEaXIsIHRlbXBsYXRlTmFtZSkpO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZSh0ZW1wbGF0ZXMpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmVzb2x2ZShbXSk7XG4gICAgfVxuICB9KTtcbn1cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhdmFpbGFibGVJbml0TGFuZ3VhZ2VzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIHJlc29sdmUgPT4ge1xuICAgIGNvbnN0IHRlbXBsYXRlcyA9IGF3YWl0IGF2YWlsYWJsZUluaXRUZW1wbGF0ZXMoKTtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IHRlbXBsYXRlIG9mIHRlbXBsYXRlcykge1xuICAgICAgZm9yIChjb25zdCBsYW5ndWFnZSBvZiB0ZW1wbGF0ZS5sYW5ndWFnZXMpIHtcbiAgICAgICAgcmVzdWx0LmFkZChsYW5ndWFnZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJlc29sdmUoWy4uLnJlc3VsdF0pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gZGlyUGF0aCBpcyB0aGUgZGlyZWN0b3J5IHRvIGJlIGxpc3RlZC5cbiAqIEByZXR1cm5zIHRoZSBsaXN0IG9mIGZpbGUgb3IgZGlyZWN0b3J5IG5hbWVzIGNvbnRhaW5lZCBpbiBgYGRpclBhdGhgYCwgZXhjbHVkaW5nIGFueSBkb3QtZmlsZSwgYW5kIHNvcnRlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbGlzdERpcmVjdG9yeShkaXJQYXRoOiBzdHJpbmcpIHtcbiAgcmV0dXJuIChhd2FpdCBmcy5yZWFkZGlyKGRpclBhdGgpKVxuICAgIC5maWx0ZXIocCA9PiAhcC5zdGFydHNXaXRoKCcuJykpXG4gICAgLmZpbHRlcihwID0+ICEocCA9PT0gJ0xJQ0VOU0UnKSlcbiAgICAvLyBpZiwgZm9yIHNvbWUgcmVhc29uLCB0aGUgdGVtcCBmb2xkZXIgZm9yIHRoZSBob29rIGRvZXNuJ3QgZ2V0IGRlbGV0ZWQgd2UgZG9uJ3Qgd2FudCB0byBkaXNwbGF5IGl0IGluIHRoaXMgbGlzdFxuICAgIC5maWx0ZXIocCA9PiAhKHAgPT09IElORk9fRE9UX0pTT04pKVxuICAgIC5zb3J0KCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcmludEF2YWlsYWJsZVRlbXBsYXRlcyhsYW5ndWFnZT86IHN0cmluZykge1xuICBwcmludCgnQXZhaWxhYmxlIHRlbXBsYXRlczonKTtcbiAgZm9yIChjb25zdCB0ZW1wbGF0ZSBvZiBhd2FpdCBhdmFpbGFibGVJbml0VGVtcGxhdGVzKCkpIHtcbiAgICBpZiAobGFuZ3VhZ2UgJiYgdGVtcGxhdGUubGFuZ3VhZ2VzLmluZGV4T2YobGFuZ3VhZ2UpID09PSAtMSkgeyBjb250aW51ZTsgfVxuICAgIHByaW50KGAqICR7Y2hhbGsuZ3JlZW4odGVtcGxhdGUubmFtZSl9OiAke3RlbXBsYXRlLmRlc2NyaXB0aW9ufWApO1xuICAgIGNvbnN0IGxhbmd1YWdlQXJnID0gbGFuZ3VhZ2UgPyBjaGFsay5ib2xkKGxhbmd1YWdlKVxuICAgICAgOiB0ZW1wbGF0ZS5sYW5ndWFnZXMubGVuZ3RoID4gMSA/IGBbJHt0ZW1wbGF0ZS5sYW5ndWFnZXMubWFwKHQgPT4gY2hhbGsuYm9sZCh0KSkuam9pbignfCcpfV1gXG4gICAgICAgIDogY2hhbGsuYm9sZCh0ZW1wbGF0ZS5sYW5ndWFnZXNbMF0pO1xuICAgIHByaW50KGAgICDilJTilIAgJHtjaGFsay5ibHVlKGBjZGsgaW5pdCAke2NoYWxrLmJvbGQodGVtcGxhdGUubmFtZSl9IC0tbGFuZ3VhZ2U9JHtsYW5ndWFnZUFyZ31gKX1gKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBpbml0aWFsaXplUHJvamVjdChcbiAgdGVtcGxhdGU6IEluaXRUZW1wbGF0ZSxcbiAgbGFuZ3VhZ2U6IHN0cmluZyxcbiAgY2FuVXNlTmV0d29yazogYm9vbGVhbixcbiAgZ2VuZXJhdGVPbmx5OiBib29sZWFuLFxuICB3b3JrRGlyOiBzdHJpbmcsXG4gIHN0YWNrTmFtZT86IHN0cmluZyxcbikge1xuICBhd2FpdCBhc3NlcnRJc0VtcHR5RGlyZWN0b3J5KHdvcmtEaXIpO1xuICBwcmludChgQXBwbHlpbmcgcHJvamVjdCB0ZW1wbGF0ZSAke2NoYWxrLmdyZWVuKHRlbXBsYXRlLm5hbWUpfSBmb3IgJHtjaGFsay5ibHVlKGxhbmd1YWdlKX1gKTtcbiAgYXdhaXQgdGVtcGxhdGUuaW5zdGFsbChsYW5ndWFnZSwgd29ya0Rpciwgc3RhY2tOYW1lKTtcbiAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoJ1JFQURNRS5tZCcpKSB7XG4gICAgcHJpbnQoY2hhbGsuZ3JlZW4oYXdhaXQgZnMucmVhZEZpbGUoJ1JFQURNRS5tZCcsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSkpKTtcbiAgfVxuXG4gIGlmICghZ2VuZXJhdGVPbmx5KSB7XG4gICAgYXdhaXQgaW5pdGlhbGl6ZUdpdFJlcG9zaXRvcnkod29ya0Rpcik7XG4gICAgYXdhaXQgcG9zdEluc3RhbGwobGFuZ3VhZ2UsIGNhblVzZU5ldHdvcmssIHdvcmtEaXIpO1xuICB9XG5cbiAgcHJpbnQoJ+KchSBBbGwgZG9uZSEnKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYXNzZXJ0SXNFbXB0eURpcmVjdG9yeSh3b3JrRGlyOiBzdHJpbmcpIHtcbiAgY29uc3QgZmlsZXMgPSBhd2FpdCBmcy5yZWFkZGlyKHdvcmtEaXIpO1xuICBpZiAoZmlsZXMuZmlsdGVyKGYgPT4gIWYuc3RhcnRzV2l0aCgnLicpKS5sZW5ndGggIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2BjZGsgaW5pdGAgY2Fubm90IGJlIHJ1biBpbiBhIG5vbi1lbXB0eSBkaXJlY3RvcnkhJyk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5pdGlhbGl6ZUdpdFJlcG9zaXRvcnkod29ya0Rpcjogc3RyaW5nKSB7XG4gIGlmIChhd2FpdCBpc0luR2l0UmVwb3NpdG9yeSh3b3JrRGlyKSkgeyByZXR1cm47IH1cbiAgcHJpbnQoJ0luaXRpYWxpemluZyBhIG5ldyBnaXQgcmVwb3NpdG9yeS4uLicpO1xuICB0cnkge1xuICAgIGF3YWl0IGV4ZWN1dGUoJ2dpdCcsIFsnaW5pdCddLCB7IGN3ZDogd29ya0RpciB9KTtcbiAgICBhd2FpdCBleGVjdXRlKCdnaXQnLCBbJ2FkZCcsICcuJ10sIHsgY3dkOiB3b3JrRGlyIH0pO1xuICAgIGF3YWl0IGV4ZWN1dGUoJ2dpdCcsIFsnY29tbWl0JywgJy0tbWVzc2FnZT1cIkluaXRpYWwgY29tbWl0XCInLCAnLS1uby1ncGctc2lnbiddLCB7IGN3ZDogd29ya0RpciB9KTtcbiAgfSBjYXRjaCB7XG4gICAgd2FybmluZygnVW5hYmxlIHRvIGluaXRpYWxpemUgZ2l0IHJlcG9zaXRvcnkgZm9yIHlvdXIgcHJvamVjdC4nKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBwb3N0SW5zdGFsbChsYW5ndWFnZTogc3RyaW5nLCBjYW5Vc2VOZXR3b3JrOiBib29sZWFu