extensions: use new wrapper functions
authorMatt Mackall <mpm@selenic.com>
Wed, 22 Oct 2008 17:34:52 -0500
changeset 7216 292fb2ad2846
parent 7215 0ab5f21c390b
child 7217 9fa2f8dcb869
extensions: use new wrapper functions
hgext/color.py
hgext/highlight/__init__.py
hgext/interhg.py
hgext/keyword.py
hgext/mq.py
hgext/pager.py
hgext/rebase.py
hgext/zeroconf/__init__.py
--- a/hgext/color.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/color.py	Wed Oct 22 17:34:52 2008 -0500
@@ -51,7 +51,7 @@
 
 import re, sys
 
-from mercurial import commands, cmdutil
+from mercurial import commands, cmdutil, extensions
 from mercurial.i18n import _
 
 # start and stop parameters for effects
@@ -89,14 +89,14 @@
     stop = '\033[' + ';'.join(stop) + 'm'
     return start + text + stop
 
-def colorstatus(statusfunc, ui, repo, *pats, **opts):
+def colorstatus(orig, ui, repo, *pats, **opts):
     '''run the status command with colored output'''
 
     delimiter = opts['print0'] and '\0' or '\n'
 
     # run status and capture it's output
     ui.pushbuffer()
-    retval = statusfunc(ui, repo, *pats, **opts)
+    retval = orig(ui, repo, *pats, **opts)
     # filter out empty strings
     lines = [ line for line in ui.popbuffer().split(delimiter) if line ]
 
@@ -139,10 +139,10 @@
                     'clean': ('none', ),
                     'copied': ('none', ), }
 
-def colorqseries(qseriesfunc, ui, repo, *dummy, **opts):
+def colorqseries(orig, ui, repo, *dummy, **opts):
     '''run the qseries command with colored output'''
     ui.pushbuffer()
-    retval = qseriesfunc(ui, repo, **opts)
+    retval = orig(ui, repo, **opts)
     patches = ui.popbuffer().splitlines()
     for patch in patches:
         patchname = patch
@@ -168,58 +168,23 @@
 
 def uisetup(ui):
     '''Initialize the extension.'''
-    nocoloropt = ('', 'no-color', None, _("don't colorize output"))
-    _decoratecmd(ui, 'status', commands.table, colorstatus, nocoloropt)
-    _configcmdeffects(ui, 'status', _status_effects);
+    _setupcmd(ui, 'status', commands.table, colorstatus, _status_effects)
     if ui.config('extensions', 'hgext.mq') is not None or \
             ui.config('extensions', 'mq') is not None:
         from hgext import mq
-        _decoratecmd(ui, 'qseries', mq.cmdtable, colorqseries, nocoloropt)
-        _configcmdeffects(ui, 'qseries', _patch_effects);
-
-def _decoratecmd(ui, cmd, table, delegate, *delegateoptions):
-    '''Replace the function that implements cmd in table with a decorator.
-
-    The decorator that becomes the new implementation of cmd calls
-    delegate.  The delegate's first argument is the replaced function,
-    followed by the normal Mercurial command arguments (ui, repo, ...).  If
-    the delegate adds command options, supply them as delegateoptions.
-    '''
-    cmdkey, cmdentry = _cmdtableitem(ui, cmd, table)
-    decorator = lambda ui, repo, *args, **opts: \
-                    _colordecorator(delegate, cmdentry[0],
-                                    ui, repo, *args, **opts)
-    # make sure 'hg help cmd' still works
-    decorator.__doc__ = cmdentry[0].__doc__
-    decoratorentry = (decorator,) + cmdentry[1:]
-    for option in delegateoptions:
-        decoratorentry[1].append(option)
-    table[cmdkey] = decoratorentry
+        _setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects)
 
-def _cmdtableitem(ui, cmd, table):
-    '''Return key, value from table for cmd, or None if not found.'''
-    aliases, entry = cmdutil.findcmd(cmd, table)
-    for candidatekey, candidateentry in table.iteritems():
-        if candidateentry is entry:
-            return candidatekey, entry
-
-def _colordecorator(colorfunc, nocolorfunc, ui, repo, *args, **opts):
-    '''Delegate to colorfunc or nocolorfunc, depending on conditions.
+def _setupcmd(ui, cmd, table, func, effectsmap):
+    '''patch in command to command table and load effect map'''
+    def nocolor(orig, *args, **kwargs):
+        if kwargs['no_color']:
+            return orig(*args, **kwargs)
+        return func(orig, *args, **kwargs)
 
-    Delegate to colorfunc unless --no-color option is set or output is not
-    to a tty.
-    '''
-    if opts['no_color'] or not sys.stdout.isatty():
-        return nocolorfunc(ui, repo, *args, **opts)
-    return colorfunc(nocolorfunc, ui, repo, *args, **opts)
+    entry = extensions.wrapcommand(table, cmd, nocolor)
+    entry[1].append(('', 'no-color', None, _("don't colorize output")))
 
-def _configcmdeffects(ui, cmdname, effectsmap):
-    '''Override default effects for cmdname with those from .hgrc file.
-
-    Entries in the .hgrc file are in the [color] section, and look like
-    'cmdname'.'status' (for instance, 'status.modified = blue bold inverse').
-    '''
     for status in effectsmap:
-        effects = ui.config('color', cmdname + '.' + status)
+        effects = ui.config('color', cmd + '.' + status)
         if effects:
             effectsmap[status] = re.split('\W+', effects)
--- a/hgext/highlight/__init__.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/highlight/__init__.py	Wed Oct 22 17:34:52 2008 -0500
@@ -20,11 +20,9 @@
 
 import highlight
 from mercurial.hgweb import webcommands, webutil, common
+from mercurial import extensions
 
-web_filerevision = webcommands._filerevision
-web_annotate = webcommands.annotate
-
-def filerevision_highlight(web, tmpl, fctx):
+def filerevision_highlight(orig, web, tmpl, fctx):
     mt = ''.join(tmpl('mimetype', encoding=web.encoding))
     # only pygmentize for mimetype containing 'html' so we both match
     # 'text/html' and possibly 'application/xhtml+xml' in the future
@@ -36,15 +34,15 @@
     if 'html' in mt:
         style = web.config('web', 'pygments_style', 'colorful')
         highlight.pygmentize('fileline', fctx, style, tmpl)
-    return web_filerevision(web, tmpl, fctx)
+    return orig(web, tmpl, fctx)
 
-def annotate_highlight(web, req, tmpl):
+def annotate_highlight(orig, web, req, tmpl):
     mt = ''.join(tmpl('mimetype', encoding=web.encoding))
     if 'html' in mt:
         fctx = webutil.filectx(web.repo, req)
         style = web.config('web', 'pygments_style', 'colorful')
         highlight.pygmentize('annotateline', fctx, style, tmpl)
-    return web_annotate(web, req, tmpl)
+    return orig(web, req, tmpl)
 
 def generate_css(web, req, tmpl):
     pg_style = web.config('web', 'pygments_style', 'colorful')
@@ -52,10 +50,8 @@
     req.respond(common.HTTP_OK, 'text/css')
     return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
 
-
 # monkeypatch in the new version
-
-webcommands._filerevision = filerevision_highlight
-webcommands.annotate = annotate_highlight
+extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
+extensions.wrapfunction(webcommands, 'annotate', annotate_highlight)
 webcommands.highlightcss = generate_css
 webcommands.__all__.append('highlightcss')
--- a/hgext/interhg.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/interhg.py	Wed Oct 22 17:34:52 2008 -0500
@@ -27,7 +27,7 @@
 
 import re
 from mercurial.hgweb import hgweb_mod
-from mercurial import templatefilters
+from mercurial import templatefilters, extensions
 from mercurial.i18n import _
 
 orig_escape = templatefilters.filters["escape"]
@@ -42,9 +42,7 @@
 
 templatefilters.filters["escape"] = interhg_escape
 
-orig_refresh = hgweb_mod.hgweb.refresh
-
-def interhg_refresh(self):
+def interhg_refresh(orig, self):
     interhg_table[:] = []
     for key, pattern in self.repo.ui.configitems('interhg'):
         # grab the delimiter from the character after the "s"
@@ -79,6 +77,6 @@
         except re.error:
             self.repo.ui.warn(_("interhg: invalid regexp for %s: %s\n")
                               % (key, regexp))
-    return orig_refresh(self)
+    return orig(self)
 
-hgweb_mod.hgweb.refresh = interhg_refresh
+extensions.wrapfunction(hgweb_mod.hgweb, 'refresh', interhg_refresh)
--- a/hgext/keyword.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/keyword.py	Wed Oct 22 17:34:52 2008 -0500
@@ -78,7 +78,7 @@
 "Log = {desc}" expands to the first line of the changeset description.
 '''
 
-from mercurial import commands, cmdutil, dispatch, filelog, revlog
+from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
 from mercurial import patch, localrepo, templater, templatefilters, util
 from mercurial.hgweb import webcommands
 from mercurial.node import nullid, hex
@@ -416,14 +416,13 @@
             kwtools['exc'].append(pat)
 
     if kwtools['inc']:
-        def kwdispatch_parse(ui, args):
+        def kwdispatch_parse(orig, ui, args):
             '''Monkeypatch dispatch._parse to obtain running hg command.'''
-            cmd, func, args, options, cmdoptions = dispatch_parse(ui, args)
+            cmd, func, args, options, cmdoptions = orig(ui, args)
             kwtools['hgcmd'] = cmd
             return cmd, func, args, options, cmdoptions
 
-        dispatch_parse = dispatch._parse
-        dispatch._parse = kwdispatch_parse
+        extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
 
 def reposetup(ui, repo):
     '''Sets up repo as kwrepo for keyword substitution.
@@ -495,14 +494,14 @@
                 del wlock, lock
 
     # monkeypatches
-    def kwpatchfile_init(self, ui, fname, missing=False):
+    def kwpatchfile_init(orig, self, ui, fname, missing=False):
         '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
         rejects or conflicts due to expanded keywords in working dir.'''
-        patchfile_init(self, ui, fname, missing)
+        orig(self, ui, fname, missing)
         # shrink keywords read from working dir
         self.lines = kwt.shrinklines(self.fname, self.lines)
 
-    def kw_diff(repo, node1=None, node2=None, match=None,
+    def kw_diff(orig, repo, node1=None, node2=None, match=None,
                 fp=None, changes=None, opts=None):
         '''Monkeypatch patch.diff to avoid expansion except when
         comparing against working dir.'''
@@ -510,37 +509,19 @@
             kwt.matcher = util.never
         elif node1 is not None and node1 != repo['.'].node():
             kwt.restrict = True
-        patch_diff(repo, node1, node2, match, fp, changes, opts)
-
-    def kwweb_annotate(web, req, tmpl):
-        '''Wraps webcommands.annotate turning off keyword expansion.'''
-        kwt.matcher = util.never
-        return webcommands_annotate(web, req, tmpl)
+        orig(repo, node1, node2, match, fp, changes, opts)
 
-    def kwweb_changeset(web, req, tmpl):
-        '''Wraps webcommands.changeset turning off keyword expansion.'''
+    def kwweb_skip(orig, web, req, tmpl):
+        '''Wraps webcommands.x turning off keyword expansion.'''
         kwt.matcher = util.never
-        return webcommands_changeset(web, req, tmpl)
-
-    def kwweb_filediff(web, req, tmpl):
-        '''Wraps webcommands.filediff turning off keyword expansion.'''
-        kwt.matcher = util.never
-        return webcommands_filediff(web, req, tmpl)
+        return orig(web, req, tmpl)
 
     repo.__class__ = kwrepo
 
-    patchfile_init = patch.patchfile.__init__
-    patch_diff = patch.diff
-    webcommands_annotate = webcommands.annotate
-    webcommands_changeset = webcommands.changeset
-    webcommands_filediff = webcommands.filediff
-
-    patch.patchfile.__init__ = kwpatchfile_init
-    patch.diff = kw_diff
-    webcommands.annotate = kwweb_annotate
-    webcommands.changeset = webcommands.rev = kwweb_changeset
-    webcommands.filediff = webcommands.diff = kwweb_filediff
-
+    extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
+    extensions.wrapfunction(patch, 'diff', kw_diff)
+    for c in 'annotate changeset rev filediff diff'.split():
+        extensions.wrapfunction(webcommands, c, kwweb_skip)
 
 cmdtable = {
     'kwdemo':
--- a/hgext/mq.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/mq.py	Wed Oct 22 17:34:52 2008 -0500
@@ -33,7 +33,7 @@
 from mercurial.node import bin, hex, short
 from mercurial.repo import RepoError
 from mercurial import commands, cmdutil, hg, patch, revlog, util
-from mercurial import repair
+from mercurial import repair, extensions
 import os, sys, re, errno, urllib
 
 commands.norepo += " qclone"
@@ -2366,22 +2366,14 @@
         repo.__class__ = mqrepo
         repo.mq = queue(ui, repo.join(""))
 
+def mqimport(orig, ui, repo, *args, **kwargs):
+    if hasattr(repo, 'abort_if_wdir_patched'):
+        repo.abort_if_wdir_patched(_('cannot import over an applied patch'),
+                                   kwargs.get('force'))
+    return orig(ui, repo, *args, **kwargs)
+
 def uisetup(ui):
-    # override import to disallow importing over patch
-    importalias, importcmd = cmdutil.findcmd('import', commands.table)
-    for alias, cmd in commands.table.iteritems():
-        if cmd is importcmd:
-            importkey = alias
-            break
-    orig_import = importcmd[0]
-    def mqimport(ui, repo, patch1, *patches, **opts):
-        if hasattr(repo, 'abort_if_wdir_patched'):
-            repo.abort_if_wdir_patched(_('cannot import over an applied patch'),
-                                       opts.get('force'))
-            orig_import(ui, repo, patch1, *patches, **opts)
-    importcmd = list(importcmd)
-    importcmd[0] = mqimport
-    commands.table[importkey] = tuple(importcmd)
+    extensions.wrapcommand(commands.table, 'import', mqimport)
 
 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
 
--- a/hgext/pager.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/pager.py	Wed Oct 22 17:34:52 2008 -0500
@@ -47,10 +47,10 @@
 '''
 
 import sys, os, signal
-from mercurial import dispatch, util
+from mercurial import dispatch, util, extensions
 
 def uisetup(ui):
-    def pagecmd(ui, options, cmd, cmdfunc):
+    def pagecmd(orig, ui, options, cmd, cmdfunc):
         p = ui.config("pager", "pager", os.environ.get("PAGER"))
         if p and sys.stdout.isatty() and '--debugger' not in sys.argv:
             attend = ui.configlist('pager', 'attend')
@@ -59,7 +59,6 @@
                 sys.stderr = sys.stdout = util.popen(p, "wb")
                 if ui.configbool('pager', 'quiet'):
                     signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-        return oldrun(ui, options, cmd, cmdfunc)
+        return orig(ui, options, cmd, cmdfunc)
 
-    oldrun = dispatch._runcommand
-    dispatch._runcommand = pagecmd
+    extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
--- a/hgext/rebase.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/rebase.py	Wed Oct 22 17:34:52 2008 -0500
@@ -13,7 +13,7 @@
 http://www.selenic.com/mercurial/wiki/index.cgi/RebaseProject
 '''
 
-from mercurial import util, repair, merge, cmdutil, dispatch, commands
+from mercurial import util, repair, merge, cmdutil, dispatch, commands, extensions
 from mercurial.commands import templateopts
 from mercurial.node import nullrev
 from mercurial.i18n import _
@@ -352,7 +352,7 @@
     state[source] = nullrev
     return repo['.'].rev(), repo[dest].rev(), state, external
 
-def pulldelegate(pullfunction, repo, *args, **opts):
+def pullrebase(orig, ui, repo, *args, **opts):
     'Call rebase after pull if the latter has been invoked with --rebase'
     if opts.get('rebase'):
         if opts.get('update'):
@@ -360,31 +360,19 @@
 
         cmdutil.bail_if_changed(repo)
         revsprepull = len(repo)
-        pullfunction(repo.ui, repo, *args, **opts)
+        orig(ui, repo, *args, **opts)
         revspostpull = len(repo)
         if revspostpull > revsprepull:
-            rebase(repo.ui, repo, **opts)
+            rebase(ui, repo, **opts)
     else:
-        pullfunction(repo.ui, repo, *args, **opts)
+        orig(ui, repo, *args, **opts)
 
 def uisetup(ui):
     'Replace pull with a decorator to provide --rebase option'
-    # cribbed from color.py
-    aliases, entry = cmdutil.findcmd('pull', commands.table)
-    for candidatekey, candidateentry in commands.table.iteritems():
-        if candidateentry is entry:
-            cmdkey, cmdentry = candidatekey, entry
-            break
-
-    decorator = lambda ui, repo, *args, **opts: \
-                    pulldelegate(cmdentry[0], repo, *args, **opts)
-    # make sure 'hg help cmd' still works
-    decorator.__doc__ = cmdentry[0].__doc__
-    decoratorentry = (decorator,) + cmdentry[1:]
-    rebaseopt = ('', 'rebase', None,
-                            _("rebase working directory to branch head"))
-    decoratorentry[1].append(rebaseopt)
-    commands.table[cmdkey] = decoratorentry
+    entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
+    entry[1].append(('', 'rebase', None,
+                     _("rebase working directory to branch head"))
+)
 
 cmdtable = {
 "rebase":
--- a/hgext/zeroconf/__init__.py	Wed Oct 22 17:34:50 2008 -0500
+++ b/hgext/zeroconf/__init__.py	Wed Oct 22 17:34:52 2008 -0500
@@ -8,6 +8,7 @@
 
 import Zeroconf, socket, time, os
 from mercurial import ui
+from mercurial import extensions
 from mercurial.hgweb import hgweb_mod
 from mercurial.hgweb import hgwebdir_mod
 
@@ -114,22 +115,20 @@
                                  v.properties.get("path", "/"))
         yield "zc-" + n, u
 
-def config(self, section, key, default=None, untrusted=False):
+def config(orig, self, section, key, default=None, untrusted=False):
     if section == "paths" and key.startswith("zc-"):
         for n, p in getzcpaths():
             if n == key:
                 return p
-    return oldconfig(self, section, key, default, untrusted)
+    return orig(self, section, key, default, untrusted)
 
-def configitems(self, section):
-    r = oldconfigitems(self, section, untrusted=False)
+def configitems(orig, self, section):
+    r = orig(self, section, untrusted=False)
     if section == "paths":
         r += getzcpaths()
     return r
 
-oldconfig = ui.ui.config
-oldconfigitems = ui.ui.configitems
-ui.ui.config = config
-ui.ui.configitems = configitems
+extensions.wrapfunction(ui.ui, 'config', config)
+extensions.wrapfunction(ui.ui, 'configitems', configitems)
 hgweb_mod.hgweb = hgwebzc
 hgwebdir_mod.hgwebdir = hgwebdirzc