Files
rocknix-config-backup/restore-rocknix.sh
2026-07-14 11:51:45 -03:00

394 lines
13 KiB
Bash
Executable File

#!/usr/bin/env bash
# restore-rocknix.sh - Restore script for ROCKNIX configurations
#
# Usage:
# ./restore-rocknix.sh [OPTIONS]
#
# Options:
# --host HOST Target console host
# --user USER SSH user (default: root)
# --backup FILE .tar.gz backup file to restore
# --all Restore all components without prompting
# --help Show help
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib-common.sh"
# Default values
BACKUP_FILE=""
RESTORE_ALL=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--host)
ROCKNIX_HOST="$2"
shift 2
;;
--user)
ROCKNIX_USER="$2"
shift 2
;;
--password)
ROCKNIX_PASSWORD="$2"
shift 2
;;
--backup)
BACKUP_FILE="$2"
shift 2
;;
--all)
RESTORE_ALL=true
shift
;;
--help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --host HOST Target console host"
echo " --user USER SSH user (default: $ROCKNIX_USER)"
echo " --password PASS SSH password"
echo " --backup FILE .tar.gz backup file to restore"
echo " --all Restore all components"
echo " --help Show this help"
exit 0
;;
*)
log ERROR "Unknown option: $1"
exit 1
;;
esac
done
# Check dependencies
check_deps || exit 1
# Ask for password if not configured
ask_password || exit 1
# If no backup specified, list available ones
if [[ -z "$BACKUP_FILE" ]]; then
log INFO "Searching for backups in ${BACKUP_DIR}..."
if [[ ! -d "$BACKUP_DIR" ]]; then
log ERROR "Backup directory not found: $BACKUP_DIR"
log INFO "Run first: ./backup-rocknix.sh"
exit 1
fi
BACKUPS=($(find "$BACKUP_DIR" -name "rocknix-config-*.tar.gz" -type f | sort -r))
if [[ ${#BACKUPS[@]} -eq 0 ]]; then
log ERROR "No backups found in ${BACKUP_DIR}"
log INFO "Run first: ./backup-rocknix.sh"
exit 1
fi
echo ""
echo -e "${CYAN}Available backups:${NC}"
echo ""
for i in "${!BACKUPS[@]}"; do
local backup="${BACKUPS[$i]}"
local name=$(basename "$backup")
local size=$(du -h "$backup" | cut -f1)
local date=$(stat -c %y "$backup" 2>/dev/null | cut -d'.' -f1)
echo -e " ${GREEN}$((i+1))${NC}) ${name}"
echo -e " Size: ${size} | Date: ${date}"
done
echo ""
read -p "Select backup (1-${#BACKUPS[@]}): " choice
if [[ "$choice" -lt 1 || "$choice" -gt ${#BACKUPS[@]} ]]; then
log ERROR "Invalid selection"
exit 1
fi
BACKUP_FILE="${BACKUPS[$((choice-1))]}"
fi
# Verify backup file exists
if [[ ! -f "$BACKUP_FILE" ]]; then
log ERROR "Backup file not found: $BACKUP_FILE"
exit 1
fi
# Show backup contents
show_backup_contents "$BACKUP_FILE"
# Verify connection with target console
echo ""
ssh_check "$ROCKNIX_HOST" "$ROCKNIX_USER" || exit 1
# Detect target device
DEVICE=$(detect_device "$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null || echo "unknown")
log INFO "Target device: ${DEVICE}"
# Check backup type
BACKUP_NAME=$(basename "$BACKUP_FILE")
if [[ "$BACKUP_NAME" == *"generic"* ]]; then
log WARN "This is a GENERIC backup (without device-specific settings)"
log WARN "Make sure the target device is compatible"
echo ""
read -p "Continue? (y/N): " confirm
if [[ "$confirm" != "s" && "$confirm" != "S" ]]; then
log INFO "Restore cancelled"
exit 0
fi
fi
# Create temporary directory
TMP_DIR=$(create_tmp_dir "rocknix-restore")
trap 'cleanup_tmp "$TMP_DIR"' EXIT
# Extract backup
log INFO "Extracting backup..."
tar -xzf "$BACKUP_FILE" -C "$TMP_DIR"
# Select components to restore
if [[ "$RESTORE_ALL" == "false" ]]; then
echo ""
echo -e "${CYAN}Which components do you want to restore?${NC}"
echo ""
COMPONENTS=(
"retroarch-core-options:RetroArch core-options"
"retroarch-opt:RetroArch .opt (core options)"
"retroarch-rmp:RetroArch .rmp (remaps)"
"retroarch-config:RetroArch overrides (config/)"
"shaders:Shaders"
"ppsspp:PPSSPP"
"drastic:DraStic"
"other-emu:Other emulators"
)
SELECTION=()
for i in "${!COMPONENTS[@]}"; do
IFS=':' read -r key label <<< "${COMPONENTS[$i]}"
# Determine if there are files of this type
case "$key" in
retroarch-core-options)
[[ -f "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" ]] && available=true || available=false
;;
retroarch-opt)
find "${TMP_DIR}/.config/retroarch/" -maxdepth 1 -name "*.opt" -type f 2>/dev/null | grep -q . && available=true || available=false
;;
retroarch-rmp)
find "${TMP_DIR}/.config/retroarch/" -maxdepth 1 -name "*.rmp" -type f 2>/dev/null | grep -q . && available=true || available=false
;;
retroarch-config)
[[ -d "${TMP_DIR}/.config/retroarch/config/" ]] && available=true || available=false
;;
shaders)
[[ -d "${TMP_DIR}/shaders/" ]] && available=true || available=false
;;
ppsspp)
[[ -f "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/ppsspp.ini" ]] && available=true || available=false
;;
drastic)
[[ -d "${TMP_DIR}/.config/drastic/config/" ]] && available=true || available=false
;;
other-emu)
[[ -d "${TMP_DIR}/.config/game/" ]] || \
[[ -d "${TMP_DIR}/.config/flycast/" ]] || \
[[ -f "${TMP_DIR}/.config/duckstation/settings.ini" ]] || \
[[ -f "${TMP_DIR}/.config/yabasanshiro/.config" ]] && available=true || available=false
;;
esac
if [[ "$available" == "true" ]]; then
SELECTION+=("$key" "$label" "on")
else
SELECTION+=("$key" "$label" "off")
fi
done
CHOICES=$(dialog --checklist "Components to restore:" \
20 60 12 \
"${SELECTION[@]}" \
3>&1 1>&2 2>&3)
# If user cancels
if [[ $? -ne 0 ]]; then
log INFO "Restore cancelled"
exit 0
fi
else
# Restore all
CHOICES="retroarch-core-options retroarch-opt retroarch-rmp retroarch-config shaders ppsspp drastic other-emu"
fi
# Confirm restore
echo ""
echo -e "${YELLOW}Restore the following components on ${ROCKNIX_HOST}?${NC}"
for choice in $CHOICES; do
case "$choice" in
retroarch-core-options) echo " - RetroArch core-options" ;;
retroarch-opt) echo " - RetroArch .opt" ;;
retroarch-rmp) echo " - RetroArch .rmp" ;;
retroarch-config) echo " - RetroArch overrides" ;;
shaders) echo " - Shaders" ;;
ppsspp) echo " - PPSSPP" ;;
drastic) echo " - DraStic" ;;
other-emu) echo " - Other emulators" ;;
esac
done
echo ""
read -p "Confirm restore? (y/N): " confirm
if [[ "$confirm" != "s" && "$confirm" != "S" ]]; then
log INFO "Restore cancelled"
exit 0
fi
# Create safety backup on target console
log INFO "Creating safety backup on console..."
SAFETY_DIR="${TMP_DIR}/safety"
mkdir -p "$SAFETY_DIR"
# Download current files before overwriting
for choice in $CHOICES; do
case "$choice" in
retroarch-core-options)
download_file ".config/retroarch/retroarch-core-options.cfg" \
"${SAFETY_DIR}/retroarch-core-options.cfg" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null || true
;;
# Add others if needed
esac
done
log INFO "Safety backup created"
# Restore files
log INFO "Restoring files..."
RESTORED=0
FAILED=0
for choice in $CHOICES; do
log INFO "Restoring: ${choice}..."
case "$choice" in
retroarch-core-options)
if [[ -f "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" ]]; then
if upload_file "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" \
".config/retroarch/retroarch-core-options.cfg" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
RESTORED=$((RESTORED + 1))
else
FAILED=$((FAILED + 1))
log WARN "Error restoring retroarch-core-options.cfg"
fi
fi
;;
retroarch-opt)
for opt_file in "${TMP_DIR}/.config/retroarch/"*.opt; do
if [[ -f "$opt_file" ]]; then
filename=$(basename "$opt_file")
if upload_file "$opt_file" \
".config/retroarch/${filename}" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
RESTORED=$((RESTORED + 1))
else
FAILED=$((FAILED + 1))
fi
fi
done
;;
retroarch-rmp)
for rmp_file in "${TMP_DIR}/.config/retroarch/"*.rmp; do
if [[ -f "$rmp_file" ]]; then
filename=$(basename "$rmp_file")
if upload_file "$rmp_file" \
".config/retroarch/${filename}" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
RESTORED=$((RESTORED + 1))
else
FAILED=$((FAILED + 1))
fi
fi
done
;;
retroarch-config)
if [[ -d "${TMP_DIR}/.config/retroarch/config/" ]]; then
if upload_dir "${TMP_DIR}/.config/retroarch/config/" \
".config/retroarch/config/" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
RESTORED=$((RESTORED + 1))
else
FAILED=$((FAILED + 1))
log WARN "Error restoring config/"
fi
fi
;;
shaders)
if [[ -d "${TMP_DIR}/shaders/" ]]; then
if upload_dir "${TMP_DIR}/shaders/" \
"shaders/" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
RESTORED=$((RESTORED + 1))
else
FAILED=$((FAILED + 1))
log WARN "Error restoring shaders/"
fi
fi
;;
ppsspp)
if [[ -f "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/ppsspp.ini" ]]; then
upload_file "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/ppsspp.ini" \
".config/ppsspp/PSP/SYSTEM/ppsspp.ini" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null && RESTORED=$((RESTORED + 1)) || FAILED=$((FAILED + 1))
fi
if [[ -f "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/controls.ini" ]]; then
upload_file "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/controls.ini" \
".config/ppsspp/PSP/SYSTEM/controls.ini" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null && RESTORED=$((RESTORED + 1)) || FAILED=$((FAILED + 1))
fi
;;
drastic)
if [[ -d "${TMP_DIR}/.config/drastic/config/" ]]; then
if upload_dir "${TMP_DIR}/.config/drastic/config/" \
".config/drastic/config/" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
RESTORED=$((RESTORED + 1))
else
FAILED=$((FAILED + 1))
log WARN "Error restoring drastic/config/"
fi
fi
;;
other-emu)
for emu_path in ".config/game/configs" ".config/flycast" ".config/duckstation" ".config/yabasanshiro"; do
if [[ -e "${TMP_DIR}/${emu_path}" ]]; then
upload_dir "${TMP_DIR}/${emu_path}/" "${emu_path}/" \
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null && RESTORED=$((RESTORED + 1)) || FAILED=$((FAILED + 1))
fi
done
;;
esac
done
# Clean up temporary safety backup
cleanup_tmp "${SAFETY_DIR}" 2>/dev/null || true
# Summary
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Restore completed${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e " Device: ${CYAN}${DEVICE}${NC}"
echo -e " Restored: ${CYAN}${RESTORED}${NC}"
if [[ $FAILED -gt 0 ]]; then
echo -e " Failed: ${RED}${FAILED}${NC}"
fi
echo ""
echo -e " ${YELLOW}Note: Restart the console to apply changes${NC}"
echo ""