#!/bin/sh

set -exu

# the archive with the highest priority where the base-files package comes from
# determines whether we are on stable, testing or unstable
DEFAULT_DIST=$(cat << END | python3 -
import apt_pkg, sys
apt_pkg.init()
c = apt_pkg.Cache(None)
d = apt_pkg.DepCache(c)
s = apt_pkg.SourceList()
s.read_main_list()

highest_prio = -1
highest_archive = None
for pkgfile, _ in d.get_candidate_ver(c["base-files"]).file_list:
	print("processing: %s"%pkgfile, file=sys.stderr)
	index = s.find_index(pkgfile)
	if index is None:
		print("index is none -- skipping", file=sys.stderr)
		continue
	if not index.is_trusted:
		print("index is not trusted -- skipping", file=sys.stderr)
		continue
	archive = pkgfile.archive
	if archive not in ["stable", "testing", "unstable"]:
		print("index archive %s is %s -- skipping"%(index, archive), file=sys.stderr)
		continue
	prio = d.policy.get_priority(pkgfile)
	if prio > highest_prio:
		highest_prio = prio
		highest_archive = archive
if highest_archive is None:
	print("highest priority apt archive is neither stable, testing or unstable", file=sys.stderr)
	for f in c.file_list:
		print('========================', file=sys.stderr)
		for a in ['architecture', 'archive', 'codename', 'component', 'filename', 'id', 'index_type', 'label', 'not_automatic', 'not_source', 'origin', 'site', 'size', 'version']:
			print("%s: %s"%(a, getattr(f, a, None)), file=sys.stderr)
		print("priority: ", d.policy.get_priority(f), file=sys.stderr)
	exit(1)
print("highest archive priority: %s"%highest_archive, file=sys.stderr)
print(highest_archive)
END
)

# On stable and testing we can run tests that require m-a:same packages to
# exist in the same version across multiple architectures. Only on unstable we
# disable this because packages in unstable are often out-of-sync.
RUN_MA_SAME_TESTS=yes
case $DEFAULT_DIST in
	unstable)
		RUN_MA_SAME_TESTS=no
		;;
	stable|testing)
		# nothing to do
		;;
	*)
		echo "unknown distribution $DEFAULT_DIST, must be one of stable, testing or unstable" >&2
		;;
esac

SRC="$(pwd)"

# change to temporary directory to not interfere with the source
cd "$AUTOPKGTEST_TMP"

# coverage.sh expects the scripts to be in the current directory
# we copy make_mirror.sh instead of symlinking it because we are going to patch
# it
cp -a "$SRC/make_mirror.sh" make_mirror.sh
ln -s "$SRC/run_qemu.sh" run_qemu.sh
ln -s "$SRC/run_null.sh" run_null.sh
cp -a "$SRC/hooks" .
ln -s "$SRC/coverage.sh" coverage.sh
ln -s "$SRC/gpgvnoexpkeysig" gpgvnoexpkeysig
ln -s "$SRC/coverage.py" coverage.py
ln -s "$SRC/coverage.txt" coverage.txt
cp -a "$SRC/tests" .

# on Debian Salsa CI, $AUTOPKGTEST_NORMAL_USER is empty
if [ -z "$AUTOPKGTEST_NORMAL_USER" ]; then
	AUTOPKGTEST_NORMAL_USER=debci
	useradd --create-home --groups sudo "$AUTOPKGTEST_NORMAL_USER"
#	useradd --create-home --groups kvm "$AUTOPKGTEST_NORMAL_USER"
#	ls -lha /dev/kvm || true
#	lsmod | grep kvm || true
else
	adduser "$AUTOPKGTEST_NORMAL_USER" sudo
#	adduser "$AUTOPKGTEST_NORMAL_USER" kvm
fi

mkdir ./shared
chown "$AUTOPKGTEST_NORMAL_USER" ./shared

echo "$AUTOPKGTEST_NORMAL_USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

# add symlink from cache to cache.A so that debootstrap finds all the packages
# which are put into cache.A even before make_mirror.sh creates the symlink
# itself
ln -s cache.A "$AUTOPKGTEST_TMP/shared/cache"
# we cannot use mini_httpd (or most other http servers) because they perform a
# chdir() into the directory that is to be served on startup. But later on we
# completely remove and replace that directory when creating the Debian mirror.
# Thus we need a really stupid server which is able to cope with having its
# www-root being replaced under its feet.
#mini_httpd -D -h 127.0.0.1 -p 80 -u "$AUTOPKGTEST_NORMAL_USER" -T UTF-8 -dd "$AUTOPKGTEST_TMP/shared/cache" &
python3 -m http.server --directory="$AUTOPKGTEST_TMP/shared/cache" --bind 127.0.0.1 80 2>/dev/null &
HTTPD_PID=$!
trap "kill $HTTPD_PID" INT QUIT TERM EXIT

# create a fake mmdebstrap file in the current directory that coverage.sh can
# copy
cat << END > ./mmdebstrap
#!/usr/bin/perl
use strict;
use warnings;
exit(1)
END

# must not be used during testing -- installed version must be used instead
cat << END > ./tarfilter
#!/usr/bin/env python3
exit(1)
END

# add entries to /etc/subuid and /etc/subgid if they don't exist yet
if [ ! -e /etc/subuid ] || ! grep "$AUTOPKGTEST_NORMAL_USER" /etc/subuid; then
	echo "$AUTOPKGTEST_NORMAL_USER:100000:65536" >> /etc/subuid
fi
if [ ! -e /etc/subgid ] || ! grep "$AUTOPKGTEST_NORMAL_USER" /etc/subgid; then
	echo "$AUTOPKGTEST_NORMAL_USER:100000:65536" >> /etc/subgid
fi

# we cannot add foreign architecture dependencies to debian/tests/control
# See https://bugs.debian.org/913082
if [ "$RUN_MA_SAME_TESTS" = "yes" ]; then
	dpkg --add-architecture armhf
	apt-get update
	HOSTARCH=$(dpkg --print-architecture)
	ret=0
	apt-get install --yes libfakechroot:armhf libfakechroot:$HOSTARCH libfakeroot:armhf libfakeroot:$HOSTARCH || ret=$?
	if [ "$ret" -ne 0 ]; then
		echo "failed installing libfakeroot and libfakechroot -- M-A:same version skew?"
		exit 77
	fi
fi

echo "running on:"
cat /etc/debian_version
echo "environment:"
env

i=0
while true; do
	rm -rf ./shared
	mkdir ./shared
	chown "$AUTOPKGTEST_NORMAL_USER" ./shared
	ln -s cache.A "$AUTOPKGTEST_TMP/shared/cache"
	ret=0
	timeout 50m runuser -u "$AUTOPKGTEST_NORMAL_USER" -- env CMD=mmdebstrap DEFAULT_DIST=$DEFAULT_DIST RUN_MA_SAME_TESTS=$RUN_MA_SAME_TESTS HAVE_UNSHARE=no HAVE_QEMU=no HAVE_PROOT=no HAVE_BINFMT=no "$SRC/make_mirror.sh" || ret=$?
	# success -- break the loop
	if [ "$ret" -eq 0 ]; then
		break
	fi
	i=$((i+1))

	# too many failures -- exit
	if [ "$i" -ge 3 ]; then
		echo "too many failures, giving up"
		exit 77
	fi

	# trying again...
	echo "make_mirror.sh failed, trying again..."
	sleep 5m
done

CONTAINER="no"
if grep --null-data --quiet --no-messages '^container=lxc$' /proc/1/environ; then
	# salsa ci
	CONTAINER="lxc"
fi

# now run the script
# we set PATH so that the umount wrapper is used
# we set CMD so that Devel::Cover is not used
#runuser -u "$AUTOPKGTEST_NORMAL_USER" -- env CMD=./mmdebstrap PATH="$AUTOPKGTEST_TMP/bin:/bin:/usr/bin" "$SRC/coverage.sh"
# HAVE_PROOT=no or otherwise:
#    proot error: can't retrieve loader path (/proc/self/fd/)
#    proot error: execve("/usr/bin/mv"): No such file or directory
#    proot info: possible causes:
#      * the program is a script but its interpreter (eg. /bin/sh) was not found;
#      * the program is an ELF but its interpreter (eg. ld-linux.so) was not found;
#      * the program is a foreign binary but qemu was not specified;
#      * qemu does not work correctly (if specified);
#      * the loader was not found or doesn't work.
#    fatal error: see `proot --help`.
# HAVE_UNSHARE=no or otherwise:
#    newuidmap: Could not open proc directory for target 23920
#    newuidmap 23920  0 1000 1 1 100000 1 failed:  at /usr/bin/mmdebstrap line 319.
#    child had a non-zero exit status: 1 at /usr/bin/mmdebstrap line 341.
#    chown failed at /usr/bin/mmdebstrap line 1698.
# HAVE_QEMU=no because there is no kvm kernel module
# HAVE_BINFMT=no because there is no binfmt_misc kernel module
runuser -u "$AUTOPKGTEST_NORMAL_USER" -- env CMD=mmdebstrap DEFAULT_DIST=$DEFAULT_DIST RUN_MA_SAME_TESTS=$RUN_MA_SAME_TESTS HAVE_UNSHARE=no HAVE_QEMU=no HAVE_PROOT=no HAVE_BINFMT=no CONTAINER=$CONTAINER "$SRC/coverage.sh"
