Migrating from Gitorious to Gitosis

Gitorious is very nice for social coding, and I thought it would be perfect for us at first. Apparently its git cloning is not quite adequate for us, as we need git pulling and git pushing and some of those cloning shouldn’t be able to write (such as deploy users).

Since we decided Gitorious wasn’t for us, we’ve just left it as it is (frequently restarting ActiveMQ and the poller, as they crash a lot). We just never had an excuse to spend the time to migrate until today when Gitorious broke completely for no apparent reason.

The process was fairly trivial, but I’ll share my code anyway as it was a somewhat interesting endeavour.

First of all then, Gitorious stores its repositories in quite an annoying way if you want to get at them outside of Rails. It stores them as some kind of hash, but split up to prevent the directories from containing trillions of entries. For instance, git@thedextrousweb.com:wordpress-plugins/wp-recaptcha is stored in /var/git/repositories/e27/004/48f5b0e17f3403aa15efd0ea8d47ce874a.git. The database then holds a mapping from the human-readable path to the actual path.

Gitosis, on the other hand, uses a mapping from wordpress-plugins/wp-recaptcha to ~/repositories/wordpress-plugins/wp-recaptcha.git, which is much more obvious.

So we need the mapping, for which we shall have to prod Rails’ database:

require File.dirname(__FILE__) + '/../config/environment'
Repository.all.each do |r|
  name = r.project.slug + '/' + r.name
  path = r.hashed_path
  puts "#{path} #{name}"

All that does is prints out the physical path to the repository, followed by the human-readable path, separated by a space. So redirect that to some file, and enter gitosis’ repository directory (possibly as the git user, or chown -R later). I’ll be using grep -v wiki here because we never used the wikis. So we first create the directories because git won’t mkdir -p:

grep -v wiki files | cut -d' ' -f2 | cut -d/ -f1 | sort | uniq | xargs mkdir

And rather than using cp -R or rsync, I thought it would be best to let git do the job:

grep -v wiki files | perl -pe 's/ /.git /;s/^/git clone --mirror \/var\/git\/repositories\//;s/$/.git/' | sh

Since we’ve only got a few users, we’re not going to bother importing all the users and groups, so we can just cut the list of repositories, remove the newlines, and append it to our writeable.