UNPKG

jsii-release

Version:

Release jsii modules to multiple package managers

612 lines 75.2 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' || process.env.PUBLIB_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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RSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLEtBQVk7SUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxLQUFLLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBRUQsZ0JBQWdCO0FBQ2hCLEVBQUU7QUFDRixxRUFBcUU7QUFDckUsNEVBQTRFO0FBQzVFLHFEQUFxRDtBQUNyRCxFQUFFO0FBQ0YsZ0dBQWdHO0FBRWhHLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUNmLElBQUksQ0FBQyxZQUFZLGtCQUFhLEVBQUUsQ0FBQztRQUMvQixJQUFBLFNBQUksRUFBQyxzQ0FBc0MsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDM0QsQ0FBQztTQUFNLElBQUksQ0FBQyxZQUFZLFdBQVcsRUFBRSxDQUFDO1FBQ3BDLElBQUEsU0FBSSxFQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkIsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztBQUN2QixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGVnYWN5IHZzIGNvbXBhdGliaWxpdHkgZW5kcG9pbnRcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqXG4gKiBUaGlzIHNjcmlwdCB0YWxrcyBhYm91dCBsZWdhY3kgdnMgY29tcGF0aWJpbGl0eSBlbmRwb2ludCBhIGJ1bmNoLlxuICpcbiAqIEJvdGggaW1wbGVtZW50IHRoZSBOZXh1cyAyIHByb3RvY29sLCBob3dldmVyOlxuICpcbiAqIC0gVGhlIFwibGVnYWN5XCIgZW5kcG9pbnQgaXMgdGhlIFNvbmF0eXBlIE9TU1JIIGVuZHBvaW50IHRoYXQgd2FzIGRlcHJlY2F0ZWQgSnVuZSAyMDI1LlxuICogLSBUaGUgXCJjb21wYXRpYmlsaXR5XCIgZW5kcG9pbnQgaXMgYSBOZXh1cyAyLWNvbXBhdGlibGUgZW5kcG9pbnQgc3Rvb2QgdXAgZm9yIHRoZSBuZXdcbiAqICAgcHVibGlzaGluZyBzZXJ2aWNlLCBDZW50cmFsIFB1Ymxpc2hpbmcuXG4gKlxuICogSXQgc2hvdWxkIGJlIHRoZSBzYW1lIHByb3RvY29sIGJ1dCBvZiBjb3Vyc2UgdGhlcmUgYXJlIHN1YnRsZSBkaWZmZXJlbmNlc1xuICogYmV0d2VlbiB0aGVtIChpbiBob3cgdGhleSBzaWduYWwgZXJyb3Igd2hlbiB5b3UgdHJ5IHRvIHJlcHVibGlzaCBhbiBhbHJlYWR5XG4gKiBwdWJsaXNoZWQgdmVyc2lvbiwgYW5kIGV2ZW4gaW4gdGhlIHdpcmUgcHJvdG9jb2wgYWNjZXB0ZWQpIHNvIHdlIGhhdmUgdG9cbiAqIHRyZWF0IHRoZW0gZGlmZmVyZW50bHkgaGVyZS5cbiAqXG4gKiBUaGVyZSBpcyBhbHNvIGFuIFwib2ZmaWNpYWwgbmV3XCIgcHJvdG9jb2wgZm9yIHRoZSBuZXcgcHVibGlzaGluZyBtZWNoYW5pc20sXG4gKiBidXQgdGhlIE1hdmVuIHBsdWdpbiB0aGV5IHN1cHBseSBmb3IgdGhhdCBkb2Vzbid0IHN1cHBvcnQgdGhhdC4gSW4gdGhlaXIgd29yZHM6XG4gKlxuICogPiBpdCBhcHBlYXJzIHRoYXQgeW91IGFyZSB1c2luZyB0aGUgXCJ0d28gc3RhZ2VcIlsxXSBkZXBsb3ltZW50IHByb2Nlc3MsIHdoaWNoIGlzXG4gKiA+IG5vdCB5ZXQgc3VwcG9ydGVkIGJ5IHRoZSBuZXcgcGx1Z2luLiBZb3UgYXJlIHRoZSBmaXJzdCBwdWJsaXNoZXIgdG8gaGF2ZVxuICogPiByZXF1ZXN0ZWQgdGhpcywgc28gd2Ugd2VyZSBub3QgZmFtaWxpYXIgd2l0aCB0aGlzIHNwZWNpZmljIHVzZWNhc2Ugd2hlblxuICogPiBidWlsZGluZyB0aGUgbmV3IHBsdWdpblxuICogPiBbMV0gPGh0dHBzOi8vZ2l0aHViLmNvbS9zb25hdHlwZS9uZXh1cy1tYXZlbi1wbHVnaW5zL2Jsb2IvNDNhOTk0MGIxMzRjM2Y4N2ViZTRkYWE4MjU1MmU4NDRkOWM1NzhiOC9zdGFnaW5nL21hdmVuLXBsdWdpbi9XT1JLRkxPV1MubWQjdHdvLXNob3RzPlxuICovXG5pbXBvcnQgeyBwcm9taXNlcyBhcyBmcyB9IGZyb20gJ2ZzJztcbmltcG9ydCB7ICQsIGNkLCBlY2hvLCBnbG9iLCBvcywgcGF0aCwgUHJvY2Vzc091dHB1dCwgcXVvdGUsIHRtcGRpciB9IGZyb20gJ3p4JztcblxuY29uc3QgTEVHQUNZX09TU1JIX1NFUlZFUl9JRCA9ICdvc3NyaCc7XG5jb25zdCBDT01QQVRfQ0VOVFJBTF9TRVJWRVJfSUQgPSAnY2VudHJhbC1vc3NyaCc7XG5cbmNvbnN0IE5FWFVTX01BVkVOX1NUQUdJTkdfUExVR0lOID0gJ29yZy5zb25hdHlwZS5wbHVnaW5zOm5leHVzLXN0YWdpbmctbWF2ZW4tcGx1Z2luOjEuNy4wJztcblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgY29uc3QgYXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcbiAgY29uc3QgamF2YVJvb3QgPSBhcmdzWzBdID8/ICdkaXN0L2phdmEnO1xuXG4gIGNkKGphdmFSb290KTtcblxuICBjb25zdCBwb21zID0gYXdhaXQgZ2xvYignKiovKi5wb20nKTtcbiAgaWYgKHBvbXMubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKGBObyBKQVJTIHRvIHB1Ymxpc2g6IG5vIC5wb20gZmlsZXMgZm91bmQgdW5kZXIgJHtwcm9jZXNzLmN3ZCgpfWApO1xuICB9XG5cbiAgZWNobyhgUE9NcyBmb3VuZDogJHtwb21zfWApO1xuXG4gIGNvbnN0IHNoYXJlZE9wdGlvbnM6IFNoYXJlZFB1Ymxpc2hPcHRpb25zID0ge1xuICAgIHVzZXJuYW1lOiBlbnZWYXIoJ01BVkVOX1VTRVJOQU1FJyksXG4gICAgcGFzc3dvcmQ6IGVudlZhcignTUFWRU5fUEFTU1dPUkQnKSxcbiAgICBkcnlSdW46IHByb2Nlc3MuZW52Lk1BVkVOX0RSWVJVTiA9PT0gJ3RydWUnIHx8IHByb2Nlc3MuZW52LlBVQkxJQl9EUllSVU4gPT09ICd0cnVlJyxcbiAgICB2ZXJib3NlOiBwcm9jZXNzLmVudi5NQVZFTl9WRVJCT1NFID09PSAndHJ1ZScsXG4gICAgcG9tcyxcbiAgfTtcblxuICBsZXQgb3B0aW9uczogTWF2ZW5QdWJsaXNoT3B0aW9ucztcbiAgY29uc3Qgc2VydmVySWQgPSBwcm9jZXNzLmVudi5NQVZFTl9TRVJWRVJfSUQgPz8gTEVHQUNZX09TU1JIX1NFUlZFUl9JRDtcblxuICBzd2l0Y2ggKHNlcnZlcklkKSB7XG4gICAgY2FzZSBMRUdBQ1lfT1NTUkhfU0VSVkVSX0lEOlxuICAgICAgb3B0aW9ucyA9IHtcbiAgICAgICAgdHlwZTogJ2xlZ2FjeS1vc3NyaCcsXG4gICAgICAgIC4uLnNoYXJlZE9wdGlvbnMsXG4gICAgICAgIHN0YWdpbmdQcm9maWxlSWQ6IGVudlZhcignTUFWRU5fU1RBR0lOR19QUk9GSUxFX0lEJyksXG4gICAgICAgIGVuZHBvaW50OiBwcm9jZXNzLmVudi5NQVZFTl9FTkRQT0lOVCxcbiAgICAgICAgcHJpdmF0ZUtleTogcGFyc2VQcml2YXRlS2V5RnJvbUVudigpLFxuICAgICAgfTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQ09NUEFUX0NFTlRSQUxfU0VSVkVSX0lEOlxuICAgICAgb3B0aW9ucyA9IHtcbiAgICAgICAgdHlwZTogJ2NvbXBhdC1vc3NyaCcsXG4gICAgICAgIC4uLnNoYXJlZE9wdGlvbnMsXG4gICAgICAgIC8vIE5vdCByZXF1aXJlZCBieSB0aGUgbmV3IGVuZHBvaW50OiBjYW4gYmUgYW55IHZhbHVlIChtYXliZSBuZXZlciB3YXMgcmVxdWlyZWQgdG8gYmVnaW4gd2l0aD8pXG4gICAgICAgIHN0YWdpbmdQcm9maWxlSWQ6ICdwdWJsaWInLFxuICAgICAgICBlbmRwb2ludDogcHJvY2Vzcy5lbnYuTUFWRU5fRU5EUE9JTlQsXG4gICAgICAgIHByaXZhdGVLZXk6IHBhcnNlUHJpdmF0ZUtleUZyb21FbnYoKSxcbiAgICAgIH07XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgLy8gV2UgaGF2ZW4ndCBpbXBsZW1lbnRlZCBzaWduaW5nIGZvciB0aGlzLCBzbyBmYWlsIGxvdWRseSBpZiBwZW9wbGUgdHJ5IHRvIHVzZSBpdCBhbnl3YXlcbiAgICAgIGlmIChwcm9jZXNzLmVudi5NQVZFTl9HUEdfUFJJVkFURV9LRVkgfHwgcHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZX0ZJTEUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKCdNQVZFTl9HUEdfUFJJVkFURV9LRVlbX0ZJTEVdIGlzIG9ubHkgc3VwcG9ydGVkIGZvciBPU1NSSCBwdWJsaXNoaW5nJyk7XG4gICAgICB9XG5cbiAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgIHR5cGU6ICdjdXN0b20tbmV4dXMnLFxuICAgICAgICAuLi5zaGFyZWRPcHRpb25zLFxuICAgICAgICBzZXJ2ZXJJZCxcbiAgICAgICAgcmVwb3NpdG9yeVVybDogZW52VmFyKCdNQVZFTl9SRVBPU0lUT1JZX1VSTCcpLFxuICAgICAgfTtcbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgYXdhaXQgbWF2ZW5QdWJsaXNoKG9wdGlvbnMpO1xuXG4gIGVjaG8oJ35+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+fn4nKTtcbiAgZWNobygn4pyFIEFsbCBEb25lIScpO1xufVxuXG5mdW5jdGlvbiBwYXJzZVByaXZhdGVLZXlGcm9tRW52KCk6IFByaXZhdGVLZXkge1xuICBpZiAocHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZX0ZJTEUpIHtcbiAgICByZXR1cm4geyB0eXBlOiAnZmlsZScsIGZpbGVOYW1lOiBwcm9jZXNzLmVudi5NQVZFTl9HUEdfUFJJVkFURV9LRVlfRklMRSwgcGFzc1BocmFzZTogZW52VmFyKCdNQVZFTl9HUEdfUFJJVkFURV9LRVlfUEFTU1BIUkFTRScpIH07XG4gIH1cbiAgaWYgKHByb2Nlc3MuZW52Lk1BVkVOX0dQR19QUklWQVRFX0tFWSkge1xuICAgIHJldHVybiB7IHR5cGU6ICdtYXRlcmlhbCcsIGtleU1hdGVyaWFsOiBwcm9jZXNzLmVudi5NQVZFTl9HUEdfUFJJVkFURV9LRVksIHBhc3NQaHJhc2U6IGVudlZhcignTUFWRU5fR1BHX1BSSVZBVEVfS0VZX1BBU1NQSFJBU0UnKSB9O1xuICB9XG4gIHRocm93IG5ldyBTaW1wbGVFcnJvcignTUFWRU5fR1BHX1BSSVZBVEVfS0VZW19GSUxFXSBpcyByZXF1aXJlZCcpO1xufVxuXG4vLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vICBNb2RlbGluZyBhbGwgdGhlIHBhcmFtZXRlcnMgc28gdGhhdCB3ZSBjYW4gcHVsbCB0aGUgZW52aXJvbm1lbnQgcGFyc2luZyBmb3J3YXJkXG4vL1xuXG5pbnRlcmZhY2UgU2hhcmVkUHVibGlzaE9wdGlvbnMge1xuICByZWFkb25seSB1c2VybmFtZTogc3RyaW5nO1xuICByZWFkb25seSBwYXNzd29yZDogc3RyaW5nO1xuICByZWFkb25seSBkcnlSdW46IGJvb2xlYW47XG4gIHJlYWRvbmx5IHZlcmJvc2U6IGJvb2xlYW47XG4gIHJlYWRvbmx5IHBvbXM6IHN0cmluZ1tdO1xufVxuXG5pbnRlcmZhY2UgTGVnYWN5T3NzcmhQdWJsaXNoT3B0aW9ucyBleHRlbmRzIFNoYXJlZFB1Ymxpc2hPcHRpb25zIHtcbiAgdHlwZTogJ2xlZ2FjeS1vc3NyaCc7XG4gIHJlYWRvbmx5IHByaXZhdGVLZXk6IFByaXZhdGVLZXk7XG4gIHJlYWRvbmx5IGVuZHBvaW50Pzogc3RyaW5nO1xuICByZWFkb25seSBzdGFnaW5nUHJvZmlsZUlkOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDb21wYXRPc3NyaFB1Ymxpc2hPcHRpb25zIGV4dGVuZHMgU2hhcmVkUHVibGlzaE9wdGlvbnMge1xuICB0eXBlOiAnY29tcGF0LW9zc3JoJztcbiAgcmVhZG9ubHkgcHJpdmF0ZUtleTogUHJpdmF0ZUtleTtcbiAgcmVhZG9ubHkgZW5kcG9pbnQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0YWdpbmdQcm9maWxlSWQ6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEN1c3RvbU5leHVzUHVibGlzaE9wdGlvbnMgZXh0ZW5kcyBTaGFyZWRQdWJsaXNoT3B0aW9ucyB7XG4gIHR5cGU6ICdjdXN0b20tbmV4dXMnO1xuICByZWFkb25seSByZXBvc2l0b3J5VXJsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNlcnZlcklkOiBzdHJpbmc7XG59XG5cbnR5cGUgUHJpdmF0ZUtleSA9XG4gIHwgeyB0eXBlOiAnZmlsZSc7IGZpbGVOYW1lOiBzdHJpbmc7IHBhc3NQaHJhc2U6IHN0cmluZyB9XG4gIHwgeyB0eXBlOiAnbWF0ZXJpYWwnOyBrZXlNYXRlcmlhbDogc3RyaW5nOyBwYXNzUGhyYXNlOiBzdHJpbmcgfVxuICA7XG5cbnR5cGUgTWF2ZW5QdWJsaXNoT3B0aW9ucyA9IExlZ2FjeU9zc3JoUHVibGlzaE9wdGlvbnMgfCBDb21wYXRPc3NyaFB1Ymxpc2hPcHRpb25zfCBDdXN0b21OZXh1c1B1Ymxpc2hPcHRpb25zO1xuXG4vLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vICBQdWJsaXNoaW5nIGZ1bmN0aW9uc1xuLy9cblxuYXN5bmMgZnVuY3Rpb24gbWF2ZW5QdWJsaXNoKG9wdGlvbnM6IE1hdmVuUHVibGlzaE9wdGlvbnMpIHtcbiAgYXdhaXQgdXNpbmcgd29ya0RpciA9IGF1dG9DbGVhbkRpcigpO1xuICBjb25zdCBtYXZlbiA9IG5ldyBNYXZlbih3b3JrRGlyLmRpciwgb3B0aW9ucy52ZXJib3NlLCBvcHRpb25zLmRyeVJ1bik7XG5cbiAgY29uc3QgeCA9IG9wdGlvbnMudHlwZTtcbiAgc3dpdGNoICh4KSB7XG4gICAgY2FzZSAnbGVnYWN5LW9zc3JoJzpcbiAgICAgIGF3YWl0IGRlcGxveUxlZ2FjeU9zc3JoKG1hdmVuLCBvcHRpb25zKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2NvbXBhdC1vc3NyaCc6XG4gICAgICBhd2FpdCBkZXBsb3lDb21wYXRPc3NyaChtYXZlbiwgb3B0aW9ucyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdjdXN0b20tbmV4dXMnOlxuICAgICAgYXdhaXQgZGVwbG95Q3VzdG9tTmV4dXMobWF2ZW4sIG9wdGlvbnMpO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGFzc2VydE5ldmVyKHgpO1xuICB9XG59XG5cbi8qKlxuICogRGVwbG95IHRvIHRoZSBsZWdhY3kgT1NTUkggTmV4dXMgc2VydmVyXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRlcGxveUxlZ2FjeU9zc3JoKG1hdmVuOiBNYXZlbiwgb3B0aW9uczogTGVnYWN5T3NzcmhQdWJsaXNoT3B0aW9ucykge1xuICBlY2hvKCfwn5OmIFB1Ymxpc2hpbmcgdG8gTWF2ZW4gQ2VudHJhbCcpO1xuICBjb25zdCBkZWZhdWx0RW5kcG9pbnQgPSAnaHR0cHM6Ly9vc3Muc29uYXR5cGUub3JnJztcblxuICBjb25zdCBzdGFnZWQgPSBhd2FpdCBkZXBsb3lTdGFnZWRSZXBvc2l0b3J5KG1hdmVuLCB7XG4gICAgLi4ub3B0aW9ucyxcbiAgICBlbmRwb2ludDogb3B0aW9ucy5lbmRwb2ludCA/PyBkZWZhdWx0RW5kcG9pbnQsXG4gICAgcmVwdWJsaXNoV2lsbDQwMDogZmFsc2UsXG4gIH0pO1xuXG4gIGlmIChzdGFnZWQudHlwZSAhPT0gJ3N1Y2Nlc3MnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLypcbiAgY29uc3QgcmVsZWFzZWQgPSBhd2FpdCByZWxlYXNlUmVwbyh7XG4gICAgc2VydmVyVXJsOiBvcHRpb25zLmVuZHBvaW50ID8/IGRlZmF1bHRFbmRwb2ludCxcbiAgICB1c2VybmFtZTogb3B0aW9ucy51c2VybmFtZSxcbiAgICBwYXNzd29yZDogb3B0aW9ucy5wYXNzd29yZCxcbiAgICByZXBvc2l0b3J5SWQ6IHN0YWdlZC5yZXBvc2l0b3J5SWQsXG4gIH0pO1xuXG4gIGlmIChyZWxlYXNlZCkge1xuICAgIHJldHVybjtcbiAgfVxuICAqL1xuXG4gIC8vIFNlbmQgYSByZW1vdGUgcmVsZWFzZSBjb21tYW5kIHRvIHRoZSByZXBvc2l0b3J5XG4gIGNvbnN0IHJlbGVhc2VPdXRwdXQgPSBhd2FpdCBtYXZlbi5leGVjKGAke05FWFVTX01BVkVOX1NUQUdJTkdfUExVR0lOfTpyYy1yZWxlYXNlYCwge1xuICAgIHByb3BlcnRpZXM6IHtcbiAgICAgIG5leHVzVXJsOiBvcHRpb25zLmVuZHBvaW50ID8/IGRlZmF1bHRFbmRwb2ludCxcbiAgICAgIHNlcnZlcklkOiBzdGFnZWQuc2VydmVySWQsXG4gICAgICBzdGFnaW5nUmVwb3NpdG9yeUlkOiBzdGFnZWQucmVwb3NpdG9yeUlkLFxuICAgIH0sXG4gICAgbm90aHJvdzogdHJ1ZSxcbiAgfSk7XG4gIGlmICghcmVsZWFzZU91dHB1dCkge1xuICAgIGVjaG8oJ/Cfj5zvuI8gU3RvcHBlZCBoZXJlIGJlY2F1c2Ugb2YgZHJ5LXJ1bicpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChyZWxlYXNlT3V0cHV0LmV4aXRDb2RlICE9PSAwKSB7XG4gICAgLy8gSWYgcmVsZWFzZSBmYWlsZWQsIGNoZWNrIGlmIHRoaXMgd2FzIGNhdXNlZCBiZWNhdXNlIHdlIGFyZSB0cnlpbmcgdG8gcHVibGlzaFxuICAgIC8vIHRoZSBzYW1lIHZlcnNpb24gYWdhaW4sIHdoaWNoIGlzIG5vdCBhbiBlcnJvci4gVGhlIG1hZ2ljIHN0cmluZyBcImRvZXMgbm90XG4gICAgLy8gYWxsb3cgdXBkYXRpbmcgYXJ0aWZhY3RcIiBmb3IgYSBcIi5wb21cIiBmaWxlIGluZGljYXRlcyB0aGF0IHdlIGFyZSB0cnlpbmcgdG9cbiAgICAvLyBvdmVycmlkZSBhbiBleGlzdGluZyB2ZXJzaW9uLiBPdGhlcndpc2UsIGZhaWwhXG5cbiAgICBjb25zdCBsb29rc0xpa2VEdXBsaWNhdGVQdWJsaXNoID0gcmVsZWFzZU91dHB1dC5saW5lcygpXG4gICAgICAuZmlsdGVyKGwgPT4gbC5pbmNsdWRlcygnZG9lcyBub3QgYWxsb3cgdXBkYXRpbmcgYXJ0aWZhY3QnKSlcbiAgICAgIC5maWx0ZXIobCA9PiBsLmluY2x1ZGVzKCcucG9tJykpXG4gICAgICAubGVuZ3RoID4gMDtcblxuICAgIGlmICghbG9va3NMaWtlRHVwbGljYXRlUHVibGlzaCkge1xuICAgICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKCdSZWxlYXNlIGZhaWxlZCcpO1xuICAgIH1cblxuICAgIGVjaG8oJ+KaoO+4jyBBcnRpZmFjdCBhbHJlYWR5IHB1Ymxpc2hlZC4gU2tpcHBpbmcnKTtcbiAgfVxufVxuXG4vKipcbiAqIERlcGxveSB0byB0aGUgY29tcGF0IE9TU1JIIE5leHVzIHNlcnZlclxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lDb21wYXRPc3NyaChtYXZlbjogTWF2ZW4sIG9wdGlvbnM6IENvbXBhdE9zc3JoUHVibGlzaE9wdGlvbnMpIHtcbiAgZWNobygn8J+TpiBQdWJsaXNoaW5nIHRvIE1hdmVuIENlbnRyYWwgKENvbXBhdCBlbmRwb2ludCknKTtcblxuICBjb25zdCBkZWZhdWx0RW5kcG9pbnQgPSAnaHR0cHM6Ly9vc3NyaC1zdGFnaW5nLWFwaS5jZW50cmFsLnNvbmF0eXBlLmNvbS8nO1xuICBjb25zdCBlbmRwb2ludCA9IG9wdGlvbnMuZW5kcG9pbnQgPz8gZGVmYXVsdEVuZHBvaW50O1xuXG4gIGNvbnN0IHN0YWdlZCA9IGF3YWl0IGRlcGxveVN0YWdlZFJlcG9zaXRvcnkobWF2ZW4sIHtcbiAgICAuLi5vcHRpb25zLFxuICAgIGVuZHBvaW50LFxuICAgIHJlcHVibGlzaFdpbGw0MDA6IHRydWUsXG4gIH0pO1xuXG4gIGlmIChzdGFnZWQudHlwZSAhPT0gJ3N1Y2Nlc3MnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgcmVsZWFzZWQgPSBhd2FpdCByZWxlYXNlUmVwbyh7XG4gICAgc2VydmVyVXJsOiBlbmRwb2ludCxcbiAgICB1c2VybmFtZTogb3B0aW9ucy51c2VybmFtZSxcbiAgICBwYXNzd29yZDogb3B0aW9ucy5wYXNzd29yZCxcbiAgICByZXBvc2l0b3J5SWQ6IHN0YWdlZC5yZXBvc2l0b3J5SWQsXG4gIH0pO1xuXG4gIGlmIChyZWxlYXNlZCA9PT0gJ2R1cGxpY2F0ZS12ZXJzaW9uJykge1xuICAgIGVjaG8oJ+KaoO+4jyBWZXJzaW9uKHMpIGFscmVhZHkgcHVibGlzaGVkLiBTa2lwcGluZycpO1xuICB9XG59XG5cbi8qKlxuICogRGVwbG95IHRvIGEgY3VzdG9tIE5leHVzIHNlcnZlclxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lDdXN0b21OZXh1cyhtYXZlbjogTWF2ZW4sIG9wdGlvbnM6IEN1c3RvbU5leHVzUHVibGlzaE9wdGlvbnMpIHtcbiAgZWNobyhg8J+TpiBQdWJsaXNoaW5nIHRvICR7b3B0aW9ucy5zZXJ2ZXJJZH1gKTtcbiAgYXdhaXQgbWF2ZW4ud3JpdGVTZXR0aW5nc0ZpbGUob3B0aW9ucy5zZXJ2ZXJJZCwgZmFsc2UpO1xuXG4gIGZvciAoY29uc3QgcG9tIG9mIG9wdGlvbnMucG9tcykge1xuICAgIGNvbnN0IGRlcGxveU91dHB1dCA9IGF3YWl0IG1hdmVuLmV4ZWMoJ2RlcGxveTpkZXBsb3ktZmlsZScsIHtcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgdXJsOiBvcHRpb25zLnJlcG9zaXRvcnlVcmwsXG4gICAgICAgIHJlcG9zaXRvcnlJZDogb3B0aW9ucy5zZXJ2ZXJJZCxcbiAgICAgICAgcG9tRmlsZTogcG9tLFxuICAgICAgICAuLi5qYXJzRnJvbVBvbShwb20pLFxuICAgICAgfSxcbiAgICAgIG5vdGhyb3c6IHRydWUsXG4gICAgfSk7XG5cbiAgICBpZiAoZGVwbG95T3V0cHV0Py5leGl0Q29kZSAmJiBkZXBsb3lPdXRwdXQuZXhpdENvZGUgPiAwKSB7XG4gICAgICBpZiAoZGVwbG95T3V0cHV0LnN0ZG91dC5pbmNsdWRlcygnNDA5IENvbmZsaWN0JykpIHtcbiAgICAgICAgZWNobygn4pqg77iPIEFydGlmYWN0IGFscmVhZHkgcHVibGlzaGVkLiBTa2lwcGluZycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKCdSZWxlYXNlIGZhaWxlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG50eXBlIERlcGxveVN0YWdlZFJlcG9SZXN1bHQgPVxuICB8IHsgdHlwZTogJ3N1Y2Nlc3MnOyByZXBvc2l0b3J5SWQ6IHN0cmluZzsgc2VydmVySWQ6IHN0cmluZyB9XG4gIHwgeyB0eXBlOiAnYWxyZWFkeS1wdWJsaXNoZWQnIH1cbiAgfCB7IHR5cGU6ICdkcnktcnVuJyB9O1xuXG4vKipcbiAqIENyZWF0ZSB0aGUgc3RhZ2luZyByZXBvc2l0b3J5LiBUaGlzIGlzIHRoZSBzYW1lIGJldHdlZW4gdGhlIGxlZ2FjeSBhbmQgY29tcGF0IGVuZHBvaW50cy5cbiAqXG4gKiBgcmVwdWJsaXNoV2lsbDQwMGA6IGluIHRoZSBjb21wYXRpYmlsaXR5IGVuZHBvaW50LCBzdGFnaW5nIGEgdmVyc2lvbiB0aGF0IGhhcyBhbHJlYWR5XG4gKiBiZWVuIHB1Ymxpc2hlZCB3aWxsIGxlYWQgdG8gYSBgNDAwIEJhZCBSZXF1ZXN0YCwgd2l0aCBubyBmdXJ0aGVyIGluZm8uIFdlIG5lZWRlZCB0byBoYXZlXG4gKiBydW4gdGhlIE1hdmVuIGNvbW1hbmQgd2l0aCBgLS1kZWJ1Z2AgbG9nZ2luZyB0byBzZWUgdGhlIGFjdHVhbCBlcnJvciBtZXNzYWdlIGluIHRoZSBvdXRwdXQuXG4gKlxuICogSW4gdGhlIGxlZ2FjeSBlbmRwb2ludCwgc3RhZ2luZyB0YWtlcyBtdWx0aXBsZSBtaW51dGVzLCBhbmQgTWF2ZW4gd2lsbCBwb2xsXG4gKiBldmVyeSAzcyBhbmQgcHJpbnQgdGhlIG91dHB1dC4gV2UgdGhlcmVmb3JlIGRvbid0IHVzZSB2ZXJib3NlIG1vZGUgdG8gYXZvaWRcbiAqIHN0ZG91dCBzcGFtLiBJbiB0aGUgbGVnYWN5IGVuZHBvaW50LCBkdXBsaWNhdGUgdmVyc2lvbiBwdWJsaXNoaW5nIGdldHNcbiAqIHJlcG9ydGVkIGR1cmluZyB0aGUgJ3JlbGVhc2UnIHN0ZXAgYW55d2F5LCBub3QgZHVyaW5nIHN0YWdpbmcuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRlcGxveVN0YWdlZFJlcG9zaXRvcnkobWF2ZW46IE1hdmVuLCBvcHRpb25zOiBPbWl0PExlZ2FjeU9zc3JoUHVibGlzaE9wdGlvbnMgfCBDb21wYXRPc3NyaFB1Ymxpc2hPcHRpb25zLCAnZW5kcG9pbnQnPiAmIHsgZW5kcG9pbnQ6IHN0cmluZzsgcmVwdWJsaXNoV2lsbDQwMDogYm9vbGVhbiB9KTogUHJvbWlzZTxEZXBsb3lTdGFnZWRSZXBvUmVzdWx0PiB7XG4gIGNvbnN0IHNlcnZlcklkID0gJ29zc3JoJztcblxuICBhd2FpdCBtYXZlbi53cml0ZVNldHRpbmdzRmlsZShzZXJ2ZXJJZCwgdHJ1ZSk7XG5cbiAgLy8gRmlyc3QgLS0gc2lnbiBhcnRpZmFjdHNcbiAgY29uc3Qgc2lnbmVkRGlyID0gcGF0aC5qb2luKG1hdmVuLndvcmtEaXIsICdzaWduZWQnKTtcbiAgYXdhaXQgZnMubWtkaXIoc2lnbmVkRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBhd2FpdCBzaWduSmFycyhtYXZlbiwgb3B0aW9ucy5wb21zLCBzaWduZWREaXIsIHNlcnZlcklkLCBvcHRpb25zLnByaXZhdGVLZXkpO1xuXG4gIGVjaG8oJ35+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+fn4nKTtcbiAgZWNobygnIERlcGxveWluZyBhbmQgY2xvc2luZyByZXBvc2l0b3J5Li4uJyk7XG4gIGVjaG8oJ35+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+fn4nKTtcblxuICBjb25zdCBuZXh1c01hdmVuU3RhZ2luZyA9ICdvcmcuc29uYXR5cGUucGx1Z2luczpuZXh1cy1zdGFnaW5nLW1hdmVuLXBsdWdpbjoxLjcuMCc7XG4gIGNvbnN0IHN0YWdlT3V0cHV0ID0gYXdhaXQgbWF2ZW4uZXhlYyhgJHtuZXh1c01hdmVuU3RhZ2luZ306ZGVwbG95LXN0YWdlZC1yZXBvc2l0b3J5YCwge1xuICAgIHByb3BlcnRpZXM6IHtcbiAgICAgIHJlcG9zaXRvcnlEaXJlY3Rvcnk6IHNpZ25lZERpcixcbiAgICAgIG5leHVzVXJsOiBvcHRpb25zLmVuZHBvaW50LFxuICAgICAgc2VydmVySWQsXG4gICAgICBzdGFnaW5nUHJvZ3Jlc3NUaW1lb3V0TWludXRlczogJzMwJyxcbiAgICAgIHN0YWdpbmdQcm9maWxlSWQ6IG9wdGlvbnMuc3RhZ2luZ1Byb2ZpbGVJZCxcbiAgICB9LFxuICAgIG5vdGhyb3c6IHRydWUsXG4gICAgdmVyYm9zZTogb3B0aW9ucy5yZXB1Ymxpc2hXaWxsNDAwLFxuICB9KTtcbiAgLy8gRklYTUU6IE5ldyBzdGFnaW5nIEFQSSB0aHJvd3MgYW4gZXJyb3IgaGVyZSBvbiBkdXBsaWNhdGUgdmVyc2lvbnNcbiAgaWYgKHN0YWdlT3V0cHV0ID09PSB1bmRlZmluZWQpIHtcbiAgICBlY2hvKCfwn4+c77iPIFN0b3BwZWQgaGVyZSBiZWNhdXNlIG9mIGRyeS1ydW4nKTtcbiAgICByZXR1cm4geyB0eXBlOiAnZHJ5LXJ1bicgfTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLnJlcHVibGlzaFdpbGw0MDAgJiYgc3RhZ2VPdXRwdXQudGV4dCgpLm1hdGNoKC9Db21wb25lbnQgd2l0aCBwYWNrYWdlIHVybC4qYWxyZWFkeSBleGlzdHMvKSkge1xuICAgIC8vIFdlJ3ZlIHNlZW4gdGhpcyBmYWlsIHdpdGggdGhlIGFib3ZlIGVycm9yIG1lc3NhZ2Ugb24gdGhlIE9TU1JIIGNvbXBhdGliaWxpdHkgQVBJIHdoZW4gdHJ5aW5nIHRvIHJlcHVibGlzaFxuICAgIC8vIGFuIGFscmVhZHktcHVibGlzaGVkIHZlcnNpb24uXG4gICAgLy9cbiAgICAvLyBUaGlzIGlzIHBvdGVudGlhbGx5IGEgcHJvYmxlbSBpZiB0aGVyZSBhcmUgbXVsdGlwbGUgdmVyc2lvbnMgaW4gdGhlIHNvdXJjZSBkaXJlY3RvcnkgYXQgb25jZSwgYmVjYXVzZSBub3RoaW5nXG4gICAgLy8gd2lsbCBiZSBwdWJsaXNoZWQgaWYgdGhlcmUncyBvbmUgcGFja2FnZSBpbiB0aGVyZSB0aGF0IGhhcyBhbHJlYWR5IGJlZW4gcHVibGlzaGVkIHByZXZpb3VzbHkuIEJ1dCBjJ2VzdCBsYSB2aWUuXG4gICAgZWNobygn4pqg77iPIFZlcnNpb24ocykgYWxyZWFkeSBwdWJsaXNoZWQuIFNraXBwaW5nJyk7XG4gICAgcmV0dXJuIHsgdHlwZTogJ2FscmVhZHktcHVibGlzaGVkJyB9O1xuICB9IGVsc2UgaWYgKHN0YWdlT3V0cHV0LmV4aXRDb2RlICYmIHN0YWdlT3V0cHV0LmV4aXRDb2RlID4gMCkge1xuICAgIHRocm93IHN0YWdlT3V0cHV0O1xuICB9XG5cbiAgLy8gR3JlcCB0aGUgcmVwb3NpdG9yeSBJRCBvdXQgb2YgdGhlIHByaW50ZWQgb3V0cHV0XG4gIC8vIFtJTkZPXSAgKiBDbG9zaW5nIHN0YWdpbmcgcmVwb3NpdG9yeSB3aXRoIElEIFwiWFhYWFhYWFhYWFwiLlxuICBjb25zdCBtID0gc3RhZ2VPdXRwdXQuc3Rkb3V0Lm1hdGNoKC9DbG9zaW5nIHN0YWdpbmcgcmVwb3NpdG9yeSB3aXRoIElEIFwiKFteXCJdKylcIi8pO1xuICBpZiAoIW0pIHtcbiAgICB0aHJvdyBuZXcgU2ltcGxlRXJyb3IoJ1VuYWJsZSB0byBleHRyYWN0IHJlcG9zaXRvcnkgSUQgZnJvbSBkZXBsb3ktc3RhZ2VkLXJlcG9zaXRvcnkgb3V0cHV0LiBUaGlzIG1lYW5zIGl0IGZhaWxlZCB0byBjbG9zZSBvciB0aGVyZSB3YXMgYW4gdW5leHBlY3RlZCBwcm9ibGVtLiBBdCBhbnkgcmF0ZSwgd2UgY2FuXFwndCByZWxlYXNlIGl0LiBTb3JyeS4nKTtcbiAgfVxuICBjb25zdCByZXBvc2l0b3J5SWQgPSBtWzFdO1xuXG4gIHJldHVybiB7IHR5cGU6ICdzdWNjZXNzJywgcmVwb3NpdG9yeUlkLCBzZXJ2ZXJJZCB9O1xufVxuXG4vKipcbiAqIFNlbmQgYSBjdXN0b20gXCJyZWxlYXNlXCIgY29tbWFuZCB0byB0aGUgbmV3IFNvbmF0eXBlIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGVuZHBvaW50XG4gKlxuICogV2hlbiB1c2luZyB0aGUgYG5leHVzLXN0YWdpbmctbWF2ZW4tcGx1Z2luYCdzIGByZWxlYXNlYCBvciBgcmMtcmVsZWFzZWAgY29tbWFuZHMsIHdlIGdldCB0aGUgZm9sbG93aW5nXG4gKiBlcnJvcjpcbiAqXG4gKiBTZW5kaW5nOlxuICpcbiAqIGBgYFxuICogPHN0YWdpbmdBY3Rpb25SZXF1ZXN0PjxkYXRhPjxzdGFnZWRSZXBvc2l0b3J5SWRzIGNsYXNzPVwiamF2YS51dGlsLkFycmF5cyRBcnJheUxpc3RcIj48YSBjbGFzcz1cInN0cmluZy1hcnJheVwiPjxzdHJpbmc+aW8uZ2l0aHViLnJpeDBycnItLTYzZWRiY2JlLWYwNTgtNDRlYi04NWY0LWZkOWRjZTFhZWY0MDwvc3RyaW5nPjwvYT48L3N0YWdlZFJlcG9zaXRvcnlJZHM+PGRlc2NyaXB0aW9uPnVua25vd248L2Rlc2NyaXB0aW9uPjxhdXRvRHJvcEFmdGVyUmVsZWFzZT50cnVlPC9hdXRvRHJvcEFmdGVyUmVsZWFzZT48L2RhdGE+PC9zdGFnaW5nQWN0aW9uUmVxdWVzdD5cbiAqIGBgYFxuICpcbiAqIEVycm9yOlxuICpcbiAqIGBgYFxuICogRmFpbGVkIHRvIHByb2Nlc3MgcmVxdWVzdDogR290IHVuZXhwZWN0ZWQgWE1MIGVsZW1lbnQgd2hlbiByZWFkaW5nIHN0YWdlZFJlcG9zaXRvcnlJZHM6IEdvdCB1bmV4cGVjdGVkIGVsZW1lbnQgU3RhcnRFbGVtZW50KGEsIHtcIlwiOiBcIlwiLCBcInhtbFwiOiBcImh0dHA6Ly93d3cudzMub3JnL1hNTC8xOTk4L25hbWVzcGFjZVwiLCBcInhtbG5zXCI6IFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC94bWxucy9cIn0sIFtjbGFzcyAtPiBzdHJpbmctYXJyYXldKSwgZXhwZWN0ZWQgb25lIG9mOiBzdHJpbmdcbiAqIGBgYFxuICpcbiAqIERvaW5nIGEgbWFudWFsIHNsaWdodGx5IG1vZGlmaWVkIHZlcnNpb24gb2YgdGhlIGFib3ZlIHJlcXVlc3Qgc3VjY2VlZHMsIHNvIHdlJ2xsIGp1c3QgcHJvY2VlZCB3aXRoIGRvaW5nXG4gKiB0aGF0LlxuICpcbiAqIFRoZSBlbmRwb2ludCBhbHNvIHN1cHBvcnRzIEpTT04sIHdoaWNoIHdlIHByZWZlciBvdmVyIFhNTC5cbiAqXG4gKiBUaGlzIGVuZHBvaW50IHdpbGwgbmV2ZXIgcmV0dXJuIGFuIGVycm9yLCBldmVuIGlmIHRoZSBwdWJsaXNoIGRpZG4ndCBoYXBwZW4gYmVjYXVzZVxuICogb2YgZHVwbGljYXRlIHZlcnNpb24gcHVibGlzaGluZyAobm90IGZvciB0aGUgbGVnYWN5LCBub3IgZm9yIHRoZSBjb21wYXRpYmlsaXR5IGVuZHBvaW50KS5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vY2VudHJhbC5zb25hdHlwZS5vcmcvcHVibGlzaC9wdWJsaXNoLXBvcnRhbC1vc3NyaC1zdGFnaW5nLWFwaS9cbiAqIEBzZWUgaHR0cHM6Ly9zdXBwb3J0LnNvbmF0eXBlLmNvbS9oYy9lbi11cy9hcnRpY2xlcy8yMTM0NjU0NDgtQXV0b21hdGljYWxseS1kcm9wcGluZy1vbGQtc3RhZ2luZy1yZXBvc2l0b3JpZXNcbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVsZWFzZVJlcG8ob3B0aW9uczogeyBzZXJ2ZXJVcmw6IHN0cmluZzsgdXNlcm5hbWU6IHN0cmluZzsgcGFzc3dvcmQ6IHN0cmluZzsgcmVwb3NpdG9yeUlkOiBzdHJpbmc7IGRlc2NyaXB0aW9uPzogc3RyaW5nIH0pOiBQcm9taXNlPCdvaycgfCAnZHVwbGljYXRlLXZlcnNpb24nPiB7XG4gIGVjaG8oYPCfmoAgUmVsZWFzaW5nIHJlcG9zaXRvcnkgJHtvcHRpb25zLnJlcG9zaXRvcnlJZH0gYXQgJHtvcHRpb25zLnNlcnZlclVybH1gKTtcbiAgY29uc3QgdXJsID0gbmV3IFVSTCgnc2VydmljZS9sb2NhbC9zdGFnaW5nL2J1bGsvcHJvbW90ZScsIG9wdGlvbnMuc2VydmVyVXJsKTtcblxuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgc3RhZ2VkUmVwb3NpdG9yeUlkczogW29wdGlvbnMucmVwb3NpdG9yeUlkXSxcbiAgICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnMuZGVzY3JpcHRpb24gPz8gJ0RlcGxveW1lbnQnLFxuICAgICAgICBhdXRvRHJvcEFmdGVyUmVsZWFzZTogdHJ1ZSxcbiAgICAgIH0sXG4gICAgfSksXG4gICAgaGVhZGVyczoge1xuICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICdBY2NlcHQnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAnQXV0aG9yaXphdGlvbic6IGBCYXNpYyAke2J0b2EoYCR7b3B0aW9ucy51c2VybmFtZX06JHtvcHRpb25zLnBhc3N3b3JkfWApfWAsXG4gICAgfSxcbiAgfSk7XG5cbiAgY29uc3QgYm9keSA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcblxuICAvLyBJdCdzIHBvc3NpYmxlIHRoYXQgKGR1ZSB0byBzb21lIHJlcGxpY2F0aW9uIGxhdGVuY3k/KSB0aGUgaW5pdGlhbCBcInN0YWdlXCIgc3VjY2VlZHMsXG4gIC8vIGJ1dCB0aGUgXCJyZWxlYXNlXCIgZmFpbHMsIGlmIHdlIHRyeSB0byBwdWJsaXNoIGFuIGFscmVhZHktcHVibGlzaGVkIHZlcnNpb24gYWdhaW4uXG4gIC8vXG4gIC8vIFVuZm9ydHVuYXRlbHkgdGhlcmUgaXMgbm8gZ3JlYXQgZXJyb3IgY29kZSB0byBkZXRlY3QgdGhpcyByaWdodCBub3csIGJ1dCBJJ3ZlIG9ic2VydmVkXG4gIC8vIHRoaXMgZXJyb3Igd2hlbiBpdCBoYXBwZW5lZC5cbiAgLy8gSSBoYXZlIGEgc3VwcG9ydCByZXF1ZXN0IG91dCB0byBTb25hdHlwZSBmb3IgdGhpcywgd2UnbGwgc2VlIGlmIHRoaXMgY2hhbmdlcyBvdmVyIHRpbWUuXG4gIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDQwMCAmJiBib2R5ID09PSAnRmFpbGVkIHRvIHByb2Nlc3MgcmVxdWVzdDogc2VydmljZSBlcnJvcicpIHtcbiAgICByZXR1cm4gJ2R1cGxpY2F0ZS12ZXJzaW9uJztcbiAgfVxuXG4gIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH06ICR7Ym9keX1gKTtcbiAgfVxuXG4gIGNvbnNvbGUubG9nKGJvZHkpO1xuXG4gIHJldHVybiAnb2snO1xufVxuXG4vKipcbiAqIFNpZ24gYW5kIHN0YWdlIG91ciBhcnRpZmFjdHMgaW50byBhIGxvY2FsIGRpcmVjdG9yeVxuICovXG5hc3luYyBmdW5jdGlvbiBzaWduSmFycyhtYXZlbjogTWF2ZW4sIHBvbXM6IHN0cmluZ1tdLCB0YXJnZXREaXI6IHN0cmluZywgc2VydmVySWQ6IHN0cmluZywga2V5OiBQcml2YXRlS2V5KSB7XG4gIGF3YWl0IHVzaW5nIGdwZyA9IGF3YWl0IGltcG9ydEdwZ0tleShrZXkpO1xuXG4gIC8vIG9uIGEgbWFjLCAtLXBpbmVudHJ5LW1vZGUgdG8gXCJsb29wYmFja1wiIGFyZSByZXF1aXJlZCBhbmQgSSBjb3VsZG4ndCBmaW5kIGFcbiAgLy8gd2F5IHRvIGRvIHNvIHZpYSAtRGdwZy5ncGdBcmd1bWVudHMgb3IgdGhlIHNldHRpbmdzIGZpbGUsIHNvIGhlcmUgd2UgYXJlLlxuICBsZXQgZ3BnQmluID0gJ2dwZyc7XG4gIGlmIChvcy5wbGF0Zm9ybSgpID09PSAnZGFyd2luJykge1xuICAgIGdwZ0JpbiA9IHBhdGguam9pbihtYXZlbi53b3JrRGlyLCAncHVibGliLWdwZy5zaCcpO1xuICAgIGF3YWl0IGZzLndyaXRlRmlsZShncGdCaW4sIFtcbiAgICAgICcjIS9iaW4vYmFzaCcsXG4gICAgICAnZXhlYyBncGcgLS1waW5lbnRyeS1tb2RlIGxvb3BiYWNrIFwiXFwkQFwiJyxcbiAgICBdLmpvaW4oJ1xcbicpLCAndXRmLTgnKTtcbiAgICBhd2FpdCAkYGNobW9kICt4ICR7Z3BnQmlufWA7XG4gIH1cblxuICBmb3IgKGNvbnN0IHBvbSBvZiBwb21zKSB7XG4gICAgYXdhaXQgbWF2ZW4uZXhlYygnZ3BnOnNpZ24tYW5kLWRlcGxveS1maWxlJywge1xuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAndXJsJzogYGZpbGU6Ly8ke3RhcmdldERpcn1gLFxuICAgICAgICAncmVwb3NpdG9yeUlkJzogc2VydmVySWQsIC8vIE1vc3QgbGlrZWx5IG5vdCBuZWNlc3NhcnlcbiAgICAgICAgJ2dwZy5ob21lZGlyJzogZ3BnLmhvbWUsXG4gICAgICAgICdncGcua2V5bmFtZSc6IGdwZy5rZXlJZCxcbiAgICAgICAgJ2dwZy5leGVjdXRhYmxlJzogZ3BnQmluLFxuICAgICAgICAncG9tRmlsZSc6IHBvbSxcbiAgICAgICAgLi4uamFyc0Zyb21Qb20ocG9tKSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBCYXNlZCBvbiB0aGUgcGF0aCBvZiBhIC5wb20gZmlsZSwgcmV0dXJuIHRoZSBwYXRocyBvZiB0aGUgY29ycmVzcG9uZGluZyBqYXJzXG4gKi9cbmZ1bmN0aW9uIGphcnNGcm9tUG9tKHBvbTogc3RyaW5nKSB7XG4gIHJldHVybiB7XG4gICAgZmlsZTogcG9tLnJlcGxhY2UoL1xcLnBvbSQvLCAnLmphcicpLFxuICAgIHNvdXJjZXM6IHBvbS5yZXBsYWNlKC9cXC5wb20kLywgJy1zb3VyY2VzLmphcicpLFxuICAgIGphdmFkb2M6IHBvbS5yZXBsYWNlKC9cXC5wb20kLywgJy1qYXZhZG9jLmphcicpLFxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHRlbXBvcmFyeSBkaXJlY3RvcnkgYW5kIGltcG9ydCB0aGUgR1BHIGtleSBtYXRlcmlhbCBpbnRvIGEgbmV3IGtleWNoYWluIHRoZXJlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGltcG9ydEdwZ0tleShrZXk6IFByaXZhdGVLZXkpIHtcbiAgLy8gR251UEcgd2lsbCBvY2Nhc2lvbmFsbHkgYmFpbCBvdXQgd2l0aCBcImdwZzogPHdoYXRldmVyPiBmYWlsZWQ6IEluYXBwcm9wcmlhdGUgaW9jdGwgZm9yIGRldmljZVwiLCB0aGUgZm9sbG93aW5nIGF0dGVtcHRzIHRvIGZpeFxuICBjb25zdCBncGdIb21lID0gYXV0b0NsZWFuRGlyKCk7XG4gIHRyeSB7XG4gICAgLy8gSW4gQ0kgZW52aXJvbm1lbnRzIHRoZXJlIHdpbGwgYmUgbm8gdHR5LCBhbmQgd2UgZG9uJ3Qgd2FudCB0aGlzIHRvIHN0b3AgdGhlIHNjcmlwdC5cbiAgICAvLyBUaGUgdmFyaWFibGUgd2lsbCBiZSBwb3B1bGF0ZWQgd2l0aCBhIG5vbnNlbnNpY2FsIHN0cmluZyAoXCJub3QgYSB0dHlcIikgYnV0IHRoYXQgZG9lc24ndCBzZWVtIHRvIG1hdHRlci5cbiAgICBjb25zdCB0dHkgPSAoYXdhaXQgJCh7IHN0ZGlvOiBbJ2luaGVyaXQnLCAncGlwZScsICdwaXBlJ10sIG5vdGhyb3c6IHRydWUgfSlgdHR5YCkuc3Rkb3V0O1xuXG4gICAgbGV0IHByaXZhdGVLZXlGaWxlO1xuICAgIGNvbnN0IHR5cGUgPSBrZXkudHlwZTtcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2ZpbGUnOlxuICAgICAgICBwcml2YXRlS2V5RmlsZSA9IGtleS5maWxlTmFtZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdtYXRlcmlhbCc6XG4gICAgICAgIHByaXZhdGVLZXlGaWxlID0gcGF0aC5qb2luKGdwZ0hvbWUuZGlyLCAncHJpdmF0ZS5wZW0nKTtcbiAgICAgICAgYXdhaXQgJGBlY2hvIC1lICR7a2V5LmtleU1hdGVyaWFsfSA+ICR7cHJpdmF0ZUtleUZpbGV9YDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBhc3NlcnROZXZlcih0eXBlKTtcbiAgICB9XG5cbiAgICBjb25zdCBlbnYgPSB7XG4gICAgICBHTlVQR0hPTUU6IGdwZ0hvbWUuZGlyLFxuICAgICAgR1BHX1RUWTogdHR5LFxuICAgIH07XG5cbiAgICBjb25zdCAkJCA9ICQoeyBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLmVudiB9IH0pO1xuXG4gICAgYXdhaXQgJCRgZ3BnIC0tYWxsb3ctc2VjcmV0LWtleS1pbXBvcnQgLS1iYXRjaCAtLXllcyAtLW5vLXR0eSAtLWltcG9ydCAke3ByaXZhdGVLZXlGaWxlfWA7XG4gICAgY29uc3QgZ3BnS2V5SWQgPSAoYXdhaXQgJCRgZ3BnIC0tbGlzdC1rZXlzIC0td2l0aC1jb2xvbnMgfCBncmVwIHB1YiB8IGN1dCAtZDogLWY1YCkuc3Rkb3V0LnRyaW0oKTtcblxuICAgIGVjaG8oYGdwZ19rZXlfaWQ9JHtncGdLZXlJZH1gKTtcblxuICAgIHJldHVybiB7XG4gICAgICBrZXlJZDogZ3BnS2V5SWQsXG4gICAgICBlbnYsXG4gICAgICBob21lOiBncGdIb21lLmRpcixcbiAgICAgIFtTeW1ib2wuYXN5bmNEaXNwb3NlXTogYXN5bmMgKCkgPT4gZ3BnSG9tZVtTeW1ib2wuYXN5bmNEaXNwb3NlXSgpLFxuICAgIH07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBhd2FpdCBncGdIb21lW1N5bWJvbC5hc3luY0Rpc3Bvc2VdKCk7XG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG5jbGFzcyBNYXZlbiB7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3NGaWxlOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHdvcmtEaXI6IHN0cmluZywgcHJpdmF0ZSByZWFkb25seSB2ZXJib3NlOiBib29sZWFuLCBwdWJsaWMgcmVhZG9ubHkgZHJ5UnVuOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXR0aW5nc0ZpbGUgPSBwYXRoLmpvaW4od29ya0RpciwgJ212bi1zZXR0aW5ncy54bWwnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBzZXR0aW5ncy54bWwgZmlsZSB3aXRoIHRoZSB1c2VyK3Bhc3N3b3JkIGZvciBtYXZlblxuICAgKi9cbiAgcHVibGljIGFzeW5jIHdyaXRlU2V0dGluZ3NGaWxlKHNlcnZlcklkOiBzdHJpbmcsIHNpZ25lZEFydGlmYWN0czogYm9vbGVhbikge1xuICAgIGNvbnN0IGxpbmVzID0gW107XG5cbiAgICBsaW5lcy5wdXNoKFxuICAgICAgJzw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIlVURi04XCIgPz4nLFxuICAgICAgJzxzZXR0aW5ncyB4bWxucz1cImh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL1NFVFRJTkdTLzEuMC4wXCInLFxuICAgICAgJyAgICAgICAgeG1sbnM6eHNpPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2VcIicsXG4gICAgICAnICAgICAgICB4c2k6c2NoZW1hTG9jYXRpb249XCJodHRwOi8vbWF2ZW4uYXBhY2hlLm9yZy9TRVRUSU5HUy8xLjAuMCcsXG4gICAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL3hzZC9zZXR0aW5ncy0xLjAuMC54c2RcIj4nLFxuICAgICAgJyAgPHNlcnZlcnM+JyxcbiAgICAgICcgICAgPHNlcnZlcj4nLFxuICAgICAgYCAgICAgIDxpZD4ke3NlcnZlcklkfTwvaWQ+YCxcbiAgICAgIC8vIE1hdmVuIHdpbGwgcmVhZCB0aGVzZSwgc3Vycm91bmRpbmcgY29kZSBoYXMgYWxyZWFkeSBtYWRlIHN1cmUgdGhleSBhcmUgc2V0XG4gICAgICAnICAgICAgPHVzZXJuYW1lPiR7ZW52Lk1BVkVOX1VTRVJOQU1FfTwvdXNlcm5hbWU+JyxcbiAgICAgICcgICAgICA8cGFzc3dvcmQ+JHtlbnYuTUFWRU5fUEFTU1dPUkR9PC9wYXNzd29yZD4nLFxuICAgICAgJyAgICA8L3NlcnZlcj4nLFxuICAgICk7XG5cbiAgICBpZiAoc2lnbmVkQXJ0aWZhY3RzKSB7XG4gICAgICBsaW5lcy5wdXNoKFxuICAgICAgICAnICAgIDxzZXJ2ZXI+JyxcbiAgICAgICAgJyAgICAgIDxpZD5ncGcucGFzc3BocmFzZTwvaWQ+JyxcbiAgICAgICAgLy8gTWF2ZW4gd2lsbCByZWFkIHRoZXNlLCBzdXJyb3VuZGluZyBjb2RlIGhhcyBhbHJlYWR5IG1hZGUgc3VyZSB0aGV5IGFyZSBzZXRcbiAgICAgICAgJyAgICAgIDxwYXNzcGhyYXNlPiR7ZW52Lk1BVkVOX0dQR19QUklWQVRFX0tFWV9QQVNTUEhSQVNFfTwvcGFzc3BocmFzZT4nLFxuICAgICAgICAnICAgIDwvc2VydmVyPicsXG4gICAgICApO1xuICAgIH1cblxuICAgIGxpbmVzLnB1c2goXG4gICAgICAnICA8L3NlcnZlcnM+JyxcbiAgICAgICc8L3NldHRpbmdzPicsXG4gICAgKTtcblxuICAgIGF3YWl0IGZzLndyaXRlRmlsZSh0aGlzLnNldHRpbmdzRmlsZSwgbGluZXMuam9pbignXFxuJyksICd1dGYtOCcpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGV4ZWMobW9qbzogc3RyaW5nLCBvcHRpb25zOiBNYXZlbkV4ZWNPcHRpb25zKTogUHJvbWlzZTxQcm9jZXNzT3V0cHV0IHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgYXJncyA9IFtcbiAgICAgIGAtLXNldHRpbmdzPSR7dGhpcy5zZXR0aW5nc0ZpbGV9YCxcbiAgICAgICctLWJhdGNoLW1vZGUnLFxuICAgICAgLi4uKG9wdGlvbnMudmVyYm9zZSA/PyB0aGlzLnZlcmJvc2UgPyBbJy1YJ10gOiBbXSksXG4gICAgICBtb2pvLFxuICAgICAgLi4uT2JqZWN0LmVudHJpZXMob3B0aW9ucy5wcm9wZXJ0aWVzKS5tYXAoKFtrLCB2XSkgPT4gYC1EJHtrfT0ke3Z9YCksXG4gICAgXTtcblxuICAgIGlmICh0aGlzLmRyeVJ1bikge1xuICAgICAgZWNobyhgW0RSWS1SVU5dIG12biAke2FyZ3MubWFwKHF1b3RlKS5qb2luKCcgJyl9YCk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBlbnYgPSB7XG4gICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgIEpES19KQVZBX09QVElPTlM6IFtcbiAgICAgICAgLy8gSWYgd2UgZG9uJ3QgYWRkIHRoaXMsIHdlJ2xsIGdldCBhbiBlcnJvciBsaWtlIHRoZSBmb2xsb3dpbmcgZHVyaW5nIHRoZSBuZXh1cy1zdGFnaW5nLW1hdmVuLXBsdWdpbjpyYy1yZWxlYXNlIG1vam8uXG4gICAgICAgIC8vIERvbid0IGtub3cgd2hlcmUgdGhpcyBpcyBjb21pbmcgZnJvbSBhbGwgb2YgYSBzdWRkZW4uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFtFUlJPUl0gbWVzc2FnZSAgICAgICAgICAgICA6IE5vIGNvbnZlcnRlciBhdmFpbGFibGVcbiAgICAgICAgLy8gW0VSUk9SXSB0eXBlICAgICAgICAgICAgICAgIDogamF2YS51dGlsLkFycmF5cyRBcnJheUxpc3RcbiAgICAgICAgLy8gW0VSUk9SXSBjb252ZXJ0ZXIgICAgICAgICAgIDogY29tLnRob3VnaHR3b3Jrcy54c3RyZWFtLmNvbnZlcnRlcnMucmVmbGVjdGlvbi5SZWZsZWN0aW9uQ29udmVydGVyXG4gICAgICAgIC8vIFtFUlJPUl0gbWVzc2FnZVsxXSAgICAgICAgICA6IFVuYWJsZSB0byBtYWtlIGZpZWxkIHByb3RlY3RlZCB0cmFuc2llbnQgaW50IGphdmEudXRpbC5BYnN0cmFjdExpc3QubW9kQ291bnQgYWNjZXNzaWJsZTogbW9kdWxlIGphdmEuYmFzZSBkb2VzIG5vdCBcIm9wZW5zIGphdmEudXRpbFwiIHRvIHVubmFtZWQgbW9kdWxlIEA3YzhkNTMxMlxuICAgICAgICAnLS1hZGQtb3BlbnM9amF2YS5iYXNlL2phdmEudXRpbD1BTEwtVU5OQU1FRCcsXG4gICAgICAgICctLWFkZC1vcGVucz1qYXZhLmJhc2UvamF2YS5sYW5nPUFMTC1VTk5BTUVEJyxcbiAgICAgICAgJy0tYWRkLW9wZW5zPWphdmEuYmFzZS9qYXZhLmxhbmcuaW52b2tlPUFMTC1VTk5BTUVEJyxcbiAgICAgIF0uam9pbignICcpLFxuICAgIH07XG5cbiAgICByZXR1cm4gJCh7IHZlcmJvc2U6IHRydWUsIG5vdGhyb3c6IG9wdGlvbnMubm90aHJvdywgZW52IH0pYG12biAke2FyZ3N9YDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgTWF2ZW5FeGVjT3B0aW9ucyB7XG4gIHByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIG5vdGhyb3c/OiBib29sZWFuO1xuICB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIGV4cGVjdGVkIGVycm9yIHRoYXQgZG9lc24ndCBuZWVkIGEgc3RhY2sgdHJhY2VcbiAqL1xuY2xhc3MgU2ltcGxlRXJyb3IgZXh0ZW5kcyBFcnJvciB7IH1cblxuLyoqXG4gKiBSZXF1aXJlIGFuIGVudmlyb25tZW50IHZhcmlhYmxlXG4gKi9cbmZ1bmN0aW9uIGVudlZhcihuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCByZXQgPSBwcm9jZXNzLmVudltuYW1lXTtcbiAgaWYgKCFyZXQpIHtcbiAgICB0aHJvdyBuZXcgU2ltcGxlRXJyb3IoYCR7bmFtZX0gaXMgcmVxdWlyZWRgKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIEEgdGVtcG9yYXJ5IGRpcmVjdG9yeSB0aGF0IGNsZWFucyB3aGVuIGl0IGdvZXMgb3V0IG9mIHNjb3BlXG4gKlxuICogVXNlIHdpdGggYHVzaW5nYC4gQ291bGQgaGF2ZSBiZWVuIGFzeW5jIGJ1dCBpdCdzIGRlcGVuZGluZ1xuICogb24gYW4gYWxyZWFkeS1zeW5jIEFQSSwgc28gd2h5IG5vdCBzeW5jP1xuICovXG5leHBvcnQgZnVuY3Rpb24gYXV0b0NsZWFuRGlyKCkge1xuICBjb25zdCBkaXIgPSB0bXBkaXIoKTtcbiAgcmV0dXJuIHtcbiAgICBkaXIsXG4gICAgW1N5bWJvbC5hc3luY0Rpc3Bvc2VdOiBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBmcy5ybShkaXIsIHsgZm9yY2U6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9LFxuICB9O1xufVxuXG5mdW5jdGlvbiBhc3NlcnROZXZlcih2YWx1ZTogbmV2ZXIpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdVbmV4cGVjdGVkIHZhbHVlOiAnICsgdmFsdWUpO1xufVxuXG4vLyBBICd6eCcgcHJpbWVyXG4vL1xuLy8gLSBCeSBkZWZhdWx0OiBzdGRlcnIgaXMgcHJpbnRlZCB0byB0aGUgdGVybWluYWwgaWYgaXQgaXMgY2FwdHVyZWQuXG4vLyAtIHsgdmVyYm9zZTogdHJ1ZSB9OiBwcmludCB0aGUgY29tbWFuZCwgc3Rkb3V0IGFuZCBzdGRlcnIgdG8gdGhlIHRlcm1pbmFsXG4vLyAtIHsgcXVpZXQ6IHRydWUgfTogcHJpbnQgbmVpdGhlciBzdGRvdXQgbm9yIHN0ZGVyclxuLy9cbi8vIC50ZXh0KCk6IHJldHVybiBldmVyeXRoaW5nIHRoYXQncyBjYXB0dXJlZCAoc3RkZXJyIGFuZCBzdGRvdXQgdG9nZXRoZXIgaWYgc3RkZXJyIGlzIGNhcHR1cmVkKVxuXG5tYWluKCkuY2F0Y2goZSA9PiB7XG4gIGlmIChlIGluc3RhbmNlb2YgUHJvY2Vzc091dHB1dCkge1xuICAgIGVjaG8oYOKdjCBTdWJwcm9jZXNzIGZhaWxlZCB3aXRoIGV4aXQgY29kZSAke2UuZXhpdENvZGV9YCk7XG4gIH0gZWxzZSBpZiAoZSBpbnN0YW5jZW9mIFNpbXBsZUVycm9yKSB7XG4gICAgZWNobygn4p2MJywgZS5tZXNzYWdlKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKGUpO1xuICB9XG4gIHByb2Nlc3MuZXhpdENvZGUgPSAxO1xufSk7XG4iXX0=