#!/bin/bash
#
# --- ROCK-COPYRIGHT-NOTE-BEGIN ---
# 
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
# Please add additional copyright information _after_ the line containing
# the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
# the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
# 
# ROCK Linux: rock-src/scripts/Create-ErrList
# ROCK Linux is Copyright (C) 1998 - 2004 Clifford Wolf
# 
# 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. A copy of the GNU General Public
# License can be found at Documentation/COPYING.
# 
# Many people helped and are helping developing ROCK Linux. Please
# have a look at http://www.rocklinux.org/ and the Documentation/TEAM
# file for details.
# 
# --- ROCK-COPYRIGHT-NOTE-END ---

config=default
repstat=0
showerr=0
showtree=0
showdepc=0
delete=0
remove=0
fulldelete=0
newdelete=0
dryrun=0
onlyupdated=0

repository=""
stages="[0123456789]"
copydir=""
movedir=""
logdir=""

while [ "$1" ] ; do
        case "$1" in
	    -cfg)
		config=$2     ; shift ; shift ;;

	    -repstat)
		repstat=1     ; shift ;;

	    -showerr)
		showerr=1     ; shift ;;

	    -showtree)
		showtree=1    ; shift ;;

	    -showdepc)
		showdepc=1    ; shift ;;

	    -repository)
		if [ $2 != '!' ] ; then
			repository=" $2 " ; shift ; shift
			while [ "$1" -a -d "package/$1" ] ; do
				repository="$repository $1 " ; shift
			done
		else
			shift ; shift ; repository=""
			for x in $( ls package/ ) ; do
				[ -d "package/$x" ] &&
					repository="$repository $x"
			done
			repository="$repository "
			while [ "$1" -a -d "package/$1" ] ; do
				repository="${repository// $1 / }" ; shift
			done
		fi
		;;

	    -stage)
		stages="[$2]" ; shift ; shift ;;

	    -logdir)
		logdir=$2     ; shift ; shift ;;

	    -copydir)
		copydir=$2    ; shift ; shift ;;

	    -movedir)
		movedir=$2    ; shift ; shift ;;

	    -delete)
		delete=1      ; shift ;;

	    -remove)
		remove=1      ; shift ;;

	    -fulldelete)
		fulldelete=1  ; shift ;;

	    -dry-run)
	        dryrun=1     ; shift ;;

	    -newdelete)
		newdelete=1  ; shift ;;

	    -updated)
		onlyupdated=1 ; shift ;;

	    -*)
x="${0//?/ }" ; x="${x#         }"
echo "Usage: $0 [ -newdelete ] [ -dry-run ]"
echo "       $0 [ -repstat ]"
echo "       $0 [ -[full]delete ] [ -remove ] <package(s)>"
echo "       $0 [ -cfg <config> ] [ -dry-run ] \\"
echo "  $x [ -repository <repositories> ] [ -copydir <copydir> ] \\" 
echo "  $x [ -movedir <movedir> ] [ -logdir <logdir> ] \\"
echo "  $x [ -stage <stage(s)> ] [ -[full]delete ] \\"
echo "  $x [ -updated ] [ -showdepc ] [ -showerr [ -showtree ] ]"
echo 
echo " Create summaries of package builds, print statistics or schedule packages"
echo " for a rebuild"
echo
echo "	-newdelete		schedule updated packages for a rebuild"
echo "	-dry-run		don't delete anything; just print what"
echo "				would happen"
echo "	-repstat		print some build statistics on repositories"
echo "	-delete			delete logs of failed builds"
echo "				(for given packages)"
echo "	-fulldelete		delete all build logs and log directory entries"
echo "				(for given packages)"
echo "	-remove			schedule given packages for a rebuild"
echo "	-cfg <config>		check this target build for errors;"
echo "				defaults to 'default'"
echo "	-repository <repositories>	check only packages from the given"
echo "					repositories"
echo "	-copydir <copydir>	copy logs of failed builds to this directory"
echo "	-movedir <movedir>	move logs of failed builds to this directory"
echo "	-logdir <logdir>	the log directory to use; defaults to "
echo "				build/<ROCKCFG-ID>/var/adm/logs"
echo "	-stage <stage>		process package builds from the given stages;"
echo "				defaults to '0123456789' (all stages)"
echo "	-updated		process updated instead of failed packages"
echo "	-showerr		show the last build log lines for each"
echo "				processed package"
echo "	-showtree		show a dependency tree"
echo "	-showdepc		show the number of packages that depend on a"
echo "				processed package"
echo
echo " If packages are given without additional options, logs of failed builds are"
echo " opened with 'less'."
echo
		exit 1 ;;

	    *)
		break ;;
        esac
done

. scripts/parse-config

logdir="${logdir:-build/$ROCKCFG_ID/var/adm/logs}"
pkgdir="${logdir%/*}/packages"

if [ "$newdelete" = 1 ]; then
	while read xpkg cksum1
	do
		if [ ! -f package/*/$xpkg/$xpkg.desc ]; then
		    pkg="`grep "=$xpkg " config/$config/packages \
			| awk '{ print $5; }'`"
		    pkg="${pkg%=*}"
		else
		    pkg=$xpkg
		fi
		    
		cksum2=$( md5sum package/*/$pkg/* 2> /dev/null | \
			  grep -v '\.cache$' | md5sum | cut -f1 -d' ' )
		if [ "$cksum1" != "$cksum2" ]; then
			echo "Scheduling package '$xpkg' for rebuild ..."
			if [ "$dryrun" = 0 ]; then
			    mine -rf -R build/$ROCKCFG_ID $xpkg
			    rm -f build/$ROCKCFG_ID/var/adm/*/?-$xpkg.*
			fi
		fi
	done < <(
		grep -R '^ROCK Linux Package Source Checksum: ' \
		     build/$ROCKCFG_ID/var/adm/packages |
		tr '/:' '  ' | cut -f6,13 -d' '
	)
	exit 0
fi

if [ "$repstat" = 1 ] ; then
    {
	echo
	echo -e "Repository\tPkg Total\tPkg OK\tPkg Error"
	echo
	total_pkgt=0 ; total_pkgo=0 ; total_pkge=0
	for x in $( cd package ; echo [a-z0-9]* ) ; do
		pkgt=0 ; pkgo=0 ; pkge=0
		for y in $( cd package/$x ; echo [a-z0-9]* ) ; do
			if [ "$( ls $logdir/$stages-$y.err 2> /dev/null )" ]
				then (( pkge++ )) ; (( total_pkge++ ))
			elif [ "$( ls $logdir/$stages-$y.log 2> /dev/null )" ]
				then (( pkgo++ )) ; (( total_pkgo++ ))
			fi
		done
		(( pkgt = pkgo + pkge )) ; (( total_pkgt += pkgt ))
		[ $pkgt != 0 ] && echo -e "$x\t$pkgt\t$pkgo\t$pkge"
	done
	echo
	echo -e "total\t$total_pkgt\t$total_pkgo\t$total_pkge"
	echo
    } | {
	expand -t20,35,50 | sed 's,^,      ,'
    }
    exit 0
fi

if [ "$1" ] ; then
	if [ "$fulldelete" = 1 ] ; then
		for x ; do
			rm -vf "$logdir"/$stages-$x.{err,log,out}
			rm -vf "$logdir"/../*/$x
		done
	elif [ "$remove" = 1 ] ; then
		for x ; do  
			echo "Scheduling package '$x' for rebuild ..."
			mine -rf -R build/$ROCKCFG_ID $x
			rm -f build/$ROCKCFG_ID/var/adm/*/?-$x.*
		done
	elif [ "$delete" = 1 ] ; then
		for x ; do rm -vf "$logdir"/$stages-$x.err ; done
	else
		for x ; do less "$logdir"/$stages-$x.err ; done
	fi
	exit 0
fi

echo
echo "Error logs from $ROCKCFG_ID:"
[ $showerr = 0 ] && echo

count_pkg=0
count_err=0
count_log=0

for stagelevel in $( echo $stages | tr -d '[]' | sed 's,.,& ,g' ) ; do
	while read x x x tree pkg x ; do

		# strip base package name
		pkg="${pkg#*=}"

		[ "$repository" -a \
			"${repository/ $tree /}" = "$repository" ] && continue

		this_is_error=0
		if [ $onlyupdated != 0 ] ; then
			[ "$( bash scripts/xfind.sh package/*/$pkg -newer "$logdir/$stagelevel-$pkg.err" -o -newer "$logdir/$stagelevel-$pkg.log" )" ] && this_is_error=1
		elif [ -f "$logdir/$stagelevel-$pkg.err" ] ; then
			this_is_error=1
		fi

		if [ $this_is_error = 1 ] ; then
			if [ $showerr = 0 ] ; then
				if [ $showdepc != 0 ]; then
					d=$( ./scripts/Check-Deps-3 $stagelevel \
						$pkg config/$config/packages | \
						cut -f3 -d' ' | sort -u | wc -l )
					d="$( printf " %3d" $d )"
				else
					d=""
				fi
				echo "[$stagelevel]$d ${tree:0:13}/${pkg:0:18}"
			else
			  echo ; echo "== $stagelevel-$pkg.* =="
			  tail -n 20 "$logdir/$stagelevel-$pkg".* | \
			  tac | perl -e '
			    my @lines;
			    my $counter;
			    while (<>) {
				chomp;
				$lines[$#lines+1] = $_;
			    }
			    for ($counter=0; $counter <= $#lines; $counter++) {
				$_=$lines[$counter];
				if ( /^checking for .*\.\.\. *Package / ||
				     /configure: error:/ ) {
					for ($_=1; $_ <= $counter; $_++) {
						print "$lines[$_]\n";
					}
					exit 0;
				}
			    }
			    for ($counter=0; $counter <= $#lines; $counter++) {
				$_=$lines[$counter];
				if ( /^(make\S*): / ) {
					my $makeprefix=$1;
					my $output="$_\n";
					while ( defined
						    ($_=$lines[$counter++]) ) {
						last unless /^(make\S*): /;
						$output="" if $1 ne $makeprefix;
						$makeprefix=$1;
						$output.="$_\n";
					}
					print $output; exit 0;
				}
			    }
			    foreach (@lines) {
				print "$_\n";
			    }
			  ' | tac | fold -s -w79
			  depcheck() {
				echo "${1}\`---> $3"
				for x in `grep -lwi $3 $logdir/*.err | \
					sed 's,.*/.-,,; s,\.err,,' | sort -u`
				do
					[ "$x" = "$3" ] && continue
					[ "${2/ $x /}" != "$2" ] && continue
					depcheck "${1}  " "$2 $3 " $x
				done
			  }
			  [ $showtree = 1 ] && depcheck "" "" $pkg
			fi
			if [ "$copydir" ] ; then
				mkdir -p "$copydir"
				cp "$logdir/$stagelevel-$pkg.err" "$copydir"
			fi
			if [ "$movedir" ] ; then
				mkdir -p "$movedir"
				mv "$logdir/$stagelevel-$pkg.err" "$movedir"
			fi
			if [ "$fulldelete" -eq 1 ] ; then
				rm -f "$logdir"/$stages-$pkg.{err,log,out}
				rm -f "$logdir"/../*/$pkg
			elif [ "$delete" -eq 1 ] ; then
				rm -f "$logdir/$stagelevel-$pkg.err"
			fi
			count_err=$(( $count_err + 1 ))
		elif [ -f "$logdir/$stagelevel-$pkg.log" ] ; then
			count_log=$(( $count_log + 1 ))
		fi
		count_pkg=$(( $count_pkg + 1 ))
	done < <( grep "^X [0-9-]*$stagelevel" config/$config/packages )
done > >(
	if [ $showerr = 0 ] ; then
		paste - - | expand -t40 | sed 's,^, ,'
	else cat ; fi
)

sleep 1
echo
echo "$count_pkg builds total, $count_log completed fine," \
     "$count_err with errors."
echo