Files
duplicate-finder/build-release.ps1
tocmo 1d46b9945d Add portable flash-drive installer
- build-release.ps1: builds Docker image, saves to tar, bundles
  everything into dist\ ready to copy to a flash drive
- installer/install.ps1: checks WSL2, Docker Desktop, loads image
  (or builds from source as fallback), prompts for photo/data paths,
  writes docker-compose.override.yml, starts container, creates
  desktop shortcut
- installer/uninstall.ps1: stops container, optionally removes image
  and data, removes shortcut and app directory
- installer/dupfinder-start-stop.ps1: start/stop/restart/open helper
  copied to target machine during install; desktop shortcut uses -Action open
  which polls until the app is responsive before launching browser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 01:32:32 -04:00

154 lines
6.6 KiB
PowerShell

#Requires -Version 5.1
<#
.SYNOPSIS
Builds the DupFinder flash-drive installer bundle.
.DESCRIPTION
1. Builds the Docker image
2. Saves it to dist\image\dupfinder.tar
3. Copies all installer scripts and source into dist\
Run this from the repo root before copying dist\ to a flash drive.
.EXAMPLE
.\build-release.ps1
.\build-release.ps1 -SkipBuild # Skip docker build (reuse existing image)
#>
param(
[switch]$SkipBuild,
[string]$ImageName = "dupfinder",
[string]$ImageTag = "latest"
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$RepoRoot = $PSScriptRoot
$DistDir = Join-Path $RepoRoot "dist"
$ImageFull = "${ImageName}:${ImageTag}"
function Write-Step([string]$msg) {
Write-Host "`n==> $msg" -ForegroundColor Cyan
}
function Write-OK([string]$msg) {
Write-Host " [OK] $msg" -ForegroundColor Green
}
function Write-Fail([string]$msg) {
Write-Host " [!!] $msg" -ForegroundColor Red
}
# ── Check Docker is running ───────────────────────────────────────────────────
Write-Step "Checking Docker..."
docker info 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Fail "Docker is not running. Start Docker Desktop and try again."
exit 1
}
Write-OK "Docker is running"
# ── Build image ───────────────────────────────────────────────────────────────
if (-not $SkipBuild) {
Write-Step "Building Docker image ($ImageFull)..."
docker build -t $ImageFull --progress=plain $RepoRoot
if ($LASTEXITCODE -ne 0) { Write-Fail "Docker build failed."; exit 1 }
Write-OK "Image built: $ImageFull"
} else {
Write-Step "Skipping build (-SkipBuild). Checking image exists..."
$exists = docker images $ImageFull --format "{{.ID}}" 2>$null
if (-not $exists) {
Write-Fail "Image $ImageFull not found locally. Remove -SkipBuild to build it."
exit 1
}
Write-OK "Image found: $ImageFull"
}
# ── Clean dist\ ──────────────────────────────────────────────────────────────
Write-Step "Preparing dist\ directory..."
if (Test-Path $DistDir) {
Remove-Item $DistDir -Recurse -Force
}
New-Item -ItemType Directory -Path $DistDir | Out-Null
New-Item -ItemType Directory -Path "$DistDir\image" | Out-Null
New-Item -ItemType Directory -Path "$DistDir\source" | Out-Null
New-Item -ItemType Directory -Path "$DistDir\assets" | Out-Null
Write-OK "dist\ ready"
# ── Save Docker image ─────────────────────────────────────────────────────────
Write-Step "Saving Docker image to dist\image\dupfinder.tar (this may take a minute)..."
docker save -o "$DistDir\image\dupfinder.tar" $ImageFull
if ($LASTEXITCODE -ne 0) { Write-Fail "docker save failed."; exit 1 }
$tarSize = [math]::Round((Get-Item "$DistDir\image\dupfinder.tar").Length / 1MB, 1)
Write-OK "Image saved (${tarSize} MB)"
# ── Copy installer scripts ────────────────────────────────────────────────────
Write-Step "Copying installer scripts..."
Copy-Item "$RepoRoot\installer\install.ps1" "$DistDir\install.ps1"
Copy-Item "$RepoRoot\installer\uninstall.ps1" "$DistDir\uninstall.ps1"
Copy-Item "$RepoRoot\installer\dupfinder-start-stop.ps1" "$DistDir\dupfinder-start-stop.ps1"
Copy-Item "$RepoRoot\docker-compose.yml" "$DistDir\docker-compose.yml"
# install.bat launcher (no-click PS1 execution for non-technical users)
@'
@echo off
echo Starting DupFinder installer...
PowerShell -ExecutionPolicy Bypass -File "%~dp0install.ps1"
pause
'@ | Set-Content "$DistDir\INSTALL.bat" -Encoding ASCII
Write-OK "Scripts copied"
# ── Copy source (fallback build) ──────────────────────────────────────────────
Write-Step "Copying source files (offline build fallback)..."
$excludeDirs = @('dist', '__pycache__', 'data', '.git', '.claude', 'installer')
$excludeFiles = @('*.db', '*.db-shm', '*.db-wal', '*.pyc', '*.pyo')
Get-ChildItem $RepoRoot -Recurse | Where-Object {
$item = $_
$skip = $false
foreach ($d in $excludeDirs) { if ($item.FullName -match [regex]::Escape($d)) { $skip = $true } }
foreach ($f in $excludeFiles) { if ($item.Name -like $f) { $skip = $true } }
-not $skip
} | ForEach-Object {
$rel = $_.FullName.Substring($RepoRoot.Length + 1)
$dst = Join-Path "$DistDir\source" $rel
if ($_.PSIsContainer) {
New-Item -ItemType Directory -Path $dst -Force | Out-Null
} else {
$dstDir = Split-Path $dst -Parent
if (-not (Test-Path $dstDir)) { New-Item -ItemType Directory -Path $dstDir -Force | Out-Null }
Copy-Item $_.FullName $dst -Force
}
}
Write-OK "Source copied"
# ── README for flash drive ────────────────────────────────────────────────────
@"
DupFinder Installer
===================
Requirements:
- Windows 10/11 (64-bit)
- Docker Desktop for Windows (if not installed, the installer will guide you)
To install:
1. Right-click INSTALL.bat -> "Run as administrator"
OR
Open PowerShell as Administrator and run:
PowerShell -ExecutionPolicy Bypass -File install.ps1
2. Follow the prompts (photos path, data path)
3. A "DupFinder" shortcut will appear on the desktop when done.
To uninstall:
Run uninstall.ps1 as Administrator.
Built: $(Get-Date -Format 'yyyy-MM-dd HH:mm')
Image: $ImageFull
"@ | Set-Content "$DistDir\README.txt" -Encoding UTF8
# ── Summary ───────────────────────────────────────────────────────────────────
$totalMB = [math]::Round((Get-ChildItem $DistDir -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB, 1)
Write-Host ""
Write-Host "============================================" -ForegroundColor Green
Write-Host " Build complete! dist\ is ${totalMB} MB total" -ForegroundColor Green
Write-Host " Copy the dist\ folder to your flash drive." -ForegroundColor Green
Write-Host "============================================" -ForegroundColor Green