#!/bin/sh
set -eu

package_file=${1:?usage: package-lifecycle /path/to/bongo.deb}
work_dir=${2:-/tmp/bongo-package-lifecycle}

die()
{
    echo "package-lifecycle: $*" >&2
    exit 1
}

assert_marker()
{
    path=$1
    expected=$2
    [ -f "$path" ] || die "state marker disappeared: $path"
    actual=$(cat "$path")
    [ "$actual" = "$expected" ] ||
        die "state marker changed: $path"
}

assert_state()
{
    assert_marker /etc/bongo/config.d/lifecycle-test \
        configuration-preserved
    assert_marker /etc/bongo/ssl.d/lifecycle-test.key \
        private-key-preserved
    assert_marker /var/lib/bongo/users/lifecycle-test/message \
        user-mail-preserved
    assert_marker \
        /var/lib/bongo/users/lifecycle-test/preferences/tasks/task.json \
        user-preference-preserved
    assert_marker /var/lib/bongo/system/lifecycle-test \
        system-store-preserved
    assert_marker /var/lib/bongo/spool/lifecycle-test \
        queue-state-preserved
    assert_marker /var/spool/bongo/maildrop/lifecycle-test \
        local-submission-preserved
}

[ "$(id -u)" -eq 0 ] || die "this test must run as root"
[ -f "$package_file" ] || die "package not found: $package_file"
[ "$(dpkg-deb -f "$package_file" Package)" = bongo ] ||
    die "not a bongo binary package: $package_file"

version=$(dpkg-deb -f "$package_file" Version)
architecture=$(dpkg-deb -f "$package_file" Architecture)
upgrade_version="${version}+lifecycle1"

rm -rf "$work_dir"
mkdir -p "$work_dir/unpacked"

install -d -m 0750 -o root -g bongo \
    /etc/bongo/config.d /etc/bongo/ssl.d
install -d -m 0750 -o bongo -g bongo \
    /var/lib/bongo/users/lifecycle-test \
    /var/lib/bongo/users/lifecycle-test/preferences/tasks \
    /var/lib/bongo/system /var/lib/bongo/spool
install -d -m 0710 -o bongo -g bongopostdrop /var/spool/bongo
install -d -m 1730 -o bongo -g bongopostdrop \
    /var/spool/bongo/maildrop
printf '%s\n' configuration-preserved > \
    /etc/bongo/config.d/lifecycle-test
printf '%s\n' private-key-preserved > \
    /etc/bongo/ssl.d/lifecycle-test.key
chmod 0640 /etc/bongo/ssl.d/lifecycle-test.key
printf '%s\n' user-mail-preserved > \
    /var/lib/bongo/users/lifecycle-test/message
printf '%s\n' user-preference-preserved > \
    /var/lib/bongo/users/lifecycle-test/preferences/tasks/task.json
printf '%s\n' system-store-preserved > \
    /var/lib/bongo/system/lifecycle-test
printf '%s\n' queue-state-preserved > \
    /var/lib/bongo/spool/lifecycle-test
printf '%s\n' local-submission-preserved > \
    /var/spool/bongo/maildrop/lifecycle-test
chown -R bongo:bongo /var/lib/bongo/users/lifecycle-test \
    /var/lib/bongo/system/lifecycle-test \
    /var/lib/bongo/spool/lifecycle-test
chown bongo:bongopostdrop /var/spool/bongo/maildrop/lifecycle-test

# A same-version reinstall must leave administrator configuration, keys,
# mailboxes, Store data, and a possibly non-empty queue untouched.
apt-get install --reinstall -y "$package_file"
assert_state

# Repack the identical payload with a higher test-only version. This exercises
# dpkg's real upgrade maintainer-script path without publishing a fake release.
dpkg-deb --raw-extract "$package_file" "$work_dir/unpacked"
sed -i "s/^Version: .*/Version: ${upgrade_version}/" \
    "$work_dir/unpacked/DEBIAN/control"
upgrade_package="$work_dir/bongo_${upgrade_version}_${architecture}.deb"
dpkg-deb --root-owner-group --build "$work_dir/unpacked" "$upgrade_package"
apt-get install -y "$upgrade_package"
[ "$(dpkg-query -W -f='${Version}' bongo)" = "$upgrade_version" ] ||
    die "test upgrade version was not installed"
assert_state

# Normal removal deletes programs while retaining Debian conffiles and all
# site-created configuration and persistent state.
apt-get remove -y bongo
[ ! -e /usr/sbin/bongo-manager ] ||
    die "program payload remained after package removal"
[ -f /etc/fail2ban/filter.d/bongo-auth.conf ] ||
    die "Debian conffile disappeared during normal removal"
assert_state

# Purge removes package-owned conffiles, but deliberately does not destroy
# setup-generated keys/configuration or mail and Store state.
apt-get purge -y bongo
[ ! -e /etc/fail2ban/filter.d/bongo-auth.conf ] ||
    die "package-owned Fail2ban conffile remained after purge"
[ ! -e /etc/fail2ban/jail.d/bongo-auth.conf ] ||
    die "package-owned Fail2ban jail remained after purge"
if dpkg-query -W bongo >/dev/null 2>&1; then
    die "package database entry remained after purge"
fi
assert_state

echo "package-lifecycle: install/reinstall/upgrade/remove/purge passed"
