##// END OF EJS Templates
fixes for rawfile, annotation, download. It will check now if it's a filenode....
marcink -
r1189:a4e1b955 beta
parent child Browse files
Show More
@@ -1,297 +1,305 b''
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
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 28 import logging
29 29 import rhodecode.lib.helpers as h
30 30
31 31 from pylons import request, response, session, tmpl_context as c, url
32 32 from pylons.i18n.translation import _
33 33 from pylons.controllers.util import redirect
34 34
35 35 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
36 36 from rhodecode.lib.base import BaseRepoController, render
37 37 from rhodecode.lib.utils import EmptyChangeset
38 38 from rhodecode.model.repo import RepoModel
39 39
40 40 from vcs.backends import ARCHIVE_SPECS
41 41 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
42 42 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
43 43 from vcs.nodes import FileNode, NodeKind
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(BaseRepoController):
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 try:
68 68 return c.rhodecode_repo.get_changeset(rev)
69 69 except EmptyRepositoryError, e:
70 70 h.flash(_('There are no files yet'), category='warning')
71 71 redirect(h.url('summary_home', repo_name=repo_name))
72 72
73 73 except RepositoryError, e:
74 74 h.flash(str(e), category='warning')
75 75 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
76 76
77
78 def __get_filenode_or_redirect(self, repo_name, cs, path):
79 """
80 Returns file_node, if error occurs or given path is directory,
81 it'll redirect to top level path
82
83 :param repo_name: repo_name
84 :param cs: given changeset
85 :param path: path to lookup
86 """
87
88
89 try:
90 file_node = cs.get_node(path)
91 if file_node.is_dir():
92 raise RepositoryError('given path is a directory')
93 except RepositoryError, e:
94 h.flash(str(e), category='warning')
95 redirect(h.url('files_home', repo_name=repo_name,
96 revision=cs.raw_id))
97
98 return file_node
99
77 100 def index(self, repo_name, revision, f_path):
78 101 #reditect to given revision from form if given
79 102 post_revision = request.POST.get('at_rev', None)
80 103 if post_revision:
81 104 cs = self.__get_cs_or_redirect(revision, repo_name)
82 105 redirect(url('files_home', repo_name=c.repo_name,
83 106 revision=cs.raw_id, f_path=f_path))
84 107
85 108
86 109 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
87 110 c.branch = request.GET.get('branch', None)
88 111 c.f_path = f_path
89 112
90 113 cur_rev = c.changeset.revision
91 114
92 115 #prev link
93 116 try:
94 117 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
95 118 c.url_prev = url('files_home', repo_name=c.repo_name,
96 119 revision=prev_rev.raw_id, f_path=f_path)
97 120 if c.branch:
98 121 c.url_prev += '?branch=%s' % c.branch
99 122 except (ChangesetDoesNotExistError, VCSError):
100 123 c.url_prev = '#'
101 124
102 125 #next link
103 126 try:
104 127 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
105 128 c.url_next = url('files_home', repo_name=c.repo_name,
106 129 revision=next_rev.raw_id, f_path=f_path)
107 130 if c.branch:
108 131 c.url_next += '?branch=%s' % c.branch
109 132 except (ChangesetDoesNotExistError, VCSError):
110 133 c.url_next = '#'
111 134
112 #files
135 #files or dirs
113 136 try:
114 137 c.files_list = c.changeset.get_node(f_path)
115 138 c.file_history = self._get_history(c.rhodecode_repo,
116 139 c.files_list, f_path)
117 140 except RepositoryError, e:
118 141 h.flash(str(e), category='warning')
119 142 redirect(h.url('files_home', repo_name=repo_name,
120 143 revision=revision))
121 144
122 145
123 146 return render('files/files.html')
124 147
125 148 def rawfile(self, repo_name, revision, f_path):
126 149 cs = self.__get_cs_or_redirect(revision, repo_name)
127 try:
128 file_node = cs.get_node(f_path)
129 except RepositoryError, e:
130 h.flash(str(e), category='warning')
131 redirect(h.url('files_home', repo_name=repo_name,
132 revision=cs.raw_id))
150 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
133 151
134 fname = f_path.split('/')[-1].encode('utf8', 'replace')
152 response.content_disposition = 'attachment; filename=%s' % \
153 f_path.split('/')[-1].encode('utf8', 'replace')
154
135 155 response.content_type = file_node.mimetype
136 response.content_disposition = 'attachment; filename=%s' % fname
137 156 return file_node.content
138 157
139 158 def raw(self, repo_name, revision, f_path):
140 159 cs = self.__get_cs_or_redirect(revision, repo_name)
141 try:
142 file_node = cs.get_node(f_path)
143 except RepositoryError, e:
144 h.flash(str(e), category='warning')
145 redirect(h.url('files_home', repo_name=repo_name,
146 revision=cs.raw_id))
160 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
147 161
148 162 response.content_type = 'text/plain'
149
150 163 return file_node.content
151 164
152 165 def annotate(self, repo_name, revision, f_path):
153 166 cs = self.__get_cs_or_redirect(revision, repo_name)
154 try:
155 c.file = cs.get_node(f_path)
156 except RepositoryError, e:
157 h.flash(str(e), category='warning')
158 redirect(h.url('files_home', repo_name=repo_name,
159 revision=cs.raw_id))
167 c.file = self.__get_filenode_or_redirect(repo_name, cs, f_path)
160 168
161 169 c.file_history = self._get_history(c.rhodecode_repo,
162 170 c.file, f_path)
163 171 c.cs = cs
164 172 c.f_path = f_path
165 173
166 174 return render('files/files_annotate.html')
167 175
168 176 def archivefile(self, repo_name, fname):
169 177
170 178 fileformat = None
171 179 revision = None
172 180 ext = None
173 181
174 182 for a_type, ext_data in ARCHIVE_SPECS.items():
175 183 archive_spec = fname.split(ext_data[1])
176 184 if len(archive_spec) == 2 and archive_spec[1] == '':
177 185 fileformat = a_type or ext_data[1]
178 186 revision = archive_spec[0]
179 187 ext = ext_data[1]
180 188
181 189 try:
182 190 dbrepo = RepoModel().get_by_repo_name(repo_name)
183 191 if dbrepo.enable_downloads is False:
184 192 return _('downloads disabled')
185 193
186 194 cs = c.rhodecode_repo.get_changeset(revision)
187 195 content_type = ARCHIVE_SPECS[fileformat][0]
188 196 except ChangesetDoesNotExistError:
189 197 return _('Unknown revision %s') % revision
190 198 except EmptyRepositoryError:
191 199 return _('Empty repository')
192 200 except (ImproperArchiveTypeError, KeyError):
193 201 return _('Unknown archive type')
194 202
195 203 response.content_type = content_type
196 204 response.content_disposition = 'attachment; filename=%s-%s%s' \
197 205 % (repo_name, revision, ext)
198 206
199 207 return cs.get_chunked_archive(stream=None, kind=fileformat)
200 208
201 209
202 210 def diff(self, repo_name, f_path):
203 211 diff1 = request.GET.get('diff1')
204 212 diff2 = request.GET.get('diff2')
205 213 c.action = request.GET.get('diff')
206 214 c.no_changes = diff1 == diff2
207 215 c.f_path = f_path
208 216
209 217 try:
210 218 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
211 219 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
212 220 node1 = c.changeset_1.get_node(f_path)
213 221 else:
214 222 c.changeset_1 = EmptyChangeset()
215 223 node1 = FileNode('.', '', changeset=c.changeset_1)
216 224
217 225 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
218 226 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
219 227 node2 = c.changeset_2.get_node(f_path)
220 228 else:
221 229 c.changeset_2 = EmptyChangeset()
222 230 node2 = FileNode('.', '', changeset=c.changeset_2)
223 231 except RepositoryError:
224 232 return redirect(url('files_home',
225 233 repo_name=c.repo_name, f_path=f_path))
226 234
227 235
228 236 if c.action == 'download':
229 237 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
230 238 format='gitdiff')
231 239
232 240 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
233 241 response.content_type = 'text/plain'
234 242 response.content_disposition = 'attachment; filename=%s' \
235 243 % diff_name
236 244 return diff.raw_diff()
237 245
238 246 elif c.action == 'raw':
239 247 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
240 248 format='gitdiff')
241 249 response.content_type = 'text/plain'
242 250 return diff.raw_diff()
243 251
244 252 elif c.action == 'diff':
245 253
246 254 if node1.is_binary or node2.is_binary:
247 255 c.cur_diff = _('Binary file')
248 256 elif node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
249 257 c.cur_diff = _('Diff is too big to display')
250 258 else:
251 259 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
252 260 format='gitdiff')
253 261 c.cur_diff = diff.as_html()
254 262 else:
255 263
256 264 #default option
257 265 if node1.is_binary or node2.is_binary:
258 266 c.cur_diff = _('Binary file')
259 267 elif node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
260 268 c.cur_diff = _('Diff is too big to display')
261 269 else:
262 270 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
263 271 format='gitdiff')
264 272 c.cur_diff = diff.as_html()
265 273
266 274 if not c.cur_diff:
267 275 c.no_changes = True
268 276 return render('files/file_diff.html')
269 277
270 278 def _get_history(self, repo, node, f_path):
271 if not node.kind is NodeKind.FILE:
279 if not node.is_file():
272 280 return []
273 281 changesets = node.history
274 282 hist_l = []
275 283
276 284 changesets_group = ([], _("Changesets"))
277 285 branches_group = ([], _("Branches"))
278 286 tags_group = ([], _("Tags"))
279 287
280 288 for chs in changesets:
281 289 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
282 290 changesets_group[0].append((chs.raw_id, n_desc,))
283 291
284 292 hist_l.append(changesets_group)
285 293
286 294 for name, chs in c.rhodecode_repo.branches.items():
287 295 #chs = chs.split(':')[-1]
288 296 branches_group[0].append((chs, name),)
289 297 hist_l.append(branches_group)
290 298
291 299 for name, chs in c.rhodecode_repo.tags.items():
292 300 #chs = chs.split(':')[-1]
293 301 tags_group[0].append((chs, name),)
294 302 hist_l.append(tags_group)
295 303
296 304 return hist_l
297 305
General Comments 0
You need to be logged in to leave comments. Login now