Quick Tip: Getting Started with Mercurial

From Aventine Solutions

Jump to: navigation, search

Mercurial is a good choice for a distributed revision control system, so I'm not going into the actual reasons to choose it. I did notice, however, that the instructions for setting it up with a centralized server using HTTP were very patchy and required a couple of days of hacking to get satisfaction; hence the reason for this article.

Contents

[edit] Goals

One of the advantages of a distributed repository approach is that they can be used in a number of collaborative scenarios and some of those may not even require a centralized server. If you're already OK with the later, then you don't need this article at all.

If you do want to have a more formalized central server to push/pull changes to/from and you want that protocol to be HTTP or HTTPS, then read on.

Another goal of mine was to feel satisfied I could get Mercurial working reasonably well in Eclipse the way I use Subversion doing most of my day to day stuff with the Eclipse GUI, and maybe only occasionally doing some housekeeping from the command line. The distributed repository approach means committing many changes to a local repository from Eclipse and occasionally pushing the sets of changes to the server, the push being also done from Eclipse. The cloning of repositories to other development workstations can be done using HTTP or HTTPS from that central server. That will be nice to collaborate across the cloud when firewalls and nasty proxies may get in the way.

Here, then, is the initial platform for this scenario:

  • Developer's workstation #1: MacOSX Leopard using the Eclipse Ganymede IDE.
  • Developer's workstation #2: Windows XP also using Eclipse Ganymede and Cygwin for the command line.
  • Mercurial Repository Server: Fedora 6 with Apache

Developer #1 and #2 will be able to push/pull changes through the central repository even when there are firewalls and a proxy (the latter may require authentication) between them.

[edit] Installing Mercurial

[edit] Windows

I use Cygwin on Windows XP, so installation is straightforward using the Cygwin package installer. Mercurial is written in Python, so Cygwin will determine the dependencies there if you don't already have it installed: Image:Screenshot-cygwin-setup-select-mercurial.JPG

Checking our work ...

% hg --version
Mercurial Distributed SCM (version 1.0.2)

Copyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

For when we make changes to our repositories in the future, we indicate our user name by creating a file .hgrc under our Cygwin home (not Windows home) directory which contains your user details as follows:

[ui]
username = Matthew Eichler <matthew.eichler@aventinesolutions.nl>

Alternatives ... a lot of Windows users say yikes, I hate Cygwin. This page gives you the alternative installs ... or you may download the source and build your own.

If you are going to use #Mercurial from Eclipse, the Cygwin version of Mercurial will not work because Eclipse will try to send Windows style paths to the Mercurial command. Instead, install the self-contained Windows distribution from Lee Cantey. (I have both installed so that I can use Mercurial from both the Cygwin command line and from Eclipse).

[edit] MacOSX

On Macintosh, I also use a convenient package installer, Fink:

  • In the Fink commnder, first do a Source Scanpackages then Source Utilities Index to get the most up-to-date listing.
  • Then, search for the Mercurial package and install either from source or binaries. The Python dependencies will also be installed if you don't already have them.

Image:Screenshot-fink-select-mercurial.png

Like we did on Windows ...

% hg --version
Mercurial Distributed SCM (version 1.0.1)

Copyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Also, just like Windows, we create an .hgrc in our home directory with our user details:

[ui]
username = Matthew Eichler <matthew.eichler@aventinesolutions.nl>

Again, maybe you're philosophically against using Fink, so consult this for alternatives.

[edit] Fedora

Once again, a package manager to the rescue, this time yum.

% su -
% yum install mercurial

Now checking what we have:

% hg --version
Mercurial Distributed SCM (version 0.9.3)

Copyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

From yumex, selection of the package looks like: Image:Screenshot-yumex-select-mercurial.png

[edit] Proxy Setup

Since we're going to use HTTP to access remote repositories, you will have to follow these instructions if you use any of the clients behind a proxy server.

[edit] Getting hgwebdir Going

Now there's a little work getting the HTTP/HTTPS interface to Mercurial repositories working, but I felt the added flexibility was worth it. The following assumes that the Fedora host is the server and already has Apache web server running on it, or that you know how to translate the setup for your particular distribution of Linux. Also, the user running Apache on my setup is apache and the group is also apache ... again, adjust this for your own particular setup.

[edit] Create a Test Respository

First, determine on the server where the home for the collection of Mercurial repositories will be. I choose /export/home/hg but something like /var/hg is also popular:

% su -
% mkdir /export/home/hg
% chown apache:apache /export/home/hg

We're going to create a test repository there for proving that our setup is working:

% su -
% cd /export/home/hg
% mkdir hgtest; cd hgtest
% hg init
# we're going to add some changes, so it's not a completely empty repo
% echo 'Hello World!' >> README.txt
% hg add README.txt
% hg commit -m 'this is the first change to my test repository'
% hg log
changeset:   5:11c41a5926be
tag:         tip
parent:      3:e768ae005b9e
user:        root@myfedoraserver.org
date:        Mon Nov 24 11:41:19 2008 +0100
summary:     this is the first change to my test repository
# now, fix all the permissions on this repository
% chown -R apache:apache .

There are some important things to note at this point. First of all, to initialize a new repository on the server, we had to have login access. Some might say this is a disadvantage to Mercurial. Second, apache will be the user accessing this repository through the web server and must own all the files. Finally, Mercurial created a subdirectory .hg which maintains metadata about the repository and we'll be adding to this later.

[edit] modpython_gateway.py

Get the modpython_gateway.py script from here and put him in the Mercurial home. No changes to this file are required:

% su -
% cd /export/home/hg
% wget http://www.aminus.net/browser/modpython_gateway.py\?format=raw ./modpython_gateway.py

[edit] hgwebdir.py

We are now going to expose our repository using CGI. There seems to be several ways to do this, but the one way that worked for me was the mod_python approach. Locate the hgwebdir.cgi and copy it into the Mercurial home (in my case, /export/home/hg), giving it the py extension instead of cgi.

Now we hack this Python script. Check that the imports match this:

from mercurial.hgweb.hgweb_mod import hgweb
from mercurial.hgweb.hgwebdir_mod import hgwebdir
from mercurial.hgweb.request import wsgiapplication

Uncomment this section so you'll get a full stack trace should something go wrong with the CGI interface:

import cgitb
cgitb.enable()

Now, we're going to add two new Python functions to this script, at the end:

def make_web_app():
    return hgwebdir("/export/home/hg/hgweb.config")

def gateway(environ, start_response):
    app = wsgiapplication(make_web_app)
    return app(environ, start_response)

You may download my version of the full script from here.

[edit] hgweb.config

Notice that the make_web_app() is configured with a file hgweb.config. We're now going to create this file in our Mercurial home /export/home/hg, and it simply contains a pointer to our collection of Mercurial repositories. As long as we create new repositories under /export/home/hg, they will automatically get picked up in the web interface:

[collections]
/export/home/hg = /export/home/hg

[edit] hgrc

Now, we're going to tweak some parameters for our test repository. Every time you add a new repository to your collection, you will have to do the same thing. Create a file hgrc in the .hg directory I mentioned earlier under /export/home/hg/hgtest:

[web]
contact = Aventine Solutions
description = testing Mercurial Web
style = gitweb
allow_push = *
push_ssl = false

In this case, we are allowing changes to be pushed from anyone that is authenticated by Apache and we are saying that not only HTTPS is required for pushing, but it is allowed from HTTP as well.

[edit] More Permissions

Now, fixing the permissions on all these files:

% su -
% cd /export/home/hg
% chown apache:apache hgweb.config hgwebdir.py modpython_gateway.py hgtest/.hg/hgrc
% chmod 755 hgwebdir.py modpython_gateway.py

[edit] Configuring Apache

The best approach to configure the Mercurial web interface for Apache is to give it it's own separate configuration file that will be included in the core Apache configuration when the server is restarted. In /etc/httpd/conf.d, create a file hg.conf with the following content:

<Location /hg>
  PythonPath "sys.path + [ '/export/home/hg' ]"
  PythonDebug On
  SetHandler mod_python
  PythonHandler modpython_gateway::handler
  PythonOption SCRIPT_NAME /hg
  PythonOption wsgi.application hgwebdir::gateway
  AuthType Basic
  AuthName "Aventine Solutions"
  AuthUserFile conf/httpd.passwd
  <LimitExcept GET>
    require user matthew
  </LimitExcept>
</Location>

After the last PythonOption, we are configuring the type of authentication Apache will be using. Whatever authentication and access control is supported by Apache is available, but in this case we have a password file in /etc/httpd/confg/httpd.passwd where there exists a user matthew and only he may do actions besides GET. Because GET is not limited, the public may access the web interface in a read-only mode and download files from the repository's contents.

Now, restart Apache:

% su -
% service httpd restart

[edit] Checking Your hgwebdir Installation

Try accessing your new configuration with the URL http://myserver.org/hg and you should see the home page as:

Image:Screenshot-firefox-mercurial-hgwebdir-homepage.png

If you click on our hgtest repository, you should see the details of this repository:

Image:Screenshot-firefox-mercurial-hgwebdir-hgtest-repository.png

[edit] Try Pushing and Pulling

This series of commands is from Cygwin Windows, but Mac users, you'll get the idea:

% cd /cygdrive/d/staging; mkdir hgtest; cd hgtest
# creating an empty repository
% hg init
# pulling changes from the server and updating
% hg pull http://myserver.org/hg/hgtest
% hg update
# making a change
% echo 'I''m making a change from Windows' >> README.txt
% hg commit -m 'I''m committing a change from Windows' >> README.txt
# pushing changes back to the server
% hg push http://aventinesolutions.mine.nu/hg/hgtest
# username and password will be asked for here

The more logical way to start, is to clone the repository from the server, make your changes and push occasionally:

% cd /cygdrive/d/staging; rm -rfv hgtest;
% hg clone http://aventinesolutions.mine.nu/hg/hgtest ./hgtest
# I've got a full copy now, let's make changes
% echo 'I''m making a change from Windows' >> README.txt
% hg commit -m 'I''m committing a change from Windows' >> README.txt
# pushing changes back to the server
% hg push http://aventinesolutions.mine.nu/hg/hgtest
# username and password will be asked for here

Either way, the web interface will now show the changes you've pushed from the client: Image:Screenshot-firefox-mercurial-hgwebdir-hgtest-repository-with-new-change.png

[edit] Default Server Path

To automatically choose a server path from your workstation(s), add this to the paths section of the .hg/hgrc in the local repository:

[paths]
default = http://matthew@aventinesolutions.org/hg/hgtest

[edit] Dealing with a Proxy

To push/pull changes from behind a proxy, you'll need to add a section in the .hgrc file on the home directory. For Cygwin, that would be the Cygwin home and not the Windows home. The file contents will look like:

[ui]
username = Matthew Eichler <matthew@myorganization.net>
[http_proxy]
host = proxy.myorganization.net:8078
user = myproxyuser
passwd = myproxypassword
no = localhost

Note that if you have a percent [%] sign in your password, escape it with an extra one [%%].

[edit] Mercurial from Eclipse

[edit] Installing the Plugin

From MacOSX or Windows, start Eclipse Ganymede and from the menu, do Help -> Software Updates -> Available Software and add the Vectrace http://www.vectrace.com/eclipse-update site. Check this site and click on Install to get the plugin: Image:Screenshot-eclipse-ganymede-availablesoftware-vectrace-mercurial-install.png

[edit] Windows Configuration

As mentioned above, you need the distribution from Lee Cantey installed to get Mercurial working with the Eclipse plugin.

Now, we're going to tell Eclipse to use the hg executible for Mercurial using Preferences -> Team -> Mercurial Eclipse:

Image:Screenshot-eclipse-ganymede-preferences-team-mercurial-windows.png

[edit] Mac Fink Configuration

Similarly, on MacOSX when Fink was used to install Mercurial, you'll have to tell the plug-in where the hg command is to be found in Preferences -> Team -> Mercurial Eclipse. With a default install, Fink executables will be in the directory /sw/bin unless you changed this:

Image:Screenshot-eclipse-ganymede-preferences-team-mercurial-fink.png

[edit] Try it Out

Once the plugin has been successfully installed and configured, you can clone the repository from the new web server by choosing File -> Import, then selecting Clone repository using Mercurial from the first step of the wizard:

Image:Screenshot-eclipse-ganymede-clone-repository-using-mercurial.png

The next step, you'll enter the parameters for cloning, including the URL and the username/password for Apache:

Image:Screenshot-eclipse-ganymede-clone-repository-using-mercurial-parameters.png

Once the repository is cloned here, it will become visible in the project explorer and right clicking on it give you access to the Team menu and all the Mercurial functionality:

Image:Screenshot-eclipse-ganymede-mercurial-project-team-context-menu.png

[edit] References

Most of the information getting the web server going came from here and you'll find there some tips on tweaking the server for your particular needs and level of security. However, I took the detour to this page in order to use the mod_python gateway method.

Personal tools