Mercurial > hg
diff mercurial/wireprotov2peer.py @ 37725:3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
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.
Differential Revision: https://phab.mercurial-scm.org/D3385
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 14 Apr 2018 15:19:36 -0700 |
parents | 89a16704114c |
children | 1467b6c27ff9 |
line wrap: on
line diff
--- 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,