From b3e253c1af03da83d2a5af6770b92f79e4a0c523 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Tue, 5 Mar 2019 11:44:52 +0530 Subject: [PATCH 01/17] Added task.json and taskdesign.md for new version of DotNetCoreInstaller task. --- Tasks/DotNetCoreInstallerV1/Task Design.md | 93 ++++++++++++++++++ Tasks/DotNetCoreInstallerV1/task.json | 108 +++++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 Tasks/DotNetCoreInstallerV1/Task Design.md create mode 100644 Tasks/DotNetCoreInstallerV1/task.json diff --git a/Tasks/DotNetCoreInstallerV1/Task Design.md b/Tasks/DotNetCoreInstallerV1/Task Design.md new file mode 100644 index 000000000000..26b5d3fa13fa --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Task Design.md @@ -0,0 +1,93 @@ +# **.NET Core Installer Task** + +The task installs .NET Core SDK/Runtime. Below are the features provided by the task and there implementation +New version of the task is being written because +- Change in installation behaviour, directly impacting user: the changed default location of installation may result in multiple versions of dotnet being available to user, in contrast to only one version being available earlier. As the versions are cached, thus the user might get newer versions than the one user had asked to be installed, and may lead to difference in build/restore. + +## **- Caching SDK/Runtime versions** +The task provides caching of dotnet sdk/runtime versions, given that the `Path to install dotnet` is same each time the task is runs. + +### What it means: +The task will only install the sdk/runtime if that version is not already installed. This will save time in cases when dotnet version is already installed. + +### How it works: +Before installting the SDK/Runtime version, it is checked if that sdk/runtime version is already installed in the specified location: `installationPath` (installationPath is a user input). + +Commonality in both approaches defined below: +1. `installationPath` will be created if it doesn't already exist. +2. All the folders from dotnet.zip/tgz will be copied inside the `installationPath` folder. +3. Files at top level (such as dotnet.exe, LICENSE.txt etc.) in dotnetVersion.zip/tgz will only be copied, if the sdk/runtime being installed is greater than all other already installed in that path. + + +Approaches to build caching of SDK/Runtime versions: + +1. **`Folder based approach`** + - `Installation process:` While installing a version, we will only extract the files from downloaded archive and then copy paste the files into the installationPath folder. + - `Caching process:` Existance of folder with name = version inside sdk or host/fxr folder will be considered as proof that sdk/runtime version is installed. Alogirthm to find if version is cached or not will be like this: + - `installationPath` should contains a folder called `sdk or host/fxr`. If it + - `exists:` check if sdk or host/fxr folder contains a folder with name = version to be downloaded. + - `exists:` Version is cached, nothing more needs to be done. + - `doesn't exist:` Version needs to be installed. + - `doesn't exist:` Version needs to be installed + +2. **`Version.Complete file based approach`** + - `Installation process:` Once all the files are successfully extracted, copied and pasted into installationPath, we will create a **`version.complete`** file in sdk/runtime folder. The Version.complete file will exist at the same level as the version folder and will be considered as a stamp of successfull installation. + - If installation is not complete/successfull, we will not create the version.complete file. + - `Caching Process:` So, the algorithm will be same as in Approach 1, but with an additional required check for `version.complete` file to be present in sdk/runtime folder along with version folder. Based on Version.Complete's existance, the following will be concluded + - `Exists`: version will be considered as cached + - `Doesn't exist`: version will be installed. (overwriting if the files already existing) + - **optionally:** `Doesn't exist but installationPath is global dotnet installation path`: in this case the version will be considered as cached even without the version.complete file. + + +## **- Supporting version wildcards** +The task input `version` accepts dotnet sdk/runtime versions in the following patterns +- `Major.Minor.PatchVersion :` complete version as present in releases.json for the Major.Minor Version channel. Example: 2.2.104 +- `Major.Minor.x :` Latest version in the Major.Minor version channel release. It can also be the latest preview version if `includePreviewVersions` input is enabled/true. +- `Major.x :` Latest version released in the Major version channel. It can also be the latest preview version if `includePreviewVersions` input is enabled/true. + +### How it works: +The correct version needs to be identified in case `x` is used to specify required version. This is how the exact needed version and its information is extracted: + + +- The `version` input is evaluated and divided into three sections: + - Major + - Minor + - Patch + +- Download and read file [releases-index.json](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json) as a JSON object `release-index`. + +- Based on Minor versions value, the following can happen + - Numeric : Then we get the corresponding channels (Major.Minor) releases.json link from `release-index`. Then the releases.json is downloaded and parsed into an object: `releaseInformation`. + - NOTE: in case exact version is not found, the function logs error and task will fail. + - \* : in this case, we find the latest channel with `support-phase` != `preview` (unless `includePreviewVersions` is true). The releases.json for the selected channel is then downloaded and parsed into json object `releaseInformation`. + - The latest version from `release.sdk/runtime.version` is the returned by the funtion. (preview version will only be selected if `includePreviewVersions` is true) + - Empty: the function will log error as version needs to be given till atleast minor version. As a result the task will fail. + + +- Based on Patch version value, the following can happen + - Empty : the function logs error and task will fail as it expects either a value or \*. + - Exact Version (alpha numeric): the exact sdk/runtime version will be searched in `releaseInformation's`. + - `version found:` the version information is returned + - `version not found:` function logs error and task will fail. + - \* : The latest sdk/runtime version will be searched in each release. The latest release is then returned. + +## **- Inbuilt option to restrict Multi-Level lookup** + +The host will probe several locations to find a suitable shared framework. If a folder is not there, it will attempt to look in pre-defined global locations using multi-level lookup. The default global locations are: + +**For Windows:** +- C:/Program Files/dotnet (64-bit processes) +- C:/Program Files (x86)/dotnet + + +**For MacOs:** +- /usr/local/share/dotnet + + +**For Linux:** +- /usr/share/dotnet + +Selecting it would mean your application would be built using the SDK and will consume only those runtimes, which are installed by the tool installer and not the ones installed on the machine.
+It's value will be set as an environment variable: `DOTNET_MULTILEVEL_LOOKUP` with values +- `0` : Disabled +- `1` : Enabled \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json new file mode 100644 index 000000000000..a875ed81b6ef --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -0,0 +1,108 @@ +{ + "id": "B0CE7256-7898-45D3-9CB5-176B752BFEA6", + "name": "DotNetCoreInstaller", + "friendlyName": "Dot NET Core SDK/Runtime Installer", + "description": "Acquires a version of the .NET Core SDK/Runtime from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks.", + "helpUrl": "", + "helpMarkDown": "", + "category": "Tool", + "runsOn": [ + "Agent", + "DeploymentGroup" + ], + "author": "Microsoft Corporation", + "version": { + "Major": 1, + "Minor": 0, + "Patch": 0 + }, + "preview": "true", + "satisfies": [ + "DotNetCore" + ], + "demands": [], + "instanceNameFormat": "Use .NET Core $(packageType) $(version)", + "groups": [ + { + "name": "advanced", + "displayName": "Advanced", + "isExpanded": true + } + ], + "inputs": [ + { + "name": "packageType", + "type": "pickList", + "label": "Package to install", + "defaultValue": "sdk", + "required": true, + "helpMarkDown": "Please select whether to install only runtime or full SDK.", + "options": { + "runtime": "Runtime", + "sdk": "SDK (contains runtime)" + } + }, + { + "name": "includePreviewVersions", + "type": "boolean", + "label": "Include Preview Versions", + "defaultValue": "false", + "required": false, + "helpMarkDown": "Kindly select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This need not be checked if you are specifing exact version, such as: 2.1.403" + }, + { + "name": "version", + "type": "string", + "label": "Version", + "defaultValue": "2.2.x", + "required": true, + "helpMarkDown": "Specify version of .NET Core SDK or runtime to install.
Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [releases-index file.](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json)." + }, + { + "name": "installationPath", + "type": "string", + "label": "Path To Install DotNet", + "defaultValue": "$(Agent.ToolsDirectory)", + "required": true, + "helpMarkDown": "Specify where DotNet SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behaviour (below description is in the assumption that MultiLevelLookup is disabled. If it is not disabled, globally installed dotnet versions will be always available. You can choose to enable/disable this via Restrict Multi Level Lookup checkbox in advanced section.)
  • $(Agent.ToolsDirectory) : As ToolsDirectory is not cleaned up after each build, other versions of dotnet installed at same location in other build/release, via tool installer, will also be available when dotnet is used.
  • $(Agent.TempDirectory) : As the TempDirectory is cleaned after each build/release, you will only have access to the dotnet version's installed in that particular build/release.
  • Global dotnet installation path such as /usr/share/dotnet : This would mean that all dotnet versions installed on the machine along with version installed by tool installer will be available for this and all subsequent build/release.
  • " + }, + { + "name": "restrictMultiLevelLookup", + "type": "boolean", + "label": "Restrict Multi Level Lookup", + "groupName": "advanced", + "defaultValue": true, + "required": false, + "helpMarkDown": "The host will probe several locations to find a suitable shared framework. If a folder is not there, it will attempt to look in pre-defined global locations using multi-level lookup. The default global locations are:
    For Windows:
    C:/Program Files/dotnet (64-bit processes)
    C:/Program Files (x86)/dotnet
    For MacOs:
    /usr/local/share/dotnet
    For Linux:
    /usr/share/dotnet

    Selecting it would mean your application would be built using the SDK and will consume only those runtimes, which are installed by the tool installer and not the ones installed on the machine." + } + ], + "execution": { + "Node": { + "target": "dotnetcoreinstaller.js" + } + }, + "messages": { + "ToolFailed": "Tool install failed: %s", + "ImplicitVersionNotSupported": "Version should be a valid and explicit version: %s", + "getMachinePlatformFailed": "Failed to get machine platform details. Error: %s.", + "getDownloadUrlsFailed": "Failed to get download urls. Error: %s.", + "UsingCachedTool": "Cached copy of .NET Core exists. No need to install afresh. Cached tool location: %s.", + "CheckingToolCache": "Checking if a cached copy exists for this version...", + "InstallingAfresh": "The cache does not contain the requested version of .NET Core. Downloading and installing it now.", + "GettingDownloadUrl": "Getting URL to download .NET Core %s version: %s.", + "CouldNotDetectPlatform": "Could not detect the machine's OS", + "NullDownloadUrls": "Could not construct download URL. Please ensure that specified version %s is valid.", + "DownloadingUrl": "Downloading .NET Core package from URL: %s", + "ExtractingPackage": "Extracting downloaded package %s.", + "CachingTool": "Caching this installed tool.", + "SuccessfullyInstalled": "Successfully installed .NET Core %s version %s.", + "ToolToInstall": "Tool to install: .NET Core %s version %s.", + "PrimaryPlatform": "Detected platform (Primary): %s", + "LegacyPlatform": "Detected platform (Legacy): %s", + "WarningVersionNotFound": "Could not fetch download information for version %s. Please check if the version specified is correct. You can refer the link for supported versions => https://github.com/dotnet/core/blob/master/release-notes/releases.json. Falling back to creating convention based URL.", + "CouldNotDownload": "Could not download installation package from this URL: %s Error: %s", + "FailedToDownloadPackage": "Failed to download package for installation", + "PrependGlobalToolPath": "Creating global tool path and pre-prending to PATH.", + "VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/" + } +} From 955cd0a4c638ceb6d29aa8df5af82c1a773c610e Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Wed, 6 Mar 2019 14:48:26 +0530 Subject: [PATCH 02/17] resolved comments --- Tasks/DotNetCoreInstallerV1/Task Design.md | 123 ++++++++++++--------- Tasks/DotNetCoreInstallerV1/task.json | 28 ++--- 2 files changed, 85 insertions(+), 66 deletions(-) diff --git a/Tasks/DotNetCoreInstallerV1/Task Design.md b/Tasks/DotNetCoreInstallerV1/Task Design.md index 26b5d3fa13fa..ba77eec2bae9 100644 --- a/Tasks/DotNetCoreInstallerV1/Task Design.md +++ b/Tasks/DotNetCoreInstallerV1/Task Design.md @@ -1,79 +1,95 @@ -# **.NET Core Installer Task** +# **.NET Core Installer Task V1** -The task installs .NET Core SDK/Runtime. Below are the features provided by the task and there implementation -New version of the task is being written because -- Change in installation behaviour, directly impacting user: the changed default location of installation may result in multiple versions of dotnet being available to user, in contrast to only one version being available earlier. As the versions are cached, thus the user might get newer versions than the one user had asked to be installed, and may lead to difference in build/restore. +The task installs user specified version of .NET Core SDK/Runtime. This can be consumed to supply a particular version of .Net Core SDK/runtime to the subsequent tasks in pipeline. -## **- Caching SDK/Runtime versions** -The task provides caching of dotnet sdk/runtime versions, given that the `Path to install dotnet` is same each time the task is runs. +### **A new major version of the task is created because of the following breaking changes:** +- **Installating multiple sdk/runtime versions side by side:** Users had asked for the feature where multiple versions of sdk/runtime can be installed and then be used in subsequent tasks in a pipeline.(one project may require multiple .Net Core sdks to build different applications), for more information about user's ask, [refer here](https://github.com/Microsoft/azure-pipelines-tasks/issues/8306). This is a breaking change, as previously the V0 task always provided only one version of sdk/runtime. -### What it means: -The task will only install the sdk/runtime if that version is not already installed. This will save time in cases when dotnet version is already installed. - -### How it works: -Before installting the SDK/Runtime version, it is checked if that sdk/runtime version is already installed in the specified location: `installationPath` (installationPath is a user input). - -Commonality in both approaches defined below: -1. `installationPath` will be created if it doesn't already exist. -2. All the folders from dotnet.zip/tgz will be copied inside the `installationPath` folder. -3. Files at top level (such as dotnet.exe, LICENSE.txt etc.) in dotnetVersion.zip/tgz will only be copied, if the sdk/runtime being installed is greater than all other already installed in that path. +## New features added in V1 task: +## **- Support for fetching latest version for a given major or major.minor version** +This feature was being asked by users who wanted to install the latest version as soon as it becomes available, without manually changing the version in the task. For information about user's asks, refer [here](https://github.com/Microsoft/azure-pipelines-tasks/issues/9171). -Approaches to build caching of SDK/Runtime versions: - -1. **`Folder based approach`** - - `Installation process:` While installing a version, we will only extract the files from downloaded archive and then copy paste the files into the installationPath folder. - - `Caching process:` Existance of folder with name = version inside sdk or host/fxr folder will be considered as proof that sdk/runtime version is installed. Alogirthm to find if version is cached or not will be like this: - - `installationPath` should contains a folder called `sdk or host/fxr`. If it - - `exists:` check if sdk or host/fxr folder contains a folder with name = version to be downloaded. - - `exists:` Version is cached, nothing more needs to be done. - - `doesn't exist:` Version needs to be installed. - - `doesn't exist:` Version needs to be installed - -2. **`Version.Complete file based approach`** - - `Installation process:` Once all the files are successfully extracted, copied and pasted into installationPath, we will create a **`version.complete`** file in sdk/runtime folder. The Version.complete file will exist at the same level as the version folder and will be considered as a stamp of successfull installation. - - If installation is not complete/successfull, we will not create the version.complete file. - - `Caching Process:` So, the algorithm will be same as in Approach 1, but with an additional required check for `version.complete` file to be present in sdk/runtime folder along with version folder. Based on Version.Complete's existance, the following will be concluded - - `Exists`: version will be considered as cached - - `Doesn't exist`: version will be installed. (overwriting if the files already existing) - - **optionally:** `Doesn't exist but installationPath is global dotnet installation path`: in this case the version will be considered as cached even without the version.complete file. - - -## **- Supporting version wildcards** -The task input `version` accepts dotnet sdk/runtime versions in the following patterns +This feature is implemented by supporting patterns in version input: `version`. This input now accepts .Net sdk/runtime versions in the following patterns - `Major.Minor.PatchVersion :` complete version as present in releases.json for the Major.Minor Version channel. Example: 2.2.104 -- `Major.Minor.x :` Latest version in the Major.Minor version channel release. It can also be the latest preview version if `includePreviewVersions` input is enabled/true. -- `Major.x :` Latest version released in the Major version channel. It can also be the latest preview version if `includePreviewVersions` input is enabled/true. +- `Major.Minor.x :` Latest version in the Major.Minor version channel release. It can also be the latest preview version if `includePreviewVersions` input is enabled/true. This can be used to get all latest bug fixes automatically in a major.minor version. As back-compat is maintained in major.minor version, thus ensuring applications being built will not break. +- `Major.x :` Latest version released in the Major version channel. It can also be the latest preview version if `includePreviewVersions` input is enabled/true. This can be used by tools or library developers who need to test with every latest version for compatibility. ### How it works: -The correct version needs to be identified in case `x` is used to specify required version. This is how the exact needed version and its information is extracted: +The correct version needs to be identified in case user enters pattern based version such as 2.2.x. This is how the exact needed version and its information is extracted: +- [releases-index.json](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json) The file containing links to all .Net Core release channels is download and read into a JSON object `releasesIndex`. This is used to find all available release channels and links to their releases.json. -- The `version` input is evaluated and divided into three sections: +- The `version` input is divided into three sections: - Major - Minor - Patch -- Download and read file [releases-index.json](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json) as a JSON object `release-index`. - - Based on Minor versions value, the following can happen - - Numeric : Then we get the corresponding channels (Major.Minor) releases.json link from `release-index`. Then the releases.json is downloaded and parsed into an object: `releaseInformation`. + - Numeric : we get the corresponding channel's (Major.Minor) releases.json link from `releasesIndex`. Then the releases.json is downloaded and parsed into an object: `channelInformation`. - NOTE: in case exact version is not found, the function logs error and task will fail. - - \* : in this case, we find the latest channel with `support-phase` != `preview` (unless `includePreviewVersions` is true). The releases.json for the selected channel is then downloaded and parsed into json object `releaseInformation`. - - The latest version from `release.sdk/runtime.version` is the returned by the funtion. (preview version will only be selected if `includePreviewVersions` is true) + - x : in this case, we find the latest channel with `support-phase` != `preview` (unless `includePreviewVersions` is true). The releases.json for the selected channel is then downloaded and parsed into json object `releaseInformation`. + - The version with heighest `release.sdk/runtime.version` is then returned. (preview version will only be selected if `includePreviewVersions` is true) - Empty: the function will log error as version needs to be given till atleast minor version. As a result the task will fail. - Based on Patch version value, the following can happen - - Empty : the function logs error and task will fail as it expects either a value or \*. - - Exact Version (alpha numeric): the exact sdk/runtime version will be searched in `releaseInformation's`. + - Empty : the function logs error and task will fail as it expects either a value or x. + - Exact Version (alpha numeric): a release with exact release.sdk/runtime.version will be searched in `channelInformation`. - `version found:` the version information is returned - `version not found:` function logs error and task will fail. - - \* : The latest sdk/runtime version will be searched in each release. The latest release is then returned. + - x : The latest sdk/runtime version among all releases in that channel will be searched. The latest version information is then returned. + +## **- Support for multiple versions to be installted side by side** +This feature was asked by users so that multiple versions can be installed using the task and they all will be available to subsequent tasks in pipeline. It is required in projects where multiple versions of SDK/runtime are required to build/run different applications. + +Advantages of this feature: +- User can build all applications in a project using a single build task and need not create different pipelines or add multiple build task. + +### How it works: +This feature is implemented, by asking user a new input: `installationPath`, the path where .Net core SDK/runtime should be installed. The Agent process should have write access on the path. +There are multiple benefits of asking `installationPath` from user: +- User can choose to install a particular version in isolation of all other version already installed, by specifying a path which is cleaned up after each release/build. +- User can augment existing set of versions installed with another version by specifying a path where a set of .Net core versions might already be installed, such as: $(Agent.ToolsDirectory) +- User can also install it at global .Net Core installation path, such as: C:\Program Files\dotnet or /usr/share/dotnet/. This way all agents running on that machine will have access to the newly added .Net core versions. + +The way a version is installed at the `installationPath` is now as follows: +- We extract all folders from dotnetVersions.zip/tgz into the `installationPath`, just like install-dotnet.ps1/sh. +- The files in root directory of archive are only copied/overriden if + - The .Net core version being installed at `installationPath` is later than all other versions already installed at the path. + +The advantage of the above installation approach are: +- Time is saved by not copying unneeded files. +- Failures which might occur while overriding existing files are avoided. + +Also to furhter optimize and save time while installation, we do not install a version if it is already cached at that path. Below described are different approaches to find out if a version is cached, + +1. **`Folder based approach`** + - `Installation process:` While installing a version, we will only extract the files from downloaded archive and then copy paste the files into the installationPath folder. + - `Caching process:` Existance of folder with name = version inside sdk or host/fxr folder will be considered as proof that sdk/runtime version is cached. Alogirthm to find if version is cached or not will be like this: + - `installationPath` should contains a folder called `sdk or host/fxr`. If it + - `exists:` check if sdk or host/fxr folder contains a folder with name = version to be downloaded. + - `exists:` Version is cached, nothing more needs to be done. + - `doesn't exist:` Version needs to be installed. + - `doesn't exist:` Version needs to be installed + +2. **`version.completed file based approach`** + - `Installation process:` Once all the files are successfully extracted, copied and pasted into installationPath, we will create a **`version.completed`** file in sdk/runtime folder. The version.completed file will exist at the same level as the version folder and will be considered as a stamp of successfull installation. + - If installation is not complete/successfull, we will not create the version.completed file. + - `Caching Process:` So, the algorithm will be same as in Approach 1, but with an additional required check for `version.completed` file to be present in sdk or host/fxr folder along with folder with name = version. Based on version.completed's existance, the following will be concluded + - `Exists`: version will be considered as cached + - `Doesn't exist`: version will be installed. (overwriting if the files already exist) + - **optionally:** `Doesn't exist but installationPath is global .Net installation path`: in this case the version will be considered as cached even without the version.completed file. + + +There are a few advantages of `version.completed` based approach over `folder only` based approach: +- Handles failed installation attempts: in case the last installation was left incomplete, the version.completed file would not exist and thus in next try, the version will be installed. + ## **- Inbuilt option to restrict Multi-Level lookup** +This feature id introduced as users had asked for an option to disable Multi-Level lookup, to know more about user's ask, refer [here](https://github.com/Microsoft/azure-pipelines-tasks/issues/9608). -The host will probe several locations to find a suitable shared framework. If a folder is not there, it will attempt to look in pre-defined global locations using multi-level lookup. The default global locations are: +Multi-level lookup configures the .Net core host to probe several locations to find a suitable shared framework. If a folder is not found in folder containing dotnet.exe, it will attempt to look in pre-defined global locations using multi-level lookup. The default global locations are: **For Windows:** - C:/Program Files/dotnet (64-bit processes) @@ -87,7 +103,8 @@ The host will probe several locations to find a suitable shared framework. If a **For Linux:** - /usr/share/dotnet -Selecting it would mean your application would be built using the SDK and will consume only those runtimes, which are installed by the tool installer and not the ones installed on the machine.
    It's value will be set as an environment variable: `DOTNET_MULTILEVEL_LOOKUP` with values - `0` : Disabled -- `1` : Enabled \ No newline at end of file +- `1` : Enabled + +For more information on Multi-Level Lookup refer [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md). \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index a875ed81b6ef..00984d60a449 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -21,6 +21,7 @@ "DotNetCore" ], "demands": [], + "releaseNotes": "
  • Support for installing multiple versions side by side.
  • Support for patterns in version to fetch latest in minor/major version.
  • Restrict Multi-level lookup
  • ", "instanceNameFormat": "Use .NET Core $(packageType) $(version)", "groups": [ { @@ -42,29 +43,30 @@ "sdk": "SDK (contains runtime)" } }, - { - "name": "includePreviewVersions", - "type": "boolean", - "label": "Include Preview Versions", - "defaultValue": "false", - "required": false, - "helpMarkDown": "Kindly select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This need not be checked if you are specifing exact version, such as: 2.1.403" - }, { "name": "version", "type": "string", "label": "Version", "defaultValue": "2.2.x", "required": true, - "helpMarkDown": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [releases-index file.](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json)." + "helpMarkDown": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [releases-index file.](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json" + }, + { + "name": "includePreviewVersions", + "type": "boolean", + "label": "Include Preview Versions", + "defaultValue": "false", + "required": false, + "helpMarkDown": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ingnored if you specify an exact version, such as: 2.1.403" }, { "name": "installationPath", "type": "string", - "label": "Path To Install DotNet", + "label": "Path To Install .Net Core", "defaultValue": "$(Agent.ToolsDirectory)", "required": true, - "helpMarkDown": "Specify where DotNet SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behaviour (below description is in the assumption that MultiLevelLookup is disabled. If it is not disabled, globally installed dotnet versions will be always available. You can choose to enable/disable this via Restrict Multi Level Lookup checkbox in advanced section.)
  • $(Agent.ToolsDirectory) : As ToolsDirectory is not cleaned up after each build, other versions of dotnet installed at same location in other build/release, via tool installer, will also be available when dotnet is used.
  • $(Agent.TempDirectory) : As the TempDirectory is cleaned after each build/release, you will only have access to the dotnet version's installed in that particular build/release.
  • Global dotnet installation path such as /usr/share/dotnet : This would mean that all dotnet versions installed on the machine along with version installed by tool installer will be available for this and all subsequent build/release.
  • " + "groupName": "advanced", + "helpMarkDown": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • Global installation path such as /usr/share/dotnet or C:\\Program Files\\Dotnet. This would cause the new version to be available machine-wide and be persisted. This requires that the agent process has permission on these folders
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version." }, { "name": "restrictMultiLevelLookup", @@ -73,7 +75,7 @@ "groupName": "advanced", "defaultValue": true, "required": false, - "helpMarkDown": "The host will probe several locations to find a suitable shared framework. If a folder is not there, it will attempt to look in pre-defined global locations using multi-level lookup. The default global locations are:
    For Windows:
    C:/Program Files/dotnet (64-bit processes)
    C:/Program Files (x86)/dotnet
    For MacOs:
    /usr/local/share/dotnet
    For Linux:
    /usr/share/dotnet

    Selecting it would mean your application would be built using the SDK and will consume only those runtimes, which are installed by the tool installer and not the ones installed on the machine." + "helpMarkDown": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
    For MacOs:
    /usr/local/share/dotnet
    For Linux:
    /usr/share/dotnet

  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md)." } ], "execution": { @@ -105,4 +107,4 @@ "PrependGlobalToolPath": "Creating global tool path and pre-prending to PATH.", "VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/" } -} +} \ No newline at end of file From a7d023dd3704cec69c48b3cd4f4fc25cde2db0d1 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Wed, 6 Mar 2019 22:13:52 +0530 Subject: [PATCH 03/17] Added DotNetInstallerTask files. --- Tasks/DotNetCoreInstallerV1/README.md | 29 + .../resources.resjson/de-de/resources.resjson | 31 + .../resources.resjson/en-US/resources.resjson | 40 + .../resources.resjson/es-es/resources.resjson | 31 + .../resources.resjson/fr-fr/resources.resjson | 31 + .../resources.resjson/it-IT/resources.resjson | 31 + .../resources.resjson/ja-jp/resources.resjson | 31 + .../resources.resjson/ko-KR/resources.resjson | 31 + .../resources.resjson/ru-RU/resources.resjson | 31 + .../resources.resjson/zh-CN/resources.resjson | 31 + .../resources.resjson/zh-TW/resources.resjson | 31 + .../ThirdPartyNotices.txt | 429 +++ .../dotnetcoreinstaller.ts | 61 + .../externals/get-os-distro.sh | 192 + .../externals/get-os-platform.ps1 | 18 + .../externals/install-dotnet.ps1 | 503 +++ .../externals/install-dotnet.sh | 815 +++++ Tasks/DotNetCoreInstallerV1/icon.png | Bin 0 -> 14924 bytes Tasks/DotNetCoreInstallerV1/icon.svg | 39 + Tasks/DotNetCoreInstallerV1/make.json | 8 + Tasks/DotNetCoreInstallerV1/package-lock.json | 124 + Tasks/DotNetCoreInstallerV1/package.json | 30 + Tasks/DotNetCoreInstallerV1/task.json | 2 +- Tasks/DotNetCoreInstallerV1/task.loc.json | 110 + Tasks/DotNetCoreInstallerV1/tsconfig.json | 8 + Tasks/DotNetCoreInstallerV1/typings.json | 9 + .../typings/globals/mocha/index.d.ts | 202 ++ .../typings/globals/mocha/typings.json | 8 + .../typings/globals/node/index.d.ts | 3084 +++++++++++++++++ .../typings/globals/node/typings.json | 8 + .../typings/globals/q/index.d.ts | 357 ++ .../typings/globals/q/typings.json | 8 + .../DotNetCoreInstallerV1/typings/index.d.ts | 3 + Tasks/DotNetCoreInstallerV1/versionFetcher.ts | 229 ++ .../DotNetCoreInstallerV1/versionInstaller.ts | 140 + .../DotNetCoreInstallerV1/versionUtilities.ts | 43 + 36 files changed, 6777 insertions(+), 1 deletion(-) create mode 100644 Tasks/DotNetCoreInstallerV1/README.md create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/de-de/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/es-es/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/fr-fr/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/it-IT/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ja-jp/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ko-KR/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ru-RU/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-CN/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-TW/resources.resjson create mode 100644 Tasks/DotNetCoreInstallerV1/ThirdPartyNotices.txt create mode 100644 Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts create mode 100644 Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh create mode 100644 Tasks/DotNetCoreInstallerV1/externals/get-os-platform.ps1 create mode 100644 Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 create mode 100644 Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh create mode 100644 Tasks/DotNetCoreInstallerV1/icon.png create mode 100644 Tasks/DotNetCoreInstallerV1/icon.svg create mode 100644 Tasks/DotNetCoreInstallerV1/make.json create mode 100644 Tasks/DotNetCoreInstallerV1/package-lock.json create mode 100644 Tasks/DotNetCoreInstallerV1/package.json create mode 100644 Tasks/DotNetCoreInstallerV1/task.loc.json create mode 100644 Tasks/DotNetCoreInstallerV1/tsconfig.json create mode 100644 Tasks/DotNetCoreInstallerV1/typings.json create mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts create mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json create mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts create mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json create mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts create mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json create mode 100644 Tasks/DotNetCoreInstallerV1/typings/index.d.ts create mode 100644 Tasks/DotNetCoreInstallerV1/versionFetcher.ts create mode 100644 Tasks/DotNetCoreInstallerV1/versionInstaller.ts create mode 100644 Tasks/DotNetCoreInstallerV1/versionUtilities.ts diff --git a/Tasks/DotNetCoreInstallerV1/README.md b/Tasks/DotNetCoreInstallerV1/README.md new file mode 100644 index 000000000000..8888c08397c6 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/README.md @@ -0,0 +1,29 @@ +# .NET Core Tool Installer + +## Overview + +The .NET Core Tool Installer task acquires a specific version of [.NET Core](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x) from internet or the tools cache and adds it to the PATH of the Azure Pipelines Agent (hosted or private). Use this task to change the version of .NET Core used in subsequent tasks like [.NET Core cli task](https://github.com/Microsoft/azure-pipelines-tasks/tree/master/Tasks/DotNetCoreCLIV2). +Adding this task before the [.NET Core cli task](https://github.com/Microsoft/azure-pipelines-tasks/tree/master/Tasks/DotNetCoreCLIV2) in a build definition ensures you are building, testing and publishing your app with the right .NET Core version. + +The tool installer approach also decouples you from the agent update cycles. If the .NET Core version you are looking for is missing from the Azure Pipelines agent (Hosted or Private), then you can use this task to get the right version installed on the agent. + + +## Contact Information + +Please report a problem at [Developer Community Forum](https://developercommunity.visualstudio.com/spaces/21/index.html) if you are facing problems in making this task work. You can also share feedback about the task like, what more functionality should be added to the task, what other tasks you would like to have, at the same place. + +## Pre-requisites for the task + +The task can run on either Windows or Linux. + +### Parameters of the task + +* **Package to install\*:** You can choose to install either runtime or full SDK. + +* **Version\*:** Specify exact version of .NET Core SDK or runtime to install. +Examples: +1. To install 1.0.4 SDK, use 1.0.4 +2. To install 1.1.2 runtime, use 1.1.2 +3. To install 2.0 preview 2 runtime, use 2.0.0-preview2-25407-01 +For getting more details about exact version, refer [this link](https://github.com/dotnet/core/blob/master/release-notes/releases.csv). + diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/de-de/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/de-de/resources.resjson new file mode 100644 index 000000000000..85197bbbe5ae --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/de-de/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": ".NET Core-Toolinstaller", + "loc.helpMarkDown": "[Weitere Informationen](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "Ruft eine bestimmte .NET Core-Version aus dem Internet oder dem Toolcache ab und fügt sie dem PATH hinzu. Verwenden Sie diese Aufgabe, um die in nachfolgenden Aufgaben verwendete .NET Core-Version zu ändern.", + "loc.instanceNameFormat": "Verwenden Sie .NET Core $(packageType) $(version).", + "loc.input.label.packageType": "Zu installierendes Paket", + "loc.input.help.packageType": "Wählen Sie aus, ob nur die Runtime oder das vollständige SDK installiert werden soll.", + "loc.input.label.version": "Version", + "loc.input.help.version": "Geben Sie die genaue Version von .NET Core SDK oder Runtime an, die installiert werden soll.
    Den Wert von \"version-sdk\" zum Installieren des SDK oder den Wert von \"version-runtime\" zum Installieren der Runtime aus beliebigen Releases finden Sie [hier](https://github.com/dotnet/core/blob/master/release-notes/releases.json).", + "loc.messages.ToolFailed": "Fehler bei der Toolinstallation: %s", + "loc.messages.ImplicitVersionNotSupported": "Die Version muss eine gültige und bestimmte Version sein: %s.", + "loc.messages.getMachinePlatformFailed": "Fehler beim Abrufen der Details zur Computerplattform. Fehler: %s.", + "loc.messages.getDownloadUrlsFailed": "Fehler beim Abrufen der Download-URLs. Fehler: %s.", + "loc.messages.UsingCachedTool": "Es ist eine zwischengespeicherte Kopie von .NET Core vorhanden. Eine Neuinstallation ist nicht erforderlich. Speicherort des zwischengespeicherten Tools: %s.", + "loc.messages.CheckingToolCache": "Es wird überprüft, ob eine zwischengespeicherte Kopie für diese Version vorhanden ist...", + "loc.messages.InstallingAfresh": "Der Cache enthält nicht die angeforderte Version von .NET Core. Laden Sie die Version jetzt herunter, und installieren Sie sie.", + "loc.messages.GettingDownloadUrl": "URL zum Herunterladen von .NET Core %s, Version %s wird abgerufen.", + "loc.messages.CouldNotDetectPlatform": "Das Betriebssystem des Computers konnte nicht ermittelt werden.", + "loc.messages.NullDownloadUrls": "Die Download-URL konnte nicht erstellt werden. Stellen Sie sicher, dass die angegebene Version %s gültig ist.", + "loc.messages.DownloadingUrl": ".NET Core-Paket wird von URL %s heruntergeladen.", + "loc.messages.ExtractingPackage": "Das heruntergeladene Paket %s wird extrahiert.", + "loc.messages.CachingTool": "Dieses installierte Tool wird zwischengespeichert.", + "loc.messages.SuccessfullyInstalled": ".NET Core %s Version %s wurde erfolgreich installiert.", + "loc.messages.ToolToInstall": "Zu installierendes Tool: .NET Core %s Version %s.", + "loc.messages.PrimaryPlatform": "Erkannte Plattform (primär): %s", + "loc.messages.LegacyPlatform": "Erkannte Plattform (Legacy): %s", + "loc.messages.WarningVersionNotFound": "Downloadinformationen für Version %s konnten nicht abgerufen werden. Überprüfen Sie, ob die angegebene Version richtig ist. Weitere Informationen finden Sie unter dem Link für unterstützte Versionen: https://github.com/dotnet/core/blob/master/release-notes/releases.json. Es wird ein Fallback zum Erstellen einer konventionsbasierten URL durchgeführt.", + "loc.messages.CouldNotDownload": "Das Installationspaket konnte nicht von dieser URL heruntergeladen werden: %s. Fehler: %s", + "loc.messages.FailedToDownloadPackage": "Fehler beim Herunterladen des Pakets für die Installation.", + "loc.messages.PrependGlobalToolPath": "Globaler Toolpfad wird erstellt und PATH vorangestellt." +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson new file mode 100644 index 000000000000..38895bd1bdce --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson @@ -0,0 +1,40 @@ +{ + "loc.friendlyName": "Dot NET Core SDK/Runtime Installer", + "loc.helpMarkDown": "", + "loc.description": "Acquires a version of the .NET Core SDK/Runtime from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks.", + "loc.instanceNameFormat": "Use .NET Core $(packageType) $(version)", + "loc.releaseNotes": "
  • Support for installing multiple versions side by side.
  • Support for patterns in version to fetch latest in minor/major version.
  • Restrict Multi-level lookup
  • ", + "loc.group.displayName.advanced": "Advanced", + "loc.input.label.packageType": "Package to install", + "loc.input.help.packageType": "Please select whether to install only runtime or full SDK.", + "loc.input.label.version": "Version", + "loc.input.help.version": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [releases-index file.](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json", + "loc.input.label.includePreviewVersions": "Include Preview Versions", + "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ingnored if you specify an exact version, such as: 2.1.403", + "loc.input.label.installationPath": "Path To Install .Net Core", + "loc.input.help.installationPath": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • Global installation path such as /usr/share/dotnet or C:\\Program Files\\Dotnet. This would cause the new version to be available machine-wide and be persisted. This requires that the agent process has permission on these folders
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version.", + "loc.input.label.restrictMultiLevelLookup": "Restrict Multi Level Lookup", + "loc.input.help.restrictMultiLevelLookup": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
    For MacOs:
    /usr/local/share/dotnet
    For Linux:
    /usr/share/dotnet

  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).", + "loc.messages.ToolFailed": "Tool install failed: %s", + "loc.messages.ImplicitVersionNotSupported": "Version should be a valid and explicit version: %s", + "loc.messages.getMachinePlatformFailed": "Failed to get machine platform details. Error: %s.", + "loc.messages.getDownloadUrlsFailed": "Failed to get download urls. Error: %s.", + "loc.messages.UsingCachedTool": "Cached copy of .NET Core exists. No need to install afresh. Cached tool location: %s.", + "loc.messages.CheckingToolCache": "Checking if a cached copy exists for this version...", + "loc.messages.InstallingAfresh": "The cache does not contain the requested version of .NET Core. Downloading and installing it now.", + "loc.messages.GettingDownloadUrl": "Getting URL to download .NET Core %s version: %s.", + "loc.messages.CouldNotDetectPlatform": "Could not detect the machine's OS", + "loc.messages.NullDownloadUrls": "Could not construct download URL. Please ensure that specified version %s is valid.", + "loc.messages.DownloadingUrl": "Downloading .NET Core package from URL: %s", + "loc.messages.ExtractingPackage": "Extracting downloaded package %s.", + "loc.messages.CachingTool": "Caching this installed tool.", + "loc.messages.SuccessfullyInstalled": "Successfully installed .NET Core %s version %s.", + "loc.messages.ToolToInstall": "Tool to install: .NET Core %s version %s.", + "loc.messages.PrimaryPlatform": "Detected platform (Primary): %s", + "loc.messages.LegacyPlatform": "Detected platform (Legacy): %s", + "loc.messages.WarningVersionNotFound": "Could not fetch download information for version %s. Please check if the version specified is correct. You can refer the link for supported versions => https://github.com/dotnet/core/blob/master/release-notes/releases.json. Falling back to creating convention based URL.", + "loc.messages.CouldNotDownload": "Could not download installation package from this URL: %s Error: %s", + "loc.messages.FailedToDownloadPackage": "Failed to download package for installation", + "loc.messages.PrependGlobalToolPath": "Creating global tool path and pre-prending to PATH.", + "loc.messages.VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/" +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/es-es/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/es-es/resources.resjson new file mode 100644 index 000000000000..00caef18eeb3 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/es-es/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": "Instalador de herramientas de .NET Core", + "loc.helpMarkDown": "[Más información](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "Adquiere una versión específica de .NET Core de Internet o de la memoria caché de herramientas y la agrega a PATH. Utilice esta tarea para cambiar la versión de .NET Core que se usa en las tareas siguientes.", + "loc.instanceNameFormat": "Usar $(packageType) $(version) de .NET Core", + "loc.input.label.packageType": "Paquete para instalar", + "loc.input.help.packageType": "Seleccione si debe instalarse solo el entorno de ejecución o el SDK completo.", + "loc.input.label.version": "Versión", + "loc.input.help.version": "Especifique la versión exacta del SDK de .NET Core O entorno de ejecución para instalar.
    Busque el valor de \"version-sdk\" para instalar el SDK, o \"version-runtime\" para instalar el entorno de ejecución desde cualquier versión [aquí](https://github.com/dotnet/core/blob/master/release-notes/releases.json)", + "loc.messages.ToolFailed": "No se pudo instalar la herramienta: %s", + "loc.messages.ImplicitVersionNotSupported": "La versión debe ser válida y explícita: %s", + "loc.messages.getMachinePlatformFailed": "Error al obtener los detalles de la plataforma de máquina. Error: %s.", + "loc.messages.getDownloadUrlsFailed": "No se pudieron obtener direcciones URL de descarga. Error: %s.", + "loc.messages.UsingCachedTool": "Existe una copia en caché de .NET Core. No es necesario instalarlo desde cero. Ubicación de la herramienta en caché: %s.", + "loc.messages.CheckingToolCache": "Comprobando si existe una copia en caché de esta versión...", + "loc.messages.InstallingAfresh": "La memoria caché no contiene la versión solicitada de .NET Core. Descargándola e instalándola ahora.", + "loc.messages.GettingDownloadUrl": "Obteniendo direcciones URL para descargar el %s de .NET Core de la versión: %s.", + "loc.messages.CouldNotDetectPlatform": "No se pudo detectar el sistema operativo de la máquina", + "loc.messages.NullDownloadUrls": "No se pueden construir direcciones URL de descarga. Asegúrese de que la versión especificada %s es válida.", + "loc.messages.DownloadingUrl": "Descargando el paquete de .NET Core de la dirección URL: %s", + "loc.messages.ExtractingPackage": "Extrayendo el paquete %s descargado.", + "loc.messages.CachingTool": "Almacenando en caché esta herramienta instalada.", + "loc.messages.SuccessfullyInstalled": ".NET Core %s versión %s se ha instalado correctamente.", + "loc.messages.ToolToInstall": "Herramienta para instalar: .NET Core %s versión %s.", + "loc.messages.PrimaryPlatform": "Se ha detectado la plataforma (principal): %s", + "loc.messages.LegacyPlatform": "Se ha detectado la plataforma (heredada): %s", + "loc.messages.WarningVersionNotFound": "No se pudo recuperar la información de descarga de la versión %s. Compruebe si la versión especificada es correcta. Puede consultar el vínculo para versiones admitidas => https://github.com/dotnet/core/blob/master/release-notes/releases.json. Revirtiendo para crear la dirección URL basada en la convención.", + "loc.messages.CouldNotDownload": "No se pudo descargar el paquete de instalación desde esta dirección URL: %s Error: %s", + "loc.messages.FailedToDownloadPackage": "No se pudo descargar el paquete de instalación", + "loc.messages.PrependGlobalToolPath": "Creando la ruta de acceso de herramientas global y anexándola como prefijo a PATH." +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/fr-fr/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/fr-fr/resources.resjson new file mode 100644 index 000000000000..81beff1d70d8 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/fr-fr/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": "Programme d'installation de .NET Core Tool", + "loc.helpMarkDown": "[Plus d'informations](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "Acquiert une version spécifique de .NET Core à partir d'Internet ou du cache d'outils, puis l'ajoute à PATH. Utilisez cette tâche pour changer la version de .NET Core utilisée dans les tâches suivantes.", + "loc.instanceNameFormat": "Utilisez .NET Core $(packageType) $(version)", + "loc.input.label.packageType": "Package à installer", + "loc.input.help.packageType": "Choisissez d'installer le runtime uniquement ou le kit SDK complet.", + "loc.input.label.version": "Version", + "loc.input.help.version": "Spécifiez la version exacte du kit SDK .NET Core à installer.
    Trouvez la valeur de 'version-sdk' pour installer le kit SDK, ou la valeur de 'version-runtime' pour installer le Runtime de toutes les versions [ici](https://github.com/dotnet/core/blob/master/release-notes/releases.json)", + "loc.messages.ToolFailed": "Échec de l'installation de l'outil : %s", + "loc.messages.ImplicitVersionNotSupported": "La version doit être une version valide et explicite : %s", + "loc.messages.getMachinePlatformFailed": "Échec de l'obtention des détails relatifs à la plateforme de la machine. Erreur : %s.", + "loc.messages.getDownloadUrlsFailed": "Échec de l'obtention des URL de téléchargement. Erreur : %s.", + "loc.messages.UsingCachedTool": "Une copie mise en cache de .NET Core existe. Vous devez effectuer une nouvelle installation. Emplacement de l'outil mis en cache : %s.", + "loc.messages.CheckingToolCache": "Vérification de l'existence d'une copie mise en cache pour cette version...", + "loc.messages.InstallingAfresh": "Le cache ne contient pas la version demandée de .NET Core. Téléchargement et installation en cours.", + "loc.messages.GettingDownloadUrl": "Obtention de l'URL de téléchargement de .NET Core %s version %s.", + "loc.messages.CouldNotDetectPlatform": "Impossible de détecter l'OS de la machine", + "loc.messages.NullDownloadUrls": "Impossible de construire l'URL de téléchargement. Vérifiez que la version %s spécifiée est valide.", + "loc.messages.DownloadingUrl": "Téléchargement du package .NET Core à partir de l'URL : %s", + "loc.messages.ExtractingPackage": "Extraction du package téléchargé %s.", + "loc.messages.CachingTool": "Mise en cache de l'outil installé.", + "loc.messages.SuccessfullyInstalled": "Installation réussie de .NET Core %s version %s.", + "loc.messages.ToolToInstall": "Outil à installer : .NET Core %s version %s.", + "loc.messages.PrimaryPlatform": "Plateforme détectée (principal) : %s", + "loc.messages.LegacyPlatform": "Plateforme détectée (héritée) : %s", + "loc.messages.WarningVersionNotFound": "Impossible de récupérer (fetch) les informations de téléchargement pour la version %s. Vérifiez si la version spécifiée est correcte. Pour connaître les versions prises en charge, consultez le lien => https://github.com/dotnet/core/blob/master/release-notes/releases.json. Retour à la création d'une URL basée sur une convention.", + "loc.messages.CouldNotDownload": "Impossible de télécharger le package d'installation à partir de cette URL : %s. Erreur : %s", + "loc.messages.FailedToDownloadPackage": "Échec du téléchargement du package pour l'installation", + "loc.messages.PrependGlobalToolPath": "Création d'un chemin d'outil global, et ajout de la valeur correspondante au début de PATH." +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/it-IT/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/it-IT/resources.resjson new file mode 100644 index 000000000000..60413643d907 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/it-IT/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": "Programma di installazione degli strumenti di .NET Core", + "loc.helpMarkDown": "[Altre informazioni](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "Acquisisce una versione specifica di .NET Core da Internet o dalla cache degli strumenti e la aggiunge a PATH. Usare questa attività per cambiare la versione di .NET Core usata nelle attività successive.", + "loc.instanceNameFormat": "Usa .NET Core $(packageType) $(version)", + "loc.input.label.packageType": "Pacchetto da installare", + "loc.input.help.packageType": "Scegliere se installare solo il runtime o l'SDK completo.", + "loc.input.label.version": "Versione", + "loc.input.help.version": "Consente di specificare la versione esatta di .NET Core SDK o del runtime da installare.
    Il valore di `version-sdk` per installare l'SDK o di `version-runtime` per installare il runtime da qualsiasi versione è disponibile [qui](https://github.com/dotnet/core/blob/master/release-notes/releases.json)", + "loc.messages.ToolFailed": "L'installazione dello strumento non è riuscita: %s", + "loc.messages.ImplicitVersionNotSupported": "La versione deve essere valida ed esplicita: %s", + "loc.messages.getMachinePlatformFailed": "Non è stato possibile ottenere i dettagli della piattaforma del computer. Errore: %s.", + "loc.messages.getDownloadUrlsFailed": "Non è stato possibile recuperare gli URL di download. Errore: %s.", + "loc.messages.UsingCachedTool": "Esiste una copia di .NET Core memorizzata nella cache. Non è necessario installarla di nuovo. Percorso dello strumento memorizzato nella cache: %s.", + "loc.messages.CheckingToolCache": "Verifica dell'esistenza di una copia memorizzata nella cache per questa versione...", + "loc.messages.InstallingAfresh": "La cache non contiene la versione richiesta di .NET Core. Verrà scaricata e installata ora.", + "loc.messages.GettingDownloadUrl": "Recupero dell'URL per scaricare .NET Core %s versione %s.", + "loc.messages.CouldNotDetectPlatform": "Non è stato possibile rilevare il sistema operativo del computer", + "loc.messages.NullDownloadUrls": "Non è stato possibile costruire l'URL di download. Assicurarsi che la versione specificata %s sia valida.", + "loc.messages.DownloadingUrl": "Download del pacchetto .NET Core dall'URL %s", + "loc.messages.ExtractingPackage": "Estrazione del pacchetto scaricato %s.", + "loc.messages.CachingTool": "Questo strumento installato verrà memorizzato nella cache.", + "loc.messages.SuccessfullyInstalled": ".NET Core %s versione %s è stato installato.", + "loc.messages.ToolToInstall": "Strumento da installare: .NET Core %s versione %s.", + "loc.messages.PrimaryPlatform": "Piattaforma rilevata (primaria): %s", + "loc.messages.LegacyPlatform": "Piattaforma rilevata (legacy): %s", + "loc.messages.WarningVersionNotFound": "Non è stato possibile recuperare le informazioni di download per la versione %s. Controllare se la versione specificata è corretta. È possibile fare riferimento al collegamento per informazioni sulle versioni supportate: https://github.com/dotnet/core/blob/master/release-notes/releases.json. Verrà eseguito il fallback all'URL basato sulla convenzione di creazione.", + "loc.messages.CouldNotDownload": "Non è stato possibile scaricare il pacchetto di installazione da questo URL: %s Errore: %s", + "loc.messages.FailedToDownloadPackage": "Non è stato possibile scaricare il pacchetto per l'installazione", + "loc.messages.PrependGlobalToolPath": "Creazione del percorso strumenti globale e aggiunta del percorso prima di PATH." +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ja-jp/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ja-jp/resources.resjson new file mode 100644 index 000000000000..7ac58cf0a05f --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ja-jp/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": ".NET Core Tool インストーラー", + "loc.helpMarkDown": "[詳細情報](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "特定のバージョンの .NET Core をインターネットまたはツール キャッシュから取得し、PATH に追加します。このタスクを使うと、後続のタスクで使用される .NET Core のバージョンを変更できます。", + "loc.instanceNameFormat": ".NET Core $(packageType) $(version) の使用", + "loc.input.label.packageType": "インストールするパッケージ", + "loc.input.help.packageType": "ランタイムのみをインストールするか、SDK 全体をインストールするかを選択してください。", + "loc.input.label.version": "バージョン", + "loc.input.help.version": "インストールする .NET Core SDK またはランタイムの正確なバージョンを指定します。
    [ここ](https://github.com/dotnet/core/blob/master/release-notes/releases.json) の任意のリリースから、SDK をインストールする場合は `version-sdk` の値、ランタイムをインストールする場合は `version-runtime` の値をご確認ください。", + "loc.messages.ToolFailed": "ツールをインストールできませんでした: %s", + "loc.messages.ImplicitVersionNotSupported": "バージョンは、有効で明示的なバージョンである必要があります: %s", + "loc.messages.getMachinePlatformFailed": "マシンのプラットフォームの詳細を取得できませんでした。エラー: %s。", + "loc.messages.getDownloadUrlsFailed": "ダウンロード URL を取得できませんでした。エラー: %s。", + "loc.messages.UsingCachedTool": ".NET Core のキャッシュ済みのコピーが存在します。新しくインストールする必要はありません。キャッシュされたツールの場所は %s です。", + "loc.messages.CheckingToolCache": "このバージョンのキャッシュ済みコピーが存在するかどうか確認しています...", + "loc.messages.InstallingAfresh": "キャッシュに要求されたバージョンの .NET Core が含まれていません。ダウンロードしてインストールしています。", + "loc.messages.GettingDownloadUrl": ".NET Core %s バージョンをダウンロードする URL を取得しています: %s。", + "loc.messages.CouldNotDetectPlatform": "マシンの OS を検出できませんでした", + "loc.messages.NullDownloadUrls": "ダウンロード URL を作成できませんでした。指定されたバージョン %s が有効であることをご確認ください。", + "loc.messages.DownloadingUrl": "URL から .NET Core パッケージをダウンロードしています: %s", + "loc.messages.ExtractingPackage": "ダウンロードされたパッケージ %s を抽出しています。", + "loc.messages.CachingTool": "このインストール済みのツールをキャッシュしています。", + "loc.messages.SuccessfullyInstalled": ".NET Core %s バージョン %s が正常にインストールされました。", + "loc.messages.ToolToInstall": "インストールするツール: .NET Core %s バージョン %s。", + "loc.messages.PrimaryPlatform": "検出されたプラットフォーム (プライマリ): %s", + "loc.messages.LegacyPlatform": "検出されたプラットフォーム (レガシ): %s", + "loc.messages.WarningVersionNotFound": "バージョン %s のダウンロード情報を取得できませんでした。指定されたバージョンが正しいことをご確認ください。サポートされているバージョンを確認するには次のリンクを参照します。https://github.com/dotnet/core/blob/master/release-notes/releases.json。規則に基づく URL の作成にフォールバックします。", + "loc.messages.CouldNotDownload": "次の URL からインストール パッケージをダウンロードできませんでした: %s。エラー: %s", + "loc.messages.FailedToDownloadPackage": "インストール用のパッケージをダウンロードできませんでした", + "loc.messages.PrependGlobalToolPath": "グローバル ツール パスを作成し、パスの先頭に追加します。" +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ko-KR/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ko-KR/resources.resjson new file mode 100644 index 000000000000..9f23ac600abf --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ko-KR/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": ".NET Core 도구 설치 관리자", + "loc.helpMarkDown": "[자세한 정보](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "인터넷 또는 도구 캐시에서 특정 버전의 .NET Core를 가져와 PATH에 추가합니다. 이 작업을 사용하여 후속 작업에 사용되는 .NET Core 버전을 변경할 수 있습니다.", + "loc.instanceNameFormat": ".NET Core $(packageType) $(version) 사용", + "loc.input.label.packageType": "설치할 패키지", + "loc.input.help.packageType": "런타임만 설치할지 또는 전체 SDK를 설치할지 선택하세요.", + "loc.input.label.version": "버전", + "loc.input.help.version": "설치할 .NET Core SDK 또는 런타임 버전을 정확하게 지정합니다.
    [여기](https://github.com/dotnet/core/blob/master/release-notes/releases.json)에서 SDK를 설치하기 위한 'version-sdk'의 값을 찾거나, 임의 릴리스의 런타임을 설치하기 위한 'version-runtime'의 값을 찾으세요.", + "loc.messages.ToolFailed": "도구 설치 실패: %s", + "loc.messages.ImplicitVersionNotSupported": "버전은 유효하고 명시적인 버전(%s)이어야 합니다.", + "loc.messages.getMachinePlatformFailed": "머신 플랫폼 정보를 가져오지 못했습니다. 오류: %s.", + "loc.messages.getDownloadUrlsFailed": "다운로드 URL을 가져오지 못했습니다. 오류: %s.", + "loc.messages.UsingCachedTool": ".NET Core의 캐시된 복사본이 있습니다. 새로 설치하지 않아도 됩니다. 캐시된 도구 위치: %s.", + "loc.messages.CheckingToolCache": "이 버전에 대해 캐시된 복사본이 있는지 확인 중...", + "loc.messages.InstallingAfresh": "캐시에 요청된 .NET Core 버전이 없습니다. 지금 다운로드하여 설치합니다.", + "loc.messages.GettingDownloadUrl": ".NET Core %s 버전, %s을(를) 다운로드할 URL을 가져오는 중입니다.", + "loc.messages.CouldNotDetectPlatform": "머신의 OS를 검색할 수 없습니다.", + "loc.messages.NullDownloadUrls": "다운로드 URL을 생성할 수 없습니다. 지정한 버전 %s이(가) 유효한지 확인하세요.", + "loc.messages.DownloadingUrl": "URL %s에서 .NET Core 패키지를 다운로드하는 중", + "loc.messages.ExtractingPackage": "다운로드한 패키지 %s의 압축을 푸는 중입니다.", + "loc.messages.CachingTool": "설치된 이 도구를 캐싱하는 중입니다.", + "loc.messages.SuccessfullyInstalled": ".NET Core %s 버전 %s을(를) 설치했습니다.", + "loc.messages.ToolToInstall": "설치할 도구: .NET Core %s 버전 %s.", + "loc.messages.PrimaryPlatform": "검색된 플랫폼(기본): %s", + "loc.messages.LegacyPlatform": "검색된 플랫폼(레거시): %s", + "loc.messages.WarningVersionNotFound": "%s 버전의 다운로드 정보를 페치할 수 없습니다. 지정한 버전이 올바른지 확인하세요. 지원되는 버전은 https://github.com/dotnet/core/blob/master/release-notes/releases.json 링크를 참조할 수 있습니다. 규칙 기반 URL 생성으로 대체합니다.", + "loc.messages.CouldNotDownload": "이 URL %s에서 설치 패키지를 다운로드할 수 없습니다. 오류: %s", + "loc.messages.FailedToDownloadPackage": "설치할 패키지를 다운로드하지 못했습니다.", + "loc.messages.PrependGlobalToolPath": "전역 도구 경로를 만들어 PATH 앞에 추가합니다." +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ru-RU/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ru-RU/resources.resjson new file mode 100644 index 000000000000..df013841e684 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/ru-RU/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": "Установщик инструментов .NET Core", + "loc.helpMarkDown": "[Дополнительные сведения](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "Скачивает указанную версию .NET Core из Интернета или из кэша инструментов и добавляет ее в переменную PATH. Используйте эту задачу, чтобы изменить версию .NET Core, которая используется в последующих задачах.", + "loc.instanceNameFormat": "Использовать .NET Core $(packageType) $(version)", + "loc.input.label.packageType": "Пакет для установки", + "loc.input.help.packageType": "Выберите, следует ли устанавливать только среду выполнения или полный пакет SDK.", + "loc.input.label.version": "Версия", + "loc.input.help.version": "Укажите точную версию пакета SDK или среды выполнения .NET Core, которую необходимо установить.
    Значение version-sdk для установки пакета SDK или version-runtime для установки среды выполнения из любого выпуска можно найти [здесь](https://github.com/dotnet/core/blob/master/release-notes/releases.json)", + "loc.messages.ToolFailed": "Сбой установки инструмента: %s", + "loc.messages.ImplicitVersionNotSupported": "Следует указать допустимую и явную версию: %s", + "loc.messages.getMachinePlatformFailed": "Не удалось получить сведения о платформе компьютера. Ошибка: %s.", + "loc.messages.getDownloadUrlsFailed": "Не удалось получить URL-адреса для скачивания. Ошибка: %s.", + "loc.messages.UsingCachedTool": "Есть кэшированная копия пакета .NET Core. Устанавливать пакет заново не нужно. Расположение кэшированного пакета: %s.", + "loc.messages.CheckingToolCache": "Проверка наличия кэшированной копии для этой версии...", + "loc.messages.InstallingAfresh": "Кэш не содержит запрошенной версии .NET Core. Идет ее скачивание и установка.", + "loc.messages.GettingDownloadUrl": "Идет получение URL-адреса для скачивания версии %s .NET Core: %s.", + "loc.messages.CouldNotDetectPlatform": "Не удалось определить ОС компьютера", + "loc.messages.NullDownloadUrls": "Не удалось сформировать URL-адрес для скачивания. Убедитесь в том, что указанная версия %s допустима.", + "loc.messages.DownloadingUrl": "Скачивается пакет .NET Core с URL-адреса: %s", + "loc.messages.ExtractingPackage": "Распаковка скачанного пакета %s.", + "loc.messages.CachingTool": "Кэширование установленного инструмента.", + "loc.messages.SuccessfullyInstalled": "Пакет .NET Core %s версии %s успешно установлен.", + "loc.messages.ToolToInstall": "Инструмент для установки: .NET Core %s версии %s.", + "loc.messages.PrimaryPlatform": "Обнаружена платформа (основная): %s", + "loc.messages.LegacyPlatform": "Обнаружена платформа (прежней версии): %s", + "loc.messages.WarningVersionNotFound": "Не удалось получить сведения о скачивании для версии %s. Проверьте, правильно ли указана версия. Список поддерживаемых версий можно найти по ссылке https://github.com/dotnet/core/blob/master/release-notes/releases.json. Будет создан URL-адрес на основе соглашений.", + "loc.messages.CouldNotDownload": "Не удалось скачать пакет установки с этого URL-адреса: %s. Ошибка: %s", + "loc.messages.FailedToDownloadPackage": "Не удалось скачать пакет для установки", + "loc.messages.PrependGlobalToolPath": "Глобальный путь к средству создается и добавляется в начало PATH." +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-CN/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-CN/resources.resjson new file mode 100644 index 000000000000..4f6d52ff586a --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-CN/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": ".NET Core 工具安装程序", + "loc.helpMarkDown": "[详细信息](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "从 Internet 或工具缓存获取特定版本的 .NET Core,并将其添加到 PATH。使用此任务更改后续任务中使用的 .NET Core 版本。", + "loc.instanceNameFormat": "使用 .NET Core $(packageType) $(version)", + "loc.input.label.packageType": "要安装的包", + "loc.input.help.packageType": "请选择仅安装运行时还是安装完整 SDK。", + "loc.input.label.version": "版本", + "loc.input.help.version": "指定要安装的 .NET Core SDK 或运行时的准确版本。
    找到用于安装 SDK 的 \"version-sdk\" 的值,或用于从任何版本安装运行时的 \"version-runtime\" 的值[此处](https://github.com/dotnet/core/blob/master/release-notes/releases.json)", + "loc.messages.ToolFailed": "工具安装失败: %s", + "loc.messages.ImplicitVersionNotSupported": "版本应为有效的显式版本: %s", + "loc.messages.getMachinePlatformFailed": "无法获取计算机平台详细信息。错误: %s。", + "loc.messages.getDownloadUrlsFailed": "无法获取下载 URL。错误: %s。", + "loc.messages.UsingCachedTool": "存在 .NET Core 的缓存副本。不需要重新安装。缓存工具位置: %s。", + "loc.messages.CheckingToolCache": "正在检查是否存在此版本的缓存副本...", + "loc.messages.InstallingAfresh": "缓存不包含 .NET Core 的请求版本。立即下载并安装。", + "loc.messages.GettingDownloadUrl": "正在获取用于下载 .NET Core %s 版本 %s 的 URL。", + "loc.messages.CouldNotDetectPlatform": "无法检测计算机的操作系统", + "loc.messages.NullDownloadUrls": "无法构造下载 URL。请确保指定的版本 %s 有效。", + "loc.messages.DownloadingUrl": "正在从 URL 下载 .NET Core 包: %s", + "loc.messages.ExtractingPackage": "正在解压已下载的包 %s。", + "loc.messages.CachingTool": "正在缓存已安装的此工具。", + "loc.messages.SuccessfullyInstalled": "已成功安装 .NET Core %s 版本 %s。", + "loc.messages.ToolToInstall": "要安装的工具: .NET Core %s 版本 %s。", + "loc.messages.PrimaryPlatform": "检测到的平台(主要): %s", + "loc.messages.LegacyPlatform": "检测到的平台(旧版): %s", + "loc.messages.WarningVersionNotFound": "无法提取版本 %s 的下载信息。请检查指定的版本是否正确。有关受支持的版本,可以访问链接 => https://github.com/dotnet/core/blob/master/release-notes/releases.json。回退到基于 URL 的约定的创建。", + "loc.messages.CouldNotDownload": "无法从该 URL 下载安装包: %s 错误: %s", + "loc.messages.FailedToDownloadPackage": "无法下载用于安装的包", + "loc.messages.PrependGlobalToolPath": "正在创建全局工具路径和追加到 PATH。" +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-TW/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-TW/resources.resjson new file mode 100644 index 000000000000..b4d68bc87da7 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/zh-TW/resources.resjson @@ -0,0 +1,31 @@ +{ + "loc.friendlyName": ".NET Core 工具安裝程式", + "loc.helpMarkDown": "[詳細資訊](https://go.microsoft.com/fwlink/?linkid=853651)", + "loc.description": "從網際網路或工具快取取得特定 .NET Core 版本,然後將其新增至 PATH。使用此工作可變更後續工作中使用的 .NET Core 版本。", + "loc.instanceNameFormat": "使用 .NET Core $(packageType) $(version)", + "loc.input.label.packageType": "要安裝的套件", + "loc.input.help.packageType": "請選取只要安裝執行階段或要安裝完整 SDK。", + "loc.input.label.version": "版本", + "loc.input.help.version": "請明確指定要安裝的 .NET Core SDK 或執行階段版本。
    請尋找 `version-sdk` 的值來安裝 SDK,或從[此處](https://github.com/dotnet/core/blob/master/release-notes/releases.json) 尋找 `version-runtime` 的值來安裝執行階段。", + "loc.messages.ToolFailed": "工具安裝失敗: %s", + "loc.messages.ImplicitVersionNotSupported": "版本應為有效的明確版本: %s", + "loc.messages.getMachinePlatformFailed": "無法取得機器平台詳細資料。錯誤: %s。", + "loc.messages.getDownloadUrlsFailed": "無法取得下載 URL。錯誤: %s。", + "loc.messages.UsingCachedTool": ".NET Core 的快取複本已存在。不需要重新安裝。快取的工具位置: %s。", + "loc.messages.CheckingToolCache": "正在檢查此版本是否有快取複本...", + "loc.messages.InstallingAfresh": "快取未包含所要求版本的 .NET Core。正在下載該版本的 .NET Core 以立即安裝。", + "loc.messages.GettingDownloadUrl": "正在取得 URL 以下載 .NET Core %s 版: %s。", + "loc.messages.CouldNotDetectPlatform": "偵測不到機器的 OS", + "loc.messages.NullDownloadUrls": "無法建構下載 URL。請確認指定的版本 %s 有效。", + "loc.messages.DownloadingUrl": "正在從 URL 下載 .NET Core 套件: %s", + "loc.messages.ExtractingPackage": "正在將下載的套件 %s 解壓縮。", + "loc.messages.CachingTool": "正在快取這個安裝的工具。", + "loc.messages.SuccessfullyInstalled": "已成功安裝 .NET Core %s 版本 %s。", + "loc.messages.ToolToInstall": "要安裝的工具: .NET Core %s 版本 %s。", + "loc.messages.PrimaryPlatform": "偵測到的平台 (主要): %s", + "loc.messages.LegacyPlatform": "偵測到的平台 (舊版): %s", + "loc.messages.WarningVersionNotFound": "無法擷取版本 %s 的下載資訊。請檢查指定的版本是否正確。您可以參閱連結了解支援的版本 => https://github.com/dotnet/core/blob/master/release-notes/releases.json。將返回建立以慣例為基礎的 URL。", + "loc.messages.CouldNotDownload": "無法從此 URL %s 下載安裝套件,錯誤: %s", + "loc.messages.FailedToDownloadPackage": "無法下載套件以進行安裝", + "loc.messages.PrependGlobalToolPath": "正在建立全域工具路徑並加到 PATH 前面。" +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/ThirdPartyNotices.txt b/Tasks/DotNetCoreInstallerV1/ThirdPartyNotices.txt new file mode 100644 index 000000000000..4128de1970a3 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/ThirdPartyNotices.txt @@ -0,0 +1,429 @@ + +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +Microsoft .NET Core Tool Installer Task incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. + +1. balanced-match (https://github.com/juliangruber/balanced-match) +2. brace-expansion (https://github.com/juliangruber/brace-expansion) +3. concat-map (https://github.com/substack/node-concat-map) +4. minimatch (https://github.com/isaacs/minimatch) +5. Mockery (https://github.com/mfncooper/mockery) +6. Node.js (https://nodejs.org/) +7. q (https://github.com/kriskowal/q) +8. semver (https://github.com/npm/node-semver/) +9. semver-compare (https://github.com/substack/semver-compare) +10. ShellJS (https://github.com/shelljs/shelljs) +11. tunnel (https://github.com/koichik/node-tunnel) +12. underscore.js (http://underscorejs.org/; https://github.com/jashkenas/underscore) +13. uuid (https://github.com/kelektiv/node-uuid) +14. VSTS-task-lib (https://github.com/Microsoft/vsts-task-lib) + +%% balanced-match NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +(MIT) + +Copyright (c) 2013 Julian Gruber + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +========================================= +END OF balanced-match NOTICES, INFORMATION, AND LICENSE + +%% brace-expansion NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +(MIT) + +Copyright (c) 2013 Julian Gruber + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +========================================= +END OF brace-expansion NOTICES, INFORMATION, AND LICENSE + +%% concat-map NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (c) James Halliday/Substack + +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF concat-map NOTICES, INFORMATION, AND LICENSE + +%% minimatch NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +========================================= +END OF minimatch NOTICES, INFORMATION, AND LICENSE + +%% Mockery NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyrights for code authored by Yahoo! Inc. is licensed under the following + terms: + + MIT License + + Copyright (c) 2011 Yahoo! Inc. All Rights Reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +========================================= +END OF Mockery NOTICES, INFORMATION, AND LICENSE + +%% Node.js NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +The Node.js license applies to all parts of Node.js that are not externally +maintained libraries. +========================================= +END OF Node.js NOTICES, INFORMATION, AND LICENSE + +%% q NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright 2009�2017 Kristopher Michael Kowal. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +========================================= +END OF q NOTICES, INFORMATION, AND LICENSE + +%% semver NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +========================================= +END OF semver NOTICES, INFORMATION, AND LICENSE + +%% semver-compare NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (c) 2014 James Halliday + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF semver-compare NOTICES, INFORMATION, AND LICENSE + +%% ShellJS NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (c) 2012, Artur Adib +All rights reserved. + +You may use this project under the terms of the New BSD license as follows: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Artur Adib nor the + names of the contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +========================================= +END OF ShellJS NOTICES, INFORMATION, AND LICENSE + +%% tunnel NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) 2012 Koichi Kobayashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +========================================= +END OF tunnel NOTICES, INFORMATION, AND LICENSE + +%% underscore.js NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (c) 2009-2017 Jeremy Ashkenas, DocumentCloud and Investigative +Reporters & Editors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +========================================= +END OF underscore.js NOTICES, INFORMATION, AND LICENSE + +%% uuid NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (c) 2010-2016 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Includes Chris Veness' SHA1 + +Copyright (c) 2014 Chris Veness + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF uuid NOTICES, INFORMATION, AND LICENSE + +%% vso-node-api NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF vso-node-api NOTICES, INFORMATION, AND LICENSE + +%% VSTS-task-lib NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF VSTS-task-lib NOTICES, INFORMATION, AND LICENSE \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts new file mode 100644 index 000000000000..9449db919db7 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -0,0 +1,61 @@ +import * as path from 'path'; + +import * as tl from 'vsts-task-lib/task'; +import * as toolLib from 'vsts-task-tool-lib/tool'; +import { DotNetCoreVersionFetcher, VersionInfo } from "./versionFetcher"; +import { VersionInstaller } from "./versionInstaller"; + +async function run() { + let packageType = tl.getInput('packageType', true); + let version = tl.getInput('version', true).trim(); + let installationPath = tl.getInput('installationPath', true).trim(); + let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions', true); + console.log(tl.loc("ToolToInstall", packageType, version)); + let versionFetcher = new DotNetCoreVersionFetcher(); + + let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(version, packageType, includePreviewVersions); + if (!versionInfo) { + throw tl.loc("MatchingVersionNotFound", version); + } + + let dotNetCoreInstaller = new VersionInstaller(packageType, installationPath); + if (!dotNetCoreInstaller.isVersionInstalled(versionInfo.version)) { + await dotNetCoreInstaller.downloadAndInstall(versionInfo.version, versionFetcher.getDownloadUrl(versionInfo, packageType)); + } + + // By default disable Multi Level Lookup unless user wants it enabled. + if (tl.getBoolInput("restrictMultiLevelLookup", true)) { + tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); + } + + addDotNetCoreToolPath(); + + // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. + tl.setVariable('DOTNET_ROOT', installationPath); +} + +function addDotNetCoreToolPath() { + // Add dot net tools path to "PATH" environment variables, so that tools can be used directly. + try { + let globalToolPath: string = ""; + if (tl.osType().match(/^Win/)) { + globalToolPath = path.join(process.env.USERPROFILE, ".dotnet\\tools"); + } else { + globalToolPath = path.join(process.env.HOME, ".dotnet/tools"); + } + + console.log(tl.loc("PrependGlobalToolPath")); + tl.mkdirP(globalToolPath); + toolLib.prependPath(globalToolPath); + } catch (error) { + //nop + } +} + +var taskManifestPath = path.join(__dirname, "task.json"); +tl.debug("Setting resource path to " + taskManifestPath); +tl.setResourcePath(taskManifestPath); + +run() + .then(() => tl.setResult(tl.TaskResult.Succeeded, "")) + .catch((error) => tl.setResult(tl.TaskResult.Failed, !!error.message ? error.message : error)); \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh b/Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh new file mode 100644 index 000000000000..e44096ac8181 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh @@ -0,0 +1,192 @@ +#!/usr/bin/env bash +# Copyright (c) .NET Foundation and contributors. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. +# + +# Stop script on NZEC +set -e +# Stop script if unbound variable found (use ${var:-} if intentional) +set -u +# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success +# This is causing it to fail +set -o pipefail + +# Use in the the functions: eval $invocation +invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"' + +# standard output may be used as a return value in the functions +# we need a way to write text on the screen in the functions so that +# it won't interfere with the return value. +# Exposing stream 3 as a pipe to standard output of the script itself +exec 3>&1 + +say_err() { + printf "%b\n" "get-os-distro: Error: $1" >&2 +} + +# This platform list is finite - if the SDK/Runtime has supported Linux distribution-specific assets, +# then and only then should the Linux distribution appear in this list. +# Adding a Linux distribution to this list does not imply distribution-specific support. +get_legacy_os_name_from_platform() { + + platform="$1" + case "$platform" in + "centos.7") + echo "centos" + return 0 + ;; + "debian.8") + echo "debian" + return 0 + ;; + "fedora.23") + echo "fedora.23" + return 0 + ;; + "fedora.27") + echo "fedora.27" + return 0 + ;; + "fedora.24") + echo "fedora.24" + return 0 + ;; + "opensuse.13.2") + echo "opensuse.13.2" + return 0 + ;; + "opensuse.42.1") + echo "opensuse.42.1" + return 0 + ;; + "opensuse.42.3") + echo "opensuse.42.3" + return 0 + ;; + "rhel.7"*) + echo "rhel" + return 0 + ;; + "ubuntu.14.04") + echo "ubuntu" + return 0 + ;; + "ubuntu.16.04") + echo "ubuntu.16.04" + return 0 + ;; + "ubuntu.16.10") + echo "ubuntu.16.10" + return 0 + ;; + "ubuntu.18.04") + echo "ubuntu.18.04" + return 0 + ;; + "alpine.3.4.3") + echo "alpine" + return 0 + ;; + esac + return 1 +} + +get_linux_platform_name() { + + if [ -e /etc/os-release ]; then + . /etc/os-release + echo "$ID.$VERSION_ID" + return 0 + elif [ -e /etc/redhat-release ]; then + local redhatRelease=$( /dev/null; then + CPUName=$(uname -m) + case $CPUName in + armv7l) + echo "arm" + return 0 + ;; + aarch64) + echo "arm64" + return 0 + ;; + esac + fi + + # Always default to 'x64' + echo "x64" + return 0 +} + +osName=$(get_current_os_name || echo "") +legacyOsName=$(get_legacy_os_name || echo "") +arch=$(get_machine_architecture || echo "") + +primaryName="$osName-$arch" +legacyName="$legacyOsName" + +echo "Primary:$primaryName" +echo "Legacy:$legacyName" + +if [ -z "$osName" ] && [ -z "$legacyOsName" ];then + exit 1 +fi diff --git a/Tasks/DotNetCoreInstallerV1/externals/get-os-platform.ps1 b/Tasks/DotNetCoreInstallerV1/externals/get-os-platform.ps1 new file mode 100644 index 000000000000..4ac8d07f5ba4 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/externals/get-os-platform.ps1 @@ -0,0 +1,18 @@ +function Get-Machine-Architecture() +{ + # possible values: AMD64, IA64, x86 + return $ENV:PROCESSOR_ARCHITECTURE +} + +function Get-CLIArchitecture-From-Architecture([string]$Architecture) +{ + switch ($Architecture.ToLower()) + { + { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } + { $_ -eq "x86" } { return "x86" } + default { throw "Architecture not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" } + } +} + +$CLIArchitecture = Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) +Write-Output "Primary:win-$CLIArchitecture" \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 b/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 new file mode 100644 index 000000000000..85404535cc2e --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 @@ -0,0 +1,503 @@ +# +# Copyright (c) .NET Foundation and contributors. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. +# + +<# +.SYNOPSIS + Installs dotnet cli +.DESCRIPTION + Installs dotnet cli. If dotnet installation already exists in the given directory + it will update it only if the requested version differs from the one already installed. +.PARAMETER Channel + Default: LTS + Download from the Channel specified. Possible values: + - Current - most current release + - LTS - most current supported release + - 2-part version in a format A.B - represents a specific release + examples: 2.0; 1.0 + - Branch name + examples: release/2.0.0; Master +.PARAMETER Version + Default: latest + Represents a build version on specific channel. Possible values: + - latest - most latest build on specific channel + - coherent - most latest coherent build on specific channel + coherent applies only to SDK downloads + - 3-part version in a format A.B.C - represents specific version of build + examples: 2.0.0-preview2-006120; 1.1.0 +.PARAMETER InstallDir + Default: %LocalAppData%\Microsoft\dotnet + Path to where to install dotnet. Note that binaries will be placed directly in a given directory. +.PARAMETER Architecture + Default: - this value represents currently running OS architecture + Architecture of dotnet binaries to be installed. + Possible values are: , x64 and x86 +.PARAMETER SharedRuntime + Default: false + Installs just the shared runtime bits, not the entire SDK +.PARAMETER DryRun + If set it will not perform installation but instead display what command line to use to consistently install + currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link + with specific version so that this command can be used deterministicly in a build script. + It also displays binaries location if you prefer to install or download it yourself. +.PARAMETER NoPath + By default this script will set environment variable PATH for the current process to the binaries folder inside installation folder. + If set it will display binaries location but not set any environment variable. +.PARAMETER Verbose + Displays diagnostics information. +.PARAMETER AzureFeed + Default: https://dotnetcli.azureedge.net/dotnet + This parameter typically is not changed by the user. + It allows to change URL for the Azure feed used by this installer. +.PARAMETER UncachedFeed + This parameter typically is not changed by the user. + It allows to change URL for the Uncached feed used by this installer. +.PARAMETER ProxyAddress + If set, the installer will use the proxy when making web requests +.PARAMETER ProxyUseDefaultCredentials + Default: false + Use default credentials, when using proxy address. +#> +[cmdletbinding()] +param( + [string]$Channel="LTS", + [string]$Version="Latest", + [string]$InstallDir="", + [string]$Architecture="", + [switch]$SharedRuntime, + [switch]$DryRun, + [switch]$NoPath, + [string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet", + [string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet", + [string]$ProxyAddress, + [switch]$ProxyUseDefaultCredentials +) + +Set-StrictMode -Version Latest +$ErrorActionPreference="Stop" +$ProgressPreference="SilentlyContinue" + +$BinFolderRelativePath="" + +# example path with regex: shared/1.0.0-beta-12345/somepath +$VersionRegEx="/\d+\.\d+[^/]+/" +$OverrideNonVersionedFiles=$true + +function Say($str) { + Write-Output "dotnet-install: $str" +} + +function Say-Verbose($str) { + Write-Verbose "dotnet-install: $str" +} + +function Say-Invocation($Invocation) { + $command = $Invocation.MyCommand; + $args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ") + Say-Verbose "$command $args" +} + +function Invoke-With-Retry([ScriptBlock]$ScriptBlock, [int]$MaxAttempts = 3, [int]$SecondsBetweenAttempts = 1) { + $Attempts = 0 + + while ($true) { + try { + return $ScriptBlock.Invoke() + } + catch { + $Attempts++ + if ($Attempts -lt $MaxAttempts) { + Start-Sleep $SecondsBetweenAttempts + } + else { + throw + } + } + } +} + +function Get-Machine-Architecture() { + Say-Invocation $MyInvocation + + # possible values: AMD64, IA64, x86 + return $ENV:PROCESSOR_ARCHITECTURE +} + +# TODO: Architecture and CLIArchitecture should be unified +function Get-CLIArchitecture-From-Architecture([string]$Architecture) { + Say-Invocation $MyInvocation + + switch ($Architecture.ToLower()) { + { $_ -eq "" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) } + { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } + { $_ -eq "x86" } { return "x86" } + default { throw "Architecture not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" } + } +} + +function Get-Version-Info-From-Version-Text([string]$VersionText) { + Say-Invocation $MyInvocation + + $Data = @($VersionText.Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); + + $VersionInfo = @{} + $VersionInfo.CommitHash = $Data[0].Trim() + $VersionInfo.Version = $Data[1].Trim() + return $VersionInfo +} + +function Load-Assembly([string] $Assembly) { + try { + Add-Type -Assembly $Assembly | Out-Null + } + catch { + # On Nano Server, Powershell Core Edition is used. Add-Type is unable to resolve base class assemblies because they are not GAC'd. + # Loading the base class assemblies is not unnecessary as the types will automatically get resolved. + } +} + +function GetHTTPResponse([Uri] $Uri) +{ + Invoke-With-Retry( + { + + $HttpClient = $null + + try { + # HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet. + Load-Assembly -Assembly System.Net.Http + + if(-not $ProxyAddress) + { + # Despite no proxy being explicitly specified, we may still be behind a default proxy + $DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy; + if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))){ + $ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString + $ProxyUseDefaultCredentials = $true + } + } + + if($ProxyAddress){ + $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler + $HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{Address=$ProxyAddress;UseDefaultCredentials=$ProxyUseDefaultCredentials} + $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler + } + else { + $HttpClient = New-Object System.Net.Http.HttpClient + } + # Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out + # 10 minutes allows it to work over much slower connections. + $HttpClient.Timeout = New-TimeSpan -Minutes 10 + $Response = $HttpClient.GetAsync($Uri).Result + if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) + { + $ErrorMsg = "Failed to download $Uri." + if ($Response -ne $null) + { + $ErrorMsg += " $Response" + } + + throw $ErrorMsg + } + + return $Response + } + finally { + if ($HttpClient -ne $null) { + $HttpClient.Dispose() + } + } + }) +} + + +function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) { + Say-Invocation $MyInvocation + + $VersionFileUrl = $null + if ($SharedRuntime) { + $VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version" + } + else { + if ($Coherent) { + $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.coherent.version" + } + else { + $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version" + } + } + + $Response = GetHTTPResponse -Uri $VersionFileUrl + $StringContent = $Response.Content.ReadAsStringAsync().Result + + switch ($Response.Content.Headers.ContentType) { + { ($_ -eq "application/octet-stream") } { $VersionText = [Text.Encoding]::UTF8.GetString($StringContent) } + { ($_ -eq "text/plain") } { $VersionText = $StringContent } + { ($_ -eq "text/plain; charset=UTF-8") } { $VersionText = $StringContent } + default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." } + } + + $VersionInfo = Get-Version-Info-From-Version-Text $VersionText + + return $VersionInfo +} + + +function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, [string]$Version) { + Say-Invocation $MyInvocation + + switch ($Version.ToLower()) { + { $_ -eq "latest" } { + $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False + return $LatestVersionInfo.Version + } + { $_ -eq "coherent" } { + $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $True + return $LatestVersionInfo.Version + } + default { return $Version } + } +} + +function Get-Download-Link([string]$AzureFeed, [string]$Channel, [string]$SpecificVersion, [string]$CLIArchitecture) { + Say-Invocation $MyInvocation + + if ($SharedRuntime) { + $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificVersion-win-$CLIArchitecture.zip" + } + else { + $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificVersion-win-$CLIArchitecture.zip" + } + + Say-Verbose "Constructed primary payload URL: $PayloadURL" + + return $PayloadURL +} + +function Get-LegacyDownload-Link([string]$AzureFeed, [string]$Channel, [string]$SpecificVersion, [string]$CLIArchitecture) { + Say-Invocation $MyInvocation + + if ($SharedRuntime) { + $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip" + } + else { + $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip" + } + + Say-Verbose "Constructed legacy payload URL: $PayloadURL" + + return $PayloadURL +} + +function Get-User-Share-Path() { + Say-Invocation $MyInvocation + + $InstallRoot = $env:DOTNET_INSTALL_DIR + if (!$InstallRoot) { + $InstallRoot = "$env:LocalAppData\Microsoft\dotnet" + } + return $InstallRoot +} + +function Resolve-Installation-Path([string]$InstallDir) { + Say-Invocation $MyInvocation + + if ($InstallDir -eq "") { + return Get-User-Share-Path + } + return $InstallDir +} + +function Get-Version-Info-From-Version-File([string]$InstallRoot, [string]$RelativePathToVersionFile) { + Say-Invocation $MyInvocation + + $VersionFile = Join-Path -Path $InstallRoot -ChildPath $RelativePathToVersionFile + Say-Verbose "Local version file: $VersionFile" + + if (Test-Path $VersionFile) { + $VersionText = cat $VersionFile + Say-Verbose "Local version file text: $VersionText" + return Get-Version-Info-From-Version-Text $VersionText + } + + Say-Verbose "Local version file not found." + + return $null +} + +function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) { + Say-Invocation $MyInvocation + + $DotnetPackagePath = Join-Path -Path $InstallRoot -ChildPath $RelativePathToPackage | Join-Path -ChildPath $SpecificVersion + Say-Verbose "Is-Dotnet-Package-Installed: Path to a package: $DotnetPackagePath" + return Test-Path $DotnetPackagePath -PathType Container +} + +function Get-Absolute-Path([string]$RelativeOrAbsolutePath) { + # Too much spam + # Say-Invocation $MyInvocation + + return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RelativeOrAbsolutePath) +} + +function Get-Path-Prefix-With-Version($path) { + $match = [regex]::match($path, $VersionRegEx) + if ($match.Success) { + return $entry.FullName.Substring(0, $match.Index + $match.Length) + } + + return $null +} + +function Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package([System.IO.Compression.ZipArchive]$Zip, [string]$OutPath) { + Say-Invocation $MyInvocation + + $ret = @() + foreach ($entry in $Zip.Entries) { + $dir = Get-Path-Prefix-With-Version $entry.FullName + if ($dir -ne $null) { + $path = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $dir) + if (-Not (Test-Path $path -PathType Container)) { + $ret += $dir + } + } + } + + $ret = $ret | Sort-Object | Get-Unique + + $values = ($ret | foreach { "$_" }) -join ";" + Say-Verbose "Directories to unpack: $values" + + return $ret +} + +# Example zip content and extraction algorithm: +# Rule: files if extracted are always being extracted to the same relative path locally +# .\ +# a.exe # file does not exist locally, extract +# b.dll # file exists locally, override only if $OverrideFiles set +# aaa\ # same rules as for files +# ... +# abc\1.0.0\ # directory contains version and exists locally +# ... # do not extract content under versioned part +# abc\asd\ # same rules as for files +# ... +# def\ghi\1.0.1\ # directory contains version and does not exist locally +# ... # extract content +function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) { + Say-Invocation $MyInvocation + + Load-Assembly -Assembly System.IO.Compression.FileSystem + Set-Variable -Name Zip + try { + $Zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath) + + $DirectoriesToUnpack = Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package -Zip $Zip -OutPath $OutPath + + foreach ($entry in $Zip.Entries) { + $PathWithVersion = Get-Path-Prefix-With-Version $entry.FullName + if (($PathWithVersion -eq $null) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) { + $DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName) + $DestinationDir = Split-Path -Parent $DestinationPath + $OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath)) + if ((-Not $DestinationPath.EndsWith("\")) -And $OverrideFiles) { + New-Item -ItemType Directory -Force -Path $DestinationDir | Out-Null + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $DestinationPath, $OverrideNonVersionedFiles) + } + } + } + } + finally { + if ($Zip -ne $null) { + $Zip.Dispose() + } + } +} + +function DownloadFile([Uri]$Uri, [string]$OutPath) { + $Stream = $null + + try { + $Response = GetHTTPResponse -Uri $Uri + $Stream = $Response.Content.ReadAsStreamAsync().Result + $File = [System.IO.File]::Create($OutPath) + $Stream.CopyTo($File) + $File.Close() + } + finally { + if ($Stream -ne $null) { + $Stream.Dispose() + } + } +} + +function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) { + $BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath) + if (-Not $NoPath) { + Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process." + $env:path = "$BinPath;" + $env:path + } + else { + Say "Binaries of dotnet can be found in $BinPath" + } +} + +$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture +$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version +$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -Channel $Channel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture +$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -Channel $Channel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture + +if ($DryRun) { + Say "Payload URLs:" + Say "Primary - $DownloadLink" + Say "Legacy - $LegacyDownloadLink" + Say "Repeatable invocation: .\$($MyInvocation.MyCommand) -Version $SpecificVersion -Channel $Channel -Architecture $CLIArchitecture -InstallDir $InstallDir" + exit 0 +} + +$InstallRoot = Resolve-Installation-Path $InstallDir +Say-Verbose "InstallRoot: $InstallRoot" + +$IsSdkInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage "sdk" -SpecificVersion $SpecificVersion +Say-Verbose ".NET SDK installed? $IsSdkInstalled" +if ($IsSdkInstalled) { + Say ".NET SDK version $SpecificVersion is already installed." + Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath + exit 0 +} + +New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null + +$installDrive = $((Get-Item $InstallRoot).PSDrive.Name); +Write-Output "${installDrive}:"; +$free = Get-CimInstance -Class win32_logicaldisk | where Deviceid -eq "${installDrive}:" +if ($free.Freespace / 1MB -le 100 ) { + Say "There is not enough disk space on drive ${installDrive}:" + exit 0 +} + +$ZipPath = [System.IO.Path]::GetTempFileName() +Say-Verbose "Zip path: $ZipPath" +Say "Downloading link: $DownloadLink" +try { + DownloadFile -Uri $DownloadLink -OutPath $ZipPath +} +catch { + Say "Cannot download: $DownloadLink" + $DownloadLink = $LegacyDownloadLink + $ZipPath = [System.IO.Path]::GetTempFileName() + Say-Verbose "Legacy zip path: $ZipPath" + Say "Downloading legacy link: $DownloadLink" + DownloadFile -Uri $DownloadLink -OutPath $ZipPath +} + +Say "Extracting zip from $DownloadLink" +Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot + +Remove-Item $ZipPath + +Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath + +Say "Installation finished" +exit 0 \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh b/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh new file mode 100644 index 000000000000..0ea08a77870a --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh @@ -0,0 +1,815 @@ +#!/usr/bin/env bash +# Copyright (c) .NET Foundation and contributors. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. +# + +# Stop script on NZEC +set -e +# Stop script if unbound variable found (use ${var:-} if intentional) +set -u +# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success +# This is causing it to fail +set -o pipefail + +# Use in the the functions: eval $invocation +invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"' + +# standard output may be used as a return value in the functions +# we need a way to write text on the screen in the functions so that +# it won't interfere with the return value. +# Exposing stream 3 as a pipe to standard output of the script itself +exec 3>&1 + +# Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors. +# See if stdout is a terminal +if [ -t 1 ]; then + # see if it supports colors + ncolors=$(tput colors) + if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then + bold="$(tput bold || echo)" + normal="$(tput sgr0 || echo)" + black="$(tput setaf 0 || echo)" + red="$(tput setaf 1 || echo)" + green="$(tput setaf 2 || echo)" + yellow="$(tput setaf 3 || echo)" + blue="$(tput setaf 4 || echo)" + magenta="$(tput setaf 5 || echo)" + cyan="$(tput setaf 6 || echo)" + white="$(tput setaf 7 || echo)" + fi +fi + +say_err() { + printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2 +} + +say() { + # using stream 3 (defined in the beginning) to not interfere with stdout of functions + # which may be used as return value + printf "%b\n" "${cyan:-}dotnet-install:${normal:-} $1" >&3 +} + +say_verbose() { + if [ "$verbose" = true ]; then + say "$1" + fi +} + +get_os_download_name_from_platform() { + eval $invocation + + platform="$1" + case "$platform" in + "centos.7") + echo "centos" + return 0 + ;; + "debian.8") + echo "debian" + return 0 + ;; + "fedora.23") + echo "fedora.23" + return 0 + ;; + "fedora.24") + echo "fedora.24" + return 0 + ;; + "opensuse.13.2") + echo "opensuse.13.2" + return 0 + ;; + "opensuse.42.1") + echo "opensuse.42.1" + return 0 + ;; + "rhel.7"*) + echo "rhel" + return 0 + ;; + "ubuntu.14.04") + echo "ubuntu" + return 0 + ;; + "ubuntu.16.04") + echo "ubuntu.16.04" + return 0 + ;; + "ubuntu.16.10") + echo "ubuntu.16.10" + return 0 + ;; + "alpine.3.4.3") + echo "alpine" + return 0 + ;; + esac + return 1 +} + +get_current_os_name() { + eval $invocation + + local uname=$(uname) + if [ "$uname" = "Darwin" ]; then + echo "osx" + return 0 + else + if [ "$uname" = "Linux" ]; then + echo "linux" + return 0 + fi + fi + + say_err "OS name could not be detected: $ID.$VERSION_ID" + return 1 +} + +get_distro_specific_os_name() { + eval $invocation + + local uname=$(uname) + if [ "$uname" = "Darwin" ]; then + echo "osx" + return 0 + elif [ -n "$runtime_id" ]; then + echo $(get_os_download_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}") + return 0 + else + if [ -e /etc/os-release ]; then + . /etc/os-release + os=$(get_os_download_name_from_platform "$ID.$VERSION_ID" || echo "") + if [ -n "$os" ]; then + echo "$os" + return 0 + fi + fi + fi + + say_verbose "Distribution specific OS name and version could not be detected: $ID.$VERSION_ID" + return 1 +} + +machine_has() { + eval $invocation + + hash "$1" > /dev/null 2>&1 + return $? +} + + +check_min_reqs() { + local hasMinimum=false + if machine_has "curl"; then + hasMinimum=true + elif machine_has "wget"; then + hasMinimum=true + fi + + if [ "$hasMinimum" = "false" ]; then + say_err "curl (recommended) or wget are required to download dotnet. Install missing prerequisite to proceed." + return 1 + fi + return 0 +} + +check_pre_reqs() { + eval $invocation + + local failing=false; + + if [ "${DOTNET_INSTALL_SKIP_PREREQS:-}" = "1" ]; then + return 0 + fi + + if [ "$(uname)" = "Linux" ]; then + if ! [ -x "$(command -v ldconfig)" ]; then + echo "ldconfig is not in PATH, trying /sbin/ldconfig." + LDCONFIG_COMMAND="/sbin/ldconfig" + else + LDCONFIG_COMMAND="ldconfig" + fi + + [ -z "$($LDCONFIG_COMMAND -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && failing=true + fi + + if [ "$failing" = true ]; then + return 1 + fi + + return 0 +} + +# args: +# input - $1 +to_lowercase() { + #eval $invocation + + echo "$1" | tr '[:upper:]' '[:lower:]' + return 0 +} + +# args: +# input - $1 +remove_trailing_slash() { + #eval $invocation + + local input=${1:-} + echo "${input%/}" + return 0 +} + +# args: +# input - $1 +remove_beginning_slash() { + #eval $invocation + + local input=${1:-} + echo "${input#/}" + return 0 +} + +# args: +# root_path - $1 +# child_path - $2 - this parameter can be empty +combine_paths() { + eval $invocation + + # TODO: Consider making it work with any number of paths. For now: + if [ ! -z "${3:-}" ]; then + say_err "combine_paths: Function takes two parameters." + return 1 + fi + + local root_path=$(remove_trailing_slash $1) + local child_path=$(remove_beginning_slash ${2:-}) + say_verbose "combine_paths: root_path=$root_path" + say_verbose "combine_paths: child_path=$child_path" + echo "$root_path/$child_path" + return 0 +} + +get_machine_architecture() { + eval $invocation + + # Currently the only one supported + echo "x64" + return 0 +} + +# args: +# architecture - $1 +get_normalized_architecture_from_architecture() { + eval $invocation + + local architecture=$(to_lowercase $1) + case $architecture in + \) + echo "$(get_normalized_architecture_from_architecture $(get_machine_architecture))" + return 0 + ;; + amd64|x64) + echo "x64" + return 0 + ;; + x86) + say_err "Architecture \`x86\` currently not supported" + return 1 + ;; + esac + + say_err "Architecture \`$architecture\` not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" + return 1 +} + +# version_info is a conceptual two line string representing commit hash and 4-part version +# format: +# Line 1: # commit_hash +# Line 2: # 4-part version + +# args: +# version_text - stdin +get_version_from_version_info() { + eval $invocation + + cat | tail -n 1 + return 0 +} + +# args: +# version_text - stdin +get_commit_hash_from_version_info() { + eval $invocation + + cat | head -n 1 + return 0 +} + +# args: +# install_root - $1 +# relative_path_to_package - $2 +# specific_version - $3 +is_dotnet_package_installed() { + eval $invocation + + local install_root=$1 + local relative_path_to_package=$2 + local specific_version=${3//[$'\t\r\n']} + + local dotnet_package_path=$(combine_paths $(combine_paths $install_root $relative_path_to_package) $specific_version) + say_verbose "is_dotnet_package_installed: dotnet_package_path=$dotnet_package_path" + + if [ -d "$dotnet_package_path" ]; then + return 0 + else + return 1 + fi +} + +# args: +# azure_feed - $1 +# channel - $2 +# normalized_architecture - $3 +get_latest_version_info() { + eval $invocation + + local azure_feed=$1 + local channel=$2 + local normalized_architecture=$3 + local coherent=$4 + + local version_file_url=null + if [ "$shared_runtime" = true ]; then + version_file_url="$uncached_feed/Runtime/$channel/latest.version" + else + if [ "$coherent" = true ]; then + version_file_url="$uncached_feed/Sdk/$channel/latest.coherent.version" + else + version_file_url="$uncached_feed/Sdk/$channel/latest.version" + fi + fi + say_verbose "get_latest_version_info: latest url: $version_file_url" + + download $version_file_url + return $? +} + +# args: +# azure_feed - $1 +# channel - $2 +# normalized_architecture - $3 +# version - $4 +get_specific_version_from_version() { + eval $invocation + + local azure_feed=$1 + local channel=$2 + local normalized_architecture=$3 + local version=$(to_lowercase $4) + + case $version in + latest) + local version_info + version_info="$(get_latest_version_info $azure_feed $channel $normalized_architecture false)" || return 1 + say_verbose "get_specific_version_from_version: version_info=$version_info" + echo "$version_info" | get_version_from_version_info + return 0 + ;; + coherent) + local version_info + version_info="$(get_latest_version_info $azure_feed $channel $normalized_architecture true)" || return 1 + say_verbose "get_specific_version_from_version: version_info=$version_info" + echo "$version_info" | get_version_from_version_info + return 0 + ;; + *) + echo $version + return 0 + ;; + esac +} + +# args: +# azure_feed - $1 +# channel - $2 +# normalized_architecture - $3 +# specific_version - $4 +construct_download_link() { + eval $invocation + + local azure_feed=$1 + local channel=$2 + local normalized_architecture=$3 + local specific_version=${4//[$'\t\r\n']} + + local osname + osname=$(get_current_os_name) || return 1 + + local download_link=null + if [ "$shared_runtime" = true ]; then + download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_version-$osname-$normalized_architecture.tar.gz" + else + download_link="$azure_feed/Sdk/$specific_version/dotnet-sdk-$specific_version-$osname-$normalized_architecture.tar.gz" + fi + + echo "$download_link" + return 0 +} + +# args: +# azure_feed - $1 +# channel - $2 +# normalized_architecture - $3 +# specific_version - $4 +construct_legacy_download_link() { + eval $invocation + + local azure_feed=$1 + local channel=$2 + local normalized_architecture=$3 + local specific_version=${4//[$'\t\r\n']} + + local distro_specific_osname + distro_specific_osname=$(get_distro_specific_os_name) || return 1 + + local legacy_download_link=null + if [ "$shared_runtime" = true ]; then + legacy_download_link="$azure_feed/Runtime/$specific_version/dotnet-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz" + else + legacy_download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz" + fi + + echo "$legacy_download_link" + return 0 +} + +get_user_install_path() { + eval $invocation + + if [ ! -z "${DOTNET_INSTALL_DIR:-}" ]; then + echo $DOTNET_INSTALL_DIR + else + echo "$HOME/.dotnet" + fi + return 0 +} + +# args: +# install_dir - $1 +resolve_installation_path() { + eval $invocation + + local install_dir=$1 + if [ "$install_dir" = "" ]; then + local user_install_path=$(get_user_install_path) + say_verbose "resolve_installation_path: user_install_path=$user_install_path" + echo "$user_install_path" + return 0 + fi + + echo "$install_dir" + return 0 +} + +# args: +# install_root - $1 +get_installed_version_info() { + eval $invocation + + local install_root=$1 + local version_file=$(combine_paths "$install_root" "$local_version_file_relative_path") + say_verbose "Local version file: $version_file" + if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then + local version_info="$(cat $version_file)" + echo "$version_info" + return 0 + fi + + say_verbose "Local version file not found." + return 0 +} + +# args: +# relative_or_absolute_path - $1 +get_absolute_path() { + eval $invocation + + local relative_or_absolute_path=$1 + echo $(cd $(dirname "$1") && pwd -P)/$(basename "$1") + return 0 +} + +# args: +# input_files - stdin +# root_path - $1 +# out_path - $2 +# override - $3 +copy_files_or_dirs_from_list() { + eval $invocation + + local root_path=$(remove_trailing_slash $1) + local out_path=$(remove_trailing_slash $2) + local override=$3 + local override_switch=$(if [ "$override" = false ]; then printf -- "-n"; fi) + + cat | uniq | while read -r file_path; do + local path=$(remove_beginning_slash ${file_path#$root_path}) + local target=$out_path/$path + if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then + mkdir -p $out_path/$(dirname $path) + cp -R $override_switch $root_path/$path $target + fi + done +} + +# args: +# zip_path - $1 +# out_path - $2 +extract_dotnet_package() { + eval $invocation + + local zip_path=$1 + local out_path=$2 + + local temp_out_path=$(mktemp -d $temporary_file_template) + + local failed=false + tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true + + local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/' + find $temp_out_path -type f | grep -Eo $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path false + find $temp_out_path -type f | grep -Ev $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path true + + rm -rf $temp_out_path + + if [ "$failed" = true ]; then + say_err "Extraction failed" + return 1 + fi +} + +# args: +# remote_path - $1 +# [out_path] - $2 - stdout if not provided +download() { + eval $invocation + + local remote_path=$1 + local out_path=${2:-} + + local failed=false + if machine_has "curl"; then + downloadcurl $remote_path $out_path || failed=true + elif machine_has "wget"; then + downloadwget $remote_path $out_path || failed=true + else + failed=true + fi + if [ "$failed" = true ]; then + say_verbose "Download failed: $remote_path" + return 1 + fi + return 0 +} + +downloadcurl() { + eval $invocation + local remote_path=$1 + local out_path=${2:-} + + local failed=false + if [ -z "$out_path" ]; then + curl --retry 10 -sSL -f --create-dirs $remote_path || failed=true + else + curl --retry 10 -sSL -f --create-dirs -o $out_path $remote_path || failed=true + fi + if [ "$failed" = true ]; then + say_verbose "Curl download failed" + return 1 + fi + return 0 +} + +downloadwget() { + eval $invocation + local remote_path=$1 + local out_path=${2:-} + + local failed=false + if [ -z "$out_path" ]; then + wget -q --tries 10 $remote_path || failed=true + else + wget -v --tries 10 -O $out_path $remote_path || failed=true + fi + if [ "$failed" = true ]; then + say_verbose "Wget download failed" + return 1 + fi + return 0 +} + +calculate_vars() { + eval $invocation + valid_legacy_download_link=true + + normalized_architecture=$(get_normalized_architecture_from_architecture "$architecture") + say_verbose "normalized_architecture=$normalized_architecture" + + specific_version=$(get_specific_version_from_version $azure_feed $channel $normalized_architecture $version) + say_verbose "specific_version=$specific_version" + if [ -z "$specific_version" ]; then + say_err "Could not get version information." + return 1 + fi + + download_link=$(construct_download_link $azure_feed $channel $normalized_architecture $specific_version) + say_verbose "download_link=$download_link" + + legacy_download_link=$(construct_legacy_download_link $azure_feed $channel $normalized_architecture $specific_version) || valid_legacy_download_link=false + + if [ "$valid_legacy_download_link" = true ]; then + say_verbose "legacy_download_link=$legacy_download_link" + else + say_verbose "Cound not construct a legacy_download_link; omitting..." + fi + + install_root=$(resolve_installation_path $install_dir) + say_verbose "install_root=$install_root" +} + +install_dotnet() { + eval $invocation + local download_failed=false + + if is_dotnet_package_installed $install_root "sdk" $specific_version; then + say ".NET SDK version $specific_version is already installed." + return 0 + fi + + mkdir -p $install_root + zip_path=$(mktemp $temporary_file_template) + say_verbose "Zip path: $zip_path" + + say "Downloading link: $download_link" + download "$download_link" $zip_path || download_failed=true + + # if the download fails, download the legacy_download_link + if [ "$download_failed" = true ] && [ "$valid_legacy_download_link" = true ]; then + say "Cannot download: $download_link" + download_link=$legacy_download_link + zip_path=$(mktemp $temporary_file_template) + say_verbose "Legacy zip path: $zip_path" + say "Downloading legacy link: $download_link" + download "$download_link" $zip_path + fi + + say "Extracting zip from $download_link" + extract_dotnet_package $zip_path $install_root + + return 0 +} + +local_version_file_relative_path="/.version" +bin_folder_relative_path="" +temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX" + +channel="LTS" +version="Latest" +install_dir="" +architecture="" +dry_run=false +no_path=false +azure_feed="https://dotnetcli.azureedge.net/dotnet" +uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet" +verbose=false +shared_runtime=false +runtime_id="" + +while [ $# -ne 0 ] +do + name=$1 + case $name in + -c|--channel|-[Cc]hannel) + shift + channel=$1 + ;; + -v|--version|-[Vv]ersion) + shift + version="$1" + ;; + -i|--install-dir|-[Ii]nstall[Dd]ir) + shift + install_dir="$1" + ;; + --arch|--architecture|-[Aa]rch|-[Aa]rchitecture) + shift + architecture="$1" + ;; + --shared-runtime|-[Ss]hared[Rr]untime) + shared_runtime=true + ;; + --dry-run|-[Dd]ry[Rr]un) + dry_run=true + ;; + --no-path|-[Nn]o[Pp]ath) + no_path=true + ;; + --verbose|-[Vv]erbose) + verbose=true + ;; + --azure-feed|-[Aa]zure[Ff]eed) + shift + azure_feed="$1" + ;; + --uncached-feed|-[Uu]ncached[Ff]eed) + shift + uncached_feed="$1" + ;; + --runtime-id|-[Rr]untime[Ii]d) + shift + runtime_id="$1" + ;; + -?|--?|-h|--help|-[Hh]elp) + script_name="$(basename $0)" + echo ".NET Tools Installer" + echo "Usage: $script_name [-c|--channel ] [-v|--version ] [-p|--prefix ]" + echo " $script_name -h|-?|--help" + echo "" + echo "$script_name is a simple command line interface for obtaining dotnet cli." + echo "" + echo "Options:" + echo " -c,--channel Download from the CHANNEL specified, Defaults to \`$channel\`." + echo " -Channel" + echo " Possible values:" + echo " - Current - most current release" + echo " - LTS - most current supported release" + echo " - 2-part version in a format A.B - represents a specific release" + echo " examples: 2.0; 1.0" + echo " - Branch name" + echo " examples: release/2.0.0; Master" + echo " -v,--version Use specific VERSION, Defaults to \`$version\`." + echo " -Version" + echo " Possible values:" + echo " - latest - most latest build on specific channel" + echo " - coherent - most latest coherent build on specific channel" + echo " coherent applies only to SDK downloads" + echo " - 3-part version in a format A.B.C - represents specific version of build" + echo " examples: 2.0.0-preview2-006120; 1.1.0" + echo " -i,--install-dir Install under specified location (see Install Location below)" + echo " -InstallDir" + echo " --architecture Architecture of .NET Tools. Currently only x64 is supported." + echo " --arch,-Architecture,-Arch" + echo " --shared-runtime Installs just the shared runtime bits, not the entire SDK." + echo " -SharedRuntime" + echo " --dry-run,-DryRun Do not perform installation. Display download link." + echo " --no-path, -NoPath Do not set PATH for the current process." + echo " --verbose,-Verbose Display diagnostics information." + echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user." + echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user." + echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)." + echo " -RuntimeId" + echo " -?,--?,-h,--help,-Help Shows this help message" + echo "" + echo "Install Location:" + echo " Location is chosen in following order:" + echo " - --install-dir option" + echo " - Environmental variable DOTNET_INSTALL_DIR" + echo " - $HOME/.dotnet" + exit 0 + ;; + *) + say_err "Unknown argument \`$name\`" + exit 1 + ;; + esac + + shift +done + +check_min_reqs +calculate_vars + +if [ "$dry_run" = true ]; then + say "Payload URL: $download_link" + if [ "$valid_legacy_download_link" = true ]; then + say "Legacy payload URL: $legacy_download_link" + fi + say "Repeatable invocation: ./$(basename $0) --version $specific_version --channel $channel --install-dir $install_dir" + exit 0 +fi + +check_pre_reqs +install_dotnet + +bin_path=$(get_absolute_path $(combine_paths $install_root $bin_folder_relative_path)) +if [ "$no_path" = false ]; then + say "Adding to current process PATH: \`$bin_path\`. Note: This change will be visible only when sourcing script." + export PATH=$bin_path:$PATH +else + say "Binaries of dotnet can be found in $bin_path" +fi + +say "Installation finished successfully." \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/icon.png b/Tasks/DotNetCoreInstallerV1/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3e954ccf8d2820a60f1fff71f900f2d222f7cdf3 GIT binary patch literal 14924 zcmeI3ZERCj7{?Ecz!+~sQHgx11r>z$_O|P~UfaT0fer1LV~d-JaCdvU-L1X1^xn~~ zF>yg9Xh2>SgpDogR0wK71_4C)AWQgwCSXJ~hPQyQ7=Z{5G)B*DyY{r}IAHjAnzVg- z&j0^B=l;%1@0a^lMftojd5`A-0LGM+x+~GQPJ8DLN1sYGdJ}z(43^d^0E~KAdk+Cy z+a>}~G*zssQENQUbAlW&@?N*QwDsn=_TlCQ*d1%k;!l9FJDC^8W~$goBelg;E6lAd65$R8V; zS74wY2B4%W$j4^&1sh~lRvP3%N+!DpEsW;G<4M-eI^IAaYiUKDvm7BvAkFGjs#=1O zsf3E$91`H1<>*o-XS;e;^ra>zEtA$W=-6RI9K@#e#BH&q5T79jx>l|v1bI~sRmrm7 z6<=i){Rnj>CEBX8>85&kL6kJE(;Q5uDK+D%e9+CS(4~0|CY!-rSjE~o*2)#wrkkvs z#e^k^D>HIrp(NNc954>`FqNOYq30Df%D0s0I#~l0ACN8 zpj7W*QjM50xvsbp*)NCCu%OH0V6ru1uGm`R$|ObQB>|SXU8un*ie9eBTU2NE*)0ZM zu$c@6&|)*#ZAEnk2#cVPFDw-7b!-fx$AjAkq;|_fv$kInslE4^8nX{by&xo_vyS&; z8g2CVTOv!E0i{Ys1+CB)Y~`Z$8#~Pw!e!~L{T+TWb}9w=kOH+m=hXLay5upIJf$>G zZ0~Zspq*zfLE940>tNDaQ^QI+6E^YxPGCGgW*@vpxB*Ic+feaTG1cHn6xpYS`4B9w zM{DBVc6&T;x-qkWgVFv0{9^i4#9Py6sDI54oKc5%uyJTLppo&hSwIVXKwGMETwkNj zs=qm=x0y}o#jx6E!isliT5Ioa#k(`DDQC4LsxEV)T1GSG(oWy_!LShBC_q=C)oQUi zn9Sx(M}-)H{u;N4cCezYOAD$L^JI2pHP#Mh#5xkj_*7wk>9LuNx1t*cbg#lBZ&uPL zIk^=caFDv92b>sBM~mPzh%v=QM1%_{E}RB2rnrcRZ~?`I(;&ta7ZDLIptx`v#F*kD zBEkg}7fyp1Q(QzuxPaoqX%J(Ii--spP+T|-VoY%n5#a)g3#UPhDJ~)+TtIQ*G>9?9 zMMQ)PC@!1^F{ZePh;RYLh0`F$6c-T@E}*z@8pN35A|k>C6c2p9G-wbpY=Ci@vV{ z&};&rcPRke762ZTH!L|e7l0w#%iP6Pk)M9s#7bs1|IM>2SLxf|om8{8>hjRy_pV&o z)z%sawO-2odc}dE&Nb7c*G8^epC71c+`0Lw<$EqH=xf?sH}9o0lkc>+PHeM+uX1h= zJNnL%1>oATzRQpN^G(<7kFOfGpY$C$E9|bhIkXtGm4D)BFE8j(oug(R_nOb251wo6 z?j3#ZYIyqG56AahWTpL!`W~Iy6>)VOc-i>(?xp*GUgqiuFK%1=$E2}f+=y8Z!CIFz zqHgu4JA02@$!(pTyE4Dj`~|G7od3SEVebzo?VFWr&UR%rYwp?d9avgjeWy+Nz5H}^ z#IA1t)|Hj>pXoBU_HBP+*w9XP<&+)WzSZlitH*?@~IY)o} zet6e}-h(|iBL41qO>1sN$ABND{Qyk6w76;GpV7nnzI`MA`k|f)CyWC*M}Y}UX?LI1GFb;-T(jq literal 0 HcmV?d00001 diff --git a/Tasks/DotNetCoreInstallerV1/icon.svg b/Tasks/DotNetCoreInstallerV1/icon.svg new file mode 100644 index 000000000000..f77ba27345c4 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/icon.svg @@ -0,0 +1,39 @@ + + + + Artboard Copy + Created with Sketch. + + + + + + + + + + + + + dotnet + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/make.json b/Tasks/DotNetCoreInstallerV1/make.json new file mode 100644 index 000000000000..3dc383b07c6a --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/make.json @@ -0,0 +1,8 @@ +{ + "cp": [ + { + "source": "externals", + "options": "-R" + } + ] +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/package-lock.json b/Tasks/DotNetCoreInstallerV1/package-lock.json new file mode 100644 index 000000000000..1de1c7a61380 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/package-lock.json @@ -0,0 +1,124 @@ +{ + "name": "dotnetcoreinstaller", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "mockery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mockery/-/mockery-1.7.0.tgz", + "integrity": "sha1-9O3g2HUMHJcnwnLqLGBiniyaHE8=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" + }, + "tunnel": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz", + "integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM=" + }, + "typed-rest-client": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.11.0.tgz", + "integrity": "sha1-DvQTUtYo7i4IePtYpniRZF9qG0E=", + "requires": { + "tunnel": "0.0.4", + "underscore": "1.8.3" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "vsts-task-lib": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vsts-task-lib/-/vsts-task-lib-2.0.6.tgz", + "integrity": "sha1-9sqGS3sDsS23N8nV/2kThGNpEFY=", + "requires": { + "minimatch": "3.0.4", + "mockery": "1.7.0", + "q": "1.5.1", + "semver": "5.4.1", + "shelljs": "0.3.0", + "uuid": "3.2.1" + } + }, + "vsts-task-tool-lib": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/vsts-task-tool-lib/-/vsts-task-tool-lib-0.4.1.tgz", + "integrity": "sha1-mYLTv14YS95SqpdCGJROEGJzRWU=", + "requires": { + "semver": "5.4.1", + "semver-compare": "1.0.0", + "typed-rest-client": "0.11.0", + "uuid": "3.2.1", + "vsts-task-lib": "2.2.1" + }, + "dependencies": { + "vsts-task-lib": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vsts-task-lib/-/vsts-task-lib-2.2.1.tgz", + "integrity": "sha512-FYllK73r1K7+sPUtWKZ4tihskJgpGB3YdNX4qr1YO0cmhFAWHm9FfEVxmKdlNeIyDtu3NyRb4wVUz0Gwi5LyGA==", + "requires": { + "minimatch": "3.0.4", + "mockery": "1.7.0", + "q": "1.5.1", + "semver": "5.4.1", + "shelljs": "0.3.0", + "uuid": "3.2.1" + } + } + } + } + } +} diff --git a/Tasks/DotNetCoreInstallerV1/package.json b/Tasks/DotNetCoreInstallerV1/package.json new file mode 100644 index 000000000000..ad44d05af7f2 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/package.json @@ -0,0 +1,30 @@ +{ + "name": "dotnetcoreinstaller", + "version": "0.1.0", + "description": ".Net Core Installer", + "main": "dotnetcoreinstaller.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Microsoft/azure-pipelines-tasks.git" + }, + "keywords": [ + "Azure", + "Pipelines", + "Tasks", + "DotNetCore" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Microsoft/azure-pipelines-tasks/issues" + }, + "homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme", + "dependencies": { + "vsts-task-lib": "2.0.6", + "vsts-task-tool-lib": "0.4.1", + "typed-rest-client": "0.11.0" + } +} diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index 00984d60a449..70d85853fe45 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -63,7 +63,7 @@ "name": "installationPath", "type": "string", "label": "Path To Install .Net Core", - "defaultValue": "$(Agent.ToolsDirectory)", + "defaultValue": "$(Agent.ToolsDirectory)/dotnet", "required": true, "groupName": "advanced", "helpMarkDown": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • Global installation path such as /usr/share/dotnet or C:\\Program Files\\Dotnet. This would cause the new version to be available machine-wide and be persisted. This requires that the agent process has permission on these folders
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version." diff --git a/Tasks/DotNetCoreInstallerV1/task.loc.json b/Tasks/DotNetCoreInstallerV1/task.loc.json new file mode 100644 index 000000000000..3e3a349626a1 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/task.loc.json @@ -0,0 +1,110 @@ +{ + "id": "B0CE7256-7898-45D3-9CB5-176B752BFEA6", + "name": "DotNetCoreInstaller", + "friendlyName": "ms-resource:loc.friendlyName", + "description": "ms-resource:loc.description", + "helpUrl": "", + "helpMarkDown": "ms-resource:loc.helpMarkDown", + "category": "Tool", + "runsOn": [ + "Agent", + "DeploymentGroup" + ], + "author": "Microsoft Corporation", + "version": { + "Major": 1, + "Minor": 0, + "Patch": 0 + }, + "preview": "true", + "satisfies": [ + "DotNetCore" + ], + "demands": [], + "releaseNotes": "ms-resource:loc.releaseNotes", + "instanceNameFormat": "ms-resource:loc.instanceNameFormat", + "groups": [ + { + "name": "advanced", + "displayName": "ms-resource:loc.group.displayName.advanced", + "isExpanded": true + } + ], + "inputs": [ + { + "name": "packageType", + "type": "pickList", + "label": "ms-resource:loc.input.label.packageType", + "defaultValue": "sdk", + "required": true, + "helpMarkDown": "ms-resource:loc.input.help.packageType", + "options": { + "runtime": "Runtime", + "sdk": "SDK (contains runtime)" + } + }, + { + "name": "version", + "type": "string", + "label": "ms-resource:loc.input.label.version", + "defaultValue": "2.2.x", + "required": true, + "helpMarkDown": "ms-resource:loc.input.help.version" + }, + { + "name": "includePreviewVersions", + "type": "boolean", + "label": "ms-resource:loc.input.label.includePreviewVersions", + "defaultValue": "false", + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.includePreviewVersions" + }, + { + "name": "installationPath", + "type": "string", + "label": "ms-resource:loc.input.label.installationPath", + "defaultValue": "$(Agent.ToolsDirectory)/dotnet", + "required": true, + "groupName": "advanced", + "helpMarkDown": "ms-resource:loc.input.help.installationPath" + }, + { + "name": "restrictMultiLevelLookup", + "type": "boolean", + "label": "ms-resource:loc.input.label.restrictMultiLevelLookup", + "groupName": "advanced", + "defaultValue": true, + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.restrictMultiLevelLookup" + } + ], + "execution": { + "Node": { + "target": "dotnetcoreinstaller.js" + } + }, + "messages": { + "ToolFailed": "ms-resource:loc.messages.ToolFailed", + "ImplicitVersionNotSupported": "ms-resource:loc.messages.ImplicitVersionNotSupported", + "getMachinePlatformFailed": "ms-resource:loc.messages.getMachinePlatformFailed", + "getDownloadUrlsFailed": "ms-resource:loc.messages.getDownloadUrlsFailed", + "UsingCachedTool": "ms-resource:loc.messages.UsingCachedTool", + "CheckingToolCache": "ms-resource:loc.messages.CheckingToolCache", + "InstallingAfresh": "ms-resource:loc.messages.InstallingAfresh", + "GettingDownloadUrl": "ms-resource:loc.messages.GettingDownloadUrl", + "CouldNotDetectPlatform": "ms-resource:loc.messages.CouldNotDetectPlatform", + "NullDownloadUrls": "ms-resource:loc.messages.NullDownloadUrls", + "DownloadingUrl": "ms-resource:loc.messages.DownloadingUrl", + "ExtractingPackage": "ms-resource:loc.messages.ExtractingPackage", + "CachingTool": "ms-resource:loc.messages.CachingTool", + "SuccessfullyInstalled": "ms-resource:loc.messages.SuccessfullyInstalled", + "ToolToInstall": "ms-resource:loc.messages.ToolToInstall", + "PrimaryPlatform": "ms-resource:loc.messages.PrimaryPlatform", + "LegacyPlatform": "ms-resource:loc.messages.LegacyPlatform", + "WarningVersionNotFound": "ms-resource:loc.messages.WarningVersionNotFound", + "CouldNotDownload": "ms-resource:loc.messages.CouldNotDownload", + "FailedToDownloadPackage": "ms-resource:loc.messages.FailedToDownloadPackage", + "PrependGlobalToolPath": "ms-resource:loc.messages.PrependGlobalToolPath", + "VersionsFileMalformed": "ms-resource:loc.messages.VersionsFileMalformed" + } +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/tsconfig.json b/Tasks/DotNetCoreInstallerV1/tsconfig.json new file mode 100644 index 000000000000..66a524cfc9e9 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "commonjs", + "sourceMap": true, + "sourceRoot": "C:\\github\\vsts-tasks\\tasks\\dotnetcoreinstaller\\" + } +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings.json b/Tasks/DotNetCoreInstallerV1/typings.json new file mode 100644 index 000000000000..d229810488e2 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings.json @@ -0,0 +1,9 @@ +{ + "name": "vsts-tasks-dotnetcoreinstaller", + "dependencies": {}, + "globalDependencies": { + "mocha": "registry:dt/mocha#2.2.5+20160720003353", + "node": "registry:dt/node#6.0.0+20160914131736", + "q": "registry:dt/q#0.0.0+20160613154756" + } +} diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts new file mode 100644 index 000000000000..be39944f1a3a --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts @@ -0,0 +1,202 @@ +// Generated by typings +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/a361a8ab3c327f208d3f82ad206971d4a63d8c25/mocha/mocha.d.ts +interface MochaSetupOptions { + //milliseconds to wait before considering a test slow + slow?: number; + + // timeout in milliseconds + timeout?: number; + + // ui name "bdd", "tdd", "exports" etc + ui?: string; + + //array of accepted globals + globals?: any[]; + + // reporter instance (function or string), defaults to `mocha.reporters.Spec` + reporter?: any; + + // bail on the first test failure + bail?: boolean; + + // ignore global leaks + ignoreLeaks?: boolean; + + // grep string or regexp to filter tests with + grep?: any; +} + +declare var mocha: Mocha; +declare var describe: Mocha.IContextDefinition; +declare var xdescribe: Mocha.IContextDefinition; +// alias for `describe` +declare var context: Mocha.IContextDefinition; +// alias for `describe` +declare var suite: Mocha.IContextDefinition; +declare var it: Mocha.ITestDefinition; +declare var xit: Mocha.ITestDefinition; +// alias for `it` +declare var test: Mocha.ITestDefinition; +declare var specify: Mocha.ITestDefinition; + +interface MochaDone { + (error?: any): any; +} + +interface ActionFunction { + (done: MochaDone): any | PromiseLike +} + +declare function setup(action: ActionFunction): void; +declare function teardown(action: ActionFunction): void; +declare function suiteSetup(action: ActionFunction): void; +declare function suiteTeardown(action: ActionFunction): void; +declare function before(action: ActionFunction): void; +declare function before(description: string, action: ActionFunction): void; +declare function after(action: ActionFunction): void; +declare function after(description: string, action: ActionFunction): void; +declare function beforeEach(action: ActionFunction): void; +declare function beforeEach(description: string, action: ActionFunction): void; +declare function afterEach(action: ActionFunction): void; +declare function afterEach(description: string, action: ActionFunction): void; + +declare class Mocha { + currentTest: Mocha.ITestDefinition; + constructor(options?: { + grep?: RegExp; + ui?: string; + reporter?: string; + timeout?: number; + bail?: boolean; + }); + + /** Setup mocha with the given options. */ + setup(options: MochaSetupOptions): Mocha; + bail(value?: boolean): Mocha; + addFile(file: string): Mocha; + /** Sets reporter by name, defaults to "spec". */ + reporter(name: string): Mocha; + /** Sets reporter constructor, defaults to mocha.reporters.Spec. */ + reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha; + ui(value: string): Mocha; + grep(value: string): Mocha; + grep(value: RegExp): Mocha; + invert(): Mocha; + ignoreLeaks(value: boolean): Mocha; + checkLeaks(): Mocha; + /** + * Function to allow assertion libraries to throw errors directly into mocha. + * This is useful when running tests in a browser because window.onerror will + * only receive the 'message' attribute of the Error. + */ + throwError(error: Error): void; + /** Enables growl support. */ + growl(): Mocha; + globals(value: string): Mocha; + globals(values: string[]): Mocha; + useColors(value: boolean): Mocha; + useInlineDiffs(value: boolean): Mocha; + timeout(value: number): Mocha; + slow(value: number): Mocha; + enableTimeouts(value: boolean): Mocha; + asyncOnly(value: boolean): Mocha; + noHighlighting(value: boolean): Mocha; + /** Runs tests and invokes `onComplete()` when finished. */ + run(onComplete?: (failures: number) => void): Mocha.IRunner; +} + +// merge the Mocha class declaration with a module +declare namespace Mocha { + /** Partial interface for Mocha's `Runnable` class. */ + interface IRunnable { + title: string; + fn: Function; + async: boolean; + sync: boolean; + timedOut: boolean; + } + + /** Partial interface for Mocha's `Suite` class. */ + interface ISuite { + parent: ISuite; + title: string; + + fullTitle(): string; + } + + /** Partial interface for Mocha's `Test` class. */ + interface ITest extends IRunnable { + parent: ISuite; + pending: boolean; + + fullTitle(): string; + } + + /** Partial interface for Mocha's `Runner` class. */ + interface IRunner {} + + interface IContextDefinition { + (description: string, spec: () => void): ISuite; + only(description: string, spec: () => void): ISuite; + skip(description: string, spec: () => void): void; + timeout(ms: number): void; + } + + interface ITestDefinition { + (expectation: string, assertion?: ActionFunction): ITest; + only(expectation: string, assertion?: ActionFunction): ITest; + skip(expectation: string, assertion?: ActionFunction): void; + timeout(ms: number): void; + state: "failed" | "passed"; + } + + export module reporters { + export class Base { + stats: { + suites: number; + tests: number; + passes: number; + pending: number; + failures: number; + }; + + constructor(runner: IRunner); + } + + export class Doc extends Base {} + export class Dot extends Base {} + export class HTML extends Base {} + export class HTMLCov extends Base {} + export class JSON extends Base {} + export class JSONCov extends Base {} + export class JSONStream extends Base {} + export class Landing extends Base {} + export class List extends Base {} + export class Markdown extends Base {} + export class Min extends Base {} + export class Nyan extends Base {} + export class Progress extends Base { + /** + * @param options.open String used to indicate the start of the progress bar. + * @param options.complete String used to indicate a complete test on the progress bar. + * @param options.incomplete String used to indicate an incomplete test on the progress bar. + * @param options.close String used to indicate the end of the progress bar. + */ + constructor(runner: IRunner, options?: { + open?: string; + complete?: string; + incomplete?: string; + close?: string; + }); + } + export class Spec extends Base {} + export class TAP extends Base {} + export class XUnit extends Base { + constructor(runner: IRunner, options?: any); + } + } +} + +declare module "mocha" { + export = Mocha; +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json b/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json new file mode 100644 index 000000000000..aab9d1c1302c --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json @@ -0,0 +1,8 @@ +{ + "resolution": "main", + "tree": { + "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/a361a8ab3c327f208d3f82ad206971d4a63d8c25/mocha/mocha.d.ts", + "raw": "registry:dt/mocha#2.2.5+20160720003353", + "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/a361a8ab3c327f208d3f82ad206971d4a63d8c25/mocha/mocha.d.ts" + } +} diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts new file mode 100644 index 000000000000..b66d17439524 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts @@ -0,0 +1,3084 @@ +// Generated by typings +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/3423aa94ffdbe8f4ded33733318e08020a2d6ca8/node/node.d.ts +interface Error { + stack?: string; +} + +interface ErrorConstructor { + captureStackTrace(targetObject: Object, constructorOpt?: Function): void; + stackTraceLimit: number; +} + +// compat for TypeScript 1.8 +// if you use with --target es3 or --target es5 and use below definitions, +// use the lib.es6.d.ts that is bundled with TypeScript 1.8. +interface MapConstructor { } +interface WeakMapConstructor { } +interface SetConstructor { } +interface WeakSetConstructor { } + +/************************************************ +* * +* GLOBAL * +* * +************************************************/ +declare var process: NodeJS.Process; +declare var global: NodeJS.Global; + +declare var __filename: string; +declare var __dirname: string; + +declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; +declare function clearTimeout(timeoutId: NodeJS.Timer): void; +declare function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; +declare function clearInterval(intervalId: NodeJS.Timer): void; +declare function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; +declare function clearImmediate(immediateId: any): void; + +interface NodeRequireFunction { + (id: string): any; +} + +interface NodeRequire extends NodeRequireFunction { + resolve(id: string): string; + cache: any; + extensions: any; + main: any; +} + +declare var require: NodeRequire; + +interface NodeModule { + exports: any; + require: NodeRequireFunction; + id: string; + filename: string; + loaded: boolean; + parent: any; + children: any[]; +} + +declare var module: NodeModule; + +// Same as module.exports +declare var exports: any; +declare var SlowBuffer: { + new (str: string, encoding?: string): Buffer; + new (size: number): Buffer; + new (size: Uint8Array): Buffer; + new (array: any[]): Buffer; + prototype: Buffer; + isBuffer(obj: any): boolean; + byteLength(string: string, encoding?: string): number; + concat(list: Buffer[], totalLength?: number): Buffer; +}; + + +// Buffer class +type BufferEncoding = "ascii" | "utf8" | "utf16le" | "ucs2" | "binary" | "hex"; +interface Buffer extends NodeBuffer { } + +/** + * Raw data is stored in instances of the Buffer class. + * A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized. + * Valid string encodings: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + */ +declare var Buffer: { + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + */ + new (str: string, encoding?: string): Buffer; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + */ + new (size: number): Buffer; + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + new (array: Uint8Array): Buffer; + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}. + * + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + */ + new (arrayBuffer: ArrayBuffer): Buffer; + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + new (array: any[]): Buffer; + /** + * Copies the passed {buffer} data onto a new {Buffer} instance. + * + * @param buffer The buffer to copy. + */ + new (buffer: Buffer): Buffer; + prototype: Buffer; + /** + * Allocates a new Buffer using an {array} of octets. + * + * @param array + */ + from(array: any[]): Buffer; + /** + * When passed a reference to the .buffer property of a TypedArray instance, + * the newly created Buffer will share the same allocated memory as the TypedArray. + * The optional {byteOffset} and {length} arguments specify a memory range + * within the {arrayBuffer} that will be shared by the Buffer. + * + * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() + * @param byteOffset + * @param length + */ + from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + /** + * Copies the passed {buffer} data onto a new Buffer instance. + * + * @param buffer + */ + from(buffer: Buffer): Buffer; + /** + * Creates a new Buffer containing the given JavaScript string {str}. + * If provided, the {encoding} parameter identifies the character encoding. + * If not provided, {encoding} defaults to 'utf8'. + * + * @param str + */ + from(str: string, encoding?: string): Buffer; + /** + * Returns true if {obj} is a Buffer + * + * @param obj object to test. + */ + isBuffer(obj: any): obj is Buffer; + /** + * Returns true if {encoding} is a valid encoding argument. + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + * + * @param encoding string to test. + */ + isEncoding(encoding: string): boolean; + /** + * Gives the actual byte length of a string. encoding defaults to 'utf8'. + * This is not the same as String.prototype.length since that returns the number of characters in a string. + * + * @param string string to test. + * @param encoding encoding used to evaluate (defaults to 'utf8') + */ + byteLength(string: string, encoding?: string): number; + /** + * Returns a buffer which is the result of concatenating all the buffers in the list together. + * + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. + * If the list has exactly one item, then the first item of the list is returned. + * If the list has more than one item, then a new Buffer is created. + * + * @param list An array of Buffer objects to concatenate + * @param totalLength Total length of the buffers when concatenated. + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. + */ + concat(list: Buffer[], totalLength?: number): Buffer; + /** + * The same as buf1.compare(buf2). + */ + compare(buf1: Buffer, buf2: Buffer): number; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @param fill if specified, buffer will be initialized by calling buf.fill(fill). + * If parameter is omitted, buffer will be filled with zeros. + * @param encoding encoding used for call to buf.fill while initalizing + */ + alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; + /** + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + allocUnsafe(size: number): Buffer; + /** + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + allocUnsafeSlow(size: number): Buffer; +}; + +/************************************************ +* * +* GLOBAL INTERFACES * +* * +************************************************/ +declare namespace NodeJS { + export interface ErrnoException extends Error { + errno?: string; + code?: string; + path?: string; + syscall?: string; + stack?: string; + } + + export class EventEmitter { + addListener(event: string, listener: Function): this; + on(event: string, listener: Function): this; + once(event: string, listener: Function): this; + removeListener(event: string, listener: Function): this; + removeAllListeners(event?: string): this; + setMaxListeners(n: number): this; + getMaxListeners(): number; + listeners(event: string): Function[]; + emit(event: string, ...args: any[]): boolean; + listenerCount(type: string): number; + // Added in Node 6... + prependListener(event: string, listener: Function): this; + prependOnceListener(event: string, listener: Function): this; + eventNames(): string[]; + } + + export interface ReadableStream extends EventEmitter { + readable: boolean; + read(size?: number): string | Buffer; + setEncoding(encoding: string): void; + pause(): ReadableStream; + resume(): ReadableStream; + pipe(destination: T, options?: { end?: boolean; }): T; + unpipe(destination?: T): void; + unshift(chunk: string): void; + unshift(chunk: Buffer): void; + wrap(oldStream: ReadableStream): ReadableStream; + } + + export interface WritableStream extends EventEmitter { + writable: boolean; + write(buffer: Buffer | string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + } + + export interface ReadWriteStream extends ReadableStream, WritableStream { + pause(): ReadWriteStream; + resume(): ReadWriteStream; + } + + export interface Events extends EventEmitter { } + + export interface Domain extends Events { + run(fn: Function): void; + add(emitter: Events): void; + remove(emitter: Events): void; + bind(cb: (err: Error, data: any) => any): any; + intercept(cb: (data: any) => any): any; + dispose(): void; + + addListener(event: string, listener: Function): this; + on(event: string, listener: Function): this; + once(event: string, listener: Function): this; + removeListener(event: string, listener: Function): this; + removeAllListeners(event?: string): this; + } + + export interface MemoryUsage { + rss: number; + heapTotal: number; + heapUsed: number; + } + + export interface ProcessVersions { + http_parser: string; + node: string; + v8: string; + ares: string; + uv: string; + zlib: string; + modules: string; + openssl: string; + } + + export interface Process extends EventEmitter { + stdout: WritableStream; + stderr: WritableStream; + stdin: ReadableStream; + argv: string[]; + execArgv: string[]; + execPath: string; + abort(): void; + chdir(directory: string): void; + cwd(): string; + env: any; + exit(code?: number): void; + exitCode: number; + getgid(): number; + setgid(id: number): void; + setgid(id: string): void; + getuid(): number; + setuid(id: number): void; + setuid(id: string): void; + version: string; + versions: ProcessVersions; + config: { + target_defaults: { + cflags: any[]; + default_configuration: string; + defines: string[]; + include_dirs: string[]; + libraries: string[]; + }; + variables: { + clang: number; + host_arch: string; + node_install_npm: boolean; + node_install_waf: boolean; + node_prefix: string; + node_shared_openssl: boolean; + node_shared_v8: boolean; + node_shared_zlib: boolean; + node_use_dtrace: boolean; + node_use_etw: boolean; + node_use_openssl: boolean; + target_arch: string; + v8_no_strict_aliasing: number; + v8_use_snapshot: boolean; + visibility: string; + }; + }; + kill(pid: number, signal?: string | number): void; + pid: number; + title: string; + arch: string; + platform: string; + memoryUsage(): MemoryUsage; + nextTick(callback: Function, ...args: any[]): void; + umask(mask?: number): number; + uptime(): number; + hrtime(time?: number[]): number[]; + domain: Domain; + + // Worker + send?(message: any, sendHandle?: any): void; + disconnect(): void; + connected: boolean; + } + + export interface Global { + Array: typeof Array; + ArrayBuffer: typeof ArrayBuffer; + Boolean: typeof Boolean; + Buffer: typeof Buffer; + DataView: typeof DataView; + Date: typeof Date; + Error: typeof Error; + EvalError: typeof EvalError; + Float32Array: typeof Float32Array; + Float64Array: typeof Float64Array; + Function: typeof Function; + GLOBAL: Global; + Infinity: typeof Infinity; + Int16Array: typeof Int16Array; + Int32Array: typeof Int32Array; + Int8Array: typeof Int8Array; + Intl: typeof Intl; + JSON: typeof JSON; + Map: MapConstructor; + Math: typeof Math; + NaN: typeof NaN; + Number: typeof Number; + Object: typeof Object; + Promise: Function; + RangeError: typeof RangeError; + ReferenceError: typeof ReferenceError; + RegExp: typeof RegExp; + Set: SetConstructor; + String: typeof String; + Symbol: Function; + SyntaxError: typeof SyntaxError; + TypeError: typeof TypeError; + URIError: typeof URIError; + Uint16Array: typeof Uint16Array; + Uint32Array: typeof Uint32Array; + Uint8Array: typeof Uint8Array; + Uint8ClampedArray: Function; + WeakMap: WeakMapConstructor; + WeakSet: WeakSetConstructor; + clearImmediate: (immediateId: any) => void; + clearInterval: (intervalId: NodeJS.Timer) => void; + clearTimeout: (timeoutId: NodeJS.Timer) => void; + console: typeof console; + decodeURI: typeof decodeURI; + decodeURIComponent: typeof decodeURIComponent; + encodeURI: typeof encodeURI; + encodeURIComponent: typeof encodeURIComponent; + escape: (str: string) => string; + eval: typeof eval; + global: Global; + isFinite: typeof isFinite; + isNaN: typeof isNaN; + parseFloat: typeof parseFloat; + parseInt: typeof parseInt; + process: Process; + root: Global; + setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => any; + setInterval: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; + setTimeout: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; + undefined: typeof undefined; + unescape: (str: string) => string; + gc: () => void; + v8debug?: any; + } + + export interface Timer { + ref(): void; + unref(): void; + } +} + +interface IterableIterator { } + +/** + * @deprecated + */ +interface NodeBuffer extends Uint8Array { + write(string: string, offset?: number, length?: number, encoding?: string): number; + toString(encoding?: string, start?: number, end?: number): string; + toJSON(): {type: 'Buffer', data: any[]}; + equals(otherBuffer: Buffer): boolean; + compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + slice(start?: number, end?: number): Buffer; + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readUInt8(offset: number, noAssert?: boolean): number; + readUInt16LE(offset: number, noAssert?: boolean): number; + readUInt16BE(offset: number, noAssert?: boolean): number; + readUInt32LE(offset: number, noAssert?: boolean): number; + readUInt32BE(offset: number, noAssert?: boolean): number; + readInt8(offset: number, noAssert?: boolean): number; + readInt16LE(offset: number, noAssert?: boolean): number; + readInt16BE(offset: number, noAssert?: boolean): number; + readInt32LE(offset: number, noAssert?: boolean): number; + readInt32BE(offset: number, noAssert?: boolean): number; + readFloatLE(offset: number, noAssert?: boolean): number; + readFloatBE(offset: number, noAssert?: boolean): number; + readDoubleLE(offset: number, noAssert?: boolean): number; + readDoubleBE(offset: number, noAssert?: boolean): number; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset: number, noAssert?: boolean): number; + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeInt8(value: number, offset: number, noAssert?: boolean): number; + writeInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeFloatLE(value: number, offset: number, noAssert?: boolean): number; + writeFloatBE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; + fill(value: any, offset?: number, end?: number): this; + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + entries(): IterableIterator<[number, number]>; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; + keys(): IterableIterator; + values(): IterableIterator; +} + +/************************************************ +* * +* MODULES * +* * +************************************************/ +declare module "buffer" { + export var INSPECT_MAX_BYTES: number; + var BuffType: typeof Buffer; + var SlowBuffType: typeof SlowBuffer; + export { BuffType as Buffer, SlowBuffType as SlowBuffer }; +} + +declare module "querystring" { + export interface StringifyOptions { + encodeURIComponent?: Function; + } + + export interface ParseOptions { + maxKeys?: number; + decodeURIComponent?: Function; + } + + export function stringify(obj: T, sep?: string, eq?: string, options?: StringifyOptions): string; + export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): any; + export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): T; + export function escape(str: string): string; + export function unescape(str: string): string; +} + +declare module "events" { + export class EventEmitter extends NodeJS.EventEmitter { + static EventEmitter: EventEmitter; + static listenerCount(emitter: EventEmitter, event: string): number; // deprecated + static defaultMaxListeners: number; + + addListener(event: string, listener: Function): this; + on(event: string, listener: Function): this; + once(event: string, listener: Function): this; + prependListener(event: string, listener: Function): this; + prependOnceListener(event: string, listener: Function): this; + removeListener(event: string, listener: Function): this; + removeAllListeners(event?: string): this; + setMaxListeners(n: number): this; + getMaxListeners(): number; + listeners(event: string): Function[]; + emit(event: string, ...args: any[]): boolean; + eventNames(): string[]; + listenerCount(type: string): number; + } +} + +declare module "http" { + import * as events from "events"; + import * as net from "net"; + import * as stream from "stream"; + + export interface RequestOptions { + protocol?: string; + host?: string; + hostname?: string; + family?: number; + port?: number; + localAddress?: string; + socketPath?: string; + method?: string; + path?: string; + headers?: { [key: string]: any }; + auth?: string; + agent?: Agent | boolean; + } + + export interface Server extends net.Server { + setTimeout(msecs: number, callback: Function): void; + maxHeadersCount: number; + timeout: number; + } + /** + * @deprecated Use IncomingMessage + */ + export interface ServerRequest extends IncomingMessage { + connection: net.Socket; + } + export interface ServerResponse extends stream.Writable { + // Extended base methods + write(buffer: Buffer): boolean; + write(buffer: Buffer, cb?: Function): boolean; + write(str: string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + write(str: string, encoding?: string, fd?: string): boolean; + + writeContinue(): void; + writeHead(statusCode: number, reasonPhrase?: string, headers?: any): void; + writeHead(statusCode: number, headers?: any): void; + statusCode: number; + statusMessage: string; + headersSent: boolean; + setHeader(name: string, value: string | string[]): void; + setTimeout(msecs: number, callback: Function): ServerResponse; + sendDate: boolean; + getHeader(name: string): string; + removeHeader(name: string): void; + write(chunk: any, encoding?: string): any; + addTrailers(headers: any): void; + finished: boolean; + + // Extended base methods + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + end(data?: any, encoding?: string): void; + } + export interface ClientRequest extends stream.Writable { + // Extended base methods + write(buffer: Buffer): boolean; + write(buffer: Buffer, cb?: Function): boolean; + write(str: string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + write(str: string, encoding?: string, fd?: string): boolean; + + write(chunk: any, encoding?: string): void; + abort(): void; + setTimeout(timeout: number, callback?: Function): void; + setNoDelay(noDelay?: boolean): void; + setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; + + setHeader(name: string, value: string | string[]): void; + getHeader(name: string): string; + removeHeader(name: string): void; + addTrailers(headers: any): void; + + // Extended base methods + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + end(data?: any, encoding?: string): void; + } + export interface IncomingMessage extends stream.Readable { + httpVersion: string; + httpVersionMajor: string; + httpVersionMinor: string; + connection: net.Socket; + headers: any; + rawHeaders: string[]; + trailers: any; + rawTrailers: any; + setTimeout(msecs: number, callback: Function): NodeJS.Timer; + /** + * Only valid for request obtained from http.Server. + */ + method?: string; + /** + * Only valid for request obtained from http.Server. + */ + url?: string; + /** + * Only valid for response obtained from http.ClientRequest. + */ + statusCode?: number; + /** + * Only valid for response obtained from http.ClientRequest. + */ + statusMessage?: string; + socket: net.Socket; + destroy(error?: Error): void; + } + /** + * @deprecated Use IncomingMessage + */ + export interface ClientResponse extends IncomingMessage { } + + export interface AgentOptions { + /** + * Keep sockets around in a pool to be used by other requests in the future. Default = false + */ + keepAlive?: boolean; + /** + * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000. + * Only relevant if keepAlive is set to true. + */ + keepAliveMsecs?: number; + /** + * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity + */ + maxSockets?: number; + /** + * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. + */ + maxFreeSockets?: number; + } + + export class Agent { + maxSockets: number; + sockets: any; + requests: any; + + constructor(opts?: AgentOptions); + + /** + * Destroy any sockets that are currently in use by the agent. + * It is usually not necessary to do this. However, if you are using an agent with KeepAlive enabled, + * then it is best to explicitly shut down the agent when you know that it will no longer be used. Otherwise, + * sockets may hang open for quite a long time before the server terminates them. + */ + destroy(): void; + } + + export var METHODS: string[]; + + export var STATUS_CODES: { + [errorCode: number]: string; + [errorCode: string]: string; + }; + export function createServer(requestListener?: (request: IncomingMessage, response: ServerResponse) => void): Server; + export function createClient(port?: number, host?: string): any; + export function request(options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; + export function get(options: any, callback?: (res: IncomingMessage) => void): ClientRequest; + export var globalAgent: Agent; +} + +declare module "cluster" { + import * as child from "child_process"; + import * as events from "events"; + + export interface ClusterSettings { + exec?: string; + args?: string[]; + silent?: boolean; + } + + export interface Address { + address: string; + port: number; + addressType: string; + } + + export class Worker extends events.EventEmitter { + id: string; + process: child.ChildProcess; + suicide: boolean; + send(message: any, sendHandle?: any): boolean; + kill(signal?: string): void; + destroy(signal?: string): void; + disconnect(): void; + isConnected(): boolean; + isDead(): boolean; + } + + export var settings: ClusterSettings; + export var isMaster: boolean; + export var isWorker: boolean; + export function setupMaster(settings?: ClusterSettings): void; + export function fork(env?: any): Worker; + export function disconnect(callback?: Function): void; + export var worker: Worker; + export var workers: { + [index: string]: Worker + }; + + // Event emitter + export function addListener(event: string, listener: Function): void; + export function on(event: "disconnect", listener: (worker: Worker) => void): void; + export function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): void; + export function on(event: "fork", listener: (worker: Worker) => void): void; + export function on(event: "listening", listener: (worker: Worker, address: any) => void): void; + export function on(event: "message", listener: (worker: Worker, message: any) => void): void; + export function on(event: "online", listener: (worker: Worker) => void): void; + export function on(event: "setup", listener: (settings: any) => void): void; + export function on(event: string, listener: Function): any; + export function once(event: string, listener: Function): void; + export function removeListener(event: string, listener: Function): void; + export function removeAllListeners(event?: string): void; + export function setMaxListeners(n: number): void; + export function listeners(event: string): Function[]; + export function emit(event: string, ...args: any[]): boolean; +} + +declare module "zlib" { + import * as stream from "stream"; + export interface ZlibOptions { chunkSize?: number; windowBits?: number; level?: number; memLevel?: number; strategy?: number; dictionary?: any; } + + export interface Gzip extends stream.Transform { } + export interface Gunzip extends stream.Transform { } + export interface Deflate extends stream.Transform { } + export interface Inflate extends stream.Transform { } + export interface DeflateRaw extends stream.Transform { } + export interface InflateRaw extends stream.Transform { } + export interface Unzip extends stream.Transform { } + + export function createGzip(options?: ZlibOptions): Gzip; + export function createGunzip(options?: ZlibOptions): Gunzip; + export function createDeflate(options?: ZlibOptions): Deflate; + export function createInflate(options?: ZlibOptions): Inflate; + export function createDeflateRaw(options?: ZlibOptions): DeflateRaw; + export function createInflateRaw(options?: ZlibOptions): InflateRaw; + export function createUnzip(options?: ZlibOptions): Unzip; + + export function deflate(buf: Buffer, callback: (error: Error, result: any) => void): void; + export function deflateSync(buf: Buffer, options?: ZlibOptions): any; + export function deflateRaw(buf: Buffer, callback: (error: Error, result: any) => void): void; + export function deflateRawSync(buf: Buffer, options?: ZlibOptions): any; + export function gzip(buf: Buffer, callback: (error: Error, result: any) => void): void; + export function gzipSync(buf: Buffer, options?: ZlibOptions): any; + export function gunzip(buf: Buffer, callback: (error: Error, result: any) => void): void; + export function gunzipSync(buf: Buffer, options?: ZlibOptions): any; + export function inflate(buf: Buffer, callback: (error: Error, result: any) => void): void; + export function inflateSync(buf: Buffer, options?: ZlibOptions): any; + export function inflateRaw(buf: Buffer, callback: (error: Error, result: any) => void): void; + export function inflateRawSync(buf: Buffer, options?: ZlibOptions): any; + export function unzip(buf: Buffer, callback: (error: Error, result: any) => void): void; + export function unzipSync(buf: Buffer, options?: ZlibOptions): any; + + // Constants + export var Z_NO_FLUSH: number; + export var Z_PARTIAL_FLUSH: number; + export var Z_SYNC_FLUSH: number; + export var Z_FULL_FLUSH: number; + export var Z_FINISH: number; + export var Z_BLOCK: number; + export var Z_TREES: number; + export var Z_OK: number; + export var Z_STREAM_END: number; + export var Z_NEED_DICT: number; + export var Z_ERRNO: number; + export var Z_STREAM_ERROR: number; + export var Z_DATA_ERROR: number; + export var Z_MEM_ERROR: number; + export var Z_BUF_ERROR: number; + export var Z_VERSION_ERROR: number; + export var Z_NO_COMPRESSION: number; + export var Z_BEST_SPEED: number; + export var Z_BEST_COMPRESSION: number; + export var Z_DEFAULT_COMPRESSION: number; + export var Z_FILTERED: number; + export var Z_HUFFMAN_ONLY: number; + export var Z_RLE: number; + export var Z_FIXED: number; + export var Z_DEFAULT_STRATEGY: number; + export var Z_BINARY: number; + export var Z_TEXT: number; + export var Z_ASCII: number; + export var Z_UNKNOWN: number; + export var Z_DEFLATED: number; + export var Z_NULL: number; +} + +declare module "os" { + export interface CpuInfo { + model: string; + speed: number; + times: { + user: number; + nice: number; + sys: number; + idle: number; + irq: number; + }; + } + + export interface NetworkInterfaceInfo { + address: string; + netmask: string; + family: string; + mac: string; + internal: boolean; + } + + export function hostname(): string; + export function loadavg(): number[]; + export function uptime(): number; + export function freemem(): number; + export function totalmem(): number; + export function cpus(): CpuInfo[]; + export function type(): string; + export function release(): string; + export function networkInterfaces(): { [index: string]: NetworkInterfaceInfo[] }; + export function homedir(): string; + export function userInfo(options?: { encoding: string }): { username: string, uid: number, gid: number, shell: any, homedir: string } + export var constants: { + UV_UDP_REUSEADDR: number, + errno: { + SIGHUP: number; + SIGINT: number; + SIGQUIT: number; + SIGILL: number; + SIGTRAP: number; + SIGABRT: number; + SIGIOT: number; + SIGBUS: number; + SIGFPE: number; + SIGKILL: number; + SIGUSR1: number; + SIGSEGV: number; + SIGUSR2: number; + SIGPIPE: number; + SIGALRM: number; + SIGTERM: number; + SIGCHLD: number; + SIGSTKFLT: number; + SIGCONT: number; + SIGSTOP: number; + SIGTSTP: number; + SIGTTIN: number; + SIGTTOU: number; + SIGURG: number; + SIGXCPU: number; + SIGXFSZ: number; + SIGVTALRM: number; + SIGPROF: number; + SIGWINCH: number; + SIGIO: number; + SIGPOLL: number; + SIGPWR: number; + SIGSYS: number; + SIGUNUSED: number; + }, + signals: { + E2BIG: number; + EACCES: number; + EADDRINUSE: number; + EADDRNOTAVAIL: number; + EAFNOSUPPORT: number; + EAGAIN: number; + EALREADY: number; + EBADF: number; + EBADMSG: number; + EBUSY: number; + ECANCELED: number; + ECHILD: number; + ECONNABORTED: number; + ECONNREFUSED: number; + ECONNRESET: number; + EDEADLK: number; + EDESTADDRREQ: number; + EDOM: number; + EDQUOT: number; + EEXIST: number; + EFAULT: number; + EFBIG: number; + EHOSTUNREACH: number; + EIDRM: number; + EILSEQ: number; + EINPROGRESS: number; + EINTR: number; + EINVAL: number; + EIO: number; + EISCONN: number; + EISDIR: number; + ELOOP: number; + EMFILE: number; + EMLINK: number; + EMSGSIZE: number; + EMULTIHOP: number; + ENAMETOOLONG: number; + ENETDOWN: number; + ENETRESET: number; + ENETUNREACH: number; + ENFILE: number; + ENOBUFS: number; + ENODATA: number; + ENODEV: number; + ENOENT: number; + ENOEXEC: number; + ENOLCK: number; + ENOLINK: number; + ENOMEM: number; + ENOMSG: number; + ENOPROTOOPT: number; + ENOSPC: number; + ENOSR: number; + ENOSTR: number; + ENOSYS: number; + ENOTCONN: number; + ENOTDIR: number; + ENOTEMPTY: number; + ENOTSOCK: number; + ENOTSUP: number; + ENOTTY: number; + ENXIO: number; + EOPNOTSUPP: number; + EOVERFLOW: number; + EPERM: number; + EPIPE: number; + EPROTO: number; + EPROTONOSUPPORT: number; + EPROTOTYPE: number; + ERANGE: number; + EROFS: number; + ESPIPE: number; + ESRCH: number; + ESTALE: number; + ETIME: number; + ETIMEDOUT: number; + ETXTBSY: number; + EWOULDBLOCK: number; + EXDEV: number; + }, + }; + export function arch(): string; + export function platform(): string; + export function tmpdir(): string; + export var EOL: string; + export function endianness(): "BE" | "LE"; +} + +declare module "https" { + import * as tls from "tls"; + import * as events from "events"; + import * as http from "http"; + + export interface ServerOptions { + pfx?: any; + key?: any; + passphrase?: string; + cert?: any; + ca?: any; + crl?: any; + ciphers?: string; + honorCipherOrder?: boolean; + requestCert?: boolean; + rejectUnauthorized?: boolean; + NPNProtocols?: any; + SNICallback?: (servername: string, cb: (err: Error, ctx: tls.SecureContext) => any) => any; + } + + export interface RequestOptions extends http.RequestOptions { + pfx?: any; + key?: any; + passphrase?: string; + cert?: any; + ca?: any; + ciphers?: string; + rejectUnauthorized?: boolean; + secureProtocol?: string; + } + + export interface Agent extends http.Agent { } + + export interface AgentOptions extends http.AgentOptions { + pfx?: any; + key?: any; + passphrase?: string; + cert?: any; + ca?: any; + ciphers?: string; + rejectUnauthorized?: boolean; + secureProtocol?: string; + maxCachedSessions?: number; + } + + export var Agent: { + new (options?: AgentOptions): Agent; + }; + export interface Server extends tls.Server { } + export function createServer(options: ServerOptions, requestListener?: Function): Server; + export function request(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + export function get(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; + export var globalAgent: Agent; +} + +declare module "punycode" { + export function decode(string: string): string; + export function encode(string: string): string; + export function toUnicode(domain: string): string; + export function toASCII(domain: string): string; + export var ucs2: ucs2; + interface ucs2 { + decode(string: string): number[]; + encode(codePoints: number[]): string; + } + export var version: any; +} + +declare module "repl" { + import * as stream from "stream"; + import * as readline from "readline"; + + export interface ReplOptions { + prompt?: string; + input?: NodeJS.ReadableStream; + output?: NodeJS.WritableStream; + terminal?: boolean; + eval?: Function; + useColors?: boolean; + useGlobal?: boolean; + ignoreUndefined?: boolean; + writer?: Function; + completer?: Function; + replMode?: any; + breakEvalOnSigint?: any; + } + + export interface REPLServer extends readline.ReadLine { + defineCommand(keyword: string, cmd: Function | { help: string, action: Function }): void; + displayPrompt(preserveCursor?: boolean): void + } + + export function start(options: ReplOptions): REPLServer; +} + +declare module "readline" { + import * as events from "events"; + import * as stream from "stream"; + + export interface Key { + sequence?: string; + name?: string; + ctrl?: boolean; + meta?: boolean; + shift?: boolean; + } + + export interface ReadLine extends events.EventEmitter { + setPrompt(prompt: string): void; + prompt(preserveCursor?: boolean): void; + question(query: string, callback: (answer: string) => void): void; + pause(): ReadLine; + resume(): ReadLine; + close(): void; + write(data: string | Buffer, key?: Key): void; + } + + export interface Completer { + (line: string): CompleterResult; + (line: string, callback: (err: any, result: CompleterResult) => void): any; + } + + export interface CompleterResult { + completions: string[]; + line: string; + } + + export interface ReadLineOptions { + input: NodeJS.ReadableStream; + output?: NodeJS.WritableStream; + completer?: Completer; + terminal?: boolean; + historySize?: number; + } + + export function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer, terminal?: boolean): ReadLine; + export function createInterface(options: ReadLineOptions): ReadLine; + + export function cursorTo(stream: NodeJS.WritableStream, x: number, y: number): void; + export function moveCursor(stream: NodeJS.WritableStream, dx: number | string, dy: number | string): void; + export function clearLine(stream: NodeJS.WritableStream, dir: number): void; + export function clearScreenDown(stream: NodeJS.WritableStream): void; +} + +declare module "vm" { + export interface Context { } + export interface ScriptOptions { + filename?: string; + lineOffset?: number; + columnOffset?: number; + displayErrors?: boolean; + timeout?: number; + cachedData?: Buffer; + produceCachedData?: boolean; + } + export interface RunningScriptOptions { + filename?: string; + lineOffset?: number; + columnOffset?: number; + displayErrors?: boolean; + timeout?: number; + } + export class Script { + constructor(code: string, options?: ScriptOptions); + runInContext(contextifiedSandbox: Context, options?: RunningScriptOptions): any; + runInNewContext(sandbox?: Context, options?: RunningScriptOptions): any; + runInThisContext(options?: RunningScriptOptions): any; + } + export function createContext(sandbox?: Context): Context; + export function isContext(sandbox: Context): boolean; + export function runInContext(code: string, contextifiedSandbox: Context, options?: RunningScriptOptions): any; + export function runInDebugContext(code: string): any; + export function runInNewContext(code: string, sandbox?: Context, options?: RunningScriptOptions): any; + export function runInThisContext(code: string, options?: RunningScriptOptions): any; +} + +declare module "child_process" { + import * as events from "events"; + import * as stream from "stream"; + + export interface ChildProcess extends events.EventEmitter { + stdin: stream.Writable; + stdout: stream.Readable; + stderr: stream.Readable; + stdio: [stream.Writable, stream.Readable, stream.Readable]; + pid: number; + kill(signal?: string): void; + send(message: any, sendHandle?: any): boolean; + connected: boolean; + disconnect(): void; + unref(): void; + ref(): void; + } + + export interface SpawnOptions { + cwd?: string; + env?: any; + stdio?: any; + detached?: boolean; + uid?: number; + gid?: number; + shell?: boolean | string; + } + export function spawn(command: string, args?: string[], options?: SpawnOptions): ChildProcess; + + export interface ExecOptions { + cwd?: string; + env?: any; + shell?: string; + timeout?: number; + maxBuffer?: number; + killSignal?: string; + uid?: number; + gid?: number; + } + export interface ExecOptionsWithStringEncoding extends ExecOptions { + encoding: BufferEncoding; + } + export interface ExecOptionsWithBufferEncoding extends ExecOptions { + encoding: string; // specify `null`. + } + export function exec(command: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function exec(command: string, options: ExecOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + // usage. child_process.exec("tsc", {encoding: null as string}, (err, stdout, stderr) => {}); + export function exec(command: string, options: ExecOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + export function exec(command: string, options: ExecOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + + export interface ExecFileOptions { + cwd?: string; + env?: any; + timeout?: number; + maxBuffer?: number; + killSignal?: string; + uid?: number; + gid?: number; + } + export interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { + encoding: BufferEncoding; + } + export interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { + encoding: string; // specify `null`. + } + export function execFile(file: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function execFile(file: string, options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + // usage. child_process.execFile("file.sh", {encoding: null as string}, (err, stdout, stderr) => {}); + export function execFile(file: string, options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + export function execFile(file: string, options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function execFile(file: string, args?: string[], callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + // usage. child_process.execFile("file.sh", ["foo"], {encoding: null as string}, (err, stdout, stderr) => {}); + export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; + export function execFile(file: string, args?: string[], options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; + + export interface ForkOptions { + cwd?: string; + env?: any; + execPath?: string; + execArgv?: string[]; + silent?: boolean; + uid?: number; + gid?: number; + } + export function fork(modulePath: string, args?: string[], options?: ForkOptions): ChildProcess; + + export interface SpawnSyncOptions { + cwd?: string; + input?: string | Buffer; + stdio?: any; + env?: any; + uid?: number; + gid?: number; + timeout?: number; + killSignal?: string; + maxBuffer?: number; + encoding?: string; + shell?: boolean | string; + } + export interface SpawnSyncOptionsWithStringEncoding extends SpawnSyncOptions { + encoding: BufferEncoding; + } + export interface SpawnSyncOptionsWithBufferEncoding extends SpawnSyncOptions { + encoding: string; // specify `null`. + } + export interface SpawnSyncReturns { + pid: number; + output: string[]; + stdout: T; + stderr: T; + status: number; + signal: string; + error: Error; + } + export function spawnSync(command: string): SpawnSyncReturns; + export function spawnSync(command: string, options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; + export function spawnSync(command: string, options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; + export function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns; + export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; + export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; + export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptions): SpawnSyncReturns; + + export interface ExecSyncOptions { + cwd?: string; + input?: string | Buffer; + stdio?: any; + env?: any; + shell?: string; + uid?: number; + gid?: number; + timeout?: number; + killSignal?: string; + maxBuffer?: number; + encoding?: string; + } + export interface ExecSyncOptionsWithStringEncoding extends ExecSyncOptions { + encoding: BufferEncoding; + } + export interface ExecSyncOptionsWithBufferEncoding extends ExecSyncOptions { + encoding: string; // specify `null`. + } + export function execSync(command: string): Buffer; + export function execSync(command: string, options?: ExecSyncOptionsWithStringEncoding): string; + export function execSync(command: string, options?: ExecSyncOptionsWithBufferEncoding): Buffer; + export function execSync(command: string, options?: ExecSyncOptions): Buffer; + + export interface ExecFileSyncOptions { + cwd?: string; + input?: string | Buffer; + stdio?: any; + env?: any; + uid?: number; + gid?: number; + timeout?: number; + killSignal?: string; + maxBuffer?: number; + encoding?: string; + } + export interface ExecFileSyncOptionsWithStringEncoding extends ExecFileSyncOptions { + encoding: BufferEncoding; + } + export interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { + encoding: string; // specify `null`. + } + export function execFileSync(command: string): Buffer; + export function execFileSync(command: string, options?: ExecFileSyncOptionsWithStringEncoding): string; + export function execFileSync(command: string, options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; + export function execFileSync(command: string, options?: ExecFileSyncOptions): Buffer; + export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithStringEncoding): string; + export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; + export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptions): Buffer; +} + +declare module "url" { + export interface Url { + href?: string; + protocol?: string; + auth?: string; + hostname?: string; + port?: string; + host?: string; + pathname?: string; + search?: string; + query?: string | any; + slashes?: boolean; + hash?: string; + path?: string; + } + + export function parse(urlStr: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): Url; + export function format(url: Url): string; + export function resolve(from: string, to: string): string; +} + +declare module "dns" { + export function lookup(domain: string, family: number, callback: (err: Error, address: string, family: number) => void): string; + export function lookup(domain: string, callback: (err: Error, address: string, family: number) => void): string; + export function resolve(domain: string, rrtype: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolve(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolve4(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolve6(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolveMx(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolveTxt(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolveSrv(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolveNs(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function resolveCname(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; + export function reverse(ip: string, callback: (err: Error, domains: string[]) => void): string[]; + + //Error codes + export var NODATA: string; + export var FORMERR: string; + export var SERVFAIL: string; + export var NOTFOUND: string; + export var NOTIMP: string; + export var REFUSED: string; + export var BADQUERY: string; + export var BADNAME: string; + export var BADFAMILY: string; + export var BADRESP: string; + export var CONNREFUSED: string; + export var TIMEOUT: string; + export var EOF: string; + export var FILE: string; + export var NOMEM: string; + export var DESTRUCTION: string; + export var BADSTR: string; + export var BADFLAGS: string; + export var NONAME: string; + export var BADHINTS: string; + export var NOTINITIALIZED: string; + export var LOADIPHLPAPI: string; + export var ADDRGETNETWORKPARAMS: string; + export var CANCELLED: string; +} + +declare module "net" { + import * as stream from "stream"; + + export interface Socket extends stream.Duplex { + // Extended base methods + write(buffer: Buffer): boolean; + write(buffer: Buffer, cb?: Function): boolean; + write(str: string, cb?: Function): boolean; + write(str: string, encoding?: string, cb?: Function): boolean; + write(str: string, encoding?: string, fd?: string): boolean; + + connect(port: number, host?: string, connectionListener?: Function): void; + connect(path: string, connectionListener?: Function): void; + bufferSize: number; + setEncoding(encoding?: string): void; + write(data: any, encoding?: string, callback?: Function): void; + destroy(): void; + pause(): Socket; + resume(): Socket; + setTimeout(timeout: number, callback?: Function): void; + setNoDelay(noDelay?: boolean): void; + setKeepAlive(enable?: boolean, initialDelay?: number): void; + address(): { port: number; family: string; address: string; }; + unref(): void; + ref(): void; + + remoteAddress: string; + remoteFamily: string; + remotePort: number; + localAddress: string; + localPort: number; + bytesRead: number; + bytesWritten: number; + + // Extended base methods + end(): void; + end(buffer: Buffer, cb?: Function): void; + end(str: string, cb?: Function): void; + end(str: string, encoding?: string, cb?: Function): void; + end(data?: any, encoding?: string): void; + } + + export var Socket: { + new (options?: { fd?: string; type?: string; allowHalfOpen?: boolean; }): Socket; + }; + + export interface ListenOptions { + port?: number; + host?: string; + backlog?: number; + path?: string; + exclusive?: boolean; + } + + export interface Server extends Socket { + listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function): Server; + listen(port: number, hostname?: string, listeningListener?: Function): Server; + listen(port: number, backlog?: number, listeningListener?: Function): Server; + listen(port: number, listeningListener?: Function): Server; + listen(path: string, backlog?: number, listeningListener?: Function): Server; + listen(path: string, listeningListener?: Function): Server; + listen(handle: any, backlog?: number, listeningListener?: Function): Server; + listen(handle: any, listeningListener?: Function): Server; + listen(options: ListenOptions, listeningListener?: Function): Server; + close(callback?: Function): Server; + address(): { port: number; family: string; address: string; }; + getConnections(cb: (error: Error, count: number) => void): void; + ref(): Server; + unref(): Server; + maxConnections: number; + connections: number; + } + export function createServer(connectionListener?: (socket: Socket) => void): Server; + export function createServer(options?: { allowHalfOpen?: boolean; }, connectionListener?: (socket: Socket) => void): Server; + export function connect(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; + export function connect(port: number, host?: string, connectionListener?: Function): Socket; + export function connect(path: string, connectionListener?: Function): Socket; + export function createConnection(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; + export function createConnection(port: number, host?: string, connectionListener?: Function): Socket; + export function createConnection(path: string, connectionListener?: Function): Socket; + export function isIP(input: string): number; + export function isIPv4(input: string): boolean; + export function isIPv6(input: string): boolean; +} + +declare module "dgram" { + import * as events from "events"; + + interface RemoteInfo { + address: string; + port: number; + size: number; + } + + interface AddressInfo { + address: string; + family: string; + port: number; + } + + interface BindOptions { + port: number; + address?: string; + exclusive?: boolean; + } + + interface SocketOptions { + type: "udp4" | "udp6"; + reuseAddr?: boolean; + } + + export function createSocket(type: string, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; + export function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; + + export interface Socket extends events.EventEmitter { + send(msg: Buffer | String | any[], port: number, address: string, callback?: (error: Error, bytes: number) => void): void; + send(msg: Buffer | String | any[], offset: number, length: number, port: number, address: string, callback?: (error: Error, bytes: number) => void): void; + bind(port?: number, address?: string, callback?: () => void): void; + bind(options: BindOptions, callback?: Function): void; + close(callback?: any): void; + address(): AddressInfo; + setBroadcast(flag: boolean): void; + setTTL(ttl: number): void; + setMulticastTTL(ttl: number): void; + setMulticastLoopback(flag: boolean): void; + addMembership(multicastAddress: string, multicastInterface?: string): void; + dropMembership(multicastAddress: string, multicastInterface?: string): void; + ref(): void; + unref(): void; + } +} + +declare module "fs" { + import * as stream from "stream"; + import * as events from "events"; + + interface Stats { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + dev: number; + ino: number; + mode: number; + nlink: number; + uid: number; + gid: number; + rdev: number; + size: number; + blksize: number; + blocks: number; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } + + interface FSWatcher extends events.EventEmitter { + close(): void; + } + + export interface ReadStream extends stream.Readable { + close(): void; + destroy(): void; + } + export interface WriteStream extends stream.Writable { + close(): void; + bytesWritten: number; + path: string | Buffer; + } + + /** + * Asynchronous rename. + * @param oldPath + * @param newPath + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + /** + * Synchronous rename + * @param oldPath + * @param newPath + */ + export function renameSync(oldPath: string, newPath: string): void; + export function truncate(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function truncate(path: string | Buffer, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function truncateSync(path: string | Buffer, len?: number): void; + export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function ftruncateSync(fd: number, len?: number): void; + export function chown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function chownSync(path: string | Buffer, uid: number, gid: number): void; + export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fchownSync(fd: number, uid: number, gid: number): void; + export function lchown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function lchownSync(path: string | Buffer, uid: number, gid: number): void; + export function chmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function chmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function chmodSync(path: string | Buffer, mode: number): void; + export function chmodSync(path: string | Buffer, mode: string): void; + export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fchmodSync(fd: number, mode: number): void; + export function fchmodSync(fd: number, mode: string): void; + export function lchmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function lchmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function lchmodSync(path: string | Buffer, mode: number): void; + export function lchmodSync(path: string | Buffer, mode: string): void; + export function stat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + export function lstat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + export function statSync(path: string | Buffer): Stats; + export function lstatSync(path: string | Buffer): Stats; + export function fstatSync(fd: number): Stats; + export function link(srcpath: string | Buffer, dstpath: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function linkSync(srcpath: string | Buffer, dstpath: string | Buffer): void; + export function symlink(srcpath: string | Buffer, dstpath: string | Buffer, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function symlinkSync(srcpath: string | Buffer, dstpath: string | Buffer, type?: string): void; + export function readlink(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void; + export function readlinkSync(path: string | Buffer): string; + export function realpath(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; + export function realpath(path: string | Buffer, cache: { [path: string]: string }, callback: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; + export function realpathSync(path: string | Buffer, cache?: { [path: string]: string }): string; + /* + * Asynchronous unlink - deletes the file specified in {path} + * + * @param path + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function unlink(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + /* + * Synchronous unlink - deletes the file specified in {path} + * + * @param path + */ + export function unlinkSync(path: string | Buffer): void; + /* + * Asynchronous rmdir - removes the directory specified in {path} + * + * @param path + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function rmdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + /* + * Synchronous rmdir - removes the directory specified in {path} + * + * @param path + */ + export function rmdirSync(path: string | Buffer): void; + /* + * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. + * + * @param path + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function mkdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; + /* + * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. + * + * @param path + * @param mode + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function mkdir(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + /* + * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. + * + * @param path + * @param mode + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function mkdir(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; + /* + * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. + * + * @param path + * @param mode + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function mkdirSync(path: string | Buffer, mode?: number): void; + /* + * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. + * + * @param path + * @param mode + * @param callback No arguments other than a possible exception are given to the completion callback. + */ + export function mkdirSync(path: string | Buffer, mode?: string): void; + /* + * Asynchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * + * @param prefix + * @param callback The created folder path is passed as a string to the callback's second parameter. + */ + export function mkdtemp(prefix: string, callback?: (err: NodeJS.ErrnoException, folder: string) => void): void; + /* + * Synchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * + * @param prefix + * @returns Returns the created folder path. + */ + export function mkdtempSync(prefix: string): string; + export function readdir(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, files: string[]) => void): void; + export function readdirSync(path: string | Buffer): string[]; + export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function closeSync(fd: number): void; + export function open(path: string | Buffer, flags: string | number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; + export function open(path: string | Buffer, flags: string | number, mode: number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; + export function openSync(path: string | Buffer, flags: string | number, mode?: number): number; + export function utimes(path: string | Buffer, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function utimes(path: string | Buffer, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function utimesSync(path: string | Buffer, atime: number, mtime: number): void; + export function utimesSync(path: string | Buffer, atime: Date, mtime: Date): void; + export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function futimesSync(fd: number, atime: number, mtime: number): void; + export function futimesSync(fd: number, atime: Date, mtime: Date): void; + export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; + export function fsyncSync(fd: number): void; + export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; + export function write(fd: number, buffer: Buffer, offset: number, length: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; + export function write(fd: number, data: any, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; + export function write(fd: number, data: any, offset: number, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; + export function write(fd: number, data: any, offset: number, encoding: string, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; + export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number; + export function writeSync(fd: number, data: any, position?: number, enconding?: string): number; + export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void; + export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; + /* + * Asynchronous readFile - Asynchronously reads the entire contents of a file. + * + * @param fileName + * @param encoding + * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. + */ + export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void; + /* + * Asynchronous readFile - Asynchronously reads the entire contents of a file. + * + * @param fileName + * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. + * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. + */ + export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void; + /* + * Asynchronous readFile - Asynchronously reads the entire contents of a file. + * + * @param fileName + * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. + * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. + */ + export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; + /* + * Asynchronous readFile - Asynchronously reads the entire contents of a file. + * + * @param fileName + * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. + */ + export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; + /* + * Synchronous readFile - Synchronously reads the entire contents of a file. + * + * @param fileName + * @param encoding + */ + export function readFileSync(filename: string, encoding: string): string; + /* + * Synchronous readFile - Synchronously reads the entire contents of a file. + * + * @param fileName + * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. + */ + export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string; + /* + * Synchronous readFile - Synchronously reads the entire contents of a file. + * + * @param fileName + * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. + */ + export function readFileSync(filename: string, options?: { flag?: string; }): Buffer; + export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; + export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; + export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; + export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; + export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; + export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; + export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; + export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void; + export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void; + export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void; + export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher; + export function watch(filename: string, encoding: string, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; + export function watch(filename: string, options: { persistent?: boolean; recursive?: boolean; encoding?: string }, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; + export function exists(path: string | Buffer, callback?: (exists: boolean) => void): void; + export function existsSync(path: string | Buffer): boolean; + + interface Constants { + /** Constant for fs.access(). File is visible to the calling process. */ + F_OK: number; + + /** Constant for fs.access(). File can be read by the calling process. */ + R_OK: number; + + /** Constant for fs.access(). File can be written by the calling process. */ + W_OK: number; + + /** Constant for fs.access(). File can be executed by the calling process. */ + X_OK: number; + } + + export const constants: Constants; + + /** Tests a user's permissions for the file specified by path. */ + export function access(path: string | Buffer, callback: (err: NodeJS.ErrnoException) => void): void; + export function access(path: string | Buffer, mode: number, callback: (err: NodeJS.ErrnoException) => void): void; + /** Synchronous version of fs.access. This throws if any accessibility checks fail, and does nothing otherwise. */ + export function accessSync(path: string | Buffer, mode?: number): void; + export function createReadStream(path: string | Buffer, options?: { + flags?: string; + encoding?: string; + fd?: number; + mode?: number; + autoClose?: boolean; + start?: number; + end?: number; + }): ReadStream; + export function createWriteStream(path: string | Buffer, options?: { + flags?: string; + encoding?: string; + fd?: number; + mode?: number; + }): WriteStream; + export function fdatasync(fd: number, callback: Function): void; + export function fdatasyncSync(fd: number): void; +} + +declare module "path" { + + /** + * A parsed path object generated by path.parse() or consumed by path.format(). + */ + export interface ParsedPath { + /** + * The root of the path such as '/' or 'c:\' + */ + root: string; + /** + * The full directory path such as '/home/user/dir' or 'c:\path\dir' + */ + dir: string; + /** + * The file name including extension (if any) such as 'index.html' + */ + base: string; + /** + * The file extension (if any) such as '.html' + */ + ext: string; + /** + * The file name without extension (if any) such as 'index' + */ + name: string; + } + + /** + * Normalize a string path, reducing '..' and '.' parts. + * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. + * + * @param p string path to normalize. + */ + export function normalize(p: string): string; + /** + * Join all arguments together and normalize the resulting path. + * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. + * + * @param paths string paths to join. + */ + export function join(...paths: any[]): string; + /** + * Join all arguments together and normalize the resulting path. + * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. + * + * @param paths string paths to join. + */ + export function join(...paths: string[]): string; + /** + * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. + * + * Starting from leftmost {from} paramter, resolves {to} to an absolute path. + * + * If {to} isn't already absolute, {from} arguments are prepended in right to left order, until an absolute path is found. If after using all {from} paths still no absolute path is found, the current working directory is used as well. The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory. + * + * @param pathSegments string paths to join. Non-string arguments are ignored. + */ + export function resolve(...pathSegments: any[]): string; + /** + * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. + * + * @param path path to test. + */ + export function isAbsolute(path: string): boolean; + /** + * Solve the relative path from {from} to {to}. + * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve. + * + * @param from + * @param to + */ + export function relative(from: string, to: string): string; + /** + * Return the directory name of a path. Similar to the Unix dirname command. + * + * @param p the path to evaluate. + */ + export function dirname(p: string): string; + /** + * Return the last portion of a path. Similar to the Unix basename command. + * Often used to extract the file name from a fully qualified path. + * + * @param p the path to evaluate. + * @param ext optionally, an extension to remove from the result. + */ + export function basename(p: string, ext?: string): string; + /** + * Return the extension of the path, from the last '.' to end of string in the last portion of the path. + * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string + * + * @param p the path to evaluate. + */ + export function extname(p: string): string; + /** + * The platform-specific file separator. '\\' or '/'. + */ + export var sep: string; + /** + * The platform-specific file delimiter. ';' or ':'. + */ + export var delimiter: string; + /** + * Returns an object from a path string - the opposite of format(). + * + * @param pathString path to evaluate. + */ + export function parse(pathString: string): ParsedPath; + /** + * Returns a path string from an object - the opposite of parse(). + * + * @param pathString path to evaluate. + */ + export function format(pathObject: ParsedPath): string; + + export module posix { + export function normalize(p: string): string; + export function join(...paths: any[]): string; + export function resolve(...pathSegments: any[]): string; + export function isAbsolute(p: string): boolean; + export function relative(from: string, to: string): string; + export function dirname(p: string): string; + export function basename(p: string, ext?: string): string; + export function extname(p: string): string; + export var sep: string; + export var delimiter: string; + export function parse(p: string): ParsedPath; + export function format(pP: ParsedPath): string; + } + + export module win32 { + export function normalize(p: string): string; + export function join(...paths: any[]): string; + export function resolve(...pathSegments: any[]): string; + export function isAbsolute(p: string): boolean; + export function relative(from: string, to: string): string; + export function dirname(p: string): string; + export function basename(p: string, ext?: string): string; + export function extname(p: string): string; + export var sep: string; + export var delimiter: string; + export function parse(p: string): ParsedPath; + export function format(pP: ParsedPath): string; + } +} + +declare module "string_decoder" { + export interface NodeStringDecoder { + write(buffer: Buffer): string; + end(buffer?: Buffer): string; + } + export var StringDecoder: { + new (encoding?: string): NodeStringDecoder; + }; +} + +declare module "tls" { + import * as crypto from "crypto"; + import * as net from "net"; + import * as stream from "stream"; + + var CLIENT_RENEG_LIMIT: number; + var CLIENT_RENEG_WINDOW: number; + + export interface Certificate { + /** + * Country code. + */ + C: string; + /** + * Street. + */ + ST: string; + /** + * Locality. + */ + L: string; + /** + * Organization. + */ + O: string; + /** + * Organizational unit. + */ + OU: string; + /** + * Common name. + */ + CN: string; + } + + export interface CipherNameAndProtocol { + /** + * The cipher name. + */ + name: string; + /** + * SSL/TLS protocol version. + */ + version: string; + } + + export class TLSSocket extends stream.Duplex { + /** + * Returns the bound address, the address family name and port of the underlying socket as reported by + * the operating system. + * @returns {any} - An object with three properties, e.g. { port: 12346, family: 'IPv4', address: '127.0.0.1' }. + */ + address(): { port: number; family: string; address: string }; + /** + * A boolean that is true if the peer certificate was signed by one of the specified CAs, otherwise false. + */ + authorized: boolean; + /** + * The reason why the peer's certificate has not been verified. + * This property becomes available only when tlsSocket.authorized === false. + */ + authorizationError: Error; + /** + * Static boolean value, always true. + * May be used to distinguish TLS sockets from regular ones. + */ + encrypted: boolean; + /** + * Returns an object representing the cipher name and the SSL/TLS protocol version of the current connection. + * @returns {CipherNameAndProtocol} - Returns an object representing the cipher name + * and the SSL/TLS protocol version of the current connection. + */ + getCipher(): CipherNameAndProtocol; + /** + * Returns an object representing the peer's certificate. + * The returned object has some properties corresponding to the field of the certificate. + * If detailed argument is true the full chain with issuer property will be returned, + * if false only the top certificate without issuer property. + * If the peer does not provide a certificate, it returns null or an empty object. + * @param {boolean} detailed - If true; the full chain with issuer property will be returned. + * @returns {any} - An object representing the peer's certificate. + */ + getPeerCertificate(detailed?: boolean): { + subject: Certificate; + issuerInfo: Certificate; + issuer: Certificate; + raw: any; + valid_from: string; + valid_to: string; + fingerprint: string; + serialNumber: string; + }; + /** + * Could be used to speed up handshake establishment when reconnecting to the server. + * @returns {any} - ASN.1 encoded TLS session or undefined if none was negotiated. + */ + getSession(): any; + /** + * NOTE: Works only with client TLS sockets. + * Useful only for debugging, for session reuse provide session option to tls.connect(). + * @returns {any} - TLS session ticket or undefined if none was negotiated. + */ + getTLSTicket(): any; + /** + * The string representation of the local IP address. + */ + localAddress: string; + /** + * The numeric representation of the local port. + */ + localPort: string; + /** + * The string representation of the remote IP address. + * For example, '74.125.127.100' or '2001:4860:a005::68'. + */ + remoteAddress: string; + /** + * The string representation of the remote IP family. 'IPv4' or 'IPv6'. + */ + remoteFamily: string; + /** + * The numeric representation of the remote port. For example, 443. + */ + remotePort: number; + /** + * Initiate TLS renegotiation process. + * + * NOTE: Can be used to request peer's certificate after the secure connection has been established. + * ANOTHER NOTE: When running as the server, socket will be destroyed with an error after handshakeTimeout timeout. + * @param {TlsOptions} options - The options may contain the following fields: rejectUnauthorized, + * requestCert (See tls.createServer() for details). + * @param {Function} callback - callback(err) will be executed with null as err, once the renegotiation + * is successfully completed. + */ + renegotiate(options: TlsOptions, callback: (err: Error) => any): any; + /** + * Set maximum TLS fragment size (default and maximum value is: 16384, minimum is: 512). + * Smaller fragment size decreases buffering latency on the client: large fragments are buffered by + * the TLS layer until the entire fragment is received and its integrity is verified; + * large fragments can span multiple roundtrips, and their processing can be delayed due to packet + * loss or reordering. However, smaller fragments add extra TLS framing bytes and CPU overhead, + * which may decrease overall server throughput. + * @param {number} size - TLS fragment size (default and maximum value is: 16384, minimum is: 512). + * @returns {boolean} - Returns true on success, false otherwise. + */ + setMaxSendFragment(size: number): boolean; + } + + export interface TlsOptions { + host?: string; + port?: number; + pfx?: string | Buffer[]; + key?: string | string[] | Buffer | any[]; + passphrase?: string; + cert?: string | string[] | Buffer | Buffer[]; + ca?: string | string[] | Buffer | Buffer[]; + crl?: string | string[]; + ciphers?: string; + honorCipherOrder?: boolean; + requestCert?: boolean; + rejectUnauthorized?: boolean; + NPNProtocols?: string[] | Buffer; + SNICallback?: (servername: string, cb: (err: Error, ctx: SecureContext) => any) => any; + ecdhCurve?: string; + dhparam?: string | Buffer; + handshakeTimeout?: number; + ALPNProtocols?: string[] | Buffer; + sessionTimeout?: number; + ticketKeys?: any; + sessionIdContext?: string; + secureProtocol?: string; + } + + export interface ConnectionOptions { + host?: string; + port?: number; + socket?: net.Socket; + pfx?: string | Buffer + key?: string | string[] | Buffer | Buffer[]; + passphrase?: string; + cert?: string | string[] | Buffer | Buffer[]; + ca?: string | Buffer | (string | Buffer)[]; + rejectUnauthorized?: boolean; + NPNProtocols?: (string | Buffer)[]; + servername?: string; + path?: string; + ALPNProtocols?: (string | Buffer)[]; + checkServerIdentity?: (servername: string, cert: string | Buffer | (string | Buffer)[]) => any; + secureProtocol?: string; + secureContext?: Object; + session?: Buffer; + minDHSize?: number; + } + + export interface Server extends net.Server { + close(): Server; + address(): { port: number; family: string; address: string; }; + addContext(hostName: string, credentials: { + key: string; + cert: string; + ca: string; + }): void; + maxConnections: number; + connections: number; + } + + export interface ClearTextStream extends stream.Duplex { + authorized: boolean; + authorizationError: Error; + getPeerCertificate(): any; + getCipher: { + name: string; + version: string; + }; + address: { + port: number; + family: string; + address: string; + }; + remoteAddress: string; + remotePort: number; + } + + export interface SecurePair { + encrypted: any; + cleartext: any; + } + + export interface SecureContextOptions { + pfx?: string | Buffer; + key?: string | Buffer; + passphrase?: string; + cert?: string | Buffer; + ca?: string | Buffer; + crl?: string | string[] + ciphers?: string; + honorCipherOrder?: boolean; + } + + export interface SecureContext { + context: any; + } + + export function createServer(options: TlsOptions, secureConnectionListener?: (cleartextStream: ClearTextStream) => void): Server; + export function connect(options: ConnectionOptions, secureConnectionListener?: () => void): ClearTextStream; + export function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () => void): ClearTextStream; + export function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () => void): ClearTextStream; + export function createSecurePair(credentials?: crypto.Credentials, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; + export function createSecureContext(details: SecureContextOptions): SecureContext; +} + +declare module "crypto" { + export interface Certificate { + exportChallenge(spkac: string | Buffer): Buffer; + exportPublicKey(spkac: string | Buffer): Buffer; + verifySpkac(spkac: Buffer): boolean; + } + export var Certificate: { + new (): Certificate; + (): Certificate; + } + + export var fips: boolean; + + export interface CredentialDetails { + pfx: string; + key: string; + passphrase: string; + cert: string; + ca: string | string[]; + crl: string | string[]; + ciphers: string; + } + export interface Credentials { context?: any; } + export function createCredentials(details: CredentialDetails): Credentials; + export function createHash(algorithm: string): Hash; + export function createHmac(algorithm: string, key: string | Buffer): Hmac; + + type Utf8AsciiLatin1Encoding = "utf8" | "ascii" | "latin1"; + type HexBase64Latin1Encoding = "latin1" | "hex" | "base64"; + type Utf8AsciiBinaryEncoding = "utf8" | "ascii" | "binary"; + type HexBase64BinaryEncoding = "binary" | "base64" | "hex"; + type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid"; + + export interface Hash extends NodeJS.ReadWriteStream { + update(data: string | Buffer): Hash; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hash; + digest(): Buffer; + digest(encoding: HexBase64Latin1Encoding): string; + } + export interface Hmac extends NodeJS.ReadWriteStream { + update(data: string | Buffer): Hmac; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hmac; + digest(): Buffer; + digest(encoding: HexBase64Latin1Encoding): string; + } + export function createCipher(algorithm: string, password: any): Cipher; + export function createCipheriv(algorithm: string, key: any, iv: any): Cipher; + export interface Cipher extends NodeJS.ReadWriteStream { + update(data: Buffer): Buffer; + update(data: string, input_encoding: Utf8AsciiBinaryEncoding): Buffer; + update(data: Buffer, input_encoding: any, output_encoding: HexBase64BinaryEncoding): string; + update(data: string, input_encoding: Utf8AsciiBinaryEncoding, output_encoding: HexBase64BinaryEncoding): string; + final(): Buffer; + final(output_encoding: string): string; + setAutoPadding(auto_padding?: boolean): void; + getAuthTag(): Buffer; + setAAD(buffer: Buffer): void; + } + export function createDecipher(algorithm: string, password: any): Decipher; + export function createDecipheriv(algorithm: string, key: any, iv: any): Decipher; + export interface Decipher extends NodeJS.ReadWriteStream { + update(data: Buffer): Buffer; + update(data: string, input_encoding: HexBase64BinaryEncoding): Buffer; + update(data: Buffer, input_encoding: any, output_encoding: Utf8AsciiBinaryEncoding): string; + update(data: string, input_encoding: HexBase64BinaryEncoding, output_encoding: Utf8AsciiBinaryEncoding): string; + final(): Buffer; + final(output_encoding: string): string; + setAutoPadding(auto_padding?: boolean): void; + setAuthTag(tag: Buffer): void; + setAAD(buffer: Buffer): void; + } + export function createSign(algorithm: string): Signer; + export interface Signer extends NodeJS.WritableStream { + update(data: string | Buffer): Signer; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Signer; + sign(private_key: string | { key: string; passphrase: string }): Buffer; + sign(private_key: string | { key: string; passphrase: string }, output_format: HexBase64Latin1Encoding): string; + } + export function createVerify(algorith: string): Verify; + export interface Verify extends NodeJS.WritableStream { + update(data: string | Buffer): Verify; + update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Verify; + verify(object: string, signature: Buffer): boolean; + verify(object: string, signature: string, signature_format: HexBase64Latin1Encoding): boolean; + } + export function createDiffieHellman(prime_length: number, generator?: number): DiffieHellman; + export function createDiffieHellman(prime: Buffer): DiffieHellman; + export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding): DiffieHellman; + export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: number | Buffer): DiffieHellman; + export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: string, generator_encoding: HexBase64Latin1Encoding): DiffieHellman; + export interface DiffieHellman { + generateKeys(): Buffer; + generateKeys(encoding: HexBase64Latin1Encoding): string; + computeSecret(other_public_key: Buffer): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; + getPrime(): Buffer; + getPrime(encoding: HexBase64Latin1Encoding): string; + getGenerator(): Buffer; + getGenerator(encoding: HexBase64Latin1Encoding): string; + getPublicKey(): Buffer; + getPublicKey(encoding: HexBase64Latin1Encoding): string; + getPrivateKey(): Buffer; + getPrivateKey(encoding: HexBase64Latin1Encoding): string; + setPublicKey(public_key: Buffer): void; + setPublicKey(public_key: string, encoding: string): void; + setPrivateKey(private_key: Buffer): void; + setPrivateKey(private_key: string, encoding: string): void; + verifyError: number; + } + export function getDiffieHellman(group_name: string): DiffieHellman; + export function pbkdf2(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string, callback: (err: Error, derivedKey: Buffer) => any): void; + export function pbkdf2Sync(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string): Buffer; + export function randomBytes(size: number): Buffer; + export function randomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; + export function pseudoRandomBytes(size: number): Buffer; + export function pseudoRandomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; + export interface RsaPublicKey { + key: string; + padding?: number; + } + export interface RsaPrivateKey { + key: string; + passphrase?: string, + padding?: number; + } + export function publicEncrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer + export function privateDecrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer + export function privateEncrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer + export function publicDecrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer + export function getCiphers(): string[]; + export function getCurves(): string[]; + export function getHashes(): string[]; + export interface ECDH { + generateKeys(): Buffer; + generateKeys(encoding: HexBase64Latin1Encoding): string; + generateKeys(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; + computeSecret(other_public_key: Buffer): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; + computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; + getPrivateKey(): Buffer; + getPrivateKey(encoding: HexBase64Latin1Encoding): string; + getPublicKey(): Buffer; + getPublicKey(encoding: HexBase64Latin1Encoding): string; + getPublicKey(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; + setPrivateKey(private_key: Buffer): void; + setPrivateKey(private_key: string, encoding: HexBase64Latin1Encoding): void; + } + export function createECDH(curve_name: string): ECDH; + export var DEFAULT_ENCODING: string; +} + +declare module "stream" { + import * as events from "events"; + + class internal extends events.EventEmitter { + pipe(destination: T, options?: { end?: boolean; }): T; + } + namespace internal { + + export class Stream extends internal { } + + export interface ReadableOptions { + highWaterMark?: number; + encoding?: string; + objectMode?: boolean; + read?: (size?: number) => any; + } + + export class Readable extends events.EventEmitter implements NodeJS.ReadableStream { + readable: boolean; + constructor(opts?: ReadableOptions); + _read(size: number): void; + read(size?: number): any; + setEncoding(encoding: string): void; + pause(): Readable; + resume(): Readable; + pipe(destination: T, options?: { end?: boolean; }): T; + unpipe(destination?: T): void; + unshift(chunk: any): void; + wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; + push(chunk: any, encoding?: string): boolean; + + /** + * Event emitter + * The defined events on documents including: + * 1. close + * 2. data + * 3. end + * 4. readable + * 5. error + **/ + addListener(event: string, listener: Function): this; + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "data", listener: (chunk: Buffer | string) => void): this; + addListener(event: "end", listener: () => void): this; + addListener(event: "readable", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + + emit(event: string, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "data", chunk: Buffer | string): boolean; + emit(event: "end"): boolean; + emit(event: "readable"): boolean; + emit(event: "error", err: Error): boolean; + + on(event: string, listener: Function): this; + on(event: "close", listener: () => void): this; + on(event: "data", listener: (chunk: Buffer | string) => void): this; + on(event: "end", listener: () => void): this; + on(event: "readable", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + + once(event: string, listener: Function): this; + once(event: "close", listener: () => void): this; + once(event: "data", listener: (chunk: Buffer | string) => void): this; + once(event: "end", listener: () => void): this; + once(event: "readable", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependListener(event: "end", listener: () => void): this; + prependListener(event: "readable", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; + prependOnceListener(event: "end", listener: () => void): this; + prependOnceListener(event: "readable", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + + removeListener(event: string, listener: Function): this; + removeListener(event: "close", listener: () => void): this; + removeListener(event: "data", listener: (chunk: Buffer | string) => void): this; + removeListener(event: "end", listener: () => void): this; + removeListener(event: "readable", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + } + + export interface WritableOptions { + highWaterMark?: number; + decodeStrings?: boolean; + objectMode?: boolean; + write?: (chunk: string | Buffer, encoding: string, callback: Function) => any; + writev?: (chunks: { chunk: string | Buffer, encoding: string }[], callback: Function) => any; + } + + export class Writable extends events.EventEmitter implements NodeJS.WritableStream { + writable: boolean; + constructor(opts?: WritableOptions); + _write(chunk: any, encoding: string, callback: Function): void; + write(chunk: any, cb?: Function): boolean; + write(chunk: any, encoding?: string, cb?: Function): boolean; + end(): void; + end(chunk: any, cb?: Function): void; + end(chunk: any, encoding?: string, cb?: Function): void; + + /** + * Event emitter + * The defined events on documents including: + * 1. close + * 2. drain + * 3. error + * 4. finish + * 5. pipe + * 6. unpipe + **/ + addListener(event: string, listener: Function): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "drain", listener: () => void): this; + addListener(event: "error", listener: (err: Error) => void): this; + addListener(event: "finish", listener: () => void): this; + addListener(event: "pipe", listener: (src: Readable) => void): this; + addListener(event: "unpipe", listener: (src: Readable) => void): this; + + emit(event: string, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "drain", chunk: Buffer | string): boolean; + emit(event: "error", err: Error): boolean; + emit(event: "finish"): boolean; + emit(event: "pipe", src: Readable): boolean; + emit(event: "unpipe", src: Readable): boolean; + + on(event: string, listener: Function): this; + on(event: "close", listener: () => void): this; + on(event: "drain", listener: () => void): this; + on(event: "error", listener: (err: Error) => void): this; + on(event: "finish", listener: () => void): this; + on(event: "pipe", listener: (src: Readable) => void): this; + on(event: "unpipe", listener: (src: Readable) => void): this; + + once(event: string, listener: Function): this; + once(event: "close", listener: () => void): this; + once(event: "drain", listener: () => void): this; + once(event: "error", listener: (err: Error) => void): this; + once(event: "finish", listener: () => void): this; + once(event: "pipe", listener: (src: Readable) => void): this; + once(event: "unpipe", listener: (src: Readable) => void): this; + + prependListener(event: string, listener: Function): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "drain", listener: () => void): this; + prependListener(event: "error", listener: (err: Error) => void): this; + prependListener(event: "finish", listener: () => void): this; + prependListener(event: "pipe", listener: (src: Readable) => void): this; + prependListener(event: "unpipe", listener: (src: Readable) => void): this; + + prependOnceListener(event: string, listener: Function): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "drain", listener: () => void): this; + prependOnceListener(event: "error", listener: (err: Error) => void): this; + prependOnceListener(event: "finish", listener: () => void): this; + prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; + prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; + + removeListener(event: string, listener: Function): this; + removeListener(event: "close", listener: () => void): this; + removeListener(event: "drain", listener: () => void): this; + removeListener(event: "error", listener: (err: Error) => void): this; + removeListener(event: "finish", listener: () => void): this; + removeListener(event: "pipe", listener: (src: Readable) => void): this; + removeListener(event: "unpipe", listener: (src: Readable) => void): this; + } + + export interface DuplexOptions extends ReadableOptions, WritableOptions { + allowHalfOpen?: boolean; + readableObjectMode?: boolean; + writableObjectMode?: boolean; + } + + // Note: Duplex extends both Readable and Writable. + export class Duplex extends Readable implements NodeJS.ReadWriteStream { + // Readable + pause(): Duplex; + resume(): Duplex; + // Writeable + writable: boolean; + constructor(opts?: DuplexOptions); + _write(chunk: any, encoding: string, callback: Function): void; + write(chunk: any, cb?: Function): boolean; + write(chunk: any, encoding?: string, cb?: Function): boolean; + end(): void; + end(chunk: any, cb?: Function): void; + end(chunk: any, encoding?: string, cb?: Function): void; + } + + export interface TransformOptions extends ReadableOptions, WritableOptions { + transform?: (chunk: string | Buffer, encoding: string, callback: Function) => any; + flush?: (callback: Function) => any; + } + + // Note: Transform lacks the _read and _write methods of Readable/Writable. + export class Transform extends events.EventEmitter implements NodeJS.ReadWriteStream { + readable: boolean; + writable: boolean; + constructor(opts?: TransformOptions); + _transform(chunk: any, encoding: string, callback: Function): void; + _flush(callback: Function): void; + read(size?: number): any; + setEncoding(encoding: string): void; + pause(): Transform; + resume(): Transform; + pipe(destination: T, options?: { end?: boolean; }): T; + unpipe(destination?: T): void; + unshift(chunk: any): void; + wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; + push(chunk: any, encoding?: string): boolean; + write(chunk: any, cb?: Function): boolean; + write(chunk: any, encoding?: string, cb?: Function): boolean; + end(): void; + end(chunk: any, cb?: Function): void; + end(chunk: any, encoding?: string, cb?: Function): void; + } + + export class PassThrough extends Transform { } + } + + export = internal; +} + +declare module "util" { + export interface InspectOptions { + showHidden?: boolean; + depth?: number; + colors?: boolean; + customInspect?: boolean; + } + + export function format(format: any, ...param: any[]): string; + export function debug(string: string): void; + export function error(...param: any[]): void; + export function puts(...param: any[]): void; + export function print(...param: any[]): void; + export function log(string: string): void; + export function inspect(object: any, showHidden?: boolean, depth?: number, color?: boolean): string; + export function inspect(object: any, options: InspectOptions): string; + export function isArray(object: any): boolean; + export function isRegExp(object: any): boolean; + export function isDate(object: any): boolean; + export function isError(object: any): boolean; + export function inherits(constructor: any, superConstructor: any): void; + export function debuglog(key: string): (msg: string, ...param: any[]) => void; + export function isBoolean(object: any): boolean; + export function isBuffer(object: any): boolean; + export function isFunction(object: any): boolean; + export function isNull(object: any): boolean; + export function isNullOrUndefined(object: any): boolean; + export function isNumber(object: any): boolean; + export function isObject(object: any): boolean; + export function isPrimitive(object: any): boolean; + export function isString(object: any): boolean; + export function isSymbol(object: any): boolean; + export function isUndefined(object: any): boolean; + export function deprecate(fn: Function, message: string): Function; +} + +declare module "assert" { + function internal(value: any, message?: string): void; + namespace internal { + export class AssertionError implements Error { + name: string; + message: string; + actual: any; + expected: any; + operator: string; + generatedMessage: boolean; + + constructor(options?: { + message?: string; actual?: any; expected?: any; + operator?: string; stackStartFunction?: Function + }); + } + + export function fail(actual: any, expected: any, message: string, operator: string): void; + export function ok(value: any, message?: string): void; + export function equal(actual: any, expected: any, message?: string): void; + export function notEqual(actual: any, expected: any, message?: string): void; + export function deepEqual(actual: any, expected: any, message?: string): void; + export function notDeepEqual(acutal: any, expected: any, message?: string): void; + export function strictEqual(actual: any, expected: any, message?: string): void; + export function notStrictEqual(actual: any, expected: any, message?: string): void; + export function deepStrictEqual(actual: any, expected: any, message?: string): void; + export function notDeepStrictEqual(actual: any, expected: any, message?: string): void; + export var throws: { + (block: Function, message?: string): void; + (block: Function, error: Function, message?: string): void; + (block: Function, error: RegExp, message?: string): void; + (block: Function, error: (err: any) => boolean, message?: string): void; + }; + + export var doesNotThrow: { + (block: Function, message?: string): void; + (block: Function, error: Function, message?: string): void; + (block: Function, error: RegExp, message?: string): void; + (block: Function, error: (err: any) => boolean, message?: string): void; + }; + + export function ifError(value: any): void; + } + + export = internal; +} + +declare module "tty" { + import * as net from "net"; + + export function isatty(fd: number): boolean; + export interface ReadStream extends net.Socket { + isRaw: boolean; + setRawMode(mode: boolean): void; + isTTY: boolean; + } + export interface WriteStream extends net.Socket { + columns: number; + rows: number; + isTTY: boolean; + } +} + +declare module "domain" { + import * as events from "events"; + + export class Domain extends events.EventEmitter implements NodeJS.Domain { + run(fn: Function): void; + add(emitter: events.EventEmitter): void; + remove(emitter: events.EventEmitter): void; + bind(cb: (err: Error, data: any) => any): any; + intercept(cb: (data: any) => any): any; + dispose(): void; + members: any[]; + enter(): void; + exit(): void; + } + + export function create(): Domain; +} + +declare module "constants" { + export var E2BIG: number; + export var EACCES: number; + export var EADDRINUSE: number; + export var EADDRNOTAVAIL: number; + export var EAFNOSUPPORT: number; + export var EAGAIN: number; + export var EALREADY: number; + export var EBADF: number; + export var EBADMSG: number; + export var EBUSY: number; + export var ECANCELED: number; + export var ECHILD: number; + export var ECONNABORTED: number; + export var ECONNREFUSED: number; + export var ECONNRESET: number; + export var EDEADLK: number; + export var EDESTADDRREQ: number; + export var EDOM: number; + export var EEXIST: number; + export var EFAULT: number; + export var EFBIG: number; + export var EHOSTUNREACH: number; + export var EIDRM: number; + export var EILSEQ: number; + export var EINPROGRESS: number; + export var EINTR: number; + export var EINVAL: number; + export var EIO: number; + export var EISCONN: number; + export var EISDIR: number; + export var ELOOP: number; + export var EMFILE: number; + export var EMLINK: number; + export var EMSGSIZE: number; + export var ENAMETOOLONG: number; + export var ENETDOWN: number; + export var ENETRESET: number; + export var ENETUNREACH: number; + export var ENFILE: number; + export var ENOBUFS: number; + export var ENODATA: number; + export var ENODEV: number; + export var ENOENT: number; + export var ENOEXEC: number; + export var ENOLCK: number; + export var ENOLINK: number; + export var ENOMEM: number; + export var ENOMSG: number; + export var ENOPROTOOPT: number; + export var ENOSPC: number; + export var ENOSR: number; + export var ENOSTR: number; + export var ENOSYS: number; + export var ENOTCONN: number; + export var ENOTDIR: number; + export var ENOTEMPTY: number; + export var ENOTSOCK: number; + export var ENOTSUP: number; + export var ENOTTY: number; + export var ENXIO: number; + export var EOPNOTSUPP: number; + export var EOVERFLOW: number; + export var EPERM: number; + export var EPIPE: number; + export var EPROTO: number; + export var EPROTONOSUPPORT: number; + export var EPROTOTYPE: number; + export var ERANGE: number; + export var EROFS: number; + export var ESPIPE: number; + export var ESRCH: number; + export var ETIME: number; + export var ETIMEDOUT: number; + export var ETXTBSY: number; + export var EWOULDBLOCK: number; + export var EXDEV: number; + export var WSAEINTR: number; + export var WSAEBADF: number; + export var WSAEACCES: number; + export var WSAEFAULT: number; + export var WSAEINVAL: number; + export var WSAEMFILE: number; + export var WSAEWOULDBLOCK: number; + export var WSAEINPROGRESS: number; + export var WSAEALREADY: number; + export var WSAENOTSOCK: number; + export var WSAEDESTADDRREQ: number; + export var WSAEMSGSIZE: number; + export var WSAEPROTOTYPE: number; + export var WSAENOPROTOOPT: number; + export var WSAEPROTONOSUPPORT: number; + export var WSAESOCKTNOSUPPORT: number; + export var WSAEOPNOTSUPP: number; + export var WSAEPFNOSUPPORT: number; + export var WSAEAFNOSUPPORT: number; + export var WSAEADDRINUSE: number; + export var WSAEADDRNOTAVAIL: number; + export var WSAENETDOWN: number; + export var WSAENETUNREACH: number; + export var WSAENETRESET: number; + export var WSAECONNABORTED: number; + export var WSAECONNRESET: number; + export var WSAENOBUFS: number; + export var WSAEISCONN: number; + export var WSAENOTCONN: number; + export var WSAESHUTDOWN: number; + export var WSAETOOMANYREFS: number; + export var WSAETIMEDOUT: number; + export var WSAECONNREFUSED: number; + export var WSAELOOP: number; + export var WSAENAMETOOLONG: number; + export var WSAEHOSTDOWN: number; + export var WSAEHOSTUNREACH: number; + export var WSAENOTEMPTY: number; + export var WSAEPROCLIM: number; + export var WSAEUSERS: number; + export var WSAEDQUOT: number; + export var WSAESTALE: number; + export var WSAEREMOTE: number; + export var WSASYSNOTREADY: number; + export var WSAVERNOTSUPPORTED: number; + export var WSANOTINITIALISED: number; + export var WSAEDISCON: number; + export var WSAENOMORE: number; + export var WSAECANCELLED: number; + export var WSAEINVALIDPROCTABLE: number; + export var WSAEINVALIDPROVIDER: number; + export var WSAEPROVIDERFAILEDINIT: number; + export var WSASYSCALLFAILURE: number; + export var WSASERVICE_NOT_FOUND: number; + export var WSATYPE_NOT_FOUND: number; + export var WSA_E_NO_MORE: number; + export var WSA_E_CANCELLED: number; + export var WSAEREFUSED: number; + export var SIGHUP: number; + export var SIGINT: number; + export var SIGILL: number; + export var SIGABRT: number; + export var SIGFPE: number; + export var SIGKILL: number; + export var SIGSEGV: number; + export var SIGTERM: number; + export var SIGBREAK: number; + export var SIGWINCH: number; + export var SSL_OP_ALL: number; + export var SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; + export var SSL_OP_CIPHER_SERVER_PREFERENCE: number; + export var SSL_OP_CISCO_ANYCONNECT: number; + export var SSL_OP_COOKIE_EXCHANGE: number; + export var SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; + export var SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; + export var SSL_OP_EPHEMERAL_RSA: number; + export var SSL_OP_LEGACY_SERVER_CONNECT: number; + export var SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number; + export var SSL_OP_MICROSOFT_SESS_ID_BUG: number; + export var SSL_OP_MSIE_SSLV2_RSA_PADDING: number; + export var SSL_OP_NETSCAPE_CA_DN_BUG: number; + export var SSL_OP_NETSCAPE_CHALLENGE_BUG: number; + export var SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number; + export var SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number; + export var SSL_OP_NO_COMPRESSION: number; + export var SSL_OP_NO_QUERY_MTU: number; + export var SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; + export var SSL_OP_NO_SSLv2: number; + export var SSL_OP_NO_SSLv3: number; + export var SSL_OP_NO_TICKET: number; + export var SSL_OP_NO_TLSv1: number; + export var SSL_OP_NO_TLSv1_1: number; + export var SSL_OP_NO_TLSv1_2: number; + export var SSL_OP_PKCS1_CHECK_1: number; + export var SSL_OP_PKCS1_CHECK_2: number; + export var SSL_OP_SINGLE_DH_USE: number; + export var SSL_OP_SINGLE_ECDH_USE: number; + export var SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number; + export var SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number; + export var SSL_OP_TLS_BLOCK_PADDING_BUG: number; + export var SSL_OP_TLS_D5_BUG: number; + export var SSL_OP_TLS_ROLLBACK_BUG: number; + export var ENGINE_METHOD_DSA: number; + export var ENGINE_METHOD_DH: number; + export var ENGINE_METHOD_RAND: number; + export var ENGINE_METHOD_ECDH: number; + export var ENGINE_METHOD_ECDSA: number; + export var ENGINE_METHOD_CIPHERS: number; + export var ENGINE_METHOD_DIGESTS: number; + export var ENGINE_METHOD_STORE: number; + export var ENGINE_METHOD_PKEY_METHS: number; + export var ENGINE_METHOD_PKEY_ASN1_METHS: number; + export var ENGINE_METHOD_ALL: number; + export var ENGINE_METHOD_NONE: number; + export var DH_CHECK_P_NOT_SAFE_PRIME: number; + export var DH_CHECK_P_NOT_PRIME: number; + export var DH_UNABLE_TO_CHECK_GENERATOR: number; + export var DH_NOT_SUITABLE_GENERATOR: number; + export var NPN_ENABLED: number; + export var RSA_PKCS1_PADDING: number; + export var RSA_SSLV23_PADDING: number; + export var RSA_NO_PADDING: number; + export var RSA_PKCS1_OAEP_PADDING: number; + export var RSA_X931_PADDING: number; + export var RSA_PKCS1_PSS_PADDING: number; + export var POINT_CONVERSION_COMPRESSED: number; + export var POINT_CONVERSION_UNCOMPRESSED: number; + export var POINT_CONVERSION_HYBRID: number; + export var O_RDONLY: number; + export var O_WRONLY: number; + export var O_RDWR: number; + export var S_IFMT: number; + export var S_IFREG: number; + export var S_IFDIR: number; + export var S_IFCHR: number; + export var S_IFBLK: number; + export var S_IFIFO: number; + export var S_IFSOCK: number; + export var S_IRWXU: number; + export var S_IRUSR: number; + export var S_IWUSR: number; + export var S_IXUSR: number; + export var S_IRWXG: number; + export var S_IRGRP: number; + export var S_IWGRP: number; + export var S_IXGRP: number; + export var S_IRWXO: number; + export var S_IROTH: number; + export var S_IWOTH: number; + export var S_IXOTH: number; + export var S_IFLNK: number; + export var O_CREAT: number; + export var O_EXCL: number; + export var O_NOCTTY: number; + export var O_DIRECTORY: number; + export var O_NOATIME: number; + export var O_NOFOLLOW: number; + export var O_SYNC: number; + export var O_SYMLINK: number; + export var O_DIRECT: number; + export var O_NONBLOCK: number; + export var O_TRUNC: number; + export var O_APPEND: number; + export var F_OK: number; + export var R_OK: number; + export var W_OK: number; + export var X_OK: number; + export var UV_UDP_REUSEADDR: number; + export var SIGQUIT: number; + export var SIGTRAP: number; + export var SIGIOT: number; + export var SIGBUS: number; + export var SIGUSR1: number; + export var SIGUSR2: number; + export var SIGPIPE: number; + export var SIGALRM: number; + export var SIGCHLD: number; + export var SIGSTKFLT: number; + export var SIGCONT: number; + export var SIGSTOP: number; + export var SIGTSTP: number; + export var SIGTTIN: number; + export var SIGTTOU: number; + export var SIGURG: number; + export var SIGXCPU: number; + export var SIGXFSZ: number; + export var SIGVTALRM: number; + export var SIGPROF: number; + export var SIGIO: number; + export var SIGPOLL: number; + export var SIGPWR: number; + export var SIGSYS: number; + export var SIGUNUSED: number; + export var defaultCoreCipherList: string; + export var defaultCipherList: string; + export var ENGINE_METHOD_RSA: number; + export var ALPN_ENABLED: number; +} + +declare module "process" { + export = process; +} + +declare module "v8" { + interface HeapSpaceInfo { + space_name: string; + space_size: number; + space_used_size: number; + space_available_size: number; + physical_space_size: number; + } + export function getHeapStatistics(): { total_heap_size: number, total_heap_size_executable: number, total_physical_size: number, total_avaialble_size: number, used_heap_size: number, heap_size_limit: number }; + export function getHeapSpaceStatistics(): HeapSpaceInfo[]; + export function setFlagsFromString(flags: string): void; +} + +declare module "timers" { + export function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; + export function clearTimeout(timeoutId: NodeJS.Timer): void; + export function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; + export function clearInterval(intervalId: NodeJS.Timer): void; + export function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; + export function clearImmediate(immediateId: any): void; +} + +declare module "console" { + export = console; +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json b/Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json new file mode 100644 index 000000000000..7b15c87df6f1 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json @@ -0,0 +1,8 @@ +{ + "resolution": "main", + "tree": { + "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/3423aa94ffdbe8f4ded33733318e08020a2d6ca8/node/node.d.ts", + "raw": "registry:dt/node#6.0.0+20160914131736", + "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/3423aa94ffdbe8f4ded33733318e08020a2d6ca8/node/node.d.ts" + } +} diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts new file mode 100644 index 000000000000..4449c31841ff --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts @@ -0,0 +1,357 @@ +// Generated by typings +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/623f30ab194a3486e014ca39bc7f2089897d6ce4/q/Q.d.ts +declare function Q(promise: Q.IPromise): Q.Promise; +/** + * If value is not a promise, returns a promise that is fulfilled with value. + */ +declare function Q(value: T): Q.Promise; + +declare namespace Q { + interface IPromise { + then(onFulfill?: (value: T) => U | IPromise, onReject?: (error: any) => U | IPromise): IPromise; + } + + interface Deferred { + promise: Promise; + resolve(value?: T): void; + resolve(value?: IPromise): void; + reject(reason: any): void; + notify(value: any): void; + makeNodeResolver(): (reason: any, value: T) => void; + } + + interface Promise { + /** + * Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object. + + * finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished. + */ + fin(finallyCallback: () => any): Promise; + /** + * Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object. + + * finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished. + */ + finally(finallyCallback: () => any): Promise; + + /** + * The then method from the Promises/A+ specification, with an additional progress handler. + */ + then(onFulfill?: (value: T) => U | IPromise, onReject?: (error: any) => U | IPromise, onProgress?: Function): Promise; + + /** + * Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason. + * + * This is especially useful in conjunction with all + */ + spread(onFulfill: (...args: any[]) => IPromise | U, onReject?: (reason: any) => IPromise | U): Promise; + + fail(onRejected: (reason: any) => U | IPromise): Promise; + + /** + * A sugar method, equivalent to promise.then(undefined, onRejected). + */ + catch(onRejected: (reason: any) => U | IPromise): Promise; + + /** + * A sugar method, equivalent to promise.then(undefined, undefined, onProgress). + */ + progress(onProgress: (progress: any) => any): Promise; + + /** + * Much like then, but with different behavior around unhandled rejection. If there is an unhandled rejection, either because promise is rejected and no onRejected callback was provided, or because onFulfilled or onRejected threw an error or returned a rejected promise, the resulting rejection reason is thrown as an exception in a future turn of the event loop. + * + * This method should be used to terminate chains of promises that will not be passed elsewhere. Since exceptions thrown in then callbacks are consumed and transformed into rejections, exceptions at the end of the chain are easy to accidentally, silently ignore. By arranging for the exception to be thrown in a future turn of the event loop, so that it won't be caught, it causes an onerror event on the browser window, or an uncaughtException event on Node.js's process object. + * + * Exceptions thrown by done will have long stack traces, if Q.longStackSupport is set to true. If Q.onerror is set, exceptions will be delivered there instead of thrown in a future turn. + * + * The Golden Rule of done vs. then usage is: either return your promise to someone else, or if the chain ends with you, call done to terminate it. + */ + done(onFulfilled?: (value: T) => any, onRejected?: (reason: any) => any, onProgress?: (progress: any) => any): void; + + /** + * If callback is a function, assumes it's a Node.js-style callback, and calls it as either callback(rejectionReason) when/if promise becomes rejected, or as callback(null, fulfillmentValue) when/if promise becomes fulfilled. If callback is not a function, simply returns promise. + */ + nodeify(callback: (reason: any, value: any) => void): Promise; + + /** + * Returns a promise to get the named property of an object. Essentially equivalent to + * + * promise.then(function (o) { + * return o[propertyName]; + * }); + */ + get(propertyName: String): Promise; + set(propertyName: String, value: any): Promise; + delete(propertyName: String): Promise; + /** + * Returns a promise for the result of calling the named method of an object with the given array of arguments. The object itself is this in the function, just like a synchronous method call. Essentially equivalent to + * + * promise.then(function (o) { + * return o[methodName].apply(o, args); + * }); + */ + post(methodName: String, args: any[]): Promise; + /** + * Returns a promise for the result of calling the named method of an object with the given variadic arguments. The object itself is this in the function, just like a synchronous method call. + */ + invoke(methodName: String, ...args: any[]): Promise; + fapply(args: any[]): Promise; + fcall(...args: any[]): Promise; + + /** + * Returns a promise for an array of the property names of an object. Essentially equivalent to + * + * promise.then(function (o) { + * return Object.keys(o); + * }); + */ + keys(): Promise; + + /** + * A sugar method, equivalent to promise.then(function () { return value; }). + */ + thenResolve(value: U): Promise; + /** + * A sugar method, equivalent to promise.then(function () { throw reason; }). + */ + thenReject(reason: any): Promise; + + /** + * Attaches a handler that will observe the value of the promise when it becomes fulfilled, returning a promise for that same value, perhaps deferred but not replaced by the promise returned by the onFulfilled handler. + */ + tap(onFulfilled: (value: T) => any): Promise; + + timeout(ms: number, message?: string): Promise; + /** + * Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed. + */ + delay(ms: number): Promise; + + /** + * Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true. + */ + isFulfilled(): boolean; + /** + * Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false. + */ + isRejected(): boolean; + /** + * Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false. + */ + isPending(): boolean; + + valueOf(): any; + + /** + * Returns a "state snapshot" object, which will be in one of three forms: + * + * - { state: "pending" } + * - { state: "fulfilled", value: } + * - { state: "rejected", reason: } + */ + inspect(): PromiseState; + } + + interface PromiseState { + /** + * "fulfilled", "rejected", "pending" + */ + state: string; + value?: T; + reason?: any; + } + + // If no value provided, returned promise will be of void type + export function when(): Promise; + + // if no fulfill, reject, or progress provided, returned promise will be of same type + export function when(value: T | IPromise): Promise; + + // If a non-promise value is provided, it will not reject or progress + export function when(value: T | IPromise, onFulfilled: (val: T) => U | IPromise, onRejected?: (reason: any) => U | IPromise, onProgress?: (progress: any) => any): Promise; + + /** + * Currently "impossible" (and I use the term loosely) to implement due to TypeScript limitations as it is now. + * See: https://github.com/Microsoft/TypeScript/issues/1784 for discussion on it. + */ + // export function try(method: Function, ...args: any[]): Promise; + + export function fbind(method: (...args: any[]) => T | IPromise, ...args: any[]): (...args: any[]) => Promise; + + export function fcall(method: (...args: any[]) => T, ...args: any[]): Promise; + + export function send(obj: any, functionName: string, ...args: any[]): Promise; + export function invoke(obj: any, functionName: string, ...args: any[]): Promise; + export function mcall(obj: any, functionName: string, ...args: any[]): Promise; + + export function denodeify(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise; + export function nbind(nodeFunction: Function, thisArg: any, ...args: any[]): (...args: any[]) => Promise; + export function nfbind(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise; + export function nfcall(nodeFunction: Function, ...args: any[]): Promise; + export function nfapply(nodeFunction: Function, args: any[]): Promise; + + export function ninvoke(nodeModule: any, functionName: string, ...args: any[]): Promise; + export function npost(nodeModule: any, functionName: string, args: any[]): Promise; + export function nsend(nodeModule: any, functionName: string, ...args: any[]): Promise; + export function nmcall(nodeModule: any, functionName: string, ...args: any[]): Promise; + + /** + * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. + */ + export function all(promises: [IPromise, IPromise, IPromise, IPromise, IPromise, IPromise]): Promise<[A, B, C, D, E, F]>; + /** + * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. + */ + export function all(promises: [IPromise, IPromise, IPromise, IPromise, IPromise]): Promise<[A, B, C, D, E]>; + /** + * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. + */ + export function all(promises: [IPromise, IPromise, IPromise, IPromise]): Promise<[A, B, C, D]>; + /** + * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. + */ + export function all(promises: [IPromise, IPromise, IPromise]): Promise<[A, B, C]>; + /** + * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. + */ + export function all(promises: [IPromise, IPromise]): Promise<[A, B]>; + /** + * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. + */ + export function all(promises: IPromise[]): Promise; + + /** + * Returns a promise for the first of an array of promises to become settled. + */ + export function race(promises: IPromise[]): Promise; + + /** + * Returns a promise that is fulfilled with an array of promise state snapshots, but only after all the original promises have settled, i.e. become either fulfilled or rejected. + */ + export function allSettled(promises: IPromise[]): Promise[]>; + + export function allResolved(promises: IPromise[]): Promise[]>; + + /** + * Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason. + * This is especially useful in conjunction with all. + */ + export function spread(promises: IPromise[], onFulfilled: (...args: T[]) => U | IPromise, onRejected?: (reason: any) => U | IPromise): Promise; + + /** + * Returns a promise that will have the same result as promise, except that if promise is not fulfilled or rejected before ms milliseconds, the returned promise will be rejected with an Error with the given message. If message is not supplied, the message will be "Timed out after " + ms + " ms". + */ + export function timeout(promise: Promise, ms: number, message?: string): Promise; + + /** + * Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed. + */ + export function delay(promise: Promise, ms: number): Promise; + /** + * Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed. + */ + export function delay(value: T, ms: number): Promise; + /** + * Returns a promise that will be fulfilled with undefined after at least ms milliseconds have passed. + */ + export function delay(ms: number): Promise ; + /** + * Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true. + */ + export function isFulfilled(promise: Promise): boolean; + /** + * Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false. + */ + export function isRejected(promise: Promise): boolean; + /** + * Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false. + */ + export function isPending(promise: Promise): boolean; + + /** + * Returns a "deferred" object with a: + * promise property + * resolve(value) method + * reject(reason) method + * notify(value) method + * makeNodeResolver() method + */ + export function defer(): Deferred; + + /** + * Returns a promise that is rejected with reason. + */ + export function reject(reason?: any): Promise; + + export function Promise(resolver: (resolve: (val: T | IPromise) => void , reject: (reason: any) => void , notify: (progress: any) => void ) => void ): Promise; + + /** + * Creates a new version of func that accepts any combination of promise and non-promise values, converting them to their fulfillment values before calling the original func. The returned version also always returns a promise: if func does a return or throw, then Q.promised(func) will return fulfilled or rejected promise, respectively. + * + * This can be useful for creating functions that accept either promises or non-promise values, and for ensuring that the function always returns a promise even in the face of unintentional thrown exceptions. + */ + export function promised(callback: (...args: any[]) => T): (...args: any[]) => Promise; + + /** + * Returns whether the given value is a Q promise. + */ + export function isPromise(object: any): boolean; + /** + * Returns whether the given value is a promise (i.e. it's an object with a then function). + */ + export function isPromiseAlike(object: any): boolean; + /** + * Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false. + */ + export function isPending(object: any): boolean; + /** + * If an object is not a promise, it is as "near" as possible. + * If a promise is rejected, it is as "near" as possible too. + * If it’s a fulfilled promise, the fulfillment value is nearer. + * If it’s a deferred promise and the deferred has been resolved, the + * resolution is "nearer". + */ + export function nearer(promise: Promise): T; + + /** + * This is an experimental tool for converting a generator function into a deferred function. This has the potential of reducing nested callbacks in engines that support yield. + */ + export function async(generatorFunction: any): (...args: any[]) => Promise; + export function nextTick(callback: Function): void; + + /** + * A settable property that will intercept any uncaught errors that would otherwise be thrown in the next tick of the event loop, usually as a result of done. Can be useful for getting the full stack trace of an error in browsers, which is not usually possible with window.onerror. + */ + export var onerror: (reason: any) => void; + /** + * A settable property that lets you turn on long stack trace support. If turned on, "stack jumps" will be tracked across asynchronous promise operations, so that if an uncaught error is thrown by done or a rejection reason's stack property is inspected in a rejection callback, a long stack trace is produced. + */ + export var longStackSupport: boolean; + + /** + * Calling resolve with a pending promise causes promise to wait on the passed promise, becoming fulfilled with its fulfillment value or rejected with its rejection reason (or staying pending forever, if the passed promise does). + * Calling resolve with a rejected promise causes promise to be rejected with the passed promise's rejection reason. + * Calling resolve with a fulfilled promise causes promise to be fulfilled with the passed promise's fulfillment value. + * Calling resolve with a non-promise value causes promise to be fulfilled with that value. + */ + export function resolve(object: IPromise): Promise; + /** + * Calling resolve with a pending promise causes promise to wait on the passed promise, becoming fulfilled with its fulfillment value or rejected with its rejection reason (or staying pending forever, if the passed promise does). + * Calling resolve with a rejected promise causes promise to be rejected with the passed promise's rejection reason. + * Calling resolve with a fulfilled promise causes promise to be fulfilled with the passed promise's fulfillment value. + * Calling resolve with a non-promise value causes promise to be fulfilled with that value. + */ + export function resolve(object: T): Promise; + + /** + * Resets the global "Q" variable to the value it has before Q was loaded. + * This will either be undefined if there was no version or the version of Q which was already loaded before. + * @returns { The last version of Q. } + */ + export function noConflict(): typeof Q; +} + +declare module "q" { + export = Q; +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json b/Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json new file mode 100644 index 000000000000..3d59355a87e8 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json @@ -0,0 +1,8 @@ +{ + "resolution": "main", + "tree": { + "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/623f30ab194a3486e014ca39bc7f2089897d6ce4/q/Q.d.ts", + "raw": "registry:dt/q#0.0.0+20160613154756", + "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/623f30ab194a3486e014ca39bc7f2089897d6ce4/q/Q.d.ts" + } +} diff --git a/Tasks/DotNetCoreInstallerV1/typings/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/index.d.ts new file mode 100644 index 000000000000..bbb3a42c2b21 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/typings/index.d.ts @@ -0,0 +1,3 @@ +/// +/// +/// diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts new file mode 100644 index 000000000000..6a94ff0be16c --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts @@ -0,0 +1,229 @@ +import * as os from 'os'; +import * as fs from 'fs'; +import * as path from 'path'; + +import * as tl from 'vsts-task-lib/task'; +import * as trm from 'vsts-task-lib/toolrunner'; +import * as toolLib from 'vsts-task-tool-lib'; + +import httpClient = require("typed-rest-client/HttpClient"); +import httpInterfaces = require("typed-rest-client/Interfaces"); +import { HttpClientResponse } from 'typed-rest-client/HttpClient'; + +import * as utils from "./versionUtilities"; + +export class DotNetCoreVersionFetcher { + constructor() { + let proxyUrl: string = tl.getVariable("agent.proxyurl"); + var requestOptions: httpInterfaces.IRequestOptions = proxyUrl ? { + proxy: { + proxyUrl: proxyUrl, + proxyUsername: tl.getVariable("agent.proxyusername"), + proxyPassword: tl.getVariable("agent.proxypassword"), + proxyBypassHosts: tl.getVariable("agent.proxybypasslist") ? JSON.parse(tl.getVariable("agent.proxybypasslist")) : null + } + } : {}; + + this.httpCallbackClient = new httpClient.HttpClient(tl.getVariable("AZURE_HTTP_USER_AGENT"), null, requestOptions); + } + + public async getVersionInfo(version: string, packageType: string, includePreviewVersions: boolean): Promise { + var requiredVersion: VersionInfo = null; + if (this.releasesIndex == null) { + await this.setReleasesIndex(); + } + + let channelInformation: any = this.getVersionChannel(version); + if (channelInformation) { + requiredVersion = await this.getVersionFromChannel(channelInformation, version, packageType, includePreviewVersions); + } + + if (!requiredVersion) { + throw tl.loc("VersionNotFound"); + } + + return requiredVersion; + } + + public getDownloadUrl(versionInfo: VersionInfo, packageType: string): string { + console.log(tl.loc("GettingDownloadUrl", packageType, versionInfo.version)); + + let osSuffixes = this.detectMachineOS(); + let downloadPackageInfoObject: any = versionInfo.files.find((downloadPackageInfo: any) => { + if (downloadPackageInfo.rid.toLowerCase() == osSuffixes[0].toLowerCase() + && (osSuffixes[0].split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip"))) { + return true; + } + + return false; + }); + + if (!!downloadPackageInfoObject && downloadPackageInfoObject.url) { + return downloadPackageInfoObject.url; + } + + return ""; + } + + private setReleasesIndex(): Promise { + return this.httpCallbackClient.get(DotNetCoreReleasesIndexUrl) + .then((response: HttpClientResponse) => { + return response.readBody(); + }) + .then((body: string) => { + this.releasesIndex = JSON.parse(body); + return this.releasesIndex; + }) + .catch((ex) => { + throw tl.loc(""); + }); + } + + private getVersionChannel(version: string): any { + let versionParts: any = utils.getVersionParts(version); + + let channelVersion = `${versionParts.majorVersion}.${versionParts.minorVersion}`; + if (versionParts.minorVersion == "x") { + var latestChannelVersion: string = `${versionParts.majorVersion}.0`; + this.releasesIndex["releases-index"].forEach(channel => { + if (utils.versionCompareFunction(channel["channel-version"], latestChannelVersion) > 0) { + latestChannelVersion = channel["channel-version"]; + } + }); + + channelVersion = latestChannelVersion; + } + + return this.releasesIndex["releases-index"].find(element => { + if (element["channel-version"] == channelVersion) { + return true + } + }); + } + + private getVersionFromChannel(channelInformation: any, version: string, packageType: string, includePreviewVersions: boolean): Promise { + let versionParts: any = utils.getVersionParts(version); + var releasesJsonUrl: string = channelInformation["releases.json"]; + var channelReleases: any = null; + + if (releasesJsonUrl) { + return this.httpCallbackClient.get(releasesJsonUrl) + .then((response: HttpClientResponse) => { + return response.readBody(); + }) + .then((body: string) => { + channelReleases = JSON.parse(body).releases; + if (versionParts.minorVersion == "x" || versionParts.patchVersion == "x") { + let dotNetSdkVersionTelemetry = `{"version":"${version}"}`; + console.log("##vso[telemetry.publish area=TaskDeploymentMethod;feature=DotNetCoreInstallerV1]" + dotNetSdkVersionTelemetry); + + let latestVersion = "0.0.0"; + channelReleases.forEach(release => { + if (release[packageType] && utils.versionCompareFunction(release[packageType].version, latestVersion) > 0 && (includePreviewVersions || !release[packageType].version.includes('preview'))) { + latestVersion = release[packageType].version; + } + }); + + if (latestVersion == "0.0.0") { + throw tl.loc("MatchingVersionNotFound", version); + } + + console.log(tl.loc("MatchingVersionForUserInputVersion", version, latestVersion)); + version = latestVersion; + } + + var versionRelease = channelReleases.find(release => { + if (release[packageType] && release[packageType].version == version) { + return true; + } + + return false; + }); + + return versionRelease ? versionRelease[packageType] : null; + }); + } + else { + throw tl.loc("UrlForReleaseChannelNotFound"); + } + } + + private detectMachineOS(): string[] { + let osSuffix = []; + let scriptRunner: trm.ToolRunner; + + try { + console.log(tl.loc("DetectingPlatform")); + if (tl.osType().match(/^Win/)) { + let escapedScript = path.join(this.getCurrentDir(), 'externals', 'get-os-platform.ps1').replace(/'/g, "''"); + let command = `& '${escapedScript}'` + + let powershellPath = tl.which('powershell', true); + scriptRunner = tl.tool(powershellPath) + .line('-NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command') + .arg(command); + } + else { + let scriptPath = path.join(this.getCurrentDir(), 'externals', 'get-os-distro.sh'); + this.setFileAttribute(scriptPath, "777"); + + scriptRunner = tl.tool(tl.which(scriptPath, true)); + } + + let result: trm.IExecSyncResult = scriptRunner.execSync(); + + if (result.code != 0) { + throw tl.loc("getMachinePlatformFailed", result.error ? result.error.message : result.stderr); + } + + let output: string = result.stdout; + + let index; + if ((index = output.indexOf("Primary:")) >= 0) { + let primary = output.substr(index + "Primary:".length).split(os.EOL)[0]; + osSuffix.push(primary); + console.log(tl.loc("PrimaryPlatform", primary)); + } + + if ((index = output.indexOf("Legacy:")) >= 0) { + let legacy = output.substr(index + "Legacy:".length).split(os.EOL)[0]; + osSuffix.push(legacy); + console.log(tl.loc("LegacyPlatform", legacy)); + } + + if (osSuffix.length == 0) { + throw tl.loc("CouldNotDetectPlatform"); + } + } + catch (ex) { + throw tl.loc("FailedInDetectingMachineArch", ex) + } + + return osSuffix; + } + + private setFileAttribute(file: string, mode: string): void { + fs.chmodSync(file, mode); + } + + private getCurrentDir(): string { + return __dirname; + } + + private releasesIndex: any; + private httpCallbackClient: httpClient.HttpClient; +} + +export class VersionInfo { + public version: string; + public files: VersionFilesData[]; +} + +export class VersionFilesData { + public name: string; + public url: string; + public rid: string; + public hash?: string; +} + +const DotNetCoreReleasesIndexUrl: string = "https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases-index.json"; \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts new file mode 100644 index 000000000000..20c29b00733d --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts @@ -0,0 +1,140 @@ +import * as path from 'path'; +import * as fs from "fs"; + +import * as tl from 'vsts-task-lib/task'; +import * as toolLib from 'vsts-task-tool-lib/tool'; + +import * as utils from "./versionUtilities"; + +export class VersionInstaller { + constructor(packageType: string, installationPath: string) { + try { + fs.existsSync(installationPath) || fs.mkdirSync(installationPath); + } + catch (ex) { + throw tl.loc("UnableToAccessPath", installationPath, ex); + } + + this.packageType = packageType; + this.installationPath = installationPath; + } + + public async downloadAndInstall(version: string, downloadUrl: string): Promise { + let downloadPath = ""; + + try { + downloadPath = await toolLib.downloadTool(downloadUrl); + } catch (error) { + tl.warning(tl.loc("CouldNotDownload", downloadUrl, JSON.stringify(error))); + } + + try { + //todo: if installation path is outside agents directory, acquire Lock for installation and start timer of 10-20 minutes, after which lock shall be auto released. + + //todo when lock work is done: Check if already installed + // this.isVersionInstalled(version); + + // Extract + console.log(tl.loc("ExtractingPackage", downloadPath)); + let extPath: string = tl.osType().match(/^Win/) ? await toolLib.extractZip(downloadPath) : await toolLib.extractTar(downloadPath); + + // Copy folders + console.log(tl.loc("InstallingDotNetVersion", version, this.installationPath)); + tl.debug(tl.loc("CopyingFoldersIntoPath", this.installationPath)); + var allEnteriesInDir: string[] = fs.readdirSync(extPath).map(name => path.join(extPath, name)); + var directoriesTobeCopied: string[] = allEnteriesInDir.filter(path => fs.lstatSync(path).isDirectory()); + directoriesTobeCopied.forEach((directoryPath) => { + tl.cp(directoryPath, this.installationPath, "-rf", false); + }); + + // Copy files + if (this.isLatestInstalledVersion(version)) { + tl.debug(tl.loc("CopyingFilesIntoPath", this.installationPath)); + var filesToBeCopied = allEnteriesInDir.filter(path => !fs.lstatSync(path).isDirectory()); + filesToBeCopied.forEach((filePath) => { + tl.cp(filePath, this.installationPath, "-f", false); + }); + } + + // Cache tool + this.createInstallationCompleteFile(version); + + console.log(tl.loc("SuccessfullyInstalled", this.packageType, version)); + } + catch (ex) { + throw tl.loc("FailedWhileInstallingVersionAtPath", version, this.installationPath, ex); + } + finally { + //todo: Release Lock and stop timer + } + + //todo: in case of failure due to: unable to acquire lock or timeout, 3 retries to install. + } + + public isVersionInstalled(version: string): boolean { + var isInstalled: boolean = false; + if (this.packageType == "sdk") { + isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "sdk", version)); + if (!(globalInstallationPaths.find(path => path == this.installationPath))) { + isInstalled = isInstalled && fs.existsSync(path.join(this.installationPath, "sdk", `${version}.complete`)); + } + } + else { + isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "host", "fxr", version)) + if (!(globalInstallationPaths.find(path => path == this.installationPath))) { + isInstalled = isInstalled && fs.existsSync(path.join(this.installationPath, "host", "fxr", `${version}.complete`)); + } + } + + isInstalled ? console.log(tl.loc("VersionFoundInToolCache")) : console.log(tl.loc("VersionNotFoundInToolCache", version)); + return isInstalled; + } + + private createInstallationCompleteFile(version: string): void { + tl.debug(tl.loc("CreatingInstallationCompeleteFile", version, this.packageType)); + if (!globalInstallationPaths.find(path => path == this.installationPath)) { + // always add for runtime as it is installed with SDK as well. + var pathToVersionCompleteFile = this.packageType == "sdk" ? path.join(this.installationPath, "sdk") : path.join(this.installationPath, "host", "fxr"); + fs.writeFileSync(path.join(pathToVersionCompleteFile, `${version}.complete`), `{ "version": "${version}" }`); + } + } + + private isLatestInstalledVersion(version: string): boolean { + var pathTobeChecked = this.packageType == "sdk" ? path.join(this.installationPath, "sdk") : path.join(this.installationPath, "host", "fxr"); + if (!fs.existsSync(pathTobeChecked)) { + throw tl.loc("PathNotFoundException", pathTobeChecked); + } + + var allEnteries: string[] = fs.readdirSync(pathTobeChecked).map(name => path.join(pathTobeChecked, name)); + var folderPaths: string[] = allEnteries.filter(element => fs.lstatSync(element).isDirectory()); + + var isLatest: boolean = folderPaths.findIndex(folderPath => utils.versionCompareFunction(path.basename(folderPath), version) > 0) < 0; + + if (!(globalInstallationPaths.find(path => path == this.installationPath))) { + var filePaths: string[] = allEnteries.filter(element => !fs.lstatSync(element).isDirectory()); + + isLatest = isLatest && filePaths.findIndex(filePath => utils.versionCompareFunction(this.getVersionCompleteFileName(path.basename(filePath)), version) > 0) < 0; + } + + isLatest ? tl.debug(tl.loc("VersionIsLocalLatest")) : tl.debug(tl.loc("VersionIsNotLocalLatest")); + return isLatest; + } + + private getVersionCompleteFileName(name: string): string { + var parts = name.split('.'); + return name.substr(0, name.length - (parts[parts.length - 1].length + 1)); + } + + + private packageType: string; + private installationPath: string; +} + +const globalInstallationPaths = [ + "C:/Program Files/dotnet", + "C:/Program Files (x86)/dotnet", + "C:\\Program Files\\dotnet", + "C:\\Program Files (x86)\\dotnet", + "/usr/local/share/dotnet", + "/usr/share/dotnet" +] \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts new file mode 100644 index 000000000000..95a1dec71617 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts @@ -0,0 +1,43 @@ +import * as tl from 'vsts-task-lib/task'; +import * as toolLib from 'vsts-task-tool-lib'; + +export function getVersionParts(version: string): { majorVersion: string, minorVersion: string, patchVersion: string } { + let versionParts: string[] = version.split('.'); + if (versionParts.length < 2) { + throw tl.loc("VersionNotAllowed", version) + } + + let majorVersion = versionParts[0]; + let minorVersion = versionParts[1]; + let patchVersion = ""; + if (minorVersion != "x" && versionParts.length > 2) { + patchVersion = versionParts[2]; + } + else { + throw tl.loc("VersionNotAllowed", version); + } + + return { "majorVersion": majorVersion, "minorVersion": minorVersion, "patchVersion": patchVersion }; +} + +export function versionCompareFunction(versionA: string, versionB: string): number { + if (!toolLib.isExplicitVersion(versionA) || !toolLib.isExplicitVersion(versionA)) { + console.log(tl.loc("ExplicitVersionRequiredForComparison", versionA, versionB)); + throw tl.loc("ExplicitVersionRequiredForComparison", versionA, versionB); + } + + var versionAParts = getVersionParts(versionA); + var versionBParts = getVersionParts(versionB); + + if (versionAParts.majorVersion != versionBParts.majorVersion) { + return versionAParts.majorVersion > versionBParts.majorVersion ? 1 : -1; + } + else if (versionAParts.minorVersion != versionBParts.minorVersion) { + return versionAParts.minorVersion > versionBParts.minorVersion ? 1 : -1; + } + else if (versionAParts.patchVersion != versionBParts.patchVersion) { + return versionAParts.patchVersion > versionBParts.patchVersion ? 1 : -1; + } + + return 0; +} \ No newline at end of file From 64d72d416bfff2d291c09c56df63ddbbb091bcd5 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Fri, 8 Mar 2019 16:04:06 +0530 Subject: [PATCH 04/17] Added fallback mechanism for version search. Resolved few comments --- .../resources.resjson/en-US/resources.resjson | 4 +- Tasks/DotNetCoreInstallerV1/Task Design.md | 39 +++++------ .../dotnetcoreinstaller.ts | 2 +- Tasks/DotNetCoreInstallerV1/task.json | 4 +- Tasks/DotNetCoreInstallerV1/versionFetcher.ts | 46 ++++++++++++- .../DotNetCoreInstallerV1/versionInstaller.ts | 66 ++++++++----------- 6 files changed, 94 insertions(+), 67 deletions(-) diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson index 38895bd1bdce..3a26a9db5e9a 100644 --- a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson @@ -12,9 +12,9 @@ "loc.input.label.includePreviewVersions": "Include Preview Versions", "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ingnored if you specify an exact version, such as: 2.1.403", "loc.input.label.installationPath": "Path To Install .Net Core", - "loc.input.help.installationPath": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • Global installation path such as /usr/share/dotnet or C:\\Program Files\\Dotnet. This would cause the new version to be available machine-wide and be persisted. This requires that the agent process has permission on these folders
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version.", + "loc.input.help.installationPath": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version.", "loc.input.label.restrictMultiLevelLookup": "Restrict Multi Level Lookup", - "loc.input.help.restrictMultiLevelLookup": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
    For MacOs:
    /usr/local/share/dotnet
    For Linux:
    /usr/share/dotnet

  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).", + "loc.input.help.restrictMultiLevelLookup": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    This is only applicable to Windows based agents.", "loc.messages.ToolFailed": "Tool install failed: %s", "loc.messages.ImplicitVersionNotSupported": "Version should be a valid and explicit version: %s", "loc.messages.getMachinePlatformFailed": "Failed to get machine platform details. Error: %s.", diff --git a/Tasks/DotNetCoreInstallerV1/Task Design.md b/Tasks/DotNetCoreInstallerV1/Task Design.md index ba77eec2bae9..2dc877f774d3 100644 --- a/Tasks/DotNetCoreInstallerV1/Task Design.md +++ b/Tasks/DotNetCoreInstallerV1/Task Design.md @@ -3,7 +3,7 @@ The task installs user specified version of .NET Core SDK/Runtime. This can be consumed to supply a particular version of .Net Core SDK/runtime to the subsequent tasks in pipeline. ### **A new major version of the task is created because of the following breaking changes:** -- **Installating multiple sdk/runtime versions side by side:** Users had asked for the feature where multiple versions of sdk/runtime can be installed and then be used in subsequent tasks in a pipeline.(one project may require multiple .Net Core sdks to build different applications), for more information about user's ask, [refer here](https://github.com/Microsoft/azure-pipelines-tasks/issues/8306). This is a breaking change, as previously the V0 task always provided only one version of sdk/runtime. +- **Installing multiple sdk/runtime versions side by side:** Users had asked for the feature where multiple versions of sdk/runtime can be installed and then be used in subsequent tasks in a pipeline.(one project may require multiple .Net Core sdks to build different applications), for more information about user's ask, [refer here](https://github.com/Microsoft/azure-pipelines-tasks/issues/8306). This is a breaking change, as previously the V0 task always provided only one version of sdk/runtime. ## New features added in V1 task: @@ -29,8 +29,8 @@ The correct version needs to be identified in case user enters pattern based ver - Numeric : we get the corresponding channel's (Major.Minor) releases.json link from `releasesIndex`. Then the releases.json is downloaded and parsed into an object: `channelInformation`. - NOTE: in case exact version is not found, the function logs error and task will fail. - x : in this case, we find the latest channel with `support-phase` != `preview` (unless `includePreviewVersions` is true). The releases.json for the selected channel is then downloaded and parsed into json object `releaseInformation`. - - The version with heighest `release.sdk/runtime.version` is then returned. (preview version will only be selected if `includePreviewVersions` is true) - - Empty: the function will log error as version needs to be given till atleast minor version. As a result the task will fail. + - The version with highest `release.sdk/runtime.version` is then returned. (preview version will only be selected if `includePreviewVersions` is true) + - Empty: the function will log error as version needs to be given till at least minor version. As a result the task will fail. - Based on Patch version value, the following can happen @@ -40,8 +40,8 @@ The correct version needs to be identified in case user enters pattern based ver - `version not found:` function logs error and task will fail. - x : The latest sdk/runtime version among all releases in that channel will be searched. The latest version information is then returned. -## **- Support for multiple versions to be installted side by side** -This feature was asked by users so that multiple versions can be installed using the task and they all will be available to subsequent tasks in pipeline. It is required in projects where multiple versions of SDK/runtime are required to build/run different applications. +## **- Support for multiple versions to be installed side by side** +This feature was asked by users so that multiple versions can be installed using the task and they all will be available to subsequent tasks in pipeline. It is required in applications where multiple versions of SDK/runtime are required to build/run different projects. Advantages of this feature: - User can build all applications in a project using a single build task and need not create different pipelines or add multiple build task. @@ -51,22 +51,22 @@ This feature is implemented, by asking user a new input: `installationPath`, the There are multiple benefits of asking `installationPath` from user: - User can choose to install a particular version in isolation of all other version already installed, by specifying a path which is cleaned up after each release/build. - User can augment existing set of versions installed with another version by specifying a path where a set of .Net core versions might already be installed, such as: $(Agent.ToolsDirectory) -- User can also install it at global .Net Core installation path, such as: C:\Program Files\dotnet or /usr/share/dotnet/. This way all agents running on that machine will have access to the newly added .Net core versions. +- User can also install it at any other location, such as: C:\user\username\temp. This will lead to changing the machine configuration and may affect all processes running on the machine. The way a version is installed at the `installationPath` is now as follows: - We extract all folders from dotnetVersions.zip/tgz into the `installationPath`, just like install-dotnet.ps1/sh. -- The files in root directory of archive are only copied/overriden if +- The files in root directory of archive are only copied/overridden if - The .Net core version being installed at `installationPath` is later than all other versions already installed at the path. The advantage of the above installation approach are: - Time is saved by not copying unneeded files. - Failures which might occur while overriding existing files are avoided. -Also to furhter optimize and save time while installation, we do not install a version if it is already cached at that path. Below described are different approaches to find out if a version is cached, +Also to further optimize and save time while installation, we do not install a version if it is already cached at that path. Below described are different approaches to find out if a version is cached, 1. **`Folder based approach`** - - `Installation process:` While installing a version, we will only extract the files from downloaded archive and then copy paste the files into the installationPath folder. - - `Caching process:` Existance of folder with name = version inside sdk or host/fxr folder will be considered as proof that sdk/runtime version is cached. Alogirthm to find if version is cached or not will be like this: + - `Installation process:` While installing a version, we will extract the files from downloaded archive and then copy paste the files into the installationPath folder. + - `Caching process:` Existence of folder with name = version inside sdk or host/fxr folder will be considered as proof that sdk/runtime version is cached. Algorithm to find if version is cached or not will be like this: - `installationPath` should contains a folder called `sdk or host/fxr`. If it - `exists:` check if sdk or host/fxr folder contains a folder with name = version to be downloaded. - `exists:` Version is cached, nothing more needs to be done. @@ -74,12 +74,11 @@ Also to furhter optimize and save time while installation, we do not install a v - `doesn't exist:` Version needs to be installed 2. **`version.completed file based approach`** - - `Installation process:` Once all the files are successfully extracted, copied and pasted into installationPath, we will create a **`version.completed`** file in sdk/runtime folder. The version.completed file will exist at the same level as the version folder and will be considered as a stamp of successfull installation. + - `Installation process:` Once all the files are successfully extracted, copied and pasted into installationPath, we will create a **`version.completed`** file in sdk/runtime folder. The version.completed file will exist at the same level as the version folder and will be considered as a stamp of successful installation. - If installation is not complete/successfull, we will not create the version.completed file. - `Caching Process:` So, the algorithm will be same as in Approach 1, but with an additional required check for `version.completed` file to be present in sdk or host/fxr folder along with folder with name = version. Based on version.completed's existance, the following will be concluded - `Exists`: version will be considered as cached - `Doesn't exist`: version will be installed. (overwriting if the files already exist) - - **optionally:** `Doesn't exist but installationPath is global .Net installation path`: in this case the version will be considered as cached even without the version.completed file. There are a few advantages of `version.completed` based approach over `folder only` based approach: @@ -87,24 +86,16 @@ There are a few advantages of `version.completed` based approach over `folder on ## **- Inbuilt option to restrict Multi-Level lookup** -This feature id introduced as users had asked for an option to disable Multi-Level lookup, to know more about user's ask, refer [here](https://github.com/Microsoft/azure-pipelines-tasks/issues/9608). +This feature is introduced as users had asked for an option to disable Multi-Level lookup, to know more about user's ask, refer [here](https://github.com/Microsoft/azure-pipelines-tasks/issues/9608). This is applicable to Windows based agents only. Multi-level lookup configures the .Net core host to probe several locations to find a suitable shared framework. If a folder is not found in folder containing dotnet.exe, it will attempt to look in pre-defined global locations using multi-level lookup. The default global locations are: **For Windows:** -- C:/Program Files/dotnet (64-bit processes) -- C:/Program Files (x86)/dotnet - - -**For MacOs:** -- /usr/local/share/dotnet - - -**For Linux:** -- /usr/share/dotnet +- C:/Program Files/dotnet (64-bit) +- C:/Program Files (x86)/dotnet (32-bit) It's value will be set as an environment variable: `DOTNET_MULTILEVEL_LOOKUP` with values - `0` : Disabled - `1` : Enabled -For more information on Multi-Level Lookup refer [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md). \ No newline at end of file +For more information on Multi-Level Lookup refer [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md). diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index 9449db919db7..ffd8590ee837 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -20,7 +20,7 @@ async function run() { let dotNetCoreInstaller = new VersionInstaller(packageType, installationPath); if (!dotNetCoreInstaller.isVersionInstalled(versionInfo.version)) { - await dotNetCoreInstaller.downloadAndInstall(versionInfo.version, versionFetcher.getDownloadUrl(versionInfo, packageType)); + await dotNetCoreInstaller.downloadAndInstall(versionInfo, versionFetcher.getDownloadUrl(versionInfo, packageType)); } // By default disable Multi Level Lookup unless user wants it enabled. diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index 70d85853fe45..afee53592eef 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -66,7 +66,7 @@ "defaultValue": "$(Agent.ToolsDirectory)/dotnet", "required": true, "groupName": "advanced", - "helpMarkDown": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • Global installation path such as /usr/share/dotnet or C:\\Program Files\\Dotnet. This would cause the new version to be available machine-wide and be persisted. This requires that the agent process has permission on these folders
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version." + "helpMarkDown": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version." }, { "name": "restrictMultiLevelLookup", @@ -75,7 +75,7 @@ "groupName": "advanced", "defaultValue": true, "required": false, - "helpMarkDown": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
    For MacOs:
    /usr/local/share/dotnet
    For Linux:
    /usr/share/dotnet

  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md)." + "helpMarkDown": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    This is only applicable to Windows based agents." } ], "execution": { diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts index 6a94ff0be16c..d07b8aaeb7c0 100644 --- a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts @@ -39,7 +39,12 @@ export class DotNetCoreVersionFetcher { } if (!requiredVersion) { - throw tl.loc("VersionNotFound"); + console.log("FallingBackToAdjacentChannels", version); + requiredVersion = await this.getVersionFromOtherChannels(version, packageType, includePreviewVersions); + } + + if (!requiredVersion) { + throw tl.loc("VersionNotFound", version); } return requiredVersion; @@ -148,6 +153,37 @@ export class DotNetCoreVersionFetcher { } } + private async getVersionFromOtherChannels(version: string, packageType: string, includePreviewVersions: boolean): Promise { + let fallbackChannels = this.getChannelsForMajorVersion(version); + if (!fallbackChannels && fallbackChannels.length < 1) { + throw tl.loc("NoSuitableChannelWereFound", version); + } + + var versionInfo: VersionInfo = null; + for (var i = 0; i < fallbackChannels.length; i++) { + console.log("LookingForVersionInChannel", (fallbackChannels[i])["channel-version"]); + versionInfo = await this.getVersionFromChannel(fallbackChannels[i], version, packageType, includePreviewVersions); + + if (versionInfo) { + break; + } + } + + return versionInfo; + } + + private getChannelsForMajorVersion(version: string): any { + var versionParts = utils.getVersionParts(version); + let adjacentChannels = []; + this.releasesIndex["releases-index"].forEach(channel => { + if (channel["channel-version"].startsWith(`${versionParts.majorVersion}`)) { + adjacentChannels.push(channel); + } + }); + + return adjacentChannels; + } + private detectMachineOS(): string[] { let osSuffix = []; let scriptRunner: trm.ToolRunner; @@ -217,6 +253,14 @@ export class DotNetCoreVersionFetcher { export class VersionInfo { public version: string; public files: VersionFilesData[]; + + public static getRuntimeVersion(versionInfo: VersionInfo): string { + if (versionInfo["runtime-version"]) { + return versionInfo["runtime-version"]; + } + + return versionInfo.version; + } } export class VersionFilesData { diff --git a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts index 20c29b00733d..48ad31269686 100644 --- a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts @@ -5,6 +5,7 @@ import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; import * as utils from "./versionUtilities"; +import { VersionInfo } from './versionFetcher'; export class VersionInstaller { constructor(packageType: string, installationPath: string) { @@ -19,8 +20,9 @@ export class VersionInstaller { this.installationPath = installationPath; } - public async downloadAndInstall(version: string, downloadUrl: string): Promise { + public async downloadAndInstall(versionInfo: VersionInfo, downloadUrl: string): Promise { let downloadPath = ""; + let version = versionInfo.version; try { downloadPath = await toolLib.downloadTool(downloadUrl); @@ -48,16 +50,21 @@ export class VersionInstaller { }); // Copy files - if (this.isLatestInstalledVersion(version)) { - tl.debug(tl.loc("CopyingFilesIntoPath", this.installationPath)); - var filesToBeCopied = allEnteriesInDir.filter(path => !fs.lstatSync(path).isDirectory()); - filesToBeCopied.forEach((filePath) => { - tl.cp(filePath, this.installationPath, "-f", false); - }); + try { + if (this.isLatestInstalledVersion(version)) { + tl.debug(tl.loc("CopyingFilesIntoPath", this.installationPath)); + var filesToBeCopied = allEnteriesInDir.filter(path => !fs.lstatSync(path).isDirectory()); + filesToBeCopied.forEach((filePath) => { + tl.cp(filePath, this.installationPath, "-f", false); + }); + } + } + catch (ex) { + tl.warning(tl.loc("FailedToCopyTopLevelFiles", ex)); } // Cache tool - this.createInstallationCompleteFile(version); + this.createInstallationCompleteFile(versionInfo); console.log(tl.loc("SuccessfullyInstalled", this.packageType, version)); } @@ -74,29 +81,28 @@ export class VersionInstaller { public isVersionInstalled(version: string): boolean { var isInstalled: boolean = false; if (this.packageType == "sdk") { - isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "sdk", version)); - if (!(globalInstallationPaths.find(path => path == this.installationPath))) { - isInstalled = isInstalled && fs.existsSync(path.join(this.installationPath, "sdk", `${version}.complete`)); - } + isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "sdk", version)) && fs.existsSync(path.join(this.installationPath, "sdk", `${version}.complete`)); } else { - isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "host", "fxr", version)) - if (!(globalInstallationPaths.find(path => path == this.installationPath))) { - isInstalled = isInstalled && fs.existsSync(path.join(this.installationPath, "host", "fxr", `${version}.complete`)); - } + isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", version)) && fs.existsSync(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", `${version}.complete`)); } isInstalled ? console.log(tl.loc("VersionFoundInToolCache")) : console.log(tl.loc("VersionNotFoundInToolCache", version)); return isInstalled; } - private createInstallationCompleteFile(version: string): void { + private createInstallationCompleteFile(versionInfo: VersionInfo): void { + let version = versionInfo.version; tl.debug(tl.loc("CreatingInstallationCompeleteFile", version, this.packageType)); - if (!globalInstallationPaths.find(path => path == this.installationPath)) { - // always add for runtime as it is installed with SDK as well. - var pathToVersionCompleteFile = this.packageType == "sdk" ? path.join(this.installationPath, "sdk") : path.join(this.installationPath, "host", "fxr"); + // always add for runtime as it is installed with SDK as well. + var pathToVersionCompleteFile: string = ""; + if (this.packageType == "sdk") { + pathToVersionCompleteFile = path.join(this.installationPath, "sdk"); fs.writeFileSync(path.join(pathToVersionCompleteFile, `${version}.complete`), `{ "version": "${version}" }`); } + + pathToVersionCompleteFile = path.join(this.installationPath, "shared", "Microsoft.NETCore.App"); + fs.writeFileSync(path.join(pathToVersionCompleteFile, `${VersionInfo.getRuntimeVersion(versionInfo)}.complete`), `{ "version": "${VersionInfo.getRuntimeVersion(versionInfo)}" }`); } private isLatestInstalledVersion(version: string): boolean { @@ -107,14 +113,9 @@ export class VersionInstaller { var allEnteries: string[] = fs.readdirSync(pathTobeChecked).map(name => path.join(pathTobeChecked, name)); var folderPaths: string[] = allEnteries.filter(element => fs.lstatSync(element).isDirectory()); - var isLatest: boolean = folderPaths.findIndex(folderPath => utils.versionCompareFunction(path.basename(folderPath), version) > 0) < 0; - - if (!(globalInstallationPaths.find(path => path == this.installationPath))) { - var filePaths: string[] = allEnteries.filter(element => !fs.lstatSync(element).isDirectory()); - - isLatest = isLatest && filePaths.findIndex(filePath => utils.versionCompareFunction(this.getVersionCompleteFileName(path.basename(filePath)), version) > 0) < 0; - } + var filePaths: string[] = allEnteries.filter(element => !fs.lstatSync(element).isDirectory()); + isLatest = isLatest && filePaths.findIndex(filePath => utils.versionCompareFunction(this.getVersionCompleteFileName(path.basename(filePath)), version) > 0) < 0; isLatest ? tl.debug(tl.loc("VersionIsLocalLatest")) : tl.debug(tl.loc("VersionIsNotLocalLatest")); return isLatest; @@ -128,13 +129,4 @@ export class VersionInstaller { private packageType: string; private installationPath: string; -} - -const globalInstallationPaths = [ - "C:/Program Files/dotnet", - "C:/Program Files (x86)/dotnet", - "C:\\Program Files\\dotnet", - "C:\\Program Files (x86)\\dotnet", - "/usr/local/share/dotnet", - "/usr/share/dotnet" -] \ No newline at end of file +} \ No newline at end of file From 0b0e6527fd4ec43cff5f786c7fd9d6e450d71e3f Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Mon, 11 Mar 2019 20:45:51 +0530 Subject: [PATCH 05/17] Handled corner scenario's and fixed for linux/mac. Resolved comments. --- .../dotnetcoreinstaller.ts | 17 +++-- Tasks/DotNetCoreInstallerV1/versionFetcher.ts | 56 ++++++++++----- .../DotNetCoreInstallerV1/versionInstaller.ts | 64 ++++++++++++----- .../DotNetCoreInstallerV1/versionUtilities.ts | 68 ++++++++++++------- 4 files changed, 139 insertions(+), 66 deletions(-) diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index ffd8590ee837..4b6b04daac1b 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -4,18 +4,21 @@ import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; import { DotNetCoreVersionFetcher, VersionInfo } from "./versionFetcher"; import { VersionInstaller } from "./versionInstaller"; +import { VersionParts } from "./versionUtilities"; async function run() { - let packageType = tl.getInput('packageType', true); - let version = tl.getInput('version', true).trim(); + let packageType = tl.getInput('packageType', true).toLowerCase(); + let versionSpec = tl.getInput('version', true).trim(); let installationPath = tl.getInput('installationPath', true).trim(); let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions', true); - console.log(tl.loc("ToolToInstall", packageType, version)); - let versionFetcher = new DotNetCoreVersionFetcher(); - let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(version, packageType, includePreviewVersions); + console.log(tl.loc("ToolToInstall", packageType, versionSpec)); + VersionParts.ValidateVersionSpec(versionSpec); + + let versionFetcher = new DotNetCoreVersionFetcher(); + let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(versionSpec, packageType, includePreviewVersions); if (!versionInfo) { - throw tl.loc("MatchingVersionNotFound", version); + throw tl.loc("MatchingVersionNotFound", versionSpec); } let dotNetCoreInstaller = new VersionInstaller(packageType, installationPath); @@ -23,6 +26,8 @@ async function run() { await dotNetCoreInstaller.downloadAndInstall(versionInfo, versionFetcher.getDownloadUrl(versionInfo, packageType)); } + toolLib.prependPath(installationPath); + // By default disable Multi Level Lookup unless user wants it enabled. if (tl.getBoolInput("restrictMultiLevelLookup", true)) { tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts index d07b8aaeb7c0..aa41f1eb5f50 100644 --- a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts @@ -4,7 +4,6 @@ import * as path from 'path'; import * as tl from 'vsts-task-lib/task'; import * as trm from 'vsts-task-lib/toolrunner'; -import * as toolLib from 'vsts-task-tool-lib'; import httpClient = require("typed-rest-client/HttpClient"); import httpInterfaces = require("typed-rest-client/Interfaces"); @@ -38,7 +37,7 @@ export class DotNetCoreVersionFetcher { requiredVersion = await this.getVersionFromChannel(channelInformation, version, packageType, includePreviewVersions); } - if (!requiredVersion) { + if (!requiredVersion && !version.endsWith("x")) { console.log("FallingBackToAdjacentChannels", version); requiredVersion = await this.getVersionFromOtherChannels(version, packageType, includePreviewVersions); } @@ -47,6 +46,8 @@ export class DotNetCoreVersionFetcher { throw tl.loc("VersionNotFound", version); } + let dotNetSdkVersionTelemetry = `{"userVersion":"${version}", "resolvedVersion":"${requiredVersion.version}"}`; + console.log("##vso[telemetry.publish area=TaskDeploymentMethod;feature=DotNetCoreInstallerV1]" + dotNetSdkVersionTelemetry); return requiredVersion; } @@ -54,9 +55,19 @@ export class DotNetCoreVersionFetcher { console.log(tl.loc("GettingDownloadUrl", packageType, versionInfo.version)); let osSuffixes = this.detectMachineOS(); - let downloadPackageInfoObject: any = versionInfo.files.find((downloadPackageInfo: any) => { - if (downloadPackageInfo.rid.toLowerCase() == osSuffixes[0].toLowerCase() - && (osSuffixes[0].split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip"))) { + let downloadPackageInfoObject: VersionFilesData = null; + osSuffixes.find((osSuffix) => { + downloadPackageInfoObject = versionInfo.files.find((downloadPackageInfo: any) => { + if (downloadPackageInfo.rid.toLowerCase() == osSuffix.toLowerCase()) { + if (osSuffix.split("-")[0] != "win" || (osSuffix.split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip"))) { + return true; + } + } + + return false; + }); + + if (downloadPackageInfoObject) { return true; } @@ -64,28 +75,29 @@ export class DotNetCoreVersionFetcher { }); if (!!downloadPackageInfoObject && downloadPackageInfoObject.url) { + tl.debug("Got download URL for platform with rid: " + downloadPackageInfoObject.rid); return downloadPackageInfoObject.url; } return ""; } - private setReleasesIndex(): Promise { + private setReleasesIndex(): Promise { return this.httpCallbackClient.get(DotNetCoreReleasesIndexUrl) .then((response: HttpClientResponse) => { return response.readBody(); }) .then((body: string) => { this.releasesIndex = JSON.parse(body); - return this.releasesIndex; + return; }) .catch((ex) => { - throw tl.loc(""); + throw tl.loc("ExceptionWhileDownloadOrReadReleasesIndex", ex); }); } private getVersionChannel(version: string): any { - let versionParts: any = utils.getVersionParts(version); + let versionParts: any = new utils.VersionParts(version); let channelVersion = `${versionParts.majorVersion}.${versionParts.minorVersion}`; if (versionParts.minorVersion == "x") { @@ -107,7 +119,7 @@ export class DotNetCoreVersionFetcher { } private getVersionFromChannel(channelInformation: any, version: string, packageType: string, includePreviewVersions: boolean): Promise { - let versionParts: any = utils.getVersionParts(version); + let versionParts: utils.VersionParts = new utils.VersionParts(version); var releasesJsonUrl: string = channelInformation["releases.json"]; var channelReleases: any = null; @@ -119,13 +131,14 @@ export class DotNetCoreVersionFetcher { .then((body: string) => { channelReleases = JSON.parse(body).releases; if (versionParts.minorVersion == "x" || versionParts.patchVersion == "x") { - let dotNetSdkVersionTelemetry = `{"version":"${version}"}`; - console.log("##vso[telemetry.publish area=TaskDeploymentMethod;feature=DotNetCoreInstallerV1]" + dotNetSdkVersionTelemetry); let latestVersion = "0.0.0"; channelReleases.forEach(release => { if (release[packageType] && utils.versionCompareFunction(release[packageType].version, latestVersion) > 0 && (includePreviewVersions || !release[packageType].version.includes('preview'))) { - latestVersion = release[packageType].version; + let matchedVersionParts = new utils.VersionParts(release[packageType].version); + if (matchedVersionParts.majorVersion == versionParts.majorVersion && (versionParts.minorVersion == "x" || (versionParts.patchVersion == "x" && matchedVersionParts.minorVersion == versionParts.minorVersion))) { + latestVersion = release[packageType].version; + } } }); @@ -173,7 +186,7 @@ export class DotNetCoreVersionFetcher { } private getChannelsForMajorVersion(version: string): any { - var versionParts = utils.getVersionParts(version); + var versionParts = new utils.VersionParts(version); let adjacentChannels = []; this.releasesIndex["releases-index"].forEach(channel => { if (channel["channel-version"].startsWith(`${versionParts.majorVersion}`)) { @@ -254,12 +267,19 @@ export class VersionInfo { public version: string; public files: VersionFilesData[]; - public static getRuntimeVersion(versionInfo: VersionInfo): string { - if (versionInfo["runtime-version"]) { - return versionInfo["runtime-version"]; + public static getRuntimeVersion(versionInfo: VersionInfo, packageType: string): string { + if (packageType == "sdk") { + if (versionInfo["runtime-version"]) { + return versionInfo["runtime-version"]; + } + + tl.warning(tl.loc("runtimeVersionPropertyNotFound")); + } + else { + return versionInfo.version; } - return versionInfo.version; + return ""; } } diff --git a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts index 48ad31269686..84d66239cdfa 100644 --- a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts @@ -10,7 +10,7 @@ import { VersionInfo } from './versionFetcher'; export class VersionInstaller { constructor(packageType: string, installationPath: string) { try { - fs.existsSync(installationPath) || fs.mkdirSync(installationPath); + tl.exist(installationPath) || tl.mkdirP(installationPath); } catch (ex) { throw tl.loc("UnableToAccessPath", installationPath, ex); @@ -27,7 +27,7 @@ export class VersionInstaller { try { downloadPath = await toolLib.downloadTool(downloadUrl); } catch (error) { - tl.warning(tl.loc("CouldNotDownload", downloadUrl, JSON.stringify(error))); + throw tl.loc("CouldNotDownload", downloadUrl, JSON.stringify(error)); } try { @@ -41,9 +41,8 @@ export class VersionInstaller { let extPath: string = tl.osType().match(/^Win/) ? await toolLib.extractZip(downloadPath) : await toolLib.extractTar(downloadPath); // Copy folders - console.log(tl.loc("InstallingDotNetVersion", version, this.installationPath)); tl.debug(tl.loc("CopyingFoldersIntoPath", this.installationPath)); - var allEnteriesInDir: string[] = fs.readdirSync(extPath).map(name => path.join(extPath, name)); + var allEnteriesInDir: string[] = tl.ls("", [extPath]).map(name => path.join(extPath, name)); var directoriesTobeCopied: string[] = allEnteriesInDir.filter(path => fs.lstatSync(path).isDirectory()); directoriesTobeCopied.forEach((directoryPath) => { tl.cp(directoryPath, this.installationPath, "-rf", false); @@ -79,12 +78,16 @@ export class VersionInstaller { } public isVersionInstalled(version: string): boolean { + if (!toolLib.isExplicitVersion(version)) { + throw tl.loc("VersionNotAllowed", version); + } + var isInstalled: boolean = false; if (this.packageType == "sdk") { - isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "sdk", version)) && fs.existsSync(path.join(this.installationPath, "sdk", `${version}.complete`)); + isInstalled = tl.exist(path.join(this.installationPath, "sdk", version)) && tl.exist(path.join(this.installationPath, "sdk", `${version}.complete`)); } else { - isInstalled = toolLib.isExplicitVersion(version) && fs.existsSync(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", version)) && fs.existsSync(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", `${version}.complete`)); + isInstalled = tl.exist(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", version)) && tl.exist(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", `${version}.complete`)); } isInstalled ? console.log(tl.loc("VersionFoundInToolCache")) : console.log(tl.loc("VersionNotFoundInToolCache", version)); @@ -92,30 +95,51 @@ export class VersionInstaller { } private createInstallationCompleteFile(versionInfo: VersionInfo): void { - let version = versionInfo.version; - tl.debug(tl.loc("CreatingInstallationCompeleteFile", version, this.packageType)); + tl.debug(tl.loc("CreatingInstallationCompeleteFile", versionInfo.version, this.packageType)); // always add for runtime as it is installed with SDK as well. var pathToVersionCompleteFile: string = ""; if (this.packageType == "sdk") { + let sdkVersion = versionInfo.version; pathToVersionCompleteFile = path.join(this.installationPath, "sdk"); - fs.writeFileSync(path.join(pathToVersionCompleteFile, `${version}.complete`), `{ "version": "${version}" }`); + tl.writeFile(path.join(pathToVersionCompleteFile, `${sdkVersion}.complete`), `{ "version": "${sdkVersion}" }`); } - pathToVersionCompleteFile = path.join(this.installationPath, "shared", "Microsoft.NETCore.App"); - fs.writeFileSync(path.join(pathToVersionCompleteFile, `${VersionInfo.getRuntimeVersion(versionInfo)}.complete`), `{ "version": "${VersionInfo.getRuntimeVersion(versionInfo)}" }`); + let runtimeVersion = VersionInfo.getRuntimeVersion(versionInfo, this.packageType); + if (runtimeVersion) { + pathToVersionCompleteFile = path.join(this.installationPath, "shared", "Microsoft.NETCore.App"); + tl.writeFile(path.join(pathToVersionCompleteFile, `${runtimeVersion}.complete`), `{ "version": "${runtimeVersion}" }`); + } + else if (this.packageType == "runtime") { + throw tl.loc("CannotFindRuntimeVersionForCompletingInstllation", versionInfo.version, this.packageType); + } } private isLatestInstalledVersion(version: string): boolean { - var pathTobeChecked = this.packageType == "sdk" ? path.join(this.installationPath, "sdk") : path.join(this.installationPath, "host", "fxr"); - if (!fs.existsSync(pathTobeChecked)) { + var pathTobeChecked = this.packageType == "sdk" ? path.join(this.installationPath, "sdk") : path.join(this.installationPath, "shared", "Microsoft.NETCore.App"); + if (!tl.exist(pathTobeChecked)) { throw tl.loc("PathNotFoundException", pathTobeChecked); } - var allEnteries: string[] = fs.readdirSync(pathTobeChecked).map(name => path.join(pathTobeChecked, name)); + var allEnteries: string[] = tl.ls("", [pathTobeChecked]).map(name => path.join(pathTobeChecked, name)); var folderPaths: string[] = allEnteries.filter(element => fs.lstatSync(element).isDirectory()); - var isLatest: boolean = folderPaths.findIndex(folderPath => utils.versionCompareFunction(path.basename(folderPath), version) > 0) < 0; + var isLatest: boolean = folderPaths.findIndex(folderPath => { + try { + return utils.versionCompareFunction(path.basename(folderPath), version) > 0; + } + catch (ex) { + // no op, folder name might not be in version format + } + }) < 0; + var filePaths: string[] = allEnteries.filter(element => !fs.lstatSync(element).isDirectory()); - isLatest = isLatest && filePaths.findIndex(filePath => utils.versionCompareFunction(this.getVersionCompleteFileName(path.basename(filePath)), version) > 0) < 0; + isLatest = isLatest && filePaths.findIndex(filePath => { + try { + return utils.versionCompareFunction(this.getVersionCompleteFileName(path.basename(filePath)), version) > 0 + } + catch (ex) { + // no op, file name might not be in version format + } + }) < 0; isLatest ? tl.debug(tl.loc("VersionIsLocalLatest")) : tl.debug(tl.loc("VersionIsNotLocalLatest")); return isLatest; @@ -123,9 +147,13 @@ export class VersionInstaller { private getVersionCompleteFileName(name: string): string { var parts = name.split('.'); - return name.substr(0, name.length - (parts[parts.length - 1].length + 1)); - } + var fileNameWithoutExtensionLength = name.length - (parts[parts.length - 1].length + 1); + if (fileNameWithoutExtensionLength > 0) { + return name.substr(0, fileNameWithoutExtensionLength); + } + throw "Not correct Complete marker file name: " + name; + } private packageType: string; private installationPath: string; diff --git a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts index 95a1dec71617..ea539b179cf6 100644 --- a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts +++ b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts @@ -1,43 +1,63 @@ import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib'; -export function getVersionParts(version: string): { majorVersion: string, minorVersion: string, patchVersion: string } { - let versionParts: string[] = version.split('.'); - if (versionParts.length < 2) { - throw tl.loc("VersionNotAllowed", version) - } - - let majorVersion = versionParts[0]; - let minorVersion = versionParts[1]; - let patchVersion = ""; - if (minorVersion != "x" && versionParts.length > 2) { - patchVersion = versionParts[2]; - } - else { - throw tl.loc("VersionNotAllowed", version); - } - - return { "majorVersion": majorVersion, "minorVersion": minorVersion, "patchVersion": patchVersion }; -} - export function versionCompareFunction(versionA: string, versionB: string): number { if (!toolLib.isExplicitVersion(versionA) || !toolLib.isExplicitVersion(versionA)) { - console.log(tl.loc("ExplicitVersionRequiredForComparison", versionA, versionB)); throw tl.loc("ExplicitVersionRequiredForComparison", versionA, versionB); } - var versionAParts = getVersionParts(versionA); - var versionBParts = getVersionParts(versionB); + var versionAParts = new VersionParts(versionA); + var versionBParts = new VersionParts(versionB); if (versionAParts.majorVersion != versionBParts.majorVersion) { - return versionAParts.majorVersion > versionBParts.majorVersion ? 1 : -1; + return Number.parseInt(versionAParts.majorVersion) > Number.parseInt(versionBParts.majorVersion) ? 1 : -1; } else if (versionAParts.minorVersion != versionBParts.minorVersion) { - return versionAParts.minorVersion > versionBParts.minorVersion ? 1 : -1; + return Number.parseInt(versionAParts.minorVersion) > Number.parseInt(versionBParts.minorVersion) ? 1 : -1; } else if (versionAParts.patchVersion != versionBParts.patchVersion) { + let versionAPatchParts = versionAParts.patchVersion.split("-"); + let versionBPatchParts = versionBParts.patchVersion.split("-"); + if (Number.parseInt(versionAPatchParts[0]) != Number.parseInt(versionBPatchParts[0])) { + return Number.parseInt(versionAPatchParts[0]) > Number.parseInt(versionBPatchParts[0]) ? 1 : -1; + } + + if (versionAPatchParts.length == versionBPatchParts.length && versionAPatchParts.length == 3) { + if (Number.parseInt(versionAPatchParts[2]) != Number.parseInt(versionBPatchParts[2])) { + return Number.parseInt(versionAPatchParts[2]) > Number.parseInt(versionBPatchParts[2]) ? 1 : -1; + } + } + return versionAParts.patchVersion > versionBParts.patchVersion ? 1 : -1; } return 0; +} + +export class VersionParts { + constructor(version: string) { + VersionParts.ValidateVersionSpec(version); + let parts: string[] = version.split("."); + + this.majorVersion = parts[0]; + this.minorVersion = parts[1]; + this.patchVersion = ""; + if (this.minorVersion != "x") { + this.patchVersion = parts[2]; + } + } + + public static ValidateVersionSpec(version): boolean { + let parts: string[] = version.split('.'); + // validate version + if (parts.length < 2 || parts.length > 3 || parts[0] == "x" || (parts[1] == "x" && parts.length > 2) || (parts[1] != "x" && parts.length <= 2) ) { + throw tl.loc("VersionNotAllowed", version) + } + + return true; + } + + majorVersion: string; + minorVersion: string; + patchVersion: string; } \ No newline at end of file From 3ee9644214ea507eeb547fc34d0209137ede2874 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Tue, 12 Mar 2019 22:37:23 +0530 Subject: [PATCH 06/17] used semver, changed platform output for mac, added strings, removed typings --- .../resources.resjson/en-US/resources.resjson | 32 +- .../dotnetcoreinstaller.ts | 6 +- .../externals/get-os-distro.sh | 4 +- .../externals/install-dotnet.ps1 | 503 --- .../externals/install-dotnet.sh | 815 ----- Tasks/DotNetCoreInstallerV1/package-lock.json | 27 +- Tasks/DotNetCoreInstallerV1/package.json | 6 +- Tasks/DotNetCoreInstallerV1/task.json | 32 +- Tasks/DotNetCoreInstallerV1/task.loc.json | 32 +- Tasks/DotNetCoreInstallerV1/typings.json | 9 - .../typings/globals/mocha/index.d.ts | 202 -- .../typings/globals/mocha/typings.json | 8 - .../typings/globals/node/index.d.ts | 3084 ----------------- .../typings/globals/node/typings.json | 8 - .../typings/globals/q/index.d.ts | 357 -- .../typings/globals/q/typings.json | 8 - .../DotNetCoreInstallerV1/typings/index.d.ts | 3 - Tasks/DotNetCoreInstallerV1/versionFetcher.ts | 155 +- .../DotNetCoreInstallerV1/versionInstaller.ts | 47 +- .../DotNetCoreInstallerV1/versionUtilities.ts | 73 +- 20 files changed, 286 insertions(+), 5125 deletions(-) delete mode 100644 Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 delete mode 100644 Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh delete mode 100644 Tasks/DotNetCoreInstallerV1/typings.json delete mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts delete mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json delete mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts delete mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json delete mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts delete mode 100644 Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json delete mode 100644 Tasks/DotNetCoreInstallerV1/typings/index.d.ts diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson index 3a26a9db5e9a..2a14bca671cd 100644 --- a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson @@ -36,5 +36,35 @@ "loc.messages.CouldNotDownload": "Could not download installation package from this URL: %s Error: %s", "loc.messages.FailedToDownloadPackage": "Failed to download package for installation", "loc.messages.PrependGlobalToolPath": "Creating global tool path and pre-prending to PATH.", - "loc.messages.VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/" + "loc.messages.VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/", + "loc.messages.MatchingVersionNotFound": "No matching version could be found for specified version: %s Kindly note the preview versions are only considered in latest version searches if Include Preview Versions checkbox is checked.", + "loc.messages.UnableToAccessPath": "Unable to access path: %s. Error: %s \n please make sure that agent process has path to the path.", + "loc.messages.VersionCanNotBeDownloadedFromUrl": "Version: %s cannot be downloaded from URL: %s. Either the URL or version is incorrect.", + "loc.messages.CopyingFoldersIntoPath": "Copying all root folders into installation path: %s", + "loc.messages.CopyingFilesIntoPath": "Copying root files (such as dotnet.exe) into installation path: %s", + "loc.messages.FailedToCopyTopLevelFiles": "Failed to copy root files into installation path: %s. Error: %s", + "loc.messages.FailedWhileInstallingVersionAtPath": "Failed while installing version: %s at path: %s with error: %s", + "loc.messages.ExplicitVersionRequired": "Version: %s is not allowed. Versions to be installed should be of format: major.minor.patchversion. For example: 2.2.1", + "loc.messages.VersionFoundInCache": "Version: %s was found in cache.", + "loc.messages.VersionNotFoundInCache": "Version %s was not found in cache.", + "loc.messages.CreatingInstallationCompeleteFile": "Creating installation complete file for .Net core %s version %s", + "loc.messages.CannotFindRuntimeVersionForCompletingInstallation": "Cannot find runtime version for package type: %s with version: %s", + "loc.messages.PathNotFoundException": "Path: %s could not be located/found. Make sure the path exists.", + "loc.messages.VersionIsLocalLatest": "Version: %s is the latest among the versions present at path: %s", + "loc.messages.VersionIsNotLocalLatest": "Version: %s is not the latest among the versions present at %s", + "loc.messages.DownloadUrlForMatchingOsNotFound": "Download URL for .Net Core %s version %s could not be found for the following OS platforms (rid): %s", + "loc.messages.ExceptionWhileDownloadOrReadReleasesIndex": "Failed to download or parse release-index.json with error: %s", + "loc.messages.MatchingVersionForUserInputVersion": "Found version %s in channel %s for user specified version spec: %s", + "loc.messages.UrlForReleaseChannelNotFound": "Could not find URL for releases.json of channel version: %s", + "loc.messages.NoSuitableChannelWereFound": "Channel corresponding to version %s could not be found.", + "loc.messages.DetectingPlatform": "Detecting OS platform to find correct download package for the OS.", + "loc.messages.FailedInDetectingMachineArch": "Failed while detecting machine OS platform with error: %s", + "loc.messages.runtimeVersionPropertyNotFound": "runtime-version property could not be found for .Net Core %s version %s.", + "loc.messages.VersionNotFound": "Version matching: %s could not be found", + "loc.messages.VersionNotAllowed": "Version %s is not allowed. Allowed version types are: majorVersion.x, majorVersion.minorVersion.x, majorVersion.minorVersion.patchVersion", + "loc.messages.VersionsCanNotBeCompared": "Versions %s and %s cannot be compared. Both versions should be explicit.", + "loc.messages.FileNameNotCorrectCompleteFileName": "File name %s is not correct version.complete file name.", + "loc.messages.ChannelVersionsNotComparable": "Channel versions %s and %s can not be compared. They both must have numeric major and minor versions.", + "loc.messages.LookingForVersionInChannel": "Searching for version in channel %s", + "loc.messages.FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels." } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index 4b6b04daac1b..e5bf7666c16e 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -4,7 +4,7 @@ import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; import { DotNetCoreVersionFetcher, VersionInfo } from "./versionFetcher"; import { VersionInstaller } from "./versionInstaller"; -import { VersionParts } from "./versionUtilities"; +import { VersionParts, Constants } from "./versionUtilities"; async function run() { let packageType = tl.getInput('packageType', true).toLowerCase(); @@ -44,9 +44,9 @@ function addDotNetCoreToolPath() { try { let globalToolPath: string = ""; if (tl.osType().match(/^Win/)) { - globalToolPath = path.join(process.env.USERPROFILE, ".dotnet\\tools"); + globalToolPath = path.join(process.env.USERPROFILE, Constants.relativeGlobalToolPath); } else { - globalToolPath = path.join(process.env.HOME, ".dotnet/tools"); + globalToolPath = path.join(process.env.HOME, Constants.relativeGlobalToolPath); } console.log(tl.loc("PrependGlobalToolPath")); diff --git a/Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh b/Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh index e44096ac8181..98df90f776c2 100644 --- a/Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh +++ b/Tasks/DotNetCoreInstallerV1/externals/get-os-distro.sh @@ -113,7 +113,7 @@ get_current_os_name() { local uname=$(uname) if [ "$uname" = "Darwin" ]; then - echo "mac" + echo "osx" return 0 elif [ "$uname" = "Linux" ]; then local linux_platform_name @@ -139,7 +139,7 @@ get_legacy_os_name() { local uname=$(uname) if [ "$uname" = "Darwin" ]; then - echo "mac" + echo "osx" return 0 else if [ -e /etc/os-release ]; then diff --git a/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 b/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 deleted file mode 100644 index 85404535cc2e..000000000000 --- a/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.ps1 +++ /dev/null @@ -1,503 +0,0 @@ -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -<# -.SYNOPSIS - Installs dotnet cli -.DESCRIPTION - Installs dotnet cli. If dotnet installation already exists in the given directory - it will update it only if the requested version differs from the one already installed. -.PARAMETER Channel - Default: LTS - Download from the Channel specified. Possible values: - - Current - most current release - - LTS - most current supported release - - 2-part version in a format A.B - represents a specific release - examples: 2.0; 1.0 - - Branch name - examples: release/2.0.0; Master -.PARAMETER Version - Default: latest - Represents a build version on specific channel. Possible values: - - latest - most latest build on specific channel - - coherent - most latest coherent build on specific channel - coherent applies only to SDK downloads - - 3-part version in a format A.B.C - represents specific version of build - examples: 2.0.0-preview2-006120; 1.1.0 -.PARAMETER InstallDir - Default: %LocalAppData%\Microsoft\dotnet - Path to where to install dotnet. Note that binaries will be placed directly in a given directory. -.PARAMETER Architecture - Default: - this value represents currently running OS architecture - Architecture of dotnet binaries to be installed. - Possible values are: , x64 and x86 -.PARAMETER SharedRuntime - Default: false - Installs just the shared runtime bits, not the entire SDK -.PARAMETER DryRun - If set it will not perform installation but instead display what command line to use to consistently install - currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link - with specific version so that this command can be used deterministicly in a build script. - It also displays binaries location if you prefer to install or download it yourself. -.PARAMETER NoPath - By default this script will set environment variable PATH for the current process to the binaries folder inside installation folder. - If set it will display binaries location but not set any environment variable. -.PARAMETER Verbose - Displays diagnostics information. -.PARAMETER AzureFeed - Default: https://dotnetcli.azureedge.net/dotnet - This parameter typically is not changed by the user. - It allows to change URL for the Azure feed used by this installer. -.PARAMETER UncachedFeed - This parameter typically is not changed by the user. - It allows to change URL for the Uncached feed used by this installer. -.PARAMETER ProxyAddress - If set, the installer will use the proxy when making web requests -.PARAMETER ProxyUseDefaultCredentials - Default: false - Use default credentials, when using proxy address. -#> -[cmdletbinding()] -param( - [string]$Channel="LTS", - [string]$Version="Latest", - [string]$InstallDir="", - [string]$Architecture="", - [switch]$SharedRuntime, - [switch]$DryRun, - [switch]$NoPath, - [string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet", - [string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet", - [string]$ProxyAddress, - [switch]$ProxyUseDefaultCredentials -) - -Set-StrictMode -Version Latest -$ErrorActionPreference="Stop" -$ProgressPreference="SilentlyContinue" - -$BinFolderRelativePath="" - -# example path with regex: shared/1.0.0-beta-12345/somepath -$VersionRegEx="/\d+\.\d+[^/]+/" -$OverrideNonVersionedFiles=$true - -function Say($str) { - Write-Output "dotnet-install: $str" -} - -function Say-Verbose($str) { - Write-Verbose "dotnet-install: $str" -} - -function Say-Invocation($Invocation) { - $command = $Invocation.MyCommand; - $args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ") - Say-Verbose "$command $args" -} - -function Invoke-With-Retry([ScriptBlock]$ScriptBlock, [int]$MaxAttempts = 3, [int]$SecondsBetweenAttempts = 1) { - $Attempts = 0 - - while ($true) { - try { - return $ScriptBlock.Invoke() - } - catch { - $Attempts++ - if ($Attempts -lt $MaxAttempts) { - Start-Sleep $SecondsBetweenAttempts - } - else { - throw - } - } - } -} - -function Get-Machine-Architecture() { - Say-Invocation $MyInvocation - - # possible values: AMD64, IA64, x86 - return $ENV:PROCESSOR_ARCHITECTURE -} - -# TODO: Architecture and CLIArchitecture should be unified -function Get-CLIArchitecture-From-Architecture([string]$Architecture) { - Say-Invocation $MyInvocation - - switch ($Architecture.ToLower()) { - { $_ -eq "" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) } - { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } - { $_ -eq "x86" } { return "x86" } - default { throw "Architecture not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" } - } -} - -function Get-Version-Info-From-Version-Text([string]$VersionText) { - Say-Invocation $MyInvocation - - $Data = @($VersionText.Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); - - $VersionInfo = @{} - $VersionInfo.CommitHash = $Data[0].Trim() - $VersionInfo.Version = $Data[1].Trim() - return $VersionInfo -} - -function Load-Assembly([string] $Assembly) { - try { - Add-Type -Assembly $Assembly | Out-Null - } - catch { - # On Nano Server, Powershell Core Edition is used. Add-Type is unable to resolve base class assemblies because they are not GAC'd. - # Loading the base class assemblies is not unnecessary as the types will automatically get resolved. - } -} - -function GetHTTPResponse([Uri] $Uri) -{ - Invoke-With-Retry( - { - - $HttpClient = $null - - try { - # HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet. - Load-Assembly -Assembly System.Net.Http - - if(-not $ProxyAddress) - { - # Despite no proxy being explicitly specified, we may still be behind a default proxy - $DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy; - if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))){ - $ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString - $ProxyUseDefaultCredentials = $true - } - } - - if($ProxyAddress){ - $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler - $HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{Address=$ProxyAddress;UseDefaultCredentials=$ProxyUseDefaultCredentials} - $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler - } - else { - $HttpClient = New-Object System.Net.Http.HttpClient - } - # Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out - # 10 minutes allows it to work over much slower connections. - $HttpClient.Timeout = New-TimeSpan -Minutes 10 - $Response = $HttpClient.GetAsync($Uri).Result - if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) - { - $ErrorMsg = "Failed to download $Uri." - if ($Response -ne $null) - { - $ErrorMsg += " $Response" - } - - throw $ErrorMsg - } - - return $Response - } - finally { - if ($HttpClient -ne $null) { - $HttpClient.Dispose() - } - } - }) -} - - -function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) { - Say-Invocation $MyInvocation - - $VersionFileUrl = $null - if ($SharedRuntime) { - $VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version" - } - else { - if ($Coherent) { - $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.coherent.version" - } - else { - $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version" - } - } - - $Response = GetHTTPResponse -Uri $VersionFileUrl - $StringContent = $Response.Content.ReadAsStringAsync().Result - - switch ($Response.Content.Headers.ContentType) { - { ($_ -eq "application/octet-stream") } { $VersionText = [Text.Encoding]::UTF8.GetString($StringContent) } - { ($_ -eq "text/plain") } { $VersionText = $StringContent } - { ($_ -eq "text/plain; charset=UTF-8") } { $VersionText = $StringContent } - default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." } - } - - $VersionInfo = Get-Version-Info-From-Version-Text $VersionText - - return $VersionInfo -} - - -function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, [string]$Version) { - Say-Invocation $MyInvocation - - switch ($Version.ToLower()) { - { $_ -eq "latest" } { - $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False - return $LatestVersionInfo.Version - } - { $_ -eq "coherent" } { - $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $True - return $LatestVersionInfo.Version - } - default { return $Version } - } -} - -function Get-Download-Link([string]$AzureFeed, [string]$Channel, [string]$SpecificVersion, [string]$CLIArchitecture) { - Say-Invocation $MyInvocation - - if ($SharedRuntime) { - $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificVersion-win-$CLIArchitecture.zip" - } - else { - $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificVersion-win-$CLIArchitecture.zip" - } - - Say-Verbose "Constructed primary payload URL: $PayloadURL" - - return $PayloadURL -} - -function Get-LegacyDownload-Link([string]$AzureFeed, [string]$Channel, [string]$SpecificVersion, [string]$CLIArchitecture) { - Say-Invocation $MyInvocation - - if ($SharedRuntime) { - $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip" - } - else { - $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip" - } - - Say-Verbose "Constructed legacy payload URL: $PayloadURL" - - return $PayloadURL -} - -function Get-User-Share-Path() { - Say-Invocation $MyInvocation - - $InstallRoot = $env:DOTNET_INSTALL_DIR - if (!$InstallRoot) { - $InstallRoot = "$env:LocalAppData\Microsoft\dotnet" - } - return $InstallRoot -} - -function Resolve-Installation-Path([string]$InstallDir) { - Say-Invocation $MyInvocation - - if ($InstallDir -eq "") { - return Get-User-Share-Path - } - return $InstallDir -} - -function Get-Version-Info-From-Version-File([string]$InstallRoot, [string]$RelativePathToVersionFile) { - Say-Invocation $MyInvocation - - $VersionFile = Join-Path -Path $InstallRoot -ChildPath $RelativePathToVersionFile - Say-Verbose "Local version file: $VersionFile" - - if (Test-Path $VersionFile) { - $VersionText = cat $VersionFile - Say-Verbose "Local version file text: $VersionText" - return Get-Version-Info-From-Version-Text $VersionText - } - - Say-Verbose "Local version file not found." - - return $null -} - -function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) { - Say-Invocation $MyInvocation - - $DotnetPackagePath = Join-Path -Path $InstallRoot -ChildPath $RelativePathToPackage | Join-Path -ChildPath $SpecificVersion - Say-Verbose "Is-Dotnet-Package-Installed: Path to a package: $DotnetPackagePath" - return Test-Path $DotnetPackagePath -PathType Container -} - -function Get-Absolute-Path([string]$RelativeOrAbsolutePath) { - # Too much spam - # Say-Invocation $MyInvocation - - return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RelativeOrAbsolutePath) -} - -function Get-Path-Prefix-With-Version($path) { - $match = [regex]::match($path, $VersionRegEx) - if ($match.Success) { - return $entry.FullName.Substring(0, $match.Index + $match.Length) - } - - return $null -} - -function Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package([System.IO.Compression.ZipArchive]$Zip, [string]$OutPath) { - Say-Invocation $MyInvocation - - $ret = @() - foreach ($entry in $Zip.Entries) { - $dir = Get-Path-Prefix-With-Version $entry.FullName - if ($dir -ne $null) { - $path = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $dir) - if (-Not (Test-Path $path -PathType Container)) { - $ret += $dir - } - } - } - - $ret = $ret | Sort-Object | Get-Unique - - $values = ($ret | foreach { "$_" }) -join ";" - Say-Verbose "Directories to unpack: $values" - - return $ret -} - -# Example zip content and extraction algorithm: -# Rule: files if extracted are always being extracted to the same relative path locally -# .\ -# a.exe # file does not exist locally, extract -# b.dll # file exists locally, override only if $OverrideFiles set -# aaa\ # same rules as for files -# ... -# abc\1.0.0\ # directory contains version and exists locally -# ... # do not extract content under versioned part -# abc\asd\ # same rules as for files -# ... -# def\ghi\1.0.1\ # directory contains version and does not exist locally -# ... # extract content -function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) { - Say-Invocation $MyInvocation - - Load-Assembly -Assembly System.IO.Compression.FileSystem - Set-Variable -Name Zip - try { - $Zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath) - - $DirectoriesToUnpack = Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package -Zip $Zip -OutPath $OutPath - - foreach ($entry in $Zip.Entries) { - $PathWithVersion = Get-Path-Prefix-With-Version $entry.FullName - if (($PathWithVersion -eq $null) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) { - $DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName) - $DestinationDir = Split-Path -Parent $DestinationPath - $OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath)) - if ((-Not $DestinationPath.EndsWith("\")) -And $OverrideFiles) { - New-Item -ItemType Directory -Force -Path $DestinationDir | Out-Null - [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $DestinationPath, $OverrideNonVersionedFiles) - } - } - } - } - finally { - if ($Zip -ne $null) { - $Zip.Dispose() - } - } -} - -function DownloadFile([Uri]$Uri, [string]$OutPath) { - $Stream = $null - - try { - $Response = GetHTTPResponse -Uri $Uri - $Stream = $Response.Content.ReadAsStreamAsync().Result - $File = [System.IO.File]::Create($OutPath) - $Stream.CopyTo($File) - $File.Close() - } - finally { - if ($Stream -ne $null) { - $Stream.Dispose() - } - } -} - -function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) { - $BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath) - if (-Not $NoPath) { - Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process." - $env:path = "$BinPath;" + $env:path - } - else { - Say "Binaries of dotnet can be found in $BinPath" - } -} - -$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture -$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -Channel $Channel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture -$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -Channel $Channel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture - -if ($DryRun) { - Say "Payload URLs:" - Say "Primary - $DownloadLink" - Say "Legacy - $LegacyDownloadLink" - Say "Repeatable invocation: .\$($MyInvocation.MyCommand) -Version $SpecificVersion -Channel $Channel -Architecture $CLIArchitecture -InstallDir $InstallDir" - exit 0 -} - -$InstallRoot = Resolve-Installation-Path $InstallDir -Say-Verbose "InstallRoot: $InstallRoot" - -$IsSdkInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage "sdk" -SpecificVersion $SpecificVersion -Say-Verbose ".NET SDK installed? $IsSdkInstalled" -if ($IsSdkInstalled) { - Say ".NET SDK version $SpecificVersion is already installed." - Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath - exit 0 -} - -New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null - -$installDrive = $((Get-Item $InstallRoot).PSDrive.Name); -Write-Output "${installDrive}:"; -$free = Get-CimInstance -Class win32_logicaldisk | where Deviceid -eq "${installDrive}:" -if ($free.Freespace / 1MB -le 100 ) { - Say "There is not enough disk space on drive ${installDrive}:" - exit 0 -} - -$ZipPath = [System.IO.Path]::GetTempFileName() -Say-Verbose "Zip path: $ZipPath" -Say "Downloading link: $DownloadLink" -try { - DownloadFile -Uri $DownloadLink -OutPath $ZipPath -} -catch { - Say "Cannot download: $DownloadLink" - $DownloadLink = $LegacyDownloadLink - $ZipPath = [System.IO.Path]::GetTempFileName() - Say-Verbose "Legacy zip path: $ZipPath" - Say "Downloading legacy link: $DownloadLink" - DownloadFile -Uri $DownloadLink -OutPath $ZipPath -} - -Say "Extracting zip from $DownloadLink" -Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot - -Remove-Item $ZipPath - -Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath - -Say "Installation finished" -exit 0 \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh b/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh deleted file mode 100644 index 0ea08a77870a..000000000000 --- a/Tasks/DotNetCoreInstallerV1/externals/install-dotnet.sh +++ /dev/null @@ -1,815 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -# Stop script on NZEC -set -e -# Stop script if unbound variable found (use ${var:-} if intentional) -set -u -# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success -# This is causing it to fail -set -o pipefail - -# Use in the the functions: eval $invocation -invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"' - -# standard output may be used as a return value in the functions -# we need a way to write text on the screen in the functions so that -# it won't interfere with the return value. -# Exposing stream 3 as a pipe to standard output of the script itself -exec 3>&1 - -# Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors. -# See if stdout is a terminal -if [ -t 1 ]; then - # see if it supports colors - ncolors=$(tput colors) - if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then - bold="$(tput bold || echo)" - normal="$(tput sgr0 || echo)" - black="$(tput setaf 0 || echo)" - red="$(tput setaf 1 || echo)" - green="$(tput setaf 2 || echo)" - yellow="$(tput setaf 3 || echo)" - blue="$(tput setaf 4 || echo)" - magenta="$(tput setaf 5 || echo)" - cyan="$(tput setaf 6 || echo)" - white="$(tput setaf 7 || echo)" - fi -fi - -say_err() { - printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2 -} - -say() { - # using stream 3 (defined in the beginning) to not interfere with stdout of functions - # which may be used as return value - printf "%b\n" "${cyan:-}dotnet-install:${normal:-} $1" >&3 -} - -say_verbose() { - if [ "$verbose" = true ]; then - say "$1" - fi -} - -get_os_download_name_from_platform() { - eval $invocation - - platform="$1" - case "$platform" in - "centos.7") - echo "centos" - return 0 - ;; - "debian.8") - echo "debian" - return 0 - ;; - "fedora.23") - echo "fedora.23" - return 0 - ;; - "fedora.24") - echo "fedora.24" - return 0 - ;; - "opensuse.13.2") - echo "opensuse.13.2" - return 0 - ;; - "opensuse.42.1") - echo "opensuse.42.1" - return 0 - ;; - "rhel.7"*) - echo "rhel" - return 0 - ;; - "ubuntu.14.04") - echo "ubuntu" - return 0 - ;; - "ubuntu.16.04") - echo "ubuntu.16.04" - return 0 - ;; - "ubuntu.16.10") - echo "ubuntu.16.10" - return 0 - ;; - "alpine.3.4.3") - echo "alpine" - return 0 - ;; - esac - return 1 -} - -get_current_os_name() { - eval $invocation - - local uname=$(uname) - if [ "$uname" = "Darwin" ]; then - echo "osx" - return 0 - else - if [ "$uname" = "Linux" ]; then - echo "linux" - return 0 - fi - fi - - say_err "OS name could not be detected: $ID.$VERSION_ID" - return 1 -} - -get_distro_specific_os_name() { - eval $invocation - - local uname=$(uname) - if [ "$uname" = "Darwin" ]; then - echo "osx" - return 0 - elif [ -n "$runtime_id" ]; then - echo $(get_os_download_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}") - return 0 - else - if [ -e /etc/os-release ]; then - . /etc/os-release - os=$(get_os_download_name_from_platform "$ID.$VERSION_ID" || echo "") - if [ -n "$os" ]; then - echo "$os" - return 0 - fi - fi - fi - - say_verbose "Distribution specific OS name and version could not be detected: $ID.$VERSION_ID" - return 1 -} - -machine_has() { - eval $invocation - - hash "$1" > /dev/null 2>&1 - return $? -} - - -check_min_reqs() { - local hasMinimum=false - if machine_has "curl"; then - hasMinimum=true - elif machine_has "wget"; then - hasMinimum=true - fi - - if [ "$hasMinimum" = "false" ]; then - say_err "curl (recommended) or wget are required to download dotnet. Install missing prerequisite to proceed." - return 1 - fi - return 0 -} - -check_pre_reqs() { - eval $invocation - - local failing=false; - - if [ "${DOTNET_INSTALL_SKIP_PREREQS:-}" = "1" ]; then - return 0 - fi - - if [ "$(uname)" = "Linux" ]; then - if ! [ -x "$(command -v ldconfig)" ]; then - echo "ldconfig is not in PATH, trying /sbin/ldconfig." - LDCONFIG_COMMAND="/sbin/ldconfig" - else - LDCONFIG_COMMAND="ldconfig" - fi - - [ -z "$($LDCONFIG_COMMAND -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && failing=true - [ -z "$($LDCONFIG_COMMAND -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && failing=true - [ -z "$($LDCONFIG_COMMAND -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && failing=true - fi - - if [ "$failing" = true ]; then - return 1 - fi - - return 0 -} - -# args: -# input - $1 -to_lowercase() { - #eval $invocation - - echo "$1" | tr '[:upper:]' '[:lower:]' - return 0 -} - -# args: -# input - $1 -remove_trailing_slash() { - #eval $invocation - - local input=${1:-} - echo "${input%/}" - return 0 -} - -# args: -# input - $1 -remove_beginning_slash() { - #eval $invocation - - local input=${1:-} - echo "${input#/}" - return 0 -} - -# args: -# root_path - $1 -# child_path - $2 - this parameter can be empty -combine_paths() { - eval $invocation - - # TODO: Consider making it work with any number of paths. For now: - if [ ! -z "${3:-}" ]; then - say_err "combine_paths: Function takes two parameters." - return 1 - fi - - local root_path=$(remove_trailing_slash $1) - local child_path=$(remove_beginning_slash ${2:-}) - say_verbose "combine_paths: root_path=$root_path" - say_verbose "combine_paths: child_path=$child_path" - echo "$root_path/$child_path" - return 0 -} - -get_machine_architecture() { - eval $invocation - - # Currently the only one supported - echo "x64" - return 0 -} - -# args: -# architecture - $1 -get_normalized_architecture_from_architecture() { - eval $invocation - - local architecture=$(to_lowercase $1) - case $architecture in - \) - echo "$(get_normalized_architecture_from_architecture $(get_machine_architecture))" - return 0 - ;; - amd64|x64) - echo "x64" - return 0 - ;; - x86) - say_err "Architecture \`x86\` currently not supported" - return 1 - ;; - esac - - say_err "Architecture \`$architecture\` not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" - return 1 -} - -# version_info is a conceptual two line string representing commit hash and 4-part version -# format: -# Line 1: # commit_hash -# Line 2: # 4-part version - -# args: -# version_text - stdin -get_version_from_version_info() { - eval $invocation - - cat | tail -n 1 - return 0 -} - -# args: -# version_text - stdin -get_commit_hash_from_version_info() { - eval $invocation - - cat | head -n 1 - return 0 -} - -# args: -# install_root - $1 -# relative_path_to_package - $2 -# specific_version - $3 -is_dotnet_package_installed() { - eval $invocation - - local install_root=$1 - local relative_path_to_package=$2 - local specific_version=${3//[$'\t\r\n']} - - local dotnet_package_path=$(combine_paths $(combine_paths $install_root $relative_path_to_package) $specific_version) - say_verbose "is_dotnet_package_installed: dotnet_package_path=$dotnet_package_path" - - if [ -d "$dotnet_package_path" ]; then - return 0 - else - return 1 - fi -} - -# args: -# azure_feed - $1 -# channel - $2 -# normalized_architecture - $3 -get_latest_version_info() { - eval $invocation - - local azure_feed=$1 - local channel=$2 - local normalized_architecture=$3 - local coherent=$4 - - local version_file_url=null - if [ "$shared_runtime" = true ]; then - version_file_url="$uncached_feed/Runtime/$channel/latest.version" - else - if [ "$coherent" = true ]; then - version_file_url="$uncached_feed/Sdk/$channel/latest.coherent.version" - else - version_file_url="$uncached_feed/Sdk/$channel/latest.version" - fi - fi - say_verbose "get_latest_version_info: latest url: $version_file_url" - - download $version_file_url - return $? -} - -# args: -# azure_feed - $1 -# channel - $2 -# normalized_architecture - $3 -# version - $4 -get_specific_version_from_version() { - eval $invocation - - local azure_feed=$1 - local channel=$2 - local normalized_architecture=$3 - local version=$(to_lowercase $4) - - case $version in - latest) - local version_info - version_info="$(get_latest_version_info $azure_feed $channel $normalized_architecture false)" || return 1 - say_verbose "get_specific_version_from_version: version_info=$version_info" - echo "$version_info" | get_version_from_version_info - return 0 - ;; - coherent) - local version_info - version_info="$(get_latest_version_info $azure_feed $channel $normalized_architecture true)" || return 1 - say_verbose "get_specific_version_from_version: version_info=$version_info" - echo "$version_info" | get_version_from_version_info - return 0 - ;; - *) - echo $version - return 0 - ;; - esac -} - -# args: -# azure_feed - $1 -# channel - $2 -# normalized_architecture - $3 -# specific_version - $4 -construct_download_link() { - eval $invocation - - local azure_feed=$1 - local channel=$2 - local normalized_architecture=$3 - local specific_version=${4//[$'\t\r\n']} - - local osname - osname=$(get_current_os_name) || return 1 - - local download_link=null - if [ "$shared_runtime" = true ]; then - download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_version-$osname-$normalized_architecture.tar.gz" - else - download_link="$azure_feed/Sdk/$specific_version/dotnet-sdk-$specific_version-$osname-$normalized_architecture.tar.gz" - fi - - echo "$download_link" - return 0 -} - -# args: -# azure_feed - $1 -# channel - $2 -# normalized_architecture - $3 -# specific_version - $4 -construct_legacy_download_link() { - eval $invocation - - local azure_feed=$1 - local channel=$2 - local normalized_architecture=$3 - local specific_version=${4//[$'\t\r\n']} - - local distro_specific_osname - distro_specific_osname=$(get_distro_specific_os_name) || return 1 - - local legacy_download_link=null - if [ "$shared_runtime" = true ]; then - legacy_download_link="$azure_feed/Runtime/$specific_version/dotnet-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz" - else - legacy_download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz" - fi - - echo "$legacy_download_link" - return 0 -} - -get_user_install_path() { - eval $invocation - - if [ ! -z "${DOTNET_INSTALL_DIR:-}" ]; then - echo $DOTNET_INSTALL_DIR - else - echo "$HOME/.dotnet" - fi - return 0 -} - -# args: -# install_dir - $1 -resolve_installation_path() { - eval $invocation - - local install_dir=$1 - if [ "$install_dir" = "" ]; then - local user_install_path=$(get_user_install_path) - say_verbose "resolve_installation_path: user_install_path=$user_install_path" - echo "$user_install_path" - return 0 - fi - - echo "$install_dir" - return 0 -} - -# args: -# install_root - $1 -get_installed_version_info() { - eval $invocation - - local install_root=$1 - local version_file=$(combine_paths "$install_root" "$local_version_file_relative_path") - say_verbose "Local version file: $version_file" - if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then - local version_info="$(cat $version_file)" - echo "$version_info" - return 0 - fi - - say_verbose "Local version file not found." - return 0 -} - -# args: -# relative_or_absolute_path - $1 -get_absolute_path() { - eval $invocation - - local relative_or_absolute_path=$1 - echo $(cd $(dirname "$1") && pwd -P)/$(basename "$1") - return 0 -} - -# args: -# input_files - stdin -# root_path - $1 -# out_path - $2 -# override - $3 -copy_files_or_dirs_from_list() { - eval $invocation - - local root_path=$(remove_trailing_slash $1) - local out_path=$(remove_trailing_slash $2) - local override=$3 - local override_switch=$(if [ "$override" = false ]; then printf -- "-n"; fi) - - cat | uniq | while read -r file_path; do - local path=$(remove_beginning_slash ${file_path#$root_path}) - local target=$out_path/$path - if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then - mkdir -p $out_path/$(dirname $path) - cp -R $override_switch $root_path/$path $target - fi - done -} - -# args: -# zip_path - $1 -# out_path - $2 -extract_dotnet_package() { - eval $invocation - - local zip_path=$1 - local out_path=$2 - - local temp_out_path=$(mktemp -d $temporary_file_template) - - local failed=false - tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true - - local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/' - find $temp_out_path -type f | grep -Eo $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path false - find $temp_out_path -type f | grep -Ev $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path true - - rm -rf $temp_out_path - - if [ "$failed" = true ]; then - say_err "Extraction failed" - return 1 - fi -} - -# args: -# remote_path - $1 -# [out_path] - $2 - stdout if not provided -download() { - eval $invocation - - local remote_path=$1 - local out_path=${2:-} - - local failed=false - if machine_has "curl"; then - downloadcurl $remote_path $out_path || failed=true - elif machine_has "wget"; then - downloadwget $remote_path $out_path || failed=true - else - failed=true - fi - if [ "$failed" = true ]; then - say_verbose "Download failed: $remote_path" - return 1 - fi - return 0 -} - -downloadcurl() { - eval $invocation - local remote_path=$1 - local out_path=${2:-} - - local failed=false - if [ -z "$out_path" ]; then - curl --retry 10 -sSL -f --create-dirs $remote_path || failed=true - else - curl --retry 10 -sSL -f --create-dirs -o $out_path $remote_path || failed=true - fi - if [ "$failed" = true ]; then - say_verbose "Curl download failed" - return 1 - fi - return 0 -} - -downloadwget() { - eval $invocation - local remote_path=$1 - local out_path=${2:-} - - local failed=false - if [ -z "$out_path" ]; then - wget -q --tries 10 $remote_path || failed=true - else - wget -v --tries 10 -O $out_path $remote_path || failed=true - fi - if [ "$failed" = true ]; then - say_verbose "Wget download failed" - return 1 - fi - return 0 -} - -calculate_vars() { - eval $invocation - valid_legacy_download_link=true - - normalized_architecture=$(get_normalized_architecture_from_architecture "$architecture") - say_verbose "normalized_architecture=$normalized_architecture" - - specific_version=$(get_specific_version_from_version $azure_feed $channel $normalized_architecture $version) - say_verbose "specific_version=$specific_version" - if [ -z "$specific_version" ]; then - say_err "Could not get version information." - return 1 - fi - - download_link=$(construct_download_link $azure_feed $channel $normalized_architecture $specific_version) - say_verbose "download_link=$download_link" - - legacy_download_link=$(construct_legacy_download_link $azure_feed $channel $normalized_architecture $specific_version) || valid_legacy_download_link=false - - if [ "$valid_legacy_download_link" = true ]; then - say_verbose "legacy_download_link=$legacy_download_link" - else - say_verbose "Cound not construct a legacy_download_link; omitting..." - fi - - install_root=$(resolve_installation_path $install_dir) - say_verbose "install_root=$install_root" -} - -install_dotnet() { - eval $invocation - local download_failed=false - - if is_dotnet_package_installed $install_root "sdk" $specific_version; then - say ".NET SDK version $specific_version is already installed." - return 0 - fi - - mkdir -p $install_root - zip_path=$(mktemp $temporary_file_template) - say_verbose "Zip path: $zip_path" - - say "Downloading link: $download_link" - download "$download_link" $zip_path || download_failed=true - - # if the download fails, download the legacy_download_link - if [ "$download_failed" = true ] && [ "$valid_legacy_download_link" = true ]; then - say "Cannot download: $download_link" - download_link=$legacy_download_link - zip_path=$(mktemp $temporary_file_template) - say_verbose "Legacy zip path: $zip_path" - say "Downloading legacy link: $download_link" - download "$download_link" $zip_path - fi - - say "Extracting zip from $download_link" - extract_dotnet_package $zip_path $install_root - - return 0 -} - -local_version_file_relative_path="/.version" -bin_folder_relative_path="" -temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX" - -channel="LTS" -version="Latest" -install_dir="" -architecture="" -dry_run=false -no_path=false -azure_feed="https://dotnetcli.azureedge.net/dotnet" -uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet" -verbose=false -shared_runtime=false -runtime_id="" - -while [ $# -ne 0 ] -do - name=$1 - case $name in - -c|--channel|-[Cc]hannel) - shift - channel=$1 - ;; - -v|--version|-[Vv]ersion) - shift - version="$1" - ;; - -i|--install-dir|-[Ii]nstall[Dd]ir) - shift - install_dir="$1" - ;; - --arch|--architecture|-[Aa]rch|-[Aa]rchitecture) - shift - architecture="$1" - ;; - --shared-runtime|-[Ss]hared[Rr]untime) - shared_runtime=true - ;; - --dry-run|-[Dd]ry[Rr]un) - dry_run=true - ;; - --no-path|-[Nn]o[Pp]ath) - no_path=true - ;; - --verbose|-[Vv]erbose) - verbose=true - ;; - --azure-feed|-[Aa]zure[Ff]eed) - shift - azure_feed="$1" - ;; - --uncached-feed|-[Uu]ncached[Ff]eed) - shift - uncached_feed="$1" - ;; - --runtime-id|-[Rr]untime[Ii]d) - shift - runtime_id="$1" - ;; - -?|--?|-h|--help|-[Hh]elp) - script_name="$(basename $0)" - echo ".NET Tools Installer" - echo "Usage: $script_name [-c|--channel ] [-v|--version ] [-p|--prefix ]" - echo " $script_name -h|-?|--help" - echo "" - echo "$script_name is a simple command line interface for obtaining dotnet cli." - echo "" - echo "Options:" - echo " -c,--channel Download from the CHANNEL specified, Defaults to \`$channel\`." - echo " -Channel" - echo " Possible values:" - echo " - Current - most current release" - echo " - LTS - most current supported release" - echo " - 2-part version in a format A.B - represents a specific release" - echo " examples: 2.0; 1.0" - echo " - Branch name" - echo " examples: release/2.0.0; Master" - echo " -v,--version Use specific VERSION, Defaults to \`$version\`." - echo " -Version" - echo " Possible values:" - echo " - latest - most latest build on specific channel" - echo " - coherent - most latest coherent build on specific channel" - echo " coherent applies only to SDK downloads" - echo " - 3-part version in a format A.B.C - represents specific version of build" - echo " examples: 2.0.0-preview2-006120; 1.1.0" - echo " -i,--install-dir
    Install under specified location (see Install Location below)" - echo " -InstallDir" - echo " --architecture Architecture of .NET Tools. Currently only x64 is supported." - echo " --arch,-Architecture,-Arch" - echo " --shared-runtime Installs just the shared runtime bits, not the entire SDK." - echo " -SharedRuntime" - echo " --dry-run,-DryRun Do not perform installation. Display download link." - echo " --no-path, -NoPath Do not set PATH for the current process." - echo " --verbose,-Verbose Display diagnostics information." - echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user." - echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user." - echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)." - echo " -RuntimeId" - echo " -?,--?,-h,--help,-Help Shows this help message" - echo "" - echo "Install Location:" - echo " Location is chosen in following order:" - echo " - --install-dir option" - echo " - Environmental variable DOTNET_INSTALL_DIR" - echo " - $HOME/.dotnet" - exit 0 - ;; - *) - say_err "Unknown argument \`$name\`" - exit 1 - ;; - esac - - shift -done - -check_min_reqs -calculate_vars - -if [ "$dry_run" = true ]; then - say "Payload URL: $download_link" - if [ "$valid_legacy_download_link" = true ]; then - say "Legacy payload URL: $legacy_download_link" - fi - say "Repeatable invocation: ./$(basename $0) --version $specific_version --channel $channel --install-dir $install_dir" - exit 0 -fi - -check_pre_reqs -install_dotnet - -bin_path=$(get_absolute_path $(combine_paths $install_root $bin_folder_relative_path)) -if [ "$no_path" = false ]; then - say "Adding to current process PATH: \`$bin_path\`. Note: This change will be visible only when sourcing script." - export PATH=$bin_path:$PATH -else - say "Binaries of dotnet can be found in $bin_path" -fi - -say "Installation finished successfully." \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/package-lock.json b/Tasks/DotNetCoreInstallerV1/package-lock.json index 1de1c7a61380..150a476f905a 100644 --- a/Tasks/DotNetCoreInstallerV1/package-lock.json +++ b/Tasks/DotNetCoreInstallerV1/package-lock.json @@ -4,6 +4,21 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/mocha": { + "version": "2.2.48", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", + "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==" + }, + "@types/node": { + "version": "6.14.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.4.tgz", + "integrity": "sha512-UqB7h2dVJr/KdZXRMJIhNUWT0HXVe9UNvfLCOsqiSGKAVaAp0QniYHlU9yegxyG6Ug2rc7VdAD4hYj3VghqvAw==" + }, + "@types/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz", + "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -42,9 +57,9 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, "semver-compare": { "version": "1.0.0", @@ -88,7 +103,7 @@ "minimatch": "3.0.4", "mockery": "1.7.0", "q": "1.5.1", - "semver": "5.4.1", + "semver": "5.6.0", "shelljs": "0.3.0", "uuid": "3.2.1" } @@ -98,7 +113,7 @@ "resolved": "https://registry.npmjs.org/vsts-task-tool-lib/-/vsts-task-tool-lib-0.4.1.tgz", "integrity": "sha1-mYLTv14YS95SqpdCGJROEGJzRWU=", "requires": { - "semver": "5.4.1", + "semver": "5.6.0", "semver-compare": "1.0.0", "typed-rest-client": "0.11.0", "uuid": "3.2.1", @@ -113,7 +128,7 @@ "minimatch": "3.0.4", "mockery": "1.7.0", "q": "1.5.1", - "semver": "5.4.1", + "semver": "5.6.0", "shelljs": "0.3.0", "uuid": "3.2.1" } diff --git a/Tasks/DotNetCoreInstallerV1/package.json b/Tasks/DotNetCoreInstallerV1/package.json index ad44d05af7f2..1db826fdadb1 100644 --- a/Tasks/DotNetCoreInstallerV1/package.json +++ b/Tasks/DotNetCoreInstallerV1/package.json @@ -23,8 +23,12 @@ }, "homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme", "dependencies": { + "@types/mocha": "^2.2.5", + "@types/node": "^6.0.101", + "@types/q": "^1.5.0", "vsts-task-lib": "2.0.6", "vsts-task-tool-lib": "0.4.1", - "typed-rest-client": "0.11.0" + "typed-rest-client": "0.11.0", + "semver": "5.6.0" } } diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index afee53592eef..db787b9659ec 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -105,6 +105,36 @@ "CouldNotDownload": "Could not download installation package from this URL: %s Error: %s", "FailedToDownloadPackage": "Failed to download package for installation", "PrependGlobalToolPath": "Creating global tool path and pre-prending to PATH.", - "VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/" + "VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/", + "MatchingVersionNotFound": "No matching version could be found for specified version: %s Kindly note the preview versions are only considered in latest version searches if Include Preview Versions checkbox is checked.", + "UnableToAccessPath": "Unable to access path: %s. Error: %s \n please make sure that agent process has path to the path.", + "VersionCanNotBeDownloadedFromUrl": "Version: %s cannot be downloaded from URL: %s. Either the URL or version is incorrect.", + "CopyingFoldersIntoPath": "Copying all root folders into installation path: %s", + "CopyingFilesIntoPath": "Copying root files (such as dotnet.exe) into installation path: %s", + "FailedToCopyTopLevelFiles": "Failed to copy root files into installation path: %s. Error: %s", + "FailedWhileInstallingVersionAtPath" : "Failed while installing version: %s at path: %s with error: %s", + "ExplicitVersionRequired": "Version: %s is not allowed. Versions to be installed should be of format: major.minor.patchversion. For example: 2.2.1", + "VersionFoundInCache": "Version: %s was found in cache.", + "VersionNotFoundInCache": "Version %s was not found in cache.", + "CreatingInstallationCompeleteFile": "Creating installation complete file for .Net core %s version %s", + "CannotFindRuntimeVersionForCompletingInstallation": "Cannot find runtime version for package type: %s with version: %s", + "PathNotFoundException": "Path: %s could not be located/found. Make sure the path exists.", + "VersionIsLocalLatest": "Version: %s is the latest among the versions present at path: %s", + "VersionIsNotLocalLatest": "Version: %s is not the latest among the versions present at %s", + "DownloadUrlForMatchingOsNotFound": "Download URL for .Net Core %s version %s could not be found for the following OS platforms (rid): %s", + "ExceptionWhileDownloadOrReadReleasesIndex": "Failed to download or parse release-index.json with error: %s", + "MatchingVersionForUserInputVersion": "Found version %s in channel %s for user specified version spec: %s", + "UrlForReleaseChannelNotFound": "Could not find URL for releases.json of channel version: %s", + "NoSuitableChannelWereFound": "Channel corresponding to version %s could not be found.", + "DetectingPlatform": "Detecting OS platform to find correct download package for the OS.", + "FailedInDetectingMachineArch": "Failed while detecting machine OS platform with error: %s", + "runtimeVersionPropertyNotFound": "runtime-version property could not be found for .Net Core %s version %s.", + "VersionNotFound": "Version matching: %s could not be found", + "VersionNotAllowed": "Version %s is not allowed. Allowed version types are: majorVersion.x, majorVersion.minorVersion.x, majorVersion.minorVersion.patchVersion", + "VersionsCanNotBeCompared": "Versions %s and %s cannot be compared. Both versions should be explicit.", + "FileNameNotCorrectCompleteFileName": "File name %s is not correct version.complete file name.", + "ChannelVersionsNotComparable": "Channel versions %s and %s can not be compared. They both must have numeric major and minor versions.", + "LookingForVersionInChannel": "Searching for version in channel %s", + "FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels." } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/task.loc.json b/Tasks/DotNetCoreInstallerV1/task.loc.json index 3e3a349626a1..50803f633e08 100644 --- a/Tasks/DotNetCoreInstallerV1/task.loc.json +++ b/Tasks/DotNetCoreInstallerV1/task.loc.json @@ -105,6 +105,36 @@ "CouldNotDownload": "ms-resource:loc.messages.CouldNotDownload", "FailedToDownloadPackage": "ms-resource:loc.messages.FailedToDownloadPackage", "PrependGlobalToolPath": "ms-resource:loc.messages.PrependGlobalToolPath", - "VersionsFileMalformed": "ms-resource:loc.messages.VersionsFileMalformed" + "VersionsFileMalformed": "ms-resource:loc.messages.VersionsFileMalformed", + "MatchingVersionNotFound": "ms-resource:loc.messages.MatchingVersionNotFound", + "UnableToAccessPath": "ms-resource:loc.messages.UnableToAccessPath", + "VersionCanNotBeDownloadedFromUrl": "ms-resource:loc.messages.VersionCanNotBeDownloadedFromUrl", + "CopyingFoldersIntoPath": "ms-resource:loc.messages.CopyingFoldersIntoPath", + "CopyingFilesIntoPath": "ms-resource:loc.messages.CopyingFilesIntoPath", + "FailedToCopyTopLevelFiles": "ms-resource:loc.messages.FailedToCopyTopLevelFiles", + "FailedWhileInstallingVersionAtPath": "ms-resource:loc.messages.FailedWhileInstallingVersionAtPath", + "ExplicitVersionRequired": "ms-resource:loc.messages.ExplicitVersionRequired", + "VersionFoundInCache": "ms-resource:loc.messages.VersionFoundInCache", + "VersionNotFoundInCache": "ms-resource:loc.messages.VersionNotFoundInCache", + "CreatingInstallationCompeleteFile": "ms-resource:loc.messages.CreatingInstallationCompeleteFile", + "CannotFindRuntimeVersionForCompletingInstallation": "ms-resource:loc.messages.CannotFindRuntimeVersionForCompletingInstallation", + "PathNotFoundException": "ms-resource:loc.messages.PathNotFoundException", + "VersionIsLocalLatest": "ms-resource:loc.messages.VersionIsLocalLatest", + "VersionIsNotLocalLatest": "ms-resource:loc.messages.VersionIsNotLocalLatest", + "DownloadUrlForMatchingOsNotFound": "ms-resource:loc.messages.DownloadUrlForMatchingOsNotFound", + "ExceptionWhileDownloadOrReadReleasesIndex": "ms-resource:loc.messages.ExceptionWhileDownloadOrReadReleasesIndex", + "MatchingVersionForUserInputVersion": "ms-resource:loc.messages.MatchingVersionForUserInputVersion", + "UrlForReleaseChannelNotFound": "ms-resource:loc.messages.UrlForReleaseChannelNotFound", + "NoSuitableChannelWereFound": "ms-resource:loc.messages.NoSuitableChannelWereFound", + "DetectingPlatform": "ms-resource:loc.messages.DetectingPlatform", + "FailedInDetectingMachineArch": "ms-resource:loc.messages.FailedInDetectingMachineArch", + "runtimeVersionPropertyNotFound": "ms-resource:loc.messages.runtimeVersionPropertyNotFound", + "VersionNotFound": "ms-resource:loc.messages.VersionNotFound", + "VersionNotAllowed": "ms-resource:loc.messages.VersionNotAllowed", + "VersionsCanNotBeCompared": "ms-resource:loc.messages.VersionsCanNotBeCompared", + "FileNameNotCorrectCompleteFileName": "ms-resource:loc.messages.FileNameNotCorrectCompleteFileName", + "ChannelVersionsNotComparable": "ms-resource:loc.messages.ChannelVersionsNotComparable", + "LookingForVersionInChannel": "ms-resource:loc.messages.LookingForVersionInChannel", + "FallingBackToAdjacentChannels": "ms-resource:loc.messages.FallingBackToAdjacentChannels" } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings.json b/Tasks/DotNetCoreInstallerV1/typings.json deleted file mode 100644 index d229810488e2..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "vsts-tasks-dotnetcoreinstaller", - "dependencies": {}, - "globalDependencies": { - "mocha": "registry:dt/mocha#2.2.5+20160720003353", - "node": "registry:dt/node#6.0.0+20160914131736", - "q": "registry:dt/q#0.0.0+20160613154756" - } -} diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts deleted file mode 100644 index be39944f1a3a..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/index.d.ts +++ /dev/null @@ -1,202 +0,0 @@ -// Generated by typings -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/a361a8ab3c327f208d3f82ad206971d4a63d8c25/mocha/mocha.d.ts -interface MochaSetupOptions { - //milliseconds to wait before considering a test slow - slow?: number; - - // timeout in milliseconds - timeout?: number; - - // ui name "bdd", "tdd", "exports" etc - ui?: string; - - //array of accepted globals - globals?: any[]; - - // reporter instance (function or string), defaults to `mocha.reporters.Spec` - reporter?: any; - - // bail on the first test failure - bail?: boolean; - - // ignore global leaks - ignoreLeaks?: boolean; - - // grep string or regexp to filter tests with - grep?: any; -} - -declare var mocha: Mocha; -declare var describe: Mocha.IContextDefinition; -declare var xdescribe: Mocha.IContextDefinition; -// alias for `describe` -declare var context: Mocha.IContextDefinition; -// alias for `describe` -declare var suite: Mocha.IContextDefinition; -declare var it: Mocha.ITestDefinition; -declare var xit: Mocha.ITestDefinition; -// alias for `it` -declare var test: Mocha.ITestDefinition; -declare var specify: Mocha.ITestDefinition; - -interface MochaDone { - (error?: any): any; -} - -interface ActionFunction { - (done: MochaDone): any | PromiseLike -} - -declare function setup(action: ActionFunction): void; -declare function teardown(action: ActionFunction): void; -declare function suiteSetup(action: ActionFunction): void; -declare function suiteTeardown(action: ActionFunction): void; -declare function before(action: ActionFunction): void; -declare function before(description: string, action: ActionFunction): void; -declare function after(action: ActionFunction): void; -declare function after(description: string, action: ActionFunction): void; -declare function beforeEach(action: ActionFunction): void; -declare function beforeEach(description: string, action: ActionFunction): void; -declare function afterEach(action: ActionFunction): void; -declare function afterEach(description: string, action: ActionFunction): void; - -declare class Mocha { - currentTest: Mocha.ITestDefinition; - constructor(options?: { - grep?: RegExp; - ui?: string; - reporter?: string; - timeout?: number; - bail?: boolean; - }); - - /** Setup mocha with the given options. */ - setup(options: MochaSetupOptions): Mocha; - bail(value?: boolean): Mocha; - addFile(file: string): Mocha; - /** Sets reporter by name, defaults to "spec". */ - reporter(name: string): Mocha; - /** Sets reporter constructor, defaults to mocha.reporters.Spec. */ - reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha; - ui(value: string): Mocha; - grep(value: string): Mocha; - grep(value: RegExp): Mocha; - invert(): Mocha; - ignoreLeaks(value: boolean): Mocha; - checkLeaks(): Mocha; - /** - * Function to allow assertion libraries to throw errors directly into mocha. - * This is useful when running tests in a browser because window.onerror will - * only receive the 'message' attribute of the Error. - */ - throwError(error: Error): void; - /** Enables growl support. */ - growl(): Mocha; - globals(value: string): Mocha; - globals(values: string[]): Mocha; - useColors(value: boolean): Mocha; - useInlineDiffs(value: boolean): Mocha; - timeout(value: number): Mocha; - slow(value: number): Mocha; - enableTimeouts(value: boolean): Mocha; - asyncOnly(value: boolean): Mocha; - noHighlighting(value: boolean): Mocha; - /** Runs tests and invokes `onComplete()` when finished. */ - run(onComplete?: (failures: number) => void): Mocha.IRunner; -} - -// merge the Mocha class declaration with a module -declare namespace Mocha { - /** Partial interface for Mocha's `Runnable` class. */ - interface IRunnable { - title: string; - fn: Function; - async: boolean; - sync: boolean; - timedOut: boolean; - } - - /** Partial interface for Mocha's `Suite` class. */ - interface ISuite { - parent: ISuite; - title: string; - - fullTitle(): string; - } - - /** Partial interface for Mocha's `Test` class. */ - interface ITest extends IRunnable { - parent: ISuite; - pending: boolean; - - fullTitle(): string; - } - - /** Partial interface for Mocha's `Runner` class. */ - interface IRunner {} - - interface IContextDefinition { - (description: string, spec: () => void): ISuite; - only(description: string, spec: () => void): ISuite; - skip(description: string, spec: () => void): void; - timeout(ms: number): void; - } - - interface ITestDefinition { - (expectation: string, assertion?: ActionFunction): ITest; - only(expectation: string, assertion?: ActionFunction): ITest; - skip(expectation: string, assertion?: ActionFunction): void; - timeout(ms: number): void; - state: "failed" | "passed"; - } - - export module reporters { - export class Base { - stats: { - suites: number; - tests: number; - passes: number; - pending: number; - failures: number; - }; - - constructor(runner: IRunner); - } - - export class Doc extends Base {} - export class Dot extends Base {} - export class HTML extends Base {} - export class HTMLCov extends Base {} - export class JSON extends Base {} - export class JSONCov extends Base {} - export class JSONStream extends Base {} - export class Landing extends Base {} - export class List extends Base {} - export class Markdown extends Base {} - export class Min extends Base {} - export class Nyan extends Base {} - export class Progress extends Base { - /** - * @param options.open String used to indicate the start of the progress bar. - * @param options.complete String used to indicate a complete test on the progress bar. - * @param options.incomplete String used to indicate an incomplete test on the progress bar. - * @param options.close String used to indicate the end of the progress bar. - */ - constructor(runner: IRunner, options?: { - open?: string; - complete?: string; - incomplete?: string; - close?: string; - }); - } - export class Spec extends Base {} - export class TAP extends Base {} - export class XUnit extends Base { - constructor(runner: IRunner, options?: any); - } - } -} - -declare module "mocha" { - export = Mocha; -} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json b/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json deleted file mode 100644 index aab9d1c1302c..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings/globals/mocha/typings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "resolution": "main", - "tree": { - "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/a361a8ab3c327f208d3f82ad206971d4a63d8c25/mocha/mocha.d.ts", - "raw": "registry:dt/mocha#2.2.5+20160720003353", - "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/a361a8ab3c327f208d3f82ad206971d4a63d8c25/mocha/mocha.d.ts" - } -} diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts deleted file mode 100644 index b66d17439524..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings/globals/node/index.d.ts +++ /dev/null @@ -1,3084 +0,0 @@ -// Generated by typings -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/3423aa94ffdbe8f4ded33733318e08020a2d6ca8/node/node.d.ts -interface Error { - stack?: string; -} - -interface ErrorConstructor { - captureStackTrace(targetObject: Object, constructorOpt?: Function): void; - stackTraceLimit: number; -} - -// compat for TypeScript 1.8 -// if you use with --target es3 or --target es5 and use below definitions, -// use the lib.es6.d.ts that is bundled with TypeScript 1.8. -interface MapConstructor { } -interface WeakMapConstructor { } -interface SetConstructor { } -interface WeakSetConstructor { } - -/************************************************ -* * -* GLOBAL * -* * -************************************************/ -declare var process: NodeJS.Process; -declare var global: NodeJS.Global; - -declare var __filename: string; -declare var __dirname: string; - -declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; -declare function clearTimeout(timeoutId: NodeJS.Timer): void; -declare function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; -declare function clearInterval(intervalId: NodeJS.Timer): void; -declare function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; -declare function clearImmediate(immediateId: any): void; - -interface NodeRequireFunction { - (id: string): any; -} - -interface NodeRequire extends NodeRequireFunction { - resolve(id: string): string; - cache: any; - extensions: any; - main: any; -} - -declare var require: NodeRequire; - -interface NodeModule { - exports: any; - require: NodeRequireFunction; - id: string; - filename: string; - loaded: boolean; - parent: any; - children: any[]; -} - -declare var module: NodeModule; - -// Same as module.exports -declare var exports: any; -declare var SlowBuffer: { - new (str: string, encoding?: string): Buffer; - new (size: number): Buffer; - new (size: Uint8Array): Buffer; - new (array: any[]): Buffer; - prototype: Buffer; - isBuffer(obj: any): boolean; - byteLength(string: string, encoding?: string): number; - concat(list: Buffer[], totalLength?: number): Buffer; -}; - - -// Buffer class -type BufferEncoding = "ascii" | "utf8" | "utf16le" | "ucs2" | "binary" | "hex"; -interface Buffer extends NodeBuffer { } - -/** - * Raw data is stored in instances of the Buffer class. - * A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized. - * Valid string encodings: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' - */ -declare var Buffer: { - /** - * Allocates a new buffer containing the given {str}. - * - * @param str String to store in buffer. - * @param encoding encoding to use, optional. Default is 'utf8' - */ - new (str: string, encoding?: string): Buffer; - /** - * Allocates a new buffer of {size} octets. - * - * @param size count of octets to allocate. - */ - new (size: number): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - */ - new (array: Uint8Array): Buffer; - /** - * Produces a Buffer backed by the same allocated memory as - * the given {ArrayBuffer}. - * - * - * @param arrayBuffer The ArrayBuffer with which to share memory. - */ - new (arrayBuffer: ArrayBuffer): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - */ - new (array: any[]): Buffer; - /** - * Copies the passed {buffer} data onto a new {Buffer} instance. - * - * @param buffer The buffer to copy. - */ - new (buffer: Buffer): Buffer; - prototype: Buffer; - /** - * Allocates a new Buffer using an {array} of octets. - * - * @param array - */ - from(array: any[]): Buffer; - /** - * When passed a reference to the .buffer property of a TypedArray instance, - * the newly created Buffer will share the same allocated memory as the TypedArray. - * The optional {byteOffset} and {length} arguments specify a memory range - * within the {arrayBuffer} that will be shared by the Buffer. - * - * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() - * @param byteOffset - * @param length - */ - from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; - /** - * Copies the passed {buffer} data onto a new Buffer instance. - * - * @param buffer - */ - from(buffer: Buffer): Buffer; - /** - * Creates a new Buffer containing the given JavaScript string {str}. - * If provided, the {encoding} parameter identifies the character encoding. - * If not provided, {encoding} defaults to 'utf8'. - * - * @param str - */ - from(str: string, encoding?: string): Buffer; - /** - * Returns true if {obj} is a Buffer - * - * @param obj object to test. - */ - isBuffer(obj: any): obj is Buffer; - /** - * Returns true if {encoding} is a valid encoding argument. - * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' - * - * @param encoding string to test. - */ - isEncoding(encoding: string): boolean; - /** - * Gives the actual byte length of a string. encoding defaults to 'utf8'. - * This is not the same as String.prototype.length since that returns the number of characters in a string. - * - * @param string string to test. - * @param encoding encoding used to evaluate (defaults to 'utf8') - */ - byteLength(string: string, encoding?: string): number; - /** - * Returns a buffer which is the result of concatenating all the buffers in the list together. - * - * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. - * If the list has exactly one item, then the first item of the list is returned. - * If the list has more than one item, then a new Buffer is created. - * - * @param list An array of Buffer objects to concatenate - * @param totalLength Total length of the buffers when concatenated. - * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. - */ - concat(list: Buffer[], totalLength?: number): Buffer; - /** - * The same as buf1.compare(buf2). - */ - compare(buf1: Buffer, buf2: Buffer): number; - /** - * Allocates a new buffer of {size} octets. - * - * @param size count of octets to allocate. - * @param fill if specified, buffer will be initialized by calling buf.fill(fill). - * If parameter is omitted, buffer will be filled with zeros. - * @param encoding encoding used for call to buf.fill while initalizing - */ - alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; - /** - * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents - * of the newly created Buffer are unknown and may contain sensitive data. - * - * @param size count of octets to allocate - */ - allocUnsafe(size: number): Buffer; - /** - * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents - * of the newly created Buffer are unknown and may contain sensitive data. - * - * @param size count of octets to allocate - */ - allocUnsafeSlow(size: number): Buffer; -}; - -/************************************************ -* * -* GLOBAL INTERFACES * -* * -************************************************/ -declare namespace NodeJS { - export interface ErrnoException extends Error { - errno?: string; - code?: string; - path?: string; - syscall?: string; - stack?: string; - } - - export class EventEmitter { - addListener(event: string, listener: Function): this; - on(event: string, listener: Function): this; - once(event: string, listener: Function): this; - removeListener(event: string, listener: Function): this; - removeAllListeners(event?: string): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string): Function[]; - emit(event: string, ...args: any[]): boolean; - listenerCount(type: string): number; - // Added in Node 6... - prependListener(event: string, listener: Function): this; - prependOnceListener(event: string, listener: Function): this; - eventNames(): string[]; - } - - export interface ReadableStream extends EventEmitter { - readable: boolean; - read(size?: number): string | Buffer; - setEncoding(encoding: string): void; - pause(): ReadableStream; - resume(): ReadableStream; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: string): void; - unshift(chunk: Buffer): void; - wrap(oldStream: ReadableStream): ReadableStream; - } - - export interface WritableStream extends EventEmitter { - writable: boolean; - write(buffer: Buffer | string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - } - - export interface ReadWriteStream extends ReadableStream, WritableStream { - pause(): ReadWriteStream; - resume(): ReadWriteStream; - } - - export interface Events extends EventEmitter { } - - export interface Domain extends Events { - run(fn: Function): void; - add(emitter: Events): void; - remove(emitter: Events): void; - bind(cb: (err: Error, data: any) => any): any; - intercept(cb: (data: any) => any): any; - dispose(): void; - - addListener(event: string, listener: Function): this; - on(event: string, listener: Function): this; - once(event: string, listener: Function): this; - removeListener(event: string, listener: Function): this; - removeAllListeners(event?: string): this; - } - - export interface MemoryUsage { - rss: number; - heapTotal: number; - heapUsed: number; - } - - export interface ProcessVersions { - http_parser: string; - node: string; - v8: string; - ares: string; - uv: string; - zlib: string; - modules: string; - openssl: string; - } - - export interface Process extends EventEmitter { - stdout: WritableStream; - stderr: WritableStream; - stdin: ReadableStream; - argv: string[]; - execArgv: string[]; - execPath: string; - abort(): void; - chdir(directory: string): void; - cwd(): string; - env: any; - exit(code?: number): void; - exitCode: number; - getgid(): number; - setgid(id: number): void; - setgid(id: string): void; - getuid(): number; - setuid(id: number): void; - setuid(id: string): void; - version: string; - versions: ProcessVersions; - config: { - target_defaults: { - cflags: any[]; - default_configuration: string; - defines: string[]; - include_dirs: string[]; - libraries: string[]; - }; - variables: { - clang: number; - host_arch: string; - node_install_npm: boolean; - node_install_waf: boolean; - node_prefix: string; - node_shared_openssl: boolean; - node_shared_v8: boolean; - node_shared_zlib: boolean; - node_use_dtrace: boolean; - node_use_etw: boolean; - node_use_openssl: boolean; - target_arch: string; - v8_no_strict_aliasing: number; - v8_use_snapshot: boolean; - visibility: string; - }; - }; - kill(pid: number, signal?: string | number): void; - pid: number; - title: string; - arch: string; - platform: string; - memoryUsage(): MemoryUsage; - nextTick(callback: Function, ...args: any[]): void; - umask(mask?: number): number; - uptime(): number; - hrtime(time?: number[]): number[]; - domain: Domain; - - // Worker - send?(message: any, sendHandle?: any): void; - disconnect(): void; - connected: boolean; - } - - export interface Global { - Array: typeof Array; - ArrayBuffer: typeof ArrayBuffer; - Boolean: typeof Boolean; - Buffer: typeof Buffer; - DataView: typeof DataView; - Date: typeof Date; - Error: typeof Error; - EvalError: typeof EvalError; - Float32Array: typeof Float32Array; - Float64Array: typeof Float64Array; - Function: typeof Function; - GLOBAL: Global; - Infinity: typeof Infinity; - Int16Array: typeof Int16Array; - Int32Array: typeof Int32Array; - Int8Array: typeof Int8Array; - Intl: typeof Intl; - JSON: typeof JSON; - Map: MapConstructor; - Math: typeof Math; - NaN: typeof NaN; - Number: typeof Number; - Object: typeof Object; - Promise: Function; - RangeError: typeof RangeError; - ReferenceError: typeof ReferenceError; - RegExp: typeof RegExp; - Set: SetConstructor; - String: typeof String; - Symbol: Function; - SyntaxError: typeof SyntaxError; - TypeError: typeof TypeError; - URIError: typeof URIError; - Uint16Array: typeof Uint16Array; - Uint32Array: typeof Uint32Array; - Uint8Array: typeof Uint8Array; - Uint8ClampedArray: Function; - WeakMap: WeakMapConstructor; - WeakSet: WeakSetConstructor; - clearImmediate: (immediateId: any) => void; - clearInterval: (intervalId: NodeJS.Timer) => void; - clearTimeout: (timeoutId: NodeJS.Timer) => void; - console: typeof console; - decodeURI: typeof decodeURI; - decodeURIComponent: typeof decodeURIComponent; - encodeURI: typeof encodeURI; - encodeURIComponent: typeof encodeURIComponent; - escape: (str: string) => string; - eval: typeof eval; - global: Global; - isFinite: typeof isFinite; - isNaN: typeof isNaN; - parseFloat: typeof parseFloat; - parseInt: typeof parseInt; - process: Process; - root: Global; - setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => any; - setInterval: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - setTimeout: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - undefined: typeof undefined; - unescape: (str: string) => string; - gc: () => void; - v8debug?: any; - } - - export interface Timer { - ref(): void; - unref(): void; - } -} - -interface IterableIterator { } - -/** - * @deprecated - */ -interface NodeBuffer extends Uint8Array { - write(string: string, offset?: number, length?: number, encoding?: string): number; - toString(encoding?: string, start?: number, end?: number): string; - toJSON(): {type: 'Buffer', data: any[]}; - equals(otherBuffer: Buffer): boolean; - compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; - copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; - slice(start?: number, end?: number): Buffer; - writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readUInt8(offset: number, noAssert?: boolean): number; - readUInt16LE(offset: number, noAssert?: boolean): number; - readUInt16BE(offset: number, noAssert?: boolean): number; - readUInt32LE(offset: number, noAssert?: boolean): number; - readUInt32BE(offset: number, noAssert?: boolean): number; - readInt8(offset: number, noAssert?: boolean): number; - readInt16LE(offset: number, noAssert?: boolean): number; - readInt16BE(offset: number, noAssert?: boolean): number; - readInt32LE(offset: number, noAssert?: boolean): number; - readInt32BE(offset: number, noAssert?: boolean): number; - readFloatLE(offset: number, noAssert?: boolean): number; - readFloatBE(offset: number, noAssert?: boolean): number; - readDoubleLE(offset: number, noAssert?: boolean): number; - readDoubleBE(offset: number, noAssert?: boolean): number; - swap16(): Buffer; - swap32(): Buffer; - swap64(): Buffer; - writeUInt8(value: number, offset: number, noAssert?: boolean): number; - writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; - writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; - writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; - writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; - writeInt8(value: number, offset: number, noAssert?: boolean): number; - writeInt16LE(value: number, offset: number, noAssert?: boolean): number; - writeInt16BE(value: number, offset: number, noAssert?: boolean): number; - writeInt32LE(value: number, offset: number, noAssert?: boolean): number; - writeInt32BE(value: number, offset: number, noAssert?: boolean): number; - writeFloatLE(value: number, offset: number, noAssert?: boolean): number; - writeFloatBE(value: number, offset: number, noAssert?: boolean): number; - writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; - writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; - fill(value: any, offset?: number, end?: number): this; - indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; - lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; - entries(): IterableIterator<[number, number]>; - includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; - keys(): IterableIterator; - values(): IterableIterator; -} - -/************************************************ -* * -* MODULES * -* * -************************************************/ -declare module "buffer" { - export var INSPECT_MAX_BYTES: number; - var BuffType: typeof Buffer; - var SlowBuffType: typeof SlowBuffer; - export { BuffType as Buffer, SlowBuffType as SlowBuffer }; -} - -declare module "querystring" { - export interface StringifyOptions { - encodeURIComponent?: Function; - } - - export interface ParseOptions { - maxKeys?: number; - decodeURIComponent?: Function; - } - - export function stringify(obj: T, sep?: string, eq?: string, options?: StringifyOptions): string; - export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): any; - export function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): T; - export function escape(str: string): string; - export function unescape(str: string): string; -} - -declare module "events" { - export class EventEmitter extends NodeJS.EventEmitter { - static EventEmitter: EventEmitter; - static listenerCount(emitter: EventEmitter, event: string): number; // deprecated - static defaultMaxListeners: number; - - addListener(event: string, listener: Function): this; - on(event: string, listener: Function): this; - once(event: string, listener: Function): this; - prependListener(event: string, listener: Function): this; - prependOnceListener(event: string, listener: Function): this; - removeListener(event: string, listener: Function): this; - removeAllListeners(event?: string): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string): Function[]; - emit(event: string, ...args: any[]): boolean; - eventNames(): string[]; - listenerCount(type: string): number; - } -} - -declare module "http" { - import * as events from "events"; - import * as net from "net"; - import * as stream from "stream"; - - export interface RequestOptions { - protocol?: string; - host?: string; - hostname?: string; - family?: number; - port?: number; - localAddress?: string; - socketPath?: string; - method?: string; - path?: string; - headers?: { [key: string]: any }; - auth?: string; - agent?: Agent | boolean; - } - - export interface Server extends net.Server { - setTimeout(msecs: number, callback: Function): void; - maxHeadersCount: number; - timeout: number; - } - /** - * @deprecated Use IncomingMessage - */ - export interface ServerRequest extends IncomingMessage { - connection: net.Socket; - } - export interface ServerResponse extends stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - writeContinue(): void; - writeHead(statusCode: number, reasonPhrase?: string, headers?: any): void; - writeHead(statusCode: number, headers?: any): void; - statusCode: number; - statusMessage: string; - headersSent: boolean; - setHeader(name: string, value: string | string[]): void; - setTimeout(msecs: number, callback: Function): ServerResponse; - sendDate: boolean; - getHeader(name: string): string; - removeHeader(name: string): void; - write(chunk: any, encoding?: string): any; - addTrailers(headers: any): void; - finished: boolean; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface ClientRequest extends stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - write(chunk: any, encoding?: string): void; - abort(): void; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; - - setHeader(name: string, value: string | string[]): void; - getHeader(name: string): string; - removeHeader(name: string): void; - addTrailers(headers: any): void; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface IncomingMessage extends stream.Readable { - httpVersion: string; - httpVersionMajor: string; - httpVersionMinor: string; - connection: net.Socket; - headers: any; - rawHeaders: string[]; - trailers: any; - rawTrailers: any; - setTimeout(msecs: number, callback: Function): NodeJS.Timer; - /** - * Only valid for request obtained from http.Server. - */ - method?: string; - /** - * Only valid for request obtained from http.Server. - */ - url?: string; - /** - * Only valid for response obtained from http.ClientRequest. - */ - statusCode?: number; - /** - * Only valid for response obtained from http.ClientRequest. - */ - statusMessage?: string; - socket: net.Socket; - destroy(error?: Error): void; - } - /** - * @deprecated Use IncomingMessage - */ - export interface ClientResponse extends IncomingMessage { } - - export interface AgentOptions { - /** - * Keep sockets around in a pool to be used by other requests in the future. Default = false - */ - keepAlive?: boolean; - /** - * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000. - * Only relevant if keepAlive is set to true. - */ - keepAliveMsecs?: number; - /** - * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity - */ - maxSockets?: number; - /** - * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. - */ - maxFreeSockets?: number; - } - - export class Agent { - maxSockets: number; - sockets: any; - requests: any; - - constructor(opts?: AgentOptions); - - /** - * Destroy any sockets that are currently in use by the agent. - * It is usually not necessary to do this. However, if you are using an agent with KeepAlive enabled, - * then it is best to explicitly shut down the agent when you know that it will no longer be used. Otherwise, - * sockets may hang open for quite a long time before the server terminates them. - */ - destroy(): void; - } - - export var METHODS: string[]; - - export var STATUS_CODES: { - [errorCode: number]: string; - [errorCode: string]: string; - }; - export function createServer(requestListener?: (request: IncomingMessage, response: ServerResponse) => void): Server; - export function createClient(port?: number, host?: string): any; - export function request(options: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest; - export function get(options: any, callback?: (res: IncomingMessage) => void): ClientRequest; - export var globalAgent: Agent; -} - -declare module "cluster" { - import * as child from "child_process"; - import * as events from "events"; - - export interface ClusterSettings { - exec?: string; - args?: string[]; - silent?: boolean; - } - - export interface Address { - address: string; - port: number; - addressType: string; - } - - export class Worker extends events.EventEmitter { - id: string; - process: child.ChildProcess; - suicide: boolean; - send(message: any, sendHandle?: any): boolean; - kill(signal?: string): void; - destroy(signal?: string): void; - disconnect(): void; - isConnected(): boolean; - isDead(): boolean; - } - - export var settings: ClusterSettings; - export var isMaster: boolean; - export var isWorker: boolean; - export function setupMaster(settings?: ClusterSettings): void; - export function fork(env?: any): Worker; - export function disconnect(callback?: Function): void; - export var worker: Worker; - export var workers: { - [index: string]: Worker - }; - - // Event emitter - export function addListener(event: string, listener: Function): void; - export function on(event: "disconnect", listener: (worker: Worker) => void): void; - export function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): void; - export function on(event: "fork", listener: (worker: Worker) => void): void; - export function on(event: "listening", listener: (worker: Worker, address: any) => void): void; - export function on(event: "message", listener: (worker: Worker, message: any) => void): void; - export function on(event: "online", listener: (worker: Worker) => void): void; - export function on(event: "setup", listener: (settings: any) => void): void; - export function on(event: string, listener: Function): any; - export function once(event: string, listener: Function): void; - export function removeListener(event: string, listener: Function): void; - export function removeAllListeners(event?: string): void; - export function setMaxListeners(n: number): void; - export function listeners(event: string): Function[]; - export function emit(event: string, ...args: any[]): boolean; -} - -declare module "zlib" { - import * as stream from "stream"; - export interface ZlibOptions { chunkSize?: number; windowBits?: number; level?: number; memLevel?: number; strategy?: number; dictionary?: any; } - - export interface Gzip extends stream.Transform { } - export interface Gunzip extends stream.Transform { } - export interface Deflate extends stream.Transform { } - export interface Inflate extends stream.Transform { } - export interface DeflateRaw extends stream.Transform { } - export interface InflateRaw extends stream.Transform { } - export interface Unzip extends stream.Transform { } - - export function createGzip(options?: ZlibOptions): Gzip; - export function createGunzip(options?: ZlibOptions): Gunzip; - export function createDeflate(options?: ZlibOptions): Deflate; - export function createInflate(options?: ZlibOptions): Inflate; - export function createDeflateRaw(options?: ZlibOptions): DeflateRaw; - export function createInflateRaw(options?: ZlibOptions): InflateRaw; - export function createUnzip(options?: ZlibOptions): Unzip; - - export function deflate(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function deflateSync(buf: Buffer, options?: ZlibOptions): any; - export function deflateRaw(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function deflateRawSync(buf: Buffer, options?: ZlibOptions): any; - export function gzip(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function gzipSync(buf: Buffer, options?: ZlibOptions): any; - export function gunzip(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function gunzipSync(buf: Buffer, options?: ZlibOptions): any; - export function inflate(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function inflateSync(buf: Buffer, options?: ZlibOptions): any; - export function inflateRaw(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function inflateRawSync(buf: Buffer, options?: ZlibOptions): any; - export function unzip(buf: Buffer, callback: (error: Error, result: any) => void): void; - export function unzipSync(buf: Buffer, options?: ZlibOptions): any; - - // Constants - export var Z_NO_FLUSH: number; - export var Z_PARTIAL_FLUSH: number; - export var Z_SYNC_FLUSH: number; - export var Z_FULL_FLUSH: number; - export var Z_FINISH: number; - export var Z_BLOCK: number; - export var Z_TREES: number; - export var Z_OK: number; - export var Z_STREAM_END: number; - export var Z_NEED_DICT: number; - export var Z_ERRNO: number; - export var Z_STREAM_ERROR: number; - export var Z_DATA_ERROR: number; - export var Z_MEM_ERROR: number; - export var Z_BUF_ERROR: number; - export var Z_VERSION_ERROR: number; - export var Z_NO_COMPRESSION: number; - export var Z_BEST_SPEED: number; - export var Z_BEST_COMPRESSION: number; - export var Z_DEFAULT_COMPRESSION: number; - export var Z_FILTERED: number; - export var Z_HUFFMAN_ONLY: number; - export var Z_RLE: number; - export var Z_FIXED: number; - export var Z_DEFAULT_STRATEGY: number; - export var Z_BINARY: number; - export var Z_TEXT: number; - export var Z_ASCII: number; - export var Z_UNKNOWN: number; - export var Z_DEFLATED: number; - export var Z_NULL: number; -} - -declare module "os" { - export interface CpuInfo { - model: string; - speed: number; - times: { - user: number; - nice: number; - sys: number; - idle: number; - irq: number; - }; - } - - export interface NetworkInterfaceInfo { - address: string; - netmask: string; - family: string; - mac: string; - internal: boolean; - } - - export function hostname(): string; - export function loadavg(): number[]; - export function uptime(): number; - export function freemem(): number; - export function totalmem(): number; - export function cpus(): CpuInfo[]; - export function type(): string; - export function release(): string; - export function networkInterfaces(): { [index: string]: NetworkInterfaceInfo[] }; - export function homedir(): string; - export function userInfo(options?: { encoding: string }): { username: string, uid: number, gid: number, shell: any, homedir: string } - export var constants: { - UV_UDP_REUSEADDR: number, - errno: { - SIGHUP: number; - SIGINT: number; - SIGQUIT: number; - SIGILL: number; - SIGTRAP: number; - SIGABRT: number; - SIGIOT: number; - SIGBUS: number; - SIGFPE: number; - SIGKILL: number; - SIGUSR1: number; - SIGSEGV: number; - SIGUSR2: number; - SIGPIPE: number; - SIGALRM: number; - SIGTERM: number; - SIGCHLD: number; - SIGSTKFLT: number; - SIGCONT: number; - SIGSTOP: number; - SIGTSTP: number; - SIGTTIN: number; - SIGTTOU: number; - SIGURG: number; - SIGXCPU: number; - SIGXFSZ: number; - SIGVTALRM: number; - SIGPROF: number; - SIGWINCH: number; - SIGIO: number; - SIGPOLL: number; - SIGPWR: number; - SIGSYS: number; - SIGUNUSED: number; - }, - signals: { - E2BIG: number; - EACCES: number; - EADDRINUSE: number; - EADDRNOTAVAIL: number; - EAFNOSUPPORT: number; - EAGAIN: number; - EALREADY: number; - EBADF: number; - EBADMSG: number; - EBUSY: number; - ECANCELED: number; - ECHILD: number; - ECONNABORTED: number; - ECONNREFUSED: number; - ECONNRESET: number; - EDEADLK: number; - EDESTADDRREQ: number; - EDOM: number; - EDQUOT: number; - EEXIST: number; - EFAULT: number; - EFBIG: number; - EHOSTUNREACH: number; - EIDRM: number; - EILSEQ: number; - EINPROGRESS: number; - EINTR: number; - EINVAL: number; - EIO: number; - EISCONN: number; - EISDIR: number; - ELOOP: number; - EMFILE: number; - EMLINK: number; - EMSGSIZE: number; - EMULTIHOP: number; - ENAMETOOLONG: number; - ENETDOWN: number; - ENETRESET: number; - ENETUNREACH: number; - ENFILE: number; - ENOBUFS: number; - ENODATA: number; - ENODEV: number; - ENOENT: number; - ENOEXEC: number; - ENOLCK: number; - ENOLINK: number; - ENOMEM: number; - ENOMSG: number; - ENOPROTOOPT: number; - ENOSPC: number; - ENOSR: number; - ENOSTR: number; - ENOSYS: number; - ENOTCONN: number; - ENOTDIR: number; - ENOTEMPTY: number; - ENOTSOCK: number; - ENOTSUP: number; - ENOTTY: number; - ENXIO: number; - EOPNOTSUPP: number; - EOVERFLOW: number; - EPERM: number; - EPIPE: number; - EPROTO: number; - EPROTONOSUPPORT: number; - EPROTOTYPE: number; - ERANGE: number; - EROFS: number; - ESPIPE: number; - ESRCH: number; - ESTALE: number; - ETIME: number; - ETIMEDOUT: number; - ETXTBSY: number; - EWOULDBLOCK: number; - EXDEV: number; - }, - }; - export function arch(): string; - export function platform(): string; - export function tmpdir(): string; - export var EOL: string; - export function endianness(): "BE" | "LE"; -} - -declare module "https" { - import * as tls from "tls"; - import * as events from "events"; - import * as http from "http"; - - export interface ServerOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - crl?: any; - ciphers?: string; - honorCipherOrder?: boolean; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: any; - SNICallback?: (servername: string, cb: (err: Error, ctx: tls.SecureContext) => any) => any; - } - - export interface RequestOptions extends http.RequestOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - ciphers?: string; - rejectUnauthorized?: boolean; - secureProtocol?: string; - } - - export interface Agent extends http.Agent { } - - export interface AgentOptions extends http.AgentOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - ciphers?: string; - rejectUnauthorized?: boolean; - secureProtocol?: string; - maxCachedSessions?: number; - } - - export var Agent: { - new (options?: AgentOptions): Agent; - }; - export interface Server extends tls.Server { } - export function createServer(options: ServerOptions, requestListener?: Function): Server; - export function request(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; - export function get(options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest; - export var globalAgent: Agent; -} - -declare module "punycode" { - export function decode(string: string): string; - export function encode(string: string): string; - export function toUnicode(domain: string): string; - export function toASCII(domain: string): string; - export var ucs2: ucs2; - interface ucs2 { - decode(string: string): number[]; - encode(codePoints: number[]): string; - } - export var version: any; -} - -declare module "repl" { - import * as stream from "stream"; - import * as readline from "readline"; - - export interface ReplOptions { - prompt?: string; - input?: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - terminal?: boolean; - eval?: Function; - useColors?: boolean; - useGlobal?: boolean; - ignoreUndefined?: boolean; - writer?: Function; - completer?: Function; - replMode?: any; - breakEvalOnSigint?: any; - } - - export interface REPLServer extends readline.ReadLine { - defineCommand(keyword: string, cmd: Function | { help: string, action: Function }): void; - displayPrompt(preserveCursor?: boolean): void - } - - export function start(options: ReplOptions): REPLServer; -} - -declare module "readline" { - import * as events from "events"; - import * as stream from "stream"; - - export interface Key { - sequence?: string; - name?: string; - ctrl?: boolean; - meta?: boolean; - shift?: boolean; - } - - export interface ReadLine extends events.EventEmitter { - setPrompt(prompt: string): void; - prompt(preserveCursor?: boolean): void; - question(query: string, callback: (answer: string) => void): void; - pause(): ReadLine; - resume(): ReadLine; - close(): void; - write(data: string | Buffer, key?: Key): void; - } - - export interface Completer { - (line: string): CompleterResult; - (line: string, callback: (err: any, result: CompleterResult) => void): any; - } - - export interface CompleterResult { - completions: string[]; - line: string; - } - - export interface ReadLineOptions { - input: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - completer?: Completer; - terminal?: boolean; - historySize?: number; - } - - export function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer, terminal?: boolean): ReadLine; - export function createInterface(options: ReadLineOptions): ReadLine; - - export function cursorTo(stream: NodeJS.WritableStream, x: number, y: number): void; - export function moveCursor(stream: NodeJS.WritableStream, dx: number | string, dy: number | string): void; - export function clearLine(stream: NodeJS.WritableStream, dir: number): void; - export function clearScreenDown(stream: NodeJS.WritableStream): void; -} - -declare module "vm" { - export interface Context { } - export interface ScriptOptions { - filename?: string; - lineOffset?: number; - columnOffset?: number; - displayErrors?: boolean; - timeout?: number; - cachedData?: Buffer; - produceCachedData?: boolean; - } - export interface RunningScriptOptions { - filename?: string; - lineOffset?: number; - columnOffset?: number; - displayErrors?: boolean; - timeout?: number; - } - export class Script { - constructor(code: string, options?: ScriptOptions); - runInContext(contextifiedSandbox: Context, options?: RunningScriptOptions): any; - runInNewContext(sandbox?: Context, options?: RunningScriptOptions): any; - runInThisContext(options?: RunningScriptOptions): any; - } - export function createContext(sandbox?: Context): Context; - export function isContext(sandbox: Context): boolean; - export function runInContext(code: string, contextifiedSandbox: Context, options?: RunningScriptOptions): any; - export function runInDebugContext(code: string): any; - export function runInNewContext(code: string, sandbox?: Context, options?: RunningScriptOptions): any; - export function runInThisContext(code: string, options?: RunningScriptOptions): any; -} - -declare module "child_process" { - import * as events from "events"; - import * as stream from "stream"; - - export interface ChildProcess extends events.EventEmitter { - stdin: stream.Writable; - stdout: stream.Readable; - stderr: stream.Readable; - stdio: [stream.Writable, stream.Readable, stream.Readable]; - pid: number; - kill(signal?: string): void; - send(message: any, sendHandle?: any): boolean; - connected: boolean; - disconnect(): void; - unref(): void; - ref(): void; - } - - export interface SpawnOptions { - cwd?: string; - env?: any; - stdio?: any; - detached?: boolean; - uid?: number; - gid?: number; - shell?: boolean | string; - } - export function spawn(command: string, args?: string[], options?: SpawnOptions): ChildProcess; - - export interface ExecOptions { - cwd?: string; - env?: any; - shell?: string; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - uid?: number; - gid?: number; - } - export interface ExecOptionsWithStringEncoding extends ExecOptions { - encoding: BufferEncoding; - } - export interface ExecOptionsWithBufferEncoding extends ExecOptions { - encoding: string; // specify `null`. - } - export function exec(command: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function exec(command: string, options: ExecOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.exec("tsc", {encoding: null as string}, (err, stdout, stderr) => {}); - export function exec(command: string, options: ExecOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function exec(command: string, options: ExecOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - - export interface ExecFileOptions { - cwd?: string; - env?: any; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - uid?: number; - gid?: number; - } - export interface ExecFileOptionsWithStringEncoding extends ExecFileOptions { - encoding: BufferEncoding; - } - export interface ExecFileOptionsWithBufferEncoding extends ExecFileOptions { - encoding: string; // specify `null`. - } - export function execFile(file: string, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.execFile("file.sh", {encoding: null as string}, (err, stdout, stderr) => {}); - export function execFile(file: string, options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function execFile(file: string, options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, args?: string[], callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithStringEncoding, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - // usage. child_process.execFile("file.sh", ["foo"], {encoding: null as string}, (err, stdout, stderr) => {}); - export function execFile(file: string, args?: string[], options?: ExecFileOptionsWithBufferEncoding, callback?: (error: Error, stdout: Buffer, stderr: Buffer) => void): ChildProcess; - export function execFile(file: string, args?: string[], options?: ExecFileOptions, callback?: (error: Error, stdout: string, stderr: string) => void): ChildProcess; - - export interface ForkOptions { - cwd?: string; - env?: any; - execPath?: string; - execArgv?: string[]; - silent?: boolean; - uid?: number; - gid?: number; - } - export function fork(modulePath: string, args?: string[], options?: ForkOptions): ChildProcess; - - export interface SpawnSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - shell?: boolean | string; - } - export interface SpawnSyncOptionsWithStringEncoding extends SpawnSyncOptions { - encoding: BufferEncoding; - } - export interface SpawnSyncOptionsWithBufferEncoding extends SpawnSyncOptions { - encoding: string; // specify `null`. - } - export interface SpawnSyncReturns { - pid: number; - output: string[]; - stdout: T; - stderr: T; - status: number; - signal: string; - error: Error; - } - export function spawnSync(command: string): SpawnSyncReturns; - export function spawnSync(command: string, options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; - export function spawnSync(command: string, options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; - export function spawnSync(command: string, options?: SpawnSyncOptions): SpawnSyncReturns; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithStringEncoding): SpawnSyncReturns; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptionsWithBufferEncoding): SpawnSyncReturns; - export function spawnSync(command: string, args?: string[], options?: SpawnSyncOptions): SpawnSyncReturns; - - export interface ExecSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - shell?: string; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - } - export interface ExecSyncOptionsWithStringEncoding extends ExecSyncOptions { - encoding: BufferEncoding; - } - export interface ExecSyncOptionsWithBufferEncoding extends ExecSyncOptions { - encoding: string; // specify `null`. - } - export function execSync(command: string): Buffer; - export function execSync(command: string, options?: ExecSyncOptionsWithStringEncoding): string; - export function execSync(command: string, options?: ExecSyncOptionsWithBufferEncoding): Buffer; - export function execSync(command: string, options?: ExecSyncOptions): Buffer; - - export interface ExecFileSyncOptions { - cwd?: string; - input?: string | Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - killSignal?: string; - maxBuffer?: number; - encoding?: string; - } - export interface ExecFileSyncOptionsWithStringEncoding extends ExecFileSyncOptions { - encoding: BufferEncoding; - } - export interface ExecFileSyncOptionsWithBufferEncoding extends ExecFileSyncOptions { - encoding: string; // specify `null`. - } - export function execFileSync(command: string): Buffer; - export function execFileSync(command: string, options?: ExecFileSyncOptionsWithStringEncoding): string; - export function execFileSync(command: string, options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; - export function execFileSync(command: string, options?: ExecFileSyncOptions): Buffer; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithStringEncoding): string; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptionsWithBufferEncoding): Buffer; - export function execFileSync(command: string, args?: string[], options?: ExecFileSyncOptions): Buffer; -} - -declare module "url" { - export interface Url { - href?: string; - protocol?: string; - auth?: string; - hostname?: string; - port?: string; - host?: string; - pathname?: string; - search?: string; - query?: string | any; - slashes?: boolean; - hash?: string; - path?: string; - } - - export function parse(urlStr: string, parseQueryString?: boolean, slashesDenoteHost?: boolean): Url; - export function format(url: Url): string; - export function resolve(from: string, to: string): string; -} - -declare module "dns" { - export function lookup(domain: string, family: number, callback: (err: Error, address: string, family: number) => void): string; - export function lookup(domain: string, callback: (err: Error, address: string, family: number) => void): string; - export function resolve(domain: string, rrtype: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolve(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolve4(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolve6(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveMx(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveTxt(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveSrv(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveNs(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function resolveCname(domain: string, callback: (err: Error, addresses: string[]) => void): string[]; - export function reverse(ip: string, callback: (err: Error, domains: string[]) => void): string[]; - - //Error codes - export var NODATA: string; - export var FORMERR: string; - export var SERVFAIL: string; - export var NOTFOUND: string; - export var NOTIMP: string; - export var REFUSED: string; - export var BADQUERY: string; - export var BADNAME: string; - export var BADFAMILY: string; - export var BADRESP: string; - export var CONNREFUSED: string; - export var TIMEOUT: string; - export var EOF: string; - export var FILE: string; - export var NOMEM: string; - export var DESTRUCTION: string; - export var BADSTR: string; - export var BADFLAGS: string; - export var NONAME: string; - export var BADHINTS: string; - export var NOTINITIALIZED: string; - export var LOADIPHLPAPI: string; - export var ADDRGETNETWORKPARAMS: string; - export var CANCELLED: string; -} - -declare module "net" { - import * as stream from "stream"; - - export interface Socket extends stream.Duplex { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - connect(port: number, host?: string, connectionListener?: Function): void; - connect(path: string, connectionListener?: Function): void; - bufferSize: number; - setEncoding(encoding?: string): void; - write(data: any, encoding?: string, callback?: Function): void; - destroy(): void; - pause(): Socket; - resume(): Socket; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setKeepAlive(enable?: boolean, initialDelay?: number): void; - address(): { port: number; family: string; address: string; }; - unref(): void; - ref(): void; - - remoteAddress: string; - remoteFamily: string; - remotePort: number; - localAddress: string; - localPort: number; - bytesRead: number; - bytesWritten: number; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - - export var Socket: { - new (options?: { fd?: string; type?: string; allowHalfOpen?: boolean; }): Socket; - }; - - export interface ListenOptions { - port?: number; - host?: string; - backlog?: number; - path?: string; - exclusive?: boolean; - } - - export interface Server extends Socket { - listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function): Server; - listen(port: number, hostname?: string, listeningListener?: Function): Server; - listen(port: number, backlog?: number, listeningListener?: Function): Server; - listen(port: number, listeningListener?: Function): Server; - listen(path: string, backlog?: number, listeningListener?: Function): Server; - listen(path: string, listeningListener?: Function): Server; - listen(handle: any, backlog?: number, listeningListener?: Function): Server; - listen(handle: any, listeningListener?: Function): Server; - listen(options: ListenOptions, listeningListener?: Function): Server; - close(callback?: Function): Server; - address(): { port: number; family: string; address: string; }; - getConnections(cb: (error: Error, count: number) => void): void; - ref(): Server; - unref(): Server; - maxConnections: number; - connections: number; - } - export function createServer(connectionListener?: (socket: Socket) => void): Server; - export function createServer(options?: { allowHalfOpen?: boolean; }, connectionListener?: (socket: Socket) => void): Server; - export function connect(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function connect(port: number, host?: string, connectionListener?: Function): Socket; - export function connect(path: string, connectionListener?: Function): Socket; - export function createConnection(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function createConnection(port: number, host?: string, connectionListener?: Function): Socket; - export function createConnection(path: string, connectionListener?: Function): Socket; - export function isIP(input: string): number; - export function isIPv4(input: string): boolean; - export function isIPv6(input: string): boolean; -} - -declare module "dgram" { - import * as events from "events"; - - interface RemoteInfo { - address: string; - port: number; - size: number; - } - - interface AddressInfo { - address: string; - family: string; - port: number; - } - - interface BindOptions { - port: number; - address?: string; - exclusive?: boolean; - } - - interface SocketOptions { - type: "udp4" | "udp6"; - reuseAddr?: boolean; - } - - export function createSocket(type: string, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - export function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - - export interface Socket extends events.EventEmitter { - send(msg: Buffer | String | any[], port: number, address: string, callback?: (error: Error, bytes: number) => void): void; - send(msg: Buffer | String | any[], offset: number, length: number, port: number, address: string, callback?: (error: Error, bytes: number) => void): void; - bind(port?: number, address?: string, callback?: () => void): void; - bind(options: BindOptions, callback?: Function): void; - close(callback?: any): void; - address(): AddressInfo; - setBroadcast(flag: boolean): void; - setTTL(ttl: number): void; - setMulticastTTL(ttl: number): void; - setMulticastLoopback(flag: boolean): void; - addMembership(multicastAddress: string, multicastInterface?: string): void; - dropMembership(multicastAddress: string, multicastInterface?: string): void; - ref(): void; - unref(): void; - } -} - -declare module "fs" { - import * as stream from "stream"; - import * as events from "events"; - - interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; - } - - interface FSWatcher extends events.EventEmitter { - close(): void; - } - - export interface ReadStream extends stream.Readable { - close(): void; - destroy(): void; - } - export interface WriteStream extends stream.Writable { - close(): void; - bytesWritten: number; - path: string | Buffer; - } - - /** - * Asynchronous rename. - * @param oldPath - * @param newPath - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /** - * Synchronous rename - * @param oldPath - * @param newPath - */ - export function renameSync(oldPath: string, newPath: string): void; - export function truncate(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncate(path: string | Buffer, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncateSync(path: string | Buffer, len?: number): void; - export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncateSync(fd: number, len?: number): void; - export function chown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chownSync(path: string | Buffer, uid: number, gid: number): void; - export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchownSync(fd: number, uid: number, gid: number): void; - export function lchown(path: string | Buffer, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchownSync(path: string | Buffer, uid: number, gid: number): void; - export function chmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmodSync(path: string | Buffer, mode: number): void; - export function chmodSync(path: string | Buffer, mode: string): void; - export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmodSync(fd: number, mode: number): void; - export function fchmodSync(fd: number, mode: string): void; - export function lchmod(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmod(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmodSync(path: string | Buffer, mode: number): void; - export function lchmodSync(path: string | Buffer, mode: string): void; - export function stat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function lstat(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function statSync(path: string | Buffer): Stats; - export function lstatSync(path: string | Buffer): Stats; - export function fstatSync(fd: number): Stats; - export function link(srcpath: string | Buffer, dstpath: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function linkSync(srcpath: string | Buffer, dstpath: string | Buffer): void; - export function symlink(srcpath: string | Buffer, dstpath: string | Buffer, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function symlinkSync(srcpath: string | Buffer, dstpath: string | Buffer, type?: string): void; - export function readlink(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void; - export function readlinkSync(path: string | Buffer): string; - export function realpath(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; - export function realpath(path: string | Buffer, cache: { [path: string]: string }, callback: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; - export function realpathSync(path: string | Buffer, cache?: { [path: string]: string }): string; - /* - * Asynchronous unlink - deletes the file specified in {path} - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function unlink(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous unlink - deletes the file specified in {path} - * - * @param path - */ - export function unlinkSync(path: string | Buffer): void; - /* - * Asynchronous rmdir - removes the directory specified in {path} - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function rmdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous rmdir - removes the directory specified in {path} - * - * @param path - */ - export function rmdirSync(path: string | Buffer): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string | Buffer, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string | Buffer, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string | Buffer, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdirSync(path: string | Buffer, mode?: number): void; - /* - * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdirSync(path: string | Buffer, mode?: string): void; - /* - * Asynchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. - * - * @param prefix - * @param callback The created folder path is passed as a string to the callback's second parameter. - */ - export function mkdtemp(prefix: string, callback?: (err: NodeJS.ErrnoException, folder: string) => void): void; - /* - * Synchronous mkdtemp - Creates a unique temporary directory. Generates six random characters to be appended behind a required prefix to create a unique temporary directory. - * - * @param prefix - * @returns Returns the created folder path. - */ - export function mkdtempSync(prefix: string): string; - export function readdir(path: string | Buffer, callback?: (err: NodeJS.ErrnoException, files: string[]) => void): void; - export function readdirSync(path: string | Buffer): string[]; - export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function closeSync(fd: number): void; - export function open(path: string | Buffer, flags: string | number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; - export function open(path: string | Buffer, flags: string | number, mode: number, callback: (err: NodeJS.ErrnoException, fd: number) => void): void; - export function openSync(path: string | Buffer, flags: string | number, mode?: number): number; - export function utimes(path: string | Buffer, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimes(path: string | Buffer, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimesSync(path: string | Buffer, atime: number, mtime: number): void; - export function utimesSync(path: string | Buffer, atime: Date, mtime: Date): void; - export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimesSync(fd: number, atime: number, mtime: number): void; - export function futimesSync(fd: number, atime: Date, mtime: Date): void; - export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fsyncSync(fd: number): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function write(fd: number, data: any, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function write(fd: number, data: any, offset: number, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function write(fd: number, data: any, offset: number, encoding: string, callback?: (err: NodeJS.ErrnoException, written: number, str: string) => void): void; - export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number; - export function writeSync(fd: number, data: any, position?: number, enconding?: string): number; - export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void; - export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param encoding - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param encoding - */ - export function readFileSync(filename: string, encoding: string): string; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. - */ - export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. - */ - export function readFileSync(filename: string, options?: { flag?: string; }): Buffer; - export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void; - export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void; - export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void; - export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher; - export function watch(filename: string, encoding: string, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; - export function watch(filename: string, options: { persistent?: boolean; recursive?: boolean; encoding?: string }, listener?: (event: string, filename: string | Buffer) => any): FSWatcher; - export function exists(path: string | Buffer, callback?: (exists: boolean) => void): void; - export function existsSync(path: string | Buffer): boolean; - - interface Constants { - /** Constant for fs.access(). File is visible to the calling process. */ - F_OK: number; - - /** Constant for fs.access(). File can be read by the calling process. */ - R_OK: number; - - /** Constant for fs.access(). File can be written by the calling process. */ - W_OK: number; - - /** Constant for fs.access(). File can be executed by the calling process. */ - X_OK: number; - } - - export const constants: Constants; - - /** Tests a user's permissions for the file specified by path. */ - export function access(path: string | Buffer, callback: (err: NodeJS.ErrnoException) => void): void; - export function access(path: string | Buffer, mode: number, callback: (err: NodeJS.ErrnoException) => void): void; - /** Synchronous version of fs.access. This throws if any accessibility checks fail, and does nothing otherwise. */ - export function accessSync(path: string | Buffer, mode?: number): void; - export function createReadStream(path: string | Buffer, options?: { - flags?: string; - encoding?: string; - fd?: number; - mode?: number; - autoClose?: boolean; - start?: number; - end?: number; - }): ReadStream; - export function createWriteStream(path: string | Buffer, options?: { - flags?: string; - encoding?: string; - fd?: number; - mode?: number; - }): WriteStream; - export function fdatasync(fd: number, callback: Function): void; - export function fdatasyncSync(fd: number): void; -} - -declare module "path" { - - /** - * A parsed path object generated by path.parse() or consumed by path.format(). - */ - export interface ParsedPath { - /** - * The root of the path such as '/' or 'c:\' - */ - root: string; - /** - * The full directory path such as '/home/user/dir' or 'c:\path\dir' - */ - dir: string; - /** - * The file name including extension (if any) such as 'index.html' - */ - base: string; - /** - * The file extension (if any) such as '.html' - */ - ext: string; - /** - * The file name without extension (if any) such as 'index' - */ - name: string; - } - - /** - * Normalize a string path, reducing '..' and '.' parts. - * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. - * - * @param p string path to normalize. - */ - export function normalize(p: string): string; - /** - * Join all arguments together and normalize the resulting path. - * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. - * - * @param paths string paths to join. - */ - export function join(...paths: any[]): string; - /** - * Join all arguments together and normalize the resulting path. - * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. - * - * @param paths string paths to join. - */ - export function join(...paths: string[]): string; - /** - * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. - * - * Starting from leftmost {from} paramter, resolves {to} to an absolute path. - * - * If {to} isn't already absolute, {from} arguments are prepended in right to left order, until an absolute path is found. If after using all {from} paths still no absolute path is found, the current working directory is used as well. The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory. - * - * @param pathSegments string paths to join. Non-string arguments are ignored. - */ - export function resolve(...pathSegments: any[]): string; - /** - * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. - * - * @param path path to test. - */ - export function isAbsolute(path: string): boolean; - /** - * Solve the relative path from {from} to {to}. - * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve. - * - * @param from - * @param to - */ - export function relative(from: string, to: string): string; - /** - * Return the directory name of a path. Similar to the Unix dirname command. - * - * @param p the path to evaluate. - */ - export function dirname(p: string): string; - /** - * Return the last portion of a path. Similar to the Unix basename command. - * Often used to extract the file name from a fully qualified path. - * - * @param p the path to evaluate. - * @param ext optionally, an extension to remove from the result. - */ - export function basename(p: string, ext?: string): string; - /** - * Return the extension of the path, from the last '.' to end of string in the last portion of the path. - * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string - * - * @param p the path to evaluate. - */ - export function extname(p: string): string; - /** - * The platform-specific file separator. '\\' or '/'. - */ - export var sep: string; - /** - * The platform-specific file delimiter. ';' or ':'. - */ - export var delimiter: string; - /** - * Returns an object from a path string - the opposite of format(). - * - * @param pathString path to evaluate. - */ - export function parse(pathString: string): ParsedPath; - /** - * Returns a path string from an object - the opposite of parse(). - * - * @param pathString path to evaluate. - */ - export function format(pathObject: ParsedPath): string; - - export module posix { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } - - export module win32 { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } -} - -declare module "string_decoder" { - export interface NodeStringDecoder { - write(buffer: Buffer): string; - end(buffer?: Buffer): string; - } - export var StringDecoder: { - new (encoding?: string): NodeStringDecoder; - }; -} - -declare module "tls" { - import * as crypto from "crypto"; - import * as net from "net"; - import * as stream from "stream"; - - var CLIENT_RENEG_LIMIT: number; - var CLIENT_RENEG_WINDOW: number; - - export interface Certificate { - /** - * Country code. - */ - C: string; - /** - * Street. - */ - ST: string; - /** - * Locality. - */ - L: string; - /** - * Organization. - */ - O: string; - /** - * Organizational unit. - */ - OU: string; - /** - * Common name. - */ - CN: string; - } - - export interface CipherNameAndProtocol { - /** - * The cipher name. - */ - name: string; - /** - * SSL/TLS protocol version. - */ - version: string; - } - - export class TLSSocket extends stream.Duplex { - /** - * Returns the bound address, the address family name and port of the underlying socket as reported by - * the operating system. - * @returns {any} - An object with three properties, e.g. { port: 12346, family: 'IPv4', address: '127.0.0.1' }. - */ - address(): { port: number; family: string; address: string }; - /** - * A boolean that is true if the peer certificate was signed by one of the specified CAs, otherwise false. - */ - authorized: boolean; - /** - * The reason why the peer's certificate has not been verified. - * This property becomes available only when tlsSocket.authorized === false. - */ - authorizationError: Error; - /** - * Static boolean value, always true. - * May be used to distinguish TLS sockets from regular ones. - */ - encrypted: boolean; - /** - * Returns an object representing the cipher name and the SSL/TLS protocol version of the current connection. - * @returns {CipherNameAndProtocol} - Returns an object representing the cipher name - * and the SSL/TLS protocol version of the current connection. - */ - getCipher(): CipherNameAndProtocol; - /** - * Returns an object representing the peer's certificate. - * The returned object has some properties corresponding to the field of the certificate. - * If detailed argument is true the full chain with issuer property will be returned, - * if false only the top certificate without issuer property. - * If the peer does not provide a certificate, it returns null or an empty object. - * @param {boolean} detailed - If true; the full chain with issuer property will be returned. - * @returns {any} - An object representing the peer's certificate. - */ - getPeerCertificate(detailed?: boolean): { - subject: Certificate; - issuerInfo: Certificate; - issuer: Certificate; - raw: any; - valid_from: string; - valid_to: string; - fingerprint: string; - serialNumber: string; - }; - /** - * Could be used to speed up handshake establishment when reconnecting to the server. - * @returns {any} - ASN.1 encoded TLS session or undefined if none was negotiated. - */ - getSession(): any; - /** - * NOTE: Works only with client TLS sockets. - * Useful only for debugging, for session reuse provide session option to tls.connect(). - * @returns {any} - TLS session ticket or undefined if none was negotiated. - */ - getTLSTicket(): any; - /** - * The string representation of the local IP address. - */ - localAddress: string; - /** - * The numeric representation of the local port. - */ - localPort: string; - /** - * The string representation of the remote IP address. - * For example, '74.125.127.100' or '2001:4860:a005::68'. - */ - remoteAddress: string; - /** - * The string representation of the remote IP family. 'IPv4' or 'IPv6'. - */ - remoteFamily: string; - /** - * The numeric representation of the remote port. For example, 443. - */ - remotePort: number; - /** - * Initiate TLS renegotiation process. - * - * NOTE: Can be used to request peer's certificate after the secure connection has been established. - * ANOTHER NOTE: When running as the server, socket will be destroyed with an error after handshakeTimeout timeout. - * @param {TlsOptions} options - The options may contain the following fields: rejectUnauthorized, - * requestCert (See tls.createServer() for details). - * @param {Function} callback - callback(err) will be executed with null as err, once the renegotiation - * is successfully completed. - */ - renegotiate(options: TlsOptions, callback: (err: Error) => any): any; - /** - * Set maximum TLS fragment size (default and maximum value is: 16384, minimum is: 512). - * Smaller fragment size decreases buffering latency on the client: large fragments are buffered by - * the TLS layer until the entire fragment is received and its integrity is verified; - * large fragments can span multiple roundtrips, and their processing can be delayed due to packet - * loss or reordering. However, smaller fragments add extra TLS framing bytes and CPU overhead, - * which may decrease overall server throughput. - * @param {number} size - TLS fragment size (default and maximum value is: 16384, minimum is: 512). - * @returns {boolean} - Returns true on success, false otherwise. - */ - setMaxSendFragment(size: number): boolean; - } - - export interface TlsOptions { - host?: string; - port?: number; - pfx?: string | Buffer[]; - key?: string | string[] | Buffer | any[]; - passphrase?: string; - cert?: string | string[] | Buffer | Buffer[]; - ca?: string | string[] | Buffer | Buffer[]; - crl?: string | string[]; - ciphers?: string; - honorCipherOrder?: boolean; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: string[] | Buffer; - SNICallback?: (servername: string, cb: (err: Error, ctx: SecureContext) => any) => any; - ecdhCurve?: string; - dhparam?: string | Buffer; - handshakeTimeout?: number; - ALPNProtocols?: string[] | Buffer; - sessionTimeout?: number; - ticketKeys?: any; - sessionIdContext?: string; - secureProtocol?: string; - } - - export interface ConnectionOptions { - host?: string; - port?: number; - socket?: net.Socket; - pfx?: string | Buffer - key?: string | string[] | Buffer | Buffer[]; - passphrase?: string; - cert?: string | string[] | Buffer | Buffer[]; - ca?: string | Buffer | (string | Buffer)[]; - rejectUnauthorized?: boolean; - NPNProtocols?: (string | Buffer)[]; - servername?: string; - path?: string; - ALPNProtocols?: (string | Buffer)[]; - checkServerIdentity?: (servername: string, cert: string | Buffer | (string | Buffer)[]) => any; - secureProtocol?: string; - secureContext?: Object; - session?: Buffer; - minDHSize?: number; - } - - export interface Server extends net.Server { - close(): Server; - address(): { port: number; family: string; address: string; }; - addContext(hostName: string, credentials: { - key: string; - cert: string; - ca: string; - }): void; - maxConnections: number; - connections: number; - } - - export interface ClearTextStream extends stream.Duplex { - authorized: boolean; - authorizationError: Error; - getPeerCertificate(): any; - getCipher: { - name: string; - version: string; - }; - address: { - port: number; - family: string; - address: string; - }; - remoteAddress: string; - remotePort: number; - } - - export interface SecurePair { - encrypted: any; - cleartext: any; - } - - export interface SecureContextOptions { - pfx?: string | Buffer; - key?: string | Buffer; - passphrase?: string; - cert?: string | Buffer; - ca?: string | Buffer; - crl?: string | string[] - ciphers?: string; - honorCipherOrder?: boolean; - } - - export interface SecureContext { - context: any; - } - - export function createServer(options: TlsOptions, secureConnectionListener?: (cleartextStream: ClearTextStream) => void): Server; - export function connect(options: ConnectionOptions, secureConnectionListener?: () => void): ClearTextStream; - export function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () => void): ClearTextStream; - export function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () => void): ClearTextStream; - export function createSecurePair(credentials?: crypto.Credentials, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; - export function createSecureContext(details: SecureContextOptions): SecureContext; -} - -declare module "crypto" { - export interface Certificate { - exportChallenge(spkac: string | Buffer): Buffer; - exportPublicKey(spkac: string | Buffer): Buffer; - verifySpkac(spkac: Buffer): boolean; - } - export var Certificate: { - new (): Certificate; - (): Certificate; - } - - export var fips: boolean; - - export interface CredentialDetails { - pfx: string; - key: string; - passphrase: string; - cert: string; - ca: string | string[]; - crl: string | string[]; - ciphers: string; - } - export interface Credentials { context?: any; } - export function createCredentials(details: CredentialDetails): Credentials; - export function createHash(algorithm: string): Hash; - export function createHmac(algorithm: string, key: string | Buffer): Hmac; - - type Utf8AsciiLatin1Encoding = "utf8" | "ascii" | "latin1"; - type HexBase64Latin1Encoding = "latin1" | "hex" | "base64"; - type Utf8AsciiBinaryEncoding = "utf8" | "ascii" | "binary"; - type HexBase64BinaryEncoding = "binary" | "base64" | "hex"; - type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid"; - - export interface Hash extends NodeJS.ReadWriteStream { - update(data: string | Buffer): Hash; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hash; - digest(): Buffer; - digest(encoding: HexBase64Latin1Encoding): string; - } - export interface Hmac extends NodeJS.ReadWriteStream { - update(data: string | Buffer): Hmac; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Hmac; - digest(): Buffer; - digest(encoding: HexBase64Latin1Encoding): string; - } - export function createCipher(algorithm: string, password: any): Cipher; - export function createCipheriv(algorithm: string, key: any, iv: any): Cipher; - export interface Cipher extends NodeJS.ReadWriteStream { - update(data: Buffer): Buffer; - update(data: string, input_encoding: Utf8AsciiBinaryEncoding): Buffer; - update(data: Buffer, input_encoding: any, output_encoding: HexBase64BinaryEncoding): string; - update(data: string, input_encoding: Utf8AsciiBinaryEncoding, output_encoding: HexBase64BinaryEncoding): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding?: boolean): void; - getAuthTag(): Buffer; - setAAD(buffer: Buffer): void; - } - export function createDecipher(algorithm: string, password: any): Decipher; - export function createDecipheriv(algorithm: string, key: any, iv: any): Decipher; - export interface Decipher extends NodeJS.ReadWriteStream { - update(data: Buffer): Buffer; - update(data: string, input_encoding: HexBase64BinaryEncoding): Buffer; - update(data: Buffer, input_encoding: any, output_encoding: Utf8AsciiBinaryEncoding): string; - update(data: string, input_encoding: HexBase64BinaryEncoding, output_encoding: Utf8AsciiBinaryEncoding): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding?: boolean): void; - setAuthTag(tag: Buffer): void; - setAAD(buffer: Buffer): void; - } - export function createSign(algorithm: string): Signer; - export interface Signer extends NodeJS.WritableStream { - update(data: string | Buffer): Signer; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Signer; - sign(private_key: string | { key: string; passphrase: string }): Buffer; - sign(private_key: string | { key: string; passphrase: string }, output_format: HexBase64Latin1Encoding): string; - } - export function createVerify(algorith: string): Verify; - export interface Verify extends NodeJS.WritableStream { - update(data: string | Buffer): Verify; - update(data: string | Buffer, input_encoding: Utf8AsciiLatin1Encoding): Verify; - verify(object: string, signature: Buffer): boolean; - verify(object: string, signature: string, signature_format: HexBase64Latin1Encoding): boolean; - } - export function createDiffieHellman(prime_length: number, generator?: number): DiffieHellman; - export function createDiffieHellman(prime: Buffer): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: number | Buffer): DiffieHellman; - export function createDiffieHellman(prime: string, prime_encoding: HexBase64Latin1Encoding, generator: string, generator_encoding: HexBase64Latin1Encoding): DiffieHellman; - export interface DiffieHellman { - generateKeys(): Buffer; - generateKeys(encoding: HexBase64Latin1Encoding): string; - computeSecret(other_public_key: Buffer): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; - getPrime(): Buffer; - getPrime(encoding: HexBase64Latin1Encoding): string; - getGenerator(): Buffer; - getGenerator(encoding: HexBase64Latin1Encoding): string; - getPublicKey(): Buffer; - getPublicKey(encoding: HexBase64Latin1Encoding): string; - getPrivateKey(): Buffer; - getPrivateKey(encoding: HexBase64Latin1Encoding): string; - setPublicKey(public_key: Buffer): void; - setPublicKey(public_key: string, encoding: string): void; - setPrivateKey(private_key: Buffer): void; - setPrivateKey(private_key: string, encoding: string): void; - verifyError: number; - } - export function getDiffieHellman(group_name: string): DiffieHellman; - export function pbkdf2(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string, callback: (err: Error, derivedKey: Buffer) => any): void; - export function pbkdf2Sync(password: string | Buffer, salt: string | Buffer, iterations: number, keylen: number, digest: string): Buffer; - export function randomBytes(size: number): Buffer; - export function randomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; - export function pseudoRandomBytes(size: number): Buffer; - export function pseudoRandomBytes(size: number, callback: (err: Error, buf: Buffer) => void): void; - export interface RsaPublicKey { - key: string; - padding?: number; - } - export interface RsaPrivateKey { - key: string; - passphrase?: string, - padding?: number; - } - export function publicEncrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer - export function privateDecrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer - export function privateEncrypt(private_key: string | RsaPrivateKey, buffer: Buffer): Buffer - export function publicDecrypt(public_key: string | RsaPublicKey, buffer: Buffer): Buffer - export function getCiphers(): string[]; - export function getCurves(): string[]; - export function getHashes(): string[]; - export interface ECDH { - generateKeys(): Buffer; - generateKeys(encoding: HexBase64Latin1Encoding): string; - generateKeys(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; - computeSecret(other_public_key: Buffer): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding): Buffer; - computeSecret(other_public_key: string, input_encoding: HexBase64Latin1Encoding, output_encoding: HexBase64Latin1Encoding): string; - getPrivateKey(): Buffer; - getPrivateKey(encoding: HexBase64Latin1Encoding): string; - getPublicKey(): Buffer; - getPublicKey(encoding: HexBase64Latin1Encoding): string; - getPublicKey(encoding: HexBase64Latin1Encoding, format: ECDHKeyFormat): string; - setPrivateKey(private_key: Buffer): void; - setPrivateKey(private_key: string, encoding: HexBase64Latin1Encoding): void; - } - export function createECDH(curve_name: string): ECDH; - export var DEFAULT_ENCODING: string; -} - -declare module "stream" { - import * as events from "events"; - - class internal extends events.EventEmitter { - pipe(destination: T, options?: { end?: boolean; }): T; - } - namespace internal { - - export class Stream extends internal { } - - export interface ReadableOptions { - highWaterMark?: number; - encoding?: string; - objectMode?: boolean; - read?: (size?: number) => any; - } - - export class Readable extends events.EventEmitter implements NodeJS.ReadableStream { - readable: boolean; - constructor(opts?: ReadableOptions); - _read(size: number): void; - read(size?: number): any; - setEncoding(encoding: string): void; - pause(): Readable; - resume(): Readable; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: any): void; - wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; - push(chunk: any, encoding?: string): boolean; - - /** - * Event emitter - * The defined events on documents including: - * 1. close - * 2. data - * 3. end - * 4. readable - * 5. error - **/ - addListener(event: string, listener: Function): this; - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "data", listener: (chunk: Buffer | string) => void): this; - addListener(event: "end", listener: () => void): this; - addListener(event: "readable", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "data", chunk: Buffer | string): boolean; - emit(event: "end"): boolean; - emit(event: "readable"): boolean; - emit(event: "error", err: Error): boolean; - - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "data", listener: (chunk: Buffer | string) => void): this; - on(event: "end", listener: () => void): this; - on(event: "readable", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "data", listener: (chunk: Buffer | string) => void): this; - once(event: "end", listener: () => void): this; - once(event: "readable", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependListener(event: "end", listener: () => void): this; - prependListener(event: "readable", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this; - prependOnceListener(event: "end", listener: () => void): this; - prependOnceListener(event: "readable", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - - removeListener(event: string, listener: Function): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "data", listener: (chunk: Buffer | string) => void): this; - removeListener(event: "end", listener: () => void): this; - removeListener(event: "readable", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - } - - export interface WritableOptions { - highWaterMark?: number; - decodeStrings?: boolean; - objectMode?: boolean; - write?: (chunk: string | Buffer, encoding: string, callback: Function) => any; - writev?: (chunks: { chunk: string | Buffer, encoding: string }[], callback: Function) => any; - } - - export class Writable extends events.EventEmitter implements NodeJS.WritableStream { - writable: boolean; - constructor(opts?: WritableOptions); - _write(chunk: any, encoding: string, callback: Function): void; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; - - /** - * Event emitter - * The defined events on documents including: - * 1. close - * 2. drain - * 3. error - * 4. finish - * 5. pipe - * 6. unpipe - **/ - addListener(event: string, listener: Function): this; - addListener(event: "close", listener: () => void): this; - addListener(event: "drain", listener: () => void): this; - addListener(event: "error", listener: (err: Error) => void): this; - addListener(event: "finish", listener: () => void): this; - addListener(event: "pipe", listener: (src: Readable) => void): this; - addListener(event: "unpipe", listener: (src: Readable) => void): this; - - emit(event: string, ...args: any[]): boolean; - emit(event: "close"): boolean; - emit(event: "drain", chunk: Buffer | string): boolean; - emit(event: "error", err: Error): boolean; - emit(event: "finish"): boolean; - emit(event: "pipe", src: Readable): boolean; - emit(event: "unpipe", src: Readable): boolean; - - on(event: string, listener: Function): this; - on(event: "close", listener: () => void): this; - on(event: "drain", listener: () => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "finish", listener: () => void): this; - on(event: "pipe", listener: (src: Readable) => void): this; - on(event: "unpipe", listener: (src: Readable) => void): this; - - once(event: string, listener: Function): this; - once(event: "close", listener: () => void): this; - once(event: "drain", listener: () => void): this; - once(event: "error", listener: (err: Error) => void): this; - once(event: "finish", listener: () => void): this; - once(event: "pipe", listener: (src: Readable) => void): this; - once(event: "unpipe", listener: (src: Readable) => void): this; - - prependListener(event: string, listener: Function): this; - prependListener(event: "close", listener: () => void): this; - prependListener(event: "drain", listener: () => void): this; - prependListener(event: "error", listener: (err: Error) => void): this; - prependListener(event: "finish", listener: () => void): this; - prependListener(event: "pipe", listener: (src: Readable) => void): this; - prependListener(event: "unpipe", listener: (src: Readable) => void): this; - - prependOnceListener(event: string, listener: Function): this; - prependOnceListener(event: "close", listener: () => void): this; - prependOnceListener(event: "drain", listener: () => void): this; - prependOnceListener(event: "error", listener: (err: Error) => void): this; - prependOnceListener(event: "finish", listener: () => void): this; - prependOnceListener(event: "pipe", listener: (src: Readable) => void): this; - prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this; - - removeListener(event: string, listener: Function): this; - removeListener(event: "close", listener: () => void): this; - removeListener(event: "drain", listener: () => void): this; - removeListener(event: "error", listener: (err: Error) => void): this; - removeListener(event: "finish", listener: () => void): this; - removeListener(event: "pipe", listener: (src: Readable) => void): this; - removeListener(event: "unpipe", listener: (src: Readable) => void): this; - } - - export interface DuplexOptions extends ReadableOptions, WritableOptions { - allowHalfOpen?: boolean; - readableObjectMode?: boolean; - writableObjectMode?: boolean; - } - - // Note: Duplex extends both Readable and Writable. - export class Duplex extends Readable implements NodeJS.ReadWriteStream { - // Readable - pause(): Duplex; - resume(): Duplex; - // Writeable - writable: boolean; - constructor(opts?: DuplexOptions); - _write(chunk: any, encoding: string, callback: Function): void; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; - } - - export interface TransformOptions extends ReadableOptions, WritableOptions { - transform?: (chunk: string | Buffer, encoding: string, callback: Function) => any; - flush?: (callback: Function) => any; - } - - // Note: Transform lacks the _read and _write methods of Readable/Writable. - export class Transform extends events.EventEmitter implements NodeJS.ReadWriteStream { - readable: boolean; - writable: boolean; - constructor(opts?: TransformOptions); - _transform(chunk: any, encoding: string, callback: Function): void; - _flush(callback: Function): void; - read(size?: number): any; - setEncoding(encoding: string): void; - pause(): Transform; - resume(): Transform; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: any): void; - wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; - push(chunk: any, encoding?: string): boolean; - write(chunk: any, cb?: Function): boolean; - write(chunk: any, encoding?: string, cb?: Function): boolean; - end(): void; - end(chunk: any, cb?: Function): void; - end(chunk: any, encoding?: string, cb?: Function): void; - } - - export class PassThrough extends Transform { } - } - - export = internal; -} - -declare module "util" { - export interface InspectOptions { - showHidden?: boolean; - depth?: number; - colors?: boolean; - customInspect?: boolean; - } - - export function format(format: any, ...param: any[]): string; - export function debug(string: string): void; - export function error(...param: any[]): void; - export function puts(...param: any[]): void; - export function print(...param: any[]): void; - export function log(string: string): void; - export function inspect(object: any, showHidden?: boolean, depth?: number, color?: boolean): string; - export function inspect(object: any, options: InspectOptions): string; - export function isArray(object: any): boolean; - export function isRegExp(object: any): boolean; - export function isDate(object: any): boolean; - export function isError(object: any): boolean; - export function inherits(constructor: any, superConstructor: any): void; - export function debuglog(key: string): (msg: string, ...param: any[]) => void; - export function isBoolean(object: any): boolean; - export function isBuffer(object: any): boolean; - export function isFunction(object: any): boolean; - export function isNull(object: any): boolean; - export function isNullOrUndefined(object: any): boolean; - export function isNumber(object: any): boolean; - export function isObject(object: any): boolean; - export function isPrimitive(object: any): boolean; - export function isString(object: any): boolean; - export function isSymbol(object: any): boolean; - export function isUndefined(object: any): boolean; - export function deprecate(fn: Function, message: string): Function; -} - -declare module "assert" { - function internal(value: any, message?: string): void; - namespace internal { - export class AssertionError implements Error { - name: string; - message: string; - actual: any; - expected: any; - operator: string; - generatedMessage: boolean; - - constructor(options?: { - message?: string; actual?: any; expected?: any; - operator?: string; stackStartFunction?: Function - }); - } - - export function fail(actual: any, expected: any, message: string, operator: string): void; - export function ok(value: any, message?: string): void; - export function equal(actual: any, expected: any, message?: string): void; - export function notEqual(actual: any, expected: any, message?: string): void; - export function deepEqual(actual: any, expected: any, message?: string): void; - export function notDeepEqual(acutal: any, expected: any, message?: string): void; - export function strictEqual(actual: any, expected: any, message?: string): void; - export function notStrictEqual(actual: any, expected: any, message?: string): void; - export function deepStrictEqual(actual: any, expected: any, message?: string): void; - export function notDeepStrictEqual(actual: any, expected: any, message?: string): void; - export var throws: { - (block: Function, message?: string): void; - (block: Function, error: Function, message?: string): void; - (block: Function, error: RegExp, message?: string): void; - (block: Function, error: (err: any) => boolean, message?: string): void; - }; - - export var doesNotThrow: { - (block: Function, message?: string): void; - (block: Function, error: Function, message?: string): void; - (block: Function, error: RegExp, message?: string): void; - (block: Function, error: (err: any) => boolean, message?: string): void; - }; - - export function ifError(value: any): void; - } - - export = internal; -} - -declare module "tty" { - import * as net from "net"; - - export function isatty(fd: number): boolean; - export interface ReadStream extends net.Socket { - isRaw: boolean; - setRawMode(mode: boolean): void; - isTTY: boolean; - } - export interface WriteStream extends net.Socket { - columns: number; - rows: number; - isTTY: boolean; - } -} - -declare module "domain" { - import * as events from "events"; - - export class Domain extends events.EventEmitter implements NodeJS.Domain { - run(fn: Function): void; - add(emitter: events.EventEmitter): void; - remove(emitter: events.EventEmitter): void; - bind(cb: (err: Error, data: any) => any): any; - intercept(cb: (data: any) => any): any; - dispose(): void; - members: any[]; - enter(): void; - exit(): void; - } - - export function create(): Domain; -} - -declare module "constants" { - export var E2BIG: number; - export var EACCES: number; - export var EADDRINUSE: number; - export var EADDRNOTAVAIL: number; - export var EAFNOSUPPORT: number; - export var EAGAIN: number; - export var EALREADY: number; - export var EBADF: number; - export var EBADMSG: number; - export var EBUSY: number; - export var ECANCELED: number; - export var ECHILD: number; - export var ECONNABORTED: number; - export var ECONNREFUSED: number; - export var ECONNRESET: number; - export var EDEADLK: number; - export var EDESTADDRREQ: number; - export var EDOM: number; - export var EEXIST: number; - export var EFAULT: number; - export var EFBIG: number; - export var EHOSTUNREACH: number; - export var EIDRM: number; - export var EILSEQ: number; - export var EINPROGRESS: number; - export var EINTR: number; - export var EINVAL: number; - export var EIO: number; - export var EISCONN: number; - export var EISDIR: number; - export var ELOOP: number; - export var EMFILE: number; - export var EMLINK: number; - export var EMSGSIZE: number; - export var ENAMETOOLONG: number; - export var ENETDOWN: number; - export var ENETRESET: number; - export var ENETUNREACH: number; - export var ENFILE: number; - export var ENOBUFS: number; - export var ENODATA: number; - export var ENODEV: number; - export var ENOENT: number; - export var ENOEXEC: number; - export var ENOLCK: number; - export var ENOLINK: number; - export var ENOMEM: number; - export var ENOMSG: number; - export var ENOPROTOOPT: number; - export var ENOSPC: number; - export var ENOSR: number; - export var ENOSTR: number; - export var ENOSYS: number; - export var ENOTCONN: number; - export var ENOTDIR: number; - export var ENOTEMPTY: number; - export var ENOTSOCK: number; - export var ENOTSUP: number; - export var ENOTTY: number; - export var ENXIO: number; - export var EOPNOTSUPP: number; - export var EOVERFLOW: number; - export var EPERM: number; - export var EPIPE: number; - export var EPROTO: number; - export var EPROTONOSUPPORT: number; - export var EPROTOTYPE: number; - export var ERANGE: number; - export var EROFS: number; - export var ESPIPE: number; - export var ESRCH: number; - export var ETIME: number; - export var ETIMEDOUT: number; - export var ETXTBSY: number; - export var EWOULDBLOCK: number; - export var EXDEV: number; - export var WSAEINTR: number; - export var WSAEBADF: number; - export var WSAEACCES: number; - export var WSAEFAULT: number; - export var WSAEINVAL: number; - export var WSAEMFILE: number; - export var WSAEWOULDBLOCK: number; - export var WSAEINPROGRESS: number; - export var WSAEALREADY: number; - export var WSAENOTSOCK: number; - export var WSAEDESTADDRREQ: number; - export var WSAEMSGSIZE: number; - export var WSAEPROTOTYPE: number; - export var WSAENOPROTOOPT: number; - export var WSAEPROTONOSUPPORT: number; - export var WSAESOCKTNOSUPPORT: number; - export var WSAEOPNOTSUPP: number; - export var WSAEPFNOSUPPORT: number; - export var WSAEAFNOSUPPORT: number; - export var WSAEADDRINUSE: number; - export var WSAEADDRNOTAVAIL: number; - export var WSAENETDOWN: number; - export var WSAENETUNREACH: number; - export var WSAENETRESET: number; - export var WSAECONNABORTED: number; - export var WSAECONNRESET: number; - export var WSAENOBUFS: number; - export var WSAEISCONN: number; - export var WSAENOTCONN: number; - export var WSAESHUTDOWN: number; - export var WSAETOOMANYREFS: number; - export var WSAETIMEDOUT: number; - export var WSAECONNREFUSED: number; - export var WSAELOOP: number; - export var WSAENAMETOOLONG: number; - export var WSAEHOSTDOWN: number; - export var WSAEHOSTUNREACH: number; - export var WSAENOTEMPTY: number; - export var WSAEPROCLIM: number; - export var WSAEUSERS: number; - export var WSAEDQUOT: number; - export var WSAESTALE: number; - export var WSAEREMOTE: number; - export var WSASYSNOTREADY: number; - export var WSAVERNOTSUPPORTED: number; - export var WSANOTINITIALISED: number; - export var WSAEDISCON: number; - export var WSAENOMORE: number; - export var WSAECANCELLED: number; - export var WSAEINVALIDPROCTABLE: number; - export var WSAEINVALIDPROVIDER: number; - export var WSAEPROVIDERFAILEDINIT: number; - export var WSASYSCALLFAILURE: number; - export var WSASERVICE_NOT_FOUND: number; - export var WSATYPE_NOT_FOUND: number; - export var WSA_E_NO_MORE: number; - export var WSA_E_CANCELLED: number; - export var WSAEREFUSED: number; - export var SIGHUP: number; - export var SIGINT: number; - export var SIGILL: number; - export var SIGABRT: number; - export var SIGFPE: number; - export var SIGKILL: number; - export var SIGSEGV: number; - export var SIGTERM: number; - export var SIGBREAK: number; - export var SIGWINCH: number; - export var SSL_OP_ALL: number; - export var SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; - export var SSL_OP_CIPHER_SERVER_PREFERENCE: number; - export var SSL_OP_CISCO_ANYCONNECT: number; - export var SSL_OP_COOKIE_EXCHANGE: number; - export var SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; - export var SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; - export var SSL_OP_EPHEMERAL_RSA: number; - export var SSL_OP_LEGACY_SERVER_CONNECT: number; - export var SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number; - export var SSL_OP_MICROSOFT_SESS_ID_BUG: number; - export var SSL_OP_MSIE_SSLV2_RSA_PADDING: number; - export var SSL_OP_NETSCAPE_CA_DN_BUG: number; - export var SSL_OP_NETSCAPE_CHALLENGE_BUG: number; - export var SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NO_COMPRESSION: number; - export var SSL_OP_NO_QUERY_MTU: number; - export var SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; - export var SSL_OP_NO_SSLv2: number; - export var SSL_OP_NO_SSLv3: number; - export var SSL_OP_NO_TICKET: number; - export var SSL_OP_NO_TLSv1: number; - export var SSL_OP_NO_TLSv1_1: number; - export var SSL_OP_NO_TLSv1_2: number; - export var SSL_OP_PKCS1_CHECK_1: number; - export var SSL_OP_PKCS1_CHECK_2: number; - export var SSL_OP_SINGLE_DH_USE: number; - export var SSL_OP_SINGLE_ECDH_USE: number; - export var SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number; - export var SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number; - export var SSL_OP_TLS_BLOCK_PADDING_BUG: number; - export var SSL_OP_TLS_D5_BUG: number; - export var SSL_OP_TLS_ROLLBACK_BUG: number; - export var ENGINE_METHOD_DSA: number; - export var ENGINE_METHOD_DH: number; - export var ENGINE_METHOD_RAND: number; - export var ENGINE_METHOD_ECDH: number; - export var ENGINE_METHOD_ECDSA: number; - export var ENGINE_METHOD_CIPHERS: number; - export var ENGINE_METHOD_DIGESTS: number; - export var ENGINE_METHOD_STORE: number; - export var ENGINE_METHOD_PKEY_METHS: number; - export var ENGINE_METHOD_PKEY_ASN1_METHS: number; - export var ENGINE_METHOD_ALL: number; - export var ENGINE_METHOD_NONE: number; - export var DH_CHECK_P_NOT_SAFE_PRIME: number; - export var DH_CHECK_P_NOT_PRIME: number; - export var DH_UNABLE_TO_CHECK_GENERATOR: number; - export var DH_NOT_SUITABLE_GENERATOR: number; - export var NPN_ENABLED: number; - export var RSA_PKCS1_PADDING: number; - export var RSA_SSLV23_PADDING: number; - export var RSA_NO_PADDING: number; - export var RSA_PKCS1_OAEP_PADDING: number; - export var RSA_X931_PADDING: number; - export var RSA_PKCS1_PSS_PADDING: number; - export var POINT_CONVERSION_COMPRESSED: number; - export var POINT_CONVERSION_UNCOMPRESSED: number; - export var POINT_CONVERSION_HYBRID: number; - export var O_RDONLY: number; - export var O_WRONLY: number; - export var O_RDWR: number; - export var S_IFMT: number; - export var S_IFREG: number; - export var S_IFDIR: number; - export var S_IFCHR: number; - export var S_IFBLK: number; - export var S_IFIFO: number; - export var S_IFSOCK: number; - export var S_IRWXU: number; - export var S_IRUSR: number; - export var S_IWUSR: number; - export var S_IXUSR: number; - export var S_IRWXG: number; - export var S_IRGRP: number; - export var S_IWGRP: number; - export var S_IXGRP: number; - export var S_IRWXO: number; - export var S_IROTH: number; - export var S_IWOTH: number; - export var S_IXOTH: number; - export var S_IFLNK: number; - export var O_CREAT: number; - export var O_EXCL: number; - export var O_NOCTTY: number; - export var O_DIRECTORY: number; - export var O_NOATIME: number; - export var O_NOFOLLOW: number; - export var O_SYNC: number; - export var O_SYMLINK: number; - export var O_DIRECT: number; - export var O_NONBLOCK: number; - export var O_TRUNC: number; - export var O_APPEND: number; - export var F_OK: number; - export var R_OK: number; - export var W_OK: number; - export var X_OK: number; - export var UV_UDP_REUSEADDR: number; - export var SIGQUIT: number; - export var SIGTRAP: number; - export var SIGIOT: number; - export var SIGBUS: number; - export var SIGUSR1: number; - export var SIGUSR2: number; - export var SIGPIPE: number; - export var SIGALRM: number; - export var SIGCHLD: number; - export var SIGSTKFLT: number; - export var SIGCONT: number; - export var SIGSTOP: number; - export var SIGTSTP: number; - export var SIGTTIN: number; - export var SIGTTOU: number; - export var SIGURG: number; - export var SIGXCPU: number; - export var SIGXFSZ: number; - export var SIGVTALRM: number; - export var SIGPROF: number; - export var SIGIO: number; - export var SIGPOLL: number; - export var SIGPWR: number; - export var SIGSYS: number; - export var SIGUNUSED: number; - export var defaultCoreCipherList: string; - export var defaultCipherList: string; - export var ENGINE_METHOD_RSA: number; - export var ALPN_ENABLED: number; -} - -declare module "process" { - export = process; -} - -declare module "v8" { - interface HeapSpaceInfo { - space_name: string; - space_size: number; - space_used_size: number; - space_available_size: number; - physical_space_size: number; - } - export function getHeapStatistics(): { total_heap_size: number, total_heap_size_executable: number, total_physical_size: number, total_avaialble_size: number, used_heap_size: number, heap_size_limit: number }; - export function getHeapSpaceStatistics(): HeapSpaceInfo[]; - export function setFlagsFromString(flags: string): void; -} - -declare module "timers" { - export function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; - export function clearTimeout(timeoutId: NodeJS.Timer): void; - export function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; - export function clearInterval(intervalId: NodeJS.Timer): void; - export function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; - export function clearImmediate(immediateId: any): void; -} - -declare module "console" { - export = console; -} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json b/Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json deleted file mode 100644 index 7b15c87df6f1..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings/globals/node/typings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "resolution": "main", - "tree": { - "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/3423aa94ffdbe8f4ded33733318e08020a2d6ca8/node/node.d.ts", - "raw": "registry:dt/node#6.0.0+20160914131736", - "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/3423aa94ffdbe8f4ded33733318e08020a2d6ca8/node/node.d.ts" - } -} diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts deleted file mode 100644 index 4449c31841ff..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings/globals/q/index.d.ts +++ /dev/null @@ -1,357 +0,0 @@ -// Generated by typings -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/623f30ab194a3486e014ca39bc7f2089897d6ce4/q/Q.d.ts -declare function Q(promise: Q.IPromise): Q.Promise; -/** - * If value is not a promise, returns a promise that is fulfilled with value. - */ -declare function Q(value: T): Q.Promise; - -declare namespace Q { - interface IPromise { - then(onFulfill?: (value: T) => U | IPromise, onReject?: (error: any) => U | IPromise): IPromise; - } - - interface Deferred { - promise: Promise; - resolve(value?: T): void; - resolve(value?: IPromise): void; - reject(reason: any): void; - notify(value: any): void; - makeNodeResolver(): (reason: any, value: T) => void; - } - - interface Promise { - /** - * Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object. - - * finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished. - */ - fin(finallyCallback: () => any): Promise; - /** - * Like a finally clause, allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful for collecting resources regardless of whether a job succeeded, like closing a database connection, shutting a server down, or deleting an unneeded key from an object. - - * finally returns a promise, which will become resolved with the same fulfillment value or rejection reason as promise. However, if callback returns a promise, the resolution of the returned promise will be delayed until the promise returned from callback is finished. - */ - finally(finallyCallback: () => any): Promise; - - /** - * The then method from the Promises/A+ specification, with an additional progress handler. - */ - then(onFulfill?: (value: T) => U | IPromise, onReject?: (error: any) => U | IPromise, onProgress?: Function): Promise; - - /** - * Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason. - * - * This is especially useful in conjunction with all - */ - spread(onFulfill: (...args: any[]) => IPromise | U, onReject?: (reason: any) => IPromise | U): Promise; - - fail(onRejected: (reason: any) => U | IPromise): Promise; - - /** - * A sugar method, equivalent to promise.then(undefined, onRejected). - */ - catch(onRejected: (reason: any) => U | IPromise): Promise; - - /** - * A sugar method, equivalent to promise.then(undefined, undefined, onProgress). - */ - progress(onProgress: (progress: any) => any): Promise; - - /** - * Much like then, but with different behavior around unhandled rejection. If there is an unhandled rejection, either because promise is rejected and no onRejected callback was provided, or because onFulfilled or onRejected threw an error or returned a rejected promise, the resulting rejection reason is thrown as an exception in a future turn of the event loop. - * - * This method should be used to terminate chains of promises that will not be passed elsewhere. Since exceptions thrown in then callbacks are consumed and transformed into rejections, exceptions at the end of the chain are easy to accidentally, silently ignore. By arranging for the exception to be thrown in a future turn of the event loop, so that it won't be caught, it causes an onerror event on the browser window, or an uncaughtException event on Node.js's process object. - * - * Exceptions thrown by done will have long stack traces, if Q.longStackSupport is set to true. If Q.onerror is set, exceptions will be delivered there instead of thrown in a future turn. - * - * The Golden Rule of done vs. then usage is: either return your promise to someone else, or if the chain ends with you, call done to terminate it. - */ - done(onFulfilled?: (value: T) => any, onRejected?: (reason: any) => any, onProgress?: (progress: any) => any): void; - - /** - * If callback is a function, assumes it's a Node.js-style callback, and calls it as either callback(rejectionReason) when/if promise becomes rejected, or as callback(null, fulfillmentValue) when/if promise becomes fulfilled. If callback is not a function, simply returns promise. - */ - nodeify(callback: (reason: any, value: any) => void): Promise; - - /** - * Returns a promise to get the named property of an object. Essentially equivalent to - * - * promise.then(function (o) { - * return o[propertyName]; - * }); - */ - get(propertyName: String): Promise; - set(propertyName: String, value: any): Promise; - delete(propertyName: String): Promise; - /** - * Returns a promise for the result of calling the named method of an object with the given array of arguments. The object itself is this in the function, just like a synchronous method call. Essentially equivalent to - * - * promise.then(function (o) { - * return o[methodName].apply(o, args); - * }); - */ - post(methodName: String, args: any[]): Promise; - /** - * Returns a promise for the result of calling the named method of an object with the given variadic arguments. The object itself is this in the function, just like a synchronous method call. - */ - invoke(methodName: String, ...args: any[]): Promise; - fapply(args: any[]): Promise; - fcall(...args: any[]): Promise; - - /** - * Returns a promise for an array of the property names of an object. Essentially equivalent to - * - * promise.then(function (o) { - * return Object.keys(o); - * }); - */ - keys(): Promise; - - /** - * A sugar method, equivalent to promise.then(function () { return value; }). - */ - thenResolve(value: U): Promise; - /** - * A sugar method, equivalent to promise.then(function () { throw reason; }). - */ - thenReject(reason: any): Promise; - - /** - * Attaches a handler that will observe the value of the promise when it becomes fulfilled, returning a promise for that same value, perhaps deferred but not replaced by the promise returned by the onFulfilled handler. - */ - tap(onFulfilled: (value: T) => any): Promise; - - timeout(ms: number, message?: string): Promise; - /** - * Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed. - */ - delay(ms: number): Promise; - - /** - * Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true. - */ - isFulfilled(): boolean; - /** - * Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false. - */ - isRejected(): boolean; - /** - * Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false. - */ - isPending(): boolean; - - valueOf(): any; - - /** - * Returns a "state snapshot" object, which will be in one of three forms: - * - * - { state: "pending" } - * - { state: "fulfilled", value: } - * - { state: "rejected", reason: } - */ - inspect(): PromiseState; - } - - interface PromiseState { - /** - * "fulfilled", "rejected", "pending" - */ - state: string; - value?: T; - reason?: any; - } - - // If no value provided, returned promise will be of void type - export function when(): Promise; - - // if no fulfill, reject, or progress provided, returned promise will be of same type - export function when(value: T | IPromise): Promise; - - // If a non-promise value is provided, it will not reject or progress - export function when(value: T | IPromise, onFulfilled: (val: T) => U | IPromise, onRejected?: (reason: any) => U | IPromise, onProgress?: (progress: any) => any): Promise; - - /** - * Currently "impossible" (and I use the term loosely) to implement due to TypeScript limitations as it is now. - * See: https://github.com/Microsoft/TypeScript/issues/1784 for discussion on it. - */ - // export function try(method: Function, ...args: any[]): Promise; - - export function fbind(method: (...args: any[]) => T | IPromise, ...args: any[]): (...args: any[]) => Promise; - - export function fcall(method: (...args: any[]) => T, ...args: any[]): Promise; - - export function send(obj: any, functionName: string, ...args: any[]): Promise; - export function invoke(obj: any, functionName: string, ...args: any[]): Promise; - export function mcall(obj: any, functionName: string, ...args: any[]): Promise; - - export function denodeify(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise; - export function nbind(nodeFunction: Function, thisArg: any, ...args: any[]): (...args: any[]) => Promise; - export function nfbind(nodeFunction: Function, ...args: any[]): (...args: any[]) => Promise; - export function nfcall(nodeFunction: Function, ...args: any[]): Promise; - export function nfapply(nodeFunction: Function, args: any[]): Promise; - - export function ninvoke(nodeModule: any, functionName: string, ...args: any[]): Promise; - export function npost(nodeModule: any, functionName: string, args: any[]): Promise; - export function nsend(nodeModule: any, functionName: string, ...args: any[]): Promise; - export function nmcall(nodeModule: any, functionName: string, ...args: any[]): Promise; - - /** - * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. - */ - export function all(promises: [IPromise, IPromise, IPromise, IPromise, IPromise, IPromise]): Promise<[A, B, C, D, E, F]>; - /** - * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. - */ - export function all(promises: [IPromise, IPromise, IPromise, IPromise, IPromise]): Promise<[A, B, C, D, E]>; - /** - * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. - */ - export function all(promises: [IPromise, IPromise, IPromise, IPromise]): Promise<[A, B, C, D]>; - /** - * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. - */ - export function all(promises: [IPromise, IPromise, IPromise]): Promise<[A, B, C]>; - /** - * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. - */ - export function all(promises: [IPromise, IPromise]): Promise<[A, B]>; - /** - * Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. - */ - export function all(promises: IPromise[]): Promise; - - /** - * Returns a promise for the first of an array of promises to become settled. - */ - export function race(promises: IPromise[]): Promise; - - /** - * Returns a promise that is fulfilled with an array of promise state snapshots, but only after all the original promises have settled, i.e. become either fulfilled or rejected. - */ - export function allSettled(promises: IPromise[]): Promise[]>; - - export function allResolved(promises: IPromise[]): Promise[]>; - - /** - * Like then, but "spreads" the array into a variadic fulfillment handler. If any of the promises in the array are rejected, instead calls onRejected with the first rejected promise's rejection reason. - * This is especially useful in conjunction with all. - */ - export function spread(promises: IPromise[], onFulfilled: (...args: T[]) => U | IPromise, onRejected?: (reason: any) => U | IPromise): Promise; - - /** - * Returns a promise that will have the same result as promise, except that if promise is not fulfilled or rejected before ms milliseconds, the returned promise will be rejected with an Error with the given message. If message is not supplied, the message will be "Timed out after " + ms + " ms". - */ - export function timeout(promise: Promise, ms: number, message?: string): Promise; - - /** - * Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed. - */ - export function delay(promise: Promise, ms: number): Promise; - /** - * Returns a promise that will have the same result as promise, but will only be fulfilled or rejected after at least ms milliseconds have passed. - */ - export function delay(value: T, ms: number): Promise; - /** - * Returns a promise that will be fulfilled with undefined after at least ms milliseconds have passed. - */ - export function delay(ms: number): Promise ; - /** - * Returns whether a given promise is in the fulfilled state. When the static version is used on non-promises, the result is always true. - */ - export function isFulfilled(promise: Promise): boolean; - /** - * Returns whether a given promise is in the rejected state. When the static version is used on non-promises, the result is always false. - */ - export function isRejected(promise: Promise): boolean; - /** - * Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false. - */ - export function isPending(promise: Promise): boolean; - - /** - * Returns a "deferred" object with a: - * promise property - * resolve(value) method - * reject(reason) method - * notify(value) method - * makeNodeResolver() method - */ - export function defer(): Deferred; - - /** - * Returns a promise that is rejected with reason. - */ - export function reject(reason?: any): Promise; - - export function Promise(resolver: (resolve: (val: T | IPromise) => void , reject: (reason: any) => void , notify: (progress: any) => void ) => void ): Promise; - - /** - * Creates a new version of func that accepts any combination of promise and non-promise values, converting them to their fulfillment values before calling the original func. The returned version also always returns a promise: if func does a return or throw, then Q.promised(func) will return fulfilled or rejected promise, respectively. - * - * This can be useful for creating functions that accept either promises or non-promise values, and for ensuring that the function always returns a promise even in the face of unintentional thrown exceptions. - */ - export function promised(callback: (...args: any[]) => T): (...args: any[]) => Promise; - - /** - * Returns whether the given value is a Q promise. - */ - export function isPromise(object: any): boolean; - /** - * Returns whether the given value is a promise (i.e. it's an object with a then function). - */ - export function isPromiseAlike(object: any): boolean; - /** - * Returns whether a given promise is in the pending state. When the static version is used on non-promises, the result is always false. - */ - export function isPending(object: any): boolean; - /** - * If an object is not a promise, it is as "near" as possible. - * If a promise is rejected, it is as "near" as possible too. - * If it’s a fulfilled promise, the fulfillment value is nearer. - * If it’s a deferred promise and the deferred has been resolved, the - * resolution is "nearer". - */ - export function nearer(promise: Promise): T; - - /** - * This is an experimental tool for converting a generator function into a deferred function. This has the potential of reducing nested callbacks in engines that support yield. - */ - export function async(generatorFunction: any): (...args: any[]) => Promise; - export function nextTick(callback: Function): void; - - /** - * A settable property that will intercept any uncaught errors that would otherwise be thrown in the next tick of the event loop, usually as a result of done. Can be useful for getting the full stack trace of an error in browsers, which is not usually possible with window.onerror. - */ - export var onerror: (reason: any) => void; - /** - * A settable property that lets you turn on long stack trace support. If turned on, "stack jumps" will be tracked across asynchronous promise operations, so that if an uncaught error is thrown by done or a rejection reason's stack property is inspected in a rejection callback, a long stack trace is produced. - */ - export var longStackSupport: boolean; - - /** - * Calling resolve with a pending promise causes promise to wait on the passed promise, becoming fulfilled with its fulfillment value or rejected with its rejection reason (or staying pending forever, if the passed promise does). - * Calling resolve with a rejected promise causes promise to be rejected with the passed promise's rejection reason. - * Calling resolve with a fulfilled promise causes promise to be fulfilled with the passed promise's fulfillment value. - * Calling resolve with a non-promise value causes promise to be fulfilled with that value. - */ - export function resolve(object: IPromise): Promise; - /** - * Calling resolve with a pending promise causes promise to wait on the passed promise, becoming fulfilled with its fulfillment value or rejected with its rejection reason (or staying pending forever, if the passed promise does). - * Calling resolve with a rejected promise causes promise to be rejected with the passed promise's rejection reason. - * Calling resolve with a fulfilled promise causes promise to be fulfilled with the passed promise's fulfillment value. - * Calling resolve with a non-promise value causes promise to be fulfilled with that value. - */ - export function resolve(object: T): Promise; - - /** - * Resets the global "Q" variable to the value it has before Q was loaded. - * This will either be undefined if there was no version or the version of Q which was already loaded before. - * @returns { The last version of Q. } - */ - export function noConflict(): typeof Q; -} - -declare module "q" { - export = Q; -} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json b/Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json deleted file mode 100644 index 3d59355a87e8..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings/globals/q/typings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "resolution": "main", - "tree": { - "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/623f30ab194a3486e014ca39bc7f2089897d6ce4/q/Q.d.ts", - "raw": "registry:dt/q#0.0.0+20160613154756", - "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/623f30ab194a3486e014ca39bc7f2089897d6ce4/q/Q.d.ts" - } -} diff --git a/Tasks/DotNetCoreInstallerV1/typings/index.d.ts b/Tasks/DotNetCoreInstallerV1/typings/index.d.ts deleted file mode 100644 index bbb3a42c2b21..000000000000 --- a/Tasks/DotNetCoreInstallerV1/typings/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -/// -/// -/// diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts index aa41f1eb5f50..f77a1759c4f6 100644 --- a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts @@ -24,31 +24,32 @@ export class DotNetCoreVersionFetcher { } : {}; this.httpCallbackClient = new httpClient.HttpClient(tl.getVariable("AZURE_HTTP_USER_AGENT"), null, requestOptions); + this.channels = []; } - public async getVersionInfo(version: string, packageType: string, includePreviewVersions: boolean): Promise { - var requiredVersion: VersionInfo = null; - if (this.releasesIndex == null) { + public async getVersionInfo(versionSpec: string, packageType: string, includePreviewVersions: boolean): Promise { + var requiredVersionInfo: VersionInfo = null; + if (!this.channels || this.channels.length < 1) { await this.setReleasesIndex(); } - let channelInformation: any = this.getVersionChannel(version); + let channelInformation = this.getVersionChannel(versionSpec); if (channelInformation) { - requiredVersion = await this.getVersionFromChannel(channelInformation, version, packageType, includePreviewVersions); + requiredVersionInfo = await this.getVersionFromChannel(channelInformation, versionSpec, packageType, includePreviewVersions); } - if (!requiredVersion && !version.endsWith("x")) { - console.log("FallingBackToAdjacentChannels", version); - requiredVersion = await this.getVersionFromOtherChannels(version, packageType, includePreviewVersions); + if (!requiredVersionInfo && !versionSpec.endsWith("x")) { + console.log(tl.loc("FallingBackToAdjacentChannels", versionSpec)); + requiredVersionInfo = await this.getVersionFromOtherChannels(versionSpec, packageType, includePreviewVersions); } - if (!requiredVersion) { - throw tl.loc("VersionNotFound", version); + if (!requiredVersionInfo) { + throw tl.loc("VersionNotFound", versionSpec); } - let dotNetSdkVersionTelemetry = `{"userVersion":"${version}", "resolvedVersion":"${requiredVersion.version}"}`; + let dotNetSdkVersionTelemetry = `{"userVersion":"${versionSpec}", "resolvedVersion":"${requiredVersionInfo.version}"}`; console.log("##vso[telemetry.publish area=TaskDeploymentMethod;feature=DotNetCoreInstallerV1]" + dotNetSdkVersionTelemetry); - return requiredVersion; + return requiredVersionInfo; } public getDownloadUrl(versionInfo: VersionInfo, packageType: string): string { @@ -59,7 +60,7 @@ export class DotNetCoreVersionFetcher { osSuffixes.find((osSuffix) => { downloadPackageInfoObject = versionInfo.files.find((downloadPackageInfo: any) => { if (downloadPackageInfo.rid.toLowerCase() == osSuffix.toLowerCase()) { - if (osSuffix.split("-")[0] != "win" || (osSuffix.split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip"))) { + if ((osSuffix.split("-")[0] != "win" && osSuffix.split("-")[0] != "osx") || (osSuffix.split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip")) || (osSuffix.split("-")[0] == "osx" && downloadPackageInfo.name.endsWith("tar.gz"))) { return true; } } @@ -79,7 +80,7 @@ export class DotNetCoreVersionFetcher { return downloadPackageInfoObject.url; } - return ""; + throw tl.loc("DownloadUrlForMatchingOsNotFound", packageType, versionInfo.version, osSuffixes.toString()); } private setReleasesIndex(): Promise { @@ -88,40 +89,52 @@ export class DotNetCoreVersionFetcher { return response.readBody(); }) .then((body: string) => { - this.releasesIndex = JSON.parse(body); - return; + let parsedReleasesIndexBody = JSON.parse(body); + if (!parsedReleasesIndexBody || !parsedReleasesIndexBody["releases-index"] || parsedReleasesIndexBody["releases-index"].length < 1) { + throw "Parsed releases index body is not correct." + } + + parsedReleasesIndexBody["releases-index"].forEach(channelRelease => { + if (channelRelease) { + try { + this.channels.push(new Channel(channelRelease)); + } + catch (ex) { + tl.debug("Channel information in releases-index.json was not proper. Error: " + JSON.stringify(ex)); + // do not fail, try to find version in the available channels. + } + } + }); }) .catch((ex) => { - throw tl.loc("ExceptionWhileDownloadOrReadReleasesIndex", ex); + throw tl.loc("ExceptionWhileDownloadOrReadReleasesIndex", JSON.stringify(ex)); }); } - private getVersionChannel(version: string): any { - let versionParts: any = new utils.VersionParts(version); + private getVersionChannel(versionSpec: string): Channel { + let versionParts = new utils.VersionParts(versionSpec); - let channelVersion = `${versionParts.majorVersion}.${versionParts.minorVersion}`; + let requiredChannelVersion = `${versionParts.majorVersion}.${versionParts.minorVersion}`; if (versionParts.minorVersion == "x") { var latestChannelVersion: string = `${versionParts.majorVersion}.0`; - this.releasesIndex["releases-index"].forEach(channel => { - if (utils.versionCompareFunction(channel["channel-version"], latestChannelVersion) > 0) { - latestChannelVersion = channel["channel-version"]; + this.channels.forEach(channel => { + if (utils.compareChannelVersion(channel.channelVersion, latestChannelVersion) > 0 && channel.channelVersion.startsWith(versionParts.majorVersion)) { + latestChannelVersion = channel.channelVersion; } }); - channelVersion = latestChannelVersion; + requiredChannelVersion = latestChannelVersion; } - return this.releasesIndex["releases-index"].find(element => { - if (element["channel-version"] == channelVersion) { + return this.channels.find(channel => { + if (channel.channelVersion == requiredChannelVersion) { return true } }); } - private getVersionFromChannel(channelInformation: any, version: string, packageType: string, includePreviewVersions: boolean): Promise { - let versionParts: utils.VersionParts = new utils.VersionParts(version); - var releasesJsonUrl: string = channelInformation["releases.json"]; - var channelReleases: any = null; + private getVersionFromChannel(channelInformation: Channel, versionSpec: string, packageType: string, includePreviewVersions: boolean): Promise { + var releasesJsonUrl: string = channelInformation.releasesJsonUrl; if (releasesJsonUrl) { return this.httpCallbackClient.get(releasesJsonUrl) @@ -129,53 +142,37 @@ export class DotNetCoreVersionFetcher { return response.readBody(); }) .then((body: string) => { - channelReleases = JSON.parse(body).releases; - if (versionParts.minorVersion == "x" || versionParts.patchVersion == "x") { - - let latestVersion = "0.0.0"; - channelReleases.forEach(release => { - if (release[packageType] && utils.versionCompareFunction(release[packageType].version, latestVersion) > 0 && (includePreviewVersions || !release[packageType].version.includes('preview'))) { - let matchedVersionParts = new utils.VersionParts(release[packageType].version); - if (matchedVersionParts.majorVersion == versionParts.majorVersion && (versionParts.minorVersion == "x" || (versionParts.patchVersion == "x" && matchedVersionParts.minorVersion == versionParts.minorVersion))) { - latestVersion = release[packageType].version; - } - } - }); - - if (latestVersion == "0.0.0") { - throw tl.loc("MatchingVersionNotFound", version); - } - - console.log(tl.loc("MatchingVersionForUserInputVersion", version, latestVersion)); - version = latestVersion; - } + var channelReleases = JSON.parse(body).releases; - var versionRelease = channelReleases.find(release => { - if (release[packageType] && release[packageType].version == version) { - return true; - } - - return false; + let versionInfoList: VersionInfo[] = channelReleases.map((release) => { + return release[packageType] && release[packageType].version ? release[packageType] : null; }); - return versionRelease ? versionRelease[packageType] : null; + let matchedVersionInfo = utils.getMatchingVersionFromList(versionInfoList, versionSpec, includePreviewVersions); + if (!matchedVersionInfo) { + console.log(tl.loc("MatchingVersionNotFound", versionSpec)); + return null; + } + + console.log(tl.loc("MatchingVersionForUserInputVersion", matchedVersionInfo.version, channelInformation.channelVersion, versionSpec)) + return matchedVersionInfo; }); } else { - throw tl.loc("UrlForReleaseChannelNotFound"); + tl.error(tl.loc("UrlForReleaseChannelNotFound", channelInformation.channelVersion)); } } - private async getVersionFromOtherChannels(version: string, packageType: string, includePreviewVersions: boolean): Promise { - let fallbackChannels = this.getChannelsForMajorVersion(version); + private async getVersionFromOtherChannels(versionSpec: string, packageType: string, includePreviewVersions: boolean): Promise { + let fallbackChannels = this.getChannelsForMajorVersion(versionSpec); if (!fallbackChannels && fallbackChannels.length < 1) { - throw tl.loc("NoSuitableChannelWereFound", version); + throw tl.loc("NoSuitableChannelWereFound", versionSpec); } var versionInfo: VersionInfo = null; for (var i = 0; i < fallbackChannels.length; i++) { - console.log("LookingForVersionInChannel", (fallbackChannels[i])["channel-version"]); - versionInfo = await this.getVersionFromChannel(fallbackChannels[i], version, packageType, includePreviewVersions); + console.log(tl.loc("LookingForVersionInChannel", (fallbackChannels[i]).channelVersion)); + versionInfo = await this.getVersionFromChannel(fallbackChannels[i], versionSpec, packageType, includePreviewVersions); if (versionInfo) { break; @@ -185,11 +182,11 @@ export class DotNetCoreVersionFetcher { return versionInfo; } - private getChannelsForMajorVersion(version: string): any { - var versionParts = new utils.VersionParts(version); - let adjacentChannels = []; - this.releasesIndex["releases-index"].forEach(channel => { - if (channel["channel-version"].startsWith(`${versionParts.majorVersion}`)) { + private getChannelsForMajorVersion(versionSpec: string): Channel[] { + var versionParts = new utils.VersionParts(versionSpec); + let adjacentChannels: Channel[] = []; + this.channels.forEach(channel => { + if (channel.channelVersion.startsWith(`${versionParts.majorVersion}`)) { adjacentChannels.push(channel); } }); @@ -245,7 +242,7 @@ export class DotNetCoreVersionFetcher { } } catch (ex) { - throw tl.loc("FailedInDetectingMachineArch", ex) + throw tl.loc("FailedInDetectingMachineArch", JSON.stringify(ex)); } return osSuffix; @@ -259,7 +256,7 @@ export class DotNetCoreVersionFetcher { return __dirname; } - private releasesIndex: any; + private channels: Channel[]; private httpCallbackClient: httpClient.HttpClient; } @@ -268,12 +265,12 @@ export class VersionInfo { public files: VersionFilesData[]; public static getRuntimeVersion(versionInfo: VersionInfo, packageType: string): string { - if (packageType == "sdk") { + if (packageType == utils.Constants.sdk) { if (versionInfo["runtime-version"]) { return versionInfo["runtime-version"]; } - tl.warning(tl.loc("runtimeVersionPropertyNotFound")); + tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, versionInfo.version)); } else { return versionInfo.version; @@ -290,4 +287,18 @@ export class VersionFilesData { public hash?: string; } +class Channel { + constructor(channelRelease: any) { + if (!channelRelease || !channelRelease["channel-version"] || !channelRelease["releases.json"]) { + throw "Object cannot be used as Channel, required properties such as channel-version, releases.json is missing. " + } + + this.channelVersion = channelRelease["channel-version"]; + this.releasesJsonUrl = channelRelease["releases.json"]; + } + + channelVersion: string; + releasesJsonUrl: string +} + const DotNetCoreReleasesIndexUrl: string = "https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases-index.json"; \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts index 84d66239cdfa..e1fea5ee2b7d 100644 --- a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts @@ -1,5 +1,6 @@ import * as path from 'path'; import * as fs from "fs"; +import * as url from "url"; import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; @@ -13,7 +14,7 @@ export class VersionInstaller { tl.exist(installationPath) || tl.mkdirP(installationPath); } catch (ex) { - throw tl.loc("UnableToAccessPath", installationPath, ex); + throw tl.loc("UnableToAccessPath", installationPath, JSON.stringify(ex)); } this.packageType = packageType; @@ -21,6 +22,10 @@ export class VersionInstaller { } public async downloadAndInstall(versionInfo: VersionInfo, downloadUrl: string): Promise { + if (!versionInfo || !versionInfo.version || !url.parse(downloadUrl)) { + throw tl.loc("VersionCanNotBeDownloadedFromUrl", versionInfo, downloadUrl); + } + let downloadPath = ""; let version = versionInfo.version; @@ -59,7 +64,7 @@ export class VersionInstaller { } } catch (ex) { - tl.warning(tl.loc("FailedToCopyTopLevelFiles", ex)); + tl.warning(tl.loc("FailedToCopyTopLevelFiles", this.installationPath, JSON.stringify(ex))); } // Cache tool @@ -68,7 +73,7 @@ export class VersionInstaller { console.log(tl.loc("SuccessfullyInstalled", this.packageType, version)); } catch (ex) { - throw tl.loc("FailedWhileInstallingVersionAtPath", version, this.installationPath, ex); + throw tl.loc("FailedWhileInstallingVersionAtPath", version, this.installationPath, JSON.stringify(ex)); } finally { //todo: Release Lock and stop timer @@ -79,43 +84,43 @@ export class VersionInstaller { public isVersionInstalled(version: string): boolean { if (!toolLib.isExplicitVersion(version)) { - throw tl.loc("VersionNotAllowed", version); + throw tl.loc("ExplicitVersionRequired", version); } var isInstalled: boolean = false; - if (this.packageType == "sdk") { - isInstalled = tl.exist(path.join(this.installationPath, "sdk", version)) && tl.exist(path.join(this.installationPath, "sdk", `${version}.complete`)); + if (this.packageType == utils.Constants.sdk) { + isInstalled = tl.exist(path.join(this.installationPath, utils.Constants.relativeSdkPath, version)) && tl.exist(path.join(this.installationPath, utils.Constants.relativeSdkPath, `${version}.complete`)); } else { - isInstalled = tl.exist(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", version)) && tl.exist(path.join(this.installationPath, "shared", "Microsoft.NETCore.App", `${version}.complete`)); + isInstalled = tl.exist(path.join(this.installationPath, utils.Constants.relativeRuntimePath, version)) && tl.exist(path.join(this.installationPath, utils.Constants.relativeRuntimePath, `${version}.complete`)); } - isInstalled ? console.log(tl.loc("VersionFoundInToolCache")) : console.log(tl.loc("VersionNotFoundInToolCache", version)); + isInstalled ? console.log(tl.loc("VersionFoundInCache", version)) : console.log(tl.loc("VersionNotFoundInCache", version)); return isInstalled; } private createInstallationCompleteFile(versionInfo: VersionInfo): void { tl.debug(tl.loc("CreatingInstallationCompeleteFile", versionInfo.version, this.packageType)); - // always add for runtime as it is installed with SDK as well. + // always add for runtime as it is installed with sdk as well. var pathToVersionCompleteFile: string = ""; - if (this.packageType == "sdk") { + if (this.packageType == utils.Constants.sdk) { let sdkVersion = versionInfo.version; - pathToVersionCompleteFile = path.join(this.installationPath, "sdk"); + pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeSdkPath); tl.writeFile(path.join(pathToVersionCompleteFile, `${sdkVersion}.complete`), `{ "version": "${sdkVersion}" }`); } let runtimeVersion = VersionInfo.getRuntimeVersion(versionInfo, this.packageType); if (runtimeVersion) { - pathToVersionCompleteFile = path.join(this.installationPath, "shared", "Microsoft.NETCore.App"); + pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeRuntimePath); tl.writeFile(path.join(pathToVersionCompleteFile, `${runtimeVersion}.complete`), `{ "version": "${runtimeVersion}" }`); } else if (this.packageType == "runtime") { - throw tl.loc("CannotFindRuntimeVersionForCompletingInstllation", versionInfo.version, this.packageType); + throw tl.loc("CannotFindRuntimeVersionForCompletingInstallation", this.packageType, versionInfo.version); } } private isLatestInstalledVersion(version: string): boolean { - var pathTobeChecked = this.packageType == "sdk" ? path.join(this.installationPath, "sdk") : path.join(this.installationPath, "shared", "Microsoft.NETCore.App"); + var pathTobeChecked = this.packageType == utils.Constants.sdk ? path.join(this.installationPath, utils.Constants.relativeSdkPath) : path.join(this.installationPath, utils.Constants.relativeRuntimePath); if (!tl.exist(pathTobeChecked)) { throw tl.loc("PathNotFoundException", pathTobeChecked); } @@ -141,18 +146,20 @@ export class VersionInstaller { } }) < 0; - isLatest ? tl.debug(tl.loc("VersionIsLocalLatest")) : tl.debug(tl.loc("VersionIsNotLocalLatest")); + isLatest ? tl.debug(tl.loc("VersionIsLocalLatest", version, this.installationPath)) : tl.debug(tl.loc("VersionIsNotLocalLatest", version, this.installationPath)); return isLatest; } private getVersionCompleteFileName(name: string): string { - var parts = name.split('.'); - var fileNameWithoutExtensionLength = name.length - (parts[parts.length - 1].length + 1); - if (fileNameWithoutExtensionLength > 0) { - return name.substr(0, fileNameWithoutExtensionLength); + if (name && name.endsWith(".complete")) { + var parts = name.split('.'); + var fileNameWithoutExtensionLength = name.length - (parts[parts.length - 1].length + 1); + if (fileNameWithoutExtensionLength > 0) { + return name.substr(0, fileNameWithoutExtensionLength); + } } - throw "Not correct Complete marker file name: " + name; + throw tl.loc("FileNameNotCorrectCompleteFileName", name); } private packageType: string; diff --git a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts index ea539b179cf6..964790570362 100644 --- a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts +++ b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts @@ -1,39 +1,62 @@ +import * as path from 'path'; import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib'; +import * as semver from 'semver'; +import { VersionInfo } from './versionFetcher'; export function versionCompareFunction(versionA: string, versionB: string): number { - if (!toolLib.isExplicitVersion(versionA) || !toolLib.isExplicitVersion(versionA)) { - throw tl.loc("ExplicitVersionRequiredForComparison", versionA, versionB); + if (!toolLib.isExplicitVersion(versionA) || !toolLib.isExplicitVersion(versionB)) { + throw tl.loc("VersionsCanNotBeCompared", versionA, versionB); } - var versionAParts = new VersionParts(versionA); - var versionBParts = new VersionParts(versionB); + return semver.compare(versionA, versionB); +} - if (versionAParts.majorVersion != versionBParts.majorVersion) { - return Number.parseInt(versionAParts.majorVersion) > Number.parseInt(versionBParts.majorVersion) ? 1 : -1; +export function compareChannelVersion(channelVersionA: string, channelVersionB: string): number { + if (!channelVersionA || !channelVersionB) { + throw "One channel version is missing" } - else if (versionAParts.minorVersion != versionBParts.minorVersion) { - return Number.parseInt(versionAParts.minorVersion) > Number.parseInt(versionBParts.minorVersion) ? 1 : -1; + + let channelVersionAParts = channelVersionA.split("."); + let channelVersionBParts = channelVersionB.split("."); + if (channelVersionAParts.length != 2 || channelVersionBParts.length != 2) { + throw tl.loc("ChannelVersionsNotComparable", channelVersionA, channelVersionB) } - else if (versionAParts.patchVersion != versionBParts.patchVersion) { - let versionAPatchParts = versionAParts.patchVersion.split("-"); - let versionBPatchParts = versionBParts.patchVersion.split("-"); - if (Number.parseInt(versionAPatchParts[0]) != Number.parseInt(versionBPatchParts[0])) { - return Number.parseInt(versionAPatchParts[0]) > Number.parseInt(versionBPatchParts[0]) ? 1 : -1; - } - if (versionAPatchParts.length == versionBPatchParts.length && versionAPatchParts.length == 3) { - if (Number.parseInt(versionAPatchParts[2]) != Number.parseInt(versionBPatchParts[2])) { - return Number.parseInt(versionAPatchParts[2]) > Number.parseInt(versionBPatchParts[2]) ? 1 : -1; - } - } + let channelAMajorVersion = Number.parseInt(channelVersionAParts[0]); + let channelAMinorVersion = Number.parseInt(channelVersionAParts[1]); + let channelBMajorVersion = Number.parseInt(channelVersionBParts[0]); + let channelBMinorVersion = Number.parseInt(channelVersionBParts[1]); - return versionAParts.patchVersion > versionBParts.patchVersion ? 1 : -1; + if (Number.isNaN(channelAMajorVersion) || Number.isNaN(channelAMinorVersion) || Number.isNaN(channelBMajorVersion) || Number.isNaN(channelBMinorVersion)) { + throw tl.loc("ChannelVersionsNotComparable", channelVersionA, channelVersionB); + } + + if (channelAMajorVersion != channelBMajorVersion) { + return channelAMajorVersion > channelBMajorVersion ? 1 : -1; + } + else if (channelAMinorVersion != channelBMinorVersion) { + return channelAMinorVersion > channelBMinorVersion ? 1 : -1; } return 0; } +export function getMatchingVersionFromList(versionInfoList: VersionInfo[], versionSpec: string, includePreviewVersions: boolean = false): VersionInfo { + let versionList: string[] = versionInfoList.map(versionInfo => { + return versionInfo && versionInfo.version ? versionInfo.version : "" + }); + + let matchedVersion = semver.maxSatisfying(versionList, versionSpec, { includePrerelease: includePreviewVersions }); + if (matchedVersion) { + return versionInfoList.find(versionInfo => { + return versionInfo.version == matchedVersion + }); + } + + return null; +} + export class VersionParts { constructor(version: string) { VersionParts.ValidateVersionSpec(version); @@ -50,7 +73,7 @@ export class VersionParts { public static ValidateVersionSpec(version): boolean { let parts: string[] = version.split('.'); // validate version - if (parts.length < 2 || parts.length > 3 || parts[0] == "x" || (parts[1] == "x" && parts.length > 2) || (parts[1] != "x" && parts.length <= 2) ) { + if (parts.length < 2 || parts.length > 3 || parts[0] == "x" || (parts[1] == "x" && parts.length > 2) || (parts[1] != "x" && parts.length <= 2) || !parts[0] || !parts[1] || (parts.length == 3 && !parts[2]) || Number.isNaN(Number.parseInt(parts[0])) || (Number.isNaN(Number.parseInt(parts[1])) && parts[1] != "x")) { throw tl.loc("VersionNotAllowed", version) } @@ -60,4 +83,12 @@ export class VersionParts { majorVersion: string; minorVersion: string; patchVersion: string; +} + +export const Constants = { + "sdk": "sdk", + "runtime": "runtime", + "relativeRuntimePath": path.join("shared", "Microsoft.NETCore.App"), + "relativeSdkPath": "sdk", + "relativeGlobalToolPath": path.join(".dotnet", "tools") } \ No newline at end of file From 49419144057edfa614a8526cb6e3547192c723c2 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Wed, 13 Mar 2019 12:46:48 +0530 Subject: [PATCH 07/17] some minor refactoring and added logging. --- .../resources.resjson/en-US/resources.resjson | 5 +++- .../dotnetcoreinstaller.ts | 16 +++++++------ Tasks/DotNetCoreInstallerV1/task.json | 7 ++++-- Tasks/DotNetCoreInstallerV1/task.loc.json | 7 ++++-- Tasks/DotNetCoreInstallerV1/versionFetcher.ts | 24 ++++++++++++------- .../DotNetCoreInstallerV1/versionInstaller.ts | 14 +++++------ .../DotNetCoreInstallerV1/versionUtilities.ts | 7 ++++-- 7 files changed, 51 insertions(+), 29 deletions(-) diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson index 2a14bca671cd..6d8f3a98a30a 100644 --- a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson @@ -66,5 +66,8 @@ "loc.messages.FileNameNotCorrectCompleteFileName": "File name %s is not correct version.complete file name.", "loc.messages.ChannelVersionsNotComparable": "Channel versions %s and %s can not be compared. They both must have numeric major and minor versions.", "loc.messages.LookingForVersionInChannel": "Searching for version in channel %s", - "loc.messages.FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels." + "loc.messages.FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels.", + "loc.messages.ErrorWhileSettingDotNetToolPath": "Failed while prepending .Net Core Tool path to PATH envrionment variable. Error: %s", + "loc.messages.RequiredChannelVersionForSpec": "Finding channel %s for version %s", + "loc.messages.ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s" } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index e5bf7666c16e..cf70275fba6a 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -8,9 +8,12 @@ import { VersionParts, Constants } from "./versionUtilities"; async function run() { let packageType = tl.getInput('packageType', true).toLowerCase(); - let versionSpec = tl.getInput('version', true).trim(); - let installationPath = tl.getInput('installationPath', true).trim(); - let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions', true); + let versionSpec = tl.getInput('version', true); + let installationPath = tl.getInput('installationPath', false); + if (!installationPath) { + installationPath = path.join(tl.getVariable('Agent.ToolsDirectory'), "dotnet"); + } + let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions', false) || false; console.log(tl.loc("ToolToInstall", packageType, versionSpec)); VersionParts.ValidateVersionSpec(versionSpec); @@ -29,10 +32,9 @@ async function run() { toolLib.prependPath(installationPath); // By default disable Multi Level Lookup unless user wants it enabled. - if (tl.getBoolInput("restrictMultiLevelLookup", true)) { - tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); - } + tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", tl.getBoolInput("restrictMultiLevelLookup", false) ? "0" : "1"); + // Add dot net tools path to "PATH" environment variables, so that tools can be used directly. addDotNetCoreToolPath(); // Set DOTNET_ROOT for dotnet core Apphost to find runtime since it is installed to a non well-known location. @@ -40,7 +42,6 @@ async function run() { } function addDotNetCoreToolPath() { - // Add dot net tools path to "PATH" environment variables, so that tools can be used directly. try { let globalToolPath: string = ""; if (tl.osType().match(/^Win/)) { @@ -54,6 +55,7 @@ function addDotNetCoreToolPath() { toolLib.prependPath(globalToolPath); } catch (error) { //nop + tl.debug(tl.loc("ErrorWhileSettingDotNetToolPath", JSON.stringify(error))); } } diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index db787b9659ec..ecc4be2b85d3 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -64,7 +64,7 @@ "type": "string", "label": "Path To Install .Net Core", "defaultValue": "$(Agent.ToolsDirectory)/dotnet", - "required": true, + "required": false, "groupName": "advanced", "helpMarkDown": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version." }, @@ -135,6 +135,9 @@ "FileNameNotCorrectCompleteFileName": "File name %s is not correct version.complete file name.", "ChannelVersionsNotComparable": "Channel versions %s and %s can not be compared. They both must have numeric major and minor versions.", "LookingForVersionInChannel": "Searching for version in channel %s", - "FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels." + "FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels.", + "ErrorWhileSettingDotNetToolPath": "Failed while prepending .Net Core Tool path to PATH envrionment variable. Error: %s", + "RequiredChannelVersionForSpec": "Finding channel %s for version %s", + "ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s" } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/task.loc.json b/Tasks/DotNetCoreInstallerV1/task.loc.json index 50803f633e08..0ff6ed489382 100644 --- a/Tasks/DotNetCoreInstallerV1/task.loc.json +++ b/Tasks/DotNetCoreInstallerV1/task.loc.json @@ -64,7 +64,7 @@ "type": "string", "label": "ms-resource:loc.input.label.installationPath", "defaultValue": "$(Agent.ToolsDirectory)/dotnet", - "required": true, + "required": false, "groupName": "advanced", "helpMarkDown": "ms-resource:loc.input.help.installationPath" }, @@ -135,6 +135,9 @@ "FileNameNotCorrectCompleteFileName": "ms-resource:loc.messages.FileNameNotCorrectCompleteFileName", "ChannelVersionsNotComparable": "ms-resource:loc.messages.ChannelVersionsNotComparable", "LookingForVersionInChannel": "ms-resource:loc.messages.LookingForVersionInChannel", - "FallingBackToAdjacentChannels": "ms-resource:loc.messages.FallingBackToAdjacentChannels" + "FallingBackToAdjacentChannels": "ms-resource:loc.messages.FallingBackToAdjacentChannels", + "ErrorWhileSettingDotNetToolPath": "ms-resource:loc.messages.ErrorWhileSettingDotNetToolPath", + "RequiredChannelVersionForSpec": "ms-resource:loc.messages.RequiredChannelVersionForSpec", + "ErrorWhileGettingVersionFromChannel": "ms-resource:loc.messages.ErrorWhileGettingVersionFromChannel" } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts index f77a1759c4f6..0ea5b529b7ae 100644 --- a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts @@ -126,6 +126,7 @@ export class DotNetCoreVersionFetcher { requiredChannelVersion = latestChannelVersion; } + tl.debug(tl.loc("RequiredChannelVersionForSpec", requiredChannelVersion, versionSpec)); return this.channels.find(channel => { if (channel.channelVersion == requiredChannelVersion) { return true @@ -144,8 +145,11 @@ export class DotNetCoreVersionFetcher { .then((body: string) => { var channelReleases = JSON.parse(body).releases; - let versionInfoList: VersionInfo[] = channelReleases.map((release) => { - return release[packageType] && release[packageType].version ? release[packageType] : null; + let versionInfoList: VersionInfo[] = []; + channelReleases.forEach((release) => { + if (release && release[packageType] && release[packageType].version) { + versionInfoList.push(release[packageType]); + } }); let matchedVersionInfo = utils.getMatchingVersionFromList(versionInfoList, versionSpec, includePreviewVersions); @@ -156,6 +160,10 @@ export class DotNetCoreVersionFetcher { console.log(tl.loc("MatchingVersionForUserInputVersion", matchedVersionInfo.version, channelInformation.channelVersion, versionSpec)) return matchedVersionInfo; + }) + .catch((ex) => { + tl.error(tl.loc("ErrorWhileGettingVersionFromChannel", versionSpec, channelInformation.channelVersion, JSON.stringify(ex))); + return null; }); } else { @@ -163,16 +171,16 @@ export class DotNetCoreVersionFetcher { } } - private async getVersionFromOtherChannels(versionSpec: string, packageType: string, includePreviewVersions: boolean): Promise { - let fallbackChannels = this.getChannelsForMajorVersion(versionSpec); + private async getVersionFromOtherChannels(version: string, packageType: string, includePreviewVersions: boolean): Promise { + let fallbackChannels = this.getChannelsForMajorVersion(version); if (!fallbackChannels && fallbackChannels.length < 1) { - throw tl.loc("NoSuitableChannelWereFound", versionSpec); + throw tl.loc("NoSuitableChannelWereFound", version); } var versionInfo: VersionInfo = null; for (var i = 0; i < fallbackChannels.length; i++) { console.log(tl.loc("LookingForVersionInChannel", (fallbackChannels[i]).channelVersion)); - versionInfo = await this.getVersionFromChannel(fallbackChannels[i], versionSpec, packageType, includePreviewVersions); + versionInfo = await this.getVersionFromChannel(fallbackChannels[i], version, packageType, includePreviewVersions); if (versionInfo) { break; @@ -182,8 +190,8 @@ export class DotNetCoreVersionFetcher { return versionInfo; } - private getChannelsForMajorVersion(versionSpec: string): Channel[] { - var versionParts = new utils.VersionParts(versionSpec); + private getChannelsForMajorVersion(version: string): Channel[] { + var versionParts = new utils.VersionParts(version); let adjacentChannels: Channel[] = []; this.channels.forEach(channel => { if (channel.channelVersion.startsWith(`${versionParts.majorVersion}`)) { diff --git a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts index e1fea5ee2b7d..e22407981471 100644 --- a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versionInstaller.ts @@ -47,8 +47,8 @@ export class VersionInstaller { // Copy folders tl.debug(tl.loc("CopyingFoldersIntoPath", this.installationPath)); - var allEnteriesInDir: string[] = tl.ls("", [extPath]).map(name => path.join(extPath, name)); - var directoriesTobeCopied: string[] = allEnteriesInDir.filter(path => fs.lstatSync(path).isDirectory()); + var allRootLevelEnteriesInDir: string[] = tl.ls("", [extPath]).map(name => path.join(extPath, name)); + var directoriesTobeCopied: string[] = allRootLevelEnteriesInDir.filter(path => fs.lstatSync(path).isDirectory()); directoriesTobeCopied.forEach((directoryPath) => { tl.cp(directoryPath, this.installationPath, "-rf", false); }); @@ -57,7 +57,7 @@ export class VersionInstaller { try { if (this.isLatestInstalledVersion(version)) { tl.debug(tl.loc("CopyingFilesIntoPath", this.installationPath)); - var filesToBeCopied = allEnteriesInDir.filter(path => !fs.lstatSync(path).isDirectory()); + var filesToBeCopied = allRootLevelEnteriesInDir.filter(path => !fs.lstatSync(path).isDirectory()); filesToBeCopied.forEach((filePath) => { tl.cp(filePath, this.installationPath, "-f", false); }); @@ -105,14 +105,14 @@ export class VersionInstaller { var pathToVersionCompleteFile: string = ""; if (this.packageType == utils.Constants.sdk) { let sdkVersion = versionInfo.version; - pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeSdkPath); - tl.writeFile(path.join(pathToVersionCompleteFile, `${sdkVersion}.complete`), `{ "version": "${sdkVersion}" }`); + pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeSdkPath, `${sdkVersion}.complete`); + tl.writeFile(pathToVersionCompleteFile, `{ "version": "${sdkVersion}" }`); } let runtimeVersion = VersionInfo.getRuntimeVersion(versionInfo, this.packageType); if (runtimeVersion) { - pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeRuntimePath); - tl.writeFile(path.join(pathToVersionCompleteFile, `${runtimeVersion}.complete`), `{ "version": "${runtimeVersion}" }`); + pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeRuntimePath, `${runtimeVersion}.complete`); + tl.writeFile(pathToVersionCompleteFile, `{ "version": "${runtimeVersion}" }`); } else if (this.packageType == "runtime") { throw tl.loc("CannotFindRuntimeVersionForCompletingInstallation", this.packageType, versionInfo.version); diff --git a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts index 964790570362..4a113682bd44 100644 --- a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts +++ b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts @@ -43,8 +43,11 @@ export function compareChannelVersion(channelVersionA: string, channelVersionB: } export function getMatchingVersionFromList(versionInfoList: VersionInfo[], versionSpec: string, includePreviewVersions: boolean = false): VersionInfo { - let versionList: string[] = versionInfoList.map(versionInfo => { - return versionInfo && versionInfo.version ? versionInfo.version : "" + let versionList: string[] = []; + versionInfoList.forEach(versionInfo => { + if (versionInfo && versionInfo.version) { + versionList.push(versionInfo.version); + } }); let matchedVersion = semver.maxSatisfying(versionList, versionSpec, { includePrerelease: includePreviewVersions }); From adc500c9df1614f3c64d07bf419036f254b61395 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Wed, 13 Mar 2019 20:38:19 +0530 Subject: [PATCH 08/17] resolving bugs for bugbash --- Tasks/DotNetCoreInstallerV0/task.json | 2 +- .../resources.resjson/en-US/resources.resjson | 20 +++++++++---------- Tasks/DotNetCoreInstallerV1/task.json | 20 +++++++++---------- Tasks/DotNetCoreInstallerV1/versionFetcher.ts | 8 ++++---- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Tasks/DotNetCoreInstallerV0/task.json b/Tasks/DotNetCoreInstallerV0/task.json index 48ce1aa2022a..67afd5d02b2f 100644 --- a/Tasks/DotNetCoreInstallerV0/task.json +++ b/Tasks/DotNetCoreInstallerV0/task.json @@ -1,7 +1,7 @@ { "id": "B0CE7256-7898-45D3-9CB5-176B752BFEA6", "name": "DotNetCoreInstaller", - "friendlyName": ".NET Core SDK Installer", + "friendlyName": ".NET Core SDK/Runtime Installer", "description": "Acquires a specific version of the .NET Core SDK from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks.", "helpUrl": "https://go.microsoft.com/fwlink/?linkid=853651", "helpMarkDown": "[More Information](https://go.microsoft.com/fwlink/?linkid=853651)", diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson index 6d8f3a98a30a..eee164ed9db3 100644 --- a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson @@ -1,24 +1,24 @@ { - "loc.friendlyName": "Dot NET Core SDK/Runtime Installer", + "loc.friendlyName": ".NET Core SDK/Runtime Installer", "loc.helpMarkDown": "", "loc.description": "Acquires a version of the .NET Core SDK/Runtime from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks.", - "loc.instanceNameFormat": "Use .NET Core $(packageType) $(version)", + "loc.instanceNameFormat": "Install .NET Core $(packageType) $(version)", "loc.releaseNotes": "
  • Support for installing multiple versions side by side.
  • Support for patterns in version to fetch latest in minor/major version.
  • Restrict Multi-level lookup
  • ", "loc.group.displayName.advanced": "Advanced", "loc.input.label.packageType": "Package to install", "loc.input.help.packageType": "Please select whether to install only runtime or full SDK.", "loc.input.label.version": "Version", - "loc.input.help.version": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [releases-index file.](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json", + "loc.input.help.version": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json", "loc.input.label.includePreviewVersions": "Include Preview Versions", - "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ingnored if you specify an exact version, such as: 2.1.403", + "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 2.1.403", "loc.input.label.installationPath": "Path To Install .Net Core", - "loc.input.help.installationPath": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version.", + "loc.input.help.installationPath": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on .Net's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configure .Net host's probing for a suitable version.", "loc.input.label.restrictMultiLevelLookup": "Restrict Multi Level Lookup", - "loc.input.help.restrictMultiLevelLookup": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    This is only applicable to Windows based agents.", + "loc.input.help.restrictMultiLevelLookup": "This input is only applicable to Windows based agents. This configures the behavior of .Net host process for looking up a suitable shared framework.
  • checked: Only versions present in the folder specified in this task would be looked by the host process.
  • unchecked: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
  • You can read more about it [**HERE**](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    ", "loc.messages.ToolFailed": "Tool install failed: %s", "loc.messages.ImplicitVersionNotSupported": "Version should be a valid and explicit version: %s", "loc.messages.getMachinePlatformFailed": "Failed to get machine platform details. Error: %s.", - "loc.messages.getDownloadUrlsFailed": "Failed to get download urls. Error: %s.", + "loc.messages.getDownloadUrlsFailed": "Failed to get download URLS. Error: %s.", "loc.messages.UsingCachedTool": "Cached copy of .NET Core exists. No need to install afresh. Cached tool location: %s.", "loc.messages.CheckingToolCache": "Checking if a cached copy exists for this version...", "loc.messages.InstallingAfresh": "The cache does not contain the requested version of .NET Core. Downloading and installing it now.", @@ -35,9 +35,9 @@ "loc.messages.WarningVersionNotFound": "Could not fetch download information for version %s. Please check if the version specified is correct. You can refer the link for supported versions => https://github.com/dotnet/core/blob/master/release-notes/releases.json. Falling back to creating convention based URL.", "loc.messages.CouldNotDownload": "Could not download installation package from this URL: %s Error: %s", "loc.messages.FailedToDownloadPackage": "Failed to download package for installation", - "loc.messages.PrependGlobalToolPath": "Creating global tool path and pre-prending to PATH.", + "loc.messages.PrependGlobalToolPath": "Creating global tool path and pre-pending to PATH.", "loc.messages.VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/", - "loc.messages.MatchingVersionNotFound": "No matching version could be found for specified version: %s Kindly note the preview versions are only considered in latest version searches if Include Preview Versions checkbox is checked.", + "loc.messages.MatchingVersionNotFound": "No matching %s version could be found for specified version: %s Kindly note the preview versions are only considered in latest version searches if Include Preview Versions checkbox is checked.", "loc.messages.UnableToAccessPath": "Unable to access path: %s. Error: %s \n please make sure that agent process has path to the path.", "loc.messages.VersionCanNotBeDownloadedFromUrl": "Version: %s cannot be downloaded from URL: %s. Either the URL or version is incorrect.", "loc.messages.CopyingFoldersIntoPath": "Copying all root folders into installation path: %s", @@ -60,7 +60,7 @@ "loc.messages.DetectingPlatform": "Detecting OS platform to find correct download package for the OS.", "loc.messages.FailedInDetectingMachineArch": "Failed while detecting machine OS platform with error: %s", "loc.messages.runtimeVersionPropertyNotFound": "runtime-version property could not be found for .Net Core %s version %s.", - "loc.messages.VersionNotFound": "Version matching: %s could not be found", + "loc.messages.VersionNotFound": "%s version matching: %s could not be found", "loc.messages.VersionNotAllowed": "Version %s is not allowed. Allowed version types are: majorVersion.x, majorVersion.minorVersion.x, majorVersion.minorVersion.patchVersion", "loc.messages.VersionsCanNotBeCompared": "Versions %s and %s cannot be compared. Both versions should be explicit.", "loc.messages.FileNameNotCorrectCompleteFileName": "File name %s is not correct version.complete file name.", diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index ecc4be2b85d3..ee593a66e331 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -1,7 +1,7 @@ { "id": "B0CE7256-7898-45D3-9CB5-176B752BFEA6", "name": "DotNetCoreInstaller", - "friendlyName": "Dot NET Core SDK/Runtime Installer", + "friendlyName": ".NET Core SDK/Runtime Installer", "description": "Acquires a version of the .NET Core SDK/Runtime from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks.", "helpUrl": "", "helpMarkDown": "", @@ -22,7 +22,7 @@ ], "demands": [], "releaseNotes": "
  • Support for installing multiple versions side by side.
  • Support for patterns in version to fetch latest in minor/major version.
  • Restrict Multi-level lookup
  • ", - "instanceNameFormat": "Use .NET Core $(packageType) $(version)", + "instanceNameFormat": "Install .NET Core $(packageType) $(version)", "groups": [ { "name": "advanced", @@ -49,7 +49,7 @@ "label": "Version", "defaultValue": "2.2.x", "required": true, - "helpMarkDown": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [releases-index file.](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json" + "helpMarkDown": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json" }, { "name": "includePreviewVersions", @@ -57,7 +57,7 @@ "label": "Include Preview Versions", "defaultValue": "false", "required": false, - "helpMarkDown": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ingnored if you specify an exact version, such as: 2.1.403" + "helpMarkDown": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 2.1.403" }, { "name": "installationPath", @@ -66,7 +66,7 @@ "defaultValue": "$(Agent.ToolsDirectory)/dotnet", "required": false, "groupName": "advanced", - "helpMarkDown": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on dotnet's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configures dotnet host's probing for a suitable version." + "helpMarkDown": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on .Net's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configure .Net host's probing for a suitable version." }, { "name": "restrictMultiLevelLookup", @@ -75,7 +75,7 @@ "groupName": "advanced", "defaultValue": true, "required": false, - "helpMarkDown": "This configures the behavior of dontnet host process for looking up a suitable shared framework.
  • true: Only versions present in the folder specified in this task would be looked by the host process.
  • false: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
  • You can read more about it [HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    This is only applicable to Windows based agents." + "helpMarkDown": "This input is only applicable to Windows based agents. This configures the behavior of .Net host process for looking up a suitable shared framework.
  • checked: Only versions present in the folder specified in this task would be looked by the host process.
  • unchecked: The host will attempt to look in pre-defined global locations using multi-level lookup.
    The default global locations are:
    For Windows:
    C:\\Program Files\\dotnet (64-bit processes)
    C:\\Program Files (x86)\\dotnet (32-bit process)
  • You can read more about it [**HERE**](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    " } ], "execution": { @@ -87,7 +87,7 @@ "ToolFailed": "Tool install failed: %s", "ImplicitVersionNotSupported": "Version should be a valid and explicit version: %s", "getMachinePlatformFailed": "Failed to get machine platform details. Error: %s.", - "getDownloadUrlsFailed": "Failed to get download urls. Error: %s.", + "getDownloadUrlsFailed": "Failed to get download URLS. Error: %s.", "UsingCachedTool": "Cached copy of .NET Core exists. No need to install afresh. Cached tool location: %s.", "CheckingToolCache": "Checking if a cached copy exists for this version...", "InstallingAfresh": "The cache does not contain the requested version of .NET Core. Downloading and installing it now.", @@ -104,9 +104,9 @@ "WarningVersionNotFound": "Could not fetch download information for version %s. Please check if the version specified is correct. You can refer the link for supported versions => https://github.com/dotnet/core/blob/master/release-notes/releases.json. Falling back to creating convention based URL.", "CouldNotDownload": "Could not download installation package from this URL: %s Error: %s", "FailedToDownloadPackage": "Failed to download package for installation", - "PrependGlobalToolPath": "Creating global tool path and pre-prending to PATH.", + "PrependGlobalToolPath": "Creating global tool path and pre-pending to PATH.", "VersionsFileMalformed": "The specified version's download links are not correctly formed in the supported versions document => %s/", - "MatchingVersionNotFound": "No matching version could be found for specified version: %s Kindly note the preview versions are only considered in latest version searches if Include Preview Versions checkbox is checked.", + "MatchingVersionNotFound": "No matching %s version could be found for specified version: %s Kindly note the preview versions are only considered in latest version searches if Include Preview Versions checkbox is checked.", "UnableToAccessPath": "Unable to access path: %s. Error: %s \n please make sure that agent process has path to the path.", "VersionCanNotBeDownloadedFromUrl": "Version: %s cannot be downloaded from URL: %s. Either the URL or version is incorrect.", "CopyingFoldersIntoPath": "Copying all root folders into installation path: %s", @@ -129,7 +129,7 @@ "DetectingPlatform": "Detecting OS platform to find correct download package for the OS.", "FailedInDetectingMachineArch": "Failed while detecting machine OS platform with error: %s", "runtimeVersionPropertyNotFound": "runtime-version property could not be found for .Net Core %s version %s.", - "VersionNotFound": "Version matching: %s could not be found", + "VersionNotFound": "%s version matching: %s could not be found", "VersionNotAllowed": "Version %s is not allowed. Allowed version types are: majorVersion.x, majorVersion.minorVersion.x, majorVersion.minorVersion.patchVersion", "VersionsCanNotBeCompared": "Versions %s and %s cannot be compared. Both versions should be explicit.", "FileNameNotCorrectCompleteFileName": "File name %s is not correct version.complete file name.", diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts index 0ea5b529b7ae..69d3829072bc 100644 --- a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts @@ -44,7 +44,7 @@ export class DotNetCoreVersionFetcher { } if (!requiredVersionInfo) { - throw tl.loc("VersionNotFound", versionSpec); + throw tl.loc("VersionNotFound", packageType, versionSpec); } let dotNetSdkVersionTelemetry = `{"userVersion":"${versionSpec}", "resolvedVersion":"${requiredVersionInfo.version}"}`; @@ -58,8 +58,8 @@ export class DotNetCoreVersionFetcher { let osSuffixes = this.detectMachineOS(); let downloadPackageInfoObject: VersionFilesData = null; osSuffixes.find((osSuffix) => { - downloadPackageInfoObject = versionInfo.files.find((downloadPackageInfo: any) => { - if (downloadPackageInfo.rid.toLowerCase() == osSuffix.toLowerCase()) { + downloadPackageInfoObject = versionInfo.files.find((downloadPackageInfo: VersionFilesData) => { + if (downloadPackageInfo.rid && osSuffix && downloadPackageInfo.rid.toLowerCase() == osSuffix.toLowerCase()) { if ((osSuffix.split("-")[0] != "win" && osSuffix.split("-")[0] != "osx") || (osSuffix.split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip")) || (osSuffix.split("-")[0] == "osx" && downloadPackageInfo.name.endsWith("tar.gz"))) { return true; } @@ -154,7 +154,7 @@ export class DotNetCoreVersionFetcher { let matchedVersionInfo = utils.getMatchingVersionFromList(versionInfoList, versionSpec, includePreviewVersions); if (!matchedVersionInfo) { - console.log(tl.loc("MatchingVersionNotFound", versionSpec)); + console.log(tl.loc("MatchingVersionNotFound", packageType, versionSpec)); return null; } From 8101e5aec20d19c86b566ea991acdbcb8adba461 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Thu, 14 Mar 2019 12:55:42 +0530 Subject: [PATCH 09/17] added L0 tests and some minor changes --- Tasks/DotNetCoreInstallerV1/Tests/L0.ts | 193 ++++++++++++++++++ .../dotnetcoreinstaller.ts | 10 +- Tasks/DotNetCoreInstallerV1/versionFetcher.ts | 5 + .../DotNetCoreInstallerV1/versionUtilities.ts | 12 +- 4 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/L0.ts diff --git a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts new file mode 100644 index 000000000000..a0b826673c99 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts @@ -0,0 +1,193 @@ +'use strict'; + +const assert = require('assert'); +const tl = require('vsts-task-lib'); +const ttm = require('vsts-task-lib/mock-test'); +const path = require('path'); + +function setResponseFile(name) { + process.env['MOCK_RESPONSES'] = path.join(__dirname, name); +} + +function runValidations(validator: () => void, tr, done) { + try { + validator(); + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } +} + +describe('DotNetCoreInstaller', function() { + this.timeout(30000); + before((done) => { + done(); + }); + after(function() { + }); + + it("[VersionUtilities] versionCompareFunction should throw for non explicit versions or empty version strings", () => { + }); + + it("[VersionUtilities] versionCompareFunction should return 1, 0 or -1 when versionA is gt, eq or lt versionB", () => { + }); + + it("[VersionUtilities] compareChannelVersion function should throw when either or both channel versions are empty or are non numeric", () => { + }); + + it("[VersionUtilities] compareChannelVersion function should return 1, 0 or -1 when channelVersionA is gt, eq or lt channelVersionB", () => { + }); + + it("[VersionUtilities] getMatchingVersionFromList should return null for empty versionInfoList or versionInfoList elements having empty version", () => { + }); + + it("[VersionUtilities] getMatchingVersionFromList should return null when no version satisfying versionSpec can be found in list", () => { + }); + + it("[VersionUtilities] getMatchingVersionFromList should return heighest version for the spec when versionSpec is not exact version", () => { + }); + + it("[VersionUtilities] getMatchingVersionFromList should return null when versionSpec is exact version and the same version is not present in versionInfoList", () => { + }); + + it("[VersionUtilities] getMatchingVersionFromList should return exact version when versionSpec is exact version and the same version is present in versionInfoList", () => { + }); + + it("[VersionUtilities] ValidateVersionSpec should throw when majorversion have non numeric characters", () => { + }); + + it("[VersionUtilities] ValidateVersionSpec should throw when minor version have non numeric characters other than being only x", () => { + }); + + it("[VersionUtilities] ValidateVersionSpec should throw when patch version is present and minor version is x", () => { + }); + + it("[VersionUtilities] ValidateVersionSpec should throw when patch version is empty and minor version is numeric", () => { + }); + + it("[VersionUtilities] ValidateVersionSpec should throw when major or minor version is empty", () => { + }); + + it("[VersionUtilities] VersionParts constructor should throw when version fails validation", () => { + }); + + it("[VersionUtilities] VersionParts constructor return object instance with correct major, minor and patch version", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should throw if version for pacakge type can not be found, and error message should contain the package type", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should throw if getting channel fails", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return correct version info for a correct version spec", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return correct version info for a version which exists in a different channel of the same major version", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info in a major version for a versionSpec of type majorVersion.x", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info in a major.minor version for a versionSpec of type majorVersion.minorVersion.x", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest preview version info if includePreviewVersion is true and latest version is a preview version", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info even if includePreviewVersion is true but latest version is non preview", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if VersionFilesData doesn't contain download URL", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if download information object with RID matching OS, could not be found", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if error encountered while detecting machine os", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if zip package is not found for windows os", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if tar.gz package is not found for linux os", () => { + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should return correct download URL for matching OS", () => { + }); + + it("[VersionFetcher.VersionInfo] getRuntimeVersion should return correct runtime-version from sdk versionInfo object", () => { + }); + + it("[VersionFetcher.VersionInfo] getRuntimeVersion should return version for runtime versionInfo object", () => { + }); + + it("[VersionFetcher.VersionInfo] getRuntimeVersion should return empty string for sdk versionInfo object if runtime-version is not present", () => { + }); + + it("[VersionFetcher.Channel] constructor should throw if object passed doesn't contain channel-version or releasesJsonUrl, or contains invalid releasesJsonUrl", () => { + }); + + it("[VersionFetcher.Channel] constructor should pass if object contains channel-version and valid releasesJsonUrl", () => { + }); + + it("[VersionInstaller] constructor should throw if installationPath doesn't exist and cannot be created", () => { + }); + + it("[VersionInstaller] downloadAndInstall should throw if passed arguments are empty or doesn't contain version or downloadUrl is malformed", () => { + }); + + it("[VersionInstaller] downloadAndInstall should throw if downloading version from URL fails", () => { + }); + + it("[VersionInstaller] downloadAndInstall should throw if extracting downloaded package or copying folders into installation path fails.", () => { + }); + + it("[VersionInstaller] downloadAndInstall should not throw if copying root files from package into installationPath fails", () => { + }); + + it("[VersionInstaller] downloadAndInstall should only copy files from root folder if version being installed in the path is greater than all other already present", () => { + }); + + it("[VersionInstaller] downloadAndInstall should throw if creating version.complete file fails.", () => { + }); + + it("[VersionInstaller] downloadAndInstall should complete successfully on complete installation and create complete file in both sdk and runtime when sdk is installed and in runtime when only runtime is installed.", () => { + }); + + it("[VersionInstaller] isVersionInstalled should throw if version being checked is not explicit.", () => { + }); + + it("[VersionInstaller] isVersionInstalled should return false if either folder or file with name as version is not present inside sdk folder.", () => { + }); + + it("[VersionInstaller] isVersionInstalled should return false if either folder or file with name as version is not present inside runtime path.", () => { + }); + + it("[VersionInstaller] isVersionInstalled should return true if both folder or file with name as version is present inside sdk/runtime path.", () => { + }); + + it("[dotnetcoreinstaller] run should default to use $(Agent.ToolsDirectory)/dotnet as installation path if installationPath input is empty.", () => { + }); + + it("[dotnetcoreinstaller] run should throw if versionSpec is invalid.", () => { + }); + + it("[dotnetcoreinstaller] run should throw if versionInfo for the version spec could not be found.", () => { + }); + + it("[dotnetcoreinstaller] run should skip installation if version found in cache.", () => { + }); + + it("[dotnetcoreinstaller] run should always prepend installationPath & dotnet_root to PATH environment variable.", () => { + }); + + it("[dotnetcoreinstaller] run should not fail if globalToolPath could not be created or set.", () => { + }); + + it("[dotnetcoreinstaller] run should always set multilevel lookup environment variable and by default restrict if input is not present.", () => { + }); +}); diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index cf70275fba6a..09880c53965c 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -32,7 +32,15 @@ async function run() { toolLib.prependPath(installationPath); // By default disable Multi Level Lookup unless user wants it enabled. - tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", tl.getBoolInput("restrictMultiLevelLookup", false) ? "0" : "1"); + let restrictMultiLevelLookup = true; + try { + restrictMultiLevelLookup = tl.getBoolInput("restrictMultiLevelLookup", true); + } + catch (ex) { + // no op, restrictMultiLevelLookup is defaulted to true + } + + tl.setVariable("DOTNET_MULTILEVEL_LOOKUP", restrictMultiLevelLookup ? "0" : "1"); // Add dot net tools path to "PATH" environment variables, so that tools can be used directly. addDotNetCoreToolPath(); diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts index 69d3829072bc..b4b98238a752 100644 --- a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionFetcher.ts @@ -118,6 +118,11 @@ export class DotNetCoreVersionFetcher { if (versionParts.minorVersion == "x") { var latestChannelVersion: string = `${versionParts.majorVersion}.0`; this.channels.forEach(channel => { + // todo: should also check if the channel is in preview state, if so then only select the channel if includePreviewVersion should be true. + // As a channel with state in preview will only have preview releases. + // example: versionSpec: 3.x Channels: 3.0 (current), 3.1 (preview). + // if (includePreviewVersion == true) select 3.1 + // else select 3.0 if (utils.compareChannelVersion(channel.channelVersion, latestChannelVersion) > 0 && channel.channelVersion.startsWith(versionParts.majorVersion)) { latestChannelVersion = channel.channelVersion; } diff --git a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts index 4a113682bd44..aff06daa5eee 100644 --- a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts +++ b/Tasks/DotNetCoreInstallerV1/versionUtilities.ts @@ -50,11 +50,13 @@ export function getMatchingVersionFromList(versionInfoList: VersionInfo[], versi } }); - let matchedVersion = semver.maxSatisfying(versionList, versionSpec, { includePrerelease: includePreviewVersions }); - if (matchedVersion) { - return versionInfoList.find(versionInfo => { - return versionInfo.version == matchedVersion - }); + if (versionList.length > 0) { + let matchedVersion = semver.maxSatisfying(versionList, versionSpec, { includePrerelease: includePreviewVersions }); + if (matchedVersion) { + return versionInfoList.find(versionInfo => { + return versionInfo.version == matchedVersion + }); + } } return null; From ca451c8f6d1c59cf4c9d628450b21a77fffc2434 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Thu, 14 Mar 2019 14:32:46 +0530 Subject: [PATCH 10/17] added DotNetCoreInstallerV1 to be built and packaged as part of pipeline --- .github/CODEOWNERS | 2 ++ make-options.json | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 20df54d50092..9c9949c9a20a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -105,6 +105,8 @@ Tasks/DotNetCoreCLIV2/* @sachinma Tasks/DotNetCoreInstallerV0/* @sachinma +Tasks/DotNetCoreInstallerV1/* @sachinma + Tasks/DownloadBuildArtifactsV0/* @Lovakumar @omeshp Tasks/DownloadFileshareArtifactsV0/* @Lovakumar @omeshp diff --git a/make-options.json b/make-options.json index def135829cea..7c9336685d4c 100644 --- a/make-options.json +++ b/make-options.json @@ -55,6 +55,7 @@ "DockerInstallerV0", "DotNetCoreCLIV2", "DotNetCoreInstallerV0", + "DotNetCoreInstallerV1", "DownloadBuildArtifactsV0", "DownloadFileshareArtifactsV0", "DownloadGitHubReleaseV0", From 6cbafe87bfa0ed3fa18806cf1d2a9034eb524bca Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Thu, 14 Mar 2019 14:59:25 +0530 Subject: [PATCH 11/17] renamed files to be small case as the task is cross platform --- Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts | 6 +++--- .../{versionFetcher.ts => versionfetcher.ts} | 2 +- .../{versionInstaller.ts => versioninstaller.ts} | 4 ++-- .../{versionUtilities.ts => versionutilities.ts} | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) rename Tasks/DotNetCoreInstallerV1/{versionFetcher.ts => versionfetcher.ts} (99%) rename Tasks/DotNetCoreInstallerV1/{versionInstaller.ts => versioninstaller.ts} (98%) rename Tasks/DotNetCoreInstallerV1/{versionUtilities.ts => versionutilities.ts} (98%) diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index 09880c53965c..7a58893d3bad 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -2,9 +2,9 @@ import * as path from 'path'; import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; -import { DotNetCoreVersionFetcher, VersionInfo } from "./versionFetcher"; -import { VersionInstaller } from "./versionInstaller"; -import { VersionParts, Constants } from "./versionUtilities"; +import { DotNetCoreVersionFetcher, VersionInfo } from "./versionfetcher"; +import { VersionInstaller } from "./versioninstaller"; +import { VersionParts, Constants } from "./versionutilities"; async function run() { let packageType = tl.getInput('packageType', true).toLowerCase(); diff --git a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts similarity index 99% rename from Tasks/DotNetCoreInstallerV1/versionFetcher.ts rename to Tasks/DotNetCoreInstallerV1/versionfetcher.ts index b4b98238a752..1a68955f8977 100644 --- a/Tasks/DotNetCoreInstallerV1/versionFetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts @@ -9,7 +9,7 @@ import httpClient = require("typed-rest-client/HttpClient"); import httpInterfaces = require("typed-rest-client/Interfaces"); import { HttpClientResponse } from 'typed-rest-client/HttpClient'; -import * as utils from "./versionUtilities"; +import * as utils from "./versionutilities"; export class DotNetCoreVersionFetcher { constructor() { diff --git a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts similarity index 98% rename from Tasks/DotNetCoreInstallerV1/versionInstaller.ts rename to Tasks/DotNetCoreInstallerV1/versioninstaller.ts index e22407981471..edc74c1e4088 100644 --- a/Tasks/DotNetCoreInstallerV1/versionInstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts @@ -5,8 +5,8 @@ import * as url from "url"; import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; -import * as utils from "./versionUtilities"; -import { VersionInfo } from './versionFetcher'; +import * as utils from "./versionutilities"; +import { VersionInfo } from './versionfetcher'; export class VersionInstaller { constructor(packageType: string, installationPath: string) { diff --git a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts b/Tasks/DotNetCoreInstallerV1/versionutilities.ts similarity index 98% rename from Tasks/DotNetCoreInstallerV1/versionUtilities.ts rename to Tasks/DotNetCoreInstallerV1/versionutilities.ts index aff06daa5eee..7a90fce1928d 100644 --- a/Tasks/DotNetCoreInstallerV1/versionUtilities.ts +++ b/Tasks/DotNetCoreInstallerV1/versionutilities.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib'; import * as semver from 'semver'; -import { VersionInfo } from './versionFetcher'; +import { VersionInfo } from './versionfetcher'; export function versionCompareFunction(versionA: string, versionB: string): number { if (!toolLib.isExplicitVersion(versionA) || !toolLib.isExplicitVersion(versionB)) { From dafc3b561bc13675db7948fe0cec99ee24f8db62 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Fri, 15 Mar 2019 18:29:42 +0530 Subject: [PATCH 12/17] Added readme.md and helpmarkdown link. Resolved comments --- Tasks/DotNetCoreInstallerV1/README.md | 41 ++++++++-- .../resources.resjson/en-US/resources.resjson | 8 +- .../Tests/package-lock.json | 14 ++++ .../DotNetCoreInstallerV1/Tests/package.json | 28 +++++++ .../dotnetcoreinstaller.ts | 7 +- Tasks/DotNetCoreInstallerV1/models.ts | 77 +++++++++++++++++++ Tasks/DotNetCoreInstallerV1/package-lock.json | 7 +- Tasks/DotNetCoreInstallerV1/package.json | 3 +- Tasks/DotNetCoreInstallerV1/task.json | 12 +-- Tasks/DotNetCoreInstallerV1/task.loc.json | 8 +- Tasks/DotNetCoreInstallerV1/tsconfig.json | 4 +- Tasks/DotNetCoreInstallerV1/versionfetcher.ts | 52 +------------ .../DotNetCoreInstallerV1/versioninstaller.ts | 12 ++- .../DotNetCoreInstallerV1/versionutilities.ts | 30 +------- 14 files changed, 190 insertions(+), 113 deletions(-) create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/package-lock.json create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/package.json create mode 100644 Tasks/DotNetCoreInstallerV1/models.ts diff --git a/Tasks/DotNetCoreInstallerV1/README.md b/Tasks/DotNetCoreInstallerV1/README.md index 8888c08397c6..ef86a00fde1b 100644 --- a/Tasks/DotNetCoreInstallerV1/README.md +++ b/Tasks/DotNetCoreInstallerV1/README.md @@ -3,10 +3,16 @@ ## Overview The .NET Core Tool Installer task acquires a specific version of [.NET Core](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x) from internet or the tools cache and adds it to the PATH of the Azure Pipelines Agent (hosted or private). Use this task to change the version of .NET Core used in subsequent tasks like [.NET Core cli task](https://github.com/Microsoft/azure-pipelines-tasks/tree/master/Tasks/DotNetCoreCLIV2). -Adding this task before the [.NET Core cli task](https://github.com/Microsoft/azure-pipelines-tasks/tree/master/Tasks/DotNetCoreCLIV2) in a build definition ensures you are building, testing and publishing your app with the right .NET Core version. +Adding this task before the [.NET Core cli task](https://github.com/Microsoft/azure-pipelines-tasks/tree/master/Tasks/DotNetCoreCLIV2) in a build definition ensures that the version would be available at the time of building, testing and publishing your app. -The tool installer approach also decouples you from the agent update cycles. If the .NET Core version you are looking for is missing from the Azure Pipelines agent (Hosted or Private), then you can use this task to get the right version installed on the agent. +The tool installer approach also allows you to decouple from the agent update cycles. If the .NET Core version you are looking for is missing from the Azure Pipelines agent (Hosted or Private), then you can use this task to get the right version installed on the agent. +### Whats New +- Support for installing multiple versions side by side. + +- Support for patterns in version to fetch latest in minor/major version. Example you can now specify 2.2.x to get the latest patch. + +- Restrict Multi-level lookup. This input is only applicable to Windows based agents. It configures the .Net Core's host process behviour for looking for a suitable shared framework on the machine. You can read more about it **[HERE](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md)** ## Contact Information @@ -20,10 +26,31 @@ The task can run on either Windows or Linux. * **Package to install\*:** You can choose to install either runtime or full SDK. -* **Version\*:** Specify exact version of .NET Core SDK or runtime to install. + +* **Version\*:** Specify version of .NET Core SDK or runtime to install. It also allows you to always get the latest version in a minor or major version. See below for examples Examples: -1. To install 1.0.4 SDK, use 1.0.4 -2. To install 1.1.2 runtime, use 1.1.2 -3. To install 2.0 preview 2 runtime, use 2.0.0-preview2-25407-01 -For getting more details about exact version, refer [this link](https://github.com/dotnet/core/blob/master/release-notes/releases.csv). + - To install 2.2.104 SDK, use 2.2.104 + - To install 2.2.1 runtime, use 2.2.1 + - To install 3.0.100-preview3-010431 sdk, use 3.0.100-preview3-010431 + - To install latest patch version of 2.1 sdk, use 2.1.x + - To install latest minor version of 2. sdk, use 2.x
    For getting more details about exact version, refer [this link](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). + + +* **Include Preview Versions**: Select if you want preview versions to be included while searching for latest versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 3.0.100-preview3-010431 + + +* **Path To Install .Net Core**: Specify where .Net Core SDK/Runtime should be installed. In case there was already a differnt version on the specified path, that earlier version wont be deleted. + + +* **Restrict Multi Level Lookup**: This input is only applicable to Windows based agents. This configures the behavior of .Net host process for looking up a suitable shared framework. + * *checked*: Only versions present in the folder specified in this task would be looked by the host process. + * *unchecked*: The host will attempt to look in pre-defined global locations using multi-level lookup. + + The default global locations are: + - **For Windows**: +
    C:\\Program Files\\dotnet (64-bit processes) +
    C:\\Program Files (x86)\\dotnet (32-bit process) + + You can read more about it [**HERE**](https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/multilevel-sharedfx-lookup.md).
    + diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson index eee164ed9db3..e5fe6fd954e4 100644 --- a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson @@ -1,6 +1,6 @@ { "loc.friendlyName": ".NET Core SDK/Runtime Installer", - "loc.helpMarkDown": "", + "loc.helpMarkDown": "[More Information](https://aka.ms/AA4ihfi)", "loc.description": "Acquires a version of the .NET Core SDK/Runtime from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks.", "loc.instanceNameFormat": "Install .NET Core $(packageType) $(version)", "loc.releaseNotes": "
  • Support for installing multiple versions side by side.
  • Support for patterns in version to fetch latest in minor/major version.
  • Restrict Multi-level lookup
  • ", @@ -10,7 +10,7 @@ "loc.input.label.version": "Version", "loc.input.help.version": "Specify version of .NET Core SDK or runtime to install.
    Versions can be given in the following formats
  • 2.x => Install latest in major version.
  • 2.2.x => Install latest in major and minor version
  • 2.2.104 => Install exact version

  • Find the value of `version` for installing SDK/Runtime, from the releases.json. The link to releases.json of that major.minor version can be found in [**releases-index file.**](https://github.com/dotnet/core/blob/master/release-notes/releases-index.json). Like link to releases.json for 2.2 version is https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json", "loc.input.label.includePreviewVersions": "Include Preview Versions", - "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 2.1.403", + "loc.input.help.includePreviewVersions": "Select if you want preview versions to be included while searching for latest versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 3.0.100-preview3-010431", "loc.input.label.installationPath": "Path To Install .Net Core", "loc.input.help.installationPath": "Specify where .Net Core SDK/Runtime should be installed. Different paths can have the following impact on .Net's behavior.
  • $(Agent.ToolsDirectory): This makes the version to be cached on the agent since this directory is not cleanup up across pipelines. All pipelines running on the agent, would have access to the versions installed previously using the agent.
  • $(Agent.TempDirectory): This can ensure that a pipeline doesn't use any cached version of .Net core since this folder is cleaned up after each pipeline.
  • Any other path: You can configure any other path given the agent process has access to the path. This will change the state of the machine and impact all processes running on it.
    Note that you can also configure Multi-Level Lookup setting which can configure .Net host's probing for a suitable version.", "loc.input.label.restrictMultiLevelLookup": "Restrict Multi Level Lookup", @@ -69,5 +69,7 @@ "loc.messages.FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels.", "loc.messages.ErrorWhileSettingDotNetToolPath": "Failed while prepending .Net Core Tool path to PATH envrionment variable. Error: %s", "loc.messages.RequiredChannelVersionForSpec": "Finding channel %s for version %s", - "loc.messages.ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s" + "loc.messages.ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s", + "loc.messages.ComparingInstalledFolderVersions": "Comparing if version being installed %s is greater than already installed version with folder name %s", + "loc.messages.ComparingInstalledFileVersions": "Comparing if version being installed %s is greater than already installed version with version complete file name %s" } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/package-lock.json b/Tasks/DotNetCoreInstallerV1/Tests/package-lock.json new file mode 100644 index 000000000000..21c0dbe90397 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "dotnetcoreinstaller", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/mocha": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", + "integrity": "sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==", + "dev": true + } + } +} diff --git a/Tasks/DotNetCoreInstallerV1/Tests/package.json b/Tasks/DotNetCoreInstallerV1/Tests/package.json new file mode 100644 index 000000000000..48625430fef8 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/package.json @@ -0,0 +1,28 @@ +{ + "name": "dotnetcoreinstaller", + "version": "1.0.0", + "description": ".Net Core Installer", + "main": "dotnetcoreinstaller.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Microsoft/azure-pipelines-tasks.git" + }, + "keywords": [ + "Azure", + "Pipelines", + "Tasks", + "DotNetCore" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Microsoft/azure-pipelines-tasks/issues" + }, + "homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme", + "devDependencies": { + "@types/mocha": "^5.2.0" + } +} diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index 7a58893d3bad..0f39bfedb6f4 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -2,9 +2,10 @@ import * as path from 'path'; import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; -import { DotNetCoreVersionFetcher, VersionInfo } from "./versionfetcher"; +import { DotNetCoreVersionFetcher } from "./versionfetcher"; import { VersionInstaller } from "./versioninstaller"; -import { VersionParts, Constants } from "./versionutilities"; +import { Constants } from "./versionutilities"; +import { VersionInfo, VersionParts } from "./models" async function run() { let packageType = tl.getInput('packageType', true).toLowerCase(); @@ -63,7 +64,7 @@ function addDotNetCoreToolPath() { toolLib.prependPath(globalToolPath); } catch (error) { //nop - tl.debug(tl.loc("ErrorWhileSettingDotNetToolPath", JSON.stringify(error))); + console.log(tl.loc("ErrorWhileSettingDotNetToolPath", JSON.stringify(error))); } } diff --git a/Tasks/DotNetCoreInstallerV1/models.ts b/Tasks/DotNetCoreInstallerV1/models.ts new file mode 100644 index 000000000000..55e8e1793593 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/models.ts @@ -0,0 +1,77 @@ +import * as utils from "./versionutilities"; +import * as semver from "semver"; + +export class VersionInfo { + public version: string; + public files: VersionFilesData[]; + + public static getRuntimeVersion(versionInfo: VersionInfo, packageType: string): string { + if (packageType == utils.Constants.sdk) { + if (versionInfo["runtime-version"]) { + return versionInfo["runtime-version"]; + } + + tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, versionInfo.version)); + } + else { + return versionInfo.version; + } + + return ""; + } +} + +export class VersionFilesData { + public name: string; + public url: string; + public rid: string; + public hash?: string; +} + +export class Channel { + constructor(channelRelease: any) { + if (!channelRelease || !channelRelease["channel-version"] || !channelRelease["releases.json"]) { + throw "Object cannot be used as Channel, required properties such as channel-version, releases.json is missing. " + } + + this.channelVersion = channelRelease["channel-version"]; + this.releasesJsonUrl = channelRelease["releases.json"]; + } + + channelVersion: string; + releasesJsonUrl: string +} + +export class VersionParts { + constructor(version: string) { + VersionParts.ValidateVersionSpec(version); + let parts: string[] = version.split("."); + + this.majorVersion = parts[0]; + this.minorVersion = parts[1]; + this.patchVersion = ""; + if (this.minorVersion != "x") { + this.patchVersion = parts[2]; + } + } + + public static ValidateVersionSpec(version): boolean { + try { + let parts = version.split('.'); + // validate version + if (parts.length < 2 || parts.length > 3 || (parts[1] == "x" && parts.length > 2) || (parts[1] != "x" && parts.length <= 2) || !parts[0] || !parts[1] || (parts.length == 3 && !parts[2]) || Number.isNaN(Number.parseInt(parts[0])) || (Number.isNaN(Number.parseInt(parts[1])) && parts[1] != "x")) { + throw ""; + } + + semver.Range(version); + return true; + } + catch (ex) { + tl.loc("VersionNotAllowed", version) + } + } + + majorVersion: string; + minorVersion: string; + patchVersion: string; +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/package-lock.json b/Tasks/DotNetCoreInstallerV1/package-lock.json index 150a476f905a..f6433390da38 100644 --- a/Tasks/DotNetCoreInstallerV1/package-lock.json +++ b/Tasks/DotNetCoreInstallerV1/package-lock.json @@ -1,14 +1,9 @@ { "name": "dotnetcoreinstaller", - "version": "0.1.0", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { - "@types/mocha": { - "version": "2.2.48", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", - "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==" - }, "@types/node": { "version": "6.14.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.4.tgz", diff --git a/Tasks/DotNetCoreInstallerV1/package.json b/Tasks/DotNetCoreInstallerV1/package.json index 1db826fdadb1..69f8b1339280 100644 --- a/Tasks/DotNetCoreInstallerV1/package.json +++ b/Tasks/DotNetCoreInstallerV1/package.json @@ -1,6 +1,6 @@ { "name": "dotnetcoreinstaller", - "version": "0.1.0", + "version": "1.0.0", "description": ".Net Core Installer", "main": "dotnetcoreinstaller.js", "scripts": { @@ -23,7 +23,6 @@ }, "homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme", "dependencies": { - "@types/mocha": "^2.2.5", "@types/node": "^6.0.101", "@types/q": "^1.5.0", "vsts-task-lib": "2.0.6", diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index ee593a66e331..55181d21121a 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -3,8 +3,8 @@ "name": "DotNetCoreInstaller", "friendlyName": ".NET Core SDK/Runtime Installer", "description": "Acquires a version of the .NET Core SDK/Runtime from the internet or the local cache and adds it to the PATH. Use this task to change the version of .NET Core used in subsequent tasks.", - "helpUrl": "", - "helpMarkDown": "", + "helpUrl": "https://aka.ms/AA4ihfi", + "helpMarkDown": "[More Information](https://aka.ms/AA4ihfi)", "category": "Tool", "runsOn": [ "Agent", @@ -39,7 +39,7 @@ "required": true, "helpMarkDown": "Please select whether to install only runtime or full SDK.", "options": { - "runtime": "Runtime", + "runtime": "Only Runtime", "sdk": "SDK (contains runtime)" } }, @@ -57,7 +57,7 @@ "label": "Include Preview Versions", "defaultValue": "false", "required": false, - "helpMarkDown": "Select if you want preview versions to be included while searching for versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 2.1.403" + "helpMarkDown": "Select if you want preview versions to be included while searching for latest versions, such as while searching 2.2.x. This setting is ignored if you specify an exact version, such as: 3.0.100-preview3-010431" }, { "name": "installationPath", @@ -138,6 +138,8 @@ "FallingBackToAdjacentChannels": "Version %s could not be found in its channel, will now search in adjacent channels.", "ErrorWhileSettingDotNetToolPath": "Failed while prepending .Net Core Tool path to PATH envrionment variable. Error: %s", "RequiredChannelVersionForSpec": "Finding channel %s for version %s", - "ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s" + "ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s", + "ComparingInstalledFolderVersions": "Comparing if version being installed %s is greater than already installed version with folder name %s", + "ComparingInstalledFileVersions": "Comparing if version being installed %s is greater than already installed version with version complete file name %s" } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/task.loc.json b/Tasks/DotNetCoreInstallerV1/task.loc.json index 0ff6ed489382..b588b0f4efb9 100644 --- a/Tasks/DotNetCoreInstallerV1/task.loc.json +++ b/Tasks/DotNetCoreInstallerV1/task.loc.json @@ -3,7 +3,7 @@ "name": "DotNetCoreInstaller", "friendlyName": "ms-resource:loc.friendlyName", "description": "ms-resource:loc.description", - "helpUrl": "", + "helpUrl": "https://aka.ms/AA4ihfi", "helpMarkDown": "ms-resource:loc.helpMarkDown", "category": "Tool", "runsOn": [ @@ -39,7 +39,7 @@ "required": true, "helpMarkDown": "ms-resource:loc.input.help.packageType", "options": { - "runtime": "Runtime", + "runtime": "Only Runtime", "sdk": "SDK (contains runtime)" } }, @@ -138,6 +138,8 @@ "FallingBackToAdjacentChannels": "ms-resource:loc.messages.FallingBackToAdjacentChannels", "ErrorWhileSettingDotNetToolPath": "ms-resource:loc.messages.ErrorWhileSettingDotNetToolPath", "RequiredChannelVersionForSpec": "ms-resource:loc.messages.RequiredChannelVersionForSpec", - "ErrorWhileGettingVersionFromChannel": "ms-resource:loc.messages.ErrorWhileGettingVersionFromChannel" + "ErrorWhileGettingVersionFromChannel": "ms-resource:loc.messages.ErrorWhileGettingVersionFromChannel", + "ComparingInstalledFolderVersions": "ms-resource:loc.messages.ComparingInstalledFolderVersions", + "ComparingInstalledFileVersions": "ms-resource:loc.messages.ComparingInstalledFileVersions" } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/tsconfig.json b/Tasks/DotNetCoreInstallerV1/tsconfig.json index 66a524cfc9e9..0438b79f69ac 100644 --- a/Tasks/DotNetCoreInstallerV1/tsconfig.json +++ b/Tasks/DotNetCoreInstallerV1/tsconfig.json @@ -1,8 +1,6 @@ { "compilerOptions": { "target": "ES6", - "module": "commonjs", - "sourceMap": true, - "sourceRoot": "C:\\github\\vsts-tasks\\tasks\\dotnetcoreinstaller\\" + "module": "commonjs" } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts index 1a68955f8977..40d1053595ca 100644 --- a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts @@ -8,6 +8,7 @@ import * as trm from 'vsts-task-lib/toolrunner'; import httpClient = require("typed-rest-client/HttpClient"); import httpInterfaces = require("typed-rest-client/Interfaces"); import { HttpClientResponse } from 'typed-rest-client/HttpClient'; +import { VersionInfo, Channel, VersionFilesData, VersionParts } from "./models" import * as utils from "./versionutilities"; @@ -68,11 +69,7 @@ export class DotNetCoreVersionFetcher { return false; }); - if (downloadPackageInfoObject) { - return true; - } - - return false; + return !!downloadPackageInfoObject; }); if (!!downloadPackageInfoObject && downloadPackageInfoObject.url) { @@ -112,7 +109,7 @@ export class DotNetCoreVersionFetcher { } private getVersionChannel(versionSpec: string): Channel { - let versionParts = new utils.VersionParts(versionSpec); + let versionParts = new VersionParts(versionSpec); let requiredChannelVersion = `${versionParts.majorVersion}.${versionParts.minorVersion}`; if (versionParts.minorVersion == "x") { @@ -196,7 +193,7 @@ export class DotNetCoreVersionFetcher { } private getChannelsForMajorVersion(version: string): Channel[] { - var versionParts = new utils.VersionParts(version); + var versionParts = new VersionParts(version); let adjacentChannels: Channel[] = []; this.channels.forEach(channel => { if (channel.channelVersion.startsWith(`${versionParts.majorVersion}`)) { @@ -273,45 +270,4 @@ export class DotNetCoreVersionFetcher { private httpCallbackClient: httpClient.HttpClient; } -export class VersionInfo { - public version: string; - public files: VersionFilesData[]; - - public static getRuntimeVersion(versionInfo: VersionInfo, packageType: string): string { - if (packageType == utils.Constants.sdk) { - if (versionInfo["runtime-version"]) { - return versionInfo["runtime-version"]; - } - - tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, versionInfo.version)); - } - else { - return versionInfo.version; - } - - return ""; - } -} - -export class VersionFilesData { - public name: string; - public url: string; - public rid: string; - public hash?: string; -} - -class Channel { - constructor(channelRelease: any) { - if (!channelRelease || !channelRelease["channel-version"] || !channelRelease["releases.json"]) { - throw "Object cannot be used as Channel, required properties such as channel-version, releases.json is missing. " - } - - this.channelVersion = channelRelease["channel-version"]; - this.releasesJsonUrl = channelRelease["releases.json"]; - } - - channelVersion: string; - releasesJsonUrl: string -} - const DotNetCoreReleasesIndexUrl: string = "https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases-index.json"; \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts index edc74c1e4088..6870eec1e907 100644 --- a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts @@ -6,7 +6,7 @@ import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib/tool'; import * as utils from "./versionutilities"; -import { VersionInfo } from './versionfetcher'; +import { VersionInfo } from "./models" export class VersionInstaller { constructor(packageType: string, installationPath: string) { @@ -55,7 +55,7 @@ export class VersionInstaller { // Copy files try { - if (this.isLatestInstalledVersion(version)) { + if (this.isLatestInstalledVersion(version) && this.packageType == utils.Constants.sdk) { tl.debug(tl.loc("CopyingFilesIntoPath", this.installationPath)); var filesToBeCopied = allRootLevelEnteriesInDir.filter(path => !fs.lstatSync(path).isDirectory()); filesToBeCopied.forEach((filePath) => { @@ -129,7 +129,9 @@ export class VersionInstaller { var folderPaths: string[] = allEnteries.filter(element => fs.lstatSync(element).isDirectory()); var isLatest: boolean = folderPaths.findIndex(folderPath => { try { - return utils.versionCompareFunction(path.basename(folderPath), version) > 0; + let versionFolderName = path.basename(folderPath); + tl.debug(tl.loc("ComparingInstalledFolderVersions", version, versionFolderName)); + return utils.versionCompareFunction(versionFolderName, version) > 0; } catch (ex) { // no op, folder name might not be in version format @@ -139,7 +141,9 @@ export class VersionInstaller { var filePaths: string[] = allEnteries.filter(element => !fs.lstatSync(element).isDirectory()); isLatest = isLatest && filePaths.findIndex(filePath => { try { - return utils.versionCompareFunction(this.getVersionCompleteFileName(path.basename(filePath)), version) > 0 + var versionCompleteFileName = this.getVersionCompleteFileName(path.basename(filePath)); + tl.debug(tl.loc("ComparingInstalledFileVersions", version, versionCompleteFileName)); + return utils.versionCompareFunction(versionCompleteFileName, version) > 0 } catch (ex) { // no op, file name might not be in version format diff --git a/Tasks/DotNetCoreInstallerV1/versionutilities.ts b/Tasks/DotNetCoreInstallerV1/versionutilities.ts index 7a90fce1928d..f742efb850b2 100644 --- a/Tasks/DotNetCoreInstallerV1/versionutilities.ts +++ b/Tasks/DotNetCoreInstallerV1/versionutilities.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import * as tl from 'vsts-task-lib/task'; import * as toolLib from 'vsts-task-tool-lib'; import * as semver from 'semver'; -import { VersionInfo } from './versionfetcher'; +import { VersionInfo } from "./models" export function versionCompareFunction(versionA: string, versionB: string): number { if (!toolLib.isExplicitVersion(versionA) || !toolLib.isExplicitVersion(versionB)) { @@ -62,34 +62,6 @@ export function getMatchingVersionFromList(versionInfoList: VersionInfo[], versi return null; } -export class VersionParts { - constructor(version: string) { - VersionParts.ValidateVersionSpec(version); - let parts: string[] = version.split("."); - - this.majorVersion = parts[0]; - this.minorVersion = parts[1]; - this.patchVersion = ""; - if (this.minorVersion != "x") { - this.patchVersion = parts[2]; - } - } - - public static ValidateVersionSpec(version): boolean { - let parts: string[] = version.split('.'); - // validate version - if (parts.length < 2 || parts.length > 3 || parts[0] == "x" || (parts[1] == "x" && parts.length > 2) || (parts[1] != "x" && parts.length <= 2) || !parts[0] || !parts[1] || (parts.length == 3 && !parts[2]) || Number.isNaN(Number.parseInt(parts[0])) || (Number.isNaN(Number.parseInt(parts[1])) && parts[1] != "x")) { - throw tl.loc("VersionNotAllowed", version) - } - - return true; - } - - majorVersion: string; - minorVersion: string; - patchVersion: string; -} - export const Constants = { "sdk": "sdk", "runtime": "runtime", From 5640949ed98bf0567009282c2d3f87d66d43506d Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Mon, 18 Mar 2019 22:34:00 +0530 Subject: [PATCH 13/17] added few L0 tests --- .../resources.resjson/en-US/resources.resjson | 4 +- Tasks/DotNetCoreInstallerV1/Tests/L0.ts | 391 ++++++++++++------ .../Tests/mocks/mockedModels.ts | 11 + .../Tests/modelsChannelTests.ts | 73 ++++ .../Tests/modelsGetRuntimeVersionTests.ts | 64 +++ .../Tests/modelsValidateVersionSpecTests.ts | 90 ++++ .../Tests/modelsVersionPartsTests.ts | 95 +++++ .../versionFetcherGetVersionInfoFailTests.ts | 44 ++ ...ersionFetcherGetVersionInfoTestsCorrect.ts | 94 +++++ ...ersionUtilityChannelVersionCompareTests.ts | 54 +++ ...nUtilityGetMatchingVersionFromListTests.ts | 89 ++++ .../versionUtilityVersionCompareTests.ts | 66 +++ Tasks/DotNetCoreInstallerV1/models.ts | 32 +- Tasks/DotNetCoreInstallerV1/task.json | 4 +- Tasks/DotNetCoreInstallerV1/task.loc.json | 4 +- Tasks/DotNetCoreInstallerV1/versionfetcher.ts | 7 +- 16 files changed, 972 insertions(+), 150 deletions(-) create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/modelsChannelTests.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/modelsVersionPartsTests.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoFailTests.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoTestsCorrect.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/versionUtilityChannelVersionCompareTests.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/versionUtilityVersionCompareTests.ts diff --git a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson index e5fe6fd954e4..08d28d200399 100644 --- a/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/DotNetCoreInstallerV1/Strings/resources.resjson/en-US/resources.resjson @@ -71,5 +71,7 @@ "loc.messages.RequiredChannelVersionForSpec": "Finding channel %s for version %s", "loc.messages.ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s", "loc.messages.ComparingInstalledFolderVersions": "Comparing if version being installed %s is greater than already installed version with folder name %s", - "loc.messages.ComparingInstalledFileVersions": "Comparing if version being installed %s is greater than already installed version with version complete file name %s" + "loc.messages.ComparingInstalledFileVersions": "Comparing if version being installed %s is greater than already installed version with version complete file name %s", + "loc.messages.InvalidChannelObject": "Object cannot be used as Channel, required properties such as channel-version, releases.json is missing.", + "loc.messages.ReleasesIndexBodyIncorrect": "Parsed releases index body is not correct. Kindly see if the releases-index section is not empty in the file." } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts index a0b826673c99..8741e3af33f5 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts @@ -21,173 +21,302 @@ function runValidations(validator: () => void, tr, done) { } } -describe('DotNetCoreInstaller', function() { +describe('DotNetCoreInstaller', function () { this.timeout(30000); before((done) => { done(); }); - after(function() { + after(function () { + }); + + it("[VersionUtilities] versionCompareFunction should throw for non explicit versions or empty version strings", (done) => { + process.env["__non_explicit__"] = "true" + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionUtilityVersionCompareTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("should have thrown and failed")); + assert(tr.stdout.indexOf("FunctionThrewAsExpected") > -1, "Should have thrown as versions are not explicit and are empty strings."); + }, tr, done); + }); + + it("[VersionUtilities] versionCompareFunction should return 1, 0 or -1 when versionA is gt, eq or lt versionB", (done) => { + process.env["__non_explicit__"] = "false"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionUtilityVersionCompareTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have succeeded")); + assert(tr.stdout.indexOf("FunctionGaveRightResult") > -1, "Should have given right results for all cases."); + }, tr, done); + }); + + it("[VersionUtilities] compareChannelVersion function should throw when either or both channel versions are empty or are non numeric", (done) => { + process.env["__non_explicit__"] = "true" + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionUtilityVersionCompareTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("should have thrown and failed")); + assert(tr.stdout.indexOf("FunctionThrewAsExpected") > -1, "Should have thrown as versions are not explicit and are empty strings."); + }, tr, done); + }); + + it("[VersionUtilities] compareChannelVersion function should return 1, 0 or -1 when channelVersionA is gt, eq or lt channelVersionB", (done) => { + process.env["__non_explicit__"] = "false"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionUtilityChannelVersionCompareTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have succeeded")); + assert(tr.stdout.indexOf("FunctionGaveRightResult") > -1, "Should have given right results for all cases."); + }, tr, done); + }); + + it("[VersionUtilities] getMatchingVersionFromList should return null for empty versionInfoList, versionInfoList elements having empty version or no matching version found in list while toggling includePreviewVersionsValue", (done) => { + process.env["__empty__"] = "true" + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionUtilityGetMatchingVersionFromListTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have succeeded")); + assert(tr.stdout.indexOf("FunctionReturnedNull") > -1, "Should have returned null for all cases and print the message."); + }, tr, done); + }); + + it("[VersionUtilities] getMatchingVersionFromList should return heighest version for the spec when versionSpec is not exact version", (done) => { + process.env["__empty__"] = "false" + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionUtilityGetMatchingVersionFromListTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have succeeded")); + assert(tr.stdout.indexOf("FuctionReturnedCorrectVersion") > -1, "Should have returned null for all cases and print the message."); + }, tr, done); + }); + + it("[Models] ValidateVersionSpec should throw when version spec is not valid range or version", (done) => { + process.env["__invalid_versionspec__"] = "true"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsValidateVersionSpecTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed")); + assert(tr.stdout.indexOf("FunctionThrewAsExpected") > -1, "Should have thrown for all invalid version specs."); + }, tr, done); + }); + + it("[Models] ValidateVersionSpec should return true when version spec is range or version", (done) => { + process.env["__invalid_versionspec__"] = "false"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsValidateVersionSpecTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have passed")); + assert(tr.stdout.indexOf("VersionsValidatedSuccessfully") > -1, "Should have returned true for all valid versions specs."); + }, tr, done); + }); + + it("[Models.VersionParts] constructor should throw when version fails validation", (done) => { + process.env["__invalid_versionparts__"] = "true"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsVersionPartsTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed")); + assert(tr.stdout.indexOf("FunctionThrewAsExpected") > -1, "Should have thrown for all invalid version specs."); + }, tr, done); + }); + + it("[Models.VersionParts] constructor return object instance with correct major, minor and patch version", (done) => { + process.env["__invalid_versionparts__"] = "false"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsVersionPartsTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have returned right objects")); + assert(tr.stdout.indexOf("VersionPartsCreatedSuccessfully") > -1, "Should have returned the correct objects and print the statement."); + }, tr, done); + }); + + it("[Models.Channel] constructor should throw if object passed doesn't contain channel-version or releasesJsonUrl, or contains invalid releasesJsonUrl", (done) => { + process.env["__invalid_channelobject__"] = "true"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsChannelTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed for incorrect objects.")); + assert(tr.stdout.indexOf("FunctionThrewAsExpected") > -1, "Should have thrown error in all cases."); + }, tr, done); + }); + + it("[Models.Channel] constructor should pass if object contains channel-version and valid releasesJsonUrl", (done) => { + process.env["__invalid_channelobject__"] = "false"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsChannelTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have successfully created channel objects.")); + assert(tr.stdout.indexOf("ChannelCreatedSuccessfully") > -1, "Should have returned the correct objects and print the statement."); + }, tr, done); + }); + + it("[Models.VersionInfo] getRuntimeVersion should return correct runtime-version from sdk versionInfo object", (done) => { + process.env["__sdk_runtime__"] = "true"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsGetRuntimeVersionTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have successfully returned runtime versions for sdk package type.")); + assert(tr.stdout.indexOf("RuntimeVersionsReturnedForSdkAreCorrect") > -1, "Should have returned correct runtime versions for all cases of packageType sdk."); + }, tr, done); + }); + + it("[Models.VersionInfo] getRuntimeVersion should return version for runtime versionInfo object", (done) => { + process.env["__sdk_runtime__"] = "false"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsGetRuntimeVersionTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have successfully returned runtime versions for runtime package type.")); + assert(tr.stdout.indexOf("RuntimeVersionsReturnedAreCorrect") > -1, "Should have returned correct runtime versions for all cases of packageType runtime."); + }, tr, done); + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should throw if version for pacakge type can not be found, and error message should contain the package type", (done) => { + process.env["__failat__"] = "versionnotfound"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoFailTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed as the wanted version of package type can not be found.")); + assert(tr.stdout.indexOf("VersionNotFound") > -1, "Should have thrown version not found exception."); + }, tr, done); + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should throw if getting channel fails", (done) => { + process.env["__failat__"] = "channelfetch"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoFailTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed as channels could not be fetched.")); + assert(tr.stdout.indexOf("ExceptionWhileDownloadOrReadReleasesIndex") > -1, "Should have thrown exception and returned."); + }, tr, done); + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return correct version info for a correct version spec", (done) => { + process.env["__versionspec__"] = "2.2.103"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoTestsCorrect.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have returned the correct version info.")); + }, tr, done); + }); + + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return correct version info for a version which exists in a different channel of the same major version", (done) => { + process.env["__versionspec__"] = "2.1.104"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoTestsCorrect.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have returned the correct version info.")); + }, tr, done); }); - it("[VersionUtilities] versionCompareFunction should throw for non explicit versions or empty version strings", () => { + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info in a major version for a versionSpec of type majorVersion.x", (done) => { + process.env["__versionspec__"] = "2.x"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoTestsCorrect.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have returned the correct version info.")); + }, tr, done); }); - it("[VersionUtilities] versionCompareFunction should return 1, 0 or -1 when versionA is gt, eq or lt versionB", () => { + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info in a major.minor version for a versionSpec of type majorVersion.minorVersion.x", (done) => { + process.env["__versionspec__"] = "2.2.x"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoTestsCorrect.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have returned the correct version info.")); + }, tr, done); }); - it("[VersionUtilities] compareChannelVersion function should throw when either or both channel versions are empty or are non numeric", () => { + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest preview version info if includePreviewVersion is true and latest version is a preview version", (done) => { + process.env["__versionspec__"] = "2.2.x"; + process.env["__inlcudepreviewversion__"] = "true"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoTestsCorrect.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have returned the correct version info.")); + }, tr, done); }); - it("[VersionUtilities] compareChannelVersion function should return 1, 0 or -1 when channelVersionA is gt, eq or lt channelVersionB", () => { + it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info even if includePreviewVersion is true but latest version is non preview", (done) => { + process.env["__versionSpec__"] = "2.3.x"; + process.env["__inlcudepreviewversion__"] = "true"; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetVersionInfoTestsCorrect.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == true, ("Should have returned the correct version info.")); + }, tr, done); }); - it("[VersionUtilities] getMatchingVersionFromList should return null for empty versionInfoList or versionInfoList elements having empty version", () => { - }); - - it("[VersionUtilities] getMatchingVersionFromList should return null when no version satisfying versionSpec can be found in list", () => { - }); - - it("[VersionUtilities] getMatchingVersionFromList should return heighest version for the spec when versionSpec is not exact version", () => { - }); + // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if VersionFilesData doesn't contain download URL", (done) => { + // }); - it("[VersionUtilities] getMatchingVersionFromList should return null when versionSpec is exact version and the same version is not present in versionInfoList", () => { - }); + // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if download information object with RID matching OS, could not be found", (done) => { + // }); - it("[VersionUtilities] getMatchingVersionFromList should return exact version when versionSpec is exact version and the same version is present in versionInfoList", () => { - }); + // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if error encountered while detecting machine os", (done) => { + // }); - it("[VersionUtilities] ValidateVersionSpec should throw when majorversion have non numeric characters", () => { - }); - - it("[VersionUtilities] ValidateVersionSpec should throw when minor version have non numeric characters other than being only x", () => { - }); + // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if zip package is not found for windows os", (done) => { + // }); - it("[VersionUtilities] ValidateVersionSpec should throw when patch version is present and minor version is x", () => { - }); - - it("[VersionUtilities] ValidateVersionSpec should throw when patch version is empty and minor version is numeric", () => { - }); - - it("[VersionUtilities] ValidateVersionSpec should throw when major or minor version is empty", () => { - }); - - it("[VersionUtilities] VersionParts constructor should throw when version fails validation", () => { - }); - - it("[VersionUtilities] VersionParts constructor return object instance with correct major, minor and patch version", () => { - }); + // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if tar.gz package is not found for linux os", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should throw if version for pacakge type can not be found, and error message should contain the package type", () => { - }); + // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should return correct download URL for matching OS", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should throw if getting channel fails", () => { - }); + // it("[VersionInstaller] constructor should throw if installationPath doesn't exist and cannot be created", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return correct version info for a correct version spec", () => { - }); + // it("[VersionInstaller] downloadAndInstall should throw if passed arguments are empty or doesn't contain version or downloadUrl is malformed", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return correct version info for a version which exists in a different channel of the same major version", () => { - }); + // it("[VersionInstaller] downloadAndInstall should throw if downloading version from URL fails", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info in a major version for a versionSpec of type majorVersion.x", () => { - }); + // it("[VersionInstaller] downloadAndInstall should throw if extracting downloaded package or copying folders into installation path fails.", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info in a major.minor version for a versionSpec of type majorVersion.minorVersion.x", () => { - }); + // it("[VersionInstaller] downloadAndInstall should not throw if copying root files from package into installationPath fails", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest preview version info if includePreviewVersion is true and latest version is a preview version", () => { - }); + // it("[VersionInstaller] downloadAndInstall should only copy files from root folder if version being installed in the path is greater than all other already present", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getVersionInfo should return latest version info even if includePreviewVersion is true but latest version is non preview", () => { - }); + // it("[VersionInstaller] downloadAndInstall should throw if creating version.complete file fails.", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if VersionFilesData doesn't contain download URL", () => { - }); + // it("[VersionInstaller] downloadAndInstall should complete successfully on complete installation and create complete file in both sdk and runtime when sdk is installed and in runtime when only runtime is installed.", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if download information object with RID matching OS, could not be found", () => { - }); + // it("[VersionInstaller] isVersionInstalled should throw if version being checked is not explicit.", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if error encountered while detecting machine os", () => { - }); + // it("[VersionInstaller] isVersionInstalled should return false if either folder or file with name as version is not present inside sdk folder.", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if zip package is not found for windows os", () => { - }); + // it("[VersionInstaller] isVersionInstalled should return false if either folder or file with name as version is not present inside runtime path.", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if tar.gz package is not found for linux os", () => { - }); + // it("[VersionInstaller] isVersionInstalled should return true if both folder or file with name as version is present inside sdk/runtime path.", (done) => { + // }); - it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should return correct download URL for matching OS", () => { - }); + // it("[dotnetcoreinstaller] run should default to use $(Agent.ToolsDirectory)/dotnet as installation path if installationPath input is empty.", (done) => { + // }); - it("[VersionFetcher.VersionInfo] getRuntimeVersion should return correct runtime-version from sdk versionInfo object", () => { - }); + // it("[dotnetcoreinstaller] run should throw if versionSpec is invalid.", (done) => { + // }); - it("[VersionFetcher.VersionInfo] getRuntimeVersion should return version for runtime versionInfo object", () => { - }); + // it("[dotnetcoreinstaller] run should throw if versionInfo for the version spec could not be found.", (done) => { + // }); - it("[VersionFetcher.VersionInfo] getRuntimeVersion should return empty string for sdk versionInfo object if runtime-version is not present", () => { - }); + // it("[dotnetcoreinstaller] run should skip installation if version found in cache.", (done) => { + // }); - it("[VersionFetcher.Channel] constructor should throw if object passed doesn't contain channel-version or releasesJsonUrl, or contains invalid releasesJsonUrl", () => { - }); + // it("[dotnetcoreinstaller] run should always prepend installationPath & dotnet_root to PATH environment variable.", (done) => { + // }); - it("[VersionFetcher.Channel] constructor should pass if object contains channel-version and valid releasesJsonUrl", () => { - }); + // it("[dotnetcoreinstaller] run should not fail if globalToolPath could not be created or set.", (done) => { + // }); - it("[VersionInstaller] constructor should throw if installationPath doesn't exist and cannot be created", () => { - }); - - it("[VersionInstaller] downloadAndInstall should throw if passed arguments are empty or doesn't contain version or downloadUrl is malformed", () => { - }); - - it("[VersionInstaller] downloadAndInstall should throw if downloading version from URL fails", () => { - }); - - it("[VersionInstaller] downloadAndInstall should throw if extracting downloaded package or copying folders into installation path fails.", () => { - }); - - it("[VersionInstaller] downloadAndInstall should not throw if copying root files from package into installationPath fails", () => { - }); - - it("[VersionInstaller] downloadAndInstall should only copy files from root folder if version being installed in the path is greater than all other already present", () => { - }); - - it("[VersionInstaller] downloadAndInstall should throw if creating version.complete file fails.", () => { - }); - - it("[VersionInstaller] downloadAndInstall should complete successfully on complete installation and create complete file in both sdk and runtime when sdk is installed and in runtime when only runtime is installed.", () => { - }); - - it("[VersionInstaller] isVersionInstalled should throw if version being checked is not explicit.", () => { - }); - - it("[VersionInstaller] isVersionInstalled should return false if either folder or file with name as version is not present inside sdk folder.", () => { - }); - - it("[VersionInstaller] isVersionInstalled should return false if either folder or file with name as version is not present inside runtime path.", () => { - }); - - it("[VersionInstaller] isVersionInstalled should return true if both folder or file with name as version is present inside sdk/runtime path.", () => { - }); - - it("[dotnetcoreinstaller] run should default to use $(Agent.ToolsDirectory)/dotnet as installation path if installationPath input is empty.", () => { - }); - - it("[dotnetcoreinstaller] run should throw if versionSpec is invalid.", () => { - }); - - it("[dotnetcoreinstaller] run should throw if versionInfo for the version spec could not be found.", () => { - }); - - it("[dotnetcoreinstaller] run should skip installation if version found in cache.", () => { - }); - - it("[dotnetcoreinstaller] run should always prepend installationPath & dotnet_root to PATH environment variable.", () => { - }); - - it("[dotnetcoreinstaller] run should not fail if globalToolPath could not be created or set.", () => { - }); - - it("[dotnetcoreinstaller] run should always set multilevel lookup environment variable and by default restrict if input is not present.", () => { - }); + // it("[dotnetcoreinstaller] run should always set multilevel lookup environment variable and by default restrict if input is not present.", (done) => { + // }); }); diff --git a/Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts b/Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts new file mode 100644 index 000000000000..e62407375453 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts @@ -0,0 +1,11 @@ +export class HttpClientResponse { + constructor(message) { + this.message = message; + } + public readBody() { + return new Promise((resolve, reject) => { + resolve(this.message); + }) + } + message: string = "" +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/modelsChannelTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/modelsChannelTests.ts new file mode 100644 index 000000000000..d075bc218147 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/modelsChannelTests.ts @@ -0,0 +1,73 @@ +'use strict'; +import { Channel } from "../models"; +import * as tl from 'vsts-task-lib/task'; + +if (process.env["__invalid_channelobject__"] == "true") { + let throwCount: number = 0; + // try with non explicit version + try { + new Channel(null); + } + catch (ex) { + throwCount++; + } + + try { + new Channel(undefined); + } + catch (ex) { + throwCount++; + } + + try { + new Channel(""); + } + catch (ex) { + throwCount++; + } + + try { + new Channel({}); + } + catch (ex) { + throwCount++; + } + + try { + new Channel({"channel-version": undefined, "releases.json": ""}); + } + catch (ex) { + throwCount++; + } + + try { + new Channel({"channel-version": "2.2", "releases.json": null}); + } + catch (ex) { + throwCount++; + } + + try { + new Channel({"channel-version": "2.2", "releases.json": ""}); + } + catch (ex) { + throwCount++; + } + + if (throwCount == 7) { + throw tl.loc("FunctionThrewAsExpected"); + } +} +else { + let channel = new Channel({"channel-version": "2.2", "releases.json": "https://channelRelease.com"}); + if (channel.channelVersion != "2.2" || channel.releasesJsonUrl != "https://channelRelease.com") { + throw tl.loc("first") + } + + channel = new Channel({"channel-version": "3.x", "releases.json": "https://channelRelease.com/downloadreleases.json"}); + if (channel.channelVersion != "3.x" || channel.releasesJsonUrl != "https://channelRelease.com/downloadreleases.json") { + throw tl.loc("second") + } + + console.log("ChannelCreatedSuccessfully"); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts new file mode 100644 index 000000000000..ef5272edc760 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts @@ -0,0 +1,64 @@ +'use strict'; +import { VersionInfo } from "../models"; +import * as tl from 'vsts-task-lib/task'; + + +if (VersionInfo.getRuntimeVersion(null, "") != "") { + throw ""; +} + +if (VersionInfo.getRuntimeVersion(null, "") != "") { + throw ""; +} + +let versionInfo = new VersionInfo(); +versionInfo.version = ""; + +if (process.env["__sdk_runtime__"] == "true") { + if (VersionInfo.getRuntimeVersion(versionInfo, "sdk") != "") { + throw ""; + } + + versionInfo.version = "2.2.100" + if (VersionInfo.getRuntimeVersion(versionInfo, "sdk") != "") { + throw ""; + } + + versionInfo.version = "2.2.104"; + versionInfo["runtime-version"] = "2.2.4"; + if (VersionInfo.getRuntimeVersion(versionInfo, "sdk") != "2.2.4") { + throw ""; + } + + versionInfo.version = ""; + versionInfo["runtime-version"] = "2.2.4"; + if (VersionInfo.getRuntimeVersion(null, "") != "") { + throw ""; + } + + console.log(tl.loc("RuntimeVersionsReturnedForSdkAreCorrect")); +} +else { + if (VersionInfo.getRuntimeVersion(versionInfo, "runtime") != "") { + throw ""; + } + + versionInfo.version = "2.2.100" + if (VersionInfo.getRuntimeVersion(versionInfo, "runtime") != "2.2.100") { + throw ""; + } + + versionInfo.version = "2.2.104"; + versionInfo["runtime-version"] = "2.2.4"; + if (VersionInfo.getRuntimeVersion(versionInfo, "runtime") != "2.2.104") { + throw ""; + } + + versionInfo.version = ""; + versionInfo["runtime-version"] = "2.2.4"; + if (VersionInfo.getRuntimeVersion(null, "") != "") { + throw ""; + } + + console.log(tl.loc("RuntimeVersionsReturnedAreCorrect")); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts new file mode 100644 index 000000000000..e095bc8fc474 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts @@ -0,0 +1,90 @@ +'use strict'; +import { VersionParts } from "../models"; +import * as tl from 'vsts-task-lib/task'; + +if (process.env["__invalid_versionspec__"] == "true") { + let throwCount: number = 0; + // try with non explicit version + try { + VersionParts.ValidateVersionSpec("2a.x"); + } + catch (ex) { + throwCount++; + } + + try { + VersionParts.ValidateVersionSpec("2.2x"); + } + catch (ex) { + throwCount++; + } + + try { + VersionParts.ValidateVersionSpec("2.x.2"); + } + catch (ex) { + throwCount++; + } + + try { + VersionParts.ValidateVersionSpec("2.2."); + } + catch (ex) { + throwCount++; + } + + try { + VersionParts.ValidateVersionSpec("2.2"); + } + catch (ex) { + throwCount++; + } + + try { + VersionParts.ValidateVersionSpec(""); + } + catch (ex) { + throwCount++; + } + + try { + VersionParts.ValidateVersionSpec(".."); + } + catch (ex) { + throwCount++; + } + + try { + VersionParts.ValidateVersionSpec("2.2.2fs"); + } + catch (ex) { + throwCount++; + } + + if (throwCount == 8) { + throw tl.loc("FunctionThrewAsExpected"); + } +} +else { + if (VersionParts.ValidateVersionSpec("2.x") != true) { + throw "" + } + + if (VersionParts.ValidateVersionSpec("2.100.x") != true) { + throw "" + } + + if (VersionParts.ValidateVersionSpec("2.100.1") != true) { + throw "" + } + + if (VersionParts.ValidateVersionSpec("2.100.13-preview") != true) { + throw "" + } + + if (VersionParts.ValidateVersionSpec("2.100.14-rc1-431") != true) { + throw "" + } + + console.log("VersionsValidatedSuccessfully"); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/modelsVersionPartsTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/modelsVersionPartsTests.ts new file mode 100644 index 000000000000..4ef6b55f328c --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/modelsVersionPartsTests.ts @@ -0,0 +1,95 @@ +'use strict'; +import { VersionParts } from "../models"; +import * as tl from 'vsts-task-lib/task'; + +if (process.env["__invalid_versionparts__"] == "true") { + let throwCount: number = 0; + // try with non explicit version + try { + new VersionParts("2a.x"); + } + catch (ex) { + throwCount++; + } + + try { + new VersionParts("2.2x"); + } + catch (ex) { + throwCount++; + } + + try { + new VersionParts("2.x.2"); + } + catch (ex) { + throwCount++; + } + + try { + new VersionParts("2.2."); + } + catch (ex) { + throwCount++; + } + + try { + new VersionParts("2.2"); + } + catch (ex) { + throwCount++; + } + + try { + new VersionParts(""); + } + catch (ex) { + throwCount++; + } + + try { + new VersionParts(".."); + } + catch (ex) { + throwCount++; + } + + try { + new VersionParts("2.2.2fs"); + } + catch (ex) { + throwCount++; + } + + if (throwCount == 8) { + throw tl.loc("FunctionThrewAsExpected"); + } +} +else { + let versionParts = new VersionParts("2.x") + if (versionParts.majorVersion != "2" || versionParts.minorVersion != "x" || versionParts.patchVersion != "") { + throw tl.loc("first") + } + + versionParts = new VersionParts("2.100.x"); + if (versionParts.majorVersion != "2" || versionParts.minorVersion != "100" || versionParts.patchVersion != "x") { + throw tl.loc("second") + } + + versionParts = new VersionParts("2.100.1"); + if (versionParts.majorVersion != "2" || versionParts.minorVersion != "100" || versionParts.patchVersion != "1") { + throw tl.loc("third") + } + + versionParts = new VersionParts("2.100.13-preview"); + if (versionParts.majorVersion != "2" || versionParts.minorVersion != "100" || versionParts.patchVersion != "13-preview") { + throw tl.loc("fourth") + } + + versionParts = new VersionParts("2.100.14-rc1-431"); + if (versionParts.majorVersion != "2" || versionParts.minorVersion != "100" || versionParts.patchVersion != "14-rc1-431") { + throw tl.loc("fifth") + } + + console.log("VersionPartsCreatedSuccessfully"); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoFailTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoFailTests.ts new file mode 100644 index 000000000000..69e94ce90651 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoFailTests.ts @@ -0,0 +1,44 @@ +import * as tl from 'vsts-task-lib/task'; +import { HttpClientResponse } from "./mocks/mockedModels" +var mockery = require('mockery'); + +mockery.enable({ + useCleanCache: true, + warnOnReplace: false, + warnOnUnregistered: false +}); + +mockery.registerMock('typed-rest-client/HttpClient', { + HttpClient: function () { + return { + get: function (url: string, headers) { + if (url == DotNetCoreReleasesIndexUrl && process.env["__failat__"] == "versionnotfound") { + return new Promise((resolve, reject) => { + resolve(new HttpClientResponse(`{"releases-index": [{"channel-version": "2.2","releases.json": "${ReleasesJsonUrl2}"}]}`)) + }); + } + else if (url == DotNetCoreReleasesIndexUrl && process.env["__failat__"] == "channelfetch") { + return new Promise((resolve, reject) => { + reject(""); + }); + } + else if (url == ReleasesJsonUrl2) { + return new Promise((resolve, reject) => { + resolve(new HttpClientResponse(`{"releases": [{"version": "2.2.104","files": ["rid":"winx64", "url": "https://dotnetWindowsDownloadUrl.com"]}]}`)); + }); + } + } + } + } +}); + +import { DotNetCoreVersionFetcher } from "../versionfetcher"; + +const DotNetCoreReleasesIndexUrl: string = "https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases-index.json"; +const ReleasesJsonUrl2: string = "https://releases.file.com/version2.2.json" + +let versionFetcher = new DotNetCoreVersionFetcher(); +versionFetcher.getVersionInfo("2.2.999-cantbefound-234", "sdk", false) + .catch((ex) => { + tl.setResult(tl.TaskResult.Failed, "FailedAsExpected"); + }); \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoTestsCorrect.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoTestsCorrect.ts new file mode 100644 index 000000000000..5d928e3957c4 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetVersionInfoTestsCorrect.ts @@ -0,0 +1,94 @@ +import * as tl from 'vsts-task-lib/task'; +import { HttpClientResponse } from "./mocks/mockedModels" +var mockery = require('mockery'); + +mockery.enable({ + useCleanCache: true, + warnOnReplace: false, + warnOnUnregistered: false +}); + +mockery.registerMock('typed-rest-client/HttpClient', { + HttpClient: function () { + return { + get: function (url: string, headers) { + if (url == DotNetCoreReleasesIndexUrl) { + return new Promise((resolve, reject) => { + resolve(new HttpClientResponse(`{"releases-index": [{"channel-version": "2.0","releases.json": "${ReleasesJsonUrl0}"}, {"channel-version": "2.1","releases.json": "${ReleasesJsonUrl1}"}, {"channel-version": "2.2","releases.json": "${ReleasesJsonUrl2}"}, {"channel-version": "2.3","releases.json": "${ReleasesJsonUrl3}"}]}`)) + }); + } + else if (url == ReleasesJsonUrl0) { + return new Promise((resolve, reject) => { + resolve(new HttpClientResponse(`{ + "releases": [ + { + "sdk": { + "version": "2.0.1", + "files": [] + } + }, + { + "sdk": { + "version": "2.1.104", + "files": [] + } + } + ] + }`)); + }); + } + else if (url == ReleasesJsonUrl1) { + return new Promise((resolve, reject) => { + resolve(new HttpClientResponse(`{"releases": [{"sdk": { "version": "2.1.103-preview-999","files": [] } }]}`)); + }); + } + else if (url == ReleasesJsonUrl2) { + return new Promise((resolve, reject) => { + resolve(new HttpClientResponse(`{"releases": [{"sdk": {"version": "2.2.106-preview-1","files": []}}, {"sdk": { "version": "2.2.105","files": []}}, {"sdk": { "version": "2.2.103","files": []}}]}`)); + }); + } + else if (url == ReleasesJsonUrl3) { + return new Promise((resolve, reject) => { + resolve(new HttpClientResponse(`{"releases": [{"sdk": { "version": "2.3.105","files": []}}, {"sdk": { "version": "2.3.103-preview-999","files": [] } }]}`)); + }); + } + } + } + } +}); + +import { DotNetCoreVersionFetcher } from "../versionfetcher"; + +const DotNetCoreReleasesIndexUrl: string = "https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases-index.json"; +const ReleasesJsonUrl0: string = "https://releases.file.com/version2.0.json"; +const ReleasesJsonUrl1: string = "https://releases.file.com/version2.1.json"; +const ReleasesJsonUrl2: string = "https://releases.file.com/version2.2.json"; +const ReleasesJsonUrl3: string = "https://releases.file.com/version2.3.json"; + +let versionFetcher = new DotNetCoreVersionFetcher(); +versionFetcher.getVersionInfo(process.env["__versionspec__"], "sdk", process.env["__inlcudepreviewversion__"] == "true") + .then((versionInfo) => { + if (process.env["__versionspec__"] == "2.2.103" && versionInfo.version != "2.2.103") { + throw ""; + } + else if (process.env["__versionspec__"] == "2.1.104" && versionInfo.version != "2.1.104") { + throw ""; + } + else if (process.env["__versionspec__"] == "2.x" && versionInfo.version != "2.3.105" ) { + throw ""; + } + else if (process.env["__versionspec__"] == "2.2.x" && process.env["__inlcudepreviewversion__"] != "true" && versionInfo.version != "2.2.105") { + throw ""; + } + else if (process.env["__versionspec__"] == "2.2.x" && process.env["__inlcudepreviewversion__"] == "true" && versionInfo.version != "2.2.106-preview-1") { + throw ""; + } + else if (process.env["__versionspec__"] == "2.3.x" && process.env["__inlcudepreviewversion__"] == "true" && versionInfo.version != "2.3.105") { + throw ""; + } + + tl.setResult(tl.TaskResult.Succeeded, "succeeded"); + }) + .catch((ex) => { + tl.setResult(tl.TaskResult.Failed, "FailedAsExpected"); + }); \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityChannelVersionCompareTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityChannelVersionCompareTests.ts new file mode 100644 index 000000000000..1eb589cfe95b --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityChannelVersionCompareTests.ts @@ -0,0 +1,54 @@ +'use strict'; +import * as versionutilities from "../versionutilities"; +import * as tl from 'vsts-task-lib/task'; + +if (process.env["__non_explicit__"] == "true") { + let throwCount: number = 0; + // try with non explicit version + try { + versionutilities.compareChannelVersion("2.2", "2.x"); + } + catch (ex) { + throwCount++; + } + + try { + versionutilities.compareChannelVersion("2.x", "2.1"); + } + catch (ex) { + throwCount++; + } + + try { + versionutilities.compareChannelVersion("", "3.14"); + } + catch (ex) { + throwCount++; + } + + try { + versionutilities.compareChannelVersion("1.127", ""); + } + catch (ex) { + throwCount++; + } + + if (throwCount == 4) { + throw tl.loc("FunctionThrewAsExpected"); + } +} +else { + if (versionutilities.compareChannelVersion("3.0", "2.999") < 1) { + throw ""; + } + + if (versionutilities.compareChannelVersion("3.547", "3.547") != 0) { + throw ""; + } + + if (versionutilities.compareChannelVersion("2.100", "2.200") > -1) { + throw ""; + } + + console.log("FunctionGaveRightResult"); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts new file mode 100644 index 000000000000..750e1a3053f2 --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts @@ -0,0 +1,89 @@ +'use strict'; +import * as versionutilities from "../versionutilities"; +import { VersionInfo } from "../models"; + +if (process.env["__empty__"] == "true") { + let throwCount: number = 0; + // empty version info list + + if (versionutilities.getMatchingVersionFromList([], "2.x") != null) { + throw "" + } + + // version info list with version field empty + if (versionutilities.getMatchingVersionFromList([new VersionInfo()], "2.1") != null) { + throw ""; + } + + // form the version info list with preview versions as well + let versionInfoList: VersionInfo[] = []; + ["3.0.100", "3.1.0-preview-850", ""].forEach((version) => { + var temp = new VersionInfo(); + temp.version = version; + versionInfoList.push(temp); + }); + + // version info list with no version matching the version spec, with includePreviewVersion as false + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.1.x", false) != null) { + throw ""; + } + + + // version info list with no version matching the version spec, with includePreviewVersion as true + if (versionutilities.getMatchingVersionFromList(versionInfoList, "2.9.x", true) != null) { + throw ""; + } + + // version info list with version exactly equal to version not present (in this case version spec is an exact version), , with includePreviewVersion as false + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.1.0", false) != null) { + throw ""; + } + + // version info list with version exactly equal to version not present (in this case version spec is an exact version), with includePreviewVersion as true + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.1.0", true) != null) { + throw ""; + } + + console.log("FunctionReturnedNull") +} +else { + // form the version info list with preview versions as well + let versionInfoList: VersionInfo[] = []; + ["3.0.100", "3.0.200-preview-850", "3.1.100", "3.1.101-preview-850", ""].forEach((version) => { + var temp = new VersionInfo(); + temp.version = version; + versionInfoList.push(temp); + }); + + // should return heighest non preview version in major version 3 + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.x", false).version != "3.1.100") { + throw ""; + } + + // should return heighest version (may be preview as well) in major version 3 + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.x", true).version != "3.1.101-preview-850") { + throw ""; + } + + // should return heighest non preview version in major version 3 and minor version 0 + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.0.x", false).version != "3.0.100") { + throw ""; + } + + // should return heighest version (may be preview as well) in major version 3 and minor version 0 + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.0.x", true).version != "3.0.200-preview-850") { + throw ""; + } + + // should return exact version from list + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.0.100", false).version != "3.0.100") { + throw ""; + } + + // should return exact version from list even if includePreviewVersion is false and the version spec is preview + if (versionutilities.getMatchingVersionFromList(versionInfoList, "3.0.200-preview-850", false).version != "3.0.200-preview-850") { + throw ""; + } + + console.log("FuctionReturnedCorrectVersion"); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityVersionCompareTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityVersionCompareTests.ts new file mode 100644 index 000000000000..8bb97787380c --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityVersionCompareTests.ts @@ -0,0 +1,66 @@ +'use strict'; +import * as versionutilities from "../versionutilities"; +import * as tl from 'vsts-task-lib/task'; + +if (process.env["__non_explicit__"] == "true") { + let throwCount: number = 0; + // try with non explicit version + try { + versionutilities.versionCompareFunction("2.2.104", "2.2.x"); + } + catch (ex) { + throwCount++; + } + + try { + versionutilities.versionCompareFunction("2.x", "2.2.2"); + } + catch (ex) { + throwCount++; + } + + try { + versionutilities.versionCompareFunction("", "2.2.104"); + } + catch (ex) { + throwCount++; + } + + try { + versionutilities.versionCompareFunction("3.0.3-preview-727", ""); + } + catch (ex) { + throwCount++; + } + + if (throwCount == 4) { + throw tl.loc("FunctionThrewAsExpected"); + } +} +else { + if (versionutilities.versionCompareFunction("2.2.104", "2.1.507") < 1) { + throw ""; + } + + if (versionutilities.versionCompareFunction("3.0.0-preview-1", "3.0.0-preview-0") < 1) { + throw ""; + } + + if (versionutilities.versionCompareFunction("2.2.104", "2.2.104") != 0) { + throw ""; + } + + if (versionutilities.versionCompareFunction("3.1.104-preview1-324", "3.1.104-preview1-324") != 0) { + throw ""; + } + + if (versionutilities.versionCompareFunction("2.1.400", "2.2.0") > -1) { + throw ""; + } + + if (versionutilities.versionCompareFunction("1.14.1", "1.15.0-preview-1") > -1) { + throw ""; + } + + console.log("FunctionGaveRightResult"); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/models.ts b/Tasks/DotNetCoreInstallerV1/models.ts index 55e8e1793593..6399b274d8e9 100644 --- a/Tasks/DotNetCoreInstallerV1/models.ts +++ b/Tasks/DotNetCoreInstallerV1/models.ts @@ -1,20 +1,28 @@ -import * as utils from "./versionutilities"; import * as semver from "semver"; +import * as url from "url"; + +import * as tl from 'vsts-task-lib/task'; + +import * as utils from "./versionutilities"; export class VersionInfo { public version: string; public files: VersionFilesData[]; public static getRuntimeVersion(versionInfo: VersionInfo, packageType: string): string { - if (packageType == utils.Constants.sdk) { - if (versionInfo["runtime-version"]) { - return versionInfo["runtime-version"]; - } + if (versionInfo) { + if (packageType == utils.Constants.sdk) { + if (versionInfo["runtime-version"]) { + return versionInfo["runtime-version"]; + } - tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, versionInfo.version)); - } - else { - return versionInfo.version; + tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, versionInfo.version)); + } + else { + if (versionInfo.version) { + return versionInfo.version; + } + } } return ""; @@ -31,7 +39,7 @@ export class VersionFilesData { export class Channel { constructor(channelRelease: any) { if (!channelRelease || !channelRelease["channel-version"] || !channelRelease["releases.json"]) { - throw "Object cannot be used as Channel, required properties such as channel-version, releases.json is missing. " + throw tl.loc("InvalidChannelObject"); } this.channelVersion = channelRelease["channel-version"]; @@ -39,7 +47,7 @@ export class Channel { } channelVersion: string; - releasesJsonUrl: string + releasesJsonUrl: string; } export class VersionParts { @@ -67,7 +75,7 @@ export class VersionParts { return true; } catch (ex) { - tl.loc("VersionNotAllowed", version) + throw tl.loc("VersionNotAllowed", version) } } diff --git a/Tasks/DotNetCoreInstallerV1/task.json b/Tasks/DotNetCoreInstallerV1/task.json index 55181d21121a..f1ee8d34b488 100644 --- a/Tasks/DotNetCoreInstallerV1/task.json +++ b/Tasks/DotNetCoreInstallerV1/task.json @@ -140,6 +140,8 @@ "RequiredChannelVersionForSpec": "Finding channel %s for version %s", "ErrorWhileGettingVersionFromChannel": "Failed while getting version %s from channel %s with error: %s", "ComparingInstalledFolderVersions": "Comparing if version being installed %s is greater than already installed version with folder name %s", - "ComparingInstalledFileVersions": "Comparing if version being installed %s is greater than already installed version with version complete file name %s" + "ComparingInstalledFileVersions": "Comparing if version being installed %s is greater than already installed version with version complete file name %s", + "InvalidChannelObject": "Object cannot be used as Channel, required properties such as channel-version, releases.json is missing.", + "ReleasesIndexBodyIncorrect": "Parsed releases index body is not correct. Kindly see if the releases-index section is not empty in the file." } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/task.loc.json b/Tasks/DotNetCoreInstallerV1/task.loc.json index b588b0f4efb9..c5528f9c8815 100644 --- a/Tasks/DotNetCoreInstallerV1/task.loc.json +++ b/Tasks/DotNetCoreInstallerV1/task.loc.json @@ -140,6 +140,8 @@ "RequiredChannelVersionForSpec": "ms-resource:loc.messages.RequiredChannelVersionForSpec", "ErrorWhileGettingVersionFromChannel": "ms-resource:loc.messages.ErrorWhileGettingVersionFromChannel", "ComparingInstalledFolderVersions": "ms-resource:loc.messages.ComparingInstalledFolderVersions", - "ComparingInstalledFileVersions": "ms-resource:loc.messages.ComparingInstalledFileVersions" + "ComparingInstalledFileVersions": "ms-resource:loc.messages.ComparingInstalledFileVersions", + "InvalidChannelObject": "ms-resource:loc.messages.InvalidChannelObject", + "ReleasesIndexBodyIncorrect": "ms-resource:loc.messages.ReleasesIndexBodyIncorrect" } } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts index 40d1053595ca..bbefe484d261 100644 --- a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts @@ -7,7 +7,6 @@ import * as trm from 'vsts-task-lib/toolrunner'; import httpClient = require("typed-rest-client/HttpClient"); import httpInterfaces = require("typed-rest-client/Interfaces"); -import { HttpClientResponse } from 'typed-rest-client/HttpClient'; import { VersionInfo, Channel, VersionFilesData, VersionParts } from "./models" import * as utils from "./versionutilities"; @@ -82,13 +81,13 @@ export class DotNetCoreVersionFetcher { private setReleasesIndex(): Promise { return this.httpCallbackClient.get(DotNetCoreReleasesIndexUrl) - .then((response: HttpClientResponse) => { + .then((response: httpClient.HttpClientResponse) => { return response.readBody(); }) .then((body: string) => { let parsedReleasesIndexBody = JSON.parse(body); if (!parsedReleasesIndexBody || !parsedReleasesIndexBody["releases-index"] || parsedReleasesIndexBody["releases-index"].length < 1) { - throw "Parsed releases index body is not correct." + throw tl.loc("ReleasesIndexBodyIncorrect") } parsedReleasesIndexBody["releases-index"].forEach(channelRelease => { @@ -141,7 +140,7 @@ export class DotNetCoreVersionFetcher { if (releasesJsonUrl) { return this.httpCallbackClient.get(releasesJsonUrl) - .then((response: HttpClientResponse) => { + .then((response: httpClient.HttpClientResponse) => { return response.readBody(); }) .then((body: string) => { From 100358485236ad438423d6a17976ed9435d8c6c6 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Tue, 19 Mar 2019 14:33:25 +0530 Subject: [PATCH 14/17] added l0 tests for versionfetcher getdownloadURL and resolved comments --- Tasks/DotNetCoreInstallerV1/Tests/L0.ts | 65 +++++++++++--- .../Tests/mocks/mockedModels.ts | 30 +++++++ .../versionFetcherGetDownloadUrlFailTests.ts | 90 +++++++++++++++++++ Tasks/DotNetCoreInstallerV1/versionfetcher.ts | 2 +- .../DotNetCoreInstallerV1/versioninstaller.ts | 2 +- 5 files changed, 177 insertions(+), 12 deletions(-) create mode 100644 Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts diff --git a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts index 8741e3af33f5..0fc74d07380d 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts @@ -245,20 +245,65 @@ describe('DotNetCoreInstaller', function () { }, tr, done); }); - // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if VersionFilesData doesn't contain download URL", (done) => { - // }); + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if VersionFilesData doesn't contain download URL", (done) => { + process.env["__ostype__"] = "win"; + process.env["__getmachineosfail__"] = "false"; + process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name":"winpackage.zip", "rid":"win-x64", "url": ""}]}`; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed as download URL is missing.")); + assert(tr.stdout.indexOf("DownloadUrlForMatchingOsNotFound") > 0, ("Should have thrown the error message as download URL is not present.")) + }, tr, done); + }); - // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if download information object with RID matching OS, could not be found", (done) => { - // }); + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if download information object with RID matching OS, could not be found", (done) => { + process.env["__ostype__"] = "win"; + process.env["__getmachineosfail__"] = "false"; + process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar.gz", "rid":"linux-x64", "url": ""}, {"name": "win.zip", "rid":"win-x86", "url": ""}]}`; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed as download URL is missing.")); + assert(tr.stdout.indexOf("DownloadUrlForMatchingOsNotFound") > 0, ("Should have thrown the error message as download URL is not present.")) + }, tr, done); + }); - // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if error encountered while detecting machine os", (done) => { - // }); + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if error encountered while detecting machine os", (done) => { + process.env["__ostype__"] = "win"; + process.env["__getmachineosfail__"] = "true"; + process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar.gz", "rid":"linux-x64", "url": ""}, {"name":"winpackage.zip", "rid":"win-x86", "url": ""}]}`; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed as machine os could not be detected.")); + assert(tr.stdout.indexOf("getMachinePlatformFailed") > 0, ("Should have thrown the error message as getMachineOs script execution was not successful.")) + }, tr, done); + }); - // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if zip package is not found for windows os", (done) => { - // }); + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if zip package is not found for windows os", (done) => { + process.env["__ostype__"] = "win"; + process.env["__getmachineosfail__"] = "false"; + process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "winpacakage.exe", "rid":"win-x64", "url": "https://path.to/file.exe"}, {"name": "winpacakage2.exe", "rid":"win-x86", "url": "https://path.to/file.exe"}]}`; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed as download URL is missing.")); + assert(tr.stdout.indexOf("DownloadUrlForMatchingOsNotFound") > 0, ("Should have thrown the error message as download url of zip could not be found for windows.")) + }, tr, done); + }); - // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if tar.gz package is not found for linux os", (done) => { - // }); + it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if tar.gz package is not found for non windows os", (done) => { + process.env["__ostype__"] = "osx"; + process.env["__getmachineosfail__"] = "false"; + process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar", "rid":"linux-x64", "url": "https://path.to/file.pkg"}, {"name": "osx.pkg", "rid":"osx-x64", "url": "https://path.to/file.pkg"}]}`; + let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); + tr.run(); + runValidations(() => { + assert(tr.succeeded == false, ("Should have failed as download URL is missing.")); + assert(tr.stdout.indexOf("DownloadUrlForMatchingOsNotFound") > 0, ("Should have thrown the error message as download url of tar file could not be found for mac os.")) + }, tr, done); + }); // it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should return correct download URL for matching OS", (done) => { // }); diff --git a/Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts b/Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts index e62407375453..413e019c521c 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/mocks/mockedModels.ts @@ -8,4 +8,34 @@ export class HttpClientResponse { }) } message: string = "" +} + +export class toolrunner { + constructor(toolPath, outputToReturn) { + this.toolPath = toolPath; + this.outputToReturn = outputToReturn; + } + public line (somearg) { + return this; + } + + public arg (args) { + return this; + } + + public execSync() { + if (this.outputToReturn) { + return this.outputToReturn; + } + + return { + code: 0, + error: null, + stdout: "", + stderr: "" + } + } + + private toolPath; + private outputToReturn; } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts new file mode 100644 index 000000000000..96d9b1f463ad --- /dev/null +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts @@ -0,0 +1,90 @@ +import * as tl from 'vsts-task-lib/task'; +import { toolrunner } from './mocks/mockedModels' +var mockery = require('mockery'); + +mockery.enable({ + useCleanCache: true, + warnOnReplace: false, + warnOnUnregistered: false +}); + +mockery.registerMock('typed-rest-client/HttpClient', { + HttpClient: function () { + return { + get: function (url: string, headers) { + return ""; + } + } + } +}); + +mockery.registerMock('vsts-task-lib/task', { + osType: function () { return process.env["__ostype__"]; }, + which: function (tool: string, check: boolean) { + if (tool == 'powershell') { + return "C:/Program Files/PowerShell"; + } + else if (tool.endsWith(".sh")) { + return "/temp/somefile.sh"; + } + }, + tool: function (pathToTool) { + if (process.env["__ostype__"].toLowerCase().includes("win")) { + if (process.env["__getmachineosfail__"] == "true") { + return new toolrunner(pathToTool, {code: 1, error: null, stderr: "failedWhileExecutingScript"}); + } + + return new toolrunner(pathToTool, { + code: 0, + error: null, + stderr: "", + stdout: `Primary:win-x64 + Legacy:win-x64` + }); + } + else if (process.env["__ostype__"].toLowerCase().includes("linux")) { + return new toolrunner(pathToTool, { + code: 0, + error: null, + stderr: "", + stdout: `Primary:linux-x64 + Legacy:ubuntu16.04` + }); + } + else if (process.env["__ostype__"].toLowerCase().includes("osx")) { + return new toolrunner(pathToTool, { + code: 0, + error: null, + stderr: "", + stdout: `Primary:osx-x64 + Legacy:osx-x64` + }); + } + }, + loc: function (locString, param: string[]) { return tl.loc(locString, param); }, + debug: function (message) { return tl.debug(message); }, + error: function (errorMessage) { return tl.error(errorMessage); }, + getVariable: function (variableName) { return tl.getVariable(variableName); }, + getHttpProxyConfiguration: function () { return ""; }, + setResourcePath: function (path) { return; } +}); + +mockery.registerMock('vsts-task-lib/toolrunner', { + +}) + +import { DotNetCoreVersionFetcher } from "../versionfetcher"; +import { VersionInfo } from '../models'; + +let versionFetcher = new DotNetCoreVersionFetcher(); +try { + let downloadUrl = versionFetcher.getDownloadUrl(JSON.parse(process.env["__versioninfo__"]) as VersionInfo, "sdk"); + if (downloadUrl) { + tl.setResult(tl.TaskResult.Succeeded, "succeeded"); + } + + tl.setResult(tl.TaskResult.Failed, "DownloadUrlWasNotReturned"); +} +catch (ex) { + tl.setResult(tl.TaskResult.Failed, "TestThrewException" + ex); +} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts index bbefe484d261..ec3d6c18e6d4 100644 --- a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts @@ -60,7 +60,7 @@ export class DotNetCoreVersionFetcher { osSuffixes.find((osSuffix) => { downloadPackageInfoObject = versionInfo.files.find((downloadPackageInfo: VersionFilesData) => { if (downloadPackageInfo.rid && osSuffix && downloadPackageInfo.rid.toLowerCase() == osSuffix.toLowerCase()) { - if ((osSuffix.split("-")[0] != "win" && osSuffix.split("-")[0] != "osx") || (osSuffix.split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip")) || (osSuffix.split("-")[0] == "osx" && downloadPackageInfo.name.endsWith("tar.gz"))) { + if ((osSuffix.split("-")[0] == "win" && downloadPackageInfo.name.endsWith(".zip")) || (osSuffix.split("-")[0] != "win" && downloadPackageInfo.name.endsWith("tar.gz"))) { return true; } } diff --git a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts index 6870eec1e907..b60784921015 100644 --- a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts @@ -55,7 +55,7 @@ export class VersionInstaller { // Copy files try { - if (this.isLatestInstalledVersion(version) && this.packageType == utils.Constants.sdk) { + if (this.packageType == utils.Constants.sdk && this.isLatestInstalledVersion(version)) { tl.debug(tl.loc("CopyingFilesIntoPath", this.installationPath)); var filesToBeCopied = allRootLevelEnteriesInDir.filter(path => !fs.lstatSync(path).isDirectory()); filesToBeCopied.forEach((filePath) => { From 9e6adf12e0813ff98d464da61edf72f7511f7fa2 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Tue, 19 Mar 2019 15:48:39 +0530 Subject: [PATCH 15/17] resolved comments --- Tasks/DotNetCoreInstallerV1/README.md | 6 +- Tasks/DotNetCoreInstallerV1/Tests/L0.ts | 20 ----- .../Tests/modelsGetRuntimeVersionTests.ts | 25 +++--- .../Tests/modelsValidateVersionSpecTests.ts | 90 ------------------- .../dotnetcoreinstaller.ts | 6 +- Tasks/DotNetCoreInstallerV1/models.ts | 36 ++++---- .../DotNetCoreInstallerV1/versioninstaller.ts | 2 +- 7 files changed, 33 insertions(+), 152 deletions(-) delete mode 100644 Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts diff --git a/Tasks/DotNetCoreInstallerV1/README.md b/Tasks/DotNetCoreInstallerV1/README.md index ef86a00fde1b..08adfbb168e5 100644 --- a/Tasks/DotNetCoreInstallerV1/README.md +++ b/Tasks/DotNetCoreInstallerV1/README.md @@ -18,13 +18,9 @@ The tool installer approach also allows you to decouple from the agent update cy Please report a problem at [Developer Community Forum](https://developercommunity.visualstudio.com/spaces/21/index.html) if you are facing problems in making this task work. You can also share feedback about the task like, what more functionality should be added to the task, what other tasks you would like to have, at the same place. -## Pre-requisites for the task - -The task can run on either Windows or Linux. - ### Parameters of the task -* **Package to install\*:** You can choose to install either runtime or full SDK. +* **Package to install\*:** You can choose to install either runtime or SDK. * **Version\*:** Specify version of .NET Core SDK or runtime to install. It also allows you to always get the latest version in a minor or major version. See below for examples diff --git a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts index 0fc74d07380d..71c1176ef3aa 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts @@ -89,26 +89,6 @@ describe('DotNetCoreInstaller', function () { }, tr, done); }); - it("[Models] ValidateVersionSpec should throw when version spec is not valid range or version", (done) => { - process.env["__invalid_versionspec__"] = "true"; - let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsValidateVersionSpecTests.js")); - tr.run(); - runValidations(() => { - assert(tr.succeeded == false, ("Should have failed")); - assert(tr.stdout.indexOf("FunctionThrewAsExpected") > -1, "Should have thrown for all invalid version specs."); - }, tr, done); - }); - - it("[Models] ValidateVersionSpec should return true when version spec is range or version", (done) => { - process.env["__invalid_versionspec__"] = "false"; - let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsValidateVersionSpecTests.js")); - tr.run(); - runValidations(() => { - assert(tr.succeeded == true, ("Should have passed")); - assert(tr.stdout.indexOf("VersionsValidatedSuccessfully") > -1, "Should have returned true for all valid versions specs."); - }, tr, done); - }); - it("[Models.VersionParts] constructor should throw when version fails validation", (done) => { process.env["__invalid_versionparts__"] = "true"; let tr = new ttm.MockTestRunner(path.join(__dirname, "modelsVersionPartsTests.js")); diff --git a/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts index ef5272edc760..4b421cd47f72 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts @@ -2,61 +2,56 @@ import { VersionInfo } from "../models"; import * as tl from 'vsts-task-lib/task'; - -if (VersionInfo.getRuntimeVersion(null, "") != "") { - throw ""; -} - -if (VersionInfo.getRuntimeVersion(null, "") != "") { +let versionInfo = new VersionInfo(); +if (versionInfo.getRuntimeVersion("") != "") { throw ""; } -let versionInfo = new VersionInfo(); versionInfo.version = ""; if (process.env["__sdk_runtime__"] == "true") { - if (VersionInfo.getRuntimeVersion(versionInfo, "sdk") != "") { + if (versionInfo.getRuntimeVersion("sdk") != "") { throw ""; } versionInfo.version = "2.2.100" - if (VersionInfo.getRuntimeVersion(versionInfo, "sdk") != "") { + if (versionInfo.getRuntimeVersion("sdk") != "") { throw ""; } versionInfo.version = "2.2.104"; versionInfo["runtime-version"] = "2.2.4"; - if (VersionInfo.getRuntimeVersion(versionInfo, "sdk") != "2.2.4") { + if (versionInfo.getRuntimeVersion("sdk") != "2.2.4") { throw ""; } versionInfo.version = ""; versionInfo["runtime-version"] = "2.2.4"; - if (VersionInfo.getRuntimeVersion(null, "") != "") { + if (versionInfo.getRuntimeVersion("") != "") { throw ""; } console.log(tl.loc("RuntimeVersionsReturnedForSdkAreCorrect")); } else { - if (VersionInfo.getRuntimeVersion(versionInfo, "runtime") != "") { + if (versionInfo.getRuntimeVersion("runtime") != "") { throw ""; } versionInfo.version = "2.2.100" - if (VersionInfo.getRuntimeVersion(versionInfo, "runtime") != "2.2.100") { + if (versionInfo.getRuntimeVersion("runtime") != "2.2.100") { throw ""; } versionInfo.version = "2.2.104"; versionInfo["runtime-version"] = "2.2.4"; - if (VersionInfo.getRuntimeVersion(versionInfo, "runtime") != "2.2.104") { + if (versionInfo.getRuntimeVersion("runtime") != "2.2.104") { throw ""; } versionInfo.version = ""; versionInfo["runtime-version"] = "2.2.4"; - if (VersionInfo.getRuntimeVersion(null, "") != "") { + if (versionInfo.getRuntimeVersion("") != "") { throw ""; } diff --git a/Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts deleted file mode 100644 index e095bc8fc474..000000000000 --- a/Tasks/DotNetCoreInstallerV1/Tests/modelsValidateVersionSpecTests.ts +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; -import { VersionParts } from "../models"; -import * as tl from 'vsts-task-lib/task'; - -if (process.env["__invalid_versionspec__"] == "true") { - let throwCount: number = 0; - // try with non explicit version - try { - VersionParts.ValidateVersionSpec("2a.x"); - } - catch (ex) { - throwCount++; - } - - try { - VersionParts.ValidateVersionSpec("2.2x"); - } - catch (ex) { - throwCount++; - } - - try { - VersionParts.ValidateVersionSpec("2.x.2"); - } - catch (ex) { - throwCount++; - } - - try { - VersionParts.ValidateVersionSpec("2.2."); - } - catch (ex) { - throwCount++; - } - - try { - VersionParts.ValidateVersionSpec("2.2"); - } - catch (ex) { - throwCount++; - } - - try { - VersionParts.ValidateVersionSpec(""); - } - catch (ex) { - throwCount++; - } - - try { - VersionParts.ValidateVersionSpec(".."); - } - catch (ex) { - throwCount++; - } - - try { - VersionParts.ValidateVersionSpec("2.2.2fs"); - } - catch (ex) { - throwCount++; - } - - if (throwCount == 8) { - throw tl.loc("FunctionThrewAsExpected"); - } -} -else { - if (VersionParts.ValidateVersionSpec("2.x") != true) { - throw "" - } - - if (VersionParts.ValidateVersionSpec("2.100.x") != true) { - throw "" - } - - if (VersionParts.ValidateVersionSpec("2.100.1") != true) { - throw "" - } - - if (VersionParts.ValidateVersionSpec("2.100.13-preview") != true) { - throw "" - } - - if (VersionParts.ValidateVersionSpec("2.100.14-rc1-431") != true) { - throw "" - } - - console.log("VersionsValidatedSuccessfully"); -} \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts index 0f39bfedb6f4..61c058bb763a 100644 --- a/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/dotnetcoreinstaller.ts @@ -17,12 +17,12 @@ async function run() { let includePreviewVersions: boolean = tl.getBoolInput('includePreviewVersions', false) || false; console.log(tl.loc("ToolToInstall", packageType, versionSpec)); - VersionParts.ValidateVersionSpec(versionSpec); + var versionSpecParts = new VersionParts(versionSpec); let versionFetcher = new DotNetCoreVersionFetcher(); - let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(versionSpec, packageType, includePreviewVersions); + let versionInfo: VersionInfo = await versionFetcher.getVersionInfo(versionSpecParts.versionSpec, packageType, includePreviewVersions); if (!versionInfo) { - throw tl.loc("MatchingVersionNotFound", versionSpec); + throw tl.loc("MatchingVersionNotFound", versionSpecParts.versionSpec); } let dotNetCoreInstaller = new VersionInstaller(packageType, installationPath); diff --git a/Tasks/DotNetCoreInstallerV1/models.ts b/Tasks/DotNetCoreInstallerV1/models.ts index 6399b274d8e9..a4234c48ccf8 100644 --- a/Tasks/DotNetCoreInstallerV1/models.ts +++ b/Tasks/DotNetCoreInstallerV1/models.ts @@ -9,19 +9,17 @@ export class VersionInfo { public version: string; public files: VersionFilesData[]; - public static getRuntimeVersion(versionInfo: VersionInfo, packageType: string): string { - if (versionInfo) { - if (packageType == utils.Constants.sdk) { - if (versionInfo["runtime-version"]) { - return versionInfo["runtime-version"]; - } - - tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, versionInfo.version)); + public getRuntimeVersion(packageType: string): string { + if (packageType == utils.Constants.sdk) { + if (this["runtime-version"]) { + return this["runtime-version"]; } - else { - if (versionInfo.version) { - return versionInfo.version; - } + + tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, this.version)); + } + else { + if (this.version) { + return this.version; } } @@ -46,8 +44,8 @@ export class Channel { this.releasesJsonUrl = channelRelease["releases.json"]; } - channelVersion: string; - releasesJsonUrl: string; + public channelVersion: string; + public releasesJsonUrl: string; } export class VersionParts { @@ -55,6 +53,7 @@ export class VersionParts { VersionParts.ValidateVersionSpec(version); let parts: string[] = version.split("."); + this.versionSpec = this.versionSpec; this.majorVersion = parts[0]; this.minorVersion = parts[1]; this.patchVersion = ""; @@ -63,7 +62,7 @@ export class VersionParts { } } - public static ValidateVersionSpec(version): boolean { + private static ValidateVersionSpec(version): boolean { try { let parts = version.split('.'); // validate version @@ -79,7 +78,8 @@ export class VersionParts { } } - majorVersion: string; - minorVersion: string; - patchVersion: string; + public majorVersion: string; + public minorVersion: string; + public patchVersion: string; + public versionSpec: string; } \ No newline at end of file diff --git a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts index b60784921015..3ba20e9c7b18 100644 --- a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts @@ -109,7 +109,7 @@ export class VersionInstaller { tl.writeFile(pathToVersionCompleteFile, `{ "version": "${sdkVersion}" }`); } - let runtimeVersion = VersionInfo.getRuntimeVersion(versionInfo, this.packageType); + let runtimeVersion = versionInfo.getRuntimeVersion(this.packageType); if (runtimeVersion) { pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeRuntimePath, `${runtimeVersion}.complete`); tl.writeFile(pathToVersionCompleteFile, `{ "version": "${runtimeVersion}" }`); From 299ed1ad127c4af1562b3a6504d3b7ec5bc52856 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Tue, 19 Mar 2019 16:10:19 +0530 Subject: [PATCH 16/17] resolved failing l0 tests for linux and mac due to case sensitivity --- Tasks/DotNetCoreInstallerV1/Tests/L0.ts | 10 +++++----- .../Tests/versionFetcherGetDownloadUrlFailTests.ts | 4 ---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts index 71c1176ef3aa..af3e5129fde9 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/L0.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/L0.ts @@ -228,7 +228,7 @@ describe('DotNetCoreInstaller', function () { it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if VersionFilesData doesn't contain download URL", (done) => { process.env["__ostype__"] = "win"; process.env["__getmachineosfail__"] = "false"; - process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name":"winpackage.zip", "rid":"win-x64", "url": ""}]}`; + process.env["__versioninfo__"] = `{"version":"2.2.104", "files": [{"name":"winpackage.zip", "rid":"win-x64", "url": ""}]}`; let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); tr.run(); runValidations(() => { @@ -240,7 +240,7 @@ describe('DotNetCoreInstaller', function () { it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if download information object with RID matching OS, could not be found", (done) => { process.env["__ostype__"] = "win"; process.env["__getmachineosfail__"] = "false"; - process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar.gz", "rid":"linux-x64", "url": ""}, {"name": "win.zip", "rid":"win-x86", "url": ""}]}`; + process.env["__versioninfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar.gz", "rid":"linux-x64", "url": ""}, {"name": "win.zip", "rid":"win-x86", "url": ""}]}`; let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); tr.run(); runValidations(() => { @@ -252,7 +252,7 @@ describe('DotNetCoreInstaller', function () { it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if error encountered while detecting machine os", (done) => { process.env["__ostype__"] = "win"; process.env["__getmachineosfail__"] = "true"; - process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar.gz", "rid":"linux-x64", "url": ""}, {"name":"winpackage.zip", "rid":"win-x86", "url": ""}]}`; + process.env["__versioninfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar.gz", "rid":"linux-x64", "url": ""}, {"name":"winpackage.zip", "rid":"win-x86", "url": ""}]}`; let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); tr.run(); runValidations(() => { @@ -264,7 +264,7 @@ describe('DotNetCoreInstaller', function () { it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if zip package is not found for windows os", (done) => { process.env["__ostype__"] = "win"; process.env["__getmachineosfail__"] = "false"; - process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "winpacakage.exe", "rid":"win-x64", "url": "https://path.to/file.exe"}, {"name": "winpacakage2.exe", "rid":"win-x86", "url": "https://path.to/file.exe"}]}`; + process.env["__versioninfo__"] = `{"version":"2.2.104", "files": [{"name": "winpacakage.exe", "rid":"win-x64", "url": "https://path.to/file.exe"}, {"name": "winpacakage2.exe", "rid":"win-x86", "url": "https://path.to/file.exe"}]}`; let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); tr.run(); runValidations(() => { @@ -276,7 +276,7 @@ describe('DotNetCoreInstaller', function () { it("[VersionFetcher.DotNetCoreVersionFetcher] getDownloadUrl should throw if tar.gz package is not found for non windows os", (done) => { process.env["__ostype__"] = "osx"; process.env["__getmachineosfail__"] = "false"; - process.env["__versionInfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar", "rid":"linux-x64", "url": "https://path.to/file.pkg"}, {"name": "osx.pkg", "rid":"osx-x64", "url": "https://path.to/file.pkg"}]}`; + process.env["__versioninfo__"] = `{"version":"2.2.104", "files": [{"name": "linux.tar", "rid":"linux-x64", "url": "https://path.to/file.pkg"}, {"name": "osx.pkg", "rid":"osx-x64", "url": "https://path.to/file.pkg"}]}`; let tr = new ttm.MockTestRunner(path.join(__dirname, "versionFetcherGetDownloadUrlFailTests.js")); tr.run(); runValidations(() => { diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts index 96d9b1f463ad..d4bf4eec35e2 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionFetcherGetDownloadUrlFailTests.ts @@ -69,10 +69,6 @@ mockery.registerMock('vsts-task-lib/task', { setResourcePath: function (path) { return; } }); -mockery.registerMock('vsts-task-lib/toolrunner', { - -}) - import { DotNetCoreVersionFetcher } from "../versionfetcher"; import { VersionInfo } from '../models'; From 9bcec89f8bc244af18d2b97770122a833ef5a805 Mon Sep 17 00:00:00 2001 From: Himanshu Yadav Date: Tue, 19 Mar 2019 17:41:03 +0530 Subject: [PATCH 17/17] few changes for fixing getting runtimeversion --- .../Tests/modelsGetRuntimeVersionTests.ts | 2 +- ...nUtilityGetMatchingVersionFromListTests.ts | 6 +++--- Tasks/DotNetCoreInstallerV1/models.ts | 19 ++++++++----------- Tasks/DotNetCoreInstallerV1/versionfetcher.ts | 7 ++++++- .../DotNetCoreInstallerV1/versioninstaller.ts | 2 +- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts index 4b421cd47f72..1bee4b862104 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/modelsGetRuntimeVersionTests.ts @@ -2,7 +2,7 @@ import { VersionInfo } from "../models"; import * as tl from 'vsts-task-lib/task'; -let versionInfo = new VersionInfo(); +let versionInfo = new VersionInfo(JSON.parse(`{"version":"", "files":""}`)); if (versionInfo.getRuntimeVersion("") != "") { throw ""; } diff --git a/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts index 750e1a3053f2..192b908541ef 100644 --- a/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts +++ b/Tasks/DotNetCoreInstallerV1/Tests/versionUtilityGetMatchingVersionFromListTests.ts @@ -11,14 +11,14 @@ if (process.env["__empty__"] == "true") { } // version info list with version field empty - if (versionutilities.getMatchingVersionFromList([new VersionInfo()], "2.1") != null) { + if (versionutilities.getMatchingVersionFromList([new VersionInfo(JSON.parse("{}"))], "2.1") != null) { throw ""; } // form the version info list with preview versions as well let versionInfoList: VersionInfo[] = []; ["3.0.100", "3.1.0-preview-850", ""].forEach((version) => { - var temp = new VersionInfo(); + var temp = new VersionInfo(JSON.parse(`{"version": "${version}"}`)); temp.version = version; versionInfoList.push(temp); }); @@ -50,7 +50,7 @@ else { // form the version info list with preview versions as well let versionInfoList: VersionInfo[] = []; ["3.0.100", "3.0.200-preview-850", "3.1.100", "3.1.101-preview-850", ""].forEach((version) => { - var temp = new VersionInfo(); + var temp = new VersionInfo(JSON.parse(`{"version": "${version}"}`)); temp.version = version; versionInfoList.push(temp); }); diff --git a/Tasks/DotNetCoreInstallerV1/models.ts b/Tasks/DotNetCoreInstallerV1/models.ts index a4234c48ccf8..b96dc29a8122 100644 --- a/Tasks/DotNetCoreInstallerV1/models.ts +++ b/Tasks/DotNetCoreInstallerV1/models.ts @@ -9,21 +9,18 @@ export class VersionInfo { public version: string; public files: VersionFilesData[]; + constructor(versionInfoObject: any) { + this.version = versionInfoObject.version; + this.files = versionInfoObject.files; + } + public getRuntimeVersion(packageType: string): string { if (packageType == utils.Constants.sdk) { - if (this["runtime-version"]) { - return this["runtime-version"]; - } - - tl.warning(tl.loc("runtimeVersionPropertyNotFound", packageType, this.version)); + return this["runtime-version"] || ""; } else { - if (this.version) { - return this.version; - } + return this.version || ""; } - - return ""; } } @@ -53,7 +50,7 @@ export class VersionParts { VersionParts.ValidateVersionSpec(version); let parts: string[] = version.split("."); - this.versionSpec = this.versionSpec; + this.versionSpec = version; this.majorVersion = parts[0]; this.minorVersion = parts[1]; this.patchVersion = ""; diff --git a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts index ec3d6c18e6d4..a541ff09e2b7 100644 --- a/Tasks/DotNetCoreInstallerV1/versionfetcher.ts +++ b/Tasks/DotNetCoreInstallerV1/versionfetcher.ts @@ -149,7 +149,12 @@ export class DotNetCoreVersionFetcher { let versionInfoList: VersionInfo[] = []; channelReleases.forEach((release) => { if (release && release[packageType] && release[packageType].version) { - versionInfoList.push(release[packageType]); + let versionInfo: VersionInfo = new VersionInfo(release[packageType]); + if (release[packageType]["runtime-version"]) { + versionInfo["runtime-version"] = release[packageType]["runtime-version"]; + } + + versionInfoList.push(versionInfo); } }); diff --git a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts index 3ba20e9c7b18..f39f15efa20c 100644 --- a/Tasks/DotNetCoreInstallerV1/versioninstaller.ts +++ b/Tasks/DotNetCoreInstallerV1/versioninstaller.ts @@ -114,7 +114,7 @@ export class VersionInstaller { pathToVersionCompleteFile = path.join(this.installationPath, utils.Constants.relativeRuntimePath, `${runtimeVersion}.complete`); tl.writeFile(pathToVersionCompleteFile, `{ "version": "${runtimeVersion}" }`); } - else if (this.packageType == "runtime") { + else if (this.packageType == utils.Constants.runtime) { throw tl.loc("CannotFindRuntimeVersionForCompletingInstallation", this.packageType, versionInfo.version); } }