#!/bin/sh
# vim: foldmethod=marker
# DJANGO GIT UPDATING SCRIPT, PLEASE READ THOSE INSTRUCTIONS.
# This script expects you to have the following structure:
#   * Some branches that match the $TRUNK regex which are *clean*
#     copies of SVN trunk or branches.
#   * A master branch coming from every of those $TRUNK branches, aka: master
#   * Any other topic branches will pull from one of those masters (or not)
# The script expects the "pull" configuration to be set correctly for every branch.
# Imagine the following scenarios:
#   * A master branch follows trunk:
#     git config branch.master.remote .
#     git config branch.master.merge trunk
#   * A master-1.0.X branch follows trunk-1.0.X
#     git config branch.master-1.0.X.remote .
#     git config branch.master-1.0.X.merge trunk-1.0.X
#   * A 6735-views branch that follows master
#     git config branch.6735-views.remote .
#     git config branch.6735-views.merge master
# By doing this configuration you tell git where to merge from when running
# "git pull" on a branch.
# If you wonder how to setup GIT to understand Django's SVN structure ask Marc Fargas
# at telenieko@telenieko.com

# Base directory of you django git repo.
DJANGO=$HOME/dev/python/django

# Regex to find local branches that represent *clean* copies of svn trunk or branches.
# We will run "git svn rebase" on this branch, and then pull from those.
# NEVER PUBLISH THOSE BRANCHES ON THE INTERNET. THANKS.
TRUNK="trunk.*"

# Regex to find the "master" branches, those are the ones that pull from $TRUNK
# and are never rebased so can be published safely.
MASTER="master.*"

# Regex of branches to ignore, in case you have some branches you
# do not want to automatically update.
IGNORE='private/.*'

## CONFIG END ##

DIR=`pwd`

# What branches do we have?
cd $DJANGO/.git/refs/heads
BRANCHES=`find -type f`
cd $DJANGO

# {{{ match_branch: Check if the branch in $1 matches the regex in $2
# Takes the branch name as $1, and the ignore list as $2
# Return value 0 if no match
# Return value 1 if matches
match_branch() {
    br=$1
    ignore=$2
    if [ `expr match "$br" "$ignore"` -gt 0 ]; then
        return 1
    elif [ "$br" = "=" ]; then
        return 1
    fi
    return 0
}
# }}}

# {{{ ignore_branch: Check if the branch in $1 has to be ignored
# (aka: not in $TRUNK, $MASTER, $IGNORE
# Takes the branch name as $1
# Return value 0 if ok.
# Return value 1 if should be ignored.
ignore_branch() {
    br=$1
    if [ `expr match "$br" "$TRUNK"` -gt 0 ]; then
        return 1
    elif [ `expr match "$br" "$MASTER"` -gt 0 ]; then
        return 1
    elif [ `expr match "$br" "$IGNORE"` -gt 0 ]; then
        return 1
    fi
    return 0
}
# }}}

# {{{ update_branch: Merge, from branch $1 the branch $MASTER.
# On failure we "git reset --hard", print a message and return 1.
update_branch() {
    echo "Merging $1 with its master"
    git checkout $1
    git pull
    RES=$?
    if ! [ $RES -eq 0 ]
    then
        echo "MERGE FAILED FOR $1 DO IT BY HAND"
        git reset --hard
        echo "MERGE FAILED FOR $1 DO IT BY HAND"
        return 1
    fi
}
# }}}

# {{{ update_svn: Update our $TRUNK branches with code from svn.
# That runs "svn fetch", "svn rebase" and merges $TRUNK into $MASTER.
update_svn() {
    cd $DJANGO
    git svn fetch
    for BR in $BRANCHES
    do
        BR=${BR:2}
        match_branch $BR  $TRUNK 
        RES=$?
        if [ $RES -eq 1 ]
        then
            echo "Merging $BR with SVN"
            git checkout $BR
            git svn rebase
            RES=$?
            if ! [ $RES -eq 0 ]
            then
                echo "COULD NOT MERGE $BR"
                return 1
            fi
        fi
    done
}
# }}}

# {{{ update_master: Update our $MASTER branches with code from our $TRUNK.
# That runs "git pull" on those branches.
update_master() {
    cd $DJANGO
    for BR in $BRANCHES
    do
        BR=${BR:2}
        match_branch $BR  $MASTER 
        RES=$?
        if [ $RES -eq 1 ]
        then
            echo "Merging $BR with trunk branch"
            git checkout $BR
            git pull
            RES=$?
            if ! [ $RES -eq 0 ]
            then
                echo "COULD NOT MERGE $BR"
                return 1
            fi
        fi
    done
}
# }}}

update_svn
RES=$?
if ! [ $RES -eq 0 ]; then
    echo "Got trouble updating svn, aborting."
    cd $DIR ; exit 1
fi

update_master
RES=$?
if ! [ $RES -eq 0 ]; then
    echo "Got trouble updating master branches, aborting."
    cd $DIR ; exit 1
fi


for BR in $BRANCHES
do
    BR=${BR:2}
    ignore_branch $BR
    RES=$?
    if [ $RES -eq 0 ]
    then
        update_branch $BR
    else
        echo "Not merging $BR with anyone."
    fi
done

# Go back to the directory we were before running.
cd $DIR