D2791: hgweb: refactor fake file object proxy for archiving
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Mon Mar 12 17:34:00 EDT 2018
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG16499427f6de: hgweb: refactor fake file object proxy for archiving (authored by indygreg, committed by ).
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D2791?vs=6852&id=6927
REVISION DETAIL
https://phab.mercurial-scm.org/D2791
AFFECTED FILES
mercurial/archival.py
mercurial/hgweb/request.py
mercurial/hgweb/webcommands.py
CHANGE DETAILS
diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -24,6 +24,9 @@
paritygen,
staticfile,
)
+from . import (
+ request as requestmod,
+)
from .. import (
archival,
@@ -1215,7 +1218,9 @@
req.headers.extend(headers)
req.respond(HTTP_OK, mimetype)
- archival.archive(web.repo, req, cnode, artype, prefix=name,
+ bodyfh = requestmod.offsettrackingwriter(req.write)
+
+ archival.archive(web.repo, bodyfh, cnode, artype, prefix=name,
matchfn=match,
subrepos=web.configbool("web", "archivesubrepos"))
return []
diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py
--- a/mercurial/hgweb/request.py
+++ b/mercurial/hgweb/request.py
@@ -290,6 +290,37 @@
headers=headers,
bodyfh=bodyfh)
+class offsettrackingwriter(object):
+ """A file object like object that is append only and tracks write count.
+
+ Instances are bound to a callable. This callable is called with data
+ whenever a ``write()`` is attempted.
+
+ Instances track the amount of written data so they can answer ``tell()``
+ requests.
+
+ The intent of this class is to wrap the ``write()`` function returned by
+ a WSGI ``start_response()`` function. Since ``write()`` is a callable and
+ not a file object, it doesn't implement other file object methods.
+ """
+ def __init__(self, writefn):
+ self._write = writefn
+ self._offset = 0
+
+ def write(self, s):
+ res = self._write(s)
+ # Some Python objects don't report the number of bytes written.
+ if res is None:
+ self._offset += len(s)
+ else:
+ self._offset += res
+
+ def flush(self):
+ pass
+
+ def tell(self):
+ return self._offset
+
class wsgiresponse(object):
"""Represents a response to a WSGI request.
diff --git a/mercurial/archival.py b/mercurial/archival.py
--- a/mercurial/archival.py
+++ b/mercurial/archival.py
@@ -195,34 +195,11 @@
if self.fileobj:
self.fileobj.close()
-class tellable(object):
- '''provide tell method for zipfile.ZipFile when writing to http
- response file object.'''
-
- def __init__(self, fp):
- self.fp = fp
- self.offset = 0
-
- def __getattr__(self, key):
- return getattr(self.fp, key)
-
- def write(self, s):
- self.fp.write(s)
- self.offset += len(s)
-
- def tell(self):
- return self.offset
-
class zipit(object):
'''write archive to zip file or stream. can write uncompressed,
or compressed with deflate.'''
def __init__(self, dest, mtime, compress=True):
- if not isinstance(dest, bytes):
- try:
- dest.tell()
- except (AttributeError, IOError):
- dest = tellable(dest)
self.z = zipfile.ZipFile(pycompat.fsdecode(dest), r'w',
compress and zipfile.ZIP_DEFLATED or
zipfile.ZIP_STORED)
To: indygreg, #hg-reviewers, durin42
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list