comparison mercurial/url.py @ 13115:bda5f35fbf67

httpsendfile: record progress information during read() This allows us to provide deterministic progress information during transfer of bundle data over HTTP. This is required because we currently buffer the bundle data to local disk prior to transfer since wsgiref lacks chunked transfer-coding support.
author Augie Fackler <durin42@gmail.com>
date Fri, 10 Dec 2010 13:31:06 -0600
parents ae163a0a3cd0
children b75fc70f0a9f
comparison
equal deleted inserted replaced
13114:8f29a08e7bbc 13115:bda5f35fbf67
256 256
257 Its purpose is to send file-like objects via HTTP and, to do so, it 257 Its purpose is to send file-like objects via HTTP and, to do so, it
258 defines a __len__ attribute to feed the Content-Length header. 258 defines a __len__ attribute to feed the Content-Length header.
259 """ 259 """
260 260
261 def __init__(self, *args, **kwargs): 261 def __init__(self, ui, *args, **kwargs):
262 # We can't just "self._data = open(*args, **kwargs)" here because there 262 # We can't just "self._data = open(*args, **kwargs)" here because there
263 # is an "open" function defined in this module that shadows the global 263 # is an "open" function defined in this module that shadows the global
264 # one 264 # one
265 self.ui = ui
265 self._data = __builtin__.open(*args, **kwargs) 266 self._data = __builtin__.open(*args, **kwargs)
266 self.read = self._data.read
267 self.seek = self._data.seek 267 self.seek = self._data.seek
268 self.close = self._data.close 268 self.close = self._data.close
269 self.write = self._data.write 269 self.write = self._data.write
270 self._len = os.fstat(self._data.fileno()).st_size
271 self._pos = 0
272 self._total = len(self) / 1024 * 2
273
274 def read(self, *args, **kwargs):
275 try:
276 ret = self._data.read(*args, **kwargs)
277 except EOFError:
278 self.ui.progress(_('sending'), None)
279 self._pos += len(ret)
280 # We pass double the max for total because we currently have
281 # to send the bundle twice in the case of a server that
282 # requires authentication. Since we can't know until we try
283 # once whether authentication will be required, just lie to
284 # the user and maybe the push succeeds suddenly at 50%.
285 self.ui.progress(_('sending'), self._pos / 1024,
286 unit=_('kb'), total=self._total)
287 return ret
270 288
271 def __len__(self): 289 def __len__(self):
272 return os.fstat(self._data.fileno()).st_size 290 return self._len
273 291
274 def _gen_sendfile(connection): 292 def _gen_sendfile(connection):
275 def _sendfile(self, data): 293 def _sendfile(self, data):
276 # send a file 294 # send a file
277 if isinstance(data, httpsendfile): 295 if isinstance(data, httpsendfile):