diff -r 3ea8323d6f95 -r 0c184ca594bb mercurial/wireprotoframing.py --- a/mercurial/wireprotoframing.py Sat Apr 14 15:19:36 2018 -0700 +++ b/mercurial/wireprotoframing.py Sat Apr 14 15:36:12 2018 -0700 @@ -87,20 +87,12 @@ b'eos': FLAG_COMMAND_RESPONSE_EOS, } -FLAG_ERROR_RESPONSE_PROTOCOL = 0x01 -FLAG_ERROR_RESPONSE_APPLICATION = 0x02 - -FLAGS_ERROR_RESPONSE = { - b'protocol': FLAG_ERROR_RESPONSE_PROTOCOL, - b'application': FLAG_ERROR_RESPONSE_APPLICATION, -} - # Maps frame types to their available flags. FRAME_TYPE_FLAGS = { FRAME_TYPE_COMMAND_REQUEST: FLAGS_COMMAND_REQUEST, FRAME_TYPE_COMMAND_DATA: FLAGS_COMMAND_DATA, FRAME_TYPE_COMMAND_RESPONSE: FLAGS_COMMAND_RESPONSE, - FRAME_TYPE_ERROR_RESPONSE: FLAGS_ERROR_RESPONSE, + FRAME_TYPE_ERROR_RESPONSE: {}, FRAME_TYPE_TEXT_OUTPUT: {}, FRAME_TYPE_PROGRESS: {}, FRAME_TYPE_STREAM_SETTINGS: {}, @@ -394,20 +386,19 @@ if done: break -def createerrorframe(stream, requestid, msg, protocol=False, application=False): +def createerrorframe(stream, requestid, msg, errtype): # TODO properly handle frame size limits. assert len(msg) <= DEFAULT_MAX_FRAME_SIZE - flags = 0 - if protocol: - flags |= FLAG_ERROR_RESPONSE_PROTOCOL - if application: - flags |= FLAG_ERROR_RESPONSE_APPLICATION + payload = cbor.dumps({ + b'type': errtype, + b'message': [{b'msg': msg}], + }, canonical=True) yield stream.makeframe(requestid=requestid, typeid=FRAME_TYPE_ERROR_RESPONSE, - flags=flags, - payload=msg) + flags=0, + payload=payload) def createtextoutputframe(stream, requestid, atoms, maxframesize=DEFAULT_MAX_FRAME_SIZE): @@ -664,12 +655,12 @@ 'framegen': makegen(), } - def onapplicationerror(self, stream, requestid, msg): + def onservererror(self, stream, requestid, msg): ensureserverstream(stream) return 'sendframes', { 'framegen': createerrorframe(stream, requestid, msg, - application=True), + errtype='server'), } def makeoutputstream(self): @@ -1051,6 +1042,7 @@ handlers = { FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe, + FRAME_TYPE_ERROR_RESPONSE: self._onerrorresponseframe, } meth = handlers.get(frame.typeid) @@ -1071,3 +1063,16 @@ 'eos': frame.flags & FLAG_COMMAND_RESPONSE_EOS, 'data': frame.payload, } + + def _onerrorresponseframe(self, request, frame): + request.state = 'errored' + del self._activerequests[request.requestid] + + # The payload should be a CBOR map. + m = cbor.loads(frame.payload) + + return 'error', { + 'request': request, + 'type': m['type'], + 'message': m['message'], + }