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