##// END OF EJS Templates
fixed key error on unknown archival
marcink -
r950:343c28c3 beta
parent child Browse files
Show More
@@ -1,267 +1,267 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 import tempfile
27 import tempfile
28 import logging
28 import logging
29 import rhodecode.lib.helpers as h
29 import rhodecode.lib.helpers as h
30
30
31 from mercurial import archival
31 from mercurial import archival
32
32
33 from pylons import request, response, session, tmpl_context as c, url
33 from pylons import request, response, session, tmpl_context as c, url
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35 from pylons.controllers.util import redirect
35 from pylons.controllers.util import redirect
36
36
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 from rhodecode.lib.base import BaseController, render
38 from rhodecode.lib.base import BaseController, render
39 from rhodecode.lib.utils import EmptyChangeset
39 from rhodecode.lib.utils import EmptyChangeset
40 from rhodecode.model.scm import ScmModel
40 from rhodecode.model.scm import ScmModel
41
41
42 from vcs.backends import ARCHIVE_SPECS
42 from vcs.backends import ARCHIVE_SPECS
43 from vcs.exceptions import RepositoryError, ChangesetError, \
43 from vcs.exceptions import RepositoryError, ChangesetError, \
44 ChangesetDoesNotExistError, EmptyRepositoryError, InproperArchiveTypeError
44 ChangesetDoesNotExistError, EmptyRepositoryError, InproperArchiveTypeError
45 from vcs.nodes import FileNode
45 from vcs.nodes import FileNode
46 from vcs.utils import diffs as differ
46 from vcs.utils import diffs as differ
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50 class FilesController(BaseController):
50 class FilesController(BaseController):
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 index(self, repo_name, revision, f_path):
59 def index(self, repo_name, revision, f_path):
60 hg_model = ScmModel()
60 hg_model = ScmModel()
61 c.repo = hg_model.get_repo(c.repo_name)
61 c.repo = hg_model.get_repo(c.repo_name)
62
62
63 try:
63 try:
64 #reditect to given revision from form
64 #reditect to given revision from form
65 post_revision = request.POST.get('at_rev', None)
65 post_revision = request.POST.get('at_rev', None)
66 if post_revision:
66 if post_revision:
67 post_revision = c.repo.get_changeset(post_revision).raw_id
67 post_revision = c.repo.get_changeset(post_revision).raw_id
68 redirect(url('files_home', repo_name=c.repo_name,
68 redirect(url('files_home', repo_name=c.repo_name,
69 revision=post_revision, f_path=f_path))
69 revision=post_revision, f_path=f_path))
70
70
71 c.branch = request.GET.get('branch', None)
71 c.branch = request.GET.get('branch', None)
72
72
73 c.f_path = f_path
73 c.f_path = f_path
74
74
75 c.changeset = c.repo.get_changeset(revision)
75 c.changeset = c.repo.get_changeset(revision)
76 cur_rev = c.changeset.revision
76 cur_rev = c.changeset.revision
77
77
78 #prev link
78 #prev link
79 try:
79 try:
80 prev_rev = c.repo.get_changeset(cur_rev).prev(c.branch).raw_id
80 prev_rev = c.repo.get_changeset(cur_rev).prev(c.branch).raw_id
81 c.url_prev = url('files_home', repo_name=c.repo_name,
81 c.url_prev = url('files_home', repo_name=c.repo_name,
82 revision=prev_rev, f_path=f_path)
82 revision=prev_rev, f_path=f_path)
83 if c.branch:
83 if c.branch:
84 c.url_prev += '?branch=%s' % c.branch
84 c.url_prev += '?branch=%s' % c.branch
85 except ChangesetDoesNotExistError:
85 except ChangesetDoesNotExistError:
86 c.url_prev = '#'
86 c.url_prev = '#'
87
87
88 #next link
88 #next link
89 try:
89 try:
90 next_rev = c.repo.get_changeset(cur_rev).next(c.branch).raw_id
90 next_rev = c.repo.get_changeset(cur_rev).next(c.branch).raw_id
91 c.url_next = url('files_home', repo_name=c.repo_name,
91 c.url_next = url('files_home', repo_name=c.repo_name,
92 revision=next_rev, f_path=f_path)
92 revision=next_rev, f_path=f_path)
93 if c.branch:
93 if c.branch:
94 c.url_next += '?branch=%s' % c.branch
94 c.url_next += '?branch=%s' % c.branch
95 except ChangesetDoesNotExistError:
95 except ChangesetDoesNotExistError:
96 c.url_next = '#'
96 c.url_next = '#'
97
97
98 #files
98 #files
99 try:
99 try:
100 c.files_list = c.changeset.get_node(f_path)
100 c.files_list = c.changeset.get_node(f_path)
101 c.file_history = self._get_history(c.repo, c.files_list, f_path)
101 c.file_history = self._get_history(c.repo, c.files_list, f_path)
102 except RepositoryError, e:
102 except RepositoryError, e:
103 h.flash(str(e), category='warning')
103 h.flash(str(e), category='warning')
104 redirect(h.url('files_home', repo_name=repo_name, revision=revision))
104 redirect(h.url('files_home', repo_name=repo_name, revision=revision))
105
105
106 except EmptyRepositoryError, e:
106 except EmptyRepositoryError, e:
107 h.flash(_('There are no files yet'), category='warning')
107 h.flash(_('There are no files yet'), category='warning')
108 redirect(h.url('summary_home', repo_name=repo_name))
108 redirect(h.url('summary_home', repo_name=repo_name))
109
109
110 except RepositoryError, e:
110 except RepositoryError, e:
111 h.flash(str(e), category='warning')
111 h.flash(str(e), category='warning')
112 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
112 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
113
113
114
114
115
115
116 return render('files/files.html')
116 return render('files/files.html')
117
117
118 def rawfile(self, repo_name, revision, f_path):
118 def rawfile(self, repo_name, revision, f_path):
119 hg_model = ScmModel()
119 hg_model = ScmModel()
120 c.repo = hg_model.get_repo(c.repo_name)
120 c.repo = hg_model.get_repo(c.repo_name)
121 file_node = c.repo.get_changeset(revision).get_node(f_path)
121 file_node = c.repo.get_changeset(revision).get_node(f_path)
122 response.content_type = file_node.mimetype
122 response.content_type = file_node.mimetype
123 response.content_disposition = 'attachment; filename=%s' \
123 response.content_disposition = 'attachment; filename=%s' \
124 % f_path.split('/')[-1]
124 % f_path.split('/')[-1]
125 return file_node.content
125 return file_node.content
126
126
127 def raw(self, repo_name, revision, f_path):
127 def raw(self, repo_name, revision, f_path):
128 hg_model = ScmModel()
128 hg_model = ScmModel()
129 c.repo = hg_model.get_repo(c.repo_name)
129 c.repo = hg_model.get_repo(c.repo_name)
130 file_node = c.repo.get_changeset(revision).get_node(f_path)
130 file_node = c.repo.get_changeset(revision).get_node(f_path)
131 response.content_type = 'text/plain'
131 response.content_type = 'text/plain'
132
132
133 return file_node.content
133 return file_node.content
134
134
135 def annotate(self, repo_name, revision, f_path):
135 def annotate(self, repo_name, revision, f_path):
136 hg_model = ScmModel()
136 hg_model = ScmModel()
137 c.repo = hg_model.get_repo(c.repo_name)
137 c.repo = hg_model.get_repo(c.repo_name)
138
138
139 try:
139 try:
140 c.cs = c.repo.get_changeset(revision)
140 c.cs = c.repo.get_changeset(revision)
141 c.file = c.cs.get_node(f_path)
141 c.file = c.cs.get_node(f_path)
142 except RepositoryError, e:
142 except RepositoryError, e:
143 h.flash(str(e), category='warning')
143 h.flash(str(e), category='warning')
144 redirect(h.url('files_home', repo_name=repo_name, revision=revision))
144 redirect(h.url('files_home', repo_name=repo_name, revision=revision))
145
145
146 c.file_history = self._get_history(c.repo, c.file, f_path)
146 c.file_history = self._get_history(c.repo, c.file, f_path)
147
147
148 c.f_path = f_path
148 c.f_path = f_path
149
149
150 return render('files/files_annotate.html')
150 return render('files/files_annotate.html')
151
151
152 def archivefile(self, repo_name, fname):
152 def archivefile(self, repo_name, fname):
153
153
154 fileformat = None
154 fileformat = None
155 revision = None
155 revision = None
156 ext = None
156 ext = None
157
157
158 for a_type, ext_data in ARCHIVE_SPECS.items():
158 for a_type, ext_data in ARCHIVE_SPECS.items():
159 archive_spec = fname.split(ext_data[1])
159 archive_spec = fname.split(ext_data[1])
160 if len(archive_spec) == 2 and archive_spec[1] == '':
160 if len(archive_spec) == 2 and archive_spec[1] == '':
161 fileformat = a_type or ext_data[1]
161 fileformat = a_type or ext_data[1]
162 revision = archive_spec[0]
162 revision = archive_spec[0]
163 ext = ext_data[1]
163 ext = ext_data[1]
164
164
165 try:
165 try:
166 repo = ScmModel().get_repo(repo_name)
166 repo = ScmModel().get_repo(repo_name)
167 cs = repo.get_changeset(revision)
167 cs = repo.get_changeset(revision)
168 content_type = ARCHIVE_SPECS[fileformat][0]
168 except ChangesetDoesNotExistError:
169 except ChangesetDoesNotExistError:
169 return _('Unknown revision %s') % revision
170 return _('Unknown revision %s') % revision
170 except EmptyRepositoryError:
171 except EmptyRepositoryError:
171 return _('Empty repository')
172 return _('Empty repository')
172 except InproperArchiveTypeError:
173 except (InproperArchiveTypeError, KeyError):
173 return _('Unknown archive type')
174 return _('Unknown archive type')
174
175
175 fname = '%s-%s%s' % (repo_name, revision, ext)
176 response.content_type = content_type
176
177 response.content_disposition = 'attachment; filename=%s-%s%s' \
177 response.content_type = ARCHIVE_SPECS[fileformat][0]
178 % (repo_name, revision, ext)
178 response.content_disposition = 'attachment; filename=%s' % fname
179
179
180 return cs.get_chunked_archive(kind=fileformat)
180 return cs.get_chunked_archive(kind=fileformat)
181
181
182
182
183 def diff(self, repo_name, f_path):
183 def diff(self, repo_name, f_path):
184 hg_model = ScmModel()
184 hg_model = ScmModel()
185 diff1 = request.GET.get('diff1')
185 diff1 = request.GET.get('diff1')
186 diff2 = request.GET.get('diff2')
186 diff2 = request.GET.get('diff2')
187 c.action = request.GET.get('diff')
187 c.action = request.GET.get('diff')
188 c.no_changes = diff1 == diff2
188 c.no_changes = diff1 == diff2
189 c.f_path = f_path
189 c.f_path = f_path
190 c.repo = hg_model.get_repo(c.repo_name)
190 c.repo = hg_model.get_repo(c.repo_name)
191
191
192 try:
192 try:
193 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
193 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
194 c.changeset_1 = c.repo.get_changeset(diff1)
194 c.changeset_1 = c.repo.get_changeset(diff1)
195 node1 = c.changeset_1.get_node(f_path)
195 node1 = c.changeset_1.get_node(f_path)
196 else:
196 else:
197 c.changeset_1 = EmptyChangeset()
197 c.changeset_1 = EmptyChangeset()
198 node1 = FileNode('.', '', changeset=c.changeset_1)
198 node1 = FileNode('.', '', changeset=c.changeset_1)
199
199
200 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
200 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
201 c.changeset_2 = c.repo.get_changeset(diff2)
201 c.changeset_2 = c.repo.get_changeset(diff2)
202 node2 = c.changeset_2.get_node(f_path)
202 node2 = c.changeset_2.get_node(f_path)
203 else:
203 else:
204 c.changeset_2 = EmptyChangeset()
204 c.changeset_2 = EmptyChangeset()
205 node2 = FileNode('.', '', changeset=c.changeset_2)
205 node2 = FileNode('.', '', changeset=c.changeset_2)
206 except RepositoryError:
206 except RepositoryError:
207 return redirect(url('files_home',
207 return redirect(url('files_home',
208 repo_name=c.repo_name, f_path=f_path))
208 repo_name=c.repo_name, f_path=f_path))
209
209
210 f_udiff = differ.get_udiff(node1, node2)
210 f_udiff = differ.get_udiff(node1, node2)
211 diff = differ.DiffProcessor(f_udiff)
211 diff = differ.DiffProcessor(f_udiff)
212
212
213 if c.action == 'download':
213 if c.action == 'download':
214 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
214 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
215 response.content_type = 'text/plain'
215 response.content_type = 'text/plain'
216 response.content_disposition = 'attachment; filename=%s' \
216 response.content_disposition = 'attachment; filename=%s' \
217 % diff_name
217 % diff_name
218 return diff.raw_diff()
218 return diff.raw_diff()
219
219
220 elif c.action == 'raw':
220 elif c.action == 'raw':
221 response.content_type = 'text/plain'
221 response.content_type = 'text/plain'
222 return diff.raw_diff()
222 return diff.raw_diff()
223
223
224 elif c.action == 'diff':
224 elif c.action == 'diff':
225 if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
225 if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
226 c.cur_diff = _('Diff is to big to display')
226 c.cur_diff = _('Diff is to big to display')
227 else:
227 else:
228 c.cur_diff = diff.as_html()
228 c.cur_diff = diff.as_html()
229 else:
229 else:
230 #default option
230 #default option
231 if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
231 if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
232 c.cur_diff = _('Diff is to big to display')
232 c.cur_diff = _('Diff is to big to display')
233 else:
233 else:
234 c.cur_diff = diff.as_html()
234 c.cur_diff = diff.as_html()
235
235
236 if not c.cur_diff: c.no_changes = True
236 if not c.cur_diff: c.no_changes = True
237 return render('files/file_diff.html')
237 return render('files/file_diff.html')
238
238
239 def _get_history(self, repo, node, f_path):
239 def _get_history(self, repo, node, f_path):
240 from vcs.nodes import NodeKind
240 from vcs.nodes import NodeKind
241 if not node.kind is NodeKind.FILE:
241 if not node.kind is NodeKind.FILE:
242 return []
242 return []
243 changesets = node.history
243 changesets = node.history
244 hist_l = []
244 hist_l = []
245
245
246 changesets_group = ([], _("Changesets"))
246 changesets_group = ([], _("Changesets"))
247 branches_group = ([], _("Branches"))
247 branches_group = ([], _("Branches"))
248 tags_group = ([], _("Tags"))
248 tags_group = ([], _("Tags"))
249
249
250 for chs in changesets:
250 for chs in changesets:
251 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
251 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
252 changesets_group[0].append((chs.raw_id, n_desc,))
252 changesets_group[0].append((chs.raw_id, n_desc,))
253
253
254 hist_l.append(changesets_group)
254 hist_l.append(changesets_group)
255
255
256 for name, chs in c.repository_branches.items():
256 for name, chs in c.repository_branches.items():
257 #chs = chs.split(':')[-1]
257 #chs = chs.split(':')[-1]
258 branches_group[0].append((chs, name),)
258 branches_group[0].append((chs, name),)
259 hist_l.append(branches_group)
259 hist_l.append(branches_group)
260
260
261 for name, chs in c.repository_tags.items():
261 for name, chs in c.repository_tags.items():
262 #chs = chs.split(':')[-1]
262 #chs = chs.split(':')[-1]
263 tags_group[0].append((chs, name),)
263 tags_group[0].append((chs, name),)
264 hist_l.append(tags_group)
264 hist_l.append(tags_group)
265
265
266 return hist_l
266 return hist_l
267
267
General Comments 0
You need to be logged in to leave comments. Login now