#!/bin/sh

usage() {
    cat <<EOF
    First: DON'T PANIC
        NOTE: This advice pertains to gitolite specific issues.  If you don't
        have ANY access to the server at all, it is OK to panic.

    Step 1: prepare

      - copy this program to your gitolite server
      - if you lost your admin key, create a new keypair on your workstation
        and copy the pub part of this new key also to the server
      - rename it to whatever your gitolite admin username is, with a .pub
        extension.  (Example, I would call it "sitaram.pub")

    Step 2: use one of the fixes below (on the server)

      - (FIX #1: REWINDING BAD ADMIN COMMITS) if your last commit(s) to the
        gitolite-admin repo pushed a very bad config and you want to rewind it
        to a known good state, run this:

            $0 rewind

        (this doesn't actually rewind; it creates a new commit that has
        the same state as the last good commit, which has the same effect)

      - (FIX #2: PUSHING A NEW ADMIN KEY) if you lost your admin key, or you
        had used the wrong key initially, then you get yourself a new keypair
        and run this with the new pubkey:

            $0 sitaram.pub          # example using my name

        Please note that this simply *replaces* the key for user "sitaram".
        It does NOT add a new admin called "sitaram".  In fact it does not
        touch the config file (access rules) at all.

    Step 3: completing the fix (on your workstation)

      - do a 'git pull' on the gitolite admin clone or make a fresh clone
EOF
    exit 1
}

if [ -z "$1" ]
then
    usage
fi

# ------------------------------------------------------------------------
# arg check
die() { echo "$@"; exit 1; }
cd $HOME        # if he didn't *start* there, it's his bloody fault
[ -f "$1" ] || [ "$1" = "rewind" ] || die "need a valid file or 'rewind'"
if [ "$1" = "rewind" ]
then
    :
else
    bn1=`basename $1`;
    admin_name=`basename $1 .pub`;
    [ "$bn1" = "$admin_name" ] && die "filename needs to end in '.pub'"
fi

# ------------------------------------------------------------------------
# setup stuff
REPO_BASE=$(  cd $HOME; perl -e 'do ".gitolite.rc"; print $REPO_BASE'  )
GL_BINDIR=$(  cd $HOME; perl -ne 'print($1), exit if /^command="(.*?)\/gl-auth-command /' < $HOME/.ssh/authorized_keys)
GL_ADMINDIR=$(cd $HOME; perl -e 'do ".gitolite.rc"; print $GL_ADMINDIR')
export REPO_BASE
export GL_BINDIR
export GL_ADMINDIR

TEMPDIR=$(mktemp -d)
export TEMPDIR
trap "/bin/rm -rf $TEMPDIR" 0

# ------------------------------------------------------------------------
# rewind the admin repo
if [ "$1" = "rewind" ]
then
    git clone $REPO_BASE/gitolite-admin.git $TEMPDIR
    cd $TEMPDIR

    echo printing the last 9 commits to the config; echo
    git log -9 --date=relative --format="%h %ar%x09%s" | perl -pe 'print "$.\t"'
    echo; read -p 'please enter how many commits you want to rewind: ' n
    good=`git rev-parse --short HEAD~$n`

    git checkout -f $good .
    git commit -m "emergency revert to $good"
    GL_BYPASS_UPDATE_HOOK=1 git push

    exit $?
fi

# ------------------------------------------------------------------------
# add/overwrite a key ($1)
git clone $REPO_BASE/gitolite-admin.git $TEMPDIR
cp $1 $TEMPDIR/keydir
cd $TEMPDIR
git add keydir
git commit -m "emergency add/update $admin_name key (from $1)"
GL_BYPASS_UPDATE_HOOK=1 git push
exit $?
