#!/bin/bash

set -e

salt=''
tmp=tmp
var=var
rsync=rsync
disable=true
interactive=true
target=source
suppressrepeatedemails=false
arch=`dpkg --print-architecture`

for config in "$@"; do
	case "$config" in
	*=*)	eval "$config"	;;
	*)	. "$config"	;;
	esac
done

if $disable; then
	echo >&2 'disabled because config inadequate (no disable=false)'
	exit 1
fi

: ${destdirtail:=$distro-$target}
: ${destdirfin:="$destdircommon$destdirtail"}

case $target in
source)
	sources=Sources
	descx=''
	;;
binary-*)
	sources=Packages
	descx="${target#binary-}"
	;;
*)
	echo >&2 'target must be source or binary-*'
	exit 1
esac

exec 3>&1
printf >&3 "starting "

rm -rf "$tmp"
mkdir "$tmp"

>"$tmp"/_log_raw

if $interactive; then
	echo '(log diverted to stdout)' >>"$tmp"/_log_raw
else
	exec >>"$tmp"/_log_raw
fi
exec 4>&1

progress () {
	echo "++++++ $1 ++++++"
}

gurl () {
	progress "fetching $1"
	curl -fsS "$1" >"$2"
}

gurl "$mirror/dists/$distro/$suite/$target/$sources.gz" "$tmp"/_$sources.gz
zcat "$tmp"/_$sources.gz >"$tmp"/_$sources-in

lastinfo="$var"/lastinfo-$target

now=`date +%s`
>>"$lastinfo"

progress selecting

if [ "x$pkg" = x ]; then
 pkg="`perl -e '
	use IO::Handle;

	$pre= "[-+.0-9a-z]+";
	$vre= "[-+.0-9a-zA-Z:~]+";

	sub f1() { $fn=shift @ARGV; open F, $fn or die "$fn $!"; }
	sub f2() { F->error and die "$fn $!"; close F or die "$fn $!"; }

	f1();
	while (<F>) {
		die unless m/^($pre) ($vre) (\d+)( .*)?$/;
		$lastver{$1}= $2;
		$lasttime{$1}= $3;
		$extras{$1}= $4." ";
	}
	f2();
	f1();
	$best_score= -1;
	sub scorepackage () {
		return if $skip;
		return if $score < $best_score
		     or ($score==$best_score and \
			 $package gt $best_package);
#printf STDERR " <----- best score=%s best_score=%s\n", $score, $best_score;
		$best_score= $score;
		$best_package= $package;
	}
	sub endpackage () {
		return unless (defined $package
				or defined $version
				or defined $skip);
		die unless defined $package;
		die unless defined $version;
		scorepackage();
		undef $package;
		undef $version;
		undef $skip;
	}
	while (<F>) {
		if (m/^Package: ($pre)$/) {
			die if defined $package;
			$package= $1;
		} elsif (m/^Version: ($vre)$/) {
			die if defined $version;
			$version= $1;
			$score= '$now' - $lasttime{$package};
			$score= 1e7 if $score>1e7;
			$score *= 5 if $lastver{$package} ne $version;
			$score *= 10 unless $extras{$package} =~ m/ nt /;
#print STDERR "$package score $score\n";
		} elsif (m/^Architecture:.*/ &&
			 !m/\s(?:'$arch'|all|any)\s/) {
#printf STDERR " <----- skip %s %s\n", $&, "'$arch'";
			$skip= 1;
		} elsif (m/^$/) {
			endpackage();
		}
	}
	f2();
	endpackage();
	die unless length $best_package;
	open L, ">&4" or die $!;
	printf L "selected %s (age %s, score %d)\n",
		$best_package,
		exists($lastime{$best_package})
		? '$now' - $lasttime{$best_package}
		: "<never-yet>",
		$best_score;
	print "$best_package\n" or die $!;
 ' "$lastinfo" "$tmp"/_$sources-in`"
else
	printf >&4 "package forced: %s\n" "$pkg"
fi

sed -n "/^Package: $pkg\$/,/^\$/p" \
 <"$tmp"/_$sources-in >"$tmp"/_this-stanza

echo
cat "$tmp"/_this-stanza

getfield () {
	eval 'p'$1'="`
		sed -n '\''s/^'$1': //p'\'' \
		 <"$tmp"/_this-stanza
	`"'
}

printf >&3 "selected \"%s\" " $pkg

tp="$tmp/$pkg"
mkdir "$tp" "$tp/src" "$tp/tmp" "$tp/out"

getfield Version

if test $target = source; then
	getfield Directory
	leafnames="`
		sed -n '/^Files:/,/^([^ ].*)?$/{ /^ /{
			s/^ [0-9a-z][0-9a-z]*  *[0-9][0-9]* //; p
			}}' \
		 <"$tmp"/_this-stanza
	`"
	for leafname in $leafnames; do
		df="$tp/src/$leafname"
		case "$leafname" in
		*/*|.*)	echo >&2 "bad leafname: $leafname"; exit 1;;
		*.dsc) fot="$df";;
		esac
		gurl "$mirror/$pDirectory/$leafname" "$df"
	done
	testmode=--source
	testmode2=''
	desc="$pkg"
	: ${upload_if_ok:=true}
else
	getfield Filename
	fot="$tp/src/$pkg.deb"
	gurl "$mirror/$pFilename" "$fot"
	testmode='--binaries=install --binary'
	testmode2=--instantiate
	desc="$pkg $descx"
	: ${upload_if_ok:=false}
fi

if [ "x$maintainer_email_override" = x ]; then
	getfield Maintainer
	maintainer_email=pMaintainer
else
	maintainer_email=maintainer_email_override
fi

printf >&3 "adt-run "

progress "starting test"

xrc () {
	printf "+ %s\n" "$*"
	set +e
	"$@"
	rc=$?
	set -e
}

echo 'fatal: adt-run did not start properly' >"$tmp"/_summary

xrc adt-run --tmp-dir "$tp"/tmp				\
	--output-dir "$tp"/out				\
	--log-file "$tp"/log 				\
	--summary "$tmp"/_summary 			\
	$adtrun_extra_opts				\
	$testmode "$fot" $testmode2			\
 ---							\
 adt-virt-xenlvm					\
	$adtvirt_extra_opts				\
	--distro="$distro"				\
 --							\
 2>&1 3>&- 4>&-

printf >&3 "%s " $rc

ourx=0
upload=true
: ${upload_if_notests:=false}
extras=''

case "$rc" in
0)	summary='all OK';			email=''
					upload=$upload_if_ok		;;
2)	summary='OK (some skipped)';		email=''
					upload=$upload_if_ok		;;
8)	summary='package declares no tests';	email=''
				upload=$upload_if_notests; extras='nt'	;;
4|6)	summary='test(s) failed!';	email="$maintainer_email"	;;
12)	summary='erroneous package!';	email="$maintainer_email"	;;
16)	summary='testbed failed!';	email="administrator_email"	;;
*)	summary='unexpected failure!';	email="administrator_email"; ourx=20;;
esac

progress "RESULTS $summary"

if  [ "x$suppresspackages" != x ] \
 && grep -x "$pkg" "$suppresspackages" >/dev/null; then
	printf >&3 "email-suppressed "
	email=''
fi

if $upload; then
	progress "bundling"
	printf "\n%s\n" "$summary" >>"$tmp"/_summary

	edest=${email%_email}
	esummary="$var"/emailed/last-$pkg,$edest
	if [ "x$edest" = x ]; then
		printf >&3 "email-none "
		rm -f "$var"/emailed/last-$pkg,*
		esummary=''
	elif $suppressrepeatedemails \
	  && [ -f "$esummary" ] \
	  && diff -u "$esummary" "$tmp"/_summary >"$var"/emailed/diff-$pkg; then
		printf >&3 "email-same $email "
		email=''
		esummary=''
	else
		cp "$tmp"/_summary "$esummary".new
	fi

	ln -f "$tmp"/_summary "$tp"/summary

	for odir in tmp out; do
		if test -d "$tp"/$odir; then
			GZIP=-2 tar -f "$tp"/$odir.tar.gz -C "$tp" -zc $odir
			rm -r "$tp"/$odir
		fi
	done

	progress "uploading"
	printf >&3 "uploading"
	$rsync -rltH --safe-links --delete "$tp" "$destrsynchead/$destdirfin/"
	printf >&3 " "
fi

if [ "x$email" != x ]; then
	progress "contacting $email"
	eval "email_addr=\$$email"
	printf >&3 "email \"%s\" " "$email_addr"
	cat >"$tmp"/_email_header <<END
From: $from
To: $email_addr
Subject: autopkgtest $distro $desc: $summary

END

	printf >"$tmp"/_email "$email_package_header" "$pkg"

	cat >>"$tmp"/_email <<END
 Test executed for:  $distro  $target  $pkg
 Outcome: $summary
END
	sed -e 's/^/  /' "$tmp"/_summary >>"$tmp"/_email
	cat >>"$tmp"/_email <<END

This message is automatically generated by the autopkgtest package
testing system.  You are receiving it because:
END
	case "$email" in
		pMaintainer)
			cat >>"$tmp"/_email <<END
 You are listed in the Maintainer field of the $pkg package in $distro
 and the test results appear to indicate a problem with the package.
END
			;;
		maintainer_email_override)
			cat >>"$tmp"/_email <<END
 The test results appear to indicate a problem with the package
 and reports for package maintainers for $distro are being directed to
 $maintainer_email_override
END
			;;
		administrator_email)
			cat >>"$tmp"/_email <<END
 You are the administrator for the autopkgtest installation.
END
			;;
		*)
			echo >&2 "huh email $email is what why?"
			exit 1
			;;
	esac
	cat >>"$tmp/_email" <<END

The test log, which is intended to be sufficient to diagnose most
failures, can be found below.  However, in case this is not
sufficient, another copy can be found along with output files, saved
temporary files, and so on, at:
 $desthttphead/$destdirfin/
$email_extra_info
If you have any questions about this service please contact me at:
 $from

Regards,
$salutation

-8<-
END
fi

printf >>"$var"/log "%s=%s rc=%s emailed='%s'\n" \
	"$target" "$pkg" $rc "$email_addr"

if [ "x$ourx" = x0 ]; then
	sed -e "/^$pkg /d" <"$lastinfo" >"$lastinfo".new
	printf "%s %s %s %s\n" "$pkg" "$pVersion" "$now" "$extras" \
		>>"$lastinfo".new
	mv "$lastinfo".new "$lastinfo"
	progress "tested."
else
	progress "fault ($ourx)."
fi

perl <"$tmp"/_log_raw >"$tmp"/_log -pe '
	s/[^\012\040-\133\135-\176]/
		$& eq "\t" ? "\\t" :
		$& eq "\r" ? "\\r" :
		$& eq "\b" ? "\\b" :
		$& eq "\\" ? "\\\\" :
		sprintf "\\x%02x", ord $&
	/ge'

if [ "x$email" = x ]; then
	if $interactive; then
		cat "$tmp"/_log >&2
	fi
else
	cat >>"$tmp"/_email 2>&1 "$tmp"/_log ||:

	if [ "x$email_signing_key" != x ]; then
		printf >&3 "signing "
		echo >>"$tmp/_email"
		gpg -u"$email_signing_key" --clearsign \
			<"$tmp/_email" >"$tmp/_email.asc"
		mv -f "$tmp/_email.asc" "$tmp/_email"
	fi
	cat "$tmp/_email_header" "$tmp/_email" >"$tmp/_email.new"
	mv -f "$tmp/_email.new" "$tmp/_email"

	if $interactive; then
		cat "$tmp"/_email >&2
	else
		sendmail -odi -oem -t -oi <"$tmp"/_email
		if [ "x$esummary" != x ]; then
			printf >&3 "email-recorded "
			mv "$esummary".new "esummary"
		fi
	fi
fi

printf >&3 "done %s.\n" $ourx
exit $ourx
