#! /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 $QUILT_DIR/scripts/patchfns ]
	then
		echo "Cannot read library $QUILT_DIR/scripts/patchfns" >&2
		exit 1
	fi
	. $QUILT_DIR/scripts/patchfns
fi

setup_colors

usage()
{
	printf $"Usage: quilt svn [-aqv] [patch|num]\n"
	if [ x$1 = x-h ]
	then
		printf $"
Commit patches to subversion.  Without options, the current patch
in the series file is applied, and then removed from the series.
If [num] is provided, commit the [num] patches starting from the
current one.  If [patch] is provided, commit all patches from the
current one to the named patch.

-a	Apply all patches from current one.

-q	Quiet operation.

-v	Verbose operation.
"
		exit 0
	else
		exit 1
	fi
}

interrupt()
{
	rollback_patch $1
	printf $"Interrupted by user; patch %s was not applied.\n" \
	       "$(print_patch $patch)" >&2
	exit 1
}

list_patches()
{
	local top=$(top_patch) n=0 patch
	if [ -n "$top" ]
	then
		echo $top
		patches_after $top
	else
		echo >&2 No current patch
		exit 1
	fi \
	| if [ -n "$opt_all" ]
	then
		cat
	else
		while read patch
		do
			if [ -n "$number" ]
			then
				if [ $n -eq $number ]
				then
					break
				fi
				n=$[$n+1]
			fi
			echo "$patch"
			if [ -z "$number" -a "$patch" = "$stop_at_patch" ]
			then
				break
			fi
		done
	fi
}

all_paths()
{
	# Read a list of files from stdin, and generate all paths leading
	# up to those
	while read path
	do
		while [ -n "$path" ]
		do
			echo $path
			newpath=${path%/*}
			if [ "$newpath" = "$path" ]
			then
				newpath=
			fi
			path="$newpath"
		done
	done
}

apply_patch()
{
	# Get the patch file
	local patch=$1
	local patch_file=$(patch_file_name $patch)

	# Get the header
	[ -e "$patch_file" ] || exit 0

	cat_file "$patch_file" \
		| patch_header > svn.commit

	# Get the list of files to modify and check that they're all in svn
	for file in $(files_in_patch $patch | all_paths | sort | uniq)
	do
		if ! svn add -q $file
		then
			echo >&2 Failed to add $file to svn control
			exit 1
		fi
	done

	# Pop the top patch (the one to commit)
	if ! quilt pop
	then
		exit $?
	fi

	# Apply the patch outside quilt
	cat_file "$patch_file" \
		| patch -p1

	# Check in the changes
	if ! svn ci -F svn.commit
	then
		exit $?
	fi

	# Remove the patch from the patch stack
	if remove_from_series "$patch"
	then
		printf $"Removed patch %s\n" "$(print_patch "$patch")"
	else
		printf $"Failed to remove patch %s\n" "$(print_patch "$patch")" >&2
		exit 1
	fi

	if ! quilt push
	then
		exit $?
	fi

	# Clean up
	rm svn.commit
}

options=`getopt -o qvh -- "$@"`

if [ $? -ne 0 ]
then
        usage
fi

eval set -- "$options"

while true
do
  case "$1" in
	  -q)
		  opt_quiet=1
		  shift ;;
	  -v)
		  opt_verbose=1
		  shift ;;
	  -a)
		  opt_all=1
		  shift ;;
	  -h)
		  usage -h ;;
	  --)
		  shift
		  break ;;
  esac
done

if [ $# -gt 1 -o \( -n "$opt_all" -a $# -ne 0 \) ]
then
	usage
fi

if [ $# -eq 1 ]
then
	if is_numeric $1
	then
		number=$1
	else
		stop_at_patch="$1"
	fi
else
	[ -z "$opt_all" ] && number=1
fi

if [ -n "$stop_at_patch" ]
then
	stop_at_patch=$(find_unapplied_patch "$stop_at_patch") || exit $?
fi

[ -n "$opt_quiet" ] && silent=-s
[ -z "$opt_verbose" ] && silent_unless_verbose=-s

# Get the list of patches to apply (including current)
patches=$(list_patches)
for patch in $patches
do
  [ -n "$opt_verbose" ] && echo "Processing patch $patch"
  if ! apply_patch "$patch"
	  then
	  echo >&2 Patch FAIL $?
	  exit 1
  fi
done

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