views:

349

answers:

1

Is it possible to write some manner of hook in mercurial that will reject changesets that effect a specific named branch in a repository?

We have a managed project and would like to allow any developers to push their changes to our repository so long as they are in their own named branch. This allows us to manage a single buildbot and a shared sandbox in the same repository (by keeping branches separate). We'd like to block any attempts to write to the default branch from outsiders (we would, internally, merge their branches over).

We're looking at using the pretxnchangegroup hook, but this has 2 concerns:

1) A user can push changes using any username; we basically only have an http-auth protecting the repository by requiring any username or password to actually connect to the repo, but it doesn't check the usernames in the commit to make sure they match the account used to push.

2) Lets say a user has done right and developed in a branch, but then they do one last commit on the default branch. The hg push fails. What does the developer do at this point to fix their push?

Any thoughts?

+1  A: 

Yeah, you can do this pretty easily with the pretxnchangegroup like you figured. I'll do it in shell, but it'd be in-process (and thus faster) if you do it in python.

Set up something like this as your pretxnchangegroup:

#!/bin/sh
for thenode in $(hg log -r $HG_NODE:tip --template '{node}\n') ; do
     if [ $(hg id --branch -r $thenode) = "default" ] ; then
          echo Commits to default branch are not allowed -- bad changeset $thenode
          exit 1
     fi
done

That makes sure that none of the arriving changesets are on branch "default".

Regarding concern 1: If you're running behind apache you'll have access to the usual CGI variables, so you can check $REMOTE_USER to make sure it matches the branch name if that's something you want to try to enforce.

Regarding concern 2: If a user sees the message that they're pushing an invalid changeset, then they'll just have to push the rest of them using push -r and they can strip or modify their changeset on default later.

Lastly, have you considered just having a separate clone for the auto-builds / main branch? Let everyone push into the staging repo, and let only the buildmaster pull approved changesets from staging into auto-build when s/he is happy with them? You get the same workflow you have now (waiting for a builder to merge), but it's much less hassle.

Ry4an