- all_packages=("$(remove_duplicates ...)") kollabierte Newlines → alle
Pakete wurden ein einzelnes Array-Element → pacman -Si matchte nichts
→ nichts installiert. Fix: readarray -t statt $()-Subshell.
- optional/install in FRESH_MODULES aufgenommen, damit die Software-Auswahl
auch auf --fresh erscheint.
330 lines
8.5 KiB
Bash
Executable File
330 lines
8.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Omeron - Modular System Setup Framework
|
||
# Usage: ./install.sh [--fresh] [--modules m1,m2] [--skip-packages] [--with-sddm] [--help]
|
||
set -euo pipefail
|
||
|
||
OMERON_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||
export OMERON_ROOT
|
||
export OMERON_PROJECT_DIR="$OMERON_ROOT"
|
||
|
||
source "$OMERON_ROOT/lib/log.sh"
|
||
source "$OMERON_ROOT/lib/tui.sh"
|
||
source "$OMERON_ROOT/lib/utils.sh"
|
||
source "$OMERON_ROOT/lib/config.sh"
|
||
source "$OMERON_ROOT/lib/modules.sh"
|
||
|
||
OMERON_FRESH_INSTALL="${OMERON_FRESH_INSTALL:-0}"
|
||
export OMERON_FRESH_INSTALL
|
||
|
||
DEFAULT_MODULES=(
|
||
"core/preflight"
|
||
"core/packages"
|
||
"core/dotfiles"
|
||
"core/services"
|
||
"homelab/setup"
|
||
"optional/install"
|
||
"core/sddm"
|
||
"post/apply-theme"
|
||
)
|
||
|
||
FRESH_MODULES=(
|
||
"core/packages"
|
||
"core/dotfiles"
|
||
"core/services"
|
||
"homelab/setup"
|
||
"optional/install"
|
||
"core/sddm"
|
||
"post/apply-theme"
|
||
)
|
||
|
||
RUN_MODULES=()
|
||
SKIP_MODULES=()
|
||
WITH_SDDM=0
|
||
|
||
usage() {
|
||
cat <<EOF
|
||
Omeron - Modular System Setup Framework
|
||
|
||
Usage: ./install.sh [OPTIONS]
|
||
|
||
Options:
|
||
--fresh Full system setup (Hyprland + GPU drivers + all deps)
|
||
--modules m1,m2 Run only specific modules (comma-separated)
|
||
--skip m1,m2 Skip specific modules (comma-separated)
|
||
--skip-packages Skip package installation
|
||
--with-sddm Include SDDM theme installation
|
||
--list-modules List all available modules
|
||
--help Show this help message
|
||
|
||
Examples:
|
||
./install.sh Interactive (detects fresh install automatically)
|
||
./install.sh --fresh Force full setup on a running system
|
||
./install.sh --modules core/dotfiles,post/apply-theme
|
||
./install.sh --skip core/packages
|
||
EOF
|
||
exit 0
|
||
}
|
||
|
||
list_modules() {
|
||
echo "Available modules:"
|
||
for module in $(module_list); do
|
||
local rel_path="${module#$OMERON_MODULE_DIR/}"
|
||
rel_path="${rel_path%.sh}"
|
||
local description=""
|
||
if source "$module" 2>/dev/null && declare -F "module_description" >/dev/null 2>&1; then
|
||
description="$(module_description)"
|
||
fi
|
||
printf " %-30s %s\n" "$rel_path" "$description"
|
||
done
|
||
exit 0
|
||
}
|
||
|
||
parse_args() {
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--fresh) OMERON_FRESH_INSTALL=1; shift ;;
|
||
--modules) IFS=',' read -ra RUN_MODULES <<< "$2"; shift 2 ;;
|
||
--skip) IFS=',' read -ra SKIP_MODULES <<< "$2"; shift 2 ;;
|
||
--skip-packages) SKIP_MODULES+=("core/packages"); shift ;;
|
||
--with-sddm) WITH_SDDM=1; shift ;;
|
||
--list-modules) list_modules ;;
|
||
-h|--help) usage ;;
|
||
*) echo "Unknown option: $1" >&2; usage ;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
detect_environment() {
|
||
tui_detect
|
||
|
||
if ((!OMERON_HAS_GUM)) && have pacman; then
|
||
printf '\033[1;36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n'
|
||
printf '\033[1;36m Ꮎ Ꮇ Ꭼ Ꮢ Ꮎ Ꮑ — Modular System Setup Framework\033[0m\n'
|
||
printf '\033[1;36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n'
|
||
printf '\n'
|
||
printf ' \033[1;33mgum is not installed.\033[0m Installing it enables the full TUI experience.\n'
|
||
printf '\n'
|
||
|
||
if tui_install_gum; then
|
||
printf ' \033[1;32m✓ gum installed!\033[0m\n'
|
||
else
|
||
if ((OMERON_HAS_WHIPTAIL)); then
|
||
printf ' \033[1;33musing whiptail as fallback\033[0m\n'
|
||
else
|
||
printf ' \033[1;33musing basic text mode (install gum for UI: pacman -S gum)\033[0m\n'
|
||
fi
|
||
fi
|
||
printf '\n'
|
||
fi
|
||
|
||
if ((!OMERON_FRESH_INSTALL)) && ((${#RUN_MODULES[@]} == 0)); then
|
||
log_info "Checking for fresh install..."
|
||
if is_fresh_install; then
|
||
OMERON_FRESH_INSTALL=1
|
||
export OMERON_FRESH_INSTALL
|
||
fi
|
||
fi
|
||
|
||
if ((OMERON_FRESH_INSTALL)) && ((!OMERON_HAS_GUM)) && have pacman; then
|
||
tui_install_gum 2>/dev/null || true
|
||
fi
|
||
}
|
||
|
||
collect_modules() {
|
||
if ((${#RUN_MODULES[@]})); then
|
||
for mod in "${RUN_MODULES[@]}"; do
|
||
printf '%s\n' "$OMERON_MODULE_DIR/$mod.sh"
|
||
done
|
||
return
|
||
fi
|
||
|
||
local modules=()
|
||
if ((OMERON_FRESH_INSTALL)); then
|
||
modules=("${FRESH_MODULES[@]}")
|
||
else
|
||
modules=("${DEFAULT_MODULES[@]}")
|
||
fi
|
||
|
||
for mod in "${modules[@]}"; do
|
||
local skip=0
|
||
for skipped in "${SKIP_MODULES[@]}"; do
|
||
if [[ "$mod" == "$skipped" || "$mod" == "core/$skipped" ]]; then
|
||
skip=1
|
||
break
|
||
fi
|
||
done
|
||
[[ "$mod" == "core/sddm" && "$WITH_SDDM" -eq 0 && "$OMERON_FRESH_INSTALL" -eq 0 ]] && skip=1
|
||
((skip)) && continue
|
||
local module_file="$OMERON_MODULE_DIR/$mod.sh"
|
||
[[ -f "$module_file" ]] && printf '%s\n' "$module_file"
|
||
done
|
||
}
|
||
|
||
collect_all_interactive() {
|
||
local modules=()
|
||
if ((OMERON_FRESH_INSTALL)); then
|
||
modules=("${FRESH_MODULES[@]}")
|
||
else
|
||
modules=("${DEFAULT_MODULES[@]}")
|
||
fi
|
||
|
||
local total=${#modules[@]}
|
||
local idx=1
|
||
local module_order=()
|
||
|
||
for mod in "${modules[@]}"; do
|
||
local module_file="$OMERON_MODULE_DIR/$mod.sh"
|
||
[[ -f "$module_file" ]] || continue
|
||
|
||
local description=""
|
||
if source "$module_file" 2>/dev/null && declare -F "module_description" >/dev/null 2>&1; then
|
||
description="$(module_description)"
|
||
fi
|
||
|
||
printf '\n'
|
||
log_step "$idx" "$total" "${description:-$mod}"
|
||
|
||
if declare -F "module_required" >/dev/null 2>&1; then
|
||
source "$module_file"
|
||
if module_required; then
|
||
tui_info "Required module — will run"
|
||
module_order+=("$module_file")
|
||
((idx++))
|
||
continue
|
||
fi
|
||
fi
|
||
|
||
if tui_confirm "Run this step?"; then
|
||
module_order+=("$module_file")
|
||
else
|
||
log_info "Skipped"
|
||
fi
|
||
((idx++))
|
||
done
|
||
|
||
printf '%s\n' "${module_order[@]}"
|
||
}
|
||
|
||
show_banner() {
|
||
tui_header " Ꮎ Ꮇ Ꭼ Ꮢ Ꮎ Ꮑ "
|
||
tui_info "Modular System Setup Framework"
|
||
tui_info "Arch / Hyprland / CachyOS"
|
||
printf '\n'
|
||
|
||
if ((OMERON_FRESH_INSTALL)); then
|
||
tui_warn "FRESH INSTALL MODE"
|
||
tui_info "Will install Hyprland, GPU drivers, and all dependencies."
|
||
printf '\n'
|
||
fi
|
||
}
|
||
|
||
show_summary() {
|
||
local modules=("$@")
|
||
|
||
tui_separator
|
||
tui_bold "Installation Summary"
|
||
tui_info "$(tui_bold "${#modules[@]}") module(s) to run"
|
||
|
||
local gpu
|
||
gpu="$(detect_gpu)"
|
||
tui_info "Detected GPU: $(tui_bold "$gpu")"
|
||
|
||
if ((${#modules[@]})); then
|
||
printf '\n'
|
||
tui_bold "Steps:"
|
||
local i=1
|
||
for mod in "${modules[@]}"; do
|
||
printf ' \033[1;36m%d.\033[0m %s\n' "$i" "$(basename "$mod" .sh)"
|
||
((i++))
|
||
done
|
||
fi
|
||
|
||
printf '\n'
|
||
if ! tui_confirm "Proceed with installation?"; then
|
||
tui_bold "Installation cancelled."
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
main() {
|
||
OMERON_LOG_FILE="${OMERON_LOG_FILE:-$HOME/.local/share/omeron/install-$(date +%Y%m%d-%H%M%S).log}"
|
||
export OMERON_LOG_FILE
|
||
|
||
parse_args "$@"
|
||
|
||
mkdir -p "$(dirname "$OMERON_LOG_FILE")"
|
||
log_info "Omeron installation started"
|
||
log_info "Log file: $OMERON_LOG_FILE"
|
||
log_info "Project: $OMERON_ROOT"
|
||
|
||
detect_environment
|
||
|
||
show_banner
|
||
|
||
local modules_to_run=()
|
||
if ((${#RUN_MODULES[@]})); then
|
||
mapfile -t modules_to_run < <(collect_modules)
|
||
else
|
||
mapfile -t modules_to_run < <(collect_all_interactive)
|
||
fi
|
||
|
||
if ((${#modules_to_run[@]} == 0)); then
|
||
tui_warn "No modules selected. Nothing to do."
|
||
exit 0
|
||
fi
|
||
|
||
show_summary "${modules_to_run[@]}"
|
||
|
||
local total=${#modules_to_run[@]}
|
||
local idx=1
|
||
|
||
for module_path in "${modules_to_run[@]}"; do
|
||
local description=""
|
||
if source "$module_path" 2>/dev/null && declare -F "module_description" >/dev/null 2>&1; then
|
||
description="$(module_description)"
|
||
fi
|
||
printf '\n'
|
||
log_step "$idx" "$total" "${description:-$(basename "$module_path" .sh)}"
|
||
|
||
module_run "$module_path" || {
|
||
local rc=$?
|
||
if declare -F "module_required" >/dev/null 2>&1; then
|
||
source "$module_path"
|
||
if module_required 2>/dev/null; then
|
||
tui_error "Required module failed. Aborting."
|
||
exit $rc
|
||
fi
|
||
fi
|
||
tui_warn "Module completed with warnings"
|
||
}
|
||
((idx++))
|
||
done
|
||
|
||
printf '\n'
|
||
tui_header " Ꮎ Ꮇ Ꭼ Ꮢ Ꮎ Ꮑ "
|
||
tui_success "Installation Complete!"
|
||
printf '\n'
|
||
tui_info "Log: ${OMERON_LOG_FILE}"
|
||
printf '\n'
|
||
|
||
if ((OMERON_FRESH_INSTALL)); then
|
||
tui_bold "Your system is ready for Hyprland!"
|
||
tui_list \
|
||
"Start Hyprland: Hyprland" \
|
||
"Or enable SDDM: sudo systemctl enable --now sddm" \
|
||
"Reload config: hyprctl reload"
|
||
else
|
||
tui_bold "What next?"
|
||
tui_list \
|
||
"Reload config: hyprctl reload" \
|
||
"Re-run installer: ./install.sh"
|
||
fi
|
||
printf '\n'
|
||
|
||
if have notify-send; then
|
||
notify-send "Omeron" "Installation complete!" >/dev/null 2>&1 || true
|
||
fi
|
||
}
|
||
|
||
main "$@"
|