67 lines
4.7 KiB
PowerShell
67 lines
4.7 KiB
PowerShell
# Official Go archive bootstrap. URLs and install policy come from runtime config.
|
|
function Get-GoVersion([string]$Executable) {
|
|
$output = & $Executable version 2>&1
|
|
if ($LASTEXITCODE -ne 0 -or "$output" -notmatch '\bgo(\d+\.\d+(?:\.\d+)?)\b') { return $null }
|
|
return [version]$Matches[1]
|
|
}
|
|
function Confirm-GoToolchainInstall([version]$Minimum) {
|
|
$answer = Read-Host "Go >= $Minimum is required to build. Download and install it now? [y/N]"
|
|
return $answer -match '^(?i:y|yes)$'
|
|
}
|
|
function Resolve-GoToolchain($Config) {
|
|
$directive = Select-String -LiteralPath (Resolve-ProjectPath 'go.mod') -Pattern '^go\s+(\d+\.\d+(?:\.\d+)?)\s*$' | Select-Object -First 1
|
|
if (-not $directive) { throw 'go.mod has no valid minimum Go version.' }
|
|
$minimum = [version]$directive.Matches[0].Groups[1].Value
|
|
$goName = $env:GAC_GO_COMMAND
|
|
if ([string]::IsNullOrWhiteSpace($goName)) { $goName = $Config.go_command }
|
|
if ([string]::IsNullOrWhiteSpace($goName)) { throw 'Set launcher.go_command or GAC_GO_COMMAND.' }
|
|
$found = Get-Command -Name $goName -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
if ($found) {
|
|
$version = Get-GoVersion $found.Source
|
|
if ($version -and $version -ge $minimum) { return $found.Source }
|
|
Write-Host "Configured Go is older than go.mod requires ($minimum)."
|
|
}
|
|
$install = $Config.go_install
|
|
if (-not $install -or $install.enabled -ne $true) { throw "Go >= $minimum is required. Install it or enable launcher.go_install." }
|
|
$root = Resolve-ProjectPath $install.directory
|
|
$receiptPath = Join-Path $root 'toolchain.json'
|
|
if (Test-Path -LiteralPath $receiptPath -PathType Leaf) {
|
|
$receipt = Get-Content -LiteralPath $receiptPath -Raw | ConvertFrom-Json
|
|
$cached = [IO.Path]::GetFullPath((Join-Path $root $receipt.executable))
|
|
if (-not $cached.StartsWith($root.TrimEnd('\') + '\', [StringComparison]::OrdinalIgnoreCase)) { throw 'Managed Go receipt points outside its configured directory.' }
|
|
if (Test-Path -LiteralPath $cached -PathType Leaf) {
|
|
$version = Get-GoVersion $cached
|
|
if ($version -and $version -ge $minimum) { return $cached }
|
|
}
|
|
}
|
|
if (-not (Confirm-GoToolchainInstall $minimum)) { throw 'Go installation was declined. Install a compatible Go version, then run the build again.' }
|
|
$machineArch = $env:PROCESSOR_ARCHITEW6432
|
|
if (-not $machineArch) { $machineArch = $env:PROCESSOR_ARCHITECTURE }
|
|
$arch = switch ($machineArch.ToUpperInvariant()) { 'AMD64' {'amd64'} 'ARM64' {'arm64'} 'X86' {'386'} default {throw "Unsupported Windows architecture: $machineArch"} }
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
|
Write-Host "Downloading Go release metadata ($($install.manifest_url))..."
|
|
$releases = Invoke-RestMethod -Uri $install.manifest_url
|
|
$release = $releases | Where-Object { $_.stable -and $_.version -match '^go\d+\.\d+\.\d+$' -and [version]$_.version.Substring(2) -ge $minimum } | Sort-Object { [version]$_.version.Substring(2) } -Descending | Select-Object -First 1
|
|
if (-not $release) { throw "No stable Go >= $minimum in the configured official manifest." }
|
|
$archive = $release.files | Where-Object { $_.os -eq 'windows' -and $_.arch -eq $arch -and $_.kind -eq 'archive' -and $_.filename -match '^[a-zA-Z0-9._-]+\.zip$' } | Select-Object -First 1
|
|
if (-not $archive -or $archive.sha256 -notmatch '^[a-fA-F0-9]{64}$') { throw 'Official manifest has no valid Windows ZIP/checksum for this machine.' }
|
|
New-Item -ItemType Directory -Path $root -Force | Out-Null
|
|
# Always extract to a new directory; never overlay an older Go installation.
|
|
$folderName = [Guid]::NewGuid().ToString('N')
|
|
$folder = Join-Path $root $folderName
|
|
$zip = Join-Path $root ($folderName + '.zip')
|
|
$download = $install.download_url.TrimEnd('/') + '/' + $archive.filename
|
|
Write-Host "Installing $($release.version) ($arch), without administrator rights..."
|
|
Invoke-WebRequest -Uri $download -OutFile $zip -UseBasicParsing
|
|
if ((Get-FileHash -LiteralPath $zip -Algorithm SHA256).Hash -ine $archive.sha256) { throw "Go archive checksum mismatch: $zip" }
|
|
Expand-Archive -LiteralPath $zip -DestinationPath $folder
|
|
$relative = Join-Path $folderName 'go/bin/go.exe'
|
|
$executable = Join-Path $root $relative
|
|
$version = Get-GoVersion $executable
|
|
if (-not $version -or $version -lt $minimum) { throw 'Downloaded Go did not pass its version check.' }
|
|
@{executable=$relative; version=$release.version; sha256=$archive.sha256} | ConvertTo-Json | Set-Content -LiteralPath $receiptPath -Encoding UTF8
|
|
Remove-Item -LiteralPath $zip
|
|
Write-Host "Go ready: $version"
|
|
return $executable
|
|
}
|