#!/usr/bin/env bash
# moving darcs & git archives around.

# set -x

# FIXME: doesn't work properly for git submodules.

[ -z "$1" ] && echo "usage: $0 <remote_host>:<remote_path> [local_path]" && exit 1
CMD=`basename $0`

DARCS_PROJECTS_DORMANT="
darcs/nodes
darcs/libhaco
darcs/brood-5
darcs/sweb
darcs/snot
darcs/packetforth
darcs/dotp
darcs/scraper
darcs/tfs
darcs/plt
darcs/ip
darcs/pltix
darcs/davinci
darcs/scope
darcs/impedance
darcs/ecos
darcs/hgl
darcs/apache-logs
"

GIT_PROJECTS_DORMANT="
git/tinyscheme
git/ecos-build
git/cx
git/arduino
git/rust-exp
git/pru
git/gdb
git/tidal-play
git/picdev
git/storage
git/quickcheck
git/erlang
git/br
"

DARCS_PROJECTS="
darcs/pr
darcs/pool
darcs/papers
darcs/meta
darcs/libprim
darcs/pd
darcs/pdp
darcs/bcr2000
darcs/analog
darcs/gaf
darcs/creb
"

GIT_PROJECTS="
git/cibs
git/asm_tools
git/nix-custom
git/studio
git/emacs_tools
git/erl_tools
git/erl_ducktape
git/erl_rust
git/uc_tools
git/sm
git/exo
git/exo/deps/admin_rkt
git/exo/deps/asm_tools
git/exo/deps/distel
git/exo/deps/emacs_tools
git/exo/deps/erl_ducktape
git/exo/deps/erl_tools
git/exo/deps/libprim
git/exo/deps/looper
git/exo/deps/nixpkgs
git/exo/deps/studio
git/exo/deps/temperv14
git/exo/deps/thermostat
git/exo/deps/uc_tools
git/exo_console
git/lars
git/eyes
git/staapl
git/staapl-exp
git/rai
git/zl
git/web
git/pyla
git/cross
git/purescript_test
git/haskell_leftovers
git/zwizwa.be
"

PROJECTS="$GIT_PROJECTS $DARCS_PROJECTS"

# Private git repos, if any
if [ -f ~/admin/bin/projects ]; then
    . ~/admin/bin/projects
    PROJECTS="$PROJECTS $GIT_PROJECTS $DARCS_PROJECTS"
fi


cleanup () {
    kill $MASTER_PID
    rm -f $DARCS_SSH
    exit 1
}
trap 'echo "INTERRUPTED: " "$@" ; cleanup ' SIGINT


setup_master () {
    # Set up control master.  The sleep command acts as timeout.
    DARCS_SSH=$(mktemp 'ssh-XXXXX' --suffix=.sh --tmpdir)
    CONTROL_PATH=${DARCS_SSH}.cm
    GIT_SSH=$DARCS_SSH
    export DARCS_SSH GIT_SSH
    cat <<EOF >$DARCS_SSH
#!/bin/bash
exec ssh -o  ControlPath=$CONTROL_PATH -o ControlMaster=no "\$@"
EOF
    chmod +x $DARCS_SSH
    ssh -o ControlPath=$CONTROL_PATH -o ControlMaster=yes $1 sleep 600 &
    MASTER_PID=$!
}





darcs_pull () {  # host project
    echo ">>> darcs_pull $1$2"
    darcs wh | grep -v 'No changes'; \
        darcs $CMD --set-default -qa $1$2 2>&1 \
            | grep -v following \
            | grep -v 'pull from current repository'
}

git_pull () {
    echo ">>> git_pull $1$2"
    git diff
    HOST=$(echo $1 | cut -d : -f 1)
    current=$(git name-rev --name-only HEAD)
    [ "$current" == undefined ] && current="HEAD"

    # Always pull current branch, regardless of branch config setup.  This will do non-ff.
    git pull $1$2 $current 2>&1 \
        | grep -v 'up-to-date' \
        | grep -v 'From ' \
        | grep -v ' * branch            master     -> FETCH_HEAD'

    # If the host is listed as an explicit repository, assume it has
    # all the branches we have.
    if [ -f .git/config ]; then
        if grep "\[remote.*\"$HOST\"\]" .git/config; then
            # First fetch all patches,
            git fetch $HOST 2>&1
            # then let fetch merge all the local branches - except the
            # current one which won't do non-ff.
            for lb in $(git branch -a | grep -v "remotes/" | grep -v $current | tr '*' ' '); do
                echo " * $lb"
                git fetch $HOST $lb:$lb #| grep -v 'From '
            done
        fi
    fi
}

project () {
    mkdir -p /tmp/$CMD/$3
    #echo "... $3";
    #echo "--- $3";
    (if cd $2/$3; then
         if [ -x _darcs ]; then
             darcs_${CMD} $1 $3
         else
             git_${CMD} $1 $3
         fi
     fi)2>&1
    ## I'd like to do this in parallel, but I get connection
    ## refused...  EDIT: using ControlMaster makes it fast enough.
}

# FIXME: override this
LOG=/dev/null

run () {
    echo "REMOTE: $1"
    echo "LOCAL:  $2"
    echo
    for project in $PROJECTS; do
	if [ -d $2/$project ]; then
            echo "$2/$project"
            (project $1 $2 $project)>$LOG 2>&1
#        else
#            echo "skipping $2/$project"
	fi
        sleep .005
        # echo
    done
    #wait
}

# FIXME: This is a departure from the original default
# LOCAL=$HOME
LOCAL=.
[ -z "$2" ] || LOCAL=$2
HOST=$(echo $1 | cut -d : -f 1)

setup_master $HOST
echo "MASTER: $MASTER_PID"
run "$1" "$LOCAL"
cleanup

