#!/bin/sh
#
# USAGE
#
# bzr2git SOURCE [DEST]
#
# SUMMARY
#
# Converts bzr branch at SOURCE to git repo at DEST.
#
# DEST will be created and must not exist prior to calling.
# If no DEST is provided, assume basename of SOURCE.
#
# SYNOPSIS
#
# Convert local bzr branch at ~/bzr/some-project to new git repo
# at ~/git/some-project:
#
# $ mkdir ~/git
# $ cd ~/git
# $ bzr2git ~/bzr/some-project
#
# You can also specify the name of the new git directory:
#
# $ mkdir ~/git
# $ bzr2git ~/bzr/some-project ~/git/some-project
#
# NOTES
#
# I whipped this together in about 15 minutes so don't get your hopes
# up. It should work fine for most simple cases but there's a variety
# of issues that make it suboptimal: it's slow, doesn't track renames
# properly, and won't bring in branches or tags properly. It works well
# enough for bringing history on a single master branch, though.
#
# You will need recent version of bzr and git as well as rsync.
#
# Copyright (c) 2008, Ryan Tomayko
#
# Please let me know if you make improvements to this script.
# bail on errors
set -e
# we need somewhere to do work...
WORK_DIR="/tmp/bzr2git-$$"
L="/tmp/bzr-log-$$"
# remove work stuff on exit
trap "rm -rf $WORK_DIR $L" 0
# exit with usage message
bail() {
echo "usage: $0 SOURCE [DEST]"
exit 1
}
# grab source and dest arguments
SOURCE="$1"
DEST="$2"
# bail if no source given
if [ -z "$SOURCE" ] ; then
echo >&2 "must specify source bzr repository and dest git tree"
bail
fi
# default DEST to basename of source
[ -z "$DEST" ] && DEST=`basename $SOURCE`
# bail if DEST already exists
if [ -d "$DEST" ] ; then
echo >&2 "$DEST already exists"
exit 1
fi
ORIG_DIR=`pwd`
# create our work directory
mkdir -p $WORK_DIR
# initialize empty git repo
mkdir $WORK_DIR/git
cd $WORK_DIR/git
git init >/dev/null
# grab bzr branch at changeset 1
rev=1
cd $WORK_DIR
bzr branch -r$rev "$SOURCE" bzr >/dev/null 2>&1
# figure out how many changesets we have in our bzr branch
last_rev=`bzr version-info --custom --template='{revno}' $SOURCE`
# loop over each changeset number
while true
do
echo "===> Importing changeset $rev of $last_rev..."
# grab meta data
cd $WORK_DIR/bzr
bzr log -r $rev > $L
AUTHOR=`cat $L | grep ^committer: | cut -c12-`
DATE=`cat $L | grep ^timestamp: | cut -c12-`
# update git work dir
rsync -ar --delete --exclude=.bzr/ --exclude=.git/ $WORK_DIR/bzr/ $WORK_DIR/git/
# perform commit
GIT_AUTHOR_DATE="$DATE"
GIT_COMMITTER_DATE="$DATE"
export GIT_AUTHOR_DATE GIT_COMMITTER_DATE
cd $WORK_DIR/git
git add .
[ "$AUTHOR" = "rtomayko" ] && AUTHOR="Ryan Tomayko "
echo $AUTHOR
cat $L | tail -n +7
cat $L | tail -n +7 | cut -c3- | git commit -q -a --author "$AUTHOR" -F - || true
# grab next rev
rev=`echo $rev + 1 | bc`
[ $rev -gt $last_rev ] && break
cd $WORK_DIR/bzr
bzr pull -r $rev --overwrite >/dev/null 2>&1
done
cd "$ORIG_DIR"
mv "$WORK_DIR/git" "$DEST"
cd $DEST
git gc --prune --aggressive
echo "New git repo ready in $DEST"