diff --git a/scripts/get-dotnetup.ps1 b/scripts/get-dotnetup.ps1 index 078d9b4938ef..c1dd1373b37c 100755 --- a/scripts/get-dotnetup.ps1 +++ b/scripts/get-dotnetup.ps1 @@ -140,6 +140,37 @@ function Get-RuntimeId { # --- Main --- +# Map a 'channel' such as 'daily' to specific version url for the binary and its .sha512 to prevent release race condition mismatches +function Resolve-FinalUrl([string]$Url) { + # Require an actual curl executable; on Windows PowerShell 5.1 'curl' is an alias for Invoke-WebRequest, so -CommandType Application excludes it. + $curl = Get-Command curl.exe -CommandType Application -ErrorAction SilentlyContinue + if (-not $curl) { $curl = Get-Command curl -CommandType Application -ErrorAction SilentlyContinue } + if ($curl) { + $sink = [System.IO.Path]::GetTempFileName() + try { + # --head resolves redirects without downloading the body. + $final = & $curl.Source --silent --show-error --location --head ` + --output $sink --write-out '%{url_effective}' $Url 2>$null + if ($LASTEXITCODE -eq 0 -and $final) { return "$final".Trim() } + } + catch { } + finally { Remove-Item $sink -Force -ErrorAction SilentlyContinue } + } + + # Fallback for hosts without a curl executable (e.g. Windows PowerShell 5.1): + try { + $req = [System.Net.WebRequest]::Create($Url) + $req.Method = "HEAD" + $req.AllowAutoRedirect = $true + $resp = $req.GetResponse() + try { return $resp.ResponseUri.AbsoluteUri } + finally { $resp.Dispose() } + } + catch { + return $null + } +} + $rid = Get-RuntimeId Write-Host "Detected runtime: $rid" -ForegroundColor Cyan @@ -148,6 +179,17 @@ $fileName = if ($rid -like "win-*") { "dotnetup-$rid.exe" } else { "dotnetup-$ri $downloadUrl = "$BaseUrl/$fileName" $checksumUrl = "$downloadUrl.sha512" +$resolvedUrl = Resolve-FinalUrl $downloadUrl +if ($resolvedUrl -and $resolvedUrl -like "*/public/*") { + Write-Host "Resolved '$Quality' to concrete build: $resolvedUrl" -ForegroundColor DarkGray + $downloadUrl = $resolvedUrl + # Checksums live under the sibling 'public-checksums' path with a .sha512 suffix. + $checksumUrl = ($resolvedUrl -replace '/public/', '/public-checksums/') + ".sha512" +} +else { + Write-Host "Could not resolve '$Quality' shortlink to a concrete build; using shortlink URLs directly." -ForegroundColor DarkGray +} + $tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "dotnetup-install-$([System.IO.Path]::GetRandomFileName())" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null diff --git a/scripts/get-dotnetup.sh b/scripts/get-dotnetup.sh index a3556d0d56fe..76dde991b6f6 100755 --- a/scripts/get-dotnetup.sh +++ b/scripts/get-dotnetup.sh @@ -169,6 +169,32 @@ FILE_NAME="dotnetup-${RID}" DOWNLOAD_URL="${BASE_URL}/${FILE_NAME}" CHECKSUM_URL="${DOWNLOAD_URL}.sha512" +# Map a 'channel' such as 'daily' to specific version url for the binary and its .sha512 to prevent release race condition mismatches +resolve_final_url() { + local url="$1" + if [ "$DOWNLOADER" = "curl" ]; then + # --head resolves redirects without downloading the body. + curl --silent --show-error --location --head --output /dev/null \ + --write-out '%{url_effective}' "$url" 2>/dev/null + elif [ "$DOWNLOADER" = "wget" ]; then + # wget lacks --write-out; --spider -S prints the redirect headers, whose final 'Location:' is the concrete build URL. tolower() keeps awk portable. + wget --spider -S "$url" 2>&1 \ + | awk 'tolower($1) == "location:" { u = $2 } END { if (u != "") print u }' + fi + # An empty result falls back to the shortlink URLs below (previous behavior). +} + +RESOLVED_URL="$(resolve_final_url "$DOWNLOAD_URL" || true)" +if [ -n "$RESOLVED_URL" ] && [[ "$RESOLVED_URL" == *"/public/"* ]]; then + info "Resolved '${QUALITY}' to concrete build: $RESOLVED_URL" + DOWNLOAD_URL="$RESOLVED_URL" + # Checksums live under the sibling 'public-checksums' path. Use sed, not bash + # ${var/p/r}, since bash 3.2 (macOS) keeps the escaped backslashes literally. + CHECKSUM_URL="$(printf '%s' "$RESOLVED_URL" | sed 's#/public/#/public-checksums/#').sha512" +else + gray "Could not resolve '${QUALITY}' shortlink to a concrete build; using shortlink URLs directly." +fi + INSTALLED_BINARY="${INSTALL_DIR}/dotnetup" TEMP_DIR=$(mktemp -d)