##// END OF EJS Templates
changes for archivals in rhodecode. Also made it work for git that way
marcink -
r1308:73b2fc32 beta
parent child Browse files
Show More
@@ -1,406 +1,420 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.files
3 rhodecode.controllers.files
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Files controller for RhodeCode
6 Files controller for RhodeCode
7
7
8 :created_on: Apr 21, 2010
8 :created_on: Apr 21, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import mimetypes
28 import 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)
235 sl = old_content.splitlines(1)
236 first_line = sl[0] if sl else ''
236 first_line = sl[0] if sl else ''
237 # modes: 0 - Unix, 1 - Mac, 2 - DOS
237 # modes: 0 - Unix, 1 - Mac, 2 - DOS
238 mode = detect_mode(first_line, 0)
238 mode = detect_mode(first_line, 0)
239 content = convert_line_endings(r_post.get('content'), mode)
239 content = convert_line_endings(r_post.get('content'), mode)
240
240
241 message = r_post.get('message') or (_('Edited %s via RhodeCode')
241 message = r_post.get('message') or (_('Edited %s via RhodeCode')
242 % (f_path))
242 % (f_path))
243
243
244 if content == old_content:
244 if content == old_content:
245 h.flash(_('No changes'),
245 h.flash(_('No changes'),
246 category='warning')
246 category='warning')
247 return redirect(url('changeset_home', repo_name=c.repo_name,
247 return redirect(url('changeset_home', repo_name=c.repo_name,
248 revision='tip'))
248 revision='tip'))
249
249
250 try:
250 try:
251 # decoding here will force that we have proper encoded values
251 # decoding here will force that we have proper encoded values
252 # in any other case this will throw exceptions and deny commit
252 # in any other case this will throw exceptions and deny commit
253 content = content.encode('utf8')
253 content = content.encode('utf8')
254 message = message.encode('utf8')
254 message = message.encode('utf8')
255 path = f_path.encode('utf8')
255 path = f_path.encode('utf8')
256 author = self.rhodecode_user.full_contact.encode('utf8')
256 author = self.rhodecode_user.full_contact.encode('utf8')
257 m = IMC(c.rhodecode_repo)
257 m = IMC(c.rhodecode_repo)
258 m.change(FileNode(path, content))
258 m.change(FileNode(path, content))
259 m.commit(message=message,
259 m.commit(message=message,
260 author=author,
260 author=author,
261 parents=[c.cs], branch=c.cs.branch)
261 parents=[c.cs], branch=c.cs.branch)
262 h.flash(_('Successfully committed to %s' % f_path),
262 h.flash(_('Successfully committed to %s' % f_path),
263 category='success')
263 category='success')
264
264
265 except Exception, e:
265 except Exception, e:
266 log.error(traceback.format_exc())
266 log.error(traceback.format_exc())
267 h.flash(_('Error occurred during commit'), category='error')
267 h.flash(_('Error occurred during commit'), category='error')
268 return redirect(url('changeset_home',
268 return redirect(url('changeset_home',
269 repo_name=c.repo_name, revision='tip'))
269 repo_name=c.repo_name, revision='tip'))
270
270
271 return render('files/files_edit.html')
271 return render('files/files_edit.html')
272
272
273 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
273 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
274 'repository.admin')
274 'repository.admin')
275 def archivefile(self, repo_name, fname):
275 def archivefile(self, repo_name, fname):
276
276
277 fileformat = None
277 fileformat = None
278 revision = None
278 revision = None
279 ext = None
279 ext = None
280
280
281 for a_type, ext_data in ARCHIVE_SPECS.items():
281 for a_type, ext_data in ARCHIVE_SPECS.items():
282 archive_spec = fname.split(ext_data[1])
282 archive_spec = fname.split(ext_data[1])
283 if len(archive_spec) == 2 and archive_spec[1] == '':
283 if len(archive_spec) == 2 and archive_spec[1] == '':
284 fileformat = a_type or ext_data[1]
284 fileformat = a_type or ext_data[1]
285 revision = archive_spec[0]
285 revision = archive_spec[0]
286 ext = ext_data[1]
286 ext = ext_data[1]
287
287
288 try:
288 try:
289 dbrepo = RepoModel().get_by_repo_name(repo_name)
289 dbrepo = RepoModel().get_by_repo_name(repo_name)
290 if dbrepo.enable_downloads is False:
290 if dbrepo.enable_downloads is False:
291 return _('downloads disabled')
291 return _('downloads disabled')
292
292
293 cs = c.rhodecode_repo.get_changeset(revision)
293 cs = c.rhodecode_repo.get_changeset(revision)
294 content_type = ARCHIVE_SPECS[fileformat][0]
294 content_type = ARCHIVE_SPECS[fileformat][0]
295 except ChangesetDoesNotExistError:
295 except ChangesetDoesNotExistError:
296 return _('Unknown revision %s') % revision
296 return _('Unknown revision %s') % revision
297 except EmptyRepositoryError:
297 except EmptyRepositoryError:
298 return _('Empty repository')
298 return _('Empty repository')
299 except (ImproperArchiveTypeError, KeyError):
299 except (ImproperArchiveTypeError, KeyError):
300 return _('Unknown archive type')
300 return _('Unknown archive type')
301
301
302 response.content_type = content_type
302 response.content_type = content_type
303 response.content_disposition = 'attachment; filename=%s-%s%s' \
303 response.content_disposition = 'attachment; filename=%s-%s%s' \
304 % (repo_name, revision, ext)
304 % (repo_name, revision, ext)
305
305
306 return cs.get_chunked_archive(stream=None, kind=fileformat)
306 import tempfile
307 archive = tempfile.mkstemp()[1]
308 t = open(archive, 'wb')
309 cs.fill_archive(stream=t, kind=fileformat)
310
311 def get_chunked_archive(archive):
312 stream = open(archive, 'rb')
313 while True:
314 data = stream.read(4096)
315 if not data:
316 os.remove(archive)
317 break
318 yield data
319
320 return get_chunked_archive(archive)
307
321
308 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
322 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
309 'repository.admin')
323 'repository.admin')
310 def diff(self, repo_name, f_path):
324 def diff(self, repo_name, f_path):
311 diff1 = request.GET.get('diff1')
325 diff1 = request.GET.get('diff1')
312 diff2 = request.GET.get('diff2')
326 diff2 = request.GET.get('diff2')
313 c.action = request.GET.get('diff')
327 c.action = request.GET.get('diff')
314 c.no_changes = diff1 == diff2
328 c.no_changes = diff1 == diff2
315 c.f_path = f_path
329 c.f_path = f_path
316 c.big_diff = False
330 c.big_diff = False
317
331
318 try:
332 try:
319 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
333 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
320 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
334 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
321 node1 = c.changeset_1.get_node(f_path)
335 node1 = c.changeset_1.get_node(f_path)
322 else:
336 else:
323 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
337 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
324 node1 = FileNode('.', '', changeset=c.changeset_1)
338 node1 = FileNode('.', '', changeset=c.changeset_1)
325
339
326 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
340 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
327 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
341 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
328 node2 = c.changeset_2.get_node(f_path)
342 node2 = c.changeset_2.get_node(f_path)
329 else:
343 else:
330 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
344 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
331 node2 = FileNode('.', '', changeset=c.changeset_2)
345 node2 = FileNode('.', '', changeset=c.changeset_2)
332 except RepositoryError:
346 except RepositoryError:
333 return redirect(url('files_home',
347 return redirect(url('files_home',
334 repo_name=c.repo_name, f_path=f_path))
348 repo_name=c.repo_name, f_path=f_path))
335
349
336 if c.action == 'download':
350 if c.action == 'download':
337 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
351 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
338 format='gitdiff')
352 format='gitdiff')
339
353
340 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
354 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
341 response.content_type = 'text/plain'
355 response.content_type = 'text/plain'
342 response.content_disposition = 'attachment; filename=%s' \
356 response.content_disposition = 'attachment; filename=%s' \
343 % diff_name
357 % diff_name
344 return diff.raw_diff()
358 return diff.raw_diff()
345
359
346 elif c.action == 'raw':
360 elif c.action == 'raw':
347 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
361 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
348 format='gitdiff')
362 format='gitdiff')
349 response.content_type = 'text/plain'
363 response.content_type = 'text/plain'
350 return diff.raw_diff()
364 return diff.raw_diff()
351
365
352 elif c.action == 'diff':
366 elif c.action == 'diff':
353 if node1.is_binary or node2.is_binary:
367 if node1.is_binary or node2.is_binary:
354 c.cur_diff = _('Binary file')
368 c.cur_diff = _('Binary file')
355 elif node1.size > self.cut_off_limit or \
369 elif node1.size > self.cut_off_limit or \
356 node2.size > self.cut_off_limit:
370 node2.size > self.cut_off_limit:
357 c.cur_diff = ''
371 c.cur_diff = ''
358 c.big_diff = True
372 c.big_diff = True
359 else:
373 else:
360 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
374 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
361 format='gitdiff')
375 format='gitdiff')
362 c.cur_diff = diff.as_html()
376 c.cur_diff = diff.as_html()
363 else:
377 else:
364
378
365 #default option
379 #default option
366 if node1.is_binary or node2.is_binary:
380 if node1.is_binary or node2.is_binary:
367 c.cur_diff = _('Binary file')
381 c.cur_diff = _('Binary file')
368 elif node1.size > self.cut_off_limit or \
382 elif node1.size > self.cut_off_limit or \
369 node2.size > self.cut_off_limit:
383 node2.size > self.cut_off_limit:
370 c.cur_diff = ''
384 c.cur_diff = ''
371 c.big_diff = True
385 c.big_diff = True
372
386
373 else:
387 else:
374 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
388 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
375 format='gitdiff')
389 format='gitdiff')
376 c.cur_diff = diff.as_html()
390 c.cur_diff = diff.as_html()
377
391
378 if not c.cur_diff and not c.big_diff:
392 if not c.cur_diff and not c.big_diff:
379 c.no_changes = True
393 c.no_changes = True
380 return render('files/file_diff.html')
394 return render('files/file_diff.html')
381
395
382 def _get_node_history(self, cs, f_path):
396 def _get_node_history(self, cs, f_path):
383 changesets = cs.get_file_history(f_path)
397 changesets = cs.get_file_history(f_path)
384 hist_l = []
398 hist_l = []
385
399
386 changesets_group = ([], _("Changesets"))
400 changesets_group = ([], _("Changesets"))
387 branches_group = ([], _("Branches"))
401 branches_group = ([], _("Branches"))
388 tags_group = ([], _("Tags"))
402 tags_group = ([], _("Tags"))
389
403
390 for chs in changesets:
404 for chs in changesets:
391 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
405 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
392 changesets_group[0].append((chs.raw_id, n_desc,))
406 changesets_group[0].append((chs.raw_id, n_desc,))
393
407
394 hist_l.append(changesets_group)
408 hist_l.append(changesets_group)
395
409
396 for name, chs in c.rhodecode_repo.branches.items():
410 for name, chs in c.rhodecode_repo.branches.items():
397 #chs = chs.split(':')[-1]
411 #chs = chs.split(':')[-1]
398 branches_group[0].append((chs, name),)
412 branches_group[0].append((chs, name),)
399 hist_l.append(branches_group)
413 hist_l.append(branches_group)
400
414
401 for name, chs in c.rhodecode_repo.tags.items():
415 for name, chs in c.rhodecode_repo.tags.items():
402 #chs = chs.split(':')[-1]
416 #chs = chs.split(':')[-1]
403 tags_group[0].append((chs, name),)
417 tags_group[0].append((chs, name),)
404 hist_l.append(tags_group)
418 hist_l.append(tags_group)
405
419
406 return hist_l
420 return hist_l
General Comments 0
You need to be logged in to leave comments. Login now