#!/bin/sh

# (C) 2017-2026 by Christian Hesse <mail@eworm.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

set -e

function help() {
	cat <<-EOM
	usage: ${0} [OPTIONS]

	 -a  abort pending system-update
	 -c  clean before download
	 -f  force if other system-update is pending
	 -h  this help
	 -p  reboot, install and poweroff immediately
	 -r  reboot and install immediately
	 -t  start timer for nightly reboot
	 -y  update sync databases
	EOM
}

CLEAN=0
POWEROFF=0
REBOOT=0
TIMER=0

while getopts 'acfhprty' opt; do
	case ${opt} in
		h)
			help
			exit 0
			;;
		a|c|f|p|r|t|y)
			;;
		*)
			exit 1
			;;
	esac
done

if systemd-detect-virt --chroot 2>/dev/null; then
	echo 'Running in chroot, skipping.' >&2
	exit 0
fi

if [ ! -d /run/systemd/system ]; then
	echo 'Current root is not booted, skipping.' >&2
	exit 0
fi

if [ "${UID}" -ne 0 ]; then
	if command -v pkexec >/dev/null; then
		echo 'Missing privileges, trying to elevate.' >&2
		exec pkexec "${0}" "${@}"
	fi

	echo "You need elevated privileges. Please run as user 'root'!" >&2
	exit 1
fi

OPTIND=1
while getopts 'acfhprty' opt; do
	case ${opt} in
		a)
			rm --force \
				/system-update \
				/run/systemd/system/systemd-poweroff.service \
				/run/systemd/system/systemd-reboot.service
			systemctl daemon-reload
			exit 0
			;;
		c)
			if pacman-conf 'CleanMethod' | grep -q 'KeepCurrent'; then
				CLEAN=1
			else
				echo 'The clean method is not set to keep current. Not cleaning.' >&2
			fi
			;;
		f)
			rm -f /system-update
			;;
		p)
			POWEROFF=1
			REBOOT=1
			;;
		r)
			REBOOT=1
			;;
		t)
			TIMER=1
			;;
		y)
			pacman --sync --refresh
			;;
	esac
done

# make sure no other update is pending
if [ -e '/system-update' -a "$(readlink '/system-update')" != '/var/cache/pacman/pkg' ]; then
	echo 'Another update is pending.' >&2
	exit 1
fi

# exclude /etc/pacman.d/offline.conf
function finish { rm -f /run/pacman.conf; }
trap finish EXIT
sed \
	-e '/^Include *= *\/etc\/pacman\.d\/offline\.conf$/s|^|#|' \
	-e '/^#Include *= *\/etc\/pacman\.d\/offline-include\.conf$/s|^#||' \
	< /etc/pacman.conf > /run/pacman.conf

# remove the symlink for now, will be recreated it later
rm -f /system-update

# check for available updates
if [ "$(pacman --config /run/pacman.conf --sync --sysupgrade --print | wc -l)" -eq 0 ]; then
	echo 'No updates available.'
	exit 0
fi

# clean cache
if [ ${CLEAN} -eq 1 ]; then
	pacman --sync --noconfirm --clean
fi

# download packages
pacman --config /run/pacman.conf --sync --noconfirm --sysupgrade --downloadonly

# delete lost directories in cache
# https://gitlab.archlinux.org/pacman/pacman/-/issues/297
find /var/cache/pacman/pkg/ -mindepth 1 -type d -name 'download-??????' -empty -delete

# enable system update
ln -sf /var/cache/pacman/pkg /system-update
if [ ${POWEROFF} -eq 1 ]; then
	touch /run/pacman-offline-poweroff
fi

# force a soft-reboot on (manual) reboot ...
ln -sf ../../../usr/lib/systemd/system/systemd-soft-reboot.service \
	/run/systemd/system/systemd-reboot.service

# ... and also on poweroff, but prepare poweroff
cp /usr/lib/systemd/system/systemd-soft-reboot.service \
	/run/systemd/system/systemd-poweroff.service
cat >> /run/systemd/system/systemd-poweroff.service <<-EOF

	[Service]
	ExecStart=/usr/bin/touch /run/pacman-offline-poweroff
	EOF

# reload for service changes
systemctl daemon-reload

# (soft-)reboot if requested
if [ ${REBOOT} -eq 1 ]; then
	echo 'Rebooting for update.'
	exec systemctl reboot
fi

echo 'Updates will be installed on next reboot.'

# start timer if requested
if [ ${TIMER} -eq 1 ]; then
	systemctl start pacman-offline-reboot.timer
fi

# show the timer (if active)
systemctl --quiet --no-pager list-timers \
	pacman-offline-prepare.timer \
	pacman-offline-reboot.timer
