##// END OF EJS Templates
started work on #93 added rev ranges view, checkboxes in changelog to view ranges of changes
marcink -
r977:28524453 beta
parent child Browse files
Show More
@@ -0,0 +1,86
1 <%inherit file="/base/base.html"/>
2
3 <%def name="title()">
4 ${c.repo_name} ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)} - ${c.rhodecode_name}
5 </%def>
6
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(u'Home',h.url('/'))}
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
11 &raquo;
12 ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)}
13 </%def>
14
15 <%def name="page_nav()">
16 ${self.menu('changelog')}
17 </%def>
18
19 <%def name="main()">
20 <div class="box">
21 <!-- box / title -->
22 <div class="title">
23 ${self.breadcrumbs()}
24 </div>
25 <div class="table">
26 <div id="body" class="diffblock">
27 <div class="code-header">
28 <div>
29 ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)}
30 ##&raquo; <span>${h.link_to(_('raw diff'),
31 ##h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</span>
32 ##&raquo; <span>${h.link_to(_('download diff'),
33 ##h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</span>
34 </div>
35 </div>
36 </div>
37 <div id="changeset_content">
38 <div class="container">
39
40 </div>
41 <span style="font-size:1.1em;font-weight: bold">${_('Files affected')}</span>
42 <div class="cs_files">
43 %for cs in c.cs_ranges:
44 ${cs}
45 %for change,filenode,diff,cs1,cs2 in c.changes[cs.raw_id]:
46 <div class="cs_${change}">${h.link_to(filenode.path,h.url.current(anchor=h.repo_name_slug('C%s-%s' % (cs.short_id,filenode.path))))}</div>
47 %endfor
48 %endfor
49 </div>
50 </div>
51
52 </div>
53 %for cs in c.cs_ranges:
54 %for change,filenode,diff,cs1,cs2 in c.changes[cs.raw_id]:
55 %if change !='removed':
56 <div style="clear:both;height:10px"></div>
57 <div class="diffblock">
58 <div id="${h.repo_name_slug('C%s-%s' % (cs.short_id,filenode.path))}" class="code-header">
59 <div class="changeset_header">
60 <span class="changeset_file">
61 ${h.link_to_if(change!='removed',filenode.path,h.url('files_home',repo_name=c.repo_name,
62 revision=filenode.changeset.raw_id,f_path=filenode.path))}
63 </span>
64 %if 1:
65 &raquo; <span>${h.link_to(_('diff'),
66 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='diff'))}</span>
67 &raquo; <span>${h.link_to(_('raw diff'),
68 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='raw'))}</span>
69 &raquo; <span>${h.link_to(_('download diff'),
70 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='download'))}</span>
71 %endif
72 </div>
73 </div>
74 <div class="code-body">
75 %if diff:
76 ${diff|n}
77 %else:
78 ${_('No changes in this file')}
79 %endif
80 </div>
81 </div>
82 %endif
83 %endfor
84 %endfor
85 </div>
86 </%def> No newline at end of file
@@ -3,7 +3,8
3 rhodecode.controllers.changeset
3 rhodecode.controllers.changeset
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 changeset controller for pylons
6 changeset controller for pylons showoing changes beetween
7 revisions
7
8
8 :created_on: Apr 25, 2010
9 :created_on: Apr 25, 2010
9 :author: marcink
10 :author: marcink
@@ -40,6 +41,7 from rhodecode.model.scm import ScmModel
40 from vcs.exceptions import RepositoryError, ChangesetError
41 from vcs.exceptions import RepositoryError, ChangesetError
41 from vcs.nodes import FileNode
42 from vcs.nodes import FileNode
42 from vcs.utils import diffs as differ
43 from vcs.utils import diffs as differ
44 from vcs.utils.ordered_dict import OrderedDict
43
45
44 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
45
47
@@ -63,25 +65,67 class ChangesetController(BaseController
63 </tr>
65 </tr>
64 </table>''' % str
66 </table>''' % str
65
67
68 def get_cs_range(repo, rev_start, rev_end):
69 """
70 Temp fix function until VCS will handle that
71 see issue #48
72 :param rev_start:
73 :param rev_end:
74 """
75
76 start_cs = repo.get_changeset(rev_start)
77 end_cs = repo.get_changeset(rev_end)
78
79 if start_cs.revision >= end_cs.revision:
80 raise Exception('Start cannot be after End')
81
82 yield start_cs
83
84 while 1:
85 next = start_cs.next()
86 yield next
87 start_cs = next
88 if next == end_cs:
89 break
90
91 #======================================================================
92 # REAL CODE BELOW
93 #======================================================================
94 #get ranges of revisions if preset
95 rev_range = revision.split('...')[:2]
96
66 try:
97 try:
67 c.changeset = hg_model.get_repo(c.repo_name).get_changeset(revision)
98 repo = hg_model.get_repo(c.repo_name)
99 if len(rev_range) == 2:
100 rev_start = rev_range[0]
101 rev_end = rev_range[1]
102 rev_ranges = get_cs_range(repo, rev_start, rev_end)
103
104 else:
105 rev_ranges = [repo.get_changeset(revision)]
68 except RepositoryError, e:
106 except RepositoryError, e:
69 log.error(traceback.format_exc())
107 log.error(traceback.format_exc())
70 h.flash(str(e), category='warning')
108 h.flash(str(e), category='warning')
71 return redirect(url('home'))
109 return redirect(url('home'))
72 else:
110
73 try:
111 c.changes = OrderedDict()
74 c.changeset_old = c.changeset.parents[0]
112 c.sum_added = 0
75 except IndexError:
113 c.sum_removed = 0
76 c.changeset_old = None
114
77 c.changes = []
115 c.cs_ranges = list(rev_ranges)
78
116
79 #===================================================================
117 for changeset in c.cs_ranges:
118 c.changes[changeset.raw_id] = []
119 try:
120 changeset_parent = changeset.parents[0]
121 except IndexError:
122 changeset_parent = None
123
124
125 #==================================================================
80 # ADDED FILES
126 # ADDED FILES
81 #===================================================================
127 #==================================================================
82 c.sum_added = 0
128 for node in changeset.added:
83 for node in c.changeset.added:
84
85 filenode_old = FileNode(node.path, '', EmptyChangeset())
129 filenode_old = FileNode(node.path, '', EmptyChangeset())
86 if filenode_old.is_binary or node.is_binary:
130 if filenode_old.is_binary or node.is_binary:
87 diff = wrap_to_table(_('binary file'))
131 diff = wrap_to_table(_('binary file'))
@@ -97,15 +141,14 class ChangesetController(BaseController
97
141
98 cs1 = None
142 cs1 = None
99 cs2 = node.last_changeset.raw_id
143 cs2 = node.last_changeset.raw_id
100 c.changes.append(('added', node, diff, cs1, cs2))
144 c.changes[changeset.raw_id].append(('added', node, diff, cs1, cs2))
101
145
102 #===================================================================
146 #==================================================================
103 # CHANGED FILES
147 # CHANGED FILES
104 #===================================================================
148 #==================================================================
105 c.sum_removed = 0
149 for node in changeset.changed:
106 for node in c.changeset.changed:
107 try:
150 try:
108 filenode_old = c.changeset_old.get_node(node.path)
151 filenode_old = changeset_parent.get_node(node.path)
109 except ChangesetError:
152 except ChangesetError:
110 filenode_old = FileNode(node.path, '', EmptyChangeset())
153 filenode_old = FileNode(node.path, '', EmptyChangeset())
111
154
@@ -125,15 +168,21 class ChangesetController(BaseController
125
168
126 cs1 = filenode_old.last_changeset.raw_id
169 cs1 = filenode_old.last_changeset.raw_id
127 cs2 = node.last_changeset.raw_id
170 cs2 = node.last_changeset.raw_id
128 c.changes.append(('changed', node, diff, cs1, cs2))
171 c.changes[changeset.raw_id].append(('changed', node, diff, cs1, cs2))
129
172
130 #===================================================================
173 #==================================================================
131 # REMOVED FILES
174 # REMOVED FILES
132 #===================================================================
175 #==================================================================
133 for node in c.changeset.removed:
176 for node in changeset.removed:
134 c.changes.append(('removed', node, None, None, None))
177 c.changes[changeset.raw_id].append(('removed', node, None, None, None))
178
179 if len(c.cs_ranges) == 1:
180 c.changeset = c.cs_ranges[0]
181 c.changes = c.changes[c.changeset.raw_id]
135
182
136 return render('changeset/changeset.html')
183 return render('changeset/changeset.html')
184 else:
185 return render('changeset/changeset_range.html')
137
186
138 def raw_changeset(self, revision):
187 def raw_changeset(self, revision):
139
188
@@ -148,9 +197,9 class ChangesetController(BaseController
148 return redirect(url('home'))
197 return redirect(url('home'))
149 else:
198 else:
150 try:
199 try:
151 c.changeset_old = c.changeset.parents[0]
200 c.changeset_parent = c.changeset.parents[0]
152 except IndexError:
201 except IndexError:
153 c.changeset_old = None
202 c.changeset_parent = None
154 c.changes = []
203 c.changes = []
155
204
156 for node in c.changeset.added:
205 for node in c.changeset.added:
@@ -166,7 +215,7 class ChangesetController(BaseController
166 c.changes.append(('added', node, diff, cs1, cs2))
215 c.changes.append(('added', node, diff, cs1, cs2))
167
216
168 for node in c.changeset.changed:
217 for node in c.changeset.changed:
169 filenode_old = c.changeset_old.get_node(node.path)
218 filenode_old = c.changeset_parent.get_node(node.path)
170 if filenode_old.is_binary or node.is_binary:
219 if filenode_old.is_binary or node.is_binary:
171 diff = _('binary file')
220 diff = _('binary file')
172 else:
221 else:
@@ -1510,7 +1510,9 float:left;
1510 border:1px solid #CCC;
1510 border:1px solid #CCC;
1511 padding:10px;
1511 padding:10px;
1512 }
1512 }
1513
1513 #graph_content #rev_range_container{
1514 padding:10px 0px;
1515 }
1514 #graph_content .container {
1516 #graph_content .container {
1515 border-bottom:1px solid #CCC;
1517 border-bottom:1px solid #CCC;
1516 border-left:1px solid #CCC;
1518 border-left:1px solid #CCC;
@@ -1531,6 +1533,9 padding-bottom:5px;
1531 font-weight:700;
1533 font-weight:700;
1532 padding-bottom:5px;
1534 padding-bottom:5px;
1533 }
1535 }
1536 #graph_content .container .left .date span{
1537 vertical-align: text-top;
1538 }
1534
1539
1535 #graph_content .container .left .message {
1540 #graph_content .container .left .message {
1536 font-size:100%;
1541 font-size:100%;
@@ -32,21 +32,25
32 </div>
32 </div>
33 <div id="graph_content">
33 <div id="graph_content">
34 <div class="container_header">
34 <div class="container_header">
35
36 ${h.form(h.url.current(),method='get')}
35 ${h.form(h.url.current(),method='get')}
37 <div class="info_box">
36 <div class="info_box">
38 <span>${_('Show')}:</span>
37 <span>${_('Show')}:</span>
39 ${h.text('size',size=1,value=c.size)}
38 ${h.text('size',size=1,value=c.size)}
40 <span>${_('revisions')}</span>
39 <span>${_('revisions')}</span>
41 ${h.submit('set',_('set'))}
40 ${h.submit('set',_('set'))}
41
42 </div>
42 </div>
43 ${h.end_form()}
43 ${h.end_form()}
44 <div id="rev_range_container" style="display:none"></div>
45 </div>
44
46
45 </div>
46 %for cnt,cs in enumerate(c.pagination):
47 %for cnt,cs in enumerate(c.pagination):
47 <div id="chg_${cnt+1}" class="container">
48 <div id="chg_${cnt+1}" class="container">
48 <div class="left">
49 <div class="left">
49 <div class="date">${_('commit')} ${cs.revision}: ${h.short_id(cs.raw_id)}@${cs.date}</div>
50 <div class="date">
51 ${h.checkbox(cs.short_id,class_="changeset_range")}
52 <span>${_('commit')} ${cs.revision}: ${h.short_id(cs.raw_id)}@${cs.date}</span>
53 </div>
50 <div class="author">
54 <div class="author">
51 <div class="gravatar">
55 <div class="gravatar">
52 <img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),20)}"/>
56 <img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),20)}"/>
@@ -113,6 +117,37
113 <script type="text/javascript" src="/js/graph.js"></script>
117 <script type="text/javascript" src="/js/graph.js"></script>
114 <script type="text/javascript">
118 <script type="text/javascript">
115 YAHOO.util.Event.onDOMReady(function(){
119 YAHOO.util.Event.onDOMReady(function(){
120
121 //Monitor range checkboxes and build a link to changesets
122 //ranges
123 var checkboxes = YUD.getElementsByClassName('changeset_range');
124 var url_tmpl = "${h.url('changeset_home',repo_name=c.repo_name,revision='__REVRANGE__')}";
125 YUE.on(checkboxes,'click',function(e){
126 var checked_checkboxes = [];
127 for (pos in checkboxes){
128 if(checkboxes[pos].checked){
129 checked_checkboxes.push(checkboxes[pos]);
130 }
131 }
132 if(checked_checkboxes.length>1){
133 var rev_end = checked_checkboxes[0].name;
134 var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
135
136 var url = url_tmpl.replace('__REVRANGE__',
137 rev_start+'...'+rev_end);
138
139 var link = "<a href="+url+">${_('Show selected changes __S -> __E')}</a>"
140 link = link.replace('__S',rev_start);
141 link = link.replace('__E',rev_end);
142 YUD.get('rev_range_container').innerHTML = link;
143 YUD.setStyle('rev_range_container','display','');
144 }
145 else{
146 YUD.setStyle('rev_range_container','display','none');
147
148 }
149 });
150
116 function set_canvas() {
151 function set_canvas() {
117 var c = document.getElementById('graph_nodes');
152 var c = document.getElementById('graph_nodes');
118 var t = document.getElementById('graph_content');
153 var t = document.getElementById('graph_content');
@@ -126,6 +161,9
126 var jsdata = ${c.jsdata|n};
161 var jsdata = ${c.jsdata|n};
127 var r = new BranchRenderer();
162 var r = new BranchRenderer();
128 r.render(jsdata);
163 r.render(jsdata);
164
165
166
129 });
167 });
130 </script>
168 </script>
131 %else:
169 %else:
@@ -23,7 +23,7
23 ${self.breadcrumbs()}
23 ${self.breadcrumbs()}
24 </div>
24 </div>
25 <div class="table">
25 <div class="table">
26 <div id="body" class="diffblock">
26 <div class="diffblock">
27 <div class="code-header">
27 <div class="code-header">
28 <div>
28 <div>
29 ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
29 ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
@@ -81,7 +81,7
81 <span style="font-size:1.1em;font-weight: bold">${_('Files affected')}</span>
81 <span style="font-size:1.1em;font-weight: bold">${_('Files affected')}</span>
82 <div class="cs_files">
82 <div class="cs_files">
83 %for change,filenode,diff,cs1,cs2 in c.changes:
83 %for change,filenode,diff,cs1,cs2 in c.changes:
84 <div class="cs_${change}">${h.link_to(filenode.path,h.url.current(anchor='CHANGE-%s'%filenode.path))}</div>
84 <div class="cs_${change}">${h.link_to(filenode.path,h.url.current(anchor=h.repo_name_slug('C%s' % filenode.path)))}</div>
85 %endfor
85 %endfor
86 </div>
86 </div>
87 </div>
87 </div>
@@ -91,8 +91,8
91 %for change,filenode,diff,cs1,cs2 in c.changes:
91 %for change,filenode,diff,cs1,cs2 in c.changes:
92 %if change !='removed':
92 %if change !='removed':
93 <div style="clear:both;height:10px"></div>
93 <div style="clear:both;height:10px"></div>
94 <div id="body" class="diffblock">
94 <div class="diffblock">
95 <div id="${'CHANGE-%s'%filenode.path}" class="code-header">
95 <div id="${h.repo_name_slug('C%s' % filenode.path)}" class="code-header">
96 <div class="changeset_header">
96 <div class="changeset_header">
97 <span class="changeset_file">
97 <span class="changeset_file">
98 ${h.link_to_if(change!='removed',filenode.path,h.url('files_home',repo_name=c.repo_name,
98 ${h.link_to_if(change!='removed',filenode.path,h.url('files_home',repo_name=c.repo_name,
@@ -119,6 +119,4
119 %endif
119 %endif
120 %endfor
120 %endfor
121 </div>
121 </div>
122 </div>
123
124 </%def> No newline at end of file
122 </%def>
General Comments 0
You need to be logged in to leave comments. Login now