Handle functions as the value of a hooks.<name> config variable
authorAlexis S. L. Carvalho <alexis@cecm.usp.br>
Fri, 09 Feb 2007 03:48:28 -0200
changeset 4070 961ccb615cf7
parent 4069 3fef134832d8
child 4071 165abe554c80
Handle functions as the value of a hooks.<name> config variable This should make it easier for extensions to add a hook when they're loaded.
mercurial/localrepo.py
tests/test-hook
tests/test-hook.out
--- a/mercurial/localrepo.py	Fri Feb 09 03:48:26 2007 -0200
+++ b/mercurial/localrepo.py	Fri Feb 09 03:48:28 2007 -0200
@@ -142,32 +142,34 @@
             be run as hooks without wrappers to convert return values.'''
 
             self.ui.note(_("calling hook %s: %s\n") % (hname, funcname))
-            d = funcname.rfind('.')
-            if d == -1:
-                raise util.Abort(_('%s hook is invalid ("%s" not in a module)')
-                                 % (hname, funcname))
-            modname = funcname[:d]
-            try:
-                obj = __import__(modname)
-            except ImportError:
+            obj = funcname
+            if not callable(obj):
+                d = funcname.rfind('.')
+                if d == -1:
+                    raise util.Abort(_('%s hook is invalid ("%s" not in '
+                                       'a module)') % (hname, funcname))
+                modname = funcname[:d]
                 try:
-                    # extensions are loaded with hgext_ prefix
-                    obj = __import__("hgext_%s" % modname)
+                    obj = __import__(modname)
                 except ImportError:
+                    try:
+                        # extensions are loaded with hgext_ prefix
+                        obj = __import__("hgext_%s" % modname)
+                    except ImportError:
+                        raise util.Abort(_('%s hook is invalid '
+                                           '(import of "%s" failed)') %
+                                         (hname, modname))
+                try:
+                    for p in funcname.split('.')[1:]:
+                        obj = getattr(obj, p)
+                except AttributeError, err:
                     raise util.Abort(_('%s hook is invalid '
-                                       '(import of "%s" failed)') %
-                                     (hname, modname))
-            try:
-                for p in funcname.split('.')[1:]:
-                    obj = getattr(obj, p)
-            except AttributeError, err:
-                raise util.Abort(_('%s hook is invalid '
-                                   '("%s" is not defined)') %
-                                 (hname, funcname))
-            if not callable(obj):
-                raise util.Abort(_('%s hook is invalid '
-                                   '("%s" is not callable)') %
-                                 (hname, funcname))
+                                       '("%s" is not defined)') %
+                                     (hname, funcname))
+                if not callable(obj):
+                    raise util.Abort(_('%s hook is invalid '
+                                       '("%s" is not callable)') %
+                                     (hname, funcname))
             try:
                 r = obj(ui=self.ui, repo=self, hooktype=name, **args)
             except (KeyboardInterrupt, util.SignalInterrupt):
@@ -205,7 +207,9 @@
                  if hname.split(".", 1)[0] == name and cmd]
         hooks.sort()
         for hname, cmd in hooks:
-            if cmd.startswith('python:'):
+            if callable(cmd):
+                r = callhook(hname, cmd) or r
+            elif cmd.startswith('python:'):
                 r = callhook(hname, cmd[7:].strip()) or r
             else:
                 r = runhook(hname, cmd) or r
--- a/tests/test-hook	Fri Feb 09 03:48:26 2007 -0200
+++ b/tests/test-hook	Fri Feb 09 03:48:28 2007 -0200
@@ -183,4 +183,24 @@
 echo a >> a
 hg --traceback commit -A -m a 2>&1 | grep '^Traceback'
 
+cd ..
+hg init c
+cd c
+
+cat > hookext.py <<EOF
+def autohook(**args):
+    print "Automatically installed hook"
+
+def reposetup(ui, repo):
+    repo.ui.setconfig("hooks", "commit.auto", autohook)
+EOF
+echo '[extensions]' >> .hg/hgrc
+echo 'hookext = hookext.py' >> .hg/hgrc
+
+touch foo
+hg add foo
+hg ci -m 'add foo'
+echo >> foo
+hg ci --debug -m 'change foo' | sed -e 's/ at .*>/>/'
+
 exit 0
--- a/tests/test-hook.out	Fri Feb 09 03:48:26 2007 -0200
+++ b/tests/test-hook.out	Fri Feb 09 03:48:28 2007 -0200
@@ -138,3 +138,7 @@
 (run 'hg update' to get a working copy)
 # make sure --traceback works
 Traceback (most recent call last):
+Automatically installed hook
+foo
+calling hook commit.auto: <function autohook>
+Automatically installed hook