2
# Copyright (C) 2006 Robey Pointer <robey@lag.net>
3
# Copyright (C) 2006 Goffredo Baroncelli <kreijack@inwind.it>
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24
from breezy.errors import (
28
from breezy import osutils, urlutils
29
from paste import httpexceptions
30
from paste.request import path_info_pop
32
from ..controllers import TemplatedBranchView
34
log = logging.getLogger("loggerhead.controllers")
37
class DownloadUI (TemplatedBranchView):
39
def encode_filename(self, filename):
41
return urlutils.escape(filename)
43
def get_args(self, environ):
46
arg = path_info_pop(environ)
52
def __call__(self, environ, start_response):
53
# /download/<rev_id>/<file_id>/[filename]
55
args = self.get_args(environ)
57
raise httpexceptions.HTTPMovedPermanently(
58
self._branch.absolute_url('/changes'))
59
revid = h.fix_revid(args[0])
60
file_id = urlutils.unquote_to_bytes(osutils.safe_utf8(args[1]))
62
path, filename, content = h.get_file(file_id, revid)
63
except (NoSuchId, NoSuchRevision):
64
raise httpexceptions.HTTPNotFound()
65
mime_type, encoding = mimetypes.guess_type(filename)
67
mime_type = 'application/octet-stream'
68
self.log.info('/download %s @ %s (%d bytes)',
72
encoded_filename = self.encode_filename(filename)
74
('Content-Type', mime_type),
75
('Content-Length', str(len(content))),
76
('Content-Disposition',
77
"attachment; filename*=utf-8''%s" % (encoded_filename,)),
79
start_response('200 OK', headers)
83
class DownloadTarballUI(DownloadUI):
85
def __call__(self, environ, start_response):
86
"""Stream a tarball from a bazaar branch."""
87
# Tried to re-use code from downloadui, not very successful
88
if not self._branch.export_tarballs:
89
raise httpexceptions.HTTPForbidden(
90
"Tarball downloads are not allowed")
91
archive_format = "tgz"
92
history = self._history
93
self.args = self.get_args(environ)
95
revid = history.fix_revid(self.args[0])
96
version_part = '-r' + self.args[0]
98
revid = self.get_revid()
100
# XXX: Perhaps some better suggestion based on the URL or path?
102
# TODO: Perhaps set the tarball suggested mtime to the revision
104
root = self._branch.friendly_name or 'branch'
105
filename = root + version_part + '.' + archive_format
106
encoded_filename = self.encode_filename(filename)
108
('Content-Type', 'application/octet-stream'),
109
('Content-Disposition',
110
"attachment; filename*=utf-8''%s" % (encoded_filename,)),
112
start_response('200 OK', headers)
113
tree = history._branch.repository.revision_tree(revid)
114
return tree.archive(root=root, format=archive_format, name=filename)