projen
Version:
CDK for software projects
271 lines • 42.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.bump = bump;
const fs_1 = require("fs");
const path_1 = require("path");
const semver_1 = require("semver");
const logging = require("../logging");
const util_1 = require("../util");
const version_1 = require("../version");
/**
* Resolves the latest version from git tags and uses `commit-and-tag-version` to bump
* to the next version based on commits.
*
* This expects `commit-and-tag-version` to be installed in the path.
*
* @param cwd working directory (git repository)
* @param options options
*/
async function bump(cwd, options) {
const versionFile = (0, path_1.join)(cwd, options.versionFile);
const prerelease = options.prerelease;
const major = options.majorVersion;
const minor = options.minorVersion;
const minMajorVersion = options.minMajorVersion;
const prefix = options.tagPrefix ?? "";
const bumpFile = (0, path_1.join)(cwd, options.bumpFile);
const changelogFile = (0, path_1.join)(cwd, options.changelog);
const releaseTagFile = (0, path_1.join)(cwd, options.releaseTagFile);
const bumpPackage = options.bumpPackage ?? "commit-and-tag-version@^12";
if (major && minMajorVersion) {
throw new Error(`minMajorVersion and majorVersion cannot be used together.`);
}
if (options.nextVersionCommand && minMajorVersion) {
throw new Error(`minMajorVersion and nextVersionCommand cannot be used together.`);
}
if (minor && !major) {
throw new Error(`minorVersion and majorVersion must be used together.`);
}
await fs_1.promises.mkdir((0, path_1.dirname)(bumpFile), { recursive: true });
await fs_1.promises.mkdir((0, path_1.dirname)(changelogFile), { recursive: true });
await fs_1.promises.mkdir((0, path_1.dirname)(releaseTagFile), { recursive: true });
const { latestVersion, latestTag, isFirstRelease } = determineLatestTag({
cwd,
major,
minor,
prerelease,
prefix,
});
const { contents, newline } = await tryReadVersionFile(versionFile);
// update version
contents.version = latestVersion;
logging.info(`Update ${versionFile} to latest resolved version: ${latestVersion}`);
await fs_1.promises.writeFile(versionFile, JSON.stringify(contents, undefined, 2) + (newline ? "\n" : ""));
// check for commits since the last release tag
let skipBump = false;
let restoreTag = false;
// First Release is never skipping bump
if (!isFirstRelease) {
const findCommits = (options.releasableCommits ?? version_1.ReleasableCommits.everyCommit().cmd).replace("$LATEST_TAG", latestTag);
const commitsSinceLastTag = (0, util_1.execOrUndefined)(findCommits, { cwd })?.split("\n");
const numCommitsSinceLastTag = commitsSinceLastTag?.length ?? 0;
logging.info(`Number of commits since ${latestTag}: ${numCommitsSinceLastTag}`);
// Nothing to release right now
if (numCommitsSinceLastTag === 0) {
logging.info("Skipping bump...");
skipBump = true;
restoreTag = true;
// delete the existing tag (locally)
// if we don't do this, commit-and-tag-version generates an empty changelog
(0, util_1.exec)(`git tag --delete ${latestTag}`, { cwd });
}
}
// Determine what version to release as
let releaseAs;
if (minMajorVersion) {
const [majorVersion] = latestVersion.split(".");
const majorVersionNumber = parseInt(majorVersion, 10);
if (majorVersionNumber < minMajorVersion) {
releaseAs = `${minMajorVersion}.0.0`;
}
}
else if (options.nextVersionCommand) {
const nextVersion = (0, util_1.execCapture)(options.nextVersionCommand, {
cwd,
modEnv: {
VERSION: latestVersion,
...(latestTag ? { LATEST_TAG: latestTag } : {}),
},
})
.toString()
.trim();
if (nextVersion) {
// Calculate the next version
if (isReleaseType(nextVersion)) {
releaseAs = (0, semver_1.inc)(latestVersion, nextVersion)?.toString();
}
else if (isFullVersionString(nextVersion) &&
nextVersion !== latestVersion) {
releaseAs = nextVersion;
}
else {
throw new Error(`nextVersionCommand "${options.nextVersionCommand}" returned invalid version: ${nextVersion}`);
}
// Don't need to validate if the final version is within the expected declared major.minor range,
// if given. That is done below after bumping.
}
}
// If the nextVersionCommand forced a specific release version, we shouldn't
// skip the bump action.
if (releaseAs) {
skipBump = false;
}
// create a commit-and-tag-version configuration file
const rcfile = (0, path_1.join)(cwd, ".versionrc.json");
await generateVersionrcFile(rcfile, versionFile, changelogFile, skipBump, prerelease, options.versionrcOptions);
const cmd = ["npx", bumpPackage];
if (isFirstRelease && !minMajorVersion) {
cmd.push("--first-release");
}
if (prefix) {
cmd.push(`--tag-prefix ${prefix}v`);
}
if (releaseAs) {
cmd.push(`--release-as ${releaseAs}`);
}
(0, util_1.exec)(cmd.join(" "), { cwd });
// add the tag back if it was previously removed
if (restoreTag) {
(0, util_1.exec)(`git tag ${latestTag}`, { cwd });
}
await fs_1.promises.rm(rcfile, { force: true, recursive: true });
const newVersion = (await tryReadVersionFile(versionFile)).version;
if (!newVersion) {
throw new Error(`bump failed: ${versionFile} does not have a version set`);
}
// if MAJOR is defined, ensure that the new version is within the same major version
if (major) {
if (!newVersion.startsWith(`${major}.`)) {
throw new Error(`bump failed: this branch is configured to only publish v${major} releases - bump resulted in ${newVersion}`);
}
}
if (minor) {
if (!newVersion.startsWith(`${major}.${minor}`)) {
throw new Error(`bump failed: this branch is configured to only publish v${major}.${minor} releases - bump resulted in ${newVersion}`);
}
}
await fs_1.promises.writeFile(bumpFile, newVersion);
const newTag = `${prefix}v${newVersion}`;
await fs_1.promises.writeFile(releaseTagFile, newTag);
}
async function tryReadVersionFile(versionFile) {
if (!(0, fs_1.existsSync)(versionFile)) {
return { contents: {}, newline: true };
}
const raw = await fs_1.promises.readFile(versionFile, "utf-8");
const contents = JSON.parse(raw);
return {
contents,
version: contents.version,
newline: raw.endsWith("\n"),
};
}
function generateVersionrcFile(rcfile, versionFile, changelogFile, skipBump, prerelease, configOptions) {
return fs_1.promises.writeFile(rcfile, JSON.stringify({
...{
packageFiles: [
{
filename: versionFile,
type: "json",
},
],
bumpFiles: [
{
filename: versionFile,
type: "json",
},
],
commitAll: false,
infile: changelogFile,
prerelease: prerelease,
header: "",
skip: {
commit: true,
tag: true,
bump: skipBump,
},
...configOptions,
},
}, undefined, 2));
}
/**
* Determines the latest release tag.
* @param major (optional) A major version line to select from
* @param prerelease (optional) A pre-release suffix.
* @returns the latest tag, and whether it is the first release or not
*/
function determineLatestTag(options) {
const { cwd, major, minor, prerelease, prefix } = options;
// filter only tags for this prefix and major version if specified (start with "vNN.").
let prefixFilter;
if (major !== undefined && minor !== undefined) {
prefixFilter = `${prefix}v${major}.${minor}.*`;
}
else if (major !== undefined) {
prefixFilter = `${prefix}v${major}.*`;
}
else {
prefixFilter = `${prefix}v*`;
}
const listGitTags = [
"git",
'-c "versionsort.suffix=-"', // makes sure pre-release versions are listed after the primary version
"tag",
'--sort="-version:refname"', // sort as versions and not lexicographically
"--list",
`"${prefixFilter}"`,
].join(" ");
const stdout = (0, util_1.execCapture)(listGitTags, { cwd }).toString("utf8");
let tags = stdout?.split("\n");
// if prerelease is set and there are existing prerelease tags, filter versions that end with "-PRE.ddd".
const prereleaseTags = tags.filter((x) => new RegExp(`-${prerelease}\.[0-9]+$`).test(x));
if (prerelease && prereleaseTags.length > 0) {
/**
* Cover the following case specifically
* 1 - v1.0.0
* 2 - v1.0.1-beta.0
* 3 - v1.0.1-beta.1
* 4 - v1.0.1
* 5 - now publish a new release on the prerelease branch
* by setting the latestTag as v1.0.1 instead of v1.0.1-beta.1
*/
const releaseTags = tags.filter((x) => new RegExp(`^v([0-9]+)\.([0-9]+)\.([0-9]+)$`).test(x));
if (releaseTags.length > 0 &&
(0, semver_1.compare)(releaseTags[0], prereleaseTags[0]) === 1) {
tags = releaseTags;
}
else {
tags = prereleaseTags;
}
}
tags = tags.filter((x) => x);
// if a pre-release tag is used, then add it to the initial version
let isFirstRelease = false;
let latestTag;
if (tags.length > 0) {
latestTag = tags[0];
}
else {
const initial = `${prefix}v${major ?? 0}.${minor ?? 0}.0`;
latestTag = prerelease ? `${initial}-${prerelease}.0` : initial;
isFirstRelease = true;
}
// remove tag prefix (if exists)
let latestVersion = latestTag;
if (prefix && latestVersion.startsWith(prefix)) {
latestVersion = latestVersion.substr(prefix.length);
}
// remove "v" prefix (if exists)
if (latestVersion.startsWith("v")) {
latestVersion = latestVersion.substring(1);
}
return { latestVersion, latestTag, isFirstRelease };
}
function isReleaseType(nextVersion) {
// We are not recognizing all of them yet. That's fine for now.
return !!nextVersion.match(/^(major|minor|patch)$/);
}
function isFullVersionString(nextVersion) {
return nextVersion.match(/^\d+\.\d+\.\d+(-[^\s]+)?$/);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVtcC12ZXJzaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlbGVhc2UvYnVtcC12ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNElBLG9CQXFMQztBQWpVRCwyQkFBZ0Q7QUFDaEQsK0JBQXFDO0FBRXJDLG1DQUFtRDtBQUNuRCxzQ0FBc0M7QUFDdEMsa0NBQTZEO0FBQzdELHdDQUErQztBQTZIL0M7Ozs7Ozs7O0dBUUc7QUFDSSxLQUFLLFVBQVUsSUFBSSxDQUFDLEdBQVcsRUFBRSxPQUFvQjtJQUMxRCxNQUFNLFdBQVcsR0FBRyxJQUFBLFdBQUksRUFBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ25ELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7SUFDdEMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQztJQUNuQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0lBQ25DLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7SUFDaEQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUM7SUFDdkMsTUFBTSxRQUFRLEdBQUcsSUFBQSxXQUFJLEVBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3QyxNQUFNLGFBQWEsR0FBRyxJQUFBLFdBQUksRUFBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ25ELE1BQU0sY0FBYyxHQUFHLElBQUEsV0FBSSxFQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDekQsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSSw0QkFBNEIsQ0FBQztJQUV4RSxJQUFJLEtBQUssSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksS0FBSyxDQUNiLDJEQUEyRCxD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QUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDbEMsYUFBYSxHQUFHLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVELE9BQU8sRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSxDQUFDO0FBQ3RELENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxXQUFtQjtJQUN4QywrREFBK0Q7SUFDL0QsT0FBTyxDQUFDLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0FBQ3RELENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUFDLFdBQW1CO0lBQzlDLE9BQU8sV0FBVyxDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0FBQ3hELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwcm9taXNlcyBhcyBmcywgZXhpc3RzU3luYyB9IGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgZGlybmFtZSwgam9pbiB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBDb25maWcgfSBmcm9tIFwiY29udmVudGlvbmFsLWNoYW5nZWxvZy1jb25maWctc3BlY1wiO1xuaW1wb3J0IHsgY29tcGFyZSwgaW5jLCBSZWxlYXNlVHlwZSB9IGZyb20gXCJzZW12ZXJcIjtcbmltcG9ydCAqIGFzIGxvZ2dpbmcgZnJvbSBcIi4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IGV4ZWMsIGV4ZWNDYXB0dXJlLCBleGVjT3JVbmRlZmluZWQgfSBmcm9tIFwiLi4vdXRpbFwiO1xuaW1wb3J0IHsgUmVsZWFzYWJsZUNvbW1pdHMgfSBmcm9tIFwiLi4vdmVyc2lvblwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJ1bXBPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIGEgLmpzb24gZmlsZSB0byBzZXQgYHZlcnNpb25gLlxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbkZpbGU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGNoYW5nZWxvZyBmaWxlIHRvIGdlbmVyYXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgY2hhbmdlbG9nOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFVzZSBhIHByZS1yZWxlYXNlIHN1ZmZpeC5cbiAgICogQGRlZmF1bHQgLSBub3JtYWwgdmVyc2lvbmluZ1xuICAgKi9cbiAgcmVhZG9ubHkgcHJlcmVsZWFzZT86IHN0cmluZztcblxuICAvKipcbiAgICogRGVmaW5lcyB0aGUgbWFqb3IgdmVyc2lvbiBsaW5lLiBUaGlzIGlzIHVzZWQgdG8gc2VsZWN0IHRoZSBsYXRlc3QgdmVyc2lvblxuICAgKiBhbmQgYWxzbyBlbmZvcmNlIHRoYXQgbmV3IG1ham9yIHZlcnNpb25zIGFyZSBub3QgcmVsZWFzZWQgYWNjaWRlbnRhbGx5LlxuICAgKlxuICAgKiBDYW4gbm90IGJlIHNldCB0b2dldGhlciB3aXRoIGBtaW5NYWpvclZlcnNpb25gLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGFueSB2ZXJzaW9uIGlzIHN1cHBvcnRlZFxuICAgKi9cbiAgcmVhZG9ubHkgbWFqb3JWZXJzaW9uPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIHRoZSBtaW5pbWFsIG1ham9yIHZlcnNpb24uIFRoaXMgaXMgdXNlZCBpZiB5b3Ugd2FudCB0byBzdGFydCB3aXRoXG4gICAqIGEgc3BlY2lmaWMgbWFqb3IgdmVyc2lvbiwgYW5kIGluY3JlbWVudCBmcm9tIHRoZXJlIG9uLlxuICAgKiBUaGlzIGNhbiBiZSB1c2VmdWwgdG8gc2V0IHRvIDEsIGFzIGJyZWFraW5nIGNoYW5nZXMgYmVmb3JlIHRoZSAxLnggbWFqb3JcbiAgICogcmVsZWFzZSBhcmUgbm90IGluY3JlbWVudGluZyB0aGUgbWFqb3IgdmVyc2lvbiBudW1iZXIuXG4gICAqXG4gICAqIENhbiBub3QgYmUgc2V0IHRvZ2V0aGVyIHdpdGggYG1ham9yVmVyc2lvbmAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbWluaW11bSB2ZXJzaW9uIGlzIGJlaW5nIGVuZm9yY2VkXG4gICAqL1xuICByZWFkb25seSBtaW5NYWpvclZlcnNpb24/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIERlZmluZXMgdGhlIG1pbm9yIHZlcnNpb24gbGluZS4gVGhpcyBpcyB1c2VkIHRvIHNlbGVjdCB0aGUgbGF0ZXN0IHZlcnNpb25cbiAgICogYW5kIGFsc28gZW5mb3JjZSB0aGF0IG5ldyBtaW5vciB2ZXJzaW9ucyBhcmUgbm90IHJlbGVhc2VkIGFjY2lkZW50YWxseS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhbnkgdmVyc2lvbiBpcyBzdXBwb3J0ZWRcbiAgICovXG4gIHJlYWRvbmx5IG1pbm9yVmVyc2lvbj86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgYSBmaWxlIHdoaWNoIHdpbGwgaW5jbHVkZSB0aGUgb3V0cHV0IHZlcnNpb24gbnVtYmVyIChhIHRleHQgZmlsZSkuXG4gICAqXG4gICAqIFJlbGF0aXZlIHRvIGN3ZC5cbiAgICpcbiAgICogQGV4YW1wbGUgXCIudmVyc2lvbi50eHRcIlxuICAgKi9cbiAgcmVhZG9ubHkgYnVtcEZpbGU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGZpbGUgd2hpY2ggd2lsbCBpbmNsdWRlIHRoZSByZWxlYXNlIHRhZyAoYSB0ZXh0IGZpbGUpLlxuICAgKlxuICAgKiBSZWxhdGl2ZSB0byBjd2QuXG4gICAqXG4gICAqIEBleGFtcGxlIFwiLnJlbGVhc2V0YWcudHh0XCJcbiAgICovXG4gIHJlYWRvbmx5IHJlbGVhc2VUYWdGaWxlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBwcmVmaXggYXBwbGllZCB0byByZWxlYXNlIHRhZ3MuIEJ1bXBzIHdpbGwgYmUgbWFkZSBiYXNlZCBvbiB0aGUgbGF0ZXN0XG4gICAqIHZlcnNpb24gZm91bmQgd2l0aCB0aGlzIHByZWZpeC5cbiAgICovXG4gIHJlYWRvbmx5IHRhZ1ByZWZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiB2YWx1ZXMgdGhhdCB3b3VsZCBhcHBlbmQgdG8gdmVyc2lvbnJjIGZpbGUgb3Igb3ZlcndyaXRlIHZhbHVlc1xuICAgKiBjb21pbmcgdG8gdGhhdCBmcm9tIGRlZmF1bHQgb25lLlxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbnJjT3B0aW9ucz86IENvbmZpZztcblxuICAvKipcbiAgICogQSBzaGVsbCBjb21tYW5kIHRvIGxpc3QgYWxsIHJlbGVhc2UgY29tbWl0cyBzaW5jZSB0aGUgbGF0ZXN0IHRhZy5cbiAgICpcbiAgICogQSBuZXcgcmVsZWFzZSB3aWxsIGJlIGluaXRpYXRlZCwgaWYgdGhlIG51bWJlciBvZiByZXR1cm5lZCBjb21taXRzIGlzIGdyZWF0ZXIgdGhhbiB6ZXJvLlxuICAgKlxuICAgKiBgJExBVEVTVF9UQUdgIHdpbGwgYmUgcmVwbGFjZWQgd2l0aCB0aGUgYWN0dWFsIGxhdGVzdCB0YWcgZm9yIHRoZSBnaXZlbiBwcmVmaXguXG4gICAqXG4gICAqIEBkZWZhdWx0IFwiZ2l0IGxvZyAtLW9uZWxpbmUgJExBVEVTVF9UQUcuLkhFQURcIlxuICAgKi9cbiAgcmVhZG9ubHkgcmVsZWFzYWJsZUNvbW1pdHM/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBgY29tbWl0LWFuZC10YWctdmVyc2lvbmAgY29tcGF0aWJsZSBwYWNrYWdlIHVzZWQgdG8gYnVtcCB0aGUgcGFja2FnZSB2ZXJzaW9uLCBhcyBhIGRlcGVuZGVuY3kgc3RyaW5nLlxuICAgKlxuICAgKiBUaGlzIGNhbiBiZSBhbnkgY29tcGF0aWJsZSBwYWNrYWdlIHZlcnNpb24sIGluY2x1ZGluZyB0aGUgZGVwcmVjYXRlZCBgc3RhbmRhcmQtdmVyc2lvbkA5YC5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJjb21taXQtYW5kLXRhZy12ZXJzaW9uQDEyXCJcbiAgICovXG4gIHJlYWRvbmx5IGJ1bXBQYWNrYWdlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIHNoZWxsIGNvbW1hbmQgdG8gY29udHJvbCB0aGUgbmV4dCB2ZXJzaW9uIHRvIHJlbGVhc2UuXG4gICAqXG4gICAqIElmIHByZXNlbnQsIHRoaXMgc2hlbGwgY29tbWFuZCB3aWxsIGJlIHJ1biBiZWZvcmUgdGhlIGJ1bXAgaXMgZXhlY3V0ZWQsIGFuZFxuICAgKiBpdCBkZXRlcm1pbmVzIHdoYXQgdmVyc2lvbiB0byByZWxlYXNlLiBJdCB3aWxsIGJlIGV4ZWN1dGVkIGluIHRoZSBmb2xsb3dpbmdcbiAgICogZW52aXJvbm1lbnQ6XG4gICAqXG4gICAqIC0gV29ya2luZyBkaXJlY3Rvcnk6IHRoZSBwcm9qZWN0IGRpcmVjdG9yeS5cbiAgICogLSBgJFZFUlNJT05gOiB0aGUgY3VycmVudCB2ZXJzaW9uLiBMb29rcyBsaWtlIGAxLjIuM2AuXG4gICAqIC0gYCRMQVRFU1RfVEFHYDogdGhlIG1vc3QgcmVjZW50IHRhZy4gTG9va3MgbGlrZSBgcHJlZml4LXYxLjIuM2AsIG9yIG1heSBiZSB1bnNldC5cbiAgICpcbiAgICogVGhlIGNvbW1hbmQgc2hvdWxkIHByaW50IG9uZSBvZiB0aGUgZm9sbG93aW5nIHRvIGBzdGRvdXRgOlxuICAgKlxuICAgKiAtIE5vdGhpbmc6IHRoZSBuZXh0IHZlcnNpb24gbnVtYmVyIHdpbGwgYmUgZGV0ZXJtaW5lZCBiYXNlZCBvbiBjb21taXQgaGlzdG9yeS5cbiAgICogLSBgeC55LnpgOiB0aGUgbmV4dCB2ZXJzaW9uIG51bWJlciB3aWxsIGJlIGB4LnkuemAuXG4gICAqIC0gYG1ham9yfG1pbm9yfHBhdGNoYDogdGhlIG5leHQgdmVyc2lvbiBudW1iZXIgd2lsbCBiZSB0aGUgY3VycmVudCB2ZXJzaW9uIG51bWJlclxuICAgKiAgIHdpdGggdGhlIGluZGljYXRlZCBjb21wb25lbnQgYnVtcGVkLlxuICAgKlxuICAgKiBUaGlzIHNldHRpbmcgY2Fubm90IGJlIHNwZWNpZmllZCB0b2dldGhlciB3aXRoIGBtaW5NYWpvclZlcnNpb25gOyB0aGUgaW52b2tlZFxuICAgKiBzY3JpcHQgY2FuIGJlIHVzZWQgdG8gYWNoaWV2ZSB0aGUgZWZmZWN0cyBvZiBgbWluTWFqb3JWZXJzaW9uYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBUaGUgbmV4dCB2ZXJzaW9uIHdpbGwgYmUgZGV0ZXJtaW5lZCBiYXNlZCBvbiB0aGUgY29tbWl0IGhpc3RvcnkgYW5kIHByb2plY3Qgc2V0dGluZ3MuXG4gICAqL1xuICByZWFkb25seSBuZXh0VmVyc2lvbkNvbW1hbmQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgdGhlIGxhdGVzdCB2ZXJzaW9uIGZyb20gZ2l0IHRhZ3MgYW5kIHVzZXMgYGNvbW1pdC1hbmQtdGFnLXZlcnNpb25gIHRvIGJ1bXBcbiAqIHRvIHRoZSBuZXh0IHZlcnNpb24gYmFzZWQgb24gY29tbWl0cy5cbiAqXG4gKiBUaGlzIGV4cGVjdHMgYGNvbW1pdC1hbmQtdGFnLXZlcnNpb25gIHRvIGJlIGluc3RhbGxlZCBpbiB0aGUgcGF0aC5cbiAqXG4gKiBAcGFyYW0gY3dkIHdvcmtpbmcgZGlyZWN0b3J5IChnaXQgcmVwb3NpdG9yeSlcbiAqIEBwYXJhbSBvcHRpb25zIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1bXAoY3dkOiBzdHJpbmcsIG9wdGlvbnM6IEJ1bXBPcHRpb25zKSB7XG4gIGNvbnN0IHZlcnNpb25GaWxlID0gam9pbihjd2QsIG9wdGlvbnMudmVyc2lvbkZpbGUpO1xuICBjb25zdCBwcmVyZWxlYXNlID0gb3B0aW9ucy5wcmVyZWxlYXNlO1xuICBjb25zdCBtYWpvciA9IG9wdGlvbnMubWFqb3JWZXJzaW9uO1xuICBjb25zdCBtaW5vciA9IG9wdGlvbnMubWlub3JWZXJzaW9uO1xuICBjb25zdCBtaW5NYWpvclZlcnNpb24gPSBvcHRpb25zLm1pbk1ham9yVmVyc2lvbjtcbiAgY29uc3QgcHJlZml4ID0gb3B0aW9ucy50YWdQcmVmaXggPz8gXCJcIjtcbiAgY29uc3QgYnVtcEZpbGUgPSBqb2luKGN3ZCwgb3B0aW9ucy5idW1wRmlsZSk7XG4gIGNvbnN0IGNoYW5nZWxvZ0ZpbGUgPSBqb2luKGN3ZCwgb3B0aW9ucy5jaGFuZ2Vsb2cpO1xuICBjb25zdCByZWxlYXNlVGFnRmlsZSA9IGpvaW4oY3dkLCBvcHRpb25zLnJlbGVhc2VUYWdGaWxlKTtcbiAgY29uc3QgYnVtcFBhY2thZ2UgPSBvcHRpb25zLmJ1bXBQYWNrYWdlID8/IFwiY29tbWl0LWFuZC10YWctdmVyc2lvbkBeMTJcIjtcblxuICBpZiAobWFqb3IgJiYgbWluTWFqb3JWZXJzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYG1pbk1ham9yVmVyc2lvbiBhbmQgbWFqb3JWZXJzaW9uIGNhbm5vdCBiZSB1c2VkIHRvZ2V0aGVyLmBcbiAgICApO1xuICB9XG4gIGlmIChvcHRpb25zLm5leHRWZXJzaW9uQ29tbWFuZCAmJiBtaW5NYWpvclZlcnNpb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgbWluTWFqb3JWZXJzaW9uIGFuZCBuZXh0VmVyc2lvbkNvbW1hbmQgY2Fubm90IGJlIHVzZWQgdG9nZXRoZXIuYFxuICAgICk7XG4gIH1cbiAgaWYgKG1pbm9yICYmICFtYWpvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihgbWlub3JWZXJzaW9uIGFuZCBtYWpvclZlcnNpb24gbXVzdCBiZSB1c2VkIHRvZ2V0aGVyLmApO1xuICB9XG5cbiAgYXdhaXQgZnMubWtkaXIoZGlybmFtZShidW1wRmlsZSksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICBhd2FpdCBmcy5ta2RpcihkaXJuYW1lKGNoYW5nZWxvZ0ZpbGUpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgYXdhaXQgZnMubWtkaXIoZGlybmFtZShyZWxlYXNlVGFnRmlsZSksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHsgbGF0ZXN0VmVyc2lvbiwgbGF0ZXN0VGFnLCBpc0ZpcnN0UmVsZWFzZSB9ID0gZGV0ZXJtaW5lTGF0ZXN0VGFnKHtcbiAgICBjd2QsXG4gICAgbWFqb3IsXG4gICAgbWlub3IsXG4gICAgcHJlcmVsZWFzZSxcbiAgICBwcmVmaXgsXG4gIH0pO1xuXG4gIGNvbnN0IHsgY29udGVudHMsIG5ld2xpbmUgfSA9IGF3YWl0IHRyeVJlYWRWZXJzaW9uRmlsZSh2ZXJzaW9uRmlsZSk7XG5cbiAgLy8gdXBkYXRlIHZlcnNpb25cbiAgY29udGVudHMudmVyc2lvbiA9IGxhdGVzdFZlcnNpb247XG5cbiAgbG9nZ2luZy5pbmZvKFxuICAgIGBVcGRhdGUgJHt2ZXJzaW9uRmlsZX0gdG8gbGF0ZXN0IHJlc29sdmVkIHZlcnNpb246ICR7bGF0ZXN0VmVyc2lvbn1gXG4gICk7XG4gIGF3YWl0IGZzLndyaXRlRmlsZShcbiAgICB2ZXJzaW9uRmlsZSxcbiAgICBKU09OLnN0cmluZ2lmeShjb250ZW50cywgdW5kZWZpbmVkLCAyKSArIChuZXdsaW5lID8gXCJcXG5cIiA6IFwiXCIpXG4gICk7XG5cbiAgLy8gY2hlY2sgZm9yIGNvbW1pdHMgc2luY2UgdGhlIGxhc3QgcmVsZWFzZSB0YWdcbiAgbGV0IHNraXBCdW1wID0gZmFsc2U7XG4gIGxldCByZXN0b3JlVGFnID0gZmFsc2U7XG5cbiAgLy8gRmlyc3QgUmVsZWFzZSBpcyBuZXZlciBza2lwcGluZyBidW1wXG4gIGlmICghaXNGaXJzdFJlbGVhc2UpIHtcbiAgICBjb25zdCBmaW5kQ29tbWl0cyA9IChcbiAgICAgIG9wdGlvbnMucmVsZWFzYWJsZUNvbW1pdHMgPz8gUmVsZWFzYWJsZUNvbW1pdHMuZXZlcnlDb21taXQoKS5jbWRcbiAgICApLnJlcGxhY2UoXCIkTEFURVNUX1RBR1wiLCBsYXRlc3RUYWcpO1xuICAgIGNvbnN0IGNvbW1pdHNTaW5jZUxhc3RUYWcgPSBleGVjT3JVbmRlZmluZWQoZmluZENvbW1pdHMsIHsgY3dkIH0pPy5zcGxpdChcbiAgICAgIFwiXFxuXCJcbiAgICApO1xuICAgIGNvbnN0IG51bUNvbW1pdHNTaW5jZUxhc3RUYWcgPSBjb21taXRzU2luY2VMYXN0VGFnPy5sZW5ndGggPz8gMDtcbiAgICBsb2dnaW5nLmluZm8oXG4gICAgICBgTnVtYmVyIG9mIGNvbW1pdHMgc2luY2UgJHtsYXRlc3RUYWd9OiAke251bUNvbW1pdHNTaW5jZUxhc3RUYWd9YFxuICAgICk7XG5cbiAgICAvLyBOb3RoaW5nIHRvIHJlbGVhc2UgcmlnaHQgbm93XG4gICAgaWYgKG51bUNvbW1pdHNTaW5jZUxhc3RUYWcgPT09IDApIHtcbiAgICAgIGxvZ2dpbmcuaW5mbyhcIlNraXBwaW5nIGJ1bXAuLi5cIik7XG4gICAgICBza2lwQnVtcCA9IHRydWU7XG4gICAgICByZXN0b3JlVGFnID0gdHJ1ZTtcblxuICAgICAgLy8gZGVsZXRlIHRoZSBleGlzdGluZyB0YWcgKGxvY2FsbHkpXG4gICAgICAvLyBpZiB3ZSBkb24ndCBkbyB0aGlzLCBjb21taXQtYW5kLXRhZy12ZXJzaW9uIGdlbmVyYXRlcyBhbiBlbXB0eSBjaGFuZ2Vsb2dcbiAgICAgIGV4ZWMoYGdpdCB0YWcgLS1kZWxldGUgJHtsYXRlc3RUYWd9YCwgeyBjd2QgfSk7XG4gICAgfVxuICB9XG5cbiAgLy8gRGV0ZXJtaW5lIHdoYXQgdmVyc2lvbiB0byByZWxlYXNlIGFzXG4gIGxldCByZWxlYXNlQXM6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgaWYgKG1pbk1ham9yVmVyc2lvbikge1xuICAgIGNvbnN0IFttYWpvclZlcnNpb25dID0gbGF0ZXN0VmVyc2lvbi5zcGxpdChcIi5cIik7XG4gICAgY29uc3QgbWFqb3JWZXJzaW9uTnVtYmVyID0gcGFyc2VJbnQobWFqb3JWZXJzaW9uLCAxMCk7XG4gICAgaWYgKG1ham9yVmVyc2lvbk51bWJlciA8IG1pbk1ham9yVmVyc2lvbikge1xuICAgICAgcmVsZWFzZUFzID0gYCR7bWluTWFqb3JWZXJzaW9ufS4wLjBgO1xuICAgIH1cbiAgfSBlbHNlIGlmIChvcHRpb25zLm5leHRWZXJzaW9uQ29tbWFuZCkge1xuICAgIGNvbnN0IG5leHRWZXJzaW9uID0gZXhlY0NhcHR1cmUob3B0aW9ucy5uZXh0VmVyc2lvbkNvbW1hbmQsIHtcbiAgICAgIGN3ZCxcbiAgICAgIG1vZEVudjoge1xuICAgICAgICBWRVJTSU9OOiBsYXRlc3RWZXJzaW9uLFxuICAgICAgICAuLi4obGF0ZXN0VGFnID8geyBMQVRFU1RfVEFHOiBsYXRlc3RUYWcgfSA6IHt9KSxcbiAgICAgIH0sXG4gICAgfSlcbiAgICAgIC50b1N0cmluZygpXG4gICAgICAudHJpbSgpO1xuXG4gICAgaWYgKG5leHRWZXJzaW9uKSB7XG4gICAgICAvLyBDYWxjdWxhdGUgdGhlIG5leHQgdmVyc2lvblxuICAgICAgaWYgKGlzUmVsZWFzZVR5cGUobmV4dFZlcnNpb24pKSB7XG4gICAgICAgIHJlbGVhc2VBcyA9IGluYyhsYXRlc3RWZXJzaW9uLCBuZXh0VmVyc2lvbik/LnRvU3RyaW5nKCk7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBpc0Z1bGxWZXJzaW9uU3RyaW5nKG5leHRWZXJzaW9uKSAmJlxuICAgICAgICBuZXh0VmVyc2lvbiAhPT0gbGF0ZXN0VmVyc2lvblxuICAgICAgKSB7XG4gICAgICAgIHJlbGVhc2VBcyA9IG5leHRWZXJzaW9uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBuZXh0VmVyc2lvbkNvbW1hbmQgXCIke29wdGlvbnMubmV4dFZlcnNpb25Db21tYW5kfVwiIHJldHVybmVkIGludmFsaWQgdmVyc2lvbjogJHtuZXh0VmVyc2lvbn1gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIERvbid0IG5lZWQgdG8gdmFsaWRhdGUgaWYgdGhlIGZpbmFsIHZlcnNpb24gaXMgd2l0aGluIHRoZSBleHBlY3RlZCBkZWNsYXJlZCBtYWpvci5taW5vciByYW5nZSxcbiAgICAgIC8vIGlmIGdpdmVuLiBUaGF0IGlzIGRvbmUgYmVsb3cgYWZ0ZXIgYnVtcGluZy5cbiAgICB9XG4gIH1cblxuICAvLyBJZiB0aGUgbmV4dFZlcnNpb25Db21tYW5kIGZvcmNlZCBhIHNwZWNpZmljIHJlbGVhc2UgdmVyc2lvbiwgd2Ugc2hvdWxkbid0XG4gIC8vIHNraXAgdGhlIGJ1bXAgYWN0aW9uLlxuICBpZiAocmVsZWFzZUFzKSB7XG4gICAgc2tpcEJ1bXAgPSBmYWxzZTtcbiAgfVxuXG4gIC8vIGNyZWF0ZSBhIGNvbW1pdC1hbmQtdGFnLXZlcnNpb24gY29uZmlndXJhdGlvbiBmaWxlXG4gIGNvbnN0IHJjZmlsZSA9IGpvaW4oY3dkLCBcIi52ZXJzaW9ucmMuanNvblwiKTtcbiAgYXdhaXQgZ2VuZXJhdGVWZXJzaW9ucmNGaWxlKFxuICAgIHJjZmlsZSxcbiAgICB2ZXJzaW9uRmlsZSxcbiAgICBjaGFuZ2Vsb2dGaWxlLFxuICAgIHNraXBCdW1wLFxuICAgIHByZXJlbGVhc2UsXG4gICAgb3B0aW9ucy52ZXJzaW9ucmNPcHRpb25zXG4gICk7XG5cbiAgY29uc3QgY21kID0gW1wibnB4XCIsIGJ1bXBQYWNrYWdlXTtcbiAgaWYgKGlzRmlyc3RSZWxlYXNlICYmICFtaW5NYWpvclZlcnNpb24pIHtcbiAgICBjbWQucHVzaChcIi0tZmlyc3QtcmVsZWFzZVwiKTtcbiAgfVxuICBpZiAocHJlZml4KSB7XG4gICAgY21kLnB1c2goYC0tdGFnLXByZWZpeCAke3ByZWZpeH12YCk7XG4gIH1cbiAgaWYgKHJlbGVhc2VBcykge1xuICAgIGNtZC5wdXNoKGAtLXJlbGVhc2UtYXMgJHtyZWxlYXNlQXN9YCk7XG4gIH1cblxuICBleGVjKGNtZC5qb2luKFwiIFwiKSwgeyBjd2QgfSk7XG5cbiAgLy8gYWRkIHRoZSB0YWcgYmFjayBpZiBpdCB3YXMgcHJldmlvdXNseSByZW1vdmVkXG4gIGlmIChyZXN0b3JlVGFnKSB7XG4gICAgZXhlYyhgZ2l0IHRhZyAke2xhdGVzdFRhZ31gLCB7IGN3ZCB9KTtcbiAgfVxuXG4gIGF3YWl0IGZzLnJtKHJjZmlsZSwgeyBmb3JjZTogdHJ1ZSwgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IG5ld1ZlcnNpb24gPSAoYXdhaXQgdHJ5UmVhZFZlcnNpb25GaWxlKHZlcnNpb25GaWxlKSkudmVyc2lvbjtcbiAgaWYgKCFuZXdWZXJzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBidW1wIGZhaWxlZDogJHt2ZXJzaW9uRmlsZX0gZG9lcyBub3QgaGF2ZSBhIHZlcnNpb24gc2V0YCk7XG4gIH1cblxuICAvLyBpZiBNQUpPUiBpcyBkZWZpbmVkLCBlbnN1cmUgdGhhdCB0aGUgbmV3IHZlcnNpb24gaXMgd2l0aGluIHRoZSBzYW1lIG1ham9yIHZlcnNpb25cbiAgaWYgKG1ham9yKSB7XG4gICAgaWYgKCFuZXdWZXJzaW9uLnN0YXJ0c1dpdGgoYCR7bWFqb3J9LmApKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBidW1wIGZhaWxlZDogdGhpcyBicmFuY2ggaXMgY29uZmlndXJlZCB0byBvbmx5IHB1Ymxpc2ggdiR7bWFqb3J9IHJlbGVhc2VzIC0gYnVtcCByZXN1bHRlZCBpbiAke25ld1ZlcnNpb259YFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgaWYgKG1pbm9yKSB7XG4gICAgaWYgKCFuZXdWZXJzaW9uLnN0YXJ0c1dpdGgoYCR7bWFqb3J9LiR7bWlub3J9YCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYGJ1bXAgZmFpbGVkOiB0aGlzIGJyYW5jaCBpcyBjb25maWd1cmVkIHRvIG9ubHkgcHVibGlzaCB2JHttYWpvcn0uJHttaW5vcn0gcmVsZWFzZXMgLSBidW1wIHJlc3VsdGVkIGluICR7bmV3VmVyc2lvbn1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGF3YWl0IGZzLndyaXRlRmlsZShidW1wRmlsZSwgbmV3VmVyc2lvbik7XG5cbiAgY29uc3QgbmV3VGFnID0gYCR7cHJlZml4fXYke25ld1ZlcnNpb259YDtcbiAgYXdhaXQgZnMud3JpdGVGaWxlKHJlbGVhc2VUYWdGaWxlLCBuZXdUYWcpO1xufVxuXG5hc3luYyBmdW5jdGlvbiB0cnlSZWFkVmVyc2lvbkZpbGUoXG4gIHZlcnNpb25GaWxlOiBzdHJpbmdcbik6IFByb21pc2U8eyBjb250ZW50czogYW55OyB2ZXJzaW9uPzogc3RyaW5nOyBuZXdsaW5lOiBib29sZWFuIH0+IHtcbiAgaWYgKCFleGlzdHNTeW5jKHZlcnNpb25GaWxlKSkge1xuICAgIHJldHVybiB7IGNvbnRlbnRzOiB7fSwgbmV3bGluZTogdHJ1ZSB9O1xuICB9XG4gIGNvbnN0IHJhdyA9IGF3YWl0IGZzLnJlYWRGaWxlKHZlcnNpb25GaWxlLCBcInV0Zi04XCIpO1xuICBjb25zdCBjb250ZW50cyA9IEpTT04ucGFyc2UocmF3KTtcblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnRzLFxuICAgIHZlcnNpb246IGNvbnRlbnRzLnZlcnNpb24sXG4gICAgbmV3bGluZTogcmF3LmVuZHNXaXRoKFwiXFxuXCIpLFxuICB9O1xufVxuXG5pbnRlcmZhY2UgTGF0ZXN0VGFnT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXb3JraW5nIGRpcmVjdG9yeSBvZiB0aGUgZ2l0IHJlcG9zaXRvcnkuXG4gICAqL1xuICByZWFkb25seSBjd2Q6IHN0cmluZztcbiAgLyoqXG4gICAqIE1ham9yIHZlcnNpb24gdG8gc2VsZWN0IGZyb20uXG4gICAqL1xuICByZWFkb25seSBtYWpvcj86IG51bWJlcjtcbiAgLyoqXG4gICAqIE1pbm9yIHZlcnNpb24gdG8gc2VsZWN0IGZyb20uXG4gICAqL1xuICByZWFkb25seSBtaW5vcj86IG51bWJlcjtcbiAgLyoqXG4gICAqIEEgcHJlLXJlbGVhc2Ugc3VmZml4LlxuICAgKi9cbiAgcmVhZG9ubHkgcHJlcmVsZWFzZT86IHN0cmluZztcbiAgLyoqXG4gICAqIEEgcHJlZml4IGFwcGxpZWQgdG8gYWxsIHRhZ3MuXG4gICAqL1xuICByZWFkb25seSBwcmVmaXg6IHN0cmluZztcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVWZXJzaW9ucmNGaWxlKFxuICByY2ZpbGU6IHN0cmluZyxcbiAgdmVyc2lvbkZpbGU6IHN0cmluZyxcbiAgY2hhbmdlbG9nRmlsZTogc3RyaW5nLFxuICBza2lwQnVtcDogYm9vbGVhbixcbiAgcHJlcmVsZWFzZT86IHN0cmluZyxcbiAgY29uZmlnT3B0aW9ucz86IENvbmZpZ1xuKSB7XG4gIHJldHVybiBmcy53cml0ZUZpbGUoXG4gICAgcmNmaWxlLFxuICAgIEpTT04uc3RyaW5naWZ5KFxuICAgICAge1xuICAgICAgICAuLi57XG4gICAgICAgICAgcGFja2FnZUZpbGVzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpbGVuYW1lOiB2ZXJzaW9uRmlsZSxcbiAgICAgICAgICAgICAgdHlwZTogXCJqc29uXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgYnVtcEZpbGVzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpbGVuYW1lOiB2ZXJzaW9uRmlsZSxcbiAgICAgICAgICAgICAgdHlwZTogXCJqc29uXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgY29tbWl0QWxsOiBmYWxzZSxcbiAgICAgICAgICBpbmZpbGU6IGNoYW5nZWxvZ0ZpbGUsXG4gICAgICAgICAgcHJlcmVsZWFzZTogcHJlcmVsZWFzZSxcbiAgICAgICAgICBoZWFkZXI6IFwiXCIsXG4gICAgICAgICAgc2tpcDoge1xuICAgICAgICAgICAgY29tbWl0OiB0cnVlLFxuICAgICAgICAgICAgdGFnOiB0cnVlLFxuICAgICAgICAgICAgYnVtcDogc2tpcEJ1bXAsXG4gICAgICAgICAgfSxcbiAgICAgICAgICAuLi5jb25maWdPcHRpb25zLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIDJcbiAgICApXG4gICk7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB0aGUgbGF0ZXN0IHJlbGVhc2UgdGFnLlxuICogQHBhcmFtIG1ham9yIChvcHRpb25hbCkgQSBtYWpvciB2ZXJzaW9uIGxpbmUgdG8gc2VsZWN0IGZyb21cbiAqIEBwYXJhbSBwcmVyZWxlYXNlIChvcHRpb25hbCkgQSBwcmUtcmVsZWFzZSBzdWZmaXguXG4gKiBAcmV0dXJucyB0aGUgbGF0ZXN0IHRhZywgYW5kIHdoZXRoZXIgaXQgaXMgdGhlIGZpcnN0IHJlbGVhc2Ugb3Igbm90XG4gKi9cbmZ1bmN0aW9uIGRldGVybWluZUxhdGVzdFRhZyhvcHRpb25zOiBMYXRlc3RUYWdPcHRpb25zKToge1xuICBsYXRlc3RWZXJzaW9uOiBzdHJpbmc7XG4gIGxhdGVzdFRhZzogc3RyaW5nO1xuICBpc0ZpcnN0UmVsZWFzZTogYm9vbGVhbjtcbn0ge1xuICBjb25zdCB7IGN3ZCwgbWFqb3IsIG1pbm9yLCBwcmVyZWxlYXNlLCBwcmVmaXggfSA9IG9wdGlvbnM7XG5cbiAgLy8gZmlsdGVyIG9ubHkgdGFncyBmb3IgdGhpcyBwcmVmaXggYW5kIG1ham9yIHZlcnNpb24gaWYgc3BlY2lmaWVkIChzdGFydCB3aXRoIFwidk5OLlwiKS5cbiAgbGV0IHByZWZpeEZpbHRlcjogc3RyaW5nO1xuICBpZiAobWFqb3IgIT09IHVuZGVmaW5lZCAmJiBtaW5vciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcHJlZml4RmlsdGVyID0gYCR7cHJlZml4fXYke21ham9yfS4ke21pbm9yfS4qYDtcbiAgfSBlbHNlIGlmIChtYWpvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcHJlZml4RmlsdGVyID0gYCR7cHJlZml4fXYke21ham9yfS4qYDtcbiAgfSBlbHNlIHtcbiAgICBwcmVmaXhGaWx0ZXIgPSBgJHtwcmVmaXh9dipgO1xuICB9XG5cbiAgY29uc3QgbGlzdEdpdFRhZ3MgPSBbXG4gICAgXCJnaXRcIixcbiAgICAnLWMgXCJ2ZXJzaW9uc29ydC5zdWZmaXg9LVwiJywgLy8gbWFrZXMgc3VyZSBwcmUtcmVsZWFzZSB2ZXJzaW9ucyBhcmUgbGlzdGVkIGFmdGVyIHRoZSBwcmltYXJ5IHZlcnNpb25cbiAgICBcInRhZ1wiLFxuICAgICctLXNvcnQ9XCItdmVyc2lvbjpyZWZuYW1lXCInLCAvLyBzb3J0IGFzIHZlcnNpb25zIGFuZCBub3QgbGV4aWNvZ3JhcGhpY2FsbHlcbiAgICBcIi0tbGlzdFwiLFxuICAgIGBcIiR7cHJlZml4RmlsdGVyfVwiYCxcbiAgXS5qb2luKFwiIFwiKTtcblxuICBjb25zdCBzdGRvdXQgPSBleGVjQ2FwdHVyZShsaXN0R2l0VGFncywgeyBjd2QgfSkudG9TdHJpbmcoXCJ1dGY4XCIpO1xuXG4gIGxldCB0YWdzID0gc3Rkb3V0Py5zcGxpdChcIlxcblwiKTtcblxuICAvLyBpZiBwcmVyZWxlYXNlIGlzIHNldCBhbmQgdGhlcmUgYXJlIGV4aXN0aW5nIHByZXJlbGVhc2UgdGFncywgZmlsdGVyIHZlcnNpb25zIHRoYXQgZW5kIHdpdGggXCItUFJFLmRkZFwiLlxuICBjb25zdCBwcmVyZWxlYXNlVGFncyA9IHRhZ3MuZmlsdGVyKCh4KSA9PlxuICAgIG5ldyBSZWdFeHAoYC0ke3ByZXJlbGVhc2V9XFwuWzAtOV0rJGApLnRlc3QoeClcbiAgKTtcbiAgaWYgKHByZXJlbGVhc2UgJiYgcHJlcmVsZWFzZVRhZ3MubGVuZ3RoID4gMCkge1xuICAgIC8qKlxuICAgICAqIENvdmVyIHRoZSBmb2xsb3dpbmcgY2FzZSBzcGVjaWZpY2FsbHlcbiAgICAgKiAxIC0gdjEuMC4wXG4gICAgICogMiAtIHYxLjAuMS1iZXRhLjBcbiAgICAgKiAzIC0gdjEuMC4xLWJldGEuMVxuICAgICAqIDQgLSB2MS4wLjFcbiAgICAgKiA1IC0gbm93IHB1Ymxpc2ggYSBuZXcgcmVsZWFzZSBvbiB0aGUgcHJlcmVsZWFzZSBicmFuY2hcbiAgICAgKiAgICBieSBzZXR0aW5nIHRoZSBsYXRlc3RUYWcgYXMgdjEuMC4xIGluc3RlYWQgb2YgdjEuMC4xLWJldGEuMVxuICAgICAqL1xuICAgIGNvbnN0IHJlbGVhc2VUYWdzID0gdGFncy5maWx0ZXIoKHgpID0+XG4gICAgICBuZXcgUmVnRXhwKGBedihbMC05XSspXFwuKFswLTldKylcXC4oWzAtOV0rKSRgKS50ZXN0KHgpXG4gICAgKTtcbiAgICBpZiAoXG4gICAgICByZWxlYXNlVGFncy5sZW5ndGggPiAwICYmXG4gICAgICBjb21wYXJlKHJlbGVhc2VUYWdzWzBdLCBwcmVyZWxlYXNlVGFnc1swXSkgPT09IDFcbiAgICApIHtcbiAgICAgIHRhZ3MgPSByZWxlYXNlVGFncztcbiAgICB9IGVsc2Uge1xuICAgICAgdGFncyA9IHByZXJlbGVhc2VUYWdzO1xuICAgIH1cbiAgfVxuXG4gIHRhZ3MgPSB0YWdzLmZpbHRlcigoeCkgPT4geCk7XG5cbiAgLy8gaWYgYSBwcmUtcmVsZWFzZSB0YWcgaXMgdXNlZCwgdGhlbiBhZGQgaXQgdG8gdGhlIGluaXRpYWwgdmVyc2lvblxuICBsZXQgaXNGaXJzdFJlbGVhc2UgPSBmYWxzZTtcbiAgbGV0IGxhdGVzdFRhZztcblxuICBpZiAodGFncy5sZW5ndGggPiAwKSB7XG4gICAgbGF0ZXN0VGFnID0gdGFnc1swXTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBpbml0aWFsID0gYCR7cHJlZml4fXYke21ham9yID8/IDB9LiR7bWlub3IgPz8gMH0uMGA7XG4gICAgbGF0ZXN0VGFnID0gcHJlcmVsZWFzZSA/IGAke2luaXRpYWx9LSR7cHJlcmVsZWFzZX0uMGAgOiBpbml0aWFsO1xuICAgIGlzRmlyc3RSZWxlYXNlID0gdHJ1ZTtcbiAgfVxuXG4gIC8vIHJlbW92ZSB0YWcgcHJlZml4IChpZiBleGlzdHMpXG4gIGxldCBsYXRlc3RWZXJzaW9uID0gbGF0ZXN0VGFnO1xuICBpZiAocHJlZml4ICYmIGxhdGVzdFZlcnNpb24uc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgbGF0ZXN0VmVyc2lvbiA9IGxhdGVzdFZlcnNpb24uc3Vic3RyKHByZWZpeC5sZW5ndGgpO1xuICB9XG5cbiAgLy8gcmVtb3ZlIFwidlwiIHByZWZpeCAoaWYgZXhpc3RzKVxuICBpZiAobGF0ZXN0VmVyc2lvbi5zdGFydHNXaXRoKFwidlwiKSkge1xuICAgIGxhdGVzdFZlcnNpb24gPSBsYXRlc3RWZXJzaW9uLnN1YnN0cmluZygxKTtcbiAgfVxuXG4gIHJldHVybiB7IGxhdGVzdFZlcnNpb24sIGxhdGVzdFRhZywgaXNGaXJzdFJlbGVhc2UgfTtcbn1cblxuZnVuY3Rpb24gaXNSZWxlYXNlVHlwZShuZXh0VmVyc2lvbjogc3RyaW5nKTogbmV4dFZlcnNpb24gaXMgUmVsZWFzZVR5cGUge1xuICAvLyBXZSBhcmUgbm90IHJlY29nbml6aW5nIGFsbCBvZiB0aGVtIHlldC4gVGhhdCdzIGZpbmUgZm9yIG5vdy5cbiAgcmV0dXJuICEhbmV4dFZlcnNpb24ubWF0Y2goL14obWFqb3J8bWlub3J8cGF0Y2gpJC8pO1xufVxuXG5mdW5jdGlvbiBpc0Z1bGxWZXJzaW9uU3RyaW5nKG5leHRWZXJzaW9uOiBzdHJpbmcpIHtcbiAgcmV0dXJuIG5leHRWZXJzaW9uLm1hdGNoKC9eXFxkK1xcLlxcZCtcXC5cXGQrKC1bXlxcc10rKT8kLyk7XG59XG4iXX0=