Compare commits

..

23 Commits

Author SHA1 Message Date
9211491ffb Merge pull request #273 from actions/v-vlsafo/update-deps
Update npm dependencies
2022-02-24 18:33:48 +03:00
edfd7b3266 Update licenses 2022-02-24 18:12:33 +03:00
9744af7b74 Update dependencies 2022-02-24 18:04:55 +03:00
7016f85f93 Merge pull request #271 from vsafonkin/v-vlsafo/update-node-version
Update default runtime to node16
2022-02-24 17:29:31 +03:00
d292011f5d Update node version to v16 2022-02-24 11:16:01 +03:00
608ee757cf Merge pull request #270 from snickler/main
Updated dotnet-install scripts to latest version
2022-02-22 16:38:32 +03:00
e54e706650 Updated dotnet-install scripts to latest version 2022-02-19 17:07:00 -05:00
c20f59e04a Avoiding installing the same version multiple times (#252) 2021-12-29 14:07:42 +03:00
13b852df87 Moved checkout above setup step to align with the other samples (#256) 2021-12-28 15:37:44 +03:00
f85bcda870 Fix the Licensed workflow (#258) 2021-12-23 14:35:09 +03:00
499789684c Warn users when installing EOL .NET versions (#245) 2021-11-23 16:58:49 +03:00
76ddd67c90 Fix a space in the documentation (#248) 2021-11-23 16:56:22 +03:00
550702114f Support multiple versions in single invocation (#240) 2021-11-23 13:03:56 +03:00
e3ce4164b3 Merge pull request #238 from vsafonkin/v-vlsafo/fix-dependencies
Update dependencies and installer scripts
2021-10-13 17:24:51 +03:00
463326422f Update jest 2021-10-13 16:35:23 +03:00
547d075822 Revert jest version 2021-10-13 14:58:41 +03:00
fc9265379f Update deps with force 2021-10-13 14:50:32 +03:00
32c76e2669 Update installer scripts 2021-10-13 14:27:43 +03:00
8ca0cf75a1 Update dependencies 2021-10-13 14:20:02 +03:00
7f88dbf08f Merge pull request #231 from actions/dependabot/npm_and_yarn/tmpl-1.0.5
Bump tmpl from 1.0.4 to 1.0.5
2021-10-13 11:12:15 +03:00
af0ed6536b Bump tmpl from 1.0.4 to 1.0.5
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-13 07:14:28 +00:00
9dd9d27e57 Merge pull request #234 from IEvangelist/patch-1
Update README.md
2021-10-12 17:27:43 +03:00
44530e8569 Update README.md
Fix the README.md file to avoid the .NET CLI repo link that is now the .NET SDK repo.
2021-10-05 10:05:48 -05:00
22 changed files with 10505 additions and 3605 deletions

View File

@ -23,10 +23,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set Node.js 12.x - name: Set Node.js 16
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 16.x
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci

View File

@ -7,6 +7,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
workflow_dispatch:
jobs: jobs:
test: test:
@ -18,7 +19,7 @@ jobs:
- name: Install licensed - name: Install licensed
run: | run: |
cd $RUNNER_TEMP cd $RUNNER_TEMP
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.4.4/licensed-3.4.4-linux-x64.tar.gz
sudo tar -xzf licensed.tar.gz sudo tar -xzf licensed.tar.gz
sudo mv licensed /usr/local/bin/licensed sudo mv licensed /usr/local/bin/licensed
- run: licensed status - run: licensed status

View File

@ -21,10 +21,11 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set Node.js 12 - name: Set Node.js 16
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 16.x
cache: npm
- run: npm ci - run: npm ci
- run: npm run build - run: npm run build
- run: npm run format-check - run: npm run format-check
@ -33,6 +34,29 @@ jobs:
if: runner.os != 'windows' if: runner.os != 'windows'
run: __tests__/verify-no-unstaged-changes.sh run: __tests__/verify-no-unstaged-changes.sh
test-setup-multiple-versions:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Clear toolcache
shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
- name: Setup dotnet 2.2.402 and 3.1.404
uses: ./
with:
dotnet-version: |
2.2.402
3.1.404
3.0.x
- name: Verify dotnet
shell: pwsh
run: __tests__/verify-dotnet.ps1 2.2.402 3.1.404 '3.0'
test-setup-full-version: test-setup-full-version:
runs-on: ${{ matrix.operating-system }} runs-on: ${{ matrix.operating-system }}
strategy: strategy:

View File

@ -1,6 +1,6 @@
--- ---
name: "@actions/core" name: "@actions/core"
version: 1.2.6 version: 1.6.0
type: npm type: npm
summary: Actions core lib summary: Actions core lib
homepage: https://github.com/actions/toolkit/tree/main/packages/core homepage: https://github.com/actions/toolkit/tree/main/packages/core

View File

@ -0,0 +1,32 @@
---
name: "@actions/http-client"
version: 1.0.11
type: npm
summary: Actions Http Client
homepage: https://github.com/actions/http-client#readme
license: mit
licenses:
- sources: LICENSE
text: |
Actions Http Client for Node.js
Copyright (c) GitHub, Inc.
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.
notices: []

View File

@ -1,6 +1,6 @@
--- ---
name: node-fetch name: node-fetch
version: 2.6.1 version: 2.6.7
type: npm type: npm
summary: A light-weight module that brings window.fetch to node.js summary: A light-weight module that brings window.fetch to node.js
homepage: https://github.com/bitinn/node-fetch homepage: https://github.com/bitinn/node-fetch

30
.licenses/npm/tr46.dep.yml generated Normal file
View File

@ -0,0 +1,30 @@
---
name: tr46
version: 0.0.3
type: npm
summary: An implementation of the Unicode TR46 spec
homepage: https://github.com/Sebmaster/tr46.js#readme
license: mit
licenses:
- sources: Auto-generated MIT license text
text: |
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.
notices: []

23
.licenses/npm/webidl-conversions.dep.yml generated Normal file
View File

@ -0,0 +1,23 @@
---
name: webidl-conversions
version: 3.0.1
type: npm
summary: Implements the WebIDL algorithms for converting to and from JavaScript values
homepage:
license: bsd-2-clause
licenses:
- sources: LICENSE.md
text: |
# The BSD 2-Clause License
Copyright (c) 2014, Domenic Denicola
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. 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.
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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
notices: []

32
.licenses/npm/whatwg-url.dep.yml generated Normal file
View File

@ -0,0 +1,32 @@
---
name: whatwg-url
version: 5.0.0
type: npm
summary: An implementation of the WHATWG URL Standard's URL API and parsing machinery
homepage:
license: mit
licenses:
- sources: LICENSE.txt
text: |
The MIT License (MIT)
Copyright (c) 20152016 Sebastian Mayr
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.
notices: []

View File

@ -4,9 +4,9 @@
<a href="https://github.com/actions/setup-dotnet"><img alt="GitHub Actions status" src="https://github.com/actions/setup-dotnet/workflows/Main%20workflow/badge.svg"></a> <a href="https://github.com/actions/setup-dotnet"><img alt="GitHub Actions status" src="https://github.com/actions/setup-dotnet/workflows/Main%20workflow/badge.svg"></a>
</p> </p>
This action sets up a [dotnet core cli](https://github.com/dotnet/cli) environment for use in actions by: This action sets up a [.NET CLI](https://github.com/dotnet/sdk) environment for use in actions by:
- optionally downloading and caching a version of dotnet by SDK version and adding to PATH - optionally downloading and caching a version(s) of dotnet by SDK version(s) and adding to PATH
- registering problem matchers for error output - registering problem matchers for error output
- setting up authentication to private package sources like GitHub Packages - setting up authentication to private package sources like GitHub Packages
@ -29,7 +29,20 @@ steps:
dotnet-version: '3.1.x' # SDK Version to use; x will use the latest version of the 3.1 channel dotnet-version: '3.1.x' # SDK Version to use; x will use the latest version of the 3.1 channel
- run: dotnet build <my project> - run: dotnet build <my project>
``` ```
Multiple versions:
> Note: In case multiple versions are installed, the latest .NET version will be used by default unless another version is specified in the `global.json` file.
```yml
steps:
- uses: actions/checkout@v2
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: |
3.1.x
5.0.x
- run: dotnet build <my project>
```
Preview version: Preview version:
```yml ```yml
steps: steps:

View File

@ -32,6 +32,27 @@ describe('installer tests', () => {
} }
}, 30000); }, 30000);
it('Aquires multiple versions of dotnet', async () => {
const versions = ['2.2.207', '3.1.120'];
for (const version of versions) {
await getDotnet(version);
}
expect(fs.existsSync(path.join(toolDir, 'sdk', '2.2.207'))).toBe(true);
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.120'))).toBe(true);
if (IS_WINDOWS) {
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true);
} else {
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true);
}
expect(process.env.DOTNET_ROOT).toBeDefined;
expect(process.env.PATH).toBeDefined;
expect(process.env.DOTNET_ROOT).toBe(toolDir);
expect(process.env.PATH?.startsWith(toolDir)).toBe(true);
}, 600000);
it('Acquires version of dotnet if no matching version is installed', async () => { it('Acquires version of dotnet if no matching version is installed', async () => {
await getDotnet('3.1.201'); await getDotnet('3.1.201');
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true); expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true);
@ -126,4 +147,5 @@ function normalizeFileContents(contents: string): string {
async function getDotnet(version: string): Promise<void> { async function getDotnet(version: string): Promise<void> {
const dotnetInstaller = new installer.DotnetCoreInstaller(version); const dotnetInstaller = new installer.DotnetCoreInstaller(version);
await dotnetInstaller.installDotnet(); await dotnetInstaller.installDotnet();
installer.DotnetCoreInstaller.addToPath();
} }

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netcoreapp3.1;netcoreapp2.2</TargetFrameworks> <TargetFrameworks>netcoreapp3.1;netcoreapp3.0;netcoreapp2.2</TargetFrameworks>
<RootNamespace>sample_csproj</RootNamespace> <RootNamespace>sample_csproj</RootNamespace>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>

View File

@ -6,6 +6,8 @@ if (!$args[0])
$dotnet = Get-Command dotnet | Select-Object -First 1 | ForEach-Object { $_.Path } $dotnet = Get-Command dotnet | Select-Object -First 1 | ForEach-Object { $_.Path }
Write-Host "Found '$dotnet'" Write-Host "Found '$dotnet'"
if($args.count -eq 1)
{
$version = & $dotnet --version | Out-String | ForEach-Object { $_.Trim() } $version = & $dotnet --version | Out-String | ForEach-Object { $_.Trim() }
Write-Host "Version $version" Write-Host "Version $version"
if (-not ($version.StartsWith($args[0].ToString()))) if (-not ($version.StartsWith($args[0].ToString())))
@ -13,22 +15,24 @@ if (-not ($version.StartsWith($args[0].ToString())))
Write-Host "PATH='$env:PATH'" Write-Host "PATH='$env:PATH'"
throw "Unexpected version" throw "Unexpected version"
} }
}
if ($args[1]) if ($args[1])
{ {
# SDKs are listed on multiple lines with the path afterwards in square brackets # SDKs are listed on multiple lines with the path afterwards in square brackets
$versions = & $dotnet --list-sdks | ForEach-Object { $_.SubString(0, $_.IndexOf('[')).Trim() } $versions = & $dotnet --list-sdks | ForEach-Object { $_.SubString(0, $_.IndexOf('[')).Trim() }
Write-Host "Installed versions: $versions" Write-Host "Installed versions: $versions"
$isInstalledVersion = $false $InstalledVersionCount = 0
foreach($arg in $args){
foreach ($version in $versions) foreach ($version in $versions)
{ {
if ($version.StartsWith($args[1].ToString())) if ($version.StartsWith($arg.ToString()))
{ {
$isInstalledVersion = $true $InstalledVersionCount++
break
} }
} }
if (-not $isInstalledVersion) }
if ( $InstalledVersionCount -ne $args.Count)
{ {
Write-Host "PATH='$env:PATH'" Write-Host "PATH='$env:PATH'"
throw "Unexpected version" throw "Unexpected version"
@ -53,6 +57,13 @@ if ($args[1])
throw "Unexpected output" throw "Unexpected output"
} }
} }
if ($args[2])
{
if ($sample_output -notlike "*Test Run Successful.*Test Run Successful.*Test Run Successful.*")
{
throw "Unexpected output"
}
}
else else
{ {
if ($sample_output -notlike "*Test Run Successful.*") if ($sample_output -notlike "*Test Run Successful.*")

View File

@ -6,7 +6,7 @@ branding:
color: green color: green
inputs: inputs:
dotnet-version: dotnet-version:
description: 'Optional SDK version to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x' description: 'Optional SDK version(s) to use. If not provided, will install global.json version when available. Examples: 2.2.104, 3.1, 3.1.x'
source-url: source-url:
description: 'Optional package source for which to set up authentication. Will consult any existing NuGet.config in the root of the repo and provide a temporary NuGet.config using the NUGET_AUTH_TOKEN environment variable as a ClearTextPassword' description: 'Optional package source for which to set up authentication. Will consult any existing NuGet.config in the root of the repo and provide a temporary NuGet.config using the NUGET_AUTH_TOKEN environment variable as a ClearTextPassword'
owner: owner:
@ -17,5 +17,5 @@ inputs:
description: 'Whether prerelease versions should be matched with non-exact versions (for example 5.0.0-preview.6 being matched by 5, 5.0, 5.x or 5.0.x). Defaults to false if not provided.' description: 'Whether prerelease versions should be matched with non-exact versions (for example 5.0.0-preview.6 being matched by 5, 5.0, 5.x or 5.0.x). Defaults to false if not provided.'
required: False required: False
runs: runs:
using: 'node12' using: 'node16'
main: 'dist/index.js' main: 'dist/index.js'

3581
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -66,11 +66,13 @@
Displays diagnostics information. Displays diagnostics information.
.PARAMETER AzureFeed .PARAMETER AzureFeed
Default: https://dotnetcli.azureedge.net/dotnet Default: https://dotnetcli.azureedge.net/dotnet
This parameter typically is not changed by the user. For internal use only.
It allows changing the URL for the Azure feed used by this installer. Allows using a different storage to download SDK archives from.
This parameter is only used if $NoCdn is false.
.PARAMETER UncachedFeed .PARAMETER UncachedFeed
This parameter typically is not changed by the user. For internal use only.
It allows changing the URL for the Uncached feed used by this installer. Allows using a different storage to download SDK archives from.
This parameter is only used if $NoCdn is true.
.PARAMETER ProxyAddress .PARAMETER ProxyAddress
If set, the installer will use the proxy when making web requests If set, the installer will use the proxy when making web requests
.PARAMETER ProxyUseDefaultCredentials .PARAMETER ProxyUseDefaultCredentials
@ -104,8 +106,8 @@ param(
[switch]$SharedRuntime, [switch]$SharedRuntime,
[switch]$DryRun, [switch]$DryRun,
[switch]$NoPath, [switch]$NoPath,
[string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet", [string]$AzureFeed,
[string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet", [string]$UncachedFeed,
[string]$FeedCredential, [string]$FeedCredential,
[string]$ProxyAddress, [string]$ProxyAddress,
[switch]$ProxyUseDefaultCredentials, [switch]$ProxyUseDefaultCredentials,
@ -119,20 +121,6 @@ Set-StrictMode -Version Latest
$ErrorActionPreference="Stop" $ErrorActionPreference="Stop"
$ProgressPreference="SilentlyContinue" $ProgressPreference="SilentlyContinue"
if ($NoCdn) {
$AzureFeed = $UncachedFeed
}
$BinFolderRelativePath=""
if ($SharedRuntime -and (-not $Runtime)) {
$Runtime = "dotnet"
}
# example path with regex: shared/1.0.0-beta-12345/somepath
$VersionRegEx="/\d+\.\d+[^/]+/"
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
function Say($str) { function Say($str) {
try { try {
Write-Host "dotnet-install: $str" Write-Host "dotnet-install: $str"
@ -207,9 +195,7 @@ function Get-Machine-Architecture() {
# To get the correct architecture, we need to use PROCESSOR_ARCHITEW6432. # To get the correct architecture, we need to use PROCESSOR_ARCHITEW6432.
# PS x64 doesn't define this, so we fall back to PROCESSOR_ARCHITECTURE. # PS x64 doesn't define this, so we fall back to PROCESSOR_ARCHITECTURE.
# Possible values: amd64, x64, x86, arm64, arm # Possible values: amd64, x64, x86, arm64, arm
if( $ENV:PROCESSOR_ARCHITEW6432 -ne $null ) {
if( $ENV:PROCESSOR_ARCHITEW6432 -ne $null )
{
return $ENV:PROCESSOR_ARCHITEW6432 return $ENV:PROCESSOR_ARCHITEW6432
} }
@ -219,8 +205,11 @@ function Get-Machine-Architecture() {
function Get-CLIArchitecture-From-Architecture([string]$Architecture) { function Get-CLIArchitecture-From-Architecture([string]$Architecture) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
if ($Architecture -eq "<auto>") {
$Architecture = Get-Machine-Architecture
}
switch ($Architecture.ToLowerInvariant()) { switch ($Architecture.ToLowerInvariant()) {
{ $_ -eq "<auto>" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) }
{ ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" }
{ $_ -eq "x86" } { return "x86" } { $_ -eq "x86" } { return "x86" }
{ $_ -eq "arm" } { return "arm" } { $_ -eq "arm" } { return "arm" }
@ -229,7 +218,25 @@ function Get-CLIArchitecture-From-Architecture([string]$Architecture) {
} }
} }
function ValidateFeedCredential([string] $FeedCredential)
{
if ($Internal -and [string]::IsNullOrWhitespace($FeedCredential)) {
$message = "Provide credentials via -FeedCredential parameter."
if ($DryRun) {
Say-Warning "$message"
} else {
throw "$message"
}
}
#FeedCredential should start with "?", for it to be added to the end of the link.
#adding "?" at the beginning of the FeedCredential if needed.
if ((![string]::IsNullOrWhitespace($FeedCredential)) -and ($FeedCredential[0] -ne '?')) {
$FeedCredential = "?" + $FeedCredential
}
return $FeedCredential
}
function Get-NormalizedQuality([string]$Quality) { function Get-NormalizedQuality([string]$Quality) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
@ -282,7 +289,7 @@ function Get-NormalizedProduct([string]$Runtime) {
# Line 2: # 4-part version # Line 2: # 4-part version
# For the aspnetcore runtime (1 line): # For the aspnetcore runtime (1 line):
# Line 1: # 4-part version # Line 1: # 4-part version
function Get-Version-Info-From-Version-Text([string]$VersionText) { function Get-Version-From-LatestVersion-File-Content([string]$VersionText) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
$Data = -split $VersionText $Data = -split $VersionText
@ -321,7 +328,11 @@ function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect,
# Despite no proxy being explicitly specified, we may still be behind a default proxy # Despite no proxy being explicitly specified, we may still be behind a default proxy
$DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy; $DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy;
if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))) { if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))) {
if ($null -ne $DefaultProxy.GetProxy($Uri)) {
$ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString $ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString
} else {
$ProxyAddress = $null
}
$ProxyUseDefaultCredentials = $true $ProxyUseDefaultCredentials = $true
} }
} catch { } catch {
@ -424,21 +435,21 @@ function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect,
} }
} }
function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel) { function Get-Version-From-LatestVersion-File([string]$AzureFeed, [string]$Channel) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
$VersionFileUrl = $null $VersionFileUrl = $null
if ($Runtime -eq "dotnet") { if ($Runtime -eq "dotnet") {
$VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version" $VersionFileUrl = "$AzureFeed/Runtime/$Channel/latest.version"
} }
elseif ($Runtime -eq "aspnetcore") { elseif ($Runtime -eq "aspnetcore") {
$VersionFileUrl = "$UncachedFeed/aspnetcore/Runtime/$Channel/latest.version" $VersionFileUrl = "$AzureFeed/aspnetcore/Runtime/$Channel/latest.version"
} }
elseif ($Runtime -eq "windowsdesktop") { elseif ($Runtime -eq "windowsdesktop") {
$VersionFileUrl = "$UncachedFeed/WindowsDesktop/$Channel/latest.version" $VersionFileUrl = "$AzureFeed/WindowsDesktop/$Channel/latest.version"
} }
elseif (-not $Runtime) { elseif (-not $Runtime) {
$VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version" $VersionFileUrl = "$AzureFeed/Sdk/$Channel/latest.version"
} }
else { else {
throw "Invalid value for `$Runtime" throw "Invalid value for `$Runtime"
@ -450,7 +461,7 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel) {
$Response = GetHTTPResponse -Uri $VersionFileUrl $Response = GetHTTPResponse -Uri $VersionFileUrl
} }
catch { catch {
Say-Error "Could not resolve version information." Say-Verbose "Failed to download latest.version file."
throw throw
} }
$StringContent = $Response.Content.ReadAsStringAsync().Result $StringContent = $Response.Content.ReadAsStringAsync().Result
@ -462,7 +473,7 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel) {
default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." } default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." }
} }
$VersionInfo = Get-Version-Info-From-Version-Text $VersionText $VersionInfo = Get-Version-From-LatestVersion-File-Content $VersionText
return $VersionInfo return $VersionInfo
} }
@ -509,7 +520,7 @@ function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel,
if (-not $JSonFile) { if (-not $JSonFile) {
if ($Version.ToLowerInvariant() -eq "latest") { if ($Version.ToLowerInvariant() -eq "latest") {
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel $LatestVersionInfo = Get-Version-From-LatestVersion-File -AzureFeed $AzureFeed -Channel $Channel
return $LatestVersionInfo.Version return $LatestVersionInfo.Version
} }
else { else {
@ -722,7 +733,8 @@ function Get-Absolute-Path([string]$RelativeOrAbsolutePath) {
} }
function Get-Path-Prefix-With-Version($path) { function Get-Path-Prefix-With-Version($path) {
$match = [regex]::match($path, $VersionRegEx) # example path with regex: shared/1.0.0-beta-12345/somepath
$match = [regex]::match($path, "/\d+\.\d+[^/]+/")
if ($match.Success) { if ($match.Success) {
return $entry.FullName.Substring(0, $match.Index + $match.Length) return $entry.FullName.Substring(0, $match.Index + $match.Length)
} }
@ -736,7 +748,7 @@ function Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package([Sys
$ret = @() $ret = @()
foreach ($entry in $Zip.Entries) { foreach ($entry in $Zip.Entries) {
$dir = Get-Path-Prefix-With-Version $entry.FullName $dir = Get-Path-Prefix-With-Version $entry.FullName
if ($dir -ne $null) { if ($null -ne $dir) {
$path = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $dir) $path = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $dir)
if (-Not (Test-Path $path -PathType Container)) { if (-Not (Test-Path $path -PathType Container)) {
$ret += $dir $ret += $dir
@ -777,7 +789,7 @@ function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) {
foreach ($entry in $Zip.Entries) { foreach ($entry in $Zip.Entries) {
$PathWithVersion = Get-Path-Prefix-With-Version $entry.FullName $PathWithVersion = Get-Path-Prefix-With-Version $entry.FullName
if (($PathWithVersion -eq $null) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) { if (($null -eq $PathWithVersion) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) {
$DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName) $DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName)
$DestinationDir = Split-Path -Parent $DestinationPath $DestinationDir = Split-Path -Parent $DestinationPath
$OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath)) $OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath))
@ -789,7 +801,7 @@ function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) {
} }
} }
finally { finally {
if ($Zip -ne $null) { if ($null -ne $Zip) {
$Zip.Dispose() $Zip.Dispose()
} }
} }
@ -818,7 +830,7 @@ function DownloadFile($Source, [string]$OutPath) {
$File.Close() $File.Close()
} }
finally { finally {
if ($Stream -ne $null) { if ($null -ne $Stream) {
$Stream.Dispose() $Stream.Dispose()
} }
} }
@ -841,8 +853,8 @@ function SafeRemoveFile($Path) {
} }
} }
function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) { function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot) {
$BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath) $BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath "")
if (-Not $NoPath) { if (-Not $NoPath) {
$SuffixedBinPath = "$BinPath;" $SuffixedBinPath = "$BinPath;"
if (-Not $env:path.Contains($SuffixedBinPath)) { if (-Not $env:path.Contains($SuffixedBinPath)) {
@ -857,6 +869,36 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolde
} }
} }
function PrintDryRunOutput($Invocation, $DownloadLinks)
{
Say "Payload URLs:"
for ($linkIndex=0; $linkIndex -lt $DownloadLinks.count; $linkIndex++) {
Say "URL #$linkIndex - $($DownloadLinks[$linkIndex].type): $($DownloadLinks[$linkIndex].downloadLink)"
}
$RepeatableCommand = ".\$ScriptName -Version `"$SpecificVersion`" -InstallDir `"$InstallRoot`" -Architecture `"$CLIArchitecture`""
if ($Runtime -eq "dotnet") {
$RepeatableCommand+=" -Runtime `"dotnet`""
}
elseif ($Runtime -eq "aspnetcore") {
$RepeatableCommand+=" -Runtime `"aspnetcore`""
}
foreach ($key in $Invocation.BoundParameters.Keys) {
if (-not (@("Architecture","Channel","DryRun","InstallDir","Runtime","SharedRuntime","Version","Quality","FeedCredential") -contains $key)) {
$RepeatableCommand+=" -$key `"$($Invocation.BoundParameters[$key])`""
}
}
if ($Invocation.BoundParameters.Keys -contains "FeedCredential") {
$RepeatableCommand+=" -FeedCredential `"<feedCredential>`""
}
Say "Repeatable invocation: $RepeatableCommand"
if ($SpecificVersion -ne $EffectiveVersion)
{
Say "NOTE: Due to finding a version manifest with this runtime, it would actually install with version '$EffectiveVersion'"
}
}
function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Internal, [string]$Product, [string]$Architecture) { function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Internal, [string]$Product, [string]$Architecture) {
Say-Invocation $MyInvocation Say-Invocation $MyInvocation
@ -930,118 +972,69 @@ function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Intern
} }
Say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" function Get-AkaMsLink-And-Version([string] $NormalizedChannel, [string] $NormalizedQuality, [bool] $Internal, [string] $ProductName, [string] $Architecture) {
Say "- The SDK needs to be installed without user interaction and without admin rights." $AkaMsDownloadLink = Get-AkaMSDownloadLink -Channel $NormalizedChannel -Quality $NormalizedQuality -Internal $Internal -Product $ProductName -Architecture $Architecture
Say "- The SDK installation doesn't need to persist across multiple CI runs."
Say "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.`r`n"
if ($Internal -and [string]::IsNullOrWhitespace($FeedCredential)) {
$message = "Provide credentials via -FeedCredential parameter."
if ($DryRun) {
Say-Warning "$message"
} else {
throw "$message"
}
}
#FeedCredential should start with "?", for it to be added to the end of the link.
#adding "?" at the beginning of the FeedCredential if needed.
if ((![string]::IsNullOrWhitespace($FeedCredential)) -and ($FeedCredential[0] -ne '?')) {
$FeedCredential = "?" + $FeedCredential
}
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
$NormalizedQuality = Get-NormalizedQuality $Quality
Say-Verbose "Normalized quality: '$NormalizedQuality'"
$NormalizedChannel = Get-NormalizedChannel $Channel
Say-Verbose "Normalized channel: '$NormalizedChannel'"
$NormalizedProduct = Get-NormalizedProduct $Runtime
Say-Verbose "Normalized product: '$NormalizedProduct'"
$DownloadLink = $null
#try to get download location from aka.ms link
#not applicable when exact version is specified via command or json file
if ([string]::IsNullOrEmpty($JSonFile) -and ($Version -eq "latest")) {
$AkaMsDownloadLink = Get-AkaMSDownloadLink -Channel $NormalizedChannel -Quality $NormalizedQuality -Internal $Internal -Product $NormalizedProduct -Architecture $CLIArchitecture
if ([string]::IsNullOrEmpty($AkaMsDownloadLink)){ if ([string]::IsNullOrEmpty($AkaMsDownloadLink)){
if (-not [string]::IsNullOrEmpty($NormalizedQuality)) { if (-not [string]::IsNullOrEmpty($NormalizedQuality)) {
# if quality is specified - exit with error - there is no fallback approach # if quality is specified - exit with error - there is no fallback approach
Say-Error "Failed to locate the latest version in the channel '$NormalizedChannel' with '$NormalizedQuality' quality for '$NormalizedProduct', os: 'win', architecture: '$CLIArchitecture'." Say-Error "Failed to locate the latest version in the channel '$NormalizedChannel' with '$NormalizedQuality' quality for '$ProductName', os: 'win', architecture: '$Architecture'."
Say-Error "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support." Say-Error "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support."
throw "aka.ms link resolution failure" throw "aka.ms link resolution failure"
} }
Say-Verbose "Falling back to latest.version file approach." Say-Verbose "Falling back to latest.version file approach."
return ($null, $null, $null)
} }
else { else {
Say-Verbose "Retrieved primary named payload URL from aka.ms link: '$AkaMsDownloadLink'." Say-Verbose "Retrieved primary named payload URL from aka.ms link: '$AkaMsDownloadLink'."
$DownloadLink = $AkaMsDownloadLink
Say-Verbose "Downloading using legacy url will not be attempted." Say-Verbose "Downloading using legacy url will not be attempted."
$LegacyDownloadLink = $null
#get version from the path #get version from the path
$pathParts = $DownloadLink.Split('/') $pathParts = $AkaMsDownloadLink.Split('/')
if ($pathParts.Length -ge 2) { if ($pathParts.Length -ge 2) {
$SpecificVersion = $pathParts[$pathParts.Length - 2] $SpecificVersion = $pathParts[$pathParts.Length - 2]
Say-Verbose "Version: '$SpecificVersion'." Say-Verbose "Version: '$SpecificVersion'."
} }
else { else {
Say-Error "Failed to extract the version from download link '$DownloadLink'." Say-Error "Failed to extract the version from download link '$AkaMsDownloadLink'."
return ($null, $null, $null)
} }
#retrieve effective (product) version #retrieve effective (product) version
$EffectiveVersion = Get-Product-Version -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -PackageDownloadLink $DownloadLink $EffectiveVersion = Get-Product-Version -SpecificVersion $SpecificVersion -PackageDownloadLink $AkaMsDownloadLink
Say-Verbose "Product version: '$EffectiveVersion'." Say-Verbose "Product version: '$EffectiveVersion'."
return ($AkaMsDownloadLink, $SpecificVersion, $EffectiveVersion);
} }
} }
if ([string]::IsNullOrEmpty($DownloadLink)) { function Get-Feeds-To-Use()
$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -JSonFile $JSonFile
$DownloadLink, $EffectiveVersion = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
}
$InstallRoot = Resolve-Installation-Path $InstallDir
Say-Verbose "InstallRoot: $InstallRoot"
$ScriptName = $MyInvocation.MyCommand.Name
if ($DryRun) {
Say "Payload URLs:"
Say "Primary named payload URL: ${DownloadLink}"
if ($LegacyDownloadLink) {
Say "Legacy named payload URL: ${LegacyDownloadLink}"
}
$RepeatableCommand = ".\$ScriptName -Version `"$SpecificVersion`" -InstallDir `"$InstallRoot`" -Architecture `"$CLIArchitecture`""
if ($Runtime -eq "dotnet") {
$RepeatableCommand+=" -Runtime `"dotnet`""
}
elseif ($Runtime -eq "aspnetcore") {
$RepeatableCommand+=" -Runtime `"aspnetcore`""
}
if (-not [string]::IsNullOrEmpty($NormalizedQuality))
{ {
$RepeatableCommand+=" -Quality `"$NormalizedQuality`"" $feeds = @(
"https://dotnetcli.azureedge.net/dotnet",
"https://dotnetbuilds.azureedge.net/public"
)
if (-not [string]::IsNullOrEmpty($AzureFeed)) {
$feeds = @($AzureFeed)
} }
foreach ($key in $MyInvocation.BoundParameters.Keys) { if ($NoCdn) {
if (-not (@("Architecture","Channel","DryRun","InstallDir","Runtime","SharedRuntime","Version","Quality","FeedCredential") -contains $key)) { $feeds = @(
$RepeatableCommand+=" -$key `"$($MyInvocation.BoundParameters[$key])`"" "https://dotnetcli.blob.core.windows.net/dotnet",
"https://dotnetbuilds.blob.core.windows.net/public"
)
if (-not [string]::IsNullOrEmpty($UncachedFeed)) {
$feeds = @($UncachedFeed)
} }
} }
if ($MyInvocation.BoundParameters.Keys -contains "FeedCredential") {
$RepeatableCommand+=" -FeedCredential `"<feedCredential>`""
}
Say "Repeatable invocation: $RepeatableCommand"
if ($SpecificVersion -ne $EffectiveVersion)
{
Say "NOTE: Due to finding a version manifest with this runtime, it would actually install with version '$EffectiveVersion'"
}
return return $feeds
} }
function Resolve-AssetName-And-RelativePath([string] $Runtime) {
if ($Runtime -eq "dotnet") { if ($Runtime -eq "dotnet") {
$assetName = ".NET Core Runtime" $assetName = ".NET Core Runtime"
$dotnetPackageRelativePath = "shared\Microsoft.NETCore.App" $dotnetPackageRelativePath = "shared\Microsoft.NETCore.App"
@ -1062,20 +1055,10 @@ else {
throw "Invalid value for `$Runtime" throw "Invalid value for `$Runtime"
} }
if ($SpecificVersion -ne $EffectiveVersion) return ($assetName, $dotnetPackageRelativePath)
{
Say "Performing installation checks for effective version: $EffectiveVersion"
$SpecificVersion = $EffectiveVersion
}
# Check if the SDK version is already installed.
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
if ($isAssetInstalled) {
Say "$assetName version $SpecificVersion is already installed."
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath
return
} }
function Prepare-Install-Directory {
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
$installDrive = $((Get-Item $InstallRoot -Force).PSDrive.Name); $installDrive = $((Get-Item $InstallRoot -Force).PSDrive.Name);
@ -1087,164 +1070,223 @@ catch{
Say-Warning "Failed to check the disk space. Installation will continue, but it may fail if you do not have enough disk space." Say-Warning "Failed to check the disk space. Installation will continue, but it may fail if you do not have enough disk space."
} }
if ( ($diskInfo -ne $null) -and ($diskInfo.Free / 1MB -le 100)) { if ( ($null -ne $diskInfo) -and ($diskInfo.Free / 1MB -le 100)) {
throw "There is not enough disk space on drive ${installDrive}:" throw "There is not enough disk space on drive ${installDrive}:"
} }
}
Say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
Say "- The SDK needs to be installed without user interaction and without admin rights."
Say "- The SDK installation doesn't need to persist across multiple CI runs."
Say "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.`r`n"
if ($SharedRuntime -and (-not $Runtime)) {
$Runtime = "dotnet"
}
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
$NormalizedQuality = Get-NormalizedQuality $Quality
Say-Verbose "Normalized quality: '$NormalizedQuality'"
$NormalizedChannel = Get-NormalizedChannel $Channel
Say-Verbose "Normalized channel: '$NormalizedChannel'"
$NormalizedProduct = Get-NormalizedProduct $Runtime
Say-Verbose "Normalized product: '$NormalizedProduct'"
$FeedCredential = ValidateFeedCredential $FeedCredential
$InstallRoot = Resolve-Installation-Path $InstallDir
Say-Verbose "InstallRoot: $InstallRoot"
$ScriptName = $MyInvocation.MyCommand.Name
($assetName, $dotnetPackageRelativePath) = Resolve-AssetName-And-RelativePath -Runtime $Runtime
$feeds = Get-Feeds-To-Use
$DownloadLinks = @()
# aka.ms links can only be used if the user did not request a specific version via the command line or a global.json file.
if ([string]::IsNullOrEmpty($JSonFile) -and ($Version -eq "latest")) {
($DownloadLink, $SpecificVersion, $EffectiveVersion) = Get-AkaMsLink-And-Version $NormalizedChannel $NormalizedQuality $Internal $NormalizedProduct $CLIArchitecture
if ($null -ne $DownloadLink) {
$DownloadLinks += New-Object PSObject -Property @{downloadLink="$DownloadLink";specificVersion="$SpecificVersion";effectiveVersion="$EffectiveVersion";type='aka.ms'}
Say-Verbose "Generated aka.ms link $DownloadLink with version $EffectiveVersion"
if (-Not $DryRun) {
Say-Verbose "Checking if the version $EffectiveVersion is already installed"
if (Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $EffectiveVersion)
{
Say "$assetName with version '$EffectiveVersion' is already installed."
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot
return
}
}
}
}
# Primary and legacy links cannot be used if a quality was specified.
# If we already have an aka.ms link, no need to search the blob feeds.
if ([string]::IsNullOrEmpty($NormalizedQuality) -and 0 -eq $DownloadLinks.count)
{
foreach ($feed in $feeds) {
try {
$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $feed -Channel $Channel -Version $Version -JSonFile $JSonFile
$DownloadLink, $EffectiveVersion = Get-Download-Link -AzureFeed $feed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $feed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
$DownloadLinks += New-Object PSObject -Property @{downloadLink="$DownloadLink";specificVersion="$SpecificVersion";effectiveVersion="$EffectiveVersion";type='primary'}
Say-Verbose "Generated primary link $DownloadLink with version $EffectiveVersion"
if (-not [string]::IsNullOrEmpty($LegacyDownloadLink)) {
$DownloadLinks += New-Object PSObject -Property @{downloadLink="$LegacyDownloadLink";specificVersion="$SpecificVersion";effectiveVersion="$EffectiveVersion";type='legacy'}
Say-Verbose "Generated legacy link $LegacyDownloadLink with version $EffectiveVersion"
}
if (-Not $DryRun) {
Say-Verbose "Checking if the version $EffectiveVersion is already installed"
if (Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $EffectiveVersion)
{
Say "$assetName with version '$EffectiveVersion' is already installed."
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot
return
}
}
}
catch
{
Say-Verbose "Failed to acquire download links from feed $feed. Exception: $_"
}
}
}
if ($DownloadLinks.count -eq 0) {
throw "Failed to resolve the exact version number."
}
if ($DryRun) {
PrintDryRunOutput $MyInvocation $DownloadLinks
return
}
Prepare-Install-Directory
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) $ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
Say-Verbose "Zip path: $ZipPath" Say-Verbose "Zip path: $ZipPath"
$DownloadFailed = $false $DownloadSucceeded = $false
$DownloadedLink = $null
$ErrorMessages = @()
$PrimaryDownloadStatusCode = 0 foreach ($link in $DownloadLinks)
$LegacyDownloadStatusCode = 0 {
Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)"
$PrimaryDownloadFailedMsg = ""
$LegacyDownloadFailedMsg = ""
Say "Downloading primary link $DownloadLink"
try { try {
DownloadFile -Source $DownloadLink -OutPath $ZipPath DownloadFile -Source $link.downloadLink -OutPath $ZipPath
Say-Verbose "Download succeeded."
$DownloadSucceeded = $true
$DownloadedLink = $link
break
} }
catch { catch {
$StatusCode = $null
$ErrorMessage = $null
if ($PSItem.Exception.Data.Contains("StatusCode")) { if ($PSItem.Exception.Data.Contains("StatusCode")) {
$PrimaryDownloadStatusCode = $PSItem.Exception.Data["StatusCode"] $StatusCode = $PSItem.Exception.Data["StatusCode"]
} }
if ($PSItem.Exception.Data.Contains("ErrorMessage")) { if ($PSItem.Exception.Data.Contains("ErrorMessage")) {
$PrimaryDownloadFailedMsg = $PSItem.Exception.Data["ErrorMessage"] $ErrorMessage = $PSItem.Exception.Data["ErrorMessage"]
} else { } else {
$PrimaryDownloadFailedMsg = $PSItem.Exception.Message $ErrorMessage = $PSItem.Exception.Message
} }
if ($PrimaryDownloadStatusCode -eq 404) { Say-Verbose "Download failed with status code $StatusCode. Error message: $ErrorMessage"
Say "The resource at $DownloadLink is not available." $ErrorMessages += "Downloading from `"$($link.type)`" link has failed with error:`nUri: $($link.downloadLink)`nStatusCode: $StatusCode`nError: $ErrorMessage"
} else {
Say $PSItem.Exception.Message
} }
# This link failed. Clean up before trying the next one.
SafeRemoveFile -Path $ZipPath SafeRemoveFile -Path $ZipPath
if ($LegacyDownloadLink) {
$DownloadLink = $LegacyDownloadLink
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
Say-Verbose "Legacy zip path: $ZipPath"
Say "Downloading legacy link $DownloadLink"
try {
DownloadFile -Source $DownloadLink -OutPath $ZipPath
}
catch {
if ($PSItem.Exception.Data.Contains("StatusCode")) {
$LegacyDownloadStatusCode = $PSItem.Exception.Data["StatusCode"]
} }
if ($PSItem.Exception.Data.Contains("ErrorMessage")) { if (-not $DownloadSucceeded) {
$LegacyDownloadFailedMsg = $PSItem.Exception.Data["ErrorMessage"] foreach ($ErrorMessage in $ErrorMessages) {
} else { Say-Error $ErrorMessages
$LegacyDownloadFailedMsg = $PSItem.Exception.Message
} }
if ($LegacyDownloadStatusCode -eq 404) { throw "Could not find `"$assetName`" with version = $($DownloadLinks[0].effectiveVersion)`nRefer to: https://aka.ms/dotnet-os-lifecycle for information on .NET support"
Say "The resource at $DownloadLink is not available."
} else {
Say $PSItem.Exception.Message
} }
SafeRemoveFile -Path $ZipPath Say "Extracting the archive."
$DownloadFailed = $true
}
}
else {
$DownloadFailed = $true
}
}
if ($DownloadFailed) {
if (($PrimaryDownloadStatusCode -eq 404) -and ((-not $LegacyDownloadLink) -or ($LegacyDownloadStatusCode -eq 404))) {
throw "Could not find `"$assetName`" with version = $SpecificVersion`nRefer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
} else {
# 404-NotFound is an expected response if it goes from only one of the links, do not show that error.
# If primary path is available (not 404-NotFound) then show the primary error else show the legacy error.
if ($PrimaryDownloadStatusCode -ne 404) {
throw "Could not download `"$assetName`" with version = $SpecificVersion`r`n$PrimaryDownloadFailedMsg"
}
if (($LegacyDownloadLink) -and ($LegacyDownloadStatusCode -ne 404)) {
throw "Could not download `"$assetName`" with version = $SpecificVersion`r`n$LegacyDownloadFailedMsg"
}
throw "Could not download `"$assetName`" with version = $SpecificVersion"
}
}
Say "Extracting zip from $DownloadLink"
Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot
# Check if the SDK version is installed; if not, fail the installation. # Check if the SDK version is installed; if not, fail the installation.
$isAssetInstalled = $false $isAssetInstalled = $false
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed. # if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
if ($SpecificVersion -Match "rtm" -or $SpecificVersion -Match "servicing") { if ($DownloadedLink.effectiveVersion -Match "rtm" -or $DownloadedLink.effectiveVersion -Match "servicing") {
$ReleaseVersion = $SpecificVersion.Split("-")[0] $ReleaseVersion = $DownloadedLink.effectiveVersion.Split("-")[0]
Say-Verbose "Checking installation: version = $ReleaseVersion" Say-Verbose "Checking installation: version = $ReleaseVersion"
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $ReleaseVersion $isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $ReleaseVersion
} }
# Check if the SDK version is installed. # Check if the SDK version is installed.
if (!$isAssetInstalled) { if (!$isAssetInstalled) {
Say-Verbose "Checking installation: version = $SpecificVersion" Say-Verbose "Checking installation: version = $($DownloadedLink.effectiveVersion)"
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion $isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $DownloadedLink.effectiveVersion
} }
# Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm. # Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm.
if (!$isAssetInstalled) { if (!$isAssetInstalled) {
Say-Error "Failed to verify the version of installed `"$assetName`".`nInstallation source: $DownloadLink.`nInstallation location: $InstallRoot.`nReport the bug at https://github.com/dotnet/install-scripts/issues." Say-Error "Failed to verify the version of installed `"$assetName`".`nInstallation source: $($DownloadedLink.downloadLink).`nInstallation location: $InstallRoot.`nReport the bug at https://github.com/dotnet/install-scripts/issues."
throw "`"$assetName`" with version = $SpecificVersion failed to install with an unknown error." throw "`"$assetName`" with version = $($DownloadedLink.effectiveVersion) failed to install with an unknown error."
} }
SafeRemoveFile -Path $ZipPath SafeRemoveFile -Path $ZipPath
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot
Say "Note that the script does not resolve dependencies during installation." Say "Note that the script does not resolve dependencies during installation."
Say "To check the list of dependencies, go to https://docs.microsoft.com/dotnet/core/install/windows#dependencies" Say "To check the list of dependencies, go to https://docs.microsoft.com/dotnet/core/install/windows#dependencies"
Say "Installation finished" Say "Installation finished"
# SIG # Begin signature block # SIG # Begin signature block
# MIIjhgYJKoZIhvcNAQcCoIIjdzCCI3MCAQExDzANBglghkgBZQMEAgEFADB5Bgor # MIInoQYJKoZIhvcNAQcCoIInkjCCJ44CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDO8obeUp97UA1H # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAuo3sRWvfrJ+Bd
# qy3NSLDwxxLLlEbGxeCzMOcKVT/3eKCCDYEwggX/MIID56ADAgECAhMzAAAB32vw # sIQ2zLeO20Ij33Vb5ljtEhxAYYSEc6CCDYEwggX/MIID56ADAgECAhMzAAACUosz
# LpKnSrTQAAAAAAHfMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # qviV8znbAAAAAAJSMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjAxMjE1MjEzMTQ1WhcNMjExMjAyMjEzMTQ1WjB0MQsw # bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQC2uxlZEACjqfHkuFyoCwfL25ofI9DZWKt4wEj3JBQ48GPt1UsDv834CcoUUPMn # AQDQ5M+Ps/X7BNuv5B/0I6uoDwj0NJOo1KrVQqO7ggRXccklyTrWL4xMShjIou2I
# s/6CtPoaQ4Thy/kbOOg/zJAnrJeiMQqRe2Lsdb/NSI2gXXX9lad1/yPUDOXo4GNw # sbYnF67wXzVAq5Om4oe+LfzSDOzjcb6ms00gBo0OQaqwQ1BijyJ7NvDf80I1fW9O
# PjXq1JZi+HZV91bUr6ZjzePj1g+bepsqd/HC1XScj0fT3aAxLRykJSzExEBmU9eS # L76Kt0Wpc2zrGhzcHdb7upPrvxvSNNUvxK3sgw7YTt31410vpEp8yfBEl/hd8ZzA
# yuOwUuq+CriudQtWGMdJU650v/KmzfM46Y6lo/MCnnpvz3zEL7PMdUdwqj/nYhGG # v47DCgJ5j1zm295s1RVZHNp6MoiQFVOECm4AwK2l28i+YER1JO4IplTH44uvzX9o
# 3UVILxX7tAdMbz7LN+6WOIpT1A41rwaoOVnv+8Ua94HwhjZmu1S73yeV7RZZNxoh # RnJHaMvWzZEpozPy4jNO2DDqbcNs4zh7AWMhE1PWFVA+CHI/En5nASvCvLmuR/t8
# EegJi9YYssXa7UZUUkCCA+KnAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE # q4bc8XR8QIZJQSp+2U6m2ldNAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUOPbML8IdkNGtCfMmVPtvI6VZ8+Mw # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUNZJaEUGL2Guwt7ZOAu4efEYXedEw
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDYzMDA5MB8GA1UdIwQYMBaAFEhu # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDY3NTk3MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAnnqH # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAFkk3
# tDyYUFaVAkvAK0eqq6nhoL95SZQu3RnpZ7tdQ89QR3++7A+4hrr7V4xxmkB5BObS # uSxkTEBh1NtAl7BivIEsAWdgX1qZ+EdZMYbQKasY6IhSLXRMxF1B3OKdR9K/kccp
# 0YK+MALE02atjwWgPdpYQ68WdLGroJZHkbZdgERG+7tETFl3aKF4KpoSaGOskZXp # kvNcGl8D7YyYS4mhCUMBR+VLrg3f8PUj38A9V5aiY2/Jok7WZFOAmjPRNNGnyeg7
# TPnCaMo2PXoAMVMGpsQEQswimZq3IQ3nRQfBlJ0PoMMcN/+Pks8ZTL1BoPYsJpok # l0lTiThFqE+2aOs6+heegqAdelGgNJKRHLWRuhGKuLIw5lkgx9Ky+QvZrn/Ddi8u
# t6cql59q6CypZYIwgyJ892HpttybHKg1ZtQLUlSXccRMlugPgEcNZJagPEgPYni4 # TIgWKp+MGG8xY6PBvvjgt9jQShlnPrZ3UY8Bvwy6rynhXBaV0V0TTL0gEx7eh/K1
# b11snjRAgf0dyQ0zI9aLXqTxWUU5pCIFiPT0b2wsxzRqCtyGqpkGM8P9GazO8eao # o8Miaru6s/7FyqOLeUS4vTHh9TgBL5DtxCYurXbSBVtL1Fj44+Od/6cmC9mmvrti
# mVItCYBcJSByBx/pS0cSYwBBHAZxJODUqxSXoSGDvmTfqUJXntnWkL4okok1FiCD # yG709Y3Rd3YdJj2f3GJq7Y7KdWq0QYhatKhBeg4fxjhg0yut2g6aM1mxjNPrE48z
# Z4jpyXOQunb6egIXvkgQ7jb2uO26Ow0m8RwleDvhOMrnHsupiOPbozKroSa6paFt # 6HWCNGu9gMK5ZudldRw4a45Z06Aoktof0CqOyTErvq0YjoE4Xpa0+87T/PVUXNqf
# VSh89abUSooR8QdZciemmoFhcWkEwFg4spzvYNP4nIs193261WyTaRMZoceGun7G # 7Y+qSU7+9LtLQuMYR4w3cSPjuNusvLf9gBnch5RqM7kaDtYWDgLyB42EfsxeMqwK
# CT2Rl653uUj+F+g94c63AhzSq4khdL4HlFIP2ePv29smfUnHtGq6yYFDLnT0q/Y+ # WwA+TVi0HrWRqfSx2olbE56hJcEkMjOSKz3sRuupFCX3UroyYf52L+2iVTrda8XW
# Di3jwloF8EWkkHRtSuXlFUbTmwr/lDDgbpZiKhLS7CBTDj32I0L5i532+uHczw82 # esPG62Mnn3T8AuLfzeJFuAbfOSERx7IFZO92UPoXE1uEjL5skl1yTZB3MubgOA4F
# oZDmYmYmIUSMbZOgS65h797rj5JJ6OkeEUJoAVwwggd6MIIFYqADAgECAgphDpDS # 8KoRNhviFAEST+nG8c8uIsbZeb08SeYQMqjVEmkwggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
@ -1284,119 +1326,141 @@ Say "Installation finished"
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWzCCFVcCAQEwgZUwfjELMAkG # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZdjCCGXICAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAd9r8C6Sp0q00AAAAAAB3zAN # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAlKLM6r4lfM52wAAAAACUjAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg7EExOCvj # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgBzhh8wf+
# ZDkub0Fc7HAVivJIlz+Omt11fROkTFKR+KQwQgYKKwYBBAGCNwIBDDE0MDKgFIAS # /kA/CamFNwS1K9Nt0wsjATKS8Y66iHQTKrIwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQBPvflyU+HQEIM4XvImAK2eQp74ABDaxeWVbl21ZF0L # BgkqhkiG9w0BAQEFAASCAQAruzFwahFXWsJ9eny7iY/KyWolnqJ9+cvDD1QaJ0qJ
# cKf5GkIzdvlCoKxforXBkRIBtLxU9Sb4ff+AO3jiw2M36ZLwZQRYcn003FTR3BAY # tHlTLP8pr0GPPtitwuk+3JME7wkx80+AZXl/ocO39tdhy1Ucd6yiyV3M1Ub/Eo4D
# 3XVGdxb64vCEMUb6Dzh9Hb1lmJjyn2NHsB514ZuUez4v/UIsV9e3TV731kY6gcQV # 37L1saazNomWeeMD6oX3FboVe1Ql17MX1SscTW5QRx8ytYgUOUIbrxFybODcdVn9
# 3ridn3IKj3RMJGtPD5qxVMZohvVIy1Xiz4n/9BpBkk4HHsSuGPmBj08jWnIcI5TF # YG7mlkgsJr2lhUhTnHtq7jV/jEu6Sk9o+g15Pbu90VncsCoNerg9aEziui6/W3/g
# eXYC4LonTOFZLcsKiW4eMRaDt0fXxJjhQF8DSJX3PAxCC73YkPrJJyXAkGNHcXCg # Wvt4WhfCPanppzWVmsvTUp5MAt5cpdNBr9b8CV/alI3TGnNwC8RuWMCK6CS4963l
# 2Lyi9Yd6oV0nbJlCSLWK7jcn5lxUIgsrb+U6F8yXoNsXoYIS5TCCEuEGCisGAQQB # f4AiLZW/fgD8UQYtl+tAyYfSerpX0sDB039jymj1FkqHoYIXADCCFvwGCisGAQQB
# gjcDAwExghLRMIISzQYJKoZIhvcNAQcCoIISvjCCEroCAQMxDzANBglghkgBZQME # gjcDAwExghbsMIIW6AYJKoZIhvcNAQcCoIIW2TCCFtUCAQMxDzANBglghkgBZQME
# AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB # AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIEwFz8qgqbYKKOXyaZMOTE0/ve/rpdJjnq1eyDVG # MDEwDQYJYIZIAWUDBAIBBQAEIEcy5EvHdubbPngOS1BSZ6xt9xSMrt3OLtUyfQaT
# mWB6AgZhHpsDT9wYEzIwMjEwODIzMTUxNzA2LjAyMVowBIACAfSggdCkgc0wgcox # IyRBAgZh+unPYkgYEzIwMjIwMjA4MTAyMjE5LjM1OVowBIACAfSggdCkgc0wgcox
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p
# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg # Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg
# RVNOOjhBODItRTM0Ri05RERBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt # RVNOOkREOEMtRTMzNy0yRkFFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
# cCBTZXJ2aWNloIIOPDCCBPEwggPZoAMCAQICEzMAAAFLT7KmSNXkwlEAAAAAAUsw # cCBTZXJ2aWNloIIRVzCCBwwwggT0oAMCAQICEzMAAAGcD6ZNYdKeSygAAQAAAZww
# DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN # dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN
# MjAxMTEyMTgyNTU5WhcNMjIwMjExMTgyNTU5WjCByjELMAkGA1UEBhMCVVMxEzAR # MjExMjAyMTkwNTE5WhcNMjMwMjI4MTkwNTE5WjCByjELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg # Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg
# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046OEE4Mi1FMzRGLTlE # T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046REQ4Qy1FMzM3LTJG
# REExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G # QUUxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0G
# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQChNnpQx3YuJr/ivobPoLtpQ9egUFl8 # CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDbUioMGV1JFj+s612s02mKu23KPUNs
# THdWZ6SAKIJdtP3L24D3/d63ommmjZjCyrQm+j/1tHDAwjQGuOwYvn79ecPCQfAB # 71OjDeJGtxkTF9rSWTiuA8XgYkAAi/5+2Ff7Ck7JcKQ9H/XD1OKwg1/bH3E1qO1z
# 91JnEp/wP4BMF2SXyMf8k9R84RthIdfGHPXTWqzpCCfNWolVEcUVm8Ad/r1LrikR # 8XRy0PlpGhmyilgE7KsOvW8PIZCf243KdldgOrxrL8HKiQodOwStyT5lLWYpMsuT
# O+4KKo6slDQJKsgKApfBU/9J7Rudvhw1rEQw0Nk1BRGWjrIp7/uWoUIfR4rcl6U1 # 2fH8k8oihje4TlpWiFPaCKLnFDaAB0Ccy6vIdtHjYB1Ie3iOZPisquL+vNdCx7gO
# utOiYIonC87PPpAJQXGRsDdKnVFF4NpWvMiyeuksn5t/Otwz82sGlne/HNQpmMzi # hB8iiTmTdsU8OSUpC8tBTeTIYPzmhaxQZd4moNk6qeCJyi7fiW4fyXdHrZ3otmgx
# gR8cZ8eXEDJJNIZxov9WAHHj28gUE29D8ivAT706ihxvTv50ZY8W51uxAgMBAAGj # xa5pXz5pUUr+cEjV+cwIYBMkaY5kHM9c6dEGkgHn0ZDJvdt/54FOdSG61WwHh4+e
# ggEbMIIBFzAdBgNVHQ4EFgQUUqpqftASlue6K3LePlTTn01K68YwHwYDVR0jBBgw # vUhwvXaB4LCMZIdCt5acOfNvtDjV3CHyFOp5AU/qgAwGftHU9brv4EUwcuteEAKH
# FoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov # 46NufE20l/WjlNUh7gAvt2zKMjO4zXRxCUTh/prBQwXJiUZeFSrEXiOfkuvSlBni
# L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENB # yAYYZp5kOnaxfCKdGYjvr4QLA93vQJ6p2Ox3IHvOdCPaCr8LsKVcFpyp8MEhhJTM
# XzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0 # +1LwqHJqFDF5O1Z9mjbYvm3R9vPhkG+RDLKoTpr7mTgkaTljd9xvm94Obp8BD9Hk
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAx # 4mPi51mtgLiuN8/6aZVESVZXtvSuNkD5DnIJQerIy5jaRKW/W2rCe9ngNDJadS7R
# MC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDAN # 96GGRl7IIE37lwIDAQABo4IBNjCCATIwHQYDVR0OBBYEFLtpCWdTXY5dtddkspy+
# BgkqhkiG9w0BAQsFAAOCAQEAFtq51Zc/O1AfJK4tEB2Nr8bGEVD5qQ8l8gXIQMrM # oxjCA/qyMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRY
# ZYtddHH+cGiqgF/4GmvmPfl5FAYh+gf/8Yd3q4/iD2+K4LtJbs/3v6mpyBl1mQ4v # MFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p
# usK65dAypWmiT1W3FiXjsmCIkjSDDsKLFBYH5yGFnNFOEMgL+O7u4osH42f80nc2 # Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEF
# WdnZV6+OvW035XPV6ZttUBfFWHdIbUkdOG1O2n4yJm10OfacItZ08fzgMMqE+f/S # BQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# TgVWNCHbR2EYqTWayrGP69jMwtVD9BGGTWti1XjpvE6yKdO8H9nuRi3L+C6jYntf # a2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAo
# aEmBTbnTFEV+kRx1CNcpSb9os86CAUehZU1aRzQ6CQ/pjzCCBnEwggRZoAMCAQIC # MSkuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZI
# CmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD # hvcNAQELBQADggIBAKcAKqYjGEczTWMs9z0m7Yo23sgqVF3LyK6gOMz7TCHAJN+F
# vbvZkQ53VkvrZUd1sE6a9ToGldcJnOmBc6iuhBlpvdN1BLBRO8QSTD1433VTj4XC
# Qd737wND1+eqKG3BdjrzbDksEwfG4v57PgrN/T7s7PkEjUGXfIgFQQkr8TQi+/HZ
# Z9kRlNccgeACqlfb4uGPxn5sdhQPoxdMvmC3qG9DONJ5UsS9KtO+bey+ohUTDa9L
# vEToc4Qzy5fuHj2H1JsmCaKG78nXpfWpwBLBxZYSpfml29onN8jcG7KD8nGSS/76
# PDlb2GMQsvv+Ra0JgL6FtGRGgYmHCpM6zVrf4V/a+SoHcC+tcdGYk2aKU5KOlv+f
# FE3n024V+z54tDAKR9z78rejdCBWqfvy5cBUQ9c5+3unHD08BEp7qP2rgpoD856v
# NDgEwO77n7EWT76nl/IyrbK2kjbHLzUMphFpXKnV1fYWJI2+E/0LHvXFGGqF4OvM
# BRxbrJVn03T2Dy5db6s5TzJzSaQvCrXYqA4HKvstQWkqkpvBHTX8M09+/vyRbVXN
# xrPdeXw6oD2Q4DksykCFfn8N2j2LdixE9wG5iilv69dzsvHIN/g9A9+thkAQCVb9
# DUSOTaMIGgsOqDYFjhT6ze9lkhHHGv/EEIkxj9l6S4hqUQyWerFkaUWDXcnZMIIH
# cTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCB
# iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMp
# TWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEw
# OTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UE
# CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
# b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ
# Q0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIh
# C3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNx
# WuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFc
# UTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAc
# nVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUo
# veO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyzi
# YrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9
# fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdH
# GO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7X
# KHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiE
# R9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/
# eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3
# FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAd
# BgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEE
# AYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMI
# MBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMB
# Af8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1Ud
# HwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3By
# b2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQRO
# MEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2Vy
# dHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4IC
# AQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pk
# bHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gng
# ugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3
# lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHC
# gRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6
# MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEU
# BHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvsh
# VGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+
# fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrp
# NPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHI
# qzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAs4wggI3AgEBMIH4
# oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUw
# IwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1U
# aGFsZXMgVFNTIEVTTjpERDhDLUUzMzctMkZBRTElMCMGA1UEAxMcTWljcm9zb2Z0
# IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAzdlp6t3ws/bnErbm
# 9c0M+9dvU0CggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN
# BgkqhkiG9w0BAQUFAAIFAOWsqGYwIhgPMjAyMjAyMDgxNjI5MjZaGA8yMDIyMDIw
# OTE2MjkyNlowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA5ayoZgIBADAKAgEAAgIi
# 7QIB/zAHAgEAAgITmjAKAgUA5a355gIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor
# BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUA
# A4GBAKFiWA9Ov0L2rGOdPitNu60BAeztCagpqKBsGnKaaSmjA/XcSXrtIvcUBBsw
# WlflwqnKvPDv3ihqUXsxY84IZZaMecGWzN1mXLh00VftiZuzoLMDlSEtvzmxeWYg
# 4nFHTR5oMqxy06auAM08mVl3P4MywHz4Yp21OIs2KSWQg3DSMYIEDTCCBAkCAQEw
# gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAGcD6ZNYdKeSygA
# AQAAAZwwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B
# CRABBDAvBgkqhkiG9w0BCQQxIgQg8oNFH9aqIpzxu29p4VzI2Hh6Hzv2T5HQOlhP
# W5ksqHkwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCA3D0WFII0syjoRd/Xe
# EIG0WUIKzzuy6P6hORrb0nqmvDCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIxMzY1NVoXDTI1MDcwMTIx # IFBDQSAyMDEwAhMzAAABnA+mTWHSnksoAAEAAAGcMCIEIOSl7GUcmDL8AU+F0I3A
# NDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # iZQESHSkml1QPlOc3M8uqdF0MA0GCSqGSIb3DQEBCwUABIICAHV226l2xxnkjTdh
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG # Q6wi7u8betBvFNfYYn5cXwy+NoU30JjQ3ynnmNSB+TQVlmcthi8duP8dud+NU5xc
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggEiMA0GCSqGSIb3 # +1jBTcJTHjWk/TDZUYpB/xNqsgUTJ8fnebVZhioPJhmFJMeQztT4NTD1ZbeJWO4O
# DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX9fp/aZRrdFQQ1aUKAIKF # EABDpRqyns2eQptCrKcPIypjvdDeYfkwjgnUEyyaTZRHPZ2kNOLY6kO9feKfntFW
# ++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkTjnxhMFmxMEQP8WCIhFRD # 8YUIaas2IzI5GcGm+kw1efHveG0WvUpeGuFKsTUA6Jb18mOyamafu32ftD5t5LXV
# DNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG8lhHhjKEHnRhZ5FfgVSx # +GMgnaJLgdogAAGwK0GiB47YNIvPlKD6bGnyTR3KNYheI1GI38w0knOecCC4NW0k
# z5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGKr0tkiVBisV39dx898Fd1 # 21qROWJdnkKLKTtBX344yTnJbbKoIPzGgyWCzSINS2SD4JHzgTu8dsmMMJWwcEZh
# rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6Kgox8NpOBpG2iAg16Hgc # BLyrzmd/vWrjUFQFXVf6RZmJJVvF28s7LWrpXPVTR8Al75j8KqyZKou4fZvyaHtx
# sOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEFTyJNAgMBAAGjggHmMIIB # S6K0jIqavLWqWd4wvx9seCtA0Pz1GWrBZADIRHG8d8cFoY95Z99z84NM81qXB246
# 4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6XIoxkPNDe3xGG8UzaFqF # IsxU2iW+96zMJriMNEKaLHzlgFoWsoXLDQhuQItjwIvzwmwygwx0MxqoFYm+lDWG
# bVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud # 8/KtSh47aZicAlwqNVGy3MZHDnX69kysQsrWoe2wDhJ3eHJ4zRL2WHVagz26L7xF
# EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYD # oSkLphLv0GiFseJhPvXGQPypnyN8
# VR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwv
# cHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEB
# BE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j
# ZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwgaAGA1UdIAEB/wSBlTCB
# kjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQe
# MiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQA
# LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/gXEDPZ2joSFvs+umzPUx
# vs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtUVwgrUYJEEvu5U4zM9GAS
# inbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9Wj8c8pl5SpFSAK84Dxf1
# L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9BOFwnzJKJ/1Vry/+tuWO
# M7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOdeyFtw5yjojz6f32WapB4
# pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1JeVk7Pf0v35jWSUPei45
# V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4TtxCd9ddJgiCGHasFAeb73x
# 4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5u+zGy9iCtHLNHfS4hQEe
# gPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKn
# QqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp
# 3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvT
# X4/edIhJEqGCAs4wggI3AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP
# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4QTgyLUUzNEYtOURE
# QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG
# BSsOAwIaAxUAkToz97fseHxNOUSQ5O/bBVSF+e6ggYMwgYCkfjB8MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg
# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOTNtrcwIhgPMjAy
# MTA4MjMxMzU1MDNaGA8yMDIxMDgyNDEzNTUwM1owdzA9BgorBgEEAYRZCgQBMS8w
# LTAKAgUA5M22twIBADAKAgEAAgIcfAIB/zAHAgEAAgIQOTAKAgUA5M8INwIBADA2
# BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIB
# AAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBADrUnASEIEovjIFdqxhyYsyiBSfNeD7e
# W4qeRl1B4DTAY8Z/U1SpnK8yy7r6oZn0D8og+QJmnWEnCPqNXAreyg8tlFyTF1TV
# K6uUlslIY4WCmrAECIFua/DuksTerny66SBw4aSEeQHtGiynnR87WcdqItBJxxRA
# pElXzs8QzC0EMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
# IDIwMTACEzMAAAFLT7KmSNXkwlEAAAAAAUswDQYJYIZIAWUDBAIBBQCgggFKMBoG
# CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQg87M/Jiqh
# MlaXNWAIAn7CM9CZw6QCPgBx3voUSIH6+qUwgfoGCyqGSIb3DQEJEAIvMYHqMIHn
# MIHkMIG9BCBr9u6EInnsZYEts/Fj/rIFv0YZW1ynhXKOP2hVPUU5IzCBmDCBgKR+
# MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT
# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABS0+ypkjV5MJRAAAA
# AAFLMCIEIGs9Mn51TUGRleeUO5lQCRHZSu0G/8Ir92l3NgMGq1/GMA0GCSqGSIb3
# DQEBCwUABIIBAA1oBIiM3guh89/Pvwwcn4hdZGGBsMk56MRMvOir8XQM0Je/rSwP
# P11S2VwYUMmBjfFX1QK7r280k3k9xcDWW79ZC4Kn2UsV7jxuUwFHgdVlgDNjg6QL
# unGuwFX5lStgNevwUH9DotoASXxgtwNNmtZNDB4NYVCxQLS7RtVSbxP+xFYXbokG
# G4DFVHBr3CGPga3OduE/YUBpxIRxtiDF/9WHo0tJEdS95tfdnsyaGo8eHNzyfTdS
# kjrNsAlqpJRT0Va/ooBXCV7Uny7PlCkRIQRTSJDy/kSXpsL22CTEHw6mU0jEU99k
# OL4uwu+aVnolWFlpbiJjQxBqfT3plBLIg88=
# SIG # End signature block # SIG # End signature block

View File

@ -135,6 +135,31 @@ get_legacy_os_name_from_platform() {
return 1 return 1
} }
get_legacy_os_name() {
eval $invocation
local uname=$(uname)
if [ "$uname" = "Darwin" ]; then
echo "osx"
return 0
elif [ -n "$runtime_id" ]; then
echo $(get_legacy_os_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}")
return 0
else
if [ -e /etc/os-release ]; then
. /etc/os-release
os=$(get_legacy_os_name_from_platform "$ID${VERSION_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: UName = $uname"
return 1
}
get_linux_platform_name() { get_linux_platform_name() {
eval $invocation eval $invocation
@ -174,8 +199,8 @@ get_current_os_name() {
echo "freebsd" echo "freebsd"
return 0 return 0
elif [ "$uname" = "Linux" ]; then elif [ "$uname" = "Linux" ]; then
local linux_platform_name local linux_platform_name=""
linux_platform_name="$(get_linux_platform_name)" || { echo "linux" && return 0 ; } linux_platform_name="$(get_linux_platform_name)" || true
if [ "$linux_platform_name" = "rhel.6" ]; then if [ "$linux_platform_name" = "rhel.6" ]; then
echo $linux_platform_name echo $linux_platform_name
@ -196,39 +221,13 @@ get_current_os_name() {
return 1 return 1
} }
get_legacy_os_name() {
eval $invocation
local uname=$(uname)
if [ "$uname" = "Darwin" ]; then
echo "osx"
return 0
elif [ -n "$runtime_id" ]; then
echo $(get_legacy_os_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}")
return 0
else
if [ -e /etc/os-release ]; then
. /etc/os-release
os=$(get_legacy_os_name_from_platform "$ID${VERSION_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: UName = $uname"
return 1
}
machine_has() { machine_has() {
eval $invocation eval $invocation
hash "$1" > /dev/null 2>&1 command -v "$1" > /dev/null 2>&1
return $? return $?
} }
check_min_reqs() { check_min_reqs() {
local hasMinimum=false local hasMinimum=false
if machine_has "curl"; then if machine_has "curl"; then
@ -321,11 +320,13 @@ get_normalized_architecture_from_architecture() {
eval $invocation eval $invocation
local architecture="$(to_lowercase "$1")" local architecture="$(to_lowercase "$1")"
case "$architecture" in
\<auto\>) if [[ $architecture == \<auto\> ]]; then
echo "$(get_normalized_architecture_from_architecture "$(get_machine_architecture)")" echo "$(get_machine_architecture)"
return 0 return 0
;; fi
case "$architecture" in
amd64|x64) amd64|x64)
echo "x64" echo "x64"
return 0 return 0
@ -425,6 +426,7 @@ get_normalized_channel() {
get_normalized_product() { get_normalized_product() {
eval $invocation eval $invocation
local product=""
local runtime="$(to_lowercase "$1")" local runtime="$(to_lowercase "$1")"
if [[ "$runtime" == "dotnet" ]]; then if [[ "$runtime" == "dotnet" ]]; then
product="dotnet-runtime" product="dotnet-runtime"
@ -446,7 +448,7 @@ get_normalized_product() {
# args: # args:
# version_text - stdin # version_text - stdin
get_version_from_version_info() { get_version_from_latestversion_file_content() {
eval $invocation eval $invocation
cat | tail -n 1 | sed 's/\r$//' cat | tail -n 1 | sed 's/\r$//'
@ -478,7 +480,7 @@ is_dotnet_package_installed() {
# azure_feed - $1 # azure_feed - $1
# channel - $2 # channel - $2
# normalized_architecture - $3 # normalized_architecture - $3
get_latest_version_info() { get_version_from_latestversion_file() {
eval $invocation eval $invocation
local azure_feed="$1" local azure_feed="$1"
@ -487,24 +489,24 @@ get_latest_version_info() {
local version_file_url=null local version_file_url=null
if [[ "$runtime" == "dotnet" ]]; then if [[ "$runtime" == "dotnet" ]]; then
version_file_url="$uncached_feed/Runtime/$channel/latest.version" version_file_url="$azure_feed/Runtime/$channel/latest.version"
elif [[ "$runtime" == "aspnetcore" ]]; then elif [[ "$runtime" == "aspnetcore" ]]; then
version_file_url="$uncached_feed/aspnetcore/Runtime/$channel/latest.version" version_file_url="$azure_feed/aspnetcore/Runtime/$channel/latest.version"
elif [ -z "$runtime" ]; then elif [ -z "$runtime" ]; then
version_file_url="$uncached_feed/Sdk/$channel/latest.version" version_file_url="$azure_feed/Sdk/$channel/latest.version"
else else
say_err "Invalid value for \$runtime" say_err "Invalid value for \$runtime"
return 1 return 1
fi fi
say_verbose "get_latest_version_info: latest url: $version_file_url" say_verbose "get_version_from_latestversion_file: latest url: $version_file_url"
download "$version_file_url" download "$version_file_url" || return $?
return $? return 0
} }
# args: # args:
# json_file - $1 # json_file - $1
parse_jsonfile_for_version() { parse_globaljson_file_for_version() {
eval $invocation eval $invocation
local json_file="$1" local json_file="$1"
@ -560,9 +562,9 @@ get_specific_version_from_version() {
if [ -z "$json_file" ]; then if [ -z "$json_file" ]; then
if [[ "$version" == "latest" ]]; then if [[ "$version" == "latest" ]]; then
local version_info local version_info
version_info="$(get_latest_version_info "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1 version_info="$(get_version_from_latestversion_file "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
say_verbose "get_specific_version_from_version: version_info=$version_info" say_verbose "get_specific_version_from_version: version_info=$version_info"
echo "$version_info" | get_version_from_version_info echo "$version_info" | get_version_from_latestversion_file_content
return 0 return 0
else else
echo "$version" echo "$version"
@ -570,7 +572,7 @@ get_specific_version_from_version() {
fi fi
else else
local version_info local version_info
version_info="$(parse_jsonfile_for_version "$json_file")" || return 1 version_info="$(parse_globaljson_file_for_version "$json_file")" || return 1
echo "$version_info" echo "$version_info"
return 0 return 0
fi fi
@ -635,14 +637,14 @@ get_specific_product_version() {
if machine_has "curl" if machine_has "curl"
then then
specific_product_version=$(curl -s --fail "${download_link}${feed_credential}") specific_product_version=$(curl -s --fail "${download_link}${feed_credential}" 2>&1)
if [ $? = 0 ]; then if [ $? = 0 ]; then
echo "${specific_product_version//[$'\t\r\n']}" echo "${specific_product_version//[$'\t\r\n']}"
return 0 return 0
fi fi
elif machine_has "wget" elif machine_has "wget"
then then
specific_product_version=$(wget -qO- "${download_link}${feed_credential}") specific_product_version=$(wget -qO- "${download_link}${feed_credential}" 2>&1)
if [ $? = 0 ]; then if [ $? = 0 ]; then
echo "${specific_product_version//[$'\t\r\n']}" echo "${specific_product_version//[$'\t\r\n']}"
return 0 return 0
@ -907,7 +909,7 @@ get_http_header_curl() {
fi fi
curl_options="-I -sSL --retry 5 --retry-delay 2 --connect-timeout 15 " curl_options="-I -sSL --retry 5 --retry-delay 2 --connect-timeout 15 "
curl $curl_options "$remote_path_with_credential" || return 1 curl $curl_options "$remote_path_with_credential" 2>&1 || return 1
return 0 return 0
} }
@ -918,15 +920,26 @@ get_http_header_wget() {
eval $invocation eval $invocation
local remote_path="$1" local remote_path="$1"
local disable_feed_credential="$2" local disable_feed_credential="$2"
local wget_options="-q -S --spider --tries 5 "
# Store options that aren't supported on all wget implementations separately.
local wget_options_extra="--waitretry 2 --connect-timeout 15 "
local wget_result=''
remote_path_with_credential="$remote_path" remote_path_with_credential="$remote_path"
if [ "$disable_feed_credential" = false ]; then if [ "$disable_feed_credential" = false ]; then
remote_path_with_credential+="$feed_credential" remote_path_with_credential+="$feed_credential"
fi fi
wget_options="-q -S --spider --tries 5 --waitretry 2 --connect-timeout 15 " wget $wget_options $wget_options_extra "$remote_path_with_credential" 2>&1
wget $wget_options "$remote_path_with_credential" 2>&1 || return 1 wget_result=$?
return 0
if [[ $wget_result == 2 ]]; then
# Parsing of the command has failed. Exclude potentially unrecognized options and retry.
wget $wget_options "$remote_path_with_credential" 2>&1
return $?
fi
return $wget_result
} }
# args: # args:
@ -988,9 +1001,9 @@ downloadcurl() {
local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs " local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs "
local failed=false local failed=false
if [ -z "$out_path" ]; then if [ -z "$out_path" ]; then
curl $curl_options "$remote_path_with_credential" || failed=true curl $curl_options "$remote_path_with_credential" 2>&1 || failed=true
else else
curl $curl_options -o "$out_path" "$remote_path_with_credential" || failed=true curl $curl_options -o "$out_path" "$remote_path_with_credential" 2>&1 || failed=true
fi fi
if [ "$failed" = true ]; then if [ "$failed" = true ]; then
local disable_feed_credential=false local disable_feed_credential=false
@ -1016,14 +1029,31 @@ downloadwget() {
local out_path="${2:-}" local out_path="${2:-}"
# Append feed_credential as late as possible before calling wget to avoid logging feed_credential # Append feed_credential as late as possible before calling wget to avoid logging feed_credential
local remote_path_with_credential="${remote_path}${feed_credential}" local remote_path_with_credential="${remote_path}${feed_credential}"
local wget_options="--tries 20 --waitretry 2 --connect-timeout 15 " local wget_options="--tries 20 "
local failed=false # Store options that aren't supported on all wget implementations separately.
local wget_options_extra="--waitretry 2 --connect-timeout 15 "
local wget_result=''
if [ -z "$out_path" ]; then if [ -z "$out_path" ]; then
wget -q $wget_options -O - "$remote_path_with_credential" || failed=true wget -q $wget_options $wget_options_extra -O - "$remote_path_with_credential" 2>&1
wget_result=$?
else else
wget $wget_options -O "$out_path" "$remote_path_with_credential" || failed=true wget $wget_options $wget_options_extra -O "$out_path" "$remote_path_with_credential" 2>&1
wget_result=$?
fi fi
if [ "$failed" = true ]; then
if [[ $wget_result == 2 ]]; then
# Parsing of the command has failed. Exclude potentially unrecognized options and retry.
if [ -z "$out_path" ]; then
wget -q $wget_options -O - "$remote_path_with_credential" 2>&1
wget_result=$?
else
wget $wget_options -O "$out_path" "$remote_path_with_credential" 2>&1
wget_result=$?
fi
fi
if [[ $wget_result != 0 ]]; then
local disable_feed_credential=false local disable_feed_credential=false
local response=$(get_http_header_wget $remote_path $disable_feed_credential) local response=$(get_http_header_wget $remote_path $disable_feed_credential)
http_code=$( echo "$response" | awk '/^ HTTP/{print $2}' | tail -1 ) http_code=$( echo "$response" | awk '/^ HTTP/{print $2}' | tail -1 )
@ -1034,6 +1064,7 @@ downloadwget() {
say_verbose "$download_error_msg" say_verbose "$download_error_msg"
return 1 return 1
fi fi
return 0 return 0
} }
@ -1090,11 +1121,197 @@ get_download_link_from_aka_ms() {
fi fi
} }
get_feeds_to_use()
{
feeds=(
"https://dotnetcli.azureedge.net/dotnet"
"https://dotnetbuilds.azureedge.net/public"
)
if [[ -n "$azure_feed" ]]; then
feeds=("$azure_feed")
fi
if [[ "$no_cdn" == "true" ]]; then
feeds=(
"https://dotnetcli.blob.core.windows.net/dotnet"
"https://dotnetbuilds.blob.core.windows.net/public"
)
if [[ -n "$uncached_feed" ]]; then
feeds=("$uncached_feed")
fi
fi
}
# THIS FUNCTION MAY EXIT (if the determined version is already installed).
generate_download_links() {
download_links=()
specific_versions=()
effective_versions=()
link_types=()
# If generate_akams_links returns false, no fallback to old links. Just terminate.
# This function may also 'exit' (if the determined version is already installed).
generate_akams_links || return
# Check other feeds only if we haven't been able to find an aka.ms link.
if [[ "${#download_links[@]}" -lt 1 ]]; then
for feed in ${feeds[@]}
do
# generate_regular_links may also 'exit' (if the determined version is already installed).
generate_regular_links $feed || return
done
fi
if [[ "${#download_links[@]}" -eq 0 ]]; then
say_err "Failed to resolve the exact version number."
return 1
fi
say_verbose "Generated ${#download_links[@]} links."
for link_index in ${!download_links[@]}
do
say_verbose "Link $link_index: ${link_types[$link_index]}, ${effective_versions[$link_index]}, ${download_links[$link_index]}"
done
}
# THIS FUNCTION MAY EXIT (if the determined version is already installed).
generate_akams_links() {
local valid_aka_ms_link=true;
normalized_version="$(to_lowercase "$version")"
if [[ -n "$json_file" || "$normalized_version" != "latest" ]]; then
# aka.ms links are not needed when exact version is specified via command or json file
return
fi
get_download_link_from_aka_ms || valid_aka_ms_link=false
if [[ "$valid_aka_ms_link" == true ]]; then
say_verbose "Retrieved primary payload URL from aka.ms link: '$aka_ms_download_link'."
say_verbose "Downloading using legacy url will not be attempted."
download_link=$aka_ms_download_link
#get version from the path
IFS='/'
read -ra pathElems <<< "$download_link"
count=${#pathElems[@]}
specific_version="${pathElems[count-2]}"
unset IFS;
say_verbose "Version: '$specific_version'."
#Retrieve effective version
effective_version="$(get_specific_product_version "$azure_feed" "$specific_version" "$download_link")"
# Add link info to arrays
download_links+=($download_link)
specific_versions+=($specific_version)
effective_versions+=($effective_version)
link_types+=("aka.ms")
# Check if the SDK version is already installed.
if [[ "$dry_run" != true ]] && is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
say "$asset_name with version '$effective_version' is already installed."
exit 0
fi
return 0
fi
# if quality is specified - exit with error - there is no fallback approach
if [ ! -z "$normalized_quality" ]; then
say_err "Failed to locate the latest version in the channel '$normalized_channel' with '$normalized_quality' quality for '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support."
return 1
fi
say_verbose "Falling back to latest.version file approach."
}
# THIS FUNCTION MAY EXIT (if the determined version is already installed)
# args:
# feed - $1
generate_regular_links() {
local feed="$1"
local valid_legacy_download_link=true
specific_version=$(get_specific_version_from_version "$feed" "$channel" "$normalized_architecture" "$version" "$json_file") || specific_version='0'
if [[ "$specific_version" == '0' ]]; then
say_verbose "Failed to resolve the specific version number using feed '$feed'"
return
fi
effective_version="$(get_specific_product_version "$feed" "$specific_version")"
say_verbose "specific_version=$specific_version"
download_link="$(construct_download_link "$feed" "$channel" "$normalized_architecture" "$specific_version" "$normalized_os")"
say_verbose "Constructed primary named payload URL: $download_link"
# Add link info to arrays
download_links+=($download_link)
specific_versions+=($specific_version)
effective_versions+=($effective_version)
link_types+=("primary")
legacy_download_link="$(construct_legacy_download_link "$feed" "$channel" "$normalized_architecture" "$specific_version")" || valid_legacy_download_link=false
if [ "$valid_legacy_download_link" = true ]; then
say_verbose "Constructed legacy named payload URL: $legacy_download_link"
download_links+=($legacy_download_link)
specific_versions+=($specific_version)
effective_versions+=($effective_version)
link_types+=("legacy")
else
legacy_download_link=""
say_verbose "Cound not construct a legacy_download_link; omitting..."
fi
# Check if the SDK version is already installed.
if [[ "$dry_run" != true ]] && is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
say "$asset_name with version '$effective_version' is already installed."
exit 0
fi
}
print_dry_run() {
say "Payload URLs:"
for link_index in "${!download_links[@]}"
do
say "URL #$link_index - ${link_types[$link_index]}: ${download_links[$link_index]}"
done
resolved_version=${specific_versions[0]}
repeatable_command="./$script_name --version "\""$resolved_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\"""
if [ ! -z "$normalized_quality" ]; then
repeatable_command+=" --quality "\""$normalized_quality"\"""
fi
if [[ "$runtime" == "dotnet" ]]; then
repeatable_command+=" --runtime "\""dotnet"\"""
elif [[ "$runtime" == "aspnetcore" ]]; then
repeatable_command+=" --runtime "\""aspnetcore"\"""
fi
repeatable_command+="$non_dynamic_parameters"
if [ -n "$feed_credential" ]; then
repeatable_command+=" --feed-credential "\""<feed_credential>"\"""
fi
say "Repeatable invocation: $repeatable_command"
}
calculate_vars() { calculate_vars() {
eval $invocation eval $invocation
valid_legacy_download_link=true
#normalize input variables script_name=$(basename "$0")
normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")" normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
say_verbose "Normalized architecture: '$normalized_architecture'." say_verbose "Normalized architecture: '$normalized_architecture'."
normalized_os="$(get_normalized_os "$user_defined_os")" normalized_os="$(get_normalized_os "$user_defined_os")"
@ -1105,76 +1322,8 @@ calculate_vars() {
say_verbose "Normalized channel: '$normalized_channel'." say_verbose "Normalized channel: '$normalized_channel'."
normalized_product="$(get_normalized_product "$runtime")" normalized_product="$(get_normalized_product "$runtime")"
say_verbose "Normalized product: '$normalized_product'." say_verbose "Normalized product: '$normalized_product'."
#try to get download location from aka.ms link
#not applicable when exact version is specified via command or json file
normalized_version="$(to_lowercase "$version")"
if [[ -z "$json_file" && "$normalized_version" == "latest" ]]; then
valid_aka_ms_link=true;
get_download_link_from_aka_ms || valid_aka_ms_link=false
if [ "$valid_aka_ms_link" == false ]; then
# if quality is specified - exit with error - there is no fallback approach
if [ ! -z "$normalized_quality" ]; then
say_err "Failed to locate the latest version in the channel '$normalized_channel' with '$normalized_quality' quality for '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support."
return 1
fi
say_verbose "Falling back to latest.version file approach."
else
say_verbose "Retrieved primary payload URL from aka.ms link: '$aka_ms_download_link'."
download_link=$aka_ms_download_link
say_verbose "Downloading using legacy url will not be attempted."
valid_legacy_download_link=false
#get version from the path
IFS='/'
read -ra pathElems <<< "$download_link"
count=${#pathElems[@]}
specific_version="${pathElems[count-2]}"
unset IFS;
say_verbose "Version: '$specific_version'."
#Retrieve product specific version
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version" "$download_link")"
say_verbose "Product specific version: '$specific_product_version'."
install_root="$(resolve_installation_path "$install_dir")" install_root="$(resolve_installation_path "$install_dir")"
say_verbose "InstallRoot: '$install_root'." say_verbose "InstallRoot: '$install_root'."
return
fi
fi
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")"
specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version")"
say_verbose "specific_version=$specific_version"
if [ -z "$specific_version" ]; then
say_err "Could not resolve version information."
return 1
fi
download_link="$(construct_download_link "$azure_feed" "$channel" "$normalized_architecture" "$specific_version" "$normalized_os")"
say_verbose "Constructed primary named payload URL: $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 "Constructed legacy named payload URL: $legacy_download_link"
else
say_verbose "Cound not construct a legacy_download_link; omitting..."
fi
install_root="$(resolve_installation_path "$install_dir")"
say_verbose "InstallRoot: $install_root"
}
install_dotnet() {
eval $invocation
local download_failed=false
local asset_name=''
local asset_relative_path=''
if [[ "$runtime" == "dotnet" ]]; then if [[ "$runtime" == "dotnet" ]]; then
asset_relative_path="shared/Microsoft.NETCore.App" asset_relative_path="shared/Microsoft.NETCore.App"
@ -1185,84 +1334,52 @@ install_dotnet() {
elif [ -z "$runtime" ]; then elif [ -z "$runtime" ]; then
asset_relative_path="sdk" asset_relative_path="sdk"
asset_name=".NET Core SDK" asset_name=".NET Core SDK"
else
say_err "Invalid value for \$runtime"
return 1
fi fi
# Check if the SDK version is already installed. get_feeds_to_use
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then }
say "$asset_name version $specific_version is already installed."
return 0 install_dotnet() {
fi eval $invocation
local download_failed=false
local download_completed=false
mkdir -p "$install_root" mkdir -p "$install_root"
zip_path="$(mktemp "$temporary_file_template")" zip_path="$(mktemp "$temporary_file_template")"
say_verbose "Zip path: $zip_path" say_verbose "Zip path: $zip_path"
for link_index in "${!download_links[@]}"
do
download_link="${download_links[$link_index]}"
specific_version="${specific_versions[$link_index]}"
effective_version="${effective_versions[$link_index]}"
link_type="${link_types[$link_index]}"
# Failures are normal in the non-legacy case for ultimately legacy downloads. say "Attempting to download using $link_type link $download_link"
# Do not output to stderr, since output to stderr is considered an error.
say "Downloading primary link $download_link"
# The download function will set variables $http_code and $download_error_msg in case of failure. # The download function will set variables $http_code and $download_error_msg in case of failure.
download "$download_link" "$zip_path" 2>&1 || download_failed=true
# if the download fails, download the legacy_download_link
if [ "$download_failed" = true ]; then
primary_path_http_code="$http_code"; primary_path_download_error_msg="$download_error_msg"
case $primary_path_http_code in
404)
say "The resource at $download_link is not available."
;;
*)
say "$primary_path_download_error_msg"
;;
esac
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
if [ "$valid_legacy_download_link" = true ]; then
download_failed=false download_failed=false
download_link="$legacy_download_link"
zip_path="$(mktemp "$temporary_file_template")"
say_verbose "Legacy zip path: $zip_path"
say "Downloading legacy link $download_link"
# The download function will set variables $http_code and $download_error_msg in case of failure.
download "$download_link" "$zip_path" 2>&1 || download_failed=true download "$download_link" "$zip_path" 2>&1 || download_failed=true
if [ "$download_failed" = true ]; then if [ "$download_failed" = true ]; then
legacy_path_http_code="$http_code"; legacy_path_download_error_msg="$download_error_msg" case $http_code in
case $legacy_path_http_code in
404) 404)
say "The resource at $download_link is not available." say "The resource at $link_type link '$download_link' is not available."
;; ;;
*) *)
say "$legacy_path_download_error_msg" say "Failed to download $link_type link '$download_link': $download_error_msg"
;; ;;
esac esac
rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed" rm -f "$zip_path" 2>&1 && say_verbose "Temporary zip file $zip_path was removed"
else
download_completed=true
break
fi fi
fi done
fi
if [ "$download_failed" = true ]; then if [[ "$download_completed" == false ]]; then
if [[ "$primary_path_http_code" = "404" && ( "$valid_legacy_download_link" = false || "$legacy_path_http_code" = "404") ]]; then
say_err "Could not find \`$asset_name\` with version = $specific_version" say_err "Could not find \`$asset_name\` with version = $specific_version"
say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support" say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
else
say_err "Could not download: \`$asset_name\` with version = $specific_version"
# 404-NotFound is an expected response if it goes from only one of the links, do not show that error.
# If primary path is available (not 404-NotFound) then show the primary error else show the legacy error.
if [ "$primary_path_http_code" != "404" ]; then
say_err "$primary_path_download_error_msg"
return 1
fi
if [[ "$valid_legacy_download_link" = true && "$legacy_path_http_code" != "404" ]]; then
say_err "$legacy_path_download_error_msg"
return 1
fi
fi
return 1 return 1
fi fi
@ -1283,14 +1400,14 @@ install_dotnet() {
fi fi
# Check if the standard SDK version is installed. # Check if the standard SDK version is installed.
say_verbose "Checking installation: version = $specific_product_version" say_verbose "Checking installation: version = $effective_version"
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_product_version"; then if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
return 0 return 0
fi fi
# Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm. # Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm.
say_err "Failed to verify the version of installed \`$asset_name\`.\nInstallation source: $download_link.\nInstallation location: $install_root.\nReport the bug at https://github.com/dotnet/install-scripts/issues." say_err "Failed to verify the version of installed \`$asset_name\`.\nInstallation source: $download_link.\nInstallation location: $install_root.\nReport the bug at https://github.com/dotnet/install-scripts/issues."
say_err "\`$asset_name\` with version = $specific_product_version failed to install with an unknown error." say_err "\`$asset_name\` with version = $effective_version failed to install with an error."
return 1 return 1
} }
@ -1308,8 +1425,8 @@ architecture="<auto>"
dry_run=false dry_run=false
no_path=false no_path=false
no_cdn=false no_cdn=false
azure_feed="https://dotnetcli.azureedge.net/dotnet" azure_feed=""
uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet" uncached_feed=""
feed_credential="" feed_credential=""
verbose=false verbose=false
runtime="" runtime=""
@ -1434,7 +1551,7 @@ do
echo " - 3-part version in a format A.B.Cxx - represents a specific SDK release" echo " - 3-part version in a format A.B.Cxx - represents a specific SDK release"
echo " examples: 5.0.1xx, 5.0.2xx." echo " examples: 5.0.1xx, 5.0.2xx."
echo " Supported since 5.0 release" echo " Supported since 5.0 release"
echo " Note: The version parameter overrides the channel parameter when any version other than `latest` is used." echo " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used."
echo " -v,--version <VERSION> Use specific VERSION, Defaults to \`$version\`." echo " -v,--version <VERSION> Use specific VERSION, Defaults to \`$version\`."
echo " -Version" echo " -Version"
echo " Possible values:" echo " Possible values:"
@ -1447,7 +1564,7 @@ do
echo " Works only in combination with channel. Not applicable for current and LTS channels and will be ignored if those channels are used." echo " Works only in combination with channel. Not applicable for current and LTS channels and will be ignored if those channels are used."
echo " For SDK use channel in A.B.Cxx format. Using quality for SDK together with channel in A.B format is not supported." echo " For SDK use channel in A.B.Cxx format. Using quality for SDK together with channel in A.B format is not supported."
echo " Supported since 5.0 release." echo " Supported since 5.0 release."
echo " Note: The version parameter overrides the channel parameter when any version other than `latest` is used, and therefore overrides the quality." echo " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used, and therefore overrides the quality."
echo " --internal,-Internal Download internal builds. Requires providing credentials via --feed-credential parameter." echo " --internal,-Internal Download internal builds. Requires providing credentials via --feed-credential parameter."
echo " --feed-credential <FEEDCREDENTIAL> Token to access Azure feed. Used as a query string to append to the Azure feed." echo " --feed-credential <FEEDCREDENTIAL> Token to access Azure feed. Used as a query string to append to the Azure feed."
echo " -FeedCredential This parameter typically is not specified." echo " -FeedCredential This parameter typically is not specified."
@ -1469,8 +1586,12 @@ do
echo " --dry-run,-DryRun Do not perform installation. Display download link." echo " --dry-run,-DryRun Do not perform installation. Display download link."
echo " --no-path, -NoPath Do not set PATH for the current process." echo " --no-path, -NoPath Do not set PATH for the current process."
echo " --verbose,-Verbose Display diagnostics information." 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 " --azure-feed,-AzureFeed For internal use only."
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user." echo " Allows using a different storage to download SDK archives from."
echo " This parameter is only used if --no-cdn is false."
echo " --uncached-feed,-UncachedFeed For internal use only."
echo " Allows using a different storage to download SDK archives from."
echo " This parameter is only used if --no-cdn is true."
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable." echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
echo " -SkipNonVersionedFiles" echo " -SkipNonVersionedFiles"
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly." echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
@ -1478,14 +1599,6 @@ do
echo " Note: global.json must have a value for 'SDK:Version'" echo " Note: global.json must have a value for 'SDK:Version'"
echo " -?,--?,-h,--help,-Help Shows this help message" echo " -?,--?,-h,--help,-Help Shows this help message"
echo "" echo ""
echo "Obsolete parameters:"
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
echo " This parameter is obsolete and may be removed in a future version of this script."
echo " Installs just the shared runtime bits, not the entire SDK."
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
echo " -RuntimeId" The parameter is obsolete and may be removed in a future version of this script. Should be used only for versions below 2.1.
echo " For primary links to override OS or/and architecture, use --os and --architecture option instead."
echo ""
echo "Install Location:" echo "Install Location:"
echo " Location is chosen in following order:" echo " Location is chosen in following order:"
echo " - --install-dir option" echo " - --install-dir option"
@ -1502,10 +1615,6 @@ do
shift shift
done done
if [ "$no_cdn" = true ]; then
azure_feed="$uncached_feed"
fi
say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:" say "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
say "- The SDK needs to be installed without user interaction and without admin rights." say "- The SDK needs to be installed without user interaction and without admin rights."
say "- The SDK installation doesn't need to persist across multiple CI runs." say "- The SDK installation doesn't need to persist across multiple CI runs."
@ -1523,33 +1632,11 @@ fi
check_min_reqs check_min_reqs
calculate_vars calculate_vars
script_name=$(basename "$0") # generate_regular_links call below will 'exit' if the determined version is already installed.
generate_download_links
if [ "$dry_run" = true ]; then if [[ "$dry_run" = true ]]; then
say "Payload URLs:" print_dry_run
say "Primary named payload URL: ${download_link}"
if [ "$valid_legacy_download_link" = true ]; then
say "Legacy named payload URL: ${legacy_download_link}"
fi
repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\"""
if [ ! -z "$normalized_quality" ]; then
repeatable_command+=" --quality "\""$normalized_quality"\"""
fi
if [[ "$runtime" == "dotnet" ]]; then
repeatable_command+=" --runtime "\""dotnet"\"""
elif [[ "$runtime" == "aspnetcore" ]]; then
repeatable_command+=" --runtime "\""aspnetcore"\"""
fi
repeatable_command+="$non_dynamic_parameters"
if [ -n "$feed_credential" ]; then
repeatable_command+=" --feed-credential "\""<feed_credential>"\"""
fi
say "Repeatable invocation: $repeatable_command"
exit 0 exit 0
fi fi

8804
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.6.0",
"@actions/exec": "^1.0.4", "@actions/exec": "^1.0.4",
"@actions/github": "^1.1.0", "@actions/github": "^1.1.0",
"@actions/http-client": "^1.0.8", "@actions/http-client": "^1.0.8",
@ -40,15 +40,15 @@
"xmlbuilder": "^13.0.2" "xmlbuilder": "^13.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^25.2.3", "@types/jest": "^27.0.2",
"@types/node": "^12.12.62", "@types/node": "^16.11.25",
"@types/semver": "^6.2.2", "@types/semver": "^6.2.2",
"@zeit/ncc": "^0.21.1", "@zeit/ncc": "^0.21.1",
"husky": "^4.3.0", "husky": "^7.0.2",
"jest": "^26.4.2", "jest": "^27.2.5",
"jest-circus": "^26.4.2", "jest-circus": "^27.2.5",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"ts-jest": "^26.4.0", "ts-jest": "^27.0.5",
"typescript": "^3.9.7", "typescript": "^3.9.7",
"wget-improved": "^3.2.1" "wget-improved": "^3.2.1"
}, },

View File

@ -165,6 +165,12 @@ export class DotnetCoreInstaller {
}); });
} }
if (resultCode != 0) {
throw new Error(`Failed to install dotnet ${resultCode}. ${output}`);
}
}
static addToPath() {
if (process.env['DOTNET_INSTALL_DIR']) { if (process.env['DOTNET_INSTALL_DIR']) {
core.addPath(process.env['DOTNET_INSTALL_DIR']); core.addPath(process.env['DOTNET_INSTALL_DIR']);
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']); core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
@ -189,10 +195,6 @@ export class DotnetCoreInstaller {
} }
console.log(process.env['PATH']); console.log(process.env['PATH']);
if (resultCode != 0) {
throw new Error(`Failed to install dotnet ${resultCode}. ${output}`);
}
} }
// versionInfo - versionInfo of the SDK/Runtime // versionInfo - versionInfo of the SDK/Runtime
@ -283,7 +285,14 @@ export class DotnetCoreInstaller {
); );
} }
return releasesInfo[0]['releases.json']; const releaseInfo = releasesInfo[0];
if (releaseInfo['support-phase'] === 'eol') {
core.warning(
`${releaseInfo['product']} ${releaseInfo['channel-version']} is no longer supported and will not receive security updates in the future. Please refer to https://aka.ms/dotnet-core-support for more information about the .NET support policy.`
);
}
return releaseInfo['releases.json'];
} }
private version: string; private version: string;

View File

@ -13,27 +13,30 @@ export async function run() {
// If a valid version still can't be identified, nothing will be installed. // If a valid version still can't be identified, nothing will be installed.
// Proxy, auth, (etc) are still set up, even if no version is identified // Proxy, auth, (etc) are still set up, even if no version is identified
// //
let version = core.getInput('dotnet-version'); let versions = core.getMultilineInput('dotnet-version');
if (!version) { if (!versions.length) {
// Try to fall back to global.json // Try to fall back to global.json
core.debug('No version found, trying to find version from global.json'); core.debug('No version found, trying to find version from global.json');
const globalJsonPath = path.join(process.cwd(), 'global.json'); const globalJsonPath = path.join(process.cwd(), 'global.json');
if (fs.existsSync(globalJsonPath)) { if (fs.existsSync(globalJsonPath)) {
version = getVersionFromGlobalJson(globalJsonPath); versions.push(getVersionFromGlobalJson(globalJsonPath));
} }
} }
if (version) { if (versions.length) {
const includePrerelease: boolean = const includePrerelease: boolean =
(core.getInput('include-prerelease') || 'false').toLowerCase() === (core.getInput('include-prerelease') || 'false').toLowerCase() ===
'true'; 'true';
let dotnetInstaller!: installer.DotnetCoreInstaller;
const dotnetInstaller = new installer.DotnetCoreInstaller( for (const version of new Set<string>(versions)) {
dotnetInstaller = new installer.DotnetCoreInstaller(
version, version,
includePrerelease includePrerelease
); );
await dotnetInstaller.installDotnet(); await dotnetInstaller.installDotnet();
} }
installer.DotnetCoreInstaller.addToPath();
}
const sourceUrl: string = core.getInput('source-url'); const sourceUrl: string = core.getInput('source-url');
const configFile: string = core.getInput('config-file'); const configFile: string = core.getInput('config-file');