#!/bin/sh

# Copyright 2009-2010 Holger Levsen (holger@layer-acht.org)
# Copyright © 2011 Andreas Beckmann <debian@abeckmann.de>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#
# Usage: detect_well_known_errors [--recheck|--recheck-failed]
#


PIUPARTS_CONF=${PIUPARTS_CONF:-/etc/piuparts/piuparts.conf}
[ -f "$PIUPARTS_CONF" ] || exit 0

# usage: get_config_value VARIABLE section key [default]
get_config_value()
{
	local section key value
	test -n "$1" && test "$1" = "$(echo "$1" | tr -c -d '[:alnum:]_')" || exit 1
	section="$2"
	key="$3"
	value="$(sed -rn '\#^\['"$section"'\]#,/^\[/ {/^'"$key"'\s*=/ {s/^'"$key"'\s*=\s*//; s/\s*$//; p}}' "$PIUPARTS_CONF")"
	test -n "$value" || value="$4"
	if [ -z "$value" ]; then
		echo "'$key' not set in section [$section] of $PIUPARTS_CONF, exiting." >&2
		exit 1
	fi
	eval "$1"='"$value"'
}

get_config_value MASTER global master-directory
get_config_value SECTIONS global sections
get_config_value HTDOCS global output-directory


PROBLEMDIR="$HOME/bin/known_problems"
PROBLEMS=$(ls $PROBLEMDIR)
OLDPWD=$(pwd)


LOGS=`mktemp`
ALLKPR=`mktemp`
KNOWNLOGS=`mktemp`
UNKNOWNLOGS=`mktemp`
KNOWNFAILURES=`mktemp`
LIST_ALL=`mktemp`
LIST_PKG=`mktemp`

for SECTION in $SECTIONS
do
	test -d $MASTER/$SECTION || continue
	date
	echo $SECTION:
	cd $MASTER/$SECTION
	mkdir -p pass bugged affected fail

	#
	# remove outdated *.bug files
	#
	find pass bugged affected fail -name '*.bug' | \
	while read bug
	do
		log="${bug%.bug}.log"
		if [ ! -f "$log" ]; then
			rm -f "$bug"
		fi
	done

	#
	# remove all *.kpr files if rechecking is requested
	#
	if [ "$1" = "--recheck" ]; then
		rm -f pass/*.kpr bugged/*.kpr affected/*.kpr fail/*.kpr
	elif [ "$1" = "--recheck-failed" ]; then
		rm -f bugged/*.kpr affected/*.kpr fail/*.kpr
	fi

	#
	# remove outdated *.kpr files
	#
	>$LOGS
	find pass bugged affected fail -name '*.kpr' | \
	while read kpr
	do
		log="${kpr%.kpr}.log"
		if [ ! -f "$log" ] || [ "$log" -nt "$kpr" ]; then
			echo "$kpr" >> $LOGS
			rm -f "$kpr"
		fi
	done
	REMOVED=$(wc -l $LOGS | awk '{ print $1 }')

	#
	# build missing *.kpr files
	#
	>$LOGS
	find pass bugged affected fail -name '*.log' | \
	while read log
	do
		kpr="${log%.log}.kpr"
		if [ ! -f "$kpr" ]; then
			> "$kpr"
			echo "$kpr" >> $LOGS
			dir="${log%%/*}"
			for problem in $PROBLEMS
			do
				# source files to get COMMAND, WHERE
				. $PROBLEMDIR/$problem
				for where in $WHERE
				do
					if [ "$dir" = "$where" ]; then
						RESULT=$(cat "$log" | eval "$COMMAND")
						if [ -n "$RESULT" ]; then
							echo "$log $problem" >> "$kpr"
						fi
					fi
				done
			done
		fi
	done
	ADDED=$(wc -l $LOGS | awk '{ print $1 }')

	echo "parsed logfiles: $REMOVED removed, $ADDED added"

	mkdir -p $HTDOCS/$SECTION
	find pass bugged affected fail -name '*.kpr' | xargs --no-run-if-empty cat > $ALLKPR
	cut -d' ' -f 2 $ALLKPR | sort | uniq -c
	ls -tr1 --color=none fail/*.log bugged/*.log affected/*.log pass/*.log 2>/dev/null > $LIST_ALL
	>$KNOWNLOGS
	#
	# loop through all known problems
	#
	for problem in $PROBLEMS
	do
		# source files to get COMMAND, HELPTEXT and ISSUE
		. $PROBLEMDIR/$problem
		grep " $problem" $ALLKPR | cut -d' ' -f1 | sort -u > $LOGS
		if [ -s $LOGS ] ; then
			OUTPUT=$HTDOCS/$SECTION/${problem%.conf}.tpl
			echo '<table class="righttable"><tr class="titlerow"><td class="titlecell">' > $OUTPUT
			echo "$HEADER in $SECTION" >> $OUTPUT
			echo '</td></tr><tr class="normalrow"><td class="contentcell2">' >> $OUTPUT
			echo "$HELPTEXT" >> $OUTPUT
                        echo "<p>The commandline to find these logs is: <pre>" >> $OUTPUT
			grep --color=never COMMAND ~/bin/known_problems/$problem |sed -e "s#| #| \\ \n  #g" >> $OUTPUT
			echo "</pre></p>" >> $OUTPUT
			echo '</td></tr><tr class="titlerow"><td class="alerttitlecell">Please file bugs!</td></tr></tr><tr class="normalrow"><td class="contentcell2" colspan="3">' >> $OUTPUT
			echo "<ul>" >> $OUTPUT
			COUNT=0
			for LOG in $(cat $LOGS|sort) ; do
				PACKAGE=${LOG##*/}
				PACKAGE=${PACKAGE%%_*}
				grep "/${PACKAGE}_" $LIST_ALL > $LIST_PKG
				LATEST=$(tail -n 1 $LIST_PKG | cut -d "/" -f1)
				if [ "${problem%_error.conf}_error.conf" = "$problem" ] ; then
					LATESTFAIL=$(grep -v ^pass/ $LIST_PKG | tail -n 1)
					if [ "$LATEST" != "pass" ] && [ "$LATESTFAIL" = "$LOG" ] ; then
						echo "<li><a href=\"$LOG\">$LOG</a>" >> $OUTPUT
						echo "    (<a href=\"http://bugs.debian.org/$PACKAGE?dist=unstable\" target=\"_blank\">BTS</a>)" >> $OUTPUT
						BUG=${LOG%.log}.bug
						test ! -s "$BUG" || cat "$BUG" >> $OUTPUT
						echo "</li>" >> $OUTPUT
						echo "$LOG" >> $KNOWNLOGS
						COUNT=$((COUNT+1))
					fi
				else
					# this is an issue, not an error
					LATESTSUCCESS=$(grep ^pass/ $LIST_PKG | tail -n 1)
					if [ "$LATEST" = "pass" ] && [ "$LATESTSUCCESS" = "$LOG" ] ; then
						echo "<li><a href=\"$LOG\">$LOG</a> (<a href=\"http://bugs.debian.org/$PACKAGE?dist=unstable\" target=\"_blank\">BTS</a>)</li>" >> $OUTPUT
						echo "$LOG" >> $KNOWNLOGS
						COUNT=$((COUNT+1))
					fi
				fi
			done
			echo "</ul>" >>$OUTPUT
			echo "<p>Affected packages in $SECTION: $COUNT</p></td></tr></table>" >> $OUTPUT
			test $COUNT -gt 0 || rm $OUTPUT
		fi
        done
	#
	# report unknown failures
	#
	find fail -name "*.log" > $LOGS
	grep -f $LOGS $KNOWNLOGS > $KNOWNFAILURES
	grep -v -f $KNOWNFAILURES $LOGS > $UNKNOWNLOGS
	if [ -s $UNKNOWNLOGS ] ; then
		OUTPUT=$HTDOCS/$SECTION/unknown_failures.tpl
		echo '<table class="righttable"><tr class="titlerow"><td class="titlecell">' > $OUTPUT
		echo "Packages with failures not yet well known detected in $SECTION" >> $OUTPUT
		echo '</td></tr><tr class="normalrow"><td class="contentcell2">' >> $OUTPUT
		echo "<p>Please investigate and improve detection of known error types!</p>" >> $OUTPUT
		echo '</td></tr><tr class="titlerow"><td class="alerttitlecell">Please file bugs!</td></tr></tr><tr class="normalrow"><td class="contentcell2" colspan="3">' >> $OUTPUT
		COUNT=0
		echo "<ul>" >> $OUTPUT
		for LOG in $(cat $UNKNOWNLOGS|sort) ; do
			PACKAGE=${LOG##*/}
			PACKAGE=${PACKAGE%%_*}
			grep "/${PACKAGE}_" $LIST_ALL > $LIST_PKG
			LATEST=$(tail -n 1 $LIST_PKG | cut -d "/" -f1)
			LATESTFAIL=$(grep -v ^pass/ $LIST_PKG | tail -n 1)
			if [ "$LATEST" != "pass" ] && [ "$LATESTFAIL" = "$LOG" ] ; then
				echo "<li><a href=\"$LOG\">$LOG</a>" >> $OUTPUT
				echo "    (<a href=\"http://bugs.debian.org/$PACKAGE?dist=unstable\" target=\"_blank\">BTS</a>)" >> $OUTPUT
				BUG=${LOG%.log}.bug
				test ! -s "$BUG" || cat "$BUG" >> $OUTPUT
				echo "</li>" >> $OUTPUT
				COUNT=$((COUNT+1))
			fi
		done
		echo "</ul>" >> $OUTPUT
		echo "<p>Affected packages in $SECTION: $COUNT</p></td></tr></table>" >> $OUTPUT
		test $COUNT -gt 0 || rm $OUTPUT
	fi
	cd "$OLDPWD"
done
rm $LOGS $ALLKPR $KNOWNLOGS $UNKNOWNLOGS $KNOWNFAILURES $LIST_ALL $LIST_PKG
date

