Browse Source

Handle 'Only in <dir>: ' header in output from diff -ru d1 d2

Matthew Wang 12 years ago
parent
commit
0525f7c1dc
7 changed files with 191 additions and 16 deletions
  1. 37
    12
      cdiff.py
  2. 3
    3
      tests/README
  3. 22
    0
      tests/dir/in.diff
  4. 23
    0
      tests/dir/out.normal
  5. 21
    0
      tests/dir/out.side-by-side
  6. 21
    0
      tests/dir/out.w70
  7. 64
    1
      tests/test_cdiff.py

+ 37
- 12
cdiff.py View File

168
     def is_eof(self, line):
168
     def is_eof(self, line):
169
         return False
169
         return False
170
 
170
 
171
+    def is_only_in_dir(self, line):
172
+        return False
173
+
171
     def markup_traditional(self):
174
     def markup_traditional(self):
172
         """Returns a generator"""
175
         """Returns a generator"""
173
         for line in self._headers:
176
         for line in self._headers:
260
 
263
 
261
             return ''.join(out)
264
             return ''.join(out)
262
 
265
 
263
-        # Setup line width and number width
266
+        # Set up line width
264
         if width <= 0:
267
         if width <= 0:
265
             width = 80
268
             width = 80
266
-        (start, offset) = self._hunks[-1]._old_addr
267
-        max1 = start + offset - 1
268
-        (start, offset) = self._hunks[-1]._new_addr
269
-        max2 = start + offset - 1
269
+
270
+        # Set up number width, note last hunk might be empty
271
+        try:
272
+            (start, offset) = self._hunks[-1]._old_addr
273
+            max1 = start + offset - 1
274
+            (start, offset) = self._hunks[-1]._new_addr
275
+            max2 = start + offset - 1
276
+        except IndexError:
277
+            max1 = max2 = 0
270
         num_width = max(len(str(max1)), len(str(max2)))
278
         num_width = max(len(str(max1)), len(str(max2)))
271
 
279
 
272
         # Setup lineno and line format
280
         # Setup lineno and line format
412
         # \ No newline at end of property
420
         # \ No newline at end of property
413
         return line.startswith(r'\ No newline at end of')
421
         return line.startswith(r'\ No newline at end of')
414
 
422
 
423
+    def is_only_in_dir(self, line):
424
+        return line.startswith('Only in ')
425
+
415
 
426
 
416
 class PatchStream(object):
427
 class PatchStream(object):
417
 
428
 
492
             line = decode(line)
503
             line = decode(line)
493
 
504
 
494
             if difflet.is_old_path(line):
505
             if difflet.is_old_path(line):
495
-                # FIXME: '--- ' breaks here, need to probe next 3 lines
506
+                # FIXME: '--- ' breaks here, need to probe next 3 lines,
507
+                # reproducible with github raw patch
508
+                #
496
                 if diff._old_path and diff._new_path and len(diff._hunks) > 0:
509
                 if diff._old_path and diff._new_path and len(diff._hunks) > 0:
497
                     # One diff constructed
510
                     # One diff constructed
498
                     yield diff
511
                     yield diff
518
                 # ignore
531
                 # ignore
519
                 pass
532
                 pass
520
 
533
 
534
+            elif difflet.is_only_in_dir(line):
535
+                # 'Only in foo: ' is considered a separate diff, so yield
536
+                # current diff, then this line
537
+                #
538
+                if diff._old_path and diff._new_path and len(diff._hunks) > 0:
539
+                    # One diff constructed
540
+                    yield diff
541
+                yield Diff([line], '', '', [])
542
+                diff = Diff([], None, None, [])
543
+
521
             else:
544
             else:
522
                 # All other non-recognized lines are considered as headers or
545
                 # All other non-recognized lines are considered as headers or
523
                 # hunk headers respectively
546
                 # hunk headers respectively
527
         if headers:
550
         if headers:
528
             raise RuntimeError('dangling header(s):\n%s' % ''.join(headers))
551
             raise RuntimeError('dangling header(s):\n%s' % ''.join(headers))
529
 
552
 
530
-        # Validate and yield the last patch set
531
-        assert diff._old_path is not None
532
-        assert diff._new_path is not None
533
-        assert len(diff._hunks) > 0
534
-        assert len(diff._hunks[-1]._hunk_meta) > 0
535
-        yield diff
553
+        # Validate and yield the last patch set if it is not yielded yet
554
+        if diff._old_path:
555
+            assert diff._new_path is not None
556
+            assert len(diff._hunks) > 0
557
+            if diff._hunks:
558
+                assert len(diff._hunks[-1]._hunk_meta) > 0
559
+                assert len(diff._hunks[-1]._hunk_list) > 0
560
+            yield diff
536
 
561
 
537
 
562
 
538
 class DiffMarkup(object):
563
 class DiffMarkup(object):

+ 3
- 3
tests/README View File

1
 # To generate expected output, chdir to a subdir and use following command, then
1
 # To generate expected output, chdir to a subdir and use following command, then
2
 # review with `less -R`
2
 # review with `less -R`
3
 #
3
 #
4
-../../cdiff.py -c always in.diff > out.normal 
5
-../../cdiff.py -c always -s in.diff > out.side-by-side
6
-../../cdiff.py -c always -s in.diff -w70 > out.w70
4
+../../cdiff.py -c always < in.diff > out.normal
5
+../../cdiff.py -c always -s < in.diff > out.side-by-side
6
+../../cdiff.py -c always -s < in.diff -w70 > out.w70

+ 22
- 0
tests/dir/in.diff View File

1
+diff -ru a/README b/README
2
+--- a/README	2013-02-22 20:26:43.000000000 +0800
3
++++ b/README	2013-02-22 20:27:51.000000000 +0800
4
+@@ -1,6 +1,6 @@
5
+-# To generate expected output, chdir to a subdir and use following command, then
6
++# To generate expected output, cd to a subdir and use following command, then
7
+ # review with `less -R`
8
+-#
9
+ ../../cdiff.py -c always in.diff > out.normal 
10
+ ../../cdiff.py -c always -s in.diff > out.side-by-side
11
+ ../../cdiff.py -c always -s in.diff -w70 > out.w70
12
++# EOF
13
+Only in a: a1
14
+Only in b: b1
15
+diff -ru a/common/foo.txt b/common/foo.txt
16
+--- a/common/foo.txt	2013-02-22 20:28:32.000000000 +0800
17
++++ b/common/foo.txt	2013-02-22 20:30:18.000000000 +0800
18
+@@ -1 +1 @@
19
+-Hello
20
++world
21
+Only in b: date.txt
22
+Only in a: time.txt

+ 23
- 0
tests/dir/out.normal View File

1
+diff -ru a/README b/README
2
+--- a/README	2013-02-22 20:26:43.000000000 +0800
3
++++ b/README	2013-02-22 20:27:51.000000000 +0800
4
+@@ -1,6 +1,6 @@
5
+-# To generate expected output, chdir to a subdir and use following command, then
6
++# To generate expected output, cd to a subdir and use following command, then
7
+ # review with `less -R`
8
+-#
9
+ ../../cdiff.py -c always in.diff > out.normal 
10
+ ../../cdiff.py -c always -s in.diff > out.side-by-side
11
+ ../../cdiff.py -c always -s in.diff -w70 > out.w70
12
++# EOF
13
+Only in a: a1
14
+Only in b: b1
15
+diff -ru a/common/foo.txt b/common/foo.txt
16
+--- a/common/foo.txt	2013-02-22 20:28:32.000000000 +0800
17
++++ b/common/foo.txt	2013-02-22 20:30:18.000000000 +0800
18
+@@ -1 +1 @@
19
+-Hello
20
++world
21
+Only in b: date.txt
22
+Only in a: time.txt
23
+

+ 21
- 0
tests/dir/out.side-by-side View File

1
+diff -ru a/README b/README
2
+--- a/README	2013-02-22 20:26:43.000000000 +0800
3
++++ b/README	2013-02-22 20:27:51.000000000 +0800
4
+@@ -1,6 +1,6 @@
5
+1 # To generate expected output, chdir to a subdir and use following command, then 1 # To generate expected output, cd to a subdir and use following command, then
6
+2 # review with `less -R`                                                          2 # review with `less -R`
7
+3 #   
8
+4 ../../cdiff.py -c always in.diff > out.normal                                    3 ../../cdiff.py -c always in.diff > out.normal 
9
+5 ../../cdiff.py -c always -s in.diff > out.side-by-side                           4 ../../cdiff.py -c always -s in.diff > out.side-by-side
10
+6 ../../cdiff.py -c always -s in.diff -w70 > out.w70                               5 ../../cdiff.py -c always -s in.diff -w70 > out.w70
11
+                                                                                   6 # EOF
12
+Only in a: a1
13
+Only in b: b1
14
+diff -ru a/common/foo.txt b/common/foo.txt
15
+--- a/common/foo.txt	2013-02-22 20:28:32.000000000 +0800
16
++++ b/common/foo.txt	2013-02-22 20:30:18.000000000 +0800
17
+@@ -1 +1 @@
18
+1 Hello                                                                            1 world
19
+Only in b: date.txt
20
+Only in a: time.txt
21
+

+ 21
- 0
tests/dir/out.w70 View File

1
+diff -ru a/README b/README
2
+--- a/README	2013-02-22 20:26:43.000000000 +0800
3
++++ b/README	2013-02-22 20:27:51.000000000 +0800
4
+@@ -1,6 +1,6 @@
5
+1 # To generate expected output, chdir to a subdir and use following co> 1 # To generate expected output, cd to a subdir and use following comma>
6
+2 # review with `less -R`                                                2 # review with `less -R`
7
+3 #   
8
+4 ../../cdiff.py -c always in.diff > out.normal                          3 ../../cdiff.py -c always in.diff > out.normal 
9
+5 ../../cdiff.py -c always -s in.diff > out.side-by-side                 4 ../../cdiff.py -c always -s in.diff > out.side-by-side
10
+6 ../../cdiff.py -c always -s in.diff -w70 > out.w70                     5 ../../cdiff.py -c always -s in.diff -w70 > out.w70
11
+                                                                         6 # EOF
12
+Only in a: a1
13
+Only in b: b1
14
+diff -ru a/common/foo.txt b/common/foo.txt
15
+--- a/common/foo.txt	2013-02-22 20:28:32.000000000 +0800
16
++++ b/common/foo.txt	2013-02-22 20:30:18.000000000 +0800
17
+@@ -1 +1 @@
18
+1 Hello                                                                  1 world
19
+Only in b: date.txt
20
+Only in a: time.txt
21
+

+ 64
- 1
tests/test_cdiff.py View File

318
         parser = cdiff.DiffParser(stream)
318
         parser = cdiff.DiffParser(stream)
319
         self.assertRaises(AssertionError, list, parser._parse())
319
         self.assertRaises(AssertionError, list, parser._parse())
320
 
320
 
321
-    def test_parse_missing_hunk(self):
321
+    def test_parse_missing_hunk_meta(self):
322
         patch = r"""\
322
         patch = r"""\
323
 --- a
323
 --- a
324
 +++ b
324
 +++ b
334
         parser = cdiff.DiffParser(stream)
334
         parser = cdiff.DiffParser(stream)
335
         self.assertRaises(AssertionError, list, parser._parse())
335
         self.assertRaises(AssertionError, list, parser._parse())
336
 
336
 
337
+    def test_parse_missing_hunk_list(self):
338
+        patch = r"""\
339
+--- a
340
++++ b
341
+@@ -1,2 +1,2 @@
342
+-foo
343
++bar
344
+ common
345
+--- c
346
++++ d
347
+@@ -1,2 +1,2 @@
348
+"""
349
+        items = patch.splitlines(True)
350
+        stream = cdiff.PatchStream(Sequential(items))
351
+        parser = cdiff.DiffParser(stream)
352
+        self.assertRaises(AssertionError, list, parser._parse())
353
+
354
+    def test_parse_only_in_dir(self):
355
+        patch = r"""\
356
+--- a
357
++++ b
358
+@@ -1,2 +1,2 @@
359
+-foo
360
++bar
361
+ common
362
+Only in foo: foo
363
+--- c
364
++++ d
365
+@@ -1,2 +1,2 @@
366
+-foo
367
++bar
368
+ common
369
+"""
370
+        items = patch.splitlines(True)
371
+        stream = cdiff.PatchStream(Sequential(items))
372
+        parser = cdiff.DiffParser(stream)
373
+
374
+        out = list(parser._parse())
375
+        self.assertEqual(len(out), 3)
376
+        self.assertEqual(len(out[1]._hunks), 0)
377
+        self.assertEqual(out[1]._headers, ['Only in foo: foo\n'])
378
+        self.assertEqual(len(out[2]._hunks), 1)
379
+        self.assertEqual(len(out[2]._hunks[0]._hunk_list), 3)
380
+
381
+    def test_parse_only_in_dir_at_last(self):
382
+        patch = r"""\
383
+--- a
384
++++ b
385
+@@ -1,2 +1,2 @@
386
+-foo
387
++bar
388
+ common
389
+Only in foo: foo
390
+"""
391
+        items = patch.splitlines(True)
392
+        stream = cdiff.PatchStream(Sequential(items))
393
+        parser = cdiff.DiffParser(stream)
394
+
395
+        out = list(parser._parse())
396
+        self.assertEqual(len(out), 2)
397
+        self.assertEqual(len(out[1]._hunks), 0)
398
+        self.assertEqual(out[1]._headers, ['Only in foo: foo\n'])
399
+
337
     def test_parse_svn_prop(self):
400
     def test_parse_svn_prop(self):
338
         patch = r"""\
401
         patch = r"""\
339
 --- a
402
 --- a