#!/bin/sh

SUBDIRECTORY_OK=Yes
OPTIONS_SPEC="\
git safe-push [options] [<repository> <refspec>...]

git safe-push is exactly like git push, but the user is asked to
confirm before the push is run. (By default, can be disabled with
--no-confirm, or 'git config core.confirm-push false'.)
--
v,verbose           be verbose
repo=               repository
all                 push all refs
mirror              mirror all refs
tags                push tags
dry-run             dry run
f,force             force updates
thin                use thin pack
receive-pack=       receive pack program
exec=               receive pack program
confirm             confirm ask before pushing
"
. git-sh-setup

confirm=`git config --bool core.confirm-push || echo true`

first=true
for x in "$@" ; do
    case "$x" in
        --confirm)    confirm=true ;;
        --no-confirm) confirm=false ;;
	*)
	    if $first ; then
                set -- "$x"
		first=false
            else
		set -- "$@" "$x"
            fi
	    ;;
    esac
done

$confirm || exec git push "$@"

git push --dry-run "$@" 2>&1 |
(
    IFS=''
    have_changes=false
    while read line ; do
	echo "$line" | (
            unset IFS
	    # 'summary' is only the summary for a successful update - no flag. It
	    # could also end up as the flag (!*=) or as a random word
	    read summary from arrow to
    	    case $summary in
	    	 "*" | -) echo "$line" >&2 ; exit 0 ;; # new or deleted
	  	 [a-f0-9][a-f0-9][a-f0-9]*[a-f0-9]..[a-f0-9][a-f0-9][a-f0-9]*[a-f0-9] |\
	  	 [a-f0-9][a-f0-9][a-f0-9]*[a-f0-9]...[a-f0-9][a-f0-9][a-f0-9]*[a-f0-9]) ;;
		     # Succesful updated, ... used for non-fastforward updated
		 *) echo "$line" >&2 ; exit 1 ;;
	    esac
	    old=`echo $summary | sed 's/\.\+.*//'`;
	    new=`echo $summary | sed 's/[^.]*\.\+//'`;

	    echo >&2 "Updating remote reference '$to' from $old to $new (local '$from')"

	    old=`git rev-parse $old`
	    new=`git rev-parse $new`
	    base=`git merge-base $old $new`
	    if [ $base = $old ] ; then
		echo >&2 "New commits being added:"
		git >&2 log --pretty='format:  %h %s' $old..$new
	    else
		echo >&2 "NOT A FAST-FORWARD"
		echo >&2 "Commits being removed:"
		git >&2 log --pretty='format:  %h %s' $new..$old
		if [ $base = $new ] ; then : ; else
		    echo >&2 "Commits being added:"
		    git >&2 log --pretty='format:  %h %s' $old..$new
		fi
	    fi
	    exit 0
	) && have_changes=true
    done
    $have_changes
) || exit 0

printf 'Proceed [y/N]? '
read yesno
case $yesno in
     [yY]*) ;;
     *) exit 1;;
esac

echo >&2 "Pushing..."

exec git push "$@"
