Adds the PyQt6 Windows client (Homepage, Scan & results, About & updates, Settings), ClamAV scanning and quarantine, browser-download watch with an exclusive scan gate, Bolt loopback/PKCE sign-in with DPAPI key storage, Gitea release feed with checksum verification, opt-in diagnostics, and Windows/portable build tooling. Co-Authored-By: Claude Code <noreply@anthropic.com>
100 lines
3.4 KiB
PowerShell
100 lines
3.4 KiB
PowerShell
#requires -Version 5.1
|
|
[CmdletBinding()]
|
|
param(
|
|
[switch]$OneFile,
|
|
[switch]$SkipInstaller
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$Root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
Set-Location $Root
|
|
|
|
function Get-Python {
|
|
$candidates = @("py -3.11", "py -3", "python")
|
|
foreach ($candidate in $candidates) {
|
|
try {
|
|
$parts = $candidate.Split(" ")
|
|
$exe = $parts[0]
|
|
$exeArgs = @($parts | Select-Object -Skip 1)
|
|
$output = & $exe @exeArgs -c "import sys; print(sys.executable); print(sys.version_info[:2])" 2>$null
|
|
if ($LASTEXITCODE -eq 0 -and $output -match "3\.11") {
|
|
return $parts
|
|
}
|
|
} catch { }
|
|
}
|
|
throw "Python 3.11 x64 is required. Install it from python.org and retry."
|
|
}
|
|
|
|
$version = "1.0.0"
|
|
$venv = Join-Path $Root ".venv-build"
|
|
$python = Get-Python
|
|
|
|
if (-not (Test-Path $venv)) {
|
|
Write-Host "Creating build environment..."
|
|
$pythonExe = $python[0]
|
|
$pythonArgs = @($python | Select-Object -Skip 1)
|
|
& $pythonExe @pythonArgs -m venv $venv
|
|
}
|
|
$py = Join-Path $venv "Scripts\python.exe"
|
|
if (-not (Test-Path $py)) {
|
|
throw "The build virtual environment could not be created."
|
|
}
|
|
|
|
& $py -m pip install --upgrade pip
|
|
& $py -m pip install -r (Join-Path $Root "requirements-dev.txt")
|
|
if ($LASTEXITCODE -ne 0) { throw "Dependency installation failed." }
|
|
|
|
if ($OneFile) {
|
|
$env:BOLTCLAM_ONEFILE = "1"
|
|
} else {
|
|
Remove-Item Env:BOLTCLAM_ONEFILE -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
Write-Host "Building BoltClam $version..."
|
|
& $py -m PyInstaller --noconfirm --clean (Join-Path $Root "BoltClam.spec")
|
|
if ($LASTEXITCODE -ne 0) { throw "PyInstaller failed." }
|
|
|
|
$dist = Join-Path $Root "dist"
|
|
$artifacts = @()
|
|
if ($OneFile) {
|
|
$exe = Join-Path $dist "BoltClam.exe"
|
|
if (-not (Test-Path $exe)) { throw "Expected $exe was not produced." }
|
|
$artifacts += $exe
|
|
} else {
|
|
$folder = Join-Path $dist "BoltClam"
|
|
$exe = Join-Path $folder "BoltClam.exe"
|
|
if (-not (Test-Path $exe)) { throw "Expected $exe was not produced." }
|
|
$zip = Join-Path $dist "BoltClam-$version-windows-x64.zip"
|
|
if (Test-Path $zip) { Remove-Item $zip -Force }
|
|
Compress-Archive -Path (Join-Path $folder "*") -DestinationPath $zip -CompressionLevel Optimal
|
|
$artifacts += $zip
|
|
|
|
if (-not $SkipInstaller) {
|
|
$isccCandidates = @(
|
|
"${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe",
|
|
"$env:ProgramFiles\Inno Setup 6\ISCC.exe"
|
|
)
|
|
$iscc = $isccCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
if ($iscc) {
|
|
Write-Host "Building installer with $iscc..."
|
|
& $iscc "/DMyAppVersion=$version" (Join-Path $Root "installer\BoltClam.iss")
|
|
if ($LASTEXITCODE -ne 0) { throw "Inno Setup failed." }
|
|
$setup = Join-Path $dist "BoltClam-$version-Setup.exe"
|
|
if (Test-Path $setup) { $artifacts += $setup }
|
|
} else {
|
|
Write-Warning "Inno Setup 6 was not found; skipping the installer."
|
|
}
|
|
}
|
|
}
|
|
|
|
$checksumPath = Join-Path $dist "SHA256SUMS.txt"
|
|
$lines = foreach ($artifact in $artifacts) {
|
|
$hash = (Get-FileHash -Algorithm SHA256 $artifact).Hash.ToLowerInvariant()
|
|
"$hash $(Split-Path -Leaf $artifact)"
|
|
}
|
|
$lines | Set-Content -Encoding ASCII $checksumPath
|
|
Write-Host ""
|
|
Write-Host "Built:"
|
|
$artifacts | ForEach-Object { Write-Host " $_" }
|
|
Write-Host "Checksums: $checksumPath"
|