# shellcheck shell=bash # ----------------------------------------------------------------------------- # preflight/lib/common.sh — shared helpers for all preflight checks. # Sourced (not executed). POSIX-friendly, macOS bash 3.2 compatible: # no associative arrays, no `mapfile`, no `${var^^}`, no process substitution. # ----------------------------------------------------------------------------- # ANSI colors (disabled if not a tty or NO_COLOR set). if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then PF_RED=$(printf '\033[31m'); PF_GRN=$(printf '\033[32m') PF_YEL=$(printf '\033[33m'); PF_RST=$(printf '\033[0m') else PF_RED=""; PF_GRN=""; PF_YEL=""; PF_RST="" fi # Per-process result counters. Each check script reports into these and prints # its own lines; preflight.sh sums up by parsing the exit code + a summary line. PF_PASS=0 PF_FAIL=0 PF_WARN=0 pf_pass() { PF_PASS=$((PF_PASS + 1)); printf ' %sPASS%s %s\n' "$PF_GRN" "$PF_RST" "$*"; } pf_fail() { PF_FAIL=$((PF_FAIL + 1)); printf ' %sFAIL%s %s\n' "$PF_RED" "$PF_RST" "$*"; } pf_warn() { PF_WARN=$((PF_WARN + 1)); printf ' %sWARN%s %s\n' "$PF_YEL" "$PF_RST" "$*"; } pf_info() { printf ' %s----%s %s\n' "$PF_YEL" "$PF_RST" "$*"; } # pf_summary : print one machine-parseable line and return an exit # code: 0 if no failures, 1 if any failure. WARN never fails. pf_summary() { printf ' -> %s: %d pass, %d warn, %d fail\n' "$1" "$PF_PASS" "$PF_WARN" "$PF_FAIL" [ "$PF_FAIL" -eq 0 ] } # pf_have : true if command exists on PATH. pf_have() { command -v "$1" >/dev/null 2>&1; } # pf_vercmp : numeric dotted-version compare. Echoes: # 0 if a == b, 1 if a > b, 2 if a < b. Missing components treated as 0. # Non-numeric leading tokens are stripped (e.g. "v3.243.0" -> "3.243.0"). pf_vercmp() { a=$(printf '%s' "$1" | sed -e 's/^[^0-9]*//' -e 's/[^0-9.].*$//') b=$(printf '%s' "$2" | sed -e 's/^[^0-9]*//' -e 's/[^0-9.].*$//') # Normalize to dot-separated fields and compare field by field. IFS=. # shellcheck disable=SC2086 set -- $a; a1=${1:-0}; a2=${2:-0}; a3=${3:-0}; a4=${4:-0} # shellcheck disable=SC2086 set -- $b; b1=${1:-0}; b2=${2:-0}; b3=${3:-0}; b4=${4:-0} unset IFS i=1 for pair in "$a1 $b1" "$a2 $b2" "$a3 $b3" "$a4 $b4"; do # shellcheck disable=SC2086 set -- $pair av=$(printf '%s' "$1" | sed 's/[^0-9].*$//'); av=${av:-0} bv=$(printf '%s' "$2" | sed 's/[^0-9].*$//'); bv=${bv:-0} if [ "$av" -gt "$bv" ] 2>/dev/null; then echo 1; return 0; fi if [ "$av" -lt "$bv" ] 2>/dev/null; then echo 2; return 0; fi i=$((i + 1)) done echo 0 } # pf_ge : true (0) if version `have` >= `min`. pf_ge() { r=$(pf_vercmp "$1" "$2") [ "$r" = "0" ] || [ "$r" = "1" ] } # pf_versions_file : absolute path to the VERSIONS pin-file (repo root). pf_versions_file() { # lib/ is preflight/lib, repo root is two levels up. printf '%s/VERSIONS' "$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/../.." && pwd)" } # pf_versions_get : echo the value of KEY from VERSIONS (greppable form). pf_versions_get() { vf=$(pf_versions_file) [ -f "$vf" ] || return 1 line=$(grep "^$1=" "$vf" 2>/dev/null | head -1) [ -n "$line" ] || return 1 printf '%s' "${line#*=}" }