# HG changeset patch # User Augie Fackler # Date 2010-12-10 19:31:06 # Node ID bda5f35fbf675672f4874e00554d9751b95e59e2 # Parent 8f29a08e7bbc5ebc06805578c62b5fd4e82038ae 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. diff --git a/mercurial/httprepo.py b/mercurial/httprepo.py --- a/mercurial/httprepo.py +++ b/mercurial/httprepo.py @@ -160,7 +160,7 @@ class httprepository(wireproto.wirerepos break tempname = changegroup.writebundle(cg, None, type) - fp = url.httpsendfile(tempname, "rb") + fp = url.httpsendfile(self.ui, tempname, "rb") headers = {'Content-Type': 'application/mercurial-0.1'} try: diff --git a/mercurial/url.py b/mercurial/url.py --- a/mercurial/url.py +++ b/mercurial/url.py @@ -258,18 +258,36 @@ class httpsendfile(object): defines a __len__ attribute to feed the Content-Length header. """ - def __init__(self, *args, **kwargs): + def __init__(self, ui, *args, **kwargs): # We can't just "self._data = open(*args, **kwargs)" here because there # is an "open" function defined in this module that shadows the global # one + self.ui = ui self._data = __builtin__.open(*args, **kwargs) - self.read = self._data.read self.seek = self._data.seek self.close = self._data.close self.write = self._data.write + self._len = os.fstat(self._data.fileno()).st_size + self._pos = 0 + self._total = len(self) / 1024 * 2 + + def read(self, *args, **kwargs): + try: + ret = self._data.read(*args, **kwargs) + except EOFError: + self.ui.progress(_('sending'), None) + self._pos += len(ret) + # We pass double the max for total because we currently have + # to send the bundle twice in the case of a server that + # requires authentication. Since we can't know until we try + # once whether authentication will be required, just lie to + # the user and maybe the push succeeds suddenly at 50%. + self.ui.progress(_('sending'), self._pos / 1024, + unit=_('kb'), total=self._total) + return ret def __len__(self): - return os.fstat(self._data.fileno()).st_size + return self._len def _gen_sendfile(connection): def _sendfile(self, data):