Browse Source

punk-runtime: strip CR before sha1sums lookups in the bash payload (punkshell 0.32.3)

fetch and list's local-file comparison anchored runtime names at
end-of-line without stripping CR first, so a CRLF-published server
sha1sums.txt aborted fetch with "Unable to locate hash" on strict
grep platforms (GNU and BSD grep; cygwin grep tolerates CRLF, and
the ps1 payload is immune via Get-Content line splitting). Both
lookups now share the tr -d '\r' form list -remote already used.

bin/punk-runtime.cmd regenerated via the scriptwrap machinery; the
re-wrap invocation in src/scriptapps/AGENTS.md is corrected to the
working -force 1 -askme 0 form found during regeneration.

Assisted-by: harness=opencode; primary-model=huggingface/moonshotai/Kimi-K3; api-location=unknown
master
Julian Noble 2 days ago
parent
commit
4f753264b2
  1. 10
      CHANGELOG.md
  2. 6
      bin/punk-runtime.cmd
  3. 2
      punkproject.toml
  4. 2
      src/scriptapps/AGENTS.md
  5. 6
      src/scriptapps/bin/punk-runtime.bash

10
CHANGELOG.md

@ -5,6 +5,16 @@ 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` Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy. "Project Versioning" section for the bump policy.
## [0.32.3] - 2026-07-31
- `punk-runtime` bash payload: `fetch` and `list`'s local-file comparison now
strip CR characters before matching sha1sums.txt entries, fixing the
"Unable to locate hash" abort when the artifact server publishes
sha1sums.txt with CRLF line endings (GNU/BSD grep anchor `$` strictly, so
the end-of-line filename match failed even with the entry present; the ps1
payload was unaffected via Get-Content line splitting). All sha1sums lookups
in the payload now share the CR-stripping form `list -remote` already used.
## [0.32.2] - 2026-07-30 ## [0.32.2] - 2026-07-30
- Linux lib-tier emission (G-140, achieved): suite_tcl90 gains a `tcllibc-linux` - Linux lib-tier emission (G-140, achieved): suite_tcl90 gains a `tcllibc-linux`

6
bin/punk-runtime.cmd

@ -1800,7 +1800,9 @@ case "$action" in
fi fi
#sha1sums.txt line format: <sha1> *<filename> (binary indicator) #sha1sums.txt line format: <sha1> *<filename> (binary indicator)
#(dots in $runtime are regex-any here - acceptable for these filenames) #(dots in $runtime are regex-any here - acceptable for these filenames)
stored_sha1=$(grep -E "^[0-9a-fA-F]{40} \*${runtime}\$" "$sha1local" | head -n 1 | cut -d' ' -f1) #strip CR: the server's sha1sums.txt may carry CRLF endings, which
#otherwise defeat the $ anchor below (as every other lookup here does)
stored_sha1=$(tr -d '\r' < "$sha1local" | grep -E "^[0-9a-fA-F]{40} \*${runtime}\$" | head -n 1 | cut -d' ' -f1)
if [[ -z "$stored_sha1" ]]; then if [[ -z "$stored_sha1" ]]; then
echo "Unable to locate hash for $runtime in $sha1local - Aborting" echo "Unable to locate hash for $runtime in $sha1local - Aborting"
echo "Please download and verify manually (or check available names with: $0 list)" echo "Please download and verify manually (or check available names with: $0 list)"
@ -1943,7 +1945,7 @@ case "$action" in
echo "----------------------------------------------------------------------------------------" echo "----------------------------------------------------------------------------------------"
for f in $(list_candidates); do for f in $(list_candidates); do
local_sha1=$(lcase "$(sha1_of "$archdir/$f")") local_sha1=$(lcase "$(sha1_of "$archdir/$f")")
stored_sha1=$(grep -E "^[0-9a-fA-F]{40} \*${f}\$" "$sha1local" | head -n 1 | cut -d' ' -f1) stored_sha1=$(tr -d '\r' < "$sha1local" | grep -E "^[0-9a-fA-F]{40} \*${f}\$" | head -n 1 | cut -d' ' -f1)
mid="" mid=""
ident="" ident=""
if [[ -n "$stored_sha1" ]]; then if [[ -n "$stored_sha1" ]]; then

2
punkproject.toml

@ -1,4 +1,4 @@
[project] [project]
name = "punkshell" name = "punkshell"
version = "0.32.2" version = "0.32.3"
license = "BSD-2-Clause" license = "BSD-2-Clause"

2
src/scriptapps/AGENTS.md

@ -13,7 +13,7 @@ Standalone Tcl scripts that serve as entry points for Punk applications and util
- Scripts here are invoked directly by the user or by build tools, not loaded as packages. - Scripts here are invoked directly by the user or by build tools, not loaded as packages.
- Wrapper configs (`.toml` files) define how scripts are packaged as platform executables. - Wrapper configs (`.toml` files) define how scripts are packaged as platform executables.
- `<name>_wrap.toml` scriptsets are the SOURCE of the generated polyglot `.cmd` scripts in `<projectroot>/bin`, and bin-deployed scriptsets live in the `bin/` subfolder here (e.g `bin/punk-runtime.ps1` + `bin/punk-runtime.bash` + `bin/punk-runtime_wrap.toml` -> `<projectroot>/bin/punk-runtime.cmd` via `punk::mix::commandset::scriptwrap::multishell punk-runtime -askme 0`, run from `src/scriptapps/bin`, alongside the `punk-getzig.*` scriptset). Fixes to a `bin/*.cmd` polyglot are made in the scriptset sources and re-wrapped - never in the output file. Regenerate and commit the bin output together with payload changes: `src/tests/modules/punk/mix/testsuites/scriptwrap/runtimecmd_roundtrip.test` pins the punk-runtime scriptset round-trip byte-identical against `bin/punk-runtime.cmd`, and `src/tests/shell/testsuites/binscripts/dtplite.test` pins the dtplite scriptset (`dtplite.tcl` + `dtplite_wrap.toml`, wrapped from this folder) against `bin/dtplite.cmd` the same way. Payload scripts embedded in polyglots must be LF-only - the wrap embeds payload bytes verbatim and the multishell output contract is LF-only. - `<name>_wrap.toml` scriptsets are the SOURCE of the generated polyglot `.cmd` scripts in `<projectroot>/bin`, and bin-deployed scriptsets live in the `bin/` subfolder here (e.g `bin/punk-runtime.ps1` + `bin/punk-runtime.bash` + `bin/punk-runtime_wrap.toml` -> `<projectroot>/bin/punk-runtime.cmd` via `punk::mix::commandset::scriptwrap::multishell punk-runtime -force 1 -askme 0` (after `package require punk::mix::commandset::scriptwrap`; `-force 1` is required because `-askme 0` alone aborts when the target exists), run from `src/scriptapps/bin`, alongside the `punk-getzig.*` scriptset). Fixes to a `bin/*.cmd` polyglot are made in the scriptset sources and re-wrapped - never in the output file. Regenerate and commit the bin output together with payload changes: `src/tests/modules/punk/mix/testsuites/scriptwrap/runtimecmd_roundtrip.test` pins the punk-runtime scriptset round-trip byte-identical against `bin/punk-runtime.cmd`, and `src/tests/shell/testsuites/binscripts/dtplite.test` pins the dtplite scriptset (`dtplite.tcl` + `dtplite_wrap.toml`, wrapped from this folder) against `bin/dtplite.cmd` the same way. Payload scripts embedded in polyglots must be LF-only - the wrap embeds payload bytes verbatim and the multishell output contract is LF-only.
- The `spud/` directory holds the spud build tool's app scripts. - The `spud/` directory holds the spud build tool's app scripts.
- The `tools/` directory holds miscellaneous build and deployment utilities. - The `tools/` directory holds miscellaneous build and deployment utilities.

6
src/scriptapps/bin/punk-runtime.bash

@ -520,7 +520,9 @@ case "$action" in
fi fi
#sha1sums.txt line format: <sha1> *<filename> (binary indicator) #sha1sums.txt line format: <sha1> *<filename> (binary indicator)
#(dots in $runtime are regex-any here - acceptable for these filenames) #(dots in $runtime are regex-any here - acceptable for these filenames)
stored_sha1=$(grep -E "^[0-9a-fA-F]{40} \*${runtime}\$" "$sha1local" | head -n 1 | cut -d' ' -f1) #strip CR: the server's sha1sums.txt may carry CRLF endings, which
#otherwise defeat the $ anchor below (as every other lookup here does)
stored_sha1=$(tr -d '\r' < "$sha1local" | grep -E "^[0-9a-fA-F]{40} \*${runtime}\$" | head -n 1 | cut -d' ' -f1)
if [[ -z "$stored_sha1" ]]; then if [[ -z "$stored_sha1" ]]; then
echo "Unable to locate hash for $runtime in $sha1local - Aborting" echo "Unable to locate hash for $runtime in $sha1local - Aborting"
echo "Please download and verify manually (or check available names with: $0 list)" echo "Please download and verify manually (or check available names with: $0 list)"
@ -663,7 +665,7 @@ case "$action" in
echo "----------------------------------------------------------------------------------------" echo "----------------------------------------------------------------------------------------"
for f in $(list_candidates); do for f in $(list_candidates); do
local_sha1=$(lcase "$(sha1_of "$archdir/$f")") local_sha1=$(lcase "$(sha1_of "$archdir/$f")")
stored_sha1=$(grep -E "^[0-9a-fA-F]{40} \*${f}\$" "$sha1local" | head -n 1 | cut -d' ' -f1) stored_sha1=$(tr -d '\r' < "$sha1local" | grep -E "^[0-9a-fA-F]{40} \*${f}\$" | head -n 1 | cut -d' ' -f1)
mid="" mid=""
ident="" ident=""
if [[ -n "$stored_sha1" ]]; then if [[ -n "$stored_sha1" ]]; then

Loading…
Cancel
Save