Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mercurial hook not executing properly

This should be a very simple thing to have run, but for some reason it won't work with my Mercurial repository. All I want is for the remote repo to automatically run hg update whenever someone pushes to it. So I have this in my .hg/hgrc file:

[hook]
changegroup = hg update

Simple, right? But for some reason, this never executes. I also tried writing a shell script that did this. .hg/hgrc looked like this:

[hooks]
changegroup = /home/marc/bin/hg-update

and hg-update looked like this:

#!/bin/sh
hg help >> /home/marc/works.txt;
hg update >> /home/marc/works.txt;
exit 0;

But again, this doesn't update. The contents of hg help are written out to works.txt, but nothing is written out for hg update. Is there something obvious I'm missing here? This has been plaguing me for days and I just can't seem to get it to work.

Update

Okay so again, using the -v switch on the command line from my workstation pushing to the remote repo doesn't print any verbose messages even when I have those echo lines in .hg/hgrc. However, when I do a push from a clone of the repo on the same filesystem (I'm logged in via SSH), this is what I get:

bash-3.00$ hg -v push ../test-repo/
pushing to ../test-repo/
searching for changes
1 changesets found
running hook prechangegroup: echo "Remote repo is at `hg tip -q`"
echo "Remote repo wdir is at `hg parents -q`"
Remote repo is at 821:1f2656753c98
Remote repo wdir is at 821:1f2656753c98
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
running hook changegroup: echo "Updating.... `hg update -v`"
echo "Remote repo is at `hg tip -q`"
echo "Remote repo wdir is at `hg parents -q`"
Updating.... resolving manifests
getting license.txt
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Remote repo is at 822:389a6c7276c6
Remote repo wdir is at 822:389a6c7276c6

So it works, but again only when I push from the same filesystem. It doesn't work if I try pushing to the repo from another workstation over the network.

like image 940
Marc W Avatar asked May 11 '09 15:05

Marc W


3 Answers

Well, after going through the same steps of frustration as Marc W did a while ago, I finally found the solution to the problem, at least when remote serving is done with the hgwebdir WSGI script.

I found out that when using this kind of remote push via HTTP or HTTPS, Mercurial simply ignores everything you write into the .hg/hgrc file or your repository. However, entering the hook in the hgwebdir config does the trick.

So if the bottom line in your hgwebdir.wsgi script is something like

application = hgwebdir('hgweb.config')

the [hooks] config section needs to go into the mentioned hgweb.config.

One drawback is that these hooks are executed for every repository listed in the [paths] section of that config. Even though HG offers another WSGI-capable function (hgweb instead of hgwebdir) to serve only a single repository, that one doesn't seem to support any hooks (neither does it have any config). This can, however, be circumvented by using a hgwebdir as described above and having some Apache RewriteRule map everything into the desired subdirectory. This one works for me:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/reponame
RewriteRule ^(.*)$ reponame/$2 [QSA]

Have fun using your remote hooks over HTTP :D

like image 124
smf68 Avatar answered Nov 13 '22 22:11

smf68


I spent some time researching this myself. I think the answer to problem is described concisely here:

Output has to be redirected to stderr (or /dev/null), because stdout is used for the data stream.

Basically, you're not redirecting to stderr, and hence polluting stdout.

like image 29
Barry Avatar answered Nov 14 '22 00:11

Barry


First of all, I want to correct a few comments above.

  • Hooks are invoked also when pushing over file system.
  • It is not necessary to keep the hook in the repo on which you want them to operate. You can also write the same hook as in your question on the user end. You have to change the event from changegroup to outgoing and also to specify the URL of remote repo with the -R switch. Then if the pushing user has sufficient privileges on the remote repo, the hook will execute successfully.

.hg/hgrc

[hooks]
outgoing = hg update -R $HG_URL

Now towards your problem.... I suggest creating both prechangegroup and changegroup hooks and printing some debugging output.

.hg/hgrc

[hooks]
prechangegroup = echo "Remote repo is at `hg tip -q`"
                 echo "Remote repo wdir is at `hg parents -q`"
changegroup    = echo "Updating.... `hg update -v`"
                 echo "Remote repo is at `hg tip -q`"
                 echo "Remote repo wdir is at `hg parents -q`"

And also push with the -v switch, so that you may know which hook is running. If you still can't figure out, post the output. I might be able to help.

like image 3
Aamir Avatar answered Nov 13 '22 23:11

Aamir