#!/bin/sh

export LC_ALL="C"

## default config
PAUSE_SECONDS=$((15*60))
HTML_OUTPUT=0
SEND_MAIL=0
NICE=
OWNER=
MACHINE=`uname`

## subroutines
usage ()
{
	echo "Usage: $0 [options]"
	echo "Options:"
	echo "-w <N>     specify timeout in secs between subsequent pull requests"
	echo "-i         when given: run with ionice -c3, can be combined with -n"
	echo "-l         when given: write html build log"
	echo "-m <owner> when given: mail errors to the committer, general errors to the <owner>"
	echo "-n         when given: run with nice, can be combined with -i"
	echo "-h         this help"
}

getCommitters ()
{
	from_date="$1"

	( git log '--pretty=tformat:%ce' --after="$from_date" ;
	  bin/g -s log '--pretty=tformat:%ce' --after="$from_date" ) | sort | uniq
}

reportError ()
{
	error_kind="$1"
	shift

	commit=`git log '--pretty=format:%h %cn - %s' -n1`

	to_mail=
	if test "$SEND_MAIL" -eq 1; then
		case "$error_kind" in
			owner) to_mail="$OWNER"
			       message="box broken" ;;
			*)     if test -z "$last_success" ; then
			          # we need at least one successful build to
				  # be reliable
			          to_mail="$OWNER"
			       else
			          to_mail=`getCommitters "$last_success"`
			       fi
			       message="last commit: $commit" ;;
		esac
	fi

	echo "$*" 1>&2
	echo "Last commit: $commit" 1>&2
	if test -n "$to_mail" ; then
		subject="Tinderbox failure, $message"
		(
			cat <<EOF
Hi folks,

One of you broke the build of LibreOffice master with your commit :-(
Please commit and push a fix ASAP!

Tinderbox info:

  `uname -a`
`grep '\$ \.\/configure' config.log`

Commits since the last success:

  ===== build =====
`git log '--pretty=tformat:%h  %s' --after="$last_success" | sed 's/^/  /'`

`bin/g log '--pretty=tformat:%h  %s' --after="$last_success" | sed 's/^/  /'`

The error is:

$*
EOF
		) | mail -r "$OWNER" -s "$subject" $to_mail
	else
		echo "$*" 1>&2
		if test "$error_kind" = "owner" ; then
			exit 1
		fi
	fi
}

gitHeads ()
{
	git rev-parse --verify HEAD
	bin/g rev-parse --verify HEAD
}

## code
while getopts hilm:nw: opt ; do
	case "$opt" in
		w) PAUSE_SECONDS="$OPTARG" ;;
		i) NICE="$NICE ionice -c3" ;;
		l) HTML_OUTPUT=1 ;;
		m) SEND_MAIL=1 ; OWNER="$OPTARG" ;;
		n) NICE="$NICE nice" ;;
		h) usage; exit ;;
		?) usage; exit ;;
	esac
done

# sanity checks
which git > /dev/null 2>&1 || {
    echo "You need git for this!"
	exit 1
}

if test "$SEND_MAIL" -eq 1 ; then
	if test -z "$OWNER" ; then
		echo "Owner not set."
		exit 1
	fi
	if test "$OWNER" = `echo ${OWNER} | sed 's/\@/_/g'` ; then
		echo "The owner address '$OWNER' does not look like an email address."
		exit 1
	fi
fi

# for build.pl
test $HTML_OUTPUT -eq 1 && export BUILD_HTML_OUTPUT=true

# main
prev_success=""
last_success=""
while true; do
	err_msg=""

	# cleanup
	$NICE make clean-local

	# FIXME we need a more exact way to determine a 'good' date; this is not accurate
	if [ "X$MACHINE" == "XDarwin" ] ; then
	    rough_checkout_date="`date -u '+%Y-%m-%d %H:%M:%S'`"
	else
	    rough_checkout_date="`date --utc --rfc-3339=seconds`"
	fi
	# try to build
	if ! err_msg=$(./autogen.sh 2>&1); then
		reportError committer `printf "autogen.sh / configure failed - error is:\n\n$err_msg"`
	elif ! err_msg=$(./download 2>&1); then
		reportError committer `printf "download failed - error is:\n\n$err_msg"`
	elif ! $NICE make >build.log 2>&1 ; then
		reportError committer `printf "building failed - error is:\n\n"` "$(tail -n100 build.log)"
	elif ! $NICE make smoketest > smoketest.log 2>&1 ; then
		reportError committer `printf "smoketest failed - error is:\n\n"` "$(tail -n100 smoketest.log)"
	elif ! $NICE make dev-install >install.log 2>&1 ; then
		reportError committer `printf "dev installation failed - error is:\n\n"` "$(tail -n100 install.log)"
	else
		echo build done
		cp build.log build/
		cp smoketest.log build/
		cp install.log build/
		gitHeads > build/git-heads.txt

		prev_success=$last_success
		last_success=$rough_checkout_date
		mv build "build-$last_success" ||
		{
			msg=
			test -z "$prev_success" || msg="Leaving 'build-$prev_success' around, exiting now"
			reportError owner `printf "Cannot move 'build' to 'build-$last_success'\n\n$msg"`
		}

		if test -n "$prev_success"; then
			rm -rf "build-$prev_success"
		fi
	fi

	if [ -d build ] ; then
		mv build.log build/
		mv smoketest.log build/
		mv install.log build/
		rm -rf build.failed
		mv build build.failed
	fi

	echo updating repo

	# new commits?
	while true; do
		old_head=$(gitHeads) && err_msg=$(git pull -r 2>&1) && err_msg2=$(bin/g pull -r 2>&1) ||
		{
			msg=
			test -z "$prev_success" || msg="Leaving 'build-$prev_success' around, exiting now"

			reportError owner `printf "git repo broken - error is:\n\n$err_msg\n$err_msg2\n$msg"`
		}
		new_head=$(gitHeads)
		
		if test "$old_head" != "$new_head"; then
			break
		fi

		echo "Waiting $PAUSE_SECONDS seconds."
		sleep $PAUSE_SECONDS
	done
done
