mercurial/wireprotov2peer.py
changeset 37725 3ea8323d6f95
parent 37722 89a16704114c
child 39435 1467b6c27ff9
--- a/mercurial/wireprotov2peer.py	Sat Apr 14 14:37:23 2018 -0700
+++ b/mercurial/wireprotov2peer.py	Sat Apr 14 15:19:36 2018 -0700
@@ -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,9 +143,20 @@
                 # 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]
@@ -139,31 +165,31 @@
             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,