Gitorious and third-party repository hooks
Recently the Dungeon Crawl Stone Soup development team decided to also move the code repository away from Sourceforge.net. There had been a few complains in the past about speed and reliability but the fact that and how they disabled the ability send emails when a commit to code was done gave the final push to move away. It has been quickly decided to setup the new git repository on Gitorious.org.
Unfortunately Gitorious does not support so-called hooks, which trigger things on certain events like informing the CIA bot in ##crawl-dev or sending summary emails to the mailing-list when changes are made.
I thought it might be useful to tell of how we made the git-hooks work, even though Gitorious does not provide this feature.
(Please, if you see something that could have been done in a smoother more elegant way, step in and let me know.)
In the past I had setup a mirror at http://git.develz.org/?p=crawl-ref.git (note the -ref). What it did was to fetch from Sourceforge/Gitorious and then update-ref to present certain branches (master, stone_soup-0.7, etc) as local branches for others to checkout. Unfortunately, I couldn’t find any hook that would trigger by fetch nor by the forced update-ref. The available hooks all said they would only react when someone pushed/committed changes (update, post-receive) – which wasn’t the case.
So, what I did was to create 2 new bare repositories: one local and hidden, the other public (crawl.git). In this hidden repository I added both, Gitorious and the new public crawl.git from git.develz.org, but with a special parameter:
git --bare init
git --bare remote add --mirror gitorious git://gitorious.org/crawl/crawl.git
git --bare remote add --mirror develz ssh://email@example.com/crawl.git
man git-remote: In mirror mode, enabled with –mirror, the refs will not be stored in the refs/remotes/ namespace, but in refs/heads/. This option only makes sense in bare repositories. If a remote uses mirror mode, furthermore, git push will always behave as if –mirror was passed.
It’s important to make even this hidden repository a bare one, otherwise the next fetch would fail because you can’t overwrite a branch you are currently in with fetch:
git --bare fetch gitorious
All branches from gitorious now pretend to be local. Which can be easily pushed to the public repository.
git --bare push develz
And since the hooks are installed on the remote develz and the changes got pushed, they are executed as they had always been on Sourceforge. Well, almost: On Sourceforge people used their own unix account to push changes. This is no longer the case and hence the sender address is always the generic account. Maybe I can find a small hack to work around that, later.
One important note: Do not replace the “fetch gitorious” with a “remote update”, or else it might get the new changes from gitorious first and then overwrite the branches with the old state of develz.
Currently I’m running the small script to update (fetch & push) every two minutes. Considering it doesn’t take much traffic at all, Gitorious should be well able to handle that.