diff mercurial/debugcommands.py @ 37483:61e405fb6372

wireproto: crude support for version 2 HTTP peer As part of implementing the server-side bits of the wire protocol command handlers for version 2, we want a way to easily test those commands. Currently, we use the "httprequest" action of `hg debugwireproto`. But this requires explicitly specifying the HTTP request headers, low-level frame details, and the data structure to encode with CBOR. That's a lot of boilerplate and a lot of it can change as the wire protocol evolves. `hg debugwireproto` has a mechanism to issue commands via the peer interface. That is *much* easier to use and we prefer to test with that going forward. This commit implements enough parts of the peer API to send basic requests via the HTTP version 2 transport. The peer code is super hacky. Again, the goal is to facilitate server testing, not robustly implement a client. The client code will receive love at a later time. Differential Revision: https://phab.mercurial-scm.org/D3177
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 28 Mar 2018 15:09:34 -0700
parents 9966f44ecab4
children 835ccc2a5ef1
line wrap: on
line diff
--- a/mercurial/debugcommands.py	Mon Mar 26 15:34:52 2018 -0700
+++ b/mercurial/debugcommands.py	Wed Mar 28 15:09:34 2018 -0700
@@ -2631,8 +2631,8 @@
 
     ``--peer`` can be used to bypass the handshake protocol and construct a
     peer instance using the specified class type. Valid values are ``raw``,
-    ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending raw data
-    payloads and don't support higher-level command actions.
+    ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
+    raw data payloads and don't support higher-level command actions.
 
     ``--noreadstderr`` can be used to disable automatic reading from stderr
     of the peer (for SSH connections only). Disabling automatic reading of
@@ -2678,8 +2678,10 @@
        command listkeys
            namespace bookmarks
 
-    Values are interpreted as Python b'' literals. This allows encoding
-    special byte sequences via backslash escaping.
+    If the value begins with ``eval:``, it will be interpreted as a Python
+    literal expression. Otherwise values are interpreted as Python b'' literals.
+    This allows sending complex types and encoding special byte sequences via
+    backslash escaping.
 
     The following arguments have special meaning:
 
@@ -2803,7 +2805,7 @@
     if opts['localssh'] and not repo:
         raise error.Abort(_('--localssh requires a repository'))
 
-    if opts['peer'] and opts['peer'] not in ('raw', 'ssh1', 'ssh2'):
+    if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
         raise error.Abort(_('invalid value for --peer'),
                           hint=_('valid values are "raw", "ssh1", and "ssh2"'))
 
@@ -2877,18 +2879,20 @@
             raise error.Abort(_('only http:// paths are currently supported'))
 
         url, authinfo = u.authinfo()
-        openerargs = {}
+        openerargs = {
+            r'useragent': b'Mercurial debugwireproto',
+        }
 
         # Turn pipes/sockets into observers so we can log I/O.
         if ui.verbose:
-            openerargs = {
+            openerargs.update({
                 r'loggingfh': ui,
                 r'loggingname': b's',
                 r'loggingopts': {
                     r'logdata': True,
                     r'logdataapis': False,
                 },
-            }
+            })
 
         if ui.debugflag:
             openerargs[r'loggingopts'][r'logdataapis'] = True
@@ -2901,7 +2905,10 @@
 
         opener = urlmod.opener(ui, authinfo, **openerargs)
 
-        if opts['peer'] == 'raw':
+        if opts['peer'] == 'http2':
+            ui.write(_('creating http peer for wire protocol version 2\n'))
+            peer = httppeer.httpv2peer(ui, path, opener)
+        elif opts['peer'] == 'raw':
             ui.write(_('using raw connection to peer\n'))
             peer = None
         elif opts['peer']:
@@ -2951,7 +2958,12 @@
                 else:
                     key, value = fields
 
-                args[key] = stringutil.unescapestr(value)
+                if value.startswith('eval:'):
+                    value = stringutil.evalpythonliteral(value[5:])
+                else:
+                    value = stringutil.unescapestr(value)
+
+                args[key] = value
 
             if batchedcommands is not None:
                 batchedcommands.append((command, args))