git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Shawn O. Pearce" <spearce@spearce.org>
To: Joshua Jensen <jjensen@workspacewhiz.com>
Cc: "git@vger.kernel.org" <git@vger.kernel.org>
Subject: Re: Deleting of the specified ref during the post-receive hook
Date: Tue, 21 Sep 2010 07:50:14 -0700	[thread overview]
Message-ID: <20100921145014.GH32601@spearce.org> (raw)
In-Reply-To: <4C98C3F2.9050006@workspacewhiz.com>

Joshua Jensen <jjensen@workspacewhiz.com> wrote:
>  I've recently asked whether there was a public script to act as an  
> automatic 'maintainer', something akin to Gerrit's push always  
> succeeding without having to pull first when using Git as a central  
> repository.  I received a number of suggestions, and I have begun trial  
> implementations.
>
> My current line of thought has an auto-merging script that monitors the  
> refs/for/ namespace (similar to Gerrit) and then applies --no-ff merges  
> to the appropriate branch.  For instance, when the user pushes to  
> refs/for/master, the post-receive hook creates a secondary ref called  
> refs/for/master-SHA1-timestamp and then deletes the refs/for/master ref:
>
> #!bin/sh
> # post-receive hook
> while read oldrev newrev ref
> do
>     case $ref in
>         refs/for/*)
>             timestamp=`date +%s`
>             `git update-ref $ref-$newrev-$timestamp $newrev`
>             `git update-ref -d $ref`

FWIW, you don't need `` around the git update-ref calls, because you
aren't using the output of the command as input to another command.

> If you'll pardon my lacking shell script skills (I'm open to learn!), my  
> primary question concerns safety.  When receiving a ref via an SSH-based  
> server (which happens to be Gitolite, but I don't think that is relevant  
> here), is the post-receive hook guaranteed to be run in a lockstep  
> manner?

No.  If there are two concurrent pushes occurring, the script may
execute in parallel.

But you'll actually get something much worse.  receive-pack will
create refs/for/master for the first user... and then might be put
to sleep while another user's receive-pack starts.  That second
user will see refs/for/master existing, and will fail their push
because their concept of $newrev doesn't match what is currently
at refs/for/master.  Then the first user wakes up, runs your
post-receive, and the ref is cleared.

The better strategy would be to use an update hook that refuses to
permit the creation of refs/for/master:

  #!/bin/sh
  ref=$1
  old=$2
  new=$3

  case $ref in
  refs/for/*)
    timestamp=`date +%s`
    git update-ref $ref-$new-$timestamp $new
    echo "Created $ref-$new-$timestamp"
    exit 1
    ;;
  *)
    exit 0
    ;;
  esac


By exit 1 here we refuse the push attempt, so receive-pack won't
create refs/for/master, and another user pushing won't see that
false failure.  However, unlike with Gerrit, every user is now going
to receive a push failure message because the hook has appeared to
reject the value, even though it accepted it.

> That is, if two people push to 'refs/for/master' at the same  
> time, is there a lock to process one user and then the other user?

There is, but only for the duration of the update hook.  So if you
used an update hook instead, one user would succeed with the push
and the other would get a lock failure, and would need to retry.

> Before I go too much deeper down this path, am I way off base here?

I'd have to ask why you are using gitolite and trying to abuse
git-receive-pack to do something that Gerrit does out of the box...

-- 
Shawn.

  reply	other threads:[~2010-09-21 14:50 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-21 14:40 Deleting of the specified ref during the post-receive hook Joshua Jensen
2010-09-21 14:50 ` Shawn O. Pearce [this message]
2010-09-21 15:55   ` Joshua Jensen
2010-09-21 16:00     ` Shawn O. Pearce

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100921145014.GH32601@spearce.org \
    --to=spearce@spearce.org \
    --cc=git@vger.kernel.org \
    --cc=jjensen@workspacewhiz.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).