SVN did a great job for me for at least four years now. Lately, I stumbled upon Mercurial and decided to have a closer look. It turned out that Mercurial (also called “hg”) comes with some great advantages, namely:
- Not a “Version Control System” (VCS), but a “Distributed Version Control System” (DVCS) enabling you to check in changes locally (offline, without an internet connection). The advantages of this one are also discussed in detail in PEP 374 (Python Foundation).
- Available in pure Python, therefore installable on a standard shared web server without root access (not a virtual server, just a “web host”). Thereby cutting my costs of maintaining a root server on my own or being charged by a specialized host for an SVN/VPS plan.
This post is a small guide on how to accomplish the mission of installing Mercurial (the pure Python version) on a shared web host. In this exemplary case a “WebPack Pro” that we rent from our ISP of choice, HostEurope, is going to be used. However, what is described herein should basically work for any web hosting plan that fulfills the following requirements. This article is therefore most interesting for people who already own a shared web hosting plan and wish to use that plan for hg hosting also.
Requirements
- Source version of Mercurial
- A shared web server at an arbitrary web host enabling execution of CGI scripts written in Python (HostEurope provides Python 2.4 which appears to be sufficient).
mod_pythonormod_wsgi(better).- SSH access to that host. This is required to setup Mercurial on your shared web server. No need for root privileges.
Installation (Step by Step)
- Unpack the Mercurial source tarball on your local system.
- Create a temporary directory on your web server and transfer the extracted Mercurial source tree to that directory. You can do so via SSH or FTP.
- SSH into the server (if you did not so already) and create a top-level directory named “python”. This is going to hold all the Python modules you would like to use, but which are not currently installed on the server’s root Python distribution.
- Change to the Mercurial source directory and build the module in pure Python mode (instructions adopted from Mercurial Wiki) :
$ python setup.py --pure build_py -c -d . build_ext -i build_mo --force
- Likewise, install the module. Here, it is essential to enter the correct prefix path, as you want an alternate installation following the prefix scheme, not a standard installation. Please specify the path to your “python” directory, which you created in step 3 (in my case this is “../../python”):
$ python setup.py --pure install --prefix ../../python --force
- If everything went well
setup.pyhas installed the Mercurial module files topython/lib/python2.4/site-packagesand thehgbinary topython/bin. - In order to get the
hgbinary running via SSH you have to export your customPYTHONPATHso Python knows where to look for the hg modules. Via SSH go to your home directory on the web host and create a.bash_profilefile as follows:$ cd ~ $ touch .bash_profile
Open the file in a text editor and add the following line to it (adjust the path so that it fits your configuration):
export PYTHONPATH=/is/htdocs/wpXXXXX_XXX/python/lib/python2.4/site-packages
In order to make
hgaccessible from any directory within the shell, add the following line (adjust path corresponding to your environment again):export PATH=/is/htdocs/wpXXXXX_XXX/python/bin:$PATH
- Logout and login again via SSH. Type
hg. If you get the Mercurial Distribution SCM help screen you now have finished installation and are ready to go for setting up Mercurial web access.
Setting up hgwebdir.cgi
- First of all, create a directory on your webspace for hg. This directory must be reachable via HTTP. You may also want to set up a subdomain, e.g. hg.yourdomain.com and link that to your hg web directory.
- Get hgwebdir.cgi from the root of the Mercurial source tree or download hgwebdir.cgi from the Mercurial website, upload it to your hg directory and rename it to
index.cgi. - Make sure your web host is configured appropriately to handle .cgi files and index.cgi files. (You should be able to configure these settings in the scripts settings of your ISP’s administrative UI.)
- Open index.cgi using your text editor of choice. It is a good idea to check the script environment statement that is located in the first line of the file. It should look like the following:
#!/usr/bin/env python
This should work on most servers. However, if your python binary is not linked (or located) in /usr/bin/python you may have to correct for this.
- Find the following comment
# enable importing on demand to reduce startup time. Beneath the comment line there should be two commented lines. Change these lines to something like this:import sys sys.path.insert(0, "/is/htdocs/wpXXXXX_XXX/python/lib/python2.4/site-packages")
Replace the absolute path to the site-packages directory with your own one.
- If everything works as intended, the script should now be callable via HTTP. Enter the address of your hg web directory into your web browser and check whether the script runs correctly.
Setting Up Your First Repository and Configuring hgweb.config
- Via SSH you can setup a first test repository like this:
$ cd /path/to/www/hg $ hg init test
hg will create a directory named
testand place a.hgsubdirectory in it containing repository-specific configuration and payload data. hgwebdir.cgihas to know which repositories to serve. You tell this by creating a file namedhgweb.config. Simply put the config file into the directory ofhgwebdir.cgi.- Open the config file with a text editor and add the following lines:
[paths] test=test
Note: more info on how to configure
hgwebdir.cgican be found on HgWebDirStepByStep (in the Mercurial Wiki). - Finally, the repository itself needs some configuration. In
test/.hgcreate a new file namedhgrcand add the following lines to it:[ui] user = Firstname Lastname
[web] push_ssl = false allow_push = * This will register a first user, allow for HTTP pushing, and allow pushing for everyone (we will take care of security later on).
- That’s it. Your first repository is served via Mercurial on your shared web host.
Testing the Whole Thing
You may want to do a simple test to check whether your repository is working and you are able to pull and push changes as intended. You can do so by opening a terminal and type something like the following:
$ hg clone http://hg.yourdomain.com/index.cgi/test $ cd test $ touch testfile $ echo "This is just a test" > testfile $ hg add testfile $ hg commit -m 'Testing...' -u username $ hg push
If everything went right, this should add the file testfile to the repository root and push it to the web server.
For now, you hopefully have a working Mercurial repository directory service up and running on your shared web host. However, there are two major flaws. Firstly, the repository address is not as beautiful as it could be, because of the index.cgi contained in any path. Secondly, the repositories are accessible for everyone. We will fix these issues in what follows.
Beautifying hgwebdir Paths
In order to strip index.cgi from the repository URLs we will have to use mod_rewrite (and your server needs to support that apache module).
Go to your hg webdir root directory and create a file named .htaccess. Open the file in a text editor and add the following lines:
# Taken and adapted from http://www.pmwiki.org/wiki/Cookbook/CleanUrls#samedir
# Used at http://ggap.sf.net/hg/
RewriteEngine On
#write base depending on where the base url lives
RewriteBase /
RewriteRule ^$ index.cgi [L]
# Send requests for files that exist to those files.
RewriteCond %{REQUEST_FILENAME} !-f
# Send requests to hgwebdir.cgi, appending the rest of url.
RewriteRule (.*) index.cgi/$1 [QSA,L]
Note: this apache script rewrites URLs so that any directory queried in the form hg.yourdomain.com/directory is automatically rewritten to hg.yourdomain.com/index.cgi/directory internally. Consequently, users can omit disturbing repetitive typing of index.cgi in hg repository URLs. Please note that you may have to adapt RewriteBase to your specific server environment. If you do not serve hg repositories via a subdomain you should specify the relative base directory of your hg webdir here instead (this may e.g. be /hg if you serve hg repositories via www.yourdomain.com/hg). The approach is also discussed in PublishingMultipleRepositories on the Mercurial Wiki.
Securing hgwebdir
You can secure your hg web directory in multiple ways. You may want to allow pulling by anyone and pushing only to specific core developers. Detailed information about hg authentication can be found on PublishingMultipleRepositories.
However, my intention is to have private repositories, which I share only with my friends (no public pulling). Me and my friends will use HTTP authentication and I will create a user and password for everyone who is allowed to pull and push. Fortunately, this scenario is relatively simple to configure for everyone who knows about apache authentication configuration using htaccess files.
First of all, use htpasswd to create a password file for hg users. Name the file .hgusers and place it in a location that is not accessible via HTTP. For example, you may want to do it this way:
$ cd /private-path $ htpasswd -c hgusers username Enter password twice, etc...
Since we already have a .htaccess file, it is even more simple. Re-open the file using a text editor and add the following lines at the end of the file:
# Authentication AuthName "Please enter your username and password." AuthType Basic Require valid-user AuthUserFile /is/htdocs/wpXXXXX_XXX/.hgusers
Please change the path to the .hgusers file conforming to your server environment.
Congratulations! You now have a running, secured, beautified, pure-python hg repository server on your cheap web hosting account.
Remarks
Building Mercurial in pure Python may have drawbacks in terms of performance. This has more thoroughly been discussed on the Mercurial mailing list, see mailing list archive on pure python Mercurial.








