mirror of
				https://github.com/actions/setup-dotnet.git
				synced 2025-10-31 23:23:46 +00:00 
			
		
		
		
	Update installers scripts
This commit is contained in:
		
							parent
							
								
									b8ab602c41
								
							
						
					
					
						commit
						12194cb2cd
					
				
							
								
								
									
										579
									
								
								externals/install-dotnet.ps1
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										579
									
								
								externals/install-dotnet.ps1
									
									
									
									
										vendored
									
									
								
							| @ -16,15 +16,27 @@ | |||||||
|     - LTS - most current supported release |     - LTS - most current supported release | ||||||
|     - 2-part version in a format A.B - represents a specific release |     - 2-part version in a format A.B - represents a specific release | ||||||
|           examples: 2.0, 1.0 |           examples: 2.0, 1.0 | ||||||
|     - Branch name |     - 3-part version in a format A.B.Cxx - represents a specific SDK release | ||||||
|           examples: release/2.0.0, Master |           examples: 5.0.1xx, 5.0.2xx | ||||||
|     Note: The version parameter overrides the channel parameter. |           Supported since 5.0 release | ||||||
|  |     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.  | ||||||
|  |     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.      | ||||||
| .PARAMETER Version | .PARAMETER Version | ||||||
|     Default: latest |     Default: latest | ||||||
|     Represents a build version on specific channel. Possible values: |     Represents a build version on specific channel. Possible values: | ||||||
|     - latest - most latest build on specific channel |     - latest - most latest build on specific channel | ||||||
|     - 3-part version in a format A.B.C - represents specific version of build |     - 3-part version in a format A.B.C - represents specific version of build | ||||||
|           examples: 2.0.0-preview2-006120, 1.1.0 |           examples: 2.0.0-preview2-006120, 1.1.0 | ||||||
|  | .PARAMETER Internal | ||||||
|  |     Download internal builds. Requires providing credentials via -FeedCredential parameter. | ||||||
|  | .PARAMETER FeedCredential | ||||||
|  |     Token to access Azure feed. Used as a query string to append to the Azure feed. | ||||||
|  |     This parameter typically is not specified. | ||||||
| .PARAMETER InstallDir | .PARAMETER InstallDir | ||||||
|     Default: %LocalAppData%\Microsoft\dotnet |     Default: %LocalAppData%\Microsoft\dotnet | ||||||
|     Path to where to install dotnet. Note that binaries will be placed directly in a given directory. |     Path to where to install dotnet. Note that binaries will be placed directly in a given directory. | ||||||
| @ -59,9 +71,6 @@ | |||||||
| .PARAMETER UncachedFeed | .PARAMETER UncachedFeed | ||||||
|     This parameter typically is not changed by the user. |     This parameter typically is not changed by the user. | ||||||
|     It allows changing the URL for the Uncached feed used by this installer. |     It allows changing the URL for the Uncached feed used by this installer. | ||||||
| .PARAMETER FeedCredential |  | ||||||
|     Used as a query string to append to the Azure feed. |  | ||||||
|     It allows changing the URL to use non-public blob storage accounts. |  | ||||||
| .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 | ||||||
| @ -81,11 +90,12 @@ | |||||||
| [cmdletbinding()] | [cmdletbinding()] | ||||||
| param( | param( | ||||||
|    [string]$Channel="LTS", |    [string]$Channel="LTS", | ||||||
|  |    [string]$Quality, | ||||||
|    [string]$Version="Latest", |    [string]$Version="Latest", | ||||||
|  |    [switch]$Internal, | ||||||
|    [string]$JSonFile, |    [string]$JSonFile, | ||||||
|    [string]$InstallDir="<auto>", |    [string]$InstallDir="<auto>", | ||||||
|    [string]$Architecture="<auto>", |    [string]$Architecture="<auto>", | ||||||
|    [ValidateSet("dotnet", "aspnetcore", "windowsdesktop", IgnoreCase = $false)] |  | ||||||
|    [string]$Runtime, |    [string]$Runtime, | ||||||
|    [Obsolete("This parameter may be removed in a future version of this script. The recommended alternative is '-Runtime dotnet'.")] |    [Obsolete("This parameter may be removed in a future version of this script. The recommended alternative is '-Runtime dotnet'.")] | ||||||
|    [switch]$SharedRuntime, |    [switch]$SharedRuntime, | ||||||
| @ -205,7 +215,7 @@ function Get-Machine-Architecture() { | |||||||
| function Get-CLIArchitecture-From-Architecture([string]$Architecture) { | function Get-CLIArchitecture-From-Architecture([string]$Architecture) { | ||||||
|     Say-Invocation $MyInvocation |     Say-Invocation $MyInvocation | ||||||
| 
 | 
 | ||||||
|     switch ($Architecture.ToLower()) { |     switch ($Architecture.ToLowerInvariant()) { | ||||||
|         { $_ -eq "<auto>" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) } |         { $_ -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" } | ||||||
| @ -215,6 +225,53 @@ function Get-CLIArchitecture-From-Architecture([string]$Architecture) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | function Get-NormalizedQuality([string]$Quality) { | ||||||
|  |     Say-Invocation $MyInvocation | ||||||
|  | 
 | ||||||
|  |     if ([string]::IsNullOrEmpty($Quality)) { | ||||||
|  |         return "" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     switch ($Quality) { | ||||||
|  |         { @("daily", "signed", "validated", "preview") -contains $_ } { return $Quality.ToLowerInvariant() } | ||||||
|  |         #ga quality is available without specifying quality, so normalizing it to empty | ||||||
|  |         { $_ -eq "ga" } { return "" } | ||||||
|  |         default { throw "'$Quality' is not a supported value for -Quality option. Supported values are: daily, signed, validated, preview, ga. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues." } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function Get-NormalizedChannel([string]$Channel) { | ||||||
|  |     Say-Invocation $MyInvocation | ||||||
|  | 
 | ||||||
|  |     if ([string]::IsNullOrEmpty($Channel)) { | ||||||
|  |         return "" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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" } | ||||||
|  |         default { return $Channel.ToLowerInvariant() } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function Get-NormalizedProduct([string]$Runtime) { | ||||||
|  |     Say-Invocation $MyInvocation | ||||||
|  | 
 | ||||||
|  |     switch ($Runtime) { | ||||||
|  |         { $_ -eq "dotnet" } { return "dotnet-runtime" } | ||||||
|  |         { $_ -eq "aspnetcore" } { return "aspnetcore-runtime" } | ||||||
|  |         { $_ -eq "windowsdesktop" } { return "windowsdesktop-runtime" } | ||||||
|  |         { [string]::IsNullOrEmpty($_) } { return "dotnet-sdk" } | ||||||
|  |         default { throw "'$Runtime' is not a supported value for -Runtime option, supported values are: dotnet, aspnetcore, windowsdesktop. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues." } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| # The version text returned from the feeds is a 1-line or 2-line string: | # The version text returned from the feeds is a 1-line or 2-line string: | ||||||
| # For the SDK and the dotnet runtime (2 lines): | # For the SDK and the dotnet runtime (2 lines): | ||||||
| # Line 1: # commit_hash | # Line 1: # commit_hash | ||||||
| @ -243,7 +300,7 @@ function Load-Assembly([string] $Assembly) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function GetHTTPResponse([Uri] $Uri) | function GetHTTPResponse([Uri] $Uri, [bool]$HeaderOnly, [bool]$DisableRedirect, [bool]$DisableFeedCredential) | ||||||
| { | { | ||||||
|     Invoke-With-Retry( |     Invoke-With-Retry( | ||||||
|     { |     { | ||||||
| @ -270,26 +327,42 @@ function GetHTTPResponse([Uri] $Uri) | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler | ||||||
|             if($ProxyAddress) { |             if($ProxyAddress) { | ||||||
|                 $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler |  | ||||||
|                 $HttpClientHandler.Proxy =  New-Object System.Net.WebProxy -Property @{ |                 $HttpClientHandler.Proxy =  New-Object System.Net.WebProxy -Property @{ | ||||||
|                     Address=$ProxyAddress; |                     Address=$ProxyAddress; | ||||||
|                     UseDefaultCredentials=$ProxyUseDefaultCredentials; |                     UseDefaultCredentials=$ProxyUseDefaultCredentials; | ||||||
|                     BypassList = $ProxyBypassList; |                     BypassList = $ProxyBypassList; | ||||||
|                 } |                 } | ||||||
|                 $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler |             }        | ||||||
|  |             if ($DisableRedirect) | ||||||
|  |             { | ||||||
|  |                 $HttpClientHandler.AllowAutoRedirect = $false | ||||||
|             } |             } | ||||||
|             else { |             $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler | ||||||
| 
 | 
 | ||||||
|                 $HttpClient = New-Object System.Net.Http.HttpClient |  | ||||||
|             } |  | ||||||
|             # Default timeout for HttpClient is 100s.  For a 50 MB download this assumes 500 KB/s average, any less will time out |             # Default timeout for HttpClient is 100s.  For a 50 MB download this assumes 500 KB/s average, any less will time out | ||||||
|             # 20 minutes allows it to work over much slower connections. |             # 20 minutes allows it to work over much slower connections. | ||||||
|             $HttpClient.Timeout = New-TimeSpan -Minutes 20 |             $HttpClient.Timeout = New-TimeSpan -Minutes 20 | ||||||
|             $Task = $HttpClient.GetAsync("${Uri}${FeedCredential}").ConfigureAwait("false"); | 
 | ||||||
|  |             if ($HeaderOnly){ | ||||||
|  |                 $completionOption = [System.Net.Http.HttpCompletionOption]::ResponseHeadersRead | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 $completionOption = [System.Net.Http.HttpCompletionOption]::ResponseContentRead | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if ($DisableFeedCredential) { | ||||||
|  |                 $UriWithCredential = $Uri | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 $UriWithCredential = "${Uri}${FeedCredential}" | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             $Task = $HttpClient.GetAsync("$UriWithCredential", $completionOption).ConfigureAwait("false"); | ||||||
|             $Response = $Task.GetAwaiter().GetResult(); |             $Response = $Task.GetAwaiter().GetResult(); | ||||||
| 
 | 
 | ||||||
|             if (($null -eq $Response) -or (-not ($Response.IsSuccessStatusCode))) { |             if (($null -eq $Response) -or ((-not $HeaderOnly) -and (-not ($Response.IsSuccessStatusCode)))) { | ||||||
|                 # The feed credential is potentially sensitive info. Do not log FeedCredential to console output. |                 # The feed credential is potentially sensitive info. Do not log FeedCredential to console output. | ||||||
|                 $DownloadException = [System.Exception] "Unable to download $Uri." |                 $DownloadException = [System.Exception] "Unable to download $Uri." | ||||||
| 
 | 
 | ||||||
| @ -349,6 +422,9 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel) { | |||||||
|     else { |     else { | ||||||
|         throw "Invalid value for `$Runtime" |         throw "Invalid value for `$Runtime" | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     Say-Verbose "Constructed latest.version URL: $VersionFileUrl" | ||||||
|  | 
 | ||||||
|     try { |     try { | ||||||
|         $Response = GetHTTPResponse -Uri $VersionFileUrl |         $Response = GetHTTPResponse -Uri $VersionFileUrl | ||||||
|     } |     } | ||||||
| @ -411,7 +487,7 @@ function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, | |||||||
|     Say-Invocation $MyInvocation |     Say-Invocation $MyInvocation | ||||||
| 
 | 
 | ||||||
|     if (-not $JSonFile) { |     if (-not $JSonFile) { | ||||||
|         if ($Version.ToLower() -eq "latest") { |         if ($Version.ToLowerInvariant() -eq "latest") { | ||||||
|             $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel |             $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel | ||||||
|             return $LatestVersionInfo.Version |             return $LatestVersionInfo.Version | ||||||
|         } |         } | ||||||
| @ -478,58 +554,116 @@ function Get-LegacyDownload-Link([string]$AzureFeed, [string]$SpecificVersion, [ | |||||||
|     return $PayloadURL |     return $PayloadURL | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function Get-Product-Version([string]$AzureFeed, [string]$SpecificVersion) { | function Get-Product-Version([string]$AzureFeed, [string]$SpecificVersion, [string]$PackageDownloadLink) { | ||||||
|     Say-Invocation $MyInvocation |     Say-Invocation $MyInvocation | ||||||
| 
 | 
 | ||||||
|     if ($Runtime -eq "dotnet") { |     # Try to get the version number, using the productVersion.txt file located next to the installer file. | ||||||
|         $ProductVersionTxtURL = "$AzureFeed/Runtime/$SpecificVersion/productVersion.txt" |     $ProductVersionTxtURLs = (Get-Product-Version-Url $AzureFeed $SpecificVersion $PackageDownloadLink -Flattened $true), | ||||||
|     } |                              (Get-Product-Version-Url $AzureFeed $SpecificVersion $PackageDownloadLink -Flattened $false) | ||||||
|     elseif ($Runtime -eq "aspnetcore") { |      | ||||||
|         $ProductVersionTxtURL = "$AzureFeed/aspnetcore/Runtime/$SpecificVersion/productVersion.txt" |     Foreach ($ProductVersionTxtURL in $ProductVersionTxtURLs) { | ||||||
|     } |         Say-Verbose "Checking for the existence of $ProductVersionTxtURL" | ||||||
|     elseif ($Runtime -eq "windowsdesktop") { | 
 | ||||||
|         # The windows desktop runtime is part of the core runtime layout prior to 5.0 |         try { | ||||||
|         $ProductVersionTxtURL = "$AzureFeed/Runtime/$SpecificVersion/productVersion.txt" |             $productVersionResponse = GetHTTPResponse($productVersionTxtUrl) | ||||||
|         if ($SpecificVersion -match '^(\d+)\.(.*)') | 
 | ||||||
|         { |             if ($productVersionResponse.StatusCode -eq 200) { | ||||||
|             $majorVersion = [int]$Matches[1] |                 $productVersion = $productVersionResponse.Content.ReadAsStringAsync().Result.Trim() | ||||||
|             if ($majorVersion -ge 5) |                 if ($productVersion -ne $SpecificVersion) | ||||||
|             { |                 { | ||||||
|                 $ProductVersionTxtURL = "$AzureFeed/WindowsDesktop/$SpecificVersion/productVersion.txt" |                     Say "Using alternate version $productVersion found in $ProductVersionTxtURL" | ||||||
|  |                 } | ||||||
|  |                 return $productVersion | ||||||
|             } |             } | ||||||
|  |             else { | ||||||
|  |                 Say-Verbose "Got StatusCode $($productVersionResponse.StatusCode) when trying to get productVersion.txt at $productVersionTxtUrl." | ||||||
|  |             } | ||||||
|  |         }  | ||||||
|  |         catch { | ||||||
|  |             Say-Verbose "Could not read productVersion.txt at $productVersionTxtUrl (Exception: '$($_.Exception.Message)'. )" | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     elseif (-not $Runtime) { | 
 | ||||||
|         $ProductVersionTxtURL = "$AzureFeed/Sdk/$SpecificVersion/productVersion.txt" |     # Getting the version number with productVersion.txt has failed. Try parsing the download link for a version number. | ||||||
|     } |     if ([string]::IsNullOrEmpty($PackageDownloadLink)) | ||||||
|     else { |     { | ||||||
|         throw "Invalid value '$Runtime' specified for `$Runtime" |         Say-Verbose "Using the default value '$SpecificVersion' as the product version." | ||||||
|  |         return $SpecificVersion | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Say-Verbose "Checking for existence of $ProductVersionTxtURL" |     $productVersion = Get-ProductVersionFromDownloadLink $PackageDownloadLink $SpecificVersion | ||||||
|  |     return $productVersion | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     try { | function Get-Product-Version-Url([string]$AzureFeed, [string]$SpecificVersion, [string]$PackageDownloadLink, [bool]$Flattened) { | ||||||
|         $productVersionResponse = GetHTTPResponse($productVersionTxtUrl) |     Say-Invocation $MyInvocation | ||||||
| 
 | 
 | ||||||
|         if ($productVersionResponse.StatusCode -eq 200) { |     $majorVersion=$null | ||||||
|             $productVersion = $productVersionResponse.Content.ReadAsStringAsync().Result.Trim() |     if ($SpecificVersion -match '^(\d+)\.(.*)') { | ||||||
|             if ($productVersion -ne $SpecificVersion) |         $majorVersion = $Matches[1] -as[int] | ||||||
|             { |     } | ||||||
|                 Say "Using alternate version $productVersion found in $ProductVersionTxtURL" |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             return $productVersion |     $pvFileName='productVersion.txt' | ||||||
|  |     if($Flattened) { | ||||||
|  |         if(-not $Runtime) { | ||||||
|  |             $pvFileName='sdk-productVersion.txt' | ||||||
|  |         } | ||||||
|  |         elseif($Runtime -eq "dotnet") { | ||||||
|  |             $pvFileName='runtime-productVersion.txt' | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             Say-Verbose "Got StatusCode $($productVersionResponse.StatusCode) trying to get productVersion.txt at $productVersionTxtUrl, so using default value of $SpecificVersion" |             $pvFileName="$Runtime-productVersion.txt" | ||||||
|             $productVersion = $SpecificVersion |  | ||||||
|         } |         } | ||||||
|     } catch { |  | ||||||
|         Say-Verbose "Could not read productVersion.txt at $productVersionTxtUrl, so using default value of $SpecificVersion (Exception: '$($_.Exception.Message)' )" |  | ||||||
|         $productVersion = $SpecificVersion |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return $productVersion |     if ([string]::IsNullOrEmpty($PackageDownloadLink)) { | ||||||
|  |         if ($Runtime -eq "dotnet") { | ||||||
|  |             $ProductVersionTxtURL = "$AzureFeed/Runtime/$SpecificVersion/$pvFileName" | ||||||
|  |         } | ||||||
|  |         elseif ($Runtime -eq "aspnetcore") { | ||||||
|  |             $ProductVersionTxtURL = "$AzureFeed/aspnetcore/Runtime/$SpecificVersion/$pvFileName" | ||||||
|  |         } | ||||||
|  |         elseif ($Runtime -eq "windowsdesktop") { | ||||||
|  |             # The windows desktop runtime is part of the core runtime layout prior to 5.0 | ||||||
|  |             $ProductVersionTxtURL = "$AzureFeed/Runtime/$SpecificVersion/$pvFileName" | ||||||
|  |             if ($majorVersion -ne $null -and $majorVersion -ge 5) { | ||||||
|  |                 $ProductVersionTxtURL = "$AzureFeed/WindowsDesktop/$SpecificVersion/$pvFileName" | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         elseif (-not $Runtime) { | ||||||
|  |             $ProductVersionTxtURL = "$AzureFeed/Sdk/$SpecificVersion/$pvFileName" | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             throw "Invalid value '$Runtime' specified for `$Runtime" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         $ProductVersionTxtURL = $PackageDownloadLink.Substring(0, $PackageDownloadLink.LastIndexOf("/"))  + "/$pvFileName" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Say-Verbose "Constructed productVersion link: $ProductVersionTxtURL" | ||||||
|  | 
 | ||||||
|  |     return $ProductVersionTxtURL | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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) | ||||||
|  |     { | ||||||
|  |         $productVersion = $filenameParts[2] | ||||||
|  |         Say-Verbose "Extracted product version '$productVersion' from download link '$PackageDownloadLink'." | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         Say-Verbose "Using the default value '$SpecificVersion' as the product version." | ||||||
|  |         $productVersion = $SpecificVersion | ||||||
|  |     } | ||||||
|  |     return $productVersion  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function Get-User-Share-Path() { | function Get-User-Share-Path() { | ||||||
| @ -702,15 +836,150 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolde | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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 = "" | ||||||
|  |         Say-Warning "Specifying quality for current 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'."  | ||||||
|  |     | ||||||
|  |     #construct aka.ms link | ||||||
|  |     $akaMsLink = "https://aka.ms/dotnet" | ||||||
|  |     if ($Internal) { | ||||||
|  |         $akaMsLink += "/internal" | ||||||
|  |     } | ||||||
|  |     $akaMsLink += "/$Channel" | ||||||
|  |     if (-not [string]::IsNullOrEmpty($Quality)) { | ||||||
|  |         $akaMsLink +="/$Quality" | ||||||
|  |     } | ||||||
|  |     $akaMsLink +="/$Product-win-$Architecture.zip" | ||||||
|  |     Say-Verbose  "Constructed aka.ms link: '$akaMsLink'." | ||||||
|  |     $akaMsDownloadLink=$null | ||||||
|  | 
 | ||||||
|  |     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 | ||||||
|  |         Say-Verbose "Received response:`n$Response" | ||||||
|  | 
 | ||||||
|  |         if ([string]::IsNullOrEmpty($Response)) { | ||||||
|  |             Say-Verbose "The link '$akaMsLink' is not valid: failed to get redirect location. The resource is not available." | ||||||
|  |             return $null | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #if HTTP code is 301 (Moved Permanently), the redirect link exists | ||||||
|  |         if  ($Response.StatusCode -eq 301) | ||||||
|  |         { | ||||||
|  |             try { | ||||||
|  |                 $akaMsDownloadLink = $Response.Headers.GetValues("Location")[0] | ||||||
|  | 
 | ||||||
|  |                 if ([string]::IsNullOrEmpty($akaMsDownloadLink)) { | ||||||
|  |                     Say-Verbose "The link '$akaMsLink' is not valid: server returned 301 (Moved Permanently), but the headers do not contain the redirect location." | ||||||
|  |                     return $null | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 Say-Verbose "The redirect location retrieved: '$akaMsDownloadLink'." | ||||||
|  |                 # This may yet be a link to another redirection. Attempt to retrieve the page again. | ||||||
|  |                 $akaMsLink = $akaMsDownloadLink | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|  |             catch { | ||||||
|  |                 Say-Verbose "The link '$akaMsLink' is not valid: failed to get redirect location." | ||||||
|  |                 return $null | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         elseif ((($Response.StatusCode -lt 300) -or ($Response.StatusCode -ge 400)) -and (-not [string]::IsNullOrEmpty($akaMsDownloadLink))) | ||||||
|  |         { | ||||||
|  |             # Redirections have ended. | ||||||
|  |             return $akaMsDownloadLink | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Say-Verbose "The link '$akaMsLink' is not valid: failed to retrieve the redirection location." | ||||||
|  |         return $null | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Say-Verbose "Aka.ms links have redirected more than the maximum allowed redirections. This may be caused by a cyclic redirection of aka.ms links." | ||||||
|  |     return $null | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 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." | ||||||
| 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" | 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 | $CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture | ||||||
| $SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -JSonFile $JSonFile | $NormalizedQuality = Get-NormalizedQuality $Quality | ||||||
| $DownloadLink, $EffectiveVersion = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture | Say-Verbose "Normalized quality: '$NormalizedQuality'" | ||||||
| $LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture | $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 (-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 '$NormalizedProduct', os: 'win', architecture: '$CLIArchitecture'." | ||||||
|  |             Say-Error "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support." | ||||||
|  |             throw "aka.ms link resolution failure" | ||||||
|  |         } | ||||||
|  |         Say-Verbose "Falling back to latest.version file approach." | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         Say-Verbose "Retrieved primary named payload URL from aka.ms link: '$AkaMsDownloadLink'." | ||||||
|  |         $DownloadLink = $AkaMsDownloadLink | ||||||
|  |         Say-Verbose  "Downloading using legacy url will not be attempted." | ||||||
|  |         $LegacyDownloadLink = $null | ||||||
|  | 
 | ||||||
|  |         #get version from the path | ||||||
|  |         $pathParts = $DownloadLink.Split('/') | ||||||
|  |         if ($pathParts.Length -ge 2) {  | ||||||
|  |             $SpecificVersion = $pathParts[$pathParts.Length - 2] | ||||||
|  |             Say-Verbose "Version: '$SpecificVersion'." | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             Say-Error "Failed to extract the version from download link '$DownloadLink'." | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #retrieve effective (product) version | ||||||
|  |         $EffectiveVersion = Get-Product-Version -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -PackageDownloadLink $DownloadLink | ||||||
|  |         Say-Verbose "Product version: '$EffectiveVersion'." | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | if ([string]::IsNullOrEmpty($DownloadLink)) { | ||||||
|  |     $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 | $InstallRoot = Resolve-Installation-Path $InstallDir | ||||||
| Say-Verbose "InstallRoot: $InstallRoot" | Say-Verbose "InstallRoot: $InstallRoot" | ||||||
| @ -718,9 +987,9 @@ $ScriptName = $MyInvocation.MyCommand.Name | |||||||
| 
 | 
 | ||||||
| if ($DryRun) { | if ($DryRun) { | ||||||
|     Say "Payload URLs:" |     Say "Payload URLs:" | ||||||
|     Say "Primary named payload URL: $DownloadLink" |     Say "Primary named payload URL: ${DownloadLink}" | ||||||
|     if ($LegacyDownloadLink) { |     if ($LegacyDownloadLink) { | ||||||
|         Say "Legacy named payload URL: $LegacyDownloadLink" |         Say "Legacy named payload URL: ${LegacyDownloadLink}" | ||||||
|     } |     } | ||||||
|     $RepeatableCommand = ".\$ScriptName -Version `"$SpecificVersion`" -InstallDir `"$InstallRoot`" -Architecture `"$CLIArchitecture`"" |     $RepeatableCommand = ".\$ScriptName -Version `"$SpecificVersion`" -InstallDir `"$InstallRoot`" -Architecture `"$CLIArchitecture`"" | ||||||
|     if ($Runtime -eq "dotnet") { |     if ($Runtime -eq "dotnet") { | ||||||
| @ -729,11 +998,20 @@ if ($DryRun) { | |||||||
|     elseif ($Runtime -eq "aspnetcore") { |     elseif ($Runtime -eq "aspnetcore") { | ||||||
|        $RepeatableCommand+=" -Runtime `"aspnetcore`"" |        $RepeatableCommand+=" -Runtime `"aspnetcore`"" | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     if (-not [string]::IsNullOrEmpty($NormalizedQuality)) | ||||||
|  |     { | ||||||
|  |         $RepeatableCommand+=" -Quality `"$NormalizedQuality`"" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     foreach ($key in $MyInvocation.BoundParameters.Keys) { |     foreach ($key in $MyInvocation.BoundParameters.Keys) { | ||||||
|         if (-not (@("Architecture","Channel","DryRun","InstallDir","Runtime","SharedRuntime","Version") -contains $key)) { |         if (-not (@("Architecture","Channel","DryRun","InstallDir","Runtime","SharedRuntime","Version","Quality","FeedCredential") -contains $key)) { | ||||||
|             $RepeatableCommand+=" -$key `"$($MyInvocation.BoundParameters[$key])`"" |             $RepeatableCommand+=" -$key `"$($MyInvocation.BoundParameters[$key])`"" | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     if ($MyInvocation.BoundParameters.Keys -contains "FeedCredential") { | ||||||
|  |         $RepeatableCommand+=" -FeedCredential `"<feedCredential>`"" | ||||||
|  |     } | ||||||
|     Say "Repeatable invocation: $RepeatableCommand" |     Say "Repeatable invocation: $RepeatableCommand" | ||||||
|     if ($SpecificVersion -ne $EffectiveVersion) |     if ($SpecificVersion -ne $EffectiveVersion) | ||||||
|     { |     { | ||||||
| @ -779,9 +1057,16 @@ if ($isAssetInstalled) { | |||||||
| 
 | 
 | ||||||
| New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null | New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null | ||||||
| 
 | 
 | ||||||
| $installDrive = $((Get-Item $InstallRoot).PSDrive.Name); | $installDrive = $((Get-Item $InstallRoot -Force).PSDrive.Name); | ||||||
| $diskInfo = Get-PSDrive -Name $installDrive | $diskInfo = $null | ||||||
| if ($diskInfo.Free / 1MB -le 100) { | 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." | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | if ( ($diskInfo -ne $null) -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}:" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -902,42 +1187,42 @@ 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 | ||||||
| # MIIjjwYJKoZIhvcNAQcCoIIjgDCCI3wCAQExDzANBglghkgBZQMEAgEFADB5Bgor | # MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor | ||||||
| # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG | ||||||
| # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCNsnhcJvx/hXmM | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAGF/0aIv/nK8pL | ||||||
| # w8KjuvvIMDBFonhg9XJFc1QwfTyH4aCCDYEwggX/MIID56ADAgECAhMzAAABh3IX | # ube4cwR/nwps7FSM0D5vjXxuQe3LXaCCDYEwggX/MIID56ADAgECAhMzAAAB32vw | ||||||
| # chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD | # LpKnSrTQAAAAAAHfMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD | ||||||
| # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy | # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy | ||||||
| # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p | # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p | ||||||
| # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw | # bmcgUENBIDIwMTEwHhcNMjAxMjE1MjEzMTQ1WhcNMjExMjAyMjEzMTQ1WjB0MQsw | ||||||
| # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u | # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u | ||||||
| # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy | # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy | ||||||
| # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB | # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB | ||||||
| # AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB | # AQC2uxlZEACjqfHkuFyoCwfL25ofI9DZWKt4wEj3JBQ48GPt1UsDv834CcoUUPMn | ||||||
| # znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH | # s/6CtPoaQ4Thy/kbOOg/zJAnrJeiMQqRe2Lsdb/NSI2gXXX9lad1/yPUDOXo4GNw | ||||||
| # sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d | # PjXq1JZi+HZV91bUr6ZjzePj1g+bepsqd/HC1XScj0fT3aAxLRykJSzExEBmU9eS | ||||||
| # weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ | # yuOwUuq+CriudQtWGMdJU650v/KmzfM46Y6lo/MCnnpvz3zEL7PMdUdwqj/nYhGG | ||||||
| # itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV | # 3UVILxX7tAdMbz7LN+6WOIpT1A41rwaoOVnv+8Ua94HwhjZmu1S73yeV7RZZNxoh | ||||||
| # Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE | # EegJi9YYssXa7UZUUkCCA+KnAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE | ||||||
| # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw | # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUOPbML8IdkNGtCfMmVPtvI6VZ8+Mw | ||||||
| # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 | # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 | ||||||
| # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu | # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDYzMDA5MB8GA1UdIwQYMBaAFEhu | ||||||
| # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu | # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu | ||||||
| # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w | # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w | ||||||
| # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 | # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 | ||||||
| # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx | # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx | ||||||
| # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy | # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAnnqH | ||||||
| # S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K | # tDyYUFaVAkvAK0eqq6nhoL95SZQu3RnpZ7tdQ89QR3++7A+4hrr7V4xxmkB5BObS | ||||||
| # NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV | # 0YK+MALE02atjwWgPdpYQ68WdLGroJZHkbZdgERG+7tETFl3aKF4KpoSaGOskZXp | ||||||
| # BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr | # TPnCaMo2PXoAMVMGpsQEQswimZq3IQ3nRQfBlJ0PoMMcN/+Pks8ZTL1BoPYsJpok | ||||||
| # qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx | # t6cql59q6CypZYIwgyJ892HpttybHKg1ZtQLUlSXccRMlugPgEcNZJagPEgPYni4 | ||||||
| # zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe | # b11snjRAgf0dyQ0zI9aLXqTxWUU5pCIFiPT0b2wsxzRqCtyGqpkGM8P9GazO8eao | ||||||
| # yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g | # mVItCYBcJSByBx/pS0cSYwBBHAZxJODUqxSXoSGDvmTfqUJXntnWkL4okok1FiCD | ||||||
| # yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf | # Z4jpyXOQunb6egIXvkgQ7jb2uO26Ow0m8RwleDvhOMrnHsupiOPbozKroSa6paFt | ||||||
| # AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI | # VSh89abUSooR8QdZciemmoFhcWkEwFg4spzvYNP4nIs193261WyTaRMZoceGun7G | ||||||
| # 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 | # CT2Rl653uUj+F+g94c63AhzSq4khdL4HlFIP2ePv29smfUnHtGq6yYFDLnT0q/Y+ | ||||||
| # GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea | # Di3jwloF8EWkkHRtSuXlFUbTmwr/lDDgbpZiKhLS7CBTDj32I0L5i532+uHczw82 | ||||||
| # jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS | # oZDmYmYmIUSMbZOgS65h797rj5JJ6OkeEUJoAVwwggd6MIIFYqADAgECAgphDpDS | ||||||
| # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK | # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK | ||||||
| # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 | # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 | ||||||
| # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 | # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 | ||||||
| @ -977,55 +1262,55 @@ 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/BvW1taslScxMNelDNMYIVZDCCFWACAQEwgZUwfjELMAkG | # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG | ||||||
| # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx | # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx | ||||||
| # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z | # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z | ||||||
| # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN | # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAd9r8C6Sp0q00AAAAAAB3zAN | ||||||
| # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor | # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor | ||||||
| # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgpT/bxWwe | # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgJROF4V78 | ||||||
| # aW0EinKMWCAzDXUjwXkIHldYzR6lw4/1Pc0wQgYKKwYBBAGCNwIBDDE0MDKgFIAS | # d/qQulLV5Z+ncgFZgk9r0UoE37o5jTCDpSowQgYKKwYBBAGCNwIBDDE0MDKgFIAS | ||||||
| # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN | # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN | ||||||
| # BgkqhkiG9w0BAQEFAASCAQCHd7sSQVq0YDg8QDx6/kLWn3s6jtvvIDCCgsO9spHM | # BgkqhkiG9w0BAQEFAASCAQB74lkh+M6W7qWNERtX5/xMFrSgaVCptxuBlBl93FN3 | ||||||
| # quPd4FPbG67DCsKDClekQs52qrtRO3Zo+JMnCw4j3bS+gZHzeJr2shbftOrpsFoD | # aQJiCaToMeDXG3Nsf/GhIFCBz4fReYrMmZg5pmjs+d8s1dgXz2oOWVwx6bhnzdXS | ||||||
| # l7OPcUmtrqul9dkQCOp8t0MP3ls0n96/YyNy6lz4BAlTdkdDx957uAxalKaCIBzb | # ce5dMqkUCzvN4QeJxTIhpeXsHwupWVbuqeTo5DdZHouTi4UFzgM0/K+sSbRI/FEe | ||||||
| # R9QyppOKIfNFvwD4EI5KI6tpmSy/uH8SrRg7ZExAYZl6J6R18WkL7KHn649lPoAQ | # rS/vxtMbrtMz57kKjB/Z86dKJeDxQydKSapL/YIamfmYx26rjpXJqEs7W+FVRJwK | ||||||
| # ujwrIXH10xOJops45ILGzKWQcHmCzLJGYapL4VHUuK+73nT+9ZROGHdk/PyvIcdw | # nNNT0OGt7tdkL6k+7XQtK3f5yUqKMdTlmPyZ73z69tAtJclkIFC3liFVTMAf4MK+ | ||||||
| # iERa+C06v305t3DA+CuHFy1tvyw7IFF6RVbLZPwxrJjToYIS7jCCEuoGCisGAQQB | # nheQal7OPNth86h4Lek3E19n2hrABTUeW2cLZ2WWEspFoYIS8TCCEu0GCisGAQQB | ||||||
| # gjcDAwExghLaMIIS1gYJKoZIhvcNAQcCoIISxzCCEsMCAQMxDzANBglghkgBZQME | # gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME | ||||||
| # AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB | # AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB | ||||||
| # MDEwDQYJYIZIAWUDBAIBBQAEIOCaTmvM1AP0WaEVqzKaaCu/R+bTlR4kCrM/ZXsb | # MDEwDQYJYIZIAWUDBAIBBQAEIEIDAx5adVXZRJeNOj9JW7M03Sl8XvjtY9M98TvW | ||||||
| # /eNOAgZgGeLsMwsYEzIwMjEwMjAzMjExNzQ5LjU5MVowBIACAfSggdSkgdEwgc4x | # cUwSAgZgieWmNfwYEzIwMjEwNTE5MTcwMDI4LjY0OVowBIACAfSggdSkgdEwgc4x | ||||||
| # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt | # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt | ||||||
| # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p | # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p | ||||||
| # Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg | # Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg | ||||||
| # VFNTIEVTTjo4OTdBLUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt | # VFNTIEVTTjpEOURFLUUzOUEtNDNGRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt | ||||||
| # U3RhbXAgU2VydmljZaCCDkEwggT1MIID3aADAgECAhMzAAABLCKvRZd1+RvuAAAA | # U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABYfWiM16gKiRpAAAA | ||||||
| # AAEsMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo | # AAFhMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo | ||||||
| # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y | # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y | ||||||
| # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw | # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw | ||||||
| # MB4XDTE5MTIxOTAxMTUwM1oXDTIxMDMxNzAxMTUwM1owgc4xCzAJBgNVBAYTAlVT | # MB4XDTIxMDExNDE5MDIyMVoXDTIyMDQxMTE5MDIyMVowgc4xCzAJBgNVBAYTAlVT | ||||||
| # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK | # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK | ||||||
| # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy | # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy | ||||||
| # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4OTdB | # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpEOURF | ||||||
| # LUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj | # LUUzOUEtNDNGRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj | ||||||
| # ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPK1zgSSq+MxAYo3qpCt | # ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJeInahBrU//GzTqhxUy | ||||||
| # QDxSMPPJy6mm/wfEJNjNUnYtLFBwl1BUS5trEk/t41ldxITKehs+ABxYqo4Qxsg3 | # AC8UXct6UJCkb2xEZKV3gjggmLAheBrxJk7tH+Pw2tTcyarLRfmV2xo5oBk5pW/O | ||||||
| # Gy1ugKiwHAnYiiekfC+ZhptNFgtnDZIn45zC0AlVr/6UfLtsLcHCh1XElLUHfEC0 | # cDc/n/TcTeQU6JIN5PlTcn0C9RlKQ6t9OuU/WAyAxGTjKE4ENnUjXtxiNlD/K2ZG | ||||||
| # nBuQcM/SpYo9e3l1qY5NdMgDGxCsmCKdiZfYXIu+U0UYIBhdzmSHnB3fxZOBVcr5 | # MLvjpROBKh7TtkUJK6ZGWw/uTRabNBxRg13TvjkGHXEUEDJ8imacw9BCeR9L6und | ||||||
| # htFHEBBNt/rFJlm/A4yb8oBsp+Uf0p5QwmO/bCcdqB15JpylOhZmWs0sUfJKlK9E | # r32tj4duOFIHD8m1es3SNN98Zq4IDBP3Ccb+HQgxpbeHIUlK0y6zmzIkvfN73Zxw | ||||||
| # rAhBwGki2eIRFKsQBdkXS9PWpF1w2gIJRvSkDEaCf+lbGTPdSzHSbfREWOF9wY3i | # fGvFv0/Max79WJY0cD8poCnZFijciWrf0eD1T2/+7HgewzrdxPdSFockUQ8QovID | ||||||
| # Yj8CAwEAAaOCARswggEXMB0GA1UdDgQWBBRRahZSGfrCQhCyIyGH9DkiaW7L0zAf | # IYkCAwEAAaOCARswggEXMB0GA1UdDgQWBBRWHpqd1hv71SVj5LAdPfNE7PhLLzAf | ||||||
| # BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH | # BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH | ||||||
| # hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU | # hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU | ||||||
| # aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF | # aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF | ||||||
| # BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0 | # BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0 | ||||||
| # YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG | # YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG | ||||||
| # AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBPFxHIwi4vAH49w9Svmz6K3tM55RlW | # AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQAQTA9bqVBmx5TTMhzj+Q8zWkPQXgCc | ||||||
| # 5pPeULXdut2Rqy6Ys0+VpZsbuaEoxs6Z1C3hMbkiqZFxxyltxJpuHTyGTg61zfNI | # SQiqy2YYWF0hWr5GEiN2LtA+EWdu1y8oysZau4CP7SzM8VTSq31CLJiOy39Z4RvE | ||||||
| # F5n6RsYF3s7IElDXNfZznF1/2iWc6uRPZK8rxxUJ/7emYXZCYwuUY0XjsCpP9pbR | # q2mr0EftFvmX2CxQ7ZyzrkhWMZaZQLkYbH5oabIFwndW34nh980BOY395tfnNS/Y | ||||||
| # RKeJi6r5arSyI+NfKxvgoM21JNt1BcdlXuAecdd/k8UjxCscffanoK2n6LFw1PcZ | # 6N0f+jXdoFn7fI2c43TFYsUqIPWjOHJloMektlD6/uS6Zn4xse/lItFm+fWOcB2A | ||||||
| # lEO7NId7o+soM2C0QY5BYdghpn7uqopB6ixyFIIkDXFub+1E7GmAEwfU6VwEHL7y | # xyXEB3ZREeSg9j7+GoEl1xT/iJuV/So7TlWdwyacQu4lv3MBsvxzRIbKhZwrDYog | ||||||
| # 9rNE8bd+JrQs+yAtkkHy9FmXg/PsGq1daVzX1So7CJ6nyphpuHSN3VfTMIIGcTCC | # moyJ+rwgQB8mKS4/M1SDRtIptamoTFJ56Tk6DuUXx1JudToelgjEZPa5MIIGcTCC | ||||||
| # BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC | # BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC | ||||||
| # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV | # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV | ||||||
| # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv | # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv | ||||||
| @ -1060,36 +1345,36 @@ Say "Installation finished" | |||||||
| # cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a | # cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a | ||||||
| # KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ | # KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ | ||||||
| # cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+ | # cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+ | ||||||
| # NR4Iuto229Nfj950iEkSoYICzzCCAjgCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT | # NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT | ||||||
| # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD | # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD | ||||||
| # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP | # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP | ||||||
| # cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4 | # cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpE | ||||||
| # OTdBLUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy | # OURFLUUzOUEtNDNGRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy | ||||||
| # dmljZaIjCgEBMAcGBSsOAwIaAxUADE5OKSMoNx/mYxYWap1RTOohbJ2ggYMwgYCk | # dmljZaIjCgEBMAcGBSsOAwIaAxUAFW5ShAw5ekTEXvL/4V1s0rbDz3mggYMwgYCk | ||||||
| # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH | ||||||
| # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD | # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD | ||||||
| # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF | # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF | ||||||
| # AOPFChkwIhgPMjAyMTAyMDMxNTQwMDlaGA8yMDIxMDIwNDE1NDAwOVowdDA6Bgor | # AORPamMwIhgPMjAyMTA1MTkxNDQzNDdaGA8yMDIxMDUyMDE0NDM0N1owdzA9Bgor | ||||||
| # BgEEAYRZCgQBMSwwKjAKAgUA48UKGQIBADAHAgEAAgIXmDAHAgEAAgIRyTAKAgUA | # BgEEAYRZCgQBMS8wLTAKAgUA5E9qYwIBADAKAgEAAgIYCAIB/zAHAgEAAgIRJjAK | ||||||
| # 48ZbmQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID | # AgUA5FC74wIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB | ||||||
| # B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAHeeznL2n6HWCjHH94Fl | # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAEP3zVlXXAn4O1Ms | ||||||
| # hcdW6TEXzq4XNgp1Gx1W9F8gJ4x+SwoV7elJZkwgGffcpHomLvIY/VSuzsl1NgtJ | # 68s11f0LWnsKutmWLnJls7YN9alFuA+jJcq/S8x2VoJAWAZTdWtdT5N7Gf/BeTAe | ||||||
| # TWM2UxoqSv58BBOrl4eGhH6kkg8Ucy2tdeK5T8cHa8pMkq2j9pFd2mRG/6VMk0dl | # 8D0krUvAYkKN9sIFxBsV9Zum88+HNP6X3yn+CD+ZzOlhtqvgG+fuuRXPutLZfLc/ | ||||||
| # Xz7Uy3Z6bZqkcABMyAfuAaGbMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMx | # BMw0pVKop8ty4t9o1C5cghIH1n8uMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC | ||||||
| # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT | # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV | ||||||
| # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt | # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp | ||||||
| # U3RhbXAgUENBIDIwMTACEzMAAAEsIq9Fl3X5G+4AAAAAASwwDQYJYIZIAWUDBAIB | # bWUtU3RhbXAgUENBIDIwMTACEzMAAAFh9aIzXqAqJGkAAAAAAWEwDQYJYIZIAWUD | ||||||
| # BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx | # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B | ||||||
| # IgQg/QYv7yp+354WTjWUIsXWndTEzXjaYjqwYjcBxCJKjdUwgfoGCyqGSIb3DQEJ | # CQQxIgQgYzAzV5OthXnPmIpD3kPIVmwz+sGvwSbjTEW5rOqHhyUwgfoGCyqGSIb3 | ||||||
| # EAIvMYHqMIHnMIHkMIG9BCBbn/0uFFh42hTM5XOoKdXevBaiSxmYK9Ilcn9nu5ZH | # DQEJEAIvMYHqMIHnMIHkMIG9BCBhz4un6mkSLd/zA+0N5YLDGp4vW/VBtNW/lpmh | ||||||
| # 4TCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw | # tAk4bzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u | ||||||
| # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x | # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp | ||||||
| # JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABLCKv | # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB | ||||||
| # RZd1+RvuAAAAAAEsMCIEIIfIM3YbzHswb/Kj/qq1l1cHA6QBl+gEXYanUNJomrpT | # YfWiM16gKiRpAAAAAAFhMCIEIArbvJb5j55rDAQa7Rx5K7mjnxUY6RgiRY1AROOp | ||||||
| # MA0GCSqGSIb3DQEBCwUABIIBAAwdcXssUZGO7ho5+NHLjIxLtQk543aKGo+lrRMY | # m2rLMA0GCSqGSIb3DQEBCwUABIIBAFS544uO7FOimzTwMDkFNhMT7GmZBc9L2wDF | ||||||
| # Q9abE1h/AaaNJl0iGxX4IihNWyfovSfYL3L4eODUBAu68tWSxeceRfWNsb/ZZfUi | # EjcDlHvcdELdWpqa8Au6rCdhW6618btwdFqR7fkNMH7F0TrY1ktOae5fZUaybIRV | ||||||
| # v89hpLssI/Gf1BEgNMA4zCuIGQiC8okusVumEpAhhvCEbSiTTTtBdolTnU/CAKui | # EMWAAqXLkVyePlssQamjt1+BYvxzYFh3T5JBr2R/rzaGJIck49r1cEsLBV0JaSQT | ||||||
| # oxaU3R9XkKh1F4oAM26+dJ1J2BLQXPs5afNvvedDsZWNQUPK1sFF3JRfzxiTrwBW | # QKiOsR+QEbSCNWXQaq/koJrKR5Ugro0y4SmSejnOj5+1/4PlTolFoJAM4pIiT2A1 | ||||||
| # EJRyflev9gyDoqCHzippgb+6+eti1WTkcA9Q49GIT11S6LOAVqkSC9N7Nqf8ksh8 | # uMs5f219BvkwyRmF32z9EpYQvBdoGpT65DQDuZQ5F6wV1Ph4H7yOzarcdnwPohT+ | ||||||
| # ARdwT8jigpsm+mj7lrVU9upDkhVYhKeO8oiZq95Q53Zkteo= | # BeH2jrcR3BMAxC3umgRUmTxnzPsoq9FJuRTyHCNygGn+VMImNfk= | ||||||
| # SIG # End signature block | # SIG # End signature block | ||||||
|  | |||||||
							
								
								
									
										428
									
								
								externals/install-dotnet.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										428
									
								
								externals/install-dotnet.sh
									
									
									
									
										vendored
									
									
								
							| @ -24,7 +24,7 @@ exec 3>&1 | |||||||
| # See if stdout is a terminal | # See if stdout is a terminal | ||||||
| if [ -t 1 ] && command -v tput > /dev/null; then | if [ -t 1 ] && command -v tput > /dev/null; then | ||||||
|     # see if it supports colors |     # see if it supports colors | ||||||
|     ncolors=$(tput colors) |     ncolors=$(tput colors || echo 0) | ||||||
|     if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then |     if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then | ||||||
|         bold="$(tput bold       || echo)" |         bold="$(tput bold       || echo)" | ||||||
|         normal="$(tput sgr0     || echo)" |         normal="$(tput sgr0     || echo)" | ||||||
| @ -368,6 +368,75 @@ get_normalized_os() { | |||||||
|     return 0 |     return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | # args: | ||||||
|  | # quality - $1 | ||||||
|  | get_normalized_quality() { | ||||||
|  |     eval $invocation | ||||||
|  | 
 | ||||||
|  |     local quality="$(to_lowercase "$1")" | ||||||
|  |     if [ ! -z "$quality" ]; then | ||||||
|  |         case "$quality" in | ||||||
|  |             daily | signed | validated | preview) | ||||||
|  |                 echo "$quality" | ||||||
|  |                 return 0 | ||||||
|  |                 ;; | ||||||
|  |             ga) | ||||||
|  |                 #ga quality is available without specifying quality, so normalizing it to empty | ||||||
|  |                 return 0 | ||||||
|  |                 ;; | ||||||
|  |             *) | ||||||
|  |                 say_err "'$quality' is not a supported value for --quality option. Supported values are: daily, signed, validated, preview, ga. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues." | ||||||
|  |                 return 1 | ||||||
|  |                 ;; | ||||||
|  |         esac | ||||||
|  |     fi | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # args: | ||||||
|  | # channel - $1 | ||||||
|  | get_normalized_channel() { | ||||||
|  |     eval $invocation | ||||||
|  | 
 | ||||||
|  |     local channel="$(to_lowercase "$1")" | ||||||
|  | 
 | ||||||
|  |     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 | ||||||
|  | 
 | ||||||
|  |     if [ ! -z "$channel" ]; then | ||||||
|  |         case "$channel" in | ||||||
|  |             lts) | ||||||
|  |                 echo "LTS" | ||||||
|  |                 return 0 | ||||||
|  |                 ;; | ||||||
|  |             *) | ||||||
|  |                 echo "$channel" | ||||||
|  |                 return 0 | ||||||
|  |                 ;; | ||||||
|  |         esac | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # args: | ||||||
|  | # runtime - $1 | ||||||
|  | get_normalized_product() { | ||||||
|  |     eval $invocation | ||||||
|  | 
 | ||||||
|  |     local runtime="$(to_lowercase "$1")" | ||||||
|  |     if [[ "$runtime" == "dotnet" ]]; then | ||||||
|  |         product="dotnet-runtime" | ||||||
|  |     elif [[ "$runtime" == "aspnetcore" ]]; then | ||||||
|  |         product="aspnetcore-runtime" | ||||||
|  |     elif [ -z "$runtime" ]; then | ||||||
|  |         product="dotnet-sdk" | ||||||
|  |     fi | ||||||
|  |     echo "$product" | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| # The version text returned from the feeds is a 1-line or 2-line string: | # The version text returned from the feeds is a 1-line or 2-line string: | ||||||
| # For the SDK and the dotnet runtime (2 lines): | # For the SDK and the dotnet runtime (2 lines): | ||||||
| # Line 1: # commit_hash | # Line 1: # commit_hash | ||||||
| @ -541,43 +610,131 @@ construct_download_link() { | |||||||
| # args: | # args: | ||||||
| # azure_feed - $1 | # azure_feed - $1 | ||||||
| # specific_version - $2 | # specific_version - $2 | ||||||
|  | # download link - $3 (optional) | ||||||
| get_specific_product_version() { | get_specific_product_version() { | ||||||
|     # If we find a 'productVersion.txt' at the root of any folder, we'll use its contents |     # If we find a 'productVersion.txt' at the root of any folder, we'll use its contents | ||||||
|     # to resolve the version of what's in the folder, superseding the specified version. |     # to resolve the version of what's in the folder, superseding the specified version. | ||||||
|  |     # if 'productVersion.txt' is missing but download link is already available, product version will be taken from download link | ||||||
|     eval $invocation |     eval $invocation | ||||||
| 
 | 
 | ||||||
|     local azure_feed="$1" |     local azure_feed="$1" | ||||||
|     local specific_version="${2//[$'\t\r\n']}" |     local specific_version="${2//[$'\t\r\n']}" | ||||||
|     local specific_product_version=$specific_version |     local package_download_link="" | ||||||
|  |     if [ $# -gt 2  ]; then | ||||||
|  |         local package_download_link="$3" | ||||||
|  |     fi | ||||||
|  |     local specific_product_version=null | ||||||
|  | 
 | ||||||
|  |     # Try to get the version number, using the productVersion.txt file located next to the installer file. | ||||||
|  |     local download_links=($(get_specific_product_version_url "$azure_feed" "$specific_version" true "$package_download_link") | ||||||
|  |         $(get_specific_product_version_url "$azure_feed" "$specific_version" false "$package_download_link")) | ||||||
|  | 
 | ||||||
|  |     for download_link in "${download_links[@]}" | ||||||
|  |     do | ||||||
|  |         say_verbose "Checking for the existence of $download_link" | ||||||
|  | 
 | ||||||
|  |         if machine_has "curl" | ||||||
|  |         then | ||||||
|  |             specific_product_version=$(curl -s --fail "${download_link}${feed_credential}") | ||||||
|  |             if [ $? = 0 ]; then | ||||||
|  |                 echo "${specific_product_version//[$'\t\r\n']}" | ||||||
|  |                 return 0 | ||||||
|  |             fi | ||||||
|  |         elif machine_has "wget" | ||||||
|  |         then | ||||||
|  |             specific_product_version=$(wget -qO- "${download_link}${feed_credential}") | ||||||
|  |             if [ $? = 0 ]; then | ||||||
|  |                 echo "${specific_product_version//[$'\t\r\n']}" | ||||||
|  |                 return 0 | ||||||
|  |             fi | ||||||
|  |         fi | ||||||
|  |     done | ||||||
|  |      | ||||||
|  |     # Getting the version number with productVersion.txt has failed. Try parsing the download link for a version number. | ||||||
|  |     say_verbose "Failed to get the version using productVersion.txt file. Download link will be parsed instead." | ||||||
|  |     specific_product_version="$(get_product_specific_version_from_download_link "$package_download_link" "$specific_version")" | ||||||
|  |     echo "${specific_product_version//[$'\t\r\n']}" | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # args: | ||||||
|  | # azure_feed - $1 | ||||||
|  | # specific_version - $2 | ||||||
|  | # is_flattened - $3 | ||||||
|  | # download link - $4 (optional) | ||||||
|  | get_specific_product_version_url() { | ||||||
|  |     eval $invocation | ||||||
|  | 
 | ||||||
|  |     local azure_feed="$1" | ||||||
|  |     local specific_version="$2" | ||||||
|  |     local is_flattened="$3" | ||||||
|  |     local package_download_link="" | ||||||
|  |     if [ $# -gt 3  ]; then | ||||||
|  |         local package_download_link="$4" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     local pvFileName="productVersion.txt" | ||||||
|  |     if [ "$is_flattened" = true ]; then | ||||||
|  |         if [ -z "$runtime" ]; then | ||||||
|  |             pvFileName="sdk-productVersion.txt" | ||||||
|  |         elif [[ "$runtime" == "dotnet" ]]; then | ||||||
|  |             pvFileName="runtime-productVersion.txt" | ||||||
|  |         else | ||||||
|  |             pvFileName="$runtime-productVersion.txt" | ||||||
|  |         fi | ||||||
|  |     fi | ||||||
| 
 | 
 | ||||||
|     local download_link=null |     local download_link=null | ||||||
|     if [[ "$runtime" == "dotnet" ]]; then | 
 | ||||||
|         download_link="$azure_feed/Runtime/$specific_version/productVersion.txt${feed_credential}" |     if [ -z "$package_download_link" ]; then | ||||||
|     elif [[ "$runtime" == "aspnetcore" ]]; then |         if [[ "$runtime" == "dotnet" ]]; then | ||||||
|         download_link="$azure_feed/aspnetcore/Runtime/$specific_version/productVersion.txt${feed_credential}" |             download_link="$azure_feed/Runtime/$specific_version/${pvFileName}" | ||||||
|     elif [ -z "$runtime" ]; then |         elif [[ "$runtime" == "aspnetcore" ]]; then | ||||||
|         download_link="$azure_feed/Sdk/$specific_version/productVersion.txt${feed_credential}" |             download_link="$azure_feed/aspnetcore/Runtime/$specific_version/${pvFileName}" | ||||||
|  |         elif [ -z "$runtime" ]; then | ||||||
|  |             download_link="$azure_feed/Sdk/$specific_version/${pvFileName}" | ||||||
|  |         else | ||||||
|  |             return 1 | ||||||
|  |         fi | ||||||
|     else |     else | ||||||
|         return 1 |         download_link="${package_download_link%/*}/${pvFileName}" | ||||||
|     fi |     fi | ||||||
| 
 | 
 | ||||||
|     if machine_has "curl" |     say_verbose "Constructed productVersion link: $download_link" | ||||||
|     then |     echo "$download_link" | ||||||
|         specific_product_version=$(curl -s --fail "$download_link") |     return 0 | ||||||
|         if [ $? -ne 0 ] | } | ||||||
|         then |  | ||||||
|             specific_product_version=$specific_version |  | ||||||
|         fi |  | ||||||
|     elif machine_has "wget" |  | ||||||
|     then |  | ||||||
|         specific_product_version=$(wget -qO- "$download_link") |  | ||||||
|         if [ $? -ne 0 ] |  | ||||||
|         then |  | ||||||
|             specific_product_version=$specific_version |  | ||||||
|         fi |  | ||||||
|     fi |  | ||||||
|     specific_product_version="${specific_product_version//[$'\t\r\n']}" |  | ||||||
| 
 | 
 | ||||||
|  | # args: | ||||||
|  | # download link - $1 | ||||||
|  | # specific version - $2 | ||||||
|  | get_product_specific_version_from_download_link() | ||||||
|  | { | ||||||
|  |     eval $invocation | ||||||
|  | 
 | ||||||
|  |     local download_link="$1" | ||||||
|  |     local specific_version="$2" | ||||||
|  |     local specific_product_version=""  | ||||||
|  | 
 | ||||||
|  |     if [ -z "$download_link" ]; then | ||||||
|  |         echo "$specific_version" | ||||||
|  |         return 0 | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     #get filename | ||||||
|  |     filename="${download_link##*/}" | ||||||
|  | 
 | ||||||
|  |     #product specific version follows the product name | ||||||
|  |     #for filename 'dotnet-sdk-3.1.404-linux-x64.tar.gz': the product version is 3.1.404 | ||||||
|  |     IFS='-' | ||||||
|  |     read -ra filename_elems <<< "$filename" | ||||||
|  |     count=${#filename_elems[@]} | ||||||
|  |     if [[ "$count" -gt 2 ]]; then | ||||||
|  |         specific_product_version="${filename_elems[2]}" | ||||||
|  |     else | ||||||
|  |         specific_product_version=$specific_version | ||||||
|  |     fi | ||||||
|  |     unset IFS; | ||||||
|     echo "$specific_product_version" |     echo "$specific_product_version" | ||||||
|     return 0 |     return 0 | ||||||
| } | } | ||||||
| @ -711,19 +868,62 @@ extract_dotnet_package() { | |||||||
|     return 0 |     return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | # args: | ||||||
|  | # remote_path - $1 | ||||||
|  | # disable_feed_credential - $2 | ||||||
|  | get_http_header() | ||||||
|  | { | ||||||
|  |     eval $invocation | ||||||
|  |     local remote_path="$1" | ||||||
|  |     local disable_feed_credential="$2" | ||||||
|  | 
 | ||||||
|  |     local failed=false | ||||||
|  |     local response | ||||||
|  |     if machine_has "curl"; then | ||||||
|  |         get_http_header_curl $remote_path $disable_feed_credential || failed=true | ||||||
|  |     elif machine_has "wget"; then | ||||||
|  |         get_http_header_wget $remote_path $disable_feed_credential || failed=true | ||||||
|  |     else | ||||||
|  |         failed=true | ||||||
|  |     fi | ||||||
|  |     if [ "$failed" = true ]; then | ||||||
|  |         say_verbose "Failed to get HTTP header: '$remote_path'." | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # args: | ||||||
|  | # remote_path - $1 | ||||||
|  | # disable_feed_credential - $2 | ||||||
| get_http_header_curl() { | get_http_header_curl() { | ||||||
|     eval $invocation |     eval $invocation | ||||||
|     local remote_path="$1" |     local remote_path="$1" | ||||||
|     remote_path_with_credential="${remote_path}${feed_credential}" |     local disable_feed_credential="$2" | ||||||
|  | 
 | ||||||
|  |     remote_path_with_credential="$remote_path" | ||||||
|  |     if [ "$disable_feed_credential" = false ]; then | ||||||
|  |         remote_path_with_credential+="$feed_credential" | ||||||
|  |     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" || return 1 | ||||||
|     return 0 |     return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | # args: | ||||||
|  | # remote_path - $1 | ||||||
|  | # disable_feed_credential - $2 | ||||||
| get_http_header_wget() { | get_http_header_wget() { | ||||||
|     eval $invocation |     eval $invocation | ||||||
|     local remote_path="$1" |     local remote_path="$1" | ||||||
|     remote_path_with_credential="${remote_path}${feed_credential}" |     local disable_feed_credential="$2" | ||||||
|  | 
 | ||||||
|  |     remote_path_with_credential="$remote_path" | ||||||
|  |     if [ "$disable_feed_credential" = false ]; then | ||||||
|  |         remote_path_with_credential+="$feed_credential" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|     wget_options="-q -S --spider --tries 5 --waitretry 2 --connect-timeout 15 " |     wget_options="-q -S --spider --tries 5 --waitretry 2 --connect-timeout 15 " | ||||||
|     wget $wget_options "$remote_path_with_credential" 2>&1 || return 1 |     wget $wget_options "$remote_path_with_credential" 2>&1 || return 1 | ||||||
|     return 0 |     return 0 | ||||||
| @ -763,7 +963,7 @@ download() { | |||||||
| 
 | 
 | ||||||
|         say "Download attempt #$attempts has failed: $http_code $download_error_msg" |         say "Download attempt #$attempts has failed: $http_code $download_error_msg" | ||||||
|         say "Attempt #$((attempts+1)) will start in $((attempts*10)) seconds." |         say "Attempt #$((attempts+1)) will start in $((attempts*10)) seconds." | ||||||
|         sleep $((attempts*20)) |         sleep $((attempts*10)) | ||||||
|     done |     done | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -783,6 +983,7 @@ downloadcurl() { | |||||||
|     local remote_path="$1" |     local remote_path="$1" | ||||||
|     local out_path="${2:-}" |     local out_path="${2:-}" | ||||||
|     # Append feed_credential as late as possible before calling curl to avoid logging feed_credential |     # Append feed_credential as late as possible before calling curl to avoid logging feed_credential | ||||||
|  |     # Avoid passing URI with credentials to functions: note, most of them echoing parameters of invocation in verbose output. | ||||||
|     local remote_path_with_credential="${remote_path}${feed_credential}" |     local remote_path_with_credential="${remote_path}${feed_credential}" | ||||||
|     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 | ||||||
| @ -792,7 +993,8 @@ downloadcurl() { | |||||||
|         curl $curl_options -o "$out_path" "$remote_path_with_credential" || failed=true |         curl $curl_options -o "$out_path" "$remote_path_with_credential" || failed=true | ||||||
|     fi |     fi | ||||||
|     if [ "$failed" = true ]; then |     if [ "$failed" = true ]; then | ||||||
|         local response=$(get_http_header_curl $remote_path_with_credential) |         local disable_feed_credential=false | ||||||
|  |         local response=$(get_http_header_curl $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 ) | ||||||
|         download_error_msg="Unable to download $remote_path." |         download_error_msg="Unable to download $remote_path." | ||||||
|         if  [[ $http_code != 2* ]]; then |         if  [[ $http_code != 2* ]]; then | ||||||
| @ -822,7 +1024,8 @@ downloadwget() { | |||||||
|         wget $wget_options -O "$out_path" "$remote_path_with_credential" || failed=true |         wget $wget_options -O "$out_path" "$remote_path_with_credential" || failed=true | ||||||
|     fi |     fi | ||||||
|     if [ "$failed" = true ]; then |     if [ "$failed" = true ]; then | ||||||
|         local response=$(get_http_header_wget $remote_path_with_credential) |         local disable_feed_credential=false | ||||||
|  |         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 ) | ||||||
|         download_error_msg="Unable to download $remote_path." |         download_error_msg="Unable to download $remote_path." | ||||||
|         if  [[ $http_code != 2* ]]; then |         if  [[ $http_code != 2* ]]; then | ||||||
| @ -834,15 +1037,115 @@ downloadwget() { | |||||||
|     return 0 |     return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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 | ||||||
|  |         normalized_quality="" | ||||||
|  |         say_warning "Specifying quality for current 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'."  | ||||||
|  | 
 | ||||||
|  |     #construct aka.ms link | ||||||
|  |     aka_ms_link="https://aka.ms/dotnet" | ||||||
|  |     if  [ "$internal" = true ]; then | ||||||
|  |         aka_ms_link="$aka_ms_link/internal" | ||||||
|  |     fi | ||||||
|  |     aka_ms_link="$aka_ms_link/$normalized_channel" | ||||||
|  |     if [[ ! -z "$normalized_quality" ]]; then | ||||||
|  |         aka_ms_link="$aka_ms_link/$normalized_quality" | ||||||
|  |     fi | ||||||
|  |     aka_ms_link="$aka_ms_link/$normalized_product-$normalized_os-$normalized_architecture.tar.gz" | ||||||
|  |     say_verbose "Constructed aka.ms link: '$aka_ms_link'." | ||||||
|  | 
 | ||||||
|  |     #get HTTP response | ||||||
|  |     #do not pass credentials as a part of the $aka_ms_link and do not apply credentials in the get_http_header 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 | ||||||
|  |     disable_feed_credential=true | ||||||
|  |     response="$(get_http_header $aka_ms_link $disable_feed_credential)" | ||||||
|  | 
 | ||||||
|  |     say_verbose "Received response: $response" | ||||||
|  |     # Get results of all the redirects. | ||||||
|  |     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' ) | ||||||
|  | 
 | ||||||
|  |     # All HTTP codes are 301 (Moved Permanently), the redirect link exists. | ||||||
|  |     if [[ -z "$broken_redirects" ]]; then | ||||||
|  |         aka_ms_download_link=$( echo "$response" | awk '$1 ~ /^Location/{print $2}' | tail -1 | tr -d '\r') | ||||||
|  | 
 | ||||||
|  |         if [[ -z "$aka_ms_download_link" ]]; then | ||||||
|  |             say_verbose "The aka.ms link '$aka_ms_link' is not valid: failed to get redirect location." | ||||||
|  |             return 1 | ||||||
|  |         fi | ||||||
|  | 
 | ||||||
|  |         say_verbose "The redirect location retrieved: '$aka_ms_download_link'." | ||||||
|  |         return 0 | ||||||
|  |     else | ||||||
|  |         say_verbose "The aka.ms link '$aka_ms_link' is not valid: received HTTP code: $(echo "$broken_redirects" | paste -sd "," -)." | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
| calculate_vars() { | calculate_vars() { | ||||||
|     eval $invocation |     eval $invocation | ||||||
|     valid_legacy_download_link=true |     valid_legacy_download_link=true | ||||||
| 
 | 
 | ||||||
|  |     #normalize input variables | ||||||
|     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")" | ||||||
|     say_verbose "normalized_os=$normalized_os" |     say_verbose "Normalized OS: '$normalized_os'." | ||||||
|  |     normalized_quality="$(get_normalized_quality "$quality")" | ||||||
|  |     say_verbose "Normalized quality: '$normalized_quality'." | ||||||
|  |     normalized_channel="$(get_normalized_channel "$channel")" | ||||||
|  |     say_verbose "Normalized channel: '$normalized_channel'." | ||||||
|  |     normalized_product="$(get_normalized_product "$runtime")" | ||||||
|  |     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")" | ||||||
|  |                 say_verbose "InstallRoot: '$install_root'." | ||||||
|  |                 return  | ||||||
|  |             fi | ||||||
|  |     fi | ||||||
| 
 | 
 | ||||||
|     specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")" |     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")" |     specific_product_version="$(get_specific_product_version "$azure_feed" "$specific_version")" | ||||||
| @ -1011,6 +1314,8 @@ feed_credential="" | |||||||
| verbose=false | verbose=false | ||||||
| runtime="" | runtime="" | ||||||
| runtime_id="" | runtime_id="" | ||||||
|  | quality="" | ||||||
|  | internal=false | ||||||
| override_non_versioned_files=true | override_non_versioned_files=true | ||||||
| non_dynamic_parameters="" | non_dynamic_parameters="" | ||||||
| user_defined_os="" | user_defined_os="" | ||||||
| @ -1027,6 +1332,14 @@ do | |||||||
|             shift |             shift | ||||||
|             version="$1" |             version="$1" | ||||||
|             ;; |             ;; | ||||||
|  |         -q|--quality|-[Qq]uality) | ||||||
|  |             shift | ||||||
|  |             quality="$1" | ||||||
|  |             ;; | ||||||
|  |         --internal|-[Ii]nternal) | ||||||
|  |             internal=true | ||||||
|  |             non_dynamic_parameters+=" $name" | ||||||
|  |             ;; | ||||||
|         -i|--install-dir|-[Ii]nstall[Dd]ir) |         -i|--install-dir|-[Ii]nstall[Dd]ir) | ||||||
|             shift |             shift | ||||||
|             install_dir="$1" |             install_dir="$1" | ||||||
| @ -1084,7 +1397,9 @@ do | |||||||
|         --feed-credential|-[Ff]eed[Cc]redential) |         --feed-credential|-[Ff]eed[Cc]redential) | ||||||
|             shift |             shift | ||||||
|             feed_credential="$1" |             feed_credential="$1" | ||||||
|             non_dynamic_parameters+=" $name "\""$1"\""" |             #feed_credential should start with "?", for it to be added to the end of the link. | ||||||
|  |             #adding "?" at the beginning of the feed_credential if needed. | ||||||
|  |             [[ -z "$(echo $feed_credential)" ]] || [[ $feed_credential == \?* ]] || feed_credential="?$feed_credential" | ||||||
|             ;; |             ;; | ||||||
|         --runtime-id|-[Rr]untime[Ii]d) |         --runtime-id|-[Rr]untime[Ii]d) | ||||||
|             shift |             shift | ||||||
| @ -1116,15 +1431,26 @@ do | |||||||
|             echo "          - LTS - most current supported release" |             echo "          - LTS - most current supported release" | ||||||
|             echo "          - 2-part version in a format A.B - represents a specific release" |             echo "          - 2-part version in a format A.B - represents a specific release" | ||||||
|             echo "              examples: 2.0; 1.0" |             echo "              examples: 2.0; 1.0" | ||||||
|             echo "          - Branch name" |             echo "          - 3-part version in a format A.B.Cxx - represents a specific SDK release" | ||||||
|             echo "              examples: release/2.0.0; Master" |             echo "              examples: 5.0.1xx, 5.0.2xx." | ||||||
|             echo "          Note: The version parameter overrides the channel parameter." |             echo "              Supported since 5.0 release" | ||||||
|  |             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:" | ||||||
|             echo "          - latest - most latest build on specific channel" |             echo "          - latest - most latest build on specific channel" | ||||||
|             echo "          - 3-part version in a format A.B.C - represents specific version of build" |             echo "          - 3-part version in a format A.B.C - represents specific version of build" | ||||||
|             echo "              examples: 2.0.0-preview2-006120; 1.1.0" |             echo "              examples: 2.0.0-preview2-006120; 1.1.0" | ||||||
|  |             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 "          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." | ||||||
|  |             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 "      -FeedCredential                This parameter typically is not specified." | ||||||
|             echo "  -i,--install-dir <DIR>             Install under specified location (see Install Location below)" |             echo "  -i,--install-dir <DIR>             Install under specified location (see Install Location below)" | ||||||
|             echo "      -InstallDir" |             echo "      -InstallDir" | ||||||
|             echo "  --architecture <ARCHITECTURE>      Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`." |             echo "  --architecture <ARCHITECTURE>      Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`." | ||||||
| @ -1145,7 +1471,6 @@ do | |||||||
|             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            Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user." | ||||||
|             echo "  --uncached-feed,-UncachedFeed      Uncached feed location. This parameter typically is not changed by the user." |             echo "  --uncached-feed,-UncachedFeed      Uncached feed location. This parameter typically is not changed by the user." | ||||||
|             echo "  --feed-credential,-FeedCredential  Azure feed shared access token. This parameter typically is not specified." |  | ||||||
|             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." | ||||||
| @ -1186,23 +1511,44 @@ say "- The SDK needs to be installed without user interaction and without admin | |||||||
| 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." | ||||||
| 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 "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." | ||||||
|  |     if [ "$dry_run" = true ]; then | ||||||
|  |         say_warning "$message" | ||||||
|  |     else | ||||||
|  |         say_err "$message" | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  | fi | ||||||
|  | 
 | ||||||
| check_min_reqs | check_min_reqs | ||||||
| calculate_vars | calculate_vars | ||||||
| script_name=$(basename "$0") | script_name=$(basename "$0") | ||||||
| 
 | 
 | ||||||
| if [ "$dry_run" = true ]; then | if [ "$dry_run" = true ]; then | ||||||
|     say "Payload URLs:" |     say "Payload URLs:" | ||||||
|     say "Primary named payload URL: $download_link" |     say "Primary named payload URL: ${download_link}" | ||||||
|     if [ "$valid_legacy_download_link" = true ]; then |     if [ "$valid_legacy_download_link" = true ]; then | ||||||
|         say "Legacy named payload URL: $legacy_download_link" |         say "Legacy named payload URL: ${legacy_download_link}" | ||||||
|     fi |     fi | ||||||
|     repeatable_command="./$script_name --version "\""$specific_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\""" |     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 |     if [[ "$runtime" == "dotnet" ]]; then | ||||||
|         repeatable_command+=" --runtime "\""dotnet"\""" |         repeatable_command+=" --runtime "\""dotnet"\""" | ||||||
|     elif [[ "$runtime" == "aspnetcore" ]]; then |     elif [[ "$runtime" == "aspnetcore" ]]; then | ||||||
|         repeatable_command+=" --runtime "\""aspnetcore"\""" |         repeatable_command+=" --runtime "\""aspnetcore"\""" | ||||||
|     fi |     fi | ||||||
|  | 
 | ||||||
|     repeatable_command+="$non_dynamic_parameters" |     repeatable_command+="$non_dynamic_parameters" | ||||||
|  | 
 | ||||||
|  |     if [ -n "$feed_credential" ]; then | ||||||
|  |         repeatable_command+=" --feed-credential "\""<feed_credential>"\""" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|     say "Repeatable invocation: $repeatable_command" |     say "Repeatable invocation: $repeatable_command" | ||||||
|     exit 0 |     exit 0 | ||||||
| fi | fi | ||||||
| @ -1219,4 +1565,4 @@ fi | |||||||
| 
 | 
 | ||||||
| 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, select your operating system and check the \"Dependencies\" section." | 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 "Installation finished successfully." | say "Installation finished successfully." | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user