revset: use delayregistrar to register predicate in extension easily

Previous patch introduced 'revset.predicate' decorator to register
revset predicate function easily.

But it shouldn't be used in extension directly, because it registers
specified function immediately. Registration itself can't be restored,
even if extension loading fails after that.

Therefore, registration should be delayed until 'uisetup()' or so.

This patch uses 'extpredicate' decorator derived from 'delayregistrar'
to register predicate in extension easily.

This patch also tests whether 'registrar.delayregistrar' avoids
function registration if 'setup()' isn't invoked on it, because
'extpredicate' is the first user of it.
This commit is contained in:
FUJIWARA Katsunori 2015-12-29 23:58:30 +09:00
parent 7a45cbf23f
commit 4d06739a86
7 changed files with 86 additions and 11 deletions

View File

@ -812,9 +812,11 @@ def overridepull(orig, ui, repo, source=None, **opts):
ui.status(_("%d largefiles cached\n") % numcached)
return result
revsetpredicate = revset.extpredicate()
@revsetpredicate('pulled()')
def pulledrevsetsymbol(repo, subset, x):
"""``pulled()``
Changesets that just has been pulled.
"""Changesets that just has been pulled.
Only available with largefiles from pull --lfrev expressions.

View File

@ -9,7 +9,7 @@
'''setup for largefiles extension: uisetup'''
from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
httppeer, merge, scmutil, sshpeer, wireproto, revset, subrepo, copies
httppeer, merge, scmutil, sshpeer, wireproto, subrepo, copies
from mercurial.i18n import _
from mercurial.hgweb import hgweb_mod, webcommands
@ -83,7 +83,6 @@ def uisetup(ui):
('', 'lfrev', [],
_('download largefiles for these revisions'), _('REV'))]
entry[1].extend(pullopt)
revset.symbols['pulled'] = overrides.pulledrevsetsymbol
entry = extensions.wrapcommand(commands.table, 'clone',
overrides.overrideclone)
@ -170,3 +169,5 @@ def uisetup(ui):
if name == 'transplant':
extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
overrides.overridetransplant)
overrides.revsetpredicate.setup()

View File

@ -3558,9 +3558,11 @@ def summaryhook(ui, repo):
# i18n: column positioning for "hg summary"
ui.note(_("mq: (empty queue)\n"))
revsetpredicate = revset.extpredicate()
@revsetpredicate('mq()')
def revsetmq(repo, subset, x):
"""``mq()``
Changesets managed by MQ.
"""Changesets managed by MQ.
"""
revset.getargs(x, 0, 0, _("mq takes no arguments"))
applied = set([repo[r.node].rev() for r in repo.mq.applied])
@ -3596,7 +3598,7 @@ def extsetup(ui):
if extmodule.__file__ != __file__:
dotable(getattr(extmodule, 'cmdtable', {}))
revset.symbols['mq'] = revsetmq
revsetpredicate.setup()
colortable = {'qguard.negative': 'red',
'qguard.positive': 'yellow',

View File

@ -64,6 +64,9 @@ def _destrebase(repo):
branch = repo[None].branch()
return repo[branch].rev()
revsetpredicate = revset.extpredicate()
@revsetpredicate('_destrebase')
def _revsetdestrebase(repo, subset, x):
# ``_rebasedefaultdest()``
@ -1238,4 +1241,4 @@ def uisetup(ui):
_("use 'hg rebase --continue' or 'hg rebase --abort'")])
# ensure rebased rev are not hidden
extensions.wrapfunction(repoview, '_getdynamicblockers', _rebasedvisible)
revset.symbols['_destrebase'] = _revsetdestrebase
revsetpredicate.setup()

View File

@ -693,9 +693,11 @@ def _dotransplant(ui, repo, *revs, **opts):
if cleanupfn:
cleanupfn()
revsetpredicate = revset.extpredicate()
@revsetpredicate('transplanted([set])')
def revsettransplanted(repo, subset, x):
"""``transplanted([set])``
Transplanted changesets in set, or all transplanted changesets.
"""Transplanted changesets in set, or all transplanted changesets.
"""
if x:
s = revset.getset(repo, subset, x)
@ -711,7 +713,7 @@ def kwtransplanted(repo, ctx, **args):
return n and revlog.hex(n) or ''
def extsetup(ui):
revset.symbols['transplanted'] = revsettransplanted
revsetpredicate.setup()
templatekw.keywords['transplanted'] = kwtransplanted
cmdutil.unfinishedstates.append(
['series', True, False, _('transplant in progress'),

View File

@ -487,11 +487,36 @@ class predicate(registrar.funcregistrar):
The first string argument of the constructor is used also in
online help.
Use 'extpredicate' instead of this to register revset predicate in
extensions.
"""
table = symbols
formatdoc = "``%s``\n %s"
getname = registrar.funcregistrar.parsefuncdecl
class extpredicate(registrar.delayregistrar):
"""Decorator to register revset predicate in extensions
Usage::
revsetpredicate = revset.extpredicate()
@revsetpredicate('mypredicate(arg1, arg2[, arg3])')
def mypredicatefunc(repo, subset, x):
'''Explanation of this revset predicate ....
'''
pass
def uisetup(ui):
revsetpredicate.setup()
'revsetpredicate' instance above can be used to decorate multiple
functions, and 'setup()' on it registers all such functions at
once.
"""
registrar = predicate
@predicate('_destupdate')
def _destupdate(repo, subset, x):
# experimental revset for update destination

View File

@ -2189,3 +2189,43 @@ test error message of bad revset
[255]
$ cd ..
Test registrar.delayregistrar via revset.extpredicate
'extpredicate' decorator shouldn't register any functions until
'setup()' on it.
$ cd repo
$ cat <<EOF > $TESTTMP/custompredicate.py
> from mercurial import revset
>
> revsetpredicate = revset.extpredicate()
>
> @revsetpredicate('custom1()')
> def custom1(repo, subset, x):
> return revset.baseset([1])
> @revsetpredicate('custom2()')
> def custom2(repo, subset, x):
> return revset.baseset([2])
>
> def uisetup(ui):
> if ui.configbool('custompredicate', 'enabled'):
> revsetpredicate.setup()
> EOF
$ cat <<EOF > .hg/hgrc
> [extensions]
> custompredicate = $TESTTMP/custompredicate.py
> EOF
$ hg debugrevspec "custom1()"
hg: parse error: unknown identifier: custom1
[255]
$ hg debugrevspec "custom2()"
hg: parse error: unknown identifier: custom2
[255]
$ hg debugrevspec "custom1() or custom2()" --config custompredicate.enabled=true
1
2
$ cd ..