param( [switch]$Clean ) $ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $n2nRoot = Join-Path $projectRoot 'third_party\n2n' $releaseRoot = Join-Path $projectRoot 'release' $portableRoot = Join-Path $projectRoot 'release\super-n2n-portable' $stagingRoot = Join-Path $releaseRoot 'super-n2n-portable-staging' $archivePath = Join-Path $releaseRoot 'super-n2n-portable.zip' $releaseRootFull = [System.IO.Path]::GetFullPath($releaseRoot) $portableRootFull = [System.IO.Path]::GetFullPath($portableRoot) $stagingRootFull = [System.IO.Path]::GetFullPath($stagingRoot) $archivePathFull = [System.IO.Path]::GetFullPath($archivePath) if ((Split-Path -Parent $portableRootFull) -ne $releaseRootFull -or (Split-Path -Leaf $portableRootFull) -ne 'super-n2n-portable') { throw "Refusing to replace an unexpected portable output directory: $portableRootFull" } if ((Split-Path -Parent $stagingRootFull) -ne $releaseRootFull -or (Split-Path -Leaf $stagingRootFull) -ne 'super-n2n-portable-staging') { throw "Refusing to replace an unexpected staging directory: $stagingRootFull" } if ((Split-Path -Parent $archivePathFull) -ne $releaseRootFull -or (Split-Path -Leaf $archivePathFull) -ne 'super-n2n-portable.zip') { throw "Refusing to replace an unexpected portable archive: $archivePathFull" } if ($Clean) { if (Test-Path -LiteralPath $portableRoot) { Remove-Item -LiteralPath $portableRoot -Recurse -Force } if (Test-Path -LiteralPath $archivePath) { Remove-Item -LiteralPath $archivePath -Force } } Push-Location $projectRoot try { & npm.cmd run tauri:portable:raw if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } $files = @{ 'super-n2n.exe' = Join-Path $projectRoot 'src-tauri\target\release\super-n2n.exe' 'n2n\edge.exe' = Join-Path $n2nRoot 'edge.exe' 'n2n\supernode.exe' = Join-Path $n2nRoot 'supernode.exe' 'n2n\LICENSE-n2n.txt' = Join-Path $n2nRoot 'LICENSE' 'drivers\tap-windows-9.24.7-I601-Win10.exe' = Join-Path $projectRoot 'third_party\tap-windows\tap-windows-9.24.7-I601-Win10.exe' 'drivers\TAP-WINDOWS-README.txt' = Join-Path $projectRoot 'third_party\tap-windows\README.txt' 'drivers\TAP-WINDOWS-SHA256SUMS.txt' = Join-Path $projectRoot 'third_party\tap-windows\SHA256SUMS.txt' 'drivers\TAP-WINDOWS-LICENSE.txt' = Join-Path $projectRoot 'third_party\tap-windows\LICENSE.txt' 'drivers\TAP-WINDOWS-GPLv2.txt' = Join-Path $projectRoot 'third_party\tap-windows\COPYRIGHT.GPL.txt' 'README.txt' = Join-Path $projectRoot 'scripts\PORTABLE-README.txt' } foreach ($entry in $files.GetEnumerator()) { if (-not (Test-Path -LiteralPath $entry.Value)) { throw "Required portable artifact is missing: $($entry.Value)" } } if (Test-Path -LiteralPath $stagingRoot) { Remove-Item -LiteralPath $stagingRoot -Recurse -Force } New-Item -ItemType Directory -Force -Path $stagingRoot | Out-Null foreach ($entry in $files.GetEnumerator()) { $destination = Join-Path $stagingRoot $entry.Key $destinationDirectory = Split-Path -Parent $destination New-Item -ItemType Directory -Force -Path $destinationDirectory | Out-Null Copy-Item -LiteralPath $entry.Value -Destination $destination -Force } Compress-Archive -Path (Join-Path $stagingRoot '*') -DestinationPath $archivePath -CompressionLevel Optimal -Force New-Item -ItemType Directory -Force -Path $portableRoot | Out-Null foreach ($legacyName in @('edge.exe', 'supernode.exe', 'LICENSE-n2n.txt')) { $legacyPath = Join-Path $portableRoot $legacyName if (Test-Path -LiteralPath $legacyPath) { try { Remove-Item -LiteralPath $legacyPath -Force } catch { Write-Warning "Could not remove legacy artifact $legacyPath because it is in use." } } } foreach ($entry in $files.GetEnumerator()) { $destination = Join-Path $portableRoot $entry.Key $destinationDirectory = Split-Path -Parent $destination New-Item -ItemType Directory -Force -Path $destinationDirectory | Out-Null try { Copy-Item -LiteralPath $entry.Value -Destination $destination -Force } catch { Write-Warning "Could not update $destination because it is in use. The zip archive is current." } } Write-Output "Portable package created: $archivePath" } finally { if (Test-Path -LiteralPath $stagingRoot) { Remove-Item -LiteralPath $stagingRoot -Recurse -Force } Pop-Location }