#!/usr/bin/env bash
#
# Make a log of changes in a GIT branch.
# Copyright (c) Petr Baudis, 2005.
# Copyright (c) David Woodhouse, 2005.
#
# Takes a -c option to add color to the output.
# Currently, the colors are:
#
#	header		Green	
#	author 		Cyan
#	committer	Magenta
#	files		Blue
#	signoff		Yellow
#
# Takes an -f option to list which files was changed.
#
# Takes an -r followed with id resolving to a commit to start from
# (HEAD by default), or id1:id2 representing an (id1;id2] range
# of commits to show.
#
# The rest of arguments are took as filenames; cg-log then displays
# only changes in those files.

. ${COGITO_LIB}cg-Xlib
# Try to fix the annoying "Broken pipe" output. May not help, but apparently
# at least somewhere it does. Bash is broken.
trap exit SIGPIPE

if [ "$1" = "-c" ]; then
	shift
	# See terminfo(5), "Color Handling"
	colheader="$(tput setaf 2)"    # Green
	colauthor="$(tput setaf 6)"    # Cyan
	colcommitter="$(tput setaf 5)" # Magenta
	colfiles="$(tput setaf 4)"     # Blue
	colsignoff="$(tput setaf 3)"   # Yellow
	coldefault="$(tput op)"        # Restore default
else
	colheader=
	colauthor=
	colcommitter=
	colfiles=
	colsignoff=
	coldefault=
fi

list_files=
if [ "$1" = "-f" ]; then
	shift
	list_files=1
fi

list_commit_files()
{
	tree1="$1"
	tree2="$2"
	sep="    * $colfiles"
	# List all files for for the initial commit
	if [ -z $tree2 ]; then
		list_cmd="git-ls-tree $tree1"
	else
		list_cmd="git-diff-tree -r $tree1 $tree2"
	fi
	echo
	$list_cmd | while read modes type sha1s file; do
		echo -n "$sep$file"
		sep=", "
	done
	echo "$coldefault:"
}

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
	revls="git-rev-tree $id2 ^$id1"
	revsort="sort -rn"
	revfmt="git-rev-tree"
else
	id1="$(commit-id $log_start)" || exit 1
	revls="git-rev-list $id1"
	revsort="cat"
	revfmt="git-rev-list"
fi

$revls | $revsort | while read time commit parents; do
	trap exit SIGPIPE
	tree1=
	tree2=
	[ "$revfmt" = "git-rev-list" ] && commit="$time"
	if [ $# -ne 0 ]; then
		parent=$(git-cat-file commit $commit | sed -n '2s/parent //p;2Q')
		[ "$parent" ] && [ "$(git-diff-tree -r $commit $parent "$@")" ] || continue
	fi
	echo $colheader""commit ${commit%:*} $coldefault;
	git-cat-file commit $commit | \
		while read key rest; do
			trap exit SIGPIPE
			case "$key" in
			"author"|"committer")
				if [ "$key" = "author" ]; then
					color="$colauthor"
				else
					color="$colcommitter"
				fi

				date=(${rest#*> })
				pdate="$(showdate $date)"
				if [ "$pdate" ]; then
					echo -n $color$key $rest | sed "s/>.*/> $pdate/"
					echo $coldefault
				else
					echo $color$key $rest $coldefault
				fi
				;;
			"tree"|"parent")
				if [ -z $tree1 ]; then
					tree1=$rest
				elif [ -z $tree2 ]; then
					tree2=$rest
				fi
				echo $colheader$key $rest $coldefault
				;;
			"")
				if [ -n "$list_files" ]; then
					list_commit_files "$tree1" "$tree2"
				fi
				echo; sed -re '
					/ *Signed-off-by:.*/Is//'$colsignoff'&'$coldefault'/
					/ *Acked-by:.*/Is//'$colsignoff'&'$coldefault'/
					s/./    &/
				'
				;;
			*)
				echo $colheader$key $rest $coldefault
				;;
			esac

		done
	echo
done | ${PAGER:-less} ${PAGER_FLAGS:--R}
