This post is in response to a comment someone made on irc earlier today:
[I] would really like a git lookaside cache which operated on an upstream repo, but pulled objects locally when they're available
In this post I present a proof-of-concept solution to this request. Please note that thisand isn't something that has actually been used or tested anywhere!
If you access a git repository via
ssh, it's easy to provide a
wrapper for git operations via the
command= option in an
authorized_keys file. We can take advantage of this to update a a
local "cache" repository prior to responding to a
A simple wrapper might look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#!/bin/bash [ "$SSH_ORIGINAL_COMMAND" ] || exit 1 eval set -- $SSH_ORIGINAL_COMMAND cd repos case $1 in (git-receive-pack|git-upload-pack) :;; (*) echo "*** Unrecognized command." >&2 exit 1 ;; esac if [ "$1" = "git-upload-pack" ]; then ( # Update the local repository cache if the file # 'git-auto-update' exists. cd "$2" [ -f git-auto-update ] && git remote update >&2 ) fi exec "$@"
If we have a
git user locally, we can place the above script into
/home/git/bin/gitwrapper, and then set up a
file that looks something like this:
command="/home/git/bin/gitwrapper" ssh-rsa AAAAB3NzaC...
Let's set up a local repository mirror:
# su - git git$ mkdir repos git$ cd repos git$ git clone --mirror http://github.com/openstack-dev/devstack.git
In order to tell the wrapper script that it should perform the automatic update logic on this repository, we need to touch the appropriate flag file:
git$ touch devstack.git/git-auto-update
If we then attempt to clone that repository:
lars$ git clone git@localhost:devstack.git
The wrapper script will check for the presence of that flag file, and
if it exists it will first perform a
git remote update before
responding to the
clone operation. This ensures that any new
objects are fetched, while ensuring fast transfer of objects that are
already available locally. The output we see after running the above
git clone looks something like:
Fetching origin From http://github.com/openstack-dev/devstack 8ce00ac..0ba1848 master -> master First, rewinding head to replay your work on top of it... Fast-forwarded master to 0ba18481672964808bbbc4160643387dc931c654.
The first three lines are the result
git remote update operation in
our cache repository.