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

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-04-09 20:23:07 UTC
  • mfrom: (4265.1.4 bbc-merge)
  • Revision ID: pqm@pqm.ubuntu.com-20090409202307-n0depb16qepoe21o
(jam) Change _fetch_uses_deltas = False for CHK repos until we can
        write a better fix.

Show diffs side-by-side

added added

removed removed

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