##// END OF EJS Templates
changed raw action to show images instead of saying about binary file...
marcink -
r1241:ed527052 beta
parent child Browse files
Show More
@@ -1,297 +1,334 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 rhodecode.lib.helpers as h
29 import rhodecode.lib.helpers as h
29
30
30 from pylons import request, response, session, tmpl_context as c, url
31 from pylons import request, response, session, tmpl_context as c, url
31 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
32 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
33
34
34 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
35 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
35 from rhodecode.lib.base import BaseRepoController, render
36 from rhodecode.lib.base import BaseRepoController, render
36 from rhodecode.lib.utils import EmptyChangeset
37 from rhodecode.lib.utils import EmptyChangeset
37 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo import RepoModel
38
39
39 from vcs.backends import ARCHIVE_SPECS
40 from vcs.backends import ARCHIVE_SPECS
40 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
41 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
41 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
42 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
42 from vcs.nodes import FileNode, NodeKind
43 from vcs.nodes import FileNode, NodeKind
43 from vcs.utils import diffs as differ
44 from vcs.utils import diffs as differ
44
45
45 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
46
47
47
48
48 class FilesController(BaseRepoController):
49 class FilesController(BaseRepoController):
49
50
50 @LoginRequired()
51 @LoginRequired()
51 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 'repository.admin')
53 'repository.admin')
53 def __before__(self):
54 def __before__(self):
54 super(FilesController, self).__before__()
55 super(FilesController, self).__before__()
55 c.cut_off_limit = self.cut_off_limit
56 c.cut_off_limit = self.cut_off_limit
56
57
57 def __get_cs_or_redirect(self, rev, repo_name):
58 def __get_cs_or_redirect(self, rev, repo_name):
58 """
59 """
59 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
60 proper message
61 proper message
61
62
62 :param rev: revision to fetch
63 :param rev: revision to fetch
63 :param repo_name: repo name to redirect after
64 :param repo_name: repo name to redirect after
64 """
65 """
65
66
66 try:
67 try:
67 return c.rhodecode_repo.get_changeset(rev)
68 return c.rhodecode_repo.get_changeset(rev)
68 except EmptyRepositoryError, e:
69 except EmptyRepositoryError, e:
69 h.flash(_('There are no files yet'), category='warning')
70 h.flash(_('There are no files yet'), category='warning')
70 redirect(h.url('summary_home', repo_name=repo_name))
71 redirect(h.url('summary_home', repo_name=repo_name))
71
72
72 except RepositoryError, e:
73 except RepositoryError, e:
73 h.flash(str(e), category='warning')
74 h.flash(str(e), category='warning')
74 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
75 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
75
76
76 def __get_filenode_or_redirect(self, repo_name, cs, path):
77 def __get_filenode_or_redirect(self, repo_name, cs, path):
77 """
78 """
78 Returns file_node, if error occurs or given path is directory,
79 Returns file_node, if error occurs or given path is directory,
79 it'll redirect to top level path
80 it'll redirect to top level path
80
81
81 :param repo_name: repo_name
82 :param repo_name: repo_name
82 :param cs: given changeset
83 :param cs: given changeset
83 :param path: path to lookup
84 :param path: path to lookup
84 """
85 """
85
86
86 try:
87 try:
87 file_node = cs.get_node(path)
88 file_node = cs.get_node(path)
88 if file_node.is_dir():
89 if file_node.is_dir():
89 raise RepositoryError('given path is a directory')
90 raise RepositoryError('given path is a directory')
90 except RepositoryError, e:
91 except RepositoryError, e:
91 h.flash(str(e), category='warning')
92 h.flash(str(e), category='warning')
92 redirect(h.url('files_home', repo_name=repo_name,
93 redirect(h.url('files_home', repo_name=repo_name,
93 revision=cs.raw_id))
94 revision=cs.raw_id))
94
95
95 return file_node
96 return file_node
96
97
97 def index(self, repo_name, revision, f_path):
98 def index(self, repo_name, revision, f_path):
98 #reditect to given revision from form if given
99 #reditect to given revision from form if given
99 post_revision = request.POST.get('at_rev', None)
100 post_revision = request.POST.get('at_rev', None)
100 if post_revision:
101 if post_revision:
101 cs = self.__get_cs_or_redirect(post_revision, repo_name)
102 cs = self.__get_cs_or_redirect(post_revision, repo_name)
102 redirect(url('files_home', repo_name=c.repo_name,
103 redirect(url('files_home', repo_name=c.repo_name,
103 revision=cs.raw_id, f_path=f_path))
104 revision=cs.raw_id, f_path=f_path))
104
105
105 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
106 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
106 c.branch = request.GET.get('branch', None)
107 c.branch = request.GET.get('branch', None)
107 c.f_path = f_path
108 c.f_path = f_path
108
109
109 cur_rev = c.changeset.revision
110 cur_rev = c.changeset.revision
110
111
111 #prev link
112 #prev link
112 try:
113 try:
113 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)
114 c.url_prev = url('files_home', repo_name=c.repo_name,
115 c.url_prev = url('files_home', repo_name=c.repo_name,
115 revision=prev_rev.raw_id, f_path=f_path)
116 revision=prev_rev.raw_id, f_path=f_path)
116 if c.branch:
117 if c.branch:
117 c.url_prev += '?branch=%s' % c.branch
118 c.url_prev += '?branch=%s' % c.branch
118 except (ChangesetDoesNotExistError, VCSError):
119 except (ChangesetDoesNotExistError, VCSError):
119 c.url_prev = '#'
120 c.url_prev = '#'
120
121
121 #next link
122 #next link
122 try:
123 try:
123 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)
124 c.url_next = url('files_home', repo_name=c.repo_name,
125 c.url_next = url('files_home', repo_name=c.repo_name,
125 revision=next_rev.raw_id, f_path=f_path)
126 revision=next_rev.raw_id, f_path=f_path)
126 if c.branch:
127 if c.branch:
127 c.url_next += '?branch=%s' % c.branch
128 c.url_next += '?branch=%s' % c.branch
128 except (ChangesetDoesNotExistError, VCSError):
129 except (ChangesetDoesNotExistError, VCSError):
129 c.url_next = '#'
130 c.url_next = '#'
130
131
131 #files or dirs
132 #files or dirs
132 try:
133 try:
133 c.files_list = c.changeset.get_node(f_path)
134 c.files_list = c.changeset.get_node(f_path)
134
135
135 if c.files_list.is_file():
136 if c.files_list.is_file():
136 c.file_history = self._get_node_history(c.changeset, f_path)
137 c.file_history = self._get_node_history(c.changeset, f_path)
137 else:
138 else:
138 c.file_history = []
139 c.file_history = []
139 except RepositoryError, e:
140 except RepositoryError, e:
140 h.flash(str(e), category='warning')
141 h.flash(str(e), category='warning')
141 redirect(h.url('files_home', repo_name=repo_name,
142 redirect(h.url('files_home', repo_name=repo_name,
142 revision=revision))
143 revision=revision))
143
144
144 return render('files/files.html')
145 return render('files/files.html')
145
146
146 def rawfile(self, repo_name, revision, f_path):
147 def rawfile(self, repo_name, revision, f_path):
147 cs = self.__get_cs_or_redirect(revision, repo_name)
148 cs = self.__get_cs_or_redirect(revision, repo_name)
148 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)
149
150
150 response.content_disposition = 'attachment; filename=%s' % \
151 response.content_disposition = 'attachment; filename=%s' % \
151 f_path.split(os.sep)[-1].encode('utf8', 'replace')
152 f_path.split(os.sep)[-1].encode('utf8', 'replace')
152
153
153 response.content_type = file_node.mimetype
154 response.content_type = file_node.mimetype
154 return file_node.content
155 return file_node.content
155
156
156 def raw(self, repo_name, revision, f_path):
157 def raw(self, repo_name, revision, f_path):
157 cs = self.__get_cs_or_redirect(revision, repo_name)
158 cs = self.__get_cs_or_redirect(revision, repo_name)
158 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)
159
160
160 response.content_type = 'text/plain'
161 raw_mimetype_mapping = {
162 # map original mimetype to a mimetype used for "show as raw"
163 # you can also provide a content-disposition to override the
164 # default "attachment" disposition.
165 # orig_type: (new_type, new_dispo)
166
167 # show images inline:
168 'image/x-icon': ('image/x-icon', 'inline'),
169 'image/png': ('image/png', 'inline'),
170 'image/gif': ('image/gif', 'inline'),
171 'image/jpeg': ('image/jpeg', 'inline'),
172 'image/svg+xml': ('image/svg+xml', 'inline'),
173 }
174
175 mimetype = file_node.mimetype
176 try:
177 mimetype, dispo = raw_mimetype_mapping[mimetype]
178 except KeyError:
179 # we don't know anything special about this, handle it safely
180 if file_node.is_binary:
181 # do same as download raw for binary files
182 mimetype, dispo = 'application/octet-stream', 'attachment'
183 else:
184 # do not just use the original mimetype, but force text/plain,
185 # otherwise it would serve text/html and that might be unsafe.
186 # Note: underlying vcs library fakes text/plain mimetype if the
187 # mimetype can not be determined and it thinks it is not binary.
188 # This might lead to erroneous text display in some cases, but
189 # helps in other cases, like with text files without extension.
190 mimetype, dispo = 'text/plain', 'inline'
191
192 if dispo == 'attachment':
193 dispo = 'attachment; filename=%s' % \
194 f_path.split(os.sep)[-1].encode('utf8', 'replace')
195
196 response.content_disposition = dispo
197 response.content_type = mimetype
161 return file_node.content
198 return file_node.content
162
199
163 def annotate(self, repo_name, revision, f_path):
200 def annotate(self, repo_name, revision, f_path):
164 c.cs = self.__get_cs_or_redirect(revision, repo_name)
201 c.cs = self.__get_cs_or_redirect(revision, repo_name)
165 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
202 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
166
203
167 c.file_history = self._get_node_history(c.cs, f_path)
204 c.file_history = self._get_node_history(c.cs, f_path)
168 c.f_path = f_path
205 c.f_path = f_path
169 return render('files/files_annotate.html')
206 return render('files/files_annotate.html')
170
207
171 def archivefile(self, repo_name, fname):
208 def archivefile(self, repo_name, fname):
172
209
173 fileformat = None
210 fileformat = None
174 revision = None
211 revision = None
175 ext = None
212 ext = None
176
213
177 for a_type, ext_data in ARCHIVE_SPECS.items():
214 for a_type, ext_data in ARCHIVE_SPECS.items():
178 archive_spec = fname.split(ext_data[1])
215 archive_spec = fname.split(ext_data[1])
179 if len(archive_spec) == 2 and archive_spec[1] == '':
216 if len(archive_spec) == 2 and archive_spec[1] == '':
180 fileformat = a_type or ext_data[1]
217 fileformat = a_type or ext_data[1]
181 revision = archive_spec[0]
218 revision = archive_spec[0]
182 ext = ext_data[1]
219 ext = ext_data[1]
183
220
184 try:
221 try:
185 dbrepo = RepoModel().get_by_repo_name(repo_name)
222 dbrepo = RepoModel().get_by_repo_name(repo_name)
186 if dbrepo.enable_downloads is False:
223 if dbrepo.enable_downloads is False:
187 return _('downloads disabled')
224 return _('downloads disabled')
188
225
189 cs = c.rhodecode_repo.get_changeset(revision)
226 cs = c.rhodecode_repo.get_changeset(revision)
190 content_type = ARCHIVE_SPECS[fileformat][0]
227 content_type = ARCHIVE_SPECS[fileformat][0]
191 except ChangesetDoesNotExistError:
228 except ChangesetDoesNotExistError:
192 return _('Unknown revision %s') % revision
229 return _('Unknown revision %s') % revision
193 except EmptyRepositoryError:
230 except EmptyRepositoryError:
194 return _('Empty repository')
231 return _('Empty repository')
195 except (ImproperArchiveTypeError, KeyError):
232 except (ImproperArchiveTypeError, KeyError):
196 return _('Unknown archive type')
233 return _('Unknown archive type')
197
234
198 response.content_type = content_type
235 response.content_type = content_type
199 response.content_disposition = 'attachment; filename=%s-%s%s' \
236 response.content_disposition = 'attachment; filename=%s-%s%s' \
200 % (repo_name, revision, ext)
237 % (repo_name, revision, ext)
201
238
202 return cs.get_chunked_archive(stream=None, kind=fileformat)
239 return cs.get_chunked_archive(stream=None, kind=fileformat)
203
240
204 def diff(self, repo_name, f_path):
241 def diff(self, repo_name, f_path):
205 diff1 = request.GET.get('diff1')
242 diff1 = request.GET.get('diff1')
206 diff2 = request.GET.get('diff2')
243 diff2 = request.GET.get('diff2')
207 c.action = request.GET.get('diff')
244 c.action = request.GET.get('diff')
208 c.no_changes = diff1 == diff2
245 c.no_changes = diff1 == diff2
209 c.f_path = f_path
246 c.f_path = f_path
210
247
211 try:
248 try:
212 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
249 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
213 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
250 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
214 node1 = c.changeset_1.get_node(f_path)
251 node1 = c.changeset_1.get_node(f_path)
215 else:
252 else:
216 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
253 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
217 node1 = FileNode('.', '', changeset=c.changeset_1)
254 node1 = FileNode('.', '', changeset=c.changeset_1)
218
255
219 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
256 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
220 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
257 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
221 node2 = c.changeset_2.get_node(f_path)
258 node2 = c.changeset_2.get_node(f_path)
222 else:
259 else:
223 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
260 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
224 node2 = FileNode('.', '', changeset=c.changeset_2)
261 node2 = FileNode('.', '', changeset=c.changeset_2)
225 except RepositoryError:
262 except RepositoryError:
226 return redirect(url('files_home',
263 return redirect(url('files_home',
227 repo_name=c.repo_name, f_path=f_path))
264 repo_name=c.repo_name, f_path=f_path))
228
265
229 if c.action == 'download':
266 if c.action == 'download':
230 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
267 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
231 format='gitdiff')
268 format='gitdiff')
232
269
233 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
270 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
234 response.content_type = 'text/plain'
271 response.content_type = 'text/plain'
235 response.content_disposition = 'attachment; filename=%s' \
272 response.content_disposition = 'attachment; filename=%s' \
236 % diff_name
273 % diff_name
237 return diff.raw_diff()
274 return diff.raw_diff()
238
275
239 elif c.action == 'raw':
276 elif c.action == 'raw':
240 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
277 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
241 format='gitdiff')
278 format='gitdiff')
242 response.content_type = 'text/plain'
279 response.content_type = 'text/plain'
243 return diff.raw_diff()
280 return diff.raw_diff()
244
281
245 elif c.action == 'diff':
282 elif c.action == 'diff':
246
283
247 if node1.is_binary or node2.is_binary:
284 if node1.is_binary or node2.is_binary:
248 c.cur_diff = _('Binary file')
285 c.cur_diff = _('Binary file')
249 elif node1.size > self.cut_off_limit or \
286 elif node1.size > self.cut_off_limit or \
250 node2.size > self.cut_off_limit:
287 node2.size > self.cut_off_limit:
251 c.cur_diff = _('Diff is too big to display')
288 c.cur_diff = _('Diff is too big to display')
252 else:
289 else:
253 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
290 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
254 format='gitdiff')
291 format='gitdiff')
255 c.cur_diff = diff.as_html()
292 c.cur_diff = diff.as_html()
256 else:
293 else:
257
294
258 #default option
295 #default option
259 if node1.is_binary or node2.is_binary:
296 if node1.is_binary or node2.is_binary:
260 c.cur_diff = _('Binary file')
297 c.cur_diff = _('Binary file')
261 elif node1.size > self.cut_off_limit or \
298 elif node1.size > self.cut_off_limit or \
262 node2.size > self.cut_off_limit:
299 node2.size > self.cut_off_limit:
263 c.cur_diff = _('Diff is too big to display')
300 c.cur_diff = _('Diff is too big to display')
264 else:
301 else:
265 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
302 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
266 format='gitdiff')
303 format='gitdiff')
267 c.cur_diff = diff.as_html()
304 c.cur_diff = diff.as_html()
268
305
269 if not c.cur_diff:
306 if not c.cur_diff:
270 c.no_changes = True
307 c.no_changes = True
271 return render('files/file_diff.html')
308 return render('files/file_diff.html')
272
309
273 def _get_node_history(self, cs, f_path):
310 def _get_node_history(self, cs, f_path):
274 changesets = cs.get_file_history(f_path)
311 changesets = cs.get_file_history(f_path)
275 hist_l = []
312 hist_l = []
276
313
277 changesets_group = ([], _("Changesets"))
314 changesets_group = ([], _("Changesets"))
278 branches_group = ([], _("Branches"))
315 branches_group = ([], _("Branches"))
279 tags_group = ([], _("Tags"))
316 tags_group = ([], _("Tags"))
280
317
281 for chs in changesets:
318 for chs in changesets:
282 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
319 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
283 changesets_group[0].append((chs.raw_id, n_desc,))
320 changesets_group[0].append((chs.raw_id, n_desc,))
284
321
285 hist_l.append(changesets_group)
322 hist_l.append(changesets_group)
286
323
287 for name, chs in c.rhodecode_repo.branches.items():
324 for name, chs in c.rhodecode_repo.branches.items():
288 #chs = chs.split(':')[-1]
325 #chs = chs.split(':')[-1]
289 branches_group[0].append((chs, name),)
326 branches_group[0].append((chs, name),)
290 hist_l.append(branches_group)
327 hist_l.append(branches_group)
291
328
292 for name, chs in c.rhodecode_repo.tags.items():
329 for name, chs in c.rhodecode_repo.tags.items():
293 #chs = chs.split(':')[-1]
330 #chs = chs.split(':')[-1]
294 tags_group[0].append((chs, name),)
331 tags_group[0].append((chs, name),)
295 hist_l.append(tags_group)
332 hist_l.append(tags_group)
296
333
297 return hist_l
334 return hist_l
@@ -1,91 +1,91 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 annotate')} - ${c.rhodecode_name}
4 ${c.repo_name} ${_('File annotate')} - ${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 ${_('annotate')} @ R${c.cs.revision}:${h.short_id(c.cs.raw_id)}
12 ${_('annotate')} @ R${c.cs.revision}:${h.short_id(c.cs.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 <ul class="links">
23 <ul class="links">
24 <li>
24 <li>
25 <span style="text-transform: uppercase;"><a href="#">${_('branch')}: ${c.cs.branch}</a></span>
25 <span style="text-transform: uppercase;"><a href="#">${_('branch')}: ${c.cs.branch}</a></span>
26 </li>
26 </li>
27 </ul>
27 </ul>
28 </div>
28 </div>
29 <div class="table">
29 <div class="table">
30 <div id="files_data">
30 <div id="files_data">
31 <h3 class="files_location">${_('Location')}: ${h.files_breadcrumbs(c.repo_name,c.cs.revision,c.file.path)}</h3>
31 <h3 class="files_location">${_('Location')}: ${h.files_breadcrumbs(c.repo_name,c.cs.revision,c.file.path)}</h3>
32 <dl class="overview">
32 <dl class="overview">
33 <dt>${_('Revision')}</dt>
33 <dt>${_('Revision')}</dt>
34 <dd>${h.link_to("r%s:%s" % (c.file.last_changeset.revision,h.short_id(c.file.last_changeset.raw_id)),
34 <dd>${h.link_to("r%s:%s" % (c.file.last_changeset.revision,h.short_id(c.file.last_changeset.raw_id)),
35 h.url('changeset_home',repo_name=c.repo_name,revision=c.file.last_changeset.raw_id))} </dd>
35 h.url('changeset_home',repo_name=c.repo_name,revision=c.file.last_changeset.raw_id))} </dd>
36 <dt>${_('Size')}</dt>
36 <dt>${_('Size')}</dt>
37 <dd>${h.format_byte_size(c.file.size,binary=True)}</dd>
37 <dd>${h.format_byte_size(c.file.size,binary=True)}</dd>
38 <dt>${_('Mimetype')}</dt>
38 <dt>${_('Mimetype')}</dt>
39 <dd>${c.file.mimetype}</dd>
39 <dd>${c.file.mimetype}</dd>
40 <dt>${_('Options')}</dt>
40 <dt>${_('Options')}</dt>
41 <dd>${h.link_to(_('show source'),
41 <dd>${h.link_to(_('show source'),
42 h.url('files_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
42 h.url('files_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
43 / ${h.link_to(_('show as raw'),
43 / ${h.link_to(_('show as raw'),
44 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
44 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
45 / ${h.link_to(_('download as raw'),
45 / ${h.link_to(_('download as raw'),
46 h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
46 h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
47 </dd>
47 </dd>
48 <dt>${_('History')}</dt>
48 <dt>${_('History')}</dt>
49 <dd>
49 <dd>
50 <div>
50 <div>
51 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
51 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
52 ${h.hidden('diff2',c.file.last_changeset.raw_id)}
52 ${h.hidden('diff2',c.file.last_changeset.raw_id)}
53 ${h.select('diff1',c.file.last_changeset.raw_id,c.file_history)}
53 ${h.select('diff1',c.file.last_changeset.raw_id,c.file_history)}
54 ${h.submit('diff','diff to revision',class_="ui-button")}
54 ${h.submit('diff','diff to revision',class_="ui-button")}
55 ${h.submit('show_rev','show at revision',class_="ui-button")}
55 ${h.submit('show_rev','show at revision',class_="ui-button")}
56 ${h.end_form()}
56 ${h.end_form()}
57 </div>
57 </div>
58 </dd>
58 </dd>
59 </dl>
59 </dl>
60 <div id="body" class="codeblock">
60 <div id="body" class="codeblock">
61 <div class="code-header">
61 <div class="code-header">
62 <div class="revision">${c.file.name}@r${c.file.last_changeset.revision}:${h.short_id(c.file.last_changeset.raw_id)}</div>
62 <div class="revision">${c.file.name}@r${c.file.last_changeset.revision}:${h.short_id(c.file.last_changeset.raw_id)}</div>
63 <div class="commit">"${c.file.message}"</div>
63 <div class="commit">"${c.file.message}"</div>
64 </div>
64 </div>
65 <div class="code-body">
65 <div class="code-body">
66 %if c.file.is_binary:
66 %if c.file.is_binary:
67 ${_('Binary file')}
67 ${_('Binary file (%s)') % c.file.mimetype}
68 %else:
68 %else:
69 % if c.file.size < c.cut_off_limit:
69 % if c.file.size < c.cut_off_limit:
70 ${h.pygmentize_annotation(c.repo_name,c.file,linenos=True,anchorlinenos=True,lineanchors='S',cssclass="code-highlight")}
70 ${h.pygmentize_annotation(c.repo_name,c.file,linenos=True,anchorlinenos=True,lineanchors='S',cssclass="code-highlight")}
71 %else:
71 %else:
72 ${_('File is to big to display')} ${h.link_to(_('show as raw'),
72 ${_('File is to big to display')} ${h.link_to(_('show as raw'),
73 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cs.revision,f_path=c.f_path))}
73 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cs.revision,f_path=c.f_path))}
74 %endif
74 %endif
75 <script type="text/javascript">
75 <script type="text/javascript">
76 YAHOO.util.Event.onDOMReady(function(){
76 YAHOO.util.Event.onDOMReady(function(){
77 YAHOO.util.Event.addListener('show_rev','click',function(e){
77 YAHOO.util.Event.addListener('show_rev','click',function(e){
78 YAHOO.util.Event.preventDefault(e);
78 YAHOO.util.Event.preventDefault(e);
79 var cs = YAHOO.util.Dom.get('diff1').value;
79 var cs = YAHOO.util.Dom.get('diff1').value;
80 var url = "${h.url('files_annotate_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
80 var url = "${h.url('files_annotate_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
81 window.location = url;
81 window.location = url;
82 });
82 });
83 });
83 });
84 </script>
84 </script>
85 %endif
85 %endif
86 </div>
86 </div>
87 </div>
87 </div>
88 </div>
88 </div>
89 </div>
89 </div>
90 </div>
90 </div>
91 </%def> No newline at end of file
91 </%def>
@@ -1,91 +1,91 b''
1 <dl>
1 <dl>
2 <dt>${_('Revision')}</dt>
2 <dt>${_('Revision')}</dt>
3 <dd>
3 <dd>
4 ${h.link_to("r%s:%s" % (c.files_list.last_changeset.revision,h.short_id(c.files_list.last_changeset.raw_id)),
4 ${h.link_to("r%s:%s" % (c.files_list.last_changeset.revision,h.short_id(c.files_list.last_changeset.raw_id)),
5 h.url('changeset_home',repo_name=c.repo_name,revision=c.files_list.last_changeset.raw_id))}
5 h.url('changeset_home',repo_name=c.repo_name,revision=c.files_list.last_changeset.raw_id))}
6 </dd>
6 </dd>
7 <dt>${_('Size')}</dt>
7 <dt>${_('Size')}</dt>
8 <dd>${h.format_byte_size(c.files_list.size,binary=True)}</dd>
8 <dd>${h.format_byte_size(c.files_list.size,binary=True)}</dd>
9 <dt>${_('Mimetype')}</dt>
9 <dt>${_('Mimetype')}</dt>
10 <dd>${c.files_list.mimetype}</dd>
10 <dd>${c.files_list.mimetype}</dd>
11 <dt>${_('Options')}</dt>
11 <dt>${_('Options')}</dt>
12 <dd>${h.link_to(_('show annotation'),
12 <dd>${h.link_to(_('show annotation'),
13 h.url('files_annotate_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
13 h.url('files_annotate_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
14 / ${h.link_to(_('show as raw'),
14 / ${h.link_to(_('show as raw'),
15 h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
15 h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
16 / ${h.link_to(_('download as raw'),
16 / ${h.link_to(_('download as raw'),
17 h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
17 h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
18 </dd>
18 </dd>
19 <dt>${_('History')}</dt>
19 <dt>${_('History')}</dt>
20 <dd>
20 <dd>
21 <div>
21 <div>
22 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
22 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
23 ${h.hidden('diff2',c.files_list.last_changeset.raw_id)}
23 ${h.hidden('diff2',c.files_list.last_changeset.raw_id)}
24 ${h.select('diff1',c.files_list.last_changeset.raw_id,c.file_history)}
24 ${h.select('diff1',c.files_list.last_changeset.raw_id,c.file_history)}
25 ${h.submit('diff','diff to revision',class_="ui-button")}
25 ${h.submit('diff','diff to revision',class_="ui-button")}
26 ${h.submit('show_rev','show at revision',class_="ui-button")}
26 ${h.submit('show_rev','show at revision',class_="ui-button")}
27 ${h.end_form()}
27 ${h.end_form()}
28 </div>
28 </div>
29 </dd>
29 </dd>
30 </dl>
30 </dl>
31
31
32
32
33 <div id="body" class="codeblock">
33 <div id="body" class="codeblock">
34 <div class="code-header">
34 <div class="code-header">
35 <div class="revision">${c.files_list.name}@r${c.files_list.last_changeset.revision}:${h.short_id(c.files_list.last_changeset.raw_id)}</div>
35 <div class="revision">${c.files_list.name}@r${c.files_list.last_changeset.revision}:${h.short_id(c.files_list.last_changeset.raw_id)}</div>
36 <div class="commit">"${c.files_list.last_changeset.message}"</div>
36 <div class="commit">"${c.files_list.last_changeset.message}"</div>
37 </div>
37 </div>
38 <div class="code-body">
38 <div class="code-body">
39 %if c.files_list.is_binary:
39 %if c.files_list.is_binary:
40 ${_('Binary file')}
40 ${_('Binary file (%s)') % c.files_list.mimetype}
41 %else:
41 %else:
42 % if c.files_list.size < c.cut_off_limit:
42 % if c.files_list.size < c.cut_off_limit:
43 ${h.pygmentize(c.files_list,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
43 ${h.pygmentize(c.files_list,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
44 %else:
44 %else:
45 ${_('File is to big to display')} ${h.link_to(_('show as raw'),
45 ${_('File is to big to display')} ${h.link_to(_('show as raw'),
46 h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
46 h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
47 %endif
47 %endif
48
48
49 <script type="text/javascript">
49 <script type="text/javascript">
50 function highlight_lines(lines){
50 function highlight_lines(lines){
51 for(pos in lines){
51 for(pos in lines){
52 YUD.setStyle('L'+lines[pos],'background-color','#FFFFBE');
52 YUD.setStyle('L'+lines[pos],'background-color','#FFFFBE');
53 }
53 }
54 }
54 }
55 page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
55 page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
56 if (page_highlights.length == 2){
56 if (page_highlights.length == 2){
57 highlight_ranges = page_highlights[1].split(",");
57 highlight_ranges = page_highlights[1].split(",");
58
58
59 var h_lines = [];
59 var h_lines = [];
60 for (pos in highlight_ranges){
60 for (pos in highlight_ranges){
61 var _range = highlight_ranges[pos].split('-');
61 var _range = highlight_ranges[pos].split('-');
62 if(_range.length == 2){
62 if(_range.length == 2){
63 var start = parseInt(_range[0]);
63 var start = parseInt(_range[0]);
64 var end = parseInt(_range[1]);
64 var end = parseInt(_range[1]);
65 if (start < end){
65 if (start < end){
66 for(var i=start;i<=end;i++){
66 for(var i=start;i<=end;i++){
67 h_lines.push(i);
67 h_lines.push(i);
68 }
68 }
69 }
69 }
70 }
70 }
71 else{
71 else{
72 h_lines.push(parseInt(highlight_ranges[pos]));
72 h_lines.push(parseInt(highlight_ranges[pos]));
73 }
73 }
74 }
74 }
75 highlight_lines(h_lines);
75 highlight_lines(h_lines);
76 }
76 }
77 </script>
77 </script>
78 %endif
78 %endif
79 </div>
79 </div>
80 </div>
80 </div>
81
81
82 <script type="text/javascript">
82 <script type="text/javascript">
83 YAHOO.util.Event.onDOMReady(function(){
83 YAHOO.util.Event.onDOMReady(function(){
84 YAHOO.util.Event.addListener('show_rev','click',function(e){
84 YAHOO.util.Event.addListener('show_rev','click',function(e){
85 YAHOO.util.Event.preventDefault(e);
85 YAHOO.util.Event.preventDefault(e);
86 var cs = YAHOO.util.Dom.get('diff1').value;
86 var cs = YAHOO.util.Dom.get('diff1').value;
87 var url = "${h.url('files_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
87 var url = "${h.url('files_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
88 window.location = url;
88 window.location = url;
89 });
89 });
90 });
90 });
91 </script> No newline at end of file
91 </script>
General Comments 0
You need to be logged in to leave comments. Login now