##// END OF EJS Templates
fixes for vcs settings module
marcink -
r1480:daa29da0 beta
parent child Browse files
Show More
@@ -1,447 +1,447 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 traceback
28 import traceback
29
29
30 from os.path import join as jn
30 from os.path import join as jn
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 from pylons.decorators import jsonify
35 from pylons.decorators import jsonify
36
36
37 from vcs.backends import ARCHIVE_SPECS
37 from vcs.conf import settings
38 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
38 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
39 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
39 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
40 from vcs.nodes import FileNode, NodeKind
40 from vcs.nodes import FileNode, NodeKind
41 from vcs.utils import diffs as differ
41 from vcs.utils import diffs as differ
42
42
43 from rhodecode.lib import convert_line_endings, detect_mode, safe_str
43 from rhodecode.lib import convert_line_endings, detect_mode, safe_str
44 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
44 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
45 from rhodecode.lib.base import BaseRepoController, render
45 from rhodecode.lib.base import BaseRepoController, render
46 from rhodecode.lib.utils import EmptyChangeset
46 from rhodecode.lib.utils import EmptyChangeset
47 import rhodecode.lib.helpers as h
47 import rhodecode.lib.helpers as h
48 from rhodecode.model.repo import RepoModel
48 from rhodecode.model.repo import RepoModel
49
49
50 log = logging.getLogger(__name__)
50 log = logging.getLogger(__name__)
51
51
52
52
53 class FilesController(BaseRepoController):
53 class FilesController(BaseRepoController):
54
54
55 @LoginRequired()
55 @LoginRequired()
56 def __before__(self):
56 def __before__(self):
57 super(FilesController, self).__before__()
57 super(FilesController, self).__before__()
58 c.cut_off_limit = self.cut_off_limit
58 c.cut_off_limit = self.cut_off_limit
59
59
60 def __get_cs_or_redirect(self, rev, repo_name):
60 def __get_cs_or_redirect(self, rev, repo_name):
61 """
61 """
62 Safe way to get changeset if error occur it redirects to tip with
62 Safe way to get changeset if error occur it redirects to tip with
63 proper message
63 proper message
64
64
65 :param rev: revision to fetch
65 :param rev: revision to fetch
66 :param repo_name: repo name to redirect after
66 :param repo_name: repo name to redirect after
67 """
67 """
68
68
69 try:
69 try:
70 return c.rhodecode_repo.get_changeset(rev)
70 return c.rhodecode_repo.get_changeset(rev)
71 except EmptyRepositoryError, e:
71 except EmptyRepositoryError, e:
72 h.flash(_('There are no files yet'), category='warning')
72 h.flash(_('There are no files yet'), category='warning')
73 redirect(h.url('summary_home', repo_name=repo_name))
73 redirect(h.url('summary_home', repo_name=repo_name))
74
74
75 except RepositoryError, e:
75 except RepositoryError, e:
76 h.flash(str(e), category='warning')
76 h.flash(str(e), category='warning')
77 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
77 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
78
78
79 def __get_filenode_or_redirect(self, repo_name, cs, path):
79 def __get_filenode_or_redirect(self, repo_name, cs, path):
80 """
80 """
81 Returns file_node, if error occurs or given path is directory,
81 Returns file_node, if error occurs or given path is directory,
82 it'll redirect to top level path
82 it'll redirect to top level path
83
83
84 :param repo_name: repo_name
84 :param repo_name: repo_name
85 :param cs: given changeset
85 :param cs: given changeset
86 :param path: path to lookup
86 :param path: path to lookup
87 """
87 """
88
88
89 try:
89 try:
90 file_node = cs.get_node(path)
90 file_node = cs.get_node(path)
91 if file_node.is_dir():
91 if file_node.is_dir():
92 raise RepositoryError('given path is a directory')
92 raise RepositoryError('given path is a directory')
93 except RepositoryError, e:
93 except RepositoryError, e:
94 h.flash(str(e), category='warning')
94 h.flash(str(e), category='warning')
95 redirect(h.url('files_home', repo_name=repo_name,
95 redirect(h.url('files_home', repo_name=repo_name,
96 revision=cs.raw_id))
96 revision=cs.raw_id))
97
97
98 return file_node
98 return file_node
99
99
100
100
101 def __get_paths(self, changeset, starting_path):
101 def __get_paths(self, changeset, starting_path):
102 """recursive walk in root dir and return a set of all path in that dir
102 """recursive walk in root dir and return a set of all path in that dir
103 based on repository walk function
103 based on repository walk function
104 """
104 """
105 _files = list()
105 _files = list()
106 _dirs = list()
106 _dirs = list()
107
107
108 try:
108 try:
109 tip = changeset
109 tip = changeset
110 for topnode, dirs, files in tip.walk(starting_path):
110 for topnode, dirs, files in tip.walk(starting_path):
111 for f in files:
111 for f in files:
112 _files.append(f.path)
112 _files.append(f.path)
113 for d in dirs:
113 for d in dirs:
114 _dirs.append(d.path)
114 _dirs.append(d.path)
115 except RepositoryError, e:
115 except RepositoryError, e:
116 log.debug(traceback.format_exc())
116 log.debug(traceback.format_exc())
117 pass
117 pass
118 return _dirs, _files
118 return _dirs, _files
119
119
120 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
120 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
121 'repository.admin')
121 'repository.admin')
122 def index(self, repo_name, revision, f_path):
122 def index(self, repo_name, revision, f_path):
123 #reditect to given revision from form if given
123 #reditect to given revision from form if given
124 post_revision = request.POST.get('at_rev', None)
124 post_revision = request.POST.get('at_rev', None)
125 if post_revision:
125 if post_revision:
126 cs = self.__get_cs_or_redirect(post_revision, repo_name)
126 cs = self.__get_cs_or_redirect(post_revision, repo_name)
127 redirect(url('files_home', repo_name=c.repo_name,
127 redirect(url('files_home', repo_name=c.repo_name,
128 revision=cs.raw_id, f_path=f_path))
128 revision=cs.raw_id, f_path=f_path))
129
129
130 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
130 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
131 c.branch = request.GET.get('branch', None)
131 c.branch = request.GET.get('branch', None)
132 c.f_path = f_path
132 c.f_path = f_path
133
133
134 cur_rev = c.changeset.revision
134 cur_rev = c.changeset.revision
135
135
136 #prev link
136 #prev link
137 try:
137 try:
138 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
138 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
139 c.url_prev = url('files_home', repo_name=c.repo_name,
139 c.url_prev = url('files_home', repo_name=c.repo_name,
140 revision=prev_rev.raw_id, f_path=f_path)
140 revision=prev_rev.raw_id, f_path=f_path)
141 if c.branch:
141 if c.branch:
142 c.url_prev += '?branch=%s' % c.branch
142 c.url_prev += '?branch=%s' % c.branch
143 except (ChangesetDoesNotExistError, VCSError):
143 except (ChangesetDoesNotExistError, VCSError):
144 c.url_prev = '#'
144 c.url_prev = '#'
145
145
146 #next link
146 #next link
147 try:
147 try:
148 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
148 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
149 c.url_next = url('files_home', repo_name=c.repo_name,
149 c.url_next = url('files_home', repo_name=c.repo_name,
150 revision=next_rev.raw_id, f_path=f_path)
150 revision=next_rev.raw_id, f_path=f_path)
151 if c.branch:
151 if c.branch:
152 c.url_next += '?branch=%s' % c.branch
152 c.url_next += '?branch=%s' % c.branch
153 except (ChangesetDoesNotExistError, VCSError):
153 except (ChangesetDoesNotExistError, VCSError):
154 c.url_next = '#'
154 c.url_next = '#'
155
155
156 #files or dirs
156 #files or dirs
157 try:
157 try:
158 c.files_list = c.changeset.get_node(f_path)
158 c.files_list = c.changeset.get_node(f_path)
159
159
160 if c.files_list.is_file():
160 if c.files_list.is_file():
161 c.file_history = self._get_node_history(c.changeset, f_path)
161 c.file_history = self._get_node_history(c.changeset, f_path)
162 else:
162 else:
163 c.file_history = []
163 c.file_history = []
164 except RepositoryError, e:
164 except RepositoryError, e:
165 h.flash(str(e), category='warning')
165 h.flash(str(e), category='warning')
166 redirect(h.url('files_home', repo_name=repo_name,
166 redirect(h.url('files_home', repo_name=repo_name,
167 revision=revision))
167 revision=revision))
168
168
169 return render('files/files.html')
169 return render('files/files.html')
170
170
171 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
171 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
172 'repository.admin')
172 'repository.admin')
173 def rawfile(self, repo_name, revision, f_path):
173 def rawfile(self, repo_name, revision, f_path):
174 cs = self.__get_cs_or_redirect(revision, repo_name)
174 cs = self.__get_cs_or_redirect(revision, repo_name)
175 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
175 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
176
176
177 response.content_disposition = 'attachment; filename=%s' % \
177 response.content_disposition = 'attachment; filename=%s' % \
178 safe_str(f_path.split(os.sep)[-1])
178 safe_str(f_path.split(os.sep)[-1])
179
179
180 response.content_type = file_node.mimetype
180 response.content_type = file_node.mimetype
181 return file_node.content
181 return file_node.content
182
182
183 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
183 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
184 'repository.admin')
184 'repository.admin')
185 def raw(self, repo_name, revision, f_path):
185 def raw(self, repo_name, revision, f_path):
186 cs = self.__get_cs_or_redirect(revision, repo_name)
186 cs = self.__get_cs_or_redirect(revision, repo_name)
187 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
187 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
188
188
189 raw_mimetype_mapping = {
189 raw_mimetype_mapping = {
190 # map original mimetype to a mimetype used for "show as raw"
190 # map original mimetype to a mimetype used for "show as raw"
191 # you can also provide a content-disposition to override the
191 # you can also provide a content-disposition to override the
192 # default "attachment" disposition.
192 # default "attachment" disposition.
193 # orig_type: (new_type, new_dispo)
193 # orig_type: (new_type, new_dispo)
194
194
195 # show images inline:
195 # show images inline:
196 'image/x-icon': ('image/x-icon', 'inline'),
196 'image/x-icon': ('image/x-icon', 'inline'),
197 'image/png': ('image/png', 'inline'),
197 'image/png': ('image/png', 'inline'),
198 'image/gif': ('image/gif', 'inline'),
198 'image/gif': ('image/gif', 'inline'),
199 'image/jpeg': ('image/jpeg', 'inline'),
199 'image/jpeg': ('image/jpeg', 'inline'),
200 'image/svg+xml': ('image/svg+xml', 'inline'),
200 'image/svg+xml': ('image/svg+xml', 'inline'),
201 }
201 }
202
202
203 mimetype = file_node.mimetype
203 mimetype = file_node.mimetype
204 try:
204 try:
205 mimetype, dispo = raw_mimetype_mapping[mimetype]
205 mimetype, dispo = raw_mimetype_mapping[mimetype]
206 except KeyError:
206 except KeyError:
207 # we don't know anything special about this, handle it safely
207 # we don't know anything special about this, handle it safely
208 if file_node.is_binary:
208 if file_node.is_binary:
209 # do same as download raw for binary files
209 # do same as download raw for binary files
210 mimetype, dispo = 'application/octet-stream', 'attachment'
210 mimetype, dispo = 'application/octet-stream', 'attachment'
211 else:
211 else:
212 # do not just use the original mimetype, but force text/plain,
212 # do not just use the original mimetype, but force text/plain,
213 # otherwise it would serve text/html and that might be unsafe.
213 # otherwise it would serve text/html and that might be unsafe.
214 # Note: underlying vcs library fakes text/plain mimetype if the
214 # Note: underlying vcs library fakes text/plain mimetype if the
215 # mimetype can not be determined and it thinks it is not
215 # mimetype can not be determined and it thinks it is not
216 # binary.This might lead to erroneous text display in some
216 # binary.This might lead to erroneous text display in some
217 # cases, but helps in other cases, like with text files
217 # cases, but helps in other cases, like with text files
218 # without extension.
218 # without extension.
219 mimetype, dispo = 'text/plain', 'inline'
219 mimetype, dispo = 'text/plain', 'inline'
220
220
221 if dispo == 'attachment':
221 if dispo == 'attachment':
222 dispo = 'attachment; filename=%s' % \
222 dispo = 'attachment; filename=%s' % \
223 safe_str(f_path.split(os.sep)[-1])
223 safe_str(f_path.split(os.sep)[-1])
224
224
225 response.content_disposition = dispo
225 response.content_disposition = dispo
226 response.content_type = mimetype
226 response.content_type = mimetype
227 return file_node.content
227 return file_node.content
228
228
229 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
229 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
230 'repository.admin')
230 'repository.admin')
231 def annotate(self, repo_name, revision, f_path):
231 def annotate(self, repo_name, revision, f_path):
232 c.cs = self.__get_cs_or_redirect(revision, repo_name)
232 c.cs = self.__get_cs_or_redirect(revision, repo_name)
233 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
233 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
234
234
235 c.file_history = self._get_node_history(c.cs, f_path)
235 c.file_history = self._get_node_history(c.cs, f_path)
236 c.f_path = f_path
236 c.f_path = f_path
237 return render('files/files_annotate.html')
237 return render('files/files_annotate.html')
238
238
239 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
239 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
240 def edit(self, repo_name, revision, f_path):
240 def edit(self, repo_name, revision, f_path):
241 r_post = request.POST
241 r_post = request.POST
242
242
243 c.cs = self.__get_cs_or_redirect(revision, repo_name)
243 c.cs = self.__get_cs_or_redirect(revision, repo_name)
244 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
244 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
245
245
246 if c.file.is_binary:
246 if c.file.is_binary:
247 return redirect(url('files_home', repo_name=c.repo_name,
247 return redirect(url('files_home', repo_name=c.repo_name,
248 revision=c.cs.raw_id, f_path=f_path))
248 revision=c.cs.raw_id, f_path=f_path))
249
249
250 c.file_history = self._get_node_history(c.cs, f_path)
250 c.file_history = self._get_node_history(c.cs, f_path)
251 c.f_path = f_path
251 c.f_path = f_path
252
252
253 if r_post:
253 if r_post:
254
254
255 old_content = c.file.content
255 old_content = c.file.content
256 sl = old_content.splitlines(1)
256 sl = old_content.splitlines(1)
257 first_line = sl[0] if sl else ''
257 first_line = sl[0] if sl else ''
258 # modes: 0 - Unix, 1 - Mac, 2 - DOS
258 # modes: 0 - Unix, 1 - Mac, 2 - DOS
259 mode = detect_mode(first_line, 0)
259 mode = detect_mode(first_line, 0)
260 content = convert_line_endings(r_post.get('content'), mode)
260 content = convert_line_endings(r_post.get('content'), mode)
261
261
262 message = r_post.get('message') or (_('Edited %s via RhodeCode')
262 message = r_post.get('message') or (_('Edited %s via RhodeCode')
263 % (f_path))
263 % (f_path))
264 author = self.rhodecode_user.full_contact
264 author = self.rhodecode_user.full_contact
265
265
266 if content == old_content:
266 if content == old_content:
267 h.flash(_('No changes'),
267 h.flash(_('No changes'),
268 category='warning')
268 category='warning')
269 return redirect(url('changeset_home', repo_name=c.repo_name,
269 return redirect(url('changeset_home', repo_name=c.repo_name,
270 revision='tip'))
270 revision='tip'))
271
271
272 try:
272 try:
273 self.scm_model.commit_change(repo=c.rhodecode_repo,
273 self.scm_model.commit_change(repo=c.rhodecode_repo,
274 repo_name=repo_name, cs=c.cs,
274 repo_name=repo_name, cs=c.cs,
275 user=self.rhodecode_user,
275 user=self.rhodecode_user,
276 author=author, message=message,
276 author=author, message=message,
277 content=content, f_path=f_path)
277 content=content, f_path=f_path)
278 h.flash(_('Successfully committed to %s' % f_path),
278 h.flash(_('Successfully committed to %s' % f_path),
279 category='success')
279 category='success')
280
280
281 except Exception:
281 except Exception:
282 log.error(traceback.format_exc())
282 log.error(traceback.format_exc())
283 h.flash(_('Error occurred during commit'), category='error')
283 h.flash(_('Error occurred during commit'), category='error')
284 return redirect(url('changeset_home',
284 return redirect(url('changeset_home',
285 repo_name=c.repo_name, revision='tip'))
285 repo_name=c.repo_name, revision='tip'))
286
286
287 return render('files/files_edit.html')
287 return render('files/files_edit.html')
288
288
289 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
289 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
290 'repository.admin')
290 'repository.admin')
291 def archivefile(self, repo_name, fname):
291 def archivefile(self, repo_name, fname):
292
292
293 fileformat = None
293 fileformat = None
294 revision = None
294 revision = None
295 ext = None
295 ext = None
296 subrepos = request.GET.get('subrepos') == 'true'
296 subrepos = request.GET.get('subrepos') == 'true'
297
297
298 for a_type, ext_data in ARCHIVE_SPECS.items():
298 for a_type, ext_data in settings.ARCHIVE_SPECS.items():
299 archive_spec = fname.split(ext_data[1])
299 archive_spec = fname.split(ext_data[1])
300 if len(archive_spec) == 2 and archive_spec[1] == '':
300 if len(archive_spec) == 2 and archive_spec[1] == '':
301 fileformat = a_type or ext_data[1]
301 fileformat = a_type or ext_data[1]
302 revision = archive_spec[0]
302 revision = archive_spec[0]
303 ext = ext_data[1]
303 ext = ext_data[1]
304
304
305 try:
305 try:
306 dbrepo = RepoModel().get_by_repo_name(repo_name)
306 dbrepo = RepoModel().get_by_repo_name(repo_name)
307 if dbrepo.enable_downloads is False:
307 if dbrepo.enable_downloads is False:
308 return _('downloads disabled')
308 return _('downloads disabled')
309
309
310 cs = c.rhodecode_repo.get_changeset(revision)
310 cs = c.rhodecode_repo.get_changeset(revision)
311 content_type = ARCHIVE_SPECS[fileformat][0]
311 content_type = settings.ARCHIVE_SPECS[fileformat][0]
312 except ChangesetDoesNotExistError:
312 except ChangesetDoesNotExistError:
313 return _('Unknown revision %s') % revision
313 return _('Unknown revision %s') % revision
314 except EmptyRepositoryError:
314 except EmptyRepositoryError:
315 return _('Empty repository')
315 return _('Empty repository')
316 except (ImproperArchiveTypeError, KeyError):
316 except (ImproperArchiveTypeError, KeyError):
317 return _('Unknown archive type')
317 return _('Unknown archive type')
318
318
319 response.content_type = content_type
319 response.content_type = content_type
320 response.content_disposition = 'attachment; filename=%s-%s%s' \
320 response.content_disposition = 'attachment; filename=%s-%s%s' \
321 % (repo_name, revision, ext)
321 % (repo_name, revision, ext)
322
322
323 import tempfile
323 import tempfile
324 archive = tempfile.mkstemp()[1]
324 archive = tempfile.mkstemp()[1]
325 t = open(archive, 'wb')
325 t = open(archive, 'wb')
326 cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
326 cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
327
327
328 def get_chunked_archive(archive):
328 def get_chunked_archive(archive):
329 stream = open(archive, 'rb')
329 stream = open(archive, 'rb')
330 while True:
330 while True:
331 data = stream.read(4096)
331 data = stream.read(4096)
332 if not data:
332 if not data:
333 os.remove(archive)
333 os.remove(archive)
334 break
334 break
335 yield data
335 yield data
336
336
337 return get_chunked_archive(archive)
337 return get_chunked_archive(archive)
338
338
339 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
339 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
340 'repository.admin')
340 'repository.admin')
341 def diff(self, repo_name, f_path):
341 def diff(self, repo_name, f_path):
342 diff1 = request.GET.get('diff1')
342 diff1 = request.GET.get('diff1')
343 diff2 = request.GET.get('diff2')
343 diff2 = request.GET.get('diff2')
344 c.action = request.GET.get('diff')
344 c.action = request.GET.get('diff')
345 c.no_changes = diff1 == diff2
345 c.no_changes = diff1 == diff2
346 c.f_path = f_path
346 c.f_path = f_path
347 c.big_diff = False
347 c.big_diff = False
348
348
349 try:
349 try:
350 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
350 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
351 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
351 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
352 node1 = c.changeset_1.get_node(f_path)
352 node1 = c.changeset_1.get_node(f_path)
353 else:
353 else:
354 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
354 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
355 node1 = FileNode('.', '', changeset=c.changeset_1)
355 node1 = FileNode('.', '', changeset=c.changeset_1)
356
356
357 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
357 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
358 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
358 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
359 node2 = c.changeset_2.get_node(f_path)
359 node2 = c.changeset_2.get_node(f_path)
360 else:
360 else:
361 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
361 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
362 node2 = FileNode('.', '', changeset=c.changeset_2)
362 node2 = FileNode('.', '', changeset=c.changeset_2)
363 except RepositoryError:
363 except RepositoryError:
364 return redirect(url('files_home',
364 return redirect(url('files_home',
365 repo_name=c.repo_name, f_path=f_path))
365 repo_name=c.repo_name, f_path=f_path))
366
366
367 if c.action == 'download':
367 if c.action == 'download':
368 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
368 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
369 format='gitdiff')
369 format='gitdiff')
370
370
371 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
371 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
372 response.content_type = 'text/plain'
372 response.content_type = 'text/plain'
373 response.content_disposition = 'attachment; filename=%s' \
373 response.content_disposition = 'attachment; filename=%s' \
374 % diff_name
374 % diff_name
375 return diff.raw_diff()
375 return diff.raw_diff()
376
376
377 elif c.action == 'raw':
377 elif c.action == 'raw':
378 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
378 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
379 format='gitdiff')
379 format='gitdiff')
380 response.content_type = 'text/plain'
380 response.content_type = 'text/plain'
381 return diff.raw_diff()
381 return diff.raw_diff()
382
382
383 elif c.action == 'diff':
383 elif c.action == 'diff':
384 if node1.is_binary or node2.is_binary:
384 if node1.is_binary or node2.is_binary:
385 c.cur_diff = _('Binary file')
385 c.cur_diff = _('Binary file')
386 elif node1.size > self.cut_off_limit or \
386 elif node1.size > self.cut_off_limit or \
387 node2.size > self.cut_off_limit:
387 node2.size > self.cut_off_limit:
388 c.cur_diff = ''
388 c.cur_diff = ''
389 c.big_diff = True
389 c.big_diff = True
390 else:
390 else:
391 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
391 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
392 format='gitdiff')
392 format='gitdiff')
393 c.cur_diff = diff.as_html()
393 c.cur_diff = diff.as_html()
394 else:
394 else:
395
395
396 #default option
396 #default option
397 if node1.is_binary or node2.is_binary:
397 if node1.is_binary or node2.is_binary:
398 c.cur_diff = _('Binary file')
398 c.cur_diff = _('Binary file')
399 elif node1.size > self.cut_off_limit or \
399 elif node1.size > self.cut_off_limit or \
400 node2.size > self.cut_off_limit:
400 node2.size > self.cut_off_limit:
401 c.cur_diff = ''
401 c.cur_diff = ''
402 c.big_diff = True
402 c.big_diff = True
403
403
404 else:
404 else:
405 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
405 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
406 format='gitdiff')
406 format='gitdiff')
407 c.cur_diff = diff.as_html()
407 c.cur_diff = diff.as_html()
408
408
409 if not c.cur_diff and not c.big_diff:
409 if not c.cur_diff and not c.big_diff:
410 c.no_changes = True
410 c.no_changes = True
411 return render('files/file_diff.html')
411 return render('files/file_diff.html')
412
412
413 def _get_node_history(self, cs, f_path):
413 def _get_node_history(self, cs, f_path):
414 changesets = cs.get_file_history(f_path)
414 changesets = cs.get_file_history(f_path)
415 hist_l = []
415 hist_l = []
416
416
417 changesets_group = ([], _("Changesets"))
417 changesets_group = ([], _("Changesets"))
418 branches_group = ([], _("Branches"))
418 branches_group = ([], _("Branches"))
419 tags_group = ([], _("Tags"))
419 tags_group = ([], _("Tags"))
420
420
421 for chs in changesets:
421 for chs in changesets:
422 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
422 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
423 changesets_group[0].append((chs.raw_id, n_desc,))
423 changesets_group[0].append((chs.raw_id, n_desc,))
424
424
425 hist_l.append(changesets_group)
425 hist_l.append(changesets_group)
426
426
427 for name, chs in c.rhodecode_repo.branches.items():
427 for name, chs in c.rhodecode_repo.branches.items():
428 #chs = chs.split(':')[-1]
428 #chs = chs.split(':')[-1]
429 branches_group[0].append((chs, name),)
429 branches_group[0].append((chs, name),)
430 hist_l.append(branches_group)
430 hist_l.append(branches_group)
431
431
432 for name, chs in c.rhodecode_repo.tags.items():
432 for name, chs in c.rhodecode_repo.tags.items():
433 #chs = chs.split(':')[-1]
433 #chs = chs.split(':')[-1]
434 tags_group[0].append((chs, name),)
434 tags_group[0].append((chs, name),)
435 hist_l.append(tags_group)
435 hist_l.append(tags_group)
436
436
437 return hist_l
437 return hist_l
438
438
439 @jsonify
439 @jsonify
440 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
440 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
441 'repository.admin')
441 'repository.admin')
442 def nodelist(self, repo_name, revision, f_path):
442 def nodelist(self, repo_name, revision, f_path):
443 if request.environ.get('HTTP_X_PARTIAL_XHR'):
443 if request.environ.get('HTTP_X_PARTIAL_XHR'):
444 cs = self.__get_cs_or_redirect(revision, repo_name)
444 cs = self.__get_cs_or_redirect(revision, repo_name)
445 _d, _f = self.__get_paths(cs, f_path)
445 _d, _f = self.__get_paths(cs, f_path)
446 return _d + _f
446 return _d + _f
447
447
General Comments 0
You need to be logged in to leave comments. Login now