On 1/5/2011 3:13 PM, Jeff King wrote:
On Wed, Jan 05, 2011 at 03:53:25PM -0500, Jeff King wrote:
If both fetch processes try to update the same ref at the same time,
one will get the lock and continue, and the other will crash with an
error (because the lock was busy). If one is slightly slower than the
other, they will probably update the refs twice, with the slower fetch
updating what the faster one had just updated. :-)
I assumed it would take the "old" value at the very beginning of the
fetch (before talking with the remote), and then see that the ref was
changed under our feet. Or does it simply do it at the end?
Hmm. Weirder even, builtin/fetch.c:s_update_ref takes a "check_old"
flag, and we do always use it for branch updates. But not for tag
updates. I can't think of why. The code blames all the way back to the
original builtin-fetch.
Anyway, when we do check, we check the value from the beginning of the
fetch. So you can get lock conflicts. For example, doing this:
mkdir repo&& cd repo&& git init
echo contents>foo&& git add .&& git commit -m one
git update-ref refs/remotes/origin/master refs/heads/master
git remote add origin some-remote-repo-that-takes-a-few-seconds
xterm -e 'git fetch -v; read'& xterm -e 'git fetch -v; read'
I.e., putting some cruft into the ref and then updating it. One fetch
will force-write over the ref properly:
+ ac32203...4e64590 master -> origin/master (forced update)
but the other one will barf on the lock:
error: Ref refs/remotes/origin/master is at 4e6459052ab329914c7712a926773e566b8c821d but expected ac32203727daa3bcb5fc041786aa45adbbe86299
...
! ac32203...4e64590 master -> origin/master (unable to update local ref)
Interestingly, in the case of ref _creation_, not update, like this:
mkdir repo&& cd repo&& git init
git remote add origin some-remote-repo-that-takes-a-few-seconds
xterm -e 'git fetch -v; read'& xterm -e 'git fetch -v; read'
then both will happily update, the second one overwriting the results of
the first. It seems in the case of locking a ref which previously didn't
exist, we don't enforce that it still doesn't exist.
I wonder if we should, but perhaps there is some corner case I am not
considering. The code is in lock_ref_sha1_basic, but blaming didn't turn
up anything helpful.
-Peff
This was actually the case in my test. Updates to the mirror are always
new branches except for master. The only pre-existing branch that might
get updated is master, but in that test it didn't. The new branches and
tags were updated. The new tags always point to the new branches. I'm
running 1.7.1 on both servers.
v/r,
Neal
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html