jsii-release
Version:
Release jsii modules to multiple package managers
247 lines • 36.5 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoReleaser = void 0;
const path = __importStar(require("path"));
const fs = __importStar(require("fs-extra"));
const git = __importStar(require("../help/git"));
const os = __importStar(require("../help/os"));
const shell = __importStar(require("../help/shell"));
/**
* Release a set of Golang modules.
*/
class GoReleaser {
constructor(props) {
if (!shell.which('git')) {
throw new Error('git must be available to in order to be able to push Go code to GitHub');
}
this.version = props.version;
this.gitCommitMessage = props.message;
this.dir = path.resolve(props.dir ?? path.join(process.cwd(), 'dist', 'go'));
this.gitBranch = props.branch ?? 'main';
this.dryRun = props.dryRun ?? false;
const gitUsername = props.username ?? git.username();
const gitUseremail = props.email ?? git.email();
if (!gitUsername) {
throw new Error('Unable to detect username. either configure a git user.name or pass GIT_USER_NAME env variable');
}
if (!gitUseremail) {
throw new Error('Unable to detect user email. either configure a git user.email or pass GIT_USER_EMAIL env variable');
}
this.gitUseremail = gitUseremail;
this.gitUsername = gitUsername;
}
/**
* Run the release process.
*
* @returns metadata about the release.
*/
release() {
const modules = this.collectModules(this.dir);
if (modules.length === 0) {
console.log('No modules detected. Skipping');
return {};
}
console.log('Detected modules:');
modules.forEach(m => console.log(` - ${m.modFile}`));
const repoURL = this.extractRepoURL(modules);
const repoDir = path.join(os.mkdtempSync(), 'repo');
const branchExists = git.branchExistsOnRemote(repoURL, this.gitBranch);
if (!branchExists) {
console.log(`Remote branch '${this.gitBranch}' not found, continuing with default branch.`);
}
const cloneOptions = {
tags: true, // we need to know about all tags to not re-create an existing one
branch: branchExists ? this.gitBranch : undefined,
};
git.clone(repoURL, repoDir, cloneOptions);
const cwd = process.cwd();
try {
process.chdir(repoDir);
return this.doRelease(modules, repoDir);
}
finally {
process.chdir(cwd);
}
}
doRelease(modules, repoDir) {
git.identify(this.gitUsername, this.gitUseremail);
git.checkout(this.gitBranch, { createIfMissing: true });
this.syncRepo(repoDir);
git.add('.');
if (!git.diffIndex()) {
console.log('No changes. Skipping release');
return {};
}
const commitMessage = this.gitCommitMessage ?? this.buildReleaseMessage(modules);
git.commit(commitMessage);
const tags = [];
for (const module of modules) {
const name = this.buildTagName(module);
const created = git.tag(name);
if (created) {
tags.push(name);
}
}
if (tags.length === 0) {
console.log('All tags already exist. Skipping release');
return {};
}
const refs = [...tags, this.gitBranch];
if (this.dryRun) {
console.log('===========================================');
console.log(' 🏜️ DRY-RUN MODE 🏜️');
console.log('===========================================');
refs.forEach(t => console.log(`Remote ref will be updated: ${t}`));
}
else {
refs.forEach(t => git.push(t));
}
return { tags, commitMessage, repoDir };
}
collectModules(dir) {
const modules = [];
for (const p of [...fs.readdirSync(dir), '.']) {
const modFile = path.join(dir, p, 'go.mod');
if (fs.existsSync(modFile)) {
modules.push(this.parseModule(modFile));
}
}
return modules;
}
parseModule(modFile) {
const version = this.extractVersion(path.dirname(modFile));
const majorVersion = Number(version.split('.')[0]);
// extract the module decleration (e.g 'module github.com/aws/constructs-go/constructs/v3')
const match = fs.readFileSync(modFile).toString().match(/module (.*)/);
if (!match || !match[1]) {
throw new Error(`Unable to detected module declaration in ${modFile}`);
}
// e.g 'github.com/aws/constructs-go/constructs/v3'
const cannonicalName = match[1];
// e.g ['github.com', 'aws', 'constructs-go', 'constructs', 'v3']
const cannonicalNameParts = cannonicalName.split('/');
// e.g 'github.com/aws/constructs-go'
const repoURL = cannonicalNameParts.slice(0, 3).join('/');
// e.g 'v3'
const majorVersionSuffix = majorVersion > 1 ? `/v${majorVersion}` : '';
if (!cannonicalName.endsWith(majorVersionSuffix)) {
throw new Error(`Module declaration in '${modFile}' expected to end with '${majorVersionSuffix}' since its major version is larger than 1`);
}
if (!repoURL.startsWith('github.com')) {
if (!(git.detectSSH() || git.detectGHE())) {
throw new Error(`Repository must be hosted on github.com. Found: '${repoURL}' in ${modFile}`);
}
}
let repoPath = cannonicalNameParts
.slice(3) // e.g ['constructs', 'v3']
.join('/'); // e.g 'constructs/v3'
// we could have something like
// constructs/v3
// or something like
// constructsv3/v3
// we only want to strip the last 'v3'
const split = repoPath.split('/');
if (split[split.length - 1] === `v${majorVersion}`) {
split.pop();
repoPath = split.join('/');
}
// strip '/' if exists (wont exist for top level modules)
repoPath = repoPath.endsWith('/') ? repoPath.substr(0, repoPath.length - 1) : repoPath;
return { modFile, version, cannonicalName, repoPath, repoURL };
}
buildTagName(m) {
return m.repoPath === '' ? `v${m.version}` : `${m.repoPath}/v${m.version}`;
}
buildReleaseMessage(modules) {
const semantic = 'chore(release)';
const versions = new Set(modules.map(m => m.version));
if (versions.size === 1) {
// single version (e.g chore(release): v1.2.3)
return `${semantic}: v${versions.values().next().value}`;
}
else {
// multiple versions (e.g chore(release): chore(release): module1@v1.2.3 module2@v1.2.3)
return `${semantic}: ${modules.map(m => `${m.repoPath ? `${m.repoPath}@` : ''}v${m.version}`).join(' ')}`;
}
}
syncRepo(repoDir) {
const topLevel = path.join(repoDir, 'go.mod');
if (fs.existsSync(topLevel)) {
// with top level modules we sync the entire repository
// so we just empty it out
fs.readdirSync(repoDir)
.filter(f => f !== '.git')
.forEach(f => git.rm(path.join(repoDir, f), { recursive: true }));
}
else {
// otherwise, we selectively remove the submodules only.
for (const p of fs.readdirSync(repoDir)) {
const submodule = path.join(repoDir, p, 'go.mod');
if (fs.existsSync(submodule)) {
git.rm(path.join(repoDir, p), { recursive: true });
}
}
}
fs.copySync(this.dir, repoDir, { recursive: true });
}
extractRepoURL(modules) {
const repos = new Set(modules.map(m => m.repoURL));
if (repos.size === 0) {
throw new Error('Unable to detect repository from module files.');
}
if (repos.size > 1) {
throw new Error('Multiple repositories found in module files');
}
return repos.values().next().value;
}
extractVersion(moduleDirectory) {
const versionFile = path.join(moduleDirectory, 'version');
const repoVersion = this.version;
const moduleVersion = fs.existsSync(versionFile) ? fs.readFileSync(versionFile).toString() : undefined;
if (repoVersion && moduleVersion && repoVersion !== moduleVersion) {
throw new Error(`Repo version (${repoVersion}) conflicts with module version (${moduleVersion}) for module in ${moduleDirectory}`);
}
// just take the one thats defined, they have to the same if both are.
const version = moduleVersion ? moduleVersion : repoVersion;
if (!version) {
throw new Error(`Unable to determine version of module ${moduleDirectory}. `
+ "Either include a 'version' file, or specify a global version using the VERSION environment variable.");
}
return version;
}
}
exports.GoReleaser = GoReleaser;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ28uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGFyZ2V0cy9nby50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwyQ0FBNkI7QUFDN0IsNkNBQStCO0FBQy9CLGlEQUFtQztBQUNuQywrQ0FBaUM7QUFDakMscURBQXVDO0FBcUh2Qzs7R0FFRztBQUNILE1BQWEsVUFBVTtJQVdyQixZQUFZLEtBQXNCO1FBRWhDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3RUFBd0UsQ0FBQyxDQUFDO1FBQzVGLENBQUM7UUFFRCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDN0IsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDdEMsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDN0UsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQztRQUN4QyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDO1FBRXBDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxRQUFRLElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRWhELElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLGdHQUFnRyxDQUFDLENBQUM7UUFDcEgsQ0FBQztRQUVELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNsQixNQUFNLElBQUksS0FBSyxDQUFDLG9HQUFvRyxDQUFDLENBQUM7UUFDeEgsQ0FBQztRQUVELElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksT0FBTztRQUNaLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlDLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN6QixPQUFPLENBQUMsR0FBRyxDQUFDLCtCQUErQixDQUFDLENBQUM7WUFDN0MsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztRQUVyRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRXBELE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixJQUFJLENBQUMsU0FBUyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQzlGLENBQUM7UUFDRCxNQUFNLFlBQVksR0FBRztZQUNuQixJQUFJLEVBQUUsSUFBSSxFQUFFLGtFQUFrRTtZQUM5RSxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTO1NBQ2xELENBQUM7UUFFRixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFMUMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQztZQUNILE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdkIsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxQyxDQUFDO2dCQUFTLENBQUM7WUFDVCxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLENBQUM7SUFFSCxDQUFDO0lBRU8sU0FBUyxDQUFDLE9BQW1CLEVBQUUsT0FBZTtRQUVwRCxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2xELEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFdkIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNiLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQztZQUNyQixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixDQUFDLENBQUM7WUFDNUMsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNqRixHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRTFCLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNoQixLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzdCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdkMsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM5QixJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFBQyxDQUFDO1FBQ25DLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1lBQ3hELE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVELE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRXZDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNkNBQTZDLENBQUMsQ0FBQztZQUMzRCxPQUFPLENBQUMsR0FBRyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7WUFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1lBQzNELElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLCtCQUErQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDckUsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLENBQUM7UUFDRCxPQUFPLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUMxQyxDQUFDO0lBRU8sY0FBYyxDQUFDLEdBQVc7UUFDaEMsTUFBTSxPQUFPLEdBQWUsRUFBRSxDQUFDO1FBQy9CLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM5QyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDNUMsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQzNCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQzFDLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVPLFdBQVcsQ0FBQyxPQUFlO1FBRWpDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQzNELE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFbkQsMkZBQTJGO1FBQzNGLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLDRDQUE0QyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3pFLENBQUM7UUFFRCxtREFBbUQ7UUFDbkQsTUFBTSxjQUFjLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWhDLGlFQUFpRTtRQUNqRSxNQUFNLG1CQUFtQixHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFdEQscUNBQXFDO1FBQ3JDLE1BQU0sT0FBTyxHQUFHLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRTFELFdBQVc7UUFDWCxNQUFNLGtCQUFrQixHQUFHLFlBQVksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUV2RSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7WUFDakQsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsT0FBTywyQkFBMkIsa0JBQWtCLDRDQUE0QyxDQUFDLENBQUM7UUFDOUksQ0FBQztRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDdEMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQzFDLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELE9BQU8sUUFBUSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ2hHLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxRQUFRLEdBQUcsbUJBQW1CO2FBQy9CLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQywyQkFBMkI7YUFDcEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsc0JBQXNCO1FBRXBDLCtCQUErQjtRQUMvQixnQkFBZ0I7UUFDaEIsb0JBQW9CO1FBQ3BCLGtCQUFrQjtRQUNsQixzQ0FBc0M7UUFDdEMsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNsQyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksWUFBWSxFQUFFLEVBQUUsQ0FBQztZQUNuRCxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDWixRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBRUQseURBQXlEO1FBQ3pELFFBQVEsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7UUFFdkYsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUVqRSxDQUFDO0lBRU8sWUFBWSxDQUFDLENBQVc7UUFDOUIsT0FBTyxDQUFDLENBQUMsUUFBUSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDN0UsQ0FBQztJQUVPLG1CQUFtQixDQUFDLE9BQW1CO1FBQzdDLE1BQU0sUUFBUSxHQUFHLGdCQUFnQixDQUFDO1FBQ2xDLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUN0RCxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEIsOENBQThDO1lBQzlDLE9BQU8sR0FBRyxRQUFRLE1BQU0sUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzNELENBQUM7YUFBTSxDQUFDO1lBQ04seUZBQXlGO1lBQ3pGLE9BQU8sR0FBRyxRQUFRLEtBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM1RyxDQUFDO0lBQ0gsQ0FBQztJQUVPLFFBQVEsQ0FBQyxPQUFlO1FBQzlCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzlDLElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQzVCLHVEQUF1RDtZQUN2RCwwQkFBMEI7WUFDMUIsRUFBRSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUM7aUJBQ3BCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxNQUFNLENBQUM7aUJBQ3pCLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7YUFBTSxDQUFDO1lBQ04sd0RBQXdEO1lBQ3hELEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUN4QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ2xELElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO29CQUM3QixHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ3JELENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRU8sY0FBYyxDQUFDLE9BQW1CO1FBQ3hDLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxDQUFTLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUMzRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1FBQ3BFLENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFNLENBQUM7SUFDdEMsQ0FBQztJQUVPLGNBQWMsQ0FBQyxlQUF1QjtRQUU1QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUUxRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ2pDLE1BQU0sYUFBYSxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUV2RyxJQUFJLFdBQVcsSUFBSSxhQUFhLElBQUksV0FBVyxLQUFLLGFBQWEsRUFBRSxDQUFDO1lBQ2xFLE1BQU0sSUFBSSxLQUFLLENBQUMsaUJBQWlCLFdBQVcsb0NBQW9DLGFBQWEsbUJBQW1CLGVBQWUsRUFBRSxDQUFDLENBQUM7UUFDckksQ0FBQztRQUVELHNFQUFzRTtRQUN0RSxNQUFNLE9BQU8sR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1FBRTVELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLGVBQWUsSUFBSTtrQkFDeEUsc0dBQXNHLENBQUMsQ0FBQztRQUM5RyxDQUFDO1FBRUQsT0FBTyxPQUFPLENBQUM7SUFFakIsQ0FBQztDQUVGO0FBNVBELGdDQTRQQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgKiBhcyBnaXQgZnJvbSAnLi4vaGVscC9naXQnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnLi4vaGVscC9vcyc7XG5pbXBvcnQgKiBhcyBzaGVsbCBmcm9tICcuLi9oZWxwL3NoZWxsJztcblxuLyoqXG4gKiBFbmNhcHN1bGF0ZXMgc29tZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcmVsZWFzZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHb1JlbGVhc2Uge1xuXG4gIC8qKlxuICAgKiBUaGUgdGFncyB0aGUgcmVsZWFzZSBjcmVhdGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgdGFncz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgY29tbWl0IG1lc3NhZ2Ugb2YgdGhlIHJlbGVhc2UuXG4gICAqL1xuICByZWFkb25seSBjb21taXRNZXNzYWdlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgZGlyZWN0b3J5IHdoZXJlIHRoZSByZXBvc2l0b3J5IHdhcyByZWxlYXNlZCBmcm9tLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVwb0Rpcj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBgR29SZWxlYXNlcmAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR29SZWxlYXNlclByb3BzIHtcblxuICAvKipcbiAgICogVGhlIHNvdXJjZSBjb2RlIGRpcmVjdG9yeS5cbiAgICpcbiAgICogQGRlZmF1bHQgJ2Rpc3QvZ28nXG4gICAqL1xuICByZWFkb25seSBkaXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGUgYSBkcnkgcnVuIG9ubHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkcnlSdW4/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgYnJhbmNoIHRvIHB1c2ggdG8uXG4gICAqXG4gICAqIEBkZWZhdWx0ICdtYWluJ1xuICAgKi9cbiAgcmVhZG9ubHkgYnJhbmNoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgdXNlcm5hbWUgdG8gdXNlIGZvciB0aGUgY29tbWl0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRha2VuIGZyb20gZ2l0IGNvbmZpZy4gdGhyb3dzIGlmIG5vdCBjb25maWd1cmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgdXNlcm5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBlbWFpbCB0byB1c2UgZm9yIHRoZSBjb21taXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGFrZW4gZnJvbSBnaXQgY29uZmlnLiB0aHJvd3MgaWYgbm90IGNvbmZpZ3VyZWQuXG4gICAqL1xuICByZWFkb25seSBlbWFpbD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHZlcnNpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGFrZW4gZnJvbSB0aGUgJ3ZlcnNpb24nLiB0aHJvd3MgaWYgZG9lc24ndCBleGlzdC5cbiAgICovXG4gIHJlYWRvbmx5IHZlcnNpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBtZXNzYWdlIHRvIHVzZSBmb3IgdGhlIGNvbW1pdCBtYXJraW5nIHRoZSByZWxlYXNlLlxuICAgKi9cbiAgcmVhZG9ubHkgbWVzc2FnZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGdpdCBjbG9uZSBkZXB0aC5cbiAgICpcbiAgICogVXN1YWxseSBvbmx5IHRoZSBsYXRlc3QgY29tbWl0IGlzIHJlcXVpcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICByZWFkb25seSBjbG9uZURlcHRoPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEluZm9ybWF0aW9uIGFib3V0IGEgc3BlY2lmaWMgbW9kdWxlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdvTW9kdWxlIHtcblxuICAvKipcbiAgICogUGF0aCB0byB0aGUgbW9kIGZpbGUuXG4gICAqL1xuICByZWFkb25seSBtb2RGaWxlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBtb2R1bGUuXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBjYW5ub25pY2FsIG5hbWUgb2YgdGhlIG1vZHVsZS4gKGUuZyAnZ2l0aHViLmNvbS9hd3MvY29uc3RydWN0cy1nby9jb25zdHJ1Y3RzL3YzYClcbiAgICovXG4gIHJlYWRvbmx5IGNhbm5vbmljYWxOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoIGluc2lkZSB0aGUgcmVwb3NpdG9yeSB0aGUgbW9kdWxlIGlzIGxvY2F0ZWQgaW4uIChlLmcgJ2NvbnN0cnVjdHMnKVxuICAgKi9cbiAgcmVhZG9ubHkgcmVwb1BhdGg6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHJlcG9zaXRvcnkgVVJMLiAoZS5nICdnaXRodWIuY29tL2F3cy9jb25zdHJ1Y3RzJylcbiAgICovXG4gIHJlYWRvbmx5IHJlcG9VUkw6IHN0cmluZztcblxufVxuXG4vKipcbiAqIFJlbGVhc2UgYSBzZXQgb2YgR29sYW5nIG1vZHVsZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBHb1JlbGVhc2VyIHtcblxuICBwcml2YXRlIHJlYWRvbmx5IHZlcnNpb24/OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZ2l0Q29tbWl0TWVzc2FnZT86IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGRpcjogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGRyeVJ1bjogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBnaXRCcmFuY2g6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBnaXRVc2VybmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGdpdFVzZXJlbWFpbDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBHb1JlbGVhc2VyUHJvcHMpIHtcblxuICAgIGlmICghc2hlbGwud2hpY2goJ2dpdCcpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dpdCBtdXN0IGJlIGF2YWlsYWJsZSB0byBpbiBvcmRlciB0byBiZSBhYmxlIHRvIHB1c2ggR28gY29kZSB0byBHaXRIdWInKTtcbiAgICB9XG5cbiAgICB0aGlzLnZlcnNpb24gPSBwcm9wcy52ZXJzaW9uO1xuICAgIHRoaXMuZ2l0Q29tbWl0TWVzc2FnZSA9IHByb3BzLm1lc3NhZ2U7XG4gICAgdGhpcy5kaXIgPSBwYXRoLnJlc29sdmUocHJvcHMuZGlyID8/IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCAnZGlzdCcsICdnbycpKTtcbiAgICB0aGlzLmdpdEJyYW5jaCA9IHByb3BzLmJyYW5jaCA/PyAnbWFpbic7XG4gICAgdGhpcy5kcnlSdW4gPSBwcm9wcy5kcnlSdW4gPz8gZmFsc2U7XG5cbiAgICBjb25zdCBnaXRVc2VybmFtZSA9IHByb3BzLnVzZXJuYW1lID8/IGdpdC51c2VybmFtZSgpO1xuICAgIGNvbnN0IGdpdFVzZXJlbWFpbCA9IHByb3BzLmVtYWlsID8/IGdpdC5lbWFpbCgpO1xuXG4gICAgaWYgKCFnaXRVc2VybmFtZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gZGV0ZWN0IHVzZXJuYW1lLiBlaXRoZXIgY29uZmlndXJlIGEgZ2l0IHVzZXIubmFtZSBvciBwYXNzIEdJVF9VU0VSX05BTUUgZW52IHZhcmlhYmxlJyk7XG4gICAgfVxuXG4gICAgaWYgKCFnaXRVc2VyZW1haWwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGRldGVjdCB1c2VyIGVtYWlsLiBlaXRoZXIgY29uZmlndXJlIGEgZ2l0IHVzZXIuZW1haWwgb3IgcGFzcyBHSVRfVVNFUl9FTUFJTCBlbnYgdmFyaWFibGUnKTtcbiAgICB9XG5cbiAgICB0aGlzLmdpdFVzZXJlbWFpbCA9IGdpdFVzZXJlbWFpbDtcbiAgICB0aGlzLmdpdFVzZXJuYW1lID0gZ2l0VXNlcm5hbWU7XG4gIH1cblxuICAvKipcbiAgICogUnVuIHRoZSByZWxlYXNlIHByb2Nlc3MuXG4gICAqXG4gICAqIEByZXR1cm5zIG1ldGFkYXRhIGFib3V0IHRoZSByZWxlYXNlLlxuICAgKi9cbiAgcHVibGljIHJlbGVhc2UoKTogR29SZWxlYXNlIHtcbiAgICBjb25zdCBtb2R1bGVzID0gdGhpcy5jb2xsZWN0TW9kdWxlcyh0aGlzLmRpcik7XG4gICAgaWYgKG1vZHVsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zb2xlLmxvZygnTm8gbW9kdWxlcyBkZXRlY3RlZC4gU2tpcHBpbmcnKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZygnRGV0ZWN0ZWQgbW9kdWxlczonKTtcbiAgICBtb2R1bGVzLmZvckVhY2gobSA9PiBjb25zb2xlLmxvZyhgIC0gJHttLm1vZEZpbGV9YCkpO1xuXG4gICAgY29uc3QgcmVwb1VSTCA9IHRoaXMuZXh0cmFjdFJlcG9VUkwobW9kdWxlcyk7XG4gICAgY29uc3QgcmVwb0RpciA9IHBhdGguam9pbihvcy5ta2R0ZW1wU3luYygpLCAncmVwbycpO1xuXG4gICAgY29uc3QgYnJhbmNoRXhpc3RzID0gZ2l0LmJyYW5jaEV4aXN0c09uUmVtb3RlKHJlcG9VUkwsIHRoaXMuZ2l0QnJhbmNoKTtcbiAgICBpZiAoIWJyYW5jaEV4aXN0cykge1xuICAgICAgY29uc29sZS5sb2coYFJlbW90ZSBicmFuY2ggJyR7dGhpcy5naXRCcmFuY2h9JyBub3QgZm91bmQsIGNvbnRpbnVpbmcgd2l0aCBkZWZhdWx0IGJyYW5jaC5gKTtcbiAgICB9XG4gICAgY29uc3QgY2xvbmVPcHRpb25zID0ge1xuICAgICAgdGFnczogdHJ1ZSwgLy8gd2UgbmVlZCB0byBrbm93IGFib3V0IGFsbCB0YWdzIHRvIG5vdCByZS1jcmVhdGUgYW4gZXhpc3Rpbmcgb25lXG4gICAgICBicmFuY2g6IGJyYW5jaEV4aXN0cyA/IHRoaXMuZ2l0QnJhbmNoIDogdW5kZWZpbmVkLFxuICAgIH07XG5cbiAgICBnaXQuY2xvbmUocmVwb1VSTCwgcmVwb0RpciwgY2xvbmVPcHRpb25zKTtcblxuICAgIGNvbnN0IGN3ZCA9IHByb2Nlc3MuY3dkKCk7XG4gICAgdHJ5IHtcbiAgICAgIHByb2Nlc3MuY2hkaXIocmVwb0Rpcik7XG4gICAgICByZXR1cm4gdGhpcy5kb1JlbGVhc2UobW9kdWxlcywgcmVwb0Rpcik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHByb2Nlc3MuY2hkaXIoY3dkKTtcbiAgICB9XG5cbiAgfVxuXG4gIHByaXZhdGUgZG9SZWxlYXNlKG1vZHVsZXM6IEdvTW9kdWxlW10sIHJlcG9EaXI6IHN0cmluZyk6IEdvUmVsZWFzZSB7XG5cbiAgICBnaXQuaWRlbnRpZnkodGhpcy5naXRVc2VybmFtZSwgdGhpcy5naXRVc2VyZW1haWwpO1xuICAgIGdpdC5jaGVja291dCh0aGlzLmdpdEJyYW5jaCwgeyBjcmVhdGVJZk1pc3Npbmc6IHRydWUgfSk7XG4gICAgdGhpcy5zeW5jUmVwbyhyZXBvRGlyKTtcblxuICAgIGdpdC5hZGQoJy4nKTtcbiAgICBpZiAoIWdpdC5kaWZmSW5kZXgoKSkge1xuICAgICAgY29uc29sZS5sb2coJ05vIGNoYW5nZXMuIFNraXBwaW5nIHJlbGVhc2UnKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICBjb25zdCBjb21taXRNZXNzYWdlID0gdGhpcy5naXRDb21taXRNZXNzYWdlID8/IHRoaXMuYnVpbGRSZWxlYXNlTWVzc2FnZShtb2R1bGVzKTtcbiAgICBnaXQuY29tbWl0KGNvbW1pdE1lc3NhZ2UpO1xuXG4gICAgY29uc3QgdGFncyA9IFtdO1xuICAgIGZvciAoY29uc3QgbW9kdWxlIG9mIG1vZHVsZXMpIHtcbiAgICAgIGNvbnN0IG5hbWUgPSB0aGlzLmJ1aWxkVGFnTmFtZShtb2R1bGUpO1xuICAgICAgY29uc3QgY3JlYXRlZCA9IGdpdC50YWcobmFtZSk7XG4gICAgICBpZiAoY3JlYXRlZCkgeyB0YWdzLnB1c2gobmFtZSk7IH1cbiAgICB9XG5cbiAgICBpZiAodGFncy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKCdBbGwgdGFncyBhbHJlYWR5IGV4aXN0LiBTa2lwcGluZyByZWxlYXNlJyk7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgY29uc3QgcmVmcyA9IFsuLi50YWdzLCB0aGlzLmdpdEJyYW5jaF07XG5cbiAgICBpZiAodGhpcy5kcnlSdW4pIHtcbiAgICAgIGNvbnNvbGUubG9nKCc9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Jyk7XG4gICAgICBjb25zb2xlLmxvZygnICAgICAgICAgICAg8J+PnO+4jyBEUlktUlVOIE1PREUg8J+PnO+4jycpO1xuICAgICAgY29uc29sZS5sb2coJz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0nKTtcbiAgICAgIHJlZnMuZm9yRWFjaCh0ID0+IGNvbnNvbGUubG9nKGBSZW1vdGUgcmVmIHdpbGwgYmUgdXBkYXRlZDogJHt0fWApKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVmcy5mb3JFYWNoKHQgPT4gZ2l0LnB1c2godCkpO1xuICAgIH1cbiAgICByZXR1cm4geyB0YWdzLCBjb21taXRNZXNzYWdlLCByZXBvRGlyIH07XG4gIH1cblxuICBwcml2YXRlIGNvbGxlY3RNb2R1bGVzKGRpcjogc3RyaW5nKTogR29Nb2R1bGVbXSB7XG4gICAgY29uc3QgbW9kdWxlczogR29Nb2R1bGVbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcCBvZiBbLi4uZnMucmVhZGRpclN5bmMoZGlyKSwgJy4nXSkge1xuICAgICAgY29uc3QgbW9kRmlsZSA9IHBhdGguam9pbihkaXIsIHAsICdnby5tb2QnKTtcbiAgICAgIGlmIChmcy5leGlzdHNTeW5jKG1vZEZpbGUpKSB7XG4gICAgICAgIG1vZHVsZXMucHVzaCh0aGlzLnBhcnNlTW9kdWxlKG1vZEZpbGUpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG1vZHVsZXM7XG4gIH1cblxuICBwcml2YXRlIHBhcnNlTW9kdWxlKG1vZEZpbGU6IHN0cmluZyk6IEdvTW9kdWxlIHtcblxuICAgIGNvbnN0IHZlcnNpb24gPSB0aGlzLmV4dHJhY3RWZXJzaW9uKHBhdGguZGlybmFtZShtb2RGaWxlKSk7XG4gICAgY29uc3QgbWFqb3JWZXJzaW9uID0gTnVtYmVyKHZlcnNpb24uc3BsaXQoJy4nKVswXSk7XG5cbiAgICAvLyBleHRyYWN0IHRoZSBtb2R1bGUgZGVjbGVyYXRpb24gKGUuZyAnbW9kdWxlIGdpdGh1Yi5jb20vYXdzL2NvbnN0cnVjdHMtZ28vY29uc3RydWN0cy92MycpXG4gICAgY29uc3QgbWF0Y2ggPSBmcy5yZWFkRmlsZVN5bmMobW9kRmlsZSkudG9TdHJpbmcoKS5tYXRjaCgvbW9kdWxlICguKikvKTtcbiAgICBpZiAoIW1hdGNoIHx8ICFtYXRjaFsxXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZGV0ZWN0ZWQgbW9kdWxlIGRlY2xhcmF0aW9uIGluICR7bW9kRmlsZX1gKTtcbiAgICB9XG5cbiAgICAvLyBlLmcgJ2dpdGh1Yi5jb20vYXdzL2NvbnN0cnVjdHMtZ28vY29uc3RydWN0cy92MydcbiAgICBjb25zdCBjYW5ub25pY2FsTmFtZSA9IG1hdGNoWzFdO1xuXG4gICAgLy8gZS5nIFsnZ2l0aHViLmNvbScsICdhd3MnLCAnY29uc3RydWN0cy1nbycsICdjb25zdHJ1Y3RzJywgJ3YzJ11cbiAgICBjb25zdCBjYW5ub25pY2FsTmFtZVBhcnRzID0gY2Fubm9uaWNhbE5hbWUuc3BsaXQoJy8nKTtcblxuICAgIC8vIGUuZyAnZ2l0aHViLmNvbS9hd3MvY29uc3RydWN0cy1nbydcbiAgICBjb25zdCByZXBvVVJMID0gY2Fubm9uaWNhbE5hbWVQYXJ0cy5zbGljZSgwLCAzKS5qb2luKCcvJyk7XG5cbiAgICAvLyBlLmcgJ3YzJ1xuICAgIGNvbnN0IG1ham9yVmVyc2lvblN1ZmZpeCA9IG1ham9yVmVyc2lvbiA+IDEgPyBgL3Yke21ham9yVmVyc2lvbn1gIDogJyc7XG5cbiAgICBpZiAoIWNhbm5vbmljYWxOYW1lLmVuZHNXaXRoKG1ham9yVmVyc2lvblN1ZmZpeCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTW9kdWxlIGRlY2xhcmF0aW9uIGluICcke21vZEZpbGV9JyBleHBlY3RlZCB0byBlbmQgd2l0aCAnJHttYWpvclZlcnNpb25TdWZmaXh9JyBzaW5jZSBpdHMgbWFqb3IgdmVyc2lvbiBpcyBsYXJnZXIgdGhhbiAxYCk7XG4gICAgfVxuXG4gICAgaWYgKCFyZXBvVVJMLnN0YXJ0c1dpdGgoJ2dpdGh1Yi5jb20nKSkge1xuICAgICAgaWYgKCEoZ2l0LmRldGVjdFNTSCgpIHx8IGdpdC5kZXRlY3RHSEUoKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZXBvc2l0b3J5IG11c3QgYmUgaG9zdGVkIG9uIGdpdGh1Yi5jb20uIEZvdW5kOiAnJHtyZXBvVVJMfScgaW4gJHttb2RGaWxlfWApO1xuICAgICAgfVxuICAgIH1cbiAgICBsZXQgcmVwb1BhdGggPSBjYW5ub25pY2FsTmFtZVBhcnRzXG4gICAgICAuc2xpY2UoMykgLy8gZS5nIFsnY29uc3RydWN0cycsICd2MyddXG4gICAgICAuam9pbignLycpOyAvLyBlLmcgJ2NvbnN0cnVjdHMvdjMnXG5cbiAgICAvLyB3ZSBjb3VsZCBoYXZlIHNvbWV0aGluZyBsaWtlXG4gICAgLy8gY29uc3RydWN0cy92M1xuICAgIC8vIG9yIHNvbWV0aGluZyBsaWtlXG4gICAgLy8gY29uc3RydWN0c3YzL3YzXG4gICAgLy8gd2Ugb25seSB3YW50IHRvIHN0cmlwIHRoZSBsYXN0ICd2MydcbiAgICBjb25zdCBzcGxpdCA9IHJlcG9QYXRoLnNwbGl0KCcvJyk7XG4gICAgaWYgKHNwbGl0W3NwbGl0Lmxlbmd0aCAtIDFdID09PSBgdiR7bWFqb3JWZXJzaW9ufWApIHtcbiAgICAgIHNwbGl0LnBvcCgpO1xuICAgICAgcmVwb1BhdGggPSBzcGxpdC5qb2luKCcvJyk7XG4gICAgfVxuXG4gICAgLy8gc3RyaXAgJy8nIGlmIGV4aXN0cyAod29udCBleGlzdCBmb3IgdG9wIGxldmVsIG1vZHVsZXMpXG4gICAgcmVwb1BhdGggPSByZXBvUGF0aC5lbmRzV2l0aCgnLycpID8gcmVwb1BhdGguc3Vic3RyKDAsIHJlcG9QYXRoLmxlbmd0aCAtIDEpIDogcmVwb1BhdGg7XG5cbiAgICByZXR1cm4geyBtb2RGaWxlLCB2ZXJzaW9uLCBjYW5ub25pY2FsTmFtZSwgcmVwb1BhdGgsIHJlcG9VUkwgfTtcblxuICB9XG5cbiAgcHJpdmF0ZSBidWlsZFRhZ05hbWUobTogR29Nb2R1bGUpIHtcbiAgICByZXR1cm4gbS5yZXBvUGF0aCA9PT0gJycgPyBgdiR7bS52ZXJzaW9ufWAgOiBgJHttLnJlcG9QYXRofS92JHttLnZlcnNpb259YDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRSZWxlYXNlTWVzc2FnZShtb2R1bGVzOiBHb01vZHVsZVtdKSB7XG4gICAgY29uc3Qgc2VtYW50aWMgPSAnY2hvcmUocmVsZWFzZSknO1xuICAgIGNvbnN0IHZlcnNpb25zID0gbmV3IFNldChtb2R1bGVzLm1hcChtID0+IG0udmVyc2lvbikpO1xuICAgIGlmICh2ZXJzaW9ucy5zaXplID09PSAxKSB7XG4gICAgICAvLyBzaW5nbGUgdmVyc2lvbiAoZS5nIGNob3JlKHJlbGVhc2UpOiB2MS4yLjMpXG4gICAgICByZXR1cm4gYCR7c2VtYW50aWN9OiB2JHt2ZXJzaW9ucy52YWx1ZXMoKS5uZXh0KCkudmFsdWV9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gbXVsdGlwbGUgdmVyc2lvbnMgKGUuZyBjaG9yZShyZWxlYXNlKTogY2hvcmUocmVsZWFzZSk6IG1vZHVsZTFAdjEuMi4zICBtb2R1bGUyQHYxLjIuMylcbiAgICAgIHJldHVybiBgJHtzZW1hbnRpY306ICR7bW9kdWxlcy5tYXAobSA9PiBgJHttLnJlcG9QYXRoID8gYCR7bS5yZXBvUGF0aH1AYCA6ICcnfXYke20udmVyc2lvbn1gKS5qb2luKCcgJyl9YDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN5bmNSZXBvKHJlcG9EaXI6IHN0cmluZykge1xuICAgIGNvbnN0IHRvcExldmVsID0gcGF0aC5qb2luKHJlcG9EaXIsICdnby5tb2QnKTtcbiAgICBpZiAoZnMuZXhpc3RzU3luYyh0b3BMZXZlbCkpIHtcbiAgICAgIC8vIHdpdGggdG9wIGxldmVsIG1vZHVsZXMgd2Ugc3luYyB0aGUgZW50aXJlIHJlcG9zaXRvcnlcbiAgICAgIC8vIHNvIHdlIGp1c3QgZW1wdHkgaXQgb3V0XG4gICAgICBmcy5yZWFkZGlyU3luYyhyZXBvRGlyKVxuICAgICAgICAuZmlsdGVyKGYgPT4gZiAhPT0gJy5naXQnKVxuICAgICAgICAuZm9yRWFjaChmID0+IGdpdC5ybShwYXRoLmpvaW4ocmVwb0RpciwgZiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gb3RoZXJ3aXNlLCB3ZSBzZWxlY3RpdmVseSByZW1vdmUgdGhlIHN1Ym1vZHVsZXMgb25seS5cbiAgICAgIGZvciAoY29uc3QgcCBvZiBmcy5yZWFkZGlyU3luYyhyZXBvRGlyKSkge1xuICAgICAgICBjb25zdCBzdWJtb2R1bGUgPSBwYXRoLmpvaW4ocmVwb0RpciwgcCwgJ2dvLm1vZCcpO1xuICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhzdWJtb2R1bGUpKSB7XG4gICAgICAgICAgZ2l0LnJtKHBhdGguam9pbihyZXBvRGlyLCBwKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZnMuY29weVN5bmModGhpcy5kaXIsIHJlcG9EaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBleHRyYWN0UmVwb1VSTChtb2R1bGVzOiBHb01vZHVsZVtdKTogc3RyaW5nIHtcbiAgICBjb25zdCByZXBvcyA9IG5ldyBTZXQ8c3RyaW5nPihtb2R1bGVzLm1hcChtID0+IG0ucmVwb1VSTCkpO1xuICAgIGlmIChyZXBvcy5zaXplID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBkZXRlY3QgcmVwb3NpdG9yeSBmcm9tIG1vZHVsZSBmaWxlcy4nKTtcbiAgICB9XG4gICAgaWYgKHJlcG9zLnNpemUgPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ011bHRpcGxlIHJlcG9zaXRvcmllcyBmb3VuZCBpbiBtb2R1bGUgZmlsZXMnKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcG9zLnZhbHVlcygpLm5leHQoKS52YWx1ZSE7XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RWZXJzaW9uKG1vZHVsZURpcmVjdG9yeTogc3RyaW5nKTogc3RyaW5nIHtcblxuICAgIGNvbnN0IHZlcnNpb25GaWxlID0gcGF0aC5qb2luKG1vZHVsZURpcmVjdG9yeSwgJ3ZlcnNpb24nKTtcblxuICAgIGNvbnN0IHJlcG9WZXJzaW9uID0gdGhpcy52ZXJzaW9uO1xuICAgIGNvbnN0IG1vZHVsZVZlcnNpb24gPSBmcy5leGlzdHNTeW5jKHZlcnNpb25GaWxlKSA/IGZzLnJlYWRGaWxlU3luYyh2ZXJzaW9uRmlsZSkudG9TdHJpbmcoKSA6IHVuZGVmaW5lZDtcblxuICAgIGlmIChyZXBvVmVyc2lvbiAmJiBtb2R1bGVWZXJzaW9uICYmIHJlcG9WZXJzaW9uICE9PSBtb2R1bGVWZXJzaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlcG8gdmVyc2lvbiAoJHtyZXBvVmVyc2lvbn0pIGNvbmZsaWN0cyB3aXRoIG1vZHVsZSB2ZXJzaW9uICgke21vZHVsZVZlcnNpb259KSBmb3IgbW9kdWxlIGluICR7bW9kdWxlRGlyZWN0b3J5fWApO1xuICAgIH1cblxuICAgIC8vIGp1c3QgdGFrZSB0aGUgb25lIHRoYXRzIGRlZmluZWQsIHRoZXkgaGF2ZSB0byB0aGUgc2FtZSBpZiBib3RoIGFyZS5cbiAgICBjb25zdCB2ZXJzaW9uID0gbW9kdWxlVmVyc2lvbiA/IG1vZHVsZVZlcnNpb24gOiByZXBvVmVyc2lvbjtcblxuICAgIGlmICghdmVyc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZGV0ZXJtaW5lIHZlcnNpb24gb2YgbW9kdWxlICR7bW9kdWxlRGlyZWN0b3J5fS4gYFxuICAgICAgICArIFwiRWl0aGVyIGluY2x1ZGUgYSAndmVyc2lvbicgZmlsZSwgb3Igc3BlY2lmeSBhIGdsb2JhbCB2ZXJzaW9uIHVzaW5nIHRoZSBWRVJTSU9OIGVudmlyb25tZW50IHZhcmlhYmxlLlwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmVyc2lvbjtcblxuICB9XG5cbn1cbiJdfQ==