diff --git a/mercurial/httpclient/_readers.py b/mercurial/httpclient/_readers.py --- a/mercurial/httpclient/_readers.py +++ b/mercurial/httpclient/_readers.py @@ -79,22 +79,21 @@ class AbstractReader(object): def read(self, amt): if self.available_data < amt and not self._finished: raise ReadNotReady() - need = [amt] - def pred(s): - needed = need[0] > 0 - need[0] -= len(s) - return needed - blocks = list(itertools.takewhile(pred, self._done_chunks)) - self._done_chunks = self._done_chunks[len(blocks):] - over_read = sum(map(len, blocks)) - amt - if over_read > 0 and blocks: - logger.debug('need to reinsert %d data into done chunks', over_read) - last = blocks[-1] - blocks[-1], reinsert = last[:-over_read], last[-over_read:] - self._done_chunks.insert(0, reinsert) + blocks = [] + need = amt + while self._done_chunks: + b = self.popchunk() + if len(b) > need: + nb = b[:need] + self.pushchunk(b[need:]) + b = nb + blocks.append(b) + need -= len(b) + if need == 0: + break result = ''.join(blocks) assert len(result) == amt or (self._finished and len(result) < amt) - self.available_data -= amt + return result def _load(self, data): # pragma: no cover