【问题标题】:Mercurial Hook - change a commit message pre commitMercurial Hook - 在提交前更改提交消息
【发布时间】:2012-05-09 18:12:44
【问题描述】:

编辑 制作了这个基本钩子以防止分支名称和提交消息 bugID 不匹配。 https://gist.github.com/2583189

所以基本上的想法是,如果分支名称类似于 bug_123 或 feature_123,则挂钩应将“BugID:xyz”附加到提交消息的末尾。但是,我在找出如何执行此操作时遇到问题,因为大多数 pretxncommit 示例人们不想改变变更集描述。

这是我目前所拥有的。它使用正确的消息更新 .hg/commit.save,但此消息永远不会传输到提交。但是,它会显示在下一次提交的默认消息框 (tortoisehg) 中。也许 pretxncommit 不是正确的钩子?

我可以使用预提交挂钩,阅读 commit.save 和 repo['tip'].branch() 文件并更改 那,如果是这样,我从哪里获取分支名称?

#
# 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')

在一个稍微不相关的注释中,如果 Fogbugz/Kiln 团队的任何人看到这个......请更新您的软件以读取分支名称,我不需要在每个该死的提交上放置 BugID:x。首先,它浪费了我的时间。其次,如果案例 ID 输入不正确,它不会出现在错误上,而不会引起很多混乱。许多开发人员使用每个错误/功能系统的分支。这是我工作的公司政策。 Fogbugz 很烂。

【问题讨论】:

  • 出于好奇:你为什么需要它?您始终可以检索提交所属的分支名称。 PS:哦,这是Kiln要求:-S好奇怪
  • 它不是供人类使用的。 Fogbugz,我们的错误跟踪器通过读取提交描述中的 BugID:x 或 case y 将提交与错误相关联。是的,我什至需要它是荒谬的。
  • FogBugz mercurial 集成使用更改组挂钩将相关信息推送到 FogBugz。您可以更改它以从分支名称而不是从提交消息中获取 FogBugz 案例 ID。当然,如果您升级 FogBugz 版本,您必须让您的变更组挂钩保持最新。
  • 我无权访问fogbugz服务器。

标签: python mercurial mercurial-hook


【解决方案1】:

我认为这里的问题是pretxncommit 钩子是在你无法再真正改变任何东西的地方执行的。而且此时您也无法真正获得提交消息,因为它没有设置在任何可访问的上下文对象上。

repo['tip'].description() 不是指正在提交的变更日志,而是指已经提交的旧提示,即repo[None],但正如一些对源代码的挖掘所揭示的那样,它不是被持久化的同一个上下文对象,所以它不是点改变它。

我能找到的唯一方法是使用较早的钩子——比如precommit——然后像这样对存储库的commitctx方法进行monkeypatch:

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

这样可以在上下文对象被提交之前访问它。

【讨论】:

  • 看起来不错。我试图使用 precommit + .hg/commit.save 来做到这一点。我会告诉你进展如何。
  • 这当然是偷偷摸摸的,但它对我有帮助
【解决方案2】:

mata 的回答很聪明,但是如果您愿意编写自己的扩展程序,实际上有一种内置方法可以做到这一点(它是 really easy,只不过是编写您想编写的钩子功能而已)。

执行此操作的“正确”方法是在reposetup 中对存储库进行子类化,如mercurial.extensions.wrapfunction 的文档字符串所示(因为事实证明wrapfunction 不是为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

例如,您的扩展程序看起来像这样(精简):

#!/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'

我已经对此进行了测试,并且效果很好。您可以通过将其保存在 python 文件中来使用扩展,例如 /some-path/fogbugz.py,并将其添加到 hgrc 中的 extensions 组下:

[extensions]
fogbugz = /some-path/fogbugz.py

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 2017-12-08
    • 2015-05-21
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多