/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_annotate.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2020-08-23 01:15:41 UTC
  • mfrom: (7520.1.4 merge-3.1)
  • Revision ID: breezy.the.bot@gmail.com-20200823011541-nv0oh7nzaganx2qy
Merge lp:brz/3.1.

Merged from https://code.launchpad.net/~jelmer/brz/merge-3.1/+merge/389690

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2009, 2011 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
17
17
"""Whitebox tests for annotate functionality."""
18
18
 
19
19
import codecs
20
 
from cStringIO import StringIO
 
20
from io import BytesIO, StringIO
21
21
 
22
 
from bzrlib import (
 
22
from .. import (
23
23
    annotate,
24
 
    conflicts,
25
 
    errors,
26
24
    tests,
27
 
    trace,
28
25
    )
 
26
from .ui_testing import StringIOWithEncoding
29
27
 
30
28
 
31
29
def annotation(text):
32
 
    return [tuple(l.split(' ', 1)) for l in text.splitlines(True)]
33
 
 
34
 
 
35
 
parent_1 = annotation("""\
 
30
    return [tuple(l.split(b' ', 1)) for l in text.splitlines(True)]
 
31
 
 
32
 
 
33
parent_1 = annotation(b"""\
36
34
rev1 a
37
35
rev2 b
38
36
rev3 c
41
39
""")
42
40
 
43
41
 
44
 
parent_2 = annotation("""\
 
42
parent_2 = annotation(b"""\
45
43
rev1 a
46
44
rev3 c
47
45
rev4 d
51
49
""")
52
50
 
53
51
 
54
 
expected_2_1 = annotation("""\
 
52
expected_2_1 = annotation(b"""\
55
53
rev1 a
56
54
blahblah b
57
55
rev3 c
68
66
# f: in 2, but not in new, so ignored
69
67
# g: not in 1 or 2, so it goes to blahblah
70
68
# h: only in parent 2, so 2 gets it
71
 
expected_1_2_2 = annotation("""\
 
69
expected_1_2_2 = annotation(b"""\
72
70
rev1 a
73
71
rev2 b
74
72
rev3 c
79
77
""")
80
78
 
81
79
 
82
 
new_1 = """\
 
80
new_1 = b"""\
83
81
a
84
82
b
85
83
c
87
85
e
88
86
""".splitlines(True)
89
87
 
90
 
expected_1 = annotation("""\
 
88
expected_1 = annotation(b"""\
91
89
blahblah a
92
90
blahblah b
93
91
blahblah c
96
94
""")
97
95
 
98
96
 
99
 
new_2 = """\
 
97
new_2 = b"""\
100
98
a
101
99
b
102
100
c
120
118
#  |/
121
119
#  E    # D should supersede A and stay as D (not become E because C references
122
120
#         A)
123
 
duplicate_base = annotation("""\
 
121
duplicate_base = annotation(b"""\
124
122
rev-base first
125
123
rev-base second
126
124
rev-base third
127
125
rev-base fourth-base
128
126
""")
129
127
 
130
 
duplicate_A = annotation("""\
 
128
duplicate_A = annotation(b"""\
131
129
rev-base first
132
130
rev-A alt-second
133
131
rev-base third
134
132
rev-A fourth-A
135
133
""")
136
134
 
137
 
duplicate_B = annotation("""\
 
135
duplicate_B = annotation(b"""\
138
136
rev-base first
139
137
rev-B alt-second
140
138
rev-base third
141
139
rev-B fourth-B
142
140
""")
143
141
 
144
 
duplicate_C = annotation("""\
 
142
duplicate_C = annotation(b"""\
145
143
rev-base first
146
144
rev-A alt-second
147
145
rev-base third
148
146
rev-C fourth-C
149
147
""")
150
148
 
151
 
duplicate_D = annotation("""\
 
149
duplicate_D = annotation(b"""\
152
150
rev-base first
153
151
rev-A alt-second
154
152
rev-base third
155
153
rev-D fourth-D
156
154
""")
157
155
 
158
 
duplicate_E = annotation("""\
 
156
duplicate_E = annotation(b"""\
159
157
rev-base first
160
158
rev-A alt-second
161
159
rev-base third
179
177
        builder = self.make_branch_builder('branch')
180
178
        builder.start_series()
181
179
        self.addCleanup(builder.finish_series)
182
 
        builder.build_snapshot('rev-1', None, [
183
 
            ('add', ('', 'root-id', 'directory', None)),
184
 
            ('add', ('a', 'a-id', 'file', 'first\n')),
185
 
            ], timestamp=1166046000.00, timezone=0, committer="joe@foo.com")
186
 
        builder.build_snapshot('rev-2', ['rev-1'], [
187
 
            ('modify', ('a-id', 'first\nsecond\n')),
188
 
            ], timestamp=1166046001.00, timezone=0, committer="joe@foo.com")
189
 
        builder.build_snapshot('rev-1_1_1', ['rev-1'], [
190
 
            ('modify', ('a-id', 'first\nthird\n')),
191
 
            ], timestamp=1166046002.00, timezone=0, committer="barry@foo.com")
192
 
        builder.build_snapshot('rev-3', ['rev-2', 'rev-1_1_1'], [
193
 
            ('modify', ('a-id', 'first\nsecond\nthird\n')),
194
 
            ], timestamp=1166046003.00, timezone=0, committer="sal@foo.com")
 
180
        builder.build_snapshot(None, [
 
181
            ('add', ('', b'root-id', 'directory', None)),
 
182
            ('add', ('a', b'a-id', 'file', b'first\n')),
 
183
            ], timestamp=1166046000.00, timezone=0, committer="joe@foo.com",
 
184
            revision_id=b'rev-1')
 
185
        builder.build_snapshot([b'rev-1'], [
 
186
            ('modify', ('a', b'first\nsecond\n')),
 
187
            ], timestamp=1166046001.00, timezone=0, committer="joe@foo.com",
 
188
            revision_id=b'rev-2')
 
189
        builder.build_snapshot([b'rev-1'], [
 
190
            ('modify', ('a', b'first\nthird\n')),
 
191
            ], timestamp=1166046002.00, timezone=0, committer="barry@foo.com",
 
192
            revision_id=b'rev-1_1_1')
 
193
        builder.build_snapshot([b'rev-2', b'rev-1_1_1'], [
 
194
            ('modify', ('a', b'first\nsecond\nthird\n')),
 
195
            ], timestamp=1166046003.00, timezone=0, committer="sal@foo.com",
 
196
            revision_id=b'rev-3')
195
197
        return builder
196
198
 
197
199
    def create_deeply_merged_trees(self):
218
220
        rev-6
219
221
        """
220
222
        builder = self.create_merged_trees()
221
 
        builder.build_snapshot('rev-1_1_2', ['rev-1_1_1'], [])
222
 
        builder.build_snapshot('rev-4', ['rev-3', 'rev-1_1_2'], [])
223
 
        builder.build_snapshot('rev-1_2_1', ['rev-1_1_1'], [
224
 
            ('modify', ('a-id', 'first\nthird\nfourth\n')),
225
 
            ], timestamp=1166046003.00, timezone=0, committer="jerry@foo.com")
226
 
        builder.build_snapshot('rev-1_2_2', ['rev-1_2_1'], [],
227
 
            timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
228
 
        builder.build_snapshot('rev-5', ['rev-4', 'rev-1_2_2'], [
229
 
            ('modify', ('a-id', 'first\nsecond\nthird\nfourth\n')),
230
 
            ], timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
231
 
        builder.build_snapshot('rev-1_3_1', ['rev-1_2_1'], [
232
 
            ('modify', ('a-id', 'first\nthird\nfourth\nfifth\nsixth\n')),
233
 
            ], timestamp=1166046005.00, timezone=0, committer="george@foo.com")
234
 
        builder.build_snapshot('rev-6', ['rev-5', 'rev-1_3_1'], [
235
 
            ('modify', ('a-id',
236
 
                        'first\nsecond\nthird\nfourth\nfifth\nsixth\n')),
237
 
            ])
 
223
        builder.build_snapshot([b'rev-1_1_1'], [], revision_id=b'rev-1_1_2')
 
224
        builder.build_snapshot([b'rev-3', b'rev-1_1_2'],
 
225
                               [], revision_id=b'rev-4')
 
226
        builder.build_snapshot([b'rev-1_1_1'], [
 
227
            ('modify', ('a', b'first\nthird\nfourth\n')),
 
228
            ], timestamp=1166046003.00, timezone=0, committer="jerry@foo.com",
 
229
            revision_id=b'rev-1_2_1')
 
230
        builder.build_snapshot([b'rev-1_2_1'], [],
 
231
                               timestamp=1166046004.00, timezone=0, committer="jerry@foo.com",
 
232
                               revision_id=b'rev-1_2_2')
 
233
        builder.build_snapshot([b'rev-4', b'rev-1_2_2'], [
 
234
            ('modify', ('a', b'first\nsecond\nthird\nfourth\n')),
 
235
            ], timestamp=1166046004.00, timezone=0, committer="jerry@foo.com",
 
236
            revision_id=b'rev-5')
 
237
        builder.build_snapshot([b'rev-1_2_1'], [
 
238
            ('modify', ('a', b'first\nthird\nfourth\nfifth\nsixth\n')),
 
239
            ], timestamp=1166046005.00, timezone=0, committer="george@foo.com",
 
240
            revision_id=b'rev-1_3_1')
 
241
        builder.build_snapshot([b'rev-5', b'rev-1_3_1'], [
 
242
            ('modify', ('a',
 
243
                        b'first\nsecond\nthird\nfourth\nfifth\nsixth\n')),
 
244
            ], revision_id=b'rev-6')
238
245
        return builder
239
246
 
240
247
    def create_duplicate_lines_tree(self):
241
248
        builder = self.make_branch_builder('branch')
242
249
        builder.start_series()
243
250
        self.addCleanup(builder.finish_series)
244
 
        base_text = ''.join(l for r, l in duplicate_base)
245
 
        a_text = ''.join(l for r, l in duplicate_A)
246
 
        b_text = ''.join(l for r, l in duplicate_B)
247
 
        c_text = ''.join(l for r, l in duplicate_C)
248
 
        d_text = ''.join(l for r, l in duplicate_D)
249
 
        e_text = ''.join(l for r, l in duplicate_E)
250
 
        builder.build_snapshot('rev-base', None, [
251
 
            ('add', ('', 'root-id', 'directory', None)),
252
 
            ('add', ('file', 'file-id', 'file', base_text)),
253
 
            ])
254
 
        builder.build_snapshot('rev-A', ['rev-base'], [
255
 
            ('modify', ('file-id', a_text))])
256
 
        builder.build_snapshot('rev-B', ['rev-base'], [
257
 
            ('modify', ('file-id', b_text))])
258
 
        builder.build_snapshot('rev-C', ['rev-A'], [
259
 
            ('modify', ('file-id', c_text))])
260
 
        builder.build_snapshot('rev-D', ['rev-B', 'rev-A'], [
261
 
            ('modify', ('file-id', d_text))])
262
 
        builder.build_snapshot('rev-E', ['rev-C', 'rev-D'], [
263
 
            ('modify', ('file-id', e_text))])
 
251
        base_text = b''.join(l for r, l in duplicate_base)
 
252
        a_text = b''.join(l for r, l in duplicate_A)
 
253
        b_text = b''.join(l for r, l in duplicate_B)
 
254
        c_text = b''.join(l for r, l in duplicate_C)
 
255
        d_text = b''.join(l for r, l in duplicate_D)
 
256
        e_text = b''.join(l for r, l in duplicate_E)
 
257
        builder.build_snapshot(None, [
 
258
            ('add', ('', b'root-id', 'directory', None)),
 
259
            ('add', ('file', b'file-id', 'file', base_text)),
 
260
            ], revision_id=b'rev-base')
 
261
        builder.build_snapshot([b'rev-base'], [
 
262
            ('modify', ('file', a_text))],
 
263
            revision_id=b'rev-A')
 
264
        builder.build_snapshot([b'rev-base'], [
 
265
            ('modify', ('file', b_text))],
 
266
            revision_id=b'rev-B')
 
267
        builder.build_snapshot([b'rev-A'], [
 
268
            ('modify', ('file', c_text))],
 
269
            revision_id=b'rev-C')
 
270
        builder.build_snapshot([b'rev-B', b'rev-A'], [
 
271
            ('modify', ('file', d_text))],
 
272
            revision_id=b'rev-D')
 
273
        builder.build_snapshot([b'rev-C', b'rev-D'], [
 
274
            ('modify', ('file', e_text))],
 
275
            revision_id=b'rev-E')
264
276
        return builder
265
277
 
266
 
    def assertRepoAnnotate(self, expected, repo, file_id, revision_id):
267
 
        """Assert that the revision is properly annotated."""
268
 
        actual = list(repo.revision_tree(revision_id).annotate_iter(file_id))
 
278
    def assertAnnotateEqualDiff(self, actual, expected):
269
279
        if actual != expected:
270
280
            # Create an easier to understand diff when the lines don't actually
271
281
            # match
272
282
            self.assertEqualDiff(''.join('\t'.join(l) for l in expected),
273
283
                                 ''.join('\t'.join(l) for l in actual))
274
284
 
 
285
    def assertBranchAnnotate(self, expected, branch, path, revision_id,
 
286
                             verbose=False, full=False, show_ids=False):
 
287
        tree = branch.repository.revision_tree(revision_id)
 
288
        to_file = StringIO()
 
289
        annotate.annotate_file_tree(tree, path, to_file,
 
290
                                    verbose=verbose, full=full, show_ids=show_ids, branch=branch)
 
291
        self.assertAnnotateEqualDiff(to_file.getvalue(), expected)
 
292
 
 
293
    def assertRepoAnnotate(self, expected, repo, path, revision_id):
 
294
        """Assert that the revision is properly annotated."""
 
295
        actual = list(repo.revision_tree(revision_id).annotate_iter(path))
 
296
        self.assertAnnotateEqualDiff(actual, expected)
 
297
 
275
298
    def test_annotate_duplicate_lines(self):
276
299
        # XXX: Should this be a per_repository test?
277
300
        builder = self.create_duplicate_lines_tree()
278
301
        repo = builder.get_branch().repository
279
302
        repo.lock_read()
280
303
        self.addCleanup(repo.unlock)
281
 
        self.assertRepoAnnotate(duplicate_base, repo, 'file-id', 'rev-base')
282
 
        self.assertRepoAnnotate(duplicate_A, repo, 'file-id', 'rev-A')
283
 
        self.assertRepoAnnotate(duplicate_B, repo, 'file-id', 'rev-B')
284
 
        self.assertRepoAnnotate(duplicate_C, repo, 'file-id', 'rev-C')
285
 
        self.assertRepoAnnotate(duplicate_D, repo, 'file-id', 'rev-D')
286
 
        self.assertRepoAnnotate(duplicate_E, repo, 'file-id', 'rev-E')
 
304
        self.assertRepoAnnotate(duplicate_base, repo, 'file', b'rev-base')
 
305
        self.assertRepoAnnotate(duplicate_A, repo, 'file', b'rev-A')
 
306
        self.assertRepoAnnotate(duplicate_B, repo, 'file', b'rev-B')
 
307
        self.assertRepoAnnotate(duplicate_C, repo, 'file', b'rev-C')
 
308
        self.assertRepoAnnotate(duplicate_D, repo, 'file', b'rev-D')
 
309
        self.assertRepoAnnotate(duplicate_E, repo, 'file', b'rev-E')
287
310
 
288
311
    def test_annotate_shows_dotted_revnos(self):
289
312
        builder = self.create_merged_trees()
290
313
 
291
 
        sio = StringIO()
292
 
        annotate.annotate_file(builder.get_branch(), 'rev-3', 'a-id',
293
 
                               to_file=sio)
294
 
        self.assertEqualDiff('1     joe@foo | first\n'
295
 
                             '2     joe@foo | second\n'
296
 
                             '1.1.1 barry@f | third\n',
297
 
                             sio.getvalue())
 
314
        self.assertBranchAnnotate('1     joe@foo | first\n'
 
315
                                  '2     joe@foo | second\n'
 
316
                                  '1.1.1 barry@f | third\n',
 
317
                                  builder.get_branch(), 'a', b'rev-3')
298
318
 
299
319
    def test_annotate_limits_dotted_revnos(self):
300
320
        """Annotate should limit dotted revnos to a depth of 12"""
301
321
        builder = self.create_deeply_merged_trees()
302
322
 
303
 
        sio = StringIO()
304
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
305
 
                               to_file=sio, verbose=False, full=False)
306
 
        self.assertEqualDiff('1     joe@foo | first\n'
307
 
                             '2     joe@foo | second\n'
308
 
                             '1.1.1 barry@f | third\n'
309
 
                             '1.2.1 jerry@f | fourth\n'
310
 
                             '1.3.1 george@ | fifth\n'
311
 
                             '              | sixth\n',
312
 
                             sio.getvalue())
 
323
        self.assertBranchAnnotate('1     joe@foo | first\n'
 
324
                                  '2     joe@foo | second\n'
 
325
                                  '1.1.1 barry@f | third\n'
 
326
                                  '1.2.1 jerry@f | fourth\n'
 
327
                                  '1.3.1 george@ | fifth\n'
 
328
                                  '              | sixth\n',
 
329
                                  builder.get_branch(), 'a', b'rev-6',
 
330
                                  verbose=False, full=False)
313
331
 
314
 
        sio = StringIO()
315
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
316
 
                               to_file=sio, verbose=False, full=True)
317
 
        self.assertEqualDiff('1     joe@foo | first\n'
318
 
                             '2     joe@foo | second\n'
319
 
                             '1.1.1 barry@f | third\n'
320
 
                             '1.2.1 jerry@f | fourth\n'
321
 
                             '1.3.1 george@ | fifth\n'
322
 
                             '1.3.1 george@ | sixth\n',
323
 
                             sio.getvalue())
 
332
        self.assertBranchAnnotate('1     joe@foo | first\n'
 
333
                                  '2     joe@foo | second\n'
 
334
                                  '1.1.1 barry@f | third\n'
 
335
                                  '1.2.1 jerry@f | fourth\n'
 
336
                                  '1.3.1 george@ | fifth\n'
 
337
                                  '1.3.1 george@ | sixth\n',
 
338
                                  builder.get_branch(), 'a', b'rev-6',
 
339
                                  verbose=False, full=True)
324
340
 
325
341
        # verbose=True shows everything, the full revno, user id, and date
326
 
        sio = StringIO()
327
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
328
 
                               to_file=sio, verbose=True, full=False)
329
 
        self.assertEqualDiff('1     joe@foo.com    20061213 | first\n'
330
 
                             '2     joe@foo.com    20061213 | second\n'
331
 
                             '1.1.1 barry@foo.com  20061213 | third\n'
332
 
                             '1.2.1 jerry@foo.com  20061213 | fourth\n'
333
 
                             '1.3.1 george@foo.com 20061213 | fifth\n'
334
 
                             '                              | sixth\n',
335
 
                             sio.getvalue())
 
342
        self.assertBranchAnnotate('1     joe@foo.com    20061213 | first\n'
 
343
                                  '2     joe@foo.com    20061213 | second\n'
 
344
                                  '1.1.1 barry@foo.com  20061213 | third\n'
 
345
                                  '1.2.1 jerry@foo.com  20061213 | fourth\n'
 
346
                                  '1.3.1 george@foo.com 20061213 | fifth\n'
 
347
                                  '                              | sixth\n',
 
348
                                  builder.get_branch(), 'a', b'rev-6',
 
349
                                  verbose=True, full=False)
336
350
 
337
 
        sio = StringIO()
338
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
339
 
                               to_file=sio, verbose=True, full=True)
340
 
        self.assertEqualDiff('1     joe@foo.com    20061213 | first\n'
341
 
                             '2     joe@foo.com    20061213 | second\n'
342
 
                             '1.1.1 barry@foo.com  20061213 | third\n'
343
 
                             '1.2.1 jerry@foo.com  20061213 | fourth\n'
344
 
                             '1.3.1 george@foo.com 20061213 | fifth\n'
345
 
                             '1.3.1 george@foo.com 20061213 | sixth\n',
346
 
                             sio.getvalue())
 
351
        self.assertBranchAnnotate('1     joe@foo.com    20061213 | first\n'
 
352
                                  '2     joe@foo.com    20061213 | second\n'
 
353
                                  '1.1.1 barry@foo.com  20061213 | third\n'
 
354
                                  '1.2.1 jerry@foo.com  20061213 | fourth\n'
 
355
                                  '1.3.1 george@foo.com 20061213 | fifth\n'
 
356
                                  '1.3.1 george@foo.com 20061213 | sixth\n',
 
357
                                  builder.get_branch(), 'a', b'rev-6',
 
358
                                  verbose=True, full=True)
347
359
 
348
360
    def test_annotate_uses_branch_context(self):
349
361
        """Dotted revnos should use the Branch context.
353
365
        """
354
366
        builder = self.create_deeply_merged_trees()
355
367
 
356
 
        sio = StringIO()
357
 
        annotate.annotate_file(builder.get_branch(), 'rev-1_3_1', 'a-id',
358
 
                               to_file=sio, verbose=False, full=False)
359
 
        self.assertEqualDiff('1     joe@foo | first\n'
360
 
                             '1.1.1 barry@f | third\n'
361
 
                             '1.2.1 jerry@f | fourth\n'
362
 
                             '1.3.1 george@ | fifth\n'
363
 
                             '              | sixth\n',
364
 
                             sio.getvalue())
 
368
        self.assertBranchAnnotate('1     joe@foo | first\n'
 
369
                                  '1.1.1 barry@f | third\n'
 
370
                                  '1.2.1 jerry@f | fourth\n'
 
371
                                  '1.3.1 george@ | fifth\n'
 
372
                                  '              | sixth\n',
 
373
                                  builder.get_branch(), 'a', b'rev-1_3_1',
 
374
                                  verbose=False, full=False)
365
375
 
366
376
    def test_annotate_show_ids(self):
367
377
        builder = self.create_deeply_merged_trees()
368
378
 
369
 
        sio = StringIO()
370
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
371
 
                               to_file=sio, show_ids=True, full=False)
372
 
 
373
379
        # It looks better with real revision ids :)
374
 
        self.assertEqualDiff('    rev-1 | first\n'
375
 
                             '    rev-2 | second\n'
376
 
                             'rev-1_1_1 | third\n'
377
 
                             'rev-1_2_1 | fourth\n'
378
 
                             'rev-1_3_1 | fifth\n'
379
 
                             '          | sixth\n',
380
 
                             sio.getvalue())
381
 
 
382
 
        sio = StringIO()
383
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
384
 
                               to_file=sio, show_ids=True, full=True)
385
 
 
386
 
        self.assertEqualDiff('    rev-1 | first\n'
387
 
                             '    rev-2 | second\n'
388
 
                             'rev-1_1_1 | third\n'
389
 
                             'rev-1_2_1 | fourth\n'
390
 
                             'rev-1_3_1 | fifth\n'
391
 
                             'rev-1_3_1 | sixth\n',
392
 
                             sio.getvalue())
 
380
        self.assertBranchAnnotate('    rev-1 | first\n'
 
381
                                  '    rev-2 | second\n'
 
382
                                  'rev-1_1_1 | third\n'
 
383
                                  'rev-1_2_1 | fourth\n'
 
384
                                  'rev-1_3_1 | fifth\n'
 
385
                                  '          | sixth\n',
 
386
                                  builder.get_branch(), 'a', b'rev-6',
 
387
                                  show_ids=True, full=False)
 
388
 
 
389
        self.assertBranchAnnotate('    rev-1 | first\n'
 
390
                                  '    rev-2 | second\n'
 
391
                                  'rev-1_1_1 | third\n'
 
392
                                  'rev-1_2_1 | fourth\n'
 
393
                                  'rev-1_3_1 | fifth\n'
 
394
                                  'rev-1_3_1 | sixth\n',
 
395
                                  builder.get_branch(), 'a', b'rev-6',
 
396
                                  show_ids=True, full=True)
393
397
 
394
398
    def test_annotate_unicode_author(self):
395
399
        tree1 = self.make_branch_and_tree('tree1')
396
400
 
397
 
        self.build_tree_contents([('tree1/a', 'adi\xc3\xb3s')])
398
 
        tree1.add(['a'], ['a-id'])
399
 
        tree1.commit('a', rev_id='rev-1',
 
401
        self.build_tree_contents([('tree1/a', b'adi\xc3\xb3s')])
 
402
        tree1.add(['a'], [b'a-id'])
 
403
        tree1.commit('a', rev_id=b'rev-1',
400
404
                     committer=u'Pepe P\xe9rez <pperez@ejemplo.com>',
401
405
                     timestamp=1166046000.00, timezone=0)
402
406
 
403
 
        self.build_tree_contents([('tree1/b', 'bye')])
404
 
        tree1.add(['b'], ['b-id'])
405
 
        tree1.commit('b', rev_id='rev-2',
 
407
        self.build_tree_contents([('tree1/b', b'bye')])
 
408
        tree1.add(['b'], [b'b-id'])
 
409
        tree1.commit('b', rev_id=b'rev-2',
406
410
                     committer=u'p\xe9rez',
407
411
                     timestamp=1166046000.00, timezone=0)
408
412
 
409
413
        tree1.lock_read()
410
414
        self.addCleanup(tree1.unlock)
 
415
 
 
416
        revtree_1 = tree1.branch.repository.revision_tree(b'rev-1')
 
417
        revtree_2 = tree1.branch.repository.revision_tree(b'rev-2')
 
418
 
411
419
        # this passes if no exception is raised
412
420
        to_file = StringIO()
413
 
        annotate.annotate_file(tree1.branch, 'rev-1', 'a-id', to_file=to_file)
414
 
 
415
 
        sio = StringIO()
416
 
        to_file = codecs.getwriter('ascii')(sio)
417
 
        to_file.encoding = 'ascii' # codecs does not set it
418
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
419
 
        self.assertEqualDiff('2   p?rez   | bye\n', sio.getvalue())
420
 
 
421
 
        # test now with to_file.encoding = None
422
 
        to_file = tests.StringIOWrapper()
423
 
        to_file.encoding = None
424
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
425
 
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
426
 
 
427
 
        # and when it does not exist
428
 
        to_file = StringIO()
429
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
430
 
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
 
421
        annotate.annotate_file_tree(revtree_1, 'a',
 
422
                                    to_file=to_file, branch=tree1.branch)
 
423
 
 
424
        sio = BytesIO()
 
425
        to_file = codecs.getwriter('ascii')(sio, 'replace')
 
426
        annotate.annotate_file_tree(revtree_2, 'b',
 
427
                                    to_file=to_file, branch=tree1.branch)
 
428
        self.assertEqualDiff(b'2   p?rez   | bye\n', sio.getvalue())
 
429
 
 
430
        # test now with unicode file-like
 
431
        to_file = StringIOWithEncoding()
 
432
        annotate.annotate_file_tree(revtree_2, 'b',
 
433
                                    to_file=to_file, branch=tree1.branch)
 
434
        self.assertContainsRe(u'2   p\xe9rez   | bye\n', to_file.getvalue())
431
435
 
432
436
    def test_annotate_author_or_committer(self):
433
437
        tree1 = self.make_branch_and_tree('tree1')
434
438
 
435
 
        self.build_tree_contents([('tree1/a', 'hello')])
436
 
        tree1.add(['a'], ['a-id'])
437
 
        tree1.commit('a', rev_id='rev-1',
 
439
        self.build_tree_contents([('tree1/a', b'hello')])
 
440
        tree1.add(['a'], [b'a-id'])
 
441
        tree1.commit('a', rev_id=b'rev-1',
438
442
                     committer='Committer <committer@example.com>',
439
443
                     timestamp=1166046000.00, timezone=0)
440
444
 
441
 
        self.build_tree_contents([('tree1/b', 'bye')])
442
 
        tree1.add(['b'], ['b-id'])
443
 
        tree1.commit('b', rev_id='rev-2',
 
445
        self.build_tree_contents([('tree1/b', b'bye')])
 
446
        tree1.add(['b'], [b'b-id'])
 
447
        tree1.commit('b', rev_id=b'rev-2',
444
448
                     committer='Committer <committer@example.com>',
445
449
                     authors=['Author <author@example.com>'],
446
450
                     timestamp=1166046000.00, timezone=0)
447
451
 
448
452
        tree1.lock_read()
449
453
        self.addCleanup(tree1.unlock)
450
 
        to_file = StringIO()
451
 
        annotate.annotate_file(tree1.branch, 'rev-1', 'a-id', to_file=to_file)
452
 
        self.assertEqual('1   committ | hello\n', to_file.getvalue())
453
 
 
454
 
        to_file = StringIO()
455
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
456
 
        self.assertEqual('2   author@ | bye\n', to_file.getvalue())
 
454
 
 
455
        self.assertBranchAnnotate('1   committ | hello\n', tree1.branch,
 
456
                                  'a', b'rev-1')
 
457
 
 
458
        self.assertBranchAnnotate('2   author@ | bye\n', tree1.branch,
 
459
                                  'b', b'rev-2')
457
460
 
458
461
 
459
462
class TestReannotate(tests.TestCase):
461
464
    def annotateEqual(self, expected, parents, newlines, revision_id,
462
465
                      blocks=None):
463
466
        annotate_list = list(annotate.reannotate(parents, newlines,
464
 
                             revision_id, blocks))
 
467
                                                 revision_id, blocks))
465
468
        self.assertEqual(len(expected), len(annotate_list))
466
469
        for e, a in zip(expected, annotate_list):
467
470
            self.assertEqual(e, a)
468
471
 
469
472
    def test_reannotate(self):
470
 
        self.annotateEqual(parent_1, [parent_1], new_1, 'blahblah')
471
 
        self.annotateEqual(expected_2_1, [parent_2], new_1, 'blahblah')
 
473
        self.annotateEqual(parent_1, [parent_1], new_1, b'blahblah')
 
474
        self.annotateEqual(expected_2_1, [parent_2], new_1, b'blahblah')
472
475
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2,
473
 
                           'blahblah')
 
476
                           b'blahblah')
474
477
 
475
478
    def test_reannotate_no_parents(self):
476
 
        self.annotateEqual(expected_1, [], new_1, 'blahblah')
 
479
        self.annotateEqual(expected_1, [], new_1, b'blahblah')
477
480
 
478
481
    def test_reannotate_left_matching_blocks(self):
479
482
        """Ensure that left_matching_blocks has an impact.
481
484
        In this case, the annotation is ambiguous, so the hint isn't actually
482
485
        lying.
483
486
        """
484
 
        parent = [('rev1', 'a\n')]
485
 
        new_text = ['a\n', 'a\n']
 
487
        parent = [(b'rev1', b'a\n')]
 
488
        new_text = [b'a\n', b'a\n']
486
489
        blocks = [(0, 0, 1), (1, 2, 0)]
487
 
        self.annotateEqual([('rev1', 'a\n'), ('rev2', 'a\n')], [parent],
488
 
                           new_text, 'rev2', blocks)
 
490
        self.annotateEqual([(b'rev1', b'a\n'), (b'rev2', b'a\n')], [parent],
 
491
                           new_text, b'rev2', blocks)
489
492
        blocks = [(0, 1, 1), (1, 2, 0)]
490
 
        self.annotateEqual([('rev2', 'a\n'), ('rev1', 'a\n')], [parent],
491
 
                           new_text, 'rev2', blocks)
 
493
        self.annotateEqual([(b'rev2', b'a\n'), (b'rev1', b'a\n')], [parent],
 
494
                           new_text, b'rev2', blocks)