Subject: Re: Remote operations synchronization, and hooks

From: Ilari Liusvaara <[email-masked]>
Date: Wed, 3 Mar 2010 01:43:21 +0200

On Tue, Mar 02, 2010 at 12:09:46AM -0500, Eli Barzilay wrote:
> Is there any kind of synchronization with remote operations?  That is,
> can there be any race conditions if multiple clients connect?  I'm
> assuming that such operations are safe, but I couldn't find a place
> with a concrete description.

With respect to Git itself, each ref update is atomic and happens as
client intended or does not happen at all. Ref updates within push
are independent. 

Thus, Git remote ops themselves are safe from races (with exception of
forced push, where race condition can lead to other client's changes
being lost).

> More specifically, I'm wondering about writing hooks (specifically, a
> `post-receive' hook), and it would make things convenient if I knew
> that it was called synchronously.

AFAIK, there can be multiple post-receives running simulataneously.

> And a related question: is there somewhere a summary of how the hooks
> are called for each operation?  The githooks man page specifies some
> of the relationships but a list with how each operation perform its
> work would be much more convenient to read through.  For example, if a
> remote update had a list of operations with "grab lock" in the
> beginning and a "release lock" after running the `post-receive' hook,
> then I wouldn't have the above question.

There are no such locks. I think the operation sequence goes as follows
(reading the source code):

1) List of modifications to do is received.
2) If additional objects are needed, pack is received and installed/unpacked.
3) pre-receive is run. If it fails, whole push is aborted.
4) For each ref pushed, do:
4a) update hook for that ref is run. If it fails, skip the ref.
4b) Do atomic compare-and-swap on ref.
5) Run post-receive hook.
6) Run post-update hook.

No locking there.

>  Also, it's unclear how
> `post-update' is related to `post-receive' -- there's one comment in
> the man entry for the former that makes it sound like it is supersedes
> by the latter, but there's nothing explicit about it.

They both execute after push has completed. Interfaces are different but
that's about it. post-receive gets old and new values, post-update only
ref names.

-Ilari