#!/bin/bash
set -eo pipefail

# Places cursor at start of line, so that subsequent text replaces existing text. For example;
# "remote: Updated branch 'master' of 'repo'. Deploying to dev." becomes
# "Updated branch 'master' of 'repo'. Deploying to dev."
strip_remote_prefix() {
    sed -u "s/^/"$'\e[1G'"/"
}

GITUSER=${GITUSER:-git}
GITHOME="/home/$GITUSER"
SELF=`which $0`

case "$1" in

# called by sshd on each `git push`
  run)
    export RECEIVE_USER=$2
    export RECEIVE_FINGERPRINT=$3
    # ssh provides the original requested command in $SSH_ORIGINAL_COMMAND
    SSH_ORIGINAL_COMMAND="$(echo $SSH_ORIGINAL_COMMAND | sed 's/\///g' )" # remove any '/'s
    export RECEIVE_REPO="$(echo $SSH_ORIGINAL_COMMAND | awk '{print $2}' | sed -e 's/'\''//g')"
    REPO_PATH="$GITHOME/$RECEIVE_REPO"
    if [ ! -d $REPO_PATH ]; then
      mkdir -p $REPO_PATH
      cd $REPO_PATH
      git init --bare > /dev/null
    fi
    cd $GITHOME
    PRERECEIVE_HOOK="$REPO_PATH/hooks/pre-receive"
    # inject a pre-receive hook
    cat > $PRERECEIVE_HOOK <<EOF
#!/bin/bash
cat | $SELF pre-receive
EOF
    chmod +x $PRERECEIVE_HOOK
    # call the original git-shell
    git-shell -c "$SSH_ORIGINAL_COMMAND"
    ;;

  pre-receive)
    while read oldrev newrev refname
    do
      LOCKFILE="/tmp/$RECEIVE_REPO.lock"
      if ( set -o noclobber; echo "$$" > "$LOCKFILE" ) 2> /dev/null; then
        trap 'rm -f "$LOCKFILE"; exit $?' INT TERM EXIT

        # check for authorization on this repo
        $GITHOME/receiver "$RECEIVE_REPO" "$newrev" "$RECEIVE_USER" "$RECEIVE_FINGERPRINT"
        rc=$?
        if [[ $rc != 0 ]] ; then
          echo "      ERROR: failed on rev $newrev - push denied"
          exit $rc
        fi
        # builder assumes that we are running this script from $GITHOME
        cd $GITHOME
        # if we're processing a receive-pack on an existing repo, run a build
        if [[ $SSH_ORIGINAL_COMMAND == git-receive-pack* ]]; then
          $GITHOME/builder $RECEIVE_USER $RECEIVE_REPO $newrev 2>&1 | strip_remote_prefix
        fi

        rm -f "$LOCKFILE"
        trap - INT TERM EXIT
      else
        echo "Another git push is ongoing. Aborting..."
        exit 1
      fi
    done
    ;;

  *)
    echo "Usage: gitreceive <command> [options]"
    ;;
esac
