D3385: wireprotov2: change command response protocol to include a leading map

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Sun Apr 15 00:23:05 UTC 2018


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The error handling mechanism for the new wire protocol isn't very
  well-defined. This commit takes us a step in the right direction
  by introducing a leading CBOR map for command responses. This map
  will contain an overall result of the command.
  
  Currently, the map indicates whether the command was overall
  successful or if an error occurred. And if an error occurred, that
  error is present in the map.
  
  There is still a dedicated error frame. My intent is to use that
  for protocol-level errors and for errors that are encountered after
  the initial response frame has been sent. This will be clarified in a
  later commit.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3385

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoframing.py
  mercurial/wireprotov2peer.py
  mercurial/wireprotov2server.py
  tests/test-http-api-httpv2.t
  tests/test-http-protocol.t
  tests/test-wireproto-command-branchmap.t
  tests/test-wireproto-command-capabilities.t
  tests/test-wireproto-command-heads.t
  tests/test-wireproto-command-known.t
  tests/test-wireproto-command-listkeys.t
  tests/test-wireproto-command-lookup.t
  tests/test-wireproto-command-pushkey.t
  tests/test-wireproto-serverreactor.py
  tests/wireprotohelpers.sh

CHANGE DETAILS

diff --git a/tests/wireprotohelpers.sh b/tests/wireprotohelpers.sh
--- a/tests/wireprotohelpers.sh
+++ b/tests/wireprotohelpers.sh
@@ -1,5 +1,5 @@
 HTTPV2=exp-http-v2-0001
-MEDIATYPE=application/mercurial-exp-framing-0004
+MEDIATYPE=application/mercurial-exp-framing-0005
 
 sendhttpraw() {
   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
diff --git a/tests/test-wireproto-serverreactor.py b/tests/test-wireproto-serverreactor.py
--- a/tests/test-wireproto-serverreactor.py
+++ b/tests/test-wireproto-serverreactor.py
@@ -12,6 +12,8 @@
 
 ffs = framing.makeframefromhumanstring
 
+OK = cbor.dumps({b'status': b'ok'})
+
 def makereactor(deferoutput=False):
     return framing.serverreactor(deferoutput=deferoutput)
 
@@ -350,7 +352,7 @@
         result = reactor.oncommandresponseready(outstream, 1, b'response')
         self.assertaction(result, b'sendframes')
         self.assertframesequal(result[1][b'framegen'], [
-            b'1 2 stream-begin command-response eos response',
+            b'1 2 stream-begin command-response eos %sresponse' % OK,
         ])
 
     def testmultiframeresponse(self):
@@ -366,7 +368,8 @@
         result = reactor.oncommandresponseready(outstream, 1, first + second)
         self.assertaction(result, b'sendframes')
         self.assertframesequal(result[1][b'framegen'], [
-            b'1 2 stream-begin command-response continuation %s' % first,
+            b'1 2 stream-begin command-response continuation %s' % OK,
+            b'1 2 0 command-response continuation %s' % first,
             b'1 2 0 command-response eos %s' % second,
         ])
 
@@ -397,7 +400,7 @@
         result = reactor.oninputeof()
         self.assertaction(result, b'sendframes')
         self.assertframesequal(result[1][b'framegen'], [
-            b'1 2 stream-begin command-response eos response',
+            b'1 2 stream-begin command-response eos %sresponse' % OK,
         ])
 
     def testmultiplecommanddeferresponse(self):
@@ -414,8 +417,8 @@
         result = reactor.oninputeof()
         self.assertaction(result, b'sendframes')
         self.assertframesequal(result[1][b'framegen'], [
-            b'1 2 stream-begin command-response eos response1',
-            b'3 2 0 command-response eos response2'
+            b'1 2 stream-begin command-response eos %sresponse1' % OK,
+            b'3 2 0 command-response eos %sresponse2' % OK,
         ])
 
     def testrequestidtracking(self):
@@ -434,9 +437,9 @@
         result = reactor.oninputeof()
         self.assertaction(result, b'sendframes')
         self.assertframesequal(result[1][b'framegen'], [
-            b'3 2 stream-begin command-response eos response3',
-            b'1 2 0 command-response eos response1',
-            b'5 2 0 command-response eos response5',
+            b'3 2 stream-begin command-response eos %sresponse3' % OK,
+            b'1 2 0 command-response eos %sresponse1' % OK,
+            b'5 2 0 command-response eos %sresponse5' % OK,
         ])
 
     def testduplicaterequestonactivecommand(self):
diff --git a/tests/test-wireproto-command-pushkey.t b/tests/test-wireproto-command-pushkey.t
--- a/tests/test-wireproto-command-pushkey.t
+++ b/tests/test-wireproto-command-pushkey.t
@@ -32,8 +32,8 @@
   sending pushkey command
   s>     *\r\n (glob)
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 105\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -43,14 +43,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     9\r\n
-  s>     \x01\x00\x00\x01\x00\x02\x012
-  s>     \xf5
+  s>     14\r\n
+  s>     \x0c\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\xf5
   s>     \r\n
-  received frame(size=1; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=12; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: True
@@ -63,8 +63,8 @@
   sending listkeys command
   s>     POST /api/exp-http-v2-0001/ro/listkeys HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 49\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -74,14 +74,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     35\r\n
-  s>     -\x00\x00\x01\x00\x02\x012
-  s>     \xa1A at X(426bada5c67598ca65036d57d9e4b64b0c1ce7a0
+  s>     40\r\n
+  s>     8\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\xa1A at X(426bada5c67598ca65036d57d9e4b64b0c1ce7a0
   s>     \r\n
-  received frame(size=45; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=56; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: {b'@': b'426bada5c67598ca65036d57d9e4b64b0c1ce7a0'}
diff --git a/tests/test-wireproto-command-lookup.t b/tests/test-wireproto-command-lookup.t
--- a/tests/test-wireproto-command-lookup.t
+++ b/tests/test-wireproto-command-lookup.t
@@ -29,8 +29,8 @@
   sending lookup command
   s>     *\r\n (glob)
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 73\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -40,14 +40,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     1d\r\n
-  s>     \x15\x00\x00\x01\x00\x02\x012
-  s>     TBk\xad\xa5\xc6u\x98\xcae\x03mW\xd9\xe4\xb6K\x0c\x1c\xe7\xa0
+  s>     28\r\n
+  s>      \x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBokTBk\xad\xa5\xc6u\x98\xcae\x03mW\xd9\xe4\xb6K\x0c\x1c\xe7\xa0
   s>     \r\n
-  received frame(size=21; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=32; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: b'Bk\xad\xa5\xc6u\x98\xcae\x03mW\xd9\xe4\xb6K\x0c\x1c\xe7\xa0'
diff --git a/tests/test-wireproto-command-listkeys.t b/tests/test-wireproto-command-listkeys.t
--- a/tests/test-wireproto-command-listkeys.t
+++ b/tests/test-wireproto-command-listkeys.t
@@ -33,8 +33,8 @@
   sending listkeys command
   s>     POST /api/exp-http-v2-0001/ro/listkeys HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 50\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -44,14 +44,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     28\r\n
-  s>      \x00\x00\x01\x00\x02\x012
-  s>     \xa3Fphases at Ibookmarks@Jnamespaces@
+  s>     33\r\n
+  s>     +\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\xa3Fphases at Ibookmarks@Jnamespaces@
   s>     \r\n
-  received frame(size=32; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=43; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
@@ -66,8 +66,8 @@
   sending listkeys command
   s>     POST /api/exp-http-v2-0001/ro/listkeys HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 46\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -77,14 +77,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     45\r\n
-  s>     =\x00\x00\x01\x00\x02\x012
-  s>     \xa2JpublishingDTrueX(be0ef73c17ade3fc89dc41701eb9fc3a91b58282A1
+  s>     50\r\n
+  s>     H\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\xa2JpublishingDTrueX(be0ef73c17ade3fc89dc41701eb9fc3a91b58282A1
   s>     \r\n
-  received frame(size=61; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=72; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: {b'be0ef73c17ade3fc89dc41701eb9fc3a91b58282': b'1', b'publishing': b'True'}
@@ -99,8 +99,8 @@
   sending listkeys command
   s>     POST /api/exp-http-v2-0001/ro/listkeys HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 49\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -110,14 +110,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     35\r\n
-  s>     -\x00\x00\x01\x00\x02\x012
-  s>     \xa1A at X(26805aba1e600a82e93661149f2313866a221a7b
+  s>     40\r\n
+  s>     8\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\xa1A at X(26805aba1e600a82e93661149f2313866a221a7b
   s>     \r\n
-  received frame(size=45; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=56; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: {b'@': b'26805aba1e600a82e93661149f2313866a221a7b'}
diff --git a/tests/test-wireproto-command-known.t b/tests/test-wireproto-command-known.t
--- a/tests/test-wireproto-command-known.t
+++ b/tests/test-wireproto-command-known.t
@@ -29,8 +29,8 @@
   sending known command
   s>     POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 20\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -40,14 +40,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     9\r\n
-  s>     \x01\x00\x00\x01\x00\x02\x012
-  s>     @
+  s>     14\r\n
+  s>     \x0c\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok@
   s>     \r\n
-  received frame(size=1; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=12; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: []
@@ -62,8 +62,8 @@
   sending known command
   s>     POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 54\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -73,14 +73,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     a\r\n
-  s>     \x02\x00\x00\x01\x00\x02\x012
-  s>     A1
+  s>     15\r\n
+  s>     \r\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBokA1
   s>     \r\n
-  received frame(size=2; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=13; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: [True]
@@ -95,8 +95,8 @@
   sending known command
   s>     POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 96\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -106,14 +106,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     c\r\n
-  s>     \x04\x00\x00\x01\x00\x02\x012
-  s>     C101
+  s>     17\r\n
+  s>     \x0f\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBokC101
   s>     \r\n
-  received frame(size=4; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=15; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: [True, False, True]
diff --git a/tests/test-wireproto-command-heads.t b/tests/test-wireproto-command-heads.t
--- a/tests/test-wireproto-command-heads.t
+++ b/tests/test-wireproto-command-heads.t
@@ -37,8 +37,8 @@
   sending heads command
   s>     POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 20\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -48,14 +48,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     48\r\n
-  s>     @\x00\x00\x01\x00\x02\x012
-  s>     \x83T\x1dok\x91\xd4J\xab\xa6\xd5\xe5\x80\xbc0\xa9\x94\x850\xdb\xe0\x0bT\xaeI.6\xb0\xc83\x9f\xfa\xf3(\xd0\x0b\x85\xb4R]\xe1\x16^T)Dm-\xc5A\x9c_\x97Dz\x8b\xc0b\xe4\xcc2\x8b\xf2A
+  s>     53\r\n
+  s>     K\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\x83T\x1dok\x91\xd4J\xab\xa6\xd5\xe5\x80\xbc0\xa9\x94\x850\xdb\xe0\x0bT\xaeI.6\xb0\xc83\x9f\xfa\xf3(\xd0\x0b\x85\xb4R]\xe1\x16^T)Dm-\xc5A\x9c_\x97Dz\x8b\xc0b\xe4\xcc2\x8b\xf2A
   s>     \r\n
-  received frame(size=64; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=75; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: [b'\x1dok\x91\xd4J\xab\xa6\xd5\xe5\x80\xbc0\xa9\x94\x850\xdb\xe0\x0b', b'\xaeI.6\xb0\xc83\x9f\xfa\xf3(\xd0\x0b\x85\xb4R]\xe1\x16^', b')Dm-\xc5A\x9c_\x97Dz\x8b\xc0b\xe4\xcc2\x8b\xf2A']
@@ -70,8 +70,8 @@
   sending heads command
   s>     POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 39\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -81,14 +81,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     1e\r\n
-  s>     \x16\x00\x00\x01\x00\x02\x012
-  s>     \x81Tx\xd2\xdc\xa46\xb2\xf5\xb1\x88\xac&~)\xb8\x1e\x07&m8\xfc
+  s>     29\r\n
+  s>     !\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\x81Tx\xd2\xdc\xa46\xb2\xf5\xb1\x88\xac&~)\xb8\x1e\x07&m8\xfc
   s>     \r\n
-  received frame(size=22; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=33; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: [b'x\xd2\xdc\xa46\xb2\xf5\xb1\x88\xac&~)\xb8\x1e\x07&m8\xfc']
diff --git a/tests/test-wireproto-command-capabilities.t b/tests/test-wireproto-command-capabilities.t
--- a/tests/test-wireproto-command-capabilities.t
+++ b/tests/test-wireproto-command-capabilities.t
@@ -192,8 +192,8 @@
   s>     Content-Type: application/mercurial-cbor\r\n
   s>     Content-Length: *\r\n (glob)
   s>     \r\n
-  s>     \xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0004GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
-  cbor> {b'apibase': b'api/', b'apis': {b'exp-http-v2-0001': {b'commands': {b'branchmap': {b'args': {}, b'permissions': [b'pull']}, b'capabilities': {b'args': {}, b'permissions': [b'pull']}, b'heads': {b'args': {b'publiconly': False}, b'permissions': [b'pull']}, b'known': {b'args': {b'nodes': [b'deadbeef']}, b'permissions': [b'pull']}, b'listkeys': {b'args': {b'namespace': b'ns'}, b'permissions': [b'pull']}, b'lookup': {b'args': {b'key': b'foo'}, b'permissions': [b'pull']}, b'pushkey': {b'args': {b'key': b'key', b'namespace': b'ns', b'new': b'new', b'old': b'old'}, b'permissions': [b'push']}}, b'compression': [{b'name': b'zstd'}, {b'name': b'zlib'}], b'framingmediatypes': [b'application/mercurial-exp-framing-0004'], b'rawrepoformats': [b'generaldelta', b'revlogv1']}}, b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'}
+  s>     \xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0005GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
+  cbor> {b'apibase': b'api/', b'apis': {b'exp-http-v2-0001': {b'commands': {b'branchmap': {b'args': {}, b'permissions': [b'pull']}, b'capabilities': {b'args': {}, b'permissions': [b'pull']}, b'heads': {b'args': {b'publiconly': False}, b'permissions': [b'pull']}, b'known': {b'args': {b'nodes': [b'deadbeef']}, b'permissions': [b'pull']}, b'listkeys': {b'args': {b'namespace': b'ns'}, b'permissions': [b'pull']}, b'lookup': {b'args': {b'key': b'foo'}, b'permissions': [b'pull']}, b'pushkey': {b'args': {b'key': b'key', b'namespace': b'ns', b'new': b'new', b'old': b'old'}, b'permissions': [b'push']}}, b'compression': [{b'name': b'zstd'}, {b'name': b'zlib'}], b'framingmediatypes': [b'application/mercurial-exp-framing-0005'], b'rawrepoformats': [b'generaldelta', b'revlogv1']}}, b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'}
 
 capabilities command returns expected info
 
@@ -217,12 +217,12 @@
   s>     Content-Type: application/mercurial-cbor\r\n
   s>     Content-Length: *\r\n (glob)
   s>     \r\n
-  s>     \xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0004GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
+  s>     \xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0005GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
   sending capabilities command
   s>     POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
   s>     *\r\n (glob)
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 27\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -232,16 +232,16 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     1d7\r\n
-  s>     \xcf\x01\x00\x01\x00\x02\x012
-  s>     \xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0004
+  s>     1e2\r\n
+  s>     \xda\x01\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0005
   s>     \r\n
-  received frame(size=463; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=474; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
-  response: [{b'commands': {b'branchmap': {b'args': {}, b'permissions': [b'pull']}, b'capabilities': {b'args': {}, b'permissions': [b'pull']}, b'heads': {b'args': {b'publiconly': False}, b'permissions': [b'pull']}, b'known': {b'args': {b'nodes': [b'deadbeef']}, b'permissions': [b'pull']}, b'listkeys': {b'args': {b'namespace': b'ns'}, b'permissions': [b'pull']}, b'lookup': {b'args': {b'key': b'foo'}, b'permissions': [b'pull']}, b'pushkey': {b'args': {b'key': b'key', b'namespace': b'ns', b'new': b'new', b'old': b'old'}, b'permissions': [b'push']}}, b'compression': [{b'name': b'zstd'}, {b'name': b'zlib'}], b'framingmediatypes': [b'application/mercurial-exp-framing-0004'], b'rawrepoformats': [b'generaldelta', b'revlogv1']}]
+  response: [{b'status': b'ok'}, {b'commands': {b'branchmap': {b'args': {}, b'permissions': [b'pull']}, b'capabilities': {b'args': {}, b'permissions': [b'pull']}, b'heads': {b'args': {b'publiconly': False}, b'permissions': [b'pull']}, b'known': {b'args': {b'nodes': [b'deadbeef']}, b'permissions': [b'pull']}, b'listkeys': {b'args': {b'namespace': b'ns'}, b'permissions': [b'pull']}, b'lookup': {b'args': {b'key': b'foo'}, b'permissions': [b'pull']}, b'pushkey': {b'args': {b'key': b'key', b'namespace': b'ns', b'new': b'new', b'old': b'old'}, b'permissions': [b'push']}}, b'compression': [{b'name': b'zstd'}, {b'name': b'zlib'}], b'framingmediatypes': [b'application/mercurial-exp-framing-0005'], b'rawrepoformats': [b'generaldelta', b'revlogv1']}]
 
   $ cat error.log
diff --git a/tests/test-wireproto-command-branchmap.t b/tests/test-wireproto-command-branchmap.t
--- a/tests/test-wireproto-command-branchmap.t
+++ b/tests/test-wireproto-command-branchmap.t
@@ -45,8 +45,8 @@
   sending branchmap command
   s>     POST /api/exp-http-v2-0001/ro/branchmap HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 24\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -56,15 +56,15 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     78\r\n
-  s>     p\x00\x00\x01\x00\x02\x012
-  s>     \xa3Gbranch1\x81T\xb5\xfa\xac\xdf\xd2c7h\xcb1R3l\xc0\x953\x81&f\x88Gbranch2\x81T"Aa\xc7X\x9a\xa4\x8f\xa8:H\xfe\xff^\x95\xb5j\xe3\'\xfcGdefault\x82T&\x80Z\xba\x1e`\n
+  s>     83\r\n
+  s>     {\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\xa3Gbranch1\x81T\xb5\xfa\xac\xdf\xd2c7h\xcb1R3l\xc0\x953\x81&f\x88Gbranch2\x81T"Aa\xc7X\x9a\xa4\x8f\xa8:H\xfe\xff^\x95\xb5j\xe3\'\xfcGdefault\x82T&\x80Z\xba\x1e`\n
   s>     \x82\xe96a\x14\x9f#\x13\x86j"\x1a{T\xbe\x0e\xf7<\x17\xad\xe3\xfc\x89\xdcAp\x1e\xb9\xfc:\x91\xb5\x82\x82
   s>     \r\n
-  received frame(size=112; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=123; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: {b'branch1': [b'\xb5\xfa\xac\xdf\xd2c7h\xcb1R3l\xc0\x953\x81&f\x88'], b'branch2': [b'"Aa\xc7X\x9a\xa4\x8f\xa8:H\xfe\xff^\x95\xb5j\xe3\'\xfc'], b'default': [b'&\x80Z\xba\x1e`\n\x82\xe96a\x14\x9f#\x13\x86j"\x1a{', b'\xbe\x0e\xf7<\x17\xad\xe3\xfc\x89\xdcAp\x1e\xb9\xfc:\x91\xb5\x82\x82']}
diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -305,12 +305,12 @@
   s>     Content-Type: application/mercurial-cbor\r\n
   s>     Content-Length: *\r\n (glob)
   s>     \r\n
-  s>     \xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0004GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
+  s>     \xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X&application/mercurial-exp-framing-0005GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
   sending heads command
   s>     POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 20\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -320,14 +320,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     1e\r\n
-  s>     \x16\x00\x00\x01\x00\x02\x012
-  s>     \x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
+  s>     29\r\n
+  s>     !\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBok\x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
   s>     \r\n
-  received frame(size=22; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=33; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
   response: [b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00']
diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -98,7 +98,7 @@
   s>     Content-Type: text/plain\r\n
   s>     Content-Length: 85\r\n
   s>     \r\n
-  s>     client MUST specify Accept header with value: application/mercurial-exp-framing-0004\n
+  s>     client MUST specify Accept header with value: application/mercurial-exp-framing-0005\n
 
 Bad Accept header results in 406
 
@@ -121,7 +121,7 @@
   s>     Content-Type: text/plain\r\n
   s>     Content-Length: 85\r\n
   s>     \r\n
-  s>     client MUST specify Accept header with value: application/mercurial-exp-framing-0004\n
+  s>     client MUST specify Accept header with value: application/mercurial-exp-framing-0005\n
 
 Bad Content-Type header results in 415
 
@@ -134,7 +134,7 @@
   using raw connection to peer
   s>     POST /api/exp-http-v2-0001/ro/customreadonly HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
   s>     content-type: badmedia\r\n
   s>     user-agent: test\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
@@ -146,7 +146,7 @@
   s>     Content-Type: text/plain\r\n
   s>     Content-Length: 88\r\n
   s>     \r\n
-  s>     client MUST send Content-Type header with value: application/mercurial-exp-framing-0004\n
+  s>     client MUST send Content-Type header with value: application/mercurial-exp-framing-0005\n
 
 Request to read-only command works out of the box
 
@@ -161,7 +161,7 @@
   s>     POST /api/exp-http-v2-0001/ro/customreadonly HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
   s>     *\r\n (glob)
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     user-agent: test\r\n
   s>     content-length: 29\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
@@ -171,11 +171,11 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     27\r\n
-  s>     \x1f\x00\x00\x01\x00\x02\x012X\x1dcustomreadonly bytes response
+  s>     32\r\n
+  s>     *\x00\x00\x01\x00\x02\x012\xa1FstatusBokX\x1dcustomreadonly bytes response
   s>     \r\n
   s>     0\r\n
   s>     \r\n
@@ -187,8 +187,8 @@
   sending customreadonly command
   s>     POST /api/exp-http-v2-0001/ro/customreadonly HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     content-length: 29\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     user-agent: Mercurial debugwireproto\r\n
@@ -198,17 +198,17 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     27\r\n
-  s>     \x1f\x00\x00\x01\x00\x02\x012
-  s>     X\x1dcustomreadonly bytes response
+  s>     32\r\n
+  s>     *\x00\x00\x01\x00\x02\x012
+  s>     \xa1FstatusBokX\x1dcustomreadonly bytes response
   s>     \r\n
-  received frame(size=31; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
+  received frame(size=42; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
   s>     0\r\n
   s>     \r\n
-  response: [b'customreadonly bytes response']
+  response: [{b'status': b'ok'}, b'customreadonly bytes response']
 
 Request to read-write command fails because server is read-only by default
 
@@ -301,8 +301,8 @@
   using raw connection to peer
   s>     POST /api/exp-http-v2-0001/rw/customreadonly HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     user-agent: test\r\n
   s>     content-length: 29\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
@@ -312,11 +312,11 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     27\r\n
-  s>     \x1f\x00\x00\x01\x00\x02\x012X\x1dcustomreadonly bytes response
+  s>     32\r\n
+  s>     *\x00\x00\x01\x00\x02\x012\xa1FstatusBokX\x1dcustomreadonly bytes response
   s>     \r\n
   s>     0\r\n
   s>     \r\n
@@ -331,7 +331,7 @@
   using raw connection to peer
   s>     POST /api/exp-http-v2-0001/rw/badcommand HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
   s>     user-agent: test\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
   s>     \r\n
@@ -393,8 +393,8 @@
   using raw connection to peer
   s>     POST /api/exp-http-v2-0001/ro/debugreflect HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     user-agent: test\r\n
   s>     content-length: 47\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
@@ -424,8 +424,8 @@
   using raw connection to peer
   s>     POST /api/exp-http-v2-0001/ro/customreadonly HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     user-agent: test\r\n
   s>     content-length: 29\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
@@ -435,11 +435,11 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     27\r\n
-  s>     \x1f\x00\x00\x01\x00\x02\x012X\x1dcustomreadonly bytes response
+  s>     32\r\n
+  s>     *\x00\x00\x01\x00\x02\x012\xa1FstatusBokX\x1dcustomreadonly bytes response
   s>     \r\n
   s>     0\r\n
   s>     \r\n
@@ -468,14 +468,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     27\r\n
-  s>     \x1f\x00\x00\x01\x00\x02\x012X\x1dcustomreadonly bytes response
+  s>     32\r\n
+  s>     *\x00\x00\x01\x00\x02\x012\xa1FstatusBokX\x1dcustomreadonly bytes response
   s>     \r\n
-  s>     27\r\n
-  s>     \x1f\x00\x00\x03\x00\x02\x002X\x1dcustomreadonly bytes response
+  s>     32\r\n
+  s>     *\x00\x00\x03\x00\x02\x002\xa1FstatusBokX\x1dcustomreadonly bytes response
   s>     \r\n
   s>     0\r\n
   s>     \r\n
@@ -495,8 +495,8 @@
   using raw connection to peer
   s>     POST /api/exp-http-v2-0001/ro/multirequest HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     user-agent: test\r\n
   s>     content-length: 115\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
@@ -506,14 +506,14 @@
   s>     HTTP/1.1 200 OK\r\n
   s>     Server: testing stub value\r\n
   s>     Date: $HTTP_DATE$\r\n
-  s>     Content-Type: application/mercurial-exp-framing-0004\r\n
+  s>     Content-Type: application/mercurial-exp-framing-0005\r\n
   s>     Transfer-Encoding: chunked\r\n
   s>     \r\n
-  s>     28\r\n
-  s>      \x00\x00\x03\x00\x02\x012\xa3Fphases at Ibookmarks@Jnamespaces@
+  s>     33\r\n
+  s>     +\x00\x00\x03\x00\x02\x012\xa1FstatusBok\xa3Fphases at Ibookmarks@Jnamespaces@
   s>     \r\n
-  s>     9\r\n
-  s>     \x01\x00\x00\x01\x00\x02\x002\xa0
+  s>     14\r\n
+  s>     \x0c\x00\x00\x01\x00\x02\x002\xa1FstatusBok\xa0
   s>     \r\n
   s>     0\r\n
   s>     \r\n
@@ -545,8 +545,8 @@
   using raw connection to peer
   s>     POST /api/exp-http-v2-0001/ro/multirequest HTTP/1.1\r\n
   s>     Accept-Encoding: identity\r\n
-  s>     accept: application/mercurial-exp-framing-0004\r\n
-  s>     content-type: application/mercurial-exp-framing-0004\r\n
+  s>     accept: application/mercurial-exp-framing-0005\r\n
+  s>     content-type: application/mercurial-exp-framing-0005\r\n
   s>     user-agent: test\r\n
   s>     content-length: 22\r\n
   s>     host: $LOCALIP:$HGPORT\r\n (glob)
diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -26,7 +26,7 @@
     wireprototypes,
 )
 
-FRAMINGTYPE = b'application/mercurial-exp-framing-0004'
+FRAMINGTYPE = b'application/mercurial-exp-framing-0005'
 
 HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2
 
diff --git a/mercurial/wireprotov2peer.py b/mercurial/wireprotov2peer.py
--- a/mercurial/wireprotov2peer.py
+++ b/mercurial/wireprotov2peer.py
@@ -18,6 +18,21 @@
     wireprotoframing,
 )
 
+def formatrichmessage(atoms):
+    """Format an encoded message from the framing protocol."""
+
+    chunks = []
+
+    for atom in atoms:
+        msg = _(atom[b'msg'])
+
+        if b'args' in atom:
+            msg = msg % atom[b'args']
+
+        chunks.append(msg)
+
+    return b''.join(chunks)
+
 class commandresponse(object):
     """Represents the response to a command request."""
 
@@ -128,42 +143,53 @@
                 # decoded value. Otherwise resolve to the rich response object.
                 decoder = COMMAND_DECODERS.get(response.command)
 
-                result = decoder(response) if decoder else response
+                # TODO consider always resolving the overall status map.
+                if decoder:
+                    objs = response.cborobjects()
+
+                    overall = next(objs)
 
-                self._futures[frame.requestid].set_result(result)
+                    if overall['status'] == 'ok':
+                        self._futures[frame.requestid].set_result(decoder(objs))
+                    else:
+                        e = error.RepoError(
+                            formatrichmessage(overall['error']['message']))
+                        self._futures[frame.requestid].set_exception(e)
+                else:
+                    self._futures[frame.requestid].set_result(response)
 
                 del self._requests[frame.requestid]
                 del self._futures[frame.requestid]
 
         else:
             raise error.ProgrammingError(
                 'unhandled action from clientreactor: %s' % action)
 
-def decodebranchmap(resp):
+def decodebranchmap(objs):
     # Response should be a single CBOR map of branch name to array of nodes.
-    bm = next(resp.cborobjects())
+    bm = next(objs)
 
     return {encoding.tolocal(k): v for k, v in bm.items()}
 
-def decodeheads(resp):
+def decodeheads(objs):
     # Array of node bytestrings.
-    return next(resp.cborobjects())
+    return next(objs)
 
-def decodeknown(resp):
+def decodeknown(objs):
     # Bytestring where each byte is a 0 or 1.
-    raw = next(resp.cborobjects())
+    raw = next(objs)
 
     return [True if c == '1' else False for c in raw]
 
-def decodelistkeys(resp):
+def decodelistkeys(objs):
     # Map with bytestring keys and values.
-    return next(resp.cborobjects())
+    return next(objs)
 
-def decodelookup(resp):
-    return next(resp.cborobjects())
+def decodelookup(objs):
+    return next(objs)
 
-def decodepushkey(resp):
-    return next(resp.cborobjects())
+def decodepushkey(objs):
+    return next(objs)
 
 COMMAND_DECODERS = {
     'branchmap': decodebranchmap,
diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py
--- a/mercurial/wireprotoframing.py
+++ b/mercurial/wireprotoframing.py
@@ -354,16 +354,27 @@
 
     Returns a generator of bytearrays.
     """
+    # Automatically send the overall CBOR response map.
+    overall = cbor.dumps({b'status': b'ok'}, canonical=True)
+    if len(overall) > maxframesize:
+        raise error.ProgrammingError('not yet implemented')
 
-    # Simple case of a single frame.
-    if len(data) <= maxframesize:
+    # Simple case where we can fit the full response in a single frame.
+    if len(overall) + len(data) <= maxframesize:
         flags = FLAG_COMMAND_RESPONSE_EOS
         yield stream.makeframe(requestid=requestid,
                                typeid=FRAME_TYPE_COMMAND_RESPONSE,
                                flags=flags,
-                               payload=data)
+                               payload=overall + data)
         return
 
+    # It's easier to send the overall CBOR map in its own frame than to track
+    # offsets.
+    yield stream.makeframe(requestid=requestid,
+                           typeid=FRAME_TYPE_COMMAND_RESPONSE,
+                           flags=FLAG_COMMAND_RESPONSE_CONTINUATION,
+                           payload=overall)
+
     offset = 0
     while True:
         chunk = data[offset:offset + maxframesize]
diff --git a/mercurial/help/internals/wireprotocol.txt b/mercurial/help/internals/wireprotocol.txt
--- a/mercurial/help/internals/wireprotocol.txt
+++ b/mercurial/help/internals/wireprotocol.txt
@@ -673,7 +673,7 @@
 
 This frame contains response data to an issued command.
 
-Response data ALWAYS consists of a series of 0 or more CBOR encoded
+Response data ALWAYS consists of a series of 1 or more CBOR encoded
 values. A CBOR value may be using indefinite length encoding. And the
 bytes constituting the value may span several frames.
 
@@ -914,7 +914,7 @@
 
 TBD
 
-Issuing Commands
+Command Protocol
 ----------------
 
 A client can request that a remote run a command by sending it
@@ -960,6 +960,35 @@
 Servers MAY dispatch to commands immediately once argument data
 is available or delay until command data is received in full.
 
+Once a ``Command Request`` frame is sent, a client must be prepared to
+receive any of the following frames associated with that request:
+``Command Response``, ``Error Response``, ``Human Output Side-Channel``,
+``Progress Update``.
+
+The *main* response for a command will be in ``Command Response`` frames.
+The payloads of these frames consist of 1 or more CBOR encoded values.
+The first CBOR value on the first ``Command Response`` frame is special
+and denotes the overall status of the command. This CBOR map contains
+the following bytestring keys:
+
+status
+   (bytestring) A well-defined message containing the overall status of
+   this command request. The following values are defined:
+
+   ok
+      The command was received successfully and its response follows.
+   error
+      There was an error processing the command. More details about the
+      error are encoded in the ``error`` key.
+
+error (optional)
+   A map containing information about an encountered error. The map has the
+   following keys:
+
+   message
+      (array of maps) A message describing the error. The message uses the
+      same format as those in the ``Human Output Side-Channel`` frame.
+
 Capabilities
 ============
 



To: indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list