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.
[sourcecode language=”python”]
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()
[/sourcecode]
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.
[sourcecode language=”python”]
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’)
[/sourcecode]
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 🙂