/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 bzrlib/tests/test_diff.py

  • Committer: Martin Pool
  • Date: 2010-04-27 04:30:01 UTC
  • mto: This revision was merged to the branch mainline in revision 5189.
  • Revision ID: mbp@sourcefrog.net-20100427043001-6rka150elrqt9i4g
Remove obsolete comment

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import os
 
18
import os.path
18
19
from cStringIO import StringIO
19
20
import subprocess
20
21
import sys
21
 
import tempfile
 
22
from tempfile import TemporaryFile
22
23
 
23
 
from bzrlib import (
24
 
    diff,
25
 
    errors,
26
 
    osutils,
27
 
    patiencediff,
28
 
    _patiencediff_py,
29
 
    revision as _mod_revision,
30
 
    revisionspec,
31
 
    revisiontree,
32
 
    tests,
33
 
    transform,
 
24
from bzrlib import tests
 
25
from bzrlib.diff import (
 
26
    DiffFromTool,
 
27
    DiffPath,
 
28
    DiffSymlink,
 
29
    DiffTree,
 
30
    DiffText,
 
31
    external_diff,
 
32
    internal_diff,
 
33
    show_diff_trees,
 
34
    get_trees_and_branches_to_diff,
 
35
    get_trees_and_branches_to_diff_locked,
34
36
    )
 
37
from bzrlib.errors import BinaryFile, NoDiff, ExecutableMissing
 
38
import bzrlib.osutils as osutils
 
39
import bzrlib.revision as _mod_revision
 
40
import bzrlib.transform as transform
 
41
import bzrlib.patiencediff
 
42
import bzrlib._patiencediff_py
 
43
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
 
44
                          TestCaseInTempDir, TestSkipped)
 
45
from bzrlib.revisiontree import RevisionTree
 
46
from bzrlib.revisionspec import RevisionSpec
35
47
from bzrlib.symbol_versioning import deprecated_in
36
 
from bzrlib.tests import test_win32utils
37
 
 
38
 
 
39
 
class _AttribFeature(tests.Feature):
 
48
 
 
49
from bzrlib.tests.test_win32utils import BackslashDirSeparatorFeature
 
50
 
 
51
 
 
52
class _AttribFeature(Feature):
40
53
 
41
54
    def _probe(self):
42
55
        if (sys.platform not in ('cygwin', 'win32')):
59
72
 
60
73
def udiff_lines(old, new, allow_binary=False):
61
74
    output = StringIO()
62
 
    diff.internal_diff('old', old, 'new', new, output, allow_binary)
 
75
    internal_diff('old', old, 'new', new, output, allow_binary)
63
76
    output.seek(0, 0)
64
77
    return output.readlines()
65
78
 
69
82
        # StringIO has no fileno, so it tests a different codepath
70
83
        output = StringIO()
71
84
    else:
72
 
        output = tempfile.TemporaryFile()
 
85
        output = TemporaryFile()
73
86
    try:
74
 
        diff.external_diff('old', old, 'new', new, output, diff_opts=['-u'])
75
 
    except errors.NoDiff:
76
 
        raise tests.TestSkipped('external "diff" not present to test')
 
87
        external_diff('old', old, 'new', new, output, diff_opts=['-u'])
 
88
    except NoDiff:
 
89
        raise TestSkipped('external "diff" not present to test')
77
90
    output.seek(0, 0)
78
91
    lines = output.readlines()
79
92
    output.close()
80
93
    return lines
81
94
 
82
95
 
83
 
class TestDiff(tests.TestCase):
 
96
class TestDiff(TestCase):
84
97
 
85
98
    def test_add_nl(self):
86
99
        """diff generates a valid diff for patches that add a newline"""
122
135
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
123
136
 
124
137
    def test_binary_lines(self):
125
 
        empty = []
126
 
        uni_lines = [1023 * 'a' + '\x00']
127
 
        self.assertRaises(errors.BinaryFile, udiff_lines, uni_lines , empty)
128
 
        self.assertRaises(errors.BinaryFile, udiff_lines, empty, uni_lines)
129
 
        udiff_lines(uni_lines , empty, allow_binary=True)
130
 
        udiff_lines(empty, uni_lines, allow_binary=True)
 
138
        self.assertRaises(BinaryFile, udiff_lines, [1023 * 'a' + '\x00'], [])
 
139
        self.assertRaises(BinaryFile, udiff_lines, [], [1023 * 'a' + '\x00'])
 
140
        udiff_lines([1023 * 'a' + '\x00'], [], allow_binary=True)
 
141
        udiff_lines([], [1023 * 'a' + '\x00'], allow_binary=True)
131
142
 
132
143
    def test_external_diff(self):
133
144
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
163
174
        orig_path = os.environ['PATH']
164
175
        try:
165
176
            os.environ['PATH'] = ''
166
 
            self.assertRaises(errors.NoDiff, diff.external_diff,
 
177
            self.assertRaises(NoDiff, external_diff,
167
178
                              'old', ['boo\n'], 'new', ['goo\n'],
168
179
                              StringIO(), diff_opts=['-u'])
169
180
        finally:
172
183
    def test_internal_diff_default(self):
173
184
        # Default internal diff encoding is utf8
174
185
        output = StringIO()
175
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
176
 
                           u'new_\xe5', ['new_text\n'], output)
 
186
        internal_diff(u'old_\xb5', ['old_text\n'],
 
187
                    u'new_\xe5', ['new_text\n'], output)
177
188
        lines = output.getvalue().splitlines(True)
178
189
        self.check_patch(lines)
179
190
        self.assertEquals(['--- old_\xc2\xb5\n',
187
198
 
188
199
    def test_internal_diff_utf8(self):
189
200
        output = StringIO()
190
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
191
 
                           u'new_\xe5', ['new_text\n'], output,
192
 
                           path_encoding='utf8')
 
201
        internal_diff(u'old_\xb5', ['old_text\n'],
 
202
                    u'new_\xe5', ['new_text\n'], output,
 
203
                    path_encoding='utf8')
193
204
        lines = output.getvalue().splitlines(True)
194
205
        self.check_patch(lines)
195
206
        self.assertEquals(['--- old_\xc2\xb5\n',
203
214
 
204
215
    def test_internal_diff_iso_8859_1(self):
205
216
        output = StringIO()
206
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
207
 
                           u'new_\xe5', ['new_text\n'], output,
208
 
                           path_encoding='iso-8859-1')
 
217
        internal_diff(u'old_\xb5', ['old_text\n'],
 
218
                    u'new_\xe5', ['new_text\n'], output,
 
219
                    path_encoding='iso-8859-1')
209
220
        lines = output.getvalue().splitlines(True)
210
221
        self.check_patch(lines)
211
222
        self.assertEquals(['--- old_\xb5\n',
219
230
 
220
231
    def test_internal_diff_no_content(self):
221
232
        output = StringIO()
222
 
        diff.internal_diff(u'old', [], u'new', [], output)
 
233
        internal_diff(u'old', [], u'new', [], output)
223
234
        self.assertEqual('', output.getvalue())
224
235
 
225
236
    def test_internal_diff_no_changes(self):
226
237
        output = StringIO()
227
 
        diff.internal_diff(u'old', ['text\n', 'contents\n'],
228
 
                           u'new', ['text\n', 'contents\n'],
229
 
                           output)
 
238
        internal_diff(u'old', ['text\n', 'contents\n'],
 
239
                      u'new', ['text\n', 'contents\n'],
 
240
                      output)
230
241
        self.assertEqual('', output.getvalue())
231
242
 
232
243
    def test_internal_diff_returns_bytes(self):
233
244
        import StringIO
234
245
        output = StringIO.StringIO()
235
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
236
 
                            u'new_\xe5', ['new_text\n'], output)
 
246
        internal_diff(u'old_\xb5', ['old_text\n'],
 
247
                    u'new_\xe5', ['new_text\n'], output)
237
248
        self.failUnless(isinstance(output.getvalue(), str),
238
249
            'internal_diff should return bytestrings')
239
250
 
240
251
 
241
 
class TestDiffFiles(tests.TestCaseInTempDir):
 
252
class TestDiffFiles(TestCaseInTempDir):
242
253
 
243
254
    def test_external_diff_binary(self):
244
255
        """The output when using external diff should use diff's i18n error"""
257
268
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
258
269
 
259
270
 
260
 
class TestShowDiffTreesHelper(tests.TestCaseWithTransport):
 
271
class TestShowDiffTreesHelper(TestCaseWithTransport):
261
272
    """Has a helper for running show_diff_trees"""
262
273
 
263
274
    def get_diff(self, tree1, tree2, specific_files=None, working_tree=None):
266
277
            extra_trees = (working_tree,)
267
278
        else:
268
279
            extra_trees = ()
269
 
        diff.show_diff_trees(tree1, tree2, output,
270
 
                             specific_files=specific_files,
271
 
                             extra_trees=extra_trees, old_label='old/',
272
 
                             new_label='new/')
 
280
        show_diff_trees(tree1, tree2, output, specific_files=specific_files,
 
281
                        extra_trees=extra_trees, old_label='old/',
 
282
                        new_label='new/')
273
283
        return output.getvalue()
274
284
 
275
285
 
414
424
        tree.commit('one', rev_id='rev-1')
415
425
 
416
426
        self.build_tree_contents([('tree/file', 'new contents\n')])
417
 
        d = self.get_diff(tree.basis_tree(), tree)
418
 
        self.assertContainsRe(d, "=== modified file 'file'\n")
419
 
        self.assertContainsRe(d, '--- old/file\t')
420
 
        self.assertContainsRe(d, '\\+\\+\\+ new/file\t')
421
 
        self.assertContainsRe(d, '-contents\n'
422
 
                                 '\\+new contents\n')
 
427
        diff = self.get_diff(tree.basis_tree(), tree)
 
428
        self.assertContainsRe(diff, "=== modified file 'file'\n")
 
429
        self.assertContainsRe(diff, '--- old/file\t')
 
430
        self.assertContainsRe(diff, '\\+\\+\\+ new/file\t')
 
431
        self.assertContainsRe(diff, '-contents\n'
 
432
                                    '\\+new contents\n')
423
433
 
424
434
    def test_modified_file_in_renamed_dir(self):
425
435
        """Test when a file is modified in a renamed directory."""
431
441
 
432
442
        tree.rename_one('dir', 'other')
433
443
        self.build_tree_contents([('tree/other/file', 'new contents\n')])
434
 
        d = self.get_diff(tree.basis_tree(), tree)
435
 
        self.assertContainsRe(d, "=== renamed directory 'dir' => 'other'\n")
436
 
        self.assertContainsRe(d, "=== modified file 'other/file'\n")
 
444
        diff = self.get_diff(tree.basis_tree(), tree)
 
445
        self.assertContainsRe(diff, "=== renamed directory 'dir' => 'other'\n")
 
446
        self.assertContainsRe(diff, "=== modified file 'other/file'\n")
437
447
        # XXX: This is technically incorrect, because it used to be at another
438
448
        # location. What to do?
439
 
        self.assertContainsRe(d, '--- old/dir/file\t')
440
 
        self.assertContainsRe(d, '\\+\\+\\+ new/other/file\t')
441
 
        self.assertContainsRe(d, '-contents\n'
442
 
                                 '\\+new contents\n')
 
449
        self.assertContainsRe(diff, '--- old/dir/file\t')
 
450
        self.assertContainsRe(diff, '\\+\\+\\+ new/other/file\t')
 
451
        self.assertContainsRe(diff, '-contents\n'
 
452
                                    '\\+new contents\n')
443
453
 
444
454
    def test_renamed_directory(self):
445
455
        """Test when only a directory is only renamed."""
450
460
        tree.commit('one', rev_id='rev-1')
451
461
 
452
462
        tree.rename_one('dir', 'newdir')
453
 
        d = self.get_diff(tree.basis_tree(), tree)
 
463
        diff = self.get_diff(tree.basis_tree(), tree)
454
464
        # Renaming a directory should be a single "you renamed this dir" even
455
465
        # when there are files inside.
456
 
        self.assertEqual(d, "=== renamed directory 'dir' => 'newdir'\n")
 
466
        self.assertEqual("=== renamed directory 'dir' => 'newdir'\n", diff)
457
467
 
458
468
    def test_renamed_file(self):
459
469
        """Test when a file is only renamed."""
463
473
        tree.commit('one', rev_id='rev-1')
464
474
 
465
475
        tree.rename_one('file', 'newname')
466
 
        d = self.get_diff(tree.basis_tree(), tree)
467
 
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
 
476
        diff = self.get_diff(tree.basis_tree(), tree)
 
477
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
468
478
        # We shouldn't have a --- or +++ line, because there is no content
469
479
        # change
470
 
        self.assertNotContainsRe(d, '---')
 
480
        self.assertNotContainsRe(diff, '---')
471
481
 
472
482
    def test_renamed_and_modified_file(self):
473
483
        """Test when a file is only renamed."""
478
488
 
479
489
        tree.rename_one('file', 'newname')
480
490
        self.build_tree_contents([('tree/newname', 'new contents\n')])
481
 
        d = self.get_diff(tree.basis_tree(), tree)
482
 
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
483
 
        self.assertContainsRe(d, '--- old/file\t')
484
 
        self.assertContainsRe(d, '\\+\\+\\+ new/newname\t')
485
 
        self.assertContainsRe(d, '-contents\n'
486
 
                                 '\\+new contents\n')
 
491
        diff = self.get_diff(tree.basis_tree(), tree)
 
492
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
 
493
        self.assertContainsRe(diff, '--- old/file\t')
 
494
        self.assertContainsRe(diff, '\\+\\+\\+ new/newname\t')
 
495
        self.assertContainsRe(diff, '-contents\n'
 
496
                                    '\\+new contents\n')
487
497
 
488
498
 
489
499
    def test_internal_diff_exec_property(self):
508
518
        tree.rename_one('c', 'new-c')
509
519
        tree.rename_one('d', 'new-d')
510
520
 
511
 
        d = self.get_diff(tree.basis_tree(), tree)
 
521
        diff = self.get_diff(tree.basis_tree(), tree)
512
522
 
513
 
        self.assertContainsRe(d, r"file 'a'.*\(properties changed:"
514
 
                                  ".*\+x to -x.*\)")
515
 
        self.assertContainsRe(d, r"file 'b'.*\(properties changed:"
516
 
                                  ".*-x to \+x.*\)")
517
 
        self.assertContainsRe(d, r"file 'c'.*\(properties changed:"
518
 
                                  ".*\+x to -x.*\)")
519
 
        self.assertContainsRe(d, r"file 'd'.*\(properties changed:"
520
 
                                  ".*-x to \+x.*\)")
521
 
        self.assertNotContainsRe(d, r"file 'e'")
522
 
        self.assertNotContainsRe(d, r"file 'f'")
 
523
        self.assertContainsRe(diff, r"file 'a'.*\(properties changed:.*\+x to -x.*\)")
 
524
        self.assertContainsRe(diff, r"file 'b'.*\(properties changed:.*-x to \+x.*\)")
 
525
        self.assertContainsRe(diff, r"file 'c'.*\(properties changed:.*\+x to -x.*\)")
 
526
        self.assertContainsRe(diff, r"file 'd'.*\(properties changed:.*-x to \+x.*\)")
 
527
        self.assertNotContainsRe(diff, r"file 'e'")
 
528
        self.assertNotContainsRe(diff, r"file 'f'")
523
529
 
524
530
 
525
531
    def test_binary_unicode_filenames(self):
541
547
        tree.add([alpha], ['file-id'])
542
548
        tree.add([omega], ['file-id-2'])
543
549
        diff_content = StringIO()
544
 
        diff.show_diff_trees(tree.basis_tree(), tree, diff_content)
545
 
        d = diff_content.getvalue()
546
 
        self.assertContainsRe(d, r"=== added file '%s'" % alpha_utf8)
547
 
        self.assertContainsRe(d, "Binary files a/%s.*and b/%s.* differ\n"
548
 
                              % (alpha_utf8, alpha_utf8))
549
 
        self.assertContainsRe(d, r"=== added file '%s'" % omega_utf8)
550
 
        self.assertContainsRe(d, r"--- a/%s" % (omega_utf8,))
551
 
        self.assertContainsRe(d, r"\+\+\+ b/%s" % (omega_utf8,))
 
550
        show_diff_trees(tree.basis_tree(), tree, diff_content)
 
551
        diff = diff_content.getvalue()
 
552
        self.assertContainsRe(diff, r"=== added file '%s'" % alpha_utf8)
 
553
        self.assertContainsRe(
 
554
            diff, "Binary files a/%s.*and b/%s.* differ\n" % (alpha_utf8, alpha_utf8))
 
555
        self.assertContainsRe(diff, r"=== added file '%s'" % omega_utf8)
 
556
        self.assertContainsRe(diff, r"--- a/%s" % (omega_utf8,))
 
557
        self.assertContainsRe(diff, r"\+\+\+ b/%s" % (omega_utf8,))
552
558
 
553
559
    def test_unicode_filename(self):
554
560
        """Test when the filename are unicode."""
573
579
        tree.add(['add_'+alpha], ['file-id'])
574
580
        self.build_tree_contents([('tree/mod_'+alpha, 'contents_mod\n')])
575
581
 
576
 
        d = self.get_diff(tree.basis_tree(), tree)
577
 
        self.assertContainsRe(d,
 
582
        diff = self.get_diff(tree.basis_tree(), tree)
 
583
        self.assertContainsRe(diff,
578
584
                "=== renamed file 'ren_%s' => 'ren_%s'\n"%(autf8, outf8))
579
 
        self.assertContainsRe(d, "=== added file 'add_%s'"%autf8)
580
 
        self.assertContainsRe(d, "=== modified file 'mod_%s'"%autf8)
581
 
        self.assertContainsRe(d, "=== removed file 'del_%s'"%autf8)
582
 
 
583
 
 
584
 
class DiffWasIs(diff.DiffPath):
 
585
        self.assertContainsRe(diff, "=== added file 'add_%s'"%autf8)
 
586
        self.assertContainsRe(diff, "=== modified file 'mod_%s'"%autf8)
 
587
        self.assertContainsRe(diff, "=== removed file 'del_%s'"%autf8)
 
588
 
 
589
 
 
590
class DiffWasIs(DiffPath):
585
591
 
586
592
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
587
593
        self.to_file.write('was: ')
591
597
        pass
592
598
 
593
599
 
594
 
class TestDiffTree(tests.TestCaseWithTransport):
 
600
class TestDiffTree(TestCaseWithTransport):
595
601
 
596
602
    def setUp(self):
597
 
        super(TestDiffTree, self).setUp()
 
603
        TestCaseWithTransport.setUp(self)
598
604
        self.old_tree = self.make_branch_and_tree('old-tree')
599
605
        self.old_tree.lock_write()
600
606
        self.addCleanup(self.old_tree.unlock)
601
607
        self.new_tree = self.make_branch_and_tree('new-tree')
602
608
        self.new_tree.lock_write()
603
609
        self.addCleanup(self.new_tree.unlock)
604
 
        self.differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
 
610
        self.differ = DiffTree(self.old_tree, self.new_tree, StringIO())
605
611
 
606
612
    def test_diff_text(self):
607
613
        self.build_tree_contents([('old-tree/olddir/',),
612
618
                                  ('new-tree/newdir/newfile', 'new\n')])
613
619
        self.new_tree.add('newdir')
614
620
        self.new_tree.add('newdir/newfile', 'file-id')
615
 
        differ = diff.DiffText(self.old_tree, self.new_tree, StringIO())
 
621
        differ = DiffText(self.old_tree, self.new_tree, StringIO())
616
622
        differ.diff_text('file-id', None, 'old label', 'new label')
617
623
        self.assertEqual(
618
624
            '--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
647
653
        self.assertContainsRe(self.differ.to_file.getvalue(), '\+contents')
648
654
 
649
655
    def test_diff_symlink(self):
650
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
656
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
651
657
        differ.diff_symlink('old target', None)
652
658
        self.assertEqual("=== target was 'old target'\n",
653
659
                         differ.to_file.getvalue())
654
660
 
655
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
661
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
656
662
        differ.diff_symlink(None, 'new target')
657
663
        self.assertEqual("=== target is 'new target'\n",
658
664
                         differ.to_file.getvalue())
659
665
 
660
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
666
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
661
667
        differ.diff_symlink('old target', 'new target')
662
668
        self.assertEqual("=== target changed 'old target' => 'new target'\n",
663
669
                         differ.to_file.getvalue())
713
719
 
714
720
    def test_register_diff(self):
715
721
        self.create_old_new()
716
 
        old_diff_factories = diff.DiffTree.diff_factories
717
 
        diff.DiffTree.diff_factories=old_diff_factories[:]
718
 
        diff.DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
 
722
        old_diff_factories = DiffTree.diff_factories
 
723
        DiffTree.diff_factories=old_diff_factories[:]
 
724
        DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
719
725
        try:
720
 
            differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
 
726
            differ = DiffTree(self.old_tree, self.new_tree, StringIO())
721
727
        finally:
722
 
            diff.DiffTree.diff_factories = old_diff_factories
 
728
            DiffTree.diff_factories = old_diff_factories
723
729
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
724
730
        self.assertNotContainsRe(
725
731
            differ.to_file.getvalue(),
730
736
 
731
737
    def test_extra_factories(self):
732
738
        self.create_old_new()
733
 
        differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO(),
734
 
                               extra_factories=[DiffWasIs.from_diff_tree])
 
739
        differ = DiffTree(self.old_tree, self.new_tree, StringIO(),
 
740
                            extra_factories=[DiffWasIs.from_diff_tree])
735
741
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
736
742
        self.assertNotContainsRe(
737
743
            differ.to_file.getvalue(),
750
756
            '.*a-file(.|\n)*b-file')
751
757
 
752
758
 
753
 
class TestPatienceDiffLib(tests.TestCase):
 
759
class TestPatienceDiffLib(TestCase):
754
760
 
755
761
    def setUp(self):
756
762
        super(TestPatienceDiffLib, self).setUp()
757
 
        self._unique_lcs = _patiencediff_py.unique_lcs_py
758
 
        self._recurse_matches = _patiencediff_py.recurse_matches_py
 
763
        self._unique_lcs = bzrlib._patiencediff_py.unique_lcs_py
 
764
        self._recurse_matches = bzrlib._patiencediff_py.recurse_matches_py
759
765
        self._PatienceSequenceMatcher = \
760
 
            _patiencediff_py.PatienceSequenceMatcher_py
 
766
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
761
767
 
762
768
    def test_diff_unicode_string(self):
763
769
        a = ''.join([unichr(i) for i in range(4000, 4500, 3)])
1070
1076
                 'how are you today?\n']
1071
1077
        txt_b = ['hello there\n',
1072
1078
                 'how are you today?\n']
1073
 
        unified_diff = patiencediff.unified_diff
 
1079
        unified_diff = bzrlib.patiencediff.unified_diff
1074
1080
        psm = self._PatienceSequenceMatcher
1075
1081
        self.assertEquals(['--- \n',
1076
1082
                           '+++ \n',
1124
1130
                 'how are you today?\n']
1125
1131
        txt_b = ['hello there\n',
1126
1132
                 'how are you today?\n']
1127
 
        unified_diff = patiencediff.unified_diff
 
1133
        unified_diff = bzrlib.patiencediff.unified_diff
1128
1134
        psm = self._PatienceSequenceMatcher
1129
1135
        self.assertEquals(['--- a\t2008-08-08\n',
1130
1136
                           '+++ b\t2008-09-09\n',
1146
1152
 
1147
1153
    def setUp(self):
1148
1154
        super(TestPatienceDiffLib_c, self).setUp()
1149
 
        from bzrlib import _patiencediff_c
1150
 
        self._unique_lcs = _patiencediff_c.unique_lcs_c
1151
 
        self._recurse_matches = _patiencediff_c.recurse_matches_c
 
1155
        import bzrlib._patiencediff_c
 
1156
        self._unique_lcs = bzrlib._patiencediff_c.unique_lcs_c
 
1157
        self._recurse_matches = bzrlib._patiencediff_c.recurse_matches_c
1152
1158
        self._PatienceSequenceMatcher = \
1153
 
            _patiencediff_c.PatienceSequenceMatcher_c
 
1159
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
1154
1160
 
1155
1161
    def test_unhashable(self):
1156
1162
        """We should get a proper exception here."""
1166
1172
                                         None, ['valid'], ['valid', []])
1167
1173
 
1168
1174
 
1169
 
class TestPatienceDiffLibFiles(tests.TestCaseInTempDir):
 
1175
class TestPatienceDiffLibFiles(TestCaseInTempDir):
1170
1176
 
1171
1177
    def setUp(self):
1172
1178
        super(TestPatienceDiffLibFiles, self).setUp()
1173
1179
        self._PatienceSequenceMatcher = \
1174
 
            _patiencediff_py.PatienceSequenceMatcher_py
 
1180
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
1175
1181
 
1176
1182
    def test_patience_unified_diff_files(self):
1177
1183
        txt_a = ['hello there\n',
1182
1188
        open('a1', 'wb').writelines(txt_a)
1183
1189
        open('b1', 'wb').writelines(txt_b)
1184
1190
 
1185
 
        unified_diff_files = patiencediff.unified_diff_files
 
1191
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
1186
1192
        psm = self._PatienceSequenceMatcher
1187
1193
        self.assertEquals(['--- a1\n',
1188
1194
                           '+++ b1\n',
1242
1248
 
1243
1249
    def setUp(self):
1244
1250
        super(TestPatienceDiffLibFiles_c, self).setUp()
1245
 
        from bzrlib import _patiencediff_c
 
1251
        import bzrlib._patiencediff_c
1246
1252
        self._PatienceSequenceMatcher = \
1247
 
            _patiencediff_c.PatienceSequenceMatcher_c
1248
 
 
1249
 
 
1250
 
class TestUsingCompiledIfAvailable(tests.TestCase):
 
1253
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
 
1254
 
 
1255
 
 
1256
class TestUsingCompiledIfAvailable(TestCase):
1251
1257
 
1252
1258
    def test_PatienceSequenceMatcher(self):
1253
1259
        if compiled_patiencediff_feature.available():
1254
1260
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1255
1261
            self.assertIs(PatienceSequenceMatcher_c,
1256
 
                          patiencediff.PatienceSequenceMatcher)
 
1262
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1257
1263
        else:
1258
1264
            from bzrlib._patiencediff_py import PatienceSequenceMatcher_py
1259
1265
            self.assertIs(PatienceSequenceMatcher_py,
1260
 
                          patiencediff.PatienceSequenceMatcher)
 
1266
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1261
1267
 
1262
1268
    def test_unique_lcs(self):
1263
1269
        if compiled_patiencediff_feature.available():
1264
1270
            from bzrlib._patiencediff_c import unique_lcs_c
1265
1271
            self.assertIs(unique_lcs_c,
1266
 
                          patiencediff.unique_lcs)
 
1272
                          bzrlib.patiencediff.unique_lcs)
1267
1273
        else:
1268
1274
            from bzrlib._patiencediff_py import unique_lcs_py
1269
1275
            self.assertIs(unique_lcs_py,
1270
 
                          patiencediff.unique_lcs)
 
1276
                          bzrlib.patiencediff.unique_lcs)
1271
1277
 
1272
1278
    def test_recurse_matches(self):
1273
1279
        if compiled_patiencediff_feature.available():
1274
1280
            from bzrlib._patiencediff_c import recurse_matches_c
1275
1281
            self.assertIs(recurse_matches_c,
1276
 
                          patiencediff.recurse_matches)
 
1282
                          bzrlib.patiencediff.recurse_matches)
1277
1283
        else:
1278
1284
            from bzrlib._patiencediff_py import recurse_matches_py
1279
1285
            self.assertIs(recurse_matches_py,
1280
 
                          patiencediff.recurse_matches)
1281
 
 
1282
 
 
1283
 
class TestDiffFromTool(tests.TestCaseWithTransport):
 
1286
                          bzrlib.patiencediff.recurse_matches)
 
1287
 
 
1288
 
 
1289
class TestDiffFromTool(TestCaseWithTransport):
1284
1290
 
1285
1291
    def test_from_string(self):
1286
 
        diff_obj = diff.DiffFromTool.from_string('diff', None, None, None)
 
1292
        diff_obj = DiffFromTool.from_string('diff', None, None, None)
1287
1293
        self.addCleanup(diff_obj.finish)
1288
1294
        self.assertEqual(['diff', '@old_path', '@new_path'],
1289
1295
            diff_obj.command_template)
1290
1296
 
1291
1297
    def test_from_string_u5(self):
1292
 
        diff_obj = diff.DiffFromTool.from_string('diff "-u 5"',
1293
 
                                                 None, None, None)
 
1298
        diff_obj = DiffFromTool.from_string('diff "-u 5"', None, None, None)
1294
1299
        self.addCleanup(diff_obj.finish)
1295
1300
        self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
1296
1301
                         diff_obj.command_template)
1297
1302
        self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
1298
1303
                         diff_obj._get_command('old-path', 'new-path'))
1299
 
 
 
1304
        
1300
1305
    def test_from_string_path_with_backslashes(self):
1301
 
        self.requireFeature(test_win32utils.BackslashDirSeparatorFeature)
 
1306
        self.requireFeature(BackslashDirSeparatorFeature)
1302
1307
        tool = 'C:\\Tools\\Diff.exe'
1303
 
        diff_obj = diff.DiffFromTool.from_string(tool, None, None, None)
 
1308
        diff_obj = DiffFromTool.from_string(tool, None, None, None)
1304
1309
        self.addCleanup(diff_obj.finish)
1305
1310
        self.assertEqual(['C:\\Tools\\Diff.exe', '@old_path', '@new_path'],
1306
1311
                         diff_obj.command_template)
1309
1314
 
1310
1315
    def test_execute(self):
1311
1316
        output = StringIO()
1312
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1313
 
                                      'print "@old_path @new_path"'],
1314
 
                                     None, None, output)
 
1317
        diff_obj = DiffFromTool(['python', '-c',
 
1318
                                 'print "@old_path @new_path"'],
 
1319
                                None, None, output)
1315
1320
        self.addCleanup(diff_obj.finish)
1316
1321
        diff_obj._execute('old', 'new')
1317
1322
        self.assertEqual(output.getvalue().rstrip(), 'old new')
1318
1323
 
1319
1324
    def test_excute_missing(self):
1320
 
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1321
 
                                     None, None, None)
 
1325
        diff_obj = DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
 
1326
                                None, None, None)
1322
1327
        self.addCleanup(diff_obj.finish)
1323
 
        e = self.assertRaises(errors.ExecutableMissing, diff_obj._execute,
1324
 
                              'old', 'new')
 
1328
        e = self.assertRaises(ExecutableMissing, diff_obj._execute, 'old',
 
1329
                              'new')
1325
1330
        self.assertEqual('a-tool-which-is-unlikely-to-exist could not be found'
1326
1331
                         ' on this machine', str(e))
1327
1332
 
1337
1342
        basis_tree = tree.basis_tree()
1338
1343
        basis_tree.lock_read()
1339
1344
        self.addCleanup(basis_tree.unlock)
1340
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1341
 
                                      'print "@old_path @new_path"'],
1342
 
                                     basis_tree, tree, output)
 
1345
        diff_obj = DiffFromTool(['python', '-c',
 
1346
                                 'print "@old_path @new_path"'],
 
1347
                                basis_tree, tree, output)
1343
1348
        diff_obj._prepare_files('file-id', 'file', 'file')
1344
1349
        # The old content should be readonly
1345
1350
        self.assertReadableByAttrib(diff_obj._root, 'old\\file',
1362
1367
        self.build_tree_contents([('tree/oldname2', 'oldcontent2')])
1363
1368
        tree.add('oldname', 'file-id')
1364
1369
        tree.add('oldname2', 'file2-id')
1365
 
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
1366
 
        tree.commit('old tree', timestamp=315532800)
 
1370
        tree.commit('old tree', timestamp=0)
1367
1371
        tree.rename_one('oldname', 'newname')
1368
1372
        tree.rename_one('oldname2', 'newname2')
1369
1373
        self.build_tree_contents([('tree/newname', 'newcontent')])
1373
1377
        self.addCleanup(old_tree.unlock)
1374
1378
        tree.lock_read()
1375
1379
        self.addCleanup(tree.unlock)
1376
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1377
 
                                      'print "@old_path @new_path"'],
1378
 
                                     old_tree, tree, output)
 
1380
        diff_obj = DiffFromTool(['python', '-c',
 
1381
                                 'print "@old_path @new_path"'],
 
1382
                                old_tree, tree, output)
1379
1383
        self.addCleanup(diff_obj.finish)
1380
1384
        self.assertContainsRe(diff_obj._root, 'bzr-diff-[^/]*')
1381
1385
        old_path, new_path = diff_obj._prepare_files('file-id', 'oldname',
1382
1386
                                                     'newname')
1383
1387
        self.assertContainsRe(old_path, 'old/oldname$')
1384
 
        self.assertEqual(315532800, os.stat(old_path).st_mtime)
 
1388
        self.assertEqual(0, os.stat(old_path).st_mtime)
1385
1389
        self.assertContainsRe(new_path, 'tree/newname$')
1386
1390
        self.assertFileEqual('oldcontent', old_path)
1387
1391
        self.assertFileEqual('newcontent', new_path)
1391
1395
        diff_obj._prepare_files('file2-id', 'oldname2', 'newname2')
1392
1396
 
1393
1397
 
1394
 
class TestGetTreesAndBranchesToDiffLocked(tests.TestCaseWithTransport):
 
1398
class TestGetTreesAndBranchesToDiffLocked(TestCaseWithTransport):
1395
1399
 
1396
1400
    def call_gtabtd(self, path_list, revision_specs, old_url, new_url):
1397
1401
        """Call get_trees_and_branches_to_diff_locked.  Overridden by
1398
1402
        TestGetTreesAndBranchesToDiff.
1399
1403
        """
1400
 
        return diff.get_trees_and_branches_to_diff_locked(
 
1404
        return get_trees_and_branches_to_diff_locked(
1401
1405
            path_list, revision_specs, old_url, new_url, self.addCleanup)
1402
1406
 
1403
1407
    def test_basic(self):
1407
1411
         specific_files, extra_trees) = self.call_gtabtd(
1408
1412
             ['tree'], None, None, None)
1409
1413
 
1410
 
        self.assertIsInstance(old_tree, revisiontree.RevisionTree)
1411
 
        self.assertEqual(_mod_revision.NULL_REVISION,
1412
 
                         old_tree.get_revision_id())
 
1414
        self.assertIsInstance(old_tree, RevisionTree)
 
1415
        self.assertEqual(_mod_revision.NULL_REVISION, old_tree.get_revision_id())
1413
1416
        self.assertEqual(tree.basedir, new_tree.basedir)
1414
1417
        self.assertEqual(tree.branch.base, old_branch.base)
1415
1418
        self.assertEqual(tree.branch.base, new_branch.base)
1424
1427
        self.build_tree_contents([('tree/file', 'newcontent')])
1425
1428
        tree.commit('new tree', timestamp=0, rev_id="new-id")
1426
1429
 
1427
 
        revisions = [revisionspec.RevisionSpec.from_string('1'),
1428
 
                     revisionspec.RevisionSpec.from_string('2')]
 
1430
        revisions = [RevisionSpec.from_string('1'),
 
1431
                     RevisionSpec.from_string('2')]
1429
1432
        (old_tree, new_tree,
1430
1433
         old_branch, new_branch,
1431
1434
         specific_files, extra_trees) = self.call_gtabtd(
1432
1435
            ['tree'], revisions, None, None)
1433
1436
 
1434
 
        self.assertIsInstance(old_tree, revisiontree.RevisionTree)
 
1437
        self.assertIsInstance(old_tree, RevisionTree)
1435
1438
        self.assertEqual("old-id", old_tree.get_revision_id())
1436
 
        self.assertIsInstance(new_tree, revisiontree.RevisionTree)
 
1439
        self.assertIsInstance(new_tree, RevisionTree)
1437
1440
        self.assertEqual("new-id", new_tree.get_revision_id())
1438
1441
        self.assertEqual(tree.branch.base, old_branch.base)
1439
1442
        self.assertEqual(tree.branch.base, new_branch.base)
1448
1451
 
1449
1452
    def call_gtabtd(self, path_list, revision_specs, old_url, new_url):
1450
1453
        return self.applyDeprecated(
1451
 
            deprecated_in((2, 2, 0)), diff.get_trees_and_branches_to_diff,
 
1454
            deprecated_in((2, 2, 0)), get_trees_and_branches_to_diff,
1452
1455
            path_list, revision_specs, old_url, new_url)
1453
1456