##// END OF EJS Templates
added changeset review status into repo/branch compare view
marcink -
r2393:b94eac50 codereview
parent child Browse files
Show More
@@ -1,140 +1,142 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 import binascii
29 29
30 30 from webob.exc import HTTPNotFound
31 31 from pylons import request, response, session, tmpl_context as c, url
32 32 from pylons.controllers.util import abort, redirect
33 33
34 34 from rhodecode.lib import helpers as h
35 35 from rhodecode.lib.base import BaseRepoController, render
36 36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 37 from rhodecode.lib import diffs
38 38
39 39 from rhodecode.model.db import Repository
40 40
41 41 log = logging.getLogger(__name__)
42 42
43 43
44 44 class CompareController(BaseRepoController):
45 45
46 46 @LoginRequired()
47 47 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
48 48 'repository.admin')
49 49 def __before__(self):
50 50 super(CompareController, self).__before__()
51 51
52
53 52 def _get_discovery(self, org_repo, org_ref, other_repo, other_ref):
54 53 from mercurial import discovery
55 54 other = org_repo._repo
56 55 repo = other_repo._repo
57 56 tip = other[org_ref[1]]
58 57 log.debug('Doing discovery for %s@%s vs %s@%s' % (
59 58 org_repo, org_ref, other_repo, other_ref)
60 59 )
61 60 log.debug('Filter heads are %s[%s]' % (tip, org_ref[1]))
62 61 tmp = discovery.findcommonincoming(
63 62 repo=repo, # other_repo we check for incoming
64 63 remote=other, # org_repo source for incoming
65 64 heads=[tip.node()],
66 65 force=False
67 66 )
68 67 return tmp
69 68
70 69 def _get_changesets(self, org_repo, org_ref, other_repo, other_ref, tmp):
71 70 changesets = []
72 71 #case two independent repos
73 72 if org_repo != other_repo:
74 73 common, incoming, rheads = tmp
75 74
76 75 if not incoming:
77 76 revs = []
78 77 else:
79 78 revs = org_repo._repo.changelog.findmissing(common, rheads)
80 79
81 80 for cs in reversed(map(binascii.hexlify, revs)):
82 81 changesets.append(org_repo.get_changeset(cs))
83 82 else:
84 83 revs = ['ancestors(%s) and not ancestors(%s)' % (org_ref[1],
85 84 other_ref[1])]
86 85 from mercurial import scmutil
87 86 out = scmutil.revrange(org_repo._repo, revs)
88 87 for cs in reversed(out):
89 88 changesets.append(org_repo.get_changeset(cs))
90 89
91 90 return changesets
92 91
93 92 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
94 93
95 94 org_repo = c.rhodecode_db_repo.repo_name
96 95 org_ref = (org_ref_type, org_ref)
97 96 other_ref = (other_ref_type, other_ref)
98 97 other_repo = request.GET.get('repo', org_repo)
99 98
100 99 c.swap_url = h.url('compare_url', repo_name=other_repo,
101 100 org_ref_type=other_ref[0], org_ref=other_ref[1],
102 101 other_ref_type=org_ref[0], other_ref=org_ref[1],
103 102 repo=org_repo)
104 103
105 104 c.org_repo = org_repo = Repository.get_by_repo_name(org_repo)
106 105 c.other_repo = other_repo = Repository.get_by_repo_name(other_repo)
107 106
108 107 if c.org_repo is None or c.other_repo is None:
109 108 log.error('Could not found repo %s or %s' % (org_repo, other_repo))
110 109 raise HTTPNotFound
111 110
112 111 discovery_data = self._get_discovery(org_repo.scm_instance,
113 112 org_ref,
114 113 other_repo.scm_instance,
115 114 other_ref)
116 115 c.cs_ranges = self._get_changesets(org_repo.scm_instance,
117 116 org_ref,
118 117 other_repo.scm_instance,
119 118 other_ref,
120 119 discovery_data)
121 120
121 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
122 c.cs_ranges])
123
124
122 125 c.org_ref = org_ref[1]
123 126 c.other_ref = other_ref[1]
124 127 # diff needs to have swapped org with other to generate proper diff
125 128 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
126 129 discovery_data)
127 130 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
128 131 _parsed = diff_processor.prepare()
129 132
130 133 c.files = []
131 134 c.changes = {}
132 # sort Added first then Modified last Deleted files
133 sorter = lambda info: {'A': 0, 'M': 1, 'D': 2}.get(info['operation'])
134 for f in sorted(_parsed, key=sorter):
135
136 for f in _parsed:
135 137 fid = h.FID('', f['filename'])
136 138 c.files.append([fid, f['operation'], f['filename'], f['stats']])
137 139 diff = diff_processor.as_html(enable_comments=False, diff_lines=[f])
138 140 c.changes[fid] = [f['operation'], f['filename'], diff]
139 141
140 142 return render('compare/compare_diff.html')
@@ -1,90 +1,90 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 <div class="container">
37 37 <table class="compare_view_commits noborder">
38 38 %for cnt, cs in enumerate(c.cs_ranges):
39 39 <tr>
40 40 <td><div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),14)}"/></div></td>
41 <td>
42 %if cs.raw_id in c.statuses:
43 <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>
44 %endif
45 </td>
41 46 <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</td>
42 47 <td><div class="author">${h.person(cs.author)}</div></td>
43 48 <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
44 <td>
45 %if hasattr(c,'statuses') and c.statuses:
46 <div title="${_('Changeset status')}" class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[cnt])}" /></div>
47 %endif
48 </td>
49 49 <td><div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message),c.repo_name)}</div></td>
50 50 </tr>
51 51 %endfor
52 52 </table>
53 53 </div>
54 54 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
55 55 <div class="cs_files">
56 56 %for fid, change, f, stat in c.files:
57 57 <div class="cs_${change}">
58 58 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
59 59 <div class="changes">${h.fancy_file_stats(stat)}</div>
60 60 </div>
61 61 %endfor
62 62 </div>
63 63 </div>
64 64 </div>
65 65
66 66 ## diff block
67 67 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
68 68 %for fid, change, f, stat in c.files:
69 69 ${diff_block.diff_block_simple([c.changes[fid]])}
70 70 %endfor
71 71
72 72 <script type="text/javascript">
73 73
74 74 YUE.onDOMReady(function(){
75 75
76 76 YUE.on(YUQ('.diff-menu-activate'),'click',function(e){
77 77 var act = e.currentTarget.nextElementSibling;
78 78
79 79 if(YUD.hasClass(act,'active')){
80 80 YUD.removeClass(act,'active');
81 81 YUD.setStyle(act,'display','none');
82 82 }else{
83 83 YUD.addClass(act,'active');
84 84 YUD.setStyle(act,'display','');
85 85 }
86 86 });
87 87 })
88 88 </script>
89 89 </div>
90 90 </%def>
General Comments 0
You need to be logged in to leave comments. Login now