From 6631521d9f45b73f9b4df76db9148d82af8d57b9 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Mon, 23 Feb 2026 11:54:25 -0600 Subject: refactor: rename custom/ to installer/ for clarity The custom/ directory name was an archiso implementation detail. Renamed to installer/ which clearly communicates that this directory contains the installer scripts and utilities that ship on the ISO. Updated all references in build.sh, Makefile, test-install.sh, and README. --- installer/lib/common.sh | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 installer/lib/common.sh (limited to 'installer/lib/common.sh') diff --git a/installer/lib/common.sh b/installer/lib/common.sh new file mode 100644 index 0000000..0f02e37 --- /dev/null +++ b/installer/lib/common.sh @@ -0,0 +1,173 @@ +#!/usr/bin/env bash +# common.sh - Shared functions for archangel installer +# Source this file: source "$(dirname "$0")/lib/common.sh" + +############################# +# Output Functions +############################# + +# Colors (optional, gracefully degrade if not supported) +if [[ -t 1 ]]; then + RED='\033[0;31m' + GREEN='\033[0;32m' + YELLOW='\033[0;33m' + BLUE='\033[0;34m' + BOLD='\033[1m' + NC='\033[0m' # No Color +else + RED='' + GREEN='' + YELLOW='' + BLUE='' + BOLD='' + NC='' +fi + +info() { echo -e "${GREEN}[INFO]${NC} $1"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } +step() { echo ""; echo -e "${BOLD}==> $1${NC}"; } +prompt() { echo -e "${BLUE}$1${NC}"; } + +# Log to file if LOG_FILE is set +log() { + local msg + msg="[$(date +'%Y-%m-%d %H:%M:%S')] $1" + if [[ -n "$LOG_FILE" ]]; then + echo "$msg" >> "$LOG_FILE" + fi +} + +############################# +# Validation Functions +############################# + +require_root() { + if [[ $EUID -ne 0 ]]; then + error "This script must be run as root" + fi +} + +command_exists() { + command -v "$1" &>/dev/null +} + +require_command() { + command_exists "$1" || error "Required command not found: $1" +} + +############################# +# FZF Prompts +############################# + +# Check if fzf is available +has_fzf() { + command_exists fzf +} + +# Generic fzf selection +# Usage: result=$(fzf_select "prompt" "option1" "option2" ...) +fzf_select() { + local prompt="$1" + shift + local options=("$@") + + if has_fzf; then + printf '%s\n' "${options[@]}" | fzf --prompt="$prompt " --height=15 --reverse + else + # Fallback to simple select + PS3="$prompt " + select opt in "${options[@]}"; do + if [[ -n "$opt" ]]; then + echo "$opt" + break + fi + done + fi +} + +# Multi-select with fzf +# Usage: readarray -t results < <(fzf_multi "prompt" "opt1" "opt2" ...) +fzf_multi() { + local prompt="$1" + shift + local options=("$@") + + if has_fzf; then + printf '%s\n' "${options[@]}" | fzf --prompt="$prompt " --height=20 --reverse --multi + else + # Fallback: just return all options (user must edit) + printf '%s\n' "${options[@]}" + fi +} + +############################# +# Filesystem Selection +############################# + +# Select filesystem type (ZFS or Btrfs) +# Sets global FILESYSTEM variable +select_filesystem() { + step "Select Filesystem" + + local options=( + "ZFS - Built-in encryption, best data integrity (recommended)" + "Btrfs - Copy-on-write, LUKS encryption, GRUB snapshot boot" + ) + + local selected + selected=$(fzf_select "Filesystem:" "${options[@]}") + + case "$selected" in + ZFS*) + FILESYSTEM="zfs" + info "Selected: ZFS" + ;; + Btrfs*) + FILESYSTEM="btrfs" + info "Selected: Btrfs" + ;; + *) + error "No filesystem selected" + ;; + esac +} + +############################# +# Disk Utilities +############################# + +# Get disk size in human-readable format +get_disk_size() { + local disk="$1" + lsblk -dno SIZE "$disk" 2>/dev/null | tr -d ' ' +} + +# Get disk model +get_disk_model() { + local disk="$1" + lsblk -dno MODEL "$disk" 2>/dev/null | tr -d ' ' | head -c 20 +} + +# Check if disk is in use (mounted or has holders) +disk_in_use() { + local disk="$1" + [[ -n "$(lsblk -no MOUNTPOINT "$disk" 2>/dev/null | grep -v '^$')" ]] && return 0 + [[ -n "$(ls /sys/block/"$(basename "$disk")"/holders/ 2>/dev/null)" ]] && return 0 + return 1 +} + +# List available disks (not in use) +list_available_disks() { + local disks=() + for disk in /dev/nvme[0-9]n[0-9] /dev/sd[a-z] /dev/vd[a-z]; do + [[ -b "$disk" ]] || continue + disk_in_use "$disk" && continue + local size + size=$(get_disk_size "$disk") + local model + model=$(get_disk_model "$disk") + disks+=("$disk ($size, $model)") + done + printf '%s\n' "${disks[@]}" +} -- cgit v1.2.3