Mercurial > kallithea
comparison rhodecode/controllers/files.py @ 1789:17caf4efe15c beta
implements #308 rewrote diffs to enable displaying full diff on each file
- fixed escaping of html special chars in file editor
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Mon, 19 Dec 2011 00:11:20 +0200 |
parents | 5610fd9b6803 |
children | ef0066e95be5 |
comparison
equal
deleted
inserted
replaced
1788:ef0613584ced | 1789:17caf4efe15c |
---|---|
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 pylons import request, response, tmpl_context as c, url |
31 | |
32 from pylons import request, response, session, tmpl_context as c, url | |
33 from pylons.i18n.translation import _ | 31 from pylons.i18n.translation import _ |
34 from pylons.controllers.util import redirect | 32 from pylons.controllers.util import redirect |
35 from pylons.decorators import jsonify | 33 from pylons.decorators import jsonify |
36 | 34 |
37 from vcs.conf import settings | 35 from vcs.conf import settings |
38 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \ | 36 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \ |
39 EmptyRepositoryError, ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError | 37 EmptyRepositoryError, ImproperArchiveTypeError, VCSError, \ |
40 from vcs.nodes import FileNode, NodeKind | 38 NodeAlreadyExistsError |
41 | 39 from vcs.nodes import FileNode |
42 | 40 |
41 from rhodecode.lib.compat import OrderedDict | |
43 from rhodecode.lib import convert_line_endings, detect_mode, safe_str | 42 from rhodecode.lib import convert_line_endings, detect_mode, safe_str |
44 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator | 43 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator |
45 from rhodecode.lib.base import BaseRepoController, render | 44 from rhodecode.lib.base import BaseRepoController, render |
46 from rhodecode.lib.utils import EmptyChangeset | 45 from rhodecode.lib.utils import EmptyChangeset |
47 from rhodecode.lib import diffs | 46 from rhodecode.lib import diffs |
48 import rhodecode.lib.helpers as h | 47 import rhodecode.lib.helpers as h |
49 from rhodecode.model.repo import RepoModel | 48 from rhodecode.model.repo import RepoModel |
49 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\ | |
50 _context_url, get_line_ctx, get_ignore_ws | |
51 from rhodecode.lib.diffs import wrapped_diff | |
50 | 52 |
51 log = logging.getLogger(__name__) | 53 log = logging.getLogger(__name__) |
52 | 54 |
53 | 55 |
54 class FilesController(BaseRepoController): | 56 class FilesController(BaseRepoController): |
103 redirect(h.url('files_home', repo_name=repo_name, | 105 redirect(h.url('files_home', repo_name=repo_name, |
104 revision=cs.raw_id)) | 106 revision=cs.raw_id)) |
105 | 107 |
106 return file_node | 108 return file_node |
107 | 109 |
108 | |
109 def __get_paths(self, changeset, starting_path): | 110 def __get_paths(self, changeset, starting_path): |
110 """recursive walk in root dir and return a set of all path in that dir | 111 """recursive walk in root dir and return a set of all path in that dir |
111 based on repository walk function | 112 based on repository walk function |
112 """ | 113 """ |
113 _files = list() | 114 _files = list() |
126 return _dirs, _files | 127 return _dirs, _files |
127 | 128 |
128 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', | 129 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
129 'repository.admin') | 130 'repository.admin') |
130 def index(self, repo_name, revision, f_path): | 131 def index(self, repo_name, revision, f_path): |
131 #reditect to given revision from form if given | 132 # redirect to given revision from form if given |
132 post_revision = request.POST.get('at_rev', None) | 133 post_revision = request.POST.get('at_rev', None) |
133 if post_revision: | 134 if post_revision: |
134 cs = self.__get_cs_or_redirect(post_revision, repo_name) | 135 cs = self.__get_cs_or_redirect(post_revision, repo_name) |
135 redirect(url('files_home', repo_name=c.repo_name, | 136 redirect(url('files_home', repo_name=c.repo_name, |
136 revision=cs.raw_id, f_path=f_path)) | 137 revision=cs.raw_id, f_path=f_path)) |
139 c.branch = request.GET.get('branch', None) | 140 c.branch = request.GET.get('branch', None) |
140 c.f_path = f_path | 141 c.f_path = f_path |
141 | 142 |
142 cur_rev = c.changeset.revision | 143 cur_rev = c.changeset.revision |
143 | 144 |
144 #prev link | 145 # prev link |
145 try: | 146 try: |
146 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch) | 147 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch) |
147 c.url_prev = url('files_home', repo_name=c.repo_name, | 148 c.url_prev = url('files_home', repo_name=c.repo_name, |
148 revision=prev_rev.raw_id, f_path=f_path) | 149 revision=prev_rev.raw_id, f_path=f_path) |
149 if c.branch: | 150 if c.branch: |
150 c.url_prev += '?branch=%s' % c.branch | 151 c.url_prev += '?branch=%s' % c.branch |
151 except (ChangesetDoesNotExistError, VCSError): | 152 except (ChangesetDoesNotExistError, VCSError): |
152 c.url_prev = '#' | 153 c.url_prev = '#' |
153 | 154 |
154 #next link | 155 # next link |
155 try: | 156 try: |
156 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch) | 157 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch) |
157 c.url_next = url('files_home', repo_name=c.repo_name, | 158 c.url_next = url('files_home', repo_name=c.repo_name, |
158 revision=next_rev.raw_id, f_path=f_path) | 159 revision=next_rev.raw_id, f_path=f_path) |
159 if c.branch: | 160 if c.branch: |
160 c.url_next += '?branch=%s' % c.branch | 161 c.url_next += '?branch=%s' % c.branch |
161 except (ChangesetDoesNotExistError, VCSError): | 162 except (ChangesetDoesNotExistError, VCSError): |
162 c.url_next = '#' | 163 c.url_next = '#' |
163 | 164 |
164 #files or dirs | 165 # files or dirs |
165 try: | 166 try: |
166 c.file = c.changeset.get_node(f_path) | 167 c.file = c.changeset.get_node(f_path) |
167 | 168 |
168 if c.file.is_file(): | 169 if c.file.is_file(): |
169 c.file_history = self._get_node_history(c.changeset, f_path) | 170 c.file_history = self._get_node_history(c.changeset, f_path) |
405 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', | 406 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
406 'repository.admin') | 407 'repository.admin') |
407 def diff(self, repo_name, f_path): | 408 def diff(self, repo_name, f_path): |
408 ignore_whitespace = request.GET.get('ignorews') == '1' | 409 ignore_whitespace = request.GET.get('ignorews') == '1' |
409 line_context = request.GET.get('context', 3) | 410 line_context = request.GET.get('context', 3) |
410 diff1 = request.GET.get('diff1') | 411 diff1 = request.GET.get('diff1', '') |
411 diff2 = request.GET.get('diff2') | 412 diff2 = request.GET.get('diff2', '') |
412 c.action = request.GET.get('diff') | 413 c.action = request.GET.get('diff') |
413 c.no_changes = diff1 == diff2 | 414 c.no_changes = diff1 == diff2 |
414 c.f_path = f_path | 415 c.f_path = f_path |
415 c.big_diff = False | 416 c.big_diff = False |
416 | 417 c.anchor_url = anchor_url |
418 c.ignorews_url = _ignorews_url | |
419 c.context_url = _context_url | |
420 c.changes = OrderedDict() | |
421 c.changes[diff2] = [] | |
417 try: | 422 try: |
418 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: | 423 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: |
419 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) | 424 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) |
420 node1 = c.changeset_1.get_node(f_path) | 425 node1 = c.changeset_1.get_node(f_path) |
421 else: | 426 else: |
427 node2 = c.changeset_2.get_node(f_path) | 432 node2 = c.changeset_2.get_node(f_path) |
428 else: | 433 else: |
429 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) | 434 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) |
430 node2 = FileNode('.', '', changeset=c.changeset_2) | 435 node2 = FileNode('.', '', changeset=c.changeset_2) |
431 except RepositoryError: | 436 except RepositoryError: |
432 return redirect(url('files_home', | 437 return redirect(url('files_home', repo_name=c.repo_name, |
433 repo_name=c.repo_name, f_path=f_path)) | 438 f_path=f_path)) |
434 | 439 |
435 if c.action == 'download': | 440 if c.action == 'download': |
436 _diff = diffs.get_gitdiff(node1, node2, | 441 _diff = diffs.get_gitdiff(node1, node2, |
437 ignore_whitespace=ignore_whitespace, | 442 ignore_whitespace=ignore_whitespace, |
438 context=line_context) | 443 context=line_context) |
439 diff = diffs.DiffProcessor(_diff,format='gitdiff') | 444 diff = diffs.DiffProcessor(_diff, format='gitdiff') |
440 | 445 |
441 diff_name = '%s_vs_%s.diff' % (diff1, diff2) | 446 diff_name = '%s_vs_%s.diff' % (diff1, diff2) |
442 response.content_type = 'text/plain' | 447 response.content_type = 'text/plain' |
443 response.content_disposition = 'attachment; filename=%s' \ | 448 response.content_disposition = 'attachment; filename=%s' \ |
444 % diff_name | 449 % diff_name |
446 | 451 |
447 elif c.action == 'raw': | 452 elif c.action == 'raw': |
448 _diff = diffs.get_gitdiff(node1, node2, | 453 _diff = diffs.get_gitdiff(node1, node2, |
449 ignore_whitespace=ignore_whitespace, | 454 ignore_whitespace=ignore_whitespace, |
450 context=line_context) | 455 context=line_context) |
451 diff = diffs.DiffProcessor(_diff,format='gitdiff') | 456 diff = diffs.DiffProcessor(_diff, format='gitdiff') |
452 response.content_type = 'text/plain' | 457 response.content_type = 'text/plain' |
453 return diff.raw_diff() | 458 return diff.raw_diff() |
454 | 459 |
455 elif c.action == 'diff': | |
456 if node1.is_binary or node2.is_binary: | |
457 c.cur_diff = _('Binary file') | |
458 elif node1.size > self.cut_off_limit or \ | |
459 node2.size > self.cut_off_limit: | |
460 c.cur_diff = '' | |
461 c.big_diff = True | |
462 else: | |
463 _diff = diffs.get_gitdiff(node1, node2, | |
464 ignore_whitespace=ignore_whitespace, | |
465 context=line_context) | |
466 diff = diffs.DiffProcessor(_diff,format='gitdiff') | |
467 c.cur_diff = diff.as_html() | |
468 else: | 460 else: |
469 | 461 fid = h.FID(diff2, node2.path) |
470 #default option | 462 line_context_lcl = get_line_ctx(fid, request.GET) |
471 if node1.is_binary or node2.is_binary: | 463 ign_whitespace_lcl = get_ignore_ws(fid, request.GET) |
472 c.cur_diff = _('Binary file') | 464 |
473 elif node1.size > self.cut_off_limit or \ | 465 lim = request.GET.get('fulldiff') or self.cut_off_limit |
474 node2.size > self.cut_off_limit: | 466 _, cs1, cs2, diff, st = wrapped_diff(filenode_old=node1, |
475 c.cur_diff = '' | 467 filenode_new=node2, |
476 c.big_diff = True | 468 cut_off_limit=lim, |
477 | 469 ignore_whitespace=ign_whitespace_lcl, |
478 else: | 470 line_context=line_context_lcl, |
479 _diff = diffs.get_gitdiff(node1, node2, | 471 enable_comments=False) |
480 ignore_whitespace=ignore_whitespace, | 472 |
481 context=line_context) | 473 c.changes = [('', node2, diff, cs1, cs2, st,)] |
482 diff = diffs.DiffProcessor(_diff,format='gitdiff') | 474 |
483 c.cur_diff = diff.as_html() | |
484 | |
485 if not c.cur_diff and not c.big_diff: | |
486 c.no_changes = True | |
487 return render('files/file_diff.html') | 475 return render('files/file_diff.html') |
488 | 476 |
489 def _get_node_history(self, cs, f_path): | 477 def _get_node_history(self, cs, f_path): |
490 changesets = cs.get_file_history(f_path) | 478 changesets = cs.get_file_history(f_path) |
491 hist_l = [] | 479 hist_l = [] |
499 changesets_group[0].append((chs.raw_id, n_desc,)) | 487 changesets_group[0].append((chs.raw_id, n_desc,)) |
500 | 488 |
501 hist_l.append(changesets_group) | 489 hist_l.append(changesets_group) |
502 | 490 |
503 for name, chs in c.rhodecode_repo.branches.items(): | 491 for name, chs in c.rhodecode_repo.branches.items(): |
504 #chs = chs.split(':')[-1] | |
505 branches_group[0].append((chs, name),) | 492 branches_group[0].append((chs, name),) |
506 hist_l.append(branches_group) | 493 hist_l.append(branches_group) |
507 | 494 |
508 for name, chs in c.rhodecode_repo.tags.items(): | 495 for name, chs in c.rhodecode_repo.tags.items(): |
509 #chs = chs.split(':')[-1] | |
510 tags_group[0].append((chs, name),) | 496 tags_group[0].append((chs, name),) |
511 hist_l.append(tags_group) | 497 hist_l.append(tags_group) |
512 | 498 |
513 return hist_l | 499 return hist_l |
514 | 500 |