#!/bin/bash
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:

# debupdate - Upgrades packages on a Debian-based system
# Written in 2016 by T. Joseph Carter <tjcarter@spiritsubstance.com>
# Based on raspbian-update by Ivan Drucker <ivan@ivanx.com>
#
# To the extent possible under law, the author(s) have dedicated all copyright
# and related and neighboring rights to this software to the public domain
# worldwide. This software is distributed without any warranty.
#
# You should have received a copy of the CC0 Public Domain Dedication along
# with this software. If not, you may find a copy here:
#  <http://creativecommons.org/publicdomain/zero/1.0/>

PROGNAME="$0"
PROGRAM="debupdate"
VERSION="0.9.0"

useAptGet=
useAutoClean=
autoYes=

aptitudeUpgradeArgs="--allow-new-upgrades --allow-new-installs safe-upgrade"
aptGetUpgradeArgs="--with-new-pkgs --auto-remove upgrade"

ShowLicense() {
	printf "%s version %s
Upgrades packages on a Debian-based system

Written in 2016 by T. Joseph Carter <tjcarter@spiritsubstance.com>
Based on raspbian-update by Ivan Drucker <ivan@ivanx.com>

To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.

You should have received a copy of the CC0 Public Domain Dedication along
with this software. If not, you may find a copy here:
 <http://creativecommons.org/publicdomain/zero/1.0/>
" $PROGRAM $VERSION
	exit 0
}

Run() {
	local cmd=( )
	for i in "${@}"; do
		# Replace argument's spaces with ''; if different, quote the string
		if [ "$i" != "${i/ /}" ]; then
			cmd=( ${cmd[@]} "'${i}'" )
		else
			cmd=( ${cmd[@]} $i )
		fi
	done
	printf ">>> %s\n" "${cmd[@]}"
	${@}
}


ShowHelp() {
	# FIXME
	printf "\nHelp\n"

	exit ${1:-0}
}


# Process command line arguments
while getopts ":hvyacy" opt; do
	case "$opt" in
		h)	ShowHelp ;;
		v)	ShowLicense ;;
		y)	autoYes=1 ;;
		a)	useAptGet=1 ;;
		c)	useAutoClean=1 ;;
		\?)
			printf "Invalid argument: -%s\n" "$OPTARG"
			badArgument=1
			;;
	esac
done
if [[ "$badArgument" ]]; then
	ShowHelp 1
fi

# Check for root access
if [[ "$UID" != "0" ]]; then
	if hash sudo 2>/dev/null; then
		Run sudo $0 "$@"
		exit $?
	else
		printf "%s requires \"root\" administrator access to upgrade your system.\n" "$PROGRAM"
		exit 1
	fi
fi

# Determine if aptitude is installed (unless we're not using it)
if [[ -z "$useAptGet" ]]; then
	if ! hash aptitude 2>/dev/null; then
		useAptGet=1
	fi
fi

# Clean apt package cache
printf "\nCleaning apt package cache...\n"
if [[ $useAptGet ]]; then
	Run apt-get ${useAutoClean:+auto}clean
else
	Run aptitude ${useAutoClean:+auto}clean
fi

# Update package lists
printf "\nUpdating list of available packages...\n"
if [[ $useAptGet ]]; then
	Run apt-get update
else
	Run aptitude update
fi
if [[ $? -ne 0 ]];
	printf "Package list update failed.\n"
	exit 1
fi

# Check to see if we even need to upgrade
if [[ $useAptGet ]]; then
	apt-get --trivial-only $aptGetUpgradeArgs &>/dev/null
else
	aptitude $aptitudeUpgradeArgs <<<"n" &>/dev/null
fi
if [[ $? -eq 0 ]]; then
	printf "Your packages are already up to date.\n"
	exit 0
fi

# Do the upgrade itself
if [[ $useAptGet ]]; then
	Run apt-get ${autoYes:+-y} $aptGetUpgradeArgs
else
	Run aptitude ${autoYes:+-y} $aptitudeUpgradeArgs
fi
if [[ $? -ne 0 ]]; then
	# FIXME
	printf "System upgrade failed.  Something about a log should be here.\n"
	exit 1
fi

# apt-get needs explicit autoremove (aptitude doesn't)
if [[ $useAptGet ]]; then
	Run apt-get autoremove
	if [[ $? -ne 0 ]]; then
		printf "Failure attempting to auto-remove unneeded packages.\n"
		exit 1
	fi
fi

# Clean apt package cache (again)
printf "Cleaning apt package cache...\n"
if [[ $useAptGet ]]; then
	Run apt-get autoclean
else
	Run aptitude autoclean
fi

printf "\nIt is generally recommended that you reboot your system after upgrades.  You
can do this with the \"reboot\" command, which must be run as root.\n\n"
