#!/bin/sh -efu

GB_REPO_NAME="$1"; shift
GB_REPO_FLAVOUR="$1"; shift
arch="$1" N="$2" EVR="$3" A="$4" F="$5" I="$6"
shift 6

stamp_echo()
{
	echo "$(LC_TIME=C date '+%Y-%b-%d %T') :: $*"
}

tmpdir=
cleanup()
{
	[ -z "$tmpdir" ] || rm -rf -- "$tmpdir"
	exit "$@"
}

tmpdir=$(mktemp -t -d "${0##*/}.XXXXXXXX")
trap 'cleanup $?' EXIT
trap 'exit 143' HUP INT QUIT PIPE TERM

q_bin='%{name}\t%|serial?{%{serial}:}|%{version}-%{release}\t%{arch}\t%{sourcerpm}\t%{sha1header}\n'
comp=$GB_REPO_FLAVOUR
if [ -z "${N##*-debuginfo}" -a -d gb-repo/$A/RPMS.debuginfo ]; then
	comp=debuginfo
fi
F_path="gb-repo/$A/RPMS.$comp/$F"
rpmquery --qf "$q_bin" -p "$F_path" > "$tmpdir/id"

if rpmquery --provides -p "$F_path" |
   grep -qs '^altlinux-release '; then
	release=$N
else
	release=altlinux-release-$GB_REPO_NAME
fi

topdir="$PWD"
cd "$tmpdir"

# Initialize.
initroot_stamp="$TMPDIR/tmp/check-install-hsh-initroot.stamp"
[ "$(cat "$initroot_stamp" 2>/dev/null)" = "$release" ] ||
setarch "$arch" -- \
hsh --init --without-stuff --no-contents-ind \
    --pkg-init-list="+$release" \
    --pkg-build-list="$release,basesystem" >out 2>&1 ||
	{
		echo "	$arch: initroot failed:"
		cat out
		exit 1
	} >&2

# Save base chroot identification.
hsh-run -- rpmquery -a --qf "$q_bin" > chroot_base
sort -u -o chroot_base{,}
echo "$release" > "$initroot_stamp"

# Check if the package is already installed.
QA='%{name}=%|epoch?{%{epoch}:}|%{version}-%{release}\n'
hsh-run -- rpmquery -a --qf "$QA" >packages0
if fgrep -qs -x -e "$N=$EVR" packages0; then
	# The package is already installed.  Since the package is part of
	# basesystem, removing it might not work very well.
	stamp_echo >&2 "[$arch] #$I $N: part of basesystem, install check OK"
	exit 0
fi

# Check if there was a successful install test for the package already.
if [ -s "$topdir"/install/chroot_install ] &&
   cmp -s {"$topdir"/install/,}id &&
   cmp -s {"$topdir"/install/,}chroot_base; then
	(set +u
	 . hsh-sh-functions
	 set_workdir
	 print_uris "$N=$EVR" 2>/dev/null
	) |
	xargs -r0 --delimiter='\n' \
		rpmquery --qf "$q_bin" -p -- |
		sort -u > chroot_install
	cat chroot_base >> chroot_install
	sort -u -o chroot_install{,}
	if cmp -s {"$topdir"/install/,}chroot_install; then
		[ ! -s "$topdir"/install/warnings ] ||
			cat -- "$topdir"/install/warnings
		stamp_echo >&2 "[$arch] #$I $N: no need to repeat, install check SKIPPED"
		exit 0
	fi
fi

rm -f -- "$initroot_stamp"
> warnings

# Install prerequisites.
# Installing prerequisites is tricky: pretend to install the package and then
# immediately mark it for removal.  This should do the right thing with circular deps.
hsh-install -- "$N=$EVR" "$N-" >out 2>&1 ||
	{
		echo "	$arch: $N=$EVR preinstall failed:"
		cat out
		exit 1
	} >&2

# Workaround for pkg-config.
hsh-run --rooter -- \
mkdir -p -m755 /etc/buildreqs/files/ignore.d /usr/share/aclocal

# Make preinstall package list.
hsh-run -- rpmquery -a --qf "$QA" >packages1
sort -u -o packages1{,}

# Make preinstall file list.
printf '%s\n%s\n' \
	'#!/.host/sh -e' \
	'/.host/find /* \( -path /dev -o -path /usr/src/tmp \) -prune -o -print' \
	>find.sh
hsh-run --rooter --execute=find.sh >flist1 2>out ||
	{
		echo "  $arch: $N=$EVR preinstall filelist check failed:"
		cat out
		exit 1
	} >&2
sort -u -o flist1{,}

# Install the package.
hsh-install -- "$N=$EVR" >out 2>&1 ||
	{
		echo "	$arch: $N=$EVR install failed:"
		cat out
		exit 1
	} >&2

# Make postinstall package list.
hsh-run -- rpmquery -a --qf "$QA" >packages2
sort -u -o packages2{,}

# Make post-install file list.
hsh-run --rooter --execute=find.sh >flist2 2>out ||
	{
		echo "  $arch: $N=$EVR post-install filelist check failed:"
		cat out
		exit 1
	} >&2
sort -u -o flist2{,}

# Check for circilar dependencies.
comm -23 packages{2,1} >new-packages
n=$(wc -l <new-packages)
if [ $n -lt 1 ]; then
	echo "warning [$arch]: $N=$EVR: pre/post-install mess-up"
	exit 1
elif [ $n -gt 1 ]; then
	what=$(fgrep -v -x -e "$N=$EVR" new-packages)
	echo > warnings \
		"warning [$arch]: $N=$EVR: circular dependencies on" $what
	cat warnings
fi >&2

# Check new files.
comm -23 flist{2,1} >new-files

if [ -s new-files ]; then
	cat >ignore-p <<'EOF'
/usr/share/locale/.*
/etc/alternatives/links/.*
/etc/rc\.d/rc[0-6]\.d/[KS][0-9].*
/etc/tcb/.*
/usr/share/mime/.*
/var/cache/fontconfig/.*
/var/cache/gconf/.*
/var/resolv/(lib|lib64)/lib.*
EOF
	if egrep -v -x -f ignore-p -- \
	   new-files >new-files+; then
		mv -f new-files{+,}
	fi
fi

hsh-run --rooter -- \
rpmquery -a --provides >instprov
sort -u -o instprov{,}

hsh-run --rooter -- \
rpmquery -al >instfiles
sort -u -o instfiles{,}

sort -u instprov instfiles >instlist
comm -23 new-files instlist >unprovided

hsh-run --rooter -- <unprovided \
xargs -r --delimiter='\n' realpath >frlist 2>out ||
	{
		echo "  $arch: $N=$EVR post-install filelist check failed:"
		cat out
		exit 1
	} >&2
sort -u -o frlist{,}

comm -23 frlist instlist >out
if [ -s out ]; then
	sed -i 's|no package provides \(/.*\)|file \1 is not owned by any package|' out
	echo "	$arch: $N=$EVR post-install unowned files:"
	cat out
	echo >> warnings \
		"	$arch: $N=$EVR post-install unowned files:"
	cat out >> warnings
fi >&2

# Save chroot identification.
hsh-run -- rpmquery -a --qf "$q_bin" > chroot_install
sort -u chroot_install > "$topdir"/install/chroot_install
cp -p id chroot_base warnings "$topdir"/install/

# Remove the package.
mountpoints="$(hsh-run -- rpmquery -aR | grep -E '^/(proc|dev/pts)$' | sort -u | tr '\n' ,)"
what=$(perl -pe 's/=\d+:/-/ or s/=/-/' <new-packages)
hsh-run --rooter --mountpoints="$mountpoints" -- \
rpm -ev -- ${what:?} </dev/null >out 2>&1 ||
	{
		echo "	$arch: $N=$EVR uninstall failed:"
		cat out
		exit 1
	} >&2

stamp_echo >&2 "[$arch] #$I $N: install check OK"
