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

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Tue Jan 5 05:48:36 CST 2016


# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1451994203 -32400
#      Tue Jan 05 20:43:23 2016 +0900
# Node ID c6554052f10db3a9312b17c658bf8c579198a5d2
# Parent  de07b46cc5de1baa86d40492941fd56c849311c3
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)

diff --git a/mercurial/registrar.py b/mercurial/registrar.py
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -208,3 +208,30 @@ 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.
+    """
+    getname = funcregistrarbase.parsefuncdecl
+    formatdoc = "``%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
@@ -3667,5 +3667,16 @@ def prettyformatset(revs):
         p = q
     return '\n'.join('  ' * l + s for l, s in lines)
 
+def loadpredicate(ui, extname, predicateobj):
+    """Load revset predicates from specified predicateobj
+    """
+    if not isinstance(predicateobj, registrar.revsetpredicate):
+        # extension may not know about recent 'revsetpredicate' naming rule
+        return
+    for name, func in predicateobj.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