#!/usr/bin/env bash

#github master branch and bitbucket trunk branch mirror each other
# keep neuron.yale.edu up to date with respect to bitbucket

#list of repositories to mirror.
repositories="iv nrn"

#crontab -e
#0 */3 * * * /home/hines/neuron/repository_mirror/repository_mirror

# bitbucket and github settings have ssh keys to allow push without
# password.

# https://github.com/felipec/git-remote-hg software is used to make
# a git clone of the bitbucket hg repository using 'git clone hg::ssh:...'
# and track the remote origin/branches/trunk with the local branches/trunk.
# Also, the git repository on github has its remote git/master branch
# tracked by the local master branch.

# It is asserted that only one remote repository can be ahead of the local
# repository. If both are ahead, the merges must be done manually.
# If bitbucket is ahead of github, then the branches/trunk is (fast forward)
# merged to master and the latter is pushed to github.
# If github is ahead of bitbucket, then master is (fast forward) merged to
# branches/trunk and the latter is pushed to bitbucket.

# original bootstrapping requires a bitbucket hg repository and a
# github git repository with the same name (manually
# created from an earlier version of the hg repository). If the git
# repository is empty, this script will create a master branch and push

# an example of how to re-establish consistency when both hg and git
# repositories are different is
if false ; then
git clone http://github.com/nrnhines/nrn nrngit
hg clone http://bitbucket.org/nrnhines/nrn nrnhg
git clone hg::nrnhg temp

cd temp  

git fetch
git checkout -b branches/trunk origin/branches/trunk
git config core.notesRef refs/notes/hg

git remote add nrngit /home/hines/neuron/hggit/nrngit
git fetch nrngit

git checkout branches/trunk
git merge nrngit/master #and fix conflicts
git commit

git push origin
git checkout master
git merge branches/trunk
cd ../nrngit
git pull ../temp

fi

local=$HOME/neuron/hggit
hgmastersite=ssh://hg@bitbucket.org/nrnhines
gitmastersite=ssh://git@github.com/nrnhines
hgcopysite=ssh://hines@neuron.yale.edu//home/hg/neuron

mkdir -p $local
cd $local

for rep in $repositories ; do
  echo -e "\n\n\n${rep}\n"
  cd $local
  if test ! -d ${rep}hggit ; then
    git clone hg::$hgmastersite/${rep} ${rep}hggit
    cd ${rep}hggit
    git fetch
    git checkout -b branches/trunk origin/branches/trunk
    git config core.notesRef refs/notes/hg

    # is the github just initialized with no commits or can
    # its master be checked out
    git remote add git $gitmastersite/$rep
    if ! git fetch git ; then
      echo "$gitmastersite/$rep does not exist. Initialize it on github"
      exit 1
    fi
    if ! git checkout -b master git/master ; then
      echo "github empty so create master branch and push"
      git branch master
      git checkout master
      git push -u git master
    elif  test "`git status -b --porcelain`" != "## master...git/master" ; then
      echo "not on branch master...git/master"
      echo "$gitmastersite/$rep has no commits"
      exit 1
    fi
    echo "on branch master...git/master"
    cd ..
  fi

  cd ${rep}hggit

  # verify validity
  git branch --list -vv

  oldhg="`git log branches/trunk --format=\"%h\" -n 1`"
  oldgit="`git log master --format=\"%h\" -n 1`"

  git checkout branches/trunk
  git pull
  git checkout master
  git pull

  newhg="`git log branches/trunk --format=\"%h\" -n 1`"
  newgit="`git log master --format=\"%h\" -n 1`"

  echo oldhg $oldhg
  echo oldgit $oldgit
  echo newhg $newhg
  echo newgit $newgit

  if test "$newgit" != "$newhg" ; then
    # they are the different.
    # pull from the one ahead and push to the one behind.
    m2t=`git log -n 1 --format="%h" master..branches/trunk`
    t2m=`git log -n 1 --format="%h" branches/trunk..master`
    if test "$m2t" = "" ; then # empty means master ahead of trunk
      echo "merge $rep master to trunk and push to bitbucket"
      git checkout branches/trunk
      git merge master branches/trunk
      git push origin
    elif test "$t2m" = "" ; then
      echo "merge $rep trunk to master and push to github"
      git checkout master
      git merge branches/trunk master
      git push git
    else
      echo "Both github and bitbucket for $rep have changes. Resolve manually."
      continue
    fi
  fi

  cd $local
  # update neuron.yale.edu if necessary

  hgcopyid=`hg identify -i $hgcopysite/$rep`
  err=$?
  if test "$err" != 0 ; then # if the repository does not exist
    echo "$hgcopysite/$rep does not exist"
    continue
  fi

  hgmasterid=`hg identify -i $hgmastersite/$rep`
  if test "$hgmasterid" = "$hgcopyid" ; then
    continue
  fi

  if test ! -d "$local/${rep}hg" ; then
    echo "cloning bitbucket repository into the local ${rep}hg"
    hg clone $hgmastersite/$rep ${rep}hg
  fi

  echo $repname $hgmasterid $hgcopyid

  cd $local/${rep}hg
  hg pull -u
  hg push $hgcopysite/$rep

done
