Mercurial Hook - change a commit message pre commit

mercurial, mercurial-hook, python

Solution

i think the problem here is that the `pretxncommit` hook is executed at a point where you can't really change anything anymore. And you can't really get the commit message at that point either, because it's not set on any context object accessible.

`repo['tip'].description()` doesn't refer to the changelog being committed but to old tip already committed, that would be `repo[None]`, but as some digging in the source revealed it's not the same context object that's being persisted, so it's no point in changing it.

the only way i could find would be to use an earlier hook - like `precommit` - and monkeypatch the `commitctx` method of the repository like this:

def precommit_hook(repo, **kwargs):

    # keep a copy of repo.commitctx
    commitctx = repo.commitctx

    def updatectx(ctx, error):

        # check if `ctx.branch()` matches ...

        # update commit text
        ctx._text += " ... additional text"

        # call original
        return commitctx(ctx, error)

    # monkeypatch the commit method
    repo.commitctx = updatectx

this way cou can access the context object just before it's committed.

Problem

Edit Made this basic hook to prevent branch name & commit message bugID mismatches. https://gist.github.com/2583189 So basically the idea is that the hook should append " BugID:xyz" to the end of the commit messages if the branch name is like bug_123, or feature_123. However I'm having problems finding out how to do this, as most examples of pretxncommit people don't want to mutate the changeset description. This is what I have so far. It updates .hg/commit.save with the right message, but this message is never transferred to the commit. It is however displayed in the default message box (tortoisehg) of the next commit. Perhaps pretxncommit isn't the right hook? Could I use a precommit hook, read the commit.save and repo['tip'].branch() file and change that, if so where would I fetch the branch name from? ``` # # Fogbugz automaticically add BugID:123 to commit messages based on branch names. # Your branch name must be in the format feature_123_description or bug_123_description # import re import mercurial, sys, os _branch_regex = re.compile('(feature|bug|case|bugid|fogbugz)_(\d+)') _commit_regex = re.compile(r'\b(?P<case>(review|case|bug[zs]?(\s| )*(id)?:?)s?(\s| )*([#:; ]| )+)((([ ,:;#]|and)*)(?P<bugid>\d+))+',re.I) def pretxncommithook(ui, repo, **kwargs): ui.write('hook pretxncommithook running from fogbugz.py\n') """ Checks a single commit message for adherence to commit message rules. To use add the following to your project .hg/hgrc for each project you want to check, or to your user hgrc to apply to all projects. [hooks] pretxncommit.fogbugz = python:fogbugz.pretxncommithook """ hg_commit_message = repo['tip'].description() commit_has_bugid = _commit_regex.match(hg_commit_message) is not None match = _branch_regex.match(repo['tip'].branch()) if match: hg_commit_message = hg_commit_message + ' BugID:'+ match.groups()[1] #hg_commit_message needs to be escaped for characters like > os.system('echo ' + hg_commit_message + ' > .hg/commit.save') ``` On a slightly unrelated note, if anyone from the Fogbugz/Kiln team sees this... please update your software to read the branch name, I should not need to put a BugID:x on every damn commit. First of all it wastes my time. Secondly if a the case ID is typed incorrectly it will not show up on the bug without a lot of messing about. A lot of developers use a branch per bug/feature system. It's company policy where I work. Fogbugz sucks.

Original source