comparison rhodecode/controllers/changeset.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 d4a7b6c82efe
children 89efedac4e6c
comparison
equal deleted inserted replaced
1788:ef0613584ced 1789:17caf4efe15c
44 from rhodecode.lib.compat import OrderedDict 44 from rhodecode.lib.compat import OrderedDict
45 from rhodecode.lib import diffs 45 from rhodecode.lib import diffs
46 from rhodecode.model.db import ChangesetComment 46 from rhodecode.model.db import ChangesetComment
47 from rhodecode.model.comment import ChangesetCommentsModel 47 from rhodecode.model.comment import ChangesetCommentsModel
48 from rhodecode.model.meta import Session 48 from rhodecode.model.meta import Session
49 from rhodecode.lib.diffs import wrapped_diff
49 50
50 log = logging.getLogger(__name__) 51 log = logging.getLogger(__name__)
51 52
52 53
53 def anchor_url(revision, path): 54 def anchor_url(revision, path):
143 144
144 params['anchor'] = fileid 145 params['anchor'] = fileid
145 return h.link_to(lbl, h.url.current(**params)) 146 return h.link_to(lbl, h.url.current(**params))
146 147
147 148
148 def wrap_to_table(str_):
149 return '''<table class="code-difftable">
150 <tr class="line no-comment">
151 <td class="lineno new"></td>
152 <td class="code no-comment"><pre>%s</pre></td>
153 </tr>
154 </table>''' % str_
155
156
157 class ChangesetController(BaseRepoController): 149 class ChangesetController(BaseRepoController):
158 150
159 @LoginRequired() 151 @LoginRequired()
160 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 152 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
161 'repository.admin') 153 'repository.admin')
190 log.error(traceback.format_exc()) 182 log.error(traceback.format_exc())
191 h.flash(str(e), category='warning') 183 h.flash(str(e), category='warning')
192 return redirect(url('home')) 184 return redirect(url('home'))
193 185
194 c.changes = OrderedDict() 186 c.changes = OrderedDict()
195 c.sum_added = 0 187
196 c.sum_removed = 0 188 c.lines_added = 0 # count of lines added
197 c.lines_added = 0 189 c.lines_deleted = 0 # count of lines removes
198 c.lines_deleted = 0 190
191 cumulative_diff = 0
199 c.cut_off = False # defines if cut off limit is reached 192 c.cut_off = False # defines if cut off limit is reached
200 193
201 c.comments = [] 194 c.comments = []
202 c.inline_comments = [] 195 c.inline_comments = []
203 c.inline_cnt = 0 196 c.inline_cnt = 0
218 211
219 #================================================================== 212 #==================================================================
220 # ADDED FILES 213 # ADDED FILES
221 #================================================================== 214 #==================================================================
222 for node in changeset.added: 215 for node in changeset.added:
223 216 fid = h.FID(revision, node.path)
224 filenode_old = FileNode(node.path, '', EmptyChangeset()) 217 line_context_lcl = get_line_ctx(fid, request.GET)
225 if filenode_old.is_binary or node.is_binary: 218 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
226 diff = wrap_to_table(_('binary file')) 219 lim = self.cut_off_limit
227 st = (0, 0) 220 if cumulative_diff > self.cut_off_limit:
228 else: 221 lim = -1
229 # in this case node.size is good parameter since those are 222 size, cs1, cs2, diff, st = wrapped_diff(filenode_old=None,
230 # added nodes and their size defines how many changes were 223 filenode_new=node,
231 # made 224 cut_off_limit=lim,
232 c.sum_added += node.size 225 ignore_whitespace=ign_whitespace_lcl,
233 fid = h.FID(revision, node.path) 226 line_context=line_context_lcl,
234 line_context_lcl = get_line_ctx(fid, request.GET) 227 enable_comments=enable_comments)
235 ignore_whitespace_lcl = get_ignore_ws(fid, request.GET) 228 cumulative_diff += size
236 if c.sum_added < self.cut_off_limit:
237 f_gitdiff = diffs.get_gitdiff(filenode_old, node,
238 ignore_whitespace=ignore_whitespace_lcl,
239 context=line_context_lcl)
240 d = diffs.DiffProcessor(f_gitdiff, format='gitdiff')
241
242 st = d.stat()
243 diff = d.as_html(enable_comments=enable_comments)
244
245 else:
246 diff = wrap_to_table(_('Changeset is to big and '
247 'was cut off, see raw '
248 'changeset instead'))
249 c.cut_off = True
250 break
251
252 cs1 = None
253 cs2 = node.last_changeset.raw_id
254 c.lines_added += st[0] 229 c.lines_added += st[0]
255 c.lines_deleted += st[1] 230 c.lines_deleted += st[1]
256 c.changes[changeset.raw_id].append(('added', node, diff, 231 c.changes[changeset.raw_id].append(('added', node, diff,
257 cs1, cs2, st)) 232 cs1, cs2, st))
258 233
259 #================================================================== 234 #==================================================================
260 # CHANGED FILES 235 # CHANGED FILES
261 #================================================================== 236 #==================================================================
262 if not c.cut_off: 237 for node in changeset.changed:
263 for node in changeset.changed: 238 try:
264 try: 239 filenode_old = changeset_parent.get_node(node.path)
265 filenode_old = changeset_parent.get_node(node.path) 240 except ChangesetError:
266 except ChangesetError: 241 log.warning('Unable to fetch parent node for diff')
267 log.warning('Unable to fetch parent node for diff') 242 filenode_old = FileNode(node.path, '', EmptyChangeset())
268 filenode_old = FileNode(node.path, '', 243
269 EmptyChangeset()) 244 fid = h.FID(revision, node.path)
270 245 line_context_lcl = get_line_ctx(fid, request.GET)
271 if filenode_old.is_binary or node.is_binary: 246 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
272 diff = wrap_to_table(_('binary file')) 247 lim = self.cut_off_limit
273 st = (0, 0) 248 if cumulative_diff > self.cut_off_limit:
274 else: 249 lim = -1
275 250 size, cs1, cs2, diff, st = wrapped_diff(filenode_old=filenode_old,
276 if c.sum_removed < self.cut_off_limit: 251 filenode_new=node,
277 fid = h.FID(revision, node.path) 252 cut_off_limit=lim,
278 line_context_lcl = get_line_ctx(fid, request.GET) 253 ignore_whitespace=ign_whitespace_lcl,
279 ignore_whitespace_lcl = get_ignore_ws(fid, request.GET,) 254 line_context=line_context_lcl,
280 f_gitdiff = diffs.get_gitdiff(filenode_old, node, 255 enable_comments=enable_comments)
281 ignore_whitespace=ignore_whitespace_lcl, 256 cumulative_diff += size
282 context=line_context_lcl) 257 c.lines_added += st[0]
283 d = diffs.DiffProcessor(f_gitdiff, 258 c.lines_deleted += st[1]
284 format='gitdiff') 259 c.changes[changeset.raw_id].append(('changed', node, diff,
285 st = d.stat() 260 cs1, cs2, st))
286 if (st[0] + st[1]) * 256 > self.cut_off_limit:
287 diff = wrap_to_table(_('Diff is to big '
288 'and was cut off, see '
289 'raw diff instead'))
290 else:
291 diff = d.as_html(enable_comments=enable_comments)
292
293 if diff:
294 c.sum_removed += len(diff)
295 else:
296 diff = wrap_to_table(_('Changeset is to big and '
297 'was cut off, see raw '
298 'changeset instead'))
299 c.cut_off = True
300 break
301
302 cs1 = filenode_old.last_changeset.raw_id
303 cs2 = node.last_changeset.raw_id
304 c.lines_added += st[0]
305 c.lines_deleted += st[1]
306 c.changes[changeset.raw_id].append(('changed', node, diff,
307 cs1, cs2, st))
308 261
309 #================================================================== 262 #==================================================================
310 # REMOVED FILES 263 # REMOVED FILES
311 #================================================================== 264 #==================================================================
312 if not c.cut_off: 265 for node in changeset.removed:
313 for node in changeset.removed: 266 c.changes[changeset.raw_id].append(('removed', node, None,
314 c.changes[changeset.raw_id].append(('removed', node, None, 267 None, None, (0, 0)))
315 None, None, (0, 0)))
316 268
317 # count inline comments 269 # count inline comments
318 for path, lines in c.inline_comments: 270 for path, lines in c.inline_comments:
319 for comments in lines.values(): 271 for comments in lines.values():
320 c.inline_cnt += len(comments) 272 c.inline_cnt += len(comments)