# HG changeset patch # User Gregory Szorc # Date 1523731568 25200 # Node ID d715a85003c8327b1936900a2c055483721530a8 # Parent a656cba08a04391f7aa038557902ee09b0be01ed wireprotov2: establish a type for representing command response It will be desirable to have a higher-level type for representing command responses. This will allow us to do nicer things. For now, the instance encapsulates existing logic. It is still a bit primitive. But we're slowly making things better. Version 1 protocols have a wrapping layer that decodes the raw string data into a data structure and that data structure is sent to the future. Version 2 doesn't yet have this layer and the future is receiving the raw wire response. Hence why debugcommands needed to be taught about the response type. Differential Revision: https://phab.mercurial-scm.org/D3380 diff -r a656cba08a04 -r d715a85003c8 mercurial/debugcommands.py --- a/mercurial/debugcommands.py Sat Apr 14 11:50:19 2018 -0700 +++ b/mercurial/debugcommands.py Sat Apr 14 11:46:08 2018 -0700 @@ -83,6 +83,7 @@ vfs as vfsmod, wireprotoframing, wireprotoserver, + wireprotov2peer, ) from .utils import ( dateutil, @@ -3012,7 +3013,16 @@ with peer.commandexecutor() as e: res = e.callcommand(command, args).result() - ui.status(_('response: %s\n') % stringutil.pprint(res)) + if isinstance(res, wireprotov2peer.commandresponse): + if res.cbor: + val = list(res.cborobjects()) + else: + val = [res.b.getvalue()] + + ui.status(_('response: %s\n') % stringutil.pprint(val)) + + else: + ui.status(_('response: %s\n') % stringutil.pprint(res)) elif action == 'batchbegin': if batchedcommands is not None: diff -r a656cba08a04 -r d715a85003c8 mercurial/wireprotov2peer.py --- a/mercurial/wireprotov2peer.py Sat Apr 14 11:50:19 2018 -0700 +++ b/mercurial/wireprotov2peer.py Sat Apr 14 11:46:08 2018 -0700 @@ -17,6 +17,26 @@ wireprotoframing, ) +class commandresponse(object): + """Represents the response to a command request.""" + + def __init__(self, requestid, command): + self.requestid = requestid + self.command = command + + self.cbor = False + self.b = util.bytesio() + + def cborobjects(self): + """Obtain decoded CBOR objects from this response.""" + size = self.b.tell() + self.b.seek(0) + + decoder = cbor.CBORDecoder(self.b) + + while self.b.tell() < size: + yield decoder.decode() + class clienthandler(object): """Object to handle higher-level client activities. @@ -48,10 +68,7 @@ rid = request.requestid self._requests[rid] = request self._futures[rid] = f - self._responses[rid] = { - 'cbor': False, - 'b': util.bytesio(), - } + self._responses[rid] = commandresponse(rid, command) return iter(()) @@ -104,28 +121,13 @@ response = self._responses[frame.requestid] if action == 'responsedata': - response['b'].write(meta['data']) + response.b.write(meta['data']) if meta['cbor']: - response['cbor'] = True + response.cbor = True if meta['eos']: - if meta['cbor']: - # If CBOR, decode every object. - b = response['b'] - - size = b.tell() - b.seek(0) - - decoder = cbor.CBORDecoder(b) - - result = [] - while b.tell() < size: - result.append(decoder.decode()) - else: - result = [response['b'].getvalue()] - - self._futures[frame.requestid].set_result(result) + self._futures[frame.requestid].set_result(response) del self._requests[frame.requestid] del self._futures[frame.requestid]