Mercurial Hook to

ensure issue

references in

Trac/Redmine

As much as I love the version control integration of the bug trackers I use (Redmine and Trac) I find myself forgetting to include the issue reference more often than I’d like to admit.

Add to this the merry dance you have to go through to ammend commit messages in Mercurial and things get even worse. (Oh how I’d love for hg to implement something similar to git’s $ git commit –amend )

Hence, a Pre-transaction-commit hook for hg that will ask me if I’m sure I want to commit without an issue number. If want to commit anyway, it’s just two extra keystrokes, and saves a whole lot of rollback/apply nonsense.

#!/usr/bin/env python
import os
import re
import subprocess
import sys
 
cmd = subprocess.Popen(['hg', 'log', '-vr', os.environ['HG_NODE']],
                       stdout=subprocess.PIPE).communicate()[0]
msg = cmd.split('description:')[1]
issue_regexes = [
    # Trac
    r'#\d+',
    # Redmine
    r'fixes #\d+',
    r'refs #\d+',
    ]
if not filter(lambda x: re.search(x, msg), issue_regexes):
    print "No issue ref or fix... message is:"
    print msg
    sys.stdout.write("Continue? [y/n] ")
    resp = raw_input().lower()
    if resp == 'n':
        sys.exit(9)

Then add the following to your project’s .hg/hgrc:

[hooks]
pretxncommit = path/to/your/pretxncommit.py

Saving you endless embarrassment:

davidmiller@pascal:~/src/buggy_repo$ hg commit -m "A context-less void"
No issue ref or fix... message is:
 
A context-less void
 
 
 
Continue? [y/n] n
transaction abort!
rollback completed
abort: pretxncommit hook exited with status 9

Love regards etc

Tags: , , , , , ,

One Response to “Mercurial Hook to ensure issue references in Trac/Redmine”

  1. Steve M says:

    I’m new to python and to Mercurial, and came across this while trying to write a hook of my own. I have a few comments/suggestions for improvements:

    1) Why do an “hg log” and then “split” the description out when you could just “hg log –template “{desc}” ?
    2) Why exactly do you need three regexes instead of one extended regexp r’(fixes |refs )*#\d+’ ?
    3) And finally, if you make your hook an in-process hook, it’s faster plus you get easier access to the description. Something like this…

    message=repo[node].description()
    if (re.search(r’(fixes |refs )*#\d+’, message) == None):
    ui.write(“No issue ref or fix. Try again”)
    return 1
    return 0

    Steve

Leave a Reply