Unify release selection across clients
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / macos-client (macos-aarch64, macos-14) (push) Canceled after 0s
ci / macos-client (macos-x86_64, macos-13) (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest, , , ) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14, , , ) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13, , , ) (push) Canceled after 0s
ci / package-release (windows-aarch64, windows-latest, aarch64, windows, aarch64-pc-windows-msvc) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest, , , ) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s

This commit is contained in:
DuProcess
2026-07-17 18:58:58 -04:00
parent 89b81d73b1
commit 7f8d5711ea
7 changed files with 641 additions and 439 deletions
+36 -132
View File
@@ -11,14 +11,17 @@ param(
[string]$BinaryBase = $env:DOSH_BINARY_BASE,
[string]$BinaryName = $env:DOSH_BINARY_NAME,
[string]$BinaryVersion = $(if ($env:DOSH_BINARY_VERSION) { $env:DOSH_BINARY_VERSION } else { "latest" }),
[switch]$BinaryExact = $($env:DOSH_BINARY_EXACT -and $env:DOSH_BINARY_EXACT -ne "0"),
[string]$UpdateCache = $(if ($env:DOSH_UPDATE_CACHE) { $env:DOSH_UPDATE_CACHE } elseif ($env:LOCALAPPDATA) { Join-Path $env:LOCALAPPDATA "dosh\source" } else { Join-Path $HOME ".cache\dosh\source" }),
[switch]$BinaryRequired = $($env:DOSH_BINARY_REQUIRED -and $env:DOSH_BINARY_REQUIRED -ne "0"),
[switch]$FromCurrent,
[switch]$ForceConfig
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
$Quiet = $env:DOSH_UPDATE_QUIET -and $env:DOSH_UPDATE_QUIET -ne "0"
$script:ResolvedSourceRef = $null
function Write-Info($Message) {
if (-not $Quiet) {
@@ -121,96 +124,18 @@ function Release-DownloadUrl {
if (-not $web) {
return $null
}
if ($BinaryVersion -eq "latest") {
return "$web/releases/latest/download/$name"
}
"$web/releases/download/$BinaryVersion/$name"
}
function Release-LatestTagDownloadUrl {
if ($BinaryUrl -or $BinaryBase -or $BinaryVersion -ne "latest") {
$releaseRef = Source-ReleaseRef
if (-not $releaseRef) {
return $null
}
$web = Repo-WebBase $Repo
if (-not $web) {
return $null
}
try {
$response = Invoke-WebRequest -UseBasicParsing -Uri "$web/releases/latest" -MaximumRedirection 5
$effective = $null
if ($response.BaseResponse.ResponseUri) {
$effective = $response.BaseResponse.ResponseUri.AbsoluteUri
} elseif ($response.BaseResponse.RequestMessage -and $response.BaseResponse.RequestMessage.RequestUri) {
$effective = $response.BaseResponse.RequestMessage.RequestUri.AbsoluteUri
}
$prefix = "$web/releases/tag/"
if ($effective -and $effective.StartsWith($prefix)) {
$tag = $effective.Substring($prefix.Length)
if ($tag) {
return "$web/releases/download/$tag/$(Release-ArtifactName)"
}
}
}
catch {
return $null
}
return $null
}
function Version-Core($Value) {
$base = $Value.TrimStart("v").Split("+")[0]
$base.Split("-")[0]
}
function Version-Prerelease($Value) {
$base = $Value.TrimStart("v").Split("+")[0]
$dash = $base.IndexOf("-")
if ($dash -lt 0) {
return ""
}
$base.Substring($dash + 1).ToLowerInvariant()
}
function Version-Parts($Value) {
[regex]::Matches((Version-Core $Value), "\d+") | ForEach-Object { [int64]$_.Value }
}
function Compare-Prerelease($Left, $Right) {
if (-not $Left -and -not $Right) {
return 0
}
if (-not $Left) {
return 1
}
if (-not $Right) {
return -1
}
if ($Left -eq $Right) {
return 0
}
if ($Left -match "(?i)^rc(\d+)$" -and $Right -match "(?i)^rc(\d+)$") {
$leftRc = [int64]([regex]::Match($Left, "(?i)^rc(\d+)$").Groups[1].Value)
$rightRc = [int64]([regex]::Match($Right, "(?i)^rc(\d+)$").Groups[1].Value)
return $leftRc.CompareTo($rightRc)
}
return [string]::CompareOrdinal($Left, $Right)
}
function Compare-DoshVersion($Left, $Right) {
$leftParts = @(Version-Parts $Left)
$rightParts = @(Version-Parts $Right)
$width = [Math]::Max($leftParts.Count, $rightParts.Count)
for ($i = 0; $i -lt $width; $i++) {
$l = if ($i -lt $leftParts.Count) { $leftParts[$i] } else { 0 }
$r = if ($i -lt $rightParts.Count) { $rightParts[$i] } else { 0 }
if ($l -lt $r) { return -1 }
if ($l -gt $r) { return 1 }
}
return Compare-Prerelease (Version-Prerelease $Left) (Version-Prerelease $Right)
"$web/releases/download/$releaseRef/$name"
}
function Current-SourceVersion {
if (Test-Path "Cargo.toml") {
if ($FromCurrent) {
if (-not (Test-Path "Cargo.toml")) {
return $null
}
$raw = Get-Content "Cargo.toml" -Raw
} else {
$web = Repo-WebBase $Repo
@@ -230,47 +155,23 @@ function Current-SourceVersion {
return $null
}
function Latest-ReleaseTag {
$web = Repo-WebBase $Repo
if (-not $web) {
function Source-ReleaseRef {
if ($BinaryUrl -or $BinaryBase) {
return $null
}
try {
$response = Invoke-WebRequest -UseBasicParsing -Uri "$web/releases/latest" -MaximumRedirection 5
$effective = $null
if ($response.BaseResponse.ResponseUri) {
$effective = $response.BaseResponse.ResponseUri.AbsoluteUri
} elseif ($response.BaseResponse.RequestMessage -and $response.BaseResponse.RequestMessage.RequestUri) {
$effective = $response.BaseResponse.RequestMessage.RequestUri.AbsoluteUri
}
$prefix = "$web/releases/tag/"
if ($effective -and $effective.StartsWith($prefix)) {
return $effective.Substring($prefix.Length)
}
if ($BinaryVersion -ne "latest" -and $BinaryExact) {
return $BinaryVersion
}
catch {
return $null
$current = Current-SourceVersion
if ($current) {
return "v$($current.TrimStart('v'))"
}
if ($BinaryVersion -ne "latest") {
return $BinaryVersion
}
return $null
}
function Latest-ReleaseIsStale {
if ($BinaryUrl -or $BinaryBase -or $BinaryVersion -ne "latest") {
return $false
}
$latest = Latest-ReleaseTag
$current = Current-SourceVersion
if (-not $latest -or -not $current) {
return $false
}
$latestVersion = $latest.TrimStart("v")
if ((Compare-DoshVersion $latestVersion $current) -lt 0) {
Write-Warning "latest release $latestVersion is older than source $current; skipping stale prebuilt"
return $true
}
return $false
}
function Verify-ArchiveChecksum($Url, $Archive) {
$checksumPath = "$Archive.sha256"
try {
@@ -475,16 +376,11 @@ if ($env:DOSH_INSTALL_BINDIR_FILE) {
Apply-PendingBinaryReplacements $bindir
function Install-Prebuilt {
if (Latest-ReleaseIsStale) {
return $false
}
$url = Release-LatestTagDownloadUrl
if (-not $url) {
$url = Release-DownloadUrl
}
$url = Release-DownloadUrl
if (-not $url) {
return $false
}
$script:ResolvedSourceRef = Source-ReleaseRef
$tmp = Join-Path ([System.IO.Path]::GetTempPath()) ("dosh-bin-" + [guid]::NewGuid())
$zip = Join-Path $tmp (Release-ArtifactName)
$extract = Join-Path $tmp "extract"
@@ -520,7 +416,10 @@ function Install-Prebuilt {
function Install-FromSource {
Ensure-Cargo
if (Test-Path "Cargo.toml") {
if ($FromCurrent) {
if (-not (Test-Path "Cargo.toml")) {
throw "-FromCurrent requires a Dosh checkout with Cargo.toml"
}
$src = (Get-Location).Path
} else {
if (-not $Repo) {
@@ -530,21 +429,26 @@ function Install-FromSource {
$sourceCache = Assert-SafeUpdateCache $UpdateCache
$parent = Split-Path -Parent $sourceCache
New-Item -ItemType Directory -Force -Path $parent | Out-Null
$sourceRef = if ($script:ResolvedSourceRef) { $script:ResolvedSourceRef } else { "main" }
if (Test-Path (Join-Path $sourceCache ".git")) {
git -C $sourceCache remote set-url origin $Repo
$fetchArgs = @("-C", $sourceCache, "fetch", "--depth", "1", "origin", "main")
$fetchArgs = @("-C", $sourceCache, "fetch", "--depth", "1", "origin", $sourceRef)
if ($Quiet) {
$fetchArgs = @("-C", $sourceCache, "fetch", "-q", "--depth", "1", "origin", "main")
$fetchArgs = @("-C", $sourceCache, "fetch", "-q", "--depth", "1", "origin", $sourceRef)
}
git @fetchArgs
git -C $sourceCache checkout -q -B main FETCH_HEAD
if ($sourceRef -eq "main") {
git -C $sourceCache checkout -q -B main FETCH_HEAD
} else {
git -C $sourceCache checkout -q --detach FETCH_HEAD
}
} else {
if (Test-Path $sourceCache) {
Remove-Item -Recurse -Force $sourceCache
}
$cloneArgs = @("clone", "--depth", "1", "--branch", "main", $Repo, $sourceCache)
$cloneArgs = @("clone", "--depth", "1", "--branch", $sourceRef, $Repo, $sourceCache)
if ($Quiet) {
$cloneArgs = @("clone", "-q", "--depth", "1", "--branch", "main", $Repo, $sourceCache)
$cloneArgs = @("clone", "-q", "--depth", "1", "--branch", $sourceRef, $Repo, $sourceCache)
}
git @cloneArgs | Out-Null
}