#!/usr/bin/env bash # Sysadmin Chronicles — Uninstaller # Usage: bash uninstall.sh [--dry-run] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$SCRIPT_DIR" source "$PROJECT_ROOT/tools/lib/ui.sh" source "$PROJECT_ROOT/tools/lib/config.sh" source "$PROJECT_ROOT/tools/lib/libvirt.sh" DRY_RUN=false for arg in "$@"; do [ "$arg" = "--dry-run" ] && DRY_RUN=true done run() { if [ "$DRY_RUN" = true ]; then echo " [dry-run] $*" else "$@" fi } OWNER_USER="${SUDO_USER:-$USER}" OWNER_HOME="$(getent passwd "$OWNER_USER" | cut -d: -f6)" OWNER_HOME="${OWNER_HOME:-$HOME}" SC_LOG_DIR="$OWNER_HOME/.local/share/sysadmin-chronicles" export LIBVIRT_DEFAULT_URI="${LIBVIRT_DEFAULT_URI:-qemu:///system}" # Load config for SC_IMAGES_DIR config_read || true sc_header "SYSADMIN CHRONICLES — UNINSTALL" [ "$DRY_RUN" = true ] && echo " [dry-run mode — nothing will be changed]" && echo "" # --------------------------------------------------------------------------- # Menu # --------------------------------------------------------------------------- cat << 'MENU' What would you like to remove? 1) Everything — full uninstall (recommended) 2) Game world only — remove VMs and snapshots, keep save data and game files 3) Save data only — reset all saves to new game state 4) Custom — choose what to remove q) Cancel MENU printf " > " >/dev/tty read -r choice /dev/null | awk '{print $1}' || echo 0)" total=$(( total + sz )) done < <(virsh domblklist "$dom" --details 2>/dev/null | awk '/disk/ && $4 != "-" {print $4}' || true) done < <(virsh list --all --name 2>/dev/null | grep "^sc-" || true) [ "$total" -gt 0 ] \ && numfmt --to=iec-i --suffix=B "$total" 2>/dev/null || echo "unknown" } _saves_size() { local d="$SC_LOG_DIR/saves" [ -d "$d" ] && du -sh "$d" 2>/dev/null | awk '{print $1}' || echo "<1 KB" } _images_size() { local d="${SC_IMAGES_DIR:-}" [ -n "$d" ] && [ -d "$d" ] && du -sh "$d" 2>/dev/null | awk '{print $1}' || echo "unknown" } # --------------------------------------------------------------------------- # "Everything" confirmation # --------------------------------------------------------------------------- if [ "$choice" = "1" ]; then local_vm_sz="$(_vm_total_size)" local_img_sz="$(_images_size)" cat << EOF This will remove: Game virtual machines (3 VMs + all snapshots) ~${local_vm_sz} Game network and storage configuration <1 MB Game access keys (~/.ssh/sc_host_key) <1 KB Desktop launcher (if it exists) <1 KB System packages (libvirt, QEMU, etc.) are NOT removed. ↑ See $SC_INSTALL_LOG if you want to remove them manually. Keep VM image files on disk? Keeping them saves the ~30-minute rebuild if you reinstall later. [Y/n — default: keep] EOF printf " Keep images? [Y/n] > " >/dev/tty read -r _keep_images " >/dev/tty read -r _confirm /dev/null | grep -q "running"; then virsh destroy "$dom" >/dev/null 2>&1 || true fi while IFS= read -r snap; do [ -z "$snap" ] && continue virsh snapshot-delete "$dom" "$snap" >/dev/null 2>&1 || true done < <(virsh snapshot-list "$dom" --name 2>/dev/null || true) virsh undefine "$dom" --remove-all-storage >/dev/null 2>&1 \ || virsh undefine "$dom" >/dev/null 2>&1 || true else echo " [dry-run] would destroy and undefine $dom" fi sc_ok "$dom removed" done < <(virsh list --all --name 2>/dev/null | grep "^sc-" || true) fi if [ "$remove_images" = true ]; then sc_section "Removing VM image files" local_images="${SC_IMAGES_DIR:-}" if [ -n "$local_images" ] && [ -d "$local_images" ]; then sc_info "Removing $local_images" run rm -rf "$local_images" sc_ok "Image directory removed" else sc_info "(no image directory found — skipping)" fi fi if [ "$remove_network" = true ]; then sc_section "Removing game network and storage config" while IFS= read -r net; do [ -z "$net" ] && continue sc_info "Removing network $net" if [ "$DRY_RUN" = false ]; then virsh net-destroy "$net" >/dev/null 2>&1 || true virsh net-undefine "$net" >/dev/null 2>&1 || true else echo " [dry-run] would destroy/undefine network $net" fi sc_ok "Network $net removed" done < <(virsh net-list --all --name 2>/dev/null | grep "^sc-" || true) if virsh pool-list --all 2>/dev/null | grep -q "sc-images"; then sc_info "Removing storage pool sc-images" if [ "$DRY_RUN" = false ]; then virsh pool-destroy sc-images >/dev/null 2>&1 || true virsh pool-undefine sc-images >/dev/null 2>&1 || true else echo " [dry-run] would destroy/undefine pool sc-images" fi sc_ok "Storage pool sc-images removed" fi fi if [ "$remove_keys" = true ]; then sc_section "Removing game SSH keys" KEY="$OWNER_HOME/.ssh/sc_host_key" if [ -f "$KEY" ]; then run rm -f "$KEY" "${KEY}.pub" sc_ok "SSH keys removed" else sc_info "(no sc_host_key found — skipping)" fi fi if [ "$remove_saves" = true ]; then sc_section "Resetting save data" SAVES_DIR="$SC_LOG_DIR/saves" if [ -d "$SAVES_DIR" ]; then run rm -rf "$SAVES_DIR" sc_ok "Save data removed" else sc_info "(no save data found — skipping)" fi fi if [ "$remove_launcher" = true ]; then sc_section "Removing desktop launcher" DESKTOP_FILE="$OWNER_HOME/.local/share/applications/sysadmin-chronicles.desktop" if [ -f "$DESKTOP_FILE" ]; then run rm -f "$DESKTOP_FILE" sc_ok "Desktop launcher removed" else sc_info "(no desktop launcher found — skipping)" fi fi if [ "$remove_config" = true ]; then sc_section "Removing install config" run rm -f "$SC_CONFIG_FILE" sc_ok "Config file removed" fi # --------------------------------------------------------------------------- echo "" echo " ──────────────────────────────────────────" echo " Uninstall complete." echo "" echo " Game files (this directory) were not removed." if [ -f "$SC_INSTALL_LOG" ]; then echo " Install log kept at: $SC_INSTALL_LOG" fi echo " ──────────────────────────────────────────" echo ""