[PATCH 1 of 2] extensions: add loadext hook

Brodie Rao dackze at gmail.com
Wed May 6 13:04:06 CDT 2009


# HG changeset patch
# User Brodie Rao <me+hg at dackz.net>
# Date 1241632018 14400
# Node ID 29ed1ba112b1182ca99c6815d11e4afd510fb8fe
# Parent  edd676eae7d7835e238e7bec6ee09f2b90007b1b
extensions: add loadext hook

This hook is meant to allow extensions to modify other extensions in a sane
way. For example, the color extension modifies mq to colorize qdiff and
qseries. At one point it would import mq from hgext if it found it in hgrc,
but this doesn't respect the path that mq is set to. Using extension.find()
is also error-prone as it fails if mq is loaded after the color extension.

diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -232,13 +232,12 @@ def uisetup(ui):
     _setupcmd(ui, 'outgoing', commands.table, None, _diff_effects)
     _setupcmd(ui, 'tip', commands.table, None, _diff_effects)
     _setupcmd(ui, 'status', commands.table, colorstatus, _status_effects)
-    try:
-        mq = extensions.find('mq')
-        _setupcmd(ui, 'qdiff', mq.cmdtable, colordiff, _diff_effects)
-        _setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects)
-    except KeyError:
-        # The mq extension is not enabled
-        pass
+    ui.setconfig('hooks', 'loadext', _setupext)
+
+def _setupext(ui, repo, hooktype, extname, mod):
+    if extname == 'mq':
+        _setupcmd(ui, 'qdiff', mod.cmdtable, colordiff, _diff_effects)
+        _setupcmd(ui, 'qseries', mod.cmdtable, colorqseries, _patch_effects)
 
 def _setupcmd(ui, cmd, table, func, effectsmap):
     '''patch in command to command table and load effect map'''
diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -5,8 +5,8 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2, incorporated herein by reference.
 
-import imp, os
-import util, cmdutil
+import os
+import util, cmdutil, hook
 from i18n import _
 
 _extensions = {}
@@ -28,17 +28,6 @@ def find(name):
                 return v
         raise KeyError(name)
 
-def loadpath(path, module_name):
-    module_name = module_name.replace('.', '_')
-    path = os.path.expanduser(path)
-    if os.path.isdir(path):
-        # module/__init__.py style
-        d, f = os.path.split(path.rstrip('/'))
-        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:]
@@ -70,6 +59,8 @@ def load(ui, name, path):
     if uisetup:
         uisetup(ui)
 
+    hook.hook(ui, None, 'loadext', quiet=True, extname=shortname, mod=mod)
+
 def loadall(ui):
     result = ui.configitems("extensions")
     for (name, path) in result:
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -7,9 +7,8 @@
 
 from i18n import _
 import util, os, sys
-from mercurial import extensions
 
-def _pythonhook(ui, repo, name, hname, funcname, args, throw):
+def _pythonhook(ui, repo, name, hname, funcname, args, throw, quiet):
     '''call python hook. hook is callable object, looked up as
     name in python module. if callable returns "true", hook
     fails, else passes. if hook raises exception, treated as
@@ -19,7 +18,8 @@ def _pythonhook(ui, repo, name, hname, f
     unmodified commands (e.g. mercurial.commands.update) can
     be run as hooks without wrappers to convert return values.'''
 
-    ui.note(_("calling hook %s: %s\n") % (hname, funcname))
+    if not quiet:
+        ui.note(_("calling hook %s: %s\n") % (hname, funcname))
     obj = funcname
     if not callable(obj):
         d = funcname.rfind('.')
@@ -95,7 +95,7 @@ def redirect(state):
     global _redirect
     _redirect = state
 
-def hook(ui, repo, name, throw=False, **args):
+def hook(ui, repo, name, throw=False, quiet=False, **args):
     r = False
 
     if _redirect:
@@ -108,11 +108,12 @@ def hook(ui, repo, name, throw=False, **
             if hname.split('.')[0] != name or not cmd:
                 continue
             if callable(cmd):
-                r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
+                r = (_pythonhook(ui, repo, name, hname, cmd, args, throw,
+                                 quiet) or r)
             elif cmd.startswith('python:'):
                 if cmd.count(':') == 2:
                     path, cmd = cmd[7:].split(':')
-                    mod = extensions.loadpath(path, 'hgkook.%s' % hname)
+                    mod = util.loadpath(path, 'hgkook.%s' % hname)
                     hookfn = getattr(mod, cmd)
                 else:
                     hookfn = cmd[7:].strip()
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1464,3 +1464,14 @@ def iterlines(iterator):
     for chunk in iterator:
         for line in chunk.splitlines():
             yield line
+
+def loadpath(path, module_name):
+    module_name = module_name.replace('.', '_')
+    path = os.path.expanduser(path)
+    if os.path.isdir(path):
+        # module/__init__.py style
+        d, f = os.path.split(path.rstrip('/'))
+        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)


More information about the Mercurial-devel mailing list