UNPKG

gitlab-ci-local

Version:

Tired of pushing to test your .gitlab-ci.yml?

168 lines 30.4 kB
import { Utils } from "./utils.js"; import assert, { AssertionError } from "assert"; import chalk from "chalk"; export class GitData { user = { GITLAB_USER_LOGIN: "local", GITLAB_USER_EMAIL: "local@gitlab.com", GITLAB_USER_NAME: "Bob Local", GITLAB_USER_ID: "1000", }; branches = { default: "main", }; remote = { schema: "git", port: "22", host: "gitlab.com", group: "fallback.group", project: "fallback.project", }; commit = { REF_NAME: "main", SHA: "0000000000000000000000000000000000000000", SHORT_SHA: "00000000", TIMESTAMP: new Date().toISOString().split(".")[0] + "Z", }; static async init(cwd, writeStreams) { const gitData = new GitData(); const promises = []; promises.push(gitData.initCommitData(cwd, writeStreams)); promises.push(gitData.initRemoteData(cwd, writeStreams)); promises.push(gitData.initUserData(cwd, writeStreams)); promises.push(gitData.initBranchData(cwd, writeStreams)); await Promise.all(promises); return gitData; } async initCommitData(cwd, writeStreams) { const promises = []; const refNamePromise = Utils.spawn(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd); promises.push(refNamePromise.then(({ stdout }) => { this.commit.REF_NAME = stdout.trimEnd(); })); const shaPromise = Utils.spawn(["git", "rev-parse", "HEAD"], cwd); promises.push(shaPromise.then(({ stdout }) => { this.commit.SHA = stdout.trimEnd(); })); try { await Promise.all(promises); } catch (e) { if (e instanceof AssertionError) { return writeStreams.stderr(chalk `{yellow ${e.message}}\n`); } writeStreams.stderr(chalk `{yellow Using fallback git commit data}\n`); writeStreams.stderr(chalk `{yellow ${e.message}\n}`); } } async initBranchData(cwd, writeStreams) { try { const { stdout: gitRemoteDefaultBranch } = await Utils.spawn(["git", "symbolic-ref", "--short", "refs/remotes/origin/HEAD"], cwd); this.branches.default = gitRemoteDefaultBranch.replace("origin/", ""); } catch (e) { if (e.stderr === "fatal: ref refs/remotes/origin/HEAD is not a symbolic ref") { writeStreams.stderr(chalk `{yellow Unable to retrieve default remote branch, falling back to \`${this.branches.default}\`. The default remote branch can be set via \`git remote set-head origin <default_branch>\`\n}`); writeStreams.stderr(chalk `{yellow ${e.message}\n}`); } else { writeStreams.stderr(chalk `{yellow Unable to retrieve default remote branch, falling back to \`${this.branches.default}\`.\n}`); writeStreams.stderr(chalk `{yellow ${e.message}\n}`); } } } static changedFiles(defaultBranch, cwd) { return Utils.syncSpawn(["git", "diff", "--name-only", defaultBranch], cwd).stdout.split("\n"); } async initRemoteData(cwd, writeStreams) { try { let gitRemoteMatch; let gitRemote; try { // NOTE: For power user that wishes to customize the remote url const res = await Utils.spawn(["git", "remote", "get-url", "gcl-origin"], cwd); gitRemote = res.stdout; } catch { const res = await Utils.spawn(["git", "remote", "get-url", "origin"], cwd); gitRemote = res.stdout; } // To simplify the regex. Stripping the trailing `/` or `.git` since they're both optional. const normalizedGitRemote = gitRemote .replace(/\/$/, "") .replace(/\.git$/, ""); if (normalizedGitRemote.startsWith("http")) { gitRemoteMatch = /(?<schema>https?):\/\/(?:([^:]+):([^@]+)@)?(?<host>[^/:]+):?(?<port>\d+)?\/(?<group>\S+)\/(?<project>\S+)/.exec(normalizedGitRemote); // regexr.com/7ve8l assert(gitRemoteMatch?.groups != null, "git remote get-url origin didn't provide valid matches"); let port = "443"; if (gitRemoteMatch.groups.schema === "https") { port = gitRemoteMatch.groups.port ?? "443"; } else if (gitRemoteMatch.groups.schema === "http") { port = gitRemoteMatch.groups.port ?? "80"; } this.remote.host = gitRemoteMatch.groups.host; this.remote.group = gitRemoteMatch.groups.group; this.remote.project = gitRemoteMatch.groups.project; this.remote.schema = gitRemoteMatch.groups.schema; this.remote.port = port; } else if (normalizedGitRemote.startsWith("ssh://")) { gitRemoteMatch = /(?<schema>ssh):\/\/(\w+)@(?<host>[^/:]+):?(?<port>\d+)?\/(?<group>\S+)\/(?<project>\S+)/.exec(normalizedGitRemote); // regexr.com/7vjq4 assert(gitRemoteMatch?.groups != null, "git remote get-url origin didn't provide valid matches"); this.remote.host = gitRemoteMatch.groups.host; this.remote.group = gitRemoteMatch.groups.group; this.remote.project = gitRemoteMatch.groups.project; this.remote.schema = gitRemoteMatch.groups.schema; this.remote.port = gitRemoteMatch.groups.port ?? "22"; } else { gitRemoteMatch = /(?<username>\S+)@(?<host>[^:]+):(?<group>\S+)\/(?<project>\S+)/.exec(normalizedGitRemote); // regexr.com/7vjoq assert(gitRemoteMatch?.groups != null, "git remote get-url origin didn't provide valid matches"); const { stdout } = await Utils.spawn(["ssh", "-G", `${gitRemoteMatch.groups.username}@${gitRemoteMatch.groups.host}`]); const port = stdout.split("\n").filter((line) => line.startsWith("port "))[0].split(" ")[1]; this.remote.host = gitRemoteMatch.groups.host; this.remote.group = gitRemoteMatch.groups.group; this.remote.project = gitRemoteMatch.groups.project; this.remote.schema = "git"; this.remote.port = port; } } catch (e) { if (e instanceof AssertionError) { writeStreams.stderr(chalk `{yellow ${e.message}}\n`); return; } writeStreams.stderr(chalk `{yellow Using fallback git remote data}\n`); writeStreams.stderr(chalk `{yellow ${e.message}\n}`); } } async initUserData(cwd, writeStreams) { const promises = []; const gitUsernamePromise = Utils.spawn(["git", "config", "user.name"], cwd).then(({ stdout }) => { this.user.GITLAB_USER_NAME = stdout.trimEnd(); }).catch((e) => { writeStreams.stderr(chalk `{yellow Using fallback git user.name}\n`); writeStreams.stderr(chalk `{yellow ${e.message}\n}`); }); promises.push(gitUsernamePromise); const gitEmailPromise = Utils.spawn(["git", "config", "user.email"], cwd).then(({ stdout }) => { const email = stdout.trimEnd(); this.user.GITLAB_USER_EMAIL = email; this.user.GITLAB_USER_LOGIN = email.replace(/@.*/, ""); }).catch((e) => { writeStreams.stderr(chalk `{yellow Using fallback git user.email}\n`); writeStreams.stderr(chalk `{yellow ${e.message}\n}`); }); promises.push(gitEmailPromise); const osUidPromise = Utils.spawn(["id", "-u"], cwd).then(({ stdout }) => { this.user.GITLAB_USER_ID = stdout.trimEnd(); }).catch((e) => { writeStreams.stderr(chalk `{yellow Using fallback linux user id}\n`); writeStreams.stderr(chalk `{yellow ${e.message}\n}`); }); promises.push(osUidPromise); await Promise.all(promises); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l0LWRhdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJnaXQtZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ2pDLE9BQU8sTUFBTSxFQUFFLEVBQUMsY0FBYyxFQUFDLE1BQU0sUUFBUSxDQUFDO0FBRTlDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUkxQixNQUFNLE9BQU8sT0FBTztJQUVBLElBQUksR0FBRztRQUNuQixpQkFBaUIsRUFBRSxPQUFPO1FBQzFCLGlCQUFpQixFQUFFLGtCQUFrQjtRQUNyQyxnQkFBZ0IsRUFBRSxXQUFXO1FBQzdCLGNBQWMsRUFBRSxNQUFNO0tBQ3pCLENBQUM7SUFFYyxRQUFRLEdBQUc7UUFDdkIsT0FBTyxFQUFFLE1BQU07S0FDbEIsQ0FBQztJQUVjLE1BQU0sR0FBRztRQUNyQixNQUFNLEVBQUUsS0FBa0I7UUFDMUIsSUFBSSxFQUFFLElBQUk7UUFDVixJQUFJLEVBQUUsWUFBWTtRQUNsQixLQUFLLEVBQUUsZ0JBQWdCO1FBQ3ZCLE9BQU8sRUFBRSxrQkFBa0I7S0FDOUIsQ0FBQztJQUVjLE1BQU0sR0FBRztRQUNyQixRQUFRLEVBQUUsTUFBTTtRQUNoQixHQUFHLEVBQUUsMENBQTBDO1FBQy9DLFNBQVMsRUFBRSxVQUFVO1FBQ3JCLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHO0tBQzFELENBQUM7SUFFRixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBRSxHQUFXLEVBQUUsWUFBMEI7UUFDdEQsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM5QixNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDcEIsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLEdB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LEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBQyxNQUFNLEVBQUMsRUFBRSxFQUFFO1lBQ2xFLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNYLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLHlDQUF5QyxDQUFDLENBQUM7WUFDcEUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsYUFBYSxDQUFDLENBQUMsT0FBTyxLQUFLLENBQUMsQ0FBQztRQUMxRCxDQUFDLENBQUMsQ0FBQztRQUNILFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFNUIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7VXRpbHN9IGZyb20gXCIuL3V0aWxzLmpzXCI7XG5pbXBvcnQgYXNzZXJ0LCB7QXNzZXJ0aW9uRXJyb3J9IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCB7V3JpdGVTdHJlYW1zfSBmcm9tIFwiLi93cml0ZS1zdHJlYW1zLmpzXCI7XG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5cbmV4cG9ydCB0eXBlIEdpdFNjaGVtYSA9IFwiZ2l0XCIgfCBcImh0dHBcIiB8IFwiaHR0cHNcIiB8IFwic3NoXCI7XG5cbmV4cG9ydCBjbGFzcyBHaXREYXRhIHtcblxuICAgIHB1YmxpYyByZWFkb25seSB1c2VyID0ge1xuICAgICAgICBHSVRMQUJfVVNFUl9MT0dJTjogXCJsb2NhbFwiLFxuICAgICAgICBHSVRMQUJfVVNFUl9FTUFJTDogXCJsb2NhbEBnaXRsYWIuY29tXCIsXG4gICAgICAgIEdJVExBQl9VU0VSX05BTUU6IFwiQm9iIExvY2FsXCIsXG4gICAgICAgIEdJVExBQl9VU0VSX0lEOiBcIjEwMDBcIixcbiAgICB9O1xuXG4gICAgcHVibGljIHJlYWRvbmx5IGJyYW5jaGVzID0ge1xuICAgICAgICBkZWZhdWx0OiBcIm1haW5cIixcbiAgICB9O1xuXG4gICAgcHVibGljIHJlYWRvbmx5IHJlbW90ZSA9IHtcbiAgICAgICAgc2NoZW1hOiBcImdpdFwiIGFzIEdpdFNjaGVtYSxcbiAgICAgICAgcG9ydDogXCIyMlwiLFxuICAgICAgICBob3N0OiBcImdpdGxhYi5jb21cIixcbiAgICAgICAgZ3JvdXA6IFwiZmFsbGJhY2suZ3JvdXBcIixcbiAgICAgICAgcHJvamVjdDogXCJmYWxsYmFjay5wcm9qZWN0XCIsXG4gICAgfTtcblxuICAgIHB1YmxpYyByZWFkb25seSBjb21taXQgPSB7XG4gICAgICAgIFJFRl9OQU1FOiBcIm1haW5cIixcbiAgICAgICAgU0hBOiBcIjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBcIixcbiAgICAgICAgU0hPUlRfU0hBOiBcIjAwMDAwMDAwXCIsXG4gICAgICAgIFRJTUVTVEFNUDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLnNwbGl0KFwiLlwiKVswXSArIFwiWlwiLFxuICAgIH07XG5cbiAgICBzdGF0aWMgYXN5bmMgaW5pdCAoY3dkOiBzdHJpbmcsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKTogUHJvbWlzZTxHaXREYXRhPiB7XG4gICAgICAgIGNvbnN0IGdpdERhdGEgPSBuZXcgR2l0RGF0YSgpO1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgICAgICBwcm9taXNlcy5wdXNoKGdpdERhdGEuaW5pdENvbW1pdERhdGEoY3dkLCB3cml0ZVN0cmVhbXMpKTtcbiAgICAgICAgcHJvbWlzZXMucHVzaChnaXREYXRhLmluaXRSZW1vdGVEYXRhKGN3ZCwgd3JpdGVTdHJlYW1zKSk7XG4gICAgICAgIHByb21pc2VzLnB1c2goZ2l0RGF0YS5pbml0VXNlckRhdGEoY3dkLCB3cml0ZVN0cmVhbXMpKTtcbiAgICAgICAgcHJvbWlzZXMucHVzaChnaXREYXRhLmluaXRCcmFuY2hEYXRhKGN3ZCwgd3JpdGVTdHJlYW1zKSk7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgICAgcmV0dXJuIGdpdERhdGE7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBpbml0Q29tbWl0RGF0YSAoY3dkOiBzdHJpbmcsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG5cbiAgICAgICAgY29uc3QgcmVmTmFtZVByb21pc2UgPSBVdGlscy5zcGF3bihbXCJnaXRcIiwgXCJyZXYtcGFyc2VcIiwgXCItLWFiYnJldi1yZWZcIiwgXCJIRUFEXCJdLCBjd2QpO1xuICAgICAgICBwcm9taXNlcy5wdXNoKHJlZk5hbWVQcm9taXNlLnRoZW4oKHtzdGRvdXR9KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbW1pdC5SRUZfTkFNRSA9IHN0ZG91dC50cmltRW5kKCk7XG4gICAgICAgIH0pKTtcblxuICAgICAgICBjb25zdCBzaGFQcm9taXNlID0gVXRpbHMuc3Bhd24oW1wiZ2l0XCIsIFwicmV2LXBhcnNlXCIsIFwiSEVBRFwiXSwgY3dkKTtcbiAgICAgICAgcHJvbWlzZXMucHVzaChzaGFQcm9taXNlLnRoZW4oKHtzdGRvdXR9KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbW1pdC5TSEEgPSBzdGRvdXQudHJpbUVuZCgpO1xuICAgICAgICB9KSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIEFzc2VydGlvbkVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtge3llbGxvdyAke2UubWVzc2FnZX19XFxuYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3RkZXJyKGNoYWxrYHt5ZWxsb3cgVXNpbmcgZmFsbGJhY2sgZ2l0IGNvbW1pdCBkYXRhfVxcbmApO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93ICAgJHtlLm1lc3NhZ2V9XFxufWApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBpbml0QnJhbmNoRGF0YSAoY3dkOiBzdHJpbmcsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB7c3Rkb3V0OiBnaXRSZW1vdGVEZWZhdWx0QnJhbmNofSA9IGF3YWl0IFV0aWxzLnNwYXduKFtcImdpdFwiLCBcInN5bWJvbGljLXJlZlwiLCBcIi0tc2hvcnRcIiwgXCJyZWZzL3JlbW90ZXMvb3JpZ2luL0hFQURcIl0sIGN3ZCk7XG4gICAgICAgICAgICB0aGlzLmJyYW5jaGVzLmRlZmF1bHQgPSBnaXRSZW1vdGVEZWZhdWx0QnJhbmNoLnJlcGxhY2UoXCJvcmlnaW4vXCIsIFwiXCIpO1xuICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgIGlmIChlLnN0ZGVyciA9PT0gXCJmYXRhbDogcmVmIHJlZnMvcmVtb3Rlcy9vcmlnaW4vSEVBRCBpcyBub3QgYSBzeW1ib2xpYyByZWZcIikge1xuICAgICAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtge3llbGxvdyBVbmFibGUgdG8gcmV0cmlldmUgZGVmYXVsdCByZW1vdGUgYnJhbmNoLCBmYWxsaW5nIGJhY2sgdG8gXFxgJHt0aGlzLmJyYW5jaGVzLmRlZmF1bHR9XFxgLiBUaGUgZGVmYXVsdCByZW1vdGUgYnJhbmNoIGNhbiBiZSBzZXQgdmlhIFxcYGdpdCByZW1vdGUgc2V0LWhlYWQgb3JpZ2luIDxkZWZhdWx0X2JyYW5jaD5cXGBcXG59YCk7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93ICAgJHtlLm1lc3NhZ2V9XFxufWApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3RkZXJyKGNoYWxrYHt5ZWxsb3cgVW5hYmxlIHRvIHJldHJpZXZlIGRlZmF1bHQgcmVtb3RlIGJyYW5jaCwgZmFsbGluZyBiYWNrIHRvIFxcYCR7dGhpcy5icmFuY2hlcy5kZWZhdWx0fVxcYC5cXG59YCk7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93ICAgJHtlLm1lc3NhZ2V9XFxufWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGNoYW5nZWRGaWxlcyAoZGVmYXVsdEJyYW5jaDogc3RyaW5nLCBjd2Q6IHN0cmluZykge1xuICAgICAgICByZXR1cm4gVXRpbHMuc3luY1NwYXduKFtcImdpdFwiLCBcImRpZmZcIiwgXCItLW5hbWUtb25seVwiLCBkZWZhdWx0QnJhbmNoXSwgY3dkKS5zdGRvdXQuc3BsaXQoXCJcXG5cIik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBpbml0UmVtb3RlRGF0YSAoY3dkOiBzdHJpbmcsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsZXQgZ2l0UmVtb3RlTWF0Y2g7XG4gICAgICAgICAgICBsZXQgZ2l0UmVtb3RlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAvLyBOT1RFOiBGb3IgcG93ZXIgdXNlciB0aGF0IHdpc2hlcyB0byBjdXN0b21pemUgdGhlIHJlbW90ZSB1cmxcbiAgICAgICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBVdGlscy5zcGF3bihbXCJnaXRcIiwgXCJyZW1vdGVcIiwgXCJnZXQtdXJsXCIsIFwiZ2NsLW9yaWdpblwiXSwgY3dkKTtcbiAgICAgICAgICAgICAgICBnaXRSZW1vdGUgPSByZXMuc3Rkb3V0O1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgVXRpbHMuc3Bhd24oW1wiZ2l0XCIsIFwicmVtb3RlXCIsIFwiZ2V0LXVybFwiLCBcIm9yaWdpblwiXSwgY3dkKTtcbiAgICAgICAgICAgICAgICBnaXRSZW1vdGUgPSByZXMuc3Rkb3V0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUbyBzaW1wbGlmeSB0aGUgcmVnZXguIFN0cmlwcGluZyB0aGUgdHJhaWxpbmcgYC9gIG9yIGAuZ2l0YCBzaW5jZSB0aGV5J3JlIGJvdGggb3B0aW9uYWwuXG4gICAgICAgICAgICBjb25zdCBub3JtYWxpemVkR2l0UmVtb3RlID0gZ2l0UmVtb3RlXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcLyQvLCBcIlwiKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXC5naXQkLywgXCJcIik7XG5cbiAgICAgICAgICAgIGlmIChub3JtYWxpemVkR2l0UmVtb3RlLnN0YXJ0c1dpdGgoXCJodHRwXCIpKSB7XG4gICAgICAgICAgICAgICAgZ2l0UmVtb3RlTWF0Y2ggPSAvKD88c2NoZW1hPmh0dHBzPyk6XFwvXFwvKD86KFteOl0rKTooW15AXSspQCk/KD88aG9zdD5bXi86XSspOj8oPzxwb3J0PlxcZCspP1xcLyg/PGdyb3VwPlxcUyspXFwvKD88cHJvamVjdD5cXFMrKS8uZXhlYyhub3JtYWxpemVkR2l0UmVtb3RlKTsgLy8gcmVnZXhyLmNvbS83dmU4bFxuICAgICAgICAgICAgICAgIGFzc2VydChnaXRSZW1vdGVNYXRjaD8uZ3JvdXBzICE9IG51bGwsIFwiZ2l0IHJlbW90ZSBnZXQtdXJsIG9yaWdpbiBkaWRuJ3QgcHJvdmlkZSB2YWxpZCBtYXRjaGVzXCIpO1xuXG4gICAgICAgICAgICAgICAgbGV0IHBvcnQgPSBcIjQ0M1wiO1xuICAgICAgICAgICAgICAgIGlmIChnaXRSZW1vdGVNYXRjaC5ncm91cHMuc2NoZW1hID09PSBcImh0dHBzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9ydCA9IGdpdFJlbW90ZU1hdGNoLmdyb3Vwcy5wb3J0ID8/IFwiNDQzXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChnaXRSZW1vdGVNYXRjaC5ncm91cHMuc2NoZW1hID09PSBcImh0dHBcIikge1xuICAgICAgICAgICAgICAgICAgICBwb3J0ID0gZ2l0UmVtb3RlTWF0Y2guZ3JvdXBzLnBvcnQgPz8gXCI4MFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZS5ob3N0ID0gZ2l0UmVtb3RlTWF0Y2guZ3JvdXBzLmhvc3Q7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGUuZ3JvdXAgPSBnaXRSZW1vdGVNYXRjaC5ncm91cHMuZ3JvdXA7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGUucHJvamVjdCA9IGdpdFJlbW90ZU1hdGNoLmdyb3Vwcy5wcm9qZWN0O1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlLnNjaGVtYSA9IGdpdFJlbW90ZU1hdGNoLmdyb3Vwcy5zY2hlbWEgYXMgR2l0U2NoZW1hO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlLnBvcnQgPSBwb3J0O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChub3JtYWxpemVkR2l0UmVtb3RlLnN0YXJ0c1dpdGgoXCJzc2g6Ly9cIikpIHtcbiAgICAgICAgICAgICAgICBnaXRSZW1vdGVNYXRjaCA9IC8oPzxzY2hlbWE+c3NoKTpcXC9cXC8oXFx3KylAKD88aG9zdD5bXi86XSspOj8oPzxwb3J0PlxcZCspP1xcLyg/PGdyb3VwPlxcUyspXFwvKD88cHJvamVjdD5cXFMrKS8uZXhlYyhub3JtYWxpemVkR2l0UmVtb3RlKTsgLy8gcmVnZXhyLmNvbS83dmpxNFxuICAgICAgICAgICAgICAgIGFzc2VydChnaXRSZW1vdGVNYXRjaD8uZ3JvdXBzICE9IG51bGwsIFwiZ2l0IHJlbW90ZSBnZXQtdXJsIG9yaWdpbiBkaWRuJ3QgcHJvdmlkZSB2YWxpZCBtYXRjaGVzXCIpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGUuaG9zdCA9IGdpdFJlbW90ZU1hdGNoLmdyb3Vwcy5ob3N0O1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlLmdyb3VwID0gZ2l0UmVtb3RlTWF0Y2guZ3JvdXBzLmdyb3VwO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlLnByb2plY3QgPSBnaXRSZW1vdGVNYXRjaC5ncm91cHMucHJvamVjdDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZS5zY2hlbWEgPSBnaXRSZW1vdGVNYXRjaC5ncm91cHMuc2NoZW1hIGFzIEdpdFNjaGVtYTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZS5wb3J0ID0gZ2l0UmVtb3RlTWF0Y2guZ3JvdXBzLnBvcnQgPz8gXCIyMlwiO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBnaXRSZW1vdGVNYXRjaCA9IC8oPzx1c2VybmFtZT5cXFMrKUAoPzxob3N0PlteOl0rKTooPzxncm91cD5cXFMrKVxcLyg/PHByb2plY3Q+XFxTKykvLmV4ZWMobm9ybWFsaXplZEdpdFJlbW90ZSk7IC8vIHJlZ2V4ci5jb20vN3Zqb3FcbiAgICAgICAgICAgICAgICBhc3NlcnQoZ2l0UmVtb3RlTWF0Y2g/Lmdyb3VwcyAhPSBudWxsLCBcImdpdCByZW1vdGUgZ2V0LXVybCBvcmlnaW4gZGlkbid0IHByb3ZpZGUgdmFsaWQgbWF0Y2hlc1wiKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHtzdGRvdXR9ID0gYXdhaXQgVXRpbHMuc3Bhd24oW1wic3NoXCIsIFwiLUdcIiwgYCR7Z2l0UmVtb3RlTWF0Y2guZ3JvdXBzLnVzZXJuYW1lfUAke2dpdFJlbW90ZU1hdGNoLmdyb3Vwcy5ob3N0fWBdKTtcbiAgICAgICAgICAgICAgICBjb25zdCBwb3J0ID0gc3Rkb3V0LnNwbGl0KFwiXFxuXCIpLmZpbHRlcigobGluZSkgPT4gbGluZS5zdGFydHNXaXRoKFwicG9ydCBcIikpWzBdLnNwbGl0KFwiIFwiKVsxXTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZS5ob3N0ID0gZ2l0UmVtb3RlTWF0Y2guZ3JvdXBzLmhvc3Q7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGUuZ3JvdXAgPSBnaXRSZW1vdGVNYXRjaC5ncm91cHMuZ3JvdXA7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGUucHJvamVjdCA9IGdpdFJlbW90ZU1hdGNoLmdyb3Vwcy5wcm9qZWN0O1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlLnNjaGVtYSA9IFwiZ2l0XCI7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGUucG9ydCA9IHBvcnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBBc3NlcnRpb25FcnJvcikge1xuICAgICAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtge3llbGxvdyAke2UubWVzc2FnZX19XFxuYCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93IFVzaW5nIGZhbGxiYWNrIGdpdCByZW1vdGUgZGF0YX1cXG5gKTtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtge3llbGxvdyAgICR7ZS5tZXNzYWdlfVxcbn1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGluaXRVc2VyRGF0YSAoY3dkOiBzdHJpbmcsIHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG5cbiAgICAgICAgY29uc3QgZ2l0VXNlcm5hbWVQcm9taXNlID0gVXRpbHMuc3Bhd24oW1wiZ2l0XCIsIFwiY29uZmlnXCIsIFwidXNlci5uYW1lXCJdLCBjd2QpLnRoZW4oKHtzdGRvdXR9KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnVzZXIuR0lUTEFCX1VTRVJfTkFNRSA9IHN0ZG91dC50cmltRW5kKCk7XG4gICAgICAgIH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3RkZXJyKGNoYWxrYHt5ZWxsb3cgVXNpbmcgZmFsbGJhY2sgZ2l0IHVzZXIubmFtZX1cXG5gKTtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtge3llbGxvdyAgICR7ZS5tZXNzYWdlfVxcbn1gKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHByb21pc2VzLnB1c2goZ2l0VXNlcm5hbWVQcm9taXNlKTtcblxuICAgICAgICBjb25zdCBnaXRFbWFpbFByb21pc2UgPSBVdGlscy5zcGF3bihbXCJnaXRcIiwgXCJjb25maWdcIiwgXCJ1c2VyLmVtYWlsXCJdLCBjd2QpLnRoZW4oKHtzdGRvdXR9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbWFpbCA9IHN0ZG91dC50cmltRW5kKCk7XG4gICAgICAgICAgICB0aGlzLnVzZXIuR0lUTEFCX1VTRVJfRU1BSUwgPSBlbWFpbDtcbiAgICAgICAgICAgIHRoaXMudXNlci5HSVRMQUJfVVNFUl9MT0dJTiA9IGVtYWlsLnJlcGxhY2UoL0AuKi8sIFwiXCIpO1xuICAgICAgICB9KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93IFVzaW5nIGZhbGxiYWNrIGdpdCB1c2VyLmVtYWlsfVxcbmApO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93ICAgJHtlLm1lc3NhZ2V9XFxufWApO1xuICAgICAgICB9KTtcbiAgICAgICAgcHJvbWlzZXMucHVzaChnaXRFbWFpbFByb21pc2UpO1xuXG4gICAgICAgIGNvbnN0IG9zVWlkUHJvbWlzZSA9IFV0aWxzLnNwYXduKFtcImlkXCIsIFwiLXVcIl0sIGN3ZCkudGhlbigoe3N0ZG91dH0pID0+IHtcbiAgICAgICAgICAgIHRoaXMudXNlci5HSVRMQUJfVVNFUl9JRCA9IHN0ZG91dC50cmltRW5kKCk7XG4gICAgICAgIH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3RkZXJyKGNoYWxrYHt5ZWxsb3cgVXNpbmcgZmFsbGJhY2sgbGludXggdXNlciBpZH1cXG5gKTtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtge3llbGxvdyAgICR7ZS5tZXNzYWdlfVxcbn1gKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHByb21pc2VzLnB1c2gob3NVaWRQcm9taXNlKTtcblxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgfVxufVxuIl19