comparison mercurial/httpconnection.py @ 15152:94b200a11cf7 stable

http: handle push of bundles > 2 GB again (issue3017) It was very elegant that httpsendfile implemented __len__ like a string. It was however also dangerous because that protocol can't handle sizes bigger than 2 GB. Mercurial tried to work around that, but it turned out to be too easy to introduce new errors in this area. With this change __len__ is no longer implemented at all and the code will work the same way for short and long posts.
author Mads Kiilerich <mads@kiilerich.com>
date Wed, 21 Sep 2011 22:52:00 +0200
parents 0593e8f81c71
children b3083042bdda
comparison
equal deleted inserted replaced
15095:ec222a29bdf0 15152:94b200a11cf7
20 20
21 # moved here from url.py to avoid a cycle 21 # moved here from url.py to avoid a cycle
22 class httpsendfile(object): 22 class httpsendfile(object):
23 """This is a wrapper around the objects returned by python's "open". 23 """This is a wrapper around the objects returned by python's "open".
24 24
25 Its purpose is to send file-like objects via HTTP and, to do so, it 25 Its purpose is to send file-like objects via HTTP.
26 defines a __len__ attribute to feed the Content-Length header. 26 It do however not define a __len__ attribute because the length
27 might be more than Py_ssize_t can handle.
27 """ 28 """
28 29
29 def __init__(self, ui, *args, **kwargs): 30 def __init__(self, ui, *args, **kwargs):
30 # We can't just "self._data = open(*args, **kwargs)" here because there 31 # We can't just "self._data = open(*args, **kwargs)" here because there
31 # is an "open" function defined in this module that shadows the global 32 # is an "open" function defined in this module that shadows the global
33 self.ui = ui 34 self.ui = ui
34 self._data = open(*args, **kwargs) 35 self._data = open(*args, **kwargs)
35 self.seek = self._data.seek 36 self.seek = self._data.seek
36 self.close = self._data.close 37 self.close = self._data.close
37 self.write = self._data.write 38 self.write = self._data.write
38 self._len = os.fstat(self._data.fileno()).st_size 39 self.length = os.fstat(self._data.fileno()).st_size
39 self._pos = 0 40 self._pos = 0
40 self._total = self._len / 1024 * 2 41 self._total = self.length / 1024 * 2
41 42
42 def read(self, *args, **kwargs): 43 def read(self, *args, **kwargs):
43 try: 44 try:
44 ret = self._data.read(*args, **kwargs) 45 ret = self._data.read(*args, **kwargs)
45 except EOFError: 46 except EOFError:
51 # once whether authentication will be required, just lie to 52 # once whether authentication will be required, just lie to
52 # the user and maybe the push succeeds suddenly at 50%. 53 # the user and maybe the push succeeds suddenly at 50%.
53 self.ui.progress(_('sending'), self._pos / 1024, 54 self.ui.progress(_('sending'), self._pos / 1024,
54 unit=_('kb'), total=self._total) 55 unit=_('kb'), total=self._total)
55 return ret 56 return ret
56
57 def __len__(self):
58 return self._len
59 57
60 # moved here from url.py to avoid a cycle 58 # moved here from url.py to avoid a cycle
61 def readauthforuri(ui, uri, user): 59 def readauthforuri(ui, uri, user):
62 # Read configuration 60 # Read configuration
63 config = dict() 61 config = dict()