~bzr-pqm/bzr/bzr.dev

5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2006-2009, 2011 Canonical Ltd
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
16
17
"""Whitebox tests for annotate functionality."""
18
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
19
import codecs
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
20
from cStringIO import StringIO
21
22
from bzrlib import (
23
    annotate,
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
24
    symbol_versioning,
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
25
    tests,
26
    )
27
28
1551.9.19 by Aaron Bentley
Merge from bzr.dev
29
def annotation(text):
30
    return [tuple(l.split(' ', 1)) for l in text.splitlines(True)]
31
32
33
parent_1 = annotation("""\
34
rev1 a
35
rev2 b
36
rev3 c
37
rev4 d
38
rev5 e
39
""")
40
41
42
parent_2 = annotation("""\
43
rev1 a
44
rev3 c
45
rev4 d
46
rev6 f
47
rev7 e
48
rev8 h
49
""")
50
51
52
expected_2_1 = annotation("""\
53
rev1 a
54
blahblah b
55
rev3 c
56
rev4 d
57
rev7 e
58
""")
59
60
61
# a: in both, same value, kept
62
# b: in 1, kept
63
# c: in both, same value, kept
64
# d: in both, same value, kept
65
# e: 1 and 2 disagree, so it goes to blahblah
66
# f: in 2, but not in new, so ignored
67
# g: not in 1 or 2, so it goes to blahblah
68
# h: only in parent 2, so 2 gets it
69
expected_1_2_2 = annotation("""\
70
rev1 a
71
rev2 b
72
rev3 c
73
rev4 d
74
blahblah e
75
blahblah g
76
rev8 h
77
""")
78
79
80
new_1 = """\
81
a
82
b
83
c
84
d
85
e
86
""".splitlines(True)
87
2770.1.1 by Aaron Bentley
Initial implmentation of plain knit annotation
88
expected_1 = annotation("""\
89
blahblah a
90
blahblah b
91
blahblah c
92
blahblah d
93
blahblah e
94
""")
95
1551.9.19 by Aaron Bentley
Merge from bzr.dev
96
97
new_2 = """\
98
a
99
b
100
c
101
d
102
e
103
g
104
h
105
""".splitlines(True)
106
107
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
108
# For the 'duplicate' series, both sides introduce the same change, which then
109
# gets merged around. The last-modified should properly reflect this.
110
# We always change the fourth line so that the file is properly tracked as
111
# being modified in each revision. In reality, this probably would happen over
112
# many revisions, and it would be a different line that changes.
113
# BASE
114
#  |\
115
#  A B  # line should be annotated as new for A and B
116
#  |\|
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
117
#  C D  # line should 'converge' and say A
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
118
#  |/
119
#  E    # D should supersede A and stay as D (not become E because C references
120
#         A)
121
duplicate_base = annotation("""\
122
rev-base first
123
rev-base second
124
rev-base third
125
rev-base fourth-base
126
""")
127
128
duplicate_A = annotation("""\
129
rev-base first
130
rev-A alt-second
131
rev-base third
132
rev-A fourth-A
133
""")
134
135
duplicate_B = annotation("""\
136
rev-base first
137
rev-B alt-second
138
rev-base third
139
rev-B fourth-B
140
""")
141
142
duplicate_C = annotation("""\
143
rev-base first
144
rev-A alt-second
145
rev-base third
146
rev-C fourth-C
147
""")
148
149
duplicate_D = annotation("""\
150
rev-base first
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
151
rev-A alt-second
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
152
rev-base third
153
rev-D fourth-D
154
""")
155
156
duplicate_E = annotation("""\
157
rev-base first
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
158
rev-A alt-second
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
159
rev-base third
160
rev-E fourth-E
161
""")
162
163
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
164
class TestAnnotate(tests.TestCaseWithTransport):
165
166
    def create_merged_trees(self):
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
167
        """create 2 trees with merges between them.
168
169
        rev-1 --+
170
         |      |
171
        rev-2  rev-1_1_1
172
         |      |
173
         +------+
174
         |
175
        rev-3
176
        """
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
177
        builder = self.make_branch_builder('branch')
178
        builder.start_series()
179
        self.addCleanup(builder.finish_series)
180
        builder.build_snapshot('rev-1', None, [
181
            ('add', ('', 'root-id', 'directory', None)),
182
            ('add', ('a', 'a-id', 'file', 'first\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
183
            ], timestamp=1166046000.00, timezone=0, committer="joe@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
184
        builder.build_snapshot('rev-2', ['rev-1'], [
185
            ('modify', ('a-id', 'first\nsecond\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
186
            ], timestamp=1166046001.00, timezone=0, committer="joe@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
187
        builder.build_snapshot('rev-1_1_1', ['rev-1'], [
188
            ('modify', ('a-id', 'first\nthird\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
189
            ], timestamp=1166046002.00, timezone=0, committer="barry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
190
        builder.build_snapshot('rev-3', ['rev-2', 'rev-1_1_1'], [
191
            ('modify', ('a-id', 'first\nsecond\nthird\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
192
            ], timestamp=1166046003.00, timezone=0, committer="sal@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
193
        return builder
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
194
195
    def create_deeply_merged_trees(self):
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
196
        """Create some trees with a more complex merge history.
197
198
        rev-1 --+
199
         |      |
200
        rev-2  rev-1_1_1 --+
201
         |      |          |
202
         +------+          |
203
         |      |          |
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
204
        rev-3  rev-1_1_2  rev-1_2_1 ------+
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
205
         |      |          |              |
206
         +------+          |              |
207
         |                 |              |
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
208
        rev-4             rev-1_2_2  rev-1_3_1
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
209
         |                 |              |
210
         +-----------------+              |
211
         |                                |
212
        rev-5                             |
213
         |                                |
214
         +--------------------------------+
215
         |
216
        rev-6
217
        """
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
218
        builder = self.create_merged_trees()
219
        builder.build_snapshot('rev-1_1_2', ['rev-1_1_1'], [])
220
        builder.build_snapshot('rev-4', ['rev-3', 'rev-1_1_2'], [])
221
        builder.build_snapshot('rev-1_2_1', ['rev-1_1_1'], [
222
            ('modify', ('a-id', 'first\nthird\nfourth\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
223
            ], timestamp=1166046003.00, timezone=0, committer="jerry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
224
        builder.build_snapshot('rev-1_2_2', ['rev-1_2_1'], [],
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
225
            timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
226
        builder.build_snapshot('rev-5', ['rev-4', 'rev-1_2_2'], [
227
            ('modify', ('a-id', 'first\nsecond\nthird\nfourth\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
228
            ], timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
229
        builder.build_snapshot('rev-1_3_1', ['rev-1_2_1'], [
230
            ('modify', ('a-id', 'first\nthird\nfourth\nfifth\nsixth\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
231
            ], timestamp=1166046005.00, timezone=0, committer="george@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
232
        builder.build_snapshot('rev-6', ['rev-5', 'rev-1_3_1'], [
233
            ('modify', ('a-id',
234
                        'first\nsecond\nthird\nfourth\nfifth\nsixth\n')),
235
            ])
236
        return builder
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
237
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
238
    def create_duplicate_lines_tree(self):
4454.3.25 by John Arbash Meinel
Use BranchBuilder for duplicate_lines_tree
239
        builder = self.make_branch_builder('branch')
240
        builder.start_series()
241
        self.addCleanup(builder.finish_series)
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
242
        base_text = ''.join(l for r, l in duplicate_base)
243
        a_text = ''.join(l for r, l in duplicate_A)
244
        b_text = ''.join(l for r, l in duplicate_B)
245
        c_text = ''.join(l for r, l in duplicate_C)
246
        d_text = ''.join(l for r, l in duplicate_D)
247
        e_text = ''.join(l for r, l in duplicate_E)
4454.3.25 by John Arbash Meinel
Use BranchBuilder for duplicate_lines_tree
248
        builder.build_snapshot('rev-base', None, [
249
            ('add', ('', 'root-id', 'directory', None)),
250
            ('add', ('file', 'file-id', 'file', base_text)),
251
            ])
252
        builder.build_snapshot('rev-A', ['rev-base'], [
253
            ('modify', ('file-id', a_text))])
254
        builder.build_snapshot('rev-B', ['rev-base'], [
255
            ('modify', ('file-id', b_text))])
256
        builder.build_snapshot('rev-C', ['rev-A'], [
257
            ('modify', ('file-id', c_text))])
258
        builder.build_snapshot('rev-D', ['rev-B', 'rev-A'], [
259
            ('modify', ('file-id', d_text))])
260
        builder.build_snapshot('rev-E', ['rev-C', 'rev-D'], [
261
            ('modify', ('file-id', e_text))])
262
        return builder
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
263
5815.3.7 by Jelmer Vernooij
Factor out assertAnnotateEqualDiff.
264
    def assertAnnotateEqualDiff(self, actual, expected):
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
265
        if actual != expected:
266
            # Create an easier to understand diff when the lines don't actually
267
            # match
268
            self.assertEqualDiff(''.join('\t'.join(l) for l in expected),
269
                                 ''.join('\t'.join(l) for l in actual))
270
5815.3.8 by Jelmer Vernooij
Add convenience method for testing annotate_file_revision_tree.
271
    def assertBranchAnnotate(self, expected, branch, file_id, revision_id,
272
            verbose=False, full=False, show_ids=False):
273
        tree = branch.repository.revision_tree(revision_id)
274
        to_file = StringIO()
5815.3.14 by Jelmer Vernooij
Kill annotate_file_revision_tree() in favor annotate_file_tree().
275
        annotate.annotate_file_tree(tree, file_id, to_file,
5815.3.8 by Jelmer Vernooij
Add convenience method for testing annotate_file_revision_tree.
276
            verbose=verbose, full=full, show_ids=show_ids, branch=branch)
277
        self.assertAnnotateEqualDiff(to_file.getvalue(), expected)
278
5815.3.7 by Jelmer Vernooij
Factor out assertAnnotateEqualDiff.
279
    def assertRepoAnnotate(self, expected, repo, file_id, revision_id):
280
        """Assert that the revision is properly annotated."""
281
        actual = list(repo.revision_tree(revision_id).annotate_iter(file_id))
282
        self.assertAnnotateEqualDiff(actual, expected)
283
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
284
    def test_annotate_duplicate_lines(self):
3689.1.4 by John Arbash Meinel
Doc strings that reference repository_implementations
285
        # XXX: Should this be a per_repository test?
4454.3.25 by John Arbash Meinel
Use BranchBuilder for duplicate_lines_tree
286
        builder = self.create_duplicate_lines_tree()
287
        repo = builder.get_branch().repository
3224.1.4 by John Arbash Meinel
Add a *failing* test to expose why we need better handling when a line is introduced on two sides of a merge.
288
        repo.lock_read()
289
        self.addCleanup(repo.unlock)
290
        self.assertRepoAnnotate(duplicate_base, repo, 'file-id', 'rev-base')
291
        self.assertRepoAnnotate(duplicate_A, repo, 'file-id', 'rev-A')
292
        self.assertRepoAnnotate(duplicate_B, repo, 'file-id', 'rev-B')
293
        self.assertRepoAnnotate(duplicate_C, repo, 'file-id', 'rev-C')
294
        self.assertRepoAnnotate(duplicate_D, repo, 'file-id', 'rev-D')
295
        self.assertRepoAnnotate(duplicate_E, repo, 'file-id', 'rev-E')
296
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
297
    def test_annotate_shows_dotted_revnos(self):
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
298
        builder = self.create_merged_trees()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
299
5815.3.8 by Jelmer Vernooij
Add convenience method for testing annotate_file_revision_tree.
300
        self.assertBranchAnnotate('1     joe@foo | first\n'
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
301
                                  '2     joe@foo | second\n'
302
                                  '1.1.1 barry@f | third\n',
303
                                  builder.get_branch(), 'a-id', 'rev-3')
304
305
    def test_annotate_file(self):
306
        builder = self.create_merged_trees()
307
308
        to_file = StringIO()
309
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
310
            annotate.annotate_file, builder.get_branch(),
311
                'rev-3', 'a-id', to_file=to_file)
312
313
        self.assertAnnotateEqualDiff('1     joe@foo | first\n'
314
                                     '2     joe@foo | second\n'
315
                                     '1.1.1 barry@f | third\n',
316
                                     to_file.getvalue())
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
317
318
    def test_annotate_limits_dotted_revnos(self):
319
        """Annotate should limit dotted revnos to a depth of 12"""
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
320
        builder = self.create_deeply_merged_trees()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
321
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
322
        self.assertBranchAnnotate('1     joe@foo | first\n'
323
                                  '2     joe@foo | second\n'
324
                                  '1.1.1 barry@f | third\n'
325
                                  '1.2.1 jerry@f | fourth\n'
326
                                  '1.3.1 george@ | fifth\n'
327
                                  '              | sixth\n',
328
                                  builder.get_branch(), 'a-id', 'rev-6',
329
                                  verbose=False, full=False)
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
330
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
331
        self.assertBranchAnnotate('1     joe@foo | first\n'
332
                                  '2     joe@foo | second\n'
333
                                  '1.1.1 barry@f | third\n'
334
                                  '1.2.1 jerry@f | fourth\n'
335
                                  '1.3.1 george@ | fifth\n'
336
                                  '1.3.1 george@ | sixth\n',
337
                                  builder.get_branch(), 'a-id', 'rev-6',
338
                                  verbose=False, full=True)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
339
340
        # verbose=True shows everything, the full revno, user id, and date
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
341
        self.assertBranchAnnotate('1     joe@foo.com    20061213 | first\n'
342
                                  '2     joe@foo.com    20061213 | second\n'
343
                                  '1.1.1 barry@foo.com  20061213 | third\n'
344
                                  '1.2.1 jerry@foo.com  20061213 | fourth\n'
345
                                  '1.3.1 george@foo.com 20061213 | fifth\n'
346
                                  '                              | sixth\n',
347
                                  builder.get_branch(), 'a-id', 'rev-6',
348
                                  verbose=True, full=False)
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
349
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
350
        self.assertBranchAnnotate('1     joe@foo.com    20061213 | first\n'
351
                                  '2     joe@foo.com    20061213 | second\n'
352
                                  '1.1.1 barry@foo.com  20061213 | third\n'
353
                                  '1.2.1 jerry@foo.com  20061213 | fourth\n'
354
                                  '1.3.1 george@foo.com 20061213 | fifth\n'
355
                                  '1.3.1 george@foo.com 20061213 | sixth\n',
356
                                  builder.get_branch(), 'a-id', 'rev-6',
357
                                  verbose=True, full=True)
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
358
359
    def test_annotate_uses_branch_context(self):
360
        """Dotted revnos should use the Branch context.
361
362
        When annotating a non-mainline revision, the annotation should still
363
        use dotted revnos from the mainline.
364
        """
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
365
        builder = self.create_deeply_merged_trees()
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
366
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
367
        self.assertBranchAnnotate('1     joe@foo | first\n'
368
                                  '1.1.1 barry@f | third\n'
369
                                  '1.2.1 jerry@f | fourth\n'
370
                                  '1.3.1 george@ | fifth\n'
371
                                  '              | sixth\n',
372
                                  builder.get_branch(), 'a-id', 'rev-1_3_1',
373
                                  verbose=False, full=False)
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
374
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
375
    def test_annotate_show_ids(self):
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
376
        builder = self.create_deeply_merged_trees()
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
377
378
        # It looks better with real revision ids :)
5815.3.9 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
379
        self.assertBranchAnnotate('    rev-1 | first\n'
380
                                  '    rev-2 | second\n'
381
                                  'rev-1_1_1 | third\n'
382
                                  'rev-1_2_1 | fourth\n'
383
                                  'rev-1_3_1 | fifth\n'
384
                                  '          | sixth\n',
385
                                  builder.get_branch(), 'a-id', 'rev-6',
386
                                  show_ids=True, full=False)
387
388
        self.assertBranchAnnotate('    rev-1 | first\n'
389
                                  '    rev-2 | second\n'
390
                                  'rev-1_1_1 | third\n'
391
                                  'rev-1_2_1 | fourth\n'
392
                                  'rev-1_3_1 | fifth\n'
393
                                  'rev-1_3_1 | sixth\n',
394
                                  builder.get_branch(), 'a-id', 'rev-6',
395
                                  show_ids=True, full=True)
1551.9.19 by Aaron Bentley
Merge from bzr.dev
396
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
397
    def test_annotate_unicode_author(self):
398
        tree1 = self.make_branch_and_tree('tree1')
399
400
        self.build_tree_contents([('tree1/a', 'adi\xc3\xb3s')])
401
        tree1.add(['a'], ['a-id'])
402
        tree1.commit('a', rev_id='rev-1',
403
                     committer=u'Pepe P\xe9rez <pperez@ejemplo.com>',
404
                     timestamp=1166046000.00, timezone=0)
405
406
        self.build_tree_contents([('tree1/b', 'bye')])
407
        tree1.add(['b'], ['b-id'])
408
        tree1.commit('b', rev_id='rev-2',
409
                     committer=u'p\xe9rez',
410
                     timestamp=1166046000.00, timezone=0)
411
3010.1.1 by Robert Collins
Lock the tree's used to test annotate_file, and add a docstring for annotate_file explaining its needs.
412
        tree1.lock_read()
413
        self.addCleanup(tree1.unlock)
5815.3.10 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
414
415
        revtree_1 = tree1.branch.repository.revision_tree('rev-1')
416
        revtree_2 = tree1.branch.repository.revision_tree('rev-2')
417
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
418
        # this passes if no exception is raised
419
        to_file = StringIO()
5815.3.14 by Jelmer Vernooij
Kill annotate_file_revision_tree() in favor annotate_file_tree().
420
        annotate.annotate_file_tree(revtree_1, 'a-id',
5815.3.10 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
421
            to_file=to_file, branch=tree1.branch)
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
422
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
423
        sio = StringIO()
424
        to_file = codecs.getwriter('ascii')(sio)
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
425
        to_file.encoding = 'ascii' # codecs does not set it
5815.3.14 by Jelmer Vernooij
Kill annotate_file_revision_tree() in favor annotate_file_tree().
426
        annotate.annotate_file_tree(revtree_2, 'b-id',
5815.3.10 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
427
            to_file=to_file, branch=tree1.branch)
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
428
        self.assertEqualDiff('2   p?rez   | bye\n', sio.getvalue())
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
429
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
430
        # test now with to_file.encoding = None
431
        to_file = tests.StringIOWrapper()
432
        to_file.encoding = None
5815.3.14 by Jelmer Vernooij
Kill annotate_file_revision_tree() in favor annotate_file_tree().
433
        annotate.annotate_file_tree(revtree_2, 'b-id',
5815.3.10 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
434
            to_file=to_file, branch=tree1.branch)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
435
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
436
437
        # and when it does not exist
438
        to_file = StringIO()
5815.3.14 by Jelmer Vernooij
Kill annotate_file_revision_tree() in favor annotate_file_tree().
439
        annotate.annotate_file_tree(revtree_2, 'b-id',
5815.3.10 by Jelmer Vernooij
Convert more tests to use annotate_file_revision_tree.
440
            to_file=to_file, branch=tree1.branch)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
441
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
442
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
443
    def test_annotate_author_or_committer(self):
444
        tree1 = self.make_branch_and_tree('tree1')
445
446
        self.build_tree_contents([('tree1/a', 'hello')])
447
        tree1.add(['a'], ['a-id'])
448
        tree1.commit('a', rev_id='rev-1',
449
                     committer='Committer <committer@example.com>',
450
                     timestamp=1166046000.00, timezone=0)
451
452
        self.build_tree_contents([('tree1/b', 'bye')])
453
        tree1.add(['b'], ['b-id'])
454
        tree1.commit('b', rev_id='rev-2',
455
                     committer='Committer <committer@example.com>',
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
456
                     authors=['Author <author@example.com>'],
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
457
                     timestamp=1166046000.00, timezone=0)
458
3010.1.1 by Robert Collins
Lock the tree's used to test annotate_file, and add a docstring for annotate_file explaining its needs.
459
        tree1.lock_read()
460
        self.addCleanup(tree1.unlock)
5815.3.11 by Jelmer Vernooij
Remove last use of deprecated method.
461
462
        self.assertBranchAnnotate('1   committ | hello\n', tree1.branch,
463
            'a-id', 'rev-1')
464
465
        to_file = StringIO()
466
        self.assertBranchAnnotate('2   author@ | bye\n', tree1.branch,
467
            'b-id', 'rev-2')
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
468
1551.9.19 by Aaron Bentley
Merge from bzr.dev
469
470
class TestReannotate(tests.TestCase):
471
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
472
    def annotateEqual(self, expected, parents, newlines, revision_id,
473
                      blocks=None):
1551.9.19 by Aaron Bentley
Merge from bzr.dev
474
        annotate_list = list(annotate.reannotate(parents, newlines,
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
475
                             revision_id, blocks))
1551.9.19 by Aaron Bentley
Merge from bzr.dev
476
        self.assertEqual(len(expected), len(annotate_list))
477
        for e, a in zip(expected, annotate_list):
478
            self.assertEqual(e, a)
479
480
    def test_reannotate(self):
481
        self.annotateEqual(parent_1, [parent_1], new_1, 'blahblah')
482
        self.annotateEqual(expected_2_1, [parent_2], new_1, 'blahblah')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
483
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2,
1551.9.19 by Aaron Bentley
Merge from bzr.dev
484
                           'blahblah')
2770.1.1 by Aaron Bentley
Initial implmentation of plain knit annotation
485
486
    def test_reannotate_no_parents(self):
487
        self.annotateEqual(expected_1, [], new_1, 'blahblah')
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
488
489
    def test_reannotate_left_matching_blocks(self):
490
        """Ensure that left_matching_blocks has an impact.
491
492
        In this case, the annotation is ambiguous, so the hint isn't actually
493
        lying.
494
        """
495
        parent = [('rev1', 'a\n')]
496
        new_text = ['a\n', 'a\n']
497
        blocks = [(0, 0, 1), (1, 2, 0)]
498
        self.annotateEqual([('rev1', 'a\n'), ('rev2', 'a\n')], [parent],
499
                           new_text, 'rev2', blocks)
500
        blocks = [(0, 1, 1), (1, 2, 0)]
501
        self.annotateEqual([('rev2', 'a\n'), ('rev1', 'a\n')], [parent],
502
                           new_text, 'rev2', blocks)