diff --git a/mercurial/hgweb/protocol.py b/mercurial/hgweb/protocol.py --- a/mercurial/hgweb/protocol.py +++ b/mercurial/hgweb/protocol.py @@ -73,21 +73,30 @@ class webproto(wireproto.abstractserverp val = self.ui.fout.getvalue() self.ui.ferr, self.ui.fout = self.oldio return val + def groupchunks(self, fh): + def getchunks(): + while True: + chunk = fh.read(32768) + if not chunk: + break + yield chunk + + return self.compresschunks(getchunks()) + + def compresschunks(self, chunks): # Don't allow untrusted settings because disabling compression or # setting a very high compression level could lead to flooding # the server's network or CPU. z = zlib.compressobj(self.ui.configint('server', 'zliblevel', -1)) - while True: - chunk = fh.read(32768) - if not chunk: - break + for chunk in chunks: data = z.compress(chunk) # Not all calls to compress() emit data. It is cheaper to inspect # that here than to send it via the generator. if data: yield data yield z.flush() + def _client(self): return 'remote:%s:%s:%s' % ( self.req.env.get('wsgi.url_scheme') or 'http', diff --git a/mercurial/sshserver.py b/mercurial/sshserver.py --- a/mercurial/sshserver.py +++ b/mercurial/sshserver.py @@ -71,6 +71,10 @@ class sshserver(wireproto.abstractserver def groupchunks(self, fh): return iter(lambda: fh.read(4096), '') + def compresschunks(self, chunks): + for chunk in chunks: + yield chunk + def sendresponse(self, v): self.fout.write("%d\n" % len(v)) self.fout.write(v) diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -85,6 +85,14 @@ class abstractserverproto(object): """ raise NotImplementedError() + def compresschunks(self, chunks): + """Generator of possible compressed chunks to send to the client. + + This is like ``groupchunks()`` except it accepts a generator as + its argument. + """ + raise NotImplementedError() + class remotebatch(peer.batcher): '''batches the queued calls; uses as few roundtrips as possible''' def __init__(self, remote): @@ -773,9 +781,7 @@ def getbundle(repo, proto, others): return ooberror(bundle2required) chunks = exchange.getbundlechunks(repo, 'serve', **opts) - # TODO avoid util.chunkbuffer() here since it is adding overhead to - # what is fundamentally a generator proxying operation. - return streamres(proto.groupchunks(util.chunkbuffer(chunks))) + return streamres(proto.compresschunks(chunks)) @wireprotocommand('heads') def heads(repo, proto):