##// END OF EJS Templates
#93 fixed errors on new revranges generation
marcink -
r978:6d223936 beta
parent child Browse files
Show More
@@ -1,241 +1,242 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.changeset
3 rhodecode.controllers.changeset
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 changeset controller for pylons showoing changes beetween
6 changeset controller for pylons showoing changes beetween
7 revisions
7 revisions
8
8
9 :created_on: Apr 25, 2010
9 :created_on: Apr 25, 2010
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software; you can redistribute it and/or
14 # This program is free software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License
15 # modify it under the terms of the GNU General Public License
16 # as published by the Free Software Foundation; version 2
16 # as published by the Free Software Foundation; version 2
17 # of the License or (at your opinion) any later version of the license.
17 # of the License or (at your opinion) any later version of the license.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 # MA 02110-1301, USA.
27 # MA 02110-1301, USA.
28 import logging
28 import logging
29 import traceback
29 import traceback
30
30
31 from pylons import tmpl_context as c, url, request, response
31 from pylons import tmpl_context as c, url, request, response
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 import rhodecode.lib.helpers as h
35 import rhodecode.lib.helpers as h
36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 from rhodecode.lib.base import BaseController, render
37 from rhodecode.lib.base import BaseController, render
38 from rhodecode.lib.utils import EmptyChangeset
38 from rhodecode.lib.utils import EmptyChangeset
39 from rhodecode.model.scm import ScmModel
39 from rhodecode.model.scm import ScmModel
40
40
41 from vcs.exceptions import RepositoryError, ChangesetError
41 from vcs.exceptions import RepositoryError, ChangesetError, \
42 ChangesetDoesNotExistError
42 from vcs.nodes import FileNode
43 from vcs.nodes import FileNode
43 from vcs.utils import diffs as differ
44 from vcs.utils import diffs as differ
44 from vcs.utils.ordered_dict import OrderedDict
45 from vcs.utils.ordered_dict import OrderedDict
45
46
46 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
47
48
48 class ChangesetController(BaseController):
49 class ChangesetController(BaseController):
49
50
50 @LoginRequired()
51 @LoginRequired()
51 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 'repository.admin')
53 'repository.admin')
53 def __before__(self):
54 def __before__(self):
54 super(ChangesetController, self).__before__()
55 super(ChangesetController, self).__before__()
55
56
56 def index(self, revision):
57 def index(self, revision):
57 hg_model = ScmModel()
58 hg_model = ScmModel()
58
59
59 def wrap_to_table(str):
60 def wrap_to_table(str):
60
61
61 return '''<table class="code-difftable">
62 return '''<table class="code-difftable">
62 <tr class="line">
63 <tr class="line">
63 <td class="lineno new"></td>
64 <td class="lineno new"></td>
64 <td class="code"><pre>%s</pre></td>
65 <td class="code"><pre>%s</pre></td>
65 </tr>
66 </tr>
66 </table>''' % str
67 </table>''' % str
67
68
68 def get_cs_range(repo, rev_start, rev_end):
69 def get_cs_range(repo, rev_start, rev_end):
69 """
70 """
70 Temp fix function until VCS will handle that
71 Temp fix function until VCS will handle that
71 see issue #48
72 see issue #48
72 :param rev_start:
73 :param rev_start:
73 :param rev_end:
74 :param rev_end:
74 """
75 """
75
76
76 start_cs = repo.get_changeset(rev_start)
77 start_cs = repo.get_changeset(rev_start)
77 end_cs = repo.get_changeset(rev_end)
78 end_cs = repo.get_changeset(rev_end)
78
79
79 if start_cs.revision >= end_cs.revision:
80 if start_cs.revision >= end_cs.revision:
80 raise Exception('Start cannot be after End')
81 raise Exception('Start revision cannot be after End')
81
82
82 yield start_cs
83 yield start_cs
83
84
84 while 1:
85 while 1:
85 next = start_cs.next()
86 next = start_cs.next()
86 yield next
87 yield next
87 start_cs = next
88 start_cs = next
88 if next == end_cs:
89 if next == end_cs:
89 break
90 break
90
91
91 #======================================================================
92 #======================================================================
92 # REAL CODE BELOW
93 # REAL CODE BELOW
93 #======================================================================
94 #======================================================================
94 #get ranges of revisions if preset
95 #get ranges of revisions if preset
95 rev_range = revision.split('...')[:2]
96 rev_range = revision.split('...')[:2]
96
97
97 try:
98 try:
98 repo = hg_model.get_repo(c.repo_name)
99 repo = hg_model.get_repo(c.repo_name)
99 if len(rev_range) == 2:
100 if len(rev_range) == 2:
100 rev_start = rev_range[0]
101 rev_start = rev_range[0]
101 rev_end = rev_range[1]
102 rev_end = rev_range[1]
102 rev_ranges = get_cs_range(repo, rev_start, rev_end)
103 rev_ranges = get_cs_range(repo, rev_start, rev_end)
104 c.cs_ranges = list(rev_ranges)
103
105
104 else:
106 else:
105 rev_ranges = [repo.get_changeset(revision)]
107 rev_ranges = [repo.get_changeset(revision)]
106 except RepositoryError, e:
108 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
107 log.error(traceback.format_exc())
109 log.error(traceback.format_exc())
108 h.flash(str(e), category='warning')
110 h.flash(str(e), category='warning')
109 return redirect(url('home'))
111 return redirect(url('home'))
110
112
111 c.changes = OrderedDict()
113 c.changes = OrderedDict()
112 c.sum_added = 0
114 c.sum_added = 0
113 c.sum_removed = 0
115 c.sum_removed = 0
114
116
115 c.cs_ranges = list(rev_ranges)
116
117
117 for changeset in c.cs_ranges:
118 for changeset in c.cs_ranges:
118 c.changes[changeset.raw_id] = []
119 c.changes[changeset.raw_id] = []
119 try:
120 try:
120 changeset_parent = changeset.parents[0]
121 changeset_parent = changeset.parents[0]
121 except IndexError:
122 except IndexError:
122 changeset_parent = None
123 changeset_parent = None
123
124
124
125
125 #==================================================================
126 #==================================================================
126 # ADDED FILES
127 # ADDED FILES
127 #==================================================================
128 #==================================================================
128 for node in changeset.added:
129 for node in changeset.added:
129 filenode_old = FileNode(node.path, '', EmptyChangeset())
130 filenode_old = FileNode(node.path, '', EmptyChangeset())
130 if filenode_old.is_binary or node.is_binary:
131 if filenode_old.is_binary or node.is_binary:
131 diff = wrap_to_table(_('binary file'))
132 diff = wrap_to_table(_('binary file'))
132 else:
133 else:
133 c.sum_added += node.size
134 c.sum_added += node.size
134 if c.sum_added < self.cut_off_limit:
135 if c.sum_added < self.cut_off_limit:
135 f_udiff = differ.get_udiff(filenode_old, node)
136 f_udiff = differ.get_udiff(filenode_old, node)
136 diff = differ.DiffProcessor(f_udiff).as_html()
137 diff = differ.DiffProcessor(f_udiff).as_html()
137
138
138 else:
139 else:
139 diff = wrap_to_table(_('Changeset is to big and was cut'
140 diff = wrap_to_table(_('Changeset is to big and was cut'
140 ' off, see raw changeset instead'))
141 ' off, see raw changeset instead'))
141
142
142 cs1 = None
143 cs1 = None
143 cs2 = node.last_changeset.raw_id
144 cs2 = node.last_changeset.raw_id
144 c.changes[changeset.raw_id].append(('added', node, diff, cs1, cs2))
145 c.changes[changeset.raw_id].append(('added', node, diff, cs1, cs2))
145
146
146 #==================================================================
147 #==================================================================
147 # CHANGED FILES
148 # CHANGED FILES
148 #==================================================================
149 #==================================================================
149 for node in changeset.changed:
150 for node in changeset.changed:
150 try:
151 try:
151 filenode_old = changeset_parent.get_node(node.path)
152 filenode_old = changeset_parent.get_node(node.path)
152 except ChangesetError:
153 except ChangesetError:
153 filenode_old = FileNode(node.path, '', EmptyChangeset())
154 filenode_old = FileNode(node.path, '', EmptyChangeset())
154
155
155 if filenode_old.is_binary or node.is_binary:
156 if filenode_old.is_binary or node.is_binary:
156 diff = wrap_to_table(_('binary file'))
157 diff = wrap_to_table(_('binary file'))
157 else:
158 else:
158
159
159 if c.sum_removed < self.cut_off_limit:
160 if c.sum_removed < self.cut_off_limit:
160 f_udiff = differ.get_udiff(filenode_old, node)
161 f_udiff = differ.get_udiff(filenode_old, node)
161 diff = differ.DiffProcessor(f_udiff).as_html()
162 diff = differ.DiffProcessor(f_udiff).as_html()
162 if diff:
163 if diff:
163 c.sum_removed += len(diff)
164 c.sum_removed += len(diff)
164 else:
165 else:
165 diff = wrap_to_table(_('Changeset is to big and was cut'
166 diff = wrap_to_table(_('Changeset is to big and was cut'
166 ' off, see raw changeset instead'))
167 ' off, see raw changeset instead'))
167
168
168
169
169 cs1 = filenode_old.last_changeset.raw_id
170 cs1 = filenode_old.last_changeset.raw_id
170 cs2 = node.last_changeset.raw_id
171 cs2 = node.last_changeset.raw_id
171 c.changes[changeset.raw_id].append(('changed', node, diff, cs1, cs2))
172 c.changes[changeset.raw_id].append(('changed', node, diff, cs1, cs2))
172
173
173 #==================================================================
174 #==================================================================
174 # REMOVED FILES
175 # REMOVED FILES
175 #==================================================================
176 #==================================================================
176 for node in changeset.removed:
177 for node in changeset.removed:
177 c.changes[changeset.raw_id].append(('removed', node, None, None, None))
178 c.changes[changeset.raw_id].append(('removed', node, None, None, None))
178
179
179 if len(c.cs_ranges) == 1:
180 if len(c.cs_ranges) == 1:
180 c.changeset = c.cs_ranges[0]
181 c.changeset = c.cs_ranges[0]
181 c.changes = c.changes[c.changeset.raw_id]
182 c.changes = c.changes[c.changeset.raw_id]
182
183
183 return render('changeset/changeset.html')
184 return render('changeset/changeset.html')
184 else:
185 else:
185 return render('changeset/changeset_range.html')
186 return render('changeset/changeset_range.html')
186
187
187 def raw_changeset(self, revision):
188 def raw_changeset(self, revision):
188
189
189 hg_model = ScmModel()
190 hg_model = ScmModel()
190 method = request.GET.get('diff', 'show')
191 method = request.GET.get('diff', 'show')
191 try:
192 try:
192 r = hg_model.get_repo(c.repo_name)
193 r = hg_model.get_repo(c.repo_name)
193 c.scm_type = r.alias
194 c.scm_type = r.alias
194 c.changeset = r.get_changeset(revision)
195 c.changeset = r.get_changeset(revision)
195 except RepositoryError:
196 except RepositoryError:
196 log.error(traceback.format_exc())
197 log.error(traceback.format_exc())
197 return redirect(url('home'))
198 return redirect(url('home'))
198 else:
199 else:
199 try:
200 try:
200 c.changeset_parent = c.changeset.parents[0]
201 c.changeset_parent = c.changeset.parents[0]
201 except IndexError:
202 except IndexError:
202 c.changeset_parent = None
203 c.changeset_parent = None
203 c.changes = []
204 c.changes = []
204
205
205 for node in c.changeset.added:
206 for node in c.changeset.added:
206 filenode_old = FileNode(node.path, '')
207 filenode_old = FileNode(node.path, '')
207 if filenode_old.is_binary or node.is_binary:
208 if filenode_old.is_binary or node.is_binary:
208 diff = _('binary file') + '\n'
209 diff = _('binary file') + '\n'
209 else:
210 else:
210 f_udiff = differ.get_udiff(filenode_old, node)
211 f_udiff = differ.get_udiff(filenode_old, node)
211 diff = differ.DiffProcessor(f_udiff).raw_diff()
212 diff = differ.DiffProcessor(f_udiff).raw_diff()
212
213
213 cs1 = None
214 cs1 = None
214 cs2 = node.last_changeset.raw_id
215 cs2 = node.last_changeset.raw_id
215 c.changes.append(('added', node, diff, cs1, cs2))
216 c.changes.append(('added', node, diff, cs1, cs2))
216
217
217 for node in c.changeset.changed:
218 for node in c.changeset.changed:
218 filenode_old = c.changeset_parent.get_node(node.path)
219 filenode_old = c.changeset_parent.get_node(node.path)
219 if filenode_old.is_binary or node.is_binary:
220 if filenode_old.is_binary or node.is_binary:
220 diff = _('binary file')
221 diff = _('binary file')
221 else:
222 else:
222 f_udiff = differ.get_udiff(filenode_old, node)
223 f_udiff = differ.get_udiff(filenode_old, node)
223 diff = differ.DiffProcessor(f_udiff).raw_diff()
224 diff = differ.DiffProcessor(f_udiff).raw_diff()
224
225
225 cs1 = filenode_old.last_changeset.raw_id
226 cs1 = filenode_old.last_changeset.raw_id
226 cs2 = node.last_changeset.raw_id
227 cs2 = node.last_changeset.raw_id
227 c.changes.append(('changed', node, diff, cs1, cs2))
228 c.changes.append(('changed', node, diff, cs1, cs2))
228
229
229 response.content_type = 'text/plain'
230 response.content_type = 'text/plain'
230
231
231 if method == 'download':
232 if method == 'download':
232 response.content_disposition = 'attachment; filename=%s.patch' % revision
233 response.content_disposition = 'attachment; filename=%s.patch' % revision
233
234
234 parent = True if len(c.changeset.parents) > 0 else False
235 parent = True if len(c.changeset.parents) > 0 else False
235 c.parent_tmpl = 'Parent %s' % c.changeset.parents[0].raw_id if parent else ''
236 c.parent_tmpl = 'Parent %s' % c.changeset.parents[0].raw_id if parent else ''
236
237
237 c.diffs = ''
238 c.diffs = ''
238 for x in c.changes:
239 for x in c.changes:
239 c.diffs += x[2]
240 c.diffs += x[2]
240
241
241 return render('changeset/raw_changeset.html')
242 return render('changeset/raw_changeset.html')
General Comments 0
You need to be logged in to leave comments. Login now