launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03966
[Merge] lp:~xaav/loggerhead/export-tarball into lp:loggerhead
You have been requested to review the proposed merge of lp:~xaav/loggerhead/export-tarball into lp:loggerhead.
For more details, see:
https://code.launchpad.net/~xaav/loggerhead/export-tarball/+merge/63931
This branch **may** accomplish exporting the tarball using chunked transfer encoding. The code all looks to be correct, but I have not tested it, so I would like your opinion.
Thanks!
--
https://code.launchpad.net/~xaav/loggerhead/export-tarball/+merge/63931
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~xaav/loggerhead/export-tarball into lp:loggerhead.
=== modified file '.bzrignore'
--- .bzrignore 2011-03-10 14:22:12 +0000
+++ .bzrignore 2011-06-13 02:18:26 +0000
@@ -8,3 +8,4 @@
loggerhead-memprofile
./docs/_build/
tags
+loggerhead/static/downloads/*
=== modified file 'loggerhead/apps/branch.py'
--- loggerhead/apps/branch.py 2011-03-16 11:40:05 +0000
+++ loggerhead/apps/branch.py 2011-06-13 02:18:26 +0000
@@ -33,7 +33,7 @@
from loggerhead.controllers.atom_ui import AtomUI
from loggerhead.controllers.changelog_ui import ChangeLogUI
from loggerhead.controllers.diff_ui import DiffUI
-from loggerhead.controllers.download_ui import DownloadUI
+from loggerhead.controllers.download_ui import DownloadUI, DownloadTarballUI
from loggerhead.controllers.filediff_ui import FileDiffUI
from loggerhead.controllers.inventory_ui import InventoryUI
from loggerhead.controllers.revision_ui import RevisionUI
@@ -49,7 +49,7 @@
def __init__(self, branch, friendly_name=None, config={},
graph_cache=None, branch_link=None, is_root=False,
- served_url=_DEFAULT, use_cdn=False):
+ served_url=_DEFAULT, use_cdn=False, export_tarballs=True):
self.branch = branch
self._config = config
self.friendly_name = friendly_name
@@ -61,6 +61,7 @@
self.is_root = is_root
self.served_url = served_url
self.use_cdn = use_cdn
+ self.export_tarballs = export_tarballs
def get_history(self):
file_cache = None
@@ -126,6 +127,7 @@
'revision': RevisionUI,
'search': SearchUI,
'view': ViewUI,
+ 'tarball': DownloadTarballUI,
}
def last_updated(self):
@@ -171,10 +173,14 @@
try:
try:
c = cls(self, self.get_history)
- return c(environ, start_response)
+ to_ret = c(environ, start_response)
except:
environ['exc_info'] = sys.exc_info()
environ['branch'] = self
raise
+ if type(to_ret) == type(httpexceptions.HTTPSeeOther('/')):
+ raise to_ret
+ else:
+ return to_ret
finally:
self.branch.unlock()
=== modified file 'loggerhead/config.py'
--- loggerhead/config.py 2010-05-12 14:38:05 +0000
+++ loggerhead/config.py 2011-06-13 02:18:26 +0000
@@ -36,6 +36,7 @@
use_cdn=False,
sql_dir=None,
allow_writes=False,
+ export_tarballs=True,
)
parser.add_option("--user-dirs", action="store_true",
help="Serve user directories as ~user.")
@@ -75,6 +76,8 @@
help="The directory to place the SQL cache in")
parser.add_option("--allow-writes", action="store_true",
help="Allow writing to the Bazaar server.")
+ parser.add_option("--export-tarballs", action="store_true",
+ help="Allow exporting revisions to tarballs.")
return parser
=== modified file 'loggerhead/controllers/__init__.py'
--- loggerhead/controllers/__init__.py 2011-03-16 11:40:05 +0000
+++ loggerhead/controllers/__init__.py 2011-06-13 02:18:26 +0000
@@ -20,7 +20,7 @@
import bzrlib.errors
import time
-from paste.httpexceptions import HTTPNotFound
+from paste.httpexceptions import HTTPNotFound, HTTPSeeOther
from paste.request import path_info_pop, parse_querystring
from loggerhead import util
=== modified file 'loggerhead/controllers/download_ui.py'
--- loggerhead/controllers/download_ui.py 2010-05-05 19:03:40 +0000
+++ loggerhead/controllers/download_ui.py 2011-06-13 02:18:26 +0000
@@ -19,17 +19,23 @@
import logging
import mimetypes
+import os
import urllib
from paste import httpexceptions
from paste.request import path_info_pop
from loggerhead.controllers import TemplatedBranchView
+from loggerhead.exporter import export_tarball
log = logging.getLogger("loggerhead.controllers")
class DownloadUI (TemplatedBranchView):
+
+ def encode_filename(self, filename):
+
+ return urllib.quote(filename.encode('utf-8'))
def __call__(self, environ, start_response):
# /download/<rev_id>/<file_id>/[filename]
@@ -58,7 +64,7 @@
path,
h.get_revno(revid),
len(content))
- encoded_filename = urllib.quote(filename.encode('utf-8'))
+ encoded_filename = self.encode_filename(filename)
headers = [
('Content-Type', mime_type),
('Content-Length', str(len(content))),
@@ -67,3 +73,34 @@
]
start_response('200 OK', headers)
return [content]
+
+class DownloadTarballUI(DownloadUI):
+
+ def __call__(self, environ, start_response):
+ """Stream a tarball from a bazaar branch."""
+
+ #Tried to re-use code from downloadui, not very successful
+
+ format = ".tar.gz"
+
+ history = self._history
+ if len(self.args):
+ revid = history.fix_revid(self.args[0])
+ else:
+ revid = self.get_revid()
+
+ if self._branch.export_tarballs:
+
+ encoded_filename = self.encode_filename("branch" + format)
+
+ headers = [
+ ('Content-Type', 'application/octet-stream'),
+ ('Content-Disposition',
+ "attachment; filename*=utf-8''%s" % (encoded_filename,)),
+ ]
+
+ start_response('200 OK', headers)
+
+ return export_tarball(history, revid, format)
+ else:
+ raise httpexceptions.HTTPSeeOther('/')
=== modified file 'loggerhead/controllers/revision_ui.py'
--- loggerhead/controllers/revision_ui.py 2011-03-02 14:07:21 +0000
+++ loggerhead/controllers/revision_ui.py 2011-06-13 02:18:26 +0000
@@ -110,7 +110,7 @@
self._branch.friendly_name,
self._branch.is_root,
'changes'))
-
+ can_export = self._branch.export_tarballs
return {
'branch': self._branch,
'revid': revid,
@@ -132,4 +132,5 @@
'compare_revid': compare_revid,
'url': self._branch.context_url,
'directory_breadcrumbs': directory_breadcrumbs,
+ 'can_export': can_export,
}
=== added file 'loggerhead/exporter.py'
--- loggerhead/exporter.py 1970-01-01 00:00:00 +0000
+++ loggerhead/exporter.py 2011-06-13 02:18:26 +0000
@@ -0,0 +1,40 @@
+"""Exports an archive from a bazaar branch"""
+
+from bzrlib.export import get_export_generator
+
+class ExporterFileObject(object):
+
+ def __init__(self):
+ self._buffer = []
+
+ def write(self, str):
+ self._buffer.append(str)
+
+ def get_buffer(self):
+ try:
+ return ''.join(self._buffer)
+ finally:
+ self._buffer = []
+
+def export_archive(history, revid, format=".tar.gz"):
+ """Export tree contents to an archive
+
+ :param history: Instance of history to export
+ :param revid: Revision to export
+ :param format: Format of the archive
+ """
+
+ fileobj = ExporterFileObject()
+
+ tree = history._branch.repository.revision_tree(revid)
+
+ for _ in get_export_generator(tree=tree, fileobj=fileobj, format=format):
+
+ yield fileobj.get_buffer()
+
+ # Might have additonal contents written
+
+ yield fileobj.get_buffer()
+
+
+
\ No newline at end of file
=== modified file 'loggerhead/history.py'
--- loggerhead/history.py 2011-03-25 13:09:10 +0000
+++ loggerhead/history.py 2011-06-13 02:18:26 +0000
@@ -33,6 +33,7 @@
import re
import textwrap
import threading
+import tarfile
from bzrlib import tag
import bzrlib.branch
@@ -44,6 +45,7 @@
from loggerhead import search
from loggerhead import util
from loggerhead.wholehistory import compute_whole_history_data
+from bzrlib.export.tar_exporter import export_tarball
def is_branch(folder):
@@ -817,3 +819,4 @@
removed=sorted(reporter.removed, key=lambda x: x.filename),
modified=sorted(reporter.modified, key=lambda x: x.filename),
text_changes=sorted(reporter.text_changes, key=lambda x: x.filename))
+
=== added directory 'loggerhead/static/downloads'
=== modified file 'loggerhead/templates/revision.pt'
--- loggerhead/templates/revision.pt 2011-02-23 03:01:15 +0000
+++ loggerhead/templates/revision.pt 2011-06-13 02:18:26 +0000
@@ -84,7 +84,10 @@
tal:attributes="href python:url(['/diff', change.revno], clear=1)">download diff</a>
<a tal:condition="python:compare_revid is not None"
tal:attributes="href python:url(['/diff', change.revno, history.get_revno(compare_revid)], clear=1)">download diff</a>
- </li>
+ </li>
+ <li tal:condition="python:can_export">
+ <a tal:attributes="href python:url(['/tarball', change.revno])">download tarball</a>
+ </li>
<li id="last"><a tal:attributes="href python:url(['/changes', change.revno]);
title string:view history from revision ${change/revno}"
tal:content="string:view history from revision ${change/revno}"></a></li>
=== modified file 'loggerhead/tests/test_controllers.py'
--- loggerhead/tests/test_controllers.py 2011-03-15 02:56:59 +0000
+++ loggerhead/tests/test_controllers.py 2011-06-13 02:18:26 +0000
@@ -12,6 +12,9 @@
from loggerhead.tests.test_simple import BasicTests
from loggerhead import util
+from os import tmpnam
+from tarfile import is_tarfile
+
class TestInventoryUI(BasicTests):
@@ -125,3 +128,14 @@
self.assertEqual(2, len(annotated))
self.assertEqual('2', annotated[0].change.revno)
self.assertEqual('1', annotated[1].change.revno)
+
+class TestDownloadTarballUI(BasicTests):
+
+ def test_download_tarball(self):
+ app = self.setUpLoggerhead()
+ res = app.get('/tarball')
+ tmpname = tmpnam()
+ f = open(tmpname, 'w')
+ f.write(res)
+ f.close()
+ self.failIf(not is_tarfile(tmpname))