Version Control with Mercurial, Apache and TortoiseHG

by posted on May 13th, 2010 in Development

[Update (Jan 2013): with GitHub, BitBucket and other free services available, it may be easier and safer to keep extra copies of your repositories offsite. I have limited experience with those services, so this should not be considered an endorsement. However, I would strongly suggest that you research them before deciding to create your own server. With the spreading popularity of distributed version control systems, some companies are creating Mercurial and Git tools that can run on your own servers (if your code must remain behind a company firewall).]

I recently started a new software project – a game engine.  Even though the current development team is a single programmer, I need a version control system (VCS) that will:

  • allow me to manage multiple repositories (with independent branching, tags, etc.)
  • allow me to synchronize code across hardware and software platforms
  • backup the entire repository on multiple machines (for safety reasons)
  • easily allow me to add/manage contributors in the future

After some research, I chose Mercurial.  If you are reading this article, you have also chosen Mercurial.  If you do not know what Mercurial is, or are unfamiliar with distributed version control systems, go here.  The rest of you can continue reading.

Introduction

This tutorial describes the steps I took to configure Mercurial for my development environment.  My main computer is a Windows PC running Windows XP Pro.  It is my primary development machine and will also host my web server.  My secondary development machine is a Macbook Pro running OSX 10.5.8.  Both my PC and Macbook are connected on the same LAN.

Mercurial, by itself, is very easy to configure and use.  It comes with a built in web-server.  However, it offers no control over who can access your repositories.  By using your own web-server, you gain the ability to encrypt your data as well as control user permissions.  Additionally, you gain the ability to host multiple repositories in a single, convenient location.  Unfortunately, web-servers are notoriously difficult to configure.  Compatibility issues, config files, and even version numbers can produce nonsensical errors that make debugging a nightmare.  I may not be able to help you configure your existing web-server (for that go here).  However, I can show you how to set up a new server that works.

Getting Started

Ingredients:

  • TortoiseHG v1.0.2:  This is a free Windows UI for Mercurial v1.5.2.  It allows us to call Mercurial commands from the Windows Explorer instead of the command line.
  • Mercurial v1.5.2:  This is the Windows command line version of Mercurial.  This is independent of TortoiseHG (which comes with its own Mercurial installation).  We need this because we need to extract some files from the installation.  It will be deleted later.
  • Python v2.6:  This is the scripting language that will be used for our repository-hosting scripts.  I could not get things working with v2.5, and v2.6 fixed some problems.
  • XAMPP v1.7.3:  This is an easy-to-configure Apache web-server that we will use to host our repository.  Note that XAMPP is generally intended for closed development environments.  The default installation is not secure.  You can plug some of the security holes by following the instructions here.  We are using XAMPP for convenience and because a more secure solution is not currently necessary.  The lessons learned in this tutorial should also extend to other, production level, Apache servers.

Install everything then configure your TortoiseHG user – but do not create your repository yet – using the instructions here.

Creating the central repositories

My development environment and server are hosted on the same machine.  However, I do not want my development repository to be the same as the central repository.  Instead, I created a separate folder outside of my development workspace and outside of my web-server to hold it.

I should probably emphasize that I work with multiple Mercurial repositories.  One for each project.  This allows me to tag and branch them individually.  All of my Mercurial repositories are located at:

C:\STEVEN-VCS\hg

However, my development repositories (clones of the central repositories) are located at various locations on my computer.

ex.

C:\STEVEN-DEV\dev\libs\somelibrary
C:\STEVEN-DEV\dev\apps\NewApplication

I suggest using folder and file names that do not contain spaces.  Spaces sometimes cause problems in scripts, console commands and web addresses.  You will save yourself some grief by avoiding them.

Once again, instructions on creating and cloning repositories with TortoiseHG can be found here.

Sharing your repositories

Before we start, I should point out that Mercurial likes to encrypt transfer data (using SSL).  You can disable this function in a config file.  However, it is just as easy set up your server for https and enjoy that extra level of security.  Instructions for configuring https on XAMPP can be found here.

Ok, let’s get started.

Create a folder called hg in your htdocs

ex.

<xampp install>\htdocs\hg

This folder will hold the script that hosts our repositories.  You can control who has access to this by creating a .htaccess file (the creation of which is outside the scope of this tutorial).

All of our repositories are hosted by a single script and config file.

Download the script template from here (Edit: the script template moved, so I have placed a copy here.  Make sure that you change the .txt extension to .cgi) and place it in the folder.  Also, create a file called hgweb.config in that same folder.  Your directory should now look like:

<xampp install>\htdocs\hg\hgwebdir.cgi
<xampp install>\htdocs\hg\hgweb.config
<xampp install>\htdocs\hg\.htaccess

Open hgwebdir.cgi for editing.

Modify the first line to point to our installation of Python 2.6. (Note: depending on your environment, this may not make any difference at all.)

ex.

Replace

#!/usr/bin/env python

with

#!C:/Python26/python.exe

On line 7, replace

#sys.path.insert(0, "/path/to/python/lib")

with something like

sys.path.insert(0, "<mercurial lib directory>")

But wait!  What’s this?

Remember how I told you to install both TortoiseHG and Mercurial?  You will now find out why.

Find your mercurial installation (NOT TortoiseHG).  Unzip the file library.zip into the folder you create for <mercurial lib directory>.  Then copy the templates folder, from your Mercurial install, into <mercurial lib directory>.  We need to use the files that are included with the Mercurial install because the files that are included in the TortoiseHG install do not work.  I have not run a diff on them to see what the difference is.  However, I have noticed that while unzipping the TortoiseHG library.zip file, there were several unusual prompts that appeared that were not in the Mercurial library.zip.  Feel free to uninstall Mercurial v1.5.2 now.  We only need TortoiseHG on the system.

Back to our hgwebdir.cgi.  Make the appropriate changes to

sys.path.insert(0, "<mercurial lib directory>")

Save and close the file.

Open the hgweb.config file and create a path to each repository.  Your file will look something like this.

[paths]
kern = C:/STEVEN-VCS/hg/kern
<repo name> = <repo directory>
hid = C:/STEVEN-VCS/hg/hid

We are almost done.  Now we need to configure the htdocs/hg folder to host our script.

Open the file xampp/apache/conf/httpd.conf and create a directory module as follows

# Some comment so that you can find these settings later
ScriptAliasMatch ^/hg(.*) <xampp>/htdocs/hg/hgwebdir.cgi$1
<Directory <xampp>/htdocs/hg>
  Options ExecCGI FollowSymLinks
  SSLRequireSSL
</Directory>

Replace the <xampp> with the exact directory.

The ScriptAliasMatch line allows us to access our script without actually typing the script name.  So instead of visiting https://localhost/hg/hgwebdir.cgi, we can visit https://localhost/hg/

This becomes more intuitive when accessing repositories because we can access them using https://<host>/hg/<repo name> instead of https://<host>/hg/hgwebdir.cgi/<repo name>

You will need to restart your server for the configuration to take effect.

Once the server has been restarted, visit https://localhost/hg/

You should see a page listing your Mercurial repositories.

Notice that the Descriptions and Contact fields are “unknown”.  This is because we still have to…

Configure our repositories

To configure your central repository simply go to the repository directory and open the .hg folder.

ex.

C:\STEVEN-VCS\hg\kern\.hg

Create a file called hgrc

This file will allow us to set the repository’s web properties.

ex.

[web]
allow_archive = bz2 gz zip
allowpull = true
allow_push = *
contact = Steven Smith
description = Orion Kernel
  • allow_archive allows a user to download a copy of the current revision in the listed formats.
  • allow_pull allows other mercurial users to clone and pull from the repository.
  • allow_push allows specific users to push their changes to the repository.  Push is currently enabled for everyone because I control who can access the repo through the server.
  • contact and description are strings that display on the website repository list.

Conclusion

This tutorial was a very brief introduction to hosting your own Mercurial server on Windows XP using TortoiseHG and XAMPP (Apache).  I would recommend reading about Mercurial on the wiki to learn more about managing users and configuring the server and repository.  I would also recommend reading the excellent Mercurial guide by Joel Spolsky.

Hopefully this tutorial will help others avoid much of the frustration I endured when configuring my own Mercurial server.

If you have any questions, feel free to contact me.

Tags:

  • http://twitter.com/ithoughts_de ithoughts_de

    Nice mercurial on windows guide! I like this!

  • sbsmith

    I hope people find it helpful. Sometimes it is difficult to get open-source projects working on their secondary platforms.

  • chao

    It's very clear and very helpful.
    It worked for me.
    Thank you very much.

  • epu

    I pulled the hg-stable source (1.5.4) and tried to set this up, but it looks like hgwebdir.cgi doesn't exist any more. Followed the link from your page to the template, and it's broken.

    No luck finding the current way to do this on the hg wiki. If you happen to know, can you please update?

  • sbsmith

    I have updated the post with a link to an example hgwebdir. I hope that helps.

  • sbsmith

    You are welcome. I'm glad it helped.

  • fatkun

    fatkun:Thank you~~It works!

  • sbsmith

    You're welcome.

  • Shaf_inet

    Out of all the instruction this work the best for me. Much Thanks!

  • Gian

    how come mine says “access forbidden!” did i miss something?
    I used python 3.1

  • Gian

    ok. found it.. it seems that i have problems with my certificate.

  • Gian

    ok. found it.. it seems that i have problems with my certificate.

  • Hanbaral

    Thank you!!

  • Felipe Canaviri

    I had some compatibility versions issue between Mercurial and Python. At the end, I used Mercurial 1.8 and Python 2.6.6, it works very well.

    Thanks so much for sharing this tutorial.

  • Whistleofmysong

    Thank you very much

  • Lee

    Thank you so so much. It worked so well. This is the absolute guide that made my setup work! I almost gave up on setting up this stuff.

    Setup:
    - Windows Server 2003 R2
    - python-2.6.6.msi
    - mercurial-2.0.2.win32-py2.6.exe
    - xampp-win32-1.7.7-VC9-installer.exe
    - I did not install TortoiseHg. :)

    Configuration of hgweb.cgi:
    - used hgweb.cgi instead of hgwebdir.cgi
    - used: sys.path.insert(0, “C:/Python26/lib/site-packages/mercurial”)
    => information acquired from executing: hg debuginstall
    ** Checking installed modules (C:Python26libsite-packagesmercurial)… **