/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: John Arbash Meinel
  • Date: 2008-10-14 21:35:27 UTC
  • mto: This revision was merged to the branch mainline in revision 3805.
  • Revision ID: john@arbash-meinel.com-20081014213527-4j9uc93aq1qmn43b
Add in a shortcut when we haven't cached much yet.

Document the current algorithm more completely, including the proper
justification for the various steps.

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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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,
34
35
    )
35
 
from bzrlib.symbol_versioning import deprecated_in
36
 
from bzrlib.tests import test_win32utils
37
 
 
38
 
 
39
 
class _AttribFeature(tests.Feature):
 
36
from bzrlib.errors import BinaryFile, NoDiff, ExecutableMissing
 
37
import bzrlib.osutils as osutils
 
38
import bzrlib.revision as _mod_revision
 
39
import bzrlib.transform as transform
 
40
import bzrlib.patiencediff
 
41
import bzrlib._patiencediff_py
 
42
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
 
43
                          TestCaseInTempDir, TestSkipped)
 
44
 
 
45
 
 
46
class _AttribFeature(Feature):
40
47
 
41
48
    def _probe(self):
42
49
        if (sys.platform not in ('cygwin', 'win32')):
53
60
AttribFeature = _AttribFeature()
54
61
 
55
62
 
56
 
compiled_patiencediff_feature = tests.ModuleAvailableFeature(
57
 
                                    'bzrlib._patiencediff_c')
 
63
class _CompiledPatienceDiffFeature(Feature):
 
64
 
 
65
    def _probe(self):
 
66
        try:
 
67
            import bzrlib._patiencediff_c
 
68
        except ImportError:
 
69
            return False
 
70
        return True
 
71
 
 
72
    def feature_name(self):
 
73
        return 'bzrlib._patiencediff_c'
 
74
 
 
75
CompiledPatienceDiffFeature = _CompiledPatienceDiffFeature()
58
76
 
59
77
 
60
78
def udiff_lines(old, new, allow_binary=False):
61
79
    output = StringIO()
62
 
    diff.internal_diff('old', old, 'new', new, output, allow_binary)
 
80
    internal_diff('old', old, 'new', new, output, allow_binary)
63
81
    output.seek(0, 0)
64
82
    return output.readlines()
65
83
 
69
87
        # StringIO has no fileno, so it tests a different codepath
70
88
        output = StringIO()
71
89
    else:
72
 
        output = tempfile.TemporaryFile()
 
90
        output = TemporaryFile()
73
91
    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')
 
92
        external_diff('old', old, 'new', new, output, diff_opts=['-u'])
 
93
    except NoDiff:
 
94
        raise TestSkipped('external "diff" not present to test')
77
95
    output.seek(0, 0)
78
96
    lines = output.readlines()
79
97
    output.close()
80
98
    return lines
81
99
 
82
100
 
83
 
class TestDiff(tests.TestCase):
 
101
class TestDiff(TestCase):
84
102
 
85
103
    def test_add_nl(self):
86
104
        """diff generates a valid diff for patches that add a newline"""
122
140
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
123
141
 
124
142
    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)
 
143
        self.assertRaises(BinaryFile, udiff_lines, [1023 * 'a' + '\x00'], [])
 
144
        self.assertRaises(BinaryFile, udiff_lines, [], [1023 * 'a' + '\x00'])
 
145
        udiff_lines([1023 * 'a' + '\x00'], [], allow_binary=True)
 
146
        udiff_lines([], [1023 * 'a' + '\x00'], allow_binary=True)
131
147
 
132
148
    def test_external_diff(self):
133
149
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
163
179
        orig_path = os.environ['PATH']
164
180
        try:
165
181
            os.environ['PATH'] = ''
166
 
            self.assertRaises(errors.NoDiff, diff.external_diff,
 
182
            self.assertRaises(NoDiff, external_diff,
167
183
                              'old', ['boo\n'], 'new', ['goo\n'],
168
184
                              StringIO(), diff_opts=['-u'])
169
185
        finally:
170
186
            os.environ['PATH'] = orig_path
171
 
 
 
187
        
172
188
    def test_internal_diff_default(self):
173
189
        # Default internal diff encoding is utf8
174
190
        output = StringIO()
175
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
176
 
                           u'new_\xe5', ['new_text\n'], output)
 
191
        internal_diff(u'old_\xb5', ['old_text\n'],
 
192
                    u'new_\xe5', ['new_text\n'], output)
177
193
        lines = output.getvalue().splitlines(True)
178
194
        self.check_patch(lines)
179
195
        self.assertEquals(['--- old_\xc2\xb5\n',
187
203
 
188
204
    def test_internal_diff_utf8(self):
189
205
        output = StringIO()
190
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
191
 
                           u'new_\xe5', ['new_text\n'], output,
192
 
                           path_encoding='utf8')
 
206
        internal_diff(u'old_\xb5', ['old_text\n'],
 
207
                    u'new_\xe5', ['new_text\n'], output,
 
208
                    path_encoding='utf8')
193
209
        lines = output.getvalue().splitlines(True)
194
210
        self.check_patch(lines)
195
211
        self.assertEquals(['--- old_\xc2\xb5\n',
203
219
 
204
220
    def test_internal_diff_iso_8859_1(self):
205
221
        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')
 
222
        internal_diff(u'old_\xb5', ['old_text\n'],
 
223
                    u'new_\xe5', ['new_text\n'], output,
 
224
                    path_encoding='iso-8859-1')
209
225
        lines = output.getvalue().splitlines(True)
210
226
        self.check_patch(lines)
211
227
        self.assertEquals(['--- old_\xb5\n',
219
235
 
220
236
    def test_internal_diff_no_content(self):
221
237
        output = StringIO()
222
 
        diff.internal_diff(u'old', [], u'new', [], output)
 
238
        internal_diff(u'old', [], u'new', [], output)
223
239
        self.assertEqual('', output.getvalue())
224
240
 
225
241
    def test_internal_diff_no_changes(self):
226
242
        output = StringIO()
227
 
        diff.internal_diff(u'old', ['text\n', 'contents\n'],
228
 
                           u'new', ['text\n', 'contents\n'],
229
 
                           output)
 
243
        internal_diff(u'old', ['text\n', 'contents\n'],
 
244
                      u'new', ['text\n', 'contents\n'],
 
245
                      output)
230
246
        self.assertEqual('', output.getvalue())
231
247
 
232
248
    def test_internal_diff_returns_bytes(self):
233
249
        import StringIO
234
250
        output = StringIO.StringIO()
235
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
236
 
                            u'new_\xe5', ['new_text\n'], output)
 
251
        internal_diff(u'old_\xb5', ['old_text\n'],
 
252
                    u'new_\xe5', ['new_text\n'], output)
237
253
        self.failUnless(isinstance(output.getvalue(), str),
238
254
            'internal_diff should return bytestrings')
239
255
 
240
256
 
241
 
class TestDiffFiles(tests.TestCaseInTempDir):
 
257
class TestDiffFiles(TestCaseInTempDir):
242
258
 
243
259
    def test_external_diff_binary(self):
244
260
        """The output when using external diff should use diff's i18n error"""
257
273
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
258
274
 
259
275
 
260
 
class TestShowDiffTreesHelper(tests.TestCaseWithTransport):
 
276
class TestShowDiffTreesHelper(TestCaseWithTransport):
261
277
    """Has a helper for running show_diff_trees"""
262
278
 
263
279
    def get_diff(self, tree1, tree2, specific_files=None, working_tree=None):
266
282
            extra_trees = (working_tree,)
267
283
        else:
268
284
            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/')
 
285
        show_diff_trees(tree1, tree2, output, specific_files=specific_files,
 
286
                        extra_trees=extra_trees, old_label='old/',
 
287
                        new_label='new/')
273
288
        return output.getvalue()
274
289
 
275
290
 
340
355
+file2 contents at rev 3
341
356
 
342
357
''')
343
 
 
 
358
        
344
359
    def test_diff_add_files(self):
345
360
        tree1 = self.b.repository.revision_tree(_mod_revision.NULL_REVISION)
346
361
        tree2 = self.b.repository.revision_tree('rev-1')
382
397
        self.wt.rename_one('file1', 'file1b')
383
398
        old_tree = self.b.repository.revision_tree('rev-1')
384
399
        new_tree = self.b.repository.revision_tree('rev-4')
385
 
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'],
 
400
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'], 
386
401
                            working_tree=self.wt)
387
402
        self.assertContainsRe(out, 'file1\t')
388
403
 
394
409
        self.wt.rename_one('file1', 'dir1/file1')
395
410
        old_tree = self.b.repository.revision_tree('rev-1')
396
411
        new_tree = self.b.repository.revision_tree('rev-4')
397
 
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'],
 
412
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'], 
398
413
                            working_tree=self.wt)
399
414
        self.assertContainsRe(out, 'file1\t')
400
 
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'],
 
415
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'], 
401
416
                            working_tree=self.wt)
402
417
        self.assertNotContainsRe(out, 'file1\t')
403
418
 
414
429
        tree.commit('one', rev_id='rev-1')
415
430
 
416
431
        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')
 
432
        diff = self.get_diff(tree.basis_tree(), tree)
 
433
        self.assertContainsRe(diff, "=== modified file 'file'\n")
 
434
        self.assertContainsRe(diff, '--- old/file\t')
 
435
        self.assertContainsRe(diff, '\\+\\+\\+ new/file\t')
 
436
        self.assertContainsRe(diff, '-contents\n'
 
437
                                    '\\+new contents\n')
423
438
 
424
439
    def test_modified_file_in_renamed_dir(self):
425
440
        """Test when a file is modified in a renamed directory."""
431
446
 
432
447
        tree.rename_one('dir', 'other')
433
448
        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")
 
449
        diff = self.get_diff(tree.basis_tree(), tree)
 
450
        self.assertContainsRe(diff, "=== renamed directory 'dir' => 'other'\n")
 
451
        self.assertContainsRe(diff, "=== modified file 'other/file'\n")
437
452
        # XXX: This is technically incorrect, because it used to be at another
438
453
        # 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')
 
454
        self.assertContainsRe(diff, '--- old/dir/file\t')
 
455
        self.assertContainsRe(diff, '\\+\\+\\+ new/other/file\t')
 
456
        self.assertContainsRe(diff, '-contents\n'
 
457
                                    '\\+new contents\n')
443
458
 
444
459
    def test_renamed_directory(self):
445
460
        """Test when only a directory is only renamed."""
450
465
        tree.commit('one', rev_id='rev-1')
451
466
 
452
467
        tree.rename_one('dir', 'newdir')
453
 
        d = self.get_diff(tree.basis_tree(), tree)
 
468
        diff = self.get_diff(tree.basis_tree(), tree)
454
469
        # Renaming a directory should be a single "you renamed this dir" even
455
470
        # when there are files inside.
456
 
        self.assertEqual(d, "=== renamed directory 'dir' => 'newdir'\n")
 
471
        self.assertEqual("=== renamed directory 'dir' => 'newdir'\n", diff)
457
472
 
458
473
    def test_renamed_file(self):
459
474
        """Test when a file is only renamed."""
463
478
        tree.commit('one', rev_id='rev-1')
464
479
 
465
480
        tree.rename_one('file', 'newname')
466
 
        d = self.get_diff(tree.basis_tree(), tree)
467
 
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
 
481
        diff = self.get_diff(tree.basis_tree(), tree)
 
482
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
468
483
        # We shouldn't have a --- or +++ line, because there is no content
469
484
        # change
470
 
        self.assertNotContainsRe(d, '---')
 
485
        self.assertNotContainsRe(diff, '---')
471
486
 
472
487
    def test_renamed_and_modified_file(self):
473
488
        """Test when a file is only renamed."""
478
493
 
479
494
        tree.rename_one('file', 'newname')
480
495
        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')
 
496
        diff = self.get_diff(tree.basis_tree(), tree)
 
497
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
 
498
        self.assertContainsRe(diff, '--- old/file\t')
 
499
        self.assertContainsRe(diff, '\\+\\+\\+ new/newname\t')
 
500
        self.assertContainsRe(diff, '-contents\n'
 
501
                                    '\\+new contents\n')
487
502
 
488
503
 
489
504
    def test_internal_diff_exec_property(self):
508
523
        tree.rename_one('c', 'new-c')
509
524
        tree.rename_one('d', 'new-d')
510
525
 
511
 
        d = self.get_diff(tree.basis_tree(), tree)
 
526
        diff = self.get_diff(tree.basis_tree(), tree)
512
527
 
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'")
 
528
        self.assertContainsRe(diff, r"file 'a'.*\(properties changed:.*\+x to -x.*\)")
 
529
        self.assertContainsRe(diff, r"file 'b'.*\(properties changed:.*-x to \+x.*\)")
 
530
        self.assertContainsRe(diff, r"file 'c'.*\(properties changed:.*\+x to -x.*\)")
 
531
        self.assertContainsRe(diff, r"file 'd'.*\(properties changed:.*-x to \+x.*\)")
 
532
        self.assertNotContainsRe(diff, r"file 'e'")
 
533
        self.assertNotContainsRe(diff, r"file 'f'")
523
534
 
524
535
 
525
536
    def test_binary_unicode_filenames(self):
541
552
        tree.add([alpha], ['file-id'])
542
553
        tree.add([omega], ['file-id-2'])
543
554
        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,))
 
555
        show_diff_trees(tree.basis_tree(), tree, diff_content)
 
556
        diff = diff_content.getvalue()
 
557
        self.assertContainsRe(diff, r"=== added file '%s'" % alpha_utf8)
 
558
        self.assertContainsRe(
 
559
            diff, "Binary files a/%s.*and b/%s.* differ\n" % (alpha_utf8, alpha_utf8))
 
560
        self.assertContainsRe(diff, r"=== added file '%s'" % omega_utf8)
 
561
        self.assertContainsRe(diff, r"--- a/%s" % (omega_utf8,))
 
562
        self.assertContainsRe(diff, r"\+\+\+ b/%s" % (omega_utf8,))
552
563
 
553
564
    def test_unicode_filename(self):
554
565
        """Test when the filename are unicode."""
573
584
        tree.add(['add_'+alpha], ['file-id'])
574
585
        self.build_tree_contents([('tree/mod_'+alpha, 'contents_mod\n')])
575
586
 
576
 
        d = self.get_diff(tree.basis_tree(), tree)
577
 
        self.assertContainsRe(d,
 
587
        diff = self.get_diff(tree.basis_tree(), tree)
 
588
        self.assertContainsRe(diff,
578
589
                "=== 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):
 
590
        self.assertContainsRe(diff, "=== added file 'add_%s'"%autf8)
 
591
        self.assertContainsRe(diff, "=== modified file 'mod_%s'"%autf8)
 
592
        self.assertContainsRe(diff, "=== removed file 'del_%s'"%autf8)
 
593
 
 
594
 
 
595
class DiffWasIs(DiffPath):
585
596
 
586
597
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
587
598
        self.to_file.write('was: ')
591
602
        pass
592
603
 
593
604
 
594
 
class TestDiffTree(tests.TestCaseWithTransport):
 
605
class TestDiffTree(TestCaseWithTransport):
595
606
 
596
607
    def setUp(self):
597
 
        super(TestDiffTree, self).setUp()
 
608
        TestCaseWithTransport.setUp(self)
598
609
        self.old_tree = self.make_branch_and_tree('old-tree')
599
610
        self.old_tree.lock_write()
600
611
        self.addCleanup(self.old_tree.unlock)
601
612
        self.new_tree = self.make_branch_and_tree('new-tree')
602
613
        self.new_tree.lock_write()
603
614
        self.addCleanup(self.new_tree.unlock)
604
 
        self.differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
 
615
        self.differ = DiffTree(self.old_tree, self.new_tree, StringIO())
605
616
 
606
617
    def test_diff_text(self):
607
618
        self.build_tree_contents([('old-tree/olddir/',),
612
623
                                  ('new-tree/newdir/newfile', 'new\n')])
613
624
        self.new_tree.add('newdir')
614
625
        self.new_tree.add('newdir/newfile', 'file-id')
615
 
        differ = diff.DiffText(self.old_tree, self.new_tree, StringIO())
 
626
        differ = DiffText(self.old_tree, self.new_tree, StringIO())
616
627
        differ.diff_text('file-id', None, 'old label', 'new label')
617
628
        self.assertEqual(
618
629
            '--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
647
658
        self.assertContainsRe(self.differ.to_file.getvalue(), '\+contents')
648
659
 
649
660
    def test_diff_symlink(self):
650
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
661
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
651
662
        differ.diff_symlink('old target', None)
652
663
        self.assertEqual("=== target was 'old target'\n",
653
664
                         differ.to_file.getvalue())
654
665
 
655
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
666
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
656
667
        differ.diff_symlink(None, 'new target')
657
668
        self.assertEqual("=== target is 'new target'\n",
658
669
                         differ.to_file.getvalue())
659
670
 
660
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
671
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
661
672
        differ.diff_symlink('old target', 'new target')
662
673
        self.assertEqual("=== target changed 'old target' => 'new target'\n",
663
674
                         differ.to_file.getvalue())
693
704
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
694
705
             ' \@\@\n-old\n\n')
695
706
        self.assertContainsRe(self.differ.to_file.getvalue(),
696
 
                              "=== target is u'new'\n")
 
707
                              "=== target is 'new'\n")
697
708
 
698
709
    def test_diff_directory(self):
699
710
        self.build_tree(['new-tree/new-dir/'])
713
724
 
714
725
    def test_register_diff(self):
715
726
        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)
 
727
        old_diff_factories = DiffTree.diff_factories
 
728
        DiffTree.diff_factories=old_diff_factories[:]
 
729
        DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
719
730
        try:
720
 
            differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
 
731
            differ = DiffTree(self.old_tree, self.new_tree, StringIO())
721
732
        finally:
722
 
            diff.DiffTree.diff_factories = old_diff_factories
 
733
            DiffTree.diff_factories = old_diff_factories
723
734
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
724
735
        self.assertNotContainsRe(
725
736
            differ.to_file.getvalue(),
730
741
 
731
742
    def test_extra_factories(self):
732
743
        self.create_old_new()
733
 
        differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO(),
734
 
                               extra_factories=[DiffWasIs.from_diff_tree])
 
744
        differ = DiffTree(self.old_tree, self.new_tree, StringIO(),
 
745
                            extra_factories=[DiffWasIs.from_diff_tree])
735
746
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
736
747
        self.assertNotContainsRe(
737
748
            differ.to_file.getvalue(),
750
761
            '.*a-file(.|\n)*b-file')
751
762
 
752
763
 
753
 
class TestPatienceDiffLib(tests.TestCase):
 
764
class TestPatienceDiffLib(TestCase):
754
765
 
755
766
    def setUp(self):
756
767
        super(TestPatienceDiffLib, self).setUp()
757
 
        self._unique_lcs = _patiencediff_py.unique_lcs_py
758
 
        self._recurse_matches = _patiencediff_py.recurse_matches_py
 
768
        self._unique_lcs = bzrlib._patiencediff_py.unique_lcs_py
 
769
        self._recurse_matches = bzrlib._patiencediff_py.recurse_matches_py
759
770
        self._PatienceSequenceMatcher = \
760
 
            _patiencediff_py.PatienceSequenceMatcher_py
 
771
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
761
772
 
762
773
    def test_diff_unicode_string(self):
763
774
        a = ''.join([unichr(i) for i in range(4000, 4500, 3)])
776
787
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
777
788
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
778
789
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
779
 
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
 
790
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1), 
780
791
                                                         (3,3), (4,4)])
781
792
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
782
793
 
797
808
        test_one('abcdbce', 'afbcgdbce', [(0,0), (1, 2), (2, 3), (3, 5),
798
809
                                          (4, 6), (5, 7), (6, 8)])
799
810
 
800
 
        # recurse_matches doesn't match non-unique
 
811
        # recurse_matches doesn't match non-unique 
801
812
        # lines surrounded by bogus text.
802
813
        # The update has been done in patiencediff.SequenceMatcher instead
803
814
 
940
951
                 ('delete', 1,2, 1,1),
941
952
                 ('equal',  2,3, 1,2),
942
953
                ])
943
 
        chk_ops('aBccDe', 'abccde',
 
954
        chk_ops('aBccDe', 'abccde', 
944
955
                [('equal',   0,1, 0,1),
945
956
                 ('replace', 1,5, 1,5),
946
957
                 ('equal',   5,6, 5,6),
947
958
                ])
948
 
        chk_ops('aBcDec', 'abcdec',
 
959
        chk_ops('aBcDec', 'abcdec', 
949
960
                [('equal',   0,1, 0,1),
950
961
                 ('replace', 1,2, 1,2),
951
962
                 ('equal',   2,3, 2,3),
952
963
                 ('replace', 3,4, 3,4),
953
964
                 ('equal',   4,6, 4,6),
954
965
                ])
955
 
        chk_ops('aBcdEcdFg', 'abcdecdfg',
 
966
        chk_ops('aBcdEcdFg', 'abcdecdfg', 
956
967
                [('equal',   0,1, 0,1),
957
968
                 ('replace', 1,8, 1,8),
958
969
                 ('equal',   8,9, 8,9)
959
970
                ])
960
 
        chk_ops('aBcdEeXcdFg', 'abcdecdfg',
 
971
        chk_ops('aBcdEeXcdFg', 'abcdecdfg', 
961
972
                [('equal',   0,1, 0,1),
962
973
                 ('replace', 1,2, 1,2),
963
974
                 ('equal',   2,4, 2,4),
1023
1034
    """
1024
1035
    gnxrf_netf = ['svyr*']
1025
1036
    gnxrf_bcgvbaf = ['ab-erphefr']
1026
 
 
 
1037
  
1027
1038
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
1028
1039
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
1029
1040
        vs vf_dhvrg():
1037
1048
'''.splitlines(True), '''\
1038
1049
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1039
1050
 
1040
 
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl
 
1051
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl 
1041
1052
    nqq gurz.
1042
1053
    """
1043
1054
    gnxrf_netf = ['svyr*']
1070
1081
                 'how are you today?\n']
1071
1082
        txt_b = ['hello there\n',
1072
1083
                 'how are you today?\n']
1073
 
        unified_diff = patiencediff.unified_diff
 
1084
        unified_diff = bzrlib.patiencediff.unified_diff
1074
1085
        psm = self._PatienceSequenceMatcher
1075
 
        self.assertEquals(['--- \n',
1076
 
                           '+++ \n',
 
1086
        self.assertEquals([ '---  \n',
 
1087
                           '+++  \n',
1077
1088
                           '@@ -1,3 +1,2 @@\n',
1078
1089
                           ' hello there\n',
1079
1090
                           '-world\n',
1084
1095
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1085
1096
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1086
1097
        # This is the result with LongestCommonSubstring matching
1087
 
        self.assertEquals(['--- \n',
1088
 
                           '+++ \n',
 
1098
        self.assertEquals(['---  \n',
 
1099
                           '+++  \n',
1089
1100
                           '@@ -1,6 +1,11 @@\n',
1090
1101
                           ' a\n',
1091
1102
                           ' b\n',
1100
1111
                           ' f\n']
1101
1112
                          , list(unified_diff(txt_a, txt_b)))
1102
1113
        # And the patience diff
1103
 
        self.assertEquals(['--- \n',
1104
 
                           '+++ \n',
 
1114
        self.assertEquals(['---  \n',
 
1115
                           '+++  \n',
1105
1116
                           '@@ -4,6 +4,11 @@\n',
1106
1117
                           ' d\n',
1107
1118
                           ' e\n',
1118
1129
                          , list(unified_diff(txt_a, txt_b,
1119
1130
                                 sequencematcher=psm)))
1120
1131
 
1121
 
    def test_patience_unified_diff_with_dates(self):
1122
 
        txt_a = ['hello there\n',
1123
 
                 'world\n',
1124
 
                 'how are you today?\n']
1125
 
        txt_b = ['hello there\n',
1126
 
                 'how are you today?\n']
1127
 
        unified_diff = patiencediff.unified_diff
1128
 
        psm = self._PatienceSequenceMatcher
1129
 
        self.assertEquals(['--- a\t2008-08-08\n',
1130
 
                           '+++ b\t2008-09-09\n',
1131
 
                           '@@ -1,3 +1,2 @@\n',
1132
 
                           ' hello there\n',
1133
 
                           '-world\n',
1134
 
                           ' how are you today?\n'
1135
 
                          ]
1136
 
                          , list(unified_diff(txt_a, txt_b,
1137
 
                                 fromfile='a', tofile='b',
1138
 
                                 fromfiledate='2008-08-08',
1139
 
                                 tofiledate='2008-09-09',
1140
 
                                 sequencematcher=psm)))
1141
 
 
1142
1132
 
1143
1133
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1144
1134
 
1145
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1135
    _test_needs_features = [CompiledPatienceDiffFeature]
1146
1136
 
1147
1137
    def setUp(self):
1148
1138
        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
 
1139
        import bzrlib._patiencediff_c
 
1140
        self._unique_lcs = bzrlib._patiencediff_c.unique_lcs_c
 
1141
        self._recurse_matches = bzrlib._patiencediff_c.recurse_matches_c
1152
1142
        self._PatienceSequenceMatcher = \
1153
 
            _patiencediff_c.PatienceSequenceMatcher_c
 
1143
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
1154
1144
 
1155
1145
    def test_unhashable(self):
1156
1146
        """We should get a proper exception here."""
1166
1156
                                         None, ['valid'], ['valid', []])
1167
1157
 
1168
1158
 
1169
 
class TestPatienceDiffLibFiles(tests.TestCaseInTempDir):
 
1159
class TestPatienceDiffLibFiles(TestCaseInTempDir):
1170
1160
 
1171
1161
    def setUp(self):
1172
1162
        super(TestPatienceDiffLibFiles, self).setUp()
1173
1163
        self._PatienceSequenceMatcher = \
1174
 
            _patiencediff_py.PatienceSequenceMatcher_py
 
1164
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
1175
1165
 
1176
1166
    def test_patience_unified_diff_files(self):
1177
1167
        txt_a = ['hello there\n',
1182
1172
        open('a1', 'wb').writelines(txt_a)
1183
1173
        open('b1', 'wb').writelines(txt_b)
1184
1174
 
1185
 
        unified_diff_files = patiencediff.unified_diff_files
 
1175
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
1186
1176
        psm = self._PatienceSequenceMatcher
1187
 
        self.assertEquals(['--- a1\n',
1188
 
                           '+++ b1\n',
 
1177
        self.assertEquals(['--- a1 \n',
 
1178
                           '+++ b1 \n',
1189
1179
                           '@@ -1,3 +1,2 @@\n',
1190
1180
                           ' hello there\n',
1191
1181
                           '-world\n',
1200
1190
        open('b2', 'wb').writelines(txt_b)
1201
1191
 
1202
1192
        # This is the result with LongestCommonSubstring matching
1203
 
        self.assertEquals(['--- a2\n',
1204
 
                           '+++ b2\n',
 
1193
        self.assertEquals(['--- a2 \n',
 
1194
                           '+++ b2 \n',
1205
1195
                           '@@ -1,6 +1,11 @@\n',
1206
1196
                           ' a\n',
1207
1197
                           ' b\n',
1217
1207
                          , list(unified_diff_files('a2', 'b2')))
1218
1208
 
1219
1209
        # And the patience diff
1220
 
        self.assertEquals(['--- a2\n',
1221
 
                           '+++ b2\n',
 
1210
        self.assertEquals(['--- a2 \n',
 
1211
                           '+++ b2 \n',
1222
1212
                           '@@ -4,6 +4,11 @@\n',
1223
1213
                           ' d\n',
1224
1214
                           ' e\n',
1238
1228
 
1239
1229
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1240
1230
 
1241
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1231
    _test_needs_features = [CompiledPatienceDiffFeature]
1242
1232
 
1243
1233
    def setUp(self):
1244
1234
        super(TestPatienceDiffLibFiles_c, self).setUp()
1245
 
        from bzrlib import _patiencediff_c
 
1235
        import bzrlib._patiencediff_c
1246
1236
        self._PatienceSequenceMatcher = \
1247
 
            _patiencediff_c.PatienceSequenceMatcher_c
1248
 
 
1249
 
 
1250
 
class TestUsingCompiledIfAvailable(tests.TestCase):
 
1237
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
 
1238
 
 
1239
 
 
1240
class TestUsingCompiledIfAvailable(TestCase):
1251
1241
 
1252
1242
    def test_PatienceSequenceMatcher(self):
1253
 
        if compiled_patiencediff_feature.available():
 
1243
        if CompiledPatienceDiffFeature.available():
1254
1244
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1255
1245
            self.assertIs(PatienceSequenceMatcher_c,
1256
 
                          patiencediff.PatienceSequenceMatcher)
 
1246
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1257
1247
        else:
1258
1248
            from bzrlib._patiencediff_py import PatienceSequenceMatcher_py
1259
1249
            self.assertIs(PatienceSequenceMatcher_py,
1260
 
                          patiencediff.PatienceSequenceMatcher)
 
1250
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1261
1251
 
1262
1252
    def test_unique_lcs(self):
1263
 
        if compiled_patiencediff_feature.available():
 
1253
        if CompiledPatienceDiffFeature.available():
1264
1254
            from bzrlib._patiencediff_c import unique_lcs_c
1265
1255
            self.assertIs(unique_lcs_c,
1266
 
                          patiencediff.unique_lcs)
 
1256
                          bzrlib.patiencediff.unique_lcs)
1267
1257
        else:
1268
1258
            from bzrlib._patiencediff_py import unique_lcs_py
1269
1259
            self.assertIs(unique_lcs_py,
1270
 
                          patiencediff.unique_lcs)
 
1260
                          bzrlib.patiencediff.unique_lcs)
1271
1261
 
1272
1262
    def test_recurse_matches(self):
1273
 
        if compiled_patiencediff_feature.available():
 
1263
        if CompiledPatienceDiffFeature.available():
1274
1264
            from bzrlib._patiencediff_c import recurse_matches_c
1275
1265
            self.assertIs(recurse_matches_c,
1276
 
                          patiencediff.recurse_matches)
 
1266
                          bzrlib.patiencediff.recurse_matches)
1277
1267
        else:
1278
1268
            from bzrlib._patiencediff_py import recurse_matches_py
1279
1269
            self.assertIs(recurse_matches_py,
1280
 
                          patiencediff.recurse_matches)
1281
 
 
1282
 
 
1283
 
class TestDiffFromTool(tests.TestCaseWithTransport):
 
1270
                          bzrlib.patiencediff.recurse_matches)
 
1271
 
 
1272
 
 
1273
class TestDiffFromTool(TestCaseWithTransport):
1284
1274
 
1285
1275
    def test_from_string(self):
1286
 
        diff_obj = diff.DiffFromTool.from_string('diff', None, None, None)
 
1276
        diff_obj = DiffFromTool.from_string('diff', None, None, None)
1287
1277
        self.addCleanup(diff_obj.finish)
1288
 
        self.assertEqual(['diff', '@old_path', '@new_path'],
 
1278
        self.assertEqual(['diff', '%(old_path)s', '%(new_path)s'],
1289
1279
            diff_obj.command_template)
1290
1280
 
1291
1281
    def test_from_string_u5(self):
1292
 
        diff_obj = diff.DiffFromTool.from_string('diff "-u 5"',
1293
 
                                                 None, None, None)
 
1282
        diff_obj = DiffFromTool.from_string('diff -u\\ 5', None, None, None)
1294
1283
        self.addCleanup(diff_obj.finish)
1295
 
        self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
 
1284
        self.assertEqual(['diff', '-u 5', '%(old_path)s', '%(new_path)s'],
1296
1285
                         diff_obj.command_template)
1297
1286
        self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
1298
1287
                         diff_obj._get_command('old-path', 'new-path'))
1299
1288
 
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
1289
    def test_execute(self):
1311
1290
        output = StringIO()
1312
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1313
 
                                      'print "@old_path @new_path"'],
1314
 
                                     None, None, output)
 
1291
        diff_obj = DiffFromTool(['python', '-c',
 
1292
                                 'print "%(old_path)s %(new_path)s"'],
 
1293
                                None, None, output)
1315
1294
        self.addCleanup(diff_obj.finish)
1316
1295
        diff_obj._execute('old', 'new')
1317
1296
        self.assertEqual(output.getvalue().rstrip(), 'old new')
1318
1297
 
1319
1298
    def test_excute_missing(self):
1320
 
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1321
 
                                     None, None, None)
 
1299
        diff_obj = DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
 
1300
                                None, None, None)
1322
1301
        self.addCleanup(diff_obj.finish)
1323
 
        e = self.assertRaises(errors.ExecutableMissing, diff_obj._execute,
1324
 
                              'old', 'new')
 
1302
        e = self.assertRaises(ExecutableMissing, diff_obj._execute, 'old',
 
1303
                              'new')
1325
1304
        self.assertEqual('a-tool-which-is-unlikely-to-exist could not be found'
1326
1305
                         ' on this machine', str(e))
1327
1306
 
1334
1313
        tree.commit('old tree')
1335
1314
        tree.lock_read()
1336
1315
        self.addCleanup(tree.unlock)
1337
 
        basis_tree = tree.basis_tree()
1338
 
        basis_tree.lock_read()
1339
 
        self.addCleanup(basis_tree.unlock)
1340
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1341
 
                                      'print "@old_path @new_path"'],
1342
 
                                     basis_tree, tree, output)
 
1316
        diff_obj = DiffFromTool(['python', '-c',
 
1317
                                 'print "%(old_path)s %(new_path)s"'],
 
1318
                                tree, tree, output)
1343
1319
        diff_obj._prepare_files('file-id', 'file', 'file')
1344
 
        # The old content should be readonly
1345
 
        self.assertReadableByAttrib(diff_obj._root, 'old\\file',
1346
 
                                    r'R.*old\\file$')
1347
 
        # The new content should use the tree object, not a 'new' file anymore
1348
 
        self.assertEndsWith(tree.basedir, 'work/tree')
1349
 
        self.assertReadableByAttrib(tree.basedir, 'file', r'work\\tree\\file$')
 
1320
        self.assertReadableByAttrib(diff_obj._root, 'old\\file', r'old\\file')
 
1321
        self.assertReadableByAttrib(diff_obj._root, 'new\\file', r'new\\file')
1350
1322
 
1351
1323
    def assertReadableByAttrib(self, cwd, relpath, regex):
1352
1324
        proc = subprocess.Popen(['attrib', relpath],
1353
1325
                                stdout=subprocess.PIPE,
1354
1326
                                cwd=cwd)
1355
 
        (result, err) = proc.communicate()
1356
 
        self.assertContainsRe(result.replace('\r\n', '\n'), regex)
 
1327
        proc.wait()
 
1328
        result = proc.stdout.read()
 
1329
        self.assertContainsRe(result, regex)
1357
1330
 
1358
1331
    def test_prepare_files(self):
1359
1332
        output = StringIO()
1362
1335
        self.build_tree_contents([('tree/oldname2', 'oldcontent2')])
1363
1336
        tree.add('oldname', 'file-id')
1364
1337
        tree.add('oldname2', 'file2-id')
1365
 
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
1366
 
        tree.commit('old tree', timestamp=315532800)
 
1338
        tree.commit('old tree', timestamp=0)
1367
1339
        tree.rename_one('oldname', 'newname')
1368
1340
        tree.rename_one('oldname2', 'newname2')
1369
1341
        self.build_tree_contents([('tree/newname', 'newcontent')])
1373
1345
        self.addCleanup(old_tree.unlock)
1374
1346
        tree.lock_read()
1375
1347
        self.addCleanup(tree.unlock)
1376
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1377
 
                                      'print "@old_path @new_path"'],
1378
 
                                     old_tree, tree, output)
 
1348
        diff_obj = DiffFromTool(['python', '-c',
 
1349
                                 'print "%(old_path)s %(new_path)s"'],
 
1350
                                old_tree, tree, output)
1379
1351
        self.addCleanup(diff_obj.finish)
1380
1352
        self.assertContainsRe(diff_obj._root, 'bzr-diff-[^/]*')
1381
1353
        old_path, new_path = diff_obj._prepare_files('file-id', 'oldname',
1382
1354
                                                     'newname')
1383
1355
        self.assertContainsRe(old_path, 'old/oldname$')
1384
 
        self.assertEqual(315532800, os.stat(old_path).st_mtime)
1385
 
        self.assertContainsRe(new_path, 'tree/newname$')
 
1356
        self.assertEqual(0, os.stat(old_path).st_mtime)
 
1357
        self.assertContainsRe(new_path, 'new/newname$')
1386
1358
        self.assertFileEqual('oldcontent', old_path)
1387
1359
        self.assertFileEqual('newcontent', new_path)
1388
1360
        if osutils.host_os_dereferences_symlinks():
1389
1361
            self.assertTrue(os.path.samefile('tree/newname', new_path))
1390
1362
        # make sure we can create files with the same parent directories
1391
1363
        diff_obj._prepare_files('file2-id', 'oldname2', 'newname2')
1392
 
 
1393
 
 
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)
1402
 
 
1403
 
    def test_basic(self):
1404
 
        tree = self.make_branch_and_tree('tree')
1405
 
        (old_tree, new_tree,
1406
 
         old_branch, new_branch,
1407
 
         specific_files, extra_trees) = self.call_gtabtd(
1408
 
             ['tree'], None, None, None)
1409
 
 
1410
 
        self.assertIsInstance(old_tree, revisiontree.RevisionTree)
1411
 
        self.assertEqual(_mod_revision.NULL_REVISION,
1412
 
                         old_tree.get_revision_id())
1413
 
        self.assertEqual(tree.basedir, new_tree.basedir)
1414
 
        self.assertEqual(tree.branch.base, old_branch.base)
1415
 
        self.assertEqual(tree.branch.base, new_branch.base)
1416
 
        self.assertIs(None, specific_files)
1417
 
        self.assertIs(None, extra_trees)
1418
 
 
1419
 
    def test_with_rev_specs(self):
1420
 
        tree = self.make_branch_and_tree('tree')
1421
 
        self.build_tree_contents([('tree/file', 'oldcontent')])
1422
 
        tree.add('file', 'file-id')
1423
 
        tree.commit('old tree', timestamp=0, rev_id="old-id")
1424
 
        self.build_tree_contents([('tree/file', 'newcontent')])
1425
 
        tree.commit('new tree', timestamp=0, rev_id="new-id")
1426
 
 
1427
 
        revisions = [revisionspec.RevisionSpec.from_string('1'),
1428
 
                     revisionspec.RevisionSpec.from_string('2')]
1429
 
        (old_tree, new_tree,
1430
 
         old_branch, new_branch,
1431
 
         specific_files, extra_trees) = self.call_gtabtd(
1432
 
            ['tree'], revisions, None, None)
1433
 
 
1434
 
        self.assertIsInstance(old_tree, revisiontree.RevisionTree)
1435
 
        self.assertEqual("old-id", old_tree.get_revision_id())
1436
 
        self.assertIsInstance(new_tree, revisiontree.RevisionTree)
1437
 
        self.assertEqual("new-id", new_tree.get_revision_id())
1438
 
        self.assertEqual(tree.branch.base, old_branch.base)
1439
 
        self.assertEqual(tree.branch.base, new_branch.base)
1440
 
        self.assertIs(None, specific_files)
1441
 
        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