#!/bin/sh # Print a table of tool versions: pinned (.tools/bin -- what make targets use, # because the Makefile prepends it to recipe PATH) vs PATH-first (what your own # shell resolves outside make). # # scripts/tool_versions.sh informational; always exits 0 # scripts/tool_versions.sh --strict exit 1 if a pinned tool is missing or # has the wrong version (used by `make # preflight`, which runs before # all/serve/serve-lan) set -u ROOT=$(cd "$(dirname "$0")/.." && pwd) BIN="$ROOT/.tools/bin" MODE=${1:-} HUGO_PIN="v0.167.0+extended" NODE_PIN="v22.11.0" LYCHEE_PIN="0.24.2" # PATH with .tools/bin stripped, so "PATH-first" shows what the user's shell # would resolve, even though make exported .tools/bin into our PATH. SYSPATH=$(printf '%s' "$PATH" | tr ':' '\n' | grep -vx "$BIN" | tr '\n' ':' | sed 's/:$//') pinned_ver() { case "$1" in # hugo release builds report "v-<40-hex-commit>+extended"; strip the commit hugo) [ -x "$BIN/hugo" ] && "$BIN/hugo" version 2>/dev/null | awk '{print $2}' | sed 's/-[0-9a-f]\{40,\}//' ;; node) [ -x "$BIN/node" ] && "$BIN/node" --version 2>/dev/null ;; npx) [ -x "$BIN/npx" ] && "$BIN/npx" --version 2>/dev/null ;; lychee) [ -x "$BIN/lychee" ] && "$BIN/lychee" --version 2>/dev/null | awk '{print $2}' ;; esac } first_path() { PATH="$SYSPATH" command -v "$1" 2>/dev/null; } first_ver() { # first_ver [ -n "${2:-}" ] || return 0 case "$1" in hugo) "$2" version 2>/dev/null | awk '{print $2}' | sed 's/-[0-9a-f]\{40,\}//' ;; node) "$2" --version 2>/dev/null ;; npx) "$2" --version 2>/dev/null ;; lychee) "$2" --version 2>/dev/null | awk '{print $2}' ;; python3) "$2" --version 2>/dev/null | awk '{print $2}' ;; esac } if [ "$MODE" = "--strict" ]; then fail=0 [ "$(pinned_ver hugo)" = "$HUGO_PIN" ] || { echo "preflight: pinned hugo $HUGO_PIN missing/wrong in $BIN" >&2; fail=1; } [ "$(pinned_ver node)" = "$NODE_PIN" ] || { echo "preflight: pinned node $NODE_PIN missing/wrong in $BIN" >&2; fail=1; } [ -n "$(pinned_ver npx)" ] || { echo "preflight: pinned npx missing in $BIN" >&2; fail=1; } [ "$(pinned_ver lychee)" = "$LYCHEE_PIN" ] || { echo "preflight: pinned lychee $LYCHEE_PIN missing/wrong in $BIN" >&2; fail=1; } command -v python3 >/dev/null 2>&1 || { echo "preflight: python3 not found on PATH (needed by serve-lan)" >&2; fail=1; } if [ "$fail" = 1 ]; then echo "preflight: fix with: make bootstrap" >&2 exit 1 fi echo "preflight: OK (pinned toolchain present in $BIN)" exit 0 fi row() { # row printf '%-8s %-27s %-27s %s\n' "$1" "$2" "$3" "${4:--}" } echo "tool pinned (.tools/bin) PATH-first (your shell)" for t in hugo node npx lychee; do pv=$(pinned_ver "$t") fp=$(first_path "$t") fv=$(first_ver "$t" "$fp") [ -n "$pv" ] || pv="(missing)" [ -n "$fv" ] || fv="(not installed)" row "$t" "$pv" "$fv" "$fp" done fp=$(first_path python3); fv=$(first_ver python3 "$fp") [ -n "$fv" ] || fv="(not installed)" row "python3" "(not pinned)" "$fv" "$fp" echo echo "make targets always use the pinned column. 'make bootstrap' installs it."