~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

  • Committer: Martin Pool
  • Date: 2010-01-29 14:09:05 UTC
  • mto: This revision was merged to the branch mainline in revision 4992.
  • Revision ID: mbp@sourcefrog.net-20100129140905-2uiarb6p8di1ywsr
Correction to url

from review: https://code.edge.launchpad.net/~mbp/bzr/doc/+merge/18250

Show diffs side-by-side

added added

removed removed

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