If you’re managing multiple mercurial repositories, it’s nice to see them all in one place, using a simple web-based repository browser. There’s various ways to publish mercurial repositories, but hgwebdir
is the only method that supports multiple repos. Since I prefer fastcgi and nginx, I decided to use hgwebdir.fcgi
, which unfortunately isn’t documented on the mercurial wiki.
hgweb.config
Let’s start by creating hgweb.config
, which tells hgwebdir
where the repos are and what the web UI should look like.
[paths] /REPO1NAME = /PATH/TO/REPO1 /REPO2NAME = /PATH/TO/REPO2 [web] base = style = monoblue
There’s a few different included themes you can choose from, I like the monoblue
style. The empty base=
line is apparently required to make everything work.
hgwebdir.fcgi
Next, make a copy of hgwebdir.fcgi
, which in Ubuntu can be found in /usr/share/doc/mercurial/examples
. Below is a simplified version with all comments removed. The one line you may want to change is the path to hgweb.config
on the server, but I’ll assume you’ll want it in /etc/mercurial
.
from mercurial import demandimport; demandimport.enable() from mercurial.hgweb.hgwebdir_mod import hgwebdir from mercurial.hgweb.request import wsgiapplication from flup.server.fcgi import WSGIServer def make_web_app(): return hgwebdir("/etc/mercurial/hgweb.config") WSGIServer(wsgiapplication(make_web_app)).run()
hg_server.conf
This is a simple nginx fastcgi config you can modify for your own purposes. It forwards all requests for hg.DOMAIN.COM
to the hgwebdir.fcgi
socket we’ll be starting below.
server { listen 80; server_name hg; server_name hg.DOMAIN.COM; access_log /var/log/hg_access.log; error_log /var/log/hg_error.log; location / { fastcgi_pass unix:/var/run/hgwebdir.sock; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; } }
The hg_server.conf
file will need a link from /etc/nginx/sites-enabled
to its location in /etc/nginx/sites-available
, assuming that you’re using the default nginx config which includes every server conf found in /etc/nginx/sites-available
.
fab hgweb restart_nginx
To make deployment easy, I use fab, so that if I make any changes to hgweb.config
or hg_server.conf
, I can simply run fab hgweb restart_nginx
. For starting hgwebdir.fcgi
, we can use spawn-fcgi
, which usually comes with lighttpd, so you’ll need that installed too.
hgweb
copies hgweb.config
and hgwebdir.fcgi
to appropriate locations on the server, then starts the fastcgi process with a socket at /var/run/hgwebdir.sock
.
restart_nginx
copies hg_server.conf
to the server and tells nginx to reload its config.
def hgweb(): env.runpath = '/var/run' put('hgweb.config', '/tmp') put('hgwebdir.fcgi', '/tmp') sudo('mv /tmp/hgwebdir.fcgi /usr/local/bin/') sudo('chmod +x /usr/local/bin/hgwebdir.fcgi') sudo('mv /tmp/hgweb.config /etc/mercurial/hgweb.config') sudo('kill `cat %s/hgwebdir.pid`' % env.runpath) sudo('spawn-fcgi -f /usr/local/bin/hgwebdir.fcgi -s %s/hgwebdir.sock -P %s/hgwebdir.pid' % (env.runpath, env.runpath), user='www-data') def restart_nginx(): put('hg_server.conf', '/tmp/') sudo('mv /tmp/hg_server.conf /etc/nginx/sites-available/') sudo('killall -HUP nginx')
Once you’ve got these commands in your fabfile.py
, you can run fab hgweb restart_nginx
to deploy.
hgrc
Now that you’ve got hgwebdir.fcgi
running (you can make sure it works by going to http://hg.DOMAIN.COM), you’ll probably want to customize the info about each repo by editing .hg/hgrc
.
[web] description = All about my repo contacts = Me
And that’s it, you should now have a fast web-based browser for multiple repos 🙂