#!/usr/bin/env bash # # common.sh — shared helper functions for all StrixScripts scripts. # # Every script in this repo MUST source this file. It provides: # - --help handling driven by a script-defined SCRIPT_HELP heredoc # - consistent error/log output # - a command-existence guard # # Usage from a script: # SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # source "${SCRIPT_DIR}/../lib/common.sh" # adjust ../ depth to match nesting # # Do NOT duplicate this logic inside individual scripts — if a script needs # behavior this file doesn't provide, extend this file instead, so every # script stays consistent. set -euo pipefail # common::show_help_if_requested scans argv for -h/--help and, if present, # prints the calling script's $SCRIPT_HELP and exits 0. # # Call this IMMEDIATELY after defining SCRIPT_HELP and BEFORE any other # argument parsing — --help must win regardless of what else is on the # command line (including invalid flags). common::show_help_if_requested() { local arg for arg in "$@"; do if [[ "$arg" == "-h" || "$arg" == "--help" ]]; then if [[ -z "${SCRIPT_HELP:-}" ]]; then echo "Error: SCRIPT_HELP is not defined for this script." >&2 exit 1 fi echo "$SCRIPT_HELP" exit 0 fi done } # common::die prints an error to stderr and exits with the given code # (default 1). Use this for every fatal error instead of a raw `exit 1`, # so error output is consistent across all scripts. common::die() { local message="$1" local code="${2:-1}" echo "Error: ${message}" >&2 exit "$code" } # common::log prints a timestamped status line to stderr. stdout is left # clean for actual script output that might be piped or captured by a # caller — never write status/progress messages to stdout. common::log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2 } # common::confirm returns success only when the user answers yes. # A no answer or end-of-input cancels the caller; invalid answers are retried. common::confirm() { local prompt="$1" local answer while true; do if ! read -r -p "${prompt} [yes/no]: " answer; then common::log "No response received; cancelling." return 1 fi case "${answer,,}" in yes) return 0 ;; no) common::log "Cancelled by user." return 1 ;; *) printf "Please answer 'yes' or 'no'.\n" >&2 ;; esac done } # common::require_cmd fails fast with a clear message if a required # external command is missing from PATH, instead of letting the script # fail later with a cryptic "command not found". common::require_cmd() { local cmd="$1" if ! command -v "$cmd" &>/dev/null; then common::die "required command '${cmd}' not found on PATH" fi }