##// END OF EJS Templates
fixed archives headers, Thanks to Thomas Waldmann
marcink -
r1238:438524e8 default
parent child Browse files
Show More
@@ -1,279 +1,279
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.files
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Files controller for RhodeCode
7 7
8 8 :created_on: Apr 21, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25 import os
26 26 import tempfile
27 27 import logging
28 28 import rhodecode.lib.helpers as h
29 29
30 30 from mercurial import archival
31 31
32 32 from pylons import request, response, session, tmpl_context as c, url
33 33 from pylons.i18n.translation import _
34 34 from pylons.controllers.util import redirect
35 35
36 36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 37 from rhodecode.lib.base import BaseController, render
38 38 from rhodecode.lib.utils import EmptyChangeset
39 39 from rhodecode.model.scm import ScmModel
40 40
41 41 from vcs.exceptions import RepositoryError, ChangesetError, \
42 42 ChangesetDoesNotExistError, EmptyRepositoryError
43 43 from vcs.nodes import FileNode
44 44 from vcs.utils import diffs as differ
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48
49 49 class FilesController(BaseController):
50 50
51 51 @LoginRequired()
52 52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
53 53 'repository.admin')
54 54 def __before__(self):
55 55 super(FilesController, self).__before__()
56 56 c.cut_off_limit = self.cut_off_limit
57 57
58 58 def __get_cs_or_redirect(self, rev, repo_name):
59 59 """
60 60 Safe way to get changeset if error occur it redirects to tip with
61 61 proper message
62 62
63 63 :param rev: revision to fetch
64 64 :param repo_name: repo name to redirect after
65 65 """
66 66
67 67 _repo = ScmModel().get_repo(c.repo_name)
68 68 try:
69 69 return _repo.get_changeset(rev)
70 70 except EmptyRepositoryError, e:
71 71 h.flash(_('There are no files yet'), category='warning')
72 72 redirect(h.url('summary_home', repo_name=repo_name))
73 73
74 74 except RepositoryError, e:
75 75 h.flash(str(e), category='warning')
76 76 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
77 77
78 78 def index(self, repo_name, revision, f_path):
79 79 cs = self.__get_cs_or_redirect(revision, repo_name)
80 80 c.repo = ScmModel().get_repo(c.repo_name)
81 81
82 82 revision = request.POST.get('at_rev', None) or revision
83 83
84 84 def get_next_rev(cur):
85 85 max_rev = len(c.repo.revisions) - 1
86 86 r = cur + 1
87 87 if r > max_rev:
88 88 r = max_rev
89 89 return r
90 90
91 91 def get_prev_rev(cur):
92 92 r = cur - 1
93 93 return r
94 94
95 95 c.f_path = f_path
96 96 c.changeset = cs
97 97 cur_rev = c.changeset.revision
98 98 prev_rev = c.repo.get_changeset(get_prev_rev(cur_rev)).raw_id
99 99 next_rev = c.repo.get_changeset(get_next_rev(cur_rev)).raw_id
100 100
101 101 c.url_prev = url('files_home', repo_name=c.repo_name,
102 102 revision=prev_rev, f_path=f_path)
103 103 c.url_next = url('files_home', repo_name=c.repo_name,
104 104 revision=next_rev, f_path=f_path)
105 105
106 106 try:
107 107 c.files_list = c.changeset.get_node(f_path)
108 108 c.file_history = self._get_history(c.repo, c.files_list, f_path)
109 109 except RepositoryError, e:
110 110 h.flash(str(e), category='warning')
111 111 redirect(h.url('files_home', repo_name=repo_name,
112 112 revision=revision))
113 113
114 114
115 115 return render('files/files.html')
116 116
117 117 def rawfile(self, repo_name, revision, f_path):
118 118 cs = self.__get_cs_or_redirect(revision, repo_name)
119 119 try:
120 120 file_node = cs.get_node(f_path)
121 121 except RepositoryError, e:
122 122 h.flash(str(e), category='warning')
123 123 redirect(h.url('files_home', repo_name=repo_name,
124 124 revision=cs.raw_id))
125 125
126 126 fname = f_path.split(os.sep)[-1].encode('utf8', 'replace')
127 127
128 128 response.content_disposition = 'attachment; filename=%s' % fname
129 129 response.content_type = file_node.mimetype
130 130 return file_node.content
131 131
132 132 def raw(self, repo_name, revision, f_path):
133 133 cs = self.__get_cs_or_redirect(revision, repo_name)
134 134 try:
135 135 file_node = cs.get_node(f_path)
136 136 except RepositoryError, e:
137 137 h.flash(str(e), category='warning')
138 138 redirect(h.url('files_home', repo_name=repo_name,
139 139 revision=cs.raw_id))
140 140
141 141 response.content_type = 'text/plain'
142 142 return file_node.content
143 143
144 144 def annotate(self, repo_name, revision, f_path):
145 145 cs = self.__get_cs_or_redirect(revision, repo_name)
146 146 try:
147 147 c.file = cs.get_node(f_path)
148 148 except RepositoryError, e:
149 149 h.flash(str(e), category='warning')
150 150 redirect(h.url('files_home', repo_name=repo_name, revision=cs.raw_id))
151 151
152 152 c.file_history = self._get_history(ScmModel().get_repo(c.repo_name), c.file, f_path)
153 153 c.cs = cs
154 154 c.f_path = f_path
155 155
156 156 return render('files/files_annotate.html')
157 157
158 158 def archivefile(self, repo_name, revision, fileformat):
159 159 archive_specs = {
160 '.tar.bz2': ('application/x-tar', 'tbz2'),
161 '.tar.gz': ('application/x-tar', 'tgz'),
160 '.tar.bz2': ('application/x-bzip2', 'tbz2'),
161 '.tar.gz': ('application/x-gzip', 'tgz'),
162 162 '.zip': ('application/zip', 'zip'),
163 163 }
164 164 if not archive_specs.has_key(fileformat):
165 165 return 'Unknown archive type %s' % fileformat
166 166
167 167 def read_in_chunks(file_object, chunk_size=1024 * 40):
168 168 """Lazy function (generator) to read a file piece by piece.
169 169 Default chunk size: 40k."""
170 170 while True:
171 171 data = file_object.read(chunk_size)
172 172 if not data:
173 173 break
174 174 yield data
175 175
176 176 archive = tempfile.TemporaryFile()
177 177 repo = ScmModel().get_repo(repo_name).repo
178 178 fname = '%s-%s%s' % (repo_name, revision, fileformat)
179 179 archival.archive(repo, archive, revision, archive_specs[fileformat][1],
180 180 prefix='%s-%s' % (repo_name, revision))
181 181 response.content_type = archive_specs[fileformat][0]
182 182 response.content_disposition = 'attachment; filename=%s' % fname
183 183 archive.seek(0)
184 184 return read_in_chunks(archive)
185 185
186 186 def diff(self, repo_name, f_path):
187 187 hg_model = ScmModel()
188 188 diff1 = request.GET.get('diff1')
189 189 diff2 = request.GET.get('diff2')
190 190 c.action = request.GET.get('diff')
191 191 c.no_changes = diff1 == diff2
192 192 c.f_path = f_path
193 193 c.repo = hg_model.get_repo(c.repo_name)
194 194
195 195 try:
196 196 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
197 197 c.changeset_1 = c.repo.get_changeset(diff1)
198 198 node1 = c.changeset_1.get_node(f_path)
199 199 else:
200 200 c.changeset_1 = EmptyChangeset()
201 201 node1 = FileNode('.', '', changeset=c.changeset_1)
202 202
203 203 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
204 204 c.changeset_2 = c.repo.get_changeset(diff2)
205 205 node2 = c.changeset_2.get_node(f_path)
206 206 else:
207 207 c.changeset_2 = EmptyChangeset()
208 208 node2 = FileNode('.', '', changeset=c.changeset_2)
209 209 except RepositoryError:
210 210 return redirect(url('files_home',
211 211 repo_name=c.repo_name, f_path=f_path))
212 212
213 213 f_udiff = differ.get_udiff(node1, node2)
214 214 diff = differ.DiffProcessor(f_udiff)
215 215
216 216 if c.action == 'download':
217 217 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
218 218 response.content_type = 'text/plain'
219 219 response.content_disposition = 'attachment; filename=%s' \
220 220 % diff_name
221 221 if node1.is_binary or node2.is_binary:
222 222 return _('binary file changed')
223 223 return diff.raw_diff()
224 224
225 225 elif c.action == 'raw':
226 226 response.content_type = 'text/plain'
227 227 if node1.is_binary or node2.is_binary:
228 228 return _('binary file changed')
229 229 return diff.raw_diff()
230 230
231 231 elif c.action == 'diff':
232 232 if node1.is_binary or node2.is_binary:
233 233 c.cur_diff = _('Binary file')
234 234 elif node1.size > self.cut_off_limit or \
235 235 node2.size > self.cut_off_limit:
236 236 c.cur_diff = _('Diff is too big to display')
237 237 else:
238 238 c.cur_diff = diff.as_html()
239 239 else:
240 240 #default option
241 241 if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
242 242 c.cur_diff = _('Diff is to big to display')
243 243 elif node1.is_binary or node2.is_binary:
244 244 c.cur_diff = _('Binary file')
245 245 else:
246 246 c.cur_diff = diff.as_html()
247 247
248 248 if not c.cur_diff:
249 249 c.no_changes = True
250 250 return render('files/file_diff.html')
251 251
252 252 def _get_history(self, repo, node, f_path):
253 253 from vcs.nodes import NodeKind
254 254 if not node.kind is NodeKind.FILE:
255 255 return []
256 256 changesets = node.history
257 257 hist_l = []
258 258
259 259 changesets_group = ([], _("Changesets"))
260 260 branches_group = ([], _("Branches"))
261 261 tags_group = ([], _("Tags"))
262 262
263 263 for chs in changesets:
264 264 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
265 265 changesets_group[0].append((chs.raw_id, n_desc,))
266 266
267 267 hist_l.append(changesets_group)
268 268
269 269 for name, chs in c.repository_branches.items():
270 270 #chs = chs.split(':')[-1]
271 271 branches_group[0].append((chs, name),)
272 272 hist_l.append(branches_group)
273 273
274 274 for name, chs in c.repository_tags.items():
275 275 #chs = chs.split(':')[-1]
276 276 tags_group[0].append((chs, name),)
277 277 hist_l.append(tags_group)
278 278
279 279 return hist_l
General Comments 0
You need to be logged in to leave comments. Login now