#! /bin/bash

#  This script is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License version 2 as
#  published by the Free Software Foundation.
#
#  See the COPYING and AUTHORS files for more details.

# Read in library functions
if [ "$(type -t patch_file_name)" != function ]
then
	if ! [ -r /usr/share/quilt/scripts/patchfns ]
	then
		echo "Cannot read library /usr/share/quilt/scripts/patchfns" >&2
		exit 1
	fi
	. /usr/share/quilt/scripts/patchfns
fi

usage()
{
	echo $"Usage: $0 [-fqv] patchname"
	exit 1
}

interrupt()
{
	rollback_patch $1
	echo $"Interrupted by user; patch $patch was not applied."
	exit 1
}

apply_patch()
{
	local patch=$1
	local patch_file=$(patch_file_name $patch) output

	if ! [ -s $patch_file ]
	then
		echo $"Patch file $patch_file appears to be empty"
		return 0
	fi
	
	if [ "x${patch_file:(-3)}" = "x.gz" ]
	then
		gzip -cd $patch_file \
		| /usr/bin/patch $QUILT_PATCH_OPTS $(patch_args $patch) \
			--backup --prefix="$QUILT_PC/$patch/" \
			-E $silent $force_apply 2>&1
	elif [ "x${patch_file:(-4)}" = "x.bz2" ]
	then
		bzip2 -cd $patch_file \
		| /usr/bin/patch $QUILT_PATCH_OPTS $(patch_args $patch) \
			--backup --prefix="$QUILT_PC/$patch/" \
			-E $silent $force_apply 2>&1
	else
		/usr/bin/patch $QUILT_PATCH_OPTS $(patch_args $patch) \
			--backup --prefix="$QUILT_PC/$patch/" \
			-E $silent $force_apply -i $patch_file 2>&1
	fi
}

rollback_patch()
{
	local patch=$1 pc_file=$(gen_tempfile)

	# FIXME backup_files should scan the directory hierarchy itself.
	files_in_patch $patch > $pc_file
	/usr/lib/quilt/backup-files $silent_unless_verbose \
		-f $pc_file -B $QUILT_PC/$patch/ -r
	if [ -z "$opt_leave_rejects" ]
	then
		sed -e 's/$/\.rej/' $pc_file | xargs rm -f
	fi
	rm -f $pc_file
}

apatch()
{
	local patch=$(stripit $1)
	local file status

	echo $"Applying $patch"
	trap "interrupt $patch" SIGINT

	output="$(apply_patch $patch)"
	status=${PIPESTATUS[0]}

	trap "" SIGINT

	if [ $status -ne 0 -a -z "$opt_leave_rejects" ]
	then
		# The reject files are removed in rollback_patch.
		echo "$output" \
		| sed -e \
's/-- saving rejects to file \(.\+\)\.rej/-- rejects in file \1/'
	elif [ -n "$output" ]
	then
		echo "$output"
	fi

	if [ $status -eq 0 -o -n "$opt_force" ]
	then
		add_to_db $patch
		if [ $status -eq 0 ]
		then
			rm -f $QUILT_PC/$patch~refresh
		else
			touch $QUILT_PC/$patch~refresh
		fi
		
		if [ -e "$QUILT_PC/$patch" ]
		then
			touch $QUILT_PC/$patch/.timestamp
		fi

		if [ "$(shopt -s nullglob ; echo $QUILT_PC/$patch/*)" = "" ]
		then
			echo $"Patch $patch appears to be empty, applied"
		elif [ $status -ne 0 ]
		then
			echo $"Applied $patch (forced; needs refresh)"
		fi
	else
		rollback_patch $patch
		echo $"Patch $patch does not apply (enforce with -f)"
		status=1
	fi
	trap - SIGINT
	return $status
}

options=`getopt -o fqvh --long leave-rejects,interactive -- "$@"`

if [ $? -ne 0 ]
then
	usage
fi

eval set -- "$options"

while true
do
	case "$1" in
	-f)
		opt_force=1
		shift ;;
	-q)
		opt_quiet=1
		shift ;;
	-v)
		opt_verbose=1
		shift ;;
	--leave-rejects)
		opt_leave_rejects=1
		shift ;;
	--interactive)
		opt_interactive=1
		shift ;;
	-h)
		usage -h ;;
	--)
		shift
		break ;;
	esac
done

if [ $# -ne 1 ]
then
	usage
fi

[ -n "$opt_quiet" ] && silent=-s
[ -z "$opt_verbose" ] && silent_unless_verbose=-s
[ -z "$opt_interactive" ] && force_apply=-f
[ -n "$opt_force" ] && opt_leave_rejects=1

patch=$(stripit $1)

top=$(top_patch)
if [ -n "$top" -a -e $QUILT_PC/$top~refresh ]
then
	echo $"The topmost patch $top needs to be refreshed first."
	exit 1
fi

apatch $patch
### Local Variables:
### mode: shell-script
### End:
# vim:filetype=sh
