[PATCH 3 of 5 V3] registrar: define revsetpredicate to decorate revset predicate

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Tue Mar 8 09:08:25 EST 2016


# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1457445893 -32400
#      Tue Mar 08 23:04:53 2016 +0900
# Node ID 18c2e4e445a18615a09def95413d3ae9d7afd794
# Parent  401f828c4fd99fe01699ad99d40c596bb97edc58
registrar: define revsetpredicate to decorate revset predicate

revsetpredicate is used to replace revset.predicate and
revset.extpredicate in subsequent patches.

This patch also adds loadpredicate() to revset, because this
combination helps to figure out how the name of safe predicate is put
into safesymbols.

This patch still uses safesymbols set to examine whether the predicate
corresponded to the 'name' is safe from DoS attack or not, because
just setting func._safe property needs changes below for such
examination.

  before:
      name in revset.safesymbols

  after:
      getattr(revset.symbols.get(name, None), '_safe', False)

"automatic registration" described in help doc of revsetpredicate
class will be achieved by the subsequent patch, which lists
loadpredicate() up in dispatch.extraloaders.

diff --git a/mercurial/registrar.py b/mercurial/registrar.py
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -205,3 +205,36 @@ class _funcregistrarbase(object):
         """Execute exra setup for registered function, if needed
         """
         pass
+
+class revsetpredicate(_funcregistrarbase):
+    """Decorator to register revset predicate
+
+    Usage::
+
+        revsetpredicate = registrar.revsetpredicate()
+
+        @revsetpredicate('mypredicate(arg1, arg2[, arg3])')
+        def mypredicatefunc(repo, subset, x):
+            '''Explanation of this revset predicate ....
+            '''
+            pass
+
+    The first string argument is used also in online help.
+
+    Optional argument 'safe' indicates whether a predicate is safe for
+    DoS attack (False by default).
+
+    'revsetpredicate' instance in example above can be used to
+    decorate multiple functions.
+
+    Decorated functions are registered automatically at loading
+    extension, if an instance named as 'revsetpredicate' is used for
+    decorating in extension.
+
+    Otherwise, explicit 'revset.loadpredicate()' is needed.
+    """
+    _getname = _funcregistrarbase._parsefuncdecl
+    _docformat = "``%s``\n    %s"
+
+    def _extrasetup(self, name, func, safe=False):
+        func._safe = safe
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -3628,5 +3628,13 @@ def prettyformatset(revs):
         p = q
     return '\n'.join('  ' * l + s for l, s in lines)
 
+def loadpredicate(ui, extname, registrarobj):
+    """Load revset predicates from specified registrarobj
+    """
+    for name, func in registrarobj._table.iteritems():
+        symbols[name] = func
+        if func._safe:
+            safesymbols.add(name)
+
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = symbols.values()


More information about the Mercurial-devel mailing list