How can I set or modify the commit message from a mercurial extension?

317 views Asked by At

I'm trying to modify this Mercurial extension to prompt the user to add a FogBugz case number to their commit message. Ideally, I'd like the user to just type in a number after being prompted and have it automatically appended to the commit message.

Here's what I've got so far:

def pretxncommit(ui, repo, **kwargs):
    tip = repo.changectx(repo.changelog.tip())
    if not RE_CASE.search(tip.description()) and len(tip.parents()) < 2:
        casenumResponse = ui.prompt('*** Please specify a case number, x to abort, or hit enter to ignore:', '')
        casenum = RE_CASENUM.search(casenumResponse)        
        if casenum:
            # this doesn't work!
            # tip.description(tip.description() + ' (Case ' + casenum.group(0) + ')')
            return True
        elif (casenumResponse == 'x'):
            ui.warn('*** User aborted\n')
            return True
        return True
    return False

What I haven't been able to find is a way to edit the commit message. tip.description appears to be readonly, and I haven't seen anything in the documentation or examples that would let me modify it. The only references I've seen to editing commit messages have to do with patches and the Mq extension, and it doesn't seem like that can help here.

Any ideas as to how I could set the commit message?

2

There are 2 answers

0
Daniel Schaffer On BEST ANSWER

I didn't end up finding a way using a hook, but I was able to do it using extensions.wrapcommand and modifying the options.

I've included the source of the resulting extension here.

Upon detecting the lack of a case in the commit message, my version prompts the user to either enter one, ignore the warning, or abort the commit.

If the user responds to the prompt by specifying a case number, it is appended to the existing commit message.

If the user responds with 'x', the commit is aborted and the changes remain outstanding.

If the user response by just hitting enter, the commit proceeds with the original caseless commit message.

I've also added the nofb option, which skips the prompt if a user is purposefully making a commit with no case number.

Here is the extension:

"""fogbugzreminder

Reminds the user to include a FogBugz case reference in their commit message if none is specified
"""

from mercurial import commands, extensions
import re

RE_CASE = re.compile(r'(case):?\s*\d+', re.IGNORECASE)
RE_CASENUM = re.compile(r'\d+', re.IGNORECASE)

def commit(originalcommit, ui, repo, **opts):

    haschange = False   
    for changetype in repo.status():
        if len(changetype) > 0:
            haschange = True

    if not haschange and ui.config('ui', 'commitsubrepos', default=True):
        ctx = repo['.']
        for subpath in sorted(ctx.substate):
            subrepo = ctx.sub(subpath)
            if subrepo.dirty(): haschange = True

    if haschange and not opts["nofb"] and not RE_CASE.search(opts["message"]):

        casenumResponse = ui.prompt('*** Please specify a case number, x to abort, or hit enter to ignore:', '')
        casenum = RE_CASENUM.search(casenumResponse)        

        if casenum:         
            opts["message"] += ' (Case ' + casenum.group(0) + ')'
            print '*** Continuing with updated commit message: ' + opts["message"]          
        elif (casenumResponse == 'x'):
            ui.warn('*** User aborted\n')
            return False    

    return originalcommit(ui, repo, **opts)

def uisetup(ui):    
    entry = extensions.wrapcommand(commands.table, "commit", commit)
    entry[1].append(('', 'nofb', None, ('suppress the fogbugzreminder warning if no case number is present in the commit message')))

To use this extension, copy the source into a file named fogbugzreminder.py. Then in your Mercurial.ini file (or hgrc, whatever your preference is), add the following line to the [extensions] section:

fogbugzreminder=[path to the fogbugzreminder.py file]
1
Paul Nathan On

You can't modify a commit message without modifying the changeset.

I would suggest looking into a precommit hook that denies committing if a bugid is left out.