Friday, March 22, 2013

Installing Mercurial 2.5.2 on IIS 7.5 and Python 2.7 64-bit

I have been given a great opportunity to move our current source control system from ClearCase to Mercurial. This includes using Active Directory for authentication and authorization. There are a number of great blog posts which helped me along the way. Please see the References at the bottom of the blog. However, I found that none of them were complete, or used older versions of the software.

Prerequisites

  • Microsoft Windows 2008 Server R2, or Microsoft Windows 7
    Note: If you are using Active Directory, the server must be a part of the domain.
  • Internet Information Server (IIS) 7.5
  • Python 2.7.3 (X86-64)
  • Mercurial 2.5.2 (X86-64)

Installation Process

Install Python

Download and install Python 2.7.3 X86-64 using the installer.

Install Mercurial

Download and install Mercurial 2.5.2 (X86-64) for use with Python 2.7.

Note: Do not install TortoiseHg. It is not required, and these directions will not work.

Install Internet Information Server (IIS)

Using the Server Manager on Windows 2008 Server R2, you need to add a role to install IIS. It is not as intuitive as it should be. On other versions of Windows, you would add it as a service.
  1. Add a Server Role.
  2. Select IIS Role.
  3. Select Role Services.
    • Application Development
      • CGI
      • ISAPI Extensions
      • ISAPI Filters
    • Security
      • Basic Authentication
      • Windows Authentication
      • Request Filtering
  4. Installation Complete

Install and Configure CGI (hgweb.cgi)

  1. Clone the mercurial repository, and copy the hgweb.cgi application to located in the project root to C:\Python27\Lib\site-packages\mercurial\hgweb.
    hg clone http://selenic.com/repo/hg
    
  2. Create a hgweb.config in C:\Python27\Lib\site-packages\mercurial\hgweb. Here is an example file:
    [web]
    encoding = UTF-8
    allow_push = *
    push_ssl = False
    contact = John Yeary
    allowzip = True
    
    [paths]
    test = C:\repos\test
    
  3. Modify the hgweb.cgi file to use the new configuration.
    #!/usr/bin/env python
    #
    # An example hgweb CGI script, edit as necessary
    # See also https://www.mercurial-scm.org/wiki/PublishingRepositories
    
    # Path to repo or hgweb config to serve (see 'hg help hgweb')
    config = "hgweb.config"
    
    
    # Uncomment and adjust if Mercurial is not installed system-wide
    # (consult "installed modules" path from 'hg debuginstall'):
    #import sys; sys.path.insert(0, "/path/to/python/lib")
    
    # Uncomment to send python tracebacks to the browser if an error occurs:
    #import cgitb; cgitb.enable()
    
    from mercurial import demandimport; demandimport.enable()
    from mercurial.hgweb import hgweb, wsgicgi
    application = hgweb(config)
    wsgicgi.launch(application)
    

Setup IIS Python CGI Handler

  1. Add a Virtual Directory to the Default Web Site
    • Alias: hg
    • Physical Path: C:\Python27\Lib\site-packages\mercurial\hgweb
  2. Select Handler Mapping from the newly created hg virtual directory.
  3. Click Actions --> Add Script Map
  4. Set the following parameters:
    • Request Path: *.cgi
    • Executable: C:\Python27\python.exe -u "%s"
    • Name: Python
  5. Restart IIS Server

Create Mercurial Test Repository

c:\>mkdir repos

c:\>cd repos

c:\repos>mkdir test

c:\repos>cd test

c:\repos\test>hg init

c:\repos\test>echo "THIS IS A TEST FILE" > README

c:\repos\test>hg add README

c:\repos\test>hg commit -u jyeary -m "Initial Import"

c:\repos\test>hg summary
parent: 0:d5c9f65c740a tip
 Initial Import
branch: default
commit: (clean)
update: (current)

Test Configuration

Using a browser, go to http://localhost/hg/hgweb.cgi. You should see the following:

Here is the changeset for the initial import

URL Rewrite (OPTIONAL)

If you want a cleaner URL for users, you will want to "prettify" your URLs. Luckily, Microsoft has a URL Rewrite plugin for IIS. You will want to install it from the link provided.
Here is the configuration for our application:
  1. Select URL Rewrite from the hg virtual directory.
  2. Create a new blank rule.
  3. Create a Rule with the following parameters:
    • Name: hgweb.cgi
    • Match URL:
      • Using: Wildcards
      • Pattern: *
    • Conditions
      • Add Condition
      • Condition Input: {REQUEST_FILENAME}
      • Check if input string: Is Not A File
    • Action
      • Action Type: Rewrite
      • Rewrite URL: hgweb.cgi/{R:1}
  4. Apply Changes
  5. Modify the hgweb.config and add the baseurl attribute.
    [web]
    encoding = UTF-8
    baseurl= /hg
    allow_push = *
    push_ssl = False
    contact = John Yeary
    allowzip = True
    
    [paths]
    test = C:\repos\test
    
The URL should be much easier now http://localhost/hg/test/

Basic Authentication (Active Directory> for push (OPTIONAL)

The default setup from the hgweb.config allows push from all clients. If we want to add more security, we need to specify authentication, and who is allowed to push.

Note: Basic Authentication passes username and password in clear text. You should use Basic Authentication in conjunction with SSL.

In the default configuration provided, you can push back any changes as shown below.
C:\Users\jyeary\Desktop>hg clone http://localhost/hg/test
destination directory: test
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

C:\Users\jyeary\Desktop>cd test

C:\Users\jyeary\Desktop\test>ls
README

C:\Users\jyeary\Desktop\test>touch FILE1

C:\Users\jyeary\Desktop\test>touch FILE2

C:\Users\jyeary\Desktop\test>hg add FILE1

C:\Users\jyeary\Desktop\test>hg add FILE2

C:\Users\jyeary\Desktop\test>hg commit -u jyeary -m "Added files."

C:\Users\jyeary\Desktop\test>hg push
pushing to http://localhost/hg/test
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 2 changes to 2 files
We will configure our application and the server to use authentication.
  1. Select the hg virtual directory.
  2. Select Authentication
  3. Select Basic Authentication and Enable it.
  4. Edit the settings for your Active Directory (AD) domain.
    • Domain: THIS IS YOUR AD DOMAIN
    • Realm: You can call this anything that you like, I personally use the domain name.
  5. You have set up the authentication, but it still will allow you to push files as demonstrated below.
    C:\Users\jyeary\Desktop\test>touch FILE3
    
    C:\Users\jyeary\Desktop\test>hg add FILE3
    
    C:\Users\jyeary\Desktop\test>hg commit -u jyeary -m "Added FILE3"
    
    C:\Users\jyeary\Desktop\test>hg push
    pushing to http://localhost/hg/test
    searching for changes
    remote: adding changesets
    remote: adding manifests
    remote: adding file changes
    remote: added 1 changesets with 1 changes to 1 files
    
  6. To enable push to require authentication, we need to modify the hgweb.config file. We will modify allow_push = *, and set it to allow push from only certain individuals.
    [web]
    encoding = UTF-8
    baseurl= /hg
    allow_push = jyeary
    push_ssl = False
    contact = John Yeary
    allowzip = True
    
    [paths]
    test = C:\repos\test
    

    Since we have set push to accept only jyeary, it will ask us to authenticate and shown below.
    C:\Users\jyeary\Desktop\test>touch FILE4
    
    C:\Users\jyeary\Desktop\test>hg add FILE4
    
    C:\Users\jyeary\Desktop\test>hg commit -u jyeary -m "Added FILE4"
    
    C:\Users\jyeary\Desktop\test>hg push
    pushing to http://localhost/hg/test
    searching for changes
    http authorization required
    realm: mydomain.com
    user: jyeary
    password:
    remote: adding changesets
    remote: adding manifests
    remote: adding file changes
    remote: added 1 changesets with 1 changes to 1 files
    

Enable SSL (OPTIONAL)

I am indicating that this is optional, but if you are using Basic Authentication; it really should be required. This shows how to create a simple self-signed certificate. In a production environment, you will want to have a certificate signed by Certification Authoritity (CA).
  1. Select the server, and select Server Certificates.
  2. Create a self-signed certificate.

  3. Right-click on the Default Web Site, and select Edit Bindings.
  4. Select Add a Binding
  5. Add an SSL binding as follows:
    • Type: https
    • Port: 443
    • SSL Certificate: selfSigned
  6. Modify the hgweb.config file, and remove the push_ssl = False line.
  7. Test the new configuration by cloning the secured repository
    Note: Unless you add the certificate fingerprint to your hgrc, you will need to use the --insecure flag with mercurial.
    C:\Users\jyeary\Desktop>hg clone --insecure https://localhost/hg/test
    warning: localhost certificate with fingerprint e5:32:64:97:6e:10:43:e5:c7:71:92:9f:08:20:e9:4d:54:d6:c3:04 not verified (check hostfingerprints or web.cacerts config setting)
    
    destination directory: test
    requesting all changes
    adding changesets
    adding manifests
    adding file changes
    added 4 changesets with 5 changes to 5 files
    warning: localhost certificate with fingerprint e5:32:64:97:6e:10:43:e5:c7:71:92:9f:08:20:e9:4d:54:d6:c3:04 not verified (check hostfingerprints or web.cacerts config setting)
    
    updating to branch default
    5 files updated, 0 files merged, 0 files removed, 0 files unresolved
    

Conclusion

Setting up Mercurial is easy to do in a Windows environment. You will gain all of the great benefits from Mercurial along with active directory. It is much easier to setup Mercurial on IIS for use with Active Directory than on a LAMP stack with winbind, or LDAP. If AD is a requirement... this is definitely the solution.

References

4 comments :

Theron said...

Is the hg executable supposed to be in the install file linked? I installed and see the hg web files in the site-packages, but I don't see where the application is installed. Nor does it recognize the program when I try to type "hg" on the command line.

Theron said...

Is the hg executable supposed to be in the hg installed linked? I ran the installer and see the hgweb files in the site-packages, but I can't find the hg executable. The OS doesn't recognize the program when attempted to run from the command line.

Can I just install any version of Mercurial that works with Python 2.7?

John Yeary said...

You need to install Mercurial for the application to work. If you have installed Mercurial, and it does not work from the command line, you will need to check your PATH to make sure it includes the executable.

Please realize that some things may have changed. This article was published in 2013.

Theron said...

Thanks for the response. Ha! It's one of the more up to date articles I could find. Always fun working with legacy stuff.

I tried the latest version of Mercurial figuring it wouldn't work and was correct, I got an incompatible repository error. Then I found and installed version 2.5.2. Everything worked great after that.

Thanks for the post!

Popular Posts