"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPlatform = exports.osType = exports.writeFile = exports.exist = exports.stats = exports.debug = exports.error = exports.warning = exports.command = exports.setTaskVariable = exports.getTaskVariable = exports.getSecureFileTicket = exports.getSecureFileName = exports.getEndpointAuthorization = exports.getEndpointAuthorizationParameterRequired = exports.getEndpointAuthorizationParameter = exports.getEndpointAuthorizationSchemeRequired = exports.getEndpointAuthorizationScheme = exports.getEndpointDataParameterRequired = exports.getEndpointDataParameter = exports.getEndpointUrlRequired = exports.getEndpointUrl = exports.getPathInputRequired = exports.getPathInput = exports.filePathSupplied = exports.getDelimitedInput = exports.getPipelineFeature = exports.getBoolFeatureFlag = exports.getBoolInput = exports.getInputRequired = exports.getInput = exports.setSecret = exports.setVariable = exports.getVariables = exports.assertAgent = exports.getVariable = exports.loc = exports.setResourcePath = exports.setSanitizedResult = exports.setResult = exports.setErrStream = exports.setStdStream = exports.AgentHostedMode = exports.Platform = exports.IssueSource = exports.FieldType = exports.ArtifactType = exports.IssueType = exports.TaskState = exports.TaskResult = void 0;
exports.updateReleaseName = exports.addBuildTag = exports.updateBuildNumber = exports.uploadBuildLog = exports.associateArtifact = exports.uploadArtifact = exports.logIssue = exports.logDetail = exports.setProgress = exports.setEndpoint = exports.addAttachment = exports.uploadSummary = exports.prependPath = exports.uploadFile = exports.CodeCoverageEnabler = exports.CodeCoveragePublisher = exports.TestPublisher = exports.getHttpCertConfiguration = exports.getHttpProxyConfiguration = exports.findMatch = exports.filter = exports.match = exports.tool = exports.execSync = exports.exec = exports.execAsync = exports.rmRF = exports.legacyFindFiles = exports.find = exports.retry = exports.mv = exports.cp = exports.ls = exports.which = exports.resolve = exports.mkdirP = exports.popd = exports.pushd = exports.cd = exports.checkPath = exports.cwd = exports.getAgentMode = exports.getNodeMajorVersion = void 0;
var shell = require("shelljs");
var childProcess = require("child_process");
var fs = require("fs");
var path = require("path");
var os = require("os");
var minimatch = require("minimatch");
var im = require("./internal");
var tcm = require("./taskcommand");
var trm = require("./toolrunner");
var semver = require("semver");
var TaskResult;
(function (TaskResult) {
    TaskResult[TaskResult["Succeeded"] = 0] = "Succeeded";
    TaskResult[TaskResult["SucceededWithIssues"] = 1] = "SucceededWithIssues";
    TaskResult[TaskResult["Failed"] = 2] = "Failed";
    TaskResult[TaskResult["Cancelled"] = 3] = "Cancelled";
    TaskResult[TaskResult["Skipped"] = 4] = "Skipped";
})(TaskResult = exports.TaskResult || (exports.TaskResult = {}));
var TaskState;
(function (TaskState) {
    TaskState[TaskState["Unknown"] = 0] = "Unknown";
    TaskState[TaskState["Initialized"] = 1] = "Initialized";
    TaskState[TaskState["InProgress"] = 2] = "InProgress";
    TaskState[TaskState["Completed"] = 3] = "Completed";
})(TaskState = exports.TaskState || (exports.TaskState = {}));
var IssueType;
(function (IssueType) {
    IssueType[IssueType["Error"] = 0] = "Error";
    IssueType[IssueType["Warning"] = 1] = "Warning";
})(IssueType = exports.IssueType || (exports.IssueType = {}));
var ArtifactType;
(function (ArtifactType) {
    ArtifactType[ArtifactType["Container"] = 0] = "Container";
    ArtifactType[ArtifactType["FilePath"] = 1] = "FilePath";
    ArtifactType[ArtifactType["VersionControl"] = 2] = "VersionControl";
    ArtifactType[ArtifactType["GitRef"] = 3] = "GitRef";
    ArtifactType[ArtifactType["TfvcLabel"] = 4] = "TfvcLabel";
})(ArtifactType = exports.ArtifactType || (exports.ArtifactType = {}));
var FieldType;
(function (FieldType) {
    FieldType[FieldType["AuthParameter"] = 0] = "AuthParameter";
    FieldType[FieldType["DataParameter"] = 1] = "DataParameter";
    FieldType[FieldType["Url"] = 2] = "Url";
})(FieldType = exports.FieldType || (exports.FieldType = {}));
exports.IssueSource = im.IssueSource;
/** Platforms supported by our build agent */
var Platform;
(function (Platform) {
    Platform[Platform["Windows"] = 0] = "Windows";
    Platform[Platform["MacOS"] = 1] = "MacOS";
    Platform[Platform["Linux"] = 2] = "Linux";
})(Platform = exports.Platform || (exports.Platform = {}));
var AgentHostedMode;
(function (AgentHostedMode) {
    AgentHostedMode[AgentHostedMode["Unknown"] = 0] = "Unknown";
    AgentHostedMode[AgentHostedMode["SelfHosted"] = 1] = "SelfHosted";
    AgentHostedMode[AgentHostedMode["MsHosted"] = 2] = "MsHosted";
})(AgentHostedMode = exports.AgentHostedMode || (exports.AgentHostedMode = {}));
//-----------------------------------------------------
// General Helpers
//-----------------------------------------------------
exports.setStdStream = im._setStdStream;
exports.setErrStream = im._setErrStream;
function setResult(result, message, done) {
    (0, exports.debug)('task result: ' + TaskResult[result]);
    // add an error issue
    if (result == TaskResult.Failed && message) {
        (0, exports.error)(message, exports.IssueSource.TaskInternal);
    }
    else if (result == TaskResult.SucceededWithIssues && message) {
        (0, exports.warning)(message, exports.IssueSource.TaskInternal);
    }
    // task.complete
    var properties = { 'result': TaskResult[result] };
    if (done) {
        properties['done'] = 'true';
    }
    (0, exports.command)('task.complete', properties, message);
}
exports.setResult = setResult;
/**
 * Sets the result of the task with sanitized message.
 *
 * @param result    TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.
 * @param message   A message which will be logged as an error issue if the result is Failed. Message will be truncated
 *                  before first occurence of wellknown sensitive keyword.
 * @param done      Optional. Instructs the agent the task is done. This is helpful when child processes
 *                  may still be running and prevent node from fully exiting. This argument is supported
 *                  from agent version 2.142.0 or higher (otherwise will no-op).
 * @returns         void
 */
function setSanitizedResult(result, message, done) {
    var pattern = /password|key|secret|bearer|authorization|token|pat/i;
    var sanitizedMessage = im._truncateBeforeSensitiveKeyword(message, pattern);
    setResult(result, sanitizedMessage, done);
}
exports.setSanitizedResult = setSanitizedResult;
//
// Catching all exceptions
//
process.on('uncaughtException', function (err) {
    if (!im.isSigPipeError(err)) {
        setResult(TaskResult.Failed, (0, exports.loc)('LIB_UnhandledEx', err.message));
        (0, exports.error)(String(err.stack), im.IssueSource.TaskInternal);
    }
});
//
// Catching unhandled rejections from promises and rethrowing them as exceptions
// For example, a promise that is rejected but not handled by a .catch() handler in node 10 
// doesn't cause an uncaughtException but causes in Node 16.
// For types definitions(Error | Any) see https://nodejs.org/docs/latest-v16.x/api/process.html#event-unhandledrejection
//
process.on('unhandledRejection', function (reason) {
    if (reason instanceof Error) {
        throw reason;
    }
    else {
        throw new Error(reason);
    }
});
//-----------------------------------------------------
// Loc Helpers
//-----------------------------------------------------
exports.setResourcePath = im._setResourcePath;
exports.loc = im._loc;
//-----------------------------------------------------
// Input Helpers
//-----------------------------------------------------
exports.getVariable = im._getVariable;
/**
 * Asserts the agent version is at least the specified minimum.
 *
 * @param    minimum    minimum version version - must be 2.104.1 or higher
 */
function assertAgent(minimum) {
    if (semver.lt(minimum, '2.104.1')) {
        throw new Error('assertAgent() requires the parameter to be 2.104.1 or higher');
    }
    var agent = (0, exports.getVariable)('Agent.Version');
    if (agent && semver.lt(agent, minimum)) {
        throw new Error("Agent version ".concat(minimum, " or higher is required"));
    }
}
exports.assertAgent = assertAgent;
/**
 * Gets a snapshot of the current state of all job variables available to the task.
 * Requires a 2.104.1 agent or higher for full functionality.
 *
 * Limitations on an agent prior to 2.104.1:
 *  1) The return value does not include all public variables. Only public variables
 *     that have been added using setVariable are returned.
 *  2) The name returned for each secret variable is the formatted environment variable
 *     name, not the actual variable name (unless it was set explicitly at runtime using
 *     setVariable).
 *
 * @returns VariableInfo[]
 */
function getVariables() {
    return Object.keys(im._knownVariableMap)
        .map(function (key) {
        var info = im._knownVariableMap[key];
        return { name: info.name, value: (0, exports.getVariable)(info.name), secret: info.secret };
    });
}
exports.getVariables = getVariables;
/**
 * Sets a variable which will be available to subsequent tasks as well.
 *
 * @param     name     name of the variable to set
 * @param     val      value to set
 * @param     secret   whether variable is secret.  Multi-line secrets are not allowed.  Optional, defaults to false
 * @param     isOutput whether variable is an output variable.  Optional, defaults to false
 * @returns   void
 */
function setVariable(name, val, secret, isOutput) {
    if (secret === void 0) { secret = false; }
    if (isOutput === void 0) { isOutput = false; }
    // once a secret always a secret
    var key = im._getVariableKey(name);
    if (im._knownVariableMap.hasOwnProperty(key)) {
        secret = secret || im._knownVariableMap[key].secret;
    }
    // store the value
    var varValue = val || '';
    (0, exports.debug)('set ' + name + '=' + (secret && varValue ? '********' : varValue));
    if (secret) {
        if (varValue && varValue.match(/\r|\n/) && "".concat(process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() != 'TRUE') {
            throw new Error((0, exports.loc)('LIB_MultilineSecret'));
        }
        im._vault.storeSecret('SECRET_' + key, varValue);
        delete process.env[key];
    }
    else {
        process.env[key] = varValue;
    }
    // store the metadata
    im._knownVariableMap[key] = { name: name, secret: secret };
    // write the setvariable command
    (0, exports.command)('task.setvariable', { 'variable': name || '', isOutput: (isOutput || false).toString(), 'issecret': (secret || false).toString() }, varValue);
}
exports.setVariable = setVariable;
/**
 * Registers a value with the logger, so the value will be masked from the logs.  Multi-line secrets are not allowed.
 *
 * @param val value to register
 */
function setSecret(val) {
    if (val) {
        if (val.match(/\r|\n/) && "".concat(process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() !== 'TRUE') {
            throw new Error((0, exports.loc)('LIB_MultilineSecret'));
        }
        (0, exports.command)('task.setsecret', {}, val);
    }
}
exports.setSecret = setSecret;
/**
 * Gets the value of an input.
 * If required is true and the value is not set, it will throw.
 *
 * @param     name     name of the input to get
 * @param     required whether input is required.  optional, defaults to false
 * @returns   string
 */
function getInput(name, required) {
    var inval = im._vault.retrieveSecret('INPUT_' + im._getVariableKey(name));
    if (required && !inval) {
        throw new Error((0, exports.loc)('LIB_InputRequired', name));
    }
    (0, exports.debug)(name + '=' + inval);
    return inval;
}
exports.getInput = getInput;
/**
 * Gets the value of an input.
 * If the value is not set, it will throw.
 *
 * @param     name     name of the input to get
 * @returns   string
 */
function getInputRequired(name) {
    return getInput(name, true);
}
exports.getInputRequired = getInputRequired;
/**
 * Gets the value of an input and converts to a bool.  Convenience.
 * If required is true and the value is not set, it will throw.
 * If required is false and the value is not set, returns false.
 *
 * @param     name     name of the bool input to get
 * @param     required whether input is required.  optional, defaults to false
 * @returns   boolean
 */
function getBoolInput(name, required) {
    return (getInput(name, required) || '').toUpperCase() == "TRUE";
}
exports.getBoolInput = getBoolInput;
/**
 * Gets the value of an feature flag and converts to a bool.
 * @IMPORTANT This method is only for internal Microsoft development. Do not use it for external tasks.
 * @param     name     name of the feature flag to get.
 * @param     defaultValue default value of the feature flag in case it's not found in env. (optional. Default value = false)
 * @returns   boolean
 * @deprecated Don't use this for new development. Use getPipelineFeature instead.
 */
function getBoolFeatureFlag(ffName, defaultValue) {
    if (defaultValue === void 0) { defaultValue = false; }
    var ffValue = process.env[ffName];
    if (!ffValue) {
        (0, exports.debug)("Feature flag ".concat(ffName, " not found. Returning ").concat(defaultValue, " as default."));
        return defaultValue;
    }
    (0, exports.debug)("Feature flag ".concat(ffName, " = ").concat(ffValue));
    return ffValue.toLowerCase() === "true";
}
exports.getBoolFeatureFlag = getBoolFeatureFlag;
/**
 * Gets the value of an task feature and converts to a bool.
 * @IMPORTANT This method is only for internal Microsoft development. Do not use it for external tasks.
 * @param     name     name of the feature to get.
 * @returns   boolean
 */
function getPipelineFeature(featureName) {
    var variableName = im._getVariableKey("DistributedTask.Tasks.".concat(featureName));
    var featureValue = process.env[variableName];
    if (!featureValue) {
        (0, exports.debug)("Feature '".concat(featureName, "' not found. Returning false as default."));
        return false;
    }
    var boolValue = featureValue.toLowerCase() === "true";
    (0, exports.debug)("Feature '".concat(featureName, "' = '").concat(featureValue, "'. Processed as '").concat(boolValue, "'."));
    return boolValue;
}
exports.getPipelineFeature = getPipelineFeature;
/**
 * Gets the value of an input and splits the value using a delimiter (space, comma, etc).
 * Empty values are removed.  This function is useful for splitting an input containing a simple
 * list of items - such as build targets.
 * IMPORTANT: Do not use this function for splitting additional args!  Instead use argString(), which
 * follows normal argument splitting rules and handles values encapsulated by quotes.
 * If required is true and the value is not set, it will throw.
 *
 * @param     name     name of the input to get
 * @param     delim    delimiter to split on
 * @param     required whether input is required.  optional, defaults to false
 * @returns   string[]
 */
function getDelimitedInput(name, delim, required) {
    var inputVal = getInput(name, required);
    if (!inputVal) {
        return [];
    }
    var result = [];
    inputVal.split(delim).forEach(function (x) {
        if (x) {
            result.push(x);
        }
    });
    return result;
}
exports.getDelimitedInput = getDelimitedInput;
/**
 * Checks whether a path inputs value was supplied by the user
 * File paths are relative with a picker, so an empty path is the root of the repo.
 * Useful if you need to condition work (like append an arg) if a value was supplied
 *
 * @param     name      name of the path input to check
 * @returns   boolean
 */
function filePathSupplied(name) {
    // normalize paths
    var pathValue = this.resolve(this.getPathInput(name) || '');
    var repoRoot = this.resolve((0, exports.getVariable)('build.sourcesDirectory') || (0, exports.getVariable)('system.defaultWorkingDirectory') || '');
    var supplied = pathValue !== repoRoot;
    (0, exports.debug)(name + 'path supplied :' + supplied);
    return supplied;
}
exports.filePathSupplied = filePathSupplied;
/**
 * Gets the value of a path input
 * It will be quoted for you if it isn't already and contains spaces
 * If required is true and the value is not set, it will throw.
 * If check is true and the path does not exist, it will throw.
 *
 * @param     name      name of the input to get
 * @param     required  whether input is required.  optional, defaults to false
 * @param     check     whether path is checked.  optional, defaults to false
 * @returns   string
 */
function getPathInput(name, required, check) {
    var inval = getInput(name, required);
    if (inval) {
        if (check) {
            (0, exports.checkPath)(inval, name);
        }
    }
    return inval;
}
exports.getPathInput = getPathInput;
/**
 * Gets the value of a path input
 * It will be quoted for you if it isn't already and contains spaces
 * If the value is not set, it will throw.
 * If check is true and the path does not exist, it will throw.
 *
 * @param     name      name of the input to get
 * @param     check     whether path is checked.  optional, defaults to false
 * @returns   string
 */
function getPathInputRequired(name, check) {
    return getPathInput(name, true, check);
}
exports.getPathInputRequired = getPathInputRequired;
//-----------------------------------------------------
// Endpoint Helpers
//-----------------------------------------------------
/**
 * Gets the url for a service endpoint
 * If the url was not set and is not optional, it will throw.
 *
 * @param     id        name of the service endpoint
 * @param     optional  whether the url is optional
 * @returns   string
 */
function getEndpointUrl(id, optional) {
    var urlval = process.env['ENDPOINT_URL_' + id];
    if (!optional && !urlval) {
        throw new Error((0, exports.loc)('LIB_EndpointNotExist', id));
    }
    (0, exports.debug)(id + '=' + urlval);
    return urlval;
}
exports.getEndpointUrl = getEndpointUrl;
/**
 * Gets the url for a service endpoint
 * If the url was not set, it will throw.
 *
 * @param     id        name of the service endpoint
 * @returns   string
 */
function getEndpointUrlRequired(id) {
    return getEndpointUrl(id, false);
}
exports.getEndpointUrlRequired = getEndpointUrlRequired;
/*
 * Gets the endpoint data parameter value with specified key for a service endpoint
 * If the endpoint data parameter was not set and is not optional, it will throw.
 *
 * @param id name of the service endpoint
 * @param key of the parameter
 * @param optional whether the endpoint data is optional
 * @returns {string} value of the endpoint data parameter
 */
function getEndpointDataParameter(id, key, optional) {
    var dataParamVal = process.env['ENDPOINT_DATA_' + id + '_' + key.toUpperCase()];
    if (!optional && !dataParamVal) {
        throw new Error((0, exports.loc)('LIB_EndpointDataNotExist', id, key));
    }
    (0, exports.debug)(id + ' data ' + key + ' = ' + dataParamVal);
    return dataParamVal;
}
exports.getEndpointDataParameter = getEndpointDataParameter;
/*
 * Gets the endpoint data parameter value with specified key for a service endpoint
 * If the endpoint data parameter was not set, it will throw.
 *
 * @param id name of the service endpoint
 * @param key of the parameter
 * @returns {string} value of the endpoint data parameter
 */
function getEndpointDataParameterRequired(id, key) {
    return getEndpointDataParameter(id, key, false);
}
exports.getEndpointDataParameterRequired = getEndpointDataParameterRequired;
/**
 * Gets the endpoint authorization scheme for a service endpoint
 * If the endpoint authorization scheme is not set and is not optional, it will throw.
 *
 * @param id name of the service endpoint
 * @param optional whether the endpoint authorization scheme is optional
 * @returns {string} value of the endpoint authorization scheme
 */
function getEndpointAuthorizationScheme(id, optional) {
    var authScheme = im._vault.retrieveSecret('ENDPOINT_AUTH_SCHEME_' + id);
    if (!optional && !authScheme) {
        throw new Error((0, exports.loc)('LIB_EndpointAuthNotExist', id));
    }
    (0, exports.debug)(id + ' auth scheme = ' + authScheme);
    return authScheme;
}
exports.getEndpointAuthorizationScheme = getEndpointAuthorizationScheme;
/**
 * Gets the endpoint authorization scheme for a service endpoint
 * If the endpoint authorization scheme is not set, it will throw.
 *
 * @param id name of the service endpoint
 * @returns {string} value of the endpoint authorization scheme
 */
function getEndpointAuthorizationSchemeRequired(id) {
    return getEndpointAuthorizationScheme(id, false);
}
exports.getEndpointAuthorizationSchemeRequired = getEndpointAuthorizationSchemeRequired;
/**
 * Gets the endpoint authorization parameter value for a service endpoint with specified key
 * If the endpoint authorization parameter is not set and is not optional, it will throw.
 *
 * @param id name of the service endpoint
 * @param key key to find the endpoint authorization parameter
 * @param optional optional whether the endpoint authorization scheme is optional
 * @returns {string} value of the endpoint authorization parameter value
 */
function getEndpointAuthorizationParameter(id, key, optional) {
    var authParam = im._vault.retrieveSecret('ENDPOINT_AUTH_PARAMETER_' + id + '_' + key.toUpperCase());
    if (!optional && !authParam) {
        throw new Error((0, exports.loc)('LIB_EndpointAuthNotExist', id));
    }
    (0, exports.debug)(id + ' auth param ' + key + ' = ' + authParam);
    return authParam;
}
exports.getEndpointAuthorizationParameter = getEndpointAuthorizationParameter;
/**
 * Gets the endpoint authorization parameter value for a service endpoint with specified key
 * If the endpoint authorization parameter is not set, it will throw.
 *
 * @param id name of the service endpoint
 * @param key key to find the endpoint authorization parameter
 * @returns {string} value of the endpoint authorization parameter value
 */
function getEndpointAuthorizationParameterRequired(id, key) {
    return getEndpointAuthorizationParameter(id, key, false);
}
exports.getEndpointAuthorizationParameterRequired = getEndpointAuthorizationParameterRequired;
/**
 * Gets the authorization details for a service endpoint
 * If the authorization was not set and is not optional, it will set the task result to Failed.
 *
 * @param     id        name of the service endpoint
 * @param     optional  whether the url is optional
 * @returns   string
 */
function getEndpointAuthorization(id, optional) {
    var aval = im._vault.retrieveSecret('ENDPOINT_AUTH_' + id);
    if (!optional && !aval) {
        setResult(TaskResult.Failed, (0, exports.loc)('LIB_EndpointAuthNotExist', id));
    }
    (0, exports.debug)(id + ' exists ' + (!!aval));
    var auth;
    try {
        if (aval) {
            auth = JSON.parse(aval);
        }
    }
    catch (err) {
        throw new Error((0, exports.loc)('LIB_InvalidEndpointAuth', aval));
    }
    return auth;
}
exports.getEndpointAuthorization = getEndpointAuthorization;
//-----------------------------------------------------
// SecureFile Helpers
//-----------------------------------------------------
/**
 * Gets the name for a secure file
 *
 * @param     id        secure file id
 * @returns   string
 */
function getSecureFileName(id) {
    var name = process.env['SECUREFILE_NAME_' + id];
    (0, exports.debug)('secure file name for id ' + id + ' = ' + name);
    return name;
}
exports.getSecureFileName = getSecureFileName;
/**
  * Gets the secure file ticket that can be used to download the secure file contents
  *
  * @param id name of the secure file
  * @returns {string} secure file ticket
  */
function getSecureFileTicket(id) {
    var ticket = im._vault.retrieveSecret('SECUREFILE_TICKET_' + id);
    (0, exports.debug)('secure file ticket for id ' + id + ' = ' + ticket);
    return ticket;
}
exports.getSecureFileTicket = getSecureFileTicket;
//-----------------------------------------------------
// Task Variable Helpers
//-----------------------------------------------------
/**
 * Gets a variable value that is set by previous step from the same wrapper task.
 * Requires a 2.115.0 agent or higher.
 *
 * @param     name     name of the variable to get
 * @returns   string
 */
function getTaskVariable(name) {
    assertAgent('2.115.0');
    var inval = im._vault.retrieveSecret('VSTS_TASKVARIABLE_' + im._getVariableKey(name));
    if (inval) {
        inval = inval.trim();
    }
    (0, exports.debug)('task variable: ' + name + '=' + inval);
    return inval;
}
exports.getTaskVariable = getTaskVariable;
/**
 * Sets a task variable which will only be available to subsequent steps belong to the same wrapper task.
 * Requires a 2.115.0 agent or higher.
 *
 * @param     name    name of the variable to set
 * @param     val     value to set
 * @param     secret  whether variable is secret.  optional, defaults to false
 * @returns   void
 */
function setTaskVariable(name, val, secret) {
    if (secret === void 0) { secret = false; }
    assertAgent('2.115.0');
    var key = im._getVariableKey(name);
    // store the value
    var varValue = val || '';
    (0, exports.debug)('set task variable: ' + name + '=' + (secret && varValue ? '********' : varValue));
    im._vault.storeSecret('VSTS_TASKVARIABLE_' + key, varValue);
    delete process.env[key];
    // write the command
    (0, exports.command)('task.settaskvariable', { 'variable': name || '', 'issecret': (secret || false).toString() }, varValue);
}
exports.setTaskVariable = setTaskVariable;
//-----------------------------------------------------
// Cmd Helpers
//-----------------------------------------------------
exports.command = im._command;
exports.warning = im._warning;
exports.error = im._error;
exports.debug = im._debug;
//-----------------------------------------------------
// Disk Functions
//-----------------------------------------------------
function _checkShell(cmd, continueOnError) {
    var se = shell.error();
    if (se) {
        (0, exports.debug)(cmd + ' failed');
        var errMsg = (0, exports.loc)('LIB_OperationFailed', cmd, se);
        (0, exports.debug)(errMsg);
        if (!continueOnError) {
            throw new Error(errMsg);
        }
    }
}
/**
 * Get's stat on a path.
 * Useful for checking whether a file or directory.  Also getting created, modified and accessed time.
 * see [fs.stat](https://nodejs.org/api/fs.html#fs_class_fs_stats)
 *
 * @param     path      path to check
 * @returns   fsStat
 */
function stats(path) {
    return fs.statSync(path);
}
exports.stats = stats;
exports.exist = im._exist;
function writeFile(file, data, options) {
    if (typeof (options) === 'string') {
        fs.writeFileSync(file, data, { encoding: options });
    }
    else {
        fs.writeFileSync(file, data, options);
    }
}
exports.writeFile = writeFile;
/**
 * @deprecated Use `getPlatform`
 * Useful for determining the host operating system.
 * see [os.type](https://nodejs.org/api/os.html#os_os_type)
 *
 * @return      the name of the operating system
 */
function osType() {
    return os.type();
}
exports.osType = osType;
/**
 * Determine the operating system the build agent is running on.
 * @returns {Platform}
 * @throws {Error} Platform is not supported by our agent
 */
function getPlatform() {
    switch (process.platform) {
        case 'win32': return Platform.Windows;
        case 'darwin': return Platform.MacOS;
        case 'linux': return Platform.Linux;
        default: throw Error((0, exports.loc)('LIB_PlatformNotSupported', process.platform));
    }
}
exports.getPlatform = getPlatform;
/**
 * Resolves major version of Node.js engine used by the agent.
 * @returns {Number} Node's major version.
 */
function getNodeMajorVersion() {
    var _a;
    var version = (_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node;
    if (!version) {
        throw new Error((0, exports.loc)('LIB_UndefinedNodeVersion'));
    }
    var parts = version.split('.').map(Number);
    if (parts.length < 1) {
        return NaN;
    }
    return parts[0];
}
exports.getNodeMajorVersion = getNodeMajorVersion;
/**
 * Return hosted type of Agent
 * @returns {AgentHostedMode}
 */
function getAgentMode() {
    var agentCloudId = (0, exports.getVariable)('Agent.CloudId');
    if (agentCloudId === undefined)
        return AgentHostedMode.Unknown;
    if (agentCloudId)
        return AgentHostedMode.MsHosted;
    return AgentHostedMode.SelfHosted;
}
exports.getAgentMode = getAgentMode;
/**
 * Returns the process's current working directory.
 * see [process.cwd](https://nodejs.org/api/process.html#process_process_cwd)
 *
 * @return      the path to the current working directory of the process
 */
function cwd() {
    return process.cwd();
}
exports.cwd = cwd;
exports.checkPath = im._checkPath;
/**
 * Change working directory.
 *
 * @param     path      new working directory path
 * @returns   void
 */
function cd(path) {
    if (path) {
        shell.cd(path);
        _checkShell('cd');
    }
}
exports.cd = cd;
/**
 * Change working directory and push it on the stack
 *
 * @param     path      new working directory path
 * @returns   void
 */
function pushd(path) {
    shell.pushd(path);
    _checkShell('pushd');
}
exports.pushd = pushd;
/**
 * Change working directory back to previously pushed directory
 *
 * @returns   void
 */
function popd() {
    shell.popd();
    _checkShell('popd');
}
exports.popd = popd;
/**
 * Make a directory.  Creates the full path with folders in between
 * Will throw if it fails
 *
 * @param     p       path to create
 * @returns   void
 */
function mkdirP(p) {
    if (!p) {
        throw new Error((0, exports.loc)('LIB_ParameterIsRequired', 'p'));
    }
    // build a stack of directories to create
    var stack = [];
    var testDir = p;
    while (true) {
        // validate the loop is not out of control
        if (stack.length >= Number(process.env['TASKLIB_TEST_MKDIRP_FAILSAFE'] || 1000)) {
            // let the framework throw
            (0, exports.debug)('loop is out of control');
            fs.mkdirSync(p);
            return;
        }
        (0, exports.debug)("testing directory '".concat(testDir, "'"));
        var stats_1 = void 0;
        try {
            stats_1 = fs.statSync(testDir);
        }
        catch (err) {
            if (err.code == 'ENOENT') {
                // validate the directory is not the drive root
                var parentDir = path.dirname(testDir);
                if (testDir == parentDir) {
                    throw new Error((0, exports.loc)('LIB_MkdirFailedInvalidDriveRoot', p, testDir)); // Unable to create directory '{p}'. Root directory does not exist: '{testDir}'
                }
                // push the dir and test the parent
                stack.push(testDir);
                testDir = parentDir;
                continue;
            }
            else if (err.code == 'UNKNOWN') {
                throw new Error((0, 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.
            }
            else {
                throw err;
            }
        }
        if (!stats_1.isDirectory()) {
            throw new Error((0, exports.loc)('LIB_MkdirFailedFileExists', p, testDir)); // Unable to create directory '{p}'. Conflicting file exists: '{testDir}'
        }
        // testDir exists
        break;
    }
    // create each directory
    while (stack.length) {
        var dir = stack.pop(); // non-null because `stack.length` was truthy
        (0, exports.debug)("mkdir '".concat(dir, "'"));
        try {
            fs.mkdirSync(dir);
        }
        catch (err) {
            throw new Error((0, exports.loc)('LIB_MkdirFailed', p, err.message)); // Unable to create directory '{p}'. {err.message}
        }
    }
}
exports.mkdirP = mkdirP;
/**
 * Resolves a sequence of paths or path segments into an absolute path.
 * Calls node.js path.resolve()
 * Allows L0 testing with consistent path formats on Mac/Linux and Windows in the mock implementation
 * @param pathSegments
 * @returns {string}
 */
function resolve() {
    var pathSegments = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        pathSegments[_i] = arguments[_i];
    }
    var absolutePath = path.resolve.apply(this, pathSegments);
    (0, exports.debug)('Absolute path for pathSegments: ' + pathSegments + ' = ' + absolutePath);
    return absolutePath;
}
exports.resolve = resolve;
exports.which = im._which;
/**
 * Returns array of files in the given path, or in current directory if no path provided.  See shelljs.ls
 * @param  {string}   options  Available options: -R (recursive), -A (all files, include files beginning with ., except for . and ..)
 * @param  {string[]} paths    Paths to search.
 * @return {string[]}          An array of files in the given path(s).
 */
function ls(options, paths) {
    if (options) {
        return shell.ls(options, paths);
    }
    else {
        return shell.ls(paths);
    }
}
exports.ls = ls;
/**
 * Copies a file or folder.
 *
 * @param     source     source path
 * @param     dest       destination path
 * @param     options    string -r, -f or -rf for recursive and force
 * @param     continueOnError optional. whether to continue on error
 * @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.
 */
function cp(source, dest, options, continueOnError, retryCount) {
    if (retryCount === void 0) { retryCount = 0; }
    while (retryCount >= 0) {
        try {
            if (options) {
                shell.cp(options, source, dest);
            }
            else {
                shell.cp(source, dest);
            }
            _checkShell('cp', false);
            break;
        }
        catch (e) {
            if (retryCount <= 0) {
                if (continueOnError) {
                    (0, exports.warning)(e, exports.IssueSource.TaskInternal);
                    break;
                }
                else {
                    throw e;
                }
            }
            else {
                console.log((0, exports.loc)('LIB_CopyFileFailed', retryCount));
                retryCount--;
            }
        }
    }
}
exports.cp = cp;
/**
 * Moves a path.
 *
 * @param     source     source path
 * @param     dest       destination path
 * @param     options    string -f or -n for force and no clobber
 * @param     continueOnError optional. whether to continue on error
 */
function mv(source, dest, options, continueOnError) {
    if (options) {
        shell.mv(options, source, dest);
    }
    else {
        shell.mv(source, dest);
    }
    _checkShell('mv', continueOnError);
}
exports.mv = mv;
/**
 * Tries to execute a function a specified number of times.
 *
 * @param   func            a function to be executed.
 * @param   args            executed function arguments array.
 * @param   retryOptions    optional. Defaults to { continueOnError: false, retryCount: 0 }.
 * @returns the same as the usual function.
 */
function retry(func, args, retryOptions) {
    if (retryOptions === void 0) { retryOptions = { continueOnError: false, retryCount: 0 }; }
    while (retryOptions.retryCount >= 0) {
        try {
            return func.apply(void 0, args);
        }
        catch (e) {
            if (retryOptions.retryCount <= 0) {
                if (retryOptions.continueOnError) {
                    (0, exports.warning)(e, exports.IssueSource.TaskInternal);
                    break;
                }
                else {
                    throw e;
                }
            }
            else {
                (0, exports.debug)("Attempt to execute function \"".concat(func === null || func === void 0 ? void 0 : func.name, "\" failed, retries left: ").concat(retryOptions.retryCount));
                retryOptions.retryCount--;
            }
        }
    }
}
exports.retry = retry;
/**
 * Gets info about item stats.
 *
 * @param path                      a path to the item to be processed.
 * @param followSymbolicLink        indicates whether to traverse descendants of symbolic link directories.
 * @param allowBrokenSymbolicLinks  when true, broken symbolic link will not cause an error.
 * @returns fs.Stats
 */
function _getStats(path, followSymbolicLink, allowBrokenSymbolicLinks) {
    // stat returns info about the target of a symlink (or symlink chain),
    // lstat returns info about a symlink itself
    var stats;
    if (followSymbolicLink) {
        try {
            // use stat (following symlinks)
            stats = fs.statSync(path);
        }
        catch (err) {
            if (err.code == 'ENOENT' && allowBrokenSymbolicLinks) {
                // fallback to lstat (broken symlinks allowed)
                stats = fs.lstatSync(path);
                (0, exports.debug)("  ".concat(path, " (broken symlink)"));
            }
            else {
                throw err;
            }
        }
    }
    else {
        // use lstat (not following symlinks)
        stats = fs.lstatSync(path);
    }
    return stats;
}
/**
 * Recursively finds all paths a given path. Returns an array of paths.
 *
 * @param     findPath  path to search
 * @param     options   optional. defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.
 * @returns   string[]
 */
function find(findPath, options) {
    if (!findPath) {
        (0, exports.debug)('no path specified');
        return [];
    }
    // normalize the path, otherwise the first result is inconsistently formatted from the rest of the results
    // because path.join() performs normalization.
    findPath = path.normalize(findPath);
    // debug trace the parameters
    (0, exports.debug)("findPath: '".concat(findPath, "'"));
    options = options || _getDefaultFindOptions();
    _debugFindOptions(options);
    // return empty if not exists
    try {
        fs.lstatSync(findPath);
    }
    catch (err) {
        if (err.code == 'ENOENT') {
            (0, exports.debug)('0 results');
            return [];
        }
        throw err;
    }
    try {
        var result = [];
        // push the first item
        var stack = [new _FindItem(findPath, 1)];
        var traversalChain = []; // used to detect cycles
        var _loop_1 = function () {
            // pop the next item and push to the result array
            var item = stack.pop(); // non-null because `stack.length` was truthy
            var stats_2 = void 0;
            try {
                // `item.path` equals `findPath` for the first item to be processed, when the `result` array is empty
                var isPathToSearch = !result.length;
                // following specified symlinks only if current path equals specified path
                var followSpecifiedSymbolicLink = options.followSpecifiedSymbolicLink && isPathToSearch;
                // following all symlinks or following symlink for the specified path
                var followSymbolicLink = options.followSymbolicLinks || followSpecifiedSymbolicLink;
                // stat the item. The stat info is used further below to determine whether to traverse deeper
                stats_2 = _getStats(item.path, followSymbolicLink, options.allowBrokenSymbolicLinks);
            }
            catch (err) {
                if (err.code == 'ENOENT' && options.skipMissingFiles) {
                    (0, exports.warning)("No such file or directory: \"".concat(item.path, "\" - skipping."), exports.IssueSource.TaskInternal);
                    return "continue";
                }
                throw err;
            }
            result.push(item.path);
            // note, isDirectory() returns false for the lstat of a symlink
            if (stats_2.isDirectory()) {
                (0, exports.debug)("  ".concat(item.path, " (directory)"));
                if (options.followSymbolicLinks) {
                    // get the realpath
                    var realPath_1;
                    if (im._isUncPath(item.path)) {
                        // Sometimes there are spontaneous issues when working with unc-paths, so retries have been added for them.
                        realPath_1 = retry(fs.realpathSync, [item.path], { continueOnError: false, retryCount: 5 });
                    }
                    else {
                        realPath_1 = fs.realpathSync(item.path);
                    }
                    // fixup the traversal chain to match the item level
                    while (traversalChain.length >= item.level) {
                        traversalChain.pop();
                    }
                    // test for a cycle
                    if (traversalChain.some(function (x) { return x == realPath_1; })) {
                        (0, exports.debug)('    cycle detected');
                        return "continue";
                    }
                    // update the traversal chain
                    traversalChain.push(realPath_1);
                }
                // push the child items in reverse onto the stack
                var childLevel_1 = item.level + 1;
                var childItems = fs.readdirSync(item.path)
                    .map(function (childName) { return new _FindItem(path.join(item.path, childName), childLevel_1); });
                for (var i = childItems.length - 1; i >= 0; i--) {
                    stack.push(childItems[i]);
                }
            }
            else {
                (0, exports.debug)("  ".concat(item.path, " (file)"));
            }
        };
        while (stack.length) {
            _loop_1();
        }
        (0, exports.debug)("".concat(result.length, " results"));
        return result;
    }
    catch (err) {
        throw new Error((0, exports.loc)('LIB_OperationFailed', 'find', err.message));
    }
}
exports.find = find;
var _FindItem = /** @class */ (function () {
    function _FindItem(path, level) {
        this.path = path;
        this.level = level;
    }
    return _FindItem;
}());
function _debugFindOptions(options) {
    (0, exports.debug)("findOptions.allowBrokenSymbolicLinks: '".concat(options.allowBrokenSymbolicLinks, "'"));
    (0, exports.debug)("findOptions.followSpecifiedSymbolicLink: '".concat(options.followSpecifiedSymbolicLink, "'"));
    (0, exports.debug)("findOptions.followSymbolicLinks: '".concat(options.followSymbolicLinks, "'"));
    (0, exports.debug)("findOptions.skipMissingFiles: '".concat(options.skipMissingFiles, "'"));
}
function _getDefaultFindOptions() {
    return {
        allowBrokenSymbolicLinks: false,
        followSpecifiedSymbolicLink: true,
        followSymbolicLinks: true,
        skipMissingFiles: false
    };
}
/**
 * Prefer tl.find() and tl.match() instead. This function is for backward compatibility
 * when porting tasks to Node from the PowerShell or PowerShell3 execution handler.
 *
 * @param    rootDirectory      path to root unrooted patterns with
 * @param    pattern            include and exclude patterns
 * @param    includeFiles       whether to include files in the result. defaults to true when includeFiles and includeDirectories are both false
 * @param    includeDirectories whether to include directories in the result
 * @returns  string[]
 */
function legacyFindFiles(rootDirectory, pattern, includeFiles, includeDirectories) {
    if (!pattern) {
        throw new Error('pattern parameter cannot be empty');
    }
    (0, exports.debug)("legacyFindFiles rootDirectory: '".concat(rootDirectory, "'"));
    (0, exports.debug)("pattern: '".concat(pattern, "'"));
    (0, exports.debug)("includeFiles: '".concat(includeFiles, "'"));
    (0, exports.debug)("includeDirectories: '".concat(includeDirectories, "'"));
    if (!includeFiles && !includeDirectories) {
        includeFiles = true;
    }
    // organize the patterns into include patterns and exclude patterns
    var includePatterns = [];
    var excludePatterns = [];
    pattern = pattern.replace(/;;/g, '\0');
    for (var _i = 0, _a = pattern.split(';'); _i < _a.length; _i++) {
        var pat = _a[_i];
        if (!pat) {
            continue;
        }
        pat = pat.replace(/\0/g, ';');
        // determine whether include pattern and remove any include/exclude prefix.
        // include patterns start with +: or anything other than -:
        // exclude patterns start with -:
        var isIncludePattern = void 0;
        if (im._startsWith(pat, '+:')) {
            pat = pat.substring(2);
            isIncludePattern = true;
        }
        else if (im._startsWith(pat, '-:')) {
            pat = pat.substring(2);
            isIncludePattern = false;
        }
        else {
            isIncludePattern = true;
        }
        // validate pattern does not end with a slash
        if (im._endsWith(pat, '/') || (process.platform == 'win32' && im._endsWith(pat, '\\'))) {
            throw new Error((0, exports.loc)('LIB_InvalidPattern', pat));
        }
        // root the pattern
        if (rootDirectory && !path.isAbsolute(pat)) {
            pat = path.join(rootDirectory, pat);
            // remove trailing slash sometimes added by path.join() on Windows, e.g.
            //      path.join('\\\\hello', 'world') => '\\\\hello\\world\\'
            //      path.join('//hello', 'world') => '\\\\hello\\world\\'
            if (im._endsWith(pat, '\\')) {
                pat = pat.substring(0, pat.length - 1);
            }
        }
        if (isIncludePattern) {
            includePatterns.push(pat);
        }
        else {
            excludePatterns.push(im._legacyFindFiles_convertPatternToRegExp(pat));
        }
    }
    // find and apply patterns
    var count = 0;
    var result = _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, !!includeFiles, !!includeDirectories);
    (0, exports.debug)('all matches:');
    for (var _b = 0, result_1 = result; _b < result_1.length; _b++) {
        var resultItem = result_1[_b];
        (0, exports.debug)(' ' + resultItem);
    }
    (0, exports.debug)('total matched: ' + result.length);
    return result;
}
exports.legacyFindFiles = legacyFindFiles;
function _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, includeFiles, includeDirectories) {
    (0, exports.debug)('getMatchingItems()');
    for (var _i = 0, includePatterns_1 = includePatterns; _i < includePatterns_1.length; _i++) {
        var pattern = includePatterns_1[_i];
        (0, exports.debug)("includePattern: '".concat(pattern, "'"));
    }
    for (var _a = 0, excludePatterns_1 = excludePatterns; _a < excludePatterns_1.length; _a++) {
        var pattern = excludePatterns_1[_a];
        (0, exports.debug)("excludePattern: ".concat(pattern));
    }
    (0, exports.debug)('includeFiles: ' + includeFiles);
    (0, exports.debug)('includeDirectories: ' + includeDirectories);
    var allFiles = {};
    var _loop_2 = function (pattern) {
        // determine the directory to search
        //
        // note, getDirectoryName removes redundant path separators
        var findPath = void 0;
        var starIndex = pattern.indexOf('*');
        var questionIndex = pattern.indexOf('?');
        if (starIndex < 0 && questionIndex < 0) {
            // if no wildcards are found, use the directory name portion of the path.
            // if there is no directory name (file name only in pattern or drive root),
            // this will return empty string.
            findPath = im._getDirectoryName(pattern);
        }
        else {
            // extract the directory prior to the first wildcard
            var index = Math.min(starIndex >= 0 ? starIndex : questionIndex, questionIndex >= 0 ? questionIndex : starIndex);
            findPath = im._getDirectoryName(pattern.substring(0, index));
        }
        // note, due to this short-circuit and the above usage of getDirectoryName, this
        // function has the same limitations regarding drive roots as the powershell
        // implementation.
        //
        // also note, since getDirectoryName eliminates slash redundancies, some additional
        // work may be required if removal of this limitation is attempted.
        if (!findPath) {
            return "continue";
        }
        var patternRegex = im._legacyFindFiles_convertPatternToRegExp(pattern);
        // find files/directories
        var items = find(findPath, { followSymbolicLinks: true })
            .filter(function (item) {
            if (includeFiles && includeDirectories) {
                return true;
            }
            var isDir = fs.statSync(item).isDirectory();
            return (includeFiles && !isDir) || (includeDirectories && isDir);
        })
            .forEach(function (item) {
            var normalizedPath = process.platform == 'win32' ? item.replace(/\\/g, '/') : item; // normalize separators
            // **/times/** will not match C:/fun/times because there isn't a trailing slash
            // so try both if including directories
            var alternatePath = "".concat(normalizedPath, "/"); // potential bug: it looks like this will result in a false
            // positive if the item is a regular file and not a directory
            var isMatch = false;
            if (patternRegex.test(normalizedPath) || (includeDirectories && patternRegex.test(alternatePath))) {
                isMatch = true;
                // test whether the path should be excluded
                for (var _i = 0, excludePatterns_2 = excludePatterns; _i < excludePatterns_2.length; _i++) {
                    var regex = excludePatterns_2[_i];
                    if (regex.test(normalizedPath) || (includeDirectories && regex.test(alternatePath))) {
                        isMatch = false;
                        break;
                    }
                }
            }
            if (isMatch) {
                allFiles[item] = item;
            }
        });
    };
    for (var _b = 0, includePatterns_2 = includePatterns; _b < includePatterns_2.length; _b++) {
        var pattern = includePatterns_2[_b];
        _loop_2(pattern);
    }
    return Object.keys(allFiles).sort();
}
/**
 * Remove a path recursively with force
 *
 * @param     inputPath path to remove
 * @throws    when the file or directory exists but could not be deleted.
 */
function rmRF(inputPath) {
    (0, exports.debug)('rm -rf ' + inputPath);
    if (getPlatform() == Platform.Windows) {
        // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
        // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
        try {
            if (fs.statSync(inputPath).isDirectory()) {
                (0, exports.debug)('removing directory ' + inputPath);
                childProcess.execSync("rd /s /q \"".concat(inputPath, "\""));
            }
            else {
                (0, exports.debug)('removing file ' + inputPath);
                childProcess.execSync("del /f /a \"".concat(inputPath, "\""));
            }
        }
        catch (err) {
            // if you try to delete a file that doesn't exist, desired result is achieved
            // other errors are valid
            if (err.code != 'ENOENT') {
                throw new Error((0, exports.loc)('LIB_OperationFailed', 'rmRF', err.message));
            }
        }
        // Shelling out fails to remove a symlink folder with missing source, this unlink catches that
        try {
            fs.unlinkSync(inputPath);
        }
        catch (err) {
            // if you try to delete a file that doesn't exist, desired result is achieved
            // other errors are valid
            if (err.code != 'ENOENT') {
                throw new Error((0, exports.loc)('LIB_OperationFailed', 'rmRF', err.message));
            }
        }
    }
    else {
        // get the lstats in order to workaround a bug in shelljs@0.3.0 where symlinks
        // with missing targets are not handled correctly by "rm('-rf', path)"
        var lstats = void 0;
        try {
            lstats = fs.lstatSync(inputPath);
        }
        catch (err) {
            // if you try to delete a file that doesn't exist, desired result is achieved
            // other errors are valid
            if (err.code == 'ENOENT') {
                return;
            }
            throw new Error((0, exports.loc)('LIB_OperationFailed', 'rmRF', err.message));
        }
        if (lstats.isDirectory()) {
            (0, exports.debug)('removing directory');
            shell.rm('-rf', inputPath);
            var errMsg = shell.error();
            if (errMsg) {
                throw new Error((0, exports.loc)('LIB_OperationFailed', 'rmRF', errMsg));
            }
            return;
        }
        (0, exports.debug)('removing file');
        try {
            fs.unlinkSync(inputPath);
        }
        catch (err) {
            throw new Error((0, exports.loc)('LIB_OperationFailed', 'rmRF', err.message));
        }
    }
}
exports.rmRF = rmRF;
/**
 * Exec a tool.  Convenience wrapper over ToolRunner to exec with args in one call.
 * Output will be streamed to the live console.
 * Returns promise with return code
 *
 * @param     tool     path to tool to exec
 * @param     args     an arg string or array of args
 * @param     options  optional exec options.  See IExecOptions
 * @returns   number
 */
function execAsync(tool, args, options) {
    var tr = this.tool(tool);
    if (args) {
        if (args instanceof Array) {
            tr.arg(args);
        }
        else if (typeof (args) === 'string') {
            tr.line(args);
        }
    }
    return tr.execAsync(options);
}
exports.execAsync = execAsync;
/**
 * Exec a tool.  Convenience wrapper over ToolRunner to exec with args in one call.
 * Output will be streamed to the live console.
 * Returns promise with return code
 *
 * @deprecated Use the {@link execAsync} method that returns a native Javascript Promise instead
 * @param     tool     path to tool to exec
 * @param     args     an arg string or array of args
 * @param     options  optional exec options.  See IExecOptions
 * @returns   number
 */
function exec(tool, args, options) {
    var tr = this.tool(tool);
    if (args) {
        if (args instanceof Array) {
            tr.arg(args);
        }
        else if (typeof (args) === 'string') {
            tr.line(args);
        }
    }
    return tr.exec(options);
}
exports.exec = exec;
/**
 * Exec a tool synchronously.  Convenience wrapper over ToolRunner to execSync with args in one call.
 * Output will be *not* be streamed to the live console.  It will be returned after execution is complete.
 * Appropriate for short running tools
 * Returns IExecResult with output and return code
 *
 * @param     tool     path to tool to exec
 * @param     args     an arg string or array of args
 * @param     options  optional exec options.  See IExecSyncOptions
 * @returns   IExecSyncResult
 */
function execSync(tool, args, options) {
    var tr = this.tool(tool);
    if (args) {
        if (args instanceof Array) {
            tr.arg(args);
        }
        else if (typeof (args) === 'string') {
            tr.line(args);
        }
    }
    return tr.execSync(options);
}
exports.execSync = execSync;
/**
 * Convenience factory to create a ToolRunner.
 *
 * @param     tool     path to tool to exec
 * @returns   ToolRunner
 */
function tool(tool) {
    var tr = new trm.ToolRunner(tool);
    tr.on('debug', function (message) {
        (0, exports.debug)(message);
    });
    return tr;
}
exports.tool = tool;
/**
 * Applies glob patterns to a list of paths. Supports interleaved exclude patterns.
 *
 * @param  list         array of paths
 * @param  patterns     patterns to apply. supports interleaved exclude patterns.
 * @param  patternRoot  optional. default root to apply to unrooted patterns. not applied to basename-only patterns when matchBase:true.
 * @param  options      optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.
 */
function match(list, patterns, patternRoot, options) {
    // trace parameters
    (0, exports.debug)("patternRoot: '".concat(patternRoot, "'"));
    options = options || _getDefaultMatchOptions(); // default match options
    _debugMatchOptions(options);
    // convert pattern to an array
    if (typeof patterns == 'string') {
        patterns = [patterns];
    }
    // hashtable to keep track of matches
    var map = {};
    var originalOptions = options;
    for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
        var pattern = patterns_1[_i];
        (0, exports.debug)("pattern: '".concat(pattern, "'"));
        // trim and skip empty
        pattern = (pattern || '').trim();
        if (!pattern) {
            (0, exports.debug)('skipping empty pattern');
            continue;
        }
        // clone match options
        var options_1 = im._cloneMatchOptions(originalOptions);
        // skip comments
        if (!options_1.nocomment && im._startsWith(pattern, '#')) {
            (0, exports.debug)('skipping comment');
            continue;
        }
        // set nocomment - brace expansion could result in a leading '#'
        options_1.nocomment = true;
        // determine whether pattern is include or exclude
        var negateCount = 0;
        if (!options_1.nonegate) {
            while (pattern.charAt(negateCount) == '!') {
                negateCount++;
            }
            pattern = pattern.substring(negateCount); // trim leading '!'
            if (negateCount) {
                (0, exports.debug)("trimmed leading '!'. pattern: '".concat(pattern, "'"));
            }
        }
        var isIncludePattern = negateCount == 0 ||
            (negateCount % 2 == 0 && !options_1.flipNegate) ||
            (negateCount % 2 == 1 && options_1.flipNegate);
        // set nonegate - brace expansion could result in a leading '!'
        options_1.nonegate = true;
        options_1.flipNegate = false;
        // expand braces - required to accurately root patterns
        var expanded = void 0;
        var preExpanded = pattern;
        if (options_1.nobrace) {
            expanded = [pattern];
        }
        else {
            // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot
            // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
            (0, exports.debug)('expanding braces');
            var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern;
            expanded = minimatch.braceExpand(convertedPattern);
        }
        // set nobrace
        options_1.nobrace = true;
        for (var _a = 0, expanded_1 = expanded; _a < expanded_1.length; _a++) {
            var pattern_1 = expanded_1[_a];
            if (expanded.length != 1 || pattern_1 != preExpanded) {
                (0, exports.debug)("pattern: '".concat(pattern_1, "'"));
            }
            // trim and skip empty
            pattern_1 = (pattern_1 || '').trim();
            if (!pattern_1) {
                (0, exports.debug)('skipping empty pattern');
                continue;
            }
            // root the pattern when all of the following conditions are true:
            if (patternRoot && // patternRoot supplied
                !im._isRooted(pattern_1) && // AND pattern not rooted
                // AND matchBase:false or not basename only
                (!options_1.matchBase || (process.platform == 'win32' ? pattern_1.replace(/\\/g, '/') : pattern_1).indexOf('/') >= 0)) {
                pattern_1 = im._ensureRooted(patternRoot, pattern_1);
                (0, exports.debug)("rooted pattern: '".concat(pattern_1, "'"));
            }
            if (isIncludePattern) {
                // apply the pattern
                (0, exports.debug)('applying include pattern against original list');
                var matchResults = minimatch.match(list, pattern_1, options_1);
                (0, exports.debug)(matchResults.length + ' matches');
                // union the results
                for (var _b = 0, matchResults_1 = matchResults; _b < matchResults_1.length; _b++) {
                    var matchResult = matchResults_1[_b];
                    map[matchResult] = true;
                }
            }
            else {
                // apply the pattern
                (0, exports.debug)('applying exclude pattern against original list');
                var matchResults = minimatch.match(list, pattern_1, options_1);
                (0, exports.debug)(matchResults.length + ' matches');
                // substract the results
                for (var _c = 0, matchResults_2 = matchResults; _c < matchResults_2.length; _c++) {
                    var matchResult = matchResults_2[_c];
                    delete map[matchResult];
                }
            }
        }
    }
    // return a filtered version of the original list (preserves order and prevents duplication)
    var result = list.filter(function (item) { return map.hasOwnProperty(item); });
    (0, exports.debug)(result.length + ' final results');
    return result;
}
exports.match = match;
/**
 * Filter to apply glob patterns
 *
 * @param  pattern  pattern to apply
 * @param  options  optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.
 */
function filter(pattern, options) {
    options = options || _getDefaultMatchOptions();
    return minimatch.filter(pattern, options);
}
exports.filter = filter;
function _debugMatchOptions(options) {
    (0, exports.debug)("matchOptions.debug: '".concat(options.debug, "'"));
    (0, exports.debug)("matchOptions.nobrace: '".concat(options.nobrace, "'"));
    (0, exports.debug)("matchOptions.noglobstar: '".concat(options.noglobstar, "'"));
    (0, exports.debug)("matchOptions.dot: '".concat(options.dot, "'"));
    (0, exports.debug)("matchOptions.noext: '".concat(options.noext, "'"));
    (0, exports.debug)("matchOptions.nocase: '".concat(options.nocase, "'"));
    (0, exports.debug)("matchOptions.nonull: '".concat(options.nonull, "'"));
    (0, exports.debug)("matchOptions.matchBase: '".concat(options.matchBase, "'"));
    (0, exports.debug)("matchOptions.nocomment: '".concat(options.nocomment, "'"));
    (0, exports.debug)("matchOptions.nonegate: '".concat(options.nonegate, "'"));
    (0, exports.debug)("matchOptions.flipNegate: '".concat(options.flipNegate, "'"));
}
function _getDefaultMatchOptions() {
    return {
        debug: false,
        nobrace: true,
        noglobstar: false,
        dot: true,
        noext: false,
        nocase: process.platform == 'win32',
        nonull: false,
        matchBase: false,
        nocomment: false,
        nonegate: false,
        flipNegate: false
    };
}
/**
 * Determines the find root from a list of patterns. Performs the find and then applies the glob patterns.
 * Supports interleaved exclude patterns. Unrooted patterns are rooted using defaultRoot, unless
 * matchOptions.matchBase is specified and the pattern is a basename only. For matchBase cases, the
 * defaultRoot is used as the find root.
 *
 * @param  defaultRoot   default path to root unrooted patterns. falls back to System.DefaultWorkingDirectory or process.cwd().
 * @param  patterns      pattern or array of patterns to apply
 * @param  findOptions   defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.
 * @param  matchOptions  defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }
 */
function findMatch(defaultRoot, patterns, findOptions, matchOptions) {
    // apply defaults for parameters and trace
    defaultRoot = defaultRoot || this.getVariable('system.defaultWorkingDirectory') || process.cwd();
    (0, exports.debug)("defaultRoot: '".concat(defaultRoot, "'"));
    patterns = patterns || [];
    patterns = typeof patterns == 'string' ? [patterns] : patterns;
    findOptions = findOptions || _getDefaultFindOptions();
    _debugFindOptions(findOptions);
    matchOptions = matchOptions || _getDefaultMatchOptions();
    _debugMatchOptions(matchOptions);
    // normalize slashes for root dir
    defaultRoot = im._normalizeSeparators(defaultRoot);
    var results = {};
    var originalMatchOptions = matchOptions;
    for (var _i = 0, _a = (patterns || []); _i < _a.length; _i++) {
        var pattern = _a[_i];
        (0, exports.debug)("pattern: '".concat(pattern, "'"));
        // trim and skip empty
        pattern = (pattern || '').trim();
        if (!pattern) {
            (0, exports.debug)('skipping empty pattern');
            continue;
        }
        // clone match options
        var matchOptions_1 = im._cloneMatchOptions(originalMatchOptions);
        // skip comments
        if (!matchOptions_1.nocomment && im._startsWith(pattern, '#')) {
            (0, exports.debug)('skipping comment');
            continue;
        }
        // set nocomment - brace expansion could result in a leading '#'
        matchOptions_1.nocomment = true;
        // determine whether pattern is include or exclude
        var negateCount = 0;
        if (!matchOptions_1.nonegate) {
            while (pattern.charAt(negateCount) == '!') {
                negateCount++;
            }
            pattern = pattern.substring(negateCount); // trim leading '!'
            if (negateCount) {
                (0, exports.debug)("trimmed leading '!'. pattern: '".concat(pattern, "'"));
            }
        }
        var isIncludePattern = negateCount == 0 ||
            (negateCount % 2 == 0 && !matchOptions_1.flipNegate) ||
            (negateCount % 2 == 1 && matchOptions_1.flipNegate);
        // set nonegate - brace expansion could result in a leading '!'
        matchOptions_1.nonegate = true;
        matchOptions_1.flipNegate = false;
        // expand braces - required to accurately interpret findPath
        var expanded = void 0;
        var preExpanded = pattern;
        if (matchOptions_1.nobrace) {
            expanded = [pattern];
        }
        else {
            // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot
            // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
            (0, exports.debug)('expanding braces');
            var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern;
            expanded = minimatch.braceExpand(convertedPattern);
        }
        // set nobrace
        matchOptions_1.nobrace = true;
        for (var _b = 0, expanded_2 = expanded; _b < expanded_2.length; _b++) {
            var pattern_2 = expanded_2[_b];
            if (expanded.length != 1 || pattern_2 != preExpanded) {
                (0, exports.debug)("pattern: '".concat(pattern_2, "'"));
            }
            // trim and skip empty
            pattern_2 = (pattern_2 || '').trim();
            if (!pattern_2) {
                (0, exports.debug)('skipping empty pattern');
                continue;
            }
            if (isIncludePattern) {
                // determine the findPath
                var findInfo = im._getFindInfoFromPattern(defaultRoot, pattern_2, matchOptions_1);
                var findPath = findInfo.findPath;
                (0, exports.debug)("findPath: '".concat(findPath, "'"));
                if (!findPath) {
                    (0, exports.debug)('skipping empty path');
                    continue;
                }
                // perform the find
                (0, exports.debug)("statOnly: '".concat(findInfo.statOnly, "'"));
                var findResults = [];
                if (findInfo.statOnly) {
                    // simply stat the path - all path segments were used to build the path
                    try {
                        fs.statSync(findPath);
                        findResults.push(findPath);
                    }
                    catch (err) {
                        if (err.code != 'ENOENT') {
                            throw err;
                        }
                        (0, exports.debug)('ENOENT');
                    }
                }
                else {
                    findResults = find(findPath, findOptions);
                }
                (0, exports.debug)("found ".concat(findResults.length, " paths"));
                // apply the pattern
                (0, exports.debug)('applying include pattern');
                if (findInfo.adjustedPattern != pattern_2) {
                    (0, exports.debug)("adjustedPattern: '".concat(findInfo.adjustedPattern, "'"));
                    pattern_2 = findInfo.adjustedPattern;
                }
                var matchResults = minimatch.match(findResults, pattern_2, matchOptions_1);
                (0, exports.debug)(matchResults.length + ' matches');
                // union the results
                for (var _c = 0, matchResults_3 = matchResults; _c < matchResults_3.length; _c++) {
                    var matchResult = matchResults_3[_c];
                    var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;
                    results[key] = matchResult;
                }
            }
            else {
                // check if basename only and matchBase=true
                if (matchOptions_1.matchBase &&
                    !im._isRooted(pattern_2) &&
                    (process.platform == 'win32' ? pattern_2.replace(/\\/g, '/') : pattern_2).indexOf('/') < 0) {
                    // do not root the pattern
                    (0, exports.debug)('matchBase and basename only');
                }
                else {
                    // root the exclude pattern
                    pattern_2 = im._ensurePatternRooted(defaultRoot, pattern_2);
                    (0, exports.debug)("after ensurePatternRooted, pattern: '".concat(pattern_2, "'"));
                }
                // apply the pattern
                (0, exports.debug)('applying exclude pattern');
                var matchResults = minimatch.match(Object.keys(results).map(function (key) { return results[key]; }), pattern_2, matchOptions_1);
                (0, exports.debug)(matchResults.length + ' matches');
                // substract the results
                for (var _d = 0, matchResults_4 = matchResults; _d < matchResults_4.length; _d++) {
                    var matchResult = matchResults_4[_d];
                    var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;
                    delete results[key];
                }
            }
        }
    }
    var finalResult = Object.keys(results)
        .map(function (key) { return results[key]; })
        .sort();
    (0, exports.debug)(finalResult.length + ' final results');
    return finalResult;
}
exports.findMatch = findMatch;
/**
 * Build Proxy URL in the following format: protocol://username:password@hostname:port
 * @param proxyUrl Url address of the proxy server (eg: http://example.com)
 * @param proxyUsername Proxy username (optional)
 * @param proxyPassword Proxy password (optional)
 * @returns string
 */
function getProxyFormattedUrl(proxyUrl, proxyUsername, proxyPassword) {
    var parsedUrl = new URL(proxyUrl);
    var proxyAddress = "".concat(parsedUrl.protocol, "//").concat(parsedUrl.host);
    if (proxyUsername) {
        proxyAddress = "".concat(parsedUrl.protocol, "//").concat(proxyUsername, ":").concat(proxyPassword, "@").concat(parsedUrl.host);
    }
    return proxyAddress;
}
/**
 * Gets http proxy configuration used by Build/Release agent
 *
 * @return  ProxyConfiguration
 */
function getHttpProxyConfiguration(requestUrl) {
    var proxyUrl = (0, exports.getVariable)('Agent.ProxyUrl');
    if (proxyUrl && proxyUrl.length > 0) {
        var proxyUsername = (0, exports.getVariable)('Agent.ProxyUsername');
        var proxyPassword = (0, exports.getVariable)('Agent.ProxyPassword');
        var proxyBypassHosts = JSON.parse((0, exports.getVariable)('Agent.ProxyBypassList') || '[]');
        var bypass_1 = false;
        if (requestUrl) {
            proxyBypassHosts.forEach(function (bypassHost) {
                if (new RegExp(bypassHost, 'i').test(requestUrl)) {
                    bypass_1 = true;
                }
            });
        }
        if (bypass_1) {
            return null;
        }
        else {
            var proxyAddress = getProxyFormattedUrl(proxyUrl, proxyUsername, proxyPassword);
            return {
                proxyUrl: proxyUrl,
                proxyUsername: proxyUsername,
                proxyPassword: proxyPassword,
                proxyBypassHosts: proxyBypassHosts,
                proxyFormattedUrl: proxyAddress
            };
        }
    }
    else {
        return null;
    }
}
exports.getHttpProxyConfiguration = getHttpProxyConfiguration;
/**
 * Gets http certificate configuration used by Build/Release agent
 *
 * @return  CertConfiguration
 */
function getHttpCertConfiguration() {
    var ca = (0, exports.getVariable)('Agent.CAInfo');
    var clientCert = (0, exports.getVariable)('Agent.ClientCert');
    if (ca || clientCert) {
        var certConfig = {};
        certConfig.caFile = ca;
        certConfig.certFile = clientCert;
        if (clientCert) {
            var clientCertKey = (0, exports.getVariable)('Agent.ClientCertKey');
            var clientCertArchive = (0, exports.getVariable)('Agent.ClientCertArchive');
            var clientCertPassword = (0, exports.getVariable)('Agent.ClientCertPassword');
            certConfig.keyFile = clientCertKey;
            certConfig.certArchiveFile = clientCertArchive;
            certConfig.passphrase = clientCertPassword;
        }
        return certConfig;
    }
    else {
        return null;
    }
}
exports.getHttpCertConfiguration = getHttpCertConfiguration;
//-----------------------------------------------------
// Test Publisher
//-----------------------------------------------------
var TestPublisher = /** @class */ (function () {
    function TestPublisher(testRunner) {
        this.testRunner = testRunner;
    }
    TestPublisher.prototype.publish = function (resultFiles, mergeResults, platform, config, runTitle, publishRunAttachments, testRunSystem) {
        // Could have used an initializer, but wanted to avoid reordering parameters when converting to strict null checks
        // (A parameter cannot both be optional and have an initializer)
        testRunSystem = testRunSystem || "VSTSTask";
        var properties = {};
        properties['type'] = this.testRunner;
        if (mergeResults) {
            properties['mergeResults'] = mergeResults;
        }
        if (platform) {
            properties['platform'] = platform;
        }
        if (config) {
            properties['config'] = config;
        }
        if (runTitle) {
            properties['runTitle'] = runTitle;
        }
        if (publishRunAttachments) {
            properties['publishRunAttachments'] = publishRunAttachments;
        }
        if (resultFiles) {
            properties['resultFiles'] = Array.isArray(resultFiles) ? resultFiles.join() : resultFiles;
        }
        properties['testRunSystem'] = testRunSystem;
        (0, exports.command)('results.publish', properties, '');
    };
    return TestPublisher;
}());
exports.TestPublisher = TestPublisher;
//-----------------------------------------------------
// Code coverage Publisher
//-----------------------------------------------------
var CodeCoveragePublisher = /** @class */ (function () {
    function CodeCoveragePublisher() {
    }
    CodeCoveragePublisher.prototype.publish = function (codeCoverageTool, summaryFileLocation, reportDirectory, additionalCodeCoverageFiles) {
        var properties = {};
        if (codeCoverageTool) {
            properties['codecoveragetool'] = codeCoverageTool;
        }
        if (summaryFileLocation) {
            properties['summaryfile'] = summaryFileLocation;
        }
        if (reportDirectory) {
            properties['reportdirectory'] = reportDirectory;
        }
        if (additionalCodeCoverageFiles) {
            properties['additionalcodecoveragefiles'] = Array.isArray(additionalCodeCoverageFiles) ? additionalCodeCoverageFiles.join() : additionalCodeCoverageFiles;
        }
        (0, exports.command)('codecoverage.publish', properties, "");
    };
    return CodeCoveragePublisher;
}());
exports.CodeCoveragePublisher = CodeCoveragePublisher;
//-----------------------------------------------------
// Code coverage Publisher
//-----------------------------------------------------
var CodeCoverageEnabler = /** @class */ (function () {
    function CodeCoverageEnabler(buildTool, ccTool) {
        this.buildTool = buildTool;
        this.ccTool = ccTool;
    }
    CodeCoverageEnabler.prototype.enableCodeCoverage = function (buildProps) {
        buildProps['buildtool'] = this.buildTool;
        buildProps['codecoveragetool'] = this.ccTool;
        (0, exports.command)('codecoverage.enable', buildProps, "");
    };
    return CodeCoverageEnabler;
}());
exports.CodeCoverageEnabler = CodeCoverageEnabler;
//-----------------------------------------------------
// Task Logging Commands
//-----------------------------------------------------
/**
 * Upload user interested file as additional log information
 * to the current timeline record.
 *
 * The file shall be available for download along with task logs.
 *
 * @param path      Path to the file that should be uploaded.
 * @returns         void
 */
function uploadFile(path) {
    (0, exports.command)("task.uploadfile", null, path);
}
exports.uploadFile = uploadFile;
/**
 * Instruction for the agent to update the PATH environment variable.
 * The specified directory is prepended to the PATH.
 * The updated environment variable will be reflected in subsequent tasks.
 *
 * @param path      Local directory path.
 * @returns         void
 */
function prependPath(path) {
    assertAgent("2.115.0");
    (0, exports.command)("task.prependpath", null, path);
}
exports.prependPath = prependPath;
/**
 * Upload and attach summary markdown to current timeline record.
 * This summary shall be added to the build/release summary and
 * not available for download with logs.
 *
 * @param path      Local directory path.
 * @returns         void
 */
function uploadSummary(path) {
    (0, exports.command)("task.uploadsummary", null, path);
}
exports.uploadSummary = uploadSummary;
/**
 * Upload and attach attachment to current timeline record.
 * These files are not available for download with logs.
 * These can only be referred to by extensions using the type or name values.
 *
 * @param type      Attachment type.
 * @param name      Attachment name.
 * @param path      Attachment path.
 * @returns         void
 */
function addAttachment(type, name, path) {
    (0, exports.command)("task.addattachment", { "type": type, "name": name }, path);
}
exports.addAttachment = addAttachment;
/**
 * Set an endpoint field with given value.
 * Value updated will be retained in the endpoint for
 * the subsequent tasks that execute within the same job.
 *
 * @param id      Endpoint id.
 * @param field   FieldType enum of AuthParameter, DataParameter or Url.
 * @param key     Key.
 * @param value   Value for key or url.
 * @returns       void
 */
function setEndpoint(id, field, key, value) {
    (0, exports.command)("task.setendpoint", { "id": id, "field": FieldType[field].toLowerCase(), "key": key }, value);
}
exports.setEndpoint = setEndpoint;
/**
 * Set progress and current operation for current task.
 *
 * @param percent           Percentage of completion.
 * @param currentOperation  Current pperation.
 * @returns                 void
 */
function setProgress(percent, currentOperation) {
    (0, exports.command)("task.setprogress", { "value": "".concat(percent) }, currentOperation);
}
exports.setProgress = setProgress;
/**
 * Indicates whether to write the logging command directly to the host or to the output pipeline.
 *
 * @param id            Timeline record Guid.
 * @param parentId      Parent timeline record Guid.
 * @param recordType    Record type.
 * @param recordName    Record name.
 * @param order         Order of timeline record.
 * @param startTime     Start time.
 * @param finishTime    End time.
 * @param progress      Percentage of completion.
 * @param state         TaskState enum of Unknown, Initialized, InProgress or Completed.
 * @param result        TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.
 * @param message       current operation
 * @returns             void
 */
function logDetail(id, message, parentId, recordType, recordName, order, startTime, finishTime, progress, state, result) {
    var properties = {
        "id": id,
        "parentid": parentId,
        "type": recordType,
        "name": recordName,
        "order": order ? order.toString() : undefined,
        "starttime": startTime,
        "finishtime": finishTime,
        "progress": progress ? progress.toString() : undefined,
        "state": state ? TaskState[state] : undefined,
        "result": result ? TaskResult[result] : undefined
    };
    (0, exports.command)("task.logdetail", properties, message);
}
exports.logDetail = logDetail;
/**
 * Log error or warning issue to timeline record of current task.
 *
 * @param type          IssueType enum of Error or Warning.
 * @param sourcePath    Source file location.
 * @param lineNumber    Line number.
 * @param columnNumber  Column number.
 * @param code          Error or warning code.
 * @param message       Error or warning message.
 * @returns             void
 */
function logIssue(type, message, sourcePath, lineNumber, columnNumber, errorCode) {
    var properties = {
        "type": IssueType[type].toLowerCase(),
        "code": errorCode,
        "sourcepath": sourcePath,
        "linenumber": lineNumber ? lineNumber.toString() : undefined,
        "columnnumber": columnNumber ? columnNumber.toString() : undefined,
    };
    (0, exports.command)("task.logissue", properties, message);
}
exports.logIssue = logIssue;
//-----------------------------------------------------
// Artifact Logging Commands
//-----------------------------------------------------
/**
 * Upload user interested file as additional log information
 * to the current timeline record.
 *
 * The file shall be available for download along with task logs.
 *
 * @param containerFolder   Folder that the file will upload to, folder will be created if needed.
 * @param path              Path to the file that should be uploaded.
 * @param name              Artifact name.
 * @returns                 void
 */
function uploadArtifact(containerFolder, path, name) {
    (0, exports.command)("artifact.upload", { "containerfolder": containerFolder, "artifactname": name }, path);
}
exports.uploadArtifact = uploadArtifact;
/**
 * Create an artifact link, artifact location is required to be
 * a file container path, VC path or UNC share path.
 *
 * The file shall be available for download along with task logs.
 *
 * @param name              Artifact name.
 * @param path              Path to the file that should be associated.
 * @param artifactType      ArtifactType enum of Container, FilePath, VersionControl, GitRef or TfvcLabel.
 * @returns                 void
 */
function associateArtifact(name, path, artifactType) {
    (0, exports.command)("artifact.associate", { "type": ArtifactType[artifactType].toLowerCase(), "artifactname": name }, path);
}
exports.associateArtifact = associateArtifact;
//-----------------------------------------------------
// Build Logging Commands
//-----------------------------------------------------
/**
 * Upload user interested log to build’s container “logs\tool” folder.
 *
 * @param path      Path to the file that should be uploaded.
 * @returns         void
 */
function uploadBuildLog(path) {
    (0, exports.command)("build.uploadlog", null, path);
}
exports.uploadBuildLog = uploadBuildLog;
/**
 * Update build number for current build.
 *
 * @param value     Value to be assigned as the build number.
 * @returns         void
 */
function updateBuildNumber(value) {
    (0, exports.command)("build.updatebuildnumber", null, value);
}
exports.updateBuildNumber = updateBuildNumber;
/**
 * Add a tag for current build.
 *
 * @param value     Tag value.
 * @returns         void
 */
function addBuildTag(value) {
    (0, exports.command)("build.addbuildtag", null, value);
}
exports.addBuildTag = addBuildTag;
//-----------------------------------------------------
// Release Logging Commands
//-----------------------------------------------------
/**
 * Update release name for current release.
 *
 * @param value     Value to be assigned as the release name.
 * @returns         void
 */
function updateReleaseName(name) {
    assertAgent("2.132.0");
    (0, exports.command)("release.updatereleasename", null, name);
}
exports.updateReleaseName = updateReleaseName;
//-----------------------------------------------------
// Tools
//-----------------------------------------------------
exports.TaskCommand = tcm.TaskCommand;
exports.commandFromString = tcm.commandFromString;
exports.ToolRunner = trm.ToolRunner;
//-----------------------------------------------------
// Validation Checks
//-----------------------------------------------------
// async await needs generators in node 4.x+
if (semver.lt(process.versions.node, '4.2.0')) {
    (0, exports.warning)('Tasks require a new agent.  Upgrade your agent or node to 4.2.0 or later', exports.IssueSource.TaskInternal);
}
//-------------------------------------------------------------------
// Populate the vault with sensitive data.  Inputs and Endpoints
//-------------------------------------------------------------------
// avoid loading twice (overwrites .taskkey)
if (!global['_vsts_task_lib_loaded']) {
    im._loadData();
    im._exposeProxySettings();
    im._exposeCertSettings();
}
