mercurial/wireprotoframing.py
changeset 40025 b099e6032f38
parent 40024 86b22a4cfab1
child 40125 e2fe1074024c
equal deleted inserted replaced
40024:86b22a4cfab1 40025:b099e6032f38
    19     attr,
    19     attr,
    20 )
    20 )
    21 from . import (
    21 from . import (
    22     encoding,
    22     encoding,
    23     error,
    23     error,
       
    24     pycompat,
    24     util,
    25     util,
    25     wireprototypes,
    26     wireprototypes,
    26 )
    27 )
    27 from .utils import (
    28 from .utils import (
    28     cborutil,
    29     cborutil,
   426     """Create an empty payload frame representing command end-of-stream."""
   427     """Create an empty payload frame representing command end-of-stream."""
   427     return stream.makeframe(requestid=requestid,
   428     return stream.makeframe(requestid=requestid,
   428                             typeid=FRAME_TYPE_COMMAND_RESPONSE,
   429                             typeid=FRAME_TYPE_COMMAND_RESPONSE,
   429                             flags=FLAG_COMMAND_RESPONSE_EOS,
   430                             flags=FLAG_COMMAND_RESPONSE_EOS,
   430                             payload=b'')
   431                             payload=b'')
       
   432 
       
   433 def createalternatelocationresponseframe(stream, requestid, location):
       
   434     data = {
       
   435         b'status': b'redirect',
       
   436         b'location': {
       
   437             b'url': location.url,
       
   438             b'mediatype': location.mediatype,
       
   439         }
       
   440     }
       
   441 
       
   442     for a in (r'size', r'fullhashes', r'fullhashseed', r'serverdercerts',
       
   443               r'servercadercerts'):
       
   444         value = getattr(location, a)
       
   445         if value is not None:
       
   446             data[b'location'][pycompat.bytestr(a)] = value
       
   447 
       
   448     return stream.makeframe(requestid=requestid,
       
   449                             typeid=FRAME_TYPE_COMMAND_RESPONSE,
       
   450                             flags=FLAG_COMMAND_RESPONSE_CONTINUATION,
       
   451                             payload=b''.join(cborutil.streamencode(data)))
   431 
   452 
   432 def createcommanderrorresponse(stream, requestid, message, args=None):
   453 def createcommanderrorresponse(stream, requestid, message, args=None):
   433     # TODO should this be using a list of {'msg': ..., 'args': {}} so atom
   454     # TODO should this be using a list of {'msg': ..., 'args': {}} so atom
   434     # formatting works consistently?
   455     # formatting works consistently?
   435     m = {
   456     m = {
   811         # In all cases, when the function finishes, the request is fully
   832         # In all cases, when the function finishes, the request is fully
   812         # handled and no new frames for it should be seen.
   833         # handled and no new frames for it should be seen.
   813 
   834 
   814         def sendframes():
   835         def sendframes():
   815             emitted = False
   836             emitted = False
       
   837             alternatelocationsent = False
   816             emitter = bufferingcommandresponseemitter(stream, requestid)
   838             emitter = bufferingcommandresponseemitter(stream, requestid)
   817             while True:
   839             while True:
   818                 try:
   840                 try:
   819                     o = next(objs)
   841                     o = next(objs)
   820                 except StopIteration:
   842                 except StopIteration:
   839                         yield frame
   861                         yield frame
   840 
   862 
   841                     break
   863                     break
   842 
   864 
   843                 try:
   865                 try:
       
   866                     # Alternate location responses can only be the first and
       
   867                     # only object in the output stream.
       
   868                     if isinstance(o, wireprototypes.alternatelocationresponse):
       
   869                         if emitted:
       
   870                             raise error.ProgrammingError(
       
   871                                 'alternatelocationresponse seen after initial '
       
   872                                 'output object')
       
   873 
       
   874                         yield createalternatelocationresponseframe(
       
   875                             stream, requestid, o)
       
   876 
       
   877                         alternatelocationsent = True
       
   878                         emitted = True
       
   879                         continue
       
   880 
       
   881                     if alternatelocationsent:
       
   882                         raise error.ProgrammingError(
       
   883                             'object follows alternatelocationresponse')
       
   884 
   844                     if not emitted:
   885                     if not emitted:
   845                         yield createcommandresponseokframe(stream, requestid)
   886                         yield createcommandresponseokframe(stream, requestid)
   846                         emitted = True
   887                         emitted = True
   847 
   888 
   848                     # Objects emitted by command functions can be serializable
   889                     # Objects emitted by command functions can be serializable
   975 
  1016 
   976         return 'runcommand', {
  1017         return 'runcommand', {
   977             'requestid': requestid,
  1018             'requestid': requestid,
   978             'command': request[b'name'],
  1019             'command': request[b'name'],
   979             'args': request[b'args'],
  1020             'args': request[b'args'],
       
  1021             'redirect': request.get(b'redirect'),
   980             'data': entry['data'].getvalue() if entry['data'] else None,
  1022             'data': entry['data'].getvalue() if entry['data'] else None,
   981         }
  1023         }
   982 
  1024 
   983     def _makewantframeresult(self):
  1025     def _makewantframeresult(self):
   984         return 'wantframe', {
  1026         return 'wantframe', {