#!/bin/sh
#
# An example hook script to mail out commit update information.
# It also blocks tags that aren't annotated.
# Called by git-receive-pack with arguments: refname sha1-old sha1-new
#
# To enable this hook:
# (1) make this file executable by "chmod +x update".
# (2) define the recipient e-mail address in $GIT_DIR/mailto file.
# (3) define the project description in $GIT_DIR/description file.
# (4) optionally define email charset in $GIT_DIR/charset file.
#

LANG=C
LANGUAGE=C
LC_ALL=C
export LANG LANGUAGE LC_ALL

mailto="$(cat $GIT_DIR/mailto 2>/dev/null)"

ref_type="$(git-cat-file -t "$3")" || exit 1

# Only allow annotated tags in a shared repo
# Remove this code to treat dumb tags the same as everything else
case "$1,$ref_type" in
refs/tags/*,commit)
	echo >&2 "*** Un-annotated tags are not allowed in this repo"
	echo >&2 "*** Use 'git-tag [ -a | -s ]' for tags you want to propagate."
	exit 1
	;;
refs/tags/*,tag)
	echo "### Pushing version '${1##refs/tags/}' to the masses" >&2
	;;
esac

[ -n "$mailto" ] || exit 0

exit_handler()
{
	local rc=$?
	trap - EXIT
	rm -rf -- "$workdir"
	exit $rc
}
workdir="$(mktemp -dt git-update.XXXXXXXX)" || exit 1
trap exit_handler HUP PIPE INT QUIT TERM EXIT

MSG="$workdir/message"
DIFF="$workdir/diff"

DIFFMAX=65536
date_format="%F %T %z"
git_dir="$(readlink -e "$GIT_DIR")"
project="$(head -n1 $GIT_DIR/description)"
charset="$(head -n1 $GIT_DIR/charset 2>/dev/null)"

cat >"$MSG" <<EOF
To: $mailto
Subject: [git update] $project: ${1##refs/heads/}
Content-Type: text/plain${charset:+; charset=$charset}
X-git-dir: $git_dir
X-git-description: $project

Update of $git_dir

EOF

if expr "$2" : '0*$' >/dev/null; then
	# new ref
	case "$1" in
	refs/tags/*)
		# a pushed and annotated tag (usually) means a new version
		tag="${1##refs/tags/}"
		if [ "$ref_type" = tag ]; then
			TAG="$workdir/tag"
			git-cat-file tag "$3" >"$TAG"
			tagger="$(sed -ne '4s/^tagger \([^>]\+>\).*/\1/p' <"$TAG")"
			ts="$(sed -ne '4s/^tagger [^>]\+>[^0-9]*\([0-9]\+\).*/\1/p' <"$TAG")"
			date="$(date --date="1970-01-01 00:00:00 $ts seconds" +"$date_format")"
			echo "Tag '$tag' created by $tagger at $date"
			echo "with the following message:"
			git-cat-file tag "$3" |sed -n '5,$p'
			echo =======
			echo
		fi
		prev="$(git-describe "$3^" 2>/dev/null| sed 's/-g.*//')"
		# the first tag in a repo will yield no $prev
		if [ -z "$prev" ]; then
			echo "Changes since the dawn of time:"
			git-rev-list --pretty "$3"
		else
			echo "Changes since \`$prev':"
			git-diff "$3" "^$prev" >"$DIFF"
			diffstat -f0 -p1 <"$DIFF"
			echo
			git-rev-list --pretty "$3" "^$prev"
			echo
			SIZE="`wc -c $DIFF | sed 's/^[^0-9]*\([0-9]*\).*$/\1/'`"
			if [ $SIZE -ge $DIFFMAX ]; then
				echo "Full changes since \`$prev' are too large ($SIZE bytes)"
			else
				echo "Full changes since \`$prev' follow:"
				cat "$DIFF"
			fi
		fi
		;;

	refs/heads/*)
		branch="${1##refs/heads/}"
		echo "New branch \`$branch' available with the following commits:"
		git-rev-list --pretty "$3" $(git-rev-parse --not --all)
		;;
	esac
else
	base="$(git-merge-base "$2" "$3")"
	prev="$(git-describe "$base" 2>/dev/null)" || prev="$base"
	case "$base" in
	"$2")
		echo "Changes since \`$prev':"
		;;
	*)
		echo "Changes since common ancestor \`$prev':"
		;;
	esac
	git-diff "$3" "^$base" >"$DIFF"
	diffstat -f0 -p1 <"$DIFF"
	echo
	git-rev-list --pretty "$3" "^$base"
	echo
	SIZE="`wc -c $DIFF | sed 's/^[^0-9]*\([0-9]*\).*$/\1/'`"
	if [ $SIZE -ge $DIFFMAX ]; then
		echo "Full changes since \`$prev' are too large ($SIZE bytes)"
	else
		echo "Full changes since \`$prev' follow:"
		cat "$DIFF"
	fi
fi >>"$MSG"

/usr/sbin/sendmail -i -t <"$MSG"
exit 0
