Restructure
This commit is contained in:
117
lib/common.sh
Normal file
117
lib/common.sh
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/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 <cmd> <pkg...>
|
||||
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 <path>
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user