##// END OF EJS Templates
Added show as raw into big diff
marcink -
r1273:64cb9612 beta
parent child Browse files
Show More
@@ -1,335 +1,339 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.files
3 rhodecode.controllers.files
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Files controller for RhodeCode
6 Files controller for RhodeCode
7
7
8 :created_on: Apr 21, 2010
8 :created_on: Apr 21, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import mimetypes
28 import mimetypes
29 import rhodecode.lib.helpers as h
29 import rhodecode.lib.helpers as h
30
30
31 from pylons import request, response, session, tmpl_context as c, url
31 from pylons import request, response, session, tmpl_context as c, url
32 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34
34
35 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
35 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
36 from rhodecode.lib.base import BaseRepoController, render
36 from rhodecode.lib.base import BaseRepoController, render
37 from rhodecode.lib.utils import EmptyChangeset
37 from rhodecode.lib.utils import EmptyChangeset
38 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo import RepoModel
39
39
40 from vcs.backends import ARCHIVE_SPECS
40 from vcs.backends import ARCHIVE_SPECS
41 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
41 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
42 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
42 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
43 from vcs.nodes import FileNode, NodeKind
43 from vcs.nodes import FileNode, NodeKind
44 from vcs.utils import diffs as differ
44 from vcs.utils import diffs as differ
45
45
46 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
47
47
48
48
49 class FilesController(BaseRepoController):
49 class FilesController(BaseRepoController):
50
50
51 @LoginRequired()
51 @LoginRequired()
52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
53 'repository.admin')
53 'repository.admin')
54 def __before__(self):
54 def __before__(self):
55 super(FilesController, self).__before__()
55 super(FilesController, self).__before__()
56 c.cut_off_limit = self.cut_off_limit
56 c.cut_off_limit = self.cut_off_limit
57
57
58 def __get_cs_or_redirect(self, rev, repo_name):
58 def __get_cs_or_redirect(self, rev, repo_name):
59 """
59 """
60 Safe way to get changeset if error occur it redirects to tip with
60 Safe way to get changeset if error occur it redirects to tip with
61 proper message
61 proper message
62
62
63 :param rev: revision to fetch
63 :param rev: revision to fetch
64 :param repo_name: repo name to redirect after
64 :param repo_name: repo name to redirect after
65 """
65 """
66
66
67 try:
67 try:
68 return c.rhodecode_repo.get_changeset(rev)
68 return c.rhodecode_repo.get_changeset(rev)
69 except EmptyRepositoryError, e:
69 except EmptyRepositoryError, e:
70 h.flash(_('There are no files yet'), category='warning')
70 h.flash(_('There are no files yet'), category='warning')
71 redirect(h.url('summary_home', repo_name=repo_name))
71 redirect(h.url('summary_home', repo_name=repo_name))
72
72
73 except RepositoryError, e:
73 except RepositoryError, e:
74 h.flash(str(e), category='warning')
74 h.flash(str(e), category='warning')
75 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
75 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
76
76
77 def __get_filenode_or_redirect(self, repo_name, cs, path):
77 def __get_filenode_or_redirect(self, repo_name, cs, path):
78 """
78 """
79 Returns file_node, if error occurs or given path is directory,
79 Returns file_node, if error occurs or given path is directory,
80 it'll redirect to top level path
80 it'll redirect to top level path
81
81
82 :param repo_name: repo_name
82 :param repo_name: repo_name
83 :param cs: given changeset
83 :param cs: given changeset
84 :param path: path to lookup
84 :param path: path to lookup
85 """
85 """
86
86
87 try:
87 try:
88 file_node = cs.get_node(path)
88 file_node = cs.get_node(path)
89 if file_node.is_dir():
89 if file_node.is_dir():
90 raise RepositoryError('given path is a directory')
90 raise RepositoryError('given path is a directory')
91 except RepositoryError, e:
91 except RepositoryError, e:
92 h.flash(str(e), category='warning')
92 h.flash(str(e), category='warning')
93 redirect(h.url('files_home', repo_name=repo_name,
93 redirect(h.url('files_home', repo_name=repo_name,
94 revision=cs.raw_id))
94 revision=cs.raw_id))
95
95
96 return file_node
96 return file_node
97
97
98 def index(self, repo_name, revision, f_path):
98 def index(self, repo_name, revision, f_path):
99 #reditect to given revision from form if given
99 #reditect to given revision from form if given
100 post_revision = request.POST.get('at_rev', None)
100 post_revision = request.POST.get('at_rev', None)
101 if post_revision:
101 if post_revision:
102 cs = self.__get_cs_or_redirect(post_revision, repo_name)
102 cs = self.__get_cs_or_redirect(post_revision, repo_name)
103 redirect(url('files_home', repo_name=c.repo_name,
103 redirect(url('files_home', repo_name=c.repo_name,
104 revision=cs.raw_id, f_path=f_path))
104 revision=cs.raw_id, f_path=f_path))
105
105
106 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
106 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
107 c.branch = request.GET.get('branch', None)
107 c.branch = request.GET.get('branch', None)
108 c.f_path = f_path
108 c.f_path = f_path
109
109
110 cur_rev = c.changeset.revision
110 cur_rev = c.changeset.revision
111
111
112 #prev link
112 #prev link
113 try:
113 try:
114 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
114 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
115 c.url_prev = url('files_home', repo_name=c.repo_name,
115 c.url_prev = url('files_home', repo_name=c.repo_name,
116 revision=prev_rev.raw_id, f_path=f_path)
116 revision=prev_rev.raw_id, f_path=f_path)
117 if c.branch:
117 if c.branch:
118 c.url_prev += '?branch=%s' % c.branch
118 c.url_prev += '?branch=%s' % c.branch
119 except (ChangesetDoesNotExistError, VCSError):
119 except (ChangesetDoesNotExistError, VCSError):
120 c.url_prev = '#'
120 c.url_prev = '#'
121
121
122 #next link
122 #next link
123 try:
123 try:
124 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
124 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
125 c.url_next = url('files_home', repo_name=c.repo_name,
125 c.url_next = url('files_home', repo_name=c.repo_name,
126 revision=next_rev.raw_id, f_path=f_path)
126 revision=next_rev.raw_id, f_path=f_path)
127 if c.branch:
127 if c.branch:
128 c.url_next += '?branch=%s' % c.branch
128 c.url_next += '?branch=%s' % c.branch
129 except (ChangesetDoesNotExistError, VCSError):
129 except (ChangesetDoesNotExistError, VCSError):
130 c.url_next = '#'
130 c.url_next = '#'
131
131
132 #files or dirs
132 #files or dirs
133 try:
133 try:
134 c.files_list = c.changeset.get_node(f_path)
134 c.files_list = c.changeset.get_node(f_path)
135
135
136 if c.files_list.is_file():
136 if c.files_list.is_file():
137 c.file_history = self._get_node_history(c.changeset, f_path)
137 c.file_history = self._get_node_history(c.changeset, f_path)
138 else:
138 else:
139 c.file_history = []
139 c.file_history = []
140 except RepositoryError, e:
140 except RepositoryError, e:
141 h.flash(str(e), category='warning')
141 h.flash(str(e), category='warning')
142 redirect(h.url('files_home', repo_name=repo_name,
142 redirect(h.url('files_home', repo_name=repo_name,
143 revision=revision))
143 revision=revision))
144
144
145 return render('files/files.html')
145 return render('files/files.html')
146
146
147 def rawfile(self, repo_name, revision, f_path):
147 def rawfile(self, repo_name, revision, f_path):
148 cs = self.__get_cs_or_redirect(revision, repo_name)
148 cs = self.__get_cs_or_redirect(revision, repo_name)
149 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
149 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
150
150
151 response.content_disposition = 'attachment; filename=%s' % \
151 response.content_disposition = 'attachment; filename=%s' % \
152 f_path.split(os.sep)[-1].encode('utf8', 'replace')
152 f_path.split(os.sep)[-1].encode('utf8', 'replace')
153
153
154 response.content_type = file_node.mimetype
154 response.content_type = file_node.mimetype
155 return file_node.content
155 return file_node.content
156
156
157 def raw(self, repo_name, revision, f_path):
157 def raw(self, repo_name, revision, f_path):
158 cs = self.__get_cs_or_redirect(revision, repo_name)
158 cs = self.__get_cs_or_redirect(revision, repo_name)
159 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
159 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
160
160
161 raw_mimetype_mapping = {
161 raw_mimetype_mapping = {
162 # map original mimetype to a mimetype used for "show as raw"
162 # map original mimetype to a mimetype used for "show as raw"
163 # you can also provide a content-disposition to override the
163 # you can also provide a content-disposition to override the
164 # default "attachment" disposition.
164 # default "attachment" disposition.
165 # orig_type: (new_type, new_dispo)
165 # orig_type: (new_type, new_dispo)
166
166
167 # show images inline:
167 # show images inline:
168 'image/x-icon': ('image/x-icon', 'inline'),
168 'image/x-icon': ('image/x-icon', 'inline'),
169 'image/png': ('image/png', 'inline'),
169 'image/png': ('image/png', 'inline'),
170 'image/gif': ('image/gif', 'inline'),
170 'image/gif': ('image/gif', 'inline'),
171 'image/jpeg': ('image/jpeg', 'inline'),
171 'image/jpeg': ('image/jpeg', 'inline'),
172 'image/svg+xml': ('image/svg+xml', 'inline'),
172 'image/svg+xml': ('image/svg+xml', 'inline'),
173 }
173 }
174
174
175 mimetype = file_node.mimetype
175 mimetype = file_node.mimetype
176 try:
176 try:
177 mimetype, dispo = raw_mimetype_mapping[mimetype]
177 mimetype, dispo = raw_mimetype_mapping[mimetype]
178 except KeyError:
178 except KeyError:
179 # we don't know anything special about this, handle it safely
179 # we don't know anything special about this, handle it safely
180 if file_node.is_binary:
180 if file_node.is_binary:
181 # do same as download raw for binary files
181 # do same as download raw for binary files
182 mimetype, dispo = 'application/octet-stream', 'attachment'
182 mimetype, dispo = 'application/octet-stream', 'attachment'
183 else:
183 else:
184 # do not just use the original mimetype, but force text/plain,
184 # do not just use the original mimetype, but force text/plain,
185 # otherwise it would serve text/html and that might be unsafe.
185 # otherwise it would serve text/html and that might be unsafe.
186 # Note: underlying vcs library fakes text/plain mimetype if the
186 # Note: underlying vcs library fakes text/plain mimetype if the
187 # mimetype can not be determined and it thinks it is not
187 # mimetype can not be determined and it thinks it is not
188 # binary.This might lead to erroneous text display in some
188 # binary.This might lead to erroneous text display in some
189 # cases, but helps in other cases, like with text files
189 # cases, but helps in other cases, like with text files
190 # without extension.
190 # without extension.
191 mimetype, dispo = 'text/plain', 'inline'
191 mimetype, dispo = 'text/plain', 'inline'
192
192
193 if dispo == 'attachment':
193 if dispo == 'attachment':
194 dispo = 'attachment; filename=%s' % \
194 dispo = 'attachment; filename=%s' % \
195 f_path.split(os.sep)[-1].encode('utf8', 'replace')
195 f_path.split(os.sep)[-1].encode('utf8', 'replace')
196
196
197 response.content_disposition = dispo
197 response.content_disposition = dispo
198 response.content_type = mimetype
198 response.content_type = mimetype
199 return file_node.content
199 return file_node.content
200
200
201 def annotate(self, repo_name, revision, f_path):
201 def annotate(self, repo_name, revision, f_path):
202 c.cs = self.__get_cs_or_redirect(revision, repo_name)
202 c.cs = self.__get_cs_or_redirect(revision, repo_name)
203 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
203 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
204
204
205 c.file_history = self._get_node_history(c.cs, f_path)
205 c.file_history = self._get_node_history(c.cs, f_path)
206 c.f_path = f_path
206 c.f_path = f_path
207 return render('files/files_annotate.html')
207 return render('files/files_annotate.html')
208
208
209 def archivefile(self, repo_name, fname):
209 def archivefile(self, repo_name, fname):
210
210
211 fileformat = None
211 fileformat = None
212 revision = None
212 revision = None
213 ext = None
213 ext = None
214
214
215 for a_type, ext_data in ARCHIVE_SPECS.items():
215 for a_type, ext_data in ARCHIVE_SPECS.items():
216 archive_spec = fname.split(ext_data[1])
216 archive_spec = fname.split(ext_data[1])
217 if len(archive_spec) == 2 and archive_spec[1] == '':
217 if len(archive_spec) == 2 and archive_spec[1] == '':
218 fileformat = a_type or ext_data[1]
218 fileformat = a_type or ext_data[1]
219 revision = archive_spec[0]
219 revision = archive_spec[0]
220 ext = ext_data[1]
220 ext = ext_data[1]
221
221
222 try:
222 try:
223 dbrepo = RepoModel().get_by_repo_name(repo_name)
223 dbrepo = RepoModel().get_by_repo_name(repo_name)
224 if dbrepo.enable_downloads is False:
224 if dbrepo.enable_downloads is False:
225 return _('downloads disabled')
225 return _('downloads disabled')
226
226
227 cs = c.rhodecode_repo.get_changeset(revision)
227 cs = c.rhodecode_repo.get_changeset(revision)
228 content_type = ARCHIVE_SPECS[fileformat][0]
228 content_type = ARCHIVE_SPECS[fileformat][0]
229 except ChangesetDoesNotExistError:
229 except ChangesetDoesNotExistError:
230 return _('Unknown revision %s') % revision
230 return _('Unknown revision %s') % revision
231 except EmptyRepositoryError:
231 except EmptyRepositoryError:
232 return _('Empty repository')
232 return _('Empty repository')
233 except (ImproperArchiveTypeError, KeyError):
233 except (ImproperArchiveTypeError, KeyError):
234 return _('Unknown archive type')
234 return _('Unknown archive type')
235
235
236 response.content_type = content_type
236 response.content_type = content_type
237 response.content_disposition = 'attachment; filename=%s-%s%s' \
237 response.content_disposition = 'attachment; filename=%s-%s%s' \
238 % (repo_name, revision, ext)
238 % (repo_name, revision, ext)
239
239
240 return cs.get_chunked_archive(stream=None, kind=fileformat)
240 return cs.get_chunked_archive(stream=None, kind=fileformat)
241
241
242 def diff(self, repo_name, f_path):
242 def diff(self, repo_name, f_path):
243 diff1 = request.GET.get('diff1')
243 diff1 = request.GET.get('diff1')
244 diff2 = request.GET.get('diff2')
244 diff2 = request.GET.get('diff2')
245 c.action = request.GET.get('diff')
245 c.action = request.GET.get('diff')
246 c.no_changes = diff1 == diff2
246 c.no_changes = diff1 == diff2
247 c.f_path = f_path
247 c.f_path = f_path
248 c.big_diff = False
248
249
249 try:
250 try:
250 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
251 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
251 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
252 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
252 node1 = c.changeset_1.get_node(f_path)
253 node1 = c.changeset_1.get_node(f_path)
253 else:
254 else:
254 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
255 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
255 node1 = FileNode('.', '', changeset=c.changeset_1)
256 node1 = FileNode('.', '', changeset=c.changeset_1)
256
257
257 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
258 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
258 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
259 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
259 node2 = c.changeset_2.get_node(f_path)
260 node2 = c.changeset_2.get_node(f_path)
260 else:
261 else:
261 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
262 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
262 node2 = FileNode('.', '', changeset=c.changeset_2)
263 node2 = FileNode('.', '', changeset=c.changeset_2)
263 except RepositoryError:
264 except RepositoryError:
264 return redirect(url('files_home',
265 return redirect(url('files_home',
265 repo_name=c.repo_name, f_path=f_path))
266 repo_name=c.repo_name, f_path=f_path))
266
267
267 if c.action == 'download':
268 if c.action == 'download':
268 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
269 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
269 format='gitdiff')
270 format='gitdiff')
270
271
271 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
272 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
272 response.content_type = 'text/plain'
273 response.content_type = 'text/plain'
273 response.content_disposition = 'attachment; filename=%s' \
274 response.content_disposition = 'attachment; filename=%s' \
274 % diff_name
275 % diff_name
275 return diff.raw_diff()
276 return diff.raw_diff()
276
277
277 elif c.action == 'raw':
278 elif c.action == 'raw':
278 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
279 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
279 format='gitdiff')
280 format='gitdiff')
280 response.content_type = 'text/plain'
281 response.content_type = 'text/plain'
281 return diff.raw_diff()
282 return diff.raw_diff()
282
283
283 elif c.action == 'diff':
284 elif c.action == 'diff':
284
285
285 if node1.is_binary or node2.is_binary:
286 if node1.is_binary or node2.is_binary:
286 c.cur_diff = _('Binary file')
287 c.cur_diff = _('Binary file')
287 elif node1.size > self.cut_off_limit or \
288 elif node1.size > self.cut_off_limit or \
288 node2.size > self.cut_off_limit:
289 node2.size > self.cut_off_limit:
289 c.cur_diff = _('Diff is too big to display')
290 c.cur_diff = ''
291 c.big_diff = True
290 else:
292 else:
291 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
293 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
292 format='gitdiff')
294 format='gitdiff')
293 c.cur_diff = diff.as_html()
295 c.cur_diff = diff.as_html()
294 else:
296 else:
295
297
296 #default option
298 #default option
297 if node1.is_binary or node2.is_binary:
299 if node1.is_binary or node2.is_binary:
298 c.cur_diff = _('Binary file')
300 c.cur_diff = _('Binary file')
299 elif node1.size > self.cut_off_limit or \
301 elif node1.size > self.cut_off_limit or \
300 node2.size > self.cut_off_limit:
302 node2.size > self.cut_off_limit:
301 c.cur_diff = _('Diff is too big to display')
303 c.cur_diff = ''
304 c.big_diff = True
305
302 else:
306 else:
303 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
307 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
304 format='gitdiff')
308 format='gitdiff')
305 c.cur_diff = diff.as_html()
309 c.cur_diff = diff.as_html()
306
310
307 if not c.cur_diff:
311 if not c.cur_diff and not c.big_diff:
308 c.no_changes = True
312 c.no_changes = True
309 return render('files/file_diff.html')
313 return render('files/file_diff.html')
310
314
311 def _get_node_history(self, cs, f_path):
315 def _get_node_history(self, cs, f_path):
312 changesets = cs.get_file_history(f_path)
316 changesets = cs.get_file_history(f_path)
313 hist_l = []
317 hist_l = []
314
318
315 changesets_group = ([], _("Changesets"))
319 changesets_group = ([], _("Changesets"))
316 branches_group = ([], _("Branches"))
320 branches_group = ([], _("Branches"))
317 tags_group = ([], _("Tags"))
321 tags_group = ([], _("Tags"))
318
322
319 for chs in changesets:
323 for chs in changesets:
320 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
324 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
321 changesets_group[0].append((chs.raw_id, n_desc,))
325 changesets_group[0].append((chs.raw_id, n_desc,))
322
326
323 hist_l.append(changesets_group)
327 hist_l.append(changesets_group)
324
328
325 for name, chs in c.rhodecode_repo.branches.items():
329 for name, chs in c.rhodecode_repo.branches.items():
326 #chs = chs.split(':')[-1]
330 #chs = chs.split(':')[-1]
327 branches_group[0].append((chs, name),)
331 branches_group[0].append((chs, name),)
328 hist_l.append(branches_group)
332 hist_l.append(branches_group)
329
333
330 for name, chs in c.rhodecode_repo.tags.items():
334 for name, chs in c.rhodecode_repo.tags.items():
331 #chs = chs.split(':')[-1]
335 #chs = chs.split(':')[-1]
332 tags_group[0].append((chs, name),)
336 tags_group[0].append((chs, name),)
333 hist_l.append(tags_group)
337 hist_l.append(tags_group)
334
338
335 return hist_l
339 return hist_l
@@ -1,50 +1,53 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('File diff')} - ${c.rhodecode_name}
4 ${c.repo_name} ${_('File diff')} - ${c.rhodecode_name}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(u'Home',h.url('/'))}
8 ${h.link_to(u'Home',h.url('/'))}
9 &raquo;
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
11 &raquo;
11 &raquo;
12 ${_('File diff')} r${c.changeset_1.revision}:${h.short_id(c.changeset_1.raw_id)} &rarr; r${c.changeset_2.revision}:${h.short_id(c.changeset_2.raw_id)}
12 ${_('File diff')} r${c.changeset_1.revision}:${h.short_id(c.changeset_1.raw_id)} &rarr; r${c.changeset_2.revision}:${h.short_id(c.changeset_2.raw_id)}
13 </%def>
13 </%def>
14
14
15 <%def name="page_nav()">
15 <%def name="page_nav()">
16 ${self.menu('files')}
16 ${self.menu('files')}
17 </%def>
17 </%def>
18 <%def name="main()">
18 <%def name="main()">
19 <div class="box">
19 <div class="box">
20 <!-- box / title -->
20 <!-- box / title -->
21 <div class="title">
21 <div class="title">
22 ${self.breadcrumbs()}
22 ${self.breadcrumbs()}
23 </div>
23 </div>
24 <div class="table">
24 <div class="table">
25 <div id="body" class="diffblock">
25 <div id="body" class="diffblock">
26 <div class="code-header">
26 <div class="code-header">
27 <div class="changeset_header">
27 <div class="changeset_header">
28 <span class="changeset_file">${h.link_to(c.f_path,h.url('files_home',repo_name=c.repo_name,
28 <span class="changeset_file">${h.link_to(c.f_path,h.url('files_home',repo_name=c.repo_name,
29 revision=c.changeset_2.raw_id,f_path=c.f_path))}</span>
29 revision=c.changeset_2.raw_id,f_path=c.f_path))}</span>
30 &raquo; <span>${h.link_to(_('diff'),
30 &raquo; <span>${h.link_to(_('diff'),
31 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='diff'))}</span>
31 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='diff'))}</span>
32 &raquo; <span>${h.link_to(_('raw diff'),
32 &raquo; <span>${h.link_to(_('raw diff'),
33 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='raw'))}</span>
33 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='raw'))}</span>
34 &raquo; <span>${h.link_to(_('download diff'),
34 &raquo; <span>${h.link_to(_('download diff'),
35 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='download'))}</span>
35 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='download'))}</span>
36 </div>
36 </div>
37 </div>
37 </div>
38 <div class="code-body">
38 <div class="code-body">
39 %if c.no_changes:
39 %if c.no_changes:
40 ${_('No changes')}
40 ${_('No changes')}
41 %elif c.big_diff:
42 ${_('Diff is to big to display')} ${h.link_to(_('raw diff'),
43 h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='raw'))}
41 %else:
44 %else:
42 ${c.cur_diff|n}
45 ${c.cur_diff|n}
43 %endif
46 %endif
44 </div>
47 </div>
45 </div>
48 </div>
46 </div>
49 </div>
47 </div>
50 </div>
48 </%def>
51 </%def>
49
52
50 No newline at end of file
53
General Comments 0
You need to be logged in to leave comments. Login now