diff mercurial/wireprotov2server.py @ 37780:8acd3a9ac4fd

wireproto: make version 2 @wireprotocommand an independent function Previously, the code for this decorator was shared between version 1 and version 2 commands. Very few parts of the function were identical. So I don't think sharing is justified. wireprotov2server now has its own @wireprotocommand decorator function. Because the decorator is no longer shared, code for configuring the transport policy has been removed. i.e. commands must have separate implementations for each wire protocol version. Differential Revision: https://phab.mercurial-scm.org/D3395
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 16 Apr 2018 21:49:59 -0700
parents 564a3eec6e63
children 352932a11905
line wrap: on
line diff
--- a/mercurial/wireprotov2server.py	Mon Apr 16 21:38:52 2018 -0700
+++ b/mercurial/wireprotov2server.py	Mon Apr 16 21:49:59 2018 -0700
@@ -405,10 +405,43 @@
 
     return proto.addcapabilities(repo, caps)
 
-def wireprotocommand(*args, **kwargs):
+def wireprotocommand(name, args=None, permission='push'):
+    """Decorator to declare a wire protocol command.
+
+    ``name`` is the name of the wire protocol command being provided.
+
+    ``args`` is a dict of argument names to example values.
+
+    ``permission`` defines the permission type needed to run this command.
+    Can be ``push`` or ``pull``. These roughly map to read-write and read-only,
+    respectively. Default is to assume command requires ``push`` permissions
+    because otherwise commands not declaring their permissions could modify
+    a repository that is supposed to be read-only.
+    """
+    transports = {k for k, v in wireprototypes.TRANSPORTS.items()
+                  if v['version'] == 2}
+
+    if permission not in ('push', 'pull'):
+        raise error.ProgrammingError('invalid wire protocol permission; '
+                                     'got %s; expected "push" or "pull"' %
+                                     permission)
+
+    if args is None:
+        args = {}
+
+    if not isinstance(args, dict):
+        raise error.ProgrammingError('arguments for version 2 commands '
+                                     'must be declared as dicts')
+
     def register(func):
-        return wireproto.wireprotocommand(
-            *args, transportpolicy=wireproto.POLICY_V2_ONLY, **kwargs)(func)
+        if name in wireproto.commandsv2:
+            raise error.ProgrammingError('%s command already registered '
+                                         'for version 2' % name)
+
+        wireproto.commandsv2[name] = wireproto.commandentry(
+            func, args=args, transports=transports, permission=permission)
+
+        return func
 
     return register