Mercurial > kallithea
comparison rhodecode/lib/diffs.py @ 2347:58bcaf1b2fe2 codereview
added stats of line changes and operation (A/M/D) into diffs lib
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 27 May 2012 23:28:22 +0200 |
parents | 8fe7c1024719 |
children | 0edbffa9e2e2 |
comparison
equal
deleted
inserted
replaced
2346:8fe7c1024719 | 2347:58bcaf1b2fe2 |
---|---|
169 self.__udiff, iterator_copy = tee(self.__udiff) | 169 self.__udiff, iterator_copy = tee(self.__udiff) |
170 return iterator_copy | 170 return iterator_copy |
171 | 171 |
172 def _extract_rev(self, line1, line2): | 172 def _extract_rev(self, line1, line2): |
173 """ | 173 """ |
174 Extract the filename and revision hint from a line. | 174 Extract the operation (A/M/D), filename and revision hint from a line. |
175 """ | 175 """ |
176 | 176 |
177 try: | 177 try: |
178 if line1.startswith('--- ') and line2.startswith('+++ '): | 178 if line1.startswith('--- ') and line2.startswith('+++ '): |
179 l1 = line1[4:].split(None, 1) | 179 l1 = line1[4:].split(None, 1) |
187 new_rev = l2[1] if len(l2) == 2 else 'new' | 187 new_rev = l2[1] if len(l2) == 2 else 'new' |
188 | 188 |
189 filename = (old_filename | 189 filename = (old_filename |
190 if old_filename != '/dev/null' else new_filename) | 190 if old_filename != '/dev/null' else new_filename) |
191 | 191 |
192 return filename, new_rev, old_rev | 192 operation = 'D' if new_filename == '/dev/null' else None |
193 if not operation: | |
194 operation = 'M' if old_filename != '/dev/null' else 'A' | |
195 | |
196 return operation, filename, new_rev, old_rev | |
193 except (ValueError, IndexError): | 197 except (ValueError, IndexError): |
194 pass | 198 pass |
195 | 199 |
196 return None, None, None | 200 return None, None, None, None |
197 | 201 |
198 def _parse_gitdiff(self, diffiterator): | 202 def _parse_gitdiff(self, diffiterator): |
199 def line_decoder(l): | 203 def line_decoder(l): |
200 if l.startswith('+') and not l.startswith('+++'): | 204 if l.startswith('+') and not l.startswith('+++'): |
201 self.adds += 1 | 205 self.adds += 1 |
286 files = [] | 290 files = [] |
287 try: | 291 try: |
288 line = lineiter.next() | 292 line = lineiter.next() |
289 # skip first context | 293 # skip first context |
290 skipfirst = True | 294 skipfirst = True |
295 | |
291 while 1: | 296 while 1: |
292 # continue until we found the old file | 297 # continue until we found the old file |
293 if not line.startswith('--- '): | 298 if not line.startswith('--- '): |
294 line = lineiter.next() | 299 line = lineiter.next() |
295 continue | 300 continue |
296 | 301 |
297 chunks = [] | 302 chunks = [] |
298 filename, old_rev, new_rev = \ | 303 stats = [0, 0] |
304 operation, filename, old_rev, new_rev = \ | |
299 self._extract_rev(line, lineiter.next()) | 305 self._extract_rev(line, lineiter.next()) |
300 files.append({ | 306 files.append({ |
301 'filename': filename, | 307 'filename': filename, |
302 'old_revision': old_rev, | 308 'old_revision': old_rev, |
303 'new_revision': new_rev, | 309 'new_revision': new_rev, |
304 'chunks': chunks | 310 'chunks': chunks, |
311 'operation': operation, | |
312 'stats': stats, | |
305 }) | 313 }) |
306 | 314 |
307 line = lineiter.next() | 315 line = lineiter.next() |
308 while line: | 316 while line: |
317 | |
309 match = self._chunk_re.match(line) | 318 match = self._chunk_re.match(line) |
310 if not match: | 319 if not match: |
311 break | 320 break |
312 | 321 |
313 lines = [] | 322 lines = [] |
344 if command in '#@': | 353 if command in '#@': |
345 continue | 354 continue |
346 elif command == '+': | 355 elif command == '+': |
347 affects_new = True | 356 affects_new = True |
348 action = 'add' | 357 action = 'add' |
358 stats[0] += 1 | |
349 elif command == '-': | 359 elif command == '-': |
350 affects_old = True | 360 affects_old = True |
351 action = 'del' | 361 action = 'del' |
362 stats[1] += 1 | |
352 else: | 363 else: |
353 affects_old = affects_new = True | 364 affects_old = affects_new = True |
354 action = 'unmod' | 365 action = 'unmod' |
355 | 366 |
356 old_line += affects_old | 367 old_line += affects_old |
360 'new_lineno': affects_new and new_line or '', | 371 'new_lineno': affects_new and new_line or '', |
361 'action': action, | 372 'action': action, |
362 'line': line | 373 'line': line |
363 }) | 374 }) |
364 line = lineiter.next() | 375 line = lineiter.next() |
365 | |
366 except StopIteration: | 376 except StopIteration: |
367 pass | 377 pass |
368 | 378 |
369 # highlight inline changes | 379 # highlight inline changes |
370 for _ in files: | 380 for _ in files: |
371 for chunk in chunks: | 381 for chunk in chunks: |
372 lineiter = iter(chunk) | 382 lineiter = iter(chunk) |
373 #first = True | |
374 try: | 383 try: |
375 while 1: | 384 while 1: |
376 line = lineiter.next() | 385 line = lineiter.next() |
377 if line['action'] != 'unmod': | 386 if line['action'] != 'unmod': |
378 nextline = lineiter.next() | 387 nextline = lineiter.next() |
380 nextline['action'] == line['action']: | 389 nextline['action'] == line['action']: |
381 continue | 390 continue |
382 self.differ(line, nextline) | 391 self.differ(line, nextline) |
383 except StopIteration: | 392 except StopIteration: |
384 pass | 393 pass |
385 | |
386 return files | 394 return files |
387 | 395 |
388 def prepare(self): | 396 def prepare(self): |
389 """ | 397 """ |
390 Prepare the passed udiff for HTML rendering. It'l return a list | 398 Prepare the passed udiff for HTML rendering. It'l return a list |
422 udiff_copy = self._parse_gitdiff(udiff_copy) | 430 udiff_copy = self._parse_gitdiff(udiff_copy) |
423 return u''.join(udiff_copy) | 431 return u''.join(udiff_copy) |
424 | 432 |
425 def as_html(self, table_class='code-difftable', line_class='line', | 433 def as_html(self, table_class='code-difftable', line_class='line', |
426 new_lineno_class='lineno old', old_lineno_class='lineno new', | 434 new_lineno_class='lineno old', old_lineno_class='lineno new', |
427 code_class='code', enable_comments=False): | 435 code_class='code', enable_comments=False, diff_lines=None): |
428 """ | 436 """ |
429 Return udiff as html table with customized css classes | 437 Return udiff as html table with customized css classes |
430 """ | 438 """ |
431 def _link_to_if(condition, label, url): | 439 def _link_to_if(condition, label, url): |
432 """ | 440 """ |
438 'url': url, | 446 'url': url, |
439 'label': label | 447 'label': label |
440 } | 448 } |
441 else: | 449 else: |
442 return label | 450 return label |
443 diff_lines = self.prepare() | 451 if diff_lines is None: |
452 diff_lines = self.prepare() | |
444 _html_empty = True | 453 _html_empty = True |
445 _html = [] | 454 _html = [] |
446 _html.append('''<table class="%(table_class)s">\n''' % { | 455 _html.append('''<table class="%(table_class)s">\n''' % { |
447 'table_class': table_class | 456 'table_class': table_class |
448 }) | 457 }) |