mercurialhooktortoisehgmercurial-hook

How to show hook output in Tortoise Hg log window?


I need simple hook for mercurial that checks commit comment using pattern. Here is my hook:

#!/usr/bin/env python
#
# save as .hg/check_whitespace.py and make executable

import re

def check_comment(comment):
    #
    print 'Checking comment...'
    pattern = '^((Issue \d+:)|(No Issue:)).+'
    if re.match(pattern, comment, flags=re.IGNORECASE):
        return 1
    else:
        print >> sys.stderr, 'Comment does not match pattern. You must start it with "Issue 12323:" or "No Issue:"'
        return 0

if __name__ == '__main__':
    import os, sys
    comment=os.popen('hg tip --template "{desc}"').read()
    if not check_comment(comment):
        sys.exit(1)
sys.exit(0)

It works. It even shows error message 'Comment does not match pattern. You must start it with "Issue 12323:" or "No Issue:"' when I commit from console. But when I trying to commit from Tortoise Hg Workbench, only system message is shown: abort: pretxncommit.check_comment hook exited with status 1.

I need to inform user what is wrong. Is there any way to force Tortoise Hg to show output from hook?


Solution

  • I got it to work by making it an in-process hook rather than an external hook. In-process hooks are defined quite differently, however.

    First, the python file needs only a single function that will be called by the name in the hook definition. The hook function is passed ui, repo, and hooktype objects. It is also passed additional objects based on the type of hook. For pretrxncommit, it is passed node, parent1, and parent2, but you're only interested in node, so the rest are gathered in kwargs. The ui object is used to give the status and error messages.

    Contents of check_comment.py:

    #!/usr/bin/env python
    
    import re
    
    def check_comment(ui, repo, hooktype, node=None, **kwargs):
        ui.status('Checking comment...\n')
        comment = repo[node].description()
        pattern = '^((Issue \d+:)|(No Issue:)).+'
        if not re.match(pattern, comment, flags=re.IGNORECASE):
            ui.warn('Comment does not match pattern. You must start it with "Issue 12323:" or "No Issue:"\n')
            return True
    

    In the hgrc, the hook would be defined with python:/path/to/file.py:function_name, like this:

    [hooks]
    pretxncommit.check_comment = python:/path/to/check_comment.py:check_comment
    

    The .suffix_name on pretxncommit is to avoid overriding any globally defined hook, especially if this is defined in the repository's hgrc rather than the global one. Suffixes are how one allows multiple responses to the same hook.