From 388f79066dc2a9c8e0dc5f9cf078910ae2522105 Mon Sep 17 00:00:00 2001 From: Stuart Leeks Date: Thu, 24 Jun 2021 07:02:25 +0100 Subject: [PATCH 1/5] Initial UID/GID update --- .github/workflows/test.yml | 2 +- azdo-task/DevContainerBuildRun/.eslintrc.json | 2 +- .../DevContainerBuildRun/dist/docker.d.ts | 10 +- azdo-task/DevContainerBuildRun/dist/exec.d.ts | 10 +- azdo-task/DevContainerBuildRun/dist/index.js | 218 ++++++++++++++++-- .../DevContainerBuildRun/dist/index.js.map | 2 +- .../DevContainerBuildRun/dist/users.d.ts | 13 ++ azdo-task/DevContainerBuildRun/lib/exec.js | 33 ++- .../DevContainerBuildRun/package-lock.json | 6 +- azdo-task/DevContainerBuildRun/package.json | 2 +- azdo-task/DevContainerBuildRun/src/docker.ts | 4 +- azdo-task/DevContainerBuildRun/src/exec.ts | 51 +++- azdo-task/LICENSE.md | 22 ++ azdo-task/README.md | 177 ++++++++++++++ azdo-task/scripts/build-package.sh | 1 + common/__tests__/users.test.ts | 35 +++ common/src/docker.ts | 124 ++++++++-- common/src/exec.ts | 10 +- common/src/users.ts | 45 ++++ common_lib/docker.d.ts | 2 +- common_lib/docker.js | 101 ++++++-- common_lib/exec.d.ts | 10 +- common_lib/users.d.ts | 13 ++ common_lib/users.js | 33 +++ github-action/dist/docker.d.ts | 2 +- github-action/dist/exec.d.ts | 10 +- github-action/dist/index.js | 173 ++++++++++---- github-action/dist/index.js.map | 2 +- github-action/dist/users.d.ts | 13 ++ github-action/lib/docker.js | 7 +- github-action/lib/exec.js | 26 +-- github-action/lib/main.js | 5 +- github-action/src/docker.ts | 11 +- github-action/src/exec.ts | 30 +-- github-action/src/main.ts | 5 +- scripts/ci.sh | 8 +- 36 files changed, 1051 insertions(+), 167 deletions(-) create mode 100644 azdo-task/DevContainerBuildRun/dist/users.d.ts create mode 100644 azdo-task/LICENSE.md create mode 100644 azdo-task/README.md create mode 100644 common/__tests__/users.test.ts create mode 100644 common/src/users.ts create mode 100644 common_lib/users.d.ts create mode 100644 common_lib/users.js create mode 100644 github-action/dist/users.d.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7bdad9c1..d0ac21f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -102,7 +102,7 @@ jobs: VERSION_SHORT: v${{ steps.build.outputs.version_short }} run: | echo "VERSION_SHORT: $VERSION_SHORT" - sudo chown -R $(whoami) . + # sudo chown -R $(whoami) . git config user.name "CI build" git config user.email stuart@leeks.net git tag -fa $VERSION_SHORT -m $VERSION_SHORT diff --git a/azdo-task/DevContainerBuildRun/.eslintrc.json b/azdo-task/DevContainerBuildRun/.eslintrc.json index 74a16ef4..d162fb7b 100644 --- a/azdo-task/DevContainerBuildRun/.eslintrc.json +++ b/azdo-task/DevContainerBuildRun/.eslintrc.json @@ -23,7 +23,7 @@ "@typescript-eslint/func-call-spacing": ["error", "never"], "@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-empty-interface": "error", - "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-extraneous-class": "error", "@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-inferrable-types": "error", diff --git a/azdo-task/DevContainerBuildRun/dist/docker.d.ts b/azdo-task/DevContainerBuildRun/dist/docker.d.ts index e3e1cf84..d4591eca 100644 --- a/azdo-task/DevContainerBuildRun/dist/docker.d.ts +++ b/azdo-task/DevContainerBuildRun/dist/docker.d.ts @@ -1,5 +1,11 @@ import { ExecFunction } from './exec'; export declare function isDockerBuildXInstalled(exec: ExecFunction): Promise; -export declare function buildImage(exec: ExecFunction, imageName: string, checkoutPath: string, subFolder: string): Promise; -export declare function runContainer(exec: ExecFunction, imageName: string, checkoutPath: string, subFolder: string, command: string, envs?: string[]): Promise; +export declare function buildImage(exec: ExecFunction, imageName: string, checkoutPath: string, subFolder: string): Promise; +export declare function runContainer(exec: ExecFunction, imageName: string, checkoutPath: string, subFolder: string, command: string, envs?: string[], mounts?: string[]): Promise; export declare function pushImage(exec: ExecFunction, imageName: string): Promise; +export interface DockerMount { + type: string; + source: string; + target: string; +} +export declare function parseMount(mountString: string): DockerMount; diff --git a/azdo-task/DevContainerBuildRun/dist/exec.d.ts b/azdo-task/DevContainerBuildRun/dist/exec.d.ts index af6505d5..444b472c 100644 --- a/azdo-task/DevContainerBuildRun/dist/exec.d.ts +++ b/azdo-task/DevContainerBuildRun/dist/exec.d.ts @@ -1 +1,9 @@ -export declare type ExecFunction = (command: string, args: string[]) => Promise; +export interface ExecResult { + exitCode: number; + stdout: string; + stderr: string; +} +export interface ExecOptions { + silent?: boolean; +} +export declare type ExecFunction = (command: string, args: string[], options: ExecOptions) => Promise; diff --git a/azdo-task/DevContainerBuildRun/dist/index.js b/azdo-task/DevContainerBuildRun/dist/index.js index 3b78c0fa..fb9a1dbe 100644 --- a/azdo-task/DevContainerBuildRun/dist/index.js +++ b/azdo-task/DevContainerBuildRun/dist/index.js @@ -37,7 +37,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", ({ value: true })); exports.pushImage = exports.runContainer = exports.buildImage = exports.isDockerBuildXInstalled = void 0; const task = __importStar(__nccwpck_require__(347)); -const docker = __importStar(__nccwpck_require__(3872)); +const docker = __importStar(__nccwpck_require__(9340)); const exec_1 = __nccwpck_require__(7757); function isDockerBuildXInstalled() { return __awaiter(this, void 0, void 0, function* () { @@ -127,14 +127,41 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", ({ value: true })); exports.exec = void 0; const task = __importStar(__nccwpck_require__(347)); -function exec(command, args) { +const stream = __importStar(__nccwpck_require__(2413)); +// https://github.com/microsoft/azure-pipelines-task-lib/blob/master/node/docs/azure-pipelines-task-lib.md +/* global BufferEncoding */ +class TeeStream extends stream.Writable { + constructor(teeStream, options) { + super(options); + this.value = ''; + this.teeStream = teeStream; + } + _write(data, encoding, callback) { + this.value += data; + this.teeStream.write(data, encoding); // NOTE - currently ignoring teeStream callback + if (callback) { + callback(); + } + } + toString() { + return this.value; + } +} +function exec(command, args, options) { + var _a; return __awaiter(this, void 0, void 0, function* () { + const outStream = new TeeStream(process.stdout); + const errStream = new TeeStream(process.stderr); const exitCode = yield task.exec(command, args, { failOnStdErr: false, - silent: false, + silent: (_a = options.silent) !== null && _a !== void 0 ? _a : false, ignoreReturnCode: true }); - return exitCode; + return { + exitCode, + stdout: outStream.toString(), + stderr: errStream.toString() + }; }); } exports.exec = exec; @@ -12938,7 +12965,7 @@ module.exports = v4; /***/ }), -/***/ 3872: +/***/ 9340: /***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { "use strict"; @@ -12949,6 +12976,7 @@ __nccwpck_require__.r(__webpack_exports__); __nccwpck_require__.d(__webpack_exports__, { "buildImage": () => (/* binding */ buildImage), "isDockerBuildXInstalled": () => (/* binding */ isDockerBuildXInstalled), + "parseMount": () => (/* binding */ parseMount), "pushImage": () => (/* binding */ pushImage), "runContainer": () => (/* binding */ runContainer) }); @@ -13040,6 +13068,36 @@ function getSubstitutionValue(regexMatch, placeholder) { return regexMatch; } +;// CONCATENATED MODULE: ../../common/src/users.ts +function parsePasswd(input) { + const result = []; + const lines = input.split('\n'); + for (const line of lines) { + const parts = line.split(':'); + const user = { + name: parts[0], + uid: parts[2], + gid: parts[3] + }; + result.push(user); + } + return result; +} +function parseGroup(input) { + const result = []; + const lines = input.split('\n'); + for (const line of lines) { + const parts = line.split(':'); + const group = { + name: parts[0], + gid: parts[2], + users: parts[3] ? parts[3].split(',') : [] + }; + result.push(group); + } + return result; +} + ;// CONCATENATED MODULE: ../../common/src/docker.ts var docker_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } @@ -13054,18 +13112,30 @@ var docker_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _a + + function isDockerBuildXInstalled(exec) { return docker_awaiter(this, void 0, void 0, function* () { - const exitCode = yield exec('docker', ['buildx', '--help']); + const { exitCode } = yield exec('docker', ['buildx', '--help'], { silent: true }); return exitCode === 0; }); } function buildImage(exec, imageName, checkoutPath, subFolder) { - var _a, _b; return docker_awaiter(this, void 0, void 0, function* () { const folder = external_path_default().join(checkoutPath, subFolder); const devcontainerJsonPath = external_path_default().join(folder, '.devcontainer/devcontainer.json'); const devcontainerConfig = yield loadFromFile(devcontainerJsonPath); + // build the image from the .devcontainer spec + yield buildImageBase(exec, imageName, folder, devcontainerConfig); + if (!devcontainerConfig.remoteUser) { + return imageName; + } + return yield ensureHostAndContainerUsersAlign(exec, imageName, devcontainerConfig); + }); +} +function buildImageBase(exec, imageName, folder, devcontainerConfig) { + var _a, _b; + return docker_awaiter(this, void 0, void 0, function* () { const configDockerfile = getDockerfile(devcontainerConfig); if (!configDockerfile) { throw new Error('dockerfile not set in devcontainer.json - devcontainer-build-run currently only supports Dockerfile-based dev containers'); @@ -13091,7 +13161,7 @@ function buildImage(exec, imageName, checkoutPath, subFolder) { // TODO - add abstraction to allow startGroup on GH actions // core.startGroup('🏗 Building dev container...') try { - const exitCode = yield exec('docker', args); + const { exitCode } = yield exec('docker', args, {}); if (exitCode !== 0) { throw new Error(`build failed with ${exitCode}`); } @@ -13101,7 +13171,69 @@ function buildImage(exec, imageName, checkoutPath, subFolder) { } }); } -function runContainer(exec, imageName, checkoutPath, subFolder, command, envs) { +// returns the name of the image to run in the next step +function ensureHostAndContainerUsersAlign(exec, imageName, devcontainerConfig) { + return docker_awaiter(this, void 0, void 0, function* () { + console.log("***HELLO***"); + if (!devcontainerConfig.remoteUser) { + return imageName; + } + const resultHostUser = yield exec('/bin/sh', ['-c', 'id -u -n'], { silent: true }); + if (resultHostUser.exitCode !== 0) { + throw new Error(`Failed to get host user (exitcode: ${resultHostUser.exitCode}):${resultHostUser.stdout}\n${resultHostUser.stderr}`); + } + const resultHostPasswd = yield exec('/bin/sh', ['-c', "cat /etc/passwd"], { silent: true }); + if (resultHostPasswd.exitCode !== 0) { + throw new Error(`Failed to get host user info (exitcode: ${resultHostPasswd.exitCode}):${resultHostPasswd.stdout}\n${resultHostPasswd.stderr}`); + } + // const resultHostGroup = await exec('sh', ['-c', "cat /etc/group"], {silent: true}) + // if (resultHostGroup.exitCode !== 0) { + // throw new Error("Failed to get host group info") + // } + const resultContainerPasswd = yield exec('docker', ['run', '--rm', imageName, 'sh', '-c', "cat /etc/passwd"], { silent: true }); + if (resultContainerPasswd.exitCode !== 0) { + throw new Error("Failed to get container user info"); + } + const resultContainerGroup = yield exec('docker', ['run', '--rm', imageName, 'sh', '-c', "cat /etc/group"], { silent: true }); + if (resultContainerGroup.exitCode !== 0) { + throw new Error("Failed to get container group info"); + } + const hostUserName = resultHostUser.stdout.trim(); + const hostUsers = parsePasswd(resultHostPasswd.stdout); + // const hostGroups = parseGroup(resultHostGroup.stdout) + const hostUser = hostUsers.find(u => u.name === hostUserName); + if (!hostUser) + throw new Error(`Failed to find host user in host info. (hostUserName='${hostUserName}')`); + const containerUserName = devcontainerConfig.remoteUser; + const containerUsers = parsePasswd(resultContainerPasswd.stdout); + const containerGroups = parseGroup(resultContainerGroup.stdout); + const containerUser = containerUsers.find(u => u.name === containerUserName); + if (!containerUser) + throw new Error("Failed to get container user info"); + const existingContainerUserGroup = containerGroups.find(g => g.gid == hostUser.gid); + if (existingContainerUserGroup) + throw new Error(`Host user GID (${hostUser.gid}) already exists as a group in the container`); + const containerUserAligned = hostUser.uid === containerUser.uid && hostUser.gid == containerUser.gid; + if (containerUserAligned) { + // all good - nothing to do + return imageName; + } + // Generate a Dockerfile to run to build a derived image with the UID/GID updated + const dockerfileContent = `FROM ${imageName} +RUN sudo sed -i /etc/passwd -e s/${containerUser.name}:x:${containerUser.uid}:${containerUser.gid}/${containerUser.name}:x:${hostUser.uid}:${hostUser.gid}/ +`; + const tempDir = external_fs_.mkdtempSync("devcontainer-build-run"); + const derivedDockerfilePath = external_path_default().join(tempDir, "Dockerfile"); + external_fs_.writeFileSync(derivedDockerfilePath, dockerfileContent); + const derivedImageName = `${imageName}-userfix`; + const derivedDockerBuid = yield exec('docker', ['buildx', 'build', '--tag', derivedImageName, '-f', derivedDockerfilePath, tempDir, '--output=type=docker'], {}); + if (derivedDockerBuid.exitCode !== 0) { + throw new Error("Failed to build derived Docker image with users updated"); + } + return derivedImageName; + }); +} +function runContainer(exec, imageName, checkoutPath, subFolder, command, envs, mounts) { return docker_awaiter(this, void 0, void 0, function* () { const checkoutPathAbsolute = getAbsolutePath(checkoutPath, process.cwd()); const folder = external_path_default().join(checkoutPathAbsolute, subFolder); @@ -13111,11 +13243,26 @@ function runContainer(exec, imageName, checkoutPath, subFolder, command, envs) { const remoteUser = getRemoteUser(devcontainerConfig); const args = ['run']; args.push('--mount', `type=bind,src=${checkoutPathAbsolute},dst=${workspaceFolder}`); + if (devcontainerConfig.mounts) { + devcontainerConfig.mounts + .map(m => substituteValues(m)) + .forEach(m => { + const mount = parseMount(m); + if (mount.type === "bind") { + // check path exists + if (!external_fs_.existsSync(mount.source)) { + console.log(`Skipping mount as source does not exist: '${m}'`); + return; + } + } + args.push('--mount', m); + }); + } args.push('--workdir', workspaceFolder); args.push('--user', remoteUser); if (devcontainerConfig.runArgs) { - const subtitutedRunArgs = devcontainerConfig.runArgs.map(a => substituteValues(a)); - args.push(...subtitutedRunArgs); + const substitutedRunArgs = devcontainerConfig.runArgs.map(a => substituteValues(a)); + args.push(...substitutedRunArgs); } if (envs) { for (const env of envs) { @@ -13123,10 +13270,11 @@ function runContainer(exec, imageName, checkoutPath, subFolder, command, envs) { } } args.push(`${imageName}:latest`); - args.push('bash', '-c', `sudo chown -R $(whoami) . && ${command}`); // TODO sort out permissions/user alignment + // args.push('bash', '-c', `sudo chown -R $(whoami) . && ${command}`) // TODO sort out permissions/user alignment + args.push('bash', '-c', command); // TODO sort out permissions/user alignment // core.startGroup('🏃‍♀️ Running dev container...') try { - const exitCode = yield exec('docker', args); + const { exitCode } = yield exec('docker', args, {}); if (exitCode !== 0) { throw new Error(`run failed with ${exitCode}`); } @@ -13142,7 +13290,7 @@ function pushImage(exec, imageName) { args.push(`${imageName}:latest`); // core.startGroup('Pushing image...') try { - const exitCode = yield exec('docker', args); + const { exitCode } = yield exec('docker', args, {}); if (exitCode !== 0) { throw new Error(`push failed with ${exitCode}`); } @@ -13152,6 +13300,40 @@ function pushImage(exec, imageName) { } }); } +function parseMount(mountString) { + // https://docs.docker.com/engine/reference/commandline/service_create/#add-bind-mounts-volumes-or-memory-filesystems + // examples: + // type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock + // src=home-cache,target=/home/vscode/.cache + let type = ''; + let source = ''; + let target = ''; + const options = mountString.split(','); + for (const option of options) { + const parts = option.split('='); + switch (parts[0]) { + case 'type': + type = parts[1]; + break; + case 'src': + case 'source': + source = parts[1]; + break; + case 'dst': + case 'destination': + case 'target': + target = parts[1]; + break; + case 'readonly': + case 'ro': + // ignore + break; + default: + throw new Error(`Unhandled mount option '${parts[0]}'`); + } + } + return { type, source, target }; +} /***/ }), @@ -13204,6 +13386,14 @@ module.exports = require("path");; /***/ }), +/***/ 2413: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream");; + +/***/ }), + /***/ 1669: /***/ ((module) => { diff --git a/azdo-task/DevContainerBuildRun/dist/index.js.map b/azdo-task/DevContainerBuildRun/dist/index.js.map index 0ca3b7ce..12611d7c 100644 --- a/azdo-task/DevContainerBuildRun/dist/index.js.map +++ b/azdo-task/DevContainerBuildRun/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../webpack://devcontainer-build-run/./lib/docker.js","../webpack://devcontainer-build-run/./lib/exec.js","../webpack://devcontainer-build-run/./lib/main.js","../webpack://devcontainer-build-run/./node_modules/azure-pipelines-task-lib/internal.js","../webpack://devcontainer-build-run/./node_modules/azure-pipelines-task-lib/node_modules/semver/semver.js","../webpack://devcontainer-build-run/./node_modules/azure-pipelines-task-lib/task.js","../webpack://devcontainer-build-run/./node_modules/azure-pipelines-task-lib/taskcommand.js","../webpack://devcontainer-build-run/./node_modules/azure-pipelines-task-lib/toolrunner.js","../webpack://devcontainer-build-run/./node_modules/azure-pipelines-task-lib/vault.js","../webpack://devcontainer-build-run/./node_modules/balanced-match/index.js","../webpack://devcontainer-build-run/./node_modules/brace-expansion/index.js","../webpack://devcontainer-build-run/./node_modules/concat-map/index.js","../webpack://devcontainer-build-run/./node_modules/minimatch/minimatch.js","../webpack://devcontainer-build-run/./node_modules/q/q.js","../webpack://devcontainer-build-run/./node_modules/shelljs/shell.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/cat.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/cd.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/chmod.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/common.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/cp.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/dirs.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/echo.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/error.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/exec.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/find.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/grep.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/ln.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/ls.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/mkdir.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/mv.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/pwd.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/rm.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/sed.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/tempdir.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/test.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/to.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/toEnd.js","../webpack://devcontainer-build-run/./node_modules/shelljs/src/which.js","../webpack://devcontainer-build-run/./node_modules/uuid/lib/bytesToUuid.js","../webpack://devcontainer-build-run/./node_modules/uuid/lib/rng.js","../webpack://devcontainer-build-run/./node_modules/uuid/v4.js","../webpack://devcontainer-build-run/../../common/node_modules/jsonc-parser/lib/umd/impl/edit.js","../webpack://devcontainer-build-run/../../common/node_modules/jsonc-parser/lib/umd/impl/format.js","../webpack://devcontainer-build-run/../../common/node_modules/jsonc-parser/lib/umd/impl/parser.js","../webpack://devcontainer-build-run/../../common/node_modules/jsonc-parser/lib/umd/impl/scanner.js","../webpack://devcontainer-build-run/../../common/node_modules/jsonc-parser/lib/umd/main.js","../webpack://devcontainer-build-run/../../common/src/config.ts","../webpack://devcontainer-build-run/../../common/src/file.ts","../webpack://devcontainer-build-run/../../common/src/envvars.ts","../webpack://devcontainer-build-run/../../common/src/docker.ts","../webpack://devcontainer-build-run/external \"child_process\"","../webpack://devcontainer-build-run/external \"crypto\"","../webpack://devcontainer-build-run/external \"events\"","../webpack://devcontainer-build-run/external \"fs\"","../webpack://devcontainer-build-run/external \"os\"","../webpack://devcontainer-build-run/external \"path\"","../webpack://devcontainer-build-run/external \"util\"","../webpack://devcontainer-build-run/webpack/bootstrap","../webpack://devcontainer-build-run/webpack/runtime/compat get default export","../webpack://devcontainer-build-run/webpack/runtime/define property getters","../webpack://devcontainer-build-run/webpack/runtime/hasOwnProperty shorthand","../webpack://devcontainer-build-run/webpack/runtime/make namespace object","../webpack://devcontainer-build-run/webpack/runtime/compat","../webpack://devcontainer-build-run/webpack/startup"],"sourcesContent":["\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.pushImage = exports.runContainer = exports.buildImage = exports.isDockerBuildXInstalled = void 0;\nconst task = __importStar(require(\"azure-pipelines-task-lib/task\"));\nconst docker = __importStar(require(\"../../../common/src/docker\"));\nconst exec_1 = require(\"./exec\");\nfunction isDockerBuildXInstalled() {\n return __awaiter(this, void 0, void 0, function* () {\n return yield docker.isDockerBuildXInstalled(exec_1.exec);\n });\n}\nexports.isDockerBuildXInstalled = isDockerBuildXInstalled;\nfunction buildImage(imageName, checkoutPath, subFolder) {\n return __awaiter(this, void 0, void 0, function* () {\n console.log('🏗 Building dev container...');\n try {\n yield docker.buildImage(exec_1.exec, imageName, checkoutPath, subFolder);\n return true;\n }\n catch (error) {\n task.setResult(task.TaskResult.Failed, error);\n return false;\n }\n });\n}\nexports.buildImage = buildImage;\nfunction runContainer(imageName, checkoutPath, subFolder, command, envs) {\n return __awaiter(this, void 0, void 0, function* () {\n console.log('🏃‍♀️ Running dev container...');\n try {\n yield docker.runContainer(exec_1.exec, imageName, checkoutPath, subFolder, command, envs);\n return true;\n }\n catch (error) {\n task.setResult(task.TaskResult.Failed, error);\n return false;\n }\n });\n}\nexports.runContainer = runContainer;\nfunction pushImage(imageName) {\n return __awaiter(this, void 0, void 0, function* () {\n console.log('📌 Pushing image...');\n try {\n yield docker.pushImage(exec_1.exec, imageName);\n return true;\n }\n catch (error) {\n task.setResult(task.TaskResult.Failed, error);\n return false;\n }\n });\n}\nexports.pushImage = pushImage;\n","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.exec = void 0;\nconst task = __importStar(require(\"azure-pipelines-task-lib/task\"));\nfunction exec(command, args) {\n return __awaiter(this, void 0, void 0, function* () {\n const exitCode = yield task.exec(command, args, {\n failOnStdErr: false,\n silent: false,\n ignoreReturnCode: true\n });\n return exitCode;\n });\n}\nexports.exec = exec;\n","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst task = __importStar(require(\"azure-pipelines-task-lib/task\"));\nconst docker_1 = require(\"./docker\");\nfunction run() {\n return __awaiter(this, void 0, void 0, function* () {\n console.log('DevContainerBuildRun starting...');\n const hasRunMain = task.getTaskVariable('hasRunMain');\n if (hasRunMain === 'true') {\n console.log('DevContainerBuildRun running post step...');\n return yield runPost();\n }\n else {\n console.log('DevContainerBuildRun running main step...');\n task.setTaskVariable('hasRunMain', 'true');\n return yield runMain();\n }\n });\n}\nfunction runMain() {\n var _a, _b, _c, _d;\n return __awaiter(this, void 0, void 0, function* () {\n try {\n const buildXInstalled = yield docker_1.isDockerBuildXInstalled();\n if (!buildXInstalled) {\n task.setResult(task.TaskResult.Failed, 'docker buildx not available: add a step to set up with docker/setup-buildx-action');\n return;\n }\n const checkoutPath = (_a = task.getInput('checkoutPath')) !== null && _a !== void 0 ? _a : '';\n const imageName = task.getInput('imageName', true);\n if (!imageName) {\n task.setResult(task.TaskResult.Failed, 'imageName input is required');\n return;\n }\n const subFolder = (_b = task.getInput('subFolder')) !== null && _b !== void 0 ? _b : '.';\n const runCommand = task.getInput('runCmd', true);\n if (!runCommand) {\n task.setResult(task.TaskResult.Failed, 'runCmd input is required');\n return;\n }\n const envs = (_d = (_c = task.getInput('env')) === null || _c === void 0 ? void 0 : _c.split('\\n')) !== null && _d !== void 0 ? _d : [];\n if (!(yield docker_1.buildImage(imageName, checkoutPath, subFolder))) {\n return;\n }\n if (!(yield docker_1.runContainer(imageName, checkoutPath, subFolder, runCommand, envs))) {\n return;\n }\n }\n catch (err) {\n task.setResult(task.TaskResult.Failed, err.message);\n }\n });\n}\nfunction runPost() {\n var _a, _b, _c, _d;\n return __awaiter(this, void 0, void 0, function* () {\n // buildReasonsForPush\n //sourceBranchFilterForPush\n const buildReasonsForPush = (_b = (_a = task.getInput('buildReasonsForPush')) === null || _a === void 0 ? void 0 : _a.split('\\n')) !== null && _b !== void 0 ? _b : [];\n const sourceBranchFilterForPush = (_d = (_c = task.getInput('sourceBranchFilterForPush')) === null || _c === void 0 ? void 0 : _c.split('\\n')) !== null && _d !== void 0 ? _d : [];\n // check build reason is allowed\n const buildReason = process.env.BUILD_REASON;\n if (!buildReasonsForPush.some(s => s === buildReason)) {\n console.log(`Image push skipped because buildReason (${buildReason}) is not in buildReasonsForPush`);\n return;\n }\n // check branch is allowed\n const sourceBranch = process.env.BUILD_SOURCEBRANCH;\n if (sourceBranchFilterForPush.length !== 0 && // empty filter allows all\n !sourceBranchFilterForPush.some(s => s === sourceBranch)) {\n console.log(`Image push skipped because source branch (${sourceBranch}) is not in sourceBranchFilterForPush`);\n return;\n }\n const imageName = task.getInput('imageName', true);\n if (!imageName) {\n task.setResult(task.TaskResult.Failed, 'imageName input is required');\n return;\n }\n yield docker_1.pushImage(imageName);\n });\n}\nrun();\n",null,"exports = module.exports = SemVer\n\nvar debug\n/* istanbul ignore next */\nif (typeof process === 'object' &&\n process.env &&\n process.env.NODE_DEBUG &&\n /\\bsemver\\b/i.test(process.env.NODE_DEBUG)) {\n debug = function () {\n var args = Array.prototype.slice.call(arguments, 0)\n args.unshift('SEMVER')\n console.log.apply(console, args)\n }\n} else {\n debug = function () {}\n}\n\n// Note: this is the semver.org version of the spec that it implements\n// Not necessarily the package version of this code.\nexports.SEMVER_SPEC_VERSION = '2.0.0'\n\nvar MAX_LENGTH = 256\nvar MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||\n /* istanbul ignore next */ 9007199254740991\n\n// Max safe segment length for coercion.\nvar MAX_SAFE_COMPONENT_LENGTH = 16\n\n// The actual regexps go on exports.re\nvar re = exports.re = []\nvar src = exports.src = []\nvar R = 0\n\n// The following Regular Expressions can be used for tokenizing,\n// validating, and parsing SemVer version strings.\n\n// ## Numeric Identifier\n// A single `0`, or a non-zero digit followed by zero or more digits.\n\nvar NUMERICIDENTIFIER = R++\nsrc[NUMERICIDENTIFIER] = '0|[1-9]\\\\d*'\nvar NUMERICIDENTIFIERLOOSE = R++\nsrc[NUMERICIDENTIFIERLOOSE] = '[0-9]+'\n\n// ## Non-numeric Identifier\n// Zero or more digits, followed by a letter or hyphen, and then zero or\n// more letters, digits, or hyphens.\n\nvar NONNUMERICIDENTIFIER = R++\nsrc[NONNUMERICIDENTIFIER] = '\\\\d*[a-zA-Z-][a-zA-Z0-9-]*'\n\n// ## Main Version\n// Three dot-separated numeric identifiers.\n\nvar MAINVERSION = R++\nsrc[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\\\.' +\n '(' + src[NUMERICIDENTIFIER] + ')\\\\.' +\n '(' + src[NUMERICIDENTIFIER] + ')'\n\nvar MAINVERSIONLOOSE = R++\nsrc[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\\\.' +\n '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\\\.' +\n '(' + src[NUMERICIDENTIFIERLOOSE] + ')'\n\n// ## Pre-release Version Identifier\n// A numeric identifier, or a non-numeric identifier.\n\nvar PRERELEASEIDENTIFIER = R++\nsrc[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +\n '|' + src[NONNUMERICIDENTIFIER] + ')'\n\nvar PRERELEASEIDENTIFIERLOOSE = R++\nsrc[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +\n '|' + src[NONNUMERICIDENTIFIER] + ')'\n\n// ## Pre-release Version\n// Hyphen, followed by one or more dot-separated pre-release version\n// identifiers.\n\nvar PRERELEASE = R++\nsrc[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +\n '(?:\\\\.' + src[PRERELEASEIDENTIFIER] + ')*))'\n\nvar PRERELEASELOOSE = R++\nsrc[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +\n '(?:\\\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'\n\n// ## Build Metadata Identifier\n// Any combination of digits, letters, or hyphens.\n\nvar BUILDIDENTIFIER = R++\nsrc[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'\n\n// ## Build Metadata\n// Plus sign, followed by one or more period-separated build metadata\n// identifiers.\n\nvar BUILD = R++\nsrc[BUILD] = '(?:\\\\+(' + src[BUILDIDENTIFIER] +\n '(?:\\\\.' + src[BUILDIDENTIFIER] + ')*))'\n\n// ## Full Version String\n// A main version, followed optionally by a pre-release version and\n// build metadata.\n\n// Note that the only major, minor, patch, and pre-release sections of\n// the version string are capturing groups. The build metadata is not a\n// capturing group, because it should not ever be used in version\n// comparison.\n\nvar FULL = R++\nvar FULLPLAIN = 'v?' + src[MAINVERSION] +\n src[PRERELEASE] + '?' +\n src[BUILD] + '?'\n\nsrc[FULL] = '^' + FULLPLAIN + '$'\n\n// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.\n// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty\n// common in the npm registry.\nvar LOOSEPLAIN = '[v=\\\\s]*' + src[MAINVERSIONLOOSE] +\n src[PRERELEASELOOSE] + '?' +\n src[BUILD] + '?'\n\nvar LOOSE = R++\nsrc[LOOSE] = '^' + LOOSEPLAIN + '$'\n\nvar GTLT = R++\nsrc[GTLT] = '((?:<|>)?=?)'\n\n// Something like \"2.*\" or \"1.2.x\".\n// Note that \"x.x\" is a valid xRange identifer, meaning \"any version\"\n// Only the first item is strictly required.\nvar XRANGEIDENTIFIERLOOSE = R++\nsrc[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\\\*'\nvar XRANGEIDENTIFIER = R++\nsrc[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\\\*'\n\nvar XRANGEPLAIN = R++\nsrc[XRANGEPLAIN] = '[v=\\\\s]*(' + src[XRANGEIDENTIFIER] + ')' +\n '(?:\\\\.(' + src[XRANGEIDENTIFIER] + ')' +\n '(?:\\\\.(' + src[XRANGEIDENTIFIER] + ')' +\n '(?:' + src[PRERELEASE] + ')?' +\n src[BUILD] + '?' +\n ')?)?'\n\nvar XRANGEPLAINLOOSE = R++\nsrc[XRANGEPLAINLOOSE] = '[v=\\\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +\n '(?:\\\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +\n '(?:\\\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +\n '(?:' + src[PRERELEASELOOSE] + ')?' +\n src[BUILD] + '?' +\n ')?)?'\n\nvar XRANGE = R++\nsrc[XRANGE] = '^' + src[GTLT] + '\\\\s*' + src[XRANGEPLAIN] + '$'\nvar XRANGELOOSE = R++\nsrc[XRANGELOOSE] = '^' + src[GTLT] + '\\\\s*' + src[XRANGEPLAINLOOSE] + '$'\n\n// Coercion.\n// Extract anything that could conceivably be a part of a valid semver\nvar COERCE = R++\nsrc[COERCE] = '(?:^|[^\\\\d])' +\n '(\\\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' +\n '(?:\\\\.(\\\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +\n '(?:\\\\.(\\\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +\n '(?:$|[^\\\\d])'\n\n// Tilde ranges.\n// Meaning is \"reasonably at or greater than\"\nvar LONETILDE = R++\nsrc[LONETILDE] = '(?:~>?)'\n\nvar TILDETRIM = R++\nsrc[TILDETRIM] = '(\\\\s*)' + src[LONETILDE] + '\\\\s+'\nre[TILDETRIM] = new RegExp(src[TILDETRIM], 'g')\nvar tildeTrimReplace = '$1~'\n\nvar TILDE = R++\nsrc[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'\nvar TILDELOOSE = R++\nsrc[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'\n\n// Caret ranges.\n// Meaning is \"at least and backwards compatible with\"\nvar LONECARET = R++\nsrc[LONECARET] = '(?:\\\\^)'\n\nvar CARETTRIM = R++\nsrc[CARETTRIM] = '(\\\\s*)' + src[LONECARET] + '\\\\s+'\nre[CARETTRIM] = new RegExp(src[CARETTRIM], 'g')\nvar caretTrimReplace = '$1^'\n\nvar CARET = R++\nsrc[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'\nvar CARETLOOSE = R++\nsrc[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'\n\n// A simple gt/lt/eq thing, or just \"\" to indicate \"any version\"\nvar COMPARATORLOOSE = R++\nsrc[COMPARATORLOOSE] = '^' + src[GTLT] + '\\\\s*(' + LOOSEPLAIN + ')$|^$'\nvar COMPARATOR = R++\nsrc[COMPARATOR] = '^' + src[GTLT] + '\\\\s*(' + FULLPLAIN + ')$|^$'\n\n// An expression to strip any whitespace between the gtlt and the thing\n// it modifies, so that `> 1.2.3` ==> `>1.2.3`\nvar COMPARATORTRIM = R++\nsrc[COMPARATORTRIM] = '(\\\\s*)' + src[GTLT] +\n '\\\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'\n\n// this one has to use the /g flag\nre[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g')\nvar comparatorTrimReplace = '$1$2$3'\n\n// Something like `1.2.3 - 1.2.4`\n// Note that these all use the loose form, because they'll be\n// checked against either the strict or loose comparator form\n// later.\nvar HYPHENRANGE = R++\nsrc[HYPHENRANGE] = '^\\\\s*(' + src[XRANGEPLAIN] + ')' +\n '\\\\s+-\\\\s+' +\n '(' + src[XRANGEPLAIN] + ')' +\n '\\\\s*$'\n\nvar HYPHENRANGELOOSE = R++\nsrc[HYPHENRANGELOOSE] = '^\\\\s*(' + src[XRANGEPLAINLOOSE] + ')' +\n '\\\\s+-\\\\s+' +\n '(' + src[XRANGEPLAINLOOSE] + ')' +\n '\\\\s*$'\n\n// Star ranges basically just allow anything at all.\nvar STAR = R++\nsrc[STAR] = '(<|>)?=?\\\\s*\\\\*'\n\n// Compile to actual regexp objects.\n// All are flag-free, unless they were created above with a flag.\nfor (var i = 0; i < R; i++) {\n debug(i, src[i])\n if (!re[i]) {\n re[i] = new RegExp(src[i])\n }\n}\n\nexports.parse = parse\nfunction parse (version, options) {\n if (!options || typeof options !== 'object') {\n options = {\n loose: !!options,\n includePrerelease: false\n }\n }\n\n if (version instanceof SemVer) {\n return version\n }\n\n if (typeof version !== 'string') {\n return null\n }\n\n if (version.length > MAX_LENGTH) {\n return null\n }\n\n var r = options.loose ? re[LOOSE] : re[FULL]\n if (!r.test(version)) {\n return null\n }\n\n try {\n return new SemVer(version, options)\n } catch (er) {\n return null\n }\n}\n\nexports.valid = valid\nfunction valid (version, options) {\n var v = parse(version, options)\n return v ? v.version : null\n}\n\nexports.clean = clean\nfunction clean (version, options) {\n var s = parse(version.trim().replace(/^[=v]+/, ''), options)\n return s ? s.version : null\n}\n\nexports.SemVer = SemVer\n\nfunction SemVer (version, options) {\n if (!options || typeof options !== 'object') {\n options = {\n loose: !!options,\n includePrerelease: false\n }\n }\n if (version instanceof SemVer) {\n if (version.loose === options.loose) {\n return version\n } else {\n version = version.version\n }\n } else if (typeof version !== 'string') {\n throw new TypeError('Invalid Version: ' + version)\n }\n\n if (version.length > MAX_LENGTH) {\n throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters')\n }\n\n if (!(this instanceof SemVer)) {\n return new SemVer(version, options)\n }\n\n debug('SemVer', version, options)\n this.options = options\n this.loose = !!options.loose\n\n var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL])\n\n if (!m) {\n throw new TypeError('Invalid Version: ' + version)\n }\n\n this.raw = version\n\n // these are actually numbers\n this.major = +m[1]\n this.minor = +m[2]\n this.patch = +m[3]\n\n if (this.major > MAX_SAFE_INTEGER || this.major < 0) {\n throw new TypeError('Invalid major version')\n }\n\n if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {\n throw new TypeError('Invalid minor version')\n }\n\n if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {\n throw new TypeError('Invalid patch version')\n }\n\n // numberify any prerelease numeric ids\n if (!m[4]) {\n this.prerelease = []\n } else {\n this.prerelease = m[4].split('.').map(function (id) {\n if (/^[0-9]+$/.test(id)) {\n var num = +id\n if (num >= 0 && num < MAX_SAFE_INTEGER) {\n return num\n }\n }\n return id\n })\n }\n\n this.build = m[5] ? m[5].split('.') : []\n this.format()\n}\n\nSemVer.prototype.format = function () {\n this.version = this.major + '.' + this.minor + '.' + this.patch\n if (this.prerelease.length) {\n this.version += '-' + this.prerelease.join('.')\n }\n return this.version\n}\n\nSemVer.prototype.toString = function () {\n return this.version\n}\n\nSemVer.prototype.compare = function (other) {\n debug('SemVer.compare', this.version, this.options, other)\n if (!(other instanceof SemVer)) {\n other = new SemVer(other, this.options)\n }\n\n return this.compareMain(other) || this.comparePre(other)\n}\n\nSemVer.prototype.compareMain = function (other) {\n if (!(other instanceof SemVer)) {\n other = new SemVer(other, this.options)\n }\n\n return compareIdentifiers(this.major, other.major) ||\n compareIdentifiers(this.minor, other.minor) ||\n compareIdentifiers(this.patch, other.patch)\n}\n\nSemVer.prototype.comparePre = function (other) {\n if (!(other instanceof SemVer)) {\n other = new SemVer(other, this.options)\n }\n\n // NOT having a prerelease is > having one\n if (this.prerelease.length && !other.prerelease.length) {\n return -1\n } else if (!this.prerelease.length && other.prerelease.length) {\n return 1\n } else if (!this.prerelease.length && !other.prerelease.length) {\n return 0\n }\n\n var i = 0\n do {\n var a = this.prerelease[i]\n var b = other.prerelease[i]\n debug('prerelease compare', i, a, b)\n if (a === undefined && b === undefined) {\n return 0\n } else if (b === undefined) {\n return 1\n } else if (a === undefined) {\n return -1\n } else if (a === b) {\n continue\n } else {\n return compareIdentifiers(a, b)\n }\n } while (++i)\n}\n\n// preminor will bump the version up to the next minor release, and immediately\n// down to pre-release. premajor and prepatch work the same way.\nSemVer.prototype.inc = function (release, identifier) {\n switch (release) {\n case 'premajor':\n this.prerelease.length = 0\n this.patch = 0\n this.minor = 0\n this.major++\n this.inc('pre', identifier)\n break\n case 'preminor':\n this.prerelease.length = 0\n this.patch = 0\n this.minor++\n this.inc('pre', identifier)\n break\n case 'prepatch':\n // If this is already a prerelease, it will bump to the next version\n // drop any prereleases that might already exist, since they are not\n // relevant at this point.\n this.prerelease.length = 0\n this.inc('patch', identifier)\n this.inc('pre', identifier)\n break\n // If the input is a non-prerelease version, this acts the same as\n // prepatch.\n case 'prerelease':\n if (this.prerelease.length === 0) {\n this.inc('patch', identifier)\n }\n this.inc('pre', identifier)\n break\n\n case 'major':\n // If this is a pre-major version, bump up to the same major version.\n // Otherwise increment major.\n // 1.0.0-5 bumps to 1.0.0\n // 1.1.0 bumps to 2.0.0\n if (this.minor !== 0 ||\n this.patch !== 0 ||\n this.prerelease.length === 0) {\n this.major++\n }\n this.minor = 0\n this.patch = 0\n this.prerelease = []\n break\n case 'minor':\n // If this is a pre-minor version, bump up to the same minor version.\n // Otherwise increment minor.\n // 1.2.0-5 bumps to 1.2.0\n // 1.2.1 bumps to 1.3.0\n if (this.patch !== 0 || this.prerelease.length === 0) {\n this.minor++\n }\n this.patch = 0\n this.prerelease = []\n break\n case 'patch':\n // If this is not a pre-release version, it will increment the patch.\n // If it is a pre-release it will bump up to the same patch version.\n // 1.2.0-5 patches to 1.2.0\n // 1.2.0 patches to 1.2.1\n if (this.prerelease.length === 0) {\n this.patch++\n }\n this.prerelease = []\n break\n // This probably shouldn't be used publicly.\n // 1.0.0 \"pre\" would become 1.0.0-0 which is the wrong direction.\n case 'pre':\n if (this.prerelease.length === 0) {\n this.prerelease = [0]\n } else {\n var i = this.prerelease.length\n while (--i >= 0) {\n if (typeof this.prerelease[i] === 'number') {\n this.prerelease[i]++\n i = -2\n }\n }\n if (i === -1) {\n // didn't increment anything\n this.prerelease.push(0)\n }\n }\n if (identifier) {\n // 1.2.0-beta.1 bumps to 1.2.0-beta.2,\n // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0\n if (this.prerelease[0] === identifier) {\n if (isNaN(this.prerelease[1])) {\n this.prerelease = [identifier, 0]\n }\n } else {\n this.prerelease = [identifier, 0]\n }\n }\n break\n\n default:\n throw new Error('invalid increment argument: ' + release)\n }\n this.format()\n this.raw = this.version\n return this\n}\n\nexports.inc = inc\nfunction inc (version, release, loose, identifier) {\n if (typeof (loose) === 'string') {\n identifier = loose\n loose = undefined\n }\n\n try {\n return new SemVer(version, loose).inc(release, identifier).version\n } catch (er) {\n return null\n }\n}\n\nexports.diff = diff\nfunction diff (version1, version2) {\n if (eq(version1, version2)) {\n return null\n } else {\n var v1 = parse(version1)\n var v2 = parse(version2)\n var prefix = ''\n if (v1.prerelease.length || v2.prerelease.length) {\n prefix = 'pre'\n var defaultResult = 'prerelease'\n }\n for (var key in v1) {\n if (key === 'major' || key === 'minor' || key === 'patch') {\n if (v1[key] !== v2[key]) {\n return prefix + key\n }\n }\n }\n return defaultResult // may be undefined\n }\n}\n\nexports.compareIdentifiers = compareIdentifiers\n\nvar numeric = /^[0-9]+$/\nfunction compareIdentifiers (a, b) {\n var anum = numeric.test(a)\n var bnum = numeric.test(b)\n\n if (anum && bnum) {\n a = +a\n b = +b\n }\n\n return a === b ? 0\n : (anum && !bnum) ? -1\n : (bnum && !anum) ? 1\n : a < b ? -1\n : 1\n}\n\nexports.rcompareIdentifiers = rcompareIdentifiers\nfunction rcompareIdentifiers (a, b) {\n return compareIdentifiers(b, a)\n}\n\nexports.major = major\nfunction major (a, loose) {\n return new SemVer(a, loose).major\n}\n\nexports.minor = minor\nfunction minor (a, loose) {\n return new SemVer(a, loose).minor\n}\n\nexports.patch = patch\nfunction patch (a, loose) {\n return new SemVer(a, loose).patch\n}\n\nexports.compare = compare\nfunction compare (a, b, loose) {\n return new SemVer(a, loose).compare(new SemVer(b, loose))\n}\n\nexports.compareLoose = compareLoose\nfunction compareLoose (a, b) {\n return compare(a, b, true)\n}\n\nexports.rcompare = rcompare\nfunction rcompare (a, b, loose) {\n return compare(b, a, loose)\n}\n\nexports.sort = sort\nfunction sort (list, loose) {\n return list.sort(function (a, b) {\n return exports.compare(a, b, loose)\n })\n}\n\nexports.rsort = rsort\nfunction rsort (list, loose) {\n return list.sort(function (a, b) {\n return exports.rcompare(a, b, loose)\n })\n}\n\nexports.gt = gt\nfunction gt (a, b, loose) {\n return compare(a, b, loose) > 0\n}\n\nexports.lt = lt\nfunction lt (a, b, loose) {\n return compare(a, b, loose) < 0\n}\n\nexports.eq = eq\nfunction eq (a, b, loose) {\n return compare(a, b, loose) === 0\n}\n\nexports.neq = neq\nfunction neq (a, b, loose) {\n return compare(a, b, loose) !== 0\n}\n\nexports.gte = gte\nfunction gte (a, b, loose) {\n return compare(a, b, loose) >= 0\n}\n\nexports.lte = lte\nfunction lte (a, b, loose) {\n return compare(a, b, loose) <= 0\n}\n\nexports.cmp = cmp\nfunction cmp (a, op, b, loose) {\n switch (op) {\n case '===':\n if (typeof a === 'object')\n a = a.version\n if (typeof b === 'object')\n b = b.version\n return a === b\n\n case '!==':\n if (typeof a === 'object')\n a = a.version\n if (typeof b === 'object')\n b = b.version\n return a !== b\n\n case '':\n case '=':\n case '==':\n return eq(a, b, loose)\n\n case '!=':\n return neq(a, b, loose)\n\n case '>':\n return gt(a, b, loose)\n\n case '>=':\n return gte(a, b, loose)\n\n case '<':\n return lt(a, b, loose)\n\n case '<=':\n return lte(a, b, loose)\n\n default:\n throw new TypeError('Invalid operator: ' + op)\n }\n}\n\nexports.Comparator = Comparator\nfunction Comparator (comp, options) {\n if (!options || typeof options !== 'object') {\n options = {\n loose: !!options,\n includePrerelease: false\n }\n }\n\n if (comp instanceof Comparator) {\n if (comp.loose === !!options.loose) {\n return comp\n } else {\n comp = comp.value\n }\n }\n\n if (!(this instanceof Comparator)) {\n return new Comparator(comp, options)\n }\n\n debug('comparator', comp, options)\n this.options = options\n this.loose = !!options.loose\n this.parse(comp)\n\n if (this.semver === ANY) {\n this.value = ''\n } else {\n this.value = this.operator + this.semver.version\n }\n\n debug('comp', this)\n}\n\nvar ANY = {}\nComparator.prototype.parse = function (comp) {\n var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]\n var m = comp.match(r)\n\n if (!m) {\n throw new TypeError('Invalid comparator: ' + comp)\n }\n\n this.operator = m[1]\n if (this.operator === '=') {\n this.operator = ''\n }\n\n // if it literally is just '>' or '' then allow anything.\n if (!m[2]) {\n this.semver = ANY\n } else {\n this.semver = new SemVer(m[2], this.options.loose)\n }\n}\n\nComparator.prototype.toString = function () {\n return this.value\n}\n\nComparator.prototype.test = function (version) {\n debug('Comparator.test', version, this.options.loose)\n\n if (this.semver === ANY) {\n return true\n }\n\n if (typeof version === 'string') {\n version = new SemVer(version, this.options)\n }\n\n return cmp(version, this.operator, this.semver, this.options)\n}\n\nComparator.prototype.intersects = function (comp, options) {\n if (!(comp instanceof Comparator)) {\n throw new TypeError('a Comparator is required')\n }\n\n if (!options || typeof options !== 'object') {\n options = {\n loose: !!options,\n includePrerelease: false\n }\n }\n\n var rangeTmp\n\n if (this.operator === '') {\n rangeTmp = new Range(comp.value, options)\n return satisfies(this.value, rangeTmp, options)\n } else if (comp.operator === '') {\n rangeTmp = new Range(this.value, options)\n return satisfies(comp.semver, rangeTmp, options)\n }\n\n var sameDirectionIncreasing =\n (this.operator === '>=' || this.operator === '>') &&\n (comp.operator === '>=' || comp.operator === '>')\n var sameDirectionDecreasing =\n (this.operator === '<=' || this.operator === '<') &&\n (comp.operator === '<=' || comp.operator === '<')\n var sameSemVer = this.semver.version === comp.semver.version\n var differentDirectionsInclusive =\n (this.operator === '>=' || this.operator === '<=') &&\n (comp.operator === '>=' || comp.operator === '<=')\n var oppositeDirectionsLessThan =\n cmp(this.semver, '<', comp.semver, options) &&\n ((this.operator === '>=' || this.operator === '>') &&\n (comp.operator === '<=' || comp.operator === '<'))\n var oppositeDirectionsGreaterThan =\n cmp(this.semver, '>', comp.semver, options) &&\n ((this.operator === '<=' || this.operator === '<') &&\n (comp.operator === '>=' || comp.operator === '>'))\n\n return sameDirectionIncreasing || sameDirectionDecreasing ||\n (sameSemVer && differentDirectionsInclusive) ||\n oppositeDirectionsLessThan || oppositeDirectionsGreaterThan\n}\n\nexports.Range = Range\nfunction Range (range, options) {\n if (!options || typeof options !== 'object') {\n options = {\n loose: !!options,\n includePrerelease: false\n }\n }\n\n if (range instanceof Range) {\n if (range.loose === !!options.loose &&\n range.includePrerelease === !!options.includePrerelease) {\n return range\n } else {\n return new Range(range.raw, options)\n }\n }\n\n if (range instanceof Comparator) {\n return new Range(range.value, options)\n }\n\n if (!(this instanceof Range)) {\n return new Range(range, options)\n }\n\n this.options = options\n this.loose = !!options.loose\n this.includePrerelease = !!options.includePrerelease\n\n // First, split based on boolean or ||\n this.raw = range\n this.set = range.split(/\\s*\\|\\|\\s*/).map(function (range) {\n return this.parseRange(range.trim())\n }, this).filter(function (c) {\n // throw out any that are not relevant for whatever reason\n return c.length\n })\n\n if (!this.set.length) {\n throw new TypeError('Invalid SemVer Range: ' + range)\n }\n\n this.format()\n}\n\nRange.prototype.format = function () {\n this.range = this.set.map(function (comps) {\n return comps.join(' ').trim()\n }).join('||').trim()\n return this.range\n}\n\nRange.prototype.toString = function () {\n return this.range\n}\n\nRange.prototype.parseRange = function (range) {\n var loose = this.options.loose\n range = range.trim()\n // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`\n var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]\n range = range.replace(hr, hyphenReplace)\n debug('hyphen replace', range)\n // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`\n range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace)\n debug('comparator trim', range, re[COMPARATORTRIM])\n\n // `~ 1.2.3` => `~1.2.3`\n range = range.replace(re[TILDETRIM], tildeTrimReplace)\n\n // `^ 1.2.3` => `^1.2.3`\n range = range.replace(re[CARETTRIM], caretTrimReplace)\n\n // normalize spaces\n range = range.split(/\\s+/).join(' ')\n\n // At this point, the range is completely trimmed and\n // ready to be split into comparators.\n\n var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]\n var set = range.split(' ').map(function (comp) {\n return parseComparator(comp, this.options)\n }, this).join(' ').split(/\\s+/)\n if (this.options.loose) {\n // in loose mode, throw out any that are not valid comparators\n set = set.filter(function (comp) {\n return !!comp.match(compRe)\n })\n }\n set = set.map(function (comp) {\n return new Comparator(comp, this.options)\n }, this)\n\n return set\n}\n\nRange.prototype.intersects = function (range, options) {\n if (!(range instanceof Range)) {\n throw new TypeError('a Range is required')\n }\n\n return this.set.some(function (thisComparators) {\n return thisComparators.every(function (thisComparator) {\n return range.set.some(function (rangeComparators) {\n return rangeComparators.every(function (rangeComparator) {\n return thisComparator.intersects(rangeComparator, options)\n })\n })\n })\n })\n}\n\n// Mostly just for testing and legacy API reasons\nexports.toComparators = toComparators\nfunction toComparators (range, options) {\n return new Range(range, options).set.map(function (comp) {\n return comp.map(function (c) {\n return c.value\n }).join(' ').trim().split(' ')\n })\n}\n\n// comprised of xranges, tildes, stars, and gtlt's at this point.\n// already replaced the hyphen ranges\n// turn into a set of JUST comparators.\nfunction parseComparator (comp, options) {\n debug('comp', comp, options)\n comp = replaceCarets(comp, options)\n debug('caret', comp)\n comp = replaceTildes(comp, options)\n debug('tildes', comp)\n comp = replaceXRanges(comp, options)\n debug('xrange', comp)\n comp = replaceStars(comp, options)\n debug('stars', comp)\n return comp\n}\n\nfunction isX (id) {\n return !id || id.toLowerCase() === 'x' || id === '*'\n}\n\n// ~, ~> --> * (any, kinda silly)\n// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0\n// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0\n// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0\n// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0\n// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0\nfunction replaceTildes (comp, options) {\n return comp.trim().split(/\\s+/).map(function (comp) {\n return replaceTilde(comp, options)\n }).join(' ')\n}\n\nfunction replaceTilde (comp, options) {\n var r = options.loose ? re[TILDELOOSE] : re[TILDE]\n return comp.replace(r, function (_, M, m, p, pr) {\n debug('tilde', comp, _, M, m, p, pr)\n var ret\n\n if (isX(M)) {\n ret = ''\n } else if (isX(m)) {\n ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'\n } else if (isX(p)) {\n // ~1.2 == >=1.2.0 <1.3.0\n ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'\n } else if (pr) {\n debug('replaceTilde pr', pr)\n ret = '>=' + M + '.' + m + '.' + p + '-' + pr +\n ' <' + M + '.' + (+m + 1) + '.0'\n } else {\n // ~1.2.3 == >=1.2.3 <1.3.0\n ret = '>=' + M + '.' + m + '.' + p +\n ' <' + M + '.' + (+m + 1) + '.0'\n }\n\n debug('tilde return', ret)\n return ret\n })\n}\n\n// ^ --> * (any, kinda silly)\n// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0\n// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0\n// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0\n// ^1.2.3 --> >=1.2.3 <2.0.0\n// ^1.2.0 --> >=1.2.0 <2.0.0\nfunction replaceCarets (comp, options) {\n return comp.trim().split(/\\s+/).map(function (comp) {\n return replaceCaret(comp, options)\n }).join(' ')\n}\n\nfunction replaceCaret (comp, options) {\n debug('caret', comp, options)\n var r = options.loose ? re[CARETLOOSE] : re[CARET]\n return comp.replace(r, function (_, M, m, p, pr) {\n debug('caret', comp, _, M, m, p, pr)\n var ret\n\n if (isX(M)) {\n ret = ''\n } else if (isX(m)) {\n ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'\n } else if (isX(p)) {\n if (M === '0') {\n ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'\n } else {\n ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'\n }\n } else if (pr) {\n debug('replaceCaret pr', pr)\n if (M === '0') {\n if (m === '0') {\n ret = '>=' + M + '.' + m + '.' + p + '-' + pr +\n ' <' + M + '.' + m + '.' + (+p + 1)\n } else {\n ret = '>=' + M + '.' + m + '.' + p + '-' + pr +\n ' <' + M + '.' + (+m + 1) + '.0'\n }\n } else {\n ret = '>=' + M + '.' + m + '.' + p + '-' + pr +\n ' <' + (+M + 1) + '.0.0'\n }\n } else {\n debug('no pr')\n if (M === '0') {\n if (m === '0') {\n ret = '>=' + M + '.' + m + '.' + p +\n ' <' + M + '.' + m + '.' + (+p + 1)\n } else {\n ret = '>=' + M + '.' + m + '.' + p +\n ' <' + M + '.' + (+m + 1) + '.0'\n }\n } else {\n ret = '>=' + M + '.' + m + '.' + p +\n ' <' + (+M + 1) + '.0.0'\n }\n }\n\n debug('caret return', ret)\n return ret\n })\n}\n\nfunction replaceXRanges (comp, options) {\n debug('replaceXRanges', comp, options)\n return comp.split(/\\s+/).map(function (comp) {\n return replaceXRange(comp, options)\n }).join(' ')\n}\n\nfunction replaceXRange (comp, options) {\n comp = comp.trim()\n var r = options.loose ? re[XRANGELOOSE] : re[XRANGE]\n return comp.replace(r, function (ret, gtlt, M, m, p, pr) {\n debug('xRange', comp, ret, gtlt, M, m, p, pr)\n var xM = isX(M)\n var xm = xM || isX(m)\n var xp = xm || isX(p)\n var anyX = xp\n\n if (gtlt === '=' && anyX) {\n gtlt = ''\n }\n\n if (xM) {\n if (gtlt === '>' || gtlt === '<') {\n // nothing is allowed\n ret = '<0.0.0'\n } else {\n // nothing is forbidden\n ret = '*'\n }\n } else if (gtlt && anyX) {\n // we know patch is an x, because we have any x at all.\n // replace X with 0\n if (xm) {\n m = 0\n }\n p = 0\n\n if (gtlt === '>') {\n // >1 => >=2.0.0\n // >1.2 => >=1.3.0\n // >1.2.3 => >= 1.2.4\n gtlt = '>='\n if (xm) {\n M = +M + 1\n m = 0\n p = 0\n } else {\n m = +m + 1\n p = 0\n }\n } else if (gtlt === '<=') {\n // <=0.7.x is actually <0.8.0, since any 0.7.x should\n // pass. Similarly, <=7.x is actually <8.0.0, etc.\n gtlt = '<'\n if (xm) {\n M = +M + 1\n } else {\n m = +m + 1\n }\n }\n\n ret = gtlt + M + '.' + m + '.' + p\n } else if (xm) {\n ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'\n } else if (xp) {\n ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'\n }\n\n debug('xRange return', ret)\n\n return ret\n })\n}\n\n// Because * is AND-ed with everything else in the comparator,\n// and '' means \"any version\", just remove the *s entirely.\nfunction replaceStars (comp, options) {\n debug('replaceStars', comp, options)\n // Looseness is ignored here. star is always as loose as it gets!\n return comp.trim().replace(re[STAR], '')\n}\n\n// This function is passed to string.replace(re[HYPHENRANGE])\n// M, m, patch, prerelease, build\n// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5\n// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do\n// 1.2 - 3.4 => >=1.2.0 <3.5.0\nfunction hyphenReplace ($0,\n from, fM, fm, fp, fpr, fb,\n to, tM, tm, tp, tpr, tb) {\n if (isX(fM)) {\n from = ''\n } else if (isX(fm)) {\n from = '>=' + fM + '.0.0'\n } else if (isX(fp)) {\n from = '>=' + fM + '.' + fm + '.0'\n } else {\n from = '>=' + from\n }\n\n if (isX(tM)) {\n to = ''\n } else if (isX(tm)) {\n to = '<' + (+tM + 1) + '.0.0'\n } else if (isX(tp)) {\n to = '<' + tM + '.' + (+tm + 1) + '.0'\n } else if (tpr) {\n to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr\n } else {\n to = '<=' + to\n }\n\n return (from + ' ' + to).trim()\n}\n\n// if ANY of the sets match ALL of its comparators, then pass\nRange.prototype.test = function (version) {\n if (!version) {\n return false\n }\n\n if (typeof version === 'string') {\n version = new SemVer(version, this.options)\n }\n\n for (var i = 0; i < this.set.length; i++) {\n if (testSet(this.set[i], version, this.options)) {\n return true\n }\n }\n return false\n}\n\nfunction testSet (set, version, options) {\n for (var i = 0; i < set.length; i++) {\n if (!set[i].test(version)) {\n return false\n }\n }\n\n if (version.prerelease.length && !options.includePrerelease) {\n // Find the set of versions that are allowed to have prereleases\n // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0\n // That should allow `1.2.3-pr.2` to pass.\n // However, `1.2.4-alpha.notready` should NOT be allowed,\n // even though it's within the range set by the comparators.\n for (i = 0; i < set.length; i++) {\n debug(set[i].semver)\n if (set[i].semver === ANY) {\n continue\n }\n\n if (set[i].semver.prerelease.length > 0) {\n var allowed = set[i].semver\n if (allowed.major === version.major &&\n allowed.minor === version.minor &&\n allowed.patch === version.patch) {\n return true\n }\n }\n }\n\n // Version has a -pre, but it's not one of the ones we like.\n return false\n }\n\n return true\n}\n\nexports.satisfies = satisfies\nfunction satisfies (version, range, options) {\n try {\n range = new Range(range, options)\n } catch (er) {\n return false\n }\n return range.test(version)\n}\n\nexports.maxSatisfying = maxSatisfying\nfunction maxSatisfying (versions, range, options) {\n var max = null\n var maxSV = null\n try {\n var rangeObj = new Range(range, options)\n } catch (er) {\n return null\n }\n versions.forEach(function (v) {\n if (rangeObj.test(v)) {\n // satisfies(v, range, options)\n if (!max || maxSV.compare(v) === -1) {\n // compare(max, v, true)\n max = v\n maxSV = new SemVer(max, options)\n }\n }\n })\n return max\n}\n\nexports.minSatisfying = minSatisfying\nfunction minSatisfying (versions, range, options) {\n var min = null\n var minSV = null\n try {\n var rangeObj = new Range(range, options)\n } catch (er) {\n return null\n }\n versions.forEach(function (v) {\n if (rangeObj.test(v)) {\n // satisfies(v, range, options)\n if (!min || minSV.compare(v) === 1) {\n // compare(min, v, true)\n min = v\n minSV = new SemVer(min, options)\n }\n }\n })\n return min\n}\n\nexports.minVersion = minVersion\nfunction minVersion (range, loose) {\n range = new Range(range, loose)\n\n var minver = new SemVer('0.0.0')\n if (range.test(minver)) {\n return minver\n }\n\n minver = new SemVer('0.0.0-0')\n if (range.test(minver)) {\n return minver\n }\n\n minver = null\n for (var i = 0; i < range.set.length; ++i) {\n var comparators = range.set[i]\n\n comparators.forEach(function (comparator) {\n // Clone to avoid manipulating the comparator's semver object.\n var compver = new SemVer(comparator.semver.version)\n switch (comparator.operator) {\n case '>':\n if (compver.prerelease.length === 0) {\n compver.patch++\n } else {\n compver.prerelease.push(0)\n }\n compver.raw = compver.format()\n /* fallthrough */\n case '':\n case '>=':\n if (!minver || gt(minver, compver)) {\n minver = compver\n }\n break\n case '<':\n case '<=':\n /* Ignore maximum versions */\n break\n /* istanbul ignore next */\n default:\n throw new Error('Unexpected operation: ' + comparator.operator)\n }\n })\n }\n\n if (minver && range.test(minver)) {\n return minver\n }\n\n return null\n}\n\nexports.validRange = validRange\nfunction validRange (range, options) {\n try {\n // Return '*' instead of '' so that truthiness works.\n // This will throw if it's invalid anyway\n return new Range(range, options).range || '*'\n } catch (er) {\n return null\n }\n}\n\n// Determine if version is less than all the versions possible in the range\nexports.ltr = ltr\nfunction ltr (version, range, options) {\n return outside(version, range, '<', options)\n}\n\n// Determine if version is greater than all the versions possible in the range.\nexports.gtr = gtr\nfunction gtr (version, range, options) {\n return outside(version, range, '>', options)\n}\n\nexports.outside = outside\nfunction outside (version, range, hilo, options) {\n version = new SemVer(version, options)\n range = new Range(range, options)\n\n var gtfn, ltefn, ltfn, comp, ecomp\n switch (hilo) {\n case '>':\n gtfn = gt\n ltefn = lte\n ltfn = lt\n comp = '>'\n ecomp = '>='\n break\n case '<':\n gtfn = lt\n ltefn = gte\n ltfn = gt\n comp = '<'\n ecomp = '<='\n break\n default:\n throw new TypeError('Must provide a hilo val of \"<\" or \">\"')\n }\n\n // If it satisifes the range it is not outside\n if (satisfies(version, range, options)) {\n return false\n }\n\n // From now on, variable terms are as if we're in \"gtr\" mode.\n // but note that everything is flipped for the \"ltr\" function.\n\n for (var i = 0; i < range.set.length; ++i) {\n var comparators = range.set[i]\n\n var high = null\n var low = null\n\n comparators.forEach(function (comparator) {\n if (comparator.semver === ANY) {\n comparator = new Comparator('>=0.0.0')\n }\n high = high || comparator\n low = low || comparator\n if (gtfn(comparator.semver, high.semver, options)) {\n high = comparator\n } else if (ltfn(comparator.semver, low.semver, options)) {\n low = comparator\n }\n })\n\n // If the edge version comparator has a operator then our version\n // isn't outside it\n if (high.operator === comp || high.operator === ecomp) {\n return false\n }\n\n // If the lowest version comparator has an operator and our version\n // is less than it then it isn't higher than the range\n if ((!low.operator || low.operator === comp) &&\n ltefn(version, low.semver)) {\n return false\n } else if (low.operator === ecomp && ltfn(version, low.semver)) {\n return false\n }\n }\n return true\n}\n\nexports.prerelease = prerelease\nfunction prerelease (version, options) {\n var parsed = parse(version, options)\n return (parsed && parsed.prerelease.length) ? parsed.prerelease : null\n}\n\nexports.intersects = intersects\nfunction intersects (r1, r2, options) {\n r1 = new Range(r1, options)\n r2 = new Range(r2, options)\n return r1.intersects(r2)\n}\n\nexports.coerce = coerce\nfunction coerce (version) {\n if (version instanceof SemVer) {\n return version\n }\n\n if (typeof version !== 'string') {\n return null\n }\n\n var match = version.match(re[COERCE])\n\n if (match == null) {\n return null\n }\n\n return parse(match[1] +\n '.' + (match[2] || '0') +\n '.' + (match[3] || '0'))\n}\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar shell = require(\"shelljs\");\r\nvar childProcess = require(\"child_process\");\r\nvar fs = require(\"fs\");\r\nvar path = require(\"path\");\r\nvar os = require(\"os\");\r\nvar minimatch = require(\"minimatch\");\r\nvar im = require(\"./internal\");\r\nvar tcm = require(\"./taskcommand\");\r\nvar trm = require(\"./toolrunner\");\r\nvar semver = require(\"semver\");\r\nvar TaskResult;\r\n(function (TaskResult) {\r\n TaskResult[TaskResult[\"Succeeded\"] = 0] = \"Succeeded\";\r\n TaskResult[TaskResult[\"SucceededWithIssues\"] = 1] = \"SucceededWithIssues\";\r\n TaskResult[TaskResult[\"Failed\"] = 2] = \"Failed\";\r\n TaskResult[TaskResult[\"Cancelled\"] = 3] = \"Cancelled\";\r\n TaskResult[TaskResult[\"Skipped\"] = 4] = \"Skipped\";\r\n})(TaskResult = exports.TaskResult || (exports.TaskResult = {}));\r\nvar TaskState;\r\n(function (TaskState) {\r\n TaskState[TaskState[\"Unknown\"] = 0] = \"Unknown\";\r\n TaskState[TaskState[\"Initialized\"] = 1] = \"Initialized\";\r\n TaskState[TaskState[\"InProgress\"] = 2] = \"InProgress\";\r\n TaskState[TaskState[\"Completed\"] = 3] = \"Completed\";\r\n})(TaskState = exports.TaskState || (exports.TaskState = {}));\r\nvar IssueType;\r\n(function (IssueType) {\r\n IssueType[IssueType[\"Error\"] = 0] = \"Error\";\r\n IssueType[IssueType[\"Warning\"] = 1] = \"Warning\";\r\n})(IssueType = exports.IssueType || (exports.IssueType = {}));\r\nvar ArtifactType;\r\n(function (ArtifactType) {\r\n ArtifactType[ArtifactType[\"Container\"] = 0] = \"Container\";\r\n ArtifactType[ArtifactType[\"FilePath\"] = 1] = \"FilePath\";\r\n ArtifactType[ArtifactType[\"VersionControl\"] = 2] = \"VersionControl\";\r\n ArtifactType[ArtifactType[\"GitRef\"] = 3] = \"GitRef\";\r\n ArtifactType[ArtifactType[\"TfvcLabel\"] = 4] = \"TfvcLabel\";\r\n})(ArtifactType = exports.ArtifactType || (exports.ArtifactType = {}));\r\nvar FieldType;\r\n(function (FieldType) {\r\n FieldType[FieldType[\"AuthParameter\"] = 0] = \"AuthParameter\";\r\n FieldType[FieldType[\"DataParameter\"] = 1] = \"DataParameter\";\r\n FieldType[FieldType[\"Url\"] = 2] = \"Url\";\r\n})(FieldType = exports.FieldType || (exports.FieldType = {}));\r\n/** Platforms supported by our build agent */\r\nvar Platform;\r\n(function (Platform) {\r\n Platform[Platform[\"Windows\"] = 0] = \"Windows\";\r\n Platform[Platform[\"MacOS\"] = 1] = \"MacOS\";\r\n Platform[Platform[\"Linux\"] = 2] = \"Linux\";\r\n})(Platform = exports.Platform || (exports.Platform = {}));\r\n//-----------------------------------------------------\r\n// General Helpers\r\n//-----------------------------------------------------\r\nexports.setStdStream = im._setStdStream;\r\nexports.setErrStream = im._setErrStream;\r\n//-----------------------------------------------------\r\n// Results\r\n//-----------------------------------------------------\r\n/**\r\n * Sets the result of the task.\r\n * Execution will continue.\r\n * If not set, task will be Succeeded.\r\n * If multiple calls are made to setResult the most pessimistic call wins (Failed) regardless of the order of calls.\r\n *\r\n * @param result TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.\r\n * @param message A message which will be logged as an error issue if the result is Failed.\r\n * @param done Optional. Instructs the agent the task is done. This is helpful when child processes\r\n * may still be running and prevent node from fully exiting. This argument is supported\r\n * from agent version 2.142.0 or higher (otherwise will no-op).\r\n * @returns void\r\n */\r\nfunction setResult(result, message, done) {\r\n exports.debug('task result: ' + TaskResult[result]);\r\n // add an error issue\r\n if (result == TaskResult.Failed && message) {\r\n exports.error(message);\r\n }\r\n else if (result == TaskResult.SucceededWithIssues && message) {\r\n exports.warning(message);\r\n }\r\n // task.complete\r\n var properties = { 'result': TaskResult[result] };\r\n if (done) {\r\n properties['done'] = 'true';\r\n }\r\n exports.command('task.complete', properties, message);\r\n}\r\nexports.setResult = setResult;\r\n//\r\n// Catching all exceptions\r\n//\r\nprocess.on('uncaughtException', function (err) {\r\n setResult(TaskResult.Failed, exports.loc('LIB_UnhandledEx', err.message));\r\n});\r\n//-----------------------------------------------------\r\n// Loc Helpers\r\n//-----------------------------------------------------\r\nexports.setResourcePath = im._setResourcePath;\r\nexports.loc = im._loc;\r\n//-----------------------------------------------------\r\n// Input Helpers\r\n//-----------------------------------------------------\r\nexports.getVariable = im._getVariable;\r\n/**\r\n * Asserts the agent version is at least the specified minimum.\r\n *\r\n * @param minimum minimum version version - must be 2.104.1 or higher\r\n */\r\nfunction assertAgent(minimum) {\r\n if (semver.lt(minimum, '2.104.1')) {\r\n throw new Error('assertAgent() requires the parameter to be 2.104.1 or higher');\r\n }\r\n var agent = exports.getVariable('Agent.Version');\r\n if (agent && semver.lt(agent, minimum)) {\r\n throw new Error(\"Agent version \" + minimum + \" or higher is required\");\r\n }\r\n}\r\nexports.assertAgent = assertAgent;\r\n/**\r\n * Gets a snapshot of the current state of all job variables available to the task.\r\n * Requires a 2.104.1 agent or higher for full functionality.\r\n *\r\n * Limitations on an agent prior to 2.104.1:\r\n * 1) The return value does not include all public variables. Only public variables\r\n * that have been added using setVariable are returned.\r\n * 2) The name returned for each secret variable is the formatted environment variable\r\n * name, not the actual variable name (unless it was set explicitly at runtime using\r\n * setVariable).\r\n *\r\n * @returns VariableInfo[]\r\n */\r\nfunction getVariables() {\r\n return Object.keys(im._knownVariableMap)\r\n .map(function (key) {\r\n var info = im._knownVariableMap[key];\r\n return { name: info.name, value: exports.getVariable(info.name), secret: info.secret };\r\n });\r\n}\r\nexports.getVariables = getVariables;\r\n/**\r\n * Sets a variable which will be available to subsequent tasks as well.\r\n *\r\n * @param name name of the variable to set\r\n * @param val value to set\r\n * @param secret whether variable is secret. Multi-line secrets are not allowed. Optional, defaults to false\r\n * @param isOutput whether variable is an output variable. Optional, defaults to false\r\n * @returns void\r\n */\r\nfunction setVariable(name, val, secret, isOutput) {\r\n if (secret === void 0) { secret = false; }\r\n if (isOutput === void 0) { isOutput = false; }\r\n // once a secret always a secret\r\n var key = im._getVariableKey(name);\r\n if (im._knownVariableMap.hasOwnProperty(key)) {\r\n secret = secret || im._knownVariableMap[key].secret;\r\n }\r\n // store the value\r\n var varValue = val || '';\r\n exports.debug('set ' + name + '=' + (secret && varValue ? '********' : varValue));\r\n if (secret) {\r\n if (varValue && varValue.match(/\\r|\\n/) && (\"\" + process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() != 'TRUE') {\r\n throw new Error(exports.loc('LIB_MultilineSecret'));\r\n }\r\n im._vault.storeSecret('SECRET_' + key, varValue);\r\n delete process.env[key];\r\n }\r\n else {\r\n process.env[key] = varValue;\r\n }\r\n // store the metadata\r\n im._knownVariableMap[key] = { name: name, secret: secret };\r\n // write the setvariable command\r\n exports.command('task.setvariable', { 'variable': name || '', isOutput: (isOutput || false).toString(), 'issecret': (secret || false).toString() }, varValue);\r\n}\r\nexports.setVariable = setVariable;\r\n/**\r\n * Registers a value with the logger, so the value will be masked from the logs. Multi-line secrets are not allowed.\r\n *\r\n * @param val value to register\r\n */\r\nfunction setSecret(val) {\r\n if (val) {\r\n if (val.match(/\\r|\\n/) && (\"\" + process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() !== 'TRUE') {\r\n throw new Error(exports.loc('LIB_MultilineSecret'));\r\n }\r\n exports.command('task.setsecret', {}, val);\r\n }\r\n}\r\nexports.setSecret = setSecret;\r\n/**\r\n * Gets the value of an input.\r\n * If required is true and the value is not set, it will throw.\r\n *\r\n * @param name name of the input to get\r\n * @param required whether input is required. optional, defaults to false\r\n * @returns string\r\n */\r\nfunction getInput(name, required) {\r\n var inval = im._vault.retrieveSecret('INPUT_' + im._getVariableKey(name));\r\n if (required && !inval) {\r\n throw new Error(exports.loc('LIB_InputRequired', name));\r\n }\r\n exports.debug(name + '=' + inval);\r\n return inval;\r\n}\r\nexports.getInput = getInput;\r\n/**\r\n * Gets the value of an input and converts to a bool. Convenience.\r\n * If required is true and the value is not set, it will throw.\r\n * If required is false and the value is not set, returns false.\r\n *\r\n * @param name name of the bool input to get\r\n * @param required whether input is required. optional, defaults to false\r\n * @returns boolean\r\n */\r\nfunction getBoolInput(name, required) {\r\n return (getInput(name, required) || '').toUpperCase() == \"TRUE\";\r\n}\r\nexports.getBoolInput = getBoolInput;\r\n/**\r\n * Gets the value of an input and splits the value using a delimiter (space, comma, etc).\r\n * Empty values are removed. This function is useful for splitting an input containing a simple\r\n * list of items - such as build targets.\r\n * IMPORTANT: Do not use this function for splitting additional args! Instead use argString(), which\r\n * follows normal argument splitting rules and handles values encapsulated by quotes.\r\n * If required is true and the value is not set, it will throw.\r\n *\r\n * @param name name of the input to get\r\n * @param delim delimiter to split on\r\n * @param required whether input is required. optional, defaults to false\r\n * @returns string[]\r\n */\r\nfunction getDelimitedInput(name, delim, required) {\r\n var inputVal = getInput(name, required);\r\n if (!inputVal) {\r\n return [];\r\n }\r\n var result = [];\r\n inputVal.split(delim).forEach(function (x) {\r\n if (x) {\r\n result.push(x);\r\n }\r\n });\r\n return result;\r\n}\r\nexports.getDelimitedInput = getDelimitedInput;\r\n/**\r\n * Checks whether a path inputs value was supplied by the user\r\n * File paths are relative with a picker, so an empty path is the root of the repo.\r\n * Useful if you need to condition work (like append an arg) if a value was supplied\r\n *\r\n * @param name name of the path input to check\r\n * @returns boolean\r\n */\r\nfunction filePathSupplied(name) {\r\n // normalize paths\r\n var pathValue = this.resolve(this.getPathInput(name) || '');\r\n var repoRoot = this.resolve(exports.getVariable('build.sourcesDirectory') || exports.getVariable('system.defaultWorkingDirectory') || '');\r\n var supplied = pathValue !== repoRoot;\r\n exports.debug(name + 'path supplied :' + supplied);\r\n return supplied;\r\n}\r\nexports.filePathSupplied = filePathSupplied;\r\n/**\r\n * Gets the value of a path input\r\n * It will be quoted for you if it isn't already and contains spaces\r\n * If required is true and the value is not set, it will throw.\r\n * If check is true and the path does not exist, it will throw.\r\n *\r\n * @param name name of the input to get\r\n * @param required whether input is required. optional, defaults to false\r\n * @param check whether path is checked. optional, defaults to false\r\n * @returns string\r\n */\r\nfunction getPathInput(name, required, check) {\r\n var inval = getInput(name, required);\r\n if (inval) {\r\n if (check) {\r\n exports.checkPath(inval, name);\r\n }\r\n }\r\n return inval;\r\n}\r\nexports.getPathInput = getPathInput;\r\n//-----------------------------------------------------\r\n// Endpoint Helpers\r\n//-----------------------------------------------------\r\n/**\r\n * Gets the url for a service endpoint\r\n * If the url was not set and is not optional, it will throw.\r\n *\r\n * @param id name of the service endpoint\r\n * @param optional whether the url is optional\r\n * @returns string\r\n */\r\nfunction getEndpointUrl(id, optional) {\r\n var urlval = process.env['ENDPOINT_URL_' + id];\r\n if (!optional && !urlval) {\r\n throw new Error(exports.loc('LIB_EndpointNotExist', id));\r\n }\r\n exports.debug(id + '=' + urlval);\r\n return urlval;\r\n}\r\nexports.getEndpointUrl = getEndpointUrl;\r\n/*\r\n * Gets the endpoint data parameter value with specified key for a service endpoint\r\n * If the endpoint data parameter was not set and is not optional, it will throw.\r\n *\r\n * @param id name of the service endpoint\r\n * @param key of the parameter\r\n * @param optional whether the endpoint data is optional\r\n * @returns {string} value of the endpoint data parameter\r\n */\r\nfunction getEndpointDataParameter(id, key, optional) {\r\n var dataParamVal = process.env['ENDPOINT_DATA_' + id + '_' + key.toUpperCase()];\r\n if (!optional && !dataParamVal) {\r\n throw new Error(exports.loc('LIB_EndpointDataNotExist', id, key));\r\n }\r\n exports.debug(id + ' data ' + key + ' = ' + dataParamVal);\r\n return dataParamVal;\r\n}\r\nexports.getEndpointDataParameter = getEndpointDataParameter;\r\n/**\r\n * Gets the endpoint authorization scheme for a service endpoint\r\n * If the endpoint authorization scheme is not set and is not optional, it will throw.\r\n *\r\n * @param id name of the service endpoint\r\n * @param optional whether the endpoint authorization scheme is optional\r\n * @returns {string} value of the endpoint authorization scheme\r\n */\r\nfunction getEndpointAuthorizationScheme(id, optional) {\r\n var authScheme = im._vault.retrieveSecret('ENDPOINT_AUTH_SCHEME_' + id);\r\n if (!optional && !authScheme) {\r\n throw new Error(exports.loc('LIB_EndpointAuthNotExist', id));\r\n }\r\n exports.debug(id + ' auth scheme = ' + authScheme);\r\n return authScheme;\r\n}\r\nexports.getEndpointAuthorizationScheme = getEndpointAuthorizationScheme;\r\n/**\r\n * Gets the endpoint authorization parameter value for a service endpoint with specified key\r\n * If the endpoint authorization parameter is not set and is not optional, it will throw.\r\n *\r\n * @param id name of the service endpoint\r\n * @param key key to find the endpoint authorization parameter\r\n * @param optional optional whether the endpoint authorization scheme is optional\r\n * @returns {string} value of the endpoint authorization parameter value\r\n */\r\nfunction getEndpointAuthorizationParameter(id, key, optional) {\r\n var authParam = im._vault.retrieveSecret('ENDPOINT_AUTH_PARAMETER_' + id + '_' + key.toUpperCase());\r\n if (!optional && !authParam) {\r\n throw new Error(exports.loc('LIB_EndpointAuthNotExist', id));\r\n }\r\n exports.debug(id + ' auth param ' + key + ' = ' + authParam);\r\n return authParam;\r\n}\r\nexports.getEndpointAuthorizationParameter = getEndpointAuthorizationParameter;\r\n/**\r\n * Gets the authorization details for a service endpoint\r\n * If the authorization was not set and is not optional, it will throw.\r\n *\r\n * @param id name of the service endpoint\r\n * @param optional whether the url is optional\r\n * @returns string\r\n */\r\nfunction getEndpointAuthorization(id, optional) {\r\n var aval = im._vault.retrieveSecret('ENDPOINT_AUTH_' + id);\r\n if (!optional && !aval) {\r\n setResult(TaskResult.Failed, exports.loc('LIB_EndpointAuthNotExist', id));\r\n }\r\n exports.debug(id + ' exists ' + (aval !== null));\r\n var auth;\r\n try {\r\n if (aval) {\r\n auth = JSON.parse(aval);\r\n }\r\n }\r\n catch (err) {\r\n throw new Error(exports.loc('LIB_InvalidEndpointAuth', aval));\r\n }\r\n return auth;\r\n}\r\nexports.getEndpointAuthorization = getEndpointAuthorization;\r\n//-----------------------------------------------------\r\n// SecureFile Helpers\r\n//-----------------------------------------------------\r\n/**\r\n * Gets the name for a secure file\r\n *\r\n * @param id secure file id\r\n * @returns string\r\n */\r\nfunction getSecureFileName(id) {\r\n var name = process.env['SECUREFILE_NAME_' + id];\r\n exports.debug('secure file name for id ' + id + ' = ' + name);\r\n return name;\r\n}\r\nexports.getSecureFileName = getSecureFileName;\r\n/**\r\n * Gets the secure file ticket that can be used to download the secure file contents\r\n *\r\n * @param id name of the secure file\r\n * @returns {string} secure file ticket\r\n */\r\nfunction getSecureFileTicket(id) {\r\n var ticket = im._vault.retrieveSecret('SECUREFILE_TICKET_' + id);\r\n exports.debug('secure file ticket for id ' + id + ' = ' + ticket);\r\n return ticket;\r\n}\r\nexports.getSecureFileTicket = getSecureFileTicket;\r\n//-----------------------------------------------------\r\n// Task Variable Helpers\r\n//-----------------------------------------------------\r\n/**\r\n * Gets a variable value that is set by previous step from the same wrapper task.\r\n * Requires a 2.115.0 agent or higher.\r\n *\r\n * @param name name of the variable to get\r\n * @returns string\r\n */\r\nfunction getTaskVariable(name) {\r\n assertAgent('2.115.0');\r\n var inval = im._vault.retrieveSecret('VSTS_TASKVARIABLE_' + im._getVariableKey(name));\r\n if (inval) {\r\n inval = inval.trim();\r\n }\r\n exports.debug('task variable: ' + name + '=' + inval);\r\n return inval;\r\n}\r\nexports.getTaskVariable = getTaskVariable;\r\n/**\r\n * Sets a task variable which will only be available to subsequent steps belong to the same wrapper task.\r\n * Requires a 2.115.0 agent or higher.\r\n *\r\n * @param name name of the variable to set\r\n * @param val value to set\r\n * @param secret whether variable is secret. optional, defaults to false\r\n * @returns void\r\n */\r\nfunction setTaskVariable(name, val, secret) {\r\n if (secret === void 0) { secret = false; }\r\n assertAgent('2.115.0');\r\n var key = im._getVariableKey(name);\r\n // store the value\r\n var varValue = val || '';\r\n exports.debug('set task variable: ' + name + '=' + (secret && varValue ? '********' : varValue));\r\n im._vault.storeSecret('VSTS_TASKVARIABLE_' + key, varValue);\r\n delete process.env[key];\r\n // write the command\r\n exports.command('task.settaskvariable', { 'variable': name || '', 'issecret': (secret || false).toString() }, varValue);\r\n}\r\nexports.setTaskVariable = setTaskVariable;\r\n//-----------------------------------------------------\r\n// Cmd Helpers\r\n//-----------------------------------------------------\r\nexports.command = im._command;\r\nexports.warning = im._warning;\r\nexports.error = im._error;\r\nexports.debug = im._debug;\r\n//-----------------------------------------------------\r\n// Disk Functions\r\n//-----------------------------------------------------\r\nfunction _checkShell(cmd, continueOnError) {\r\n var se = shell.error();\r\n if (se) {\r\n exports.debug(cmd + ' failed');\r\n var errMsg = exports.loc('LIB_OperationFailed', cmd, se);\r\n exports.debug(errMsg);\r\n if (!continueOnError) {\r\n throw new Error(errMsg);\r\n }\r\n }\r\n}\r\n/**\r\n * Get's stat on a path.\r\n * Useful for checking whether a file or directory. Also getting created, modified and accessed time.\r\n * see [fs.stat](https://nodejs.org/api/fs.html#fs_class_fs_stats)\r\n *\r\n * @param path path to check\r\n * @returns fsStat\r\n */\r\nfunction stats(path) {\r\n return fs.statSync(path);\r\n}\r\nexports.stats = stats;\r\nexports.exist = im._exist;\r\nfunction writeFile(file, data, options) {\r\n if (typeof (options) === 'string') {\r\n fs.writeFileSync(file, data, { encoding: options });\r\n }\r\n else {\r\n fs.writeFileSync(file, data, options);\r\n }\r\n}\r\nexports.writeFile = writeFile;\r\n/**\r\n * @deprecated Use `getPlatform`\r\n * Useful for determining the host operating system.\r\n * see [os.type](https://nodejs.org/api/os.html#os_os_type)\r\n *\r\n * @return the name of the operating system\r\n */\r\nfunction osType() {\r\n return os.type();\r\n}\r\nexports.osType = osType;\r\n/**\r\n * Determine the operating system the build agent is running on.\r\n * @returns {Platform}\r\n * @throws {Error} Platform is not supported by our agent\r\n */\r\nfunction getPlatform() {\r\n switch (process.platform) {\r\n case 'win32': return Platform.Windows;\r\n case 'darwin': return Platform.MacOS;\r\n case 'linux': return Platform.Linux;\r\n default: throw Error(exports.loc('LIB_PlatformNotSupported', process.platform));\r\n }\r\n}\r\nexports.getPlatform = getPlatform;\r\n/**\r\n * Returns the process's current working directory.\r\n * see [process.cwd](https://nodejs.org/api/process.html#process_process_cwd)\r\n *\r\n * @return the path to the current working directory of the process\r\n */\r\nfunction cwd() {\r\n return process.cwd();\r\n}\r\nexports.cwd = cwd;\r\nexports.checkPath = im._checkPath;\r\n/**\r\n * Change working directory.\r\n *\r\n * @param path new working directory path\r\n * @returns void\r\n */\r\nfunction cd(path) {\r\n if (path) {\r\n shell.cd(path);\r\n _checkShell('cd');\r\n }\r\n}\r\nexports.cd = cd;\r\n/**\r\n * Change working directory and push it on the stack\r\n *\r\n * @param path new working directory path\r\n * @returns void\r\n */\r\nfunction pushd(path) {\r\n shell.pushd(path);\r\n _checkShell('pushd');\r\n}\r\nexports.pushd = pushd;\r\n/**\r\n * Change working directory back to previously pushed directory\r\n *\r\n * @returns void\r\n */\r\nfunction popd() {\r\n shell.popd();\r\n _checkShell('popd');\r\n}\r\nexports.popd = popd;\r\n/**\r\n * Make a directory. Creates the full path with folders in between\r\n * Will throw if it fails\r\n *\r\n * @param p path to create\r\n * @returns void\r\n */\r\nfunction mkdirP(p) {\r\n if (!p) {\r\n throw new Error(exports.loc('LIB_ParameterIsRequired', 'p'));\r\n }\r\n // build a stack of directories to create\r\n var stack = [];\r\n var testDir = p;\r\n while (true) {\r\n // validate the loop is not out of control\r\n if (stack.length >= (process.env['TASKLIB_TEST_MKDIRP_FAILSAFE'] || 1000)) {\r\n // let the framework throw\r\n exports.debug('loop is out of control');\r\n fs.mkdirSync(p);\r\n return;\r\n }\r\n exports.debug(\"testing directory '\" + testDir + \"'\");\r\n var stats_1 = void 0;\r\n try {\r\n stats_1 = fs.statSync(testDir);\r\n }\r\n catch (err) {\r\n if (err.code == 'ENOENT') {\r\n // validate the directory is not the drive root\r\n var parentDir = path.dirname(testDir);\r\n if (testDir == parentDir) {\r\n throw new Error(exports.loc('LIB_MkdirFailedInvalidDriveRoot', p, testDir)); // Unable to create directory '{p}'. Root directory does not exist: '{testDir}'\r\n }\r\n // push the dir and test the parent\r\n stack.push(testDir);\r\n testDir = parentDir;\r\n continue;\r\n }\r\n else if (err.code == 'UNKNOWN') {\r\n throw new Error(exports.loc('LIB_MkdirFailedInvalidShare', p, testDir)); // Unable to create directory '{p}'. Unable to verify the directory exists: '{testDir}'. If directory is a file share, please verify the share name is correct, the share is online, and the current process has permission to access the share.\r\n }\r\n else {\r\n throw err;\r\n }\r\n }\r\n if (!stats_1.isDirectory()) {\r\n throw new Error(exports.loc('LIB_MkdirFailedFileExists', p, testDir)); // Unable to create directory '{p}'. Conflicting file exists: '{testDir}'\r\n }\r\n // testDir exists\r\n break;\r\n }\r\n // create each directory\r\n while (stack.length) {\r\n var dir = stack.pop(); // non-null because `stack.length` was truthy\r\n exports.debug(\"mkdir '\" + dir + \"'\");\r\n try {\r\n fs.mkdirSync(dir);\r\n }\r\n catch (err) {\r\n throw new Error(exports.loc('LIB_MkdirFailed', p, err.message)); // Unable to create directory '{p}'. {err.message}\r\n }\r\n }\r\n}\r\nexports.mkdirP = mkdirP;\r\n/**\r\n * Resolves a sequence of paths or path segments into an absolute path.\r\n * Calls node.js path.resolve()\r\n * Allows L0 testing with consistent path formats on Mac/Linux and Windows in the mock implementation\r\n * @param pathSegments\r\n * @returns {string}\r\n */\r\nfunction resolve() {\r\n var pathSegments = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n pathSegments[_i] = arguments[_i];\r\n }\r\n var absolutePath = path.resolve.apply(this, pathSegments);\r\n exports.debug('Absolute path for pathSegments: ' + pathSegments + ' = ' + absolutePath);\r\n return absolutePath;\r\n}\r\nexports.resolve = resolve;\r\nexports.which = im._which;\r\n/**\r\n * Returns array of files in the given path, or in current directory if no path provided. See shelljs.ls\r\n * @param {string} options Available options: -R (recursive), -A (all files, include files beginning with ., except for . and ..)\r\n * @param {string[]} paths Paths to search.\r\n * @return {string[]} An array of files in the given path(s).\r\n */\r\nfunction ls(options, paths) {\r\n if (options) {\r\n return shell.ls(options, paths);\r\n }\r\n else {\r\n return shell.ls(paths);\r\n }\r\n}\r\nexports.ls = ls;\r\n/**\r\n * Copies a file or folder.\r\n *\r\n * @param source source path\r\n * @param dest destination path\r\n * @param options string -r, -f or -rf for recursive and force\r\n * @param continueOnError optional. whether to continue on error\r\n * @param retryCount optional. Retry count to copy the file. It might help to resolve intermittent issues e.g. with UNC target paths on a remote host.\r\n */\r\nfunction cp(source, dest, options, continueOnError, retryCount) {\r\n if (retryCount === void 0) { retryCount = 0; }\r\n while (retryCount >= 0) {\r\n if (options) {\r\n shell.cp(options, source, dest);\r\n }\r\n else {\r\n shell.cp(source, dest);\r\n }\r\n try {\r\n _checkShell('cp', false);\r\n break;\r\n }\r\n catch (e) {\r\n if (retryCount <= 0) {\r\n if (continueOnError) {\r\n exports.warning(e);\r\n break;\r\n }\r\n else {\r\n throw e;\r\n }\r\n }\r\n else {\r\n console.log(exports.loc('LIB_CopyFileFailed', retryCount));\r\n retryCount--;\r\n }\r\n }\r\n }\r\n}\r\nexports.cp = cp;\r\n/**\r\n * Moves a path.\r\n *\r\n * @param source source path\r\n * @param dest destination path\r\n * @param options string -f or -n for force and no clobber\r\n * @param continueOnError optional. whether to continue on error\r\n */\r\nfunction mv(source, dest, options, continueOnError) {\r\n if (options) {\r\n shell.mv(options, source, dest);\r\n }\r\n else {\r\n shell.mv(source, dest);\r\n }\r\n _checkShell('mv', continueOnError);\r\n}\r\nexports.mv = mv;\r\n/**\r\n * Recursively finds all paths a given path. Returns an array of paths.\r\n *\r\n * @param findPath path to search\r\n * @param options optional. defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.\r\n * @returns string[]\r\n */\r\nfunction find(findPath, options) {\r\n if (!findPath) {\r\n exports.debug('no path specified');\r\n return [];\r\n }\r\n // normalize the path, otherwise the first result is inconsistently formatted from the rest of the results\r\n // because path.join() performs normalization.\r\n findPath = path.normalize(findPath);\r\n // debug trace the parameters\r\n exports.debug(\"findPath: '\" + findPath + \"'\");\r\n options = options || _getDefaultFindOptions();\r\n _debugFindOptions(options);\r\n // return empty if not exists\r\n try {\r\n fs.lstatSync(findPath);\r\n }\r\n catch (err) {\r\n if (err.code == 'ENOENT') {\r\n exports.debug('0 results');\r\n return [];\r\n }\r\n throw err;\r\n }\r\n try {\r\n var result = [];\r\n // push the first item\r\n var stack = [new _FindItem(findPath, 1)];\r\n var traversalChain = []; // used to detect cycles\r\n var _loop_1 = function () {\r\n // pop the next item and push to the result array\r\n var item = stack.pop(); // non-null because `stack.length` was truthy\r\n result.push(item.path);\r\n // stat the item. the stat info is used further below to determine whether to traverse deeper\r\n //\r\n // stat returns info about the target of a symlink (or symlink chain),\r\n // lstat returns info about a symlink itself\r\n var stats_2 = void 0;\r\n if (options.followSymbolicLinks) {\r\n try {\r\n // use stat (following all symlinks)\r\n stats_2 = fs.statSync(item.path);\r\n }\r\n catch (err) {\r\n if (err.code == 'ENOENT' && options.allowBrokenSymbolicLinks) {\r\n // fallback to lstat (broken symlinks allowed)\r\n stats_2 = fs.lstatSync(item.path);\r\n exports.debug(\" \" + item.path + \" (broken symlink)\");\r\n }\r\n else {\r\n throw err;\r\n }\r\n }\r\n }\r\n else if (options.followSpecifiedSymbolicLink && result.length == 1) {\r\n try {\r\n // use stat (following symlinks for the specified path and this is the specified path)\r\n stats_2 = fs.statSync(item.path);\r\n }\r\n catch (err) {\r\n if (err.code == 'ENOENT' && options.allowBrokenSymbolicLinks) {\r\n // fallback to lstat (broken symlinks allowed)\r\n stats_2 = fs.lstatSync(item.path);\r\n exports.debug(\" \" + item.path + \" (broken symlink)\");\r\n }\r\n else {\r\n throw err;\r\n }\r\n }\r\n }\r\n else {\r\n // use lstat (not following symlinks)\r\n stats_2 = fs.lstatSync(item.path);\r\n }\r\n // note, isDirectory() returns false for the lstat of a symlink\r\n if (stats_2.isDirectory()) {\r\n exports.debug(\" \" + item.path + \" (directory)\");\r\n if (options.followSymbolicLinks) {\r\n // get the realpath\r\n var realPath_1 = fs.realpathSync(item.path);\r\n // fixup the traversal chain to match the item level\r\n while (traversalChain.length >= item.level) {\r\n traversalChain.pop();\r\n }\r\n // test for a cycle\r\n if (traversalChain.some(function (x) { return x == realPath_1; })) {\r\n exports.debug(' cycle detected');\r\n return \"continue\";\r\n }\r\n // update the traversal chain\r\n traversalChain.push(realPath_1);\r\n }\r\n // push the child items in reverse onto the stack\r\n var childLevel_1 = item.level + 1;\r\n var childItems = fs.readdirSync(item.path)\r\n .map(function (childName) { return new _FindItem(path.join(item.path, childName), childLevel_1); });\r\n for (var i = childItems.length - 1; i >= 0; i--) {\r\n stack.push(childItems[i]);\r\n }\r\n }\r\n else {\r\n exports.debug(\" \" + item.path + \" (file)\");\r\n }\r\n };\r\n while (stack.length) {\r\n _loop_1();\r\n }\r\n exports.debug(result.length + \" results\");\r\n return result;\r\n }\r\n catch (err) {\r\n throw new Error(exports.loc('LIB_OperationFailed', 'find', err.message));\r\n }\r\n}\r\nexports.find = find;\r\nvar _FindItem = /** @class */ (function () {\r\n function _FindItem(path, level) {\r\n this.path = path;\r\n this.level = level;\r\n }\r\n return _FindItem;\r\n}());\r\nfunction _debugFindOptions(options) {\r\n exports.debug(\"findOptions.allowBrokenSymbolicLinks: '\" + options.allowBrokenSymbolicLinks + \"'\");\r\n exports.debug(\"findOptions.followSpecifiedSymbolicLink: '\" + options.followSpecifiedSymbolicLink + \"'\");\r\n exports.debug(\"findOptions.followSymbolicLinks: '\" + options.followSymbolicLinks + \"'\");\r\n}\r\nfunction _getDefaultFindOptions() {\r\n return {\r\n allowBrokenSymbolicLinks: false,\r\n followSpecifiedSymbolicLink: true,\r\n followSymbolicLinks: true\r\n };\r\n}\r\n/**\r\n * Prefer tl.find() and tl.match() instead. This function is for backward compatibility\r\n * when porting tasks to Node from the PowerShell or PowerShell3 execution handler.\r\n *\r\n * @param rootDirectory path to root unrooted patterns with\r\n * @param pattern include and exclude patterns\r\n * @param includeFiles whether to include files in the result. defaults to true when includeFiles and includeDirectories are both false\r\n * @param includeDirectories whether to include directories in the result\r\n * @returns string[]\r\n */\r\nfunction legacyFindFiles(rootDirectory, pattern, includeFiles, includeDirectories) {\r\n if (!pattern) {\r\n throw new Error('pattern parameter cannot be empty');\r\n }\r\n exports.debug(\"legacyFindFiles rootDirectory: '\" + rootDirectory + \"'\");\r\n exports.debug(\"pattern: '\" + pattern + \"'\");\r\n exports.debug(\"includeFiles: '\" + includeFiles + \"'\");\r\n exports.debug(\"includeDirectories: '\" + includeDirectories + \"'\");\r\n if (!includeFiles && !includeDirectories) {\r\n includeFiles = true;\r\n }\r\n // organize the patterns into include patterns and exclude patterns\r\n var includePatterns = [];\r\n var excludePatterns = [];\r\n pattern = pattern.replace(/;;/g, '\\0');\r\n for (var _i = 0, _a = pattern.split(';'); _i < _a.length; _i++) {\r\n var pat = _a[_i];\r\n if (!pat) {\r\n continue;\r\n }\r\n pat = pat.replace(/\\0/g, ';');\r\n // determine whether include pattern and remove any include/exclude prefix.\r\n // include patterns start with +: or anything other than -:\r\n // exclude patterns start with -:\r\n var isIncludePattern = void 0;\r\n if (im._startsWith(pat, '+:')) {\r\n pat = pat.substring(2);\r\n isIncludePattern = true;\r\n }\r\n else if (im._startsWith(pat, '-:')) {\r\n pat = pat.substring(2);\r\n isIncludePattern = false;\r\n }\r\n else {\r\n isIncludePattern = true;\r\n }\r\n // validate pattern does not end with a slash\r\n if (im._endsWith(pat, '/') || (process.platform == 'win32' && im._endsWith(pat, '\\\\'))) {\r\n throw new Error(exports.loc('LIB_InvalidPattern', pat));\r\n }\r\n // root the pattern\r\n if (rootDirectory && !path.isAbsolute(pat)) {\r\n pat = path.join(rootDirectory, pat);\r\n // remove trailing slash sometimes added by path.join() on Windows, e.g.\r\n // path.join('\\\\\\\\hello', 'world') => '\\\\\\\\hello\\\\world\\\\'\r\n // path.join('//hello', 'world') => '\\\\\\\\hello\\\\world\\\\'\r\n if (im._endsWith(pat, '\\\\')) {\r\n pat = pat.substring(0, pat.length - 1);\r\n }\r\n }\r\n if (isIncludePattern) {\r\n includePatterns.push(pat);\r\n }\r\n else {\r\n excludePatterns.push(im._legacyFindFiles_convertPatternToRegExp(pat));\r\n }\r\n }\r\n // find and apply patterns\r\n var count = 0;\r\n var result = _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, !!includeFiles, !!includeDirectories);\r\n exports.debug('all matches:');\r\n for (var _b = 0, result_1 = result; _b < result_1.length; _b++) {\r\n var resultItem = result_1[_b];\r\n exports.debug(' ' + resultItem);\r\n }\r\n exports.debug('total matched: ' + result.length);\r\n return result;\r\n}\r\nexports.legacyFindFiles = legacyFindFiles;\r\nfunction _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, includeFiles, includeDirectories) {\r\n exports.debug('getMatchingItems()');\r\n for (var _i = 0, includePatterns_1 = includePatterns; _i < includePatterns_1.length; _i++) {\r\n var pattern = includePatterns_1[_i];\r\n exports.debug(\"includePattern: '\" + pattern + \"'\");\r\n }\r\n for (var _a = 0, excludePatterns_1 = excludePatterns; _a < excludePatterns_1.length; _a++) {\r\n var pattern = excludePatterns_1[_a];\r\n exports.debug(\"excludePattern: \" + pattern);\r\n }\r\n exports.debug('includeFiles: ' + includeFiles);\r\n exports.debug('includeDirectories: ' + includeDirectories);\r\n var allFiles = {};\r\n var _loop_2 = function (pattern) {\r\n // determine the directory to search\r\n //\r\n // note, getDirectoryName removes redundant path separators\r\n var findPath = void 0;\r\n var starIndex = pattern.indexOf('*');\r\n var questionIndex = pattern.indexOf('?');\r\n if (starIndex < 0 && questionIndex < 0) {\r\n // if no wildcards are found, use the directory name portion of the path.\r\n // if there is no directory name (file name only in pattern or drive root),\r\n // this will return empty string.\r\n findPath = im._getDirectoryName(pattern);\r\n }\r\n else {\r\n // extract the directory prior to the first wildcard\r\n var index = Math.min(starIndex >= 0 ? starIndex : questionIndex, questionIndex >= 0 ? questionIndex : starIndex);\r\n findPath = im._getDirectoryName(pattern.substring(0, index));\r\n }\r\n // note, due to this short-circuit and the above usage of getDirectoryName, this\r\n // function has the same limitations regarding drive roots as the powershell\r\n // implementation.\r\n //\r\n // also note, since getDirectoryName eliminates slash redundancies, some additional\r\n // work may be required if removal of this limitation is attempted.\r\n if (!findPath) {\r\n return \"continue\";\r\n }\r\n var patternRegex = im._legacyFindFiles_convertPatternToRegExp(pattern);\r\n // find files/directories\r\n var items = find(findPath, { followSymbolicLinks: true })\r\n .filter(function (item) {\r\n if (includeFiles && includeDirectories) {\r\n return true;\r\n }\r\n var isDir = fs.statSync(item).isDirectory();\r\n return (includeFiles && !isDir) || (includeDirectories && isDir);\r\n })\r\n .forEach(function (item) {\r\n var normalizedPath = process.platform == 'win32' ? item.replace(/\\\\/g, '/') : item; // normalize separators\r\n // **/times/** will not match C:/fun/times because there isn't a trailing slash\r\n // so try both if including directories\r\n var alternatePath = normalizedPath + \"/\"; // potential bug: it looks like this will result in a false\r\n // positive if the item is a regular file and not a directory\r\n var isMatch = false;\r\n if (patternRegex.test(normalizedPath) || (includeDirectories && patternRegex.test(alternatePath))) {\r\n isMatch = true;\r\n // test whether the path should be excluded\r\n for (var _i = 0, excludePatterns_2 = excludePatterns; _i < excludePatterns_2.length; _i++) {\r\n var regex = excludePatterns_2[_i];\r\n if (regex.test(normalizedPath) || (includeDirectories && regex.test(alternatePath))) {\r\n isMatch = false;\r\n break;\r\n }\r\n }\r\n }\r\n if (isMatch) {\r\n allFiles[item] = item;\r\n }\r\n });\r\n };\r\n for (var _b = 0, includePatterns_2 = includePatterns; _b < includePatterns_2.length; _b++) {\r\n var pattern = includePatterns_2[_b];\r\n _loop_2(pattern);\r\n }\r\n return Object.keys(allFiles).sort();\r\n}\r\n/**\r\n * Remove a path recursively with force\r\n *\r\n * @param inputPath path to remove\r\n * @throws when the file or directory exists but could not be deleted.\r\n */\r\nfunction rmRF(inputPath) {\r\n exports.debug('rm -rf ' + inputPath);\r\n if (getPlatform() == Platform.Windows) {\r\n // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another\r\n // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.\r\n try {\r\n if (fs.statSync(inputPath).isDirectory()) {\r\n exports.debug('removing directory ' + inputPath);\r\n childProcess.execSync(\"rd /s /q \\\"\" + inputPath + \"\\\"\");\r\n }\r\n else {\r\n exports.debug('removing file ' + inputPath);\r\n childProcess.execSync(\"del /f /a \\\"\" + inputPath + \"\\\"\");\r\n }\r\n }\r\n catch (err) {\r\n // if you try to delete a file that doesn't exist, desired result is achieved\r\n // other errors are valid\r\n if (err.code != 'ENOENT') {\r\n throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));\r\n }\r\n }\r\n // Shelling out fails to remove a symlink folder with missing source, this unlink catches that\r\n try {\r\n fs.unlinkSync(inputPath);\r\n }\r\n catch (err) {\r\n // if you try to delete a file that doesn't exist, desired result is achieved\r\n // other errors are valid\r\n if (err.code != 'ENOENT') {\r\n throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));\r\n }\r\n }\r\n }\r\n else {\r\n // get the lstats in order to workaround a bug in shelljs@0.3.0 where symlinks\r\n // with missing targets are not handled correctly by \"rm('-rf', path)\"\r\n var lstats = void 0;\r\n try {\r\n lstats = fs.lstatSync(inputPath);\r\n }\r\n catch (err) {\r\n // if you try to delete a file that doesn't exist, desired result is achieved\r\n // other errors are valid\r\n if (err.code == 'ENOENT') {\r\n return;\r\n }\r\n throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));\r\n }\r\n if (lstats.isDirectory()) {\r\n exports.debug('removing directory');\r\n shell.rm('-rf', inputPath);\r\n var errMsg = shell.error();\r\n if (errMsg) {\r\n throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', errMsg));\r\n }\r\n return;\r\n }\r\n exports.debug('removing file');\r\n try {\r\n fs.unlinkSync(inputPath);\r\n }\r\n catch (err) {\r\n throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));\r\n }\r\n }\r\n}\r\nexports.rmRF = rmRF;\r\n/**\r\n * Exec a tool. Convenience wrapper over ToolRunner to exec with args in one call.\r\n * Output will be streamed to the live console.\r\n * Returns promise with return code\r\n *\r\n * @param tool path to tool to exec\r\n * @param args an arg string or array of args\r\n * @param options optional exec options. See IExecOptions\r\n * @returns number\r\n */\r\nfunction exec(tool, args, options) {\r\n var tr = this.tool(tool);\r\n tr.on('debug', function (data) {\r\n exports.debug(data);\r\n });\r\n if (args) {\r\n if (args instanceof Array) {\r\n tr.arg(args);\r\n }\r\n else if (typeof (args) === 'string') {\r\n tr.line(args);\r\n }\r\n }\r\n return tr.exec(options);\r\n}\r\nexports.exec = exec;\r\n/**\r\n * Exec a tool synchronously. Convenience wrapper over ToolRunner to execSync with args in one call.\r\n * Output will be *not* be streamed to the live console. It will be returned after execution is complete.\r\n * Appropriate for short running tools\r\n * Returns IExecResult with output and return code\r\n *\r\n * @param tool path to tool to exec\r\n * @param args an arg string or array of args\r\n * @param options optional exec options. See IExecSyncOptions\r\n * @returns IExecSyncResult\r\n */\r\nfunction execSync(tool, args, options) {\r\n var tr = this.tool(tool);\r\n tr.on('debug', function (data) {\r\n exports.debug(data);\r\n });\r\n if (args) {\r\n if (args instanceof Array) {\r\n tr.arg(args);\r\n }\r\n else if (typeof (args) === 'string') {\r\n tr.line(args);\r\n }\r\n }\r\n return tr.execSync(options);\r\n}\r\nexports.execSync = execSync;\r\n/**\r\n * Convenience factory to create a ToolRunner.\r\n *\r\n * @param tool path to tool to exec\r\n * @returns ToolRunner\r\n */\r\nfunction tool(tool) {\r\n var tr = new trm.ToolRunner(tool);\r\n tr.on('debug', function (message) {\r\n exports.debug(message);\r\n });\r\n return tr;\r\n}\r\nexports.tool = tool;\r\n/**\r\n * Applies glob patterns to a list of paths. Supports interleaved exclude patterns.\r\n *\r\n * @param list array of paths\r\n * @param patterns patterns to apply. supports interleaved exclude patterns.\r\n * @param patternRoot optional. default root to apply to unrooted patterns. not applied to basename-only patterns when matchBase:true.\r\n * @param options optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.\r\n */\r\nfunction match(list, patterns, patternRoot, options) {\r\n // trace parameters\r\n exports.debug(\"patternRoot: '\" + patternRoot + \"'\");\r\n options = options || _getDefaultMatchOptions(); // default match options\r\n _debugMatchOptions(options);\r\n // convert pattern to an array\r\n if (typeof patterns == 'string') {\r\n patterns = [patterns];\r\n }\r\n // hashtable to keep track of matches\r\n var map = {};\r\n var originalOptions = options;\r\n for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {\r\n var pattern = patterns_1[_i];\r\n exports.debug(\"pattern: '\" + pattern + \"'\");\r\n // trim and skip empty\r\n pattern = (pattern || '').trim();\r\n if (!pattern) {\r\n exports.debug('skipping empty pattern');\r\n continue;\r\n }\r\n // clone match options\r\n var options_1 = im._cloneMatchOptions(originalOptions);\r\n // skip comments\r\n if (!options_1.nocomment && im._startsWith(pattern, '#')) {\r\n exports.debug('skipping comment');\r\n continue;\r\n }\r\n // set nocomment - brace expansion could result in a leading '#'\r\n options_1.nocomment = true;\r\n // determine whether pattern is include or exclude\r\n var negateCount = 0;\r\n if (!options_1.nonegate) {\r\n while (pattern.charAt(negateCount) == '!') {\r\n negateCount++;\r\n }\r\n pattern = pattern.substring(negateCount); // trim leading '!'\r\n if (negateCount) {\r\n exports.debug(\"trimmed leading '!'. pattern: '\" + pattern + \"'\");\r\n }\r\n }\r\n var isIncludePattern = negateCount == 0 ||\r\n (negateCount % 2 == 0 && !options_1.flipNegate) ||\r\n (negateCount % 2 == 1 && options_1.flipNegate);\r\n // set nonegate - brace expansion could result in a leading '!'\r\n options_1.nonegate = true;\r\n options_1.flipNegate = false;\r\n // expand braces - required to accurately root patterns\r\n var expanded = void 0;\r\n var preExpanded = pattern;\r\n if (options_1.nobrace) {\r\n expanded = [pattern];\r\n }\r\n else {\r\n // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot\r\n // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).\r\n exports.debug('expanding braces');\r\n var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\\\/g, '/') : pattern;\r\n expanded = minimatch.braceExpand(convertedPattern);\r\n }\r\n // set nobrace\r\n options_1.nobrace = true;\r\n for (var _a = 0, expanded_1 = expanded; _a < expanded_1.length; _a++) {\r\n var pattern_1 = expanded_1[_a];\r\n if (expanded.length != 1 || pattern_1 != preExpanded) {\r\n exports.debug(\"pattern: '\" + pattern_1 + \"'\");\r\n }\r\n // trim and skip empty\r\n pattern_1 = (pattern_1 || '').trim();\r\n if (!pattern_1) {\r\n exports.debug('skipping empty pattern');\r\n continue;\r\n }\r\n // root the pattern when all of the following conditions are true:\r\n if (patternRoot && // patternRoot supplied\r\n !im._isRooted(pattern_1) && // AND pattern not rooted\r\n // AND matchBase:false or not basename only\r\n (!options_1.matchBase || (process.platform == 'win32' ? pattern_1.replace(/\\\\/g, '/') : pattern_1).indexOf('/') >= 0)) {\r\n pattern_1 = im._ensureRooted(patternRoot, pattern_1);\r\n exports.debug(\"rooted pattern: '\" + pattern_1 + \"'\");\r\n }\r\n if (isIncludePattern) {\r\n // apply the pattern\r\n exports.debug('applying include pattern against original list');\r\n var matchResults = minimatch.match(list, pattern_1, options_1);\r\n exports.debug(matchResults.length + ' matches');\r\n // union the results\r\n for (var _b = 0, matchResults_1 = matchResults; _b < matchResults_1.length; _b++) {\r\n var matchResult = matchResults_1[_b];\r\n map[matchResult] = true;\r\n }\r\n }\r\n else {\r\n // apply the pattern\r\n exports.debug('applying exclude pattern against original list');\r\n var matchResults = minimatch.match(list, pattern_1, options_1);\r\n exports.debug(matchResults.length + ' matches');\r\n // substract the results\r\n for (var _c = 0, matchResults_2 = matchResults; _c < matchResults_2.length; _c++) {\r\n var matchResult = matchResults_2[_c];\r\n delete map[matchResult];\r\n }\r\n }\r\n }\r\n }\r\n // return a filtered version of the original list (preserves order and prevents duplication)\r\n var result = list.filter(function (item) { return map.hasOwnProperty(item); });\r\n exports.debug(result.length + ' final results');\r\n return result;\r\n}\r\nexports.match = match;\r\n/**\r\n * Filter to apply glob patterns\r\n *\r\n * @param pattern pattern to apply\r\n * @param options optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.\r\n */\r\nfunction filter(pattern, options) {\r\n options = options || _getDefaultMatchOptions();\r\n return minimatch.filter(pattern, options);\r\n}\r\nexports.filter = filter;\r\nfunction _debugMatchOptions(options) {\r\n exports.debug(\"matchOptions.debug: '\" + options.debug + \"'\");\r\n exports.debug(\"matchOptions.nobrace: '\" + options.nobrace + \"'\");\r\n exports.debug(\"matchOptions.noglobstar: '\" + options.noglobstar + \"'\");\r\n exports.debug(\"matchOptions.dot: '\" + options.dot + \"'\");\r\n exports.debug(\"matchOptions.noext: '\" + options.noext + \"'\");\r\n exports.debug(\"matchOptions.nocase: '\" + options.nocase + \"'\");\r\n exports.debug(\"matchOptions.nonull: '\" + options.nonull + \"'\");\r\n exports.debug(\"matchOptions.matchBase: '\" + options.matchBase + \"'\");\r\n exports.debug(\"matchOptions.nocomment: '\" + options.nocomment + \"'\");\r\n exports.debug(\"matchOptions.nonegate: '\" + options.nonegate + \"'\");\r\n exports.debug(\"matchOptions.flipNegate: '\" + options.flipNegate + \"'\");\r\n}\r\nfunction _getDefaultMatchOptions() {\r\n return {\r\n debug: false,\r\n nobrace: true,\r\n noglobstar: false,\r\n dot: true,\r\n noext: false,\r\n nocase: process.platform == 'win32',\r\n nonull: false,\r\n matchBase: false,\r\n nocomment: false,\r\n nonegate: false,\r\n flipNegate: false\r\n };\r\n}\r\n/**\r\n * Determines the find root from a list of patterns. Performs the find and then applies the glob patterns.\r\n * Supports interleaved exclude patterns. Unrooted patterns are rooted using defaultRoot, unless\r\n * matchOptions.matchBase is specified and the pattern is a basename only. For matchBase cases, the\r\n * defaultRoot is used as the find root.\r\n *\r\n * @param defaultRoot default path to root unrooted patterns. falls back to System.DefaultWorkingDirectory or process.cwd().\r\n * @param patterns pattern or array of patterns to apply\r\n * @param findOptions defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.\r\n * @param matchOptions defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }\r\n */\r\nfunction findMatch(defaultRoot, patterns, findOptions, matchOptions) {\r\n // apply defaults for parameters and trace\r\n defaultRoot = defaultRoot || this.getVariable('system.defaultWorkingDirectory') || process.cwd();\r\n exports.debug(\"defaultRoot: '\" + defaultRoot + \"'\");\r\n patterns = patterns || [];\r\n patterns = typeof patterns == 'string' ? [patterns] : patterns;\r\n findOptions = findOptions || _getDefaultFindOptions();\r\n _debugFindOptions(findOptions);\r\n matchOptions = matchOptions || _getDefaultMatchOptions();\r\n _debugMatchOptions(matchOptions);\r\n // normalize slashes for root dir\r\n defaultRoot = im._normalizeSeparators(defaultRoot);\r\n var results = {};\r\n var originalMatchOptions = matchOptions;\r\n for (var _i = 0, _a = (patterns || []); _i < _a.length; _i++) {\r\n var pattern = _a[_i];\r\n exports.debug(\"pattern: '\" + pattern + \"'\");\r\n // trim and skip empty\r\n pattern = (pattern || '').trim();\r\n if (!pattern) {\r\n exports.debug('skipping empty pattern');\r\n continue;\r\n }\r\n // clone match options\r\n var matchOptions_1 = im._cloneMatchOptions(originalMatchOptions);\r\n // skip comments\r\n if (!matchOptions_1.nocomment && im._startsWith(pattern, '#')) {\r\n exports.debug('skipping comment');\r\n continue;\r\n }\r\n // set nocomment - brace expansion could result in a leading '#'\r\n matchOptions_1.nocomment = true;\r\n // determine whether pattern is include or exclude\r\n var negateCount = 0;\r\n if (!matchOptions_1.nonegate) {\r\n while (pattern.charAt(negateCount) == '!') {\r\n negateCount++;\r\n }\r\n pattern = pattern.substring(negateCount); // trim leading '!'\r\n if (negateCount) {\r\n exports.debug(\"trimmed leading '!'. pattern: '\" + pattern + \"'\");\r\n }\r\n }\r\n var isIncludePattern = negateCount == 0 ||\r\n (negateCount % 2 == 0 && !matchOptions_1.flipNegate) ||\r\n (negateCount % 2 == 1 && matchOptions_1.flipNegate);\r\n // set nonegate - brace expansion could result in a leading '!'\r\n matchOptions_1.nonegate = true;\r\n matchOptions_1.flipNegate = false;\r\n // expand braces - required to accurately interpret findPath\r\n var expanded = void 0;\r\n var preExpanded = pattern;\r\n if (matchOptions_1.nobrace) {\r\n expanded = [pattern];\r\n }\r\n else {\r\n // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot\r\n // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).\r\n exports.debug('expanding braces');\r\n var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\\\/g, '/') : pattern;\r\n expanded = minimatch.braceExpand(convertedPattern);\r\n }\r\n // set nobrace\r\n matchOptions_1.nobrace = true;\r\n for (var _b = 0, expanded_2 = expanded; _b < expanded_2.length; _b++) {\r\n var pattern_2 = expanded_2[_b];\r\n if (expanded.length != 1 || pattern_2 != preExpanded) {\r\n exports.debug(\"pattern: '\" + pattern_2 + \"'\");\r\n }\r\n // trim and skip empty\r\n pattern_2 = (pattern_2 || '').trim();\r\n if (!pattern_2) {\r\n exports.debug('skipping empty pattern');\r\n continue;\r\n }\r\n if (isIncludePattern) {\r\n // determine the findPath\r\n var findInfo = im._getFindInfoFromPattern(defaultRoot, pattern_2, matchOptions_1);\r\n var findPath = findInfo.findPath;\r\n exports.debug(\"findPath: '\" + findPath + \"'\");\r\n if (!findPath) {\r\n exports.debug('skipping empty path');\r\n continue;\r\n }\r\n // perform the find\r\n exports.debug(\"statOnly: '\" + findInfo.statOnly + \"'\");\r\n var findResults = [];\r\n if (findInfo.statOnly) {\r\n // simply stat the path - all path segments were used to build the path\r\n try {\r\n fs.statSync(findPath);\r\n findResults.push(findPath);\r\n }\r\n catch (err) {\r\n if (err.code != 'ENOENT') {\r\n throw err;\r\n }\r\n exports.debug('ENOENT');\r\n }\r\n }\r\n else {\r\n findResults = find(findPath, findOptions);\r\n }\r\n exports.debug(\"found \" + findResults.length + \" paths\");\r\n // apply the pattern\r\n exports.debug('applying include pattern');\r\n if (findInfo.adjustedPattern != pattern_2) {\r\n exports.debug(\"adjustedPattern: '\" + findInfo.adjustedPattern + \"'\");\r\n pattern_2 = findInfo.adjustedPattern;\r\n }\r\n var matchResults = minimatch.match(findResults, pattern_2, matchOptions_1);\r\n exports.debug(matchResults.length + ' matches');\r\n // union the results\r\n for (var _c = 0, matchResults_3 = matchResults; _c < matchResults_3.length; _c++) {\r\n var matchResult = matchResults_3[_c];\r\n var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;\r\n results[key] = matchResult;\r\n }\r\n }\r\n else {\r\n // check if basename only and matchBase=true\r\n if (matchOptions_1.matchBase &&\r\n !im._isRooted(pattern_2) &&\r\n (process.platform == 'win32' ? pattern_2.replace(/\\\\/g, '/') : pattern_2).indexOf('/') < 0) {\r\n // do not root the pattern\r\n exports.debug('matchBase and basename only');\r\n }\r\n else {\r\n // root the exclude pattern\r\n pattern_2 = im._ensurePatternRooted(defaultRoot, pattern_2);\r\n exports.debug(\"after ensurePatternRooted, pattern: '\" + pattern_2 + \"'\");\r\n }\r\n // apply the pattern\r\n exports.debug('applying exclude pattern');\r\n var matchResults = minimatch.match(Object.keys(results).map(function (key) { return results[key]; }), pattern_2, matchOptions_1);\r\n exports.debug(matchResults.length + ' matches');\r\n // substract the results\r\n for (var _d = 0, matchResults_4 = matchResults; _d < matchResults_4.length; _d++) {\r\n var matchResult = matchResults_4[_d];\r\n var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;\r\n delete results[key];\r\n }\r\n }\r\n }\r\n }\r\n var finalResult = Object.keys(results)\r\n .map(function (key) { return results[key]; })\r\n .sort();\r\n exports.debug(finalResult.length + ' final results');\r\n return finalResult;\r\n}\r\nexports.findMatch = findMatch;\r\n/**\r\n * Gets http proxy configuration used by Build/Release agent\r\n *\r\n * @return ProxyConfiguration\r\n */\r\nfunction getHttpProxyConfiguration(requestUrl) {\r\n var proxyUrl = exports.getVariable('Agent.ProxyUrl');\r\n if (proxyUrl && proxyUrl.length > 0) {\r\n var proxyUsername = exports.getVariable('Agent.ProxyUsername');\r\n var proxyPassword = exports.getVariable('Agent.ProxyPassword');\r\n var proxyBypassHosts = JSON.parse(exports.getVariable('Agent.ProxyBypassList') || '[]');\r\n var bypass_1 = false;\r\n if (requestUrl) {\r\n proxyBypassHosts.forEach(function (bypassHost) {\r\n if (new RegExp(bypassHost, 'i').test(requestUrl)) {\r\n bypass_1 = true;\r\n }\r\n });\r\n }\r\n if (bypass_1) {\r\n return null;\r\n }\r\n else {\r\n return {\r\n proxyUrl: proxyUrl,\r\n proxyUsername: proxyUsername,\r\n proxyPassword: proxyPassword,\r\n proxyBypassHosts: proxyBypassHosts\r\n };\r\n }\r\n }\r\n else {\r\n return null;\r\n }\r\n}\r\nexports.getHttpProxyConfiguration = getHttpProxyConfiguration;\r\n/**\r\n * Gets http certificate configuration used by Build/Release agent\r\n *\r\n * @return CertConfiguration\r\n */\r\nfunction getHttpCertConfiguration() {\r\n var ca = exports.getVariable('Agent.CAInfo');\r\n var clientCert = exports.getVariable('Agent.ClientCert');\r\n if (ca || clientCert) {\r\n var certConfig = {};\r\n certConfig.caFile = ca;\r\n certConfig.certFile = clientCert;\r\n if (clientCert) {\r\n var clientCertKey = exports.getVariable('Agent.ClientCertKey');\r\n var clientCertArchive = exports.getVariable('Agent.ClientCertArchive');\r\n var clientCertPassword = exports.getVariable('Agent.ClientCertPassword');\r\n certConfig.keyFile = clientCertKey;\r\n certConfig.certArchiveFile = clientCertArchive;\r\n certConfig.passphrase = clientCertPassword;\r\n }\r\n return certConfig;\r\n }\r\n else {\r\n return null;\r\n }\r\n}\r\nexports.getHttpCertConfiguration = getHttpCertConfiguration;\r\n//-----------------------------------------------------\r\n// Test Publisher\r\n//-----------------------------------------------------\r\nvar TestPublisher = /** @class */ (function () {\r\n function TestPublisher(testRunner) {\r\n this.testRunner = testRunner;\r\n }\r\n TestPublisher.prototype.publish = function (resultFiles, mergeResults, platform, config, runTitle, publishRunAttachments, testRunSystem) {\r\n // Could have used an initializer, but wanted to avoid reordering parameters when converting to strict null checks\r\n // (A parameter cannot both be optional and have an initializer)\r\n testRunSystem = testRunSystem || \"VSTSTask\";\r\n var properties = {};\r\n properties['type'] = this.testRunner;\r\n if (mergeResults) {\r\n properties['mergeResults'] = mergeResults;\r\n }\r\n if (platform) {\r\n properties['platform'] = platform;\r\n }\r\n if (config) {\r\n properties['config'] = config;\r\n }\r\n if (runTitle) {\r\n properties['runTitle'] = runTitle;\r\n }\r\n if (publishRunAttachments) {\r\n properties['publishRunAttachments'] = publishRunAttachments;\r\n }\r\n if (resultFiles) {\r\n properties['resultFiles'] = Array.isArray(resultFiles) ? resultFiles.join() : resultFiles;\r\n }\r\n properties['testRunSystem'] = testRunSystem;\r\n exports.command('results.publish', properties, '');\r\n };\r\n return TestPublisher;\r\n}());\r\nexports.TestPublisher = TestPublisher;\r\n//-----------------------------------------------------\r\n// Code coverage Publisher\r\n//-----------------------------------------------------\r\nvar CodeCoveragePublisher = /** @class */ (function () {\r\n function CodeCoveragePublisher() {\r\n }\r\n CodeCoveragePublisher.prototype.publish = function (codeCoverageTool, summaryFileLocation, reportDirectory, additionalCodeCoverageFiles) {\r\n var properties = {};\r\n if (codeCoverageTool) {\r\n properties['codecoveragetool'] = codeCoverageTool;\r\n }\r\n if (summaryFileLocation) {\r\n properties['summaryfile'] = summaryFileLocation;\r\n }\r\n if (reportDirectory) {\r\n properties['reportdirectory'] = reportDirectory;\r\n }\r\n if (additionalCodeCoverageFiles) {\r\n properties['additionalcodecoveragefiles'] = Array.isArray(additionalCodeCoverageFiles) ? additionalCodeCoverageFiles.join() : additionalCodeCoverageFiles;\r\n }\r\n exports.command('codecoverage.publish', properties, \"\");\r\n };\r\n return CodeCoveragePublisher;\r\n}());\r\nexports.CodeCoveragePublisher = CodeCoveragePublisher;\r\n//-----------------------------------------------------\r\n// Code coverage Publisher\r\n//-----------------------------------------------------\r\nvar CodeCoverageEnabler = /** @class */ (function () {\r\n function CodeCoverageEnabler(buildTool, ccTool) {\r\n this.buildTool = buildTool;\r\n this.ccTool = ccTool;\r\n }\r\n CodeCoverageEnabler.prototype.enableCodeCoverage = function (buildProps) {\r\n buildProps['buildtool'] = this.buildTool;\r\n buildProps['codecoveragetool'] = this.ccTool;\r\n exports.command('codecoverage.enable', buildProps, \"\");\r\n };\r\n return CodeCoverageEnabler;\r\n}());\r\nexports.CodeCoverageEnabler = CodeCoverageEnabler;\r\n//-----------------------------------------------------\r\n// Task Logging Commands\r\n//-----------------------------------------------------\r\n/**\r\n * Upload user interested file as additional log information\r\n * to the current timeline record.\r\n *\r\n * The file shall be available for download along with task logs.\r\n *\r\n * @param path Path to the file that should be uploaded.\r\n * @returns void\r\n */\r\nfunction uploadFile(path) {\r\n exports.command(\"task.uploadfile\", null, path);\r\n}\r\nexports.uploadFile = uploadFile;\r\n/**\r\n * Instruction for the agent to update the PATH environment variable.\r\n * The specified directory is prepended to the PATH.\r\n * The updated environment variable will be reflected in subsequent tasks.\r\n *\r\n * @param path Local directory path.\r\n * @returns void\r\n */\r\nfunction prependPath(path) {\r\n assertAgent(\"2.115.0\");\r\n exports.command(\"task.prependpath\", null, path);\r\n}\r\nexports.prependPath = prependPath;\r\n/**\r\n * Upload and attach summary markdown to current timeline record.\r\n * This summary shall be added to the build/release summary and\r\n * not available for download with logs.\r\n *\r\n * @param path Local directory path.\r\n * @returns void\r\n */\r\nfunction uploadSummary(path) {\r\n exports.command(\"task.uploadsummary\", null, path);\r\n}\r\nexports.uploadSummary = uploadSummary;\r\n/**\r\n * Upload and attach attachment to current timeline record.\r\n * These files are not available for download with logs.\r\n * These can only be referred to by extensions using the type or name values.\r\n *\r\n * @param type Attachment type.\r\n * @param name Attachment name.\r\n * @param path Attachment path.\r\n * @returns void\r\n */\r\nfunction addAttachment(type, name, path) {\r\n exports.command(\"task.addattachment\", { \"type\": type, \"name\": name }, path);\r\n}\r\nexports.addAttachment = addAttachment;\r\n/**\r\n * Set an endpoint field with given value.\r\n * Value updated will be retained in the endpoint for\r\n * the subsequent tasks that execute within the same job.\r\n *\r\n * @param id Endpoint id.\r\n * @param field FieldType enum of AuthParameter, DataParameter or Url.\r\n * @param key Key.\r\n * @param value Value for key or url.\r\n * @returns void\r\n */\r\nfunction setEndpoint(id, field, key, value) {\r\n exports.command(\"task.setendpoint\", { \"id\": id, \"field\": FieldType[field].toLowerCase(), \"key\": key }, value);\r\n}\r\nexports.setEndpoint = setEndpoint;\r\n/**\r\n * Set progress and current operation for current task.\r\n *\r\n * @param percent Percentage of completion.\r\n * @param currentOperation Current pperation.\r\n * @returns void\r\n */\r\nfunction setProgress(percent, currentOperation) {\r\n exports.command(\"task.setprogress\", { \"value\": \"\" + percent }, currentOperation);\r\n}\r\nexports.setProgress = setProgress;\r\n/**\r\n * Indicates whether to write the logging command directly to the host or to the output pipeline.\r\n *\r\n * @param id Timeline record Guid.\r\n * @param parentId Parent timeline record Guid.\r\n * @param recordType Record type.\r\n * @param recordName Record name.\r\n * @param order Order of timeline record.\r\n * @param startTime Start time.\r\n * @param finishTime End time.\r\n * @param progress Percentage of completion.\r\n * @param state TaskState enum of Unknown, Initialized, InProgress or Completed.\r\n * @param result TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.\r\n * @param message current operation\r\n * @returns void\r\n */\r\nfunction logDetail(id, message, parentId, recordType, recordName, order, startTime, finishTime, progress, state, result) {\r\n var properties = {\r\n \"id\": id,\r\n \"parentid\": parentId,\r\n \"type\": recordType,\r\n \"name\": recordName,\r\n \"order\": order ? order.toString() : undefined,\r\n \"starttime\": startTime,\r\n \"finishtime\": finishTime,\r\n \"progress\": progress ? progress.toString() : undefined,\r\n \"state\": state ? TaskState[state] : undefined,\r\n \"result\": result ? TaskResult[result] : undefined\r\n };\r\n exports.command(\"task.logdetail\", properties, message);\r\n}\r\nexports.logDetail = logDetail;\r\n/**\r\n * Log error or warning issue to timeline record of current task.\r\n *\r\n * @param type IssueType enum of Error or Warning.\r\n * @param sourcePath Source file location.\r\n * @param lineNumber Line number.\r\n * @param columnNumber Column number.\r\n * @param code Error or warning code.\r\n * @param message Error or warning message.\r\n * @returns void\r\n */\r\nfunction logIssue(type, message, sourcePath, lineNumber, columnNumber, errorCode) {\r\n var properties = {\r\n \"type\": IssueType[type].toLowerCase(),\r\n \"code\": errorCode,\r\n \"sourcepath\": sourcePath,\r\n \"linenumber\": lineNumber ? lineNumber.toString() : undefined,\r\n \"columnnumber\": columnNumber ? columnNumber.toString() : undefined,\r\n };\r\n exports.command(\"task.logissue\", properties, message);\r\n}\r\nexports.logIssue = logIssue;\r\n//-----------------------------------------------------\r\n// Artifact Logging Commands\r\n//-----------------------------------------------------\r\n/**\r\n * Upload user interested file as additional log information\r\n * to the current timeline record.\r\n *\r\n * The file shall be available for download along with task logs.\r\n *\r\n * @param containerFolder Folder that the file will upload to, folder will be created if needed.\r\n * @param path Path to the file that should be uploaded.\r\n * @param name Artifact name.\r\n * @returns void\r\n */\r\nfunction uploadArtifact(containerFolder, path, name) {\r\n exports.command(\"artifact.upload\", { \"containerfolder\": containerFolder, \"artifactname\": name }, path);\r\n}\r\nexports.uploadArtifact = uploadArtifact;\r\n/**\r\n * Create an artifact link, artifact location is required to be\r\n * a file container path, VC path or UNC share path.\r\n *\r\n * The file shall be available for download along with task logs.\r\n *\r\n * @param name Artifact name.\r\n * @param path Path to the file that should be associated.\r\n * @param artifactType ArtifactType enum of Container, FilePath, VersionControl, GitRef or TfvcLabel.\r\n * @returns void\r\n */\r\nfunction associateArtifact(name, path, artifactType) {\r\n exports.command(\"artifact.associate\", { \"type\": ArtifactType[artifactType].toLowerCase(), \"artifactname\": name }, path);\r\n}\r\nexports.associateArtifact = associateArtifact;\r\n//-----------------------------------------------------\r\n// Build Logging Commands\r\n//-----------------------------------------------------\r\n/**\r\n * Upload user interested log to build’s container “logs\\tool” folder.\r\n *\r\n * @param path Path to the file that should be uploaded.\r\n * @returns void\r\n */\r\nfunction uploadBuildLog(path) {\r\n exports.command(\"build.uploadlog\", null, path);\r\n}\r\nexports.uploadBuildLog = uploadBuildLog;\r\n/**\r\n * Update build number for current build.\r\n *\r\n * @param value Value to be assigned as the build number.\r\n * @returns void\r\n */\r\nfunction updateBuildNumber(value) {\r\n exports.command(\"build.updatebuildnumber\", null, value);\r\n}\r\nexports.updateBuildNumber = updateBuildNumber;\r\n/**\r\n * Add a tag for current build.\r\n *\r\n * @param value Tag value.\r\n * @returns void\r\n */\r\nfunction addBuildTag(value) {\r\n exports.command(\"build.addbuildtag\", null, value);\r\n}\r\nexports.addBuildTag = addBuildTag;\r\n//-----------------------------------------------------\r\n// Release Logging Commands\r\n//-----------------------------------------------------\r\n/**\r\n * Update release name for current release.\r\n *\r\n * @param value Value to be assigned as the release name.\r\n * @returns void\r\n */\r\nfunction updateReleaseName(name) {\r\n assertAgent(\"2.132\");\r\n exports.command(\"release.updatereleasename\", null, name);\r\n}\r\nexports.updateReleaseName = updateReleaseName;\r\n//-----------------------------------------------------\r\n// Tools\r\n//-----------------------------------------------------\r\nexports.TaskCommand = tcm.TaskCommand;\r\nexports.commandFromString = tcm.commandFromString;\r\nexports.ToolRunner = trm.ToolRunner;\r\n//-----------------------------------------------------\r\n// Validation Checks\r\n//-----------------------------------------------------\r\n// async await needs generators in node 4.x+\r\nif (semver.lt(process.versions.node, '4.2.0')) {\r\n this.warning('Tasks require a new agent. Upgrade your agent or node to 4.2.0 or later');\r\n}\r\n//-------------------------------------------------------------------\r\n// Populate the vault with sensitive data. Inputs and Endpoints\r\n//-------------------------------------------------------------------\r\n// avoid loading twice (overwrites .taskkey)\r\nif (!global['_vsts_task_lib_loaded']) {\r\n im._loadData();\r\n im._exposeProxySettings();\r\n im._exposeCertSettings();\r\n}\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n//\r\n// Command Format:\r\n// ##vso[artifact.command key=value;key=value]user message\r\n// \r\n// Examples:\r\n// ##vso[task.progress value=58]\r\n// ##vso[task.issue type=warning;]This is the user warning message\r\n//\r\nvar CMD_PREFIX = '##vso[';\r\nvar TaskCommand = /** @class */ (function () {\r\n function TaskCommand(command, properties, message) {\r\n if (!command) {\r\n command = 'missing.command';\r\n }\r\n this.command = command;\r\n this.properties = properties;\r\n this.message = message;\r\n }\r\n TaskCommand.prototype.toString = function () {\r\n var cmdStr = CMD_PREFIX + this.command;\r\n if (this.properties && Object.keys(this.properties).length > 0) {\r\n cmdStr += ' ';\r\n for (var key in this.properties) {\r\n if (this.properties.hasOwnProperty(key)) {\r\n var val = this.properties[key];\r\n if (val) {\r\n // safely append the val - avoid blowing up when attempting to\r\n // call .replace() if message is not a string for some reason\r\n cmdStr += key + '=' + escape('' + (val || '')) + ';';\r\n }\r\n }\r\n }\r\n }\r\n cmdStr += ']';\r\n // safely append the message - avoid blowing up when attempting to\r\n // call .replace() if message is not a string for some reason\r\n var message = '' + (this.message || '');\r\n cmdStr += escapedata(message);\r\n return cmdStr;\r\n };\r\n return TaskCommand;\r\n}());\r\nexports.TaskCommand = TaskCommand;\r\nfunction commandFromString(commandLine) {\r\n var preLen = CMD_PREFIX.length;\r\n var lbPos = commandLine.indexOf('[');\r\n var rbPos = commandLine.indexOf(']');\r\n if (lbPos == -1 || rbPos == -1 || rbPos - lbPos < 3) {\r\n throw new Error('Invalid command brackets');\r\n }\r\n var cmdInfo = commandLine.substring(lbPos + 1, rbPos);\r\n var spaceIdx = cmdInfo.indexOf(' ');\r\n var command = cmdInfo;\r\n var properties = {};\r\n if (spaceIdx > 0) {\r\n command = cmdInfo.trim().substring(0, spaceIdx);\r\n var propSection = cmdInfo.trim().substring(spaceIdx + 1);\r\n var propLines = propSection.split(';');\r\n propLines.forEach(function (propLine) {\r\n propLine = propLine.trim();\r\n if (propLine.length > 0) {\r\n var eqIndex = propLine.indexOf('=');\r\n if (eqIndex == -1) {\r\n throw new Error('Invalid property: ' + propLine);\r\n }\r\n var key = propLine.substring(0, eqIndex);\r\n var val = propLine.substring(eqIndex + 1);\r\n properties[key] = unescape(val);\r\n }\r\n });\r\n }\r\n var msg = unescapedata(commandLine.substring(rbPos + 1));\r\n var cmd = new TaskCommand(command, properties, msg);\r\n return cmd;\r\n}\r\nexports.commandFromString = commandFromString;\r\nfunction escapedata(s) {\r\n return s.replace(/%/g, '%25')\r\n .replace(/\\r/g, '%0D')\r\n .replace(/\\n/g, '%0A');\r\n}\r\nfunction unescapedata(s) {\r\n return s.replace(/%0D/g, '\\r')\r\n .replace(/%0A/g, '\\n')\r\n .replace(/%25/g, '%');\r\n}\r\nfunction escape(s) {\r\n return s.replace(/%/g, '%25')\r\n .replace(/\\r/g, '%0D')\r\n .replace(/\\n/g, '%0A')\r\n .replace(/]/g, '%5D')\r\n .replace(/;/g, '%3B');\r\n}\r\nfunction unescape(s) {\r\n return s.replace(/%0D/g, '\\r')\r\n .replace(/%0A/g, '\\n')\r\n .replace(/%5D/g, ']')\r\n .replace(/%3B/g, ';')\r\n .replace(/%25/g, '%');\r\n}\r\n","\"use strict\";\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = function (d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n }\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar Q = require(\"q\");\r\nvar os = require(\"os\");\r\nvar events = require(\"events\");\r\nvar child = require(\"child_process\");\r\nvar im = require(\"./internal\");\r\nvar fs = require(\"fs\");\r\nvar ToolRunner = /** @class */ (function (_super) {\r\n __extends(ToolRunner, _super);\r\n function ToolRunner(toolPath) {\r\n var _this = _super.call(this) || this;\r\n _this.cmdSpecialChars = [' ', '\\t', '&', '(', ')', '[', ']', '{', '}', '^', '=', ';', '!', '\\'', '+', ',', '`', '~', '|', '<', '>', '\"'];\r\n if (!toolPath) {\r\n throw new Error('Parameter \\'toolPath\\' cannot be null or empty.');\r\n }\r\n _this.toolPath = im._which(toolPath, true);\r\n _this.args = [];\r\n _this._debug('toolRunner toolPath: ' + toolPath);\r\n return _this;\r\n }\r\n ToolRunner.prototype._debug = function (message) {\r\n this.emit('debug', message);\r\n };\r\n ToolRunner.prototype._argStringToArray = function (argString) {\r\n var args = [];\r\n var inQuotes = false;\r\n var escaped = false;\r\n var lastCharWasSpace = true;\r\n var arg = '';\r\n var append = function (c) {\r\n // we only escape double quotes.\r\n if (escaped && c !== '\"') {\r\n arg += '\\\\';\r\n }\r\n arg += c;\r\n escaped = false;\r\n };\r\n for (var i = 0; i < argString.length; i++) {\r\n var c = argString.charAt(i);\r\n if (c === ' ' && !inQuotes) {\r\n if (!lastCharWasSpace) {\r\n args.push(arg);\r\n arg = '';\r\n }\r\n lastCharWasSpace = true;\r\n continue;\r\n }\r\n else {\r\n lastCharWasSpace = false;\r\n }\r\n if (c === '\"') {\r\n if (!escaped) {\r\n inQuotes = !inQuotes;\r\n }\r\n else {\r\n append(c);\r\n }\r\n continue;\r\n }\r\n if (c === \"\\\\\" && escaped) {\r\n append(c);\r\n continue;\r\n }\r\n if (c === \"\\\\\" && inQuotes) {\r\n escaped = true;\r\n continue;\r\n }\r\n append(c);\r\n lastCharWasSpace = false;\r\n }\r\n if (!lastCharWasSpace) {\r\n args.push(arg.trim());\r\n }\r\n return args;\r\n };\r\n ToolRunner.prototype._getCommandString = function (options, noPrefix) {\r\n var _this = this;\r\n var toolPath = this._getSpawnFileName();\r\n var args = this._getSpawnArgs(options);\r\n var cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool\r\n var commandParts = [];\r\n if (process.platform == 'win32') {\r\n // Windows + cmd file\r\n if (this._isCmdFile()) {\r\n commandParts.push(toolPath);\r\n commandParts = commandParts.concat(args);\r\n }\r\n // Windows + verbatim\r\n else if (options.windowsVerbatimArguments) {\r\n commandParts.push(\"\\\"\" + toolPath + \"\\\"\");\r\n commandParts = commandParts.concat(args);\r\n }\r\n else if (options.shell) {\r\n commandParts.push(this._windowsQuoteCmdArg(toolPath));\r\n commandParts = commandParts.concat(args);\r\n }\r\n // Windows (regular)\r\n else {\r\n commandParts.push(this._windowsQuoteCmdArg(toolPath));\r\n commandParts = commandParts.concat(args.map(function (arg) { return _this._windowsQuoteCmdArg(arg); }));\r\n }\r\n }\r\n else {\r\n // OSX/Linux - this can likely be improved with some form of quoting.\r\n // creating processes on Unix is fundamentally different than Windows.\r\n // on Unix, execvp() takes an arg array.\r\n commandParts.push(toolPath);\r\n commandParts = commandParts.concat(args);\r\n }\r\n cmd += commandParts.join(' ');\r\n // append second tool\r\n if (this.pipeOutputToTool) {\r\n cmd += ' | ' + this.pipeOutputToTool._getCommandString(options, /*noPrefix:*/ true);\r\n }\r\n return cmd;\r\n };\r\n ToolRunner.prototype._processLineBuffer = function (data, strBuffer, onLine) {\r\n try {\r\n var s = strBuffer + data.toString();\r\n var n = s.indexOf(os.EOL);\r\n while (n > -1) {\r\n var line = s.substring(0, n);\r\n onLine(line);\r\n // the rest of the string ...\r\n s = s.substring(n + os.EOL.length);\r\n n = s.indexOf(os.EOL);\r\n }\r\n strBuffer = s;\r\n }\r\n catch (err) {\r\n // streaming lines to console is best effort. Don't fail a build.\r\n this._debug('error processing line');\r\n }\r\n };\r\n /**\r\n * Wraps an arg string with specified char if it's not already wrapped\r\n * @returns {string} Arg wrapped with specified char\r\n * @param {string} arg Input argument string\r\n * @param {string} wrapChar A char input string should be wrapped with\r\n */\r\n ToolRunner.prototype._wrapArg = function (arg, wrapChar) {\r\n if (!this._isWrapped(arg, wrapChar)) {\r\n return \"\" + wrapChar + arg + wrapChar;\r\n }\r\n return arg;\r\n };\r\n /**\r\n * Unwraps an arg string wrapped with specified char\r\n * @param arg Arg wrapped with specified char\r\n * @param wrapChar A char to be removed\r\n */\r\n ToolRunner.prototype._unwrapArg = function (arg, wrapChar) {\r\n if (this._isWrapped(arg, wrapChar)) {\r\n var pattern = new RegExp(\"(^\\\\\\\\?\" + wrapChar + \")|(\\\\\\\\?\" + wrapChar + \"$)\", 'g');\r\n return arg.trim().replace(pattern, '');\r\n }\r\n return arg;\r\n };\r\n /**\r\n * Determine if arg string is wrapped with specified char\r\n * @param arg Input arg string\r\n */\r\n ToolRunner.prototype._isWrapped = function (arg, wrapChar) {\r\n var pattern = new RegExp(\"^\\\\\\\\?\" + wrapChar + \".+\\\\\\\\?\" + wrapChar + \"$\");\r\n return pattern.test(arg.trim());\r\n };\r\n ToolRunner.prototype._getSpawnFileName = function (options) {\r\n if (process.platform == 'win32') {\r\n if (this._isCmdFile()) {\r\n return process.env['COMSPEC'] || 'cmd.exe';\r\n }\r\n }\r\n if (options && options.shell) {\r\n return this._wrapArg(this.toolPath, '\"');\r\n }\r\n return this.toolPath;\r\n };\r\n ToolRunner.prototype._getSpawnArgs = function (options) {\r\n var _this = this;\r\n if (process.platform == 'win32') {\r\n if (this._isCmdFile()) {\r\n var argline = \"/D /S /C \\\"\" + this._windowsQuoteCmdArg(this.toolPath);\r\n for (var i = 0; i < this.args.length; i++) {\r\n argline += ' ';\r\n argline += options.windowsVerbatimArguments ? this.args[i] : this._windowsQuoteCmdArg(this.args[i]);\r\n }\r\n argline += '\"';\r\n return [argline];\r\n }\r\n if (options.windowsVerbatimArguments) {\r\n // note, in Node 6.x options.argv0 can be used instead of overriding args.slice and args.unshift.\r\n // for more details, refer to https://github.com/nodejs/node/blob/v6.x/lib/child_process.js\r\n var args_1 = this.args.slice(0); // copy the array\r\n // override slice to prevent Node from creating a copy of the arg array.\r\n // we need Node to use the \"unshift\" override below.\r\n args_1.slice = function () {\r\n if (arguments.length != 1 || arguments[0] != 0) {\r\n throw new Error('Unexpected arguments passed to args.slice when windowsVerbatimArguments flag is set.');\r\n }\r\n return args_1;\r\n };\r\n // override unshift\r\n //\r\n // when using the windowsVerbatimArguments option, Node does not quote the tool path when building\r\n // the cmdline parameter for the win32 function CreateProcess(). an unquoted space in the tool path\r\n // causes problems for tools when attempting to parse their own command line args. tools typically\r\n // assume their arguments begin after arg 0.\r\n //\r\n // by hijacking unshift, we can quote the tool path when it pushed onto the args array. Node builds\r\n // the cmdline parameter from the args array.\r\n //\r\n // note, we can't simply pass a quoted tool path to Node for multiple reasons:\r\n // 1) Node verifies the file exists (calls win32 function GetFileAttributesW) and the check returns\r\n // false if the path is quoted.\r\n // 2) Node passes the tool path as the application parameter to CreateProcess, which expects the\r\n // path to be unquoted.\r\n //\r\n // also note, in addition to the tool path being embedded within the cmdline parameter, Node also\r\n // passes the tool path to CreateProcess via the application parameter (optional parameter). when\r\n // present, Windows uses the application parameter to determine which file to run, instead of\r\n // interpreting the file from the cmdline parameter.\r\n args_1.unshift = function () {\r\n if (arguments.length != 1) {\r\n throw new Error('Unexpected arguments passed to args.unshift when windowsVerbatimArguments flag is set.');\r\n }\r\n return Array.prototype.unshift.call(args_1, \"\\\"\" + arguments[0] + \"\\\"\"); // quote the file name\r\n };\r\n return args_1;\r\n }\r\n else if (options.shell) {\r\n var args = [];\r\n for (var _i = 0, _a = this.args; _i < _a.length; _i++) {\r\n var arg = _a[_i];\r\n if (this._needQuotesForCmd(arg, '%')) {\r\n args.push(this._wrapArg(arg, '\"'));\r\n }\r\n else {\r\n args.push(arg);\r\n }\r\n }\r\n return args;\r\n }\r\n }\r\n else if (options.shell) {\r\n return this.args.map(function (arg) {\r\n if (_this._isWrapped(arg, \"'\")) {\r\n return arg;\r\n }\r\n // remove wrapping double quotes to avoid escaping\r\n arg = _this._unwrapArg(arg, '\"');\r\n arg = _this._escapeChar(arg, '\"');\r\n return _this._wrapArg(arg, '\"');\r\n });\r\n }\r\n return this.args;\r\n };\r\n /**\r\n * Escape specified character.\r\n * @param arg String to escape char in\r\n * @param charToEscape Char should be escaped\r\n */\r\n ToolRunner.prototype._escapeChar = function (arg, charToEscape) {\r\n var escChar = \"\\\\\";\r\n var output = '';\r\n var charIsEscaped = false;\r\n for (var _i = 0, arg_1 = arg; _i < arg_1.length; _i++) {\r\n var char = arg_1[_i];\r\n if (char === charToEscape && !charIsEscaped) {\r\n output += escChar + char;\r\n }\r\n else {\r\n output += char;\r\n }\r\n charIsEscaped = char === escChar && !charIsEscaped;\r\n }\r\n return output;\r\n };\r\n ToolRunner.prototype._isCmdFile = function () {\r\n var upperToolPath = this.toolPath.toUpperCase();\r\n return im._endsWith(upperToolPath, '.CMD') || im._endsWith(upperToolPath, '.BAT');\r\n };\r\n /**\r\n * Determine whether the cmd arg needs to be quoted. Returns true if arg contains any of special chars array.\r\n * @param arg The cmd command arg.\r\n * @param additionalChars Additional chars which should be also checked.\r\n */\r\n ToolRunner.prototype._needQuotesForCmd = function (arg, additionalChars) {\r\n var specialChars = this.cmdSpecialChars;\r\n if (additionalChars) {\r\n specialChars = this.cmdSpecialChars.concat(additionalChars);\r\n }\r\n var _loop_1 = function (char) {\r\n if (specialChars.some(function (x) { return x === char; })) {\r\n return { value: true };\r\n }\r\n };\r\n for (var _i = 0, arg_2 = arg; _i < arg_2.length; _i++) {\r\n var char = arg_2[_i];\r\n var state_1 = _loop_1(char);\r\n if (typeof state_1 === \"object\")\r\n return state_1.value;\r\n }\r\n return false;\r\n };\r\n ToolRunner.prototype._windowsQuoteCmdArg = function (arg) {\r\n // for .exe, apply the normal quoting rules that libuv applies\r\n if (!this._isCmdFile()) {\r\n return this._uv_quote_cmd_arg(arg);\r\n }\r\n // otherwise apply quoting rules specific to the cmd.exe command line parser.\r\n // the libuv rules are generic and are not designed specifically for cmd.exe\r\n // command line parser.\r\n //\r\n // for a detailed description of the cmd.exe command line parser, refer to\r\n // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912\r\n // need quotes for empty arg\r\n if (!arg) {\r\n return '\"\"';\r\n }\r\n // determine whether the arg needs to be quoted\r\n var needsQuotes = this._needQuotesForCmd(arg);\r\n // short-circuit if quotes not needed\r\n if (!needsQuotes) {\r\n return arg;\r\n }\r\n // the following quoting rules are very similar to the rules that by libuv applies.\r\n //\r\n // 1) wrap the string in quotes\r\n //\r\n // 2) double-up quotes - i.e. \" => \"\"\r\n //\r\n // this is different from the libuv quoting rules. libuv replaces \" with \\\", which unfortunately\r\n // doesn't work well with a cmd.exe command line.\r\n //\r\n // note, replacing \" with \"\" also works well if the arg is passed to a downstream .NET console app.\r\n // for example, the command line:\r\n // foo.exe \"myarg:\"\"my val\"\"\"\r\n // is parsed by a .NET console app into an arg array:\r\n // [ \"myarg:\\\"my val\\\"\" ]\r\n // which is the same end result when applying libuv quoting rules. although the actual\r\n // command line from libuv quoting rules would look like:\r\n // foo.exe \"myarg:\\\"my val\\\"\"\r\n //\r\n // 3) double-up slashes that preceed a quote,\r\n // e.g. hello \\world => \"hello \\world\"\r\n // hello\\\"world => \"hello\\\\\"\"world\"\r\n // hello\\\\\"world => \"hello\\\\\\\\\"\"world\"\r\n // hello world\\ => \"hello world\\\\\"\r\n //\r\n // technically this is not required for a cmd.exe command line, or the batch argument parser.\r\n // the reasons for including this as a .cmd quoting rule are:\r\n //\r\n // a) this is optimized for the scenario where the argument is passed from the .cmd file to an\r\n // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.\r\n //\r\n // b) it's what we've been doing previously (by deferring to node default behavior) and we\r\n // haven't heard any complaints about that aspect.\r\n //\r\n // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be\r\n // escaped when used on the command line directly - even though within a .cmd file % can be escaped\r\n // by using %%.\r\n //\r\n // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts\r\n // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.\r\n //\r\n // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would\r\n // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the\r\n // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args\r\n // to an external program.\r\n //\r\n // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.\r\n // % can be escaped within a .cmd file.\r\n var reverse = '\"';\r\n var quote_hit = true;\r\n for (var i = arg.length; i > 0; i--) { // walk the string in reverse\r\n reverse += arg[i - 1];\r\n if (quote_hit && arg[i - 1] == '\\\\') {\r\n reverse += '\\\\'; // double the slash\r\n }\r\n else if (arg[i - 1] == '\"') {\r\n quote_hit = true;\r\n reverse += '\"'; // double the quote\r\n }\r\n else {\r\n quote_hit = false;\r\n }\r\n }\r\n reverse += '\"';\r\n return reverse.split('').reverse().join('');\r\n };\r\n ToolRunner.prototype._uv_quote_cmd_arg = function (arg) {\r\n // Tool runner wraps child_process.spawn() and needs to apply the same quoting as\r\n // Node in certain cases where the undocumented spawn option windowsVerbatimArguments\r\n // is used.\r\n //\r\n // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,\r\n // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),\r\n // pasting copyright notice from Node within this function:\r\n //\r\n // Copyright Joyent, Inc. and other Node contributors. All rights reserved.\r\n //\r\n // Permission is hereby granted, free of charge, to any person obtaining a copy\r\n // of this software and associated documentation files (the \"Software\"), to\r\n // deal in the Software without restriction, including without limitation the\r\n // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\r\n // sell copies of the Software, and to permit persons to whom the Software is\r\n // furnished to do so, subject to the following conditions:\r\n //\r\n // The above copyright notice and this permission notice shall be included in\r\n // all copies or substantial portions of the Software.\r\n //\r\n // THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r\n // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\r\n // IN THE SOFTWARE.\r\n if (!arg) {\r\n // Need double quotation for empty argument\r\n return '\"\"';\r\n }\r\n if (arg.indexOf(' ') < 0 && arg.indexOf('\\t') < 0 && arg.indexOf('\"') < 0) {\r\n // No quotation needed\r\n return arg;\r\n }\r\n if (arg.indexOf('\"') < 0 && arg.indexOf('\\\\') < 0) {\r\n // No embedded double quotes or backslashes, so I can just wrap\r\n // quote marks around the whole thing.\r\n return \"\\\"\" + arg + \"\\\"\";\r\n }\r\n // Expected input/output:\r\n // input : hello\"world\r\n // output: \"hello\\\"world\"\r\n // input : hello\"\"world\r\n // output: \"hello\\\"\\\"world\"\r\n // input : hello\\world\r\n // output: hello\\world\r\n // input : hello\\\\world\r\n // output: hello\\\\world\r\n // input : hello\\\"world\r\n // output: \"hello\\\\\\\"world\"\r\n // input : hello\\\\\"world\r\n // output: \"hello\\\\\\\\\\\"world\"\r\n // input : hello world\\\r\n // output: \"hello world\\\\\" - note the comment in libuv actually reads \"hello world\\\"\r\n // but it appears the comment is wrong, it should be \"hello world\\\\\"\r\n var reverse = '\"';\r\n var quote_hit = true;\r\n for (var i = arg.length; i > 0; i--) { // walk the string in reverse\r\n reverse += arg[i - 1];\r\n if (quote_hit && arg[i - 1] == '\\\\') {\r\n reverse += '\\\\';\r\n }\r\n else if (arg[i - 1] == '\"') {\r\n quote_hit = true;\r\n reverse += '\\\\';\r\n }\r\n else {\r\n quote_hit = false;\r\n }\r\n }\r\n reverse += '\"';\r\n return reverse.split('').reverse().join('');\r\n };\r\n ToolRunner.prototype._cloneExecOptions = function (options) {\r\n options = options || {};\r\n var result = {\r\n cwd: options.cwd || process.cwd(),\r\n env: options.env || process.env,\r\n silent: options.silent || false,\r\n failOnStdErr: options.failOnStdErr || false,\r\n ignoreReturnCode: options.ignoreReturnCode || false,\r\n windowsVerbatimArguments: options.windowsVerbatimArguments || false,\r\n shell: options.shell || false\r\n };\r\n result.outStream = options.outStream || process.stdout;\r\n result.errStream = options.errStream || process.stderr;\r\n return result;\r\n };\r\n ToolRunner.prototype._getSpawnOptions = function (options) {\r\n options = options || {};\r\n var result = {};\r\n result.cwd = options.cwd;\r\n result.env = options.env;\r\n result.shell = options.shell;\r\n result['windowsVerbatimArguments'] = options.windowsVerbatimArguments || this._isCmdFile();\r\n return result;\r\n };\r\n ToolRunner.prototype._getSpawnSyncOptions = function (options) {\r\n var result = {};\r\n result.cwd = options.cwd;\r\n result.env = options.env;\r\n result.shell = options.shell;\r\n result['windowsVerbatimArguments'] = options.windowsVerbatimArguments || this._isCmdFile();\r\n return result;\r\n };\r\n ToolRunner.prototype.execWithPiping = function (pipeOutputToTool, options) {\r\n var _this = this;\r\n var defer = Q.defer();\r\n this._debug('exec tool: ' + this.toolPath);\r\n this._debug('arguments:');\r\n this.args.forEach(function (arg) {\r\n _this._debug(' ' + arg);\r\n });\r\n var success = true;\r\n var optionsNonNull = this._cloneExecOptions(options);\r\n if (!optionsNonNull.silent) {\r\n optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);\r\n }\r\n var cp;\r\n var toolPath = pipeOutputToTool.toolPath;\r\n var toolPathFirst;\r\n var successFirst = true;\r\n var returnCodeFirst;\r\n var fileStream;\r\n var waitingEvents = 0; // number of process or stream events we are waiting on to complete\r\n var returnCode = 0;\r\n var error;\r\n toolPathFirst = this.toolPath;\r\n // Following node documentation example from this link on how to pipe output of one process to another\r\n // https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options\r\n //start the child process for both tools\r\n waitingEvents++;\r\n var cpFirst = child.spawn(this._getSpawnFileName(optionsNonNull), this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(optionsNonNull));\r\n waitingEvents++;\r\n cp = child.spawn(pipeOutputToTool._getSpawnFileName(optionsNonNull), pipeOutputToTool._getSpawnArgs(optionsNonNull), pipeOutputToTool._getSpawnOptions(optionsNonNull));\r\n fileStream = this.pipeOutputToFile ? fs.createWriteStream(this.pipeOutputToFile) : null;\r\n if (fileStream) {\r\n waitingEvents++;\r\n fileStream.on('finish', function () {\r\n waitingEvents--; //file write is complete\r\n fileStream = null;\r\n if (waitingEvents == 0) {\r\n if (error) {\r\n defer.reject(error);\r\n }\r\n else {\r\n defer.resolve(returnCode);\r\n }\r\n }\r\n });\r\n fileStream.on('error', function (err) {\r\n waitingEvents--; //there were errors writing to the file, write is done\r\n _this._debug(\"Failed to pipe output of \" + toolPathFirst + \" to file \" + _this.pipeOutputToFile + \". Error = \" + err);\r\n fileStream = null;\r\n if (waitingEvents == 0) {\r\n if (error) {\r\n defer.reject(error);\r\n }\r\n else {\r\n defer.resolve(returnCode);\r\n }\r\n }\r\n });\r\n }\r\n //pipe stdout of first tool to stdin of second tool\r\n cpFirst.stdout.on('data', function (data) {\r\n try {\r\n if (fileStream) {\r\n fileStream.write(data);\r\n }\r\n cp.stdin.write(data);\r\n }\r\n catch (err) {\r\n _this._debug('Failed to pipe output of ' + toolPathFirst + ' to ' + toolPath);\r\n _this._debug(toolPath + ' might have exited due to errors prematurely. Verify the arguments passed are valid.');\r\n }\r\n });\r\n cpFirst.stderr.on('data', function (data) {\r\n if (fileStream) {\r\n fileStream.write(data);\r\n }\r\n successFirst = !optionsNonNull.failOnStdErr;\r\n if (!optionsNonNull.silent) {\r\n var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;\r\n s.write(data);\r\n }\r\n });\r\n cpFirst.on('error', function (err) {\r\n waitingEvents--; //first process is complete with errors\r\n if (fileStream) {\r\n fileStream.end();\r\n }\r\n cp.stdin.end();\r\n error = new Error(toolPathFirst + ' failed. ' + err.message);\r\n if (waitingEvents == 0) {\r\n defer.reject(error);\r\n }\r\n });\r\n cpFirst.on('close', function (code, signal) {\r\n waitingEvents--; //first process is complete\r\n if (code != 0 && !optionsNonNull.ignoreReturnCode) {\r\n successFirst = false;\r\n returnCodeFirst = code;\r\n returnCode = returnCodeFirst;\r\n }\r\n _this._debug('success of first tool:' + successFirst);\r\n if (fileStream) {\r\n fileStream.end();\r\n }\r\n cp.stdin.end();\r\n if (waitingEvents == 0) {\r\n if (error) {\r\n defer.reject(error);\r\n }\r\n else {\r\n defer.resolve(returnCode);\r\n }\r\n }\r\n });\r\n var stdbuffer = '';\r\n cp.stdout.on('data', function (data) {\r\n _this.emit('stdout', data);\r\n if (!optionsNonNull.silent) {\r\n optionsNonNull.outStream.write(data);\r\n }\r\n _this._processLineBuffer(data, stdbuffer, function (line) {\r\n _this.emit('stdline', line);\r\n });\r\n });\r\n var errbuffer = '';\r\n cp.stderr.on('data', function (data) {\r\n _this.emit('stderr', data);\r\n success = !optionsNonNull.failOnStdErr;\r\n if (!optionsNonNull.silent) {\r\n var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;\r\n s.write(data);\r\n }\r\n _this._processLineBuffer(data, errbuffer, function (line) {\r\n _this.emit('errline', line);\r\n });\r\n });\r\n cp.on('error', function (err) {\r\n waitingEvents--; //process is done with errors\r\n error = new Error(toolPath + ' failed. ' + err.message);\r\n if (waitingEvents == 0) {\r\n defer.reject(error);\r\n }\r\n });\r\n cp.on('close', function (code, signal) {\r\n waitingEvents--; //process is complete\r\n _this._debug('rc:' + code);\r\n returnCode = code;\r\n if (stdbuffer.length > 0) {\r\n _this.emit('stdline', stdbuffer);\r\n }\r\n if (errbuffer.length > 0) {\r\n _this.emit('errline', errbuffer);\r\n }\r\n if (code != 0 && !optionsNonNull.ignoreReturnCode) {\r\n success = false;\r\n }\r\n _this._debug('success:' + success);\r\n if (!successFirst) { //in the case output is piped to another tool, check exit code of both tools\r\n error = new Error(toolPathFirst + ' failed with return code: ' + returnCodeFirst);\r\n }\r\n else if (!success) {\r\n error = new Error(toolPath + ' failed with return code: ' + code);\r\n }\r\n if (waitingEvents == 0) {\r\n if (error) {\r\n defer.reject(error);\r\n }\r\n else {\r\n defer.resolve(returnCode);\r\n }\r\n }\r\n });\r\n return defer.promise;\r\n };\r\n /**\r\n * Add argument\r\n * Append an argument or an array of arguments\r\n * returns ToolRunner for chaining\r\n *\r\n * @param val string cmdline or array of strings\r\n * @returns ToolRunner\r\n */\r\n ToolRunner.prototype.arg = function (val) {\r\n if (!val) {\r\n return this;\r\n }\r\n if (val instanceof Array) {\r\n this._debug(this.toolPath + ' arg: ' + JSON.stringify(val));\r\n this.args = this.args.concat(val);\r\n }\r\n else if (typeof (val) === 'string') {\r\n this._debug(this.toolPath + ' arg: ' + val);\r\n this.args = this.args.concat(val.trim());\r\n }\r\n return this;\r\n };\r\n /**\r\n * Parses an argument line into one or more arguments\r\n * e.g. .line('\"arg one\" two -z') is equivalent to .arg(['arg one', 'two', '-z'])\r\n * returns ToolRunner for chaining\r\n *\r\n * @param val string argument line\r\n * @returns ToolRunner\r\n */\r\n ToolRunner.prototype.line = function (val) {\r\n if (!val) {\r\n return this;\r\n }\r\n this._debug(this.toolPath + ' arg: ' + val);\r\n this.args = this.args.concat(this._argStringToArray(val));\r\n return this;\r\n };\r\n /**\r\n * Add argument(s) if a condition is met\r\n * Wraps arg(). See arg for details\r\n * returns ToolRunner for chaining\r\n *\r\n * @param condition boolean condition\r\n * @param val string cmdline or array of strings\r\n * @returns ToolRunner\r\n */\r\n ToolRunner.prototype.argIf = function (condition, val) {\r\n if (condition) {\r\n this.arg(val);\r\n }\r\n return this;\r\n };\r\n /**\r\n * Pipe output of exec() to another tool\r\n * @param tool\r\n * @param file optional filename to additionally stream the output to.\r\n * @returns {ToolRunner}\r\n */\r\n ToolRunner.prototype.pipeExecOutputToTool = function (tool, file) {\r\n this.pipeOutputToTool = tool;\r\n this.pipeOutputToFile = file;\r\n return this;\r\n };\r\n /**\r\n * Exec a tool.\r\n * Output will be streamed to the live console.\r\n * Returns promise with return code\r\n *\r\n * @param tool path to tool to exec\r\n * @param options optional exec options. See IExecOptions\r\n * @returns number\r\n */\r\n ToolRunner.prototype.exec = function (options) {\r\n var _this = this;\r\n if (this.pipeOutputToTool) {\r\n return this.execWithPiping(this.pipeOutputToTool, options);\r\n }\r\n var defer = Q.defer();\r\n this._debug('exec tool: ' + this.toolPath);\r\n this._debug('arguments:');\r\n this.args.forEach(function (arg) {\r\n _this._debug(' ' + arg);\r\n });\r\n var optionsNonNull = this._cloneExecOptions(options);\r\n if (!optionsNonNull.silent) {\r\n optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);\r\n }\r\n var state = new ExecState(optionsNonNull, this.toolPath);\r\n state.on('debug', function (message) {\r\n _this._debug(message);\r\n });\r\n var cp = child.spawn(this._getSpawnFileName(options), this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(options));\r\n this.childProcess = cp;\r\n // it is possible for the child process to end its last line without a new line.\r\n // because stdout is buffered, this causes the last line to not get sent to the parent\r\n // stream. Adding this event forces a flush before the child streams are closed.\r\n cp.stdout.on('finish', function () {\r\n if (!optionsNonNull.silent) {\r\n optionsNonNull.outStream.write(os.EOL);\r\n }\r\n });\r\n var stdbuffer = '';\r\n cp.stdout.on('data', function (data) {\r\n _this.emit('stdout', data);\r\n if (!optionsNonNull.silent) {\r\n optionsNonNull.outStream.write(data);\r\n }\r\n _this._processLineBuffer(data, stdbuffer, function (line) {\r\n _this.emit('stdline', line);\r\n });\r\n });\r\n var errbuffer = '';\r\n cp.stderr.on('data', function (data) {\r\n state.processStderr = true;\r\n _this.emit('stderr', data);\r\n if (!optionsNonNull.silent) {\r\n var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;\r\n s.write(data);\r\n }\r\n _this._processLineBuffer(data, errbuffer, function (line) {\r\n _this.emit('errline', line);\r\n });\r\n });\r\n cp.on('error', function (err) {\r\n state.processError = err.message;\r\n state.processExited = true;\r\n state.processClosed = true;\r\n state.CheckComplete();\r\n });\r\n cp.on('exit', function (code, signal) {\r\n state.processExitCode = code;\r\n state.processExited = true;\r\n _this._debug(\"Exit code \" + code + \" received from tool '\" + _this.toolPath + \"'\");\r\n state.CheckComplete();\r\n });\r\n cp.on('close', function (code, signal) {\r\n state.processExitCode = code;\r\n state.processExited = true;\r\n state.processClosed = true;\r\n _this._debug(\"STDIO streams have closed for tool '\" + _this.toolPath + \"'\");\r\n state.CheckComplete();\r\n });\r\n state.on('done', function (error, exitCode) {\r\n if (stdbuffer.length > 0) {\r\n _this.emit('stdline', stdbuffer);\r\n }\r\n if (errbuffer.length > 0) {\r\n _this.emit('errline', errbuffer);\r\n }\r\n cp.removeAllListeners();\r\n if (error) {\r\n defer.reject(error);\r\n }\r\n else {\r\n defer.resolve(exitCode);\r\n }\r\n });\r\n return defer.promise;\r\n };\r\n /**\r\n * Exec a tool synchronously.\r\n * Output will be *not* be streamed to the live console. It will be returned after execution is complete.\r\n * Appropriate for short running tools\r\n * Returns IExecSyncResult with output and return code\r\n *\r\n * @param tool path to tool to exec\r\n * @param options optional exec options. See IExecSyncOptions\r\n * @returns IExecSyncResult\r\n */\r\n ToolRunner.prototype.execSync = function (options) {\r\n var _this = this;\r\n this._debug('exec tool: ' + this.toolPath);\r\n this._debug('arguments:');\r\n this.args.forEach(function (arg) {\r\n _this._debug(' ' + arg);\r\n });\r\n var success = true;\r\n options = this._cloneExecOptions(options);\r\n if (!options.silent) {\r\n options.outStream.write(this._getCommandString(options) + os.EOL);\r\n }\r\n var r = child.spawnSync(this._getSpawnFileName(options), this._getSpawnArgs(options), this._getSpawnSyncOptions(options));\r\n if (!options.silent && r.stdout && r.stdout.length > 0) {\r\n options.outStream.write(r.stdout);\r\n }\r\n if (!options.silent && r.stderr && r.stderr.length > 0) {\r\n options.errStream.write(r.stderr);\r\n }\r\n var res = { code: r.status, error: r.error };\r\n res.stdout = (r.stdout) ? r.stdout.toString() : '';\r\n res.stderr = (r.stderr) ? r.stderr.toString() : '';\r\n return res;\r\n };\r\n /**\r\n * Used to close child process by sending SIGNINT signal.\r\n * It allows executed script to have some additional logic on SIGINT, before exiting.\r\n */\r\n ToolRunner.prototype.killChildProcess = function () {\r\n if (this.childProcess) {\r\n this.childProcess.kill();\r\n }\r\n };\r\n return ToolRunner;\r\n}(events.EventEmitter));\r\nexports.ToolRunner = ToolRunner;\r\nvar ExecState = /** @class */ (function (_super) {\r\n __extends(ExecState, _super);\r\n function ExecState(options, toolPath) {\r\n var _this = _super.call(this) || this;\r\n _this.delay = 10000; // 10 seconds\r\n _this.timeout = null;\r\n if (!toolPath) {\r\n throw new Error('toolPath must not be empty');\r\n }\r\n _this.options = options;\r\n _this.toolPath = toolPath;\r\n var delay = process.env['TASKLIB_TEST_TOOLRUNNER_EXITDELAY'];\r\n if (delay) {\r\n _this.delay = parseInt(delay);\r\n }\r\n return _this;\r\n }\r\n ExecState.prototype.CheckComplete = function () {\r\n if (this.done) {\r\n return;\r\n }\r\n if (this.processClosed) {\r\n this._setResult();\r\n }\r\n else if (this.processExited) {\r\n this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this);\r\n }\r\n };\r\n ExecState.prototype._debug = function (message) {\r\n this.emit('debug', message);\r\n };\r\n ExecState.prototype._setResult = function () {\r\n // determine whether there is an error\r\n var error;\r\n if (this.processExited) {\r\n if (this.processError) {\r\n error = new Error(im._loc('LIB_ProcessError', this.toolPath, this.processError));\r\n }\r\n else if (this.processExitCode != 0 && !this.options.ignoreReturnCode) {\r\n error = new Error(im._loc('LIB_ProcessExitCode', this.toolPath, this.processExitCode));\r\n }\r\n else if (this.processStderr && this.options.failOnStdErr) {\r\n error = new Error(im._loc('LIB_ProcessStderr', this.toolPath));\r\n }\r\n }\r\n // clear the timeout\r\n if (this.timeout) {\r\n clearTimeout(this.timeout);\r\n this.timeout = null;\r\n }\r\n this.done = true;\r\n this.emit('done', error, this.processExitCode);\r\n };\r\n ExecState.HandleTimeout = function (state) {\r\n if (state.done) {\r\n return;\r\n }\r\n if (!state.processClosed && state.processExited) {\r\n console.log(im._loc('LIB_StdioNotClosed', state.delay / 1000, state.toolPath));\r\n state._debug(im._loc('LIB_StdioNotClosed', state.delay / 1000, state.toolPath));\r\n }\r\n state._setResult();\r\n };\r\n return ExecState;\r\n}(events.EventEmitter));\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar fs = require(\"fs\");\r\nvar path = require(\"path\");\r\nvar crypto = require(\"crypto\");\r\nvar uuidV4 = require('uuid/v4');\r\nvar algorithm = \"aes-256-ctr\";\r\nvar encryptEncoding = 'hex';\r\nvar unencryptedEncoding = 'utf8';\r\n//\r\n// Store sensitive data in proc.\r\n// Main goal: Protects tasks which would dump envvars from leaking secrets inadvertently\r\n// the task lib clears after storing.\r\n// Also protects against a dump of a process getting the secrets\r\n// The secret is generated and stored externally for the lifetime of the task.\r\n//\r\nvar Vault = /** @class */ (function () {\r\n function Vault(keyPath) {\r\n this._keyFile = path.join(keyPath, '.taskkey');\r\n this._store = {};\r\n this.genKey();\r\n }\r\n Vault.prototype.initialize = function () {\r\n };\r\n Vault.prototype.storeSecret = function (name, data) {\r\n if (!name || name.length == 0) {\r\n return false;\r\n }\r\n name = name.toLowerCase();\r\n if (!data || data.length == 0) {\r\n if (this._store.hasOwnProperty(name)) {\r\n delete this._store[name];\r\n }\r\n return false;\r\n }\r\n var key = this.getKey();\r\n var iv = crypto.randomBytes(16);\r\n var cipher = crypto.createCipheriv(algorithm, key, iv);\r\n var crypted = cipher.update(data, unencryptedEncoding, encryptEncoding);\r\n var cryptedFinal = cipher.final(encryptEncoding);\r\n this._store[name] = iv.toString(encryptEncoding) + crypted + cryptedFinal;\r\n return true;\r\n };\r\n Vault.prototype.retrieveSecret = function (name) {\r\n var secret;\r\n name = (name || '').toLowerCase();\r\n if (this._store.hasOwnProperty(name)) {\r\n var key = this.getKey();\r\n var data = this._store[name];\r\n var ivDataBuffer = Buffer.from(data, encryptEncoding);\r\n var iv = ivDataBuffer.slice(0, 16);\r\n var encryptedText = ivDataBuffer.slice(16);\r\n var decipher = crypto.createDecipheriv(algorithm, key, iv);\r\n var dec = decipher.update(encryptedText, encryptEncoding, unencryptedEncoding);\r\n var decFinal = decipher.final(unencryptedEncoding);\r\n secret = dec + decFinal;\r\n }\r\n return secret;\r\n };\r\n Vault.prototype.getKey = function () {\r\n var key = fs.readFileSync(this._keyFile).toString('utf8');\r\n // Key needs to be hashed to correct length to match algorithm (aes-256-ctr)\r\n return crypto.createHash('sha256').update(key).digest();\r\n };\r\n Vault.prototype.genKey = function () {\r\n fs.writeFileSync(this._keyFile, uuidV4(), { encoding: 'utf8' });\r\n };\r\n return Vault;\r\n}());\r\nexports.Vault = Vault;\r\n","'use strict';\nmodule.exports = balanced;\nfunction balanced(a, b, str) {\n if (a instanceof RegExp) a = maybeMatch(a, str);\n if (b instanceof RegExp) b = maybeMatch(b, str);\n\n var r = range(a, b, str);\n\n return r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + a.length, r[1]),\n post: str.slice(r[1] + b.length)\n };\n}\n\nfunction maybeMatch(reg, str) {\n var m = str.match(reg);\n return m ? m[0] : null;\n}\n\nbalanced.range = range;\nfunction range(a, b, str) {\n var begs, beg, left, right, result;\n var ai = str.indexOf(a);\n var bi = str.indexOf(b, ai + 1);\n var i = ai;\n\n if (ai >= 0 && bi > 0) {\n if(a===b) {\n return [ai, bi];\n }\n begs = [];\n left = str.length;\n\n while (i >= 0 && !result) {\n if (i == ai) {\n begs.push(i);\n ai = str.indexOf(a, i + 1);\n } else if (begs.length == 1) {\n result = [ begs.pop(), bi ];\n } else {\n beg = begs.pop();\n if (beg < left) {\n left = beg;\n right = bi;\n }\n\n bi = str.indexOf(b, i + 1);\n }\n\n i = ai < bi && ai >= 0 ? ai : bi;\n }\n\n if (begs.length) {\n result = [ left, right ];\n }\n }\n\n return result;\n}\n","var concatMap = require('concat-map');\nvar balanced = require('balanced-match');\n\nmodule.exports = expandTop;\n\nvar escSlash = '\\0SLASH'+Math.random()+'\\0';\nvar escOpen = '\\0OPEN'+Math.random()+'\\0';\nvar escClose = '\\0CLOSE'+Math.random()+'\\0';\nvar escComma = '\\0COMMA'+Math.random()+'\\0';\nvar escPeriod = '\\0PERIOD'+Math.random()+'\\0';\n\nfunction numeric(str) {\n return parseInt(str, 10) == str\n ? parseInt(str, 10)\n : str.charCodeAt(0);\n}\n\nfunction escapeBraces(str) {\n return str.split('\\\\\\\\').join(escSlash)\n .split('\\\\{').join(escOpen)\n .split('\\\\}').join(escClose)\n .split('\\\\,').join(escComma)\n .split('\\\\.').join(escPeriod);\n}\n\nfunction unescapeBraces(str) {\n return str.split(escSlash).join('\\\\')\n .split(escOpen).join('{')\n .split(escClose).join('}')\n .split(escComma).join(',')\n .split(escPeriod).join('.');\n}\n\n\n// Basically just str.split(\",\"), but handling cases\n// where we have nested braced sections, which should be\n// treated as individual members, like {a,{b,c},d}\nfunction parseCommaParts(str) {\n if (!str)\n return [''];\n\n var parts = [];\n var m = balanced('{', '}', str);\n\n if (!m)\n return str.split(',');\n\n var pre = m.pre;\n var body = m.body;\n var post = m.post;\n var p = pre.split(',');\n\n p[p.length-1] += '{' + body + '}';\n var postParts = parseCommaParts(post);\n if (post.length) {\n p[p.length-1] += postParts.shift();\n p.push.apply(p, postParts);\n }\n\n parts.push.apply(parts, p);\n\n return parts;\n}\n\nfunction expandTop(str) {\n if (!str)\n return [];\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.substr(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.substr(2);\n }\n\n return expand(escapeBraces(str), true).map(unescapeBraces);\n}\n\nfunction identity(e) {\n return e;\n}\n\nfunction embrace(str) {\n return '{' + str + '}';\n}\nfunction isPadded(el) {\n return /^-?0\\d/.test(el);\n}\n\nfunction lte(i, y) {\n return i <= y;\n}\nfunction gte(i, y) {\n return i >= y;\n}\n\nfunction expand(str, isTop) {\n var expansions = [];\n\n var m = balanced('{', '}', str);\n if (!m || /\\$$/.test(m.pre)) return [str];\n\n var isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body);\n var isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(m.body);\n var isSequence = isNumericSequence || isAlphaSequence;\n var isOptions = m.body.indexOf(',') >= 0;\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,.*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post;\n return expand(str);\n }\n return [str];\n }\n\n var n;\n if (isSequence) {\n n = m.body.split(/\\.\\./);\n } else {\n n = parseCommaParts(m.body);\n if (n.length === 1) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand(n[0], false).map(embrace);\n if (n.length === 1) {\n var post = m.post.length\n ? expand(m.post, false)\n : [''];\n return post.map(function(p) {\n return m.pre + n[0] + p;\n });\n }\n }\n }\n\n // at this point, n is the parts, and we know it's not a comma set\n // with a single entry.\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n var pre = m.pre;\n var post = m.post.length\n ? expand(m.post, false)\n : [''];\n\n var N;\n\n if (isSequence) {\n var x = numeric(n[0]);\n var y = numeric(n[1]);\n var width = Math.max(n[0].length, n[1].length)\n var incr = n.length == 3\n ? Math.abs(numeric(n[2]))\n : 1;\n var test = lte;\n var reverse = y < x;\n if (reverse) {\n incr *= -1;\n test = gte;\n }\n var pad = n.some(isPadded);\n\n N = [];\n\n for (var i = x; test(i, y); i += incr) {\n var c;\n if (isAlphaSequence) {\n c = String.fromCharCode(i);\n if (c === '\\\\')\n c = '';\n } else {\n c = String(i);\n if (pad) {\n var need = width - c.length;\n if (need > 0) {\n var z = new Array(need + 1).join('0');\n if (i < 0)\n c = '-' + z + c.slice(1);\n else\n c = z + c;\n }\n }\n }\n N.push(c);\n }\n } else {\n N = concatMap(n, function(el) { return expand(el, false) });\n }\n\n for (var j = 0; j < N.length; j++) {\n for (var k = 0; k < post.length; k++) {\n var expansion = pre + N[j] + post[k];\n if (!isTop || isSequence || expansion)\n expansions.push(expansion);\n }\n }\n\n return expansions;\n}\n\n","module.exports = function (xs, fn) {\n var res = [];\n for (var i = 0; i < xs.length; i++) {\n var x = fn(xs[i], i);\n if (isArray(x)) res.push.apply(res, x);\n else res.push(x);\n }\n return res;\n};\n\nvar isArray = Array.isArray || function (xs) {\n return Object.prototype.toString.call(xs) === '[object Array]';\n};\n","module.exports = minimatch\nminimatch.Minimatch = Minimatch\n\nvar path = { sep: '/' }\ntry {\n path = require('path')\n} catch (er) {}\n\nvar GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}\nvar expand = require('brace-expansion')\n\nvar plTypes = {\n '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},\n '?': { open: '(?:', close: ')?' },\n '+': { open: '(?:', close: ')+' },\n '*': { open: '(?:', close: ')*' },\n '@': { open: '(?:', close: ')' }\n}\n\n// any single thing other than /\n// don't need to escape / when using new RegExp()\nvar qmark = '[^/]'\n\n// * => any number of characters\nvar star = qmark + '*?'\n\n// ** when dots are allowed. Anything goes, except .. and .\n// not (^ or / followed by one or two dots followed by $ or /),\n// followed by anything, any number of times.\nvar twoStarDot = '(?:(?!(?:\\\\\\/|^)(?:\\\\.{1,2})($|\\\\\\/)).)*?'\n\n// not a ^ or / followed by a dot,\n// followed by anything, any number of times.\nvar twoStarNoDot = '(?:(?!(?:\\\\\\/|^)\\\\.).)*?'\n\n// characters that need to be escaped in RegExp.\nvar reSpecials = charSet('().*{}+?[]^$\\\\!')\n\n// \"abc\" -> { a:true, b:true, c:true }\nfunction charSet (s) {\n return s.split('').reduce(function (set, c) {\n set[c] = true\n return set\n }, {})\n}\n\n// normalizes slashes.\nvar slashSplit = /\\/+/\n\nminimatch.filter = filter\nfunction filter (pattern, options) {\n options = options || {}\n return function (p, i, list) {\n return minimatch(p, pattern, options)\n }\n}\n\nfunction ext (a, b) {\n a = a || {}\n b = b || {}\n var t = {}\n Object.keys(b).forEach(function (k) {\n t[k] = b[k]\n })\n Object.keys(a).forEach(function (k) {\n t[k] = a[k]\n })\n return t\n}\n\nminimatch.defaults = function (def) {\n if (!def || !Object.keys(def).length) return minimatch\n\n var orig = minimatch\n\n var m = function minimatch (p, pattern, options) {\n return orig.minimatch(p, pattern, ext(def, options))\n }\n\n m.Minimatch = function Minimatch (pattern, options) {\n return new orig.Minimatch(pattern, ext(def, options))\n }\n\n return m\n}\n\nMinimatch.defaults = function (def) {\n if (!def || !Object.keys(def).length) return Minimatch\n return minimatch.defaults(def).Minimatch\n}\n\nfunction minimatch (p, pattern, options) {\n if (typeof pattern !== 'string') {\n throw new TypeError('glob pattern string required')\n }\n\n if (!options) options = {}\n\n // shortcut: comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n return false\n }\n\n // \"\" only matches \"\"\n if (pattern.trim() === '') return p === ''\n\n return new Minimatch(pattern, options).match(p)\n}\n\nfunction Minimatch (pattern, options) {\n if (!(this instanceof Minimatch)) {\n return new Minimatch(pattern, options)\n }\n\n if (typeof pattern !== 'string') {\n throw new TypeError('glob pattern string required')\n }\n\n if (!options) options = {}\n pattern = pattern.trim()\n\n // windows support: need to use /, not \\\n if (path.sep !== '/') {\n pattern = pattern.split(path.sep).join('/')\n }\n\n this.options = options\n this.set = []\n this.pattern = pattern\n this.regexp = null\n this.negate = false\n this.comment = false\n this.empty = false\n\n // make the set of regexps etc.\n this.make()\n}\n\nMinimatch.prototype.debug = function () {}\n\nMinimatch.prototype.make = make\nfunction make () {\n // don't do it more than once.\n if (this._made) return\n\n var pattern = this.pattern\n var options = this.options\n\n // empty patterns and comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n this.comment = true\n return\n }\n if (!pattern) {\n this.empty = true\n return\n }\n\n // step 1: figure out negation, etc.\n this.parseNegate()\n\n // step 2: expand braces\n var set = this.globSet = this.braceExpand()\n\n if (options.debug) this.debug = console.error\n\n this.debug(this.pattern, set)\n\n // step 3: now we have a set, so turn each one into a series of path-portion\n // matching patterns.\n // These will be regexps, except in the case of \"**\", which is\n // set to the GLOBSTAR object for globstar behavior,\n // and will not contain any / characters\n set = this.globParts = set.map(function (s) {\n return s.split(slashSplit)\n })\n\n this.debug(this.pattern, set)\n\n // glob --> regexps\n set = set.map(function (s, si, set) {\n return s.map(this.parse, this)\n }, this)\n\n this.debug(this.pattern, set)\n\n // filter out everything that didn't compile properly.\n set = set.filter(function (s) {\n return s.indexOf(false) === -1\n })\n\n this.debug(this.pattern, set)\n\n this.set = set\n}\n\nMinimatch.prototype.parseNegate = parseNegate\nfunction parseNegate () {\n var pattern = this.pattern\n var negate = false\n var options = this.options\n var negateOffset = 0\n\n if (options.nonegate) return\n\n for (var i = 0, l = pattern.length\n ; i < l && pattern.charAt(i) === '!'\n ; i++) {\n negate = !negate\n negateOffset++\n }\n\n if (negateOffset) this.pattern = pattern.substr(negateOffset)\n this.negate = negate\n}\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nminimatch.braceExpand = function (pattern, options) {\n return braceExpand(pattern, options)\n}\n\nMinimatch.prototype.braceExpand = braceExpand\n\nfunction braceExpand (pattern, options) {\n if (!options) {\n if (this instanceof Minimatch) {\n options = this.options\n } else {\n options = {}\n }\n }\n\n pattern = typeof pattern === 'undefined'\n ? this.pattern : pattern\n\n if (typeof pattern === 'undefined') {\n throw new TypeError('undefined pattern')\n }\n\n if (options.nobrace ||\n !pattern.match(/\\{.*\\}/)) {\n // shortcut. no need to expand.\n return [pattern]\n }\n\n return expand(pattern)\n}\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion. Otherwise, any series\n// of * is equivalent to a single *. Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\nMinimatch.prototype.parse = parse\nvar SUBPARSE = {}\nfunction parse (pattern, isSub) {\n if (pattern.length > 1024 * 64) {\n throw new TypeError('pattern is too long')\n }\n\n var options = this.options\n\n // shortcuts\n if (!options.noglobstar && pattern === '**') return GLOBSTAR\n if (pattern === '') return ''\n\n var re = ''\n var hasMagic = !!options.nocase\n var escaping = false\n // ? => one single character\n var patternListStack = []\n var negativeLists = []\n var stateChar\n var inClass = false\n var reClassStart = -1\n var classStart = -1\n // . and .. never match anything that doesn't start with .,\n // even when options.dot is set.\n var patternStart = pattern.charAt(0) === '.' ? '' // anything\n // not (start or / followed by . or .. followed by / or end)\n : options.dot ? '(?!(?:^|\\\\\\/)\\\\.{1,2}(?:$|\\\\\\/))'\n : '(?!\\\\.)'\n var self = this\n\n function clearStateChar () {\n if (stateChar) {\n // we had some state-tracking character\n // that wasn't consumed by this pass.\n switch (stateChar) {\n case '*':\n re += star\n hasMagic = true\n break\n case '?':\n re += qmark\n hasMagic = true\n break\n default:\n re += '\\\\' + stateChar\n break\n }\n self.debug('clearStateChar %j %j', stateChar, re)\n stateChar = false\n }\n }\n\n for (var i = 0, len = pattern.length, c\n ; (i < len) && (c = pattern.charAt(i))\n ; i++) {\n this.debug('%s\\t%s %s %j', pattern, i, re, c)\n\n // skip over any that are escaped.\n if (escaping && reSpecials[c]) {\n re += '\\\\' + c\n escaping = false\n continue\n }\n\n switch (c) {\n case '/':\n // completely not allowed, even escaped.\n // Should already be path-split by now.\n return false\n\n case '\\\\':\n clearStateChar()\n escaping = true\n continue\n\n // the various stateChar values\n // for the \"extglob\" stuff.\n case '?':\n case '*':\n case '+':\n case '@':\n case '!':\n this.debug('%s\\t%s %s %j <-- stateChar', pattern, i, re, c)\n\n // all of those are literals inside a class, except that\n // the glob [!a] means [^a] in regexp\n if (inClass) {\n this.debug(' in class')\n if (c === '!' && i === classStart + 1) c = '^'\n re += c\n continue\n }\n\n // if we already have a stateChar, then it means\n // that there was something like ** or +? in there.\n // Handle the stateChar, then proceed with this one.\n self.debug('call clearStateChar %j', stateChar)\n clearStateChar()\n stateChar = c\n // if extglob is disabled, then +(asdf|foo) isn't a thing.\n // just clear the statechar *now*, rather than even diving into\n // the patternList stuff.\n if (options.noext) clearStateChar()\n continue\n\n case '(':\n if (inClass) {\n re += '('\n continue\n }\n\n if (!stateChar) {\n re += '\\\\('\n continue\n }\n\n patternListStack.push({\n type: stateChar,\n start: i - 1,\n reStart: re.length,\n open: plTypes[stateChar].open,\n close: plTypes[stateChar].close\n })\n // negation is (?:(?!js)[^/]*)\n re += stateChar === '!' ? '(?:(?!(?:' : '(?:'\n this.debug('plType %j %j', stateChar, re)\n stateChar = false\n continue\n\n case ')':\n if (inClass || !patternListStack.length) {\n re += '\\\\)'\n continue\n }\n\n clearStateChar()\n hasMagic = true\n var pl = patternListStack.pop()\n // negation is (?:(?!js)[^/]*)\n // The others are (?:)\n re += pl.close\n if (pl.type === '!') {\n negativeLists.push(pl)\n }\n pl.reEnd = re.length\n continue\n\n case '|':\n if (inClass || !patternListStack.length || escaping) {\n re += '\\\\|'\n escaping = false\n continue\n }\n\n clearStateChar()\n re += '|'\n continue\n\n // these are mostly the same in regexp and glob\n case '[':\n // swallow any state-tracking char before the [\n clearStateChar()\n\n if (inClass) {\n re += '\\\\' + c\n continue\n }\n\n inClass = true\n classStart = i\n reClassStart = re.length\n re += c\n continue\n\n case ']':\n // a right bracket shall lose its special\n // meaning and represent itself in\n // a bracket expression if it occurs\n // first in the list. -- POSIX.2 2.8.3.2\n if (i === classStart + 1 || !inClass) {\n re += '\\\\' + c\n escaping = false\n continue\n }\n\n // handle the case where we left a class open.\n // \"[z-a]\" is valid, equivalent to \"\\[z-a\\]\"\n if (inClass) {\n // split where the last [ was, make sure we don't have\n // an invalid re. if so, re-walk the contents of the\n // would-be class to re-translate any characters that\n // were passed through as-is\n // TODO: It would probably be faster to determine this\n // without a try/catch and a new RegExp, but it's tricky\n // to do safely. For now, this is safe and works.\n var cs = pattern.substring(classStart + 1, i)\n try {\n RegExp('[' + cs + ']')\n } catch (er) {\n // not a valid class!\n var sp = this.parse(cs, SUBPARSE)\n re = re.substr(0, reClassStart) + '\\\\[' + sp[0] + '\\\\]'\n hasMagic = hasMagic || sp[1]\n inClass = false\n continue\n }\n }\n\n // finish up the class.\n hasMagic = true\n inClass = false\n re += c\n continue\n\n default:\n // swallow any state char that wasn't consumed\n clearStateChar()\n\n if (escaping) {\n // no need\n escaping = false\n } else if (reSpecials[c]\n && !(c === '^' && inClass)) {\n re += '\\\\'\n }\n\n re += c\n\n } // switch\n } // for\n\n // handle the case where we left a class open.\n // \"[abc\" is valid, equivalent to \"\\[abc\"\n if (inClass) {\n // split where the last [ was, and escape it\n // this is a huge pita. We now have to re-walk\n // the contents of the would-be class to re-translate\n // any characters that were passed through as-is\n cs = pattern.substr(classStart + 1)\n sp = this.parse(cs, SUBPARSE)\n re = re.substr(0, reClassStart) + '\\\\[' + sp[0]\n hasMagic = hasMagic || sp[1]\n }\n\n // handle the case where we had a +( thing at the *end*\n // of the pattern.\n // each pattern list stack adds 3 chars, and we need to go through\n // and escape any | chars that were passed through as-is for the regexp.\n // Go through and escape them, taking care not to double-escape any\n // | chars that were already escaped.\n for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {\n var tail = re.slice(pl.reStart + pl.open.length)\n this.debug('setting tail', re, pl)\n // maybe some even number of \\, then maybe 1 \\, followed by a |\n tail = tail.replace(/((?:\\\\{2}){0,64})(\\\\?)\\|/g, function (_, $1, $2) {\n if (!$2) {\n // the | isn't already escaped, so escape it.\n $2 = '\\\\'\n }\n\n // need to escape all those slashes *again*, without escaping the\n // one that we need for escaping the | character. As it works out,\n // escaping an even number of slashes can be done by simply repeating\n // it exactly after itself. That's why this trick works.\n //\n // I am sorry that you have to see this.\n return $1 + $1 + $2 + '|'\n })\n\n this.debug('tail=%j\\n %s', tail, tail, pl, re)\n var t = pl.type === '*' ? star\n : pl.type === '?' ? qmark\n : '\\\\' + pl.type\n\n hasMagic = true\n re = re.slice(0, pl.reStart) + t + '\\\\(' + tail\n }\n\n // handle trailing things that only matter at the very end.\n clearStateChar()\n if (escaping) {\n // trailing \\\\\n re += '\\\\\\\\'\n }\n\n // only need to apply the nodot start if the re starts with\n // something that could conceivably capture a dot\n var addPatternStart = false\n switch (re.charAt(0)) {\n case '.':\n case '[':\n case '(': addPatternStart = true\n }\n\n // Hack to work around lack of negative lookbehind in JS\n // A pattern like: *.!(x).!(y|z) needs to ensure that a name\n // like 'a.xyz.yz' doesn't match. So, the first negative\n // lookahead, has to look ALL the way ahead, to the end of\n // the pattern.\n for (var n = negativeLists.length - 1; n > -1; n--) {\n var nl = negativeLists[n]\n\n var nlBefore = re.slice(0, nl.reStart)\n var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)\n var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)\n var nlAfter = re.slice(nl.reEnd)\n\n nlLast += nlAfter\n\n // Handle nested stuff like *(*.js|!(*.json)), where open parens\n // mean that we should *not* include the ) in the bit that is considered\n // \"after\" the negated section.\n var openParensBefore = nlBefore.split('(').length - 1\n var cleanAfter = nlAfter\n for (i = 0; i < openParensBefore; i++) {\n cleanAfter = cleanAfter.replace(/\\)[+*?]?/, '')\n }\n nlAfter = cleanAfter\n\n var dollar = ''\n if (nlAfter === '' && isSub !== SUBPARSE) {\n dollar = '$'\n }\n var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast\n re = newRe\n }\n\n // if the re is not \"\" at this point, then we need to make sure\n // it doesn't match against an empty path part.\n // Otherwise a/* will match a/, which it should not.\n if (re !== '' && hasMagic) {\n re = '(?=.)' + re\n }\n\n if (addPatternStart) {\n re = patternStart + re\n }\n\n // parsing just a piece of a larger pattern.\n if (isSub === SUBPARSE) {\n return [re, hasMagic]\n }\n\n // skip the regexp for non-magical patterns\n // unescape anything in it, though, so that it'll be\n // an exact match against a file etc.\n if (!hasMagic) {\n return globUnescape(pattern)\n }\n\n var flags = options.nocase ? 'i' : ''\n try {\n var regExp = new RegExp('^' + re + '$', flags)\n } catch (er) {\n // If it was an invalid regular expression, then it can't match\n // anything. This trick looks for a character after the end of\n // the string, which is of course impossible, except in multi-line\n // mode, but it's not a /m regex.\n return new RegExp('$.')\n }\n\n regExp._glob = pattern\n regExp._src = re\n\n return regExp\n}\n\nminimatch.makeRe = function (pattern, options) {\n return new Minimatch(pattern, options || {}).makeRe()\n}\n\nMinimatch.prototype.makeRe = makeRe\nfunction makeRe () {\n if (this.regexp || this.regexp === false) return this.regexp\n\n // at this point, this.set is a 2d array of partial\n // pattern strings, or \"**\".\n //\n // It's better to use .match(). This function shouldn't\n // be used, really, but it's pretty convenient sometimes,\n // when you just want to work with a regex.\n var set = this.set\n\n if (!set.length) {\n this.regexp = false\n return this.regexp\n }\n var options = this.options\n\n var twoStar = options.noglobstar ? star\n : options.dot ? twoStarDot\n : twoStarNoDot\n var flags = options.nocase ? 'i' : ''\n\n var re = set.map(function (pattern) {\n return pattern.map(function (p) {\n return (p === GLOBSTAR) ? twoStar\n : (typeof p === 'string') ? regExpEscape(p)\n : p._src\n }).join('\\\\\\/')\n }).join('|')\n\n // must match entire pattern\n // ending in a * or ** will make it less strict.\n re = '^(?:' + re + ')$'\n\n // can match anything, as long as it's not this.\n if (this.negate) re = '^(?!' + re + ').*$'\n\n try {\n this.regexp = new RegExp(re, flags)\n } catch (ex) {\n this.regexp = false\n }\n return this.regexp\n}\n\nminimatch.match = function (list, pattern, options) {\n options = options || {}\n var mm = new Minimatch(pattern, options)\n list = list.filter(function (f) {\n return mm.match(f)\n })\n if (mm.options.nonull && !list.length) {\n list.push(pattern)\n }\n return list\n}\n\nMinimatch.prototype.match = match\nfunction match (f, partial) {\n this.debug('match', f, this.pattern)\n // short-circuit in the case of busted things.\n // comments, etc.\n if (this.comment) return false\n if (this.empty) return f === ''\n\n if (f === '/' && partial) return true\n\n var options = this.options\n\n // windows: need to use /, not \\\n if (path.sep !== '/') {\n f = f.split(path.sep).join('/')\n }\n\n // treat the test path as a set of pathparts.\n f = f.split(slashSplit)\n this.debug(this.pattern, 'split', f)\n\n // just ONE of the pattern sets in this.set needs to match\n // in order for it to be valid. If negating, then just one\n // match means that we have failed.\n // Either way, return on the first hit.\n\n var set = this.set\n this.debug(this.pattern, 'set', set)\n\n // Find the basename of the path by looking for the last non-empty segment\n var filename\n var i\n for (i = f.length - 1; i >= 0; i--) {\n filename = f[i]\n if (filename) break\n }\n\n for (i = 0; i < set.length; i++) {\n var pattern = set[i]\n var file = f\n if (options.matchBase && pattern.length === 1) {\n file = [filename]\n }\n var hit = this.matchOne(file, pattern, partial)\n if (hit) {\n if (options.flipNegate) return true\n return !this.negate\n }\n }\n\n // didn't get any hits. this is success if it's a negative\n // pattern, failure otherwise.\n if (options.flipNegate) return false\n return this.negate\n}\n\n// set partial to true to test if, for example,\n// \"/a/b\" matches the start of \"/*/b/*/d\"\n// Partial means, if you run out of file before you run\n// out of pattern, then that's fine, as long as all\n// the parts match.\nMinimatch.prototype.matchOne = function (file, pattern, partial) {\n var options = this.options\n\n this.debug('matchOne',\n { 'this': this, file: file, pattern: pattern })\n\n this.debug('matchOne', file.length, pattern.length)\n\n for (var fi = 0,\n pi = 0,\n fl = file.length,\n pl = pattern.length\n ; (fi < fl) && (pi < pl)\n ; fi++, pi++) {\n this.debug('matchOne loop')\n var p = pattern[pi]\n var f = file[fi]\n\n this.debug(pattern, p, f)\n\n // should be impossible.\n // some invalid regexp stuff in the set.\n if (p === false) return false\n\n if (p === GLOBSTAR) {\n this.debug('GLOBSTAR', [pattern, p, f])\n\n // \"**\"\n // a/**/b/**/c would match the following:\n // a/b/x/y/z/c\n // a/x/y/z/b/c\n // a/b/x/b/x/c\n // a/b/c\n // To do this, take the rest of the pattern after\n // the **, and see if it would match the file remainder.\n // If so, return success.\n // If not, the ** \"swallows\" a segment, and try again.\n // This is recursively awful.\n //\n // a/**/b/**/c matching a/b/x/y/z/c\n // - a matches a\n // - doublestar\n // - matchOne(b/x/y/z/c, b/**/c)\n // - b matches b\n // - doublestar\n // - matchOne(x/y/z/c, c) -> no\n // - matchOne(y/z/c, c) -> no\n // - matchOne(z/c, c) -> no\n // - matchOne(c, c) yes, hit\n var fr = fi\n var pr = pi + 1\n if (pr === pl) {\n this.debug('** at the end')\n // a ** at the end will just swallow the rest.\n // We have found a match.\n // however, it will not swallow /.x, unless\n // options.dot is set.\n // . and .. are *never* matched by **, for explosively\n // exponential reasons.\n for (; fi < fl; fi++) {\n if (file[fi] === '.' || file[fi] === '..' ||\n (!options.dot && file[fi].charAt(0) === '.')) return false\n }\n return true\n }\n\n // ok, let's see if we can swallow whatever we can.\n while (fr < fl) {\n var swallowee = file[fr]\n\n this.debug('\\nglobstar while', file, fr, pattern, pr, swallowee)\n\n // XXX remove this slice. Just pass the start index.\n if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {\n this.debug('globstar found match!', fr, fl, swallowee)\n // found a match.\n return true\n } else {\n // can't swallow \".\" or \"..\" ever.\n // can only swallow \".foo\" when explicitly asked.\n if (swallowee === '.' || swallowee === '..' ||\n (!options.dot && swallowee.charAt(0) === '.')) {\n this.debug('dot detected!', file, fr, pattern, pr)\n break\n }\n\n // ** swallows a segment, and continue.\n this.debug('globstar swallow a segment, and continue')\n fr++\n }\n }\n\n // no match was found.\n // However, in partial mode, we can't say this is necessarily over.\n // If there's more *pattern* left, then\n if (partial) {\n // ran out of file\n this.debug('\\n>>> no match, partial?', file, fr, pattern, pr)\n if (fr === fl) return true\n }\n return false\n }\n\n // something other than **\n // non-magic patterns just have to match exactly\n // patterns with magic have been turned into regexps.\n var hit\n if (typeof p === 'string') {\n if (options.nocase) {\n hit = f.toLowerCase() === p.toLowerCase()\n } else {\n hit = f === p\n }\n this.debug('string match', p, f, hit)\n } else {\n hit = f.match(p)\n this.debug('pattern match', p, f, hit)\n }\n\n if (!hit) return false\n }\n\n // Note: ending in / means that we'll get a final \"\"\n // at the end of the pattern. This can only match a\n // corresponding \"\" at the end of the file.\n // If the file ends in /, then it can only match a\n // a pattern that ends in /, unless the pattern just\n // doesn't have any more for it. But, a/b/ should *not*\n // match \"a/b/*\", even though \"\" matches against the\n // [^/]*? pattern, except in partial mode, where it might\n // simply not be reached yet.\n // However, a/b/ should still satisfy a/*\n\n // now either we fell off the end of the pattern, or we're done.\n if (fi === fl && pi === pl) {\n // ran out of pattern and filename at the same time.\n // an exact hit!\n return true\n } else if (fi === fl) {\n // ran out of file, but still had pattern left.\n // this is ok if we're doing the match as part of\n // a glob fs traversal.\n return partial\n } else if (pi === pl) {\n // ran out of pattern, still have file left.\n // this is only acceptable if we're on the very last\n // empty segment of a file with a trailing slash.\n // a/* should match a/b/\n var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')\n return emptyFileEnd\n }\n\n // should be unreachable.\n throw new Error('wtf?')\n}\n\n// replace stuff like \\* with *\nfunction globUnescape (s) {\n return s.replace(/\\\\(.)/g, '$1')\n}\n\nfunction regExpEscape (s) {\n return s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n}\n","// vim:ts=4:sts=4:sw=4:\n/*!\n *\n * Copyright 2009-2017 Kris Kowal under the terms of the MIT\n * license found at https://github.com/kriskowal/q/blob/v1/LICENSE\n *\n * With parts by Tyler Close\n * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found\n * at http://www.opensource.org/licenses/mit-license.html\n * Forked at ref_send.js version: 2009-05-11\n *\n * With parts by Mark Miller\n * Copyright (C) 2011 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\n(function (definition) {\n \"use strict\";\n\n // This file will function properly as a