changeset 4692:7b8cbcb927b2

diff: refactor diff parsing - fail on any parse error instead of showing an incorrect diff
author Mads Kiilerich <madski@unity3d.com>
date Mon, 15 Dec 2014 13:47:36 +0100
parents 42d18c125aa8
children 9740ec3be07a
files kallithea/lib/diffs.py kallithea/tests/fixtures/diff_with_diff_data.diff kallithea/tests/fixtures/hg_diff_mod_single_file_and_rename_and_chmod.diff kallithea/tests/models/test_diff_parsers.py
diffstat 4 files changed, 25 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/lib/diffs.py	Mon Dec 15 13:47:36 2014 +0100
+++ b/kallithea/lib/diffs.py	Mon Dec 15 13:47:36 2014 +0100
@@ -506,21 +506,21 @@
         Parse the diff and return data for the template.
         """
 
-        lineiter = iter(diff)
         stats = [0, 0]
+        (old_line, old_end, new_line, new_end) = (None, None, None, None)
 
         try:
             chunks = []
-            line = lineiter.next()
+            line = diff.next()
 
-            while line:
+            while True:
                 lines = []
                 chunks.append(lines)
 
                 match = self._chunk_re.match(line)
 
                 if not match:
-                    break
+                    raise Exception('error parsing diff @@ line %r' % line)
 
                 gr = match.groups()
                 (old_line, old_end,
@@ -542,19 +542,16 @@
                             'line':       line,
                         })
 
-                line = lineiter.next()
+                line = diff.next()
 
                 while old_line < old_end or new_line < new_end:
-                    command = ' '
-                    if line:
-                        command = line[0]
+                    if not line:
+                        raise Exception('error parsing diff - empty line at -%s+%s' % (old_line, new_line))
 
                     affects_old = affects_new = False
 
-                    # ignore those if we don't expect them
-                    if command in '#@':
-                        continue
-                    elif command == '+':
+                    command = line[0]
+                    if command == '+':
                         affects_new = True
                         action = 'add'
                         stats[0] += 1
@@ -562,9 +559,11 @@
                         affects_old = True
                         action = 'del'
                         stats[1] += 1
-                    else:
+                    elif command == ' ':
                         affects_old = affects_new = True
                         action = 'unmod'
+                    else:
+                        raise Exception('error parsing diff - unknown command in line %r at -%s+%s' % (line, old_line, new_line))
 
                     if not self._newline_marker.match(line):
                         old_line += affects_old
@@ -576,7 +575,7 @@
                             'line':         self._clean_line(line, command)
                         })
 
-                    line = lineiter.next()
+                    line = diff.next()
 
                     if self._newline_marker.match(line):
                         # we need to append to lines, since this is not
@@ -587,9 +586,16 @@
                             'action':       'context',
                             'line':         self._clean_line(line, command)
                         })
-
+                        line = diff.next()
+                if old_line > old_end:
+                        raise Exception('error parsing diff - more than %s "-" lines at -%s+%s' % (old_end, old_line, new_line))
+                if new_line > new_end:
+                        raise Exception('error parsing diff - more than %s "+" lines at -%s+%s' % (new_end, old_line, new_line))
         except StopIteration:
             pass
+        if old_line != old_end or new_line != new_end:
+            raise Exception('diff processing broken when old %s<>%s or new %s<>%s line %r' % (old_line, old_end, new_line, new_end, line))
+
         return chunks, stats
 
     def _safe_id(self, idstring):
--- a/kallithea/tests/fixtures/diff_with_diff_data.diff	Mon Dec 15 13:47:36 2014 +0100
+++ b/kallithea/tests/fixtures/diff_with_diff_data.diff	Mon Dec 15 13:47:36 2014 +0100
@@ -414,3 +414,4 @@
 -
  if __name__ == '__main__':
      unittest.main()
+ 
--- a/kallithea/tests/fixtures/hg_diff_mod_single_file_and_rename_and_chmod.diff	Mon Dec 15 13:47:36 2014 +0100
+++ b/kallithea/tests/fixtures/hg_diff_mod_single_file_and_rename_and_chmod.diff	Mon Dec 15 13:47:36 2014 +0100
@@ -9,7 +9,7 @@
  readme2
  line 1
   line2
-
+ 
 +line 1
 + line2
-+
\ No newline at end of file
++
--- a/kallithea/tests/models/test_diff_parsers.py	Mon Dec 15 13:47:36 2014 +0100
+++ b/kallithea/tests/models/test_diff_parsers.py	Mon Dec 15 13:47:36 2014 +0100
@@ -255,7 +255,7 @@
     @parameterized.expand([(x,) for x in DIFF_FIXTURES])
     def test_diff(self, diff_fixture):
 
-        diff = fixture.load_resource(diff_fixture)
+        diff = fixture.load_resource(diff_fixture, strip=False)
 
         diff_proc = DiffProcessor(diff)
         diff_proc_d = diff_proc.prepare()