changeset 37587:192b7ad06932

keepalive: rewrite readinto() to not use read() It turns out http.client on Python 3 sometimes uses readinto() in the implementation of read(). Unfortunately, Python 2 doesn't have a readinto() in httplib's client, so we have to support both codepaths. Subclassing is bad, folks. Differential Revision: https://phab.mercurial-scm.org/D3246
author Augie Fackler <augie@google.com>
date Wed, 11 Apr 2018 14:39:49 -0400
parents b94fecf4cd8c
children 165a77f7ec13
files mercurial/keepalive.py
diffstat 1 files changed, 19 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/keepalive.py	Thu Apr 12 17:22:59 2018 +0530
+++ b/mercurial/keepalive.py	Wed Apr 11 14:39:49 2018 -0400
@@ -384,6 +384,7 @@
         self._connection = None # (same)
 
     _raw_read = httplib.HTTPResponse.read
+    _raw_readinto = getattr(httplib.HTTPResponse, 'readinto', None)
 
     def close(self):
         if self.fp:
@@ -523,12 +524,24 @@
         return list
 
     def readinto(self, dest):
-        res = self.read(len(dest))
-        if not res:
-            return 0
-
-        dest[0:len(res)] = res
-        return len(res)
+        if self._raw_readinto is None:
+            res = self.read(len(dest))
+            if not res:
+                return 0
+            dest[0:len(res)] = res
+            return len(res)
+        total = len(dest)
+        have = len(self._rbuf)
+        if have >= total:
+            dest[0:total] = self._rbuf[:total]
+            self._rbuf = self._rbuf[total:]
+            return total
+        mv = memoryview(dest)
+        got = self._raw_readinto(mv[have:total])
+        dest[0:have] = self._rbuf
+        got += len(self._rbuf)
+        self._rbuf = ''
+        return got
 
 def safesend(self, str):
     """Send `str' to the server.