##// END OF EJS Templates
Optimized look of compare view of changesets....
marcink -
r3011:25d77aef beta
parent child Browse files
Show More
@@ -1,153 +1,161 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.compare
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 compare controller for pylons showoing differences between two
7 7 repos, branches, bookmarks or tips
8 8
9 9 :created_on: May 6, 2012
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26 import logging
27 27 import traceback
28 28
29 29 from webob.exc import HTTPNotFound
30 30 from pylons import request, response, session, tmpl_context as c, url
31 31 from pylons.controllers.util import abort, redirect
32 32 from pylons.i18n.translation import _
33 33
34 34 from rhodecode.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError
35 35 from rhodecode.lib import helpers as h
36 36 from rhodecode.lib.base import BaseRepoController, render
37 37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 38 from rhodecode.lib import diffs
39 39
40 40 from rhodecode.model.db import Repository
41 41 from rhodecode.model.pull_request import PullRequestModel
42 42 from webob.exc import HTTPBadRequest
43 43 from rhodecode.lib.utils2 import str2bool
44 from rhodecode.lib.diffs import LimitedDiffContainer
44 45
45 46 log = logging.getLogger(__name__)
46 47
47 48
48 49 class CompareController(BaseRepoController):
49 50
50 51 @LoginRequired()
51 52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 53 'repository.admin')
53 54 def __before__(self):
54 55 super(CompareController, self).__before__()
55 56
56 57 def __get_cs_or_redirect(self, rev, repo, redirect_after=True,
57 58 partial=False):
58 59 """
59 60 Safe way to get changeset if error occur it redirects to changeset with
60 61 proper message. If partial is set then don't do redirect raise Exception
61 62 instead
62 63
63 64 :param rev: revision to fetch
64 65 :param repo: repo instance
65 66 """
66 67
67 68 try:
68 69 type_, rev = rev
69 70 return repo.scm_instance.get_changeset(rev)
70 71 except EmptyRepositoryError, e:
71 72 if not redirect_after:
72 73 return None
73 74 h.flash(h.literal(_('There are no changesets yet')),
74 75 category='warning')
75 76 redirect(url('summary_home', repo_name=repo.repo_name))
76 77
77 78 except RepositoryError, e:
78 79 log.error(traceback.format_exc())
79 80 h.flash(str(e), category='warning')
80 81 if not partial:
81 82 redirect(h.url('summary_home', repo_name=repo.repo_name))
82 83 raise HTTPBadRequest()
83 84
84 85 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
85 86
86 87 org_repo = c.rhodecode_db_repo.repo_name
87 88 org_ref = (org_ref_type, org_ref)
88 89 other_ref = (other_ref_type, other_ref)
89 90 other_repo = request.GET.get('repo', org_repo)
90 91 bundle_compare = str2bool(request.GET.get('bundle', True))
92 c.fulldiff = fulldiff = request.GET.get('fulldiff')
91 93
92 94 c.swap_url = h.url('compare_url', repo_name=other_repo,
93 95 org_ref_type=other_ref[0], org_ref=other_ref[1],
94 96 other_ref_type=org_ref[0], other_ref=org_ref[1],
95 97 repo=org_repo, as_form=request.GET.get('as_form'),
96 98 bundle=bundle_compare)
97 99
98 100 c.org_repo = org_repo = Repository.get_by_repo_name(org_repo)
99 101 c.other_repo = other_repo = Repository.get_by_repo_name(other_repo)
100 102
101 103 if c.org_repo is None or c.other_repo is None:
102 104 log.error('Could not found repo %s or %s' % (org_repo, other_repo))
103 105 raise HTTPNotFound
104 106
105 107 if c.org_repo != c.other_repo and h.is_git(c.rhodecode_repo):
106 108 log.error('compare of two remote repos not available for GIT REPOS')
107 109 raise HTTPNotFound
108 110
109 111 if c.org_repo.scm_instance.alias != c.other_repo.scm_instance.alias:
110 112 log.error('compare of two different kind of remote repos not available')
111 113 raise HTTPNotFound
112 114
113 115 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
114 116 self.__get_cs_or_redirect(rev=org_ref, repo=org_repo, partial=partial)
115 117 self.__get_cs_or_redirect(rev=other_ref, repo=other_repo, partial=partial)
116 118
117 119 c.cs_ranges, discovery_data = PullRequestModel().get_compare_data(
118 120 org_repo, org_ref, other_repo, other_ref
119 121 )
120 122
121 123 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
122 124 c.cs_ranges])
123 125 c.target_repo = c.repo_name
124 126 # defines that we need hidden inputs with changesets
125 127 c.as_form = request.GET.get('as_form', False)
126 128 if partial:
127 129 return render('compare/compare_cs.html')
128 130
129 131 if not bundle_compare and c.cs_ranges:
130 132 # case we want a simple diff without incoming changesets, just
131 133 # for review purposes. Make the diff on the forked repo, with
132 134 # revision that is common ancestor
133 135 other_ref = ('rev', c.cs_ranges[-1].parents[0].raw_id)
134 136 other_repo = org_repo
135 137
136 138 c.org_ref = org_ref[1]
137 139 c.other_ref = other_ref[1]
138 140
139 141 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
140 142 discovery_data, bundle_compare=bundle_compare)
141 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
143 diff_limit = self.cut_off_limit if not fulldiff else None
144 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff',
145 diff_limit=diff_limit)
142 146 _parsed = diff_processor.prepare()
143 147
148 c.limited_diff = False
149 if isinstance(_parsed, LimitedDiffContainer):
150 c.limited_diff = True
151
144 152 c.files = []
145 153 c.changes = {}
146 154
147 155 for f in _parsed:
148 156 fid = h.FID('', f['filename'])
149 157 c.files.append([fid, f['operation'], f['filename'], f['stats']])
150 158 diff = diff_processor.as_html(enable_comments=False, parsed_lines=[f])
151 159 c.changes[fid] = [f['operation'], f['filename'], diff]
152 160
153 161 return render('compare/compare_diff.html')
@@ -1,27 +1,28 b''
1 1 ## Changesets table !
2 2 <div class="container">
3 3 <table class="compare_view_commits noborder">
4 4 %if not c.cs_ranges:
5 5 <tr><td>${_('No changesets')}</td></tr>
6 6 %else:
7 7 %for cnt, cs in enumerate(c.cs_ranges):
8 8 <tr>
9 9 <td><div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),14)}"/></div></td>
10 10 <td>
11 11 %if cs.raw_id in c.statuses:
12 12 <div title="${c.statuses[cs.raw_id][1]}" class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[cs.raw_id][0])}" /></div>
13 13 %endif
14 14 </td>
15 15 <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.target_repo,revision=cs.raw_id))}
16 16 %if c.as_form:
17 17 ${h.hidden('revisions',cs.raw_id)}
18 18 %endif
19 19 </td>
20 20 <td><div class="author">${h.person(cs.author)}</div></td>
21 <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
22 <td><div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message),c.repo_name)}</div></td>
21 <td><span class="tooltip" title="${h.tooltip(h.age(cs.date))}">${cs.date}</span></td>
22 <td><div class="message tooltip" title="${h.tooltip(cs.message)}" style="white-space:normal">${h.urlify_commit(h.shorter(cs.message, 60),c.repo_name)}</div></td>
23 23 </tr>
24 24 %endfor
25
25 26 %endif
26 27 </table>
27 28 </div>
@@ -1,77 +1,82 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${c.repo_name} ${_('Compare')} ${'%s@%s' % (c.org_repo.repo_name, c.org_ref)} -> ${'%s@%s' % (c.other_repo.repo_name, c.other_ref)}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 9 ${h.link_to(_(u'Home'),h.url('/'))}
10 10 &raquo;
11 11 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
12 12 &raquo;
13 13 ${_('Compare')}
14 14 </%def>
15 15
16 16 <%def name="page_nav()">
17 17 ${self.menu('changelog')}
18 18 </%def>
19 19
20 20 <%def name="main()">
21 21 <div class="box">
22 22 <!-- box / title -->
23 23 <div class="title">
24 24 ${self.breadcrumbs()}
25 25 </div>
26 26 <div class="table">
27 27 <div id="body" class="diffblock">
28 28 <div class="code-header cv">
29 29 <h3 class="code-header-title">${_('Compare View')}</h3>
30 30 <div>
31 31 ${'%s@%s' % (c.org_repo.repo_name, c.org_ref)} -> ${'%s@%s' % (c.other_repo.repo_name, c.other_ref)} <a href="${c.swap_url}">[swap]</a>
32 32 </div>
33 33 </div>
34 34 </div>
35 35 <div id="changeset_compare_view_content">
36 36 ##CS
37 37 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Outgoing changesets')}</div>
38 38 <%include file="compare_cs.html" />
39 39
40 40 ## FILES
41 41 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
42 42 <div class="cs_files">
43 43 %for fid, change, f, stat in c.files:
44 44 <div class="cs_${change}">
45 45 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
46 46 <div class="changes">${h.fancy_file_stats(stat)}</div>
47 47 </div>
48 48 %endfor
49 49 </div>
50 % if c.limited_diff:
51 <h5>${_('Changeset was too big and was cut off...')}</h5>
52 % endif
50 53 </div>
51 54 </div>
52 55
53 56 ## diff block
54 57 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
55 58 %for fid, change, f, stat in c.files:
56 59 ${diff_block.diff_block_simple([c.changes[fid]])}
57 60 %endfor
58
61 % if c.limited_diff:
62 <h4>${_('Changeset was too big and was cut off...')}</h4>
63 % endif
59 64 <script type="text/javascript">
60 65
61 66 YUE.onDOMReady(function(){
62 67
63 68 YUE.on(YUQ('.diff-menu-activate'),'click',function(e){
64 69 var act = e.currentTarget.nextElementSibling;
65 70
66 71 if(YUD.hasClass(act,'active')){
67 72 YUD.removeClass(act,'active');
68 73 YUD.setStyle(act,'display','none');
69 74 }else{
70 75 YUD.addClass(act,'active');
71 76 YUD.setStyle(act,'display','');
72 77 }
73 78 });
74 79 })
75 80 </script>
76 81 </div>
77 82 </%def>
General Comments 0
You need to be logged in to leave comments. Login now