#!/bin/sh
# arctic - the declarative system commands, in one place
#
#   arctic rebuild              reconcile the system to /etc/arctic/system.conf
#   arctic shell <pkgs>...      ephemeral package environment (arctic-shell)
#   arctic gc                   prune the package cache, orphans, unused shells
#   arctic generations          list snapshots (what a rollback can go back to)
#   arctic rollback <name>      go back to one
#
# rebuild and shell are also their own commands (arctic-rebuild, arctic-shell)
# if that is easier to type or script against.
# shellcheck shell=sh disable=SC2039

set -u
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

for d in /usr/lib/alpm "$(dirname "$0")/../alpm" ./alpm; do
	[ -f "$d/libalpm.sh" ] && { . "$d/libalpm.sh"; break; }
done

if [ -t 1 ]; then
	R=$(printf '\033[0m'); TEAL=$(printf '\033[38;5;44m'); GREY=$(printf '\033[38;5;245m')
else
	R= ; TEAL= ; GREY=
fi
note() { printf '%s::%s %s\n' "$TEAL" "$R" "$*"; }

need_root() { [ "$(id -u)" = "0" ] || { echo "Must be run as root." >&2; exit 1; }; }

cmd_gc() {
	need_root
	note "removing orphaned packages"
	ALPM_YES=1 alpm autoremove

	note "pruning the package cache (keeping the installed version of each)"
	pruned=0
	for f in /var/cache/alpm/pkg/*.alpmz; do
		[ -f "$f" ] || continue
		b=$(basename "$f")
		p=${b%-*-*.alpmz}
		iv=$(installed_version "$p" 2>/dev/null)
		[ -n "$iv" ] && case "$b" in "$p-$iv"*) continue ;; esac
		rm -f "$f"; pruned=$((pruned+1))
	done
	[ "$pruned" -gt 0 ] && note "removed $pruned old cached package(s)" || note "cache already minimal"

	if command -v arctic-snapshot >/dev/null 2>&1; then
		note "pruning old snapshots"
		arctic-snapshot prune >/dev/null 2>&1 || :
	fi

	note "removing unused arctic-shell environments"
	n=0
	for d in /var/cache/arctic-shell/*/; do
		[ -d "$d" ] || continue
		[ -f "${d}.arctic-shell-keep" ] && continue
		last=$(cat "${d}.arctic-shell-last-used" 2>/dev/null || echo 0)
		now=$(date '+%s')
		# Older than 7 days and not marked --keep.
		[ $(( now - last )) -gt 604800 ] || continue
		rm -rf "$d"; n=$((n+1))
	done
	[ "$n" -gt 0 ] && note "removed $n unused shell environment(s)"

	note "done"
}

cmd_generations() {
	command -v arctic-snapshot >/dev/null 2>&1 || { echo "arctic-snapshot is not installed" >&2; exit 1; }
	arctic-snapshot list
}

cmd_rollback() {
	command -v arctic-snapshot >/dev/null 2>&1 || { echo "arctic-snapshot is not installed" >&2; exit 1; }
	[ $# -gt 0 ] || { echo "usage: arctic rollback <name>" >&2; exit 1; }
	arctic-snapshot rollback "$1"
}

case "${1:-}" in
rebuild) shift; exec arctic-rebuild "$@" ;;
shell)   shift; exec arctic-shell "$@" ;;
gc)      cmd_gc ;;
generations|gens) cmd_generations ;;
rollback) shift; cmd_rollback "$@" ;;
-h|--help|help|"") sed -n '2,10p' "$0" | sed 's/^# \?//' ;;
*) echo "arctic: unknown command '$1' (see 'arctic help')" >&2; exit 1 ;;
esac
