diff --git a/hgext/color.py b/hgext/color.py --- a/hgext/color.py +++ b/hgext/color.py @@ -51,7 +51,7 @@ qseries.missing = red bold 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 @@ def render_effects(text, *effects): 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 @@ def colorstatus(statusfunc, ui, repo, *p '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 colorqseries(qseriesfunc, ui, repo, 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) diff --git a/hgext/highlight/__init__.py b/hgext/highlight/__init__.py --- a/hgext/highlight/__init__.py +++ b/hgext/highlight/__init__.py @@ -20,11 +20,9 @@ The default is 'colorful'. 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 @@ def filerevision_highlight(web, tmpl, fc 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 @@ def generate_css(web, req, tmpl): 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') diff --git a/hgext/interhg.py b/hgext/interhg.py --- a/hgext/interhg.py +++ b/hgext/interhg.py @@ -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 @@ def interhg_escape(x): 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 @@ def interhg_refresh(self): 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) diff --git a/hgext/keyword.py b/hgext/keyword.py --- a/hgext/keyword.py +++ b/hgext/keyword.py @@ -78,7 +78,7 @@ like CVS' $Log$, are not supported. A ke "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 @@ def uisetup(ui): 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 @@ def reposetup(ui, repo): 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 @@ def reposetup(ui, repo): 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': diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -33,7 +33,7 @@ from mercurial.i18n import _ 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 @@ def reposetup(ui, repo): 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'))] diff --git a/hgext/pager.py b/hgext/pager.py --- a/hgext/pager.py +++ b/hgext/pager.py @@ -47,10 +47,10 @@ them in the global .hgrc ''' 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 @@ def uisetup(ui): 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) diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -13,7 +13,7 @@ For more information: 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 @@ def buildstate(repo, dest, src, base, co 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 @@ def pulldelegate(pullfunction, repo, *ar 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": diff --git a/hgext/zeroconf/__init__.py b/hgext/zeroconf/__init__.py --- a/hgext/zeroconf/__init__.py +++ b/hgext/zeroconf/__init__.py @@ -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 @@ def getzcpaths(): 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