[PATCH] hooks: hook ordering via sort variable in [hooks]

Matt Zuba matt.zuba at goodwillaz.org
Sun Jan 15 15:21:51 CST 2012

> Your emailer is mangling your patches.

Sorry for the mangled patch; I changed my Thunderbird settings so
hopefully that doesn't happen this time around.  If so, I'll just
resubmit the new patch with patchbomb.

> Using a heap here is overkill. I would do something like:

I'm still fairly new to Python, still learning my way around, thanks for
the suggestion.  Here is a new patch:

# HG changeset patch
# User Matt Zuba <matt.zuba at goodwillaz.org>
# Date 1326660612 25200
# Node ID 986b56a0e64c14117edfc51024a33100bdd730f1
# Parent  e5feebc1f3bb50f0180c76d31e8456a390a86c78
hooks: prioritize run order of hooks

As of Mercurial 1.3, hooks are sorted in the order they are read into
Mercurial.  There are many instances when someone may want the hooks
sorted in a specific order; this patch allows prioritizing hooks, while
maintaining the existing enumeration for hooks without a priority.

diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -655,7 +655,10 @@
 various actions such as starting or finishing a commit. Multiple
 hooks can be run for the same action by appending a suffix to the
 action. Overriding a site-wide hook can be done by changing its
-value or setting it to an empty string.
+value or setting it to an empty string.  Hooks can be prioritized
+by adding a prefix of ``priority`` to the hook name on a new line
+and setting the priority.  The default priority is 0 if
+not specified.

 Example ``.hg/hgrc``::

@@ -666,6 +669,8 @@
   incoming =
   incoming.email = /my/email/hook
   incoming.autobuild = /my/build/hook
+  # force autobuild hook to run before other incoming hooks
+  priority.incoming.autobuild = 1

 Most hooks are run with environment variables set that give useful
 additional information. For each hook below, the environment
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -124,6 +124,14 @@
         ui.warn(_('warning: %s hook %s\n') % (name, desc))
     return r

+def _allhooks(ui):
+    hooks = []
+    for name, cmd in ui.configitems('hooks'):
+        if not name.startswith('priority'):
+            priority = ui.configint('hooks', 'priority.%s' % name, 0)
+            hooks.append((-priority, len(hooks), name, cmd))
+    return [(k, v) for p, o, k, v in sorted(hooks)]
 _redirect = False
 def redirect(state):
     global _redirect
@@ -147,7 +155,7 @@

-        for hname, cmd in ui.configitems('hooks'):
+        for hname, cmd in _allhooks(ui):
             if hname.split('.')[0] != name or not cmd:
             if util.safehasattr(cmd, '__call__'):
diff --git a/tests/test-hook.t b/tests/test-hook.t
--- a/tests/test-hook.t
+++ b/tests/test-hook.t
@@ -553,3 +553,19 @@
   calling hook pre-identify: hooktests.verbosehook
   verbose output from hook
+Ensure hooks can be prioritized
+  $ echo '[hooks]' > .hg/hgrc
+  $ echo 'pre-identify.a = python:hooktests.verbosehook' >> .hg/hgrc
+  $ echo 'pre-identify.b = python:hooktests.verbosehook' >> .hg/hgrc
+  $ echo 'priority.pre-identify.b = 1' >> .hg/hgrc
+  $ echo 'pre-identify.c = python:hooktests.verbosehook' >> .hg/hgrc
+  $ hg id --verbose
+  calling hook pre-identify.b: hooktests.verbosehook
+  verbose output from hook
+  calling hook pre-identify.a: hooktests.verbosehook
+  verbose output from hook
+  calling hook pre-identify.c: hooktests.verbosehook
+  verbose output from hook
+  cb9a9f314b8b

More information about the Mercurial-devel mailing list