#! /bin/sh

tmp=/tmp/$$
status=1
prog=`basename $0`
SCRATCH_REMOVE=false
MOUNT_REMOVE=false

_cleanup()
{
    rm -f $tmp
    if $MOUNT_REMOVE
    then
	echo "$prog: Unmounting xfs workarea from $SCRATCH_MOUNT"
	sudo umount $SCRATCH_MOUNT
	MOUNT_REMOVE=false
    fi
    if $SCRATCH_REMOVE
    then
	echo "$prog: Removing $SCRATCH..."
	rm -rf $SCRATCH
	SCRATCH_REMOVE=false
    elif [ -d $SCRATCH ]
    then
	echo "$prog: $SCRATCH not removed"
    fi
}

trap "_cleanup; exit \$status" 0 1 2 15

_usage()
{
    cat << EOF
Usage: $prog [-c cmd_workarea] [-r] mangrove_workarea xfs_workarea scratch

Update XFS patches in mangrove to build the latest XFS bits against the
kernel referenced by mangrove.

Options:
-c                   xfs-cmds workarea, defaults to ~/isms/xfs-cmds
-r                   Reuse scratch directory and kernel source that is
		     already there

mangrove_workarea    Path to a mangrove workarea
xfs_workarea         Path to an xfs-linux workarea
scratch              Scratch directory for kernel source
EOF
    exit 1
}

CMD_WORKAREA=~/isms/xfs-cmds
SCRATCH_REUSE=false

while getopts "c:r" c
do
    case $c in
	c) CMD_WORKAREA=$OPTARG;;
	r) SCRATCH_REUSE=true;;
	\?) _usage
	    exit 1
	    break;;
    esac
done

shift `expr $OPTIND - 1`

if [ $# -ne 3 ]
then
    _usage
    exit 1
fi

MAN_WORKAREA=$1
XFS_WORKAREA=$2
SCRATCH=$3

MAN_KERNEL=
CMD_SKIP=$CMD_WORKAREA/xfsmisc/skip_mangrove
CMD_APPLY=$CMD_WORKAREA/xfsmisc/pq_apply_patches

# Check that a workarea is clean
_check_clean()
{
    cd $1
    export WORKAREA=`pwd`
    if ! p_list -c > $tmp.clean_list
    then
	echo "$prog: p_list failed on $1"
	return 1
    fi

    if [ -s $tmp.clean_list ]
    then
	echo "$prog: Modified files in $1. Aborting."
	return 1
    fi

    return 0
}

# Check that a workarea is really clean
_check_really_clean()
{
    _check_clean $1 || return 1

    cd $1
    export WORKAREA=`pwd`
    if ! p_check -w > $tmp.clean_check
    then
	echo "$prog: p_list failed on $1"
	return 1
    fi

    if [ -s $tmp.clean_check ]
    then
	echo "$prog: Non-ptools files in $1:"
	cat $tmp.clean_check
	echo -n "Remove? [y] "
	read ans
	if [ "X$ans" = "X" -o "X$ans" = "Xy" ]
	then
	    cat $tmp.clean_check | xargs rm
	else
	    echo "$prog: Non-ptools files in $1. Aborting."
	    return 1
	fi
     fi

     return 0
}

if [ ! -d $MAN_WORKAREA ]
then
    echo "$prog: Unable to find mangrove workarea ($MAN_WORKAREA)"
    exit 1
fi

cd $MAN_WORKAREA
MAN_WORKAREA=`pwd`
MAN_RPMSEARCH=linuxmeister/bin/rpmsearchpath
MAN_SERIES=$MAN_WORKAREA/sles10/kernel/patches/series.conf
MAN_PATCHES=$MAN_WORKAREA/sles10/kernel/patches/patches.enhancedxfs

_check_clean $MAN_WORKAREA || exit 1

if [ ! -r $MAN_SERIES ]
then
    echo "$prog: Unable to find mangrove series file ($MAN_SERIES)"
    exit 1
fi

if [ ! -d $MAN_PATCHES ]
then
    echo "$prog: Unable to find mangrove patches ($MAN_PATCHES)"
    exit 1
fi

if [ ! -d $XFS_WORKAREA ]
then
    echo "$prog: Unable to find xfs workarea ($XFS_WORKAREA)"
    exit 1
fi

cd $XFS_WORKAREA
XFS_WORKAREA=`pwd`

_check_really_clean $XFS_WORKAREA || exit 1

if [ ! -d $CMD_WORKAREA ]
then
    echo "$prog: Cannot open xfs-cmd workarea ($CMD_WORKAREA)"
    exit 1
fi

if [ ! -f $CMD_SKIP ]
then
    echo "$prog: Unable to open skip file ($CMD_SKIP)"
    exit 1
fi

if [ ! -x $CMD_APPLY ]
then
    echo "$prog: Unable to access apply cmd ($CMD_APPLY)"
    exit 1
fi

if ! $SCRATCH_REUSE
then

    if [ -d $SCRATCH ]
    then
	echo "$prog: Scratch directory already exists ($SCRATCH)"
	exit 1
    fi

    if ! mkdir $SCRATCH
    then
	echo "$prog: Unable to creatch scratch directory ($SCRATCH)"
	exit 1
    fi
    SCRATCH_REMOVE=true

    cd $MAN_WORKAREA

    if [ ! -x $MAN_RPMSEARCH ]
    then
	echo "$prog: Unable to find rpmsearchpath in mangrove"
	exit 1
    fi

    if $MAN_RPMSEARCH | tr ':' '\n' > $tmp.rpmsearch
    then
	:
    else
	echo "$prog: rpmsearchpath failed"
	exit 1
    fi

    MAN_KERNELSRC=
    touch $tmp.search

    # Try to identify the kernel src RPM
    for p in `cat $tmp.rpmsearch`
    do
	find $p | grep kernel-source | grep ia64.rpm >> $tmp.search
    done

    if [ -s $tmp.search ]
    then
	touch $tmp.out
	echo "Found these potential kernel source RPMs:"
	count=`awk -v out=$tmp.out < $tmp.search '
		    { printf("[%d] %s\n", NR, $0) >> out; }
    END		{ print NR }'`
	cat $tmp.out
	echo ""
	echo -n "Please select RPM [1-$count]: "
	read ans
	MAN_KERNELSRC=`awk -v ans=$ans < $tmp.search 'ans == NR { print }'`
    else
	echo "Did not find any potential kernel source RPMs"
    fi

    if [ "X$MAN_KERNELSRC" = "X" ]
    then
	echo -n "Please provide path to kernel source RPM: "
	read MAN_KERNELSRC
	if [ "X$MAN_KERNELSRC" = "X" ]
	then
	    echo "$prog: No kernel source RPM found. Aborting."
	    exit 1
	fi
    fi

    if [ ! -r $MAN_KERNELSRC ]
    then
	echo "$prog: Unable to open $MAN_KERNELSRC. Aborting."
	exit 1
    fi

    MAN_KERNELVER=`basename $MAN_KERNELSRC .ia64.rpm | sed -e 's/kernel-source-//'`

# Check the scratch area and try to determine the kernel version
else
    if [ ! -d $SCRATCH ]
    then
	echo "$prog: scratch directory does not exist ($SCRATCH)"
	exit 1
    fi

    if [ ! -d $SCRATCH/usr/src ]
    then
	echo "$prog: scratch directory does not appear to contain linux ($SCRATCH/usr/src)"
	exit 1
    fi

   if ! ls -1d $SCRATCH/usr/src/linux-* > $tmp.ver1
   then
	echo "$prog: scratch directory does not appear to contain linux source ($SCRATCH/usr/src/linux-\*)"
	exit 1
   fi

   if [ ! -s $tmp.ver1 ]
   then
	echo "$prog: scratch directory does not appear to contain linux source ($SCRATCH/usr/src/linux-\*)"
	exit 1
   fi

   basename `grep -v obj $tmp.ver1` | sed -e 's/linux-//' > $tmp.ver2
   MAN_KERNELVER=`cat $tmp.ver2`
   MAN_KERNELSRC="n/a"
fi

if [ "X$MAN_KERNELVER" = "X" ]
then
    echo "$prog: Unable to identify kernel version"
    exit 1
fi

SCRATCH_KERNEL=$SCRATCH/usr/src/linux-$MAN_KERNELVER
SCRATCH_ENHANCED=$SCRATCH/usr/src/enhanced

if [ -d $SCRATCH_KERNEL/patches ]
then
    echo "$prog: Quilt patches may have been applied to scratch area ($SCRATCH_KERNEL/patches), please remove"
    exit 1
fi

if [ -d $SCRATCH/usr/src/patches ]
then
    echo "$prog: Quilt patches may have been applied to scratch area, please remove"
    exit 1
fi

echo ""
echo "       Mangrove: $MAN_WORKAREA"
echo "            XFS: $XFS_WORKAREA"
echo "  Kernel Source: $MAN_KERNELSRC"
echo " Kernel Version: $MAN_KERNELVER"
echo "        Scratch: $SCRATCH"
echo " Scratch Kernel: $SCRATCH_KERNEL"
echo "Enhanced Kernel: $SCRATCH_KERNEL"
echo ""

echo -n "Proceed? [y] "
read ans

if [ "X$ans" != "X" -a "X$ans" != "Xy" ]
then
    exit 0
fi

if ! $SCRATCH_REUSE
then
    cd $SCRATCH
    echo ""
    echo "Unpacking kernel source..."
    if ! rpm2cpio - < $MAN_KERNELSRC | cpio -icdv 2>&1 > $tmp.cpio
    then
	echo "$prog: Unpack failed:"
	cat $tmp.cpio
	exit 1
    fi
    SCRATCH_REMOVE=false
fi

if [ ! -d $SCRATCH_KERNEL ]
then
    echo "$prog: Unable to find kernel source ($SCRATCH_KERNEL)"
    exit 1
fi

if [ ! -d $SCRATCH_ENHANCED ]
then
    echo ""
    echo "Copying kernel source to $SCRATCH_ENHANCED"
    if ! cp -r $SCRATCH_KERNEL $SCRATCH_ENHANCED
    then
	echo "$prog: Copy of kernel source failed"
	exit 1
    fi
fi

SCRATCH_MOUNT=$SCRATCH/usr/src/enhanced/fs/xfs
mount | fgrep $SCRATCH_MOUNT | fgrep $XFS_WORKAREA 2>&1 > $tmp.mount
if [ ! -s $tmp.mount ]
then
    echo ""
    echo "Mounting XFS workarea over kernel source copy..."
    if sudo mount -o rw,bind $XFS_WORKAREA $SCRATCH_MOUNT
    then
	MOUNT_REMOVE=true
    else
	echo "$prog: Failed to bind mount XFS workarea to $SCRATCH_MOUNT"
	exit 1
    fi
else
    echo ""
    echo "XFS workarea appears to be mounted over $SCRATCH_MOUNT, skipping mount"
fi

echo ""
echo "Generating diff..."
cd $SCRATCH/usr/src
if diff -X  $CMD_SKIP -Naur linux-$MAN_KERNELVER enhanced > $tmp.xfs_update 2>&1
then
    if [ -s $tmp.diff_err ]
    then
    	echo "$prog: Diff failed"
    else
	echo "$prog: No differences found! What the?"
    fi
    exit 1 
fi

diffstat $tmp.xfs_update

cd $SCRATCH_KERNEL

echo ""
echo "Importing patch..."
if ! quilt import -P xfs_tot_rollup.patch $tmp.xfs_update 2>&1 > $tmp.quilt_import
then
    echo "$prog: Quilt import failed"
    cat $tmp.quilt_import
    exit 1
fi

if ! quilt push 2>&1 > $tmp.quilt_push
then
    echo "$prog: Quilt push failed"
    cat $tmp.quilt_push
    exit 1
fi

echo ""
echo "Apply mangrove patches..."
grep enhancedxfs $MAN_SERIES \
| awk '{print $2}' \
| xargs -n 1 basename \
| grep -v xfs_tot_rollup \
> $tmp.patch_list

if [ ! -s $tmp.patch_list ]
then
    echo "$prog: Failed to list patches in mangrove"
    exit 1
fi

cd $SCRATCH_KERNEL
if ! $CMD_APPLY $MAN_PATCHES $tmp.patch_list
then
    echo "$prog: Unable to apply mangrove patches"
    exit 1
fi

echo ""
echo "Copy patches into mangrove workarea..."
export WORKAREA=$MAN_WORKAREA
cd $MAN_PATCHES
if ! p_modify xfs_* 2>&1 > $tmp.modify
then
    echo "$prog: modify old patches failed"
    cat $tmp.modify
    exit 1
fi

cp $SCRATCH_KERNEL/patches/xfs_* .

p_check -w > $tmp.extra
if [ -s $tmp.extra ]
then
    echo "$prog: Extra file(s) copies from scratch patch directory"
    cat $tmp.extra
    exit 1
fi

echo ""
echo "Done, following files were modified in $MAN_WORKAREA:"
cd $MAN_PATCHES
p_list -c

SCRATCH_REMOVE=true
status=0
