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