Mercurial Hook - change a commit message pre commit

前端 未结 2 806
时光取名叫无心
时光取名叫无心 2021-02-06 05:48

Edit Made this basic hook to prevent branch name & commit message bugID mismatches. https://gist.github.com/2583189

So basically the idea is that th

相关标签:
2条回答
  • 2021-02-06 06:18

    mata's answer is clever, but there's actually a built in way to do this if you're willing to write your own extension (it's really easy, little more than just writing the hook functionality you wanted to write anyway).

    The "right" way to do this is to subclass the repository in reposetup, as shown in the docstring of mercurial.extensions.wrapfunction (because it turns out wrapfunction is not the right way to do it for repos:

    Wrapping methods of the repository object is not recommended since
    it conflicts with extensions that extend the repository by
    subclassing. All extensions that need to extend methods of
    localrepository should use this subclassing trick: namely,
    reposetup() should look like
    
      def reposetup(ui, repo):
          class myrepo(repo.__class__):
              def whatever(self, *args, **kwargs):
                  [...extension stuff...]
                  super(myrepo, self).whatever(*args, **kwargs)
                  [...extension stuff...]
    
          repo.__class__ = myrepo
    

    So for instance, your extension would look like this (stripped down):

    #!/usr/bin/python
    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)
    
    #One of mercurial's callbacks for extensions. This is where you
    # you want to subclass repo to add your functionality.
    def reposetup(ui, repo):
    
        #Create a derived class that actually does what you want.
        class myrepo(repo.__class__):
            def commitctx(self, ctx, *args, **kwargs):
                match = _branch_regex.match(ctx.branch())
                if match:
                    ctx._text += ' BugID:'+ match.groups()[1]
    
        #Make sure to actually use the new subclass.
        repo.__class__ = myrepo
    
    ### Finish off the extensions stuff
    
    # We aren't adding any commands to hg.
    cmdtables = {}
    
    #List of known compatible versions of hg.
    testedwith = '2.7.1'
    

    I have tested this and it works fine. You can use the extension by saving it in a python file, say /some-path/fogbugz.py, and adding it under the extensions group in your hgrc:

    [extensions]
    fogbugz = /some-path/fogbugz.py
    
    0 讨论(0)
  • 2021-02-06 06:28

    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.

    0 讨论(0)
提交回复
热议问题