/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_diff.py

  • Committer: Jelmer Vernooij
  • Date: 2018-11-16 23:15:15 UTC
  • mfrom: (7180 work)
  • mto: This revision was merged to the branch mainline in revision 7183.
  • Revision ID: jelmer@jelmer.uk-20181116231515-zqd2yn6kj8lfydyp
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
import os
18
18
import re
19
19
import subprocess
 
20
import sys
20
21
import tempfile
21
22
 
22
23
from .. import (
104
105
class TestDiffOptionsScenarios(tests.TestCase):
105
106
 
106
107
    scenarios = [(s, dict(style=s)) for s in diff.style_option_list]
107
 
    style = None # Set by load_tests_apply_scenarios from scenarios
 
108
    style = None  # Set by load_tests_apply_scenarios from scenarios
108
109
 
109
110
    def test_unified_not_added(self):
110
111
        # Verify that for all valid style options, '-u' is not
120
121
        lines = udiff_lines([b'boo'], [b'boo\n'])
121
122
        self.check_patch(lines)
122
123
        self.assertEqual(lines[4], b'\\ No newline at end of file\n')
123
 
            ## "expected no-nl, got %r" % lines[4]
 
124
        ## "expected no-nl, got %r" % lines[4]
124
125
 
125
126
    def test_add_nl_2(self):
126
127
        """diff generates a valid diff for patches that change last line and
129
130
        lines = udiff_lines([b'boo'], [b'goo\n'])
130
131
        self.check_patch(lines)
131
132
        self.assertEqual(lines[4], b'\\ No newline at end of file\n')
132
 
            ## "expected no-nl, got %r" % lines[4]
 
133
        ## "expected no-nl, got %r" % lines[4]
133
134
 
134
135
    def test_remove_nl(self):
135
136
        """diff generates a valid diff for patches that change last line and
138
139
        lines = udiff_lines([b'boo\n'], [b'boo'])
139
140
        self.check_patch(lines)
140
141
        self.assertEqual(lines[5], b'\\ No newline at end of file\n')
141
 
            ## "expected no-nl, got %r" % lines[5]
 
142
        ## "expected no-nl, got %r" % lines[5]
142
143
 
143
144
    def check_patch(self, lines):
144
145
        self.assertTrue(len(lines) > 1)
145
 
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
146
 
        self.assertTrue(lines[0].startswith (b'---'))
147
 
            ## 'No orig line for patch:\n%s' % "".join(lines)
148
 
        self.assertTrue(lines[1].startswith (b'+++'))
149
 
            ## 'No mod line for patch:\n%s' % "".join(lines)
 
146
        ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
 
147
        self.assertTrue(lines[0].startswith(b'---'))
 
148
        ## 'No orig line for patch:\n%s' % "".join(lines)
 
149
        self.assertTrue(lines[1].startswith(b'+++'))
 
150
        ## 'No mod line for patch:\n%s' % "".join(lines)
150
151
        self.assertTrue(len(lines) > 2)
151
 
            ## "No hunks for patch:\n%s" % "".join(lines)
 
152
        ## "No hunks for patch:\n%s" % "".join(lines)
152
153
        self.assertTrue(lines[2].startswith(b'@@'))
153
 
            ## "No hunk header for patch:\n%s" % "".join(lines)
 
154
        ## "No hunk header for patch:\n%s" % "".join(lines)
154
155
        self.assertTrue(b'@@' in lines[2][2:])
155
 
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
 
156
        ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
156
157
 
157
158
    def test_binary_lines(self):
158
159
        empty = []
170
171
    def test_external_diff_no_fileno(self):
171
172
        # Make sure that we can handle not having a fileno, even
172
173
        # if the diff is large
173
 
        lines = external_udiff_lines([b'boo\n']*10000,
174
 
                                     [b'goo\n']*10000,
 
174
        lines = external_udiff_lines([b'boo\n'] * 10000,
 
175
                                     [b'goo\n'] * 10000,
175
176
                                     use_stringio=True)
176
177
        self.check_patch(lines)
177
178
 
181
182
        lines = external_udiff_lines([b'\x00foobar\n'], [b'foo\x00bar\n'])
182
183
        # Older versions of diffutils say "Binary files", newer
183
184
        # versions just say "Files".
184
 
        self.assertContainsRe(lines[0], b'(Binary f|F)iles old and new differ\n')
 
185
        self.assertContainsRe(
 
186
            lines[0], b'(Binary f|F)iles old and new differ\n')
185
187
        self.assertEqual(lines[1:], [b'\n'])
186
188
 
187
189
    def test_no_external_diff(self):
201
203
        lines = output.getvalue().splitlines(True)
202
204
        self.check_patch(lines)
203
205
        self.assertEqual([b'--- old_\xc2\xb5\n',
204
 
                           b'+++ new_\xc3\xa5\n',
205
 
                           b'@@ -1,1 +1,1 @@\n',
206
 
                           b'-old_text\n',
207
 
                           b'+new_text\n',
208
 
                           b'\n',
209
 
                          ]
210
 
                          , lines)
 
206
                          b'+++ new_\xc3\xa5\n',
 
207
                          b'@@ -1,1 +1,1 @@\n',
 
208
                          b'-old_text\n',
 
209
                          b'+new_text\n',
 
210
                          b'\n',
 
211
                          ], lines)
211
212
 
212
213
    def test_internal_diff_utf8(self):
213
214
        output = BytesIO()
217
218
        lines = output.getvalue().splitlines(True)
218
219
        self.check_patch(lines)
219
220
        self.assertEqual([b'--- old_\xc2\xb5\n',
220
 
                           b'+++ new_\xc3\xa5\n',
221
 
                           b'@@ -1,1 +1,1 @@\n',
222
 
                           b'-old_text\n',
223
 
                           b'+new_text\n',
224
 
                           b'\n',
225
 
                          ]
226
 
                          , lines)
 
221
                          b'+++ new_\xc3\xa5\n',
 
222
                          b'@@ -1,1 +1,1 @@\n',
 
223
                          b'-old_text\n',
 
224
                          b'+new_text\n',
 
225
                          b'\n',
 
226
                          ], lines)
227
227
 
228
228
    def test_internal_diff_iso_8859_1(self):
229
229
        output = BytesIO()
238
238
                          b'-old_text\n',
239
239
                          b'+new_text\n',
240
240
                          b'\n',
241
 
                          ]
242
 
                          , lines)
 
241
                          ], lines)
243
242
 
244
243
    def test_internal_diff_no_content(self):
245
244
        output = BytesIO()
262
261
    def test_internal_diff_default_context(self):
263
262
        output = BytesIO()
264
263
        diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
265
 
                           b'same_text\n', b'same_text\n', b'old_text\n'],
 
264
                                   b'same_text\n', b'same_text\n', b'old_text\n'],
266
265
                           'new', [b'same_text\n', b'same_text\n', b'same_text\n',
267
 
                           b'same_text\n', b'same_text\n', b'new_text\n'], output)
 
266
                                   b'same_text\n', b'same_text\n', b'new_text\n'], output)
268
267
        lines = output.getvalue().splitlines(True)
269
268
        self.check_patch(lines)
270
269
        self.assertEqual([b'--- old\n',
271
 
                           b'+++ new\n',
272
 
                           b'@@ -3,4 +3,4 @@\n',
273
 
                           b' same_text\n',
274
 
                           b' same_text\n',
275
 
                           b' same_text\n',
276
 
                           b'-old_text\n',
277
 
                           b'+new_text\n',
278
 
                           b'\n',
279
 
                          ]
280
 
                          , lines)
 
270
                          b'+++ new\n',
 
271
                          b'@@ -3,4 +3,4 @@\n',
 
272
                          b' same_text\n',
 
273
                          b' same_text\n',
 
274
                          b' same_text\n',
 
275
                          b'-old_text\n',
 
276
                          b'+new_text\n',
 
277
                          b'\n',
 
278
                          ], lines)
281
279
 
282
280
    def test_internal_diff_no_context(self):
283
281
        output = BytesIO()
284
282
        diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
285
 
                           b'same_text\n', b'same_text\n', b'old_text\n'],
 
283
                                   b'same_text\n', b'same_text\n', b'old_text\n'],
286
284
                           'new', [b'same_text\n', b'same_text\n', b'same_text\n',
287
 
                           b'same_text\n', b'same_text\n', b'new_text\n'], output,
 
285
                                   b'same_text\n', b'same_text\n', b'new_text\n'], output,
288
286
                           context_lines=0)
289
287
        lines = output.getvalue().splitlines(True)
290
288
        self.check_patch(lines)
291
289
        self.assertEqual([b'--- old\n',
292
 
                           b'+++ new\n',
293
 
                           b'@@ -6,1 +6,1 @@\n',
294
 
                           b'-old_text\n',
295
 
                           b'+new_text\n',
296
 
                           b'\n',
297
 
                          ]
298
 
                          , lines)
 
290
                          b'+++ new\n',
 
291
                          b'@@ -6,1 +6,1 @@\n',
 
292
                          b'-old_text\n',
 
293
                          b'+new_text\n',
 
294
                          b'\n',
 
295
                          ], lines)
299
296
 
300
297
    def test_internal_diff_more_context(self):
301
298
        output = BytesIO()
302
299
        diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
303
 
                           b'same_text\n', b'same_text\n', b'old_text\n'],
 
300
                                   b'same_text\n', b'same_text\n', b'old_text\n'],
304
301
                           'new', [b'same_text\n', b'same_text\n', b'same_text\n',
305
 
                           b'same_text\n', b'same_text\n', b'new_text\n'], output,
 
302
                                   b'same_text\n', b'same_text\n', b'new_text\n'], output,
306
303
                           context_lines=4)
307
304
        lines = output.getvalue().splitlines(True)
308
305
        self.check_patch(lines)
316
313
                          b'-old_text\n',
317
314
                          b'+new_text\n',
318
315
                          b'\n',
319
 
                          ]
320
 
                          , lines)
321
 
 
 
316
                          ], lines)
322
317
 
323
318
 
324
319
class TestDiffFiles(tests.TestCaseInTempDir):
331
326
        lines = external_udiff_lines([b'\x00foobar\n'], [b'foo\x00bar\n'])
332
327
 
333
328
        cmd = ['diff', '-u', '--binary', 'old', 'new']
334
 
        with open('old', 'wb') as f: f.write(b'\x00foobar\n')
335
 
        with open('new', 'wb') as f: f.write(b'foo\x00bar\n')
 
329
        with open('old', 'wb') as f:
 
330
            f.write(b'\x00foobar\n')
 
331
        with open('new', 'wb') as f:
 
332
            f.write(b'foo\x00bar\n')
336
333
        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
337
 
                                     stdin=subprocess.PIPE)
 
334
                                stdin=subprocess.PIPE)
338
335
        out, err = pipe.communicate()
339
336
        # We should output whatever diff tells us, plus a trailing newline
340
337
        self.assertEqual(out.splitlines(True) + [b'\n'], lines)
347
344
    else:
348
345
        extra_trees = ()
349
346
    diff.show_diff_trees(tree1, tree2, output,
350
 
        specific_files=specific_files,
351
 
        extra_trees=extra_trees, old_label='old/',
352
 
        new_label='new/')
 
347
                         specific_files=specific_files,
 
348
                         extra_trees=extra_trees, old_label='old/',
 
349
                         new_label='new/')
353
350
    return output.getvalue()
354
351
 
355
352
 
366
363
        self.wt.add(['file1', 'file2'])
367
364
        self.wt.commit(
368
365
            message='Revision 1',
369
 
            timestamp=1143849600, # 2006-04-01 00:00:00 UTC
 
366
            timestamp=1143849600,  # 2006-04-01 00:00:00 UTC
370
367
            timezone=0,
371
368
            rev_id=b'rev-1')
372
369
        self.build_tree_contents([('file1', b'file1 contents at rev 2\n')])
373
370
        self.wt.commit(
374
371
            message='Revision 2',
375
 
            timestamp=1143936000, # 2006-04-02 00:00:00 UTC
 
372
            timestamp=1143936000,  # 2006-04-02 00:00:00 UTC
376
373
            timezone=28800,
377
374
            rev_id=b'rev-2')
378
375
        self.build_tree_contents([('file2', b'file2 contents at rev 3\n')])
379
376
        self.wt.commit(
380
377
            message='Revision 3',
381
 
            timestamp=1144022400, # 2006-04-03 00:00:00 UTC
 
378
            timestamp=1144022400,  # 2006-04-03 00:00:00 UTC
382
379
            timezone=-3600,
383
380
            rev_id=b'rev-3')
384
381
        self.wt.remove(['file2'])
385
382
        self.wt.commit(
386
383
            message='Revision 4',
387
 
            timestamp=1144108800, # 2006-04-04 00:00:00 UTC
 
384
            timestamp=1144108800,  # 2006-04-04 00:00:00 UTC
388
385
            timezone=0,
389
386
            rev_id=b'rev-4')
390
387
        self.build_tree_contents([
391
388
            ('file1', b'file1 contents in working tree\n')
392
389
            ])
393
390
        # set the date stamps for files in the working tree to known values
394
 
        os.utime('file1', (1144195200, 1144195200)) # 2006-04-05 00:00:00 UTC
 
391
        os.utime('file1', (1144195200, 1144195200))  # 2006-04-05 00:00:00 UTC
395
392
 
396
393
    def test_diff_rev_tree_working_tree(self):
397
394
        output = get_diff_as_string(self.wt.basis_tree(), self.wt)
463
460
        old_tree = self.b.repository.revision_tree(b'rev-1')
464
461
        new_tree = self.b.repository.revision_tree(b'rev-4')
465
462
        out = get_diff_as_string(old_tree, new_tree, specific_files=['file1b'],
466
 
                            working_tree=self.wt)
 
463
                                 working_tree=self.wt)
467
464
        self.assertContainsRe(out, b'file1\t')
468
465
 
469
466
    def test_recursive_diff(self):
475
472
        old_tree = self.b.repository.revision_tree(b'rev-1')
476
473
        new_tree = self.b.repository.revision_tree(b'rev-4')
477
474
        out = get_diff_as_string(old_tree, new_tree, specific_files=['dir1'],
478
 
                            working_tree=self.wt)
 
475
                                 working_tree=self.wt)
479
476
        self.assertContainsRe(out, b'file1\t')
480
477
        out = get_diff_as_string(old_tree, new_tree, specific_files=['dir2'],
481
 
                            working_tree=self.wt)
 
478
                                 working_tree=self.wt)
482
479
        self.assertNotContainsRe(out, b'file1\t')
483
480
 
484
481
 
564
561
        self.assertContainsRe(d, b'-contents\n'
565
562
                                 b'\\+new contents\n')
566
563
 
567
 
 
568
564
    def test_internal_diff_exec_property(self):
569
565
        tree = self.make_branch_and_tree('tree')
570
566
 
635
631
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
636
632
 
637
633
        tree = self.make_branch_and_tree('tree')
638
 
        self.build_tree_contents([('tree/ren_'+alpha, b'contents\n')])
639
 
        tree.add(['ren_'+alpha], [b'file-id-2'])
640
 
        self.build_tree_contents([('tree/del_'+alpha, b'contents\n')])
641
 
        tree.add(['del_'+alpha], [b'file-id-3'])
642
 
        self.build_tree_contents([('tree/mod_'+alpha, b'contents\n')])
643
 
        tree.add(['mod_'+alpha], [b'file-id-4'])
 
634
        self.build_tree_contents([('tree/ren_' + alpha, b'contents\n')])
 
635
        tree.add(['ren_' + alpha], [b'file-id-2'])
 
636
        self.build_tree_contents([('tree/del_' + alpha, b'contents\n')])
 
637
        tree.add(['del_' + alpha], [b'file-id-3'])
 
638
        self.build_tree_contents([('tree/mod_' + alpha, b'contents\n')])
 
639
        tree.add(['mod_' + alpha], [b'file-id-4'])
644
640
 
645
641
        tree.commit('one', rev_id=b'rev-1')
646
642
 
647
 
        tree.rename_one('ren_'+alpha, 'ren_'+omega)
648
 
        tree.remove('del_'+alpha)
649
 
        self.build_tree_contents([('tree/add_'+alpha, b'contents\n')])
650
 
        tree.add(['add_'+alpha], [b'file-id'])
651
 
        self.build_tree_contents([('tree/mod_'+alpha, b'contents_mod\n')])
 
643
        tree.rename_one('ren_' + alpha, 'ren_' + omega)
 
644
        tree.remove('del_' + alpha)
 
645
        self.build_tree_contents([('tree/add_' + alpha, b'contents\n')])
 
646
        tree.add(['add_' + alpha], [b'file-id'])
 
647
        self.build_tree_contents([('tree/mod_' + alpha, b'contents_mod\n')])
652
648
 
653
649
        d = get_diff_as_string(tree.basis_tree(), tree)
654
650
        self.assertContainsRe(d,
655
 
                b"=== renamed file 'ren_%s' => 'ren_%s'\n"%(autf8, outf8))
656
 
        self.assertContainsRe(d, b"=== added file 'add_%s'"%autf8)
657
 
        self.assertContainsRe(d, b"=== modified file 'mod_%s'"%autf8)
658
 
        self.assertContainsRe(d, b"=== removed file 'del_%s'"%autf8)
 
651
                              b"=== renamed file 'ren_%s' => 'ren_%s'\n" % (autf8, outf8))
 
652
        self.assertContainsRe(d, b"=== added file 'add_%s'" % autf8)
 
653
        self.assertContainsRe(d, b"=== modified file 'mod_%s'" % autf8)
 
654
        self.assertContainsRe(d, b"=== removed file 'del_%s'" % autf8)
659
655
 
660
656
    def test_unicode_filename_path_encoding(self):
661
657
        """Test for bug #382699: unicode filenames on Windows should be shown
678
674
 
679
675
        sio = BytesIO()
680
676
        diff.show_diff_trees(tree.basis_tree(), tree, sio,
681
 
            path_encoding='cp1251')
 
677
                             path_encoding='cp1251')
682
678
 
683
679
        output = subst_dates(sio.getvalue())
684
680
        shouldbe = (b'''\
696
692
+foo
697
693
 
698
694
''' % {b'directory': _russian_test.encode('cp1251'),
699
 
       b'test_txt': test_txt.encode('cp1251'),
700
 
      })
 
695
            b'test_txt': test_txt.encode('cp1251'),
 
696
       })
701
697
        self.assertEqualDiff(output, shouldbe)
702
698
 
703
699
 
836
832
    def test_register_diff(self):
837
833
        self.create_old_new()
838
834
        old_diff_factories = diff.DiffTree.diff_factories
839
 
        diff.DiffTree.diff_factories=old_diff_factories[:]
 
835
        diff.DiffTree.diff_factories = old_diff_factories[:]
840
836
        diff.DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
841
837
        try:
842
838
            differ = diff.DiffTree(self.old_tree, self.new_tree, BytesIO())
869
865
        self.old_tree.add('b-file')
870
866
        self.differ.show_diff(None)
871
867
        self.assertContainsRe(self.differ.to_file.getvalue(),
872
 
            b'.*a-file(.|\n)*b-file')
 
868
                              b'.*a-file(.|\n)*b-file')
873
869
 
874
870
 
875
871
class TestPatienceDiffLib(tests.TestCase):
896
892
        self.assertEqual(unique_lcs('a', 'a'), [(0, 0)])
897
893
        self.assertEqual(unique_lcs('a', 'b'), [])
898
894
        self.assertEqual(unique_lcs('ab', 'ab'), [(0, 0), (1, 1)])
899
 
        self.assertEqual(unique_lcs('abcde', 'cdeab'), [(2, 0), (3, 1), (4, 2)])
900
 
        self.assertEqual(unique_lcs('cdeab', 'abcde'), [(0, 2), (1, 3), (2, 4)])
 
895
        self.assertEqual(unique_lcs('abcde', 'cdeab'),
 
896
                         [(2, 0), (3, 1), (4, 2)])
 
897
        self.assertEqual(unique_lcs('cdeab', 'abcde'),
 
898
                         [(0, 2), (1, 3), (2, 4)])
901
899
        self.assertEqual(unique_lcs('abXde', 'abYde'), [(0, 0), (1, 1),
902
 
                                                         (3, 3), (4, 4)])
 
900
                                                        (3, 3), (4, 4)])
903
901
        self.assertEqual(unique_lcs('acbac', 'abc'), [(2, 1)])
904
902
 
905
903
    def test_recurse_matches(self):
966
964
 
967
965
        # make sure it supports passing in lists
968
966
        self.assertDiffBlocks(
969
 
                   ['hello there\n',
970
 
                    'world\n',
971
 
                    'how are you today?\n'],
972
 
                   ['hello there\n',
973
 
                    'how are you today?\n'],
974
 
                [(0, 0, 1), (2, 1, 1)])
 
967
            ['hello there\n',
 
968
             'world\n',
 
969
             'how are you today?\n'],
 
970
            ['hello there\n',
 
971
             'how are you today?\n'],
 
972
            [(0, 0, 1), (2, 1, 1)])
975
973
 
976
974
        # non unique lines surrounded by non-matching lines
977
975
        # won't be found
978
976
        self.assertDiffBlocks('aBccDe', 'abccde', [(0, 0, 1), (5, 5, 1)])
979
977
 
980
978
        # But they only need to be locally unique
981
 
        self.assertDiffBlocks('aBcDec', 'abcdec', [(0, 0, 1), (2, 2, 1), (4, 4, 2)])
 
979
        self.assertDiffBlocks('aBcDec', 'abcdec', [
 
980
                              (0, 0, 1), (2, 2, 1), (4, 4, 2)])
982
981
 
983
982
        # non unique blocks won't be matched
984
983
        self.assertDiffBlocks('aBcdEcdFg', 'abcdecdfg', [(0, 0, 1), (8, 8, 1)])
985
984
 
986
985
        # but locally unique ones will
987
986
        self.assertDiffBlocks('aBcdEeXcdFg', 'abcdecdfg', [(0, 0, 1), (2, 2, 2),
988
 
                                              (5, 4, 1), (7, 5, 2), (10, 8, 1)])
 
987
                                                           (5, 4, 1), (7, 5, 2), (10, 8, 1)])
989
988
 
990
989
        self.assertDiffBlocks('abbabbXd', 'cabbabxd', [(7, 7, 1)])
991
990
        self.assertDiffBlocks('abbabbbb', 'cabbabbc', [])
1024
1023
        chk_ops([], [], [])
1025
1024
        chk_ops('abc', '', [('delete', 0, 3, 0, 0)])
1026
1025
        chk_ops('', 'abc', [('insert', 0, 0, 0, 3)])
1027
 
        chk_ops('abcd', 'abcd', [('equal',    0, 4, 0, 4)])
1028
 
        chk_ops('abcd', 'abce', [('equal',   0, 3, 0, 3),
 
1026
        chk_ops('abcd', 'abcd', [('equal', 0, 4, 0, 4)])
 
1027
        chk_ops('abcd', 'abce', [('equal', 0, 3, 0, 3),
1029
1028
                                 ('replace', 3, 4, 3, 4)
1030
 
                                ])
 
1029
                                 ])
1031
1030
        chk_ops('eabc', 'abce', [('delete', 0, 1, 0, 0),
1032
 
                                 ('equal',  1, 4, 0, 3),
 
1031
                                 ('equal', 1, 4, 0, 3),
1033
1032
                                 ('insert', 4, 4, 3, 4)
1034
 
                                ])
 
1033
                                 ])
1035
1034
        chk_ops('eabce', 'abce', [('delete', 0, 1, 0, 0),
1036
 
                                  ('equal',  1, 5, 0, 4)
1037
 
                                 ])
1038
 
        chk_ops('abcde', 'abXde', [('equal',   0, 2, 0, 2),
 
1035
                                  ('equal', 1, 5, 0, 4)
 
1036
                                  ])
 
1037
        chk_ops('abcde', 'abXde', [('equal', 0, 2, 0, 2),
1039
1038
                                   ('replace', 2, 3, 2, 3),
1040
 
                                   ('equal',   3, 5, 3, 5)
1041
 
                                  ])
1042
 
        chk_ops('abcde', 'abXYZde', [('equal',   0, 2, 0, 2),
 
1039
                                   ('equal', 3, 5, 3, 5)
 
1040
                                   ])
 
1041
        chk_ops('abcde', 'abXYZde', [('equal', 0, 2, 0, 2),
1043
1042
                                     ('replace', 2, 3, 2, 5),
1044
 
                                     ('equal',   3, 5, 5, 7)
 
1043
                                     ('equal', 3, 5, 5, 7)
 
1044
                                     ])
 
1045
        chk_ops('abde', 'abXYZde', [('equal', 0, 2, 0, 2),
 
1046
                                    ('insert', 2, 2, 2, 5),
 
1047
                                    ('equal', 2, 4, 5, 7)
1045
1048
                                    ])
1046
 
        chk_ops('abde', 'abXYZde', [('equal',  0, 2, 0, 2),
1047
 
                                    ('insert', 2, 2, 2, 5),
1048
 
                                    ('equal',  2, 4, 5, 7)
1049
 
                                   ])
1050
1049
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1051
 
                [('equal',  0, 6,  0, 6),
1052
 
                 ('insert', 6, 6,  6, 11),
1053
 
                 ('equal',  6, 16, 11, 21)
1054
 
                ])
 
1050
                [('equal', 0, 6, 0, 6),
 
1051
                 ('insert', 6, 6, 6, 11),
 
1052
                 ('equal', 6, 16, 11, 21)
 
1053
                 ])
1055
1054
        chk_ops(
1056
 
                [ 'hello there\n'
1057
 
                , 'world\n'
1058
 
                , 'how are you today?\n'],
1059
 
                [ 'hello there\n'
1060
 
                , 'how are you today?\n'],
1061
 
                [('equal',  0, 1, 0, 1),
1062
 
                 ('delete', 1, 2, 1, 1),
1063
 
                 ('equal',  2, 3, 1, 2),
1064
 
                ])
 
1055
            ['hello there\n', 'world\n', 'how are you today?\n'],
 
1056
            ['hello there\n', 'how are you today?\n'],
 
1057
            [('equal', 0, 1, 0, 1),
 
1058
             ('delete', 1, 2, 1, 1),
 
1059
             ('equal', 2, 3, 1, 2),
 
1060
             ])
1065
1061
        chk_ops('aBccDe', 'abccde',
1066
 
                [('equal',   0, 1, 0, 1),
 
1062
                [('equal', 0, 1, 0, 1),
1067
1063
                 ('replace', 1, 5, 1, 5),
1068
 
                 ('equal',   5, 6, 5, 6),
1069
 
                ])
 
1064
                 ('equal', 5, 6, 5, 6),
 
1065
                 ])
1070
1066
        chk_ops('aBcDec', 'abcdec',
1071
 
                [('equal',   0, 1, 0, 1),
 
1067
                [('equal', 0, 1, 0, 1),
1072
1068
                 ('replace', 1, 2, 1, 2),
1073
 
                 ('equal',   2, 3, 2, 3),
 
1069
                 ('equal', 2, 3, 2, 3),
1074
1070
                 ('replace', 3, 4, 3, 4),
1075
 
                 ('equal',   4, 6, 4, 6),
1076
 
                ])
 
1071
                 ('equal', 4, 6, 4, 6),
 
1072
                 ])
1077
1073
        chk_ops('aBcdEcdFg', 'abcdecdfg',
1078
 
                [('equal',   0, 1, 0, 1),
 
1074
                [('equal', 0, 1, 0, 1),
1079
1075
                 ('replace', 1, 8, 1, 8),
1080
 
                 ('equal',   8, 9, 8, 9)
1081
 
                ])
 
1076
                 ('equal', 8, 9, 8, 9)
 
1077
                 ])
1082
1078
        chk_ops('aBcdEeXcdFg', 'abcdecdfg',
1083
 
                [('equal',   0, 1, 0, 1),
 
1079
                [('equal', 0, 1, 0, 1),
1084
1080
                 ('replace', 1, 2, 1, 2),
1085
 
                 ('equal',   2, 4, 2, 4),
 
1081
                 ('equal', 2, 4, 2, 4),
1086
1082
                 ('delete', 4, 5, 4, 4),
1087
 
                 ('equal',   5, 6, 4, 5),
 
1083
                 ('equal', 5, 6, 4, 5),
1088
1084
                 ('delete', 6, 7, 5, 5),
1089
 
                 ('equal',   7, 9, 5, 7),
 
1085
                 ('equal', 7, 9, 5, 7),
1090
1086
                 ('replace', 9, 10, 7, 8),
1091
 
                 ('equal',   10, 11, 8, 9)
1092
 
                ])
 
1087
                 ('equal', 10, 11, 8, 9)
 
1088
                 ])
1093
1089
 
1094
1090
    def test_grouped_opcodes(self):
1095
1091
        def chk_ops(a, b, expected_codes, n=3):
1101
1097
        chk_ops('abc', '', [[('delete', 0, 3, 0, 0)]])
1102
1098
        chk_ops('', 'abc', [[('insert', 0, 0, 0, 3)]])
1103
1099
        chk_ops('abcd', 'abcd', [])
1104
 
        chk_ops('abcd', 'abce', [[('equal',   0, 3, 0, 3),
 
1100
        chk_ops('abcd', 'abce', [[('equal', 0, 3, 0, 3),
1105
1101
                                  ('replace', 3, 4, 3, 4)
1106
 
                                 ]])
 
1102
                                  ]])
1107
1103
        chk_ops('eabc', 'abce', [[('delete', 0, 1, 0, 0),
1108
 
                                 ('equal',  1, 4, 0, 3),
1109
 
                                 ('insert', 4, 4, 3, 4)
1110
 
                                ]])
 
1104
                                  ('equal', 1, 4, 0, 3),
 
1105
                                  ('insert', 4, 4, 3, 4)
 
1106
                                  ]])
1111
1107
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1112
 
                [[('equal',  3, 6, 3, 6),
 
1108
                [[('equal', 3, 6, 3, 6),
1113
1109
                  ('insert', 6, 6, 6, 11),
1114
 
                  ('equal',  6, 9, 11, 14)
 
1110
                  ('equal', 6, 9, 11, 14)
1115
1111
                  ]])
1116
1112
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1117
 
                [[('equal',  2, 6, 2, 6),
 
1113
                [[('equal', 2, 6, 2, 6),
1118
1114
                  ('insert', 6, 6, 6, 11),
1119
 
                  ('equal',  6, 10, 11, 15)
 
1115
                  ('equal', 6, 10, 11, 15)
1120
1116
                  ]], 4)
1121
1117
        chk_ops('Xabcdef', 'abcdef',
1122
1118
                [[('delete', 0, 1, 0, 0),
1123
 
                  ('equal',  1, 4, 0, 3)
 
1119
                  ('equal', 1, 4, 0, 3)
1124
1120
                  ]])
1125
1121
        chk_ops('abcdef', 'abcdefX',
1126
 
                [[('equal',  3, 6, 3, 6),
 
1122
                [[('equal', 3, 6, 3, 6),
1127
1123
                  ('insert', 6, 6, 6, 7)
1128
1124
                  ]])
1129
1125
 
1130
 
 
1131
1126
    def test_multiple_ranges(self):
1132
1127
        # There was an earlier bug where we used a bad set of ranges,
1133
1128
        # this triggers that specific bug, to make sure it doesn't regress
1183
1178
 
1184
1179
 
1185
1180
pynff pzq_zxqve(Pbzznaq):
1186
 
'''.splitlines(True)
1187
 
, [(0, 0, 1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
 
1181
'''.splitlines(True), [(0, 0, 1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
1188
1182
 
1189
1183
    def test_patience_unified_diff(self):
1190
1184
        txt_a = ['hello there\n',
1195
1189
        unified_diff = patiencediff.unified_diff
1196
1190
        psm = self._PatienceSequenceMatcher
1197
1191
        self.assertEqual(['--- \n',
1198
 
                           '+++ \n',
1199
 
                           '@@ -1,3 +1,2 @@\n',
1200
 
                           ' hello there\n',
1201
 
                           '-world\n',
1202
 
                           ' how are you today?\n'
1203
 
                          ]
1204
 
                          , list(unified_diff(txt_a, txt_b,
1205
 
                                 sequencematcher=psm)))
1206
 
        txt_a = [x+'\n' for x in 'abcdefghijklmnop']
1207
 
        txt_b = [x+'\n' for x in 'abcdefxydefghijklmnop']
 
1192
                          '+++ \n',
 
1193
                          '@@ -1,3 +1,2 @@\n',
 
1194
                          ' hello there\n',
 
1195
                          '-world\n',
 
1196
                          ' how are you today?\n'
 
1197
                          ], list(unified_diff(txt_a, txt_b,
 
1198
                                               sequencematcher=psm)))
 
1199
        txt_a = [x + '\n' for x in 'abcdefghijklmnop']
 
1200
        txt_b = [x + '\n' for x in 'abcdefxydefghijklmnop']
1208
1201
        # This is the result with LongestCommonSubstring matching
1209
1202
        self.assertEqual(['--- \n',
1210
 
                           '+++ \n',
1211
 
                           '@@ -1,6 +1,11 @@\n',
1212
 
                           ' a\n',
1213
 
                           ' b\n',
1214
 
                           ' c\n',
1215
 
                           '+d\n',
1216
 
                           '+e\n',
1217
 
                           '+f\n',
1218
 
                           '+x\n',
1219
 
                           '+y\n',
1220
 
                           ' d\n',
1221
 
                           ' e\n',
1222
 
                           ' f\n']
1223
 
                          , list(unified_diff(txt_a, txt_b)))
 
1203
                          '+++ \n',
 
1204
                          '@@ -1,6 +1,11 @@\n',
 
1205
                          ' a\n',
 
1206
                          ' b\n',
 
1207
                          ' c\n',
 
1208
                          '+d\n',
 
1209
                          '+e\n',
 
1210
                          '+f\n',
 
1211
                          '+x\n',
 
1212
                          '+y\n',
 
1213
                          ' d\n',
 
1214
                          ' e\n',
 
1215
                          ' f\n'], list(unified_diff(txt_a, txt_b)))
1224
1216
        # And the patience diff
1225
1217
        self.assertEqual(['--- \n',
1226
 
                           '+++ \n',
1227
 
                           '@@ -4,6 +4,11 @@\n',
1228
 
                           ' d\n',
1229
 
                           ' e\n',
1230
 
                           ' f\n',
1231
 
                           '+x\n',
1232
 
                           '+y\n',
1233
 
                           '+d\n',
1234
 
                           '+e\n',
1235
 
                           '+f\n',
1236
 
                           ' g\n',
1237
 
                           ' h\n',
1238
 
                           ' i\n',
1239
 
                          ]
1240
 
                          , list(unified_diff(txt_a, txt_b,
1241
 
                                 sequencematcher=psm)))
 
1218
                          '+++ \n',
 
1219
                          '@@ -4,6 +4,11 @@\n',
 
1220
                          ' d\n',
 
1221
                          ' e\n',
 
1222
                          ' f\n',
 
1223
                          '+x\n',
 
1224
                          '+y\n',
 
1225
                          '+d\n',
 
1226
                          '+e\n',
 
1227
                          '+f\n',
 
1228
                          ' g\n',
 
1229
                          ' h\n',
 
1230
                          ' i\n',
 
1231
                          ], list(unified_diff(txt_a, txt_b,
 
1232
                                               sequencematcher=psm)))
1242
1233
 
1243
1234
    def test_patience_unified_diff_with_dates(self):
1244
1235
        txt_a = ['hello there\n',
1249
1240
        unified_diff = patiencediff.unified_diff
1250
1241
        psm = self._PatienceSequenceMatcher
1251
1242
        self.assertEqual(['--- a\t2008-08-08\n',
1252
 
                           '+++ b\t2008-09-09\n',
1253
 
                           '@@ -1,3 +1,2 @@\n',
1254
 
                           ' hello there\n',
1255
 
                           '-world\n',
1256
 
                           ' how are you today?\n'
1257
 
                          ]
1258
 
                          , list(unified_diff(txt_a, txt_b,
1259
 
                                 fromfile='a', tofile='b',
1260
 
                                 fromfiledate='2008-08-08',
1261
 
                                 tofiledate='2008-09-09',
1262
 
                                 sequencematcher=psm)))
 
1243
                          '+++ b\t2008-09-09\n',
 
1244
                          '@@ -1,3 +1,2 @@\n',
 
1245
                          ' hello there\n',
 
1246
                          '-world\n',
 
1247
                          ' how are you today?\n'
 
1248
                          ], list(unified_diff(txt_a, txt_b,
 
1249
                                               fromfile='a', tofile='b',
 
1250
                                               fromfiledate='2008-08-08',
 
1251
                                               tofiledate='2008-09-09',
 
1252
                                               sequencematcher=psm)))
1263
1253
 
1264
1254
 
1265
1255
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1279
1269
        # We need to be able to hash items in the sequence, lists are
1280
1270
        # unhashable, and thus cannot be diffed
1281
1271
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1282
 
                                         None, [[]], [])
1283
 
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1284
 
                                         None, ['valid', []], [])
1285
 
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1286
 
                                         None, ['valid'], [[]])
1287
 
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1288
 
                                         None, ['valid'], ['valid', []])
 
1272
                              None, [[]], [])
 
1273
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
 
1274
                              None, ['valid', []], [])
 
1275
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
 
1276
                              None, ['valid'], [[]])
 
1277
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
 
1278
                              None, ['valid'], ['valid', []])
1289
1279
 
1290
1280
 
1291
1281
class TestPatienceDiffLibFiles(tests.TestCaseInTempDir):
1301
1291
                 b'how are you today?\n']
1302
1292
        txt_b = [b'hello there\n',
1303
1293
                 b'how are you today?\n']
1304
 
        with open('a1', 'wb') as f: f.writelines(txt_a)
1305
 
        with open('b1', 'wb') as f: f.writelines(txt_b)
 
1294
        with open('a1', 'wb') as f:
 
1295
            f.writelines(txt_a)
 
1296
        with open('b1', 'wb') as f:
 
1297
            f.writelines(txt_b)
1306
1298
 
1307
1299
        unified_diff_files = patiencediff.unified_diff_files
1308
1300
        psm = self._PatienceSequenceMatcher
1312
1304
                          b' hello there\n',
1313
1305
                          b'-world\n',
1314
1306
                          b' how are you today?\n',
1315
 
                          ]
1316
 
                          , list(unified_diff_files(b'a1', b'b1',
1317
 
                                 sequencematcher=psm)))
 
1307
                          ], list(unified_diff_files(b'a1', b'b1',
 
1308
                                                     sequencematcher=psm)))
1318
1309
 
1319
 
        txt_a = [x+'\n' for x in 'abcdefghijklmnop']
1320
 
        txt_b = [x+'\n' for x in 'abcdefxydefghijklmnop']
1321
 
        with open('a2', 'wt') as f: f.writelines(txt_a)
1322
 
        with open('b2', 'wt') as f: f.writelines(txt_b)
 
1310
        txt_a = [x + '\n' for x in 'abcdefghijklmnop']
 
1311
        txt_b = [x + '\n' for x in 'abcdefxydefghijklmnop']
 
1312
        with open('a2', 'wt') as f:
 
1313
            f.writelines(txt_a)
 
1314
        with open('b2', 'wt') as f:
 
1315
            f.writelines(txt_b)
1323
1316
 
1324
1317
        # This is the result with LongestCommonSubstring matching
1325
1318
        self.assertEqual([b'--- a2\n',
1335
1328
                          b'+y\n',
1336
1329
                          b' d\n',
1337
1330
                          b' e\n',
1338
 
                          b' f\n']
1339
 
                          , list(unified_diff_files(b'a2', b'b2')))
 
1331
                          b' f\n'], list(unified_diff_files(b'a2', b'b2')))
1340
1332
 
1341
1333
        # And the patience diff
1342
1334
        self.assertEqual([b'--- a2\n',
1407
1399
        diff_obj = diff.DiffFromTool.from_string('diff', None, None, None)
1408
1400
        self.addCleanup(diff_obj.finish)
1409
1401
        self.assertEqual(['diff', '@old_path', '@new_path'],
1410
 
            diff_obj.command_template)
 
1402
                         diff_obj.command_template)
1411
1403
 
1412
1404
    def test_from_string_u5(self):
1413
1405
        diff_obj = diff.DiffFromTool.from_string('diff "-u 5"',
1430
1422
 
1431
1423
    def test_execute(self):
1432
1424
        output = BytesIO()
1433
 
        diff_obj = diff.DiffFromTool(['python', '-c',
 
1425
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1434
1426
                                      'print("@old_path @new_path")'],
1435
1427
                                     None, None, output)
1436
1428
        self.addCleanup(diff_obj.finish)
1458
1450
        basis_tree = tree.basis_tree()
1459
1451
        basis_tree.lock_read()
1460
1452
        self.addCleanup(basis_tree.unlock)
1461
 
        diff_obj = diff.DiffFromTool(['python', '-c',
 
1453
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1462
1454
                                      'print "@old_path @new_path"'],
1463
1455
                                     basis_tree, tree, output)
1464
1456
        diff_obj._prepare_files('file', 'file', file_id=b'file-id')
1494
1486
        self.addCleanup(old_tree.unlock)
1495
1487
        tree.lock_read()
1496
1488
        self.addCleanup(tree.unlock)
1497
 
        diff_obj = diff.DiffFromTool(['python', '-c',
 
1489
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1498
1490
                                      'print "@old_path @new_path"'],
1499
1491
                                     old_tree, tree, output)
1500
1492
        self.addCleanup(diff_obj.finish)
1501
1493
        self.assertContainsRe(diff_obj._root, 'brz-diff-[^/]*')
1502
1494
        old_path, new_path = diff_obj._prepare_files(
1503
 
                'oldname', 'newname', file_id=b'file-id')
 
1495
            'oldname', 'newname', file_id=b'file-id')
1504
1496
        self.assertContainsRe(old_path, 'old/oldname$')
1505
1497
        self.assertEqual(315532800, os.stat(old_path).st_mtime)
1506
1498
        self.assertContainsRe(new_path, 'tree/newname$')