UNPKG

jsii-release

Version:

Release jsii modules to multiple package managers

612 lines 75.1 kB
"use strict";
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
    if (value !== null && value !== void 0) {
        if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
        var dispose, inner;
        if (async) {
            if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
            dispose = value[Symbol.asyncDispose];
        }
        if (dispose === void 0) {
            if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
            dispose = value[Symbol.dispose];
            if (async) inner = dispose;
        }
        if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
        if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
        env.stack.push({ value: value, dispose: dispose, async: async });
    }
    else if (async) {
        env.stack.push({ async: true });
    }
    return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
    return function (env) {
        function fail(e) {
            env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
            env.hasError = true;
        }
        var r, s = 0;
        function next() {
            while (r = env.stack.pop()) {
                try {
                    if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
                    if (r.dispose) {
                        var result = r.dispose.call(r.value);
                        if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
                    }
                    else s |= 1;
                }
                catch (e) {
                    fail(e);
                }
            }
            if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
            if (env.hasError) throw env.error;
        }
        return next();
    };
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.autoCleanDir = autoCleanDir;
/**
 * Legacy vs compatibility endpoint
 * ==================================
 *
 * This script talks about legacy vs compatibility endpoint a bunch.
 *
 * Both implement the Nexus 2 protocol, however:
 *
 * - The "legacy" endpoint is the Sonatype OSSRH endpoint that was deprecated June 2025.
 * - The "compatibility" endpoint is a Nexus 2-compatible endpoint stood up for the new
 *   publishing service, Central Publishing.
 *
 * It should be the same protocol but of course there are subtle differences
 * between them (in how they signal error when you try to republish an already
 * published version, and even in the wire protocol accepted) so we have to
 * treat them differently here.
 *
 * There is also an "official new" protocol for the new publishing mechanism,
 * but the Maven plugin they supply for that doesn't support that. In their words:
 *
 * > it appears that you are using the "two stage"[1] deployment process, which is
 * > not yet supported by the new plugin. You are the first publisher to have
 * > requested this, so we were not familiar with this specific usecase when
 * > building the new plugin
 * > [1] <https://github.com/sonatype/nexus-maven-plugins/blob/43a9940b134c3f87ebe4daa82552e844d9c578b8/staging/maven-plugin/WORKFLOWS.md#two-shots>
 */
const fs_1 = require("fs");
const zx_1 = require("zx");
const LEGACY_OSSRH_SERVER_ID = 'ossrh';
const COMPAT_CENTRAL_SERVER_ID = 'central-ossrh';
const NEXUS_MAVEN_STAGING_PLUGIN = 'org.sonatype.plugins:nexus-staging-maven-plugin:1.7.0';
async function main() {
    const args = process.argv.slice(2);
    const javaRoot = args[0] ?? 'dist/java';
    (0, zx_1.cd)(javaRoot);
    const poms = await (0, zx_1.glob)('**/*.pom');
    if (poms.length === 0) {
        throw new SimpleError(`No JARS to publish: no .pom files found under ${process.cwd()}`);
    }
    (0, zx_1.echo)(`POMs found: ${poms}`);
    const sharedOptions = {
        username: envVar('MAVEN_USERNAME'),
        password: envVar('MAVEN_PASSWORD'),
        dryRun: process.env.MAVEN_DRYRUN === 'true',
        verbose: process.env.MAVEN_VERBOSE === 'true',
        poms,
    };
    let options;
    const serverId = process.env.MAVEN_SERVER_ID ?? LEGACY_OSSRH_SERVER_ID;
    switch (serverId) {
        case LEGACY_OSSRH_SERVER_ID:
            options = {
                type: 'legacy-ossrh',
                ...sharedOptions,
                stagingProfileId: envVar('MAVEN_STAGING_PROFILE_ID'),
                endpoint: process.env.MAVEN_ENDPOINT,
                privateKey: parsePrivateKeyFromEnv(),
            };
            break;
        case COMPAT_CENTRAL_SERVER_ID:
            options = {
                type: 'compat-ossrh',
                ...sharedOptions,
                // Not required by the new endpoint: can be any value (maybe never was required to begin with?)
                stagingProfileId: 'publib',
                endpoint: process.env.MAVEN_ENDPOINT,
                privateKey: parsePrivateKeyFromEnv(),
            };
            break;
        default:
            // We haven't implemented signing for this, so fail loudly if people try to use it anyway
            if (process.env.MAVEN_GPG_PRIVATE_KEY || process.env.MAVEN_GPG_PRIVATE_KEY_FILE) {
                throw new SimpleError('MAVEN_GPG_PRIVATE_KEY[_FILE] is only supported for OSSRH publishing');
            }
            options = {
                type: 'custom-nexus',
                ...sharedOptions,
                serverId,
                repositoryUrl: envVar('MAVEN_REPOSITORY_URL'),
            };
            break;
    }
    await mavenPublish(options);
    (0, zx_1.echo)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
    (0, zx_1.echo)('✅ All Done!');
}
function parsePrivateKeyFromEnv() {
    if (process.env.MAVEN_GPG_PRIVATE_KEY_FILE) {
        return { type: 'file', fileName: process.env.MAVEN_GPG_PRIVATE_KEY_FILE, passPhrase: envVar('MAVEN_GPG_PRIVATE_KEY_PASSPHRASE') };
    }
    if (process.env.MAVEN_GPG_PRIVATE_KEY) {
        return { type: 'material', keyMaterial: process.env.MAVEN_GPG_PRIVATE_KEY, passPhrase: envVar('MAVEN_GPG_PRIVATE_KEY_PASSPHRASE') };
    }
    throw new SimpleError('MAVEN_GPG_PRIVATE_KEY[_FILE] is required');
}
//----------------------------------------------------------------------
//  Publishing functions
//
async function mavenPublish(options) {
    const env_1 = { stack: [], error: void 0, hasError: false };
    try {
        const workDir = __addDisposableResource(env_1, autoCleanDir(), true);
        const maven = new Maven(workDir.dir, options.verbose, options.dryRun);
        const x = options.type;
        switch (x) {
            case 'legacy-ossrh':
                await deployLegacyOssrh(maven, options);
                break;
            case 'compat-ossrh':
                await deployCompatOssrh(maven, options);
                break;
            case 'custom-nexus':
                await deployCustomNexus(maven, options);
                break;
            default:
                assertNever(x);
        }
    }
    catch (e_1) {
        env_1.error = e_1;
        env_1.hasError = true;
    }
    finally {
        const result_1 = __disposeResources(env_1);
        if (result_1)
            await result_1;
    }
}
/**
 * Deploy to the legacy OSSRH Nexus server
 */
async function deployLegacyOssrh(maven, options) {
    (0, zx_1.echo)('📦 Publishing to Maven Central');
    const defaultEndpoint = 'https://oss.sonatype.org';
    const staged = await deployStagedRepository(maven, {
        ...options,
        endpoint: options.endpoint ?? defaultEndpoint,
        republishWill400: false,
    });
    if (staged.type !== 'success') {
        return;
    }
    /*
    const released = await releaseRepo({
      serverUrl: options.endpoint ?? defaultEndpoint,
      username: options.username,
      password: options.password,
      repositoryId: staged.repositoryId,
    });
  
    if (released) {
      return;
    }
    */
    // Send a remote release command to the repository
    const releaseOutput = await maven.exec(`${NEXUS_MAVEN_STAGING_PLUGIN}:rc-release`, {
        properties: {
            nexusUrl: options.endpoint ?? defaultEndpoint,
            serverId: staged.serverId,
            stagingRepositoryId: staged.repositoryId,
        },
        nothrow: true,
    });
    if (!releaseOutput) {
        (0, zx_1.echo)('🏜️ Stopped here because of dry-run');
        return;
    }
    if (releaseOutput.exitCode !== 0) {
        // If release failed, check if this was caused because we are trying to publish
        // the same version again, which is not an error. The magic string "does not
        // allow updating artifact" for a ".pom" file indicates that we are trying to
        // override an existing version. Otherwise, fail!
        const looksLikeDuplicatePublish = releaseOutput.lines()
            .filter(l => l.includes('does not allow updating artifact'))
            .filter(l => l.includes('.pom'))
            .length > 0;
        if (!looksLikeDuplicatePublish) {
            throw new SimpleError('Release failed');
        }
        (0, zx_1.echo)('⚠️ Artifact already published. Skipping');
    }
}
/**
 * Deploy to the compat OSSRH Nexus server
 */
async function deployCompatOssrh(maven, options) {
    (0, zx_1.echo)('📦 Publishing to Maven Central (Compat endpoint)');
    const defaultEndpoint = 'https://ossrh-staging-api.central.sonatype.com/';
    const endpoint = options.endpoint ?? defaultEndpoint;
    const staged = await deployStagedRepository(maven, {
        ...options,
        endpoint,
        republishWill400: true,
    });
    if (staged.type !== 'success') {
        return;
    }
    const released = await releaseRepo({
        serverUrl: endpoint,
        username: options.username,
        password: options.password,
        repositoryId: staged.repositoryId,
    });
    if (released === 'duplicate-version') {
        (0, zx_1.echo)('⚠️ Version(s) already published. Skipping');
    }
}
/**
 * Deploy to a custom Nexus server
 */
async function deployCustomNexus(maven, options) {
    (0, zx_1.echo)(`📦 Publishing to ${options.serverId}`);
    await maven.writeSettingsFile(options.serverId, false);
    for (const pom of options.poms) {
        const deployOutput = await maven.exec('deploy:deploy-file', {
            properties: {
                url: options.repositoryUrl,
                repositoryId: options.serverId,
                pomFile: pom,
                ...jarsFromPom(pom),
            },
            nothrow: true,
        });
        if (deployOutput?.exitCode && deployOutput.exitCode > 0) {
            if (deployOutput.stdout.includes('409 Conflict')) {
                (0, zx_1.echo)('⚠️ Artifact already published. Skipping');
            }
            else {
                throw new SimpleError('Release failed');
            }
        }
    }
}
/**
 * Create the staging repository. This is the same between the legacy and compat endpoints.
 *
 * `republishWill400`: in the compatibility endpoint, staging a version that has already
 * been published will lead to a `400 Bad Request`, with no further info. We needed to have
 * run the Maven command with `--debug` logging to see the actual error message in the output.
 *
 * In the legacy endpoint, staging takes multiple minutes, and Maven will poll
 * every 3s and print the output. We therefore don't use verbose mode to avoid
 * stdout spam. In the legacy endpoint, duplicate version publishing gets
 * reported during the 'release' step anyway, not during staging.
 */
async function deployStagedRepository(maven, options) {
    const serverId = 'ossrh';
    await maven.writeSettingsFile(serverId, true);
    // First -- sign artifacts
    const signedDir = zx_1.path.join(maven.workDir, 'signed');
    await fs_1.promises.mkdir(signedDir, { recursive: true });
    await signJars(maven, options.poms, signedDir, serverId, options.privateKey);
    (0, zx_1.echo)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
    (0, zx_1.echo)(' Deploying and closing repository...');
    (0, zx_1.echo)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
    const nexusMavenStaging = 'org.sonatype.plugins:nexus-staging-maven-plugin:1.7.0';
    const stageOutput = await maven.exec(`${nexusMavenStaging}:deploy-staged-repository`, {
        properties: {
            repositoryDirectory: signedDir,
            nexusUrl: options.endpoint,
            serverId,
            stagingProgressTimeoutMinutes: '30',
            stagingProfileId: options.stagingProfileId,
        },
        nothrow: true,
        verbose: options.republishWill400,
    });
    // FIXME: New staging API throws an error here on duplicate versions
    if (stageOutput === undefined) {
        (0, zx_1.echo)('🏜️ Stopped here because of dry-run');
        return { type: 'dry-run' };
    }
    if (options.republishWill400 && stageOutput.text().match(/Component with package url.*already exists/)) {
        // We've seen this fail with the above error message on the OSSRH compatibility API when trying to republish
        // an already-published version.
        //
        // This is potentially a problem if there are multiple versions in the source directory at once, because nothing
        // will be published if there's one package in there that has already been published previously. But c'est la vie.
        (0, zx_1.echo)('⚠️ Version(s) already published. Skipping');
        return { type: 'already-published' };
    }
    else if (stageOutput.exitCode && stageOutput.exitCode > 0) {
        throw stageOutput;
    }
    // Grep the repository ID out of the printed output
    // [INFO]  * Closing staging repository with ID "XXXXXXXXXX".
    const m = stageOutput.stdout.match(/Closing staging repository with ID "([^"]+)"/);
    if (!m) {
        throw new SimpleError('Unable to extract repository ID from deploy-staged-repository output. This means it failed to close or there was an unexpected problem. At any rate, we can\'t release it. Sorry.');
    }
    const repositoryId = m[1];
    return { type: 'success', repositoryId, serverId };
}
/**
 * Send a custom "release" command to the new Sonatype backwards compatibility endpoint
 *
 * When using the `nexus-staging-maven-plugin`'s `release` or `rc-release` commands, we get the following
 * error:
 *
 * Sending:
 *
 * ```
 * <stagingActionRequest><data><stagedRepositoryIds class="java.util.Arrays$ArrayList"><a class="string-array"><string>io.github.rix0rrr--63edbcbe-f058-44eb-85f4-fd9dce1aef40</string></a></stagedRepositoryIds><description>unknown</description><autoDropAfterRelease>true</autoDropAfterRelease></data></stagingActionRequest>
 * ```
 *
 * Error:
 *
 * ```
 * Failed to process request: Got unexpected XML element when reading stagedRepositoryIds: Got unexpected element StartElement(a, {"": "", "xml": "http://www.w3.org/XML/1998/namespace", "xmlns": "http://www.w3.org/2000/xmlns/"}, [class -> string-array]), expected one of: string
 * ```
 *
 * Doing a manual slightly modified version of the above request succeeds, so we'll just proceed with doing
 * that.
 *
 * The endpoint also supports JSON, which we prefer over XML.
 *
 * This endpoint will never return an error, even if the publish didn't happen because
 * of duplicate version publishing (not for the legacy, nor for the compatibility endpoint).
 *
 * @see https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/
 * @see https://support.sonatype.com/hc/en-us/articles/213465448-Automatically-dropping-old-staging-repositories
 */
async function releaseRepo(options) {
    (0, zx_1.echo)(`🚀 Releasing repository ${options.repositoryId} at ${options.serverUrl}`);
    const url = new URL('service/local/staging/bulk/promote', options.serverUrl);
    const response = await fetch(url, {
        method: 'POST',
        body: JSON.stringify({
            data: {
                stagedRepositoryIds: [options.repositoryId],
                description: options.description ?? 'Deployment',
                autoDropAfterRelease: true,
            },
        }),
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': `Basic ${btoa(`${options.username}:${options.password}`)}`,
        },
    });
    const body = await response.text();
    // It's possible that (due to some replication latency?) the initial "stage" succeeds,
    // but the "release" fails, if we try to publish an already-published version again.
    //
    // Unfortunately there is no great error code to detect this right now, but I've observed
    // this error when it happened.
    // I have a support request out to Sonatype for this, we'll see if this changes over time.
    if (response.status === 400 && body === 'Failed to process request: service error') {
        return 'duplicate-version';
    }
    if (!response.ok) {
        throw new Error(`HTTP ${response.status} ${response.statusText}: ${body}`);
    }
    console.log(body);
    return 'ok';
}
/**
 * Sign and stage our artifacts into a local directory
 */
async function signJars(maven, poms, targetDir, serverId, key) {
    const env_2 = { stack: [], error: void 0, hasError: false };
    try {
        const gpg = __addDisposableResource(env_2, await importGpgKey(key), true);
        // on a mac, --pinentry-mode to "loopback" are required and I couldn't find a
        // way to do so via -Dgpg.gpgArguments or the settings file, so here we are.
        let gpgBin = 'gpg';
        if (zx_1.os.platform() === 'darwin') {
            gpgBin = zx_1.path.join(maven.workDir, 'publib-gpg.sh');
            await fs_1.promises.writeFile(gpgBin, [
                '#!/bin/bash',
                'exec gpg --pinentry-mode loopback "\$@"',
            ].join('\n'), 'utf-8');
            await (0, zx_1.$) `chmod +x ${gpgBin}`;
        }
        for (const pom of poms) {
            await maven.exec('gpg:sign-and-deploy-file', {
                properties: {
                    'url': `file://${targetDir}`,
                    'repositoryId': serverId, // Most likely not necessary
                    'gpg.homedir': gpg.home,
                    'gpg.keyname': gpg.keyId,
                    'gpg.executable': gpgBin,
                    'pomFile': pom,
                    ...jarsFromPom(pom),
                },
            });
        }
    }
    catch (e_2) {
        env_2.error = e_2;
        env_2.hasError = true;
    }
    finally {
        const result_2 = __disposeResources(env_2);
        if (result_2)
            await result_2;
    }
}
/**
 * Based on the path of a .pom file, return the paths of the corresponding jars
 */
function jarsFromPom(pom) {
    return {
        file: pom.replace(/\.pom$/, '.jar'),
        sources: pom.replace(/\.pom$/, '-sources.jar'),
        javadoc: pom.replace(/\.pom$/, '-javadoc.jar'),
    };
}
/**
 * Create a temporary directory and import the GPG key material into a new keychain there
 */
async function importGpgKey(key) {
    // GnuPG will occasionally bail out with "gpg: <whatever> failed: Inappropriate ioctl for device", the following attempts to fix
    const gpgHome = autoCleanDir();
    try {
        // In CI environments there will be no tty, and we don't want this to stop the script.
        // The variable will be populated with a nonsensical string ("not a tty") but that doesn't seem to matter.
        const tty = (await (0, zx_1.$)({ stdio: ['inherit', 'pipe', 'pipe'], nothrow: true }) `tty`).stdout;
        let privateKeyFile;
        const type = key.type;
        switch (type) {
            case 'file':
                privateKeyFile = key.fileName;
                break;
            case 'material':
                privateKeyFile = zx_1.path.join(gpgHome.dir, 'private.pem');
                await (0, zx_1.$) `echo -e ${key.keyMaterial} > ${privateKeyFile}`;
                break;
            default:
                assertNever(type);
        }
        const env = {
            GNUPGHOME: gpgHome.dir,
            GPG_TTY: tty,
        };
        const $$ = (0, zx_1.$)({ env: { ...process.env, ...env } });
        await $$ `gpg --allow-secret-key-import --batch --yes --no-tty --import ${privateKeyFile}`;
        const gpgKeyId = (await $$ `gpg --list-keys --with-colons | grep pub | cut -d: -f5`).stdout.trim();
        (0, zx_1.echo)(`gpg_key_id=${gpgKeyId}`);
        return {
            keyId: gpgKeyId,
            env,
            home: gpgHome.dir,
            [Symbol.asyncDispose]: async () => gpgHome[Symbol.asyncDispose](),
        };
    }
    catch (e) {
        await gpgHome[Symbol.asyncDispose]();
        throw e;
    }
}
class Maven {
    constructor(workDir, verbose, dryRun) {
        this.workDir = workDir;
        this.verbose = verbose;
        this.dryRun = dryRun;
        this.settingsFile = zx_1.path.join(workDir, 'mvn-settings.xml');
    }
    /**
     * Create a settings.xml file with the user+password for maven
     */
    async writeSettingsFile(serverId, signedArtifacts) {
        const lines = [];
        lines.push('<?xml version="1.0" encoding="UTF-8" ?>', '<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"', '        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"', '        xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0', '                            http://maven.apache.org/xsd/settings-1.0.0.xsd">', '  <servers>', '    <server>', `      <id>${serverId}</id>`, 
        // Maven will read these, surrounding code has already made sure they are set
        '      <username>${env.MAVEN_USERNAME}</username>', '      <password>${env.MAVEN_PASSWORD}</password>', '    </server>');
        if (signedArtifacts) {
            lines.push('    <server>', '      <id>gpg.passphrase</id>', 
            // Maven will read these, surrounding code has already made sure they are set
            '      <passphrase>${env.MAVEN_GPG_PRIVATE_KEY_PASSPHRASE}</passphrase>', '    </server>');
        }
        lines.push('  </servers>', '</settings>');
        await fs_1.promises.writeFile(this.settingsFile, lines.join('\n'), 'utf-8');
    }
    async exec(mojo, options) {
        const args = [
            `--settings=${this.settingsFile}`,
            '--batch-mode',
            ...(options.verbose ?? this.verbose ? ['-X'] : []),
            mojo,
            ...Object.entries(options.properties).map(([k, v]) => `-D${k}=${v}`),
        ];
        if (this.dryRun) {
            (0, zx_1.echo)(`[DRY-RUN] mvn ${args.map(zx_1.quote).join(' ')}`);
            return undefined;
        }
        const env = {
            ...process.env,
            JDK_JAVA_OPTIONS: [
                // If we don't add this, we'll get an error like the following during the nexus-staging-maven-plugin:rc-release mojo.
                // Don't know where this is coming from all of a sudden.
                //
                // [ERROR] message             : No converter available
                // [ERROR] type                : java.util.Arrays$ArrayList
                // [ERROR] converter           : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
                // [ERROR] message[1]          : Unable to make field protected transient int java.util.AbstractList.modCount accessible: module java.base does not "opens java.util" to unnamed module @7c8d5312
                '--add-opens=java.base/java.util=ALL-UNNAMED',
                '--add-opens=java.base/java.lang=ALL-UNNAMED',
                '--add-opens=java.base/java.lang.invoke=ALL-UNNAMED',
            ].join(' '),
        };
        return (0, zx_1.$)({ verbose: true, nothrow: options.nothrow, env }) `mvn ${args}`;
    }
}
/**
 * A expected error that doesn't need a stack trace
 */
class SimpleError extends Error {
}
/**
 * Require an environment variable
 */
function envVar(name) {
    const ret = process.env[name];
    if (!ret) {
        throw new SimpleError(`${name} is required`);
    }
    return ret;
}
/**
 * A temporary directory that cleans when it goes out of scope
 *
 * Use with `using`. Could have been async but it's depending
 * on an already-sync API, so why not sync?
 */
function autoCleanDir() {
    const dir = (0, zx_1.tmpdir)();
    return {
        dir,
        [Symbol.asyncDispose]: async () => {
            await fs_1.promises.rm(dir, { force: true, recursive: true });
        },
    };
}
function assertNever(value) {
    throw new Error('Unexpected value: ' + value);
}
// A 'zx' primer
//
// - By default: stderr is printed to the terminal if it is captured.
// - { verbose: true }: print the command, stdout and stderr to the terminal
// - { quiet: true }: print neither stdout nor stderr
//
// .text(): return everything that's captured (stderr and stdout together if stderr is captured)
main().catch(e => {
    if (e instanceof zx_1.ProcessOutput) {
        (0, zx_1.echo)(`❌ Subprocess failed with exit code ${e.exitCode}`);
    }
    else if (e instanceof SimpleError) {
        (0, zx_1.echo)('❌', e.message);
    }
    else {
        console.error(e);
    }
    process.exitCode = 1;
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGliLW1hdmVuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jpbi9wdWJsaWItbWF2ZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNm5CQSxvQ0FRQztBQXJvQkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFDSCwyQkFBb0M7QUFDcEMsMkJBQStFO0FBRS9FLE1BQU0sc0JBQXNCLEdBQUcsT0FBTyxDQUFDO0FBQ3ZDLE1BQU0sd0JBQXdCLEdBQUcsZUFBZSxDQUFDO0FBRWpELE1BQU0sMEJBQTBCLEdBQUcsdURBQXVELENBQUM7QUFFM0YsS0FBSyxVQUFVLElBQUk7SUFDakIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQztJQUV4QyxJQUFBLE9BQUUsRUFBQyxRQUFRLENBQUMsQ0FBQztJQUViLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBQSxTQUFJLEVBQUMsVUFBVSxDQUFDLENBQUM7SUFDcEMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3RCLE1BQU0sSUFBSSxXQUFXLENBQUMsaURBQWlELE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUYsQ0FBQztJQUVELElBQUEsU0FBSSxFQUFDLGVBQWUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUU1QixNQUFNLGFBQWEsR0FBeUI7UUFDMUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUNsQyxRQUFRLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQ2xDLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksS0FBSyxN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RSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDckQsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxXQUFXLENBQUMsS0FBWTtJQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLG9CQUFvQixHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRCxnQkFBZ0I7QUFDaEIsRUFBRTtBQUNGLHFFQUFxRTtBQUNyRSw0RUFBNEU7QUFDNUUscURBQXFEO0FBQ3JELEVBQUU7QUFDRixnR0FBZ0c7QUFFaEcsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO0lBQ2YsSUFBSSxDQUFDLFlBQVksa0JBQWEsRUFBRSxDQUFDO1FBQy9CLElBQUEsU0FBSSxFQUFDLHNDQUFzQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUMzRCxDQUFDO1NBQU0sSUFBSSxDQUFDLFlBQVksV0FBVyxFQUFFLENBQUM7UUFDcEMsSUFBQSxTQUFJLEVBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2QixDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUNELE9BQU8sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBMZWdhY3kgdnMgY29tcGF0aWJpbGl0eSBlbmRwb2ludFxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICpcbiAqIFRoaXMgc2NyaXB0IHRhbGtzIGFib3V0IGxlZ2FjeSB2cyBjb21wYXRpYmlsaXR5IGVuZHBvaW50IGEgYnVuY2guXG4gKlxuICogQm90aCBpbXBsZW1lbnQgdGhlIE5leHVzIDIgcHJvdG9jb2wsIGhvd2V2ZXI6XG4gKlxuICogLSBUaGUgXCJsZWdhY3lcIiBlbmRwb2ludCBpcyB0aGUgU29uYXR5cGUgT1NTUkggZW5kcG9pbnQgdGhhdCB3YXMgZGVwcmVjYXRlZCBKdW5lIDIwMjUuXG4gKiAtIFRoZSBcImNvbXBhdGliaWxpdHlcIiBlbmRwb2ludCBpcyBhIE5leHVzIDItY29tcGF0aWJsZSBlbmRwb2ludCBzdG9vZCB1cCBmb3IgdGhlIG5ld1xuICogICBwdWJsaXNoaW5nIHNlcnZpY2UsIENlbnRyYWwgUHVibGlzaGluZy5cbiAqXG4gKiBJdCBzaG91bGQgYmUgdGhlIHNhbWUgcHJvdG9jb2wgYnV0IG9mIGNvdXJzZSB0aGVyZSBhcmUgc3VidGxlIGRpZmZlcmVuY2VzXG4gKiBiZXR3ZWVuIHRoZW0gKGluIGhvdyB0aGV5IHNpZ25hbCBlcnJvciB3aGVuIHlvdSB0cnkgdG8gcmVwdWJsaXNoIGFuIGFscmVhZHlcbiAqIHB1Ymxpc2hlZCB2ZXJzaW9uLCBhbmQgZXZlbiBpbiB0aGUgd2lyZSBwcm90b2NvbCBhY2NlcHRlZCkgc28gd2UgaGF2ZSB0b1xuICogdHJlYXQgdGhlbSBkaWZmZXJlbnRseSBoZXJlLlxuICpcbiAqIFRoZXJlIGlzIGFsc28gYW4gXCJvZmZpY2lhbCBuZXdcIiBwcm90b2NvbCBmb3IgdGhlIG5ldyBwdWJsaXNoaW5nIG1lY2hhbmlzbSxcbiAqIGJ1dCB0aGUgTWF2ZW4gcGx1Z2luIHRoZXkgc3VwcGx5IGZvciB0aGF0IGRvZXNuJ3Qgc3VwcG9ydCB0aGF0LiBJbiB0aGVpciB3b3JkczpcbiAqXG4gKiA+IGl0IGFwcGVhcnMgdGhhdCB5b3UgYXJlIHVzaW5nIHRoZSBcInR3byBzdGFnZVwiWzFdIGRlcGxveW1lbnQgcHJvY2Vzcywgd2hpY2ggaXNcbiAqID4gbm90IHlldCBzdXBwb3J0ZWQgYnkgdGhlIG5ldyBwbHVnaW4uIFlvdSBhcmUgdGhlIGZpcnN0IHB1Ymxpc2hlciB0byBoYXZlXG4gKiA+IHJlcXVlc3RlZCB0aGlzLCBzbyB3ZSB3ZXJlIG5vdCBmYW1pbGlhciB3aXRoIHRoaXMgc3BlY2lmaWMgdXNlY2FzZSB3aGVuXG4gKiA+IGJ1aWxkaW5nIHRoZSBuZXcgcGx1Z2luXG4gKiA+IFsxXSA8aHR0cHM6Ly9naXRodWIuY29tL3NvbmF0eXBlL25leHVzLW1hdmVuLXBsdWdpbnMvYmxvYi80M2E5OTQwYjEzNGMzZjg3ZWJlNGRhYTgyNTUyZTg0NGQ5YzU3OGI4L3N0YWdpbmcvbWF2ZW4tcGx1Z2luL1dPUktGTE9XUy5tZCN0d28tc2hvdHM+XG4gKi9cbmltcG9ydCB7IHByb21pc2VzIGFzIGZzIH0gZnJvbSAnZnMnO1xuaW1wb3J0IHsgJCwgY2QsIGVjaG8sIGdsb2IsIG9zLCBwYXRoLCBQcm9jZXNzT3V0cHV0LCBxdW90ZSwgdG1wZGlyIH0gZnJvbSAnengnO1xuXG5jb25zdCBMRUdBQ1lfT1NTUkhfU0VSVkVSX0lEID0gJ29zc3JoJztcbmNvbnN0IENPTVBBVF9DRU5UUkFMX1NFUlZFUl9JRCA9ICdjZW50cmFsLW9zc3JoJztcblxuY29uc3QgTkVYVVNfTUFWRU5fU1RBR0lOR19QTFVHSU4gPSAnb3JnLnNvbmF0eXBlLnBsdWdpbnM6bmV4dXMtc3RhZ2luZy1tYXZlbi1wbHVnaW46MS43LjAnO1xuXG5hc3luYyBmdW5jdGlvbiBtYWluKCkge1xuICBjb25zdCBhcmdzID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpO1xuICBjb25zdCBqYXZhUm9vdCA9IGFyZ3NbMF0gPz8gJ2Rpc3QvamF2YSc7XG5cbiAgY2QoamF2YVJvb3QpO1xuXG4gIGNvbnN0IHBvbXMgPSBhd2FpdCBnbG9iKCcqKi8qLnBvbScpO1xuICBpZiAocG9tcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgU2ltcGxlRXJyb3IoYE5vIEpBUlMgdG8gcHVibGlzaDogbm8gLnBvbSBmaWxlcyBmb3VuZCB1bmRlciAke3Byb2Nlc3MuY3dkKCl9YCk7XG4gIH1cblxuICBlY2hvKGBQT01zIGZvdW5kOiAke3BvbXN9YCk7XG5cbiAgY29uc3Qgc2hhcmVkT3B0aW9uczogU2hhcmVkUHVibGlzaE9wdGlvbnMgPSB7XG4gICAgdXNlcm5hbWU6IGVudlZhcignTUFWRU5fVVNFUk5BTUUnKSxcbiAgICBwYXNzd29yZDogZW52VmFyKCdNQVZFTl9QQVNTV09SRCcpLFxuICAgIGRyeVJ1bjogcHJvY2Vzcy5lbnYuTUFWRU5fRFJZUlVOID09PSAndHJ1ZScsXG4gICAgdmVyYm9zZTogcHJvY2Vzcy5lbnYuTUFWRU5fVkVSQk9TRSA9PT0gJ3RydWUnLFxuICAgIHBvbXMsXG4gIH07XG5cbiAgbGV0IG9wdGlvbnM6IE1hdmVuUHVibGlzaE9wdGlvbnM7XG4gIGNvbnN0IHNlcnZlcklkID0gcHJvY2Vzcy5lbnYuTUFWRU5fU0VSVkVSX0lEID8/IExFR0FDWV9PU1NSSF9TRVJWRVJfSUQ7XG5cbiAgc3dpdGNoIChzZXJ2ZXJJZCkge1xuICAgIGNhc2UgTEVHQUNZX09TU1JIX1NFUlZFUl9JRDpcbiAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgIHR5cGU6ICdsZWdhY3ktb3NzcmgnLFxuICAgICAgICAuLi5zaGFyZWRPcHRpb25zLFxuICAgICAgICBzdGFnaW5nUHJvZmlsZUlkOiBlbnZWYXIoJ01BVkVOX1NUQUdJTkdfUFJPRklMRV9JRCcpLFxuICAgICAgICBlbmRwb2ludDogcHJvY2Vzcy5lbnYuTUFWRU5fRU5EUE9JTlQsXG4gICAgICAgIHByaXZhdGVLZXk6IHBhcnNlUHJpdmF0ZUtleUZyb21FbnYoKSxcbiAgICAgIH07XG4gICAgICBicmVhaztcbiAgICBjYXNlIENPTVBBVF9DRU5UUkFMX1NFUlZFUl9JRDpcbiAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgIHR5cGU6ICdjb21wYXQtb3NzcmgnLFxuICAgICAgICAuLi5zaGFyZWRPcHRpb25zLFxuICAgICAgICAvLyBOb3QgcmVxdWlyZWQgYnkgdGhlIG5ldyBlbmRwb2ludDogY2FuIGJlIGFueSB2YWx1ZSAobWF5YmUgbmV2ZXIgd2FzIHJlcXVpcmVkIHRvIGJlZ2luIHdpdGg/KVxuICAgICAgICBzdGFnaW5nUHJvZmlsZUlkOiAncHVibGliJyxcbiAgICAgICAgZW5kcG9pbnQ6IHByb2Nlc3MuZW52Lk1BVkVOX0VORFBPSU5ULFxuICAgICAgICBwcml2YXRlS2V5OiBwYXJzZVByaXZhdGVLZXlGcm9tRW52KCksXG4gICAgICB9O1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIC8vIFdlIGhhdmVuJ3QgaW1wbGVtZW50ZWQgc2lnbmluZyBmb3IgdGhpcywgc28gZmFpbCBsb3VkbHkgaWYgcGVvcGxlIHRyeSB0byB1c2UgaXQgYW55d2F5XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZIHx8IHByb2Nlc3MuZW52Lk1BVkVOX0dQR19QUklWQVRFX0tFWV9GSUxFKSB7XG4gICAgICAgIHRocm93IG5ldyBTaW1wbGVFcnJvcignTUFWRU5fR1BHX1BSSVZBVEVfS0VZW19GSUxFXSBpcyBvbmx5IHN1cHBvcnRlZCBmb3IgT1NTUkggcHVibGlzaGluZycpO1xuICAgICAgfVxuXG4gICAgICBvcHRpb25zID0ge1xuICAgICAgICB0eXBlOiAnY3VzdG9tLW5leHVzJyxcbiAgICAgICAgLi4uc2hhcmVkT3B0aW9ucyxcbiAgICAgICAgc2VydmVySWQsXG4gICAgICAgIHJlcG9zaXRvcnlVcmw6IGVudlZhcignTUFWRU5fUkVQT1NJVE9SWV9VUkwnKSxcbiAgICAgIH07XG4gICAgICBicmVhaztcbiAgfVxuXG4gIGF3YWl0IG1hdmVuUHVibGlzaChvcHRpb25zKTtcblxuICBlY2hvKCd+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+Jyk7XG4gIGVjaG8oJ+KchSBBbGwgRG9uZSEnKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VQcml2YXRlS2V5RnJvbUVudigpOiBQcml2YXRlS2V5IHtcbiAgaWYgKHByb2Nlc3MuZW52Lk1BVkVOX0dQR19QUklWQVRFX0tFWV9GSUxFKSB7XG4gICAgcmV0dXJuIHsgdHlwZTogJ2ZpbGUnLCBmaWxlTmFtZTogcHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZX0ZJTEUsIHBhc3NQaHJhc2U6IGVudlZhcignTUFWRU5fR1BHX1BSSVZBVEVfS0VZX1BBU1NQSFJBU0UnKSB9O1xuICB9XG4gIGlmIChwcm9jZXNzLmVudi5NQVZFTl9HUEdfUFJJVkFURV9LRVkpIHtcbiAgICByZXR1cm4geyB0eXBlOiAnbWF0ZXJpYWwnLCBrZXlNYXRlcmlhbDogcHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZLCBwYXNzUGhyYXNlOiBlbnZWYXIoJ01BVkVOX0dQR19QUklWQVRFX0tFWV9QQVNTUEhSQVNFJykgfTtcbiAgfVxuICB0aHJvdyBuZXcgU2ltcGxlRXJyb3IoJ01BVkVOX0dQR19QUklWQVRFX0tFWVtfRklMRV0gaXMgcmVxdWlyZWQnKTtcbn1cblxuLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyAgTW9kZWxpbmcgYWxsIHRoZSBwYXJhbWV0ZXJzIHNvIHRoYXQgd2UgY2FuIHB1bGwgdGhlIGVudmlyb25tZW50IHBhcnNpbmcgZm9yd2FyZFxuLy9cblxuaW50ZXJmYWNlIFNoYXJlZFB1Ymxpc2hPcHRpb25zIHtcbiAgcmVhZG9ubHkgdXNlcm5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgcGFzc3dvcmQ6IHN0cmluZztcbiAgcmVhZG9ubHkgZHJ5UnVuOiBib29sZWFuO1xuICByZWFkb25seSB2ZXJib3NlOiBib29sZWFuO1xuICByZWFkb25seSBwb21zOiBzdHJpbmdbXTtcbn1cblxuaW50ZXJmYWNlIExlZ2FjeU9zc3JoUHVibGlzaE9wdGlvbnMgZXh0ZW5kcyBTaGFyZWRQdWJsaXNoT3B0aW9ucyB7XG4gIHR5cGU6ICdsZWdhY3ktb3NzcmgnO1xuICByZWFkb25seSBwcml2YXRlS2V5OiBQcml2YXRlS2V5O1xuICByZWFkb25seSBlbmRwb2ludD86IHN0cmluZztcbiAgcmVhZG9ubHkgc3RhZ2luZ1Byb2ZpbGVJZDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ29tcGF0T3NzcmhQdWJsaXNoT3B0aW9ucyBleHRlbmRzIFNoYXJlZFB1Ymxpc2hPcHRpb25zIHtcbiAgdHlwZTogJ2NvbXBhdC1vc3NyaCc7XG4gIHJlYWRvbmx5IHByaXZhdGVLZXk6IFByaXZhdGVLZXk7XG4gIHJlYWRvbmx5IGVuZHBvaW50Pzogc3RyaW5nO1xuICByZWFkb25seSBzdGFnaW5nUHJvZmlsZUlkOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDdXN0b21OZXh1c1B1Ymxpc2hPcHRpb25zIGV4dGVuZHMgU2hhcmVkUHVibGlzaE9wdGlvbnMge1xuICB0eXBlOiAnY3VzdG9tLW5leHVzJztcbiAgcmVhZG9ubHkgcmVwb3NpdG9yeVVybDogc3RyaW5nO1xuICByZWFkb25seSBzZXJ2ZXJJZDogc3RyaW5nO1xufVxuXG50eXBlIFByaXZhdGVLZXkgPVxuICB8IHsgdHlwZTogJ2ZpbGUnOyBmaWxlTmFtZTogc3RyaW5nOyBwYXNzUGhyYXNlOiBzdHJpbmcgfVxuICB8IHsgdHlwZTogJ21hdGVyaWFsJzsga2V5TWF0ZXJpYWw6IHN0cmluZzsgcGFzc1BocmFzZTogc3RyaW5nIH1cbiAgO1xuXG50eXBlIE1hdmVuUHVibGlzaE9wdGlvbnMgPSBMZWdhY3lPc3NyaFB1Ymxpc2hPcHRpb25zIHwgQ29tcGF0T3NzcmhQdWJsaXNoT3B0aW9uc3wgQ3VzdG9tTmV4dXNQdWJsaXNoT3B0aW9ucztcblxuLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyAgUHVibGlzaGluZyBmdW5jdGlvbnNcbi8vXG5cbmFzeW5jIGZ1bmN0aW9uIG1hdmVuUHVibGlzaChvcHRpb25zOiBNYXZlblB1Ymxpc2hPcHRpb25zKSB7XG4gIGF3YWl0IHVzaW5nIHdvcmtEaXIgPSBhdXRvQ2xlYW5EaXIoKTtcbiAgY29uc3QgbWF2ZW4gPSBuZXcgTWF2ZW4od29ya0Rpci5kaXIsIG9wdGlvbnMudmVyYm9zZSwgb3B0aW9ucy5kcnlSdW4pO1xuXG4gIGNvbnN0IHggPSBvcHRpb25zLnR5cGU7XG4gIHN3aXRjaCAoeCkge1xuICAgIGNhc2UgJ2xlZ2FjeS1vc3NyaCc6XG4gICAgICBhd2FpdCBkZXBsb3lMZWdhY3lPc3NyaChtYXZlbiwgb3B0aW9ucyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdjb21wYXQtb3NzcmgnOlxuICAgICAgYXdhaXQgZGVwbG95Q29tcGF0T3NzcmgobWF2ZW4sIG9wdGlvbnMpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnY3VzdG9tLW5leHVzJzpcbiAgICAgIGF3YWl0IGRlcGxveUN1c3RvbU5leHVzKG1hdmVuLCBvcHRpb25zKTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBhc3NlcnROZXZlcih4KTtcbiAgfVxufVxuXG4vKipcbiAqIERlcGxveSB0byB0aGUgbGVnYWN5IE9TU1JIIE5leHVzIHNlcnZlclxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lMZWdhY3lPc3NyaChtYXZlbjogTWF2ZW4sIG9wdGlvbnM6IExlZ2FjeU9zc3JoUHVibGlzaE9wdGlvbnMpIHtcbiAgZWNobygn8J+TpiBQdWJsaXNoaW5nIHRvIE1hdmVuIENlbnRyYWwnKTtcbiAgY29uc3QgZGVmYXVsdEVuZHBvaW50ID0gJ2h0dHBzOi8vb3NzLnNvbmF0eXBlLm9yZyc7XG5cbiAgY29uc3Qgc3RhZ2VkID0gYXdhaXQgZGVwbG95U3RhZ2VkUmVwb3NpdG9yeShtYXZlbiwge1xuICAgIC4uLm9wdGlvbnMsXG4gICAgZW5kcG9pbnQ6IG9wdGlvbnMuZW5kcG9pbnQgPz8gZGVmYXVsdEVuZHBvaW50LFxuICAgIHJlcHVibGlzaFdpbGw0MDA6IGZhbHNlLFxuICB9KTtcblxuICBpZiAoc3RhZ2VkLnR5cGUgIT09ICdzdWNjZXNzJykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8qXG4gIGNvbnN0IHJlbGVhc2VkID0gYXdhaXQgcmVsZWFzZVJlcG8oe1xuICAgIHNlcnZlclVybDogb3B0aW9ucy5lbmRwb2ludCA/PyBkZWZhdWx0RW5kcG9pbnQsXG4gICAgdXNlcm5hbWU6IG9wdGlvbnMudXNlcm5hbWUsXG4gICAgcGFzc3dvcmQ6IG9wdGlvbnMucGFzc3dvcmQsXG4gICAgcmVwb3NpdG9yeUlkOiBzdGFnZWQucmVwb3NpdG9yeUlkLFxuICB9KTtcblxuICBpZiAocmVsZWFzZWQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgKi9cblxuICAvLyBTZW5kIGEgcmVtb3RlIHJlbGVhc2UgY29tbWFuZCB0byB0aGUgcmVwb3NpdG9yeVxuICBjb25zdCByZWxlYXNlT3V0cHV0ID0gYXdhaXQgbWF2ZW4uZXhlYyhgJHtORVhVU19NQVZFTl9TVEFHSU5HX1BMVUdJTn06cmMtcmVsZWFzZWAsIHtcbiAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICBuZXh1c1VybDogb3B0aW9ucy5lbmRwb2ludCA/PyBkZWZhdWx0RW5kcG9pbnQsXG4gICAgICBzZXJ2ZXJJZDogc3RhZ2VkLnNlcnZlcklkLFxuICAgICAgc3RhZ2luZ1JlcG9zaXRvcnlJZDogc3RhZ2VkLnJlcG9zaXRvcnlJZCxcbiAgICB9LFxuICAgIG5vdGhyb3c6IHRydWUsXG4gIH0pO1xuICBpZiAoIXJlbGVhc2VPdXRwdXQpIHtcbiAgICBlY2hvKCfwn4+c77iPIFN0b3BwZWQgaGVyZSBiZWNhdXNlIG9mIGRyeS1ydW4nKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAocmVsZWFzZU91dHB1dC5leGl0Q29kZSAhPT0gMCkge1xuICAgIC8vIElmIHJlbGVhc2UgZmFpbGVkLCBjaGVjayBpZiB0aGlzIHdhcyBjYXVzZWQgYmVjYXVzZSB3ZSBhcmUgdHJ5aW5nIHRvIHB1Ymxpc2hcbiAgICAvLyB0aGUgc2FtZSB2ZXJzaW9uIGFnYWluLCB3aGljaCBpcyBub3QgYW4gZXJyb3IuIFRoZSBtYWdpYyBzdHJpbmcgXCJkb2VzIG5vdFxuICAgIC8vIGFsbG93IHVwZGF0aW5nIGFydGlmYWN0XCIgZm9yIGEgXCIucG9tXCIgZmlsZSBpbmRpY2F0ZXMgdGhhdCB3ZSBhcmUgdHJ5aW5nIHRvXG4gICAgLy8gb3ZlcnJpZGUgYW4gZXhpc3RpbmcgdmVyc2lvbi4gT3RoZXJ3aXNlLCBmYWlsIVxuXG4gICAgY29uc3QgbG9va3NMaWtlRHVwbGljYXRlUHVibGlzaCA9IHJlbGVhc2VPdXRwdXQubGluZXMoKVxuICAgICAgLmZpbHRlcihsID0+IGwuaW5jbHVkZXMoJ2RvZXMgbm90IGFsbG93IHVwZGF0aW5nIGFydGlmYWN0JykpXG4gICAgICAuZmlsdGVyKGwgPT4gbC5pbmNsdWRlcygnLnBvbScpKVxuICAgICAgLmxlbmd0aCA+IDA7XG5cbiAgICBpZiAoIWxvb2tzTGlrZUR1cGxpY2F0ZVB1Ymxpc2gpIHtcbiAgICAgIHRocm93IG5ldyBTaW1wbGVFcnJvcignUmVsZWFzZSBmYWlsZWQnKTtcbiAgICB9XG5cbiAgICBlY2hvKCfimqDvuI8gQXJ0aWZhY3QgYWxyZWFkeSBwdWJsaXNoZWQuIFNraXBwaW5nJyk7XG4gIH1cbn1cblxuLyoqXG4gKiBEZXBsb3kgdG8gdGhlIGNvbXBhdCBPU1NSSCBOZXh1cyBzZXJ2ZXJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVwbG95Q29tcGF0T3NzcmgobWF2ZW46IE1hdmVuLCBvcHRpb25zOiBDb21wYXRPc3NyaFB1Ymxpc2hPcHRpb25zKSB7XG4gIGVjaG8oJ/Cfk6YgUHVibGlzaGluZyB0byBNYXZlbiBDZW50cmFsIChDb21wYXQgZW5kcG9pbnQpJyk7XG5cbiAgY29uc3QgZGVmYXVsdEVuZHBvaW50ID0gJ2h0dHBzOi8vb3Nzcmgtc3RhZ2luZy1hcGkuY2VudHJhbC5zb25hdHlwZS5jb20vJztcbiAgY29uc3QgZW5kcG9pbnQgPSBvcHRpb25zLmVuZHBvaW50ID8/IGRlZmF1bHRFbmRwb2ludDtcblxuICBjb25zdCBzdGFnZWQgPSBhd2FpdCBkZXBsb3lTdGFnZWRSZXBvc2l0b3J5KG1hdmVuLCB7XG4gICAgLi4ub3B0aW9ucyxcbiAgICBlbmRwb2ludCxcbiAgICByZXB1Ymxpc2hXaWxsNDAwOiB0cnVlLFxuICB9KTtcblxuICBpZiAoc3RhZ2VkLnR5cGUgIT09ICdzdWNjZXNzJykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHJlbGVhc2VkID0gYXdhaXQgcmVsZWFzZVJlcG8oe1xuICAgIHNlcnZlclVybDogZW5kcG9pbnQsXG4gICAgdXNlcm5hbWU6IG9wdGlvbnMudXNlcm5hbWUsXG4gICAgcGFzc3dvcmQ6IG9wdGlvbnMucGFzc3dvcmQsXG4gICAgcmVwb3NpdG9yeUlkOiBzdGFnZWQucmVwb3NpdG9yeUlkLFxuICB9KTtcblxuICBpZiAocmVsZWFzZWQgPT09ICdkdXBsaWNhdGUtdmVyc2lvbicpIHtcbiAgICBlY2hvKCfimqDvuI8gVmVyc2lvbihzKSBhbHJlYWR5IHB1Ymxpc2hlZC4gU2tpcHBpbmcnKTtcbiAgfVxufVxuXG4vKipcbiAqIERlcGxveSB0byBhIGN1c3RvbSBOZXh1cyBzZXJ2ZXJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVwbG95Q3VzdG9tTmV4dXMobWF2ZW46IE1hdmVuLCBvcHRpb25zOiBDdXN0b21OZXh1c1B1Ymxpc2hPcHRpb25zKSB7XG4gIGVjaG8oYPCfk6YgUHVibGlzaGluZyB0byAke29wdGlvbnMuc2VydmVySWR9YCk7XG4gIGF3YWl0IG1hdmVuLndyaXRlU2V0dGluZ3NGaWxlKG9wdGlvbnMuc2VydmVySWQsIGZhbHNlKTtcblxuICBmb3IgKGNvbnN0IHBvbSBvZiBvcHRpb25zLnBvbXMpIHtcbiAgICBjb25zdCBkZXBsb3lPdXRwdXQgPSBhd2FpdCBtYXZlbi5leGVjKCdkZXBsb3k6ZGVwbG95LWZpbGUnLCB7XG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIHVybDogb3B0aW9ucy5yZXBvc2l0b3J5VXJsLFxuICAgICAgICByZXBvc2l0b3J5SWQ6IG9wdGlvbnMuc2VydmVySWQsXG4gICAgICAgIHBvbUZpbGU6IHBvbSxcbiAgICAgICAgLi4uamFyc0Zyb21Qb20ocG9tKSxcbiAgICAgIH0sXG4gICAgICBub3Rocm93OiB0cnVlLFxuICAgIH0pO1xuXG4gICAgaWYgKGRlcGxveU91dHB1dD8uZXhpdENvZGUgJiYgZGVwbG95T3V0cHV0LmV4aXRDb2RlID4gMCkge1xuICAgICAgaWYgKGRlcGxveU91dHB1dC5zdGRvdXQuaW5jbHVkZXMoJzQwOSBDb25mbGljdCcpKSB7XG4gICAgICAgIGVjaG8oJ+KaoO+4jyBBcnRpZmFjdCBhbHJlYWR5IHB1Ymxpc2hlZC4gU2tpcHBpbmcnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBTaW1wbGVFcnJvcignUmVsZWFzZSBmYWlsZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxudHlwZSBEZXBsb3lTdGFnZWRSZXBvUmVzdWx0ID1cbiAgfCB7IHR5cGU6ICdzdWNjZXNzJzsgcmVwb3NpdG9yeUlkOiBzdHJpbmc7IHNlcnZlcklkOiBzdHJpbmcgfVxuICB8IHsgdHlwZTogJ2FscmVhZHktcHVibGlzaGVkJyB9XG4gIHwgeyB0eXBlOiAnZHJ5LXJ1bicgfTtcblxuLyoqXG4gKiBDcmVhdGUgdGhlIHN0YWdpbmcgcmVwb3NpdG9yeS4gVGhpcyBpcyB0aGUgc2FtZSBiZXR3ZWVuIHRoZSBsZWdhY3kgYW5kIGNvbXBhdCBlbmRwb2ludHMuXG4gKlxuICogYHJlcHVibGlzaFdpbGw0MDBgOiBpbiB0aGUgY29tcGF0aWJpbGl0eSBlbmRwb2ludCwgc3RhZ2luZyBhIHZlcnNpb24gdGhhdCBoYXMgYWxyZWFkeVxuICogYmVlbiBwdWJsaXNoZWQgd2lsbCBsZWFkIHRvIGEgYDQwMCBCYWQgUmVxdWVzdGAsIHdpdGggbm8gZnVydGhlciBpbmZvLiBXZSBuZWVkZWQgdG8gaGF2ZVxuICogcnVuIHRoZSBNYXZlbiBjb21tYW5kIHdpdGggYC0tZGVidWdgIGxvZ2dpbmcgdG8gc2VlIHRoZSBhY3R1YWwgZXJyb3IgbWVzc2FnZSBpbiB0aGUgb3V0cHV0LlxuICpcbiAqIEluIHRoZSBsZWdhY3kgZW5kcG9pbnQsIHN0YWdpbmcgdGFrZXMgbXVsdGlwbGUgbWludXRlcywgYW5kIE1hdmVuIHdpbGwgcG9sbFxuICogZXZlcnkgM3MgYW5kIHByaW50IHRoZSBvdXRwdXQuIFdlIHRoZXJlZm9yZSBkb24ndCB1c2UgdmVyYm9zZSBtb2RlIHRvIGF2b2lkXG4gKiBzdGRvdXQgc3BhbS4gSW4gdGhlIGxlZ2FjeSBlbmRwb2ludCwgZHVwbGljYXRlIHZlcnNpb24gcHVibGlzaGluZyBnZXRzXG4gKiByZXBvcnRlZCBkdXJpbmcgdGhlICdyZWxlYXNlJyBzdGVwIGFueXdheSwgbm90IGR1cmluZyBzdGFnaW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lTdGFnZWRSZXBvc2l0b3J5KG1hdmVuOiBNYXZlbiwgb3B0aW9uczogT21pdDxMZWdhY3lPc3NyaFB1Ymxpc2hPcHRpb25zIHwgQ29tcGF0T3NzcmhQdWJsaXNoT3B0aW9ucywgJ2VuZHBvaW50Jz4gJiB7IGVuZHBvaW50OiBzdHJpbmc7IHJlcHVibGlzaFdpbGw0MDA6IGJvb2xlYW4gfSk6IFByb21pc2U8RGVwbG95U3RhZ2VkUmVwb1Jlc3VsdD4ge1xuICBjb25zdCBzZXJ2ZXJJZCA9ICdvc3NyaCc7XG5cbiAgYXdhaXQgbWF2ZW4ud3JpdGVTZXR0aW5nc0ZpbGUoc2VydmVySWQsIHRydWUpO1xuXG4gIC8vIEZpcnN0IC0tIHNpZ24gYXJ0aWZhY3RzXG4gIGNvbnN0IHNpZ25lZERpciA9IHBhdGguam9pbihtYXZlbi53b3JrRGlyLCAnc2lnbmVkJyk7XG4gIGF3YWl0IGZzLm1rZGlyKHNpZ25lZERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgYXdhaXQgc2lnbkphcnMobWF2ZW4sIG9wdGlvbnMucG9tcywgc2lnbmVkRGlyLCBzZXJ2ZXJJZCwgb3B0aW9ucy5wcml2YXRlS2V5KTtcblxuICBlY2hvKCd+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+Jyk7XG4gIGVjaG8oJyBEZXBsb3lpbmcgYW5kIGNsb3NpbmcgcmVwb3NpdG9yeS4uLicpO1xuICBlY2hvKCd+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+Jyk7XG5cbiAgY29uc3QgbmV4dXNNYXZlblN0YWdpbmcgPSAnb3JnLnNvbmF0eXBlLnBsdWdpbnM6bmV4dXMtc3RhZ2luZy1tYXZlbi1wbHVnaW46MS43LjAnO1xuICBjb25zdCBzdGFnZU91dHB1dCA9IGF3YWl0IG1hdmVuLmV4ZWMoYCR7bmV4dXNNYXZlblN0YWdpbmd9OmRlcGxveS1zdGFnZWQtcmVwb3NpdG9yeWAsIHtcbiAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICByZXBvc2l0b3J5RGlyZWN0b3J5OiBzaWduZWREaXIsXG4gICAgICBuZXh1c1VybDogb3B0aW9ucy5lbmRwb2ludCxcbiAgICAgIHNlcnZlcklkLFxuICAgICAgc3RhZ2luZ1Byb2dyZXNzVGltZW91dE1pbnV0ZXM6ICczMCcsXG4gICAgICBzdGFnaW5nUHJvZmlsZUlkOiBvcHRpb25zLnN0YWdpbmdQcm9maWxlSWQsXG4gICAgfSxcbiAgICBub3Rocm93OiB0cnVlLFxuICAgIHZlcmJvc2U6IG9wdGlvbnMucmVwdWJsaXNoV2lsbDQwMCxcbiAgfSk7XG4gIC8vIEZJWE1FOiBOZXcgc3RhZ2luZyBBUEkgdGhyb3dzIGFuIGVycm9yIGhlcmUgb24gZHVwbGljYXRlIHZlcnNpb25zXG4gIGlmIChzdGFnZU91dHB1dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZWNobygn8J+PnO+4jyBTdG9wcGVkIGhlcmUgYmVjYXVzZSBvZiBkcnktcnVuJyk7XG4gICAgcmV0dXJuIHsgdHlwZTogJ2RyeS1ydW4nIH07XG4gIH1cblxuICBpZiAob3B0aW9ucy5yZXB1Ymxpc2hXaWxsNDAwICYmIHN0YWdlT3V0cHV0LnRleHQoKS5tYXRjaCgvQ29tcG9uZW50IHdpdGggcGFja2FnZSB1cmwuKmFscmVhZHkgZXhpc3RzLykpIHtcbiAgICAvLyBXZSd2ZSBzZWVuIHRoaXMgZmFpbCB3aXRoIHRoZSBhYm92ZSBlcnJvciBtZXNzYWdlIG9uIHRoZSBPU1NSSCBjb21wYXRpYmlsaXR5IEFQSSB3aGVuIHRyeWluZyB0byByZXB1Ymxpc2hcbiAgICAvLyBhbiBhbHJlYWR5LXB1Ymxpc2hlZCB2ZXJzaW9uLlxuICAgIC8vXG4gICAgLy8gVGhpcyBpcyBwb3RlbnRpYWxseSBhIHByb2JsZW0gaWYgdGhlcmUgYXJlIG11bHRpcGxlIHZlcnNpb25zIGluIHRoZSBzb3VyY2UgZGlyZWN0b3J5IGF0IG9uY2UsIGJlY2F1c2Ugbm90aGluZ1xuICAgIC8vIHdpbGwgYmUgcHVibGlzaGVkIGlmIHRoZXJlJ3Mgb25lIHBhY2thZ2UgaW4gdGhlcmUgdGhhdCBoYXMgYWxyZWFkeSBiZWVuIHB1Ymxpc2hlZCBwcmV2aW91c2x5LiBCdXQgYydlc3QgbGEgdmllLlxuICAgIGVjaG8oJ+KaoO+4jyBWZXJzaW9uKHMpIGFscmVhZHkgcHVibGlzaGVkLiBTa2lwcGluZycpO1xuICAgIHJldHVybiB7IHR5cGU6ICdhbHJlYWR5LXB1Ymxpc2hlZCcgfTtcbiAgfSBlbHNlIGlmIChzdGFnZU91dHB1dC5leGl0Q29kZSAmJiBzdGFnZU91dHB1dC5leGl0Q29kZSA+IDApIHtcbiAgICB0aHJvdyBzdGFnZU91dHB1dDtcbiAgfVxuXG4gIC8vIEdyZXAgdGhlIHJlcG9zaXRvcnkgSUQgb3V0IG9mIHRoZSBwcmludGVkIG91dHB1dFxuICAvLyBbSU5GT10gICogQ2xvc2luZyBzdGFnaW5nIHJlcG9zaXRvcnkgd2l0aCBJRCBcIlhYWFhYWFhYWFhcIi5cbiAgY29uc3QgbSA9IHN0YWdlT3V0cHV0LnN0ZG91dC5tYXRjaCgvQ2xvc2luZyBzdGFnaW5nIHJlcG9zaXRvcnkgd2l0aCBJRCBcIihbXlwiXSspXCIvKTtcbiAgaWYgKCFtKSB7XG4gICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKCdVbmFibGUgdG8gZXh0cmFjdCByZXBvc2l0b3J5IElEIGZyb20gZGVwbG95LXN0YWdlZC1yZXBvc2l0b3J5IG91dHB1dC4gVGhpcyBtZWFucyBpdCBmYWlsZWQgdG8gY2xvc2Ugb3IgdGhlcmUgd2FzIGFuIHVuZXhwZWN0ZWQgcHJvYmxlbS4gQXQgYW55IHJhdGUsIHdlIGNhblxcJ3QgcmVsZWFzZSBpdC4gU29ycnkuJyk7XG4gIH1cbiAgY29uc3QgcmVwb3NpdG9yeUlkID0gbVsxXTtcblxuICByZXR1cm4geyB0eXBlOiAnc3VjY2VzcycsIHJlcG9zaXRvcnlJZCwgc2VydmVySWQgfTtcbn1cblxuLyoqXG4gKiBTZW5kIGEgY3VzdG9tIFwicmVsZWFzZVwiIGNvbW1hbmQgdG8gdGhlIG5ldyBTb25hdHlwZSBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBlbmRwb2ludFxuICpcbiAqIFdoZW4gdXNpbmcgdGhlIGBuZXh1cy1zdGFnaW5nLW1hdmVuLXBsdWdpbmAncyBgcmVsZWFzZWAgb3IgYHJjLXJlbGVhc2VgIGNvbW1hbmRzLCB3ZSBnZXQgdGhlIGZvbGxvd2luZ1xuICogZXJyb3I6XG4gKlxuICogU2VuZGluZzpcbiAqXG4gKiBgYGBcbiAqIDxzdGFnaW5nQWN0aW9uUmVxdWVzdD48ZGF0YT48c3RhZ2VkUmVwb3NpdG9yeUlkcyBjbGFzcz1cImphdmEudXRpbC5BcnJheXMkQXJyYXlMaXN0XCI+PGEgY2xhc3M9XCJzdHJpbmctYXJyYXlcIj48c3RyaW5nPmlvLmdpdGh1Yi5yaXgwcnJyLS02M2VkYmNiZS1mMDU4LTQ0ZWItODVmNC1mZDlkY2UxYWVmNDA8L3N0cmluZz48L2E+PC9zdGFnZWRSZXBvc2l0b3J5SWRzPjxkZXNjcmlwdGlvbj51bmtub3duPC9kZXNjcmlwdGlvbj48YXV0b0Ryb3BBZnRlclJlbGVhc2U+dHJ1ZTwvYXV0b0Ryb3BBZnRlclJlbGVhc2U+PC9kYXRhPjwvc3RhZ2luZ0FjdGlvblJlcXVlc3Q+XG4gKiBgYGBcbiAqXG4gKiBFcnJvcjpcbiAqXG4gKiBgYGBcbiAqIEZhaWxlZCB0byBwcm9jZXNzIHJlcXVlc3Q6IEdvdCB1bmV4cGVjdGVkIFhNTCBlbGVtZW50IHdoZW4gcmVhZGluZyBzdGFnZWRSZXBvc2l0b3J5SWRzOiBHb3QgdW5leHBlY3RlZCBlbGVtZW50IFN0YXJ0RWxlbWVudChhLCB7XCJcIjogXCJcIiwgXCJ4bWxcIjogXCJodHRwOi8vd3d3LnczLm9yZy9YTUwvMTk5OC9uYW1lc3BhY2VcIiwgXCJ4bWxuc1wiOiBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAveG1sbnMvXCJ9LCBbY2xhc3MgLT4gc3RyaW5nLWFycmF5XSksIGV4cGVjdGVkIG9uZSBvZjogc3RyaW5nXG4gKiBgYGBcbiAqXG4gKiBEb2luZyBhIG1hbnVhbCBzbGlnaHRseSBtb2RpZmllZCB2ZXJzaW9uIG9mIHRoZSBhYm92ZSByZXF1ZXN0IHN1Y2NlZWRzLCBzbyB3ZSdsbCBqdXN0IHByb2NlZWQgd2l0aCBkb2luZ1xuICogdGhhdC5cbiAqXG4gKiBUaGUgZW5kcG9pbnQgYWxzbyBzdXBwb3J0cyBKU09OLCB3aGljaCB3ZSBwcmVmZXIgb3ZlciBYTUwuXG4gKlxuICogVGhpcyBlbmRwb2ludCB3aWxsIG5ldmVyIHJldHVybiBhbiBlcnJvciwgZXZlbiBpZiB0aGUgcHVibGlzaCBkaWRuJ3QgaGFwcGVuIGJlY2F1c2VcbiAqIG9mIGR1cGxpY2F0ZSB2ZXJzaW9uIHB1Ymxpc2hpbmcgKG5vdCBmb3IgdGhlIGxlZ2FjeSwgbm9yIGZvciB0aGUgY29tcGF0aWJpbGl0eSBlbmRwb2ludCkuXG4gKlxuICogQHNlZSBodHRwczovL2NlbnRyYWwuc29uYXR5cGUub3JnL3B1Ymxpc2gvcHVibGlzaC1wb3J0YWwtb3Nzcmgtc3RhZ2luZy1hcGkvXG4gKiBAc2VlIGh0dHBzOi8vc3VwcG9ydC5zb25hdHlwZS5jb20vaGMvZW4tdXMvYXJ0aWNsZXMvMjEzNDY1NDQ4LUF1dG9tYXRpY2FsbHktZHJvcHBpbmctb2xkLXN0YWdpbmctcmVwb3NpdG9yaWVzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlbGVhc2VSZXBvKG9wdGlvbnM6IHsgc2VydmVyVXJsOiBzdHJpbmc7IHVzZXJuYW1lOiBzdHJpbmc7IHBhc3N3b3JkOiBzdHJpbmc7IHJlcG9zaXRvcnlJZDogc3RyaW5nOyBkZXNjcmlwdGlvbj86IHN0cmluZyB9KTogUHJvbWlzZTwnb2snIHwgJ2R1cGxpY2F0ZS12ZXJzaW9uJz4ge1xuICBlY2hvKGDwn5qAIFJlbGVhc2luZyByZXBvc2l0b3J5ICR7b3B0aW9ucy5yZXBvc2l0b3J5SWR9IGF0ICR7b3B0aW9ucy5zZXJ2ZXJVcmx9YCk7XG4gIGNvbnN0IHVybCA9IG5ldyBVUkwoJ3NlcnZpY2UvbG9jYWwvc3RhZ2luZy9idWxrL3Byb21vdGUnLCBvcHRpb25zLnNlcnZlclVybCk7XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwsIHtcbiAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICBkYXRhOiB7XG4gICAgICAgIHN0YWdlZFJlcG9zaXRvcnlJZHM6IFtvcHRpb25zLnJlcG9zaXRvcnlJZF0sXG4gICAgICAgIGRlc2NyaXB0aW9uOiBvcHRpb25zLmRlc2NyaXB0aW9uID8/ICdEZXBsb3ltZW50JyxcbiAgICAgICAgYXV0b0Ryb3BBZnRlclJlbGVhc2U6IHRydWUsXG4gICAgICB9LFxuICAgIH0pLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAnQWNjZXB0JzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgJ0F1dGhvcml6YXRpb24nOiBgQmFzaWMgJHtidG9hKGAke29wdGlvbnMudXNlcm5hbWV9OiR7b3B0aW9ucy5wYXNzd29yZH1gKX1gLFxuICAgIH0sXG4gIH0pO1xuXG4gIGNvbnN0IGJvZHkgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG5cbiAgLy8gSXQncyBwb3NzaWJsZSB0aGF0IChkdWUgdG8gc29tZSByZXBsaWNhdGlvbiBsYXRlbmN5PykgdGhlIGluaXRpYWwgXCJzdGFnZVwiIHN1Y2NlZWRzLFxuICAvLyBidXQgdGhlIFwicmVsZWFzZVwiIGZhaWxzLCBpZiB3ZSB0cnkgdG8gcHVibGlzaCBhbiBhbHJlYWR5LXB1Ymxpc2hlZCB2ZXJzaW9uIGFnYWluLlxuICAvL1xuICAvLyBVbmZvcnR1bmF0ZWx5IHRoZXJlIGlzIG5vIGdyZWF0IGVycm9yIGNvZGUgdG8gZGV0ZWN0IHRoaXMgcmlnaHQgbm93LCBidXQgSSd2ZSBvYnNlcnZlZFxuICAvLyB0aGlzIGVycm9yIHdoZW4gaXQgaGFwcGVuZWQuXG4gIC8vIEkgaGF2ZSBhIHN1cHBvcnQgcmVxdWVzdCBvdXQgdG8gU29uYXR5cGUgZm9yIHRoaXMsIHdlJ2xsIHNlZSBpZiB0aGlzIGNoYW5nZXMgb3ZlciB0aW1lLlxuICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MDAgJiYgYm9keSA9PT0gJ0ZhaWxlZCB0byBwcm9jZXNzIHJlcXVlc3Q6IHNlcnZpY2UgZXJyb3InKSB7XG4gICAgcmV0dXJuICdkdXBsaWNhdGUtdmVyc2lvbic7XG4gIH1cblxuICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9OiAke2JvZHl9YCk7XG4gIH1cblxuICBjb25zb2xlLmxvZyhib2R5KTtcblxuICByZXR1cm4gJ29rJztcbn1cblxuLyoqXG4gKiBTaWduIGFuZCBzdGFnZSBvdXIgYXJ0aWZhY3RzIGludG8gYSBsb2NhbCBkaXJlY3RvcnlcbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2lnbkphcnMobWF2ZW46IE1hdmVuLCBwb21zOiBzdHJpbmdbXSwgdGFyZ2V0RGlyOiBzdHJpbmcsIHNlcnZlcklkOiBzdHJpbmcsIGtleTogUHJpdmF0ZUtleSkge1xuICBhd2FpdCB1c2luZyBncGcgPSBhd2FpdCBpbXBvcnRHcGdLZXkoa2V5KTtcblxuICAvLyBvbiBhIG1hYywgLS1waW5lbnRyeS1tb2RlIHRvIFwibG9vcGJhY2tcIiBhcmUgcmVxdWlyZWQgYW5kIEkgY291bGRuJ3QgZmluZCBhXG4gIC8vIHdheSB0byBkbyBzbyB2aWEgLURncGcuZ3BnQXJndW1lbnRzIG9yIHRoZSBzZXR0aW5ncyBmaWxlLCBzbyBoZXJlIHdlIGFyZS5cbiAgbGV0IGdwZ0JpbiA9ICdncGcnO1xuICBpZiAob3MucGxhdGZvcm0oKSA9PT0gJ2RhcndpbicpIHtcbiAgICBncGdCaW4gPSBwYXRoLmpvaW4obWF2ZW4ud29ya0RpciwgJ3B1YmxpYi1ncGcuc2gnKTtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoZ3BnQmluLCBbXG4gICAgICAnIyEvYmluL2Jhc2gnLFxuICAgICAgJ2V4ZWMgZ3BnIC0tcGluZW50cnktbW9kZSBsb29wYmFjayBcIlxcJEBcIicsXG4gICAgXS5qb2luKCdcXG4nKSwgJ3V0Zi04Jyk7XG4gICAgYXdhaXQgJGBjaG1vZCAreCAke2dwZ0Jpbn1gO1xuICB9XG5cbiAgZm9yIChjb25zdCBwb20gb2YgcG9tcykge1xuICAgIGF3YWl0IG1hdmVuLmV4ZWMoJ2dwZzpzaWduLWFuZC1kZXBsb3ktZmlsZScsIHtcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgJ3VybCc6IGBmaWxlOi8vJHt0YXJnZXREaXJ9YCxcbiAgICAgICAgJ3JlcG9zaXRvcnlJZCc6IHNlcnZlcklkLCAvLyBNb3N0IGxpa2VseSBub3QgbmVjZXNzYXJ5XG4gICAgICAgICdncGcuaG9tZWRpcic6IGdwZy5ob21lLFxuICAgICAgICAnZ3BnLmtleW5hbWUnOiBncGcua2V5SWQsXG4gICAgICAgICdncGcuZXhlY3V0YWJsZSc6IGdwZ0JpbixcbiAgICAgICAgJ3BvbUZpbGUnOiBwb20sXG4gICAgICAgIC4uLmphcnNGcm9tUG9tKHBvbSksXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogQmFzZWQgb24gdGhlIHBhdGggb2YgYSAucG9tIGZpbGUsIHJldHVybiB0aGUgcGF0aHMgb2YgdGhlIGNvcnJlc3BvbmRpbmcgamFyc1xuICovXG5mdW5jdGlvbiBqYXJzRnJvbVBvbShwb206IHN0cmluZykge1xuICByZXR1cm4ge1xuICAgIGZpbGU6IHBvbS5yZXBsYWNlKC9cXC5wb20kLywgJy5qYXInKSxcbiAgICBzb3VyY2VzOiBwb20ucmVwbGFjZSgvXFwucG9tJC8sICctc291cmNlcy5qYXInKSxcbiAgICBqYXZhZG9jOiBwb20ucmVwbGFjZSgvXFwucG9tJC8sICctamF2YWRvYy5qYXInKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSB0ZW1wb3JhcnkgZGlyZWN0b3J5IGFuZCBpbXBvcnQgdGhlIEdQRyBrZXkgbWF0ZXJpYWwgaW50byBhIG5ldyBrZXljaGFpbiB0aGVyZVxuICovXG5hc3luYyBmdW5jdGlvbiBpbXBvcnRHcGdLZXkoa2V5OiBQcml2YXRlS2V5KSB7XG4gIC8vIEdudVBHIHdpbGwgb2NjYXNpb25hbGx5IGJhaWwgb3V0IHdpdGggXCJncGc6IDx3aGF0ZXZlcj4gZmFpbGVkOiBJbmFwcHJvcHJpYXRlIGlvY3RsIGZvciBkZXZpY2VcIiwgdGhlIGZvbGxvd2luZyBhdHRlbXB0cyB0byBmaXhcbiAgY29uc3QgZ3BnSG9tZSA9IGF1dG9DbGVhbkRpcigpO1xuICB0cnkge1xuICAgIC8vIEluIENJIGVudmlyb25tZW50cyB0aGVyZSB3aWxsIGJlIG5vIHR0eSwgYW5kIHdlIGRvbid0IHdhbnQgdGhpcyB0byBzdG9wIHRoZSBzY3JpcHQuXG4gICAgLy8gVGhlIHZhcmlhYmxlIHdpbGwgYmUgcG9wdWxhdGVkIHdpdGggYSBub25zZW5zaWNhbCBzdHJpbmcgKFwibm90IGEgdHR5XCIpIGJ1dCB0aGF0IGRvZXNuJ3Qgc2VlbSB0byBtYXR0ZXIuXG4gICAgY29uc3QgdHR5ID0gKGF3YWl0ICQoeyBzdGRpbzogWydpbmhlcml0JywgJ3BpcGUnLCAncGlwZSddLCBub3Rocm93OiB0cnVlIH0pYHR0eWApLnN0ZG91dDtcblxuICAgIGxldCBwcml2YXRlS2V5RmlsZTtcbiAgICBjb25zdCB0eXBlID0ga2V5LnR5cGU7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlICdmaWxlJzpcbiAgICAgICAgcHJpdmF0ZUtleUZpbGUgPSBrZXkuZmlsZU5hbWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbWF0ZXJpYWwnOlxuICAgICAgICBwcml2YXRlS2V5RmlsZSA9IHBhdGguam9pbihncGdIb21lLmRpciwgJ3ByaXZhdGUucGVtJyk7XG4gICAgICAgIGF3YWl0ICRgZWNobyAtZSAke2tleS5rZXlNYXRlcmlhbH0gPiAke3ByaXZhdGVLZXlGaWxlfWA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYXNzZXJ0TmV2ZXIodHlwZSk7XG4gICAgfVxuXG4gICAgY29uc3QgZW52ID0ge1xuICAgICAgR05VUEdIT01FOiBncGdIb21lLmRpcixcbiAgICAgIEdQR19UVFk6IHR0eSxcbiAgICB9O1xuXG4gICAgY29uc3QgJCQgPSAkKHsgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi5lbnYgfSB9KTtcblxuICAgIGF3YWl0ICQkYGdwZyAtLWFsbG93LXNlY3JldC1rZXktaW1wb3J0IC0tYmF0Y2ggLS15ZXMgLS1uby10dHkgLS1pbXBvcnQgJHtwcml2YXRlS2V5RmlsZX1gO1xuICAgIGNvbnN0IGdwZ0tleUlkID0gKGF3YWl0ICQkYGdwZyAtLWxpc3Qta2V5cyAtLXdpdGgtY29sb25zIHwgZ3JlcCBwdWIgfCBjdXQgLWQ6IC1mNWApLnN0ZG91dC50cmltKCk7XG5cbiAgICBlY2hvKGBncGdfa2V5X2lkPSR7Z3BnS2V5SWR9YCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAga2V5SWQ6IGdwZ0tleUlkLFxuICAgICAgZW52LFxuICAgICAgaG9tZTogZ3BnSG9tZS5kaXIsXG4gICAgICBbU3ltYm9sLmFzeW5jRGlzcG9zZV06IGFzeW5jICgpID0+IGdwZ0hvbWVbU3ltYm9sLmFzeW5jRGlzcG9zZV0oKSxcbiAgICB9O1xuICB9IGNhdGNoIChlKSB7XG4gICAgYXdhaXQgZ3BnSG9tZVtTeW1ib2wuYXN5bmNEaXNwb3NlXSgpO1xuICAgIHRocm93IGU7XG4gIH1cbn1cblxuY2xhc3MgTWF2ZW4ge1xuICBwcml2YXRlIHJlYWRvbmx5IHNldHRpbmdzRmlsZTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSB3b3JrRGlyOiBzdHJpbmcsIHByaXZhdGUgcmVhZG9ubHkgdmVyYm9zZTogYm9vbGVhbiwgcHVibGljIHJlYWRvbmx5IGRyeVJ1bjogYm9vbGVhbikge1xuICAgIHRoaXMuc2V0dGluZ3NGaWxlID0gcGF0aC5qb2luKHdvcmtEaXIsICdtdm4tc2V0dGluZ3MueG1sJyk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgc2V0dGluZ3MueG1sIGZpbGUgd2l0aCB0aGUgdXNlcitwYXNzd29yZCBmb3IgbWF2ZW5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB3cml0ZVNldHRpbmdzRmlsZShzZXJ2ZXJJZDogc3RyaW5nLCBzaWduZWRBcnRpZmFjdHM6IGJvb2xlYW4pIHtcbiAgICBjb25zdCBsaW5lcyA9IFtdO1xuXG4gICAgbGluZXMucHVzaChcbiAgICAgICc8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtOFwiID8+JyxcbiAgICAgICc8c2V0dGluZ3MgeG1sbnM9XCJodHRwOi8vbWF2ZW4uYXBhY2hlLm9yZy9TRVRUSU5HUy8xLjAuMFwiJyxcbiAgICAgICcgICAgICAgIHhtbG5zOnhzaT1cImh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlXCInLFxuICAgICAgJyAgICAgICAgeHNpOnNjaGVtYUxvY2F0aW9uPVwiaHR0cDovL21hdmVuLmFwYWNoZS5vcmcvU0VUVElOR1MvMS4wLjAnLFxuICAgICAgJyAgICAgICAgICAgICAgICAgICAgICAgICAgICBodHRwOi8vbWF2ZW4uYXBhY2hlLm9yZy94c2Qvc2V0dGluZ3MtMS4wLjAueHNkXCI+JyxcbiAgICAgICcgIDxzZXJ2ZXJzPicsXG4gICAgICAnICAgIDxzZXJ2ZXI+JyxcbiAgICAgIGAgICAgICA8aWQ+JHtzZXJ2ZXJJZH08L2lkPmAsXG4gICAgICAvLyBNYXZlbiB3aWxsIHJlYWQgdGhlc2UsIHN1cnJvdW5kaW5nIGNvZGUgaGFzIGFscmVhZHkgbWFkZSBzdXJlIHRoZXkgYXJlIHNldFxuICAgICAgJyAgICAgIDx1c2VybmFtZT4ke2Vudi5NQVZFTl9VU0VSTkFNRX08L3VzZXJuYW1lPicsXG4gICAgICAnICAgICAgPHBhc3N3b3JkPiR7ZW52Lk1BVkVOX1BBU1NXT1JEfTwvcGFzc3dvcmQ+JyxcbiAgICAgICcgICAgPC9zZXJ2ZXI+JyxcbiAgICApO1xuXG4gICAgaWYgKHNpZ25lZEFydGlmYWN0cykge1xuICAgICAgbGluZXMucHVzaChcbiAgICAgICAgJyAgICA8c2VydmVyPicsXG4gICAgICAgICcgICAgICA8aWQ+Z3BnLnBhc3NwaHJhc2U8L2lkPicsXG4gICAgICAgIC8vIE1hdmVuIHdpbGwgcmVhZCB0aGVzZSwgc3Vycm91bmRpbmcgY29kZSBoYXMgYWxyZWFkeSBtYWRlIHN1cmUgdGhleSBhcmUgc2V0XG4gICAgICAgICcgICAgICA8cGFzc3BocmFzZT4ke2Vudi5NQVZFTl9HUEdfUFJJVkFURV9LRVlfUEFTU1BIUkFTRX08L3Bhc3NwaHJhc2U+JyxcbiAgICAgICAgJyAgICA8L3NlcnZlcj4nLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBsaW5lcy5wdXNoKFxuICAgICAgJyAgPC9zZXJ2ZXJzPicsXG4gICAgICAnPC9zZXR0aW5ncz4nLFxuICAgICk7XG5cbiAgICBhd2FpdCBmcy53cml0ZUZpbGUodGhpcy5zZXR0aW5nc0ZpbGUsIGxpbmVzLmpvaW4oJ1xcbicpLCAndXRmLTgnKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBleGVjKG1vam86IHN0cmluZywgb3B0aW9uczogTWF2ZW5FeGVjT3B0aW9ucyk6IFByb21pc2U8UHJvY2Vzc091dHB1dCB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IGFyZ3MgPSBbXG4gICAgICBgLS1zZXR0aW5ncz0ke3RoaXMuc2V0dGluZ3NGaWxlfWAsXG4gICAgICAnLS1iYXRjaC1tb2RlJyxcbiAgICAgIC4uLihvcHRpb25zLnZlcmJvc2UgPz8gdGhpcy52ZXJib3NlID8gWyctWCddIDogW10pLFxuICAgICAgbW9qbyxcbiAgICAgIC4uLk9iamVjdC5lbnRyaWVzKG9wdGlvbnMucHJvcGVydGllcykubWFwKChbaywgdl0pID0+IGAtRCR7a309JHt2fWApLFxuICAgIF07XG5cbiAgICBpZiAodGhpcy5kcnlSdW4pIHtcbiAgICAgIGVjaG8oYFtEUlktUlVOXSBtdm4gJHthcmdzLm1hcChxdW90ZSkuam9pbignICcpfWApO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgY29uc3QgZW52ID0ge1xuICAgICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgICBKREtfSkFWQV9PUFRJT05TOiBbXG4gICAgICAgIC8vIElmIHdlIGRvbid0IGFkZCB0aGlzLCB3ZSdsbCBnZXQgYW4gZXJyb3IgbGlrZSB0aGUgZm9sbG93aW5nIGR1cmluZyB0aGUgbmV4dXMtc3RhZ2luZy1tYXZlbi1wbHVnaW46cmMtcmVsZWFzZSBtb2pvLlxuICAgICAgICAvLyBEb24ndCBrbm93IHdoZXJlIHRoaXMgaXMgY29taW5nIGZyb20gYWxsIG9mIGEgc3VkZGVuLlxuICAgICAgICAvL1xuICAgICAgICAvLyBbRVJST1JdIG1lc3NhZ2UgICAgICAgICAgICAgOiBObyBjb252ZXJ0ZXIgYXZhaWxhYmxlXG4gICAgICAgIC8vIFtFUlJPUl0gdHlwZSAgICAgICAgICAgICAgICA6IGphdmEudXRpbC5BcnJheXMkQXJyYXlMaXN0XG4gICAgICAgIC8vIFtFUlJPUl0gY29udmVydGVyICAgICAgICAgICA6IGNvbS50aG91Z2h0d29ya3MueHN0cmVhbS5jb252ZXJ0ZXJzLnJlZmxlY3Rpb24uUmVmbGVjdGlvbkNvbnZlcnRlclxuICAgICAgICAvLyBbRVJST1JdIG1lc3NhZ2VbMV0gICAgICAgICAgOiBVbmFibGUgdG8gbWFrZSBmaWVsZCBwcm90ZWN0ZWQgdHJhbnNpZW50IGludCBqYXZhLnV0aWwuQWJzdHJhY3RMaXN0Lm1vZENvdW50IGFjY2Vzc2libGU6IG1vZHVsZSBqYXZhLmJhc2UgZG9lcyBub3QgXCJvcGVucyBqYXZhLnV0aWxcIiB0byB1bm5hbWVkIG1vZHVsZSBAN2M4ZDUzMTJcbiAgICAgICAgJy0tYWRkLW9wZW5zPWphdmEuYmFzZS9qYXZhLnV0aWw9QUxMLVVOTkFNRUQnLFxuICAgICAgICAnLS1hZGQtb3BlbnM9amF2YS5iYXNlL2phdmEubGFuZz1BTEwtVU5OQU1FRCcsXG4gICAgICAgICctLWFkZC1vcGVucz1qYXZhLmJhc2UvamF2YS5sYW5nLmludm9rZT1BTEwtVU5OQU1FRCcsXG4gICAgICBdLmpvaW4oJyAnKSxcbiAgICB9O1xuXG4gICAgcmV0dXJuICQoeyB2ZXJib3NlOiB0cnVlLCBub3Rocm93OiBvcHRpb25zLm5vdGhyb3csIGVudiB9KWBtdm4gJHthcmdzfWA7XG4gIH1cbn1cblxuaW50ZXJmYWNlIE1hdmVuRXhlY09wdGlvbnMge1xuICBwcm9wZXJ0aWVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBub3Rocm93PzogYm9vbGVhbjtcbiAgdmVyYm9zZT86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQSBleHBlY3RlZCBlcnJvciB0aGF0IGRvZXNuJ3QgbmVlZCBhIHN0YWNrIHRyYWNlXG4gKi9cbmNsYXNzIFNpbXBsZUVycm9yIGV4dGVuZHMgRXJyb3IgeyB9XG5cbi8qKlxuICogUmVxdWlyZSBhbiBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICovXG5mdW5jdGlvbiBlbnZWYXIobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcmV0ID0gcHJvY2Vzcy5lbnZbbmFtZV07XG4gIGlmICghcmV0KSB7XG4gICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKGAke25hbWV9IGlzIHJlcXVpcmVkYCk7XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuLyoqXG4gKiBBIHRlbXBvcmFyeSBkaXJlY3RvcnkgdGhhdCBjbGVhbnMgd2hlbiBpdCBnb2VzIG91dCBvZiBzY29wZVxuICpcbiAqIFVzZSB3aXRoIGB1c2luZ2AuIENvdWxkIGhhdmUgYmVlbiBhc3luYyBidXQgaXQncyBkZXBlbmRpbmdcbiAqIG9uIGFuIGFscmVhZHktc3luYyBBUEksIHNvIHdoeSBub3Qgc3luYz9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1dG9DbGVhbkRpcigpIHtcbiAgY29uc3QgZGlyID0gdG1wZGlyKCk7XG4gIHJldHVybiB7XG4gICAgZGlyLFxuICAgIFtTeW1ib2wuYXN5bmNEaXNwb3NlXTogYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgZnMucm0oZGlyLCB7IGZvcmNlOiB0cnVlLCByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gYXNzZXJ0TmV2ZXIodmFsdWU6IG5ldmVyKSB7XG4gIHRocm93IG5ldyBFcnJvcignVW5leHBlY3RlZCB2YWx1ZTogJyArIHZhbHVlKTtcbn1cblxuLy8gQSAnengnIHByaW1lclxuLy9cbi8vIC0gQnkgZGVmYXVsdDogc3RkZXJyIGlzIHByaW50ZWQgdG8gdGhlIHRlcm1pbmFsIGlmIGl0IGlzIGNhcHR1cmVkLlxuLy8gLSB7IHZlcmJvc2U6IHRydWUgfTogcHJpbnQgdGhlIGNvbW1hbmQsIHN0ZG91dCBhbmQgc3RkZXJyIHRvIHRoZSB0ZXJtaW5hbFxuLy8gLSB7IHF1aWV0OiB0cnVlIH06IHByaW50IG5laXRoZXIgc3Rkb3V0IG5vciBzdGRlcnJcbi8vXG4vLyAudGV4dCgpOiByZXR1cm4gZXZlcnl0aGluZyB0aGF0J3MgY2FwdHVyZWQgKHN0ZGVyciBhbmQgc3Rkb3V0IHRvZ2V0aGVyIGlmIHN0ZGVyciBpcyBjYXB0dXJlZClcblxubWFpbigpLmNhdGNoKGUgPT4ge1xuICBpZiAoZSBpbnN0YW5jZW9mIFByb2Nlc3NPdXRwdXQpIHtcbiAgICBlY2hvKGDinYwgU3VicHJvY2VzcyBmYWlsZWQgd2l0aCBleGl0IGNvZGUgJHtlLmV4aXRDb2RlfWApO1xuICB9IGVsc2UgaWYgKGUgaW5zdGFuY2VvZiBTaW1wbGVFcnJvcikge1xuICAgIGVjaG8oJ+KdjCcsIGUubWVzc2FnZSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcihlKTtcbiAgfVxuICBwcm9jZXNzLmV4aXRDb2RlID0gMTtcbn0pO1xuIl19