Package sections: always-on + advanced menu #3
@@ -395,7 +395,179 @@ fi
|
||||
#------------------------------------------
|
||||
# 6 Done
|
||||
#------------------------------------------
|
||||
step "7 Summary"
|
||||
|
||||
#------------------------------------------
|
||||
# 6 Always-installed packages
|
||||
#------------------------------------------
|
||||
# Add a category here and it is installed on every run, no questions asked.
|
||||
# Keep each category one line so diffs stay readable.
|
||||
ALWAYS_PACKAGES=(
|
||||
# Terminals
|
||||
"ghostty ghostty-bash-completion"
|
||||
)
|
||||
|
||||
step "6 Always-installed packages"
|
||||
rule
|
||||
|
||||
for category in "${ALWAYS_PACKAGES[@]}"; do
|
||||
# shellcheck disable=SC2086
|
||||
install_packages $category
|
||||
done
|
||||
ok "Always-packages installed."
|
||||
pause_if_debug
|
||||
|
||||
|
||||
#------------------------------------------
|
||||
# 7 Advanced: optional tool selection (menu-driven)
|
||||
#------------------------------------------
|
||||
# Add categories/apps by editing these parallel arrays:
|
||||
# ADV_CATEGORIES : display order
|
||||
# ADV_<NAME> : "pkg1 pkg2 ..." for each category (dots/minus -> underscore)
|
||||
ADV_CATEGORIES=(
|
||||
"Virtualisation"
|
||||
"Browsers"
|
||||
)
|
||||
# shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES
|
||||
ADV_Virtualisation=(
|
||||
"qemu-kvm:QEMU/KVM (full virt stack):qemu-kvm libvirt virt-install virt-manager virt-viewer edk2-ovmf swtpm guestfs-tools libguestfs-tools"
|
||||
"virtualbox:VirtualBox (Oracle):VirtualBox kernel-devel kernel-headers dkms akmod-VirtualBox"
|
||||
)
|
||||
# shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES
|
||||
ADV_Browsers=(
|
||||
"firefox:Firefox:firefox"
|
||||
"chromium:Chromium:chromium"
|
||||
"google-chrome:Google Chrome (adds repo):google-chrome-stable"
|
||||
"brave:Brave (adds repo):brave-browser"
|
||||
)
|
||||
|
||||
run_advanced_menu() {
|
||||
local done_any=false
|
||||
while true; do
|
||||
printf "\n"
|
||||
color_gray "Optional tools - select a category to pick from:"
|
||||
printf "\n"
|
||||
local i=1 cat
|
||||
for cat in "${ADV_CATEGORIES[@]}"; do
|
||||
echo " $i) $cat"
|
||||
i=$((i+1))
|
||||
done
|
||||
echo " x) Done with optional tools"
|
||||
local choice
|
||||
if ! read -t 90 -rp "Category [1-${#ADV_CATEGORIES[@]}/x] (default: x): " choice; then
|
||||
printf "\n"; choice="x"
|
||||
fi
|
||||
[[ "${choice,,}" == "x" || -z "$choice" ]] && break
|
||||
|
||||
if [[ ! "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > ${#ADV_CATEGORIES[@]} )); then
|
||||
err "Invalid choice: $choice"
|
||||
continue
|
||||
fi
|
||||
cat="${ADV_CATEGORIES[$((choice-1))]}"
|
||||
|
||||
# apps for this category — nameref, because ${!var} on an array name
|
||||
# would only give element 0 (that bug showed in testing: Browsers
|
||||
# listed exactly one entry)
|
||||
local var="ADV_${cat//[ .-]/_}"
|
||||
local -n entries_ref="$var"
|
||||
local -a entries
|
||||
# shellcheck disable=SC2206
|
||||
entries=("${entries_ref[@]}")
|
||||
|
||||
printf "\n"
|
||||
color_cyan "$cat:"
|
||||
local j=1 entry
|
||||
local -a ids=() labels=()
|
||||
for entry in "${entries[@]}"; do
|
||||
ids+=("${entry%%:*}") # entry id
|
||||
local rest="${entry#*:}"
|
||||
labels+=("${rest%%:*}") # display label
|
||||
echo " $j) ${labels[-1]}"
|
||||
j=$((j+1))
|
||||
done
|
||||
echo " x) Back"
|
||||
|
||||
local sel
|
||||
if ! read -t 90 -rp "Install which? (comma-separate for multiple, default: back): " sel; then
|
||||
printf "\n"; continue
|
||||
fi
|
||||
[[ "${sel,,}" == "x" || -z "$sel" ]] && continue
|
||||
|
||||
# Resolve picks to package lists. Entry format: id:Label:packages...
|
||||
local -a to_install=()
|
||||
local pick n rest
|
||||
IFS=',' read -ra picks <<< "$sel"
|
||||
for pick in "${picks[@]}"; do
|
||||
pick="${pick// /}"
|
||||
[[ "$pick" =~ ^[0-9]+$ ]] || { err "Ignoring invalid pick: $pick"; continue; }
|
||||
n=${#entries[@]}
|
||||
if (( pick < 1 || pick > n )); then err "Ignoring out-of-range pick: $pick"; continue; fi
|
||||
entry="${entries[$((pick-1))]}"
|
||||
rest="${entry#*:}"; rest="${rest#*:}" # drop id and label -> packages
|
||||
# word-split into SEPARATE packages: quoting $rest whole makes dnf
|
||||
# look for one package named "qemu-kvm libvirt ..." (seen on the VM)
|
||||
# shellcheck disable=SC2206
|
||||
to_install+=(${rest})
|
||||
done
|
||||
|
||||
if (( ${#to_install[@]} > 0 )); then
|
||||
step "Installing from $cat: ${to_install[*]}"
|
||||
# install_category_pkgs wires any needed third-party repo first.
|
||||
# Failure must NOT kill the script: warn in red and drop back to
|
||||
# the menu (set -e is bypassed for this one call).
|
||||
if install_category_pkgs "$cat" "${to_install[@]}"; then
|
||||
done_any=true
|
||||
else
|
||||
color_red " Installation failed: ${to_install[*]}"
|
||||
color_red " (dnf reported no match / transaction failure — see output above)"
|
||||
warn " Returning to the menu. The system is unchanged."
|
||||
pause_if_debug
|
||||
fi
|
||||
unset to_install; local -a to_install=() # fresh slate for next pick
|
||||
fi
|
||||
done
|
||||
$done_any && ok "Optional tools installed."
|
||||
}
|
||||
|
||||
# Per-category pre-repo wiring. Add third-party repos here when you add an
|
||||
# app that needs one; packages alone stay generic.
|
||||
install_category_pkgs() {
|
||||
local cat="$1"; shift
|
||||
case "$cat" in
|
||||
Browsers)
|
||||
local needs_chrome=false needs_brave=false item
|
||||
for item in "$@"; do
|
||||
[[ "$item" == *google-chrome* ]] && needs_chrome=true
|
||||
[[ "$item" == *brave* ]] && needs_brave=true
|
||||
done
|
||||
if $needs_chrome && ! pkg_installed google-chrome-stable; then
|
||||
info "Adding Google Chrome repo..."
|
||||
sudo dnf install -y fedora-workstation-repositories 2>/dev/null || true
|
||||
sudo dnf config-manager setopt google-chrome.enabled=1 2>/dev/null || \
|
||||
sudo dnf install -y "https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm"
|
||||
fi
|
||||
if $needs_brave && ! pkg_installed brave-browser; then
|
||||
info "Adding Brave repo..."
|
||||
sudo dnf install -y dnf-plugins-core
|
||||
sudo dnf config-manager add --from-repofile=https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo || \
|
||||
true
|
||||
sudo rpm --import https://brave-browser-rpm-release.s3.brave.com/brave-core.asc 2>/dev/null || true
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
# Resilient install: report failure but return non-zero instead of
|
||||
# aborting under set -e; the caller turns it into a red warning.
|
||||
install_packages "$@" || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
# Interactive only: an unattended --yes run must not hang on this menu.
|
||||
# Skip silently there; use --de/--twm/--dotfiles for everything unattended.
|
||||
if [[ "$ASSUME_YES" != "true" ]]; then
|
||||
run_advanced_menu
|
||||
fi
|
||||
pause_if_debug
|
||||
|
||||
step "8 Summary"
|
||||
rule
|
||||
ok "DE: $DE"
|
||||
ok "TWM: $TWM"
|
||||
|
||||
Reference in New Issue
Block a user