#!/bin/sh

DEBUG=$(git config --type bool --default false netbsd.debug)
if $DEBUG; then
	echo BEGIN update $$ "$@"
	trap 'echo END update $$' EXIT HUP INT TERM
fi

set -Ceu
if $DEBUG; then
	set -x
fi

ref=$1
old=$2
new=$3

if $DEBUG; then
	i=0
	while [ "$i" -lt "${GIT_PUSH_OPTION_COUNT:-0}" ]; do
		eval echo [update] GIT_PUSH_OPTION_$i=\$GIT_PUSH_OPTION_$i
		i=$((i + 1))
	done
fi

# Allow only refs/heads/* to be updated.
#
# In the future, we should consider:
#
#       refs/tags/*                     git cinnabar tag
#	refs/namespaces/dev/$DEV/*      developer namespace
#
case $ref in
refs/heads/*)
	;;
*)	echo 'only head updates are allowed' >&2
	exit 1
	;;
esac

# Lock the cinnabar bridge so pushes don't happen concurrently.  If the
# system crashes in the middle, no big deal -- the lock will be broken,
# but no concurrent pushes will be happening anyway.  The lock will be
# released when this process exits (specifically, when all file
# descriptors referencing this open of the lock file are closed).
#
# This doesn't make batch ref updates atomic -- it only ensures that
# each ref update is forwarded on to Mercurial in serial and no
# concurrent pushes attempts to update cinnabar metadata
# simultaneously.  It's possible that metadata updates by git-cinnabar
# are already safe but let's play it safer.
#
# If the lock can't be acquired immediately, print message to say where
# the holdup is coming from.
exec 3>>$GIT_DIR/cinnabridge.lock
if ! flock -n 3 3<&3; then
	echo 'waiting for Mercurial bridge lock...' >&2
	flock 3 3<&3
	echo 'Mercurial bridge lock acquired' >&2
fi

# Push back to the origin via git-cinnabar.  Set the environment
# variable TNFREPO_HG_GIT_PUSH while doing this so that any hg hooks
# know this is coming from a git-push and won't try to recursively come
# back to the git repo to git-fetch.
TNFREPO_HG_GIT_PUSH= \
git push origin "$new:$ref" || exit $?
