diff --git a/update_arch.sh b/update_arch.sh index 41cf427..b41fa9f 100755 --- a/update_arch.sh +++ b/update_arch.sh @@ -2,6 +2,95 @@ set -e sudo -v +ACTION="${1:-update}" + +restore_latest_state() { + printf -- '\033[33m Gathering restore options\n\033[37m' + + BOOT_BACKUP_DIR="${HOME}/boot-backups" + + TIMESLICE_INFO="" + SNAPSHOT_CREATED="" + TIMESLICE_LABEL="" + if pacman -Qs timeshift >/dev/null; then + TIMESLICE_INFO=$(sudo timeshift --list | awk ' + /^Snapshot/ {snap=$2} + /^Created on/ {created=$4 " " $5} + END { if (snap != "") { print snap "|" created } } + ') + if [ -n "$TIMESLICE_INFO" ]; then + TIMESLICE_LABEL=${TIMESLICE_INFO%%|*} + SNAPSHOT_CREATED=${TIMESLICE_INFO##*|} + if [ "$SNAPSHOT_CREATED" = "$TIMESLICE_LABEL" ]; then + SNAPSHOT_CREATED="" + fi + fi + fi + + LATEST_BOOT="" + if [ -d "$BOOT_BACKUP_DIR" ]; then + LATEST_BOOT=$( (ls -1t "$BOOT_BACKUP_DIR"/boot-*.tar.gz 2>/dev/null || true) | head -n1 ) + fi + + if [ -n "$TIMESLICE_LABEL" ]; then + if [ -n "$SNAPSHOT_CREATED" ]; then + printf -- '\033[33m Latest Timeshift snapshot: %s (created %s)\n\033[37m' "$TIMESLICE_LABEL" "$SNAPSHOT_CREATED" + else + printf -- '\033[33m Latest Timeshift snapshot: %s\n\033[37m' "$TIMESLICE_LABEL" + fi + else + printf -- '\033[33m No Timeshift snapshots available\n\033[37m' + fi + + if [ -n "$LATEST_BOOT" ]; then + BOOT_BASENAME=$(basename "$LATEST_BOOT") + BOOT_STAMP=${BOOT_BASENAME#boot-} + BOOT_STAMP=${BOOT_STAMP%.tar.gz} + printf -- '\033[33m Latest /boot archive: %s (saved %s)\n\033[37m' "$BOOT_BASENAME" "$BOOT_STAMP" + else + printf -- '\033[33m No /boot backup archives available\n\033[37m' + fi + + if [ -z "$TIMESLICE_LABEL" ] && [ -z "$LATEST_BOOT" ]; then + printf -- '\033[31m Nothing to restore\n\033[37m' + exit 1 + fi + + RESTORED_ANY=0 + + if [ -n "$TIMESLICE_LABEL" ]; then + read -r -p "Restore this Timeshift snapshot? [y/N]: " CONFIRM + if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then + printf -- '\033[33m Starting Timeshift restore (follow on-screen prompts)\n\033[37m' + sudo timeshift --restore --snapshot "$TIMESLICE_LABEL" --yes + RESTORED_ANY=1 + else + printf -- '\033[33m Timeshift restore skipped\n\033[37m' + fi + fi + + if [ -n "$LATEST_BOOT" ]; then + read -r -p "Restore /boot from this archive? [y/N]: " BOOT_CONFIRM + if [[ "$BOOT_CONFIRM" =~ ^[Yy]$ ]]; then + printf -- '\033[33m Restoring /boot from %s\n\033[37m' "$LATEST_BOOT" + sudo tar -C /boot -xpf "$LATEST_BOOT" + printf -- '\033[32m /boot restore complete\n\033[37m' + RESTORED_ANY=1 + else + printf -- '\033[33m /boot restore skipped\n\033[37m' + fi + fi + + if [ "$RESTORED_ANY" -eq 0 ]; then + printf -- '\033[33m No restore actions performed\n\033[37m' + fi +} + +if [ "$ACTION" == "restore" ]; then + restore_latest_state + exit 0 +fi + if ! pacman -Qs inetutils >/dev/null; then sudo pacman -Syy --noconfirm inetutils fi @@ -91,6 +180,30 @@ EOT fi fi +# Back up /boot ahead of kernel upgrades so it aligns with Timeshift snapshots +sudo pacman -Sy --noconfirm >/dev/null +KERNEL_PACKAGES=(linux linux-lts linux-zen linux-hardened linux-rt linux-rt-lts linux-rt-bfq linux-xanmod linux-xanmod-lts linux-xanmod-tt) +PENDING_KERNELS=() +for kernel_pkg in "${KERNEL_PACKAGES[@]}"; do + if pacman -Qi "$kernel_pkg" >/dev/null 2>&1; then + if pacman -Qu "$kernel_pkg" >/dev/null 2>&1; then + PENDING_KERNELS+=("$kernel_pkg") + fi + fi +done + +if [ "${#PENDING_KERNELS[@]}" -gt 0 ]; then + printf -- '\\033[33m Kernel update detected; backing up /boot\\n\\033[37m' + BOOT_BACKUP_DIR="${HOME}/boot-backups" + mkdir -p "$BOOT_BACKUP_DIR" + BACKUP_FILE="${BOOT_BACKUP_DIR}/boot-$(date +%Y%m%d-%H%M%S).tar.gz" + sudo tar -C /boot -acf "$BACKUP_FILE" . + sudo chown "$USER":"$USER" "$BACKUP_FILE" + printf -- '\\033[32m Saved /boot backup to %s\\n\\033[37m' "$BACKUP_FILE" +else + printf -- '\\033[33m No kernel update detected; skipping /boot backup\\n\\033[37m' +fi + # Update all pacman packages printf -- '\033[33m Updating pacman packages\n\033[37m' sudo pacman -Suyy --noconfirm diff --git a/update_wrapper.sh b/update_wrapper.sh index 9a21c64..5482046 100755 --- a/update_wrapper.sh +++ b/update_wrapper.sh @@ -17,8 +17,8 @@ if [ -d ~/linuxbox ]; then cd ~/linuxbox && git pull && if [ "$OS" == "Ubuntu" ]; then - ./update_ubuntu.sh + ./update_ubuntu.sh "$@" elif [ "$OS" == "Arch Linux" ]; then - ./update_arch.sh + ./update_arch.sh "$@" fi fi