comparison mercurial/wireprotoserver.py @ 37414:2d965bfeb8f6

wireproto: allow direct stream processing for unbundle Introduce a new option server.streamunbundle which starts a transaction immediately to apply a bundle instead of writing it to a temporary file first. This side steps the need for a large tmp directory at the cost of preventing concurrent pushes. This is a reasonable trade-off for many setups as concurrent pushes for the main branch at least are disallowed anyway. The option defaults to off to preserve existing behavior. Change the wireproto interface to provide a generator for reading the payload and make callers responsible for consuming all data. Differential Revision: https://phab.mercurial-scm.org/D2470
author Joerg Sonnenberger <joerg@bec.de>
date Tue, 27 Feb 2018 02:37:31 +0100
parents afcfdf53e4b5
children 0b7475ea38cf
comparison
equal deleted inserted replaced
37413:33af46d639b4 37414:2d965bfeb8f6
104 if self._protocaps is None: 104 if self._protocaps is None:
105 value = decodevaluefromheaders(self._req, r'X-HgProto') 105 value = decodevaluefromheaders(self._req, r'X-HgProto')
106 self._protocaps = set(value.split(' ')) 106 self._protocaps = set(value.split(' '))
107 return self._protocaps 107 return self._protocaps
108 108
109 def forwardpayload(self, fp): 109 def getpayload(self):
110 # Existing clients *always* send Content-Length. 110 # Existing clients *always* send Content-Length.
111 length = int(self._req.headers[b'Content-Length']) 111 length = int(self._req.headers[b'Content-Length'])
112 112
113 # If httppostargs is used, we need to read Content-Length 113 # If httppostargs is used, we need to read Content-Length
114 # minus the amount that was consumed by args. 114 # minus the amount that was consumed by args.
115 length -= int(self._req.headers.get(b'X-HgArgs-Post', 0)) 115 length -= int(self._req.headers.get(b'X-HgArgs-Post', 0))
116 for s in util.filechunkiter(self._req.bodyfh, limit=length): 116 return util.filechunkiter(self._req.bodyfh, limit=length)
117 fp.write(s)
118 117
119 @contextlib.contextmanager 118 @contextlib.contextmanager
120 def mayberedirectstdio(self): 119 def mayberedirectstdio(self):
121 oldout = self._ui.fout 120 oldout = self._ui.fout
122 olderr = self._ui.ferr 121 olderr = self._ui.ferr
608 607
609 def getprotocaps(self): 608 def getprotocaps(self):
610 # Protocol capabilities are currently not implemented for HTTP V2. 609 # Protocol capabilities are currently not implemented for HTTP V2.
611 return set() 610 return set()
612 611
613 def forwardpayload(self, fp): 612 def getpayload(self):
614 raise NotImplementedError 613 raise NotImplementedError
615 614
616 @contextlib.contextmanager 615 @contextlib.contextmanager
617 def mayberedirectstdio(self): 616 def mayberedirectstdio(self):
618 raise NotImplementedError 617 raise NotImplementedError
781 return [data[k] for k in keys] 780 return [data[k] for k in keys]
782 781
783 def getprotocaps(self): 782 def getprotocaps(self):
784 return self._protocaps 783 return self._protocaps
785 784
786 def forwardpayload(self, fpout): 785 def getpayload(self):
787 # We initially send an empty response. This tells the client it is 786 # We initially send an empty response. This tells the client it is
788 # OK to start sending data. If a client sees any other response, it 787 # OK to start sending data. If a client sees any other response, it
789 # interprets it as an error. 788 # interprets it as an error.
790 _sshv1respondbytes(self._fout, b'') 789 _sshv1respondbytes(self._fout, b'')
791 790
794 # <chunk size>\n<chunk> 793 # <chunk size>\n<chunk>
795 # ... 794 # ...
796 # 0\n 795 # 0\n
797 count = int(self._fin.readline()) 796 count = int(self._fin.readline())
798 while count: 797 while count:
799 fpout.write(self._fin.read(count)) 798 yield self._fin.read(count)
800 count = int(self._fin.readline()) 799 count = int(self._fin.readline())
801 800
802 @contextlib.contextmanager 801 @contextlib.contextmanager
803 def mayberedirectstdio(self): 802 def mayberedirectstdio(self):
804 yield None 803 yield None