#!/usr/bin/env bash # # setup.sh — bootstrap entrypoint. # Detects distro/arch, lists modular steps, asks y/N per step, runs them. # # Flags: # --yes run all steps without prompting # --only NAME run only the step matching NAME # --skip NAME run all steps except NAME # --create-user force creating a sudo user (otherwise Arch auto-creates, Debian asks) # --username NAME override the sudo user name (default: mk) # -h|--help usage set -euo pipefail # Default config target = whoever is running this. The create-user step # (05-create-user) may override these to point at a freshly-created sudoer. export TARGET_USER="$USER" export TARGET_HOME="$HOME" BOOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck disable=SC1091 source "$BOOT_DIR/lib/detect.sh" source "$BOOT_DIR/lib/log.sh" source "$BOOT_DIR/lib/prompt.sh" # helper: resolve the target user's real home even when we're root operating # on a created user (whose home isn't $HOME). target_home() { getent passwd "${TARGET_USER:-$USER}" | cut -d: -f6; } ALL=0; ONLY=""; SKIP=""; CREATE_USER=0; USERNAME_ARG="" while (( $# )); do case "$1" in --yes|-y) ALL=1; shift ;; --only) ONLY="${2:-}"; shift 2 ;; --skip) SKIP="${2:-}"; shift 2 ;; --create-user) CREATE_USER=1; shift ;; --username) USERNAME_ARG="${2:-}"; shift 2 ;; -h|--help) grep -E '^# --' "$0" | sed 's/^# //' exit 0 ;; *) echo "unknown arg: $1" >&2; shift ;; esac done export CREATE_USER USERNAME_ARG # ---------------------------------------------------------------- collect steps NAMES=(); DESCS=(); RUNS=() for f in "$BOOT_DIR"/modules/*.sh; do step_name=""; step_desc=""; step_run="" # shellcheck disable=SC1090 source "$f" [[ -z "$step_name" ]] && continue NAMES+=("$step_name") DESCS+=("$step_desc") RUNS+=("$step_run") done # ----------------------------------------------------------------- print plan echo printf 'Detected: \033[1mdistro\033[0m=%s \033[1march\033[0m=%s \033[1muser\033[0m=%s\n' "$DISTRO" "$ARCH" "$USER" echo echo "Steps:" for i in "${!NAMES[@]}"; do printf ' [%02d] %-12s — %s\n' "$((i+1))" "${NAMES[$i]}" "${DESCS[$i]}" done echo # ----------------------------------------------------------------- decide run run_step() { # name local n="$1" i for i in "${!NAMES[@]}"; do if [[ "${NAMES[$i]}" == "$n" ]]; then echo; echo "── ${NAMES[$i]} ──────────────────────────────────────────────" # shellcheck disable=SCSC2086 "${RUNS[$i]}" return $? fi done err "no step named '$n'"; return 1 } if [[ -n "$ONLY" ]]; then run_step "$ONLY" elif (( ALL )); then for n in "${NAMES[@]}"; do [[ -n "$SKIP" && "$n" == "$SKIP" ]] && continue run_step "$n" done else for i in "${!NAMES[@]}"; do local_run=1 [[ -n "$SKIP" && "${NAMES[$i]}" == "$SKIP" ]] && local_run=0 if (( local_run )) && yn "Run step [$(printf %02d $((i+1)))] ${NAMES[$i]}?" y; then run_step "${NAMES[$i]}" || warn "step ${NAMES[$i]} had an error (continuing)" else echo " skip ${NAMES[$i]}" fi done fi echo ok "bootstrap done." echo " re-run any step: bash $BOOT_DIR/setup.sh --only " echo " run everything: bash $BOOT_DIR/setup.sh --yes"