/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to breezy/tests/test_diff.py

  • Committer: Jelmer Vernooij
  • Date: 2018-11-06 01:18:08 UTC
  • mfrom: (7143 work)
  • mto: This revision was merged to the branch mainline in revision 7151.
  • Revision ID: jelmer@jelmer.uk-20181106011808-y870f4vq0ork3ahu
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import os
 
18
import re
18
19
import subprocess
 
20
import sys
19
21
import tempfile
20
22
 
21
23
from .. import (
32
34
    )
33
35
from ..sixish import (
34
36
    BytesIO,
 
37
    unichr,
35
38
    )
36
39
from ..tests import (
37
40
    features,
38
41
    EncodingAdapter,
39
42
    )
40
 
from ..tests.blackbox.test_diff import subst_dates
41
43
from ..tests.scenarios import load_tests_apply_scenarios
42
44
 
43
45
 
44
46
load_tests = load_tests_apply_scenarios
45
47
 
46
48
 
 
49
def subst_dates(string):
 
50
    """Replace date strings with constant values."""
 
51
    return re.sub(br'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]\d{4}',
 
52
                  b'YYYY-MM-DD HH:MM:SS +ZZZZ', string)
 
53
 
 
54
 
47
55
def udiff_lines(old, new, allow_binary=False):
48
56
    output = BytesIO()
49
57
    diff.internal_diff('old', old, 'new', new, output, allow_binary)
110
118
 
111
119
    def test_add_nl(self):
112
120
        """diff generates a valid diff for patches that add a newline"""
113
 
        lines = udiff_lines(['boo'], ['boo\n'])
 
121
        lines = udiff_lines([b'boo'], [b'boo\n'])
114
122
        self.check_patch(lines)
115
 
        self.assertEqual(lines[4], '\\ No newline at end of file\n')
 
123
        self.assertEqual(lines[4], b'\\ No newline at end of file\n')
116
124
            ## "expected no-nl, got %r" % lines[4]
117
125
 
118
126
    def test_add_nl_2(self):
119
127
        """diff generates a valid diff for patches that change last line and
120
128
        add a newline.
121
129
        """
122
 
        lines = udiff_lines(['boo'], ['goo\n'])
 
130
        lines = udiff_lines([b'boo'], [b'goo\n'])
123
131
        self.check_patch(lines)
124
 
        self.assertEqual(lines[4], '\\ No newline at end of file\n')
 
132
        self.assertEqual(lines[4], b'\\ No newline at end of file\n')
125
133
            ## "expected no-nl, got %r" % lines[4]
126
134
 
127
135
    def test_remove_nl(self):
128
136
        """diff generates a valid diff for patches that change last line and
129
137
        add a newline.
130
138
        """
131
 
        lines = udiff_lines(['boo\n'], ['boo'])
 
139
        lines = udiff_lines([b'boo\n'], [b'boo'])
132
140
        self.check_patch(lines)
133
 
        self.assertEqual(lines[5], '\\ No newline at end of file\n')
 
141
        self.assertEqual(lines[5], b'\\ No newline at end of file\n')
134
142
            ## "expected no-nl, got %r" % lines[5]
135
143
 
136
144
    def check_patch(self, lines):
137
145
        self.assertTrue(len(lines) > 1)
138
146
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
139
 
        self.assertTrue(lines[0].startswith ('---'))
 
147
        self.assertTrue(lines[0].startswith (b'---'))
140
148
            ## 'No orig line for patch:\n%s' % "".join(lines)
141
 
        self.assertTrue(lines[1].startswith ('+++'))
 
149
        self.assertTrue(lines[1].startswith (b'+++'))
142
150
            ## 'No mod line for patch:\n%s' % "".join(lines)
143
151
        self.assertTrue(len(lines) > 2)
144
152
            ## "No hunks for patch:\n%s" % "".join(lines)
145
 
        self.assertTrue(lines[2].startswith('@@'))
 
153
        self.assertTrue(lines[2].startswith(b'@@'))
146
154
            ## "No hunk header for patch:\n%s" % "".join(lines)
147
 
        self.assertTrue('@@' in lines[2][2:])
 
155
        self.assertTrue(b'@@' in lines[2][2:])
148
156
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
149
157
 
150
158
    def test_binary_lines(self):
151
159
        empty = []
152
 
        uni_lines = [1023 * 'a' + '\x00']
 
160
        uni_lines = [1023 * b'a' + b'\x00']
153
161
        self.assertRaises(errors.BinaryFile, udiff_lines, uni_lines, empty)
154
162
        self.assertRaises(errors.BinaryFile, udiff_lines, empty, uni_lines)
155
163
        udiff_lines(uni_lines, empty, allow_binary=True)
156
164
        udiff_lines(empty, uni_lines, allow_binary=True)
157
165
 
158
166
    def test_external_diff(self):
159
 
        lines = external_udiff_lines(['boo\n'], ['goo\n'])
 
167
        lines = external_udiff_lines([b'boo\n'], [b'goo\n'])
160
168
        self.check_patch(lines)
161
 
        self.assertEqual('\n', lines[-1])
 
169
        self.assertEqual(b'\n', lines[-1])
162
170
 
163
171
    def test_external_diff_no_fileno(self):
164
172
        # Make sure that we can handle not having a fileno, even
165
173
        # if the diff is large
166
 
        lines = external_udiff_lines(['boo\n']*10000,
167
 
                                     ['goo\n']*10000,
 
174
        lines = external_udiff_lines([b'boo\n']*10000,
 
175
                                     [b'goo\n']*10000,
168
176
                                     use_stringio=True)
169
177
        self.check_patch(lines)
170
178
 
171
179
    def test_external_diff_binary_lang_c(self):
172
180
        for lang in ('LANG', 'LC_ALL', 'LANGUAGE'):
173
181
            self.overrideEnv(lang, 'C')
174
 
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
 
182
        lines = external_udiff_lines([b'\x00foobar\n'], [b'foo\x00bar\n'])
175
183
        # Older versions of diffutils say "Binary files", newer
176
184
        # versions just say "Files".
177
 
        self.assertContainsRe(lines[0], '(Binary f|F)iles old and new differ\n')
178
 
        self.assertEqual(lines[1:], ['\n'])
 
185
        self.assertContainsRe(lines[0], b'(Binary f|F)iles old and new differ\n')
 
186
        self.assertEqual(lines[1:], [b'\n'])
179
187
 
180
188
    def test_no_external_diff(self):
181
189
        """Check that NoDiff is raised when diff is not available"""
183
191
        # XXX: Weird, using None instead of '' breaks the test -- vila 20101216
184
192
        self.overrideEnv('PATH', '')
185
193
        self.assertRaises(errors.NoDiff, diff.external_diff,
186
 
                          'old', ['boo\n'], 'new', ['goo\n'],
 
194
                          b'old', [b'boo\n'], b'new', [b'goo\n'],
187
195
                          BytesIO(), diff_opts=['-u'])
188
196
 
189
197
    def test_internal_diff_default(self):
190
198
        # Default internal diff encoding is utf8
191
199
        output = BytesIO()
192
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
193
 
                           u'new_\xe5', ['new_text\n'], output)
 
200
        diff.internal_diff(u'old_\xb5', [b'old_text\n'],
 
201
                           u'new_\xe5', [b'new_text\n'], output)
194
202
        lines = output.getvalue().splitlines(True)
195
203
        self.check_patch(lines)
196
 
        self.assertEqual(['--- old_\xc2\xb5\n',
197
 
                           '+++ new_\xc3\xa5\n',
198
 
                           '@@ -1,1 +1,1 @@\n',
199
 
                           '-old_text\n',
200
 
                           '+new_text\n',
201
 
                           '\n',
 
204
        self.assertEqual([b'--- old_\xc2\xb5\n',
 
205
                           b'+++ new_\xc3\xa5\n',
 
206
                           b'@@ -1,1 +1,1 @@\n',
 
207
                           b'-old_text\n',
 
208
                           b'+new_text\n',
 
209
                           b'\n',
202
210
                          ]
203
211
                          , lines)
204
212
 
205
213
    def test_internal_diff_utf8(self):
206
214
        output = BytesIO()
207
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
208
 
                           u'new_\xe5', ['new_text\n'], output,
 
215
        diff.internal_diff(u'old_\xb5', [b'old_text\n'],
 
216
                           u'new_\xe5', [b'new_text\n'], output,
209
217
                           path_encoding='utf8')
210
218
        lines = output.getvalue().splitlines(True)
211
219
        self.check_patch(lines)
212
 
        self.assertEqual(['--- old_\xc2\xb5\n',
213
 
                           '+++ new_\xc3\xa5\n',
214
 
                           '@@ -1,1 +1,1 @@\n',
215
 
                           '-old_text\n',
216
 
                           '+new_text\n',
217
 
                           '\n',
 
220
        self.assertEqual([b'--- old_\xc2\xb5\n',
 
221
                           b'+++ new_\xc3\xa5\n',
 
222
                           b'@@ -1,1 +1,1 @@\n',
 
223
                           b'-old_text\n',
 
224
                           b'+new_text\n',
 
225
                           b'\n',
218
226
                          ]
219
227
                          , lines)
220
228
 
221
229
    def test_internal_diff_iso_8859_1(self):
222
230
        output = BytesIO()
223
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
224
 
                           u'new_\xe5', ['new_text\n'], output,
 
231
        diff.internal_diff(u'old_\xb5', [b'old_text\n'],
 
232
                           u'new_\xe5', [b'new_text\n'], output,
225
233
                           path_encoding='iso-8859-1')
226
234
        lines = output.getvalue().splitlines(True)
227
235
        self.check_patch(lines)
228
 
        self.assertEqual(['--- old_\xb5\n',
229
 
                           '+++ new_\xe5\n',
230
 
                           '@@ -1,1 +1,1 @@\n',
231
 
                           '-old_text\n',
232
 
                           '+new_text\n',
233
 
                           '\n',
 
236
        self.assertEqual([b'--- old_\xb5\n',
 
237
                          b'+++ new_\xe5\n',
 
238
                          b'@@ -1,1 +1,1 @@\n',
 
239
                          b'-old_text\n',
 
240
                          b'+new_text\n',
 
241
                          b'\n',
234
242
                          ]
235
243
                          , lines)
236
244
 
237
245
    def test_internal_diff_no_content(self):
238
246
        output = BytesIO()
239
247
        diff.internal_diff(u'old', [], u'new', [], output)
240
 
        self.assertEqual('', output.getvalue())
 
248
        self.assertEqual(b'', output.getvalue())
241
249
 
242
250
    def test_internal_diff_no_changes(self):
243
251
        output = BytesIO()
244
 
        diff.internal_diff(u'old', ['text\n', 'contents\n'],
245
 
                           u'new', ['text\n', 'contents\n'],
 
252
        diff.internal_diff(u'old', [b'text\n', b'contents\n'],
 
253
                           u'new', [b'text\n', b'contents\n'],
246
254
                           output)
247
 
        self.assertEqual('', output.getvalue())
 
255
        self.assertEqual(b'', output.getvalue())
248
256
 
249
257
    def test_internal_diff_returns_bytes(self):
250
258
        output = StubO()
251
 
        diff.internal_diff(u'old_\xb5', ['old_text\n'],
252
 
                            u'new_\xe5', ['new_text\n'], output)
 
259
        diff.internal_diff(u'old_\xb5', [b'old_text\n'],
 
260
                           u'new_\xe5', [b'new_text\n'], output)
253
261
        output.check_types(self, bytes)
254
262
 
255
263
    def test_internal_diff_default_context(self):
256
264
        output = BytesIO()
257
 
        diff.internal_diff('old', ['same_text\n', 'same_text\n', 'same_text\n',
258
 
                           'same_text\n', 'same_text\n', 'old_text\n'],
259
 
                           'new', ['same_text\n', 'same_text\n', 'same_text\n',
260
 
                           'same_text\n', 'same_text\n', 'new_text\n'], output)
 
265
        diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
 
266
                           b'same_text\n', b'same_text\n', b'old_text\n'],
 
267
                           'new', [b'same_text\n', b'same_text\n', b'same_text\n',
 
268
                           b'same_text\n', b'same_text\n', b'new_text\n'], output)
261
269
        lines = output.getvalue().splitlines(True)
262
270
        self.check_patch(lines)
263
 
        self.assertEqual(['--- old\n',
264
 
                           '+++ new\n',
265
 
                           '@@ -3,4 +3,4 @@\n',
266
 
                           ' same_text\n',
267
 
                           ' same_text\n',
268
 
                           ' same_text\n',
269
 
                           '-old_text\n',
270
 
                           '+new_text\n',
271
 
                           '\n',
 
271
        self.assertEqual([b'--- old\n',
 
272
                           b'+++ new\n',
 
273
                           b'@@ -3,4 +3,4 @@\n',
 
274
                           b' same_text\n',
 
275
                           b' same_text\n',
 
276
                           b' same_text\n',
 
277
                           b'-old_text\n',
 
278
                           b'+new_text\n',
 
279
                           b'\n',
272
280
                          ]
273
281
                          , lines)
274
282
 
275
283
    def test_internal_diff_no_context(self):
276
284
        output = BytesIO()
277
 
        diff.internal_diff('old', ['same_text\n', 'same_text\n', 'same_text\n',
278
 
                           'same_text\n', 'same_text\n', 'old_text\n'],
279
 
                           'new', ['same_text\n', 'same_text\n', 'same_text\n',
280
 
                           'same_text\n', 'same_text\n', 'new_text\n'], output,
 
285
        diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
 
286
                           b'same_text\n', b'same_text\n', b'old_text\n'],
 
287
                           'new', [b'same_text\n', b'same_text\n', b'same_text\n',
 
288
                           b'same_text\n', b'same_text\n', b'new_text\n'], output,
281
289
                           context_lines=0)
282
290
        lines = output.getvalue().splitlines(True)
283
291
        self.check_patch(lines)
284
 
        self.assertEqual(['--- old\n',
285
 
                           '+++ new\n',
286
 
                           '@@ -6,1 +6,1 @@\n',
287
 
                           '-old_text\n',
288
 
                           '+new_text\n',
289
 
                           '\n',
 
292
        self.assertEqual([b'--- old\n',
 
293
                           b'+++ new\n',
 
294
                           b'@@ -6,1 +6,1 @@\n',
 
295
                           b'-old_text\n',
 
296
                           b'+new_text\n',
 
297
                           b'\n',
290
298
                          ]
291
299
                          , lines)
292
300
 
293
301
    def test_internal_diff_more_context(self):
294
302
        output = BytesIO()
295
 
        diff.internal_diff('old', ['same_text\n', 'same_text\n', 'same_text\n',
296
 
                           'same_text\n', 'same_text\n', 'old_text\n'],
297
 
                           'new', ['same_text\n', 'same_text\n', 'same_text\n',
298
 
                           'same_text\n', 'same_text\n', 'new_text\n'], output,
 
303
        diff.internal_diff('old', [b'same_text\n', b'same_text\n', b'same_text\n',
 
304
                           b'same_text\n', b'same_text\n', b'old_text\n'],
 
305
                           'new', [b'same_text\n', b'same_text\n', b'same_text\n',
 
306
                           b'same_text\n', b'same_text\n', b'new_text\n'], output,
299
307
                           context_lines=4)
300
308
        lines = output.getvalue().splitlines(True)
301
309
        self.check_patch(lines)
302
 
        self.assertEqual(['--- old\n',
303
 
                           '+++ new\n',
304
 
                           '@@ -2,5 +2,5 @@\n',
305
 
                           ' same_text\n',
306
 
                           ' same_text\n',
307
 
                           ' same_text\n',
308
 
                           ' same_text\n',
309
 
                           '-old_text\n',
310
 
                           '+new_text\n',
311
 
                           '\n',
 
310
        self.assertEqual([b'--- old\n',
 
311
                          b'+++ new\n',
 
312
                          b'@@ -2,5 +2,5 @@\n',
 
313
                          b' same_text\n',
 
314
                          b' same_text\n',
 
315
                          b' same_text\n',
 
316
                          b' same_text\n',
 
317
                          b'-old_text\n',
 
318
                          b'+new_text\n',
 
319
                          b'\n',
312
320
                          ]
313
321
                          , lines)
314
322
 
315
323
 
316
324
 
317
 
 
318
 
 
319
325
class TestDiffFiles(tests.TestCaseInTempDir):
320
326
 
321
327
    def test_external_diff_binary(self):
323
329
        for lang in ('LANG', 'LC_ALL', 'LANGUAGE'):
324
330
            self.overrideEnv(lang, 'C')
325
331
        # Make sure external_diff doesn't fail in the current LANG
326
 
        lines = external_udiff_lines(['\x00foobar\n'], ['foo\x00bar\n'])
 
332
        lines = external_udiff_lines([b'\x00foobar\n'], [b'foo\x00bar\n'])
327
333
 
328
334
        cmd = ['diff', '-u', '--binary', 'old', 'new']
329
 
        with open('old', 'wb') as f: f.write('\x00foobar\n')
330
 
        with open('new', 'wb') as f: f.write('foo\x00bar\n')
 
335
        with open('old', 'wb') as f: f.write(b'\x00foobar\n')
 
336
        with open('new', 'wb') as f: f.write(b'foo\x00bar\n')
331
337
        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
332
338
                                     stdin=subprocess.PIPE)
333
339
        out, err = pipe.communicate()
334
340
        # We should output whatever diff tells us, plus a trailing newline
335
 
        self.assertEqual(out.splitlines(True) + ['\n'], lines)
 
341
        self.assertEqual(out.splitlines(True) + [b'\n'], lines)
336
342
 
337
343
 
338
344
def get_diff_as_string(tree1, tree2, specific_files=None, working_tree=None):
392
398
        output = get_diff_as_string(self.wt.basis_tree(), self.wt)
393
399
        # note that the date for old/file1 is from rev 2 rather than from
394
400
        # the basis revision (rev 4)
395
 
        self.assertEqualDiff(output, '''\
 
401
        self.assertEqualDiff(output, b'''\
396
402
=== modified file 'file1'
397
403
--- old/file1\t2006-04-02 00:00:00 +0000
398
404
+++ new/file1\t2006-04-05 00:00:00 +0000
403
409
''')
404
410
 
405
411
    def test_diff_rev_tree_rev_tree(self):
406
 
        tree1 = self.b.repository.revision_tree('rev-2')
407
 
        tree2 = self.b.repository.revision_tree('rev-3')
 
412
        tree1 = self.b.repository.revision_tree(b'rev-2')
 
413
        tree2 = self.b.repository.revision_tree(b'rev-3')
408
414
        output = get_diff_as_string(tree1, tree2)
409
 
        self.assertEqualDiff(output, '''\
 
415
        self.assertEqualDiff(output, b'''\
410
416
=== modified file 'file2'
411
417
--- old/file2\t2006-04-01 00:00:00 +0000
412
418
+++ new/file2\t2006-04-03 00:00:00 +0000
418
424
 
419
425
    def test_diff_add_files(self):
420
426
        tree1 = self.b.repository.revision_tree(_mod_revision.NULL_REVISION)
421
 
        tree2 = self.b.repository.revision_tree('rev-1')
 
427
        tree2 = self.b.repository.revision_tree(b'rev-1')
422
428
        output = get_diff_as_string(tree1, tree2)
423
429
        # the files have the epoch time stamp for the tree in which
424
430
        # they don't exist.
425
 
        self.assertEqualDiff(output, '''\
 
431
        self.assertEqualDiff(output, b'''\
426
432
=== added file 'file1'
427
433
--- old/file1\t1970-01-01 00:00:00 +0000
428
434
+++ new/file1\t2006-04-01 00:00:00 +0000
438
444
''')
439
445
 
440
446
    def test_diff_remove_files(self):
441
 
        tree1 = self.b.repository.revision_tree('rev-3')
442
 
        tree2 = self.b.repository.revision_tree('rev-4')
 
447
        tree1 = self.b.repository.revision_tree(b'rev-3')
 
448
        tree2 = self.b.repository.revision_tree(b'rev-4')
443
449
        output = get_diff_as_string(tree1, tree2)
444
450
        # the file has the epoch time stamp for the tree in which
445
451
        # it doesn't exist.
446
 
        self.assertEqualDiff(output, '''\
 
452
        self.assertEqualDiff(output, b'''\
447
453
=== removed file 'file2'
448
454
--- old/file2\t2006-04-03 00:00:00 +0000
449
455
+++ new/file2\t1970-01-01 00:00:00 +0000
455
461
    def test_show_diff_specified(self):
456
462
        """A working tree filename can be used to identify a file"""
457
463
        self.wt.rename_one('file1', 'file1b')
458
 
        old_tree = self.b.repository.revision_tree('rev-1')
459
 
        new_tree = self.b.repository.revision_tree('rev-4')
 
464
        old_tree = self.b.repository.revision_tree(b'rev-1')
 
465
        new_tree = self.b.repository.revision_tree(b'rev-4')
460
466
        out = get_diff_as_string(old_tree, new_tree, specific_files=['file1b'],
461
467
                            working_tree=self.wt)
462
 
        self.assertContainsRe(out, 'file1\t')
 
468
        self.assertContainsRe(out, b'file1\t')
463
469
 
464
470
    def test_recursive_diff(self):
465
471
        """Children of directories are matched"""
467
473
        os.mkdir('dir2')
468
474
        self.wt.add(['dir1', 'dir2'])
469
475
        self.wt.rename_one('file1', 'dir1/file1')
470
 
        old_tree = self.b.repository.revision_tree('rev-1')
471
 
        new_tree = self.b.repository.revision_tree('rev-4')
 
476
        old_tree = self.b.repository.revision_tree(b'rev-1')
 
477
        new_tree = self.b.repository.revision_tree(b'rev-4')
472
478
        out = get_diff_as_string(old_tree, new_tree, specific_files=['dir1'],
473
479
                            working_tree=self.wt)
474
 
        self.assertContainsRe(out, 'file1\t')
 
480
        self.assertContainsRe(out, b'file1\t')
475
481
        out = get_diff_as_string(old_tree, new_tree, specific_files=['dir2'],
476
482
                            working_tree=self.wt)
477
 
        self.assertNotContainsRe(out, 'file1\t')
 
483
        self.assertNotContainsRe(out, b'file1\t')
478
484
 
479
485
 
480
486
class TestShowDiffTrees(tests.TestCaseWithTransport):
489
495
 
490
496
        self.build_tree_contents([('tree/file', b'new contents\n')])
491
497
        d = get_diff_as_string(tree.basis_tree(), tree)
492
 
        self.assertContainsRe(d, "=== modified file 'file'\n")
493
 
        self.assertContainsRe(d, '--- old/file\t')
494
 
        self.assertContainsRe(d, '\\+\\+\\+ new/file\t')
495
 
        self.assertContainsRe(d, '-contents\n'
496
 
                                 '\\+new contents\n')
 
498
        self.assertContainsRe(d, b"=== modified file 'file'\n")
 
499
        self.assertContainsRe(d, b'--- old/file\t')
 
500
        self.assertContainsRe(d, b'\\+\\+\\+ new/file\t')
 
501
        self.assertContainsRe(d, b'-contents\n'
 
502
                                 b'\\+new contents\n')
497
503
 
498
504
    def test_modified_file_in_renamed_dir(self):
499
505
        """Test when a file is modified in a renamed directory."""
506
512
        tree.rename_one('dir', 'other')
507
513
        self.build_tree_contents([('tree/other/file', b'new contents\n')])
508
514
        d = get_diff_as_string(tree.basis_tree(), tree)
509
 
        self.assertContainsRe(d, "=== renamed directory 'dir' => 'other'\n")
510
 
        self.assertContainsRe(d, "=== modified file 'other/file'\n")
 
515
        self.assertContainsRe(d, b"=== renamed directory 'dir' => 'other'\n")
 
516
        self.assertContainsRe(d, b"=== modified file 'other/file'\n")
511
517
        # XXX: This is technically incorrect, because it used to be at another
512
518
        # location. What to do?
513
 
        self.assertContainsRe(d, '--- old/dir/file\t')
514
 
        self.assertContainsRe(d, '\\+\\+\\+ new/other/file\t')
515
 
        self.assertContainsRe(d, '-contents\n'
516
 
                                 '\\+new contents\n')
 
519
        self.assertContainsRe(d, b'--- old/dir/file\t')
 
520
        self.assertContainsRe(d, b'\\+\\+\\+ new/other/file\t')
 
521
        self.assertContainsRe(d, b'-contents\n'
 
522
                                 b'\\+new contents\n')
517
523
 
518
524
    def test_renamed_directory(self):
519
525
        """Test when only a directory is only renamed."""
527
533
        d = get_diff_as_string(tree.basis_tree(), tree)
528
534
        # Renaming a directory should be a single "you renamed this dir" even
529
535
        # when there are files inside.
530
 
        self.assertEqual(d, "=== renamed directory 'dir' => 'newdir'\n")
 
536
        self.assertEqual(d, b"=== renamed directory 'dir' => 'newdir'\n")
531
537
 
532
538
    def test_renamed_file(self):
533
539
        """Test when a file is only renamed."""
538
544
 
539
545
        tree.rename_one('file', 'newname')
540
546
        d = get_diff_as_string(tree.basis_tree(), tree)
541
 
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
 
547
        self.assertContainsRe(d, b"=== renamed file 'file' => 'newname'\n")
542
548
        # We shouldn't have a --- or +++ line, because there is no content
543
549
        # change
544
 
        self.assertNotContainsRe(d, '---')
 
550
        self.assertNotContainsRe(d, b'---')
545
551
 
546
552
    def test_renamed_and_modified_file(self):
547
553
        """Test when a file is only renamed."""
553
559
        tree.rename_one('file', 'newname')
554
560
        self.build_tree_contents([('tree/newname', b'new contents\n')])
555
561
        d = get_diff_as_string(tree.basis_tree(), tree)
556
 
        self.assertContainsRe(d, "=== renamed file 'file' => 'newname'\n")
557
 
        self.assertContainsRe(d, '--- old/file\t')
558
 
        self.assertContainsRe(d, '\\+\\+\\+ new/newname\t')
559
 
        self.assertContainsRe(d, '-contents\n'
560
 
                                 '\\+new contents\n')
 
562
        self.assertContainsRe(d, b"=== renamed file 'file' => 'newname'\n")
 
563
        self.assertContainsRe(d, b'--- old/file\t')
 
564
        self.assertContainsRe(d, b'\\+\\+\\+ new/newname\t')
 
565
        self.assertContainsRe(d, b'-contents\n'
 
566
                                 b'\\+new contents\n')
561
567
 
562
568
 
563
569
    def test_internal_diff_exec_property(self):
564
570
        tree = self.make_branch_and_tree('tree')
565
571
 
566
572
        tt = transform.TreeTransform(tree)
567
 
        tt.new_file('a', tt.root, 'contents\n', 'a-id', True)
568
 
        tt.new_file('b', tt.root, 'contents\n', 'b-id', False)
569
 
        tt.new_file('c', tt.root, 'contents\n', 'c-id', True)
570
 
        tt.new_file('d', tt.root, 'contents\n', 'd-id', False)
571
 
        tt.new_file('e', tt.root, 'contents\n', 'control-e-id', True)
572
 
        tt.new_file('f', tt.root, 'contents\n', 'control-f-id', False)
 
573
        tt.new_file('a', tt.root, [b'contents\n'], b'a-id', True)
 
574
        tt.new_file('b', tt.root, [b'contents\n'], b'b-id', False)
 
575
        tt.new_file('c', tt.root, [b'contents\n'], b'c-id', True)
 
576
        tt.new_file('d', tt.root, [b'contents\n'], b'd-id', False)
 
577
        tt.new_file('e', tt.root, [b'contents\n'], b'control-e-id', True)
 
578
        tt.new_file('f', tt.root, [b'contents\n'], b'control-f-id', False)
573
579
        tt.apply()
574
580
        tree.commit('one', rev_id=b'rev-1')
575
581
 
576
582
        tt = transform.TreeTransform(tree)
577
 
        tt.set_executability(False, tt.trans_id_file_id('a-id'))
578
 
        tt.set_executability(True, tt.trans_id_file_id('b-id'))
579
 
        tt.set_executability(False, tt.trans_id_file_id('c-id'))
580
 
        tt.set_executability(True, tt.trans_id_file_id('d-id'))
 
583
        tt.set_executability(False, tt.trans_id_file_id(b'a-id'))
 
584
        tt.set_executability(True, tt.trans_id_file_id(b'b-id'))
 
585
        tt.set_executability(False, tt.trans_id_file_id(b'c-id'))
 
586
        tt.set_executability(True, tt.trans_id_file_id(b'd-id'))
581
587
        tt.apply()
582
588
        tree.rename_one('c', 'new-c')
583
589
        tree.rename_one('d', 'new-d')
584
590
 
585
591
        d = get_diff_as_string(tree.basis_tree(), tree)
586
592
 
587
 
        self.assertContainsRe(d, r"file 'a'.*\(properties changed:"
588
 
                                 r".*\+x to -x.*\)")
589
 
        self.assertContainsRe(d, r"file 'b'.*\(properties changed:"
590
 
                                 r".*-x to \+x.*\)")
591
 
        self.assertContainsRe(d, r"file 'c'.*\(properties changed:"
592
 
                                 r".*\+x to -x.*\)")
593
 
        self.assertContainsRe(d, r"file 'd'.*\(properties changed:"
594
 
                                 r".*-x to \+x.*\)")
595
 
        self.assertNotContainsRe(d, r"file 'e'")
596
 
        self.assertNotContainsRe(d, r"file 'f'")
 
593
        self.assertContainsRe(d, br"file 'a'.*\(properties changed:"
 
594
                                 br".*\+x to -x.*\)")
 
595
        self.assertContainsRe(d, br"file 'b'.*\(properties changed:"
 
596
                                 br".*-x to \+x.*\)")
 
597
        self.assertContainsRe(d, br"file 'c'.*\(properties changed:"
 
598
                                 br".*\+x to -x.*\)")
 
599
        self.assertContainsRe(d, br"file 'd'.*\(properties changed:"
 
600
                                 br".*-x to \+x.*\)")
 
601
        self.assertNotContainsRe(d, br"file 'e'")
 
602
        self.assertNotContainsRe(d, br"file 'f'")
597
603
 
598
604
    def test_binary_unicode_filenames(self):
599
605
        """Test that contents of files are *not* encoded in UTF-8 when there
606
612
        alpha, omega = u'\u03b1', u'\u03c9'
607
613
        alpha_utf8, omega_utf8 = alpha.encode('utf8'), omega.encode('utf8')
608
614
        self.build_tree_contents(
609
 
            [('tree/' + alpha, chr(0)),
 
615
            [('tree/' + alpha, b'\0'),
610
616
             ('tree/' + omega,
611
 
              ('The %s and the %s\n' % (alpha_utf8, omega_utf8)))])
 
617
              (b'The %s and the %s\n' % (alpha_utf8, omega_utf8)))])
612
618
        tree.add([alpha], [b'file-id'])
613
619
        tree.add([omega], [b'file-id-2'])
614
620
        diff_content = StubO()
615
621
        diff.show_diff_trees(tree.basis_tree(), tree, diff_content)
616
622
        diff_content.check_types(self, bytes)
617
623
        d = b''.join(diff_content.write_record)
618
 
        self.assertContainsRe(d, r"=== added file '%s'" % alpha_utf8)
619
 
        self.assertContainsRe(d, "Binary files a/%s.*and b/%s.* differ\n"
 
624
        self.assertContainsRe(d, br"=== added file '%s'" % alpha_utf8)
 
625
        self.assertContainsRe(d, b"Binary files a/%s.*and b/%s.* differ\n"
620
626
                              % (alpha_utf8, alpha_utf8))
621
 
        self.assertContainsRe(d, r"=== added file '%s'" % omega_utf8)
622
 
        self.assertContainsRe(d, r"--- a/%s" % (omega_utf8,))
623
 
        self.assertContainsRe(d, r"\+\+\+ b/%s" % (omega_utf8,))
 
627
        self.assertContainsRe(d, br"=== added file '%s'" % omega_utf8)
 
628
        self.assertContainsRe(d, br"--- a/%s" % (omega_utf8,))
 
629
        self.assertContainsRe(d, br"\+\+\+ b/%s" % (omega_utf8,))
624
630
 
625
631
    def test_unicode_filename(self):
626
632
        """Test when the filename are unicode."""
647
653
 
648
654
        d = get_diff_as_string(tree.basis_tree(), tree)
649
655
        self.assertContainsRe(d,
650
 
                "=== renamed file 'ren_%s' => 'ren_%s'\n"%(autf8, outf8))
651
 
        self.assertContainsRe(d, "=== added file 'add_%s'"%autf8)
652
 
        self.assertContainsRe(d, "=== modified file 'mod_%s'"%autf8)
653
 
        self.assertContainsRe(d, "=== removed file 'del_%s'"%autf8)
 
656
                b"=== renamed file 'ren_%s' => 'ren_%s'\n"%(autf8, outf8))
 
657
        self.assertContainsRe(d, b"=== added file 'add_%s'"%autf8)
 
658
        self.assertContainsRe(d, b"=== modified file 'mod_%s'"%autf8)
 
659
        self.assertContainsRe(d, b"=== removed file 'del_%s'"%autf8)
654
660
 
655
661
    def test_unicode_filename_path_encoding(self):
656
662
        """Test for bug #382699: unicode filenames on Windows should be shown
676
682
            path_encoding='cp1251')
677
683
 
678
684
        output = subst_dates(sio.getvalue())
679
 
        shouldbe = ('''\
 
685
        shouldbe = (b'''\
680
686
=== added directory '%(directory)s'
681
687
=== added file '%(test_txt)s'
682
688
--- a/%(test_txt)s\tYYYY-MM-DD HH:MM:SS +ZZZZ
690
696
@@ -0,0 +1,1 @@
691
697
+foo
692
698
 
693
 
''' % {'directory': _russian_test.encode('cp1251'),
694
 
       'test_txt': test_txt.encode('cp1251'),
 
699
''' % {b'directory': _russian_test.encode('cp1251'),
 
700
       b'test_txt': test_txt.encode('cp1251'),
695
701
      })
696
702
        self.assertEqualDiff(output, shouldbe)
697
703
 
699
705
class DiffWasIs(diff.DiffPath):
700
706
 
701
707
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
702
 
        self.to_file.write('was: ')
 
708
        self.to_file.write(b'was: ')
703
709
        self.to_file.write(self.old_tree.get_file(old_path).read())
704
 
        self.to_file.write('is: ')
 
710
        self.to_file.write(b'is: ')
705
711
        self.to_file.write(self.new_tree.get_file(new_path).read())
706
712
 
707
713
 
730
736
        differ.diff_text('olddir/oldfile', None, 'old label',
731
737
                         'new label', b'file-id', None)
732
738
        self.assertEqual(
733
 
            '--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
 
739
            b'--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
734
740
            differ.to_file.getvalue())
735
741
        differ.to_file.seek(0)
736
742
        differ.diff_text(None, 'newdir/newfile',
737
743
                         'old label', 'new label', None, b'file-id')
738
744
        self.assertEqual(
739
 
            '--- old label\n+++ new label\n@@ -0,0 +1,1 @@\n+new\n\n',
 
745
            b'--- old label\n+++ new label\n@@ -0,0 +1,1 @@\n+new\n\n',
740
746
            differ.to_file.getvalue())
741
747
        differ.to_file.seek(0)
742
748
        differ.diff_text('olddir/oldfile', 'newdir/newfile',
743
749
                         'old label', 'new label', b'file-id', b'file-id')
744
750
        self.assertEqual(
745
 
            '--- old label\n+++ new label\n@@ -1,1 +1,1 @@\n-old\n+new\n\n',
 
751
            b'--- old label\n+++ new label\n@@ -1,1 +1,1 @@\n-old\n+new\n\n',
746
752
            differ.to_file.getvalue())
747
753
 
748
754
    def test_diff_deletion(self):
752
758
        self.new_tree.add('file', b'file-id')
753
759
        os.unlink('new-tree/file')
754
760
        self.differ.show_diff(None)
755
 
        self.assertContainsRe(self.differ.to_file.getvalue(), '-contents')
 
761
        self.assertContainsRe(self.differ.to_file.getvalue(), b'-contents')
756
762
 
757
763
    def test_diff_creation(self):
758
764
        self.build_tree_contents([('old-tree/file', b'contents'),
761
767
        self.new_tree.add('file', b'file-id')
762
768
        os.unlink('old-tree/file')
763
769
        self.differ.show_diff(None)
764
 
        self.assertContainsRe(self.differ.to_file.getvalue(), r'\+contents')
 
770
        self.assertContainsRe(self.differ.to_file.getvalue(), br'\+contents')
765
771
 
766
772
    def test_diff_symlink(self):
767
773
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, BytesIO())
768
774
        differ.diff_symlink('old target', None)
769
 
        self.assertEqual("=== target was 'old target'\n",
 
775
        self.assertEqual(b"=== target was 'old target'\n",
770
776
                         differ.to_file.getvalue())
771
777
 
772
778
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, BytesIO())
773
779
        differ.diff_symlink(None, 'new target')
774
 
        self.assertEqual("=== target is 'new target'\n",
 
780
        self.assertEqual(b"=== target is 'new target'\n",
775
781
                         differ.to_file.getvalue())
776
782
 
777
783
        differ = diff.DiffSymlink(self.old_tree, self.new_tree, BytesIO())
778
784
        differ.diff_symlink('old target', 'new target')
779
 
        self.assertEqual("=== target changed 'old target' => 'new target'\n",
 
785
        self.assertEqual(b"=== target changed 'old target' => 'new target'\n",
780
786
                         differ.to_file.getvalue())
781
787
 
782
788
    def test_diff(self):
788
794
                                  ('new-tree/newdir/newfile', b'new\n')])
789
795
        self.new_tree.add('newdir')
790
796
        self.new_tree.add('newdir/newfile', b'file-id')
791
 
        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
 
797
        self.differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
792
798
        self.assertContainsRe(
793
799
            self.differ.to_file.getvalue(),
794
 
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
795
 
            r' \@\@\n-old\n\+new\n\n')
 
800
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
 
801
            br' \@\@\n-old\n\+new\n\n')
796
802
 
797
803
    def test_diff_kind_change(self):
798
804
        self.requireFeature(features.SymlinkFeature)
804
810
        os.symlink('new', 'new-tree/newdir/newfile')
805
811
        self.new_tree.add('newdir')
806
812
        self.new_tree.add('newdir/newfile', b'file-id')
807
 
        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
 
813
        self.differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
808
814
        self.assertContainsRe(
809
815
            self.differ.to_file.getvalue(),
810
 
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
811
 
            r' \@\@\n-old\n\n')
 
816
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
 
817
            br' \@\@\n-old\n\n')
812
818
        self.assertContainsRe(self.differ.to_file.getvalue(),
813
 
                              "=== target is u'new'\n")
 
819
                              b"=== target is 'new'\n")
814
820
 
815
821
    def test_diff_directory(self):
816
822
        self.build_tree(['new-tree/new-dir/'])
817
823
        self.new_tree.add('new-dir', b'new-dir-id')
818
824
        self.differ.diff(b'new-dir-id', None, 'new-dir')
819
 
        self.assertEqual(self.differ.to_file.getvalue(), '')
 
825
        self.assertEqual(self.differ.to_file.getvalue(), b'')
820
826
 
821
827
    def create_old_new(self):
822
828
        self.build_tree_contents([('old-tree/olddir/',),
837
843
            differ = diff.DiffTree(self.old_tree, self.new_tree, BytesIO())
838
844
        finally:
839
845
            diff.DiffTree.diff_factories = old_diff_factories
840
 
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
 
846
        differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
841
847
        self.assertNotContainsRe(
842
848
            differ.to_file.getvalue(),
843
 
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
844
 
            r' \@\@\n-old\n\+new\n\n')
 
849
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
 
850
            br' \@\@\n-old\n\+new\n\n')
845
851
        self.assertContainsRe(differ.to_file.getvalue(),
846
 
                              'was: old\nis: new\n')
 
852
                              b'was: old\nis: new\n')
847
853
 
848
854
    def test_extra_factories(self):
849
855
        self.create_old_new()
850
856
        differ = diff.DiffTree(self.old_tree, self.new_tree, BytesIO(),
851
857
                               extra_factories=[DiffWasIs.from_diff_tree])
852
 
        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
 
858
        differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
853
859
        self.assertNotContainsRe(
854
860
            differ.to_file.getvalue(),
855
 
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
856
 
            r' \@\@\n-old\n\+new\n\n')
 
861
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
 
862
            br' \@\@\n-old\n\+new\n\n')
857
863
        self.assertContainsRe(differ.to_file.getvalue(),
858
 
                              'was: old\nis: new\n')
 
864
                              b'was: old\nis: new\n')
859
865
 
860
866
    def test_alphabetical_order(self):
861
867
        self.build_tree(['new-tree/a-file'])
864
870
        self.old_tree.add('b-file')
865
871
        self.differ.show_diff(None)
866
872
        self.assertContainsRe(self.differ.to_file.getvalue(),
867
 
            '.*a-file(.|\n)*b-file')
 
873
            b'.*a-file(.|\n)*b-file')
868
874
 
869
875
 
870
876
class TestPatienceDiffLib(tests.TestCase):
1291
1297
            _patiencediff_py.PatienceSequenceMatcher_py
1292
1298
 
1293
1299
    def test_patience_unified_diff_files(self):
1294
 
        txt_a = ['hello there\n',
1295
 
                 'world\n',
1296
 
                 'how are you today?\n']
1297
 
        txt_b = ['hello there\n',
1298
 
                 'how are you today?\n']
 
1300
        txt_a = [b'hello there\n',
 
1301
                 b'world\n',
 
1302
                 b'how are you today?\n']
 
1303
        txt_b = [b'hello there\n',
 
1304
                 b'how are you today?\n']
1299
1305
        with open('a1', 'wb') as f: f.writelines(txt_a)
1300
1306
        with open('b1', 'wb') as f: f.writelines(txt_b)
1301
1307
 
1302
1308
        unified_diff_files = patiencediff.unified_diff_files
1303
1309
        psm = self._PatienceSequenceMatcher
1304
 
        self.assertEqual(['--- a1\n',
1305
 
                           '+++ b1\n',
1306
 
                           '@@ -1,3 +1,2 @@\n',
1307
 
                           ' hello there\n',
1308
 
                           '-world\n',
1309
 
                           ' how are you today?\n',
 
1310
        self.assertEqual([b'--- a1\n',
 
1311
                          b'+++ b1\n',
 
1312
                          b'@@ -1,3 +1,2 @@\n',
 
1313
                          b' hello there\n',
 
1314
                          b'-world\n',
 
1315
                          b' how are you today?\n',
1310
1316
                          ]
1311
 
                          , list(unified_diff_files('a1', 'b1',
 
1317
                          , list(unified_diff_files(b'a1', b'b1',
1312
1318
                                 sequencematcher=psm)))
1313
1319
 
1314
1320
        txt_a = [x+'\n' for x in 'abcdefghijklmnop']
1315
1321
        txt_b = [x+'\n' for x in 'abcdefxydefghijklmnop']
1316
 
        with open('a2', 'wb') as f: f.writelines(txt_a)
1317
 
        with open('b2', 'wb') as f: f.writelines(txt_b)
 
1322
        with open('a2', 'wt') as f: f.writelines(txt_a)
 
1323
        with open('b2', 'wt') as f: f.writelines(txt_b)
1318
1324
 
1319
1325
        # This is the result with LongestCommonSubstring matching
1320
 
        self.assertEqual(['--- a2\n',
1321
 
                           '+++ b2\n',
1322
 
                           '@@ -1,6 +1,11 @@\n',
1323
 
                           ' a\n',
1324
 
                           ' b\n',
1325
 
                           ' c\n',
1326
 
                           '+d\n',
1327
 
                           '+e\n',
1328
 
                           '+f\n',
1329
 
                           '+x\n',
1330
 
                           '+y\n',
1331
 
                           ' d\n',
1332
 
                           ' e\n',
1333
 
                           ' f\n']
1334
 
                          , list(unified_diff_files('a2', 'b2')))
 
1326
        self.assertEqual([b'--- a2\n',
 
1327
                          b'+++ b2\n',
 
1328
                          b'@@ -1,6 +1,11 @@\n',
 
1329
                          b' a\n',
 
1330
                          b' b\n',
 
1331
                          b' c\n',
 
1332
                          b'+d\n',
 
1333
                          b'+e\n',
 
1334
                          b'+f\n',
 
1335
                          b'+x\n',
 
1336
                          b'+y\n',
 
1337
                          b' d\n',
 
1338
                          b' e\n',
 
1339
                          b' f\n']
 
1340
                          , list(unified_diff_files(b'a2', b'b2')))
1335
1341
 
1336
1342
        # And the patience diff
1337
 
        self.assertEqual(['--- a2\n',
1338
 
                          '+++ b2\n',
1339
 
                          '@@ -4,6 +4,11 @@\n',
1340
 
                          ' d\n',
1341
 
                          ' e\n',
1342
 
                          ' f\n',
1343
 
                          '+x\n',
1344
 
                          '+y\n',
1345
 
                          '+d\n',
1346
 
                          '+e\n',
1347
 
                          '+f\n',
1348
 
                          ' g\n',
1349
 
                          ' h\n',
1350
 
                          ' i\n'],
1351
 
                         list(unified_diff_files('a2', 'b2',
 
1343
        self.assertEqual([b'--- a2\n',
 
1344
                          b'+++ b2\n',
 
1345
                          b'@@ -4,6 +4,11 @@\n',
 
1346
                          b' d\n',
 
1347
                          b' e\n',
 
1348
                          b' f\n',
 
1349
                          b'+x\n',
 
1350
                          b'+y\n',
 
1351
                          b'+d\n',
 
1352
                          b'+e\n',
 
1353
                          b'+f\n',
 
1354
                          b' g\n',
 
1355
                          b' h\n',
 
1356
                          b' i\n'],
 
1357
                         list(unified_diff_files(b'a2', b'b2',
1352
1358
                                                 sequencematcher=psm)))
1353
1359
 
1354
1360
 
1425
1431
 
1426
1432
    def test_execute(self):
1427
1433
        output = BytesIO()
1428
 
        diff_obj = diff.DiffFromTool(['python', '-c',
1429
 
                                      'print "@old_path @new_path"'],
 
1434
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
 
1435
                                      'print("@old_path @new_path")'],
1430
1436
                                     None, None, output)
1431
1437
        self.addCleanup(diff_obj.finish)
1432
1438
        diff_obj._execute('old', 'new')
1433
 
        self.assertEqual(output.getvalue().rstrip(), 'old new')
 
1439
        self.assertEqual(output.getvalue().rstrip(), b'old new')
1434
1440
 
1435
1441
    def test_execute_missing(self):
1436
1442
        diff_obj = diff.DiffFromTool(['a-tool-which-is-unlikely-to-exist'],
1453
1459
        basis_tree = tree.basis_tree()
1454
1460
        basis_tree.lock_read()
1455
1461
        self.addCleanup(basis_tree.unlock)
1456
 
        diff_obj = diff.DiffFromTool(['python', '-c',
 
1462
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1457
1463
                                      'print "@old_path @new_path"'],
1458
1464
                                     basis_tree, tree, output)
1459
1465
        diff_obj._prepare_files('file', 'file', file_id=b'file-id')
1489
1495
        self.addCleanup(old_tree.unlock)
1490
1496
        tree.lock_read()
1491
1497
        self.addCleanup(tree.unlock)
1492
 
        diff_obj = diff.DiffFromTool(['python', '-c',
 
1498
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1493
1499
                                      'print "@old_path @new_path"'],
1494
1500
                                     old_tree, tree, output)
1495
1501
        self.addCleanup(diff_obj.finish)
1496
1502
        self.assertContainsRe(diff_obj._root, 'brz-diff-[^/]*')
1497
1503
        old_path, new_path = diff_obj._prepare_files(
1498
 
                'oldname', 'newname', file_id='file-id')
 
1504
                'oldname', 'newname', file_id=b'file-id')
1499
1505
        self.assertContainsRe(old_path, 'old/oldname$')
1500
1506
        self.assertEqual(315532800, os.stat(old_path).st_mtime)
1501
1507
        self.assertContainsRe(new_path, 'tree/newname$')
1502
 
        self.assertFileEqual('oldcontent', old_path)
1503
 
        self.assertFileEqual('newcontent', new_path)
 
1508
        self.assertFileEqual(b'oldcontent', old_path)
 
1509
        self.assertFileEqual(b'newcontent', new_path)
1504
1510
        if osutils.host_os_dereferences_symlinks():
1505
1511
            self.assertTrue(os.path.samefile('tree/newname', new_path))
1506
1512
        # make sure we can create files with the same parent directories
1507
 
        diff_obj._prepare_files('oldname2', 'newname2', file_id='file2-id')
 
1513
        diff_obj._prepare_files('oldname2', 'newname2', file_id=b'file2-id')
1508
1514
 
1509
1515
 
1510
1516
class TestDiffFromToolEncodedFilename(tests.TestCaseWithTransport):
1576
1582
        tree.add('file', b'file-id')
1577
1583
        tree.commit('old tree', timestamp=0, rev_id=b"old-id")
1578
1584
        self.build_tree_contents([('tree/file', b'newcontent')])
1579
 
        tree.commit('new tree', timestamp=0, rev_id="new-id")
 
1585
        tree.commit('new tree', timestamp=0, rev_id=b"new-id")
1580
1586
 
1581
1587
        revisions = [revisionspec.RevisionSpec.from_string('1'),
1582
1588
                     revisionspec.RevisionSpec.from_string('2')]
1586
1592
            ['tree'], revisions, None, None)
1587
1593
 
1588
1594
        self.assertIsInstance(old_tree, revisiontree.RevisionTree)
1589
 
        self.assertEqual("old-id", old_tree.get_revision_id())
 
1595
        self.assertEqual(b"old-id", old_tree.get_revision_id())
1590
1596
        self.assertIsInstance(new_tree, revisiontree.RevisionTree)
1591
 
        self.assertEqual("new-id", new_tree.get_revision_id())
 
1597
        self.assertEqual(b"new-id", new_tree.get_revision_id())
1592
1598
        self.assertEqual(tree.branch.base, old_branch.base)
1593
1599
        self.assertEqual(tree.branch.base, new_branch.base)
1594
1600
        self.assertIs(None, specific_files)