#!/bin/sh

# Put in software-suspend-2.0.0.XX-for-2.X.X/ directory.
# See usage below. Path to patches are extracted from $0

usage() {
	cat <<EOT
Usage:
   apply [path to patches]

   apply -R [path to patches]
    or
   unapply [path to patches]

The current directory _must_ be the kernel source tree you wish to patch.
The script must be able to find the path to the patches somehow. This can be
achieved by specifying the full path to apply, eg:

   /path/to/software-suspend-directory/apply

or, by specifying it as a parameter.

   apply /path/to/patches

EOT
	exit 1
}

prompt_no() {
	echo -n "$1 [yN]? "
	read REPLY || exit 1
	case $REPLY in [Yy]*) return 0 ;; esac
	return 1
}

prompt_yes() {
	echo -n "$1 [Yn]? "
	read REPLY || exit 1
	case $REPLY in [Nn]*) return 1 ;; esac
	return 0
}

apply_patch() {
	patch -p1 -s -f --dry-run < "$1" > /dev/null 2>&1
	[ $? -ne 0 ] && return 1
	patch -p1 -s < "$1"
	[ $? -ne 0 ] && return 2
	return 0
}

reverse_patch() {
	patch -p1 -s -f -R --dry-run < $1 > /dev/null 2>&1
	[ $? -ne 0 ] && return 1
	patch -p1 -s -R < $1
	[ $? -ne 0 ] && return 2
	return 0
}

reverse_patches() {
	REVERSED=""
	for i in $PATCH_DIR/[0-9]* ; do
		REVERSED="$i $REVERSED"
	done
	for i in $REVERSED ; do 
		i=${i##$PATCH_DIR/}
		echo -n "Reversing $i ... "
		reverse_patch $PATCH_DIR/$i
		ret=$?
		if [ $ret -eq 1 ] ; then
			echo "(skipped)"
		elif [ $ret -eq 2 ] ; then
			echo
			echo "Eeep! Patch $i was supposed to reverse cleanly but didn't!"
			prompt_no "Do you wish to continue reversing more patches" || return 1
		else
			echo
		fi
	done
	exit 0
}

UNAPPLY=
[ "`basename $0`" = "unapply" ] && UNAPPLY=1

case "x$1" in
	x-R)
		UNAPPLY=1
		shift
		;;
	x-h|x--help)
		usage
		;;
esac

PATCH_DIR=$1
[ -z "$PATCH_DIR" ] && PATCH_DIR=`dirname $0`
if [ ! -d "$PATCH_DIR" ] ; then
	echo "Error: Patch directory $PATCH_DIR is not a valid directory."
	usage
fi

# Check we're in something resembling a kernel tree
if ! [ -f Makefile -a -d kernel ] ; then
	echo "Current directory doesn't look like a kernel tree. Aborting."
	exit 1
fi

# If we're in reversal mode.
if [ -n "$UNAPPLY" ] ; then
	reverse_patches
	exit
fi

APPLIED_PATCHES=""
bugger=
for i in $PATCH_DIR/[0-9]* ; do
	name=${i##$PATCH_DIR/}

	echo "Applying $name ..."
	apply_patch $i
	ret=$?
	if [ $ret -eq 1 ] ; then
		prompt_yes "$name will not apply cleanly. Reverse applied patches" || exit 1
		bugger=1
		break
	elif [ $ret -eq 2 ] ; then
		echo "Eeep! Patch $name was supposed to apply cleanly but didn't!"
		echo "Stopping right now. The patches that did successfully apply were:"
		for i in $APPLIED_PATCHES ; do echo $i ; done
		exit 2
	fi
	APPLIED_PATCHES="$name $APPLIED_PATCHES"
done

if [ -n "$bugger" ] ; then
	echo "Reversing patches..."
	for i in $APPLIED_PATCHES ; do
		echo "Reversing $i"
		reverse_patch $PATCH_DIR/$i
		if [ $? -ne 0 ] ; then
			echo "Argh! Reversing failed. I don't know what's going on. Aborting now."
			exit 2
		fi
	done
	echo "Done."
else
	echo "All happy!"
fi

