#!/bin/sh

set -e

# mark types we want to list/restore:
marktypes='auto manual' # auto hold install manual purge remove

# newline
nl='
'

case "$0" in
	apt-mark-list|*/apt-mark-list)
		# output list of mark status and packages
		List= # initialize List
		for mark in $marktypes
		do
			list="$(apt-mark show"$mark")"
			# if our list for mark type $mar isn't empty,
			# prepend mark type on each line
			[ -z "$list" ] ||
			list="$(
				printf '%s\n' "$list" |
				sed -e "s/^/$mark /"
			)"
			# if our list for mark type isn't empty, append it to List
			[ -z "$list" ] ||
			List="${List:+$List$nl}$list"
		done
		# output our List if it's not empty
		[ -z "$List" ] ||
		printf '%s\n' "$List" |
		sort -u
		exit
	;;
	apt-mark-restore|*/apt-mark-restore)
		# restore mark status to packages
		n=
		[ "$#" -le 0 ] || {
			case "$1" in
				-|--)
					:
				;;
				-n)
					n=n
					shift
				;;
				-?*)
					1>&2 printf '%s\n' 'usage: apt-mark-restore [-n] [file ...]'
					exit 1
				;;
			esac
		}
		in="$(cat -- "$@")" # reference listing (to set to, as applicable)
		[ -n "$in" ] || exit 0
		List="$(apt-mark-list)"
		[ -n "$List" ] || exit 0
		# was in reference listing but not same in current:
		was="$(
			{
				printf '%s\n' "$List" "$List"
				printf '%s\n' "$in" |
				sort -u
			} |
			sort |
			uniq -u
		)"
		[ -n "$was" ] || exit 0
		# packages from the respective lists:
		waspkgs="$(
			printf '%s\n' "$was" |
			awk '{print $2;}'
		)"
		Listpkgs="$(
			printf '%s\n' "$List" |
			awk '{print $2;}'
		)"
		# thin waspkgs to only packages in both reference and current:
		waspkgs="$(
			{
				printf '%s\n' "$waspkgs" | sort -u
				printf '%s\n' "$Listpkgs" | sort -u
			} | sort | uniq -d
		)"
		[ -n "$waspkgs" ] || exit 0
		# now get the $waspkgs with their mark status from $was
		was="$(
			printf '%s\n' "$was" |
			sed -e 's/$/ /' |
			grep -F -e "$(
				printf '%s\n' "$waspkgs" |
				sed -ne 's/^[^ ]\{1,\} \([^ ]\{1,\}\)$/ \1 /p'
			)" |
			sed -e 's/ $//'
		)"
		[ -n "$was" ] || exit 0
		# Assemble lists of types needing adjustment
		for mark in $marktypes
		do
			eval "$mark"=\""$(
				printf '%s\n' "$was" |
				sed -ne "s/^$mark //p" |
				{
					tr '\012' ' '
					echo
				} | sed -e 's/ $//'
			)"\"
			eval [ -z \"$"$mark"\" ] || {
				case "$n" in
					'')
						eval apt-mark "$mark" $"$mark"
					;;
					n)
						eval printf \''%s\n'\' \""apt-mark $mark "\$"$mark"\"
					;;
				esac
			}
		done
	;;
	*)
		1>&2 printf '%s %s\n' "$0: expecting to be invoked as apt-mark-list" \
			"or apt-mark-restore, aborting"
		exit 1
	;;
esac

