#! /bin/sh -e
# Update trivial page.

KDIR=~/devel/kernel
TRIVIALDIR=$KDIR/trivial

KERNELS="2.4 2.6"

cd ~/devel/kernel/www/trivial/

TMPFILES=""
trap 'rm -rf $TMPFILES *.tmp' 0
#trap 'echo rm -rf $TMPFILES *.tmp >&2' 0

# Patch didn't apply: figure out possible conflicts.
diagnose()
{
    echo "Patch conflict for $1 $2" >&2
    if [ -f "$2"/Conflicts ]; then return; fi
    DIAG_FILES=$(grep '^+++ ' < "$2"/Patch | sed -e 's:[^/]*/::' -e 's/[	 ].*//')
    echo "It touches $DIAG_FILES" >&2
    for d in $TRIVIALDIR/*; do
	if [ -f "$d"/Closed -o -f "$d"/$1-failed -o -f "$d"/$1-included ]; then
	    :
	elif fgrep -q -- $1 "$d"/Versions; then
	    # It's a candidate, does it patch same files?
	    for DIAG_F in $DIAG_FILES; do
		if fgrep -q -- $DIAG_F "$d"/Patch; then
		    echo Possibly from: "$d" >&2
		    echo "$d" >> "$2"/Conflicts
		fi
	    done
	fi
    done
}

# Create a giant patch for the given major kernel
create_patch()
{
    CP_MASTER=$KDIR/linux-$2
    CP_WORKING=$KDIR/.$$.trivial
    CP_TMPFILES="$TMPFILES"
    TMPFILES="$TMPFILES $CP_WORKING"
    cp -al $CP_MASTER $CP_WORKING

    for d in $TRIVIALDIR/*; do
	# If not closed, apply it.
	if [ -f "$d"/Closed -o -f "$d"/$1-failed -o -f "$d"/$1-included ]; then
	    :
	elif fgrep -q -- $1 "$d"/Versions; then
	    lkpatch --ignore-whitespace $CP_WORKING "$d"/Patch || diagnose "$1" "$d"
	fi
    done
    (cd $KDIR && kerndiff `basename $CP_MASTER` `basename $CP_WORKING`)
    rm -rf $CP_WORKING
    TMPFILES="$CP_TMPFILES"
}

# Create a table showing which patches applied where
create_table()
{
    for d in $TRIVIALDIR/*; do
	if [ x"$(find "$d" -name Closed -mtime +7)" = x ]; then
	    CT_BASE=`basename "$d" | tr '	' ' '`
	    # xxx-failed or xxx-included.
	    for CT_VER; do
		if [ -f "$d/$CT_VER"-failed ]; then
		    CT_STATUSFILE=`echo $CT_BASE | tr -c '[A-Za-z0-9_.]' _`.status
		    CT_STATUS="<a href=\"$CT_STATUSFILE\">FAILED</a>"
		    cp "$d/$CT_VER"-failed $CT_STATUSFILE.tmp
		elif [ -f "$d/$CT_VER"-included ]; then
		    CT_STATUSFILE=`echo $CT_BASE | tr -c '[A-Za-z0-9_.]' _`.status
		    CT_STATUS="<a href=\"$CT_STATUSFILE\">INCLUDED</a>"
		    cp "$d/$CT_VER"-included $CT_STATUSFILE.tmp
		elif [ -f "$d/Conflicts" ]; then
		    if fgrep -q -- $CT_VER "$d"/Versions; then
			CT_STATUS="CONFLICTS/PENDING"
		    else
			CT_STATUS="-"
		    fi
		else
		    if fgrep -q -- $CT_VER "$d"/Versions; then
			CT_STATUS="PENDING"
		    else
			CT_STATUS="-"
		    fi
		fi
		echo "$CT_BASE	$CT_STATUS" >> trivial-table-$CT_VER.tmp
	    done
	fi
    done
}

# Clean up the author field
massage_author()
{
    echo "$@" | tr -d \" | sed 's/.*(\([^)]*\))/\1/' | sed 's/@/ from /'
}

TMPFILE=`mktemp`
TMPFILES="$TMPFILES $TMPFILE"

for VER in $KERNELS; do
    LATEST_VER=`latest-kernel-version $VER`
    # Create megapatch
    echo "Trivial patch collection for $LATEST_VER `date -u`" > $TMPFILE
    echo Creating megapatch for $LATEST_VER...
    create_patch $VER $LATEST_VER >> $TMPFILE
    gzip -9 < $TMPFILE > trivial-patch-$VER.gz.tmp
done

# Create table.
echo Creating tables for $KERNELS...
create_table $KERNELS

echo Creating web page...

# Start web page
LINE=$(fgrep -xn '<!-- table-here -->' template-index.html | cut -d: -f1)
# Prepend...
head -$(($LINE - 1)) template-index.html > trivial-table.tmp

for VER in $KERNELS; do
    echo "<td><strong>`latest-kernel-version $VER`</strong></td>" >> trivial-table.tmp
done

# Do a join and create web page
# FIXME: Make this a generic iterative join.
join -t'	' trivial-table-2.4.tmp trivial-table-2.6.tmp |
    while IFS='	' read TITLE STATE24 STATE25; do
	# Split author and subject (first colon)
	AUTHOR=`echo $TITLE | cut -d: -f1`
	SUBJECT=`echo $TITLE | cut -d: -f2-`
	echo "<tr><td>`massage_author $AUTHOR`</td>"
	echo "<td>$SUBJECT</td>"
	echo "<td>$STATE24</td>"
	echo "<td>$STATE25</td>"
	echo "</tr>"
    done >> trivial-table.tmp

# Append...
tail +$LINE template-index.html >> trivial-table.tmp

# Commit.
mv trivial-table.tmp index.html
for VER in $KERNELS; do mv trivial-patch-$VER.gz.tmp trivial-patch-$VER.gz; done
rm -f *.status
for f in *.status.tmp; do mv "$f" "$(basename "$f" .tmp)"; done

exit 0