keepalive: borrow code from newer httplib to patch ValueError (issue1088)
authorMatt Mackall <mpm@selenic.com>
Mon, 16 Feb 2009 17:37:23 -0600
changeset 7781 a45206455d85
parent 7780 9892c4d94fb7
child 7782 140429276b63
keepalive: borrow code from newer httplib to patch ValueError (issue1088)
mercurial/keepalive.py
--- a/mercurial/keepalive.py	Mon Feb 16 17:37:23 2009 -0600
+++ b/mercurial/keepalive.py	Mon Feb 16 17:37:23 2009 -0600
@@ -389,6 +389,63 @@
         self._rbuf = ''
         return s
 
+    # stolen from Python SVN #68532 to fix issue1088
+    def _read_chunked(self, amt):
+        chunk_left = self.chunk_left
+        value = ''
+
+        # XXX This accumulates chunks by repeated string concatenation,
+        # which is not efficient as the number or size of chunks gets big.
+        while True:
+            if chunk_left is None:
+                line = self.fp.readline()
+                i = line.find(';')
+                if i >= 0:
+                    line = line[:i] # strip chunk-extensions
+                try:
+                    chunk_left = int(line, 16)
+                except ValueError:
+                    # close the connection as protocol synchronisation is
+                    # probably lost
+                    self.close()
+                    raise IncompleteRead(value)
+                if chunk_left == 0:
+                    break
+            if amt is None:
+                value += self._safe_read(chunk_left)
+            elif amt < chunk_left:
+                value += self._safe_read(amt)
+                self.chunk_left = chunk_left - amt
+                return value
+            elif amt == chunk_left:
+                value += self._safe_read(amt)
+                self._safe_read(2)  # toss the CRLF at the end of the chunk
+                self.chunk_left = None
+                return value
+            else:
+                value += self._safe_read(chunk_left)
+                amt -= chunk_left
+
+            # we read the whole chunk, get another
+            self._safe_read(2)      # toss the CRLF at the end of the chunk
+            chunk_left = None
+
+        # read and discard trailer up to the CRLF terminator
+        ### note: we shouldn't have any trailers!
+        while True:
+            line = self.fp.readline()
+            if not line:
+                # a vanishingly small number of sites EOF without
+                # sending the trailer
+                break
+            if line == '\r\n':
+                break
+
+        # we read everything; close the "file"
+        self.close()
+
+        return value
+
     def readline(self, limit=-1):
         data = ""
         i = self._rbuf.find('\n')