# OpenOcta Installer (Release) # # $ErrorActionPreference = "Stop" # BaseUrl: use env OPENOCTA_BASE_URL if set, else default (IP for domains without ICP filing) if ($env:OPENOCTA_BASE_URL) { $BaseUrl = $env:OPENOCTA_BASE_URL.TrimEnd('/') } else { $BaseUrl = "https://openocta.com/pkg" } $FetchUrl = "${BaseUrl}?dist" Write-Host "[1/4] Checking latest version from server..." -ForegroundColor Cyan try { $HtmlContent = curl.exe -fsSL -A "curl/7.68.0" $FetchUrl 2>&1 if ($LASTEXITCODE -ne 0) { throw "curl failed: $HtmlContent" } $HtmlContent = $HtmlContent -join "`n" $Versions = [regex]::Matches($HtmlContent, 'href="v(\d+\.\d+\.\d+)(?:/|")') | ForEach-Object { $_.Groups[1].Value } | Select-Object -Unique if ($Versions.Count -eq 0) { $Preview = $HtmlContent.Substring(0, [math]::Min(200, $HtmlContent.Length)) throw "No valid version found in HTML. Server returned preview:`n$Preview..." } $LatestVersion = $Versions | Sort-Object { [version]$_ } | Select-Object -Last 1 } catch { Write-Error "Fetch version failed. URL: '$FetchUrl' Error: $($_.Exception.Message)" exit 1 } Write-Host "[2/4] Found latest version: v$LatestVersion" -ForegroundColor Green $Version = $LatestVersion $DownloadUrl = "$BaseUrl/v$Version" $Arch = $env:PROCESSOR_ARCHITECTURE.ToLower() if ($Arch -eq "amd64") { $Arch = "amd64" } elseif ($Arch -eq "arm64") { $Arch = "arm64" } else { Write-Error "Unsupported architecture: $Arch" exit 1 } # Auto-detect actual filename from version directory (handles -SNAPSHOT etc.) $VersionHtml = curl.exe -fsSL -A "curl/7.68.0" "${DownloadUrl}?dist" 2>&1 if ($LASTEXITCODE -ne 0) { Write-Error "Failed to list version directory."; exit 1 } $VersionHtml = $VersionHtml -join "`n" $Pattern = "openocta_[^""]*_windows_${Arch}\.zip" $Match = [regex]::Match($VersionHtml, "href=""($Pattern)""") if ($Match.Success) { $Filename = $Match.Groups[1].Value } else { $Filename = "openocta_${Version}_windows_${Arch}.zip" } $FullDownloadUrl = "$DownloadUrl/$Filename" $InstallDir = "$env:USERPROFILE\.openocta\bin" $ZipPath = "$env:TEMP\$Filename" $ExtractTemp = "$env:TEMP\openocta_extract_$([guid]::NewGuid())" Write-Host "[3/4] Downloading from: $FullDownloadUrl ..." -ForegroundColor Cyan curl.exe -fsSL -o $ZipPath $FullDownloadUrl 2>&1 if ($LASTEXITCODE -ne 0) { Write-Error "Download failed." exit 1 } Write-Host "[4/4] Extracting and installing..." -ForegroundColor Cyan if (!(Test-Path $InstallDir)) { New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null } Expand-Archive -Path $ZipPath -DestinationPath $ExtractTemp -Force $ExePath = Get-ChildItem -Path $ExtractTemp -Recurse -Filter "openocta.exe" | Select-Object -First 1 if ($ExePath) { $TargetExe = "$InstallDir\openocta.exe" if (Test-Path $TargetExe) { # Stop existing processes to avoid "File in use" errors Stop-Process -Name "openocta" -Force -ErrorAction SilentlyContinue # Give some time for processes to fully exit Start-Sleep -Seconds 1 Remove-Item -Path $TargetExe -Force -ErrorAction SilentlyContinue } Move-Item -Path $ExePath.FullName -Destination $TargetExe -Force Write-Host "Installed successfully -> $TargetExe" -ForegroundColor Green } else { Write-Error "openocta.exe not found in zip" exit 1 } Remove-Item -Path $ZipPath -Force Remove-Item -Path $ExtractTemp -Recurse -Force # Add to system PATH (all users). Fall back to user PATH if not admin. $PathUpdated = $false try { $MachinePath = [Environment]::GetEnvironmentVariable("PATH", "Machine") if ($MachinePath -notmatch [regex]::Escape($InstallDir)) { $NewPath = "$MachinePath;$InstallDir" [Environment]::SetEnvironmentVariable("PATH", $NewPath, "Machine") $PathUpdated = $true Write-Host "PATH added to system (Machine). New terminals will have openocta." -ForegroundColor Yellow } } catch { $UserPath = [Environment]::GetEnvironmentVariable("PATH", "User") if ($UserPath -notmatch [regex]::Escape($InstallDir)) { $NewPath = "$UserPath;$InstallDir" [Environment]::SetEnvironmentVariable("PATH", $NewPath, "User") $PathUpdated = $true Write-Host "PATH added to user (run as Administrator for system-wide)." -ForegroundColor Yellow } } if (-not $PathUpdated) { $UserPath = [Environment]::GetEnvironmentVariable("PATH", "User") if ($UserPath -notmatch [regex]::Escape($InstallDir)) { $NewPath = "$UserPath;$InstallDir" [Environment]::SetEnvironmentVariable("PATH", $NewPath, "User") Write-Host "PATH added to user." -ForegroundColor Yellow } } # Make openocta available in this session without restart if ($env:Path -notmatch [regex]::Escape($InstallDir)) { $env:Path = "$env:Path;$InstallDir" } Write-Host "Done!" -ForegroundColor Cyan Write-Host "The PATH has been updated for this session. You can now use 'openocta' directly." -ForegroundColor Green Write-Host "`nReady to go! Run the following to start:" -ForegroundColor Yellow Write-Host " openocta gateway run`n" -ForegroundColor Green