wdir="$(pwd)"; [ "$(pwd)" = "/" ] && wdir="" case "$0" in /*) scriptpath="${0}";; *) scriptpath="$wdir/${0#./}";; esac scriptdir="${scriptpath%/*}" scriptdir=$(realpath $scriptdir) scriptpath=$(realpath $scriptpath) basename=$(basename "$scriptpath") #e.g punk-runtime.bash scriptroot="${basename%.*}" #e.g "punk-runtime" #artifact server base url - overridable for mirrors/testing url_kitbase="${PUNKBIN_URL:-https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master}" runtime_available=0 #$OSTYPE varies in capitalization across for example zsh and bash #uname probably a more consistent bet arch=$(uname -m) #machine/architecture plat=$(uname -s) #platform/system #even though most of the platform prongs are very similar, #we keep the code separate so it can be tweaked easily for unexpected differences #each prong sets local_platform (the CANONICAL punkshell platform-DIR name - see #punk::platform / 'help platforms': cpu tokens normalized amd64->x86_64, #aarch64->arm64) and, where a runtime is published for the platform, rt_default #(default runtime name). narch="$arch" case "$narch" in amd64) narch="x86_64";; aarch64|arm64) narch="arm64";; esac if [[ "$plat" = "Linux"* ]]; then if [[ "$arch" = "x86_64"* ]]; then local_platform="linux-x86_64" rt_default="tclkit-902-Linux64-intel-dyn" runtime_available=1 elif [[ "$narch" = "arm64" ]]; then #canonical arm64 (aarch64). punkbin's existing arm kit predates the #arm64 name and sits in linux-arm - no fetch default here until a #linux-arm64 punkbin folder exists; name runtimes explicitly. local_platform="linux-arm64" elif [[ "$arch" = "arm"* ]]; then #32-bit arm local_platform="linux-arm" rt_default="tclkit-902-Linux64-arm-dyn" runtime_available=1 else local_platform="linux-$narch" fi os="linux" elif [[ "$plat" = "Darwin"* ]]; then os="macosx" #universal (multi-arch) binaries - the runtime tier keeps ONE macosx folder #(per-arch macosx-x86_64/macosx-arm64 names serve the lib tree tier) local_platform="macosx" rt_default="tclkit-902-Darwin64-dyn" runtime_available=1 elif [[ "$plat" = "FreeBSD"* ]]; then #canonical names (2026-07-22): freebsd-x86_64 (punkbin's actual folder; this #payload previously said freebsd-amd64) / freebsd-arm64 local_platform="freebsd-$narch" os="freebsd" elif [[ "$plat" == "DragonFly"* ]]; then local_platform="dragonflybsd-$narch" os="dragonflybsd" elif [[ "$plat" == "NetBSD"* ]]; then local_platform="netbsd-$narch" os="netbsd" elif [[ "$plat" == "OpenBSD"* ]]; then local_platform="openbsd-$narch" os="openbsd" elif [[ "$plat" == "MINGW32"* ]]; then #REVIEW os="win32" local_platform="win32-x86_64" rt_default="tclsh902z.exe" runtime_available=1 elif [[ "$plat" == "MINGW64"* ]]; then #REVIEW os="win32" local_platform="win32-x86_64" rt_default="tclsh902z.exe" runtime_available=1 elif [[ "$plat" == "CYGWIN_NT"* ]]; then os="win32" local_platform="win32-x86_64" rt_default="tclsh902z.exe" runtime_available=1 elif [[ "$plat" == "MSYS_NT"* ]]; then echo MSYS os="win32" #use 'command -v' (shell builtin preferred over external which) interp=`ps -p $$ | awk '$1 != "PID" {print $(NF)}' | tr -d '()' | sed -E 's/^.*\/|^-//'` shellpath=`command -v $interp` shellfolder="${shellpath%/*}" #avoid dependency on basename or dirname #"c:/windows/system32/" is quite likely in the path ahead of msys,git etc. #This breaks calls to various unix utils such as sed etc (wsl related?) export PATH="$shellfolder${PATH:+:${PATH}}" local_platform="win32-x86_64" rt_default="tclsh902z.exe" runtime_available=1 else local_platform="other" os="other" fi #-- platform resolution (G-105 cross-build staging) --------------------------- #The prongs above detect the LOCAL platform. fetch/list/use accept #'-platform

' to aim at another punkbin platform-dir (cross-build staging / #provisioning); resolution: -platform arg > PUNK_RUNTIME_PLATFORM env > local. #Values are punkbin platform-dir names (e.g win32-x86_64, linux-x86_64, macosx) #- NOT zig triples (the buildsuite maps triples to platform dirs at build time). #Validation is shape-only: the server's sha1sums/404 is the truth for what #exists. 'run' is LOCAL ONLY (foreign binaries are not runnable here) - only a #LEADING -platform is rejected there; later args belong to the launched runtime. action="${1:-}" [[ $# -gt 0 ]] && shift platform_opt="" case "$action" in fetch|list|use|platforms) newargs=() while [[ $# -gt 0 ]]; do if [[ "$1" == "-platform" ]]; then shift if [[ $# -eq 0 ]]; then echo "option -platform requires a value (a punkbin platform-dir name, e.g linux-x86_64)" exit 1 fi platform_opt="$1" else newargs+=("$1") fi shift done set -- ${newargs[@]+"${newargs[@]}"} ;; run) if [[ "${1:-}" == "-platform" ]]; then echo "'run' launches the LOCAL platform's active runtime - it takes no -platform option" echo "(foreign-platform folders are cross-build staging; deploy them to their platform to run)" exit 1 fi ;; esac platform="${platform_opt:-${PUNK_RUNTIME_PLATFORM:-$local_platform}}" if ! [[ "$platform" =~ ^[a-z0-9][a-z0-9_-]*$ ]]; then echo "invalid platform name '$platform' (expected a punkbin platform-dir name such as win32-x86_64, linux-x86_64, macosx)" exit 1 fi is_local=0 [[ "$platform" == "$local_platform" ]] && is_local=1 archdir="${scriptdir}/runtime/${platform}" archtail="$platform" #server folder name e.g linux-x86_64 active_file="${archdir}/active.toml" #sha1 of a file - tool varies by platform (sha1sum: linux/coreutils, shasum: macosx, #sha1: BSDs, openssl: common fallback). Empty result means no tool available. sha1_of() { if command -v sha1sum >/dev/null 2>&1; then sha1sum "$1" | awk '{print $1}' elif command -v shasum >/dev/null 2>&1; then shasum -a 1 "$1" | awk '{print $1}' elif command -v sha1 >/dev/null 2>&1; then sha1 -q "$1" elif command -v openssl >/dev/null 2>&1; then openssl dgst -sha1 -r "$1" | awk '{print $1}' else echo "" fi } lcase() { printf '%s' "$1" | tr 'A-F' 'a-f'; } #active runtime marker: constrained single-key toml, per platform folder #(local per-machine state - ignored by git and fossil) get_active() { if [[ -f "$active_file" ]]; then sed -n 's/^[[:space:]]*active[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' "$active_file" | head -n 1 fi } set_active() { printf 'active = "%s"\n' "$1" > "$active_file" echo "active runtime for $archtail set to: $1 (recorded in $active_file)" } #installed runtime candidates - exclude directories, build copies and #non-runtime files (ps1-payload parity: files only, same extension excludes) list_candidates() { local f if [[ -d "$archdir" ]]; then for f in "$archdir"/*; do [[ -f "$f" ]] || continue f="${f##*/}" case "$f" in *_BUILDCOPY*|*.txt|*.toml|*.tm|*.tmp|*.log) continue;; esac printf '%s\n' "$f" done fi } #name minus a .exe suffix only - dotted tcl patchlevels (tclsh9.0.5-punk) make #generic last-dot extension stripping wrong for extensionless unix names rootname_of() { case "$1" in *.exe|*.EXE) printf '%s' "${1%.???}";; *) printf '%s' "$1";; esac } #G-103 artifact metadata: a runtime may carry a .toml beside it (emitted #by the buildsuite kit-family-artifacts step / fetched from punkbin). Prints a #short "[variant=... tcl=... rN ...]" summary for list output, "" when absent. metadata_summary() { local exename="$1" tomlfile parts variant tclpatch revision piperepl artname target tomlfile="$archdir/$(rootname_of "$exename").toml" [[ -f "$tomlfile" ]] || return 0 variant=$(sed -n 's/^[[:space:]]*variant[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' "$tomlfile" | head -n 1) tclpatch=$(sed -n 's/^[[:space:]]*tcl_patchlevel[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' "$tomlfile" | head -n 1) revision=$(sed -n 's/^[[:space:]]*revision[[:space:]]*=[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$tomlfile" | head -n 1) piperepl=$(sed -n 's/^[[:space:]]*piperepl[[:space:]]*=[[:space:]]*\(true\|false\).*/\1/p' "$tomlfile" | head -n 1) artname=$(sed -n 's/^[[:space:]]*name[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' "$tomlfile" | head -n 1) target=$(sed -n 's/^[[:space:]]*target[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' "$tomlfile" | head -n 1) parts="" [[ -n "$variant" ]] && parts="$parts variant=$variant" [[ -n "$tclpatch" ]] && parts="$parts tcl=$tclpatch" [[ -n "$revision" ]] && parts="$parts r$revision" if [[ "$piperepl" == "true" ]]; then parts="$parts piperepl=on" elif [[ "$piperepl" == "false" ]]; then parts="$parts piperepl=off"; fi #a materialized working copy records which immutable artifact it came from [[ -n "$artname" && "$artname" != "$exename" ]] && parts="$parts from=$artname" #integrity flag: a runtime filed under a platform folder its metadata says it #was not built for (cross-platform fetch/staging misfiling) [[ -n "$target" && "$target" != "$archtail" ]] && parts="$parts !TARGET-MISMATCH:$target" [[ -n "$parts" ]] && printf '[%s]' "${parts# }" } #operator help (the 'help' action; the no-args case shows show_usage only). #Keep in sync with the ps1 payload's Show-PunkRuntimeHelp/Show-PunkRuntimeUsage. show_usage() { echo "Usage: $0 {fetch|list|use|run|platforms|help}" echo " fetch ?? ?-platform

? download+verify a runtime from punkbin" echo " list ?-remote? ?-platform

? installed (or server) runtimes + metadata" echo " use ?-platform

? select active / materialize -r artifact" echo " run ?args...? launch the active local-platform runtime" echo " platforms ?-remote? local platform folders / platforms the server serves" echo " help full help (options, env vars, examples)" } show_help() { echo "punk-runtime - manage the plain Tcl runtimes under bin/runtime//" echo "" show_usage echo "" echo "Actions:" echo " fetch ?? ?-platform

?" echo " Download a runtime from the punkbin artifact server into" echo " bin/runtime/

/ with sha1 verification against the server's" echo " sha1sums.txt. -r-named family artifacts also fetch their" echo " .toml metadata record. Omitting fetches the" echo " local platform's default runtime; a FOREIGN platform fetch" echo " requires an explicit ." echo " list ?-remote? ?-platform

?" echo " List installed runtimes with artifact-metadata summaries" echo " (variant, tcl patchlevel, revision, piperepl policy, source" echo " artifact of a materialized copy; a !TARGET-MISMATCH flag marks" echo " a runtime filed under the wrong platform folder). -remote" echo " compares local runtimes against the server's sha1sums." echo " use ?-platform

?" echo " Select the runtime that 'run' launches (records active.toml in" echo " the platform folder). An immutable -r ARTIFACT name is" echo " MATERIALIZED into its WORKING name (name minus -r - what" echo " mapvfs and projects reference), metadata toml copied alongside." echo " run ?args...?" echo " Launch the ACTIVE runtime of the LOCAL platform, passing args." echo " Resolution: PUNK_ACTIVE_RUNTIME env > active.toml > sole" echo " installed candidate. Takes no -platform (foreign binaries are" echo " not runnable here)." echo " platforms ?-remote?" echo " List local platform folders under bin/runtime/. With -remote," echo " list the platforms the artifact server serves - read from the" echo " server's platforms.txt discovery manifest (part of the punkbin" echo " layout; third-party mirrors carry the same file), with local" echo " presence marked. Servers without the manifest get an actionable" echo " message (name platforms explicitly with -platform)." echo "" echo "Platforms: punkbin platform-dir names (e.g win32-x86_64, linux-x86_64," echo " macosx) - not zig triples. Default is the local platform; override" echo " order: -platform argument > PUNK_RUNTIME_PLATFORM env var." echo " Foreign-platform folders serve cross-build staging and provisioning:" echo " active.toml travels with the folder when it is deployed to its real" echo " platform (unix exec bits are restored at deploy time - e.g rsync/tar/" echo " chmod on the receiving side)." echo "" echo "Env: PUNKBIN_URL (artifact server base url), PUNK_RUNTIME_PLATFORM," echo " PUNK_ACTIVE_RUNTIME (run-time selection override)" echo "" echo "Examples:" echo " $0 platforms -remote" echo " $0 fetch tclsh9.0.5-punk-r1.exe" echo " $0 use tclsh9.0.5-punk-r1.exe (materializes tclsh9.0.5-punk.exe)" echo " $0 list -remote -platform linux-x86_64" echo " $0 fetch tclsh9.0.5-punk-r1 -platform linux-x86_64" echo " $0 use tclsh9.0.5-punk-r1 -platform linux-x86_64" echo " $0 run myscript.tcl arg1 arg2" } #G-103 artifact-tier names carry -r before the (optional) .exe suffix; prints #the WORKING name (artifact minus -r) when the name is artifact-tier, else "" working_name_of() { local w w=$(printf '%s' "$1" | sed -E 's/^(.*)-r[0-9]+(\.[Ee][Xx][Ee])?$/\1\2/') if [[ "$w" != "$1" ]]; then printf '%s' "$w"; fi } case "$action" in "fetch") runtime="$rt_default" if [[ -n "${1:-}" ]]; then runtime="$1" elif [[ "$is_local" -ne 1 ]]; then #fetch-name defaults only make sense for the platform we are standing #on - a foreign-platform fetch (cross-build staging) names its runtime echo "No default runtime for foreign platform '$platform' - name it explicitly:" echo " $0 fetch -platform $platform" echo " (see available names: $0 list -remote -platform $platform)" exit 1 fi if [[ ( "$runtime_available" -eq 1 || -n "${1:-}" ) && "$archtail" != "other" && -n "$runtime" ]]; then url="${url_kitbase}/${archtail}/${runtime}" output="${archdir}/${runtime}" sha1url="${url_kitbase}/${archtail}/sha1sums.txt" sha1local="${archdir}/sha1sums.txt" mkdir -p "$archdir" echo "Fetching $sha1url" if ! curl -fsSL --output "$sha1local" "$sha1url"; then echo "An error occurred while downloading $sha1url" if [[ -f "$output" ]]; then echo "A runtime is available at $output - but we failed to retrieve the list of sha1sums from the server" echo "Unable to check for updated version at this time." else echo "Please retry - or manually download a runtime from ${url_kitbase}/${archtail} and verify checksums" fi exit 1 fi #sha1sums.txt line format: * (binary indicator) #(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) if [[ -z "$stored_sha1" ]]; then echo "Unable to locate hash for $runtime in $sha1local - Aborting" echo "Please download and verify manually (or check available names with: $0 list)" exit 1 fi probe=$(sha1_of "$sha1local") if [[ -z "$probe" ]]; then echo "No sha1 tool found (tried sha1sum, shasum, sha1, openssl) - refusing unverified download." echo "Please install one (e.g coreutils or openssl) and retry." exit 1 fi need_download=1 if [[ -f "$output" ]]; then echo "Runtime already found at $output" echo "Checking sha1 checksum of local file versus sha1 of server file" local_sha1=$(sha1_of "$output") if [[ "$(lcase "$local_sha1")" == "$(lcase "$stored_sha1")" ]]; then need_download=0 echo "Local copy of runtime at $output matches sha1 checksum of file on server." echo "No download required" else echo "$runtime on server has different sha1 hash - Download required" fi else echo "$runtime not found locally - Download required" fi if [[ "$need_download" -eq 1 ]]; then echo "Downloading from $url ..." if ! curl -fSL --output "${output}.tmp" "$url"; then echo "Error: Failed to download to ${output}.tmp" exit 1 fi echo "comparing sha1 checksum of downloaded file with data in sha1sums.txt" new_sha1=$(sha1_of "${output}.tmp") if [[ "$(lcase "$new_sha1")" == "$(lcase "$stored_sha1")" ]]; then echo "sha1 checksum ok" mv -f "${output}.tmp" "$output" chmod +x "$output" echo "Runtime is available at $output" if [[ "$plat" == "Linux"* ]]; then echo "Please ensure libxFt.so.2 is available" echo "e.g on Ubuntu: sudo apt-get install libxft2" fi else echo "WARNING! sha1 of downloaded file at ${output}.tmp does not match stored sha1 from sha1sums.txt" echo "The .tmp file has been left in place for inspection - it has NOT been installed." exit 1 fi fi #G-103: family artifacts (-r names) carry a metadata toml alongside #on the server - fetch it too; absence is fine (pre-family runtimes) if [[ -n "$(working_name_of "$runtime")" ]]; then tomlname="$(rootname_of "$runtime").toml" if curl -fsSL --output "${archdir}/${tomlname}" "${url_kitbase}/${archtail}/${tomlname}"; then echo "artifact metadata saved at ${archdir}/${tomlname}" else rm -f "${archdir}/${tomlname}" echo "no artifact metadata toml on server for $runtime (ok for pre-family runtimes)" fi fi #first fetch establishes the active runtime; later fetches never steal it if [[ -z "$(get_active)" ]]; then set_active "$runtime" fi else echo "No default runtime currently published for $os ($archtail)" echo "If one exists on the server, name it explicitly: $0 fetch " fi ;; "list") if [[ "${1:-}" == "-remote" ]]; then #compare local runtimes with those listed on the artifact server #(functional parity with the powershell payload's 'list -remote') sha1url="${url_kitbase}/${archtail}/sha1sums.txt" sha1local="${archdir}/sha1sums.txt" mkdir -p "$archdir" if curl -fsSL --output "$sha1local" "$sha1url"; then echo "Fetched $sha1url" elif [[ -f "$sha1local" ]]; then echo "WARNING: could not fetch $sha1url - using cached copy at $sha1local" else echo "Unable to fetch $sha1url and no cached copy available" exit 1 fi probe=$(sha1_of "$sha1local") if [[ -z "$probe" ]]; then echo "No sha1 tool found (tried sha1sum, shasum, sha1, openssl) - cannot compare local runtimes." exit 1 fi echo "-----------------------------------------------------------------------" echo "Runtimes for $archtail" echo "Local $archdir" echo "Remote ${url_kitbase}/${archtail}" echo "-----------------------------------------------------------------------" echo "Local Remote" echo "-----------------------------------------------------------------------" for f in $(list_candidates); do local_sha1=$(lcase "$(sha1_of "$archdir/$f")") stored_sha1=$(grep -E "^[0-9a-fA-F]{40} \*${f}\$" "$sha1local" | head -n 1 | cut -d' ' -f1) if [[ -z "$stored_sha1" ]]; then rhs="(not listed on server)" elif [[ "$local_sha1" == "$(lcase "$stored_sha1")" ]]; then rhs="Same version" else rhs="UPDATE AVAILABLE" fi printf '%-35s %s\n' "$f" "$rhs" done #remote-only entries while IFS= read -r line; do rname=$(printf '%s' "$line" | sed -n 's/^[0-9a-fA-F]\{40\} \*\(.*\)$/\1/p') if [[ -n "$rname" && ! -f "$archdir/$rname" ]]; then printf '%-35s %s\n' "-" "$rname" fi done < "$sha1local" echo "-----------------------------------------------------------------------" else if [[ -d "$archdir" ]]; then candidates=$(list_candidates) active=$(get_active) count=$(printf '%s\n' "$candidates" | grep -c . ) echo "$count runtime(s) in $archdir" for f in $candidates; do meta=$(metadata_summary "$f") if [[ "$f" == "$active" ]]; then printf '* %-35s (active) %s\n' "$f" "$meta" else printf ' %-35s %s\n' "$f" "$meta" fi done if [[ -n "$active" && ! -f "$archdir/$active" ]]; then echo "WARNING: active runtime '$active' (from $active_file) is not present - use '$0 use ' to reselect" fi echo "Use: '$0 list -remote' to compare local runtimes with those available on the artifact server" echo "Use: '$0 use ' to select the runtime that 'run' launches" echo "Use: '$0 use -name>' to materialize an immutable -r artifact into its working name and select it" else echo "No runtimes available in $archdir" echo " Use '$0 fetch' to install." fi fi ;; "use") #with -platform: manage THAT platform folder's selection/materialization #(cross-build staging - active.toml travels with the folder when deployed; #'run' on this machine only ever consults the local platform) if [[ -z "${1:-}" ]]; then echo "Usage: $0 use ?-platform

?" echo "Installed candidates ($platform):" for f in $(list_candidates); do echo " $f" done active=$(get_active) if [[ -n "$active" ]]; then echo "Currently active: $active" fi exit 1 fi case "$1" in *_BUILDCOPY|*.txt|*.toml|*.tm|*.tmp) echo "'$1' is not a selectable runtime" exit 1 ;; esac if [[ ! -f "$archdir/$1" ]]; then echo "No runtime named '$1' found in $archdir" echo "Installed candidates:" for f in $(list_candidates); do echo " $f" done exit 1 fi #G-103 artifact-tier names (-r, immutable): 'use' MATERIALIZES the #artifact into its WORKING name (name minus -r - what mapvfs and #projects reference), copies its metadata toml alongside, and selects #the working name. Republishing artifacts never churns consumers. #(chmod is a no-op when staging unix runtimes from windows filesystems - #exec bits are restored at deploy time, e.g rsync/tar/chmod on the guest.) working=$(working_name_of "$1") if [[ -n "$working" ]]; then cp -f "$archdir/$1" "$archdir/$working" chmod +x "$archdir/$working" srctoml="$archdir/$(rootname_of "$1").toml" desttoml="$archdir/$(rootname_of "$working").toml" if [[ -f "$srctoml" ]]; then cp -f "$srctoml" "$desttoml" echo "materialized $working from artifact $1 (metadata toml copied alongside)" else echo "materialized $working from artifact $1 (no metadata toml found beside the artifact)" fi set_active "$working" else set_active "$1" fi ;; "run") #resolution order: PUNK_ACTIVE_RUNTIME env override, active.toml, single #installed candidate - otherwise error with candidates (no last-in-list guessing). #LOCAL platform only: the -platform arg is rejected in the scan above, and a #PUNK_RUNTIME_PLATFORM env override is likewise ignored here (foreign #binaries are not runnable; the env override serves list/fetch/use). if [[ "$is_local" -ne 1 ]]; then archdir="${scriptdir}/runtime/${local_platform}" active_file="${archdir}/active.toml" fi activeruntime="" if [[ -n "$PUNK_ACTIVE_RUNTIME" ]]; then activeruntime="$PUNK_ACTIVE_RUNTIME" if [[ ! -f "$archdir/$activeruntime" ]]; then echo "PUNK_ACTIVE_RUNTIME '$activeruntime' not found in $archdir" exit 1 fi else activeruntime=$(get_active) if [[ -n "$activeruntime" && ! -f "$archdir/$activeruntime" ]]; then echo "active runtime '$activeruntime' (from $active_file) is not present in $archdir" echo "Reselect with: $0 use (or fetch it: $0 fetch $activeruntime)" exit 1 fi if [[ -z "$activeruntime" ]]; then candidates=$(list_candidates) count=$(printf '%s\n' "$candidates" | grep -c . ) if [[ "$count" -eq 1 ]]; then activeruntime="$candidates" elif [[ "$count" -eq 0 ]]; then echo "No runtimes seem to be installed in $archdir" echo "Please use '$0 fetch' to install." exit 1 else echo "Multiple runtimes installed and no active runtime selected." echo "Select one with: $0 use " echo "Installed candidates:" for f in $candidates; do echo " $f" done exit 1 fi fi fi activeruntime_fullpath="$archdir/$activeruntime" #echo "using $activeruntime_fullpath" #(the action was already shifted off during the option scan - "$@" is #exactly the runtime's argument list) $activeruntime_fullpath "$@" ;; "platforms") #enumerate platform folders: local (bin/runtime/*) and, with -remote, the #server's platforms.txt discovery manifest (raw-file servers have no #directory listing - the manifest is part of the punkbin layout contract; #third-party mirrors carry the same file). -platform is ignored here #(this action enumerates ALL platforms). rtroot="${scriptdir}/runtime" localdirs="" if [[ -d "$rtroot" ]]; then localdirs=$(ls -1 "$rtroot" 2>/dev/null | while read -r d; do [[ -d "$rtroot/$d" ]] && echo "$d"; done) fi if [[ "${1:-}" == "-remote" ]]; then manifesturl="${url_kitbase}/platforms.txt" manifestlocal="${rtroot}/platforms.txt" mkdir -p "$rtroot" if curl -fsSL --output "$manifestlocal" "$manifesturl"; then echo "Fetched $manifesturl" elif [[ -f "$manifestlocal" ]]; then echo "WARNING: could not fetch $manifesturl - using cached copy at $manifestlocal" else echo "No platforms.txt available from $manifesturl" echo "(pre-convention punkbin or third-party mirror without the discovery manifest)" echo "Name platforms explicitly with -platform; canonical names: 'help platforms' in the punk shell" exit 1 fi echo "-----------------------------------------------------------------------" echo "Platforms served by ${url_kitbase}" echo "-----------------------------------------------------------------------" remoteplatforms="" while IFS= read -r line; do line="${line#"${line%%[![:space:]]*}"}" [[ -z "$line" || "${line:0:1}" == "#" ]] && continue remoteplatforms="$remoteplatforms $line" marks="" [[ "$line" == "$local_platform" ]] && marks="local platform" if printf '%s\n' $localdirs | grep -qx "$line"; then [[ -n "$marks" ]] && marks="$marks, " marks="${marks}local dir present" fi if [[ -n "$marks" ]]; then printf ' %-25s (%s)\n' "$line" "$marks" else printf ' %-25s\n' "$line" fi done < "$manifestlocal" for d in $localdirs; do if ! printf '%s\n' $remoteplatforms | grep -qx "$d"; then printf ' %-25s (local dir only - not served remotely)\n' "$d" fi done echo "-----------------------------------------------------------------------" echo "Use: '$0 list -remote -platform ' to see a platform's runtimes" else echo "-----------------------------------------------------------------------" echo "Local platform folders under $rtroot" echo "-----------------------------------------------------------------------" if [[ -z "$localdirs" ]]; then echo " (none - 'fetch' creates the local platform's folder)" fi for d in $localdirs; do if [[ "$d" == "$local_platform" ]]; then printf '* %-25s (local platform)\n' "$d" else printf ' %-25s\n' "$d" fi done echo "-----------------------------------------------------------------------" echo "Use: '$0 platforms -remote' to see platforms served by the artifact server" echo "Canonical platform names: 'help platforms' in the punk shell" fi ;; "help") show_help ;; "") #no action: short usage + pointer at the fuller help show_usage echo "" echo "'$0 help' gives options, env vars and examples." ;; *) echo "unknown action '$action'" show_usage exit 1 ;; esac #(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)