#! /bin/sh

tmp=/tmp/$$
prog=`basename $0`
status=1

_usage()
{
    cat << EOF
Usage: $prog [-nq] [-a dir] [-p level] [-Q quilt] patch

Apply a patch to a ptools tree.

-a dir     Adjust patch from this subdirectory
           (shift an xfs-linux patch to a linux patch by using
            fs/xfs as the argument)
-n         List files that would have been modified, but do
           not actually apply the patch.
-p level   Patch level
-q         Create a quilt patch of the same name
-Q quilt   Create a quilt patch of this name
EOF
    exit 1
}

_cleanup()
{
    if $quilt_remove
    then
	quilt delete $base
	quilt_remove=false
    fi
    rm -f $tmp.*
}

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

quilt=false
quilt_remove=false
level=""
base=""
oldtop="."
adjust=false
here=`pwd`
dryrun=false

while getopts "a:np:qQ:" c
do
    case $c in
	a) adjust=true; oldtop=$OPTARG;;
        n) dryrun=true;;
	p) level="-p $OPTARG";;
	q) quilt=true;;
	Q) quilt=true; base=$OPTARG;;
	\?) _usage
	    exit 1
	    break;;
    esac
done

shift `expr $OPTIND - 1`

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

if $dryrun
then
    quilt=false;
fi

patch=$1
if [ "X$base" = "X" ]
then
    base=`basename $patch .patch`
fi

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

if $adjust
then
    if [ ! -d $oldtop ]
    then
	echo "$prog: Unable to find subdirectory $oldtop"
	exit 1
    fi
fi

if $quilt
then
    if quilt --version > /dev/null 2>&1
    then
	:
    else
	echo "$prog: quilt is not available"
	exit 1
    fi

    if quilt applied > $tmp.qa 2> /dev/null
    then
	mv $tmp.qa $tmp.exist
    else
	touch $tmp.exist
    fi
    if quilt unapplied > $tmp.qu 2> /dev/null
    then
	cat $tmp.qu >> $tmp.exist
    fi

    if [ -s $tmp.exist ]
    then
	echo $base | join - $tmp.exist > $tmp.join
	if [ -s $tmp.join ]
	then
	    echo "$prog: Quilt patch $base already exists"
	    exit 1
	fi
    fi

    echo ""
    echo "Create quilt patch $base..."
    if quilt new $base
    then
	quilt_remove=true
    else
	echo "$prog: Unable to create quilt patch $base"
	exit 1
    fi
fi

echo ""
echo "Testing patch $patch..."
cd $oldtop
if patch --dry-run $level < $patch > $tmp.err 2>&1
then
    echo "...patch tested successfully."
else
    echo "$prog: Patch does not apply:"
    cat $tmp.err
    exit 1
fi
cd $here

sed -e '/^Hunk #/d' < $tmp.err \
| awk -v oldtop=$oldtop '{print oldtop "/" $NF}' \
| sort > $tmp.files

if [ -s $tmp.files ]
then
    :
else
    echo "$prog: No files found in $patch"
    exit 1
fi

if $quilt
then
    echo ""
    echo "Adding files to quilt patch..."
fi

touch $tmp.mod $tmp.fetal
cat $tmp.files | while read f
do
    if [ -f $f ]
    then
	echo $f >> $tmp.mod
    else
	echo $f >> $tmp.fetal
    fi
    $quilt && quilt add $f
done

if $dryrun
then
    echo ""
    echo "Files to be modified:"
    cat $tmp.mod
    echo ""
    echo "New files:"
    cat $tmp.fetal 
    status=0
    exit 0
fi

if [ -s $tmp.mod ]
then
    cat $tmp.mod | p_state -i | grep trunk \
    | awk '{print $1}' > $tmp.trunk
    if [ -s $tmp.trunk ]
    then
	echo ""
	echo "Modifying:"
	cat $tmp.trunk | p_modify -i
    fi
fi

echo ""
echo "Applying patch $patch..."
cd $oldtop
if patch $level < $patch
then
    :
else
    echo "$prog: Patch did not apply"
    exit 1
fi
cd $here

if [ -s $tmp.fetal ]
then
    echo ""
    echo "Marking new files fetal..."
    cat $tmp.fetal | p_fetal -i 
fi

if $quilt
then
    echo ""
    echo "Refreshing quilt patch $base..."
    if quilt refresh
    then
	quilt_remove=false
    else
	echo "$prog: Unable to refresh quilt patch $base"
	exit 1
    fi
fi

status=0
