防止mercurial precommit hook在hetedit上运行

时间:2015-11-23 10:19:35

标签: mercurial mercurial-hook

我想在Mercurial自动提交的代码上运行clang-format(实际上是clang-format-diff.py,只格式化已更改的内容)。我知道我可以用precommit钩子做到这一点。事实上,我已经在过去完成了it messed up some histedits,所以我删除了钩子,现在手动执行,在提交之前运行命令。

显然,问题是我可以而且有时会忘记这样做。

有没有办法只在“正常”提交时运行钩子,而不是在hetedit或rebase上运行?

2 个答案:

答案 0 :(得分:2)

据我所知,目前还没有直接的方法。但是你可以创建一个别名来代替rebase和histedit,让我们称之为hrebase和hhistedit,它们会禁用它们的使用。

为了在命令行上禁用单次运行的挂钩,您可以使用--config hook.HOOKNAME=,例如:

hg --config hook.HOOKNAME= rebase -d2 -b5

然后你定义了你的别名:

[alias]
hrebase = rebase --config hook.HOOKNAME=
hhistedit = histedit --config hook.HOOKNAME=

答案 1 :(得分:1)

为了包装单个命令(在您的情况下为commit),您可以使用别名或扩展名。别名方法相当简单,但有一些缺点。别名示例:

commit = !$HG commit --config alias.commit=commit --config hooks.precommit.clang=/tmp/msg "$@"

创建这样的别名涉及一些微妙的问题:首先,普通别名不接受--config参数(所有配置都已在别名扩展时解析)。因此,我们需要使用shell别名(!$HG)来解决此问题;第二,为了避免在shell别名扩展期间卡在递归中(与普通别名不同,Mercurial不能为shell别名执行此操作),我们必须对自身实现commit(因此--config alias.commit=commit部分)

这种方法有一些缺点:首先,它将启动时间加倍(因为Mercurial会因shell别名而被调用两次);虽然这是相对较少的开销,但是对于人类用户来说可能是烦人的。其次,它与脚本的交互性很差;脚本和GUI可能会在他们不打算或者(更糟)禁用别名时无意中使用别名,从而绕过钩子。

另一种方法是使用扩展来包装commit命令。例如:

# Simple extension to provide a hook for manual commits only

"""hook for manual commits

This extension allows the selective definition of a hook for
manual commits only (i.e. outside graft, histedit, rebase, etc.).

In order to use it, add the following lines to your ``.hg/hgrc`` or
``~/.hgrc`` file::

    [extensions]
    manualcommithook=/path/to/extension
    [hooks]
    premanualcommit=/path/to/hook

The ``hooks.premanualcommit`` hook will then be (temporarily) installed
under ``hooks.precommit.manual``, but only for manual commits.
"""

from mercurial import commands, extensions

def commit_with_hook(original_cmd, ui, repo, *pats, **opts):
  hook = ui.config("hooks", "premanualcommit")
  if hook:
    if ui.config("hooks", "precommit.manual"):
      ui.warn("overriding existing precommit.manual hook\n")
    ui.setconfig("hooks", "precommit.manual", hook)
  return original_cmd(ui, repo, *pats, **opts)

def uisetup(ui):
  extensions.wrapcommand(commands.table, "commit", commit_with_hook)

有关如何使用扩展程序的说明,请参阅doc注释。