Gitolite quick and dirty mirror
Tue, 8 May, 2012 (700 Words)I’m running a gitolite instance on my personal server to manage my repositories (personnal, private or public) ; and I am quickly going to share with you how I setup a quick and dirty mirror feature.
First, I am using gitolite 3. The mirroring we are going to setup is not the supported mirroring built-in. We are going to implement a simplier way to set mirror thing :
- Write a custom gitolite command ; the idea is to be able to write
git-config
stuff. - Write a hook that take a specific
git-config
(let saymirror.url
) and do a simple mirroring.
Gitolite commands
Gitolite 3 has been rewritten to be more flexible : Why a completely new version.
The rewrite made it really easy to extend gitolite. I’ve fork gitolite on github
I’ve created a repository git
to easily add commands to my gitolite instance via local code. The gitolite command I wrote is
a quick and dirty script in shell to add git config
. The source should speek
for itself ; It should include some way to check if the given config is not
already present in the gitolite-admin
configuration file — and so might be
rewritten in Perl
.
The command is write-git-config
because a git-config
command already exists
in the built-in commands.
#!/bin/sh
# Usage: ssh git@host write-git-config <repo> <key> <value>
#
# Set git-config value for user-created ("wild") repo.
die() { echo "$@" >&2; exit 1; }
usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
[ -z "$1" ] && [ -z "$2" ] && [ -z "$3" ] && usage
[ "$1" = "-h" ] && usage
[ -z "$GL_USER" ] && die GL_USER not set
# ----------------------------------------------------------------------
repo=$1; shift
key=$1; shift
value=$1; shift
# this shell script takes arguments that are completely under the user's
# control, so make sure you quote those suckers!
if gitolite query-rc -q WRITER_CAN_UPDATE_DESC
then
gitolite access -q "$repo" $GL_USER W any || die You are not authorised
else
gitolite creator "$repo" $GL_USER || die You are not authorised
fi
# if it passes, $repo is a valid repo name so it is known to contain only sane
# characters. This is because 'gitolite creator' return true only if there
# *is* a repo of that name and it has a gl-creator file that contains the same
# text as $GL_USER.
configfile=`gitolite query-rc GL_REPO_BASE`/"$repo".git/config
git config --file "$configfile" "$key" "$value"
Gitolite hooks
The next step is to write a quick post-receive
hook that check if there is a
certain git-config
entry and run git push --mirror
. The file is in
$HOME/.gitolite/hooks/common/post-receive
; you could add a better system to
hooks (to be able to add “dynamic” hooks, …).
#!/bin/sh
# Simple gitolite mirroring
# flush STDIN coming from git, because gitolite's own post-receive.mirrorpush
# script does the same thing
[ -t 0 ] || cat >/dev/null
[ -z "$GL_REPO" ] && die GL_REPO not set
target=`git config --get mirror.url`
[ -z "$target" ] && exit 0
# Support a REPO variable for wildcard mirrors
gl_repo_escaped=$(echo $GL_REPO | sed 's/\//\\\//g')
target=$(echo $target | sed -e "s/REPO/$gl_repo_escaped/g")
# Do the mirror push
git push --mirror $target
The next, and final step is to run gitolite compile
to update links to hooks
for every repositories.
For real
And finaly, this is the final step you’ll do.
$ ssh git@host write-git-config vincent/vcsh-home mirror.url git@github.com:vdemeester/vcsh-home.git
$ git push
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 294 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: To git@github.com:vdemeester/vcsh-home.git
remote: 65681a8..701c990 master -> master
To git@host:vincent/vcsh-home.git
65681a8..701c990 master -> master
And that should be it !
Update 2012/10/04 : Moved from gitolite fork to gitolite local code repository.