#! /usr/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()
{
	printf $"Usage: quilt annotate {file}\n"
	if [ x$1 = x-h ]
	then
		printf $"
Print an annotated listing of the specified file showing which
patches modify which lines.
"
		exit 0
	else
		exit 1
	fi
}

empty_file()
{
	local patch=$1 file=$2
	local backup_file=$(backup_file_name $patch $file)
	[ -s "$backup_file" ] \
	&& sed -e 's:.*::' "$backup_file"
}

annotation_for()
{
	local patch=$1 next_patch=$2 file=$3 annotation=$4
	local old_file=$(backup_file_name $patch "$file") new_file
	[ -s "$old_file" ] || old_file=/dev/null
        if [ -z "$next_patch" ]
        then
                new_file="$file"
        else
                new_file="$(backup_file_name $next_patch $file)"
		[ -s "$new_file" ] || new_file=/dev/null
        fi
	/usr/bin/diff -Ne "$old_file" "$new_file" \
	| /usr/bin/perl -e '
	while (<>) {
	    if (/^\d+(?:,\d+)?[ac]$/) {
		print;
		while (<>) {
		    last if /^\.$/;
		    print "'"$annotation"'\n";
		}
		print;
		next;
	    }
	    print;
	}
	'
}

merge_files()
{
	local a b saved_IFS="$IFS"
	local template=$1 file=$2

	[ -e "$file" ] || file=/dev/null

	exec 3< "$template"
	exec 4< "$file"
	IFS=
	while read -r a <&3
	do
		read -r b <&4
		echo "$a"$'\t'"$b"
	done
	IFS="$saved_IFS"
	exec 3<&-
	exec 4<&-
}

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

if [ $? -ne 0 ]
then
	usage
fi

eval set -- "$options"

while true
do
	case "$1" in
	-h)
		usage -h ;;
	--)
		shift
		break ;;
	esac
done

if [ $# -ne 1 ]
then
	usage
fi
opt_file="$SUBDIR$1"

for patch in $(cat_series); do
	if [ -f "$(backup_file_name $patch "$opt_file")" ]
	then
		patches[${#patches[@]}]="$patch"
	fi
done

if [ ${#patches[@]} = 0 ]
then
	sed -e 's:^:'$'\t'':' "$opt_file"
	exit 0
fi

template=$(gen_tempfile)

trap "rm -f $template" EXIT

# The annotated listing is generated as follows: A file of annotations
# is created based on a file that contains the same number of lines as
# the source file, but all lines are empty.
#
# Then, for each patch that modifies the source file, an ed-style diff
# (which has no context, and removes lines that are removed without
# caring for the line's contents) is generated. In that diff, all line
# additions are replaced with the identifier of the patch (1, 2, ...).
# These patches are then applied to the empty file. 
#
# Finally, the annotations listing is merged with the source file line
# by line.

empty_file ${patches[0]} "$opt_file" > $template
for ((n = 0; n < ${#patches[@]}; n++))
do
	annotation_for "${patches[$n]}" "${patches[$((n+1))]}" "$opt_file" \
		       $((n+1))
done \
| /usr/bin/patch $template
merge_files $template "$opt_file"

echo
for ((n = 0; n < ${#patches[@]}; n++))
do
	echo "$((n+1))"$'\t'"$(print_patch ${patches[$n]})"
done

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