Mercurial > public > mercurial-scm > hg
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() |