projen
Version:
CDK for software projects
258 lines • 42 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");
const bump_type_1 = require("./bump-type");
const commit_tag_version_1 = require("./commit-tag-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 tagPrefix = 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);
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: tagPrefix,
});
// Write the current version into the version file so that CATV will know the current version
const { contents, newline } = await tryReadVersionFile(versionFile);
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" : ""));
// Determine the initial bump status. CATV will always do a patch even if
// there are no commits, so look at commits ourselves first to decide
// if we even should do nothing at all.
const shouldRelease = isFirstRelease
? true
: hasNewInterestingCommits({
cwd,
latestTag,
releasableCommits: options.releasableCommits,
});
const catv = new commit_tag_version_1.CommitAndTagVersion(options.bumpPackage, cwd, {
versionFile,
changelogFile,
prerelease,
configOptions: options.versionrcOptions,
tagPrefix,
});
// We used to translate `isFirstRelease` to the `--first-release` flag of CATV.
// What that does is skip a bump, only generate the changelog.
//
// Our `{ bump: none }` does the same, so we don't need to carry over this
// flag anymore.
let bumpType = shouldRelease && !isFirstRelease
? (0, bump_type_1.relativeBumpType)(latestVersion, await catv.dryRun())
: { bump: "none" };
logging.info(`Bump from commits: ${(0, bump_type_1.renderBumpType)(bumpType)}`);
if (options.nextVersionCommand) {
const nextVersion = (0, util_1.execCapture)(options.nextVersionCommand, {
cwd,
modEnv: {
VERSION: latestVersion,
SUGGESTED_BUMP: (0, bump_type_1.renderBumpType)(bumpType),
...(latestTag ? { LATEST_TAG: latestTag } : {}),
},
})
.toString()
.trim();
if (nextVersion) {
try {
bumpType = (0, bump_type_1.parseBumpType)(nextVersion);
logging.info(`Bump from nextVersionCommand: ${(0, bump_type_1.renderBumpType)(bumpType)}`);
}
catch (e) {
throw new Error(`nextVersionCommand "${options.nextVersionCommand}" returned invalid output: ${e}`);
}
}
}
// Respect minMajorVersion to correct the result of the nextVersionCommand
if (minMajorVersion) {
const bumpedVersion = (0, bump_type_1.performBump)(latestVersion, bumpType);
const [majorVersion] = bumpedVersion.split(".");
const majorVersionNumber = parseInt(majorVersion, 10);
if (majorVersionNumber < minMajorVersion) {
bumpType = { bump: "absolute", absolute: `${minMajorVersion}.0.0` };
}
}
// Invoke CATV with the options we landed on. If we decided not to do a bump,
// we will use this to regenerate the changelog of the most recent version.
const newRelease = bumpType.bump !== "none";
// If we're not doing a new release and this is not the
// first release, we're just regenerating the previous changelog again.
if (!newRelease && !isFirstRelease) {
await catv.regeneratePreviousChangeLog(latestVersion, latestTag);
}
else {
// Otherwise we're either doing a bump + release, or we're releasing the
// first version as 0.0.0 (which is already the number in the file so we
// skip bumping).
await catv.invoke({
releaseAs: newRelease ? (0, bump_type_1.renderBumpType)(bumpType) : undefined,
skipBump: !newRelease,
});
}
// Validate the version that we ended up with
const newVersion = (await tryReadVersionFile(versionFile)).version;
if (!newVersion) {
throw new Error(`bump failed: ${versionFile} does not have a version set`);
}
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}`);
}
}
// Report curent status into the dist/ directory
const newTag = `${tagPrefix}v${newVersion}`;
await fs_1.promises.writeFile(bumpFile, newVersion);
await fs_1.promises.writeFile(releaseTagFile, newTag);
}
/**
* Determine based on releaseable commits whether we should release or not
*/
function hasNewInterestingCommits(options) {
const findCommits = (options.releasableCommits ?? version_1.ReleasableCommits.everyCommit().cmd).replace("$LATEST_TAG", options.latestTag);
const commitsSinceLastTag = (0, util_1.execOrUndefined)(findCommits, {
cwd: options.cwd,
})?.split("\n");
const numCommitsSinceLastTag = commitsSinceLastTag?.length ?? 0;
logging.info(`Number of commits since ${options.latestTag}: ${numCommitsSinceLastTag}`);
// Nothing to release right now
if (numCommitsSinceLastTag === 0) {
logging.info("No new interesting commits.");
return false;
}
return true;
}
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"),
};
}
/**
* 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) {
let prereleaseTag = prereleaseTags[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(`^${prefix}v([0-9]+)\\.([0-9]+)\\.([0-9]+)$`).test(x));
let releaseTag;
if (releaseTags.length > 0) {
releaseTag = releaseTags[0];
}
if (prefix) {
releaseTag = releaseTag?.substring(prefix.length);
prereleaseTag = prereleaseTag.substring(prefix.length);
}
if (releaseTag && (0, semver_1.compare)(releaseTag, prereleaseTag) === 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 };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVtcC12ZXJzaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlbGVhc2UvYnVtcC12ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBb0pBLG9CQTRKQztBQWhURCwyQkFBZ0Q7QUFDaEQsK0JBQXFDO0FBRXJDLG1DQUFpQztBQUNqQyxzQ0FBc0M7QUFDdEMsa0NBQXVEO0FBQ3ZELHdDQUErQztBQUUvQywyQ0FLcUI7QUFDckIsNkRBQTJEO0FBNkgzRDs7Ozs7Ozs7R0FRRztBQUNJLEtBQUssVUFBVSxJQUFJLENBQUMsR0FBVyxFQUFFLE9BQW9CO0lBQzFELE1BQU0sV0FBVyxHQUFHLElBQUEsV0FBSSxFQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDbkQsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUN0QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0lBQ25DLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7SUFDbkMsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQztJQUNoRCxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztJQUMxQyxNQUFNLFFBQVEsR0FBRyxJQUFBLFdBQUksRUFBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzdDLE1BQU0sYUFBYSxHQUFHLElBQUEsV0FBSSxFQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkQsTUFBTSxjQUFjLEdBQUcsSUFBQSxXQUFJLEVBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUV6RCxJQUFJLEtBQUssSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksS0FBSyxDQUNiLDJEQUEyRCxDQUM1RCxDQUFDO0lBQ0osQ0FBQztJQUNELElB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fSBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBDb25maWcgfSBmcm9tIFwiY29udmVudGlvbmFsLWNoYW5nZWxvZy1jb25maWctc3BlY1wiO1xuaW1wb3J0IHsgY29tcGFyZSB9IGZyb20gXCJzZW12ZXJcIjtcbmltcG9ydCAqIGFzIGxvZ2dpbmcgZnJvbSBcIi4uL2xvZ2dpbmdcIjtcbmltcG9ydCB7IGV4ZWNDYXB0dXJlLCBleGVjT3JVbmRlZmluZWQgfSBmcm9tIFwiLi4vdXRpbFwiO1xuaW1wb3J0IHsgUmVsZWFzYWJsZUNvbW1pdHMgfSBmcm9tIFwiLi4vdmVyc2lvblwiO1xuaW1wb3J0IHR5cGUgeyBCdW1wVHlwZSB9IGZyb20gXCIuL2J1bXAtdHlwZVwiO1xuaW1wb3J0IHtcbiAgcGFyc2VCdW1wVHlwZSxcbiAgcGVyZm9ybUJ1bXAsXG4gIHJlbGF0aXZlQnVtcFR5cGUsXG4gIHJlbmRlckJ1bXBUeXBlLFxufSBmcm9tIFwiLi9idW1wLXR5cGVcIjtcbmltcG9ydCB7IENvbW1pdEFuZFRhZ1ZlcnNpb24gfSBmcm9tIFwiLi9jb21taXQtdGFnLXZlcnNpb25cIjtcblxuZXhwb3J0IGludGVyZmFjZSBCdW1wT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiBhIC5qc29uIGZpbGUgdG8gc2V0IGB2ZXJzaW9uYC5cbiAgICovXG4gIHJlYWRvbmx5IHZlcnNpb25GaWxlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBjaGFuZ2Vsb2cgZmlsZSB0byBnZW5lcmF0ZS5cbiAgICovXG4gIHJlYWRvbmx5IGNoYW5nZWxvZzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBVc2UgYSBwcmUtcmVsZWFzZSBzdWZmaXguXG4gICAqIEBkZWZhdWx0IC0gbm9ybWFsIHZlcnNpb25pbmdcbiAgICovXG4gIHJlYWRvbmx5IHByZXJlbGVhc2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIERlZmluZXMgdGhlIG1ham9yIHZlcnNpb24gbGluZS4gVGhpcyBpcyB1c2VkIHRvIHNlbGVjdCB0aGUgbGF0ZXN0IHZlcnNpb25cbiAgICogYW5kIGFsc28gZW5mb3JjZSB0aGF0IG5ldyBtYWpvciB2ZXJzaW9ucyBhcmUgbm90IHJlbGVhc2VkIGFjY2lkZW50YWxseS5cbiAgICpcbiAgICogQ2FuIG5vdCBiZSBzZXQgdG9nZXRoZXIgd2l0aCBgbWluTWFqb3JWZXJzaW9uYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhbnkgdmVyc2lvbiBpcyBzdXBwb3J0ZWRcbiAgICovXG4gIHJlYWRvbmx5IG1ham9yVmVyc2lvbj86IG51bWJlcjtcblxuICAvKipcbiAgICogRGVmaW5lcyB0aGUgbWluaW1hbCBtYWpvciB2ZXJzaW9uLiBUaGlzIGlzIHVzZWQgaWYgeW91IHdhbnQgdG8gc3RhcnQgd2l0aFxuICAgKiBhIHNwZWNpZmljIG1ham9yIHZlcnNpb24sIGFuZCBpbmNyZW1lbnQgZnJvbSB0aGVyZSBvbi5cbiAgICogVGhpcyBjYW4gYmUgdXNlZnVsIHRvIHNldCB0byAxLCBhcyBicmVha2luZyBjaGFuZ2VzIGJlZm9yZSB0aGUgMS54IG1ham9yXG4gICAqIHJlbGVhc2UgYXJlIG5vdCBpbmNyZW1lbnRpbmcgdGhlIG1ham9yIHZlcnNpb24gbnVtYmVyLlxuICAgKlxuICAgKiBDYW4gbm90IGJlIHNldCB0b2dldGhlciB3aXRoIGBtYWpvclZlcnNpb25gLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIG1pbmltdW0gdmVyc2lvbiBpcyBiZWluZyBlbmZvcmNlZFxuICAgKi9cbiAgcmVhZG9ubHkgbWluTWFqb3JWZXJzaW9uPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIHRoZSBtaW5vciB2ZXJzaW9uIGxpbmUuIFRoaXMgaXMgdXNlZCB0byBzZWxlY3QgdGhlIGxhdGVzdCB2ZXJzaW9uXG4gICAqIGFuZCBhbHNvIGVuZm9yY2UgdGhhdCBuZXcgbWlub3IgdmVyc2lvbnMgYXJlIG5vdCByZWxlYXNlZCBhY2NpZGVudGFsbHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYW55IHZlcnNpb24gaXMgc3VwcG9ydGVkXG4gICAqL1xuICByZWFkb25seSBtaW5vclZlcnNpb24/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIGEgZmlsZSB3aGljaCB3aWxsIGluY2x1ZGUgdGhlIG91dHB1dCB2ZXJzaW9uIG51bWJlciAoYSB0ZXh0IGZpbGUpLlxuICAgKlxuICAgKiBSZWxhdGl2ZSB0byBjd2QuXG4gICAqXG4gICAqIEBleGFtcGxlIFwiLnZlcnNpb24udHh0XCJcbiAgICovXG4gIHJlYWRvbmx5IGJ1bXBGaWxlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBmaWxlIHdoaWNoIHdpbGwgaW5jbHVkZSB0aGUgcmVsZWFzZSB0YWcgKGEgdGV4dCBmaWxlKS5cbiAgICpcbiAgICogUmVsYXRpdmUgdG8gY3dkLlxuICAgKlxuICAgKiBAZXhhbXBsZSBcIi5yZWxlYXNldGFnLnR4dFwiXG4gICAqL1xuICByZWFkb25seSByZWxlYXNlVGFnRmlsZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgcHJlZml4IGFwcGxpZWQgdG8gcmVsZWFzZSB0YWdzLiBCdW1wcyB3aWxsIGJlIG1hZGUgYmFzZWQgb24gdGhlIGxhdGVzdFxuICAgKiB2ZXJzaW9uIGZvdW5kIHdpdGggdGhpcyBwcmVmaXguXG4gICAqL1xuICByZWFkb25seSB0YWdQcmVmaXg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gdmFsdWVzIHRoYXQgd291bGQgYXBwZW5kIHRvIHZlcnNpb25yYyBmaWxlIG9yIG92ZXJ3cml0ZSB2YWx1ZXNcbiAgICogY29taW5nIHRvIHRoYXQgZnJvbSBkZWZhdWx0IG9uZS5cbiAgICovXG4gIHJlYWRvbmx5IHZlcnNpb25yY09wdGlvbnM/OiBDb25maWc7XG5cbiAgLyoqXG4gICAqIEEgc2hlbGwgY29tbWFuZCB0byBsaXN0IGFsbCByZWxlYXNlIGNvbW1pdHMgc2luY2UgdGhlIGxhdGVzdCB0YWcuXG4gICAqXG4gICAqIEEgbmV3IHJlbGVhc2Ugd2lsbCBiZSBpbml0aWF0ZWQsIGlmIHRoZSBudW1iZXIgb2YgcmV0dXJuZWQgY29tbWl0cyBpcyBncmVhdGVyIHRoYW4gemVyby5cbiAgICpcbiAgICogYCRMQVRFU1RfVEFHYCB3aWxsIGJlIHJlcGxhY2VkIHdpdGggdGhlIGFjdHVhbCBsYXRlc3QgdGFnIGZvciB0aGUgZ2l2ZW4gcHJlZml4LlxuICAgKlxuICAgKiBAZGVmYXVsdCBcImdpdCBsb2cgLS1vbmVsaW5lICRMQVRFU1RfVEFHLi5IRUFEXCJcbiAgICovXG4gIHJlYWRvbmx5IHJlbGVhc2FibGVDb21taXRzPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgYGNvbW1pdC1hbmQtdGFnLXZlcnNpb25gIGNvbXBhdGlibGUgcGFja2FnZSB1c2VkIHRvIGJ1bXAgdGhlIHBhY2thZ2UgdmVyc2lvbiwgYXMgYSBkZXBlbmRlbmN5IHN0cmluZy5cbiAgICpcbiAgICogVGhpcyBjYW4gYmUgYW55IGNvbXBhdGlibGUgcGFja2FnZSB2ZXJzaW9uLCBpbmNsdWRpbmcgdGhlIGRlcHJlY2F0ZWQgYHN0YW5kYXJkLXZlcnNpb25AOWAuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwiY29tbWl0LWFuZC10YWctdmVyc2lvbkAxMlwiXG4gICAqL1xuICByZWFkb25seSBidW1wUGFja2FnZT86IHN0cmluZztcblxuICAvKipcbiAgICogQSBzaGVsbCBjb21tYW5kIHRvIGNvbnRyb2wgdGhlIG5leHQgdmVyc2lvbiB0byByZWxlYXNlLlxuICAgKlxuICAgKiBJZiBwcmVzZW50LCB0aGlzIHNoZWxsIGNvbW1hbmQgd2lsbCBiZSBydW4gYmVmb3JlIHRoZSBidW1wIGlzIGV4ZWN1dGVkLCBhbmRcbiAgICogaXQgZGV0ZXJtaW5lcyB3aGF0IHZlcnNpb24gdG8gcmVsZWFzZS4gSXQgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgZm9sbG93aW5nXG4gICAqIGVudmlyb25tZW50OlxuICAgKlxuICAgKiAtIFdvcmtpbmcgZGlyZWN0b3J5OiB0aGUgcHJvamVjdCBkaXJlY3RvcnkuXG4gICAqIC0gYCRWRVJTSU9OYDogdGhlIGN1cnJlbnQgdmVyc2lvbi4gTG9va3MgbGlrZSBgMS4yLjNgLlxuICAgKiAtIGAkTEFURVNUX1RBR2A6IHRoZSBtb3N0IHJlY2VudCB0YWcuIExvb2tzIGxpa2UgYHByZWZpeC12MS4yLjNgLCBvciBtYXkgYmUgdW5zZXQuXG4gICAqXG4gICAqIFRoZSBjb21tYW5kIHNob3VsZCBwcmludCBvbmUgb2YgdGhlIGZvbGxvd2luZyB0byBgc3Rkb3V0YDpcbiAgICpcbiAgICogLSBOb3RoaW5nOiB0aGUgbmV4dCB2ZXJzaW9uIG51bWJlciB3aWxsIGJlIGRldGVybWluZWQgYmFzZWQgb24gY29tbWl0IGhpc3RvcnkuXG4gICAqIC0gYHgueS56YDogdGhlIG5leHQgdmVyc2lvbiBudW1iZXIgd2lsbCBiZSBgeC55LnpgLlxuICAgKiAtIGBtYWpvcnxtaW5vcnxwYXRjaGA6IHRoZSBuZXh0IHZlcnNpb24gbnVtYmVyIHdpbGwgYmUgdGhlIGN1cnJlbnQgdmVyc2lvbiBudW1iZXJcbiAgICogICB3aXRoIHRoZSBpbmRpY2F0ZWQgY29tcG9uZW50IGJ1bXBlZC5cbiAgICpcbiAgICogVGhpcyBzZXR0aW5nIGNhbm5vdCBiZSBzcGVjaWZpZWQgdG9nZXRoZXIgd2l0aCBgbWluTWFqb3JWZXJzaW9uYDsgdGhlIGludm9rZWRcbiAgICogc2NyaXB0IGNhbiBiZSB1c2VkIHRvIGFjaGlldmUgdGhlIGVmZmVjdHMgb2YgYG1pbk1ham9yVmVyc2lvbmAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIG5leHQgdmVyc2lvbiB3aWxsIGJlIGRldGVybWluZWQgYmFzZWQgb24gdGhlIGNvbW1pdCBoaXN0b3J5IGFuZCBwcm9qZWN0IHNldHRpbmdzLlxuICAgKi9cbiAgcmVhZG9ubHkgbmV4dFZlcnNpb25Db21tYW5kPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBsYXRlc3QgdmVyc2lvbiBmcm9tIGdpdCB0YWdzIGFuZCB1c2VzIGBjb21taXQtYW5kLXRhZy12ZXJzaW9uYCB0byBidW1wXG4gKiB0byB0aGUgbmV4dCB2ZXJzaW9uIGJhc2VkIG9uIGNvbW1pdHMuXG4gKlxuICogVGhpcyBleHBlY3RzIGBjb21taXQtYW5kLXRhZy12ZXJzaW9uYCB0byBiZSBpbnN0YWxsZWQgaW4gdGhlIHBhdGguXG4gKlxuICogQHBhcmFtIGN3ZCB3b3JraW5nIGRpcmVjdG9yeSAoZ2l0IHJlcG9zaXRvcnkpXG4gKiBAcGFyYW0gb3B0aW9ucyBvcHRpb25zXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidW1wKGN3ZDogc3RyaW5nLCBvcHRpb25zOiBCdW1wT3B0aW9ucykge1xuICBjb25zdCB2ZXJzaW9uRmlsZSA9IGpvaW4oY3dkLCBvcHRpb25zLnZlcnNpb25GaWxlKTtcbiAgY29uc3QgcHJlcmVsZWFzZSA9IG9wdGlvbnMucHJlcmVsZWFzZTtcbiAgY29uc3QgbWFqb3IgPSBvcHRpb25zLm1ham9yVmVyc2lvbjtcbiAgY29uc3QgbWlub3IgPSBvcHRpb25zLm1pbm9yVmVyc2lvbjtcbiAgY29uc3QgbWluTWFqb3JWZXJzaW9uID0gb3B0aW9ucy5taW5NYWpvclZlcnNpb247XG4gIGNvbnN0IHRhZ1ByZWZpeCA9IG9wdGlvbnMudGFnUHJlZml4ID8/IFwiXCI7XG4gIGNvbnN0IGJ1bXBGaWxlID0gam9pbihjd2QsIG9wdGlvbnMuYnVtcEZpbGUpO1xuICBjb25zdCBjaGFuZ2Vsb2dGaWxlID0gam9pbihjd2QsIG9wdGlvbnMuY2hhbmdlbG9nKTtcbiAgY29uc3QgcmVsZWFzZVRhZ0ZpbGUgPSBqb2luKGN3ZCwgb3B0aW9ucy5yZWxlYXNlVGFnRmlsZSk7XG5cbiAgaWYgKG1ham9yICYmIG1pbk1ham9yVmVyc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBtaW5NYWpvclZlcnNpb24gYW5kIG1ham9yVmVyc2lvbiBjYW5ub3QgYmUgdXNlZCB0b2dldGhlci5gLFxuICAgICk7XG4gIH1cbiAgaWYgKG9wdGlvbnMubmV4dFZlcnNpb25Db21tYW5kICYmIG1pbk1ham9yVmVyc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBtaW5NYWpvclZlcnNpb24gYW5kIG5leHRWZXJzaW9uQ29tbWFuZCBjYW5ub3QgYmUgdXNlZCB0b2dldGhlci5gLFxuICAgICk7XG4gIH1cbiAgaWYgKG1pbm9yICYmICFtYWpvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihgbWlub3JWZXJzaW9uIGFuZCBtYWpvclZlcnNpb24gbXVzdCBiZSB1c2VkIHRvZ2V0aGVyLmApO1xuICB9XG5cbiAgYXdhaXQgZnMubWtkaXIoZGlybmFtZShidW1wRmlsZSksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICBhd2FpdCBmcy5ta2RpcihkaXJuYW1lKGNoYW5nZWxvZ0ZpbGUpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgYXdhaXQgZnMubWtkaXIoZGlybmFtZShyZWxlYXNlVGFnRmlsZSksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHsgbGF0ZXN0VmVyc2lvbiwgbGF0ZXN0VGFnLCBpc0ZpcnN0UmVsZWFzZSB9ID0gZGV0ZXJtaW5lTGF0ZXN0VGFnKHtcbiAgICBjd2QsXG4gICAgbWFqb3IsXG4gICAgbWlub3IsXG4gICAgcHJlcmVsZWFzZSxcbiAgICBwcmVmaXg6IHRhZ1ByZWZpeCxcbiAgfSk7XG5cbiAgLy8gV3JpdGUgdGhlIGN1cnJlbnQgdmVyc2lvbiBpbnRvIHRoZSB2ZXJzaW9uIGZpbGUgc28gdGhhdCBDQVRWIHdpbGwga25vdyB0aGUgY3VycmVudCB2ZXJzaW9uXG4gIGNvbnN0IHsgY29udGVudHMsIG5ld2xpbmUgfSA9IGF3YWl0IHRyeVJlYWRWZXJzaW9uRmlsZSh2ZXJzaW9uRmlsZSk7XG4gIGNvbnRlbnRzLnZlcnNpb24gPSBsYXRlc3RWZXJzaW9uO1xuICBsb2dnaW5nLmluZm8oXG4gICAgYFVwZGF0ZSAke3ZlcnNpb25GaWxlfSB0byBsYXRlc3QgcmVzb2x2ZWQgdmVyc2lvbjogJHtsYXRlc3RWZXJzaW9ufWAsXG4gICk7XG4gIGF3YWl0IGZzLndyaXRlRmlsZShcbiAgICB2ZXJzaW9uRmlsZSxcbiAgICBKU09OLnN0cmluZ2lmeShjb250ZW50cywgdW5kZWZpbmVkLCAyKSArIChuZXdsaW5lID8gXCJcXG5cIiA6IFwiXCIpLFxuICApO1xuXG4gIC8vIERldGVybWluZSB0aGUgaW5pdGlhbCBidW1wIHN0YXR1cy4gQ0FUViB3aWxsIGFsd2F5cyBkbyBhIHBhdGNoIGV2ZW4gaWZcbiAgLy8gdGhlcmUgYXJlIG5vIGNvbW1pdHMsIHNvIGxvb2sgYXQgY29tbWl0cyBvdXJzZWx2ZXMgZmlyc3QgdG8gZGVjaWRlXG4gIC8vIGlmIHdlIGV2ZW4gc2hvdWxkIGRvIG5vdGhpbmcgYXQgYWxsLlxuICBjb25zdCBzaG91bGRSZWxlYXNlID0gaXNGaXJzdFJlbGVhc2VcbiAgICA/IHRydWVcbiAgICA6IGhhc05ld0ludGVyZXN0aW5nQ29tbWl0cyh7XG4gICAgICAgIGN3ZCxcbiAgICAgICAgbGF0ZXN0VGFnLFxuICAgICAgICByZWxlYXNhYmxlQ29tbWl0czogb3B0aW9ucy5yZWxlYXNhYmxlQ29tbWl0cyxcbiAgICAgIH0pO1xuXG4gIGNvbnN0IGNhdHYgPSBuZXcgQ29tbWl0QW5kVGFnVmVyc2lvbihvcHRpb25zLmJ1bXBQYWNrYWdlLCBjd2QsIHtcbiAgICB2ZXJzaW9uRmlsZSxcbiAgICBjaGFuZ2Vsb2dGaWxlLFxuICAgIHByZXJlbGVhc2UsXG4gICAgY29uZmlnT3B0aW9uczogb3B0aW9ucy52ZXJzaW9ucmNPcHRpb25zLFxuICAgIHRhZ1ByZWZpeCxcbiAgfSk7XG5cbiAgLy8gV2UgdXNlZCB0byB0cmFuc2xhdGUgYGlzRmlyc3RSZWxlYXNlYCB0byB0aGUgYC0tZmlyc3QtcmVsZWFzZWAgZmxhZyBvZiBDQVRWLlxuICAvLyBXaGF0IHRoYXQgZG9lcyBpcyBza2lwIGEgYnVtcCwgb25seSBnZW5lcmF0ZSB0aGUgY2hhbmdlbG9nLlxuICAvL1xuICAvLyBPdXIgYHsgYnVtcDogbm9uZSB9YCBkb2VzIHRoZSBzYW1lLCBzbyB3ZSBkb24ndCBuZWVkIHRvIGNhcnJ5IG92ZXIgdGhpc1xuICAvLyBmbGFnIGFueW1vcmUuXG4gIGxldCBidW1wVHlwZTogQnVtcFR5cGUgPVxuICAgIHNob3VsZFJlbGVhc2UgJiYgIWlzRmlyc3RSZWxlYXNlXG4gICAgICA/IHJlbGF0aXZlQnVtcFR5cGUobGF0ZXN0VmVyc2lvbiwgYXdhaXQgY2F0di5kcnlSdW4oKSlcbiAgICAgIDogeyBidW1wOiBcIm5vbmVcIiB9O1xuXG4gIGxvZ2dpbmcuaW5mbyhgQnVtcCBmcm9tIGNvbW1pdHM6ICR7cmVuZGVyQnVtcFR5cGUoYnVtcFR5cGUpfWApO1xuICBpZiAob3B0aW9ucy5uZXh0VmVyc2lvbkNvbW1hbmQpIHtcbiAgICBjb25zdCBuZXh0VmVyc2lvbiA9IGV4ZWNDYXB0dXJlKG9wdGlvbnMubmV4dFZlcnNpb25Db21tYW5kLCB7XG4gICAgICBjd2QsXG4gICAgICBtb2RFbnY6IHtcbiAgICAgICAgVkVSU0lPTjogbGF0ZXN0VmVyc2lvbixcbiAgICAgICAgU1VHR0VTVEVEX0JVTVA6IHJlbmRlckJ1bXBUeXBlKGJ1bXBUeXBlKSxcbiAgICAgICAgLi4uKGxhdGVzdFRhZyA/IHsgTEFURVNUX1RBRzogbGF0ZXN0VGFnIH0gOiB7fSksXG4gICAgICB9LFxuICAgIH0pXG4gICAgICAudG9TdHJpbmcoKVxuICAgICAgLnRyaW0oKTtcblxuICAgIGlmIChuZXh0VmVyc2lvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYnVtcFR5cGUgPSBwYXJzZUJ1bXBUeXBlKG5leHRWZXJzaW9uKTtcbiAgICAgICAgbG9nZ2luZy5pbmZvKFxuICAgICAgICAgIGBCdW1wIGZyb20gbmV4dFZlcnNpb25Db21tYW5kOiAke3JlbmRlckJ1bXBUeXBlKGJ1bXBUeXBlKX1gLFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYG5leHRWZXJzaW9uQ29tbWFuZCBcIiR7b3B0aW9ucy5uZXh0VmVyc2lvbkNvbW1hbmR9XCIgcmV0dXJuZWQgaW52YWxpZCBvdXRwdXQ6ICR7ZX1gLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFJlc3BlY3QgbWluTWFqb3JWZXJzaW9uIHRvIGNvcnJlY3QgdGhlIHJlc3VsdCBvZiB0aGUgbmV4dFZlcnNpb25Db21tYW5kXG4gIGlmIChtaW5NYWpvclZlcnNpb24pIHtcbiAgICBjb25zdCBidW1wZWRWZXJzaW9uID0gcGVyZm9ybUJ1bXAobGF0ZXN0VmVyc2lvbiwgYnVtcFR5cGUpO1xuICAgIGNvbnN0IFttYWpvclZlcnNpb25dID0gYnVtcGVkVmVyc2lvbi5zcGxpdChcIi5cIik7XG4gICAgY29uc3QgbWFqb3JWZXJzaW9uTnVtYmVyID0gcGFyc2VJbnQobWFqb3JWZXJzaW9uLCAxMCk7XG4gICAgaWYgKG1ham9yVmVyc2lvbk51bWJlciA8IG1pbk1ham9yVmVyc2lvbikge1xuICAgICAgYnVtcFR5cGUgPSB7IGJ1bXA6IFwiYWJzb2x1dGVcIiwgYWJzb2x1dGU6IGAke21pbk1ham9yVmVyc2lvbn0uMC4wYCB9O1xuICAgIH1cbiAgfVxuXG4gIC8vIEludm9rZSBDQVRWIHdpdGggdGhlIG9wdGlvbnMgd2UgbGFuZGVkIG9uLiBJZiB3ZSBkZWNpZGVkIG5vdCB0byBkbyBhIGJ1bXAsXG4gIC8vIHdlIHdpbGwgdXNlIHRoaXMgdG8gcmVnZW5lcmF0ZSB0aGUgY2hhbmdlbG9nIG9mIHRoZSBtb3N0IHJlY2VudCB2ZXJzaW9uLlxuICBjb25zdCBuZXdSZWxlYXNlID0gYnVtcFR5cGUuYnVtcCAhPT0gXCJub25lXCI7XG5cbiAgLy8gSWYgd2UncmUgbm90IGRvaW5nIGEgbmV3IHJlbGVhc2UgYW5kIHRoaXMgaXMgbm90IHRoZVxuICAvLyBmaXJzdCByZWxlYXNlLCB3ZSdyZSBqdXN0IHJlZ2VuZXJhdGluZyB0aGUgcHJldmlvdXMgY2hhbmdlbG9nIGFnYWluLlxuICBpZiAoIW5ld1JlbGVhc2UgJiYgIWlzRmlyc3RSZWxlYXNlKSB7XG4gICAgYXdhaXQgY2F0di5yZWdlbmVyYXRlUHJldmlvdXNDaGFuZ2VMb2cobGF0ZXN0VmVyc2lvbiwgbGF0ZXN0VGFnKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBPdGhlcndpc2Ugd2UncmUgZWl0aGVyIGRvaW5nIGEgYnVtcCArIHJlbGVhc2UsIG9yIHdlJ3JlIHJlbGVhc2luZyB0aGVcbiAgICAvLyBmaXJzdCB2ZXJzaW9uIGFzIDAuMC4wICh3aGljaCBpcyBhbHJlYWR5IHRoZSBudW1iZXIgaW4gdGhlIGZpbGUgc28gd2VcbiAgICAvLyBza2lwIGJ1bXBpbmcpLlxuICAgIGF3YWl0IGNhdHYuaW52b2tlKHtcbiAgICAgIHJlbGVhc2VBczogbmV3UmVsZWFzZSA/IHJlbmRlckJ1bXBUeXBlKGJ1bXBUeXBlKSA6IHVuZGVmaW5lZCxcbiAgICAgIHNraXBCdW1wOiAhbmV3UmVsZWFzZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFZhbGlkYXRlIHRoZSB2ZXJzaW9uIHRoYXQgd2UgZW5kZWQgdXAgd2l0aFxuICBjb25zdCBuZXdWZXJzaW9uID0gKGF3YWl0IHRyeVJlYWRWZXJzaW9uRmlsZSh2ZXJzaW9uRmlsZSkpLnZlcnNpb247XG4gIGlmICghbmV3VmVyc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcihgYnVtcCBmYWlsZWQ6ICR7dmVyc2lvbkZpbGV9IGRvZXMgbm90IGhhdmUgYSB2ZXJzaW9uIHNldGApO1xuICB9XG4gIGlmIChtYWpvcikge1xuICAgIGlmICghbmV3VmVyc2lvbi5zdGFydHNXaXRoKGAke21ham9yfS5gKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgYnVtcCBmYWlsZWQ6IHRoaXMgYnJhbmNoIGlzIGNvbmZpZ3VyZWQgdG8gb25seSBwdWJsaXNoIHYke21ham9yfSByZWxlYXNlcyAtIGJ1bXAgcmVzdWx0ZWQgaW4gJHtuZXdWZXJzaW9ufWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBpZiAobWlub3IpIHtcbiAgICBpZiAoIW5ld1ZlcnNpb24uc3RhcnRzV2l0aChgJHttYWpvcn0uJHttaW5vcn1gKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgYnVtcCBmYWlsZWQ6IHRoaXMgYnJhbmNoIGlzIGNvbmZpZ3VyZWQgdG8gb25seSBwdWJsaXNoIHYke21ham9yfS4ke21pbm9yfSByZWxlYXNlcyAtIGJ1bXAgcmVzdWx0ZWQgaW4gJHtuZXdWZXJzaW9ufWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJlcG9ydCBjdXJlbnQgc3RhdHVzIGludG8gdGhlIGRpc3QvIGRpcmVjdG9yeVxuICBjb25zdCBuZXdUYWcgPSBgJHt0YWdQcmVmaXh9diR7bmV3VmVyc2lvbn1gO1xuICBhd2FpdCBmcy53cml0ZUZpbGUoYnVtcEZpbGUsIG5ld1ZlcnNpb24pO1xuICBhd2FpdCBmcy53cml0ZUZpbGUocmVsZWFzZVRhZ0ZpbGUsIG5ld1RhZyk7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGJhc2VkIG9uIHJlbGVhc2VhYmxlIGNvbW1pdHMgd2hldGhlciB3ZSBzaG91bGQgcmVsZWFzZSBvciBub3RcbiAqL1xuZnVuY3Rpb24gaGFzTmV3SW50ZXJlc3RpbmdDb21taXRzKG9wdGlvbnM6IHtcbiAgcmVsZWFzYWJsZUNvbW1pdHM/OiBzdHJpbmc7XG4gIGxhdGVzdFRhZzogc3RyaW5nO1xuICBjd2Q6IHN0cmluZztcbn0pIHtcbiAgY29uc3QgZmluZENvbW1pdHMgPSAoXG4gICAgb3B0aW9ucy5yZWxlYXNhYmxlQ29tbWl0cyA/PyBSZWxlYXNhYmxlQ29tbWl0cy5ldmVyeUNvbW1pdCgpLmNtZFxuICApLnJlcGxhY2UoXCIkTEFURVNUX1RBR1wiLCBvcHRpb25zLmxhdGVzdFRhZyk7XG5cbiAgY29uc3QgY29tbWl0c1NpbmNlTGFzdFRhZyA9IGV4ZWNPclVuZGVmaW5lZChmaW5kQ29tbWl0cywge1xuICAgIGN3ZDogb3B0aW9ucy5jd2QsXG4gIH0pPy5zcGxpdChcIlxcblwiKTtcbiAgY29uc3QgbnVtQ29tbWl0c1NpbmNlTGFzdFRhZyA9IGNvbW1pdHNTaW5jZUxhc3RUYWc/Lmxlbmd0aCA/PyAwO1xuICBsb2dnaW5nLmluZm8oXG4gICAgYE51bWJlciBvZiBjb21taXRzIHNpbmNlICR7b3B0aW9ucy5sYXRlc3RUYWd9OiAke251bUNvbW1pdHNTaW5jZUxhc3RUYWd9YCxcbiAgKTtcblxuICAvLyBOb3RoaW5nIHRvIHJlbGVhc2UgcmlnaHQgbm93XG4gIGlmIChudW1Db21taXRzU2luY2VMYXN0VGFnID09PSAwKSB7XG4gICAgbG9nZ2luZy5pbmZvKFwiTm8gbmV3IGludGVyZXN0aW5nIGNvbW1pdHMuXCIpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5hc3luYyBmdW5jdGlvbiB0cnlSZWFkVmVyc2lvbkZpbGUoXG4gIHZlcnNpb25GaWxlOiBzdHJpbmcsXG4pOiBQcm9taXNlPHsgY29udGVudHM6IGFueTsgdmVyc2lvbj86IHN0cmluZzsgbmV3bGluZTogYm9vbGVhbiB9PiB7XG4gIGlmICghZXhpc3RzU3luYyh2ZXJzaW9uRmlsZSkpIHtcbiAgICByZXR1cm4geyBjb250ZW50czoge30sIG5ld2xpbmU6IHRydWUgfTtcbiAgfVxuICBjb25zdCByYXcgPSBhd2FpdCBmcy5yZWFkRmlsZSh2ZXJzaW9uRmlsZSwgXCJ1dGYtOFwiKTtcbiAgY29uc3QgY29udGVudHMgPSBKU09OLnBhcnNlKHJhdyk7XG5cbiAgcmV0dXJuIHtcbiAgICBjb250ZW50cyxcbiAgICB2ZXJzaW9uOiBjb250ZW50cy52ZXJzaW9uLFxuICAgIG5ld2xpbmU6IHJhdy5lbmRzV2l0aChcIlxcblwiKSxcbiAgfTtcbn1cblxuaW50ZXJmYWNlIExhdGVzdFRhZ09wdGlvbnMge1xuICAvKipcbiAgICogV29ya2luZyBkaXJlY3Rvcnkgb2YgdGhlIGdpdCByZXBvc2l0b3J5LlxuICAgKi9cbiAgcmVhZG9ubHkgY3dkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBNYWpvciB2ZXJzaW9uIHRvIHNlbGVjdCBmcm9tLlxuICAgKi9cbiAgcmVhZG9ubHkgbWFqb3I/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBNaW5vciB2ZXJzaW9uIHRvIHNlbGVjdCBmcm9tLlxuICAgKi9cbiAgcmVhZG9ubHkgbWlub3I/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBBIHByZS1yZWxlYXNlIHN1ZmZpeC5cbiAgICovXG4gIHJlYWRvbmx5IHByZXJlbGVhc2U/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBBIHByZWZpeCBhcHBsaWVkIHRvIGFsbCB0YWdzLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJlZml4OiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB0aGUgbGF0ZXN0IHJlbGVhc2UgdGFnLlxuICogQHBhcmFtIG1ham9yIChvcHRpb25hbCkgQSBtYWpvciB2ZXJzaW9uIGxpbmUgdG8gc2VsZWN0IGZyb21cbiAqIEBwYXJhbSBwcmVyZWxlYXNlIChvcHRpb25hbCkgQSBwcmUtcmVsZWFzZSBzdWZmaXguXG4gKiBAcmV0dXJucyB0aGUgbGF0ZXN0IHRhZywgYW5kIHdoZXRoZXIgaXQgaXMgdGhlIGZpcnN0IHJlbGVhc2Ugb3Igbm90XG4gKi9cbmZ1bmN0aW9uIGRldGVybWluZUxhdGVzdFRhZyhvcHRpb25zOiBMYXRlc3RUYWdPcHRpb25zKToge1xuICBsYXRlc3RWZXJzaW9uOiBzdHJpbmc7XG4gIGxhdGVzdFRhZzogc3RyaW5nO1xuICBpc0ZpcnN0UmVsZWFzZTogYm9vbGVhbjtcbn0ge1xuICBjb25zdCB7IGN3ZCwgbWFqb3IsIG1pbm9yLCBwcmVyZWxlYXNlLCBwcmVmaXggfSA9IG9wdGlvbnM7XG5cbiAgLy8gZmlsdGVyIG9ubHkgdGFncyBmb3IgdGhpcyBwcmVmaXggYW5kIG1ham9yIHZlcnNpb24gaWYgc3BlY2lmaWVkIChzdGFydCB3aXRoIFwidk5OLlwiKS5cbiAgbGV0IHByZWZpeEZpbHRlcjogc3RyaW5nO1xuICBpZiAobWFqb3IgIT09IHVuZGVmaW5lZCAmJiBtaW5vciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcHJlZml4RmlsdGVyID0gYCR7cHJlZml4fXYke21ham9yfS4ke21pbm9yfS4qYDtcbiAgfSBlbHNlIGlmIChtYWpvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcHJlZml4RmlsdGVyID0gYCR7cHJlZml4fXYke21ham9yfS4qYDtcbiAgfSBlbHNlIHtcbiAgICBwcmVmaXhGaWx0ZXIgPSBgJHtwcmVmaXh9dipgO1xuICB9XG5cbiAgY29uc3QgbGlzdEdpdFRhZ3MgPSBbXG4gICAgXCJnaXRcIixcbiAgICAnLWMgXCJ2ZXJzaW9uc29ydC5zdWZmaXg9LVwiJywgLy8gbWFrZXMgc3VyZSBwcmUtcmVsZWFzZSB2ZXJzaW9ucyBhcmUgbGlzdGVkIGFmdGVyIHRoZSBwcmltYXJ5IHZlcnNpb25cbiAgICBcInRhZ1wiLFxuICAgICctLXNvcnQ9XCItdmVyc2lvbjpyZWZuYW1lXCInLCAvLyBzb3J0IGFzIHZlcnNpb25zIGFuZCBub3QgbGV4aWNvZ3JhcGhpY2FsbHlcbiAgICBcIi0tbGlzdFwiLFxuICAgIGBcIiR7cHJlZml4RmlsdGVyfVwiYCxcbiAgXS5qb2luKFwiIFwiKTtcblxuICBjb25zdCBzdGRvdXQgPSBleGVjQ2FwdHVyZShsaXN0R2l0VGFncywgeyBjd2QgfSkudG9TdHJpbmcoXCJ1dGY4XCIpO1xuXG4gIGxldCB0YWdzID0gc3Rkb3V0Py5zcGxpdChcIlxcblwiKTtcblxuICAvLyBpZiBwcmVyZWxlYXNlIGlzIHNldCBhbmQgdGhlcmUgYXJlIGV4aXN0aW5nIHByZXJlbGVhc2UgdGFncywgZmlsdGVyIHZlcnNpb25zIHRoYXQgZW5kIHdpdGggXCItUFJFLmRkZFwiLlxuICBjb25zdCBwcmVyZWxlYXNlVGFncyA9IHRhZ3MuZmlsdGVyKCh4KSA9PlxuICAgIG5ldyBSZWdFeHAoYC0ke3ByZXJlbGVhc2V9XFxcXC5bMC05XSskYCkudGVzdCh4KSxcbiAgKTtcbiAgaWYgKHByZXJlbGVhc2UgJiYgcHJlcmVsZWFzZVRhZ3MubGVuZ3RoID4gMCkge1xuICAgIGxldCBwcmVyZWxlYXNlVGFnID0gcHJlcmVsZWFzZVRhZ3NbMF07XG5cbiAgICAvKipcbiAgICAgKiBDb3ZlciB0aGUgZm9sbG93aW5nIGNhc2Ugc3BlY2lmaWNhbGx5XG4gICAgICogMSAtIHYxLjAuMFxuICAgICAqIDIgLSB2MS4wLjEtYmV0YS4wXG4gICAgICogMyAtIHYxLjAuMS1iZXRhLjFcbiAgICAgKiA0IC0gdjEuMC4xXG4gICAgICogNSAtIG5vdyBwdWJsaXNoIGEgbmV3IHJlbGVhc2Ugb24gdGhlIHByZXJlbGVhc2UgYnJhbmNoXG4gICAgICogICAgYnkgc2V0dGluZyB0aGUgbGF0ZXN0VGFnIGFzIHYxLjAuMSBpbnN0ZWFkIG9mIHYxLjAuMS1iZXRhLjFcbiAgICAgKi9cbiAgICBjb25zdCByZWxlYXNlVGFncyA9IHRhZ3MuZmlsdGVyKCh4KSA9PlxuICAgICAgbmV3IFJlZ0V4cChgXiR7cHJlZml4fXYoWzAtOV0rKVxcXFwuKFswLTldKylcXFxcLihbMC05XSspJGApLnRlc3QoeCksXG4gICAgKTtcblxuICAgIGxldCByZWxlYXNlVGFnOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKHJlbGVhc2VUYWdzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJlbGVhc2VUYWcgPSByZWxlYXNlVGFnc1swXTtcbiAgICB9XG5cbiAgICBpZiAocHJlZml4KSB7XG4gICAgICByZWxlYXNlVGFnID0gcmVsZWFzZVRhZz8uc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpO1xuICAgICAgcHJlcmVsZWFzZVRhZyA9IHByZXJlbGVhc2VUYWcuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpO1xuICAgIH1cblxuICAgIGlmIChyZWxlYXNlVGFnICYmIGNvbXBhcmUocmVsZWFzZVRhZywgcHJlcmVsZWFzZVRhZykgPT09IDEpIHtcbiAgICAgIHRhZ3MgPSByZWxlYXNlVGFncztcbiAgICB9IGVsc2Uge1xuICAgICAgdGFncyA9IHByZXJlbGVhc2VUYWdzO1xuICAgIH1cbiAgfVxuXG4gIHRhZ3MgPSB0YWdzLmZpbHRlcigoeCkgPT4geCk7XG5cbiAgLy8gaWYgYSBwcmUtcmVsZWFzZSB0YWcgaXMgdXNlZCwgdGhlbiBhZGQgaXQgdG8gdGhlIGluaXRpYWwgdmVyc2lvblxuICBsZXQgaXNGaXJzdFJlbGVhc2UgPSBmYWxzZTtcbiAgbGV0IGxhdGVzdFRhZztcblxuICBpZiAodGFncy5sZW5ndGggPiAwKSB7XG4gICAgbGF0ZXN0VGFnID0gdGFnc1swXTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBpbml0aWFsID0gYCR7cHJlZml4fXYke21ham9yID8/IDB9LiR7bWlub3IgPz8gMH0uMGA7XG4gICAgbGF0ZXN0VGFnID0gcHJlcmVsZWFzZSA/IGAke2luaXRpYWx9LSR7cHJlcmVsZWFzZX0uMGAgOiBpbml0aWFsO1xuICAgIGlzRmlyc3RSZWxlYXNlID0gdHJ1ZTtcbiAgfVxuXG4gIC8vIHJlbW92ZSB0YWcgcHJlZml4IChpZiBleGlzdHMpXG4gIGxldCBsYXRlc3RWZXJzaW9uID0gbGF0ZXN0VGFnO1xuICBpZiAocHJlZml4ICYmIGxhdGVzdFZlcnNpb24uc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgbGF0ZXN0VmVyc2lvbiA9IGxhdGVzdFZlcnNpb24uc3Vic3RyKHByZWZpeC5sZW5ndGgpO1xuICB9XG5cbiAgLy8gcmVtb3ZlIFwidlwiIHByZWZpeCAoaWYgZXhpc3RzKVxuICBpZiAobGF0ZXN0VmVyc2lvbi5zdGFydHNXaXRoKFwidlwiKSkge1xuICAgIGxhdGVzdFZlcnNpb24gPSBsYXRlc3RWZXJzaW9uLnN1YnN0cmluZygxKTtcbiAgfVxuXG4gIHJldHVybiB7IGxhdGVzdFZlcnNpb24sIGxhdGVzdFRhZywgaXNGaXJzdFJlbGVhc2UgfTtcbn1cbiJdfQ==