Files
StrixScripts/lib/common.sh
T

114 lines
3.6 KiB
Bash

#!/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
}
# common::show_block_devices prints available block devices and highlights
# the selected device when output is going to a terminal.
common::show_block_devices() {
local selected_device="$1"
local color=0
if [[ -t 1 && -z "${NO_COLOR:-}" ]]; then
color=1
fi
common::log "Available block devices and mount points (selected device highlighted):"
lsblk --list --paths --output PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS \
| awk -v selected="$selected_device" -v color="$color" '
NR > 1 && $1 == selected && color {
printf "\033[31m%s\033[0m\n", $0
next
}
{ print }
'
}