#!/usr/bin/env bash
#
# Make a patch from a given commit.
# Copyright (c) Petr Baudis, 2005
#
# Takes an -s option which specifies whether to print a short
# version of the patch without a patch header with meta info such
# as author and committer.
#
# Takes an -r followed with ID defaulting to HEAD, or id1:id2, forming
# a range (id1;id2]. (Use "id1:" to take just everything from id1 to HEAD.)

. ${COGITO_LIB}cg-Xlib

omit_header=
has_diffstat=
if [ "$1" = "-s" ]; then
	shift
	omit_header=1
else
	which diffstat >/dev/null 2>&1 && has_diffstat=1
fi

showpatch () {
	header=$(mktemp -t gitpatch.XXXXXX)
	patch=$(mktemp -t gitpatch.XXXXXX)
	id=$1
	cg-diff -p -r $id >$patch
	git-cat-file commit $id | while read key rest; do
		case "$key" in
		"author"|"committer")
			date=(${rest#*> })
			pdate="$(showdate $date)"
			if [ "$pdate" ]; then
				echo $key $rest | sed "s/>.*/> $pdate/" >>$header
			else
				echo $key $rest >>$header
			fi
			;;
		"")
			cat
			if [ ! "$omit_header" ]; then
				echo
				echo ---

				echo commit $id
				cat $header

				if [ "$has_diffstat" ]; then
					echo
					cat $patch | diffstat -p1
				fi
			fi
			;;
		*)
			echo $key $rest >>$header
			;;
		esac
	done
	echo
	cat $patch
	rm $header $patch
}


log_start=
log_end=
if [ "$1" = "-r" ]; then
	shift
	log_start="$1"
	shift
	if echo "$log_start" | grep -q ':'; then
		log_end=$(echo "$log_start" | cut -d : -f 2)
		log_start=$(echo "$log_start" | cut -d : -f 1)
	fi
fi
if [ "$1" = "-r" ]; then
	shift
	log_end="$1"
	shift
fi

if [ "$log_end" ]; then
	id1=$(commit-id $log_start) || exit 1
	id2=$(commit-id $log_end) || exit 1

	git-rev-tree $id2 ^$id1 | sort -n | while read time commit rest; do
		id=$(echo $commit | cut -d : -f 1)
		showpatch $id
		echo
		echo
		echo -e '\014'
		echo '!-------------------------------------------------------------flip-'
		echo
		echo
	done

else
	id=$(commit-id $log_start) || exit 1
	showpatch $id
fi
