#!/bin/bash

## Copyright (C) 2025 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

set -o errexit
set -o nounset
set -o errtrace
set -o pipefail

privleap_project_dir="$(dirname "$(readlink -f "${0}")")"
target_distribution="trixie"
autopkgtest_tarball_path="${HOME}/.cache/sbuild/${target_distribution}-amd64.tar.zst"

create_autopkgtest_tarball() {
  mkdir -p ~/.cache/sbuild
  ## TODO: Can we use dracut instead of initramfs-tools? (We have to install
  ## initramfs-tools here right now to make the autopkgtest environment happy
  ## but maybe dracut will work instead.)
  sudo mmdebstrap \
    --include=ca-certificates,passwd,adduser,initramfs-tools \
    --skip=output/dev \
    --variant=debootstrap \
    "${target_distribution}" \
    "${autopkgtest_tarball_path}" \
    --customize-hook='chroot "$1" passwd --delete root' \
    --customize-hook='chroot "$1" useradd --home-dir /home/user --create-home user' \
    --customize-hook='chroot "$1" passwd --delete user' \
    --customize-hook='cp /etc/hosts "$1/etc/hosts"' \
    --customize-hook=/usr/share/autopkgtest/setup-commands/setup-testbed \
    https://deb.debian.org/debian
}

offer_package_install() {
  local pkg_name install_yn
  pkg_name="$1"
  1>&2 echo "${pkg_name} is not installed, but is needed to run the test suite."
  1>&2 echo -n 'Would you like to install it now? [y/N] '
  read -r install_yn
  if [ "${install_yn,,}" = 'y' ]; then
    sudo apt-get install "${pkg_name}"
  else
    1>&2 echo 'Test run aborted.'
    exit 1
  fi
}

print_usage() {
  local help_info
  help_info='run_autopkgtest: Runs regression tests for privleap using autopkgtest
Usage:
  run_autopkgtest [--reset-tarball]
Options:
  --reset-tarball: Deletes and recreates the tarball used by unshare
                   for running the tests.'
  1>&2 echo "${help_info}"
}

run_autopkgtest() {
  local arg
  arg="${1:-}"
  if [ "${arg}" = '--help' ] || [ "${arg}" = '-h' ] || [ "${arg}" = '-?' ]; then
    print_usage
    exit 0
  fi

  if [ "$(id -u)" = '0' ]; then
    1>&2 echo 'Do not run this script as root!'
    exit 1
  fi

  if [ "${arg}" = '--reset-tarball' ]; then
    rm -f "${autopkgtest_tarball_path}"
  elif [ -n "${arg}" ]; then
    1>&2 echo "Unrecognized argument: '${arg}'. Try 'run_autopkgtest --help' for usage info."
    exit 1
  fi

  ## Dependency checks
  if ! [ -x '/usr/bin/unshare' ]; then
    1>&2 echo 'unshare is not executable or does not exist!'
    exit 1
  fi
  if ! [ -f '/usr/bin/autopkgtest' ]; then
    offer_package_install 'autopkgtest'
  fi
  if ! [ -f '/usr/bin/mmdebstrap' ]; then
    offer_package_install 'mmdebstrap'
  fi
  if ! [ -f '/usr/bin/dh' ]; then
    offer_package_install 'debhelper'
  fi
  if ! [ -f '/usr/share/keyrings/debian-archive-trixie-stable.gpg' ]; then
    offer_package_install 'debian-archive-keyring'
  fi
  if [ "$(basename "${privleap_project_dir}")" != 'privleap' ]; then
    1>&2 echo 'The run_autopkgtest script does not appear to be in the root of the privleap source tree!'
    exit 1
  fi
  if [ "$(stat -c "%u|%a" /usr/bin/newuidmap)" != '0|4755' ]; then
    1>&2 echo 'autopkgtest requires /usr/bin/newuidmap to be SUID-root!'
    exit 1
  fi
  if [ "$(stat -c "%u|%a" /usr/bin/newgidmap)" != '0|4755' ]; then
    1>&2 echo 'autopkgtest requires /usr/bin/newgidmap to be SUID-root!'
    exit 1
  fi
  if [ "$(pwd)" != "${privleap_project_dir}" ]; then
    cd "${privleap_project_dir}" >/dev/null || {
      1>&2 echo 'Cannot change to privleap source tree directory!'
      exit 1
    }
  fi

  if ! [ -f "${autopkgtest_tarball_path}" ]; then
    create_autopkgtest_tarball
  fi

  dpkg-buildpackage -i -us -uc -b || {
    1>&2 echo 'Cannot build privleap deb package!'
    exit 1
  }
  cd ..
  autopkgtest -l "${privleap_project_dir}/privleap-test-log.txt" \
    --apt-upgrade -B privleap*.deb "${privleap_project_dir}" -- unshare
  echo "Test complete. Results are stored in ${privleap_project_dir}/privleap-test-log.txt."
}

run_autopkgtest "$@"
