#!/bin/sh
#
# Copyright 2024 Jacob Dybvald Ludvigsen (Papiris)
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This script abstracts the process of choosing a btrfs snapshot
# of the root subvolume to boot into on the next boot

# How many snapshots to list
num_list=5

echo "Snapshots you can choose to boot from:"
echo ""

# list of all snapshots
entries="$(ls -1 /.snapshots/ | sort -gr | tr '\n' ' ')"

# List recent snapshots which aren't of type 'pre'
k=0
for entry in $entries; do

  if [ $k -le $num_list ]; then
    info_file="/.snapshots/$entry/info.xml"

    if [ -f "$info_file" ]; then
      snap_type=$(awk -F'[<>]' '/<type>/{print $3}' "$info_file")
      snap_date=$(awk -F'[<>]' '/<date>/{print $3}' "$info_file")

      if [ "$snap_type" != "post" ]; then
        k=$((k+1))
    echo "$entry is a $snap_type snapshot"
        echo "made on $snap_date"
        echo ""
      fi
    fi
  fi
  if [ $k -eq $num_list ]; then break
  fi
done

echo "Cancel (ctrl+c) keeps the current root"
echo ""

# Prompt for user input
read -p "Enter snapshot number: " input
echo ""

# Validate user input
if [ "$(expr "$input" : '[0-9][0-9]*$')" -eq 0 ]; then
  echo "Invalid input."
  echo "Please enter number."
  exit 1
fi

# Check if input is among listed snapshots
if ! echo "$entries" | grep -q "$input"; then
  echo "Invalid input."
  echo "Please pick among listed snapshots."
  exit 1
fi

# Current root subvol
cur_root="$(btrfs subvolume show / | \
grep 'Name:[[:space:]]*[^[:space:]]*' | awk '{print $2}')"

# Make a temporary dir to mount in, to ensure separation from regular files
mkdir -p /mnt/snapshots

# Create a rw snapshot under the toplevel subvol
# and set it as the default for the filesystem
mount -o subvolid=5 /dev/mapper/root /mnt/snapshots

# If there isn't a rw subvol of the chosen snapshot, make it
if [ ! -d /mnt/snapshots/@"$input" ]; then
  btrfs subvol snapshot "/.snapshots/$input/snapshot" "/mnt/snapshots/@$input" > /dev/null
fi

# Set chosen snapshot as default root subvol to mount on boot
btrfs subvol set-default "/mnt/snapshots/@$input"

# Print which snapshot is scheduled to boot
echo "Snapshot chosen for next boot: $input"
echo ""

# Delete old rw snapshots
echo "Cleaning up old read-write snapshots"
for btrfs_subvol in /mnt/snapshots/@*; do

  # get rid of @ prefix
  subvol_name="${btrfs_subvol##*@}"

  # Check if the subvol name consists of digits
  if [ "$subvol_name" -eq "$subvol_name" ] 2>/dev/null; then

    # Check if the numbered subvol is currently booted or chosen for next boot
    # If not, delete it
    if [ "$subvol_name" != "$input" ] && [ "@$subvol_name" != "$cur_root" ]; then
      btrfs subvol delete "$btrfs_subvol"  > /dev/null
    fi
  fi
done

# unmount parent subvolume
umount /mnt/snapshots

# Check if unmounting was successful
if [ $? -eq 0 ]; then
  rmdir /mnt/snapshots
else
  echo "Error unmounting /mnt/snapshots."
fi
