我想在Mercurial自动提交的代码上运行clang-format(实际上是clang-format-diff.py,只格式化已更改的内容)。我知道我可以用precommit钩子做到这一点。事实上,我已经在过去完成了it messed up some histedits,所以我删除了钩子,现在手动执行,在提交之前运行命令。
显然,问题是我可以而且有时会忘记这样做。
有没有办法只在“正常”提交时运行钩子,而不是在hetedit或rebase上运行?
答案 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注释。