I've got a nicely working recipe that I've been using for about a year
now where I specify my git repo using a local filesystem path:
set :repository, '/pub/git/project.git'
By local filesystem path, I mean a path that's local to the
deployment server, not my desktop development machine. There are some
nice side effects of this:
1. Clones during deployment are very, very fast: basically
instantaneous
2. No password prompts during clone, and no need to store my a private
key for repo access on the server either
3. Clones during deployment take up basically no disk space because
hard links are used instead of replicating the data
Here's an excerpt from the git-clone man page explaining what
happens here:
When the repository to clone from is on a local machine, this flag bypasses
normal git aware transport
mechanism and clones the repository by making a copy of HEAD and everything
under objects and refs
directories. The files under .git/objects/ directory are hardlinked to save
space when possible. This is
now the default when the source repository is specified with /path/to/repo
syntax
I also specify my branch in the old way, as a remote branch (no longer
supported):
set :branch, 'origin/master'
So this all works fine under Capistrano 2.2.0 (the latest available at
the time I wrote the recipe). I don't want my deployments breaking, so
I made a conscious decision to stay with 2.2.0 unless some compelling
reason arose. I'm looking at updating now because there might be some
other patches to Capistrano that I'm interested in getting accepted
(http://capistrano.lighthouseapp.com/projects/8716/tickets/61, for
instance).
Versions after 2.2.0 can't use this /foo/bar/baz repo pattern since
this commit:
http://github.com/jamis/capistrano/commit/ec9a7fa52c9f417a9a01a7e764b520be1ec32c5c
Basically, instead of running git rev-parse on the _local_ machine,
Capistrano started using git ls-remote to query the _remote_
machine. Fair enough; HEAD on your local machine might not mean the
same thing on the remote one.
This means that you have to change your /foo/bar/baz repos to
u...@machine:/foo/bar/baz, and also your branch specification needs
to change from origin/whatever to whatever (where in most cases
whatever will be master).
So that's fine, but in making this change I basically lose all three
benefits that I mentioned earlier on: clones are slower because they
now pass through the network transport layer (even if only on the
loopback interface), I either need to specify a passphrase during
clone or set-up a private key on the server, and my deployments now
use up more disk space (unless I use the :export_via option to blow
away the .git dir after cloning).
So after all that I finally get to the point of this message.
I'm looking for opinions on the best way to elegantly support /foo/
bar/baz style repos under versions of Capistrano post-2.2.0.
My two real options are:
1. Maintain a local fork of Capistrano that does what I want
If I do this the easiest course is probably just to copy the git.rb
file from Capistrano, modify it minimally (probably just patching the
query_revision method and little else), and make sure it gets required
before my deploy.rb is evaluated. By keeping a separate modified copy
of git.rb on hand it should be easier to update Capistrano if I ever
need to.
2. Patch Capistrano itself and submit upstream
This is the one I'm not sure about it because instead of minimal hacks
something generalized and robust would be required.
- special case handling in query_revision so that for /foo/bar/baz
repos we go back to the old behaviour of using git rev-parse?
- alternatively, for /foo/bar/baz repos we could call the equivalent
of git remote -v | grep origin | awk '{print $2}' or similar to get
the u...@machine:/foo/bar/baz form and continue on to the git ls-
remote code path (toy patch pasted at bottom of this message to
demonstrate what I am talking about).
- introduce an additional configuration variable, so we could have one
variable for specifying the repo as seen from the development machine
(u...@machine:/foo/bar/baz) and one for as seen from the deployment
machine (/foo/bar/baz); I don't really like this at all as it sounds
like exposing an implementation detail at the interface level and it
would differentiate Git from the other SCM modules in Capistrano.
Perhaps there are others but that's all that occurs to me now. Any
other ideas? Which idea is most likely to be useful to others and
accepted into Capistrano? I'm thinking that my second idea is the best
candidate so far. But if all this is going to be unpopular I'll just
do what I said above and use a local fork of git.rb. Before going any
further, I wanted to ask the group for feedback.
Thanks for letting me know what you think.
Cheers,
Wincent
P.S. Here's the toy patch: not even tested for syntax correctness;
it's just a demonstration of what kind of change _might_ be suitable:
diff --git