0265afa054
Import the runnable game code, content, docs, scripts, and repo guidance while leaving local agent state, dependency installs, build output, and backup copies out of the published tree.
293 lines
9.4 KiB
Bash
Executable File
293 lines
9.4 KiB
Bash
Executable File
#!/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/tty
|
|
echo ""
|
|
|
|
case "$choice" in
|
|
q|Q) echo " Cancelled."; exit 0 ;;
|
|
1|2|3|4) ;;
|
|
*) echo " Invalid choice."; exit 1 ;;
|
|
esac
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Measure sizes for "Everything" overview
|
|
# ---------------------------------------------------------------------------
|
|
|
|
_vm_total_size() {
|
|
local total=0
|
|
local dom disk sz
|
|
while IFS= read -r dom; do
|
|
[ -z "$dom" ] && continue
|
|
while IFS= read -r disk; do
|
|
[ -z "$disk" ] && continue
|
|
[ -f "$disk" ] || continue
|
|
sz="$(du -sb "$disk" 2>/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
|
|
_keep_images="${_keep_images:-Y}"
|
|
echo ""
|
|
|
|
echo " Type REMOVE to confirm, or anything else to cancel:"
|
|
printf " > " >/dev/tty
|
|
read -r _confirm </dev/tty
|
|
echo ""
|
|
if [ "$_confirm" != "REMOVE" ]; then
|
|
echo " Cancelled."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# "Custom" submenu
|
|
# ---------------------------------------------------------------------------
|
|
|
|
remove_vms=false
|
|
remove_images=false
|
|
remove_network=false
|
|
remove_keys=false
|
|
remove_saves=false
|
|
remove_launcher=false
|
|
remove_config=false
|
|
|
|
case "$choice" in
|
|
1)
|
|
remove_vms=true
|
|
remove_network=true
|
|
remove_keys=true
|
|
remove_launcher=true
|
|
remove_config=true
|
|
case "${_keep_images:-Y}" in
|
|
n|N) remove_images=true ;;
|
|
esac
|
|
;;
|
|
2)
|
|
remove_vms=true
|
|
remove_images=true
|
|
remove_network=true
|
|
remove_keys=true
|
|
;;
|
|
3)
|
|
remove_saves=true
|
|
;;
|
|
4)
|
|
echo " Choose components to remove (y/n for each):"
|
|
echo ""
|
|
sc_confirm " Remove game virtual machines and snapshots?" "N" && remove_vms=true || true
|
|
sc_confirm " Remove VM image files on disk (large)?" "N" && remove_images=true || true
|
|
sc_confirm " Remove game network (sc-internal)?" "N" && remove_network=true || true
|
|
sc_confirm " Remove game SSH keys (~/.ssh/sc_host_key)?" "N" && remove_keys=true || true
|
|
sc_confirm " Reset save data?" "N" && remove_saves=true || true
|
|
sc_confirm " Remove desktop launcher?" "N" && remove_launcher=true || true
|
|
sc_confirm " Remove install config file?" "N" && remove_config=true || true
|
|
echo ""
|
|
;;
|
|
esac
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Execute removals
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if [ "$remove_vms" = true ]; then
|
|
sc_section "Removing game virtual machines"
|
|
while IFS= read -r dom; do
|
|
[ -z "$dom" ] && continue
|
|
sc_info "Removing $dom..."
|
|
if [ "$DRY_RUN" = false ]; then
|
|
if virsh domstate "$dom" 2>/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 ""
|