/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: Vincent Ladeuil
  • Date: 2008-01-05 22:09:47 UTC
  • mto: (3928.1.1 bzr.integration)
  • mto: This revision was merged to the branch mainline in revision 3929.
  • Revision ID: v.ladeuil+lp@free.fr-20080105220947-t2kymulzeqf1g5n5
Fix the server name in script and ssl files.

* bzrlib/tests/ssl_certs/create_ssls.py:
(ssl_params): We use localhost, not 127.0.0.1.

* bzrlib/tests/ssl_certs/server_without_pass.key,
bzrlib/tests/ssl_certs/server_with_pass.key,
bzrlib/tests/ssl_certs/server.csr,
bzrlib/tests/ssl_certs/server.crt:
Re-generated since the server name was wrong.

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
18
from cStringIO import StringIO
 
19
import errno
19
20
import subprocess
20
 
import sys
21
 
import tempfile
 
21
from tempfile import TemporaryFile
22
22
 
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,
 
23
from bzrlib.diff import (
 
24
    DiffFromTool,
 
25
    DiffPath,
 
26
    DiffSymlink,
 
27
    DiffTree,
 
28
    DiffText,
 
29
    external_diff,
 
30
    internal_diff,
 
31
    show_diff_trees,
34
32
    )
35
 
from bzrlib.symbol_versioning import deprecated_in
36
 
from bzrlib.tests import test_win32utils
37
 
 
38
 
 
39
 
class _AttribFeature(tests.Feature):
 
33
from bzrlib.errors import BinaryFile, NoDiff, ExecutableMissing
 
34
import bzrlib.osutils as osutils
 
35
import bzrlib.patiencediff
 
36
import bzrlib._patiencediff_py
 
37
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
 
38
                          TestCaseInTempDir, TestSkipped)
 
39
 
 
40
 
 
41
class _CompiledPatienceDiffFeature(Feature):
40
42
 
41
43
    def _probe(self):
42
 
        if (sys.platform not in ('cygwin', 'win32')):
43
 
            return False
44
44
        try:
45
 
            proc = subprocess.Popen(['attrib', '.'], stdout=subprocess.PIPE)
46
 
        except OSError, e:
 
45
            import bzrlib._patiencediff_c
 
46
        except ImportError:
47
47
            return False
48
 
        return (0 == proc.wait())
 
48
        return True
49
49
 
50
50
    def feature_name(self):
51
 
        return 'attrib Windows command-line tool'
52
 
 
53
 
AttribFeature = _AttribFeature()
54
 
 
55
 
 
56
 
compiled_patiencediff_feature = tests.ModuleAvailableFeature(
57
 
                                    'bzrlib._patiencediff_c')
58
 
 
 
51
        return 'bzrlib._patiencediff_c'
 
52
 
 
53
CompiledPatienceDiffFeature = _CompiledPatienceDiffFeature()
 
54
 
 
55
 
 
56
class _UnicodeFilename(Feature):
 
57
    """Does the filesystem support Unicode filenames?"""
 
58
 
 
59
    def _probe(self):
 
60
        try:
 
61
            os.stat(u'\u03b1')
 
62
        except UnicodeEncodeError:
 
63
            return False
 
64
        except (IOError, OSError):
 
65
            # The filesystem allows the Unicode filename but the file doesn't
 
66
            # exist.
 
67
            return True
 
68
        else:
 
69
            # The filesystem allows the Unicode filename and the file exists,
 
70
            # for some reason.
 
71
            return True
 
72
 
 
73
UnicodeFilename = _UnicodeFilename()
 
74
 
 
75
 
 
76
class TestUnicodeFilename(TestCase):
 
77
 
 
78
    def test_probe_passes(self):
 
79
        """UnicodeFilename._probe passes."""
 
80
        # We can't test much more than that because the behaviour depends
 
81
        # on the platform.
 
82
        UnicodeFilename._probe()
 
83
        
59
84
 
60
85
def udiff_lines(old, new, allow_binary=False):
61
86
    output = StringIO()
62
 
    diff.internal_diff('old', old, 'new', new, output, allow_binary)
 
87
    internal_diff('old', old, 'new', new, output, allow_binary)
63
88
    output.seek(0, 0)
64
89
    return output.readlines()
65
90
 
69
94
        # StringIO has no fileno, so it tests a different codepath
70
95
        output = StringIO()
71
96
    else:
72
 
        output = tempfile.TemporaryFile()
 
97
        output = TemporaryFile()
73
98
    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')
 
99
        external_diff('old', old, 'new', new, output, diff_opts=['-u'])
 
100
    except NoDiff:
 
101
        raise TestSkipped('external "diff" not present to test')
77
102
    output.seek(0, 0)
78
103
    lines = output.readlines()
79
104
    output.close()
80
105
    return lines
81
106
 
82
107
 
83
 
class TestDiff(tests.TestCase):
 
108
class TestDiff(TestCase):
84
109
 
85
110
    def test_add_nl(self):
86
111
        """diff generates a valid diff for patches that add a newline"""
122
147
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
123
148
 
124
149
    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)
 
150
        self.assertRaises(BinaryFile, udiff_lines, [1023 * 'a' + '\x00'], [])
 
151
        self.assertRaises(BinaryFile, udiff_lines, [], [1023 * 'a' + '\x00'])
 
152
        udiff_lines([1023 * 'a' + '\x00'], [], allow_binary=True)
 
153
        udiff_lines([], [1023 * 'a' + '\x00'], allow_binary=True)
131
154
 
132
155
    def test_external_diff(self):
133
156
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
163
186
        orig_path = os.environ['PATH']
164
187
        try:
165
188
            os.environ['PATH'] = ''
166
 
            self.assertRaises(errors.NoDiff, diff.external_diff,
 
189
            self.assertRaises(NoDiff, external_diff,
167
190
                              'old', ['boo\n'], 'new', ['goo\n'],
168
191
                              StringIO(), diff_opts=['-u'])
169
192
        finally:
170
193
            os.environ['PATH'] = orig_path
171
 
 
 
194
        
172
195
    def test_internal_diff_default(self):
173
196
        # Default internal diff encoding is utf8
174
197
        output = StringIO()
175
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
176
 
                           u'new_\xe5', ['new_text\n'], output)
 
198
        internal_diff(u'old_\xb5', ['old_text\n'],
 
199
                    u'new_\xe5', ['new_text\n'], output)
177
200
        lines = output.getvalue().splitlines(True)
178
201
        self.check_patch(lines)
179
202
        self.assertEquals(['--- old_\xc2\xb5\n',
187
210
 
188
211
    def test_internal_diff_utf8(self):
189
212
        output = StringIO()
190
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
191
 
                           u'new_\xe5', ['new_text\n'], output,
192
 
                           path_encoding='utf8')
 
213
        internal_diff(u'old_\xb5', ['old_text\n'],
 
214
                    u'new_\xe5', ['new_text\n'], output,
 
215
                    path_encoding='utf8')
193
216
        lines = output.getvalue().splitlines(True)
194
217
        self.check_patch(lines)
195
218
        self.assertEquals(['--- old_\xc2\xb5\n',
203
226
 
204
227
    def test_internal_diff_iso_8859_1(self):
205
228
        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')
 
229
        internal_diff(u'old_\xb5', ['old_text\n'],
 
230
                    u'new_\xe5', ['new_text\n'], output,
 
231
                    path_encoding='iso-8859-1')
209
232
        lines = output.getvalue().splitlines(True)
210
233
        self.check_patch(lines)
211
234
        self.assertEquals(['--- old_\xb5\n',
219
242
 
220
243
    def test_internal_diff_no_content(self):
221
244
        output = StringIO()
222
 
        diff.internal_diff(u'old', [], u'new', [], output)
 
245
        internal_diff(u'old', [], u'new', [], output)
223
246
        self.assertEqual('', output.getvalue())
224
247
 
225
248
    def test_internal_diff_no_changes(self):
226
249
        output = StringIO()
227
 
        diff.internal_diff(u'old', ['text\n', 'contents\n'],
228
 
                           u'new', ['text\n', 'contents\n'],
229
 
                           output)
 
250
        internal_diff(u'old', ['text\n', 'contents\n'],
 
251
                      u'new', ['text\n', 'contents\n'],
 
252
                      output)
230
253
        self.assertEqual('', output.getvalue())
231
254
 
232
255
    def test_internal_diff_returns_bytes(self):
233
256
        import StringIO
234
257
        output = StringIO.StringIO()
235
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
236
 
                            u'new_\xe5', ['new_text\n'], output)
 
258
        internal_diff(u'old_\xb5', ['old_text\n'],
 
259
                    u'new_\xe5', ['new_text\n'], output)
237
260
        self.failUnless(isinstance(output.getvalue(), str),
238
261
            'internal_diff should return bytestrings')
239
262
 
240
263
 
241
 
class TestDiffFiles(tests.TestCaseInTempDir):
 
264
class TestDiffFiles(TestCaseInTempDir):
242
265
 
243
266
    def test_external_diff_binary(self):
244
267
        """The output when using external diff should use diff's i18n error"""
257
280
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
258
281
 
259
282
 
260
 
class TestShowDiffTreesHelper(tests.TestCaseWithTransport):
 
283
class TestShowDiffTreesHelper(TestCaseWithTransport):
261
284
    """Has a helper for running show_diff_trees"""
262
285
 
263
286
    def get_diff(self, tree1, tree2, specific_files=None, working_tree=None):
266
289
            extra_trees = (working_tree,)
267
290
        else:
268
291
            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/')
 
292
        show_diff_trees(tree1, tree2, output, specific_files=specific_files,
 
293
                        extra_trees=extra_trees, old_label='old/',
 
294
                        new_label='new/')
273
295
        return output.getvalue()
274
296
 
275
297
 
340
362
+file2 contents at rev 3
341
363
 
342
364
''')
343
 
 
 
365
        
344
366
    def test_diff_add_files(self):
345
 
        tree1 = self.b.repository.revision_tree(_mod_revision.NULL_REVISION)
 
367
        tree1 = self.b.repository.revision_tree(None)
346
368
        tree2 = self.b.repository.revision_tree('rev-1')
347
369
        output = self.get_diff(tree1, tree2)
348
370
        # the files have the epoch time stamp for the tree in which
382
404
        self.wt.rename_one('file1', 'file1b')
383
405
        old_tree = self.b.repository.revision_tree('rev-1')
384
406
        new_tree = self.b.repository.revision_tree('rev-4')
385
 
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'],
 
407
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'], 
386
408
                            working_tree=self.wt)
387
409
        self.assertContainsRe(out, 'file1\t')
388
410
 
394
416
        self.wt.rename_one('file1', 'dir1/file1')
395
417
        old_tree = self.b.repository.revision_tree('rev-1')
396
418
        new_tree = self.b.repository.revision_tree('rev-4')
397
 
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'],
 
419
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'], 
398
420
                            working_tree=self.wt)
399
421
        self.assertContainsRe(out, 'file1\t')
400
 
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'],
 
422
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'], 
401
423
                            working_tree=self.wt)
402
424
        self.assertNotContainsRe(out, 'file1\t')
403
425
 
414
436
        tree.commit('one', rev_id='rev-1')
415
437
 
416
438
        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')
 
439
        diff = self.get_diff(tree.basis_tree(), tree)
 
440
        self.assertContainsRe(diff, "=== modified file 'file'\n")
 
441
        self.assertContainsRe(diff, '--- old/file\t')
 
442
        self.assertContainsRe(diff, '\\+\\+\\+ new/file\t')
 
443
        self.assertContainsRe(diff, '-contents\n'
 
444
                                    '\\+new contents\n')
423
445
 
424
446
    def test_modified_file_in_renamed_dir(self):
425
447
        """Test when a file is modified in a renamed directory."""
431
453
 
432
454
        tree.rename_one('dir', 'other')
433
455
        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")
 
456
        diff = self.get_diff(tree.basis_tree(), tree)
 
457
        self.assertContainsRe(diff, "=== renamed directory 'dir' => 'other'\n")
 
458
        self.assertContainsRe(diff, "=== modified file 'other/file'\n")
437
459
        # XXX: This is technically incorrect, because it used to be at another
438
460
        # 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')
 
461
        self.assertContainsRe(diff, '--- old/dir/file\t')
 
462
        self.assertContainsRe(diff, '\\+\\+\\+ new/other/file\t')
 
463
        self.assertContainsRe(diff, '-contents\n'
 
464
                                    '\\+new contents\n')
443
465
 
444
466
    def test_renamed_directory(self):
445
467
        """Test when only a directory is only renamed."""
450
472
        tree.commit('one', rev_id='rev-1')
451
473
 
452
474
        tree.rename_one('dir', 'newdir')
453
 
        d = self.get_diff(tree.basis_tree(), tree)
 
475
        diff = self.get_diff(tree.basis_tree(), tree)
454
476
        # Renaming a directory should be a single "you renamed this dir" even
455
477
        # when there are files inside.
456
 
        self.assertEqual(d, "=== renamed directory 'dir' => 'newdir'\n")
 
478
        self.assertEqual("=== renamed directory 'dir' => 'newdir'\n", diff)
457
479
 
458
480
    def test_renamed_file(self):
459
481
        """Test when a file is only renamed."""
463
485
        tree.commit('one', rev_id='rev-1')
464
486
 
465
487
        tree.rename_one('file', 'newname')
466
 
        d = self.get_diff(tree.basis_tree(), tree)
467
 
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
 
488
        diff = self.get_diff(tree.basis_tree(), tree)
 
489
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
468
490
        # We shouldn't have a --- or +++ line, because there is no content
469
491
        # change
470
 
        self.assertNotContainsRe(d, '---')
 
492
        self.assertNotContainsRe(diff, '---')
471
493
 
472
494
    def test_renamed_and_modified_file(self):
473
495
        """Test when a file is only renamed."""
478
500
 
479
501
        tree.rename_one('file', 'newname')
480
502
        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')
487
 
 
488
 
 
489
 
    def test_internal_diff_exec_property(self):
490
 
        tree = self.make_branch_and_tree('tree')
491
 
 
492
 
        tt = transform.TreeTransform(tree)
493
 
        tt.new_file('a', tt.root, 'contents\n', 'a-id', True)
494
 
        tt.new_file('b', tt.root, 'contents\n', 'b-id', False)
495
 
        tt.new_file('c', tt.root, 'contents\n', 'c-id', True)
496
 
        tt.new_file('d', tt.root, 'contents\n', 'd-id', False)
497
 
        tt.new_file('e', tt.root, 'contents\n', 'control-e-id', True)
498
 
        tt.new_file('f', tt.root, 'contents\n', 'control-f-id', False)
499
 
        tt.apply()
500
 
        tree.commit('one', rev_id='rev-1')
501
 
 
502
 
        tt = transform.TreeTransform(tree)
503
 
        tt.set_executability(False, tt.trans_id_file_id('a-id'))
504
 
        tt.set_executability(True, tt.trans_id_file_id('b-id'))
505
 
        tt.set_executability(False, tt.trans_id_file_id('c-id'))
506
 
        tt.set_executability(True, tt.trans_id_file_id('d-id'))
507
 
        tt.apply()
508
 
        tree.rename_one('c', 'new-c')
509
 
        tree.rename_one('d', 'new-d')
510
 
 
511
 
        d = self.get_diff(tree.basis_tree(), tree)
512
 
 
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
 
 
 
503
        diff = self.get_diff(tree.basis_tree(), tree)
 
504
        self.assertContainsRe(diff, "=== renamed file 'file' => 'newname'\n")
 
505
        self.assertContainsRe(diff, '--- old/file\t')
 
506
        self.assertContainsRe(diff, '\\+\\+\\+ new/newname\t')
 
507
        self.assertContainsRe(diff, '-contents\n'
 
508
                                    '\\+new contents\n')
524
509
 
525
510
    def test_binary_unicode_filenames(self):
526
511
        """Test that contents of files are *not* encoded in UTF-8 when there
527
512
        is a binary file in the diff.
528
513
        """
529
514
        # See https://bugs.launchpad.net/bugs/110092.
530
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
515
        self.requireFeature(UnicodeFilename)
531
516
 
532
517
        # This bug isn't triggered with cStringIO.
533
518
        from StringIO import StringIO
541
526
        tree.add([alpha], ['file-id'])
542
527
        tree.add([omega], ['file-id-2'])
543
528
        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,))
 
529
        show_diff_trees(tree.basis_tree(), tree, diff_content)
 
530
        diff = diff_content.getvalue()
 
531
        self.assertContainsRe(diff, r"=== added file '%s'" % alpha_utf8)
 
532
        self.assertContainsRe(
 
533
            diff, "Binary files a/%s.*and b/%s.* differ\n" % (alpha_utf8, alpha_utf8))
 
534
        self.assertContainsRe(diff, r"=== added file '%s'" % omega_utf8)
 
535
        self.assertContainsRe(diff, r"--- a/%s" % (omega_utf8,))
 
536
        self.assertContainsRe(diff, r"\+\+\+ b/%s" % (omega_utf8,))
552
537
 
553
538
    def test_unicode_filename(self):
554
539
        """Test when the filename are unicode."""
555
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
540
        self.requireFeature(UnicodeFilename)
556
541
 
557
542
        alpha, omega = u'\u03b1', u'\u03c9'
558
543
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
573
558
        tree.add(['add_'+alpha], ['file-id'])
574
559
        self.build_tree_contents([('tree/mod_'+alpha, 'contents_mod\n')])
575
560
 
576
 
        d = self.get_diff(tree.basis_tree(), tree)
577
 
        self.assertContainsRe(d,
 
561
        diff = self.get_diff(tree.basis_tree(), tree)
 
562
        self.assertContainsRe(diff,
578
563
                "=== 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):
 
564
        self.assertContainsRe(diff, "=== added file 'add_%s'"%autf8)
 
565
        self.assertContainsRe(diff, "=== modified file 'mod_%s'"%autf8)
 
566
        self.assertContainsRe(diff, "=== removed file 'del_%s'"%autf8)
 
567
 
 
568
 
 
569
class DiffWasIs(DiffPath):
585
570
 
586
571
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
587
572
        self.to_file.write('was: ')
591
576
        pass
592
577
 
593
578
 
594
 
class TestDiffTree(tests.TestCaseWithTransport):
 
579
class TestDiffTree(TestCaseWithTransport):
595
580
 
596
581
    def setUp(self):
597
 
        super(TestDiffTree, self).setUp()
 
582
        TestCaseWithTransport.setUp(self)
598
583
        self.old_tree = self.make_branch_and_tree('old-tree')
599
584
        self.old_tree.lock_write()
600
585
        self.addCleanup(self.old_tree.unlock)
601
586
        self.new_tree = self.make_branch_and_tree('new-tree')
602
587
        self.new_tree.lock_write()
603
588
        self.addCleanup(self.new_tree.unlock)
604
 
        self.differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
 
589
        self.differ = DiffTree(self.old_tree, self.new_tree, StringIO())
605
590
 
606
591
    def test_diff_text(self):
607
592
        self.build_tree_contents([('old-tree/olddir/',),
612
597
                                  ('new-tree/newdir/newfile', 'new\n')])
613
598
        self.new_tree.add('newdir')
614
599
        self.new_tree.add('newdir/newfile', 'file-id')
615
 
        differ = diff.DiffText(self.old_tree, self.new_tree, StringIO())
 
600
        differ = DiffText(self.old_tree, self.new_tree, StringIO())
616
601
        differ.diff_text('file-id', None, 'old label', 'new label')
617
602
        self.assertEqual(
618
603
            '--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
647
632
        self.assertContainsRe(self.differ.to_file.getvalue(), '\+contents')
648
633
 
649
634
    def test_diff_symlink(self):
650
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
635
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
651
636
        differ.diff_symlink('old target', None)
652
637
        self.assertEqual("=== target was 'old target'\n",
653
638
                         differ.to_file.getvalue())
654
639
 
655
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
640
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
656
641
        differ.diff_symlink(None, 'new target')
657
642
        self.assertEqual("=== target is 'new target'\n",
658
643
                         differ.to_file.getvalue())
659
644
 
660
 
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, StringIO())
 
645
        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
661
646
        differ.diff_symlink('old target', 'new target')
662
647
        self.assertEqual("=== target changed 'old target' => 'new target'\n",
663
648
                         differ.to_file.getvalue())
678
663
             ' \@\@\n-old\n\+new\n\n')
679
664
 
680
665
    def test_diff_kind_change(self):
681
 
        self.requireFeature(tests.SymlinkFeature)
682
666
        self.build_tree_contents([('old-tree/olddir/',),
683
667
                                  ('old-tree/olddir/oldfile', 'old\n')])
684
668
        self.old_tree.add('olddir')
693
677
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
694
678
             ' \@\@\n-old\n\n')
695
679
        self.assertContainsRe(self.differ.to_file.getvalue(),
696
 
                              "=== target is u'new'\n")
 
680
                              "=== target is 'new'\n")
697
681
 
698
682
    def test_diff_directory(self):
699
683
        self.build_tree(['new-tree/new-dir/'])
713
697
 
714
698
    def test_register_diff(self):
715
699
        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)
 
700
        old_diff_factories = DiffTree.diff_factories
 
701
        DiffTree.diff_factories=old_diff_factories[:]
 
702
        DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
719
703
        try:
720
 
            differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO())
 
704
            differ = DiffTree(self.old_tree, self.new_tree, StringIO())
721
705
        finally:
722
 
            diff.DiffTree.diff_factories = old_diff_factories
 
706
            DiffTree.diff_factories = old_diff_factories
723
707
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
724
708
        self.assertNotContainsRe(
725
709
            differ.to_file.getvalue(),
730
714
 
731
715
    def test_extra_factories(self):
732
716
        self.create_old_new()
733
 
        differ = diff.DiffTree(self.old_tree, self.new_tree, StringIO(),
734
 
                               extra_factories=[DiffWasIs.from_diff_tree])
 
717
        differ = DiffTree(self.old_tree, self.new_tree, StringIO(),
 
718
                            extra_factories=[DiffWasIs.from_diff_tree])
735
719
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
736
720
        self.assertNotContainsRe(
737
721
            differ.to_file.getvalue(),
750
734
            '.*a-file(.|\n)*b-file')
751
735
 
752
736
 
753
 
class TestPatienceDiffLib(tests.TestCase):
 
737
class TestPatienceDiffLib(TestCase):
754
738
 
755
739
    def setUp(self):
756
740
        super(TestPatienceDiffLib, self).setUp()
757
 
        self._unique_lcs = _patiencediff_py.unique_lcs_py
758
 
        self._recurse_matches = _patiencediff_py.recurse_matches_py
 
741
        self._unique_lcs = bzrlib._patiencediff_py.unique_lcs_py
 
742
        self._recurse_matches = bzrlib._patiencediff_py.recurse_matches_py
759
743
        self._PatienceSequenceMatcher = \
760
 
            _patiencediff_py.PatienceSequenceMatcher_py
761
 
 
762
 
    def test_diff_unicode_string(self):
763
 
        a = ''.join([unichr(i) for i in range(4000, 4500, 3)])
764
 
        b = ''.join([unichr(i) for i in range(4300, 4800, 2)])
765
 
        sm = self._PatienceSequenceMatcher(None, a, b)
766
 
        mb = sm.get_matching_blocks()
767
 
        self.assertEquals(35, len(mb))
 
744
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
768
745
 
769
746
    def test_unique_lcs(self):
770
747
        unique_lcs = self._unique_lcs
776
753
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
777
754
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
778
755
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
779
 
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
 
756
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1), 
780
757
                                                         (3,3), (4,4)])
781
758
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
782
759
 
797
774
        test_one('abcdbce', 'afbcgdbce', [(0,0), (1, 2), (2, 3), (3, 5),
798
775
                                          (4, 6), (5, 7), (6, 8)])
799
776
 
800
 
        # recurse_matches doesn't match non-unique
 
777
        # recurse_matches doesn't match non-unique 
801
778
        # lines surrounded by bogus text.
802
779
        # The update has been done in patiencediff.SequenceMatcher instead
803
780
 
940
917
                 ('delete', 1,2, 1,1),
941
918
                 ('equal',  2,3, 1,2),
942
919
                ])
943
 
        chk_ops('aBccDe', 'abccde',
 
920
        chk_ops('aBccDe', 'abccde', 
944
921
                [('equal',   0,1, 0,1),
945
922
                 ('replace', 1,5, 1,5),
946
923
                 ('equal',   5,6, 5,6),
947
924
                ])
948
 
        chk_ops('aBcDec', 'abcdec',
 
925
        chk_ops('aBcDec', 'abcdec', 
949
926
                [('equal',   0,1, 0,1),
950
927
                 ('replace', 1,2, 1,2),
951
928
                 ('equal',   2,3, 2,3),
952
929
                 ('replace', 3,4, 3,4),
953
930
                 ('equal',   4,6, 4,6),
954
931
                ])
955
 
        chk_ops('aBcdEcdFg', 'abcdecdfg',
 
932
        chk_ops('aBcdEcdFg', 'abcdecdfg', 
956
933
                [('equal',   0,1, 0,1),
957
934
                 ('replace', 1,8, 1,8),
958
935
                 ('equal',   8,9, 8,9)
959
936
                ])
960
 
        chk_ops('aBcdEeXcdFg', 'abcdecdfg',
 
937
        chk_ops('aBcdEeXcdFg', 'abcdecdfg', 
961
938
                [('equal',   0,1, 0,1),
962
939
                 ('replace', 1,2, 1,2),
963
940
                 ('equal',   2,4, 2,4),
1023
1000
    """
1024
1001
    gnxrf_netf = ['svyr*']
1025
1002
    gnxrf_bcgvbaf = ['ab-erphefr']
1026
 
 
 
1003
  
1027
1004
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
1028
1005
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
1029
1006
        vs vf_dhvrg():
1037
1014
'''.splitlines(True), '''\
1038
1015
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1039
1016
 
1040
 
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl
 
1017
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl 
1041
1018
    nqq gurz.
1042
1019
    """
1043
1020
    gnxrf_netf = ['svyr*']
1070
1047
                 'how are you today?\n']
1071
1048
        txt_b = ['hello there\n',
1072
1049
                 'how are you today?\n']
1073
 
        unified_diff = patiencediff.unified_diff
 
1050
        unified_diff = bzrlib.patiencediff.unified_diff
1074
1051
        psm = self._PatienceSequenceMatcher
1075
 
        self.assertEquals(['--- \n',
1076
 
                           '+++ \n',
 
1052
        self.assertEquals([ '---  \n',
 
1053
                           '+++  \n',
1077
1054
                           '@@ -1,3 +1,2 @@\n',
1078
1055
                           ' hello there\n',
1079
1056
                           '-world\n',
1084
1061
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1085
1062
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1086
1063
        # This is the result with LongestCommonSubstring matching
1087
 
        self.assertEquals(['--- \n',
1088
 
                           '+++ \n',
 
1064
        self.assertEquals(['---  \n',
 
1065
                           '+++  \n',
1089
1066
                           '@@ -1,6 +1,11 @@\n',
1090
1067
                           ' a\n',
1091
1068
                           ' b\n',
1100
1077
                           ' f\n']
1101
1078
                          , list(unified_diff(txt_a, txt_b)))
1102
1079
        # And the patience diff
1103
 
        self.assertEquals(['--- \n',
1104
 
                           '+++ \n',
 
1080
        self.assertEquals(['---  \n',
 
1081
                           '+++  \n',
1105
1082
                           '@@ -4,6 +4,11 @@\n',
1106
1083
                           ' d\n',
1107
1084
                           ' e\n',
1118
1095
                          , list(unified_diff(txt_a, txt_b,
1119
1096
                                 sequencematcher=psm)))
1120
1097
 
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
1098
 
1143
1099
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1144
1100
 
1145
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1101
    _test_needs_features = [CompiledPatienceDiffFeature]
1146
1102
 
1147
1103
    def setUp(self):
1148
1104
        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
 
1105
        import bzrlib._patiencediff_c
 
1106
        self._unique_lcs = bzrlib._patiencediff_c.unique_lcs_c
 
1107
        self._recurse_matches = bzrlib._patiencediff_c.recurse_matches_c
1152
1108
        self._PatienceSequenceMatcher = \
1153
 
            _patiencediff_c.PatienceSequenceMatcher_c
 
1109
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
1154
1110
 
1155
1111
    def test_unhashable(self):
1156
1112
        """We should get a proper exception here."""
1166
1122
                                         None, ['valid'], ['valid', []])
1167
1123
 
1168
1124
 
1169
 
class TestPatienceDiffLibFiles(tests.TestCaseInTempDir):
 
1125
class TestPatienceDiffLibFiles(TestCaseInTempDir):
1170
1126
 
1171
1127
    def setUp(self):
1172
1128
        super(TestPatienceDiffLibFiles, self).setUp()
1173
1129
        self._PatienceSequenceMatcher = \
1174
 
            _patiencediff_py.PatienceSequenceMatcher_py
 
1130
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
1175
1131
 
1176
1132
    def test_patience_unified_diff_files(self):
1177
1133
        txt_a = ['hello there\n',
1182
1138
        open('a1', 'wb').writelines(txt_a)
1183
1139
        open('b1', 'wb').writelines(txt_b)
1184
1140
 
1185
 
        unified_diff_files = patiencediff.unified_diff_files
 
1141
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
1186
1142
        psm = self._PatienceSequenceMatcher
1187
 
        self.assertEquals(['--- a1\n',
1188
 
                           '+++ b1\n',
 
1143
        self.assertEquals(['--- a1 \n',
 
1144
                           '+++ b1 \n',
1189
1145
                           '@@ -1,3 +1,2 @@\n',
1190
1146
                           ' hello there\n',
1191
1147
                           '-world\n',
1200
1156
        open('b2', 'wb').writelines(txt_b)
1201
1157
 
1202
1158
        # This is the result with LongestCommonSubstring matching
1203
 
        self.assertEquals(['--- a2\n',
1204
 
                           '+++ b2\n',
 
1159
        self.assertEquals(['--- a2 \n',
 
1160
                           '+++ b2 \n',
1205
1161
                           '@@ -1,6 +1,11 @@\n',
1206
1162
                           ' a\n',
1207
1163
                           ' b\n',
1217
1173
                          , list(unified_diff_files('a2', 'b2')))
1218
1174
 
1219
1175
        # And the patience diff
1220
 
        self.assertEquals(['--- a2\n',
1221
 
                           '+++ b2\n',
 
1176
        self.assertEquals(['--- a2 \n',
 
1177
                           '+++ b2 \n',
1222
1178
                           '@@ -4,6 +4,11 @@\n',
1223
1179
                           ' d\n',
1224
1180
                           ' e\n',
1238
1194
 
1239
1195
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1240
1196
 
1241
 
    _test_needs_features = [compiled_patiencediff_feature]
 
1197
    _test_needs_features = [CompiledPatienceDiffFeature]
1242
1198
 
1243
1199
    def setUp(self):
1244
1200
        super(TestPatienceDiffLibFiles_c, self).setUp()
1245
 
        from bzrlib import _patiencediff_c
 
1201
        import bzrlib._patiencediff_c
1246
1202
        self._PatienceSequenceMatcher = \
1247
 
            _patiencediff_c.PatienceSequenceMatcher_c
1248
 
 
1249
 
 
1250
 
class TestUsingCompiledIfAvailable(tests.TestCase):
 
1203
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
 
1204
 
 
1205
 
 
1206
class TestUsingCompiledIfAvailable(TestCase):
1251
1207
 
1252
1208
    def test_PatienceSequenceMatcher(self):
1253
 
        if compiled_patiencediff_feature.available():
 
1209
        if CompiledPatienceDiffFeature.available():
1254
1210
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1255
1211
            self.assertIs(PatienceSequenceMatcher_c,
1256
 
                          patiencediff.PatienceSequenceMatcher)
 
1212
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1257
1213
        else:
1258
1214
            from bzrlib._patiencediff_py import PatienceSequenceMatcher_py
1259
1215
            self.assertIs(PatienceSequenceMatcher_py,
1260
 
                          patiencediff.PatienceSequenceMatcher)
 
1216
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1261
1217
 
1262
1218
    def test_unique_lcs(self):
1263
 
        if compiled_patiencediff_feature.available():
 
1219
        if CompiledPatienceDiffFeature.available():
1264
1220
            from bzrlib._patiencediff_c import unique_lcs_c
1265
1221
            self.assertIs(unique_lcs_c,
1266
 
                          patiencediff.unique_lcs)
 
1222
                          bzrlib.patiencediff.unique_lcs)
1267
1223
        else:
1268
1224
            from bzrlib._patiencediff_py import unique_lcs_py
1269
1225
            self.assertIs(unique_lcs_py,
1270
 
                          patiencediff.unique_lcs)
 
1226
                          bzrlib.patiencediff.unique_lcs)
1271
1227
 
1272
1228
    def test_recurse_matches(self):
1273
 
        if compiled_patiencediff_feature.available():
 
1229
        if CompiledPatienceDiffFeature.available():
1274
1230
            from bzrlib._patiencediff_c import recurse_matches_c
1275
1231
            self.assertIs(recurse_matches_c,
1276
 
                          patiencediff.recurse_matches)
 
1232
                          bzrlib.patiencediff.recurse_matches)
1277
1233
        else:
1278
1234
            from bzrlib._patiencediff_py import recurse_matches_py
1279
1235
            self.assertIs(recurse_matches_py,
1280
 
                          patiencediff.recurse_matches)
1281
 
 
1282
 
 
1283
 
class TestDiffFromTool(tests.TestCaseWithTransport):
 
1236
                          bzrlib.patiencediff.recurse_matches)
 
1237
 
 
1238
 
 
1239
class TestDiffFromTool(TestCaseWithTransport):
1284
1240
 
1285
1241
    def test_from_string(self):
1286
 
        diff_obj = diff.DiffFromTool.from_string('diff', None, None, None)
 
1242
        diff_obj = DiffFromTool.from_string('diff', None, None, None)
1287
1243
        self.addCleanup(diff_obj.finish)
1288
 
        self.assertEqual(['diff', '@old_path', '@new_path'],
 
1244
        self.assertEqual(['diff', '%(old_path)s', '%(new_path)s'],
1289
1245
            diff_obj.command_template)
1290
 
 
1291
 
    def test_from_string_u5(self):
1292
 
        diff_obj = diff.DiffFromTool.from_string('diff "-u 5"',
1293
 
                                                 None, None, None)
1294
 
        self.addCleanup(diff_obj.finish)
1295
 
        self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
 
1246
        diff_obj = DiffFromTool.from_string('diff -u\\ 5', None, None, None)
 
1247
        self.assertEqual(['diff', '-u 5', '%(old_path)s', '%(new_path)s'],
1296
1248
                         diff_obj.command_template)
1297
1249
        self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
1298
1250
                         diff_obj._get_command('old-path', 'new-path'))
1299
1251
 
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
1252
    def test_execute(self):
1311
1253
        output = StringIO()
1312
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1313
 
                                      'print "@old_path @new_path"'],
1314
 
                                     None, None, output)
 
1254
        diff_obj = DiffFromTool(['python', '-c',
 
1255
                                 'print "%(old_path)s %(new_path)s"'],
 
1256
                                None, None, output)
1315
1257
        self.addCleanup(diff_obj.finish)
1316
1258
        diff_obj._execute('old', 'new')
1317
 
        self.assertEqual(output.getvalue().rstrip(), 'old new')
 
1259
        self.assertEqual(output.getvalue(), 'old new\n')
1318
1260
 
1319
1261
    def test_excute_missing(self):
1320
 
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1321
 
                                     None, None, None)
 
1262
        diff_obj = DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
 
1263
                                None, None, None)
1322
1264
        self.addCleanup(diff_obj.finish)
1323
 
        e = self.assertRaises(errors.ExecutableMissing, diff_obj._execute,
1324
 
                              'old', 'new')
 
1265
        e = self.assertRaises(ExecutableMissing, diff_obj._execute, 'old',
 
1266
                              'new')
1325
1267
        self.assertEqual('a-tool-which-is-unlikely-to-exist could not be found'
1326
1268
                         ' on this machine', str(e))
1327
1269
 
1328
 
    def test_prepare_files_creates_paths_readable_by_windows_tool(self):
1329
 
        self.requireFeature(AttribFeature)
 
1270
    def test_prepare_files(self):
1330
1271
        output = StringIO()
1331
1272
        tree = self.make_branch_and_tree('tree')
1332
 
        self.build_tree_contents([('tree/file', 'content')])
 
1273
        self.build_tree_contents([('tree/file', 'oldcontent')])
1333
1274
        tree.add('file', 'file-id')
1334
1275
        tree.commit('old tree')
1335
 
        tree.lock_read()
1336
 
        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)
1343
 
        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$')
1350
 
 
1351
 
    def assertReadableByAttrib(self, cwd, relpath, regex):
1352
 
        proc = subprocess.Popen(['attrib', relpath],
1353
 
                                stdout=subprocess.PIPE,
1354
 
                                cwd=cwd)
1355
 
        (result, err) = proc.communicate()
1356
 
        self.assertContainsRe(result.replace('\r\n', '\n'), regex)
1357
 
 
1358
 
    def test_prepare_files(self):
1359
 
        output = StringIO()
1360
 
        tree = self.make_branch_and_tree('tree')
1361
 
        self.build_tree_contents([('tree/oldname', 'oldcontent')])
1362
 
        self.build_tree_contents([('tree/oldname2', 'oldcontent2')])
1363
 
        tree.add('oldname', 'file-id')
1364
 
        tree.add('oldname2', 'file2-id')
1365
 
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
1366
 
        tree.commit('old tree', timestamp=315532800)
1367
 
        tree.rename_one('oldname', 'newname')
1368
 
        tree.rename_one('oldname2', 'newname2')
1369
 
        self.build_tree_contents([('tree/newname', 'newcontent')])
1370
 
        self.build_tree_contents([('tree/newname2', 'newcontent2')])
 
1276
        self.build_tree_contents([('tree/file', 'newcontent')])
1371
1277
        old_tree = tree.basis_tree()
1372
1278
        old_tree.lock_read()
1373
1279
        self.addCleanup(old_tree.unlock)
1374
 
        tree.lock_read()
1375
 
        self.addCleanup(tree.unlock)
1376
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1377
 
                                      'print "@old_path @new_path"'],
1378
 
                                     old_tree, tree, output)
 
1280
        diff_obj = DiffFromTool(['python', '-c',
 
1281
                                 'print "%(old_path)s %(new_path)s"'],
 
1282
                                old_tree, tree, output)
1379
1283
        self.addCleanup(diff_obj.finish)
1380
1284
        self.assertContainsRe(diff_obj._root, 'bzr-diff-[^/]*')
1381
1285
        old_path, new_path = diff_obj._prepare_files('file-id', 'oldname',
1382
1286
                                                     'newname')
1383
1287
        self.assertContainsRe(old_path, 'old/oldname$')
1384
 
        self.assertEqual(315532800, os.stat(old_path).st_mtime)
1385
 
        self.assertContainsRe(new_path, 'tree/newname$')
 
1288
        self.assertContainsRe(new_path, 'new/newname$')
1386
1289
        self.assertFileEqual('oldcontent', old_path)
1387
1290
        self.assertFileEqual('newcontent', new_path)
1388
 
        if osutils.host_os_dereferences_symlinks():
1389
 
            self.assertTrue(os.path.samefile('tree/newname', new_path))
1390
1291
        # make sure we can create files with the same parent directories
1391
 
        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
 
 
 
1292
        diff_obj._prepare_files('file-id', 'oldname2', 'newname2')