mirror of
https://github.com/actions/setup-dotnet.git
synced 2025-01-19 06:41:44 +07:00
new cdn url changes
This commit is contained in:
parent
a351d9ea84
commit
94bfe42e69
599
externals/install-dotnet.ps1
vendored
599
externals/install-dotnet.ps1
vendored
@ -9,20 +9,27 @@
|
||||
.DESCRIPTION
|
||||
Installs dotnet cli. If dotnet installation already exists in the given directory
|
||||
it will update it only if the requested version differs from the one already installed.
|
||||
|
||||
Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:
|
||||
- The SDK needs to be installed without user interaction and without admin rights.
|
||||
- The SDK installation doesn't need to persist across multiple CI runs.
|
||||
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.
|
||||
|
||||
.PARAMETER Channel
|
||||
Default: LTS
|
||||
Download from the Channel specified. Possible values:
|
||||
- Current - most current release
|
||||
- LTS - most current supported release
|
||||
- STS - the most recent Standard Term Support release
|
||||
- LTS - the most recent Long Term Support release
|
||||
- 2-part version in a format A.B - represents a specific release
|
||||
examples: 2.0, 1.0
|
||||
- 3-part version in a format A.B.Cxx - represents a specific SDK release
|
||||
examples: 5.0.1xx, 5.0.2xx
|
||||
Supported since 5.0 release
|
||||
Warning: Value "Current" is deprecated for the Channel parameter. Use "STS" instead.
|
||||
Note: The version parameter overrides the channel parameter when any version other than 'latest' is used.
|
||||
.PARAMETER Quality
|
||||
Download the latest build of specified quality in the channel. The possible values are: daily, signed, validated, preview, GA.
|
||||
Works only in combination with channel. Not applicable for current and LTS channels and will be ignored if those channels are used.
|
||||
Works only in combination with channel. Not applicable for STS and LTS channels and will be ignored if those channels are used.
|
||||
For SDK use channel in A.B.Cxx format: using quality together with channel in A.B format is not supported.
|
||||
Supported since 5.0 release.
|
||||
Note: The version parameter overrides the channel parameter when any version other than 'latest' is used, and therefore overrides the quality.
|
||||
@ -91,16 +98,26 @@
|
||||
.PARAMETER DownloadTimeout
|
||||
Determines timeout duration in seconds for dowloading of the SDK file
|
||||
Default: 1200 seconds (20 minutes)
|
||||
.PARAMETER KeepZip
|
||||
If set, downloaded file is kept
|
||||
.PARAMETER ZipPath
|
||||
Use that path to store installer, generated by default
|
||||
.EXAMPLE
|
||||
dotnet-install.ps1 -Version 7.0.401
|
||||
Installs the .NET SDK version 7.0.401
|
||||
.EXAMPLE
|
||||
dotnet-install.ps1 -Channel 8.0 -Quality GA
|
||||
Installs the latest GA (general availability) version of the .NET 8.0 SDK
|
||||
#>
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
[string]$Channel="LTS",
|
||||
[string]$Channel = "LTS",
|
||||
[string]$Quality,
|
||||
[string]$Version="Latest",
|
||||
[string]$Version = "Latest",
|
||||
[switch]$Internal,
|
||||
[string]$JSonFile,
|
||||
[Alias('i')][string]$InstallDir="<auto>",
|
||||
[string]$Architecture="<auto>",
|
||||
[Alias('i')][string]$InstallDir = "<auto>",
|
||||
[string]$Architecture = "<auto>",
|
||||
[string]$Runtime,
|
||||
[Obsolete("This parameter may be removed in a future version of this script. The recommended alternative is '-Runtime dotnet'.")]
|
||||
[switch]$SharedRuntime,
|
||||
@ -111,15 +128,18 @@ param(
|
||||
[string]$FeedCredential,
|
||||
[string]$ProxyAddress,
|
||||
[switch]$ProxyUseDefaultCredentials,
|
||||
[string[]]$ProxyBypassList=@(),
|
||||
[string[]]$ProxyBypassList = @(),
|
||||
[switch]$SkipNonVersionedFiles,
|
||||
[switch]$NoCdn,
|
||||
[int]$DownloadTimeout=1200
|
||||
[int]$DownloadTimeout = 1200,
|
||||
[switch]$KeepZip,
|
||||
[string]$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()),
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference="Stop"
|
||||
$ProgressPreference="SilentlyContinue"
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
function Say($str) {
|
||||
try {
|
||||
@ -163,6 +183,29 @@ function Say-Verbose($str) {
|
||||
}
|
||||
}
|
||||
|
||||
function Measure-Action($name, $block) {
|
||||
$time = Measure-Command $block
|
||||
$totalSeconds = $time.TotalSeconds
|
||||
Say-Verbose "Action '$name' took $totalSeconds seconds"
|
||||
}
|
||||
|
||||
function Get-Remote-File-Size($zipUri) {
|
||||
try {
|
||||
$response = Invoke-WebRequest -Uri $zipUri -Method Head
|
||||
$fileSize = $response.Headers["Content-Length"]
|
||||
if ((![string]::IsNullOrEmpty($fileSize))) {
|
||||
Say "Remote file $zipUri size is $fileSize bytes."
|
||||
|
||||
return $fileSize
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Say-Verbose "Content-Length header was not extracted for $zipUri."
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Say-Invocation($Invocation) {
|
||||
$command = $Invocation.MyCommand;
|
||||
$args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ")
|
||||
@ -200,14 +243,13 @@ function Get-Machine-Architecture() {
|
||||
# To get the correct architecture, we need to use PROCESSOR_ARCHITEW6432.
|
||||
# PS x64 doesn't define this, so we fall back to PROCESSOR_ARCHITECTURE.
|
||||
# Possible values: amd64, x64, x86, arm64, arm
|
||||
if( $ENV:PROCESSOR_ARCHITEW6432 -ne $null ) {
|
||||
if ( $ENV:PROCESSOR_ARCHITEW6432 -ne $null ) {
|
||||
return $ENV:PROCESSOR_ARCHITEW6432
|
||||
}
|
||||
|
||||
try {
|
||||
if( ((Get-CimInstance -ClassName CIM_OperatingSystem).OSArchitecture) -like "ARM*") {
|
||||
if( [Environment]::Is64BitOperatingSystem )
|
||||
{
|
||||
if ( ((Get-CimInstance -ClassName CIM_OperatingSystem).OSArchitecture) -like "ARM*") {
|
||||
if ( [Environment]::Is64BitOperatingSystem ) {
|
||||
return "arm64"
|
||||
}
|
||||
return "arm"
|
||||
@ -236,13 +278,13 @@ function Get-CLIArchitecture-From-Architecture([string]$Architecture) {
|
||||
}
|
||||
}
|
||||
|
||||
function ValidateFeedCredential([string] $FeedCredential)
|
||||
{
|
||||
function ValidateFeedCredential([string] $FeedCredential) {
|
||||
if ($Internal -and [string]::IsNullOrWhitespace($FeedCredential)) {
|
||||
$message = "Provide credentials via -FeedCredential parameter."
|
||||
if ($DryRun) {
|
||||
Say-Warning "$message"
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw "$message"
|
||||
}
|
||||
}
|
||||
@ -277,13 +319,18 @@ function Get-NormalizedChannel([string]$Channel) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if ($Channel.Contains("Current")) {
|
||||
Say-Warning 'Value "Current" is deprecated for -Channel option. Use "STS" instead.'
|
||||
}
|
||||
|
||||
if ($Channel.StartsWith('release/')) {
|
||||
Say-Warning 'Using branch name with -Channel option is no longer supported with newer releases. Use -Quality option with a channel in X.Y format instead, such as "-Channel 5.0 -Quality Daily."'
|
||||
}
|
||||
|
||||
switch ($Channel) {
|
||||
{ $_ -eq "lts" } { return "LTS" }
|
||||
{ $_ -eq "current" } { return "current" }
|
||||
{ $_ -eq "sts" } { return "STS" }
|
||||
{ $_ -eq "current" } { return "STS" }
|
||||
default { return $Channel.ToLowerInvariant() }
|
||||
}
|
||||
}
|
||||
@ -329,8 +376,7 @@ function Load-Assembly([string] $Assembly) {
|
||||
}
|
||||
}
|
||||
|
||||
function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect, [bool]$DisableFeedCredential)
|
||||
{
|
||||
function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect, [bool]$DisableFeedCredential) {
|
||||
$cts = New-Object System.Threading.CancellationTokenSource
|
||||
|
||||
$downloadScript = {
|
||||
@ -341,19 +387,21 @@ function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect,
|
||||
# HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet.
|
||||
Load-Assembly -Assembly System.Net.Http
|
||||
|
||||
if(-not $ProxyAddress) {
|
||||
if (-not $ProxyAddress) {
|
||||
try {
|
||||
# Despite no proxy being explicitly specified, we may still be behind a default proxy
|
||||
$DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy;
|
||||
if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))) {
|
||||
if ($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))) {
|
||||
if ($null -ne $DefaultProxy.GetProxy($Uri)) {
|
||||
$ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$ProxyAddress = $null
|
||||
}
|
||||
$ProxyUseDefaultCredentials = $true
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
catch {
|
||||
# Eat the exception and move forward as the above code is an attempt
|
||||
# at resolving the DefaultProxy that may not have been a problem.
|
||||
$ProxyAddress = $null
|
||||
@ -362,15 +410,14 @@ function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect,
|
||||
}
|
||||
|
||||
$HttpClientHandler = New-Object System.Net.Http.HttpClientHandler
|
||||
if($ProxyAddress) {
|
||||
if ($ProxyAddress) {
|
||||
$HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{
|
||||
Address=$ProxyAddress;
|
||||
UseDefaultCredentials=$ProxyUseDefaultCredentials;
|
||||
Address = $ProxyAddress;
|
||||
UseDefaultCredentials = $ProxyUseDefaultCredentials;
|
||||
BypassList = $ProxyBypassList;
|
||||
}
|
||||
}
|
||||
if ($DisableRedirect)
|
||||
{
|
||||
if ($DisableRedirect) {
|
||||
$HttpClientHandler.AllowAutoRedirect = $false
|
||||
}
|
||||
$HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler
|
||||
@ -379,7 +426,7 @@ function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect,
|
||||
# Defaulting to 20 minutes allows it to work over much slower connections.
|
||||
$HttpClient.Timeout = New-TimeSpan -Seconds $DownloadTimeout
|
||||
|
||||
if ($HeaderOnly){
|
||||
if ($HeaderOnly) {
|
||||
$completionOption = [System.Net.Http.HttpCompletionOption]::ResponseHeadersRead
|
||||
}
|
||||
else {
|
||||
@ -404,8 +451,7 @@ function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect,
|
||||
$DownloadException.Data["StatusCode"] = [int] $Response.StatusCode
|
||||
$DownloadException.Data["ErrorMessage"] = "Unable to download $Uri. Returned HTTP status code: " + $DownloadException.Data["StatusCode"]
|
||||
|
||||
if (404 -eq [int] $Response.StatusCode)
|
||||
{
|
||||
if (404 -eq [int] $Response.StatusCode) {
|
||||
$cts.Cancel()
|
||||
}
|
||||
}
|
||||
@ -444,10 +490,8 @@ function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect,
|
||||
try {
|
||||
return Invoke-With-Retry $downloadScript $cts.Token
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ($null -ne $cts)
|
||||
{
|
||||
finally {
|
||||
if ($null -ne $cts) {
|
||||
$cts.Dispose()
|
||||
}
|
||||
}
|
||||
@ -565,11 +609,9 @@ function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string
|
||||
elseif ($Runtime -eq "windowsdesktop") {
|
||||
# The windows desktop runtime is part of the core runtime layout prior to 5.0
|
||||
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/windowsdesktop-runtime-$SpecificProductVersion-win-$CLIArchitecture.zip"
|
||||
if ($SpecificVersion -match '^(\d+)\.(.*)$')
|
||||
{
|
||||
if ($SpecificVersion -match '^(\d+)\.(.*)$') {
|
||||
$majorVersion = [int]$Matches[1]
|
||||
if ($majorVersion -ge 5)
|
||||
{
|
||||
if ($majorVersion -ge 5) {
|
||||
$PayloadURL = "$AzureFeed/WindowsDesktop/$SpecificVersion/windowsdesktop-runtime-$SpecificProductVersion-win-$CLIArchitecture.zip"
|
||||
}
|
||||
}
|
||||
@ -619,8 +661,7 @@ function Get-Product-Version([string]$AzureFeed, [string]$SpecificVersion, [stri
|
||||
|
||||
if ($productVersionResponse.StatusCode -eq 200) {
|
||||
$productVersion = $productVersionResponse.Content.ReadAsStringAsync().Result.Trim()
|
||||
if ($productVersion -ne $SpecificVersion)
|
||||
{
|
||||
if ($productVersion -ne $SpecificVersion) {
|
||||
Say "Using alternate version $productVersion found in $ProductVersionTxtURL"
|
||||
}
|
||||
return $productVersion
|
||||
@ -635,8 +676,7 @@ function Get-Product-Version([string]$AzureFeed, [string]$SpecificVersion, [stri
|
||||
}
|
||||
|
||||
# Getting the version number with productVersion.txt has failed. Try parsing the download link for a version number.
|
||||
if ([string]::IsNullOrEmpty($PackageDownloadLink))
|
||||
{
|
||||
if ([string]::IsNullOrEmpty($PackageDownloadLink)) {
|
||||
Say-Verbose "Using the default value '$SpecificVersion' as the product version."
|
||||
return $SpecificVersion
|
||||
}
|
||||
@ -648,21 +688,21 @@ function Get-Product-Version([string]$AzureFeed, [string]$SpecificVersion, [stri
|
||||
function Get-Product-Version-Url([string]$AzureFeed, [string]$SpecificVersion, [string]$PackageDownloadLink, [bool]$Flattened) {
|
||||
Say-Invocation $MyInvocation
|
||||
|
||||
$majorVersion=$null
|
||||
$majorVersion = $null
|
||||
if ($SpecificVersion -match '^(\d+)\.(.*)') {
|
||||
$majorVersion = $Matches[1] -as[int]
|
||||
$majorVersion = $Matches[1] -as [int]
|
||||
}
|
||||
|
||||
$pvFileName='productVersion.txt'
|
||||
if($Flattened) {
|
||||
if(-not $Runtime) {
|
||||
$pvFileName='sdk-productVersion.txt'
|
||||
$pvFileName = 'productVersion.txt'
|
||||
if ($Flattened) {
|
||||
if (-not $Runtime) {
|
||||
$pvFileName = 'sdk-productVersion.txt'
|
||||
}
|
||||
elseif($Runtime -eq "dotnet") {
|
||||
$pvFileName='runtime-productVersion.txt'
|
||||
elseif ($Runtime -eq "dotnet") {
|
||||
$pvFileName = 'runtime-productVersion.txt'
|
||||
}
|
||||
else {
|
||||
$pvFileName="$Runtime-productVersion.txt"
|
||||
$pvFileName = "$Runtime-productVersion.txt"
|
||||
}
|
||||
}
|
||||
|
||||
@ -696,16 +736,14 @@ function Get-Product-Version-Url([string]$AzureFeed, [string]$SpecificVersion, [
|
||||
return $ProductVersionTxtURL
|
||||
}
|
||||
|
||||
function Get-ProductVersionFromDownloadLink([string]$PackageDownloadLink, [string]$SpecificVersion)
|
||||
{
|
||||
function Get-ProductVersionFromDownloadLink([string]$PackageDownloadLink, [string]$SpecificVersion) {
|
||||
Say-Invocation $MyInvocation
|
||||
|
||||
#product specific version follows the product name
|
||||
#for filename 'dotnet-sdk-3.1.404-win-x64.zip': the product version is 3.1.400
|
||||
$filename = $PackageDownloadLink.Substring($PackageDownloadLink.LastIndexOf("/") + 1)
|
||||
$filenameParts = $filename.Split('-')
|
||||
if ($filenameParts.Length -gt 2)
|
||||
{
|
||||
if ($filenameParts.Length -gt 2) {
|
||||
$productVersion = $filenameParts[2]
|
||||
Say-Verbose "Extracted product version '$productVersion' from download link '$PackageDownloadLink'."
|
||||
}
|
||||
@ -723,6 +761,9 @@ function Get-User-Share-Path() {
|
||||
if (!$InstallRoot) {
|
||||
$InstallRoot = "$env:LocalAppData\Microsoft\dotnet"
|
||||
}
|
||||
elseif ($InstallRoot -like "$env:ProgramFiles\dotnet\?*") {
|
||||
Say-Warning "The install root specified by the environment variable DOTNET_INSTALL_DIR points to the sub folder of $env:ProgramFiles\dotnet which is the default dotnet install root using .NET SDK installer. It is better to keep aligned with .NET SDK installer."
|
||||
}
|
||||
return $InstallRoot
|
||||
}
|
||||
|
||||
@ -735,6 +776,19 @@ function Resolve-Installation-Path([string]$InstallDir) {
|
||||
return $InstallDir
|
||||
}
|
||||
|
||||
function Test-User-Write-Access([string]$InstallDir) {
|
||||
try {
|
||||
$tempFileName = [guid]::NewGuid().ToString()
|
||||
$tempFilePath = Join-Path -Path $InstallDir -ChildPath $tempFileName
|
||||
New-Item -Path $tempFilePath -ItemType File -Force
|
||||
Remove-Item $tempFilePath -Force
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) {
|
||||
Say-Invocation $MyInvocation
|
||||
|
||||
@ -810,7 +864,7 @@ function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) {
|
||||
if (($null -eq $PathWithVersion) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) {
|
||||
$DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName)
|
||||
$DestinationDir = Split-Path -Parent $DestinationPath
|
||||
$OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath))
|
||||
$OverrideFiles = $OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath))
|
||||
if ((-Not $DestinationPath.EndsWith("\")) -And $OverrideFiles) {
|
||||
New-Item -ItemType Directory -Force -Path $DestinationDir | Out-Null
|
||||
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $DestinationPath, $OverrideNonVersionedFiles)
|
||||
@ -818,8 +872,7 @@ function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
catch {
|
||||
Say-Error "Failed to extract package. Exception: $_"
|
||||
throw;
|
||||
}
|
||||
@ -851,6 +904,8 @@ function DownloadFile($Source, [string]$OutPath) {
|
||||
$File = [System.IO.File]::Create($OutPath)
|
||||
$Stream.CopyTo($File)
|
||||
$File.Close()
|
||||
|
||||
ValidateRemoteLocalFileSizes -LocalFileOutPath $OutPath -SourceUri $Source
|
||||
}
|
||||
finally {
|
||||
if ($null -ne $Stream) {
|
||||
@ -859,19 +914,40 @@ function DownloadFile($Source, [string]$OutPath) {
|
||||
}
|
||||
}
|
||||
|
||||
function ValidateRemoteLocalFileSizes([string]$LocalFileOutPath, $SourceUri) {
|
||||
try {
|
||||
$remoteFileSize = Get-Remote-File-Size -zipUri $SourceUri
|
||||
$fileSize = [long](Get-Item $LocalFileOutPath).Length
|
||||
Say "Downloaded file $SourceUri size is $fileSize bytes."
|
||||
|
||||
if ((![string]::IsNullOrEmpty($remoteFileSize)) -and !([string]::IsNullOrEmpty($fileSize)) ) {
|
||||
if ($remoteFileSize -ne $fileSize) {
|
||||
Say "The remote and local file sizes are not equal. Remote file size is $remoteFileSize bytes and local size is $fileSize bytes. The local package may be corrupted."
|
||||
}
|
||||
else {
|
||||
Say "The remote and local file sizes are equal."
|
||||
}
|
||||
}
|
||||
else {
|
||||
Say "Either downloaded or local package size can not be measured. One of them may be corrupted."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Say "Either downloaded or local package size can not be measured. One of them may be corrupted."
|
||||
}
|
||||
}
|
||||
|
||||
function SafeRemoveFile($Path) {
|
||||
try {
|
||||
if (Test-Path $Path) {
|
||||
Remove-Item $Path
|
||||
Say-Verbose "The temporary file `"$Path`" was removed."
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Say-Verbose "The temporary file `"$Path`" does not exist, therefore is not removed."
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
catch {
|
||||
Say-Warning "Failed to remove the temporary file: `"$Path`", remove it manually."
|
||||
}
|
||||
}
|
||||
@ -883,7 +959,8 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot) {
|
||||
if (-Not $env:path.Contains($SuffixedBinPath)) {
|
||||
Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process."
|
||||
$env:path = $SuffixedBinPath + $env:path
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Say-Verbose "Current process PATH already contains `"$BinPath`""
|
||||
}
|
||||
}
|
||||
@ -892,43 +969,67 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot) {
|
||||
}
|
||||
}
|
||||
|
||||
function PrintDryRunOutput($Invocation, $DownloadLinks)
|
||||
{
|
||||
function PrintDryRunOutput($Invocation, $DownloadLinks) {
|
||||
Say "Payload URLs:"
|
||||
|
||||
for ($linkIndex=0; $linkIndex -lt $DownloadLinks.count; $linkIndex++) {
|
||||
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`""
|
||||
$RepeatableCommand += " -Runtime `"dotnet`""
|
||||
}
|
||||
elseif ($Runtime -eq "aspnetcore") {
|
||||
$RepeatableCommand+=" -Runtime `"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 (-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>`""
|
||||
$RepeatableCommand += " -FeedCredential `"<feedCredential>`""
|
||||
}
|
||||
Say "Repeatable invocation: $RepeatableCommand"
|
||||
if ($SpecificVersion -ne $EffectiveVersion)
|
||||
{
|
||||
if ($SpecificVersion -ne $EffectiveVersion) {
|
||||
Say "NOTE: Due to finding a version manifest with this runtime, it would actually install with version '$EffectiveVersion'"
|
||||
}
|
||||
}
|
||||
|
||||
# grab the 'stem' of the redirect and check it against all of our configured feeds,
|
||||
# if it matches, we can be sure that the redirect is valid and we should use it for
|
||||
# subsequent processing
|
||||
function Sanitize-RedirectUrl([string]$url) {
|
||||
$urlSegments = ([System.Uri]$url).Segments;
|
||||
$urlStem = $urlSegments[2..($urlSegments.Length - 1)] -join "";
|
||||
Write-Verbose "Checking configured feeds for the asset at $urlStem"
|
||||
foreach ($prospectiveFeed in $feeds) {
|
||||
$trialUrl = "$prospectiveFeed/$urlStem";
|
||||
Write-Verbose "Checking $trialUrl"
|
||||
try {
|
||||
$trialResponse = Invoke-WebRequest -Uri $trialUrl -Method HEAD
|
||||
if ($trialResponse.StatusCode -eq 200) {
|
||||
Write-Verbose "Found a match at $trialUrl"
|
||||
return $trialUrl;
|
||||
}
|
||||
else {
|
||||
Write-Verbose "No match at $trialUrl"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "Failed to check $trialUrl"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Internal, [string]$Product, [string]$Architecture) {
|
||||
Say-Invocation $MyInvocation
|
||||
|
||||
#quality is not supported for LTS or current channel
|
||||
if (![string]::IsNullOrEmpty($Quality) -and (@("LTS", "current") -contains $Channel)) {
|
||||
#quality is not supported for LTS or STS channel
|
||||
if (![string]::IsNullOrEmpty($Quality) -and (@("LTS", "STS") -contains $Channel)) {
|
||||
$Quality = ""
|
||||
Say-Warning "Specifying quality for current or LTS channel is not supported, the quality will be ignored."
|
||||
Say-Warning "Specifying quality for STS or LTS channel is not supported, the quality will be ignored."
|
||||
}
|
||||
Say-Verbose "Retrieving primary payload URL from aka.ms link for channel: '$Channel', quality: '$Quality' product: '$Product', os: 'win', architecture: '$Architecture'."
|
||||
|
||||
@ -939,19 +1040,18 @@ function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Intern
|
||||
}
|
||||
$akaMsLink += "/$Channel"
|
||||
if (-not [string]::IsNullOrEmpty($Quality)) {
|
||||
$akaMsLink +="/$Quality"
|
||||
$akaMsLink += "/$Quality"
|
||||
}
|
||||
$akaMsLink +="/$Product-win-$Architecture.zip"
|
||||
$akaMsLink += "/$Product-win-$Architecture.zip"
|
||||
Say-Verbose "Constructed aka.ms link: '$akaMsLink'."
|
||||
$akaMsDownloadLink=$null
|
||||
$akaMsDownloadLink = $null
|
||||
|
||||
for ($maxRedirections = 9; $maxRedirections -ge 0; $maxRedirections--)
|
||||
{
|
||||
for ($maxRedirections = 9; $maxRedirections -ge 0; $maxRedirections--) {
|
||||
#get HTTP response
|
||||
#do not pass credentials as a part of the $akaMsLink and do not apply credentials in the GetHTTPResponse function
|
||||
#otherwise the redirect link would have credentials as well
|
||||
#it would result in applying credentials twice to the resulting link and thus breaking it, and in echoing credentials to the output as a part of redirect link
|
||||
$Response= GetHTTPResponse -Uri $akaMsLink -HeaderOnly $true -DisableRedirect $true -DisableFeedCredential $true
|
||||
$Response = GetHTTPResponse -Uri $akaMsLink -HeaderOnly $true -DisableRedirect $true -DisableFeedCredential $true
|
||||
Say-Verbose "Received response:`n$Response"
|
||||
|
||||
if ([string]::IsNullOrEmpty($Response)) {
|
||||
@ -960,8 +1060,7 @@ function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Intern
|
||||
}
|
||||
|
||||
#if HTTP code is 301 (Moved Permanently), the redirect link exists
|
||||
if ($Response.StatusCode -eq 301)
|
||||
{
|
||||
if ($Response.StatusCode -eq 301) {
|
||||
try {
|
||||
$akaMsDownloadLink = $Response.Headers.GetValues("Location")[0]
|
||||
|
||||
@ -980,9 +1079,13 @@ function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Intern
|
||||
return $null
|
||||
}
|
||||
}
|
||||
elseif ((($Response.StatusCode -lt 300) -or ($Response.StatusCode -ge 400)) -and (-not [string]::IsNullOrEmpty($akaMsDownloadLink)))
|
||||
{
|
||||
elseif ((($Response.StatusCode -lt 300) -or ($Response.StatusCode -ge 400)) -and (-not [string]::IsNullOrEmpty($akaMsDownloadLink))) {
|
||||
# Redirections have ended.
|
||||
$actualRedirectUrl = Sanitize-RedirectUrl $akaMsDownloadLink
|
||||
if ($null -ne $actualRedirectUrl) {
|
||||
$akaMsDownloadLink = $actualRedirectUrl
|
||||
}
|
||||
|
||||
return $akaMsDownloadLink
|
||||
}
|
||||
|
||||
@ -998,7 +1101,7 @@ function Get-AkaMSDownloadLink([string]$Channel, [string]$Quality, [bool]$Intern
|
||||
function Get-AkaMsLink-And-Version([string] $NormalizedChannel, [string] $NormalizedQuality, [bool] $Internal, [string] $ProductName, [string] $Architecture) {
|
||||
$AkaMsDownloadLink = Get-AkaMSDownloadLink -Channel $NormalizedChannel -Quality $NormalizedQuality -Internal $Internal -Product $ProductName -Architecture $Architecture
|
||||
|
||||
if ([string]::IsNullOrEmpty($AkaMsDownloadLink)){
|
||||
if ([string]::IsNullOrEmpty($AkaMsDownloadLink)) {
|
||||
if (-not [string]::IsNullOrEmpty($NormalizedQuality)) {
|
||||
# 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 '$ProductName', os: 'win', architecture: '$Architecture'."
|
||||
@ -1031,10 +1134,11 @@ function Get-AkaMsLink-And-Version([string] $NormalizedChannel, [string] $Normal
|
||||
}
|
||||
}
|
||||
|
||||
function Get-Feeds-To-Use()
|
||||
{
|
||||
function Get-Feeds-To-Use() {
|
||||
$feeds = @(
|
||||
"https://dotnetcli.azureedge.net/dotnet",
|
||||
"https://builds.dotnet.microsoft.com/dotnet"
|
||||
"https://dotnetcli.azureedge.net/dotnet"
|
||||
"https://ci.dot.net/public"
|
||||
"https://dotnetbuilds.azureedge.net/public"
|
||||
)
|
||||
|
||||
@ -1053,6 +1157,8 @@ function Get-Feeds-To-Use()
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "Initialized feeds: $feeds"
|
||||
|
||||
return $feeds
|
||||
}
|
||||
|
||||
@ -1082,26 +1188,39 @@ function Resolve-AssetName-And-RelativePath([string] $Runtime) {
|
||||
}
|
||||
|
||||
function Prepare-Install-Directory {
|
||||
$diskSpaceWarning = "Failed to check the disk space. Installation will continue, but it may fail if you do not have enough disk space.";
|
||||
|
||||
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
||||
Say-Verbose $diskSpaceWarning
|
||||
return
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
||||
|
||||
$installDrive = $((Get-Item $InstallRoot -Force).PSDrive.Name);
|
||||
$diskInfo = $null
|
||||
try{
|
||||
try {
|
||||
$diskInfo = Get-PSDrive -Name $installDrive
|
||||
}
|
||||
catch{
|
||||
Say-Warning "Failed to check the disk space. Installation will continue, but it may fail if you do not have enough disk space."
|
||||
catch {
|
||||
Say-Warning $diskSpaceWarning
|
||||
}
|
||||
|
||||
# The check is relevant for PS version >= 7, the result can be irrelevant for older versions. See https://github.com/PowerShell/PowerShell/issues/12442.
|
||||
if ( ($null -ne $diskInfo) -and ($diskInfo.Free / 1MB -le 100)) {
|
||||
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 ($Help) {
|
||||
Get-Help $PSCommandPath -Examples
|
||||
exit
|
||||
}
|
||||
|
||||
Say-Verbose "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||
Say-Verbose "- The SDK needs to be installed without user interaction and without admin rights."
|
||||
Say-Verbose "- The SDK installation doesn't need to persist across multiple CI runs."
|
||||
Say-Verbose "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"
|
||||
@ -1109,16 +1228,22 @@ if ($SharedRuntime -and (-not $Runtime)) {
|
||||
|
||||
$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
|
||||
Measure-Action "Product discovery" {
|
||||
$script:CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
||||
$script:NormalizedQuality = Get-NormalizedQuality $Quality
|
||||
Say-Verbose "Normalized quality: '$NormalizedQuality'"
|
||||
$script:NormalizedChannel = Get-NormalizedChannel $Channel
|
||||
Say-Verbose "Normalized channel: '$NormalizedChannel'"
|
||||
$script:NormalizedProduct = Get-NormalizedProduct $Runtime
|
||||
Say-Verbose "Normalized product: '$NormalizedProduct'"
|
||||
$script:FeedCredential = ValidateFeedCredential $FeedCredential
|
||||
}
|
||||
|
||||
$InstallRoot = Resolve-Installation-Path $InstallDir
|
||||
if (-not (Test-User-Write-Access $InstallRoot)) {
|
||||
Say-Error "The current user doesn't have write access to the installation root '$InstallRoot' to install .NET. Please try specifying a different installation directory using the -InstallDir parameter, or ensure the selected directory has the appropriate permissions."
|
||||
throw
|
||||
}
|
||||
Say-Verbose "InstallRoot: $InstallRoot"
|
||||
$ScriptName = $MyInvocation.MyCommand.Name
|
||||
($assetName, $dotnetPackageRelativePath) = Resolve-AssetName-And-RelativePath -Runtime $Runtime
|
||||
@ -1127,7 +1252,7 @@ $feeds = Get-Feeds-To-Use
|
||||
$DownloadLinks = @()
|
||||
|
||||
if ($Version.ToLowerInvariant() -ne "latest" -and -not [string]::IsNullOrEmpty($Quality)) {
|
||||
throw "Quality and Version options are not allowed to be specified simultaneously. See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#options for details."
|
||||
throw "Quality and Version options are not allowed to be specified simultaneously. See https:// learn.microsoft.com/dotnet/core/tools/dotnet-install-script#options for details."
|
||||
}
|
||||
|
||||
# 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.
|
||||
@ -1135,13 +1260,12 @@ 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'}
|
||||
$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)
|
||||
{
|
||||
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
|
||||
@ -1152,34 +1276,31 @@ if ([string]::IsNullOrEmpty($JSonFile) -and ($Version -eq "latest")) {
|
||||
|
||||
# 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)
|
||||
{
|
||||
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'}
|
||||
$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'}
|
||||
$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)
|
||||
{
|
||||
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
|
||||
{
|
||||
catch {
|
||||
Say-Verbose "Failed to acquire download links from feed $feed. Exception: $_"
|
||||
}
|
||||
}
|
||||
@ -1194,21 +1315,19 @@ if ($DryRun) {
|
||||
return
|
||||
}
|
||||
|
||||
Prepare-Install-Directory
|
||||
Measure-Action "Installation directory preparation" { Prepare-Install-Directory }
|
||||
|
||||
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
|
||||
Say-Verbose "Zip path: $ZipPath"
|
||||
|
||||
$DownloadSucceeded = $false
|
||||
$DownloadedLink = $null
|
||||
$ErrorMessages = @()
|
||||
|
||||
foreach ($link in $DownloadLinks)
|
||||
{
|
||||
foreach ($link in $DownloadLinks) {
|
||||
Say-Verbose "Downloading `"$($link.type)`" link $($link.downloadLink)"
|
||||
|
||||
try {
|
||||
DownloadFile -Source $link.downloadLink -OutPath $ZipPath
|
||||
Measure-Action "Package download" { DownloadFile -Source $link.downloadLink -OutPath $ZipPath }
|
||||
Say-Verbose "Download succeeded."
|
||||
$DownloadSucceeded = $true
|
||||
$DownloadedLink = $link
|
||||
@ -1224,7 +1343,8 @@ foreach ($link in $DownloadLinks)
|
||||
|
||||
if ($PSItem.Exception.Data.Contains("ErrorMessage")) {
|
||||
$ErrorMessage = $PSItem.Exception.Data["ErrorMessage"]
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$ErrorMessage = $PSItem.Exception.Message
|
||||
}
|
||||
|
||||
@ -1245,7 +1365,7 @@ if (-not $DownloadSucceeded) {
|
||||
}
|
||||
|
||||
Say "Extracting the archive."
|
||||
Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot
|
||||
Measure-Action "Package extraction" { Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot }
|
||||
|
||||
# Check if the SDK version is installed; if not, fail the installation.
|
||||
$isAssetInstalled = $false
|
||||
@ -1269,226 +1389,13 @@ if (!$isAssetInstalled) {
|
||||
throw "`"$assetName`" with version = $($DownloadedLink.effectiveVersion) failed to install with an unknown error."
|
||||
}
|
||||
|
||||
SafeRemoveFile -Path $ZipPath
|
||||
if (-not $KeepZip) {
|
||||
SafeRemoveFile -Path $ZipPath
|
||||
}
|
||||
|
||||
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot
|
||||
Measure-Action "Setting up shell environment" { Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot }
|
||||
|
||||
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 "Note that the script does not ensure your Windows version is supported during the installation."
|
||||
Say "To check the list of supported versions, go to https://learn.microsoft.com/dotnet/core/install/windows#supported-versions"
|
||||
Say "Installed version is $($DownloadedLink.effectiveVersion)"
|
||||
Say "Installation finished"
|
||||
|
||||
# SIG # Begin signature block
|
||||
# MIInnQYJKoZIhvcNAQcCoIInjjCCJ4oCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBPbD3vCI+sY1o7
|
||||
# t+9GwL7gEDtWJk/5Ypegl3ITSKy+X6CCDYEwggX/MIID56ADAgECAhMzAAACzI61
|
||||
# lqa90clOAAAAAALMMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
||||
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
||||
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
||||
# bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAxWhcNMjMwNTExMjA0NjAxWjB0MQsw
|
||||
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
||||
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
||||
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
# AQCiTbHs68bADvNud97NzcdP0zh0mRr4VpDv68KobjQFybVAuVgiINf9aG2zQtWK
|
||||
# No6+2X2Ix65KGcBXuZyEi0oBUAAGnIe5O5q/Y0Ij0WwDyMWaVad2Te4r1Eic3HWH
|
||||
# UfiiNjF0ETHKg3qa7DCyUqwsR9q5SaXuHlYCwM+m59Nl3jKnYnKLLfzhl13wImV9
|
||||
# DF8N76ANkRyK6BYoc9I6hHF2MCTQYWbQ4fXgzKhgzj4zeabWgfu+ZJCiFLkogvc0
|
||||
# RVb0x3DtyxMbl/3e45Eu+sn/x6EVwbJZVvtQYcmdGF1yAYht+JnNmWwAxL8MgHMz
|
||||
# xEcoY1Q1JtstiY3+u3ulGMvhAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
|
||||
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUiLhHjTKWzIqVIp+sM2rOHH11rfQw
|
||||
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
|
||||
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDcwNTI5MB8GA1UdIwQYMBaAFEhu
|
||||
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
|
||||
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
|
||||
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
|
||||
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
|
||||
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAeA8D
|
||||
# sOAHS53MTIHYu8bbXrO6yQtRD6JfyMWeXaLu3Nc8PDnFc1efYq/F3MGx/aiwNbcs
|
||||
# J2MU7BKNWTP5JQVBA2GNIeR3mScXqnOsv1XqXPvZeISDVWLaBQzceItdIwgo6B13
|
||||
# vxlkkSYMvB0Dr3Yw7/W9U4Wk5K/RDOnIGvmKqKi3AwyxlV1mpefy729FKaWT7edB
|
||||
# d3I4+hldMY8sdfDPjWRtJzjMjXZs41OUOwtHccPazjjC7KndzvZHx/0VWL8n0NT/
|
||||
# 404vftnXKifMZkS4p2sB3oK+6kCcsyWsgS/3eYGw1Fe4MOnin1RhgrW1rHPODJTG
|
||||
# AUOmW4wc3Q6KKr2zve7sMDZe9tfylonPwhk971rX8qGw6LkrGFv31IJeJSe/aUbG
|
||||
# dUDPkbrABbVvPElgoj5eP3REqx5jdfkQw7tOdWkhn0jDUh2uQen9Atj3RkJyHuR0
|
||||
# GUsJVMWFJdkIO/gFwzoOGlHNsmxvpANV86/1qgb1oZXdrURpzJp53MsDaBY/pxOc
|
||||
# J0Cvg6uWs3kQWgKk5aBzvsX95BzdItHTpVMtVPW4q41XEvbFmUP1n6oL5rdNdrTM
|
||||
# j/HXMRk1KCksax1Vxo3qv+13cCsZAaQNaIAvt5LvkshZkDZIP//0Hnq7NnWeYR3z
|
||||
# 4oFiw9N2n3bb9baQWuWPswG0Dq9YT9kb+Cs4qIIwggd6MIIFYqADAgECAgphDpDS
|
||||
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
|
||||
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
|
||||
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
|
||||
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
|
||||
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
|
||||
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
|
||||
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
|
||||
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
|
||||
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
|
||||
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
|
||||
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
|
||||
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
|
||||
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
|
||||
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
|
||||
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
|
||||
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
|
||||
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
|
||||
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
|
||||
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
|
||||
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
|
||||
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
|
||||
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
|
||||
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
||||
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
|
||||
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
||||
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
|
||||
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
|
||||
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
|
||||
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
|
||||
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
|
||||
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
|
||||
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
|
||||
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
|
||||
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
|
||||
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
|
||||
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
|
||||
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
|
||||
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
|
||||
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
|
||||
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZcjCCGW4CAQEwgZUwfjELMAkG
|
||||
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
|
||||
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
|
||||
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAsyOtZamvdHJTgAAAAACzDAN
|
||||
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
|
||||
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgNQFZgkyG
|
||||
# luNzcU2g8/R/8PaAnIpTnmBnw3/0HJQjl9wwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
|
||||
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
|
||||
# BgkqhkiG9w0BAQEFAASCAQABpLusOOxklzXjvllIe1AgDCgkYd0BN4cT3yQ8uULV
|
||||
# e+OnVgGOLnPcffCSGZ/SQMgJndoRMBSBd0jH5JxSkSuLXJpEWs1nl4QUg93FxYLr
|
||||
# pMdFepMsN733h5JuZGcTFf7P23IOxYaVEC+mKLbkOxIJaxgDQYSgliSg9X2hwLJ2
|
||||
# frCUV4b3ZWL0R495LhGpo65B7Ik/OOeHXWcs8d7vOnE/ObPHFv3fn1QTrq+KvbhA
|
||||
# TWEmL3P9P0Jn7k6gJjrTOxpgcDenr0IE5X63oe7y32LgLlJbr1OjKQUUCPVQ16d9
|
||||
# bgkhRp0gghdSAbDKjQuEAQ+e3GTeoNWnzxPlQfMLP0droYIW/DCCFvgGCisGAQQB
|
||||
# gjcDAwExghboMIIW5AYJKoZIhvcNAQcCoIIW1TCCFtECAQMxDzANBglghkgBZQME
|
||||
# AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB
|
||||
# MDEwDQYJYIZIAWUDBAIBBQAEIGXZSvVWqDs0wjW8JLHjKJ41lgzXHpdGqPCyYSvk
|
||||
# gIH0AgZi1XtjQncYEzIwMjIwODAzMTI1NjA1Ljc2OFowBIACAfSggdCkgc0wgcox
|
||||
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
|
||||
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p
|
||||
# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg
|
||||
# RVNOOjEyQkMtRTNBRS03NEVCMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
|
||||
# cCBTZXJ2aWNloIIRUzCCBwwwggT0oAMCAQICEzMAAAGhAYVVmblUXYoAAQAAAaEw
|
||||
# DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
|
||||
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
|
||||
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN
|
||||
# MjExMjAyMTkwNTI0WhcNMjMwMjI4MTkwNTI0WjCByjELMAkGA1UEBhMCVVMxEzAR
|
||||
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
|
||||
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg
|
||||
# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046MTJCQy1FM0FFLTc0
|
||||
# RUIxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0G
|
||||
# CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDayTxe5WukkrYxxVuHLYW9BEWCD9kk
|
||||
# jnnHsOKwGddIPbZlLY+l5ovLDNf+BEMQKAZQI3DX91l1yCDuP9X7tOPC48ZRGXA/
|
||||
# bf9ql0FK5438gIl7cV528XeEOFwc/A+UbIUfW296Omg8Z62xaQv3jrG4U/priArF
|
||||
# /er1UA1HNuIGUyqjlygiSPwK2NnFApi1JD+Uef5c47kh7pW1Kj7RnchpFeY9MekP
|
||||
# QRia7cEaUYU4sqCiJVdDJpefLvPT9EdthlQx75ldx+AwZf2a9T7uQRSBh8tpxPdI
|
||||
# DDkKiWMwjKTrAY09A3I/jidqPuc8PvX+sqxqyZEN2h4GA0Edjmk64nkIukAK18K5
|
||||
# nALDLO9SMTxpAwQIHRDtZeTClvAPCEoy1vtPD7f+eqHqStuu+XCkfRjXEpX9+h9f
|
||||
# rsB0/BgD5CBf3ELLAa8TefMfHZWEJRTPNrbXMKizSrUSkVv/3HP/ZsJpwaz5My2R
|
||||
# byc3Ah9bT76eBJkyfT5FN9v/KQ0HnxhRMs6HHhTmNx+LztYci+vHf0D3QH1eCjZW
|
||||
# ZRjp1mOyxpPU2mDMG6gelvJse1JzRADo7YIok/J3Ccbm8MbBbm85iogFltFHecHF
|
||||
# EFwrsDGBFnNYHMhcbarQNA+gY2e2l9fAkX3MjI7Uklkoz74/P6KIqe5jcd9FPCbb
|
||||
# SbYH9OLsteeYOQIDAQABo4IBNjCCATIwHQYDVR0OBBYEFBa/IDLbY475VQyKiZSw
|
||||
# 47l0/cypMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRY
|
||||
# MFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p
|
||||
# Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEF
|
||||
# BQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
|
||||
# a2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAo
|
||||
# MSkuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZI
|
||||
# hvcNAQELBQADggIBACDDIxElfXlG5YKcKrLPSS+f3JWZprwKEiASvivaHTBRlXtA
|
||||
# s+TkadcsEei+9w5vmF5tCUzTH4c0nCI7bZxnsL+S6XsiOs3Z1V4WX+IwoXUJ4zLv
|
||||
# s0+mT4vjGDtYfKQ/bsmJKar2c99m/fHv1Wm2CTcyaePvi86Jh3UyLjdRILWbtzs4
|
||||
# oImFMwwKbzHdPopxrBhgi+C1YZshosWLlgzyuxjUl+qNg1m52MJmf11loI7D9HJo
|
||||
# aQzd+rf928Y8rvULmg2h/G50o+D0UJ1Fa/cJJaHfB3sfKw9X6GrtXYGjmM3+g+Ah
|
||||
# aVsfupKXNtOFu5tnLKvAH5OIjEDYV1YKmlXuBuhbYassygPFMmNgG2Ank3drEcDc
|
||||
# ZhCXXqpRszNo1F6Gu5JCpQZXbOJM9Ue5PlJKtmImAYIGsw+pnHy/r5ggSYOp4g5Z
|
||||
# 1oU9GhVCM3V0T9adee6OUXBk1rE4dZc/UsPlj0qoiljL+lN1A5gkmmz7k5tIObVG
|
||||
# B7dJdz8J0FwXRE5qYu1AdvauVbZwGQkL1x8aK/svjEQW0NUyJ29znDHiXl5vLoRT
|
||||
# jjFpshUBi2+IY+mNqbLmj24j5eT+bjDlE3HmNtLPpLcMDYqZ1H+6U6YmaiNmac2j
|
||||
# RXDAaeEE/uoDMt2dArfJP7M+MDv3zzNNTINeuNEtDVgm9zwfgIUCXnDZuVtiMIIH
|
||||
# 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
|
||||
# qzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAsowggIzAgEBMIH4
|
||||
# oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
|
||||
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUw
|
||||
# IwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1U
|
||||
# aGFsZXMgVFNTIEVTTjoxMkJDLUUzQUUtNzRFQjElMCMGA1UEAxMcTWljcm9zb2Z0
|
||||
# IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAG3F2jO4LEMVLwgKG
|
||||
# XdYMN4FBgOCggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
|
||||
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
|
||||
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN
|
||||
# BgkqhkiG9w0BAQUFAAIFAOaUaAIwIhgPMjAyMjA4MDMxMTIwMzRaGA8yMDIyMDgw
|
||||
# NDExMjAzNFowczA5BgorBgEEAYRZCgQBMSswKTAKAgUA5pRoAgIBADAGAgEAAgEI
|
||||
# MAcCAQACAhIDMAoCBQDmlbmCAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQB
|
||||
# hFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEA
|
||||
# bqvBFqohycksQZhSEJZTiCeQ6hwWlYWRXL1PerCFbLmK+4vgr57BkwFsu5KzBE2z
|
||||
# i1eHNrssK4BcBLYyIhDIjMSqqtrvclrB6SSDag1WcxZrz42xatvyhKXZd52a5R5Q
|
||||
# xJw66cvwkDa4UmEtVOnbkaOPyyAql72D9w/XLHY0nmUxggQNMIIECQIBATCBkzB8
|
||||
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
|
||||
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N
|
||||
# aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAaEBhVWZuVRdigABAAAB
|
||||
# oTANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEE
|
||||
# MC8GCSqGSIb3DQEJBDEiBCCGB/0CqUv9yvdxWNnaciRCHPCM4WmcYpKBUNiR1Xg+
|
||||
# yjCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIOsIVPE6gYJoIIKOhHIF7UlJ
|
||||
# Cswl4IJPISvOKInfjtCEMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
|
||||
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
|
||||
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
|
||||
# IDIwMTACEzMAAAGhAYVVmblUXYoAAQAAAaEwIgQgy8rtxrFwV1rcLxTDP8W6Af+y
|
||||
# Za2AaaMVTQY3E9A2eHMwDQYJKoZIhvcNAQELBQAEggIAEJIvjnhqXrrsyJWHHG9i
|
||||
# gKBBM3d51KglP0nJ0dY1zp7uUIBTQ53LVONE1SFiqbw6akydYum6iTaI7tvFWJRW
|
||||
# dx5Fq56gt+QY2YO0nsn3zH3ulyUUkhHuMsx5N/pQT6tsEMu6tWCuWucf44JQHlyY
|
||||
# x8/C+S5QoA7DId3ugccCFpZWUMb76QWReDtalDz3XY/gNSBT2DTJ8WT78WREcYKu
|
||||
# aBO52cUXKKLtr5ZoPcdEElB/TPuctcC6Hh0+J4Y6PCNwOVPodpEmjMSV0tAN8tZp
|
||||
# T3cyf9YPnwXNdDiaikZlPSO0pXCM5+KjrBm5hnj6+J8qMc+Qc91UMh2J96kZWVmm
|
||||
# PsWE7YA4DlWrIWn2mdGLtTJP4sOlqRjigP9rdBFo0oG9c1ySKw3rN7zpGTDnFdkS
|
||||
# vxeCoLWx48BJ4bE3Siwx6cwrYScmIgyobLb1Ztu5FEmFUn8maX5oo8IY9kPsODOG
|
||||
# 3y8hPoLOOj2lRdslV9bdjtrbnqeY5Nq/oKuftbX8iD2MYFgWOqeufw3TcQiSz2uF
|
||||
# tKGolAePdRf1S7c81CC89g7tcwy1TILR9M2JdWOwosAtpFXxX6Vc1OGiRwPAyXBL
|
||||
# dvDqiTx5zb9k87hfJvwix/oXfo4fNCNdE/i/VbmsAJjcxd+eEBbJ9Oc+oPqC/5zq
|
||||
# pPtLXUsVfUWX58dPRnYeMAg=
|
||||
# SIG # End signature block
|
||||
|
309
externals/install-dotnet.sh
vendored
309
externals/install-dotnet.sh
vendored
@ -298,11 +298,20 @@ get_machine_architecture() {
|
||||
if command -v uname > /dev/null; then
|
||||
CPUName=$(uname -m)
|
||||
case $CPUName in
|
||||
armv1*|armv2*|armv3*|armv4*|armv5*|armv6*)
|
||||
echo "armv6-or-below"
|
||||
return 0
|
||||
;;
|
||||
armv*l)
|
||||
echo "arm"
|
||||
return 0
|
||||
;;
|
||||
aarch64|arm64)
|
||||
if [ "$(getconf LONG_BIT)" -lt 64 ]; then
|
||||
# This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS)
|
||||
echo "arm"
|
||||
return 0
|
||||
fi
|
||||
echo "arm64"
|
||||
return 0
|
||||
;;
|
||||
@ -310,6 +319,22 @@ get_machine_architecture() {
|
||||
echo "s390x"
|
||||
return 0
|
||||
;;
|
||||
ppc64le)
|
||||
echo "ppc64le"
|
||||
return 0
|
||||
;;
|
||||
loongarch64)
|
||||
echo "loongarch64"
|
||||
return 0
|
||||
;;
|
||||
riscv64)
|
||||
echo "riscv64"
|
||||
return 0
|
||||
;;
|
||||
powerpc|ppc)
|
||||
echo "ppc"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@ -326,7 +351,13 @@ get_normalized_architecture_from_architecture() {
|
||||
local architecture="$(to_lowercase "$1")"
|
||||
|
||||
if [[ $architecture == \<auto\> ]]; then
|
||||
echo "$(get_machine_architecture)"
|
||||
machine_architecture="$(get_machine_architecture)"
|
||||
if [[ "$machine_architecture" == "armv6-or-below" ]]; then
|
||||
say_err "Architecture \`$machine_architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo $machine_architecture
|
||||
return 0
|
||||
fi
|
||||
|
||||
@ -347,6 +378,14 @@ get_normalized_architecture_from_architecture() {
|
||||
echo "s390x"
|
||||
return 0
|
||||
;;
|
||||
ppc64le)
|
||||
echo "ppc64le"
|
||||
return 0
|
||||
;;
|
||||
loongarch64)
|
||||
echo "loongarch64"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues"
|
||||
@ -384,11 +423,17 @@ get_normalized_architecture_for_specific_sdk_version() {
|
||||
# args:
|
||||
# version or channel - $1
|
||||
is_arm64_supported() {
|
||||
#any channel or version that starts with the specified versions
|
||||
case "$1" in
|
||||
( "1"* | "2"* | "3"* | "4"* | "5"*)
|
||||
# Extract the major version by splitting on the dot
|
||||
major_version="${1%%.*}"
|
||||
|
||||
# Check if the major version is a valid number and less than 6
|
||||
case "$major_version" in
|
||||
[0-9]*)
|
||||
if [ "$major_version" -lt 6 ]; then
|
||||
echo false
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
echo true
|
||||
@ -407,8 +452,13 @@ get_normalized_os() {
|
||||
echo "$osname"
|
||||
return 0
|
||||
;;
|
||||
macos)
|
||||
osname='osx'
|
||||
echo "$osname"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
say_err "'$user_defined_os' is not a supported value for --os option, supported values are: osx, linux, linux-musl, freebsd, rhel.6. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
|
||||
say_err "'$user_defined_os' is not a supported value for --os option, supported values are: osx, macos, linux, linux-musl, freebsd, rhel.6. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
@ -451,6 +501,10 @@ get_normalized_channel() {
|
||||
|
||||
local channel="$(to_lowercase "$1")"
|
||||
|
||||
if [[ $channel == current ]]; then
|
||||
say_warning 'Value "Current" is deprecated for -Channel option. Use "STS" instead.'
|
||||
fi
|
||||
|
||||
if [[ $channel == release/* ]]; then
|
||||
say_warning 'Using branch name with -Channel option is no longer supported with newer releases. Use -Quality option with a channel in X.Y format instead.';
|
||||
fi
|
||||
@ -461,6 +515,14 @@ get_normalized_channel() {
|
||||
echo "LTS"
|
||||
return 0
|
||||
;;
|
||||
sts)
|
||||
echo "STS"
|
||||
return 0
|
||||
;;
|
||||
current)
|
||||
echo "STS"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
echo "$channel"
|
||||
return 0
|
||||
@ -526,6 +588,40 @@ is_dotnet_package_installed() {
|
||||
fi
|
||||
}
|
||||
|
||||
# args:
|
||||
# downloaded file - $1
|
||||
# remote_file_size - $2
|
||||
validate_remote_local_file_sizes()
|
||||
{
|
||||
eval $invocation
|
||||
|
||||
local downloaded_file="$1"
|
||||
local remote_file_size="$2"
|
||||
local file_size=''
|
||||
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
file_size="$(stat -c '%s' "$downloaded_file")"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# hardcode in order to avoid conflicts with GNU stat
|
||||
file_size="$(/usr/bin/stat -f '%z' "$downloaded_file")"
|
||||
fi
|
||||
|
||||
if [ -n "$file_size" ]; then
|
||||
say "Downloaded file size is $file_size bytes."
|
||||
|
||||
if [ -n "$remote_file_size" ] && [ -n "$file_size" ]; then
|
||||
if [ "$remote_file_size" -ne "$file_size" ]; then
|
||||
say "The remote and local file sizes are not equal. The remote file size is $remote_file_size bytes and the local size is $file_size bytes. The local package may be corrupted."
|
||||
else
|
||||
say "The remote and local file sizes are equal."
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
say "Either downloaded or local package size can not be measured. One of them may be corrupted."
|
||||
fi
|
||||
}
|
||||
|
||||
# args:
|
||||
# azure_feed - $1
|
||||
# channel - $2
|
||||
@ -860,6 +956,37 @@ get_absolute_path() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# args:
|
||||
# override - $1 (boolean, true or false)
|
||||
get_cp_options() {
|
||||
eval $invocation
|
||||
|
||||
local override="$1"
|
||||
local override_switch=""
|
||||
|
||||
if [ "$override" = false ]; then
|
||||
override_switch="-n"
|
||||
|
||||
# create temporary files to check if 'cp -u' is supported
|
||||
tmp_dir="$(mktemp -d)"
|
||||
tmp_file="$tmp_dir/testfile"
|
||||
tmp_file2="$tmp_dir/testfile2"
|
||||
|
||||
touch "$tmp_file"
|
||||
|
||||
# use -u instead of -n if it's available
|
||||
if cp -u "$tmp_file" "$tmp_file2" 2>/dev/null; then
|
||||
override_switch="-u"
|
||||
fi
|
||||
|
||||
# clean up
|
||||
rm -f "$tmp_file" "$tmp_file2"
|
||||
rm -rf "$tmp_dir"
|
||||
fi
|
||||
|
||||
echo "$override_switch"
|
||||
}
|
||||
|
||||
# args:
|
||||
# input_files - stdin
|
||||
# root_path - $1
|
||||
@ -871,15 +998,7 @@ copy_files_or_dirs_from_list() {
|
||||
local root_path="$(remove_trailing_slash "$1")"
|
||||
local out_path="$(remove_trailing_slash "$2")"
|
||||
local override="$3"
|
||||
local osname="$(get_current_os_name)"
|
||||
local override_switch=$(
|
||||
if [ "$override" = false ]; then
|
||||
if [ "$osname" = "linux-musl" ]; then
|
||||
printf -- "-u";
|
||||
else
|
||||
printf -- "-n";
|
||||
fi
|
||||
fi)
|
||||
local override_switch="$(get_cp_options "$override")"
|
||||
|
||||
cat | uniq | while read -r file_path; do
|
||||
local path="$(remove_beginning_slash "${file_path#$root_path}")"
|
||||
@ -894,14 +1013,39 @@ copy_files_or_dirs_from_list() {
|
||||
done
|
||||
}
|
||||
|
||||
# args:
|
||||
# zip_uri - $1
|
||||
get_remote_file_size() {
|
||||
local zip_uri="$1"
|
||||
|
||||
if machine_has "curl"; then
|
||||
file_size=$(curl -sI "$zip_uri" | grep -i content-length | awk '{ num = $2 + 0; print num }')
|
||||
elif machine_has "wget"; then
|
||||
file_size=$(wget --spider --server-response -O /dev/null "$zip_uri" 2>&1 | grep -i 'Content-Length:' | awk '{ num = $2 + 0; print num }')
|
||||
else
|
||||
say "Neither curl nor wget is available on this system."
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -n "$file_size" ]; then
|
||||
say "Remote file $zip_uri size is $file_size bytes."
|
||||
echo "$file_size"
|
||||
else
|
||||
say_verbose "Content-Length header was not extracted for $zip_uri."
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# args:
|
||||
# zip_path - $1
|
||||
# out_path - $2
|
||||
# remote_file_size - $3
|
||||
extract_dotnet_package() {
|
||||
eval $invocation
|
||||
|
||||
local zip_path="$1"
|
||||
local out_path="$2"
|
||||
local remote_file_size="$3"
|
||||
|
||||
local temp_out_path="$(mktemp -d "$temporary_file_template")"
|
||||
|
||||
@ -912,8 +1056,12 @@ extract_dotnet_package() {
|
||||
find "$temp_out_path" -type f | grep -Eo "$folders_with_version_regex" | sort | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" false
|
||||
find "$temp_out_path" -type f | grep -Ev "$folders_with_version_regex" | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" "$override_non_versioned_files"
|
||||
|
||||
validate_remote_local_file_sizes "$zip_path" "$remote_file_size"
|
||||
|
||||
rm -rf "$temp_out_path"
|
||||
rm -f "$zip_path" && say_verbose "Temporary zip file $zip_path was removed"
|
||||
if [ -z ${keep_zip+x} ]; then
|
||||
rm -f "$zip_path" && say_verbose "Temporary archive file $zip_path was removed"
|
||||
fi
|
||||
|
||||
if [ "$failed" = true ]; then
|
||||
say_err "Extraction failed"
|
||||
@ -1124,13 +1272,69 @@ downloadwget() {
|
||||
return 0
|
||||
}
|
||||
|
||||
extract_stem() {
|
||||
local url="$1"
|
||||
# extract the protocol
|
||||
proto="$(echo $1 | grep :// | sed -e's,^\(.*://\).*,\1,g')"
|
||||
# remove the protocol
|
||||
url="${1/$proto/}"
|
||||
# extract the path (if any) - since we know all of our feeds have a first path segment, we can skip the first one. otherwise we'd use -f2- to get the full path
|
||||
full_path="$(echo $url | grep / | cut -d/ -f2-)"
|
||||
path="$(echo $full_path | cut -d/ -f2-)"
|
||||
echo $path
|
||||
}
|
||||
|
||||
check_url_exists() {
|
||||
eval $invocation
|
||||
local url="$1"
|
||||
|
||||
local code=""
|
||||
if machine_has "curl"
|
||||
then
|
||||
code=$(curl --head -o /dev/null -w "%{http_code}" -s --fail "$url");
|
||||
elif machine_has "wget"
|
||||
then
|
||||
# get the http response, grab the status code
|
||||
server_response=$(wget -qO- --method=HEAD --server-response "$url" 2>&1)
|
||||
code=$(echo "$server_response" | grep "HTTP/" | awk '{print $2}')
|
||||
fi
|
||||
if [ $code = "200" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
sanitize_redirect_url() {
|
||||
eval $invocation
|
||||
|
||||
local url_stem
|
||||
url_stem=$(extract_stem "$1")
|
||||
say_verbose "Checking configured feeds for the asset at ${yellow:-}$url_stem${normal:-}"
|
||||
|
||||
for feed in "${feeds[@]}"
|
||||
do
|
||||
local trial_url="$feed/$url_stem"
|
||||
say_verbose "Checking ${yellow:-}$trial_url${normal:-}"
|
||||
if check_url_exists "$trial_url"; then
|
||||
say_verbose "Found a match at ${yellow:-}$trial_url${normal:-}"
|
||||
echo "$trial_url"
|
||||
return 0
|
||||
else
|
||||
say_verbose "No match at ${yellow:-}$trial_url${normal:-}"
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
get_download_link_from_aka_ms() {
|
||||
eval $invocation
|
||||
|
||||
#quality is not supported for LTS or current channel
|
||||
if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "current") ]]; then
|
||||
#quality is not supported for LTS or STS channel
|
||||
#STS maps to current
|
||||
if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "STS") ]]; then
|
||||
normalized_quality=""
|
||||
say_warning "Specifying quality for current or LTS channel is not supported, the quality will be ignored."
|
||||
say_warning "Specifying quality for STS or LTS channel is not supported, the quality will be ignored."
|
||||
fi
|
||||
|
||||
say_verbose "Retrieving primary payload URL from aka.ms for channel: '$normalized_channel', quality: '$normalized_quality', product: '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
|
||||
@ -1159,6 +1363,12 @@ get_download_link_from_aka_ms() {
|
||||
http_codes=$( echo "$response" | awk '$1 ~ /^HTTP/ {print $2}' )
|
||||
# They all need to be 301, otherwise some links are broken (except for the last, which is not a redirect but 200 or 404).
|
||||
broken_redirects=$( echo "$http_codes" | sed '$d' | grep -v '301' )
|
||||
# The response may end without final code 2xx/4xx/5xx somehow, e.g. network restrictions on www.bing.com causes redirecting to bing.com fails with connection refused.
|
||||
# In this case it should not exclude the last.
|
||||
last_http_code=$( echo "$http_codes" | tail -n 1 )
|
||||
if ! [[ $last_http_code =~ ^(2|4|5)[0-9][0-9]$ ]]; then
|
||||
broken_redirects=$( echo "$http_codes" | grep -v '301' )
|
||||
fi
|
||||
|
||||
# All HTTP codes are 301 (Moved Permanently), the redirect link exists.
|
||||
if [[ -z "$broken_redirects" ]]; then
|
||||
@ -1169,6 +1379,11 @@ get_download_link_from_aka_ms() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
sanitized_redirect_url=$(sanitize_redirect_url "$aka_ms_download_link")
|
||||
if [[ -n "$sanitized_redirect_url" ]]; then
|
||||
aka_ms_download_link="$sanitized_redirect_url"
|
||||
fi
|
||||
|
||||
say_verbose "The redirect location retrieved: '$aka_ms_download_link'."
|
||||
return 0
|
||||
else
|
||||
@ -1180,7 +1395,9 @@ get_download_link_from_aka_ms() {
|
||||
get_feeds_to_use()
|
||||
{
|
||||
feeds=(
|
||||
"https://builds.dotnet.microsoft.com/dotnet"
|
||||
"https://dotnetcli.azureedge.net/dotnet"
|
||||
"https://ci.dot.net/public"
|
||||
"https://dotnetbuilds.azureedge.net/public"
|
||||
)
|
||||
|
||||
@ -1239,7 +1456,7 @@ generate_akams_links() {
|
||||
|
||||
normalized_version="$(to_lowercase "$version")"
|
||||
if [[ "$normalized_version" != "latest" ]] && [ -n "$normalized_quality" ]; then
|
||||
say_err "Quality and Version options are not allowed to be specified simultaneously. See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#options for details."
|
||||
say_err "Quality and Version options are not allowed to be specified simultaneously. See https://learn.microsoft.com/dotnet/core/tools/dotnet-install-script#options for details."
|
||||
return 1
|
||||
fi
|
||||
|
||||
@ -1406,10 +1623,11 @@ install_dotnet() {
|
||||
eval $invocation
|
||||
local download_failed=false
|
||||
local download_completed=false
|
||||
local remote_file_size=0
|
||||
|
||||
mkdir -p "$install_root"
|
||||
zip_path="$(mktemp "$temporary_file_template")"
|
||||
say_verbose "Zip path: $zip_path"
|
||||
zip_path="${zip_path:-$(mktemp "$temporary_file_template")}"
|
||||
say_verbose "Archive path: $zip_path"
|
||||
|
||||
for link_index in "${!download_links[@]}"
|
||||
do
|
||||
@ -1433,7 +1651,7 @@ install_dotnet() {
|
||||
say "Failed to download $link_type link '$download_link': $download_error_msg"
|
||||
;;
|
||||
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 archive file $zip_path was removed"
|
||||
else
|
||||
download_completed=true
|
||||
break
|
||||
@ -1446,8 +1664,10 @@ install_dotnet() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
say "Extracting zip from $download_link"
|
||||
extract_dotnet_package "$zip_path" "$install_root" || return 1
|
||||
remote_file_size="$(get_remote_file_size "$download_link")"
|
||||
|
||||
say "Extracting archive from $download_link"
|
||||
extract_dotnet_package "$zip_path" "$install_root" "$remote_file_size" || return 1
|
||||
|
||||
# Check if the SDK version is installed; if not, fail the installation.
|
||||
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
|
||||
@ -1597,25 +1817,42 @@ do
|
||||
override_non_versioned_files=false
|
||||
non_dynamic_parameters+=" $name"
|
||||
;;
|
||||
--keep-zip|-[Kk]eep[Zz]ip)
|
||||
keep_zip=true
|
||||
non_dynamic_parameters+=" $name"
|
||||
;;
|
||||
--zip-path|-[Zz]ip[Pp]ath)
|
||||
shift
|
||||
zip_path="$1"
|
||||
;;
|
||||
-?|--?|-h|--help|-[Hh]elp)
|
||||
script_name="$(basename "$0")"
|
||||
script_name="dotnet-install.sh"
|
||||
echo ".NET Tools Installer"
|
||||
echo "Usage: $script_name [-c|--channel <CHANNEL>] [-v|--version <VERSION>] [-p|--prefix <DESTINATION>]"
|
||||
echo "Usage:"
|
||||
echo " # Install a .NET SDK of a given Quality from a given Channel"
|
||||
echo " $script_name [-c|--channel <CHANNEL>] [-q|--quality <QUALITY>]"
|
||||
echo " # Install a .NET SDK of a specific public version"
|
||||
echo " $script_name [-v|--version <VERSION>]"
|
||||
echo " $script_name -h|-?|--help"
|
||||
echo ""
|
||||
echo "$script_name is a simple command line interface for obtaining dotnet cli."
|
||||
echo " Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||
echo " - The SDK needs to be installed without user interaction and without admin rights."
|
||||
echo " - The SDK installation doesn't need to persist across multiple CI runs."
|
||||
echo " 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."
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -c,--channel <CHANNEL> Download from the channel specified, Defaults to \`$channel\`."
|
||||
echo " -Channel"
|
||||
echo " Possible values:"
|
||||
echo " - Current - most current release"
|
||||
echo " - LTS - most current supported release"
|
||||
echo " - STS - the most recent Standard Term Support release"
|
||||
echo " - LTS - the most recent Long Term Support release"
|
||||
echo " - 2-part version in a format A.B - represents a specific release"
|
||||
echo " examples: 2.0; 1.0"
|
||||
echo " - 3-part version in a format A.B.Cxx - represents a specific SDK release"
|
||||
echo " examples: 5.0.1xx, 5.0.2xx."
|
||||
echo " Supported since 5.0 release"
|
||||
echo " Warning: Value 'Current' is deprecated for the Channel parameter. Use 'STS' instead."
|
||||
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 " -Version"
|
||||
@ -1626,7 +1863,7 @@ do
|
||||
echo " -q,--quality <quality> Download the latest build of specified quality in the channel."
|
||||
echo " -Quality"
|
||||
echo " The possible values are: daily, signed, validated, preview, GA."
|
||||
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 STS 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 " 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."
|
||||
@ -1637,7 +1874,7 @@ do
|
||||
echo " -InstallDir"
|
||||
echo " --architecture <ARCHITECTURE> Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`."
|
||||
echo " --arch,-Architecture,-Arch"
|
||||
echo " Possible values: x64, arm, arm64 and s390x"
|
||||
echo " Possible values: x64, arm, arm64, s390x, ppc64le and loongarch64"
|
||||
echo " --os <system> Specifies operating system to be used when selecting the installer."
|
||||
echo " Overrides the OS determination approach used by the script. Supported values: osx, linux, linux-musl, freebsd, rhel.6."
|
||||
echo " In case any other value is provided, the platform will be determined by the script based on machine configuration."
|
||||
@ -1662,6 +1899,8 @@ do
|
||||
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
||||
echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
|
||||
echo " Note: global.json must have a value for 'SDK:Version'"
|
||||
echo " --keep-zip,-KeepZip If set, downloaded file is kept."
|
||||
echo " --zip-path, -ZipPath If set, downloaded file is stored at the specified path."
|
||||
echo " -?,--?,-h,--help,-Help Shows this help message"
|
||||
echo ""
|
||||
echo "Install Location:"
|
||||
@ -1680,10 +1919,10 @@ do
|
||||
shift
|
||||
done
|
||||
|
||||
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.\n"
|
||||
say_verbose "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
|
||||
say_verbose "- The SDK needs to be installed without user interaction and without admin rights."
|
||||
say_verbose "- The SDK installation doesn't need to persist across multiple CI runs."
|
||||
say_verbose "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.\n"
|
||||
|
||||
if [ "$internal" = true ] && [ -z "$(echo $feed_credential)" ]; then
|
||||
message="Provide credentials via --feed-credential parameter."
|
||||
@ -1716,5 +1955,5 @@ else
|
||||
fi
|
||||
|
||||
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, select your operating system and check the \"Dependencies\" section."
|
||||
say "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section."
|
||||
say "Installation finished successfully."
|
||||
|
Loading…
Reference in New Issue
Block a user