Bläddra i källkod

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

Matthew Wang 11 år sedan
förälder
incheckning
0525f7c1dc
7 ändrade filer med 191 tillägg och 16 borttagningar
  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 Visa fil

@@ -168,6 +168,9 @@ class Diff(object):
168 168
     def is_eof(self, line):
169 169
         return False
170 170
 
171
+    def is_only_in_dir(self, line):
172
+        return False
173
+
171 174
     def markup_traditional(self):
172 175
         """Returns a generator"""
173 176
         for line in self._headers:
@@ -260,13 +263,18 @@ class Diff(object):
260 263
 
261 264
             return ''.join(out)
262 265
 
263
-        # Setup line width and number width
266
+        # Set up line width
264 267
         if width <= 0:
265 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 278
         num_width = max(len(str(max1)), len(str(max2)))
271 279
 
272 280
         # Setup lineno and line format
@@ -412,6 +420,9 @@ class Udiff(Diff):
412 420
         # \ No newline at end of property
413 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 427
 class PatchStream(object):
417 428
 
@@ -492,7 +503,9 @@ class DiffParser(object):
492 503
             line = decode(line)
493 504
 
494 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 509
                 if diff._old_path and diff._new_path and len(diff._hunks) > 0:
497 510
                     # One diff constructed
498 511
                     yield diff
@@ -518,6 +531,16 @@ class DiffParser(object):
518 531
                 # ignore
519 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 544
             else:
522 545
                 # All other non-recognized lines are considered as headers or
523 546
                 # hunk headers respectively
@@ -527,12 +550,14 @@ class DiffParser(object):
527 550
         if headers:
528 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 563
 class DiffMarkup(object):

+ 3
- 3
tests/README Visa fil

@@ -1,6 +1,6 @@
1 1
 # To generate expected output, chdir to a subdir and use following command, then
2 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 Visa fil

@@ -0,0 +1,22 @@
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 Visa fil

@@ -0,0 +1,23 @@
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 Visa fil

@@ -0,0 +1,21 @@
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 Visa fil

@@ -0,0 +1,21 @@
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 Visa fil

@@ -318,7 +318,7 @@ spam
318 318
         parser = cdiff.DiffParser(stream)
319 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 322
         patch = r"""\
323 323
 --- a
324 324
 +++ b
@@ -334,6 +334,69 @@ spam
334 334
         parser = cdiff.DiffParser(stream)
335 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 400
     def test_parse_svn_prop(self):
338 401
         patch = r"""\
339 402
 --- a