#!/usr/bin/env bash # common.sh - shared helpers. Sourced by bootstrap.sh, not run directly. # Exported once so we never rely on the `$SUDO VAR=val cmd` pattern, which # breaks when $SUDO is empty (running as root): the var assignment gets parsed # before $SUDO expands, so `DEBIAN_FRONTEND=...` ends up treated as a command. export DEBIAN_FRONTEND=noninteractive # ---- colors / logging ------------------------------------------------------- if [[ -t 1 ]]; then C_RESET=$'\e[0m'; C_DIM=$'\e[2m'; C_RED=$'\e[31m'; C_GRN=$'\e[32m' C_YLW=$'\e[33m'; C_BLU=$'\e[34m'; C_BOLD=$'\e[1m' else C_RESET=""; C_DIM=""; C_RED=""; C_GRN=""; C_YLW=""; C_BLU=""; C_BOLD="" fi log() { printf '%s[*]%s %s\n' "$C_BLU" "$C_RESET" "$*"; } ok() { printf '%s[+]%s %s\n' "$C_GRN" "$C_RESET" "$*"; } warn() { printf '%s[!]%s %s\n' "$C_YLW" "$C_RESET" "$*" >&2; } err() { printf '%s[x]%s %s\n' "$C_RED" "$C_RESET" "$*" >&2; } die() { err "$*"; exit 1; } step() { printf '\n%s== %s ==%s\n' "$C_BOLD" "$*" "$C_RESET"; } # ---- privilege -------------------------------------------------------------- # Sets $SUDO to "sudo" if not root, "" if root. Fails if neither works. detect_sudo() { if [[ $EUID -eq 0 ]]; then SUDO="" elif command -v sudo >/dev/null 2>&1; then SUDO="sudo" # prime the credential cache early so prompts don't appear mid-run $SUDO -v || die "sudo authentication failed" else die "not root and sudo not available" fi } # ---- distro detection ------------------------------------------------------- # Sets DISTRO_ID (debian/ubuntu/...), DISTRO_LIKE, DISTRO_CODENAME, PKG_MGR. detect_distro() { [[ -r /etc/os-release ]] || die "/etc/os-release missing - unsupported system" # shellcheck disable=SC1091 . /etc/os-release DISTRO_ID="${ID:-unknown}" # shellcheck disable=SC2034 # used in bootstrap.sh main() DISTRO_LIKE="${ID_LIKE:-}" DISTRO_CODENAME="${VERSION_CODENAME:-}" if command -v apt-get >/dev/null 2>&1; then PKG_MGR="apt" elif command -v dnf >/dev/null 2>&1; then PKG_MGR="dnf" elif command -v pacman >/dev/null 2>&1; then PKG_MGR="pacman" else die "no supported package manager found (apt/dnf/pacman)" fi ok "detected ${DISTRO_ID} ${DISTRO_CODENAME:-} (pkg: ${PKG_MGR})" } # ---- package helpers (apt-focused, dnf/pacman best-effort) ------------------ APT_UPDATED=0 pkg_refresh() { case "$PKG_MGR" in apt) if [[ $APT_UPDATED -eq 0 ]]; then log "apt-get update" # a single broken third-party repo shouldn't abort the whole bootstrap; # downstream installs will fail loudly if a needed pkg is truly missing. $SUDO apt-get update -qq || warn "apt-get update reported errors (broken repo?) - continuing" APT_UPDATED=1 fi ;; dnf) $SUDO dnf -q makecache ;; pacman) $SUDO pacman -Sy --noconfirm >/dev/null ;; esac } # is a binary already on PATH? have() { command -v "$1" >/dev/null 2>&1; } # install one or more packages, skipping any already-present *packages* pkg_install() { pkg_refresh case "$PKG_MGR" in apt) $SUDO apt-get install -y -qq \ --no-install-recommends "$@" ;; dnf) $SUDO dnf install -y "$@" ;; pacman) $SUDO pacman -S --needed --noconfirm "$@" ;; esac } # install a package only if a given command is missing. usage: ensure_cmd ensure_cmd() { local cmd="$1"; shift if have "$cmd"; then printf '%s - %s already present%s\n' "$C_DIM" "$cmd" "$C_RESET" return 0 fi log "installing ${cmd} (pkg: $*)" pkg_install "$@" } # write file from stdin only if content differs (idempotent). usage: write_if_changed write_if_changed() { local target="$1" tmp tmp="$(mktemp)" cat > "$tmp" if [[ -f "$target" ]] && cmp -s "$tmp" "$target"; then rm -f "$tmp" return 1 # unchanged fi $SUDO install -D -m "${2:-0644}" "$tmp" "$target" rm -f "$tmp" return 0 # changed }