#!/bin/sh
set -eu

root=/run/mouse-root
active_file=/etc/mouse-boot-environment
btrfs=/sbin/btrfs

fail() {
    printf '%s\n' "mouse-bootenv: $*" >&2
    exit 1
}

read_environment() {
    [ -f "$active_file" ] || fail "missing $active_file"
    environment=$(cat "$active_file")
    case "$environment" in
        default|alternate) ;;
        *) fail "invalid boot environment: $environment" ;;
    esac
}

other_environment() {
    case "$1" in
        default) printf '%s\n' alternate ;;
        alternate) printf '%s\n' default ;;
        *) fail "invalid boot environment: $1" ;;
    esac
}

require_storage() {
    [ -d "$root/ROOT/default" ] || fail "MOUSE btrfs root is not mounted"
    [ -d "$root/ROOT/alternate" ] || fail "alternate boot environment is missing"
}

set_default() {
    target_path=$1
    target_id=$("$btrfs" inspect-internal rootid "$target_path")
    case "$target_id" in
        ''|*[!0-9]*) fail "could not resolve the subvolume ID for $target_path" ;;
    esac
    "$btrfs" subvolume set-default "$target_id" "$root"
}

activate() {
    target=$1
    case "$target" in
        default|alternate) ;;
        *) fail "invalid boot environment: $target" ;;
    esac
    [ "$(cat "$root/ROOT/$target/etc/mouse-boot-environment")" = "$target" ] ||
        fail "$target has an invalid environment marker"
    set_default "$root/ROOT/$target"
    sync
    printf '%s\n' "$target will boot next"
}

read_environment
require_storage

case "${1:-status}" in
    status)
        printf '%s\n' "running: $environment"
        "$btrfs" subvolume get-default "$root"
        ;;
    prepare)
        inactive=$(other_environment "$environment")
        set_default "$root/ROOT/$environment"
        "$btrfs" subvolume delete --commit-after "$root/ROOT/$inactive"
        "$btrfs" subvolume snapshot \
            "$root/ROOT/$environment" \
            "$root/ROOT/$inactive"
        printf '%s\n' "$inactive" \
            >"$root/ROOT/$inactive/etc/mouse-boot-environment"
        sync
        printf '%s\n' "$inactive is ready for an update"
        ;;
    activate)
        [ "$#" -eq 2 ] || fail "usage: mouse-bootenv activate default|alternate"
        activate "$2"
        ;;
    rollback)
        [ "$#" -eq 1 ] || fail "usage: mouse-bootenv rollback"
        activate "$(other_environment "$environment")"
        ;;
    *)
        fail "usage: mouse-bootenv [status|prepare|activate NAME|rollback]"
        ;;
esac
