##// END OF EJS Templates
hgweb: refactor fake file object proxy for archiving...
Gregory Szorc -
r36891:16499427 default
parent child Browse files
Show More
@@ -195,34 +195,11 b' class tarit(object):'
195 195 if self.fileobj:
196 196 self.fileobj.close()
197 197
198 class tellable(object):
199 '''provide tell method for zipfile.ZipFile when writing to http
200 response file object.'''
201
202 def __init__(self, fp):
203 self.fp = fp
204 self.offset = 0
205
206 def __getattr__(self, key):
207 return getattr(self.fp, key)
208
209 def write(self, s):
210 self.fp.write(s)
211 self.offset += len(s)
212
213 def tell(self):
214 return self.offset
215
216 198 class zipit(object):
217 199 '''write archive to zip file or stream. can write uncompressed,
218 200 or compressed with deflate.'''
219 201
220 202 def __init__(self, dest, mtime, compress=True):
221 if not isinstance(dest, bytes):
222 try:
223 dest.tell()
224 except (AttributeError, IOError):
225 dest = tellable(dest)
226 203 self.z = zipfile.ZipFile(pycompat.fsdecode(dest), r'w',
227 204 compress and zipfile.ZIP_DEFLATED or
228 205 zipfile.ZIP_STORED)
@@ -290,6 +290,37 b' def parserequestfromenv(env, bodyfh):'
290 290 headers=headers,
291 291 bodyfh=bodyfh)
292 292
293 class offsettrackingwriter(object):
294 """A file object like object that is append only and tracks write count.
295
296 Instances are bound to a callable. This callable is called with data
297 whenever a ``write()`` is attempted.
298
299 Instances track the amount of written data so they can answer ``tell()``
300 requests.
301
302 The intent of this class is to wrap the ``write()`` function returned by
303 a WSGI ``start_response()`` function. Since ``write()`` is a callable and
304 not a file object, it doesn't implement other file object methods.
305 """
306 def __init__(self, writefn):
307 self._write = writefn
308 self._offset = 0
309
310 def write(self, s):
311 res = self._write(s)
312 # Some Python objects don't report the number of bytes written.
313 if res is None:
314 self._offset += len(s)
315 else:
316 self._offset += res
317
318 def flush(self):
319 pass
320
321 def tell(self):
322 return self._offset
323
293 324 class wsgiresponse(object):
294 325 """Represents a response to a WSGI request.
295 326
@@ -24,6 +24,9 b' from .common import ('
24 24 paritygen,
25 25 staticfile,
26 26 )
27 from . import (
28 request as requestmod,
29 )
27 30
28 31 from .. import (
29 32 archival,
@@ -1215,7 +1218,9 b' def archive(web, req, tmpl):'
1215 1218 req.headers.extend(headers)
1216 1219 req.respond(HTTP_OK, mimetype)
1217 1220
1218 archival.archive(web.repo, req, cnode, artype, prefix=name,
1221 bodyfh = requestmod.offsettrackingwriter(req.write)
1222
1223 archival.archive(web.repo, bodyfh, cnode, artype, prefix=name,
1219 1224 matchfn=match,
1220 1225 subrepos=web.configbool("web", "archivesubrepos"))
1221 1226 return []
General Comments 0
You need to be logged in to leave comments. Login now