#!/bin/sh
# dpkg's database made whole after an install that stopped part way (the
# page closed, a program killed): run at boot (/etc/gex/boot) and before
# apt-get update. With it, apt never refuses an install with "dpkg was
# interrupted": packages left unpacked or half-configured are configured
# (their scripts fail-safe, /usr/lib/gex/maint-safe), and one left
# half-installed (its files part written) is removed, for apt to install
# again when asked. Then apt's dependencies made whole too (below).
S=/var/lib/dpkg/status
dirty=
[ -n "$(ls -A /var/lib/dpkg/updates 2>/dev/null)" ] && dirty=1
grep -qE '^Status: [a-z]+ [a-z]+ (half-installed|unpacked|half-configured|triggers-awaited|triggers-pending)$|^Status: [a-z]+ reinstreq ' "$S" && dirty=1
[ -n "$dirty" ] || exit 0
echo "gex: dpkg was interrupted; putting its database right" >&2
/usr/lib/gex/maint-safe
dpkg --configure -a >/dev/null 2>&1
for p in $(awk 'BEGIN { RS = ""; FS = "\n" } /\nStatus: [a-z]+ (reinstreq [a-z-]+|[a-z]+ half-installed)(\n|$)/ { for (i = 1; i <= NF; i++) if ($i ~ /^Package: /) n = substr($i, 10); else if ($i ~ /^Architecture: /) a = substr($i, 15); print n ":" a }' "$S"); do
    dpkg --remove --force-remove-reinstreq --force-depends --force-remove-essential "$p" >/dev/null 2>&1 &&
        echo "gex: removed $p (half-installed): its unpack stopped part way" | tee -a /var/log/gex-maint.log >&2
done
dpkg --configure -a >/dev/null 2>&1
# and apt's view whole: a package configured above may need one whose
# unpack failed (thunderbird-l10n-kab, thunderbird's libxul out of space),
# and apt refuses every install, of anything, while a dependency is unmet.
# Debian's own repair first (apt-get -f install: the missing package
# installed). If that cannot, the packages apt names as having an unmet
# dependency are removed, once, each logged with why (no package whose
# dependencies are met is ever removed), for apt to install again when asked.
if ! apt-get check >/dev/null 2>&1; then
    apt-get -y -f install >/dev/null 2>&1
    apt-get check 2>&1 | sed -n 's/^ \([^ :]*\(:[a-z0-9-]*\)\{0,1\}\) : \(.*\)/\1|\3/p' | sort -u -t'|' -k1,1 |
    while IFS='|' read -r p why; do
        st=$(dpkg-query -W -f='${Status}' "$p" 2>/dev/null)
        dpkg --remove --force-depends "$p" >/dev/null 2>&1 &&
            echo "gex: removed $p ($st): unmet $why" | tee -a /var/log/gex-maint.log >&2
    done
fi
exit 0
