From c0263ff934950c4a51d8328cfd7d5296ba330bc2 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Wed, 29 Jul 2026 14:41:41 +1000 Subject: [PATCH] punk-getzig: spaced-path + Windows PowerShell 5 fixes (launcher and payload); punkshell 0.30.5 User-reported: './punk-getzig.cmd' from a spaced checkout failed with 'C:\repo\jn\program: The term ... is not recognized' while punk-runtime worked. Root cause: punk-getzig_wrap.toml still used the pwsh '-c' command-string launcher, which tokenizes a spaced script path - punk-runtime received the 'cmd.exe /c powershell ... -File' fix during G-119 (its wrap toml carries the comment) and punk-getzig never did. Adopting the same launcher surfaced three latent payload issues, all fixed in src/scriptapps/bin/punk-getzig.ps1: - Resolve-Path -RelativeBasePath is pwsh 7.4+ - replaced with the Push-Location + -Relative spelling (PS5-compatible) - Invoke-WebRequest without -UseBasicParsing NullReferences on PS5 (IE parsing engine); all three call sites fixed, with progress suppressed around the large distribution download (PS5 -OutFile slowdown) - Invoke-Expression "$zigexe version" splits spaced paths under ANY powershell (latent even on pwsh) - both sites now use the call operator Payload growth pushed :exit_multishell across a 512-byte boundary; the punk-runtime-style '(512B spacer)' comment added to punk-getzig.bash and the polyglot regenerated (checkfile ERROR-free). Verified in the 'C:/repo/jn/program files/punkshell' checkout: full fetch (community-mirror latency ordering, local punkbin mirror, minisign verify, extract, ZIG VERSION: 0.16.0) and the already-installed branch; main-repo argless run clean. Sources and regenerated bin/punk-getzig.cmd committed together per the wrap workflow (no roundtrip pin exists for punk-getzig - candidate noted in the completion report). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- CHANGELOG.md | 15 ++++++++++ bin/punk-getzig.cmd | 36 ++++++++++++++++++------ punkproject.toml | 2 +- src/scriptapps/bin/punk-getzig.bash | 4 +++ src/scriptapps/bin/punk-getzig.ps1 | 28 ++++++++++++++---- src/scriptapps/bin/punk-getzig_wrap.toml | 10 +++++-- 6 files changed, 78 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ee23c10..b29d21b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to Entries are newest-first; one bullet per notable change. See the root `AGENTS.md` "Project Versioning" section for the bump policy. +## [0.30.5] - 2026-07-29 + +- `punk-getzig.cmd` fixed for spaced checkout paths and Windows PowerShell 5: + the launcher moves off the `pwsh -c` form (which tokenized a spaced script + path - same `cmd.exe /c powershell ... -File` fix punk-runtime received in + G-119) and the payload drops its pwsh-isms: `Resolve-Path + -RelativeBasePath` (7.4+) becomes the Push-Location `-Relative` form, + `Invoke-WebRequest` gains `-UseBasicParsing` (PS5 IE-engine + NullReferenceException) with progress suppressed for the large download, + and two `Invoke-Expression "$zigexe version"` sites (which split spaced + paths under ANY powershell) become call-operator invocations. Verified end + to end from a "program files" checkout: mirror-latency selection, fetch + from the local punkbin mirror, minisign verification, extraction and both + the fresh-install and already-installed branches. + ## [0.30.4] - 2026-07-29 - `punk-runtime fetch` now prints a one-line materialization hint when the diff --git a/bin/punk-getzig.cmd b/bin/punk-getzig.cmd index 42554918..1acdd424 100644 --- a/bin/punk-getzig.cmd +++ b/bin/punk-getzig.cmd @@ -95,8 +95,8 @@ set ^"endlocal=for %%# in (1 2) do if %%#==2 (%\n% @REM If more than 64 chars needed for a target, it can still be done but overall script padding may need checking/adjusting @REM Supporting more explicit oses than those listed may also require script padding adjustment : <> -@SET "nextshellpath[win32___________]=pwsh -nop -nol -ExecutionPolicy bypass -c_______________________________________________________________________________________" -@SET "nextshelltype[win32___________]=pwsh____________" +@SET "nextshellpath[win32___________]=cmd.exe /c powershell -nop -nol -ExecutionPolicy bypass -File___________________________________________________________________" +@SET "nextshelltype[win32___________]=powershell______" @SET "nextshellpath[dragonflybsd____]=/usr/bin/env bash_______________________________________________________________________________________________________________" @SET "nextshelltype[dragonflybsd____]=bash____________" @SET "nextshellpath[freebsd_________]=/usr/bin/env bash_______________________________________________________________________________________________________________" @@ -1301,6 +1301,10 @@ echo " and extract to ${targetdir} (the tarball's own root folder name) manuall #tar -xf "./tools/${tarball}" -C ./tools #"${targetdir}/zig" version +#(512B spacer) byte-alignment padding so template labels beyond the payloads clear cmd's +#512-byte label-scan boundaries - resize this comment if scriptwrap checkfile reports a +#boundary-spanning label after a payload edit (see bin/AGENTS.md polyglot workflow) + # @@ -1634,7 +1638,12 @@ Write-Host "requested zig version: $releaseversion -> $zigfolder" Write-Output "powershell version: $($PSVersionTable.PSVersion)" if (Get-Command $zigexe -ErrorAction SilentlyContinue) { - $relative_zigfolder = Resolve-Path -Path $zigfolder -RelativeBasePath $outbase -Relative + #-RelativeBasePath is pwsh 7.4+; Push-Location + -Relative is the + #PS-5.1-compatible spelling of the same computation (the launcher runs + #Windows PowerShell - see punk-getzig_wrap.toml) + Push-Location $outbase + $relative_zigfolder = Resolve-Path -Path $zigfolder -Relative + Pop-Location Write-Host "zig.exe is installed in $relative_zigfolder" $zigv = & $zigexe version 2>&1 $stdout = $zigv | Where-Object {$_ -is [string]} @@ -1790,7 +1799,7 @@ if (-not $download_required) { $null = extractZip $releasearchive $toolsfolder $zigexe = Join-Path $zigfolder -ChildPath "zig.exe" - $v = Invoke-Expression "$zigexe version" + $v = & $zigexe version Write-Host "ZIG VERSION: ${v}" exit 0 } @@ -1799,7 +1808,10 @@ if (-not $download_required) { $mirrors_url = "https://ziglang.org/download/community-mirrors.txt" #some mirrors have no index and the base url will produce a 404, some have an html index, some have a modified copy of the ziglang.org/download/index.json -$mirrors_response = $(Invoke-WebRequest -Uri $mirrors_url) +#-UseBasicParsing: required for reliability on powershell 5 (without it PS5's +#Invoke-WebRequest uses the IE parsing engine - NullReferenceException on +#machines without it); harmless no-op on pwsh. Same convention as punk-runtime. +$mirrors_response = $(Invoke-WebRequest -UseBasicParsing -Uri $mirrors_url) if ($mirrors_response.StatusCode -eq 200) { #https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools/zig-x86_64-windows-0.15.1.zip $mirror_array = @("https://gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools") @@ -1907,7 +1919,7 @@ if ($mirrors_response.StatusCode -eq 200) { } #download the minisig first - because if that fails, we should move on without trying the larger download Write-Host "Downloading minisig signature from $sig_uristring" - Invoke-WebRequest -Uri $sig_uristring -Outfile "${outfile}.minisig" + Invoke-WebRequest -UseBasicParsing -Uri $sig_uristring -Outfile "${outfile}.minisig" if (-not(Test-Path -Path "${outfile}.minisig" -PathType Leaf)) { write-Host "Failed to download minisig signature from $sig_uristring to ${outfile}.minisig .. aborting download from $uristring" continue @@ -1915,7 +1927,15 @@ if ($mirrors_response.StatusCode -eq 200) { Write-Host "Downloading zig distribution from $full_uristring" Write-Host "Download to: $outfile" - Invoke-WebRequest -Uri $full_uristring -OutFile $outfile + #progress rendering makes PS5's Invoke-WebRequest -OutFile drastically + #slow on large files - suppress for the transfer, restore after + $OriginalProgressPreference = $Global:ProgressPreference + $Global:ProgressPreference = 'SilentlyContinue' + try { + Invoke-WebRequest -UseBasicParsing -Uri $full_uristring -OutFile $outfile + } finally { + $Global:ProgressPreference = $OriginalProgressPreference + } if (-not(Test-Path -Path $outfile -PathType Leaf)) { write-Host "Failed to download zig package from $full_uristring to ${outfile} .. aborting download from $uristring" @@ -1953,7 +1973,7 @@ if ($mirrors_response.StatusCode -eq 200) { $null = extractZip $releasearchive $toolsfolder $zigexe = Join-Path $zigfolder -ChildPath "zig.exe" - $v = Invoke-Expression "$zigexe version" + $v = & $zigexe version Write-Host "ZIG VERSION: ${v}" $test_ok = 1 ;#todo diff --git a/punkproject.toml b/punkproject.toml index 1e075dc6..7a19a2c2 100644 --- a/punkproject.toml +++ b/punkproject.toml @@ -1,4 +1,4 @@ [project] name = "punkshell" -version = "0.30.4" +version = "0.30.5" license = "BSD-2-Clause" diff --git a/src/scriptapps/bin/punk-getzig.bash b/src/scriptapps/bin/punk-getzig.bash index fa554847..68c508af 100644 --- a/src/scriptapps/bin/punk-getzig.bash +++ b/src/scriptapps/bin/punk-getzig.bash @@ -20,3 +20,7 @@ echo " and extract to ${targetdir} (the tarball's own root folder name) manuall #minisign verification as per the powershell side (zig minisign pubkey), then: #tar -xf "./tools/${tarball}" -C ./tools #"${targetdir}/zig" version + +#(512B spacer) byte-alignment padding so template labels beyond the payloads clear cmd's +#512-byte label-scan boundaries - resize this comment if scriptwrap checkfile reports a +#boundary-spanning label after a payload edit (see bin/AGENTS.md polyglot workflow) diff --git a/src/scriptapps/bin/punk-getzig.ps1 b/src/scriptapps/bin/punk-getzig.ps1 index 454f863e..df6d4c38 100644 --- a/src/scriptapps/bin/punk-getzig.ps1 +++ b/src/scriptapps/bin/punk-getzig.ps1 @@ -38,7 +38,12 @@ Write-Host "requested zig version: $releaseversion -> $zigfolder" Write-Output "powershell version: $($PSVersionTable.PSVersion)" if (Get-Command $zigexe -ErrorAction SilentlyContinue) { - $relative_zigfolder = Resolve-Path -Path $zigfolder -RelativeBasePath $outbase -Relative + #-RelativeBasePath is pwsh 7.4+; Push-Location + -Relative is the + #PS-5.1-compatible spelling of the same computation (the launcher runs + #Windows PowerShell - see punk-getzig_wrap.toml) + Push-Location $outbase + $relative_zigfolder = Resolve-Path -Path $zigfolder -Relative + Pop-Location Write-Host "zig.exe is installed in $relative_zigfolder" $zigv = & $zigexe version 2>&1 $stdout = $zigv | Where-Object {$_ -is [string]} @@ -194,7 +199,7 @@ if (-not $download_required) { $null = extractZip $releasearchive $toolsfolder $zigexe = Join-Path $zigfolder -ChildPath "zig.exe" - $v = Invoke-Expression "$zigexe version" + $v = & $zigexe version Write-Host "ZIG VERSION: ${v}" exit 0 } @@ -203,7 +208,10 @@ if (-not $download_required) { $mirrors_url = "https://ziglang.org/download/community-mirrors.txt" #some mirrors have no index and the base url will produce a 404, some have an html index, some have a modified copy of the ziglang.org/download/index.json -$mirrors_response = $(Invoke-WebRequest -Uri $mirrors_url) +#-UseBasicParsing: required for reliability on powershell 5 (without it PS5's +#Invoke-WebRequest uses the IE parsing engine - NullReferenceException on +#machines without it); harmless no-op on pwsh. Same convention as punk-runtime. +$mirrors_response = $(Invoke-WebRequest -UseBasicParsing -Uri $mirrors_url) if ($mirrors_response.StatusCode -eq 200) { #https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools/zig-x86_64-windows-0.15.1.zip $mirror_array = @("https://gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools") @@ -311,7 +319,7 @@ if ($mirrors_response.StatusCode -eq 200) { } #download the minisig first - because if that fails, we should move on without trying the larger download Write-Host "Downloading minisig signature from $sig_uristring" - Invoke-WebRequest -Uri $sig_uristring -Outfile "${outfile}.minisig" + Invoke-WebRequest -UseBasicParsing -Uri $sig_uristring -Outfile "${outfile}.minisig" if (-not(Test-Path -Path "${outfile}.minisig" -PathType Leaf)) { write-Host "Failed to download minisig signature from $sig_uristring to ${outfile}.minisig .. aborting download from $uristring" continue @@ -319,7 +327,15 @@ if ($mirrors_response.StatusCode -eq 200) { Write-Host "Downloading zig distribution from $full_uristring" Write-Host "Download to: $outfile" - Invoke-WebRequest -Uri $full_uristring -OutFile $outfile + #progress rendering makes PS5's Invoke-WebRequest -OutFile drastically + #slow on large files - suppress for the transfer, restore after + $OriginalProgressPreference = $Global:ProgressPreference + $Global:ProgressPreference = 'SilentlyContinue' + try { + Invoke-WebRequest -UseBasicParsing -Uri $full_uristring -OutFile $outfile + } finally { + $Global:ProgressPreference = $OriginalProgressPreference + } if (-not(Test-Path -Path $outfile -PathType Leaf)) { write-Host "Failed to download zig package from $full_uristring to ${outfile} .. aborting download from $uristring" @@ -357,7 +373,7 @@ if ($mirrors_response.StatusCode -eq 200) { $null = extractZip $releasearchive $toolsfolder $zigexe = Join-Path $zigfolder -ChildPath "zig.exe" - $v = Invoke-Expression "$zigexe version" + $v = & $zigexe version Write-Host "ZIG VERSION: ${v}" $test_ok = 1 ;#todo diff --git a/src/scriptapps/bin/punk-getzig_wrap.toml b/src/scriptapps/bin/punk-getzig_wrap.toml index 755c405a..a0e31939 100644 --- a/src/scriptapps/bin/punk-getzig_wrap.toml +++ b/src/scriptapps/bin/punk-getzig_wrap.toml @@ -16,6 +16,12 @@ #valid nextshelltype entries are: tcl perl pwsh powershell bash. #nextshellpath entries must be 64 characters or less. - win32.nextshellpath="pwsh -nop -nol -ExecutionPolicy bypass -c" - win32.nextshelltype="pwsh" + #win32.nextshellpath="pwsh -nop -nol -ExecutionPolicy bypass -c" + #win32.nextshelltype="pwsh" + + #powershell needs cmd.exe to preserve spaced args - and the -c (command + #string) form breaks on a spaced script path outright (tokenizes at the + #space). Same fix as punk-runtime_wrap.toml, found there during G-119. + win32.nextshellpath="cmd.exe /c powershell -nop -nol -ExecutionPolicy bypass -File" + win32.nextshelltype="powershell" win32.outputfile="punk-getzig.cmd"