[PATCH 1 of 2] ability to load hooks from arbitrary python module

Alexander Solovyov piranha at piranha.org.ua
Thu Mar 26 18:29:54 CDT 2009


# HG changeset patch
# User Alexander Solovyov <piranha at piranha.org.ua>
# Date 1238110089 -7200
# Node ID d6b9bc879d59149a96bfa054bb1b6d0cf312571c
# Parent  67e59a9886d5902de5b94cd2552d854b6292ec63
ability to load hooks from arbitrary python module

diff --git a/doc/hgrc.5.txt b/doc/hgrc.5.txt
--- a/doc/hgrc.5.txt
+++ b/doc/hgrc.5.txt
@@ -475,6 +475,7 @@ hooks::
   The syntax for Python hooks is as follows:
 
     hookname = python:modulename.submodule.callable
+    hookname = python:/path/to/python/module.py:callable
 
   Python hooks are run within the Mercurial process. Each hook is
   called with at least three keyword arguments: a ui object (keyword
diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -28,6 +28,16 @@ def find(name):
                 return v
         raise KeyError(name)
 
+def loadpath(path, module_name):
+    path = os.path.expanduser(path)
+    if os.path.isdir(path):
+        # module/__init__.py style
+        d, f = os.path.split(path)
+        fd, fpath, desc = imp.find_module(f, [d])
+        return imp.load_module(module_name, fd, fpath, desc)
+    else:
+        return imp.load_source(module_name, path)
+
 def load(ui, name, path):
     if name.startswith('hgext.') or name.startswith('hgext/'):
         shortname = name[6:]
@@ -41,13 +51,7 @@ def load(ui, name, path):
         # choose an unique name so that it doesn't
         # conflicts with other modules
         module_name = "hgext_%s" % name.replace('.', '_')
-        if os.path.isdir(path):
-            # module/__init__.py style
-            d, f = os.path.split(path)
-            fd, fpath, desc = imp.find_module(f, [d])
-            mod = imp.load_module(module_name, fd, fpath, desc)
-        else:
-            mod = imp.load_source(module_name, path)
+        mod = loadpath(path, module_name)
     else:
         def importh(name):
             mod = __import__(name)
@@ -72,7 +76,6 @@ def loadall(ui):
         if path:
             if path[0] == '!':
                 continue
-            path = os.path.expanduser(path)
         try:
             load(ui, name, path)
         except KeyboardInterrupt:
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -7,6 +7,7 @@
 
 from i18n import _
 import util, os, sys
+from mercurial import extensions
 
 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
     '''call python hook. hook is callable object, looked up as
@@ -94,6 +95,7 @@ def redirect(state):
     global _redirect
     _redirect = state
 
+
 def hook(ui, repo, name, throw=False, **args):
     r = False
 
@@ -109,8 +111,15 @@ def hook(ui, repo, name, throw=False, **
             if callable(cmd):
                 r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
             elif cmd.startswith('python:'):
-                r = _pythonhook(ui, repo, name, hname, cmd[7:].strip(),
-                                args, throw) or r
+                if cmd.count(':') == 2:
+                    module_name = 'hghook_%s' % hname.replace('.', '_')
+                    path, cmd = cmd[7:].split(':')
+                    mod = extensions.loadpath(path, module_name)
+                    r = _pythonhook(ui, repo, name, hname, getattr(mod, cmd),
+                                    args, throw) or r
+                else:
+                    r = _pythonhook(ui, repo, name, hname, cmd[7:].strip(),
+                                    args, throw) or r
             else:
                 r = _exthook(ui, repo, hname, cmd, args, throw) or r
     finally:


More information about the Mercurial-devel mailing list