~bzr-pqm/bzr/bzr.dev

2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
1
# Copyright (C) 2006 Canonical Ltd
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,
24
    conflicts,
25
    errors,
26
    tests,
27
    trace,
28
    )
29
30
1551.9.19 by Aaron Bentley
Merge from bzr.dev
31
def annotation(text):
32
    return [tuple(l.split(' ', 1)) for l in text.splitlines(True)]
33
34
35
parent_1 = annotation("""\
36
rev1 a
37
rev2 b
38
rev3 c
39
rev4 d
40
rev5 e
41
""")
42
43
44
parent_2 = annotation("""\
45
rev1 a
46
rev3 c
47
rev4 d
48
rev6 f
49
rev7 e
50
rev8 h
51
""")
52
53
54
expected_2_1 = annotation("""\
55
rev1 a
56
blahblah b
57
rev3 c
58
rev4 d
59
rev7 e
60
""")
61
62
63
# a: in both, same value, kept
64
# b: in 1, kept
65
# c: in both, same value, kept
66
# d: in both, same value, kept
67
# e: 1 and 2 disagree, so it goes to blahblah
68
# f: in 2, but not in new, so ignored
69
# g: not in 1 or 2, so it goes to blahblah
70
# h: only in parent 2, so 2 gets it
71
expected_1_2_2 = annotation("""\
72
rev1 a
73
rev2 b
74
rev3 c
75
rev4 d
76
blahblah e
77
blahblah g
78
rev8 h
79
""")
80
81
82
new_1 = """\
83
a
84
b
85
c
86
d
87
e
88
""".splitlines(True)
89
2770.1.1 by Aaron Bentley
Initial implmentation of plain knit annotation
90
expected_1 = annotation("""\
91
blahblah a
92
blahblah b
93
blahblah c
94
blahblah d
95
blahblah e
96
""")
97
1551.9.19 by Aaron Bentley
Merge from bzr.dev
98
99
new_2 = """\
100
a
101
b
102
c
103
d
104
e
105
g
106
h
107
""".splitlines(True)
108
109
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.
110
# For the 'duplicate' series, both sides introduce the same change, which then
111
# gets merged around. The last-modified should properly reflect this.
112
# We always change the fourth line so that the file is properly tracked as
113
# being modified in each revision. In reality, this probably would happen over
114
# many revisions, and it would be a different line that changes.
115
# BASE
116
#  |\
117
#  A B  # line should be annotated as new for A and B
118
#  |\|
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
119
#  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.
120
#  |/
121
#  E    # D should supersede A and stay as D (not become E because C references
122
#         A)
123
duplicate_base = annotation("""\
124
rev-base first
125
rev-base second
126
rev-base third
127
rev-base fourth-base
128
""")
129
130
duplicate_A = annotation("""\
131
rev-base first
132
rev-A alt-second
133
rev-base third
134
rev-A fourth-A
135
""")
136
137
duplicate_B = annotation("""\
138
rev-base first
139
rev-B alt-second
140
rev-base third
141
rev-B fourth-B
142
""")
143
144
duplicate_C = annotation("""\
145
rev-base first
146
rev-A alt-second
147
rev-base third
148
rev-C fourth-C
149
""")
150
151
duplicate_D = annotation("""\
152
rev-base first
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
153
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.
154
rev-base third
155
rev-D fourth-D
156
""")
157
158
duplicate_E = annotation("""\
159
rev-base first
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
160
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.
161
rev-base third
162
rev-E fourth-E
163
""")
164
165
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
166
class TestAnnotate(tests.TestCaseWithTransport):
167
168
    def create_merged_trees(self):
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
169
        """create 2 trees with merges between them.
170
171
        rev-1 --+
172
         |      |
173
        rev-2  rev-1_1_1
174
         |      |
175
         +------+
176
         |
177
        rev-3
178
        """
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
179
        builder = self.make_branch_builder('branch')
180
        builder.start_series()
181
        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')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
185
            ], timestamp=1166046000.00, timezone=0, committer="joe@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
186
        builder.build_snapshot('rev-2', ['rev-1'], [
187
            ('modify', ('a-id', 'first\nsecond\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
188
            ], timestamp=1166046001.00, timezone=0, committer="joe@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
189
        builder.build_snapshot('rev-1_1_1', ['rev-1'], [
190
            ('modify', ('a-id', 'first\nthird\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
191
            ], timestamp=1166046002.00, timezone=0, committer="barry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
192
        builder.build_snapshot('rev-3', ['rev-2', 'rev-1_1_1'], [
193
            ('modify', ('a-id', 'first\nsecond\nthird\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
194
            ], timestamp=1166046003.00, timezone=0, committer="sal@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
195
        return builder
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
196
197
    def create_deeply_merged_trees(self):
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
198
        """Create some trees with a more complex merge history.
199
200
        rev-1 --+
201
         |      |
202
        rev-2  rev-1_1_1 --+
203
         |      |          |
204
         +------+          |
205
         |      |          |
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
206
        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.
207
         |      |          |              |
208
         +------+          |              |
209
         |                 |              |
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
210
        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.
211
         |                 |              |
212
         +-----------------+              |
213
         |                                |
214
        rev-5                             |
215
         |                                |
216
         +--------------------------------+
217
         |
218
        rev-6
219
        """
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
220
        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')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
225
            ], timestamp=1166046003.00, timezone=0, committer="jerry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
226
        builder.build_snapshot('rev-1_2_2', ['rev-1_2_1'], [],
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
227
            timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
228
        builder.build_snapshot('rev-5', ['rev-4', 'rev-1_2_2'], [
229
            ('modify', ('a-id', 'first\nsecond\nthird\nfourth\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
230
            ], timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
231
        builder.build_snapshot('rev-1_3_1', ['rev-1_2_1'], [
232
            ('modify', ('a-id', 'first\nthird\nfourth\nfifth\nsixth\n')),
4523.2.1 by Vincent Ladeuil
Fix TZ-dependent tests.
233
            ], timestamp=1166046005.00, timezone=0, committer="george@foo.com")
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
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
            ])
238
        return builder
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
239
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.
240
    def create_duplicate_lines_tree(self):
4454.3.25 by John Arbash Meinel
Use BranchBuilder for duplicate_lines_tree
241
        builder = self.make_branch_builder('branch')
242
        builder.start_series()
243
        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.
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)
4454.3.25 by John Arbash Meinel
Use BranchBuilder for duplicate_lines_tree
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))])
264
        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.
265
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))
269
        if actual != expected:
270
            # Create an easier to understand diff when the lines don't actually
271
            # match
272
            self.assertEqualDiff(''.join('\t'.join(l) for l in expected),
273
                                 ''.join('\t'.join(l) for l in actual))
274
275
    def test_annotate_duplicate_lines(self):
3689.1.4 by John Arbash Meinel
Doc strings that reference repository_implementations
276
        # XXX: Should this be a per_repository test?
4454.3.25 by John Arbash Meinel
Use BranchBuilder for duplicate_lines_tree
277
        builder = self.create_duplicate_lines_tree()
278
        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.
279
        repo.lock_read()
280
        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')
287
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
288
    def test_annotate_shows_dotted_revnos(self):
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
289
        builder = self.create_merged_trees()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
290
291
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
292
        annotate.annotate_file(builder.get_branch(), 'rev-3', 'a-id',
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
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())
298
299
    def test_annotate_limits_dotted_revnos(self):
300
        """Annotate should limit dotted revnos to a depth of 12"""
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
301
        builder = self.create_deeply_merged_trees()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
302
303
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
304
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
305
                               to_file=sio, verbose=False, full=False)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
312
                             sio.getvalue())
313
314
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
315
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
316
                               to_file=sio, verbose=False, full=True)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
323
                             sio.getvalue())
324
325
        # verbose=True shows everything, the full revno, user id, and date
326
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
327
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
328
                               to_file=sio, verbose=True, full=False)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
335
                             sio.getvalue())
336
337
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
338
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
339
                               to_file=sio, verbose=True, full=True)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
346
                             sio.getvalue())
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
347
348
    def test_annotate_uses_branch_context(self):
349
        """Dotted revnos should use the Branch context.
350
351
        When annotating a non-mainline revision, the annotation should still
352
        use dotted revnos from the mainline.
353
        """
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
354
        builder = self.create_deeply_merged_trees()
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
355
356
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
357
        annotate.annotate_file(builder.get_branch(), 'rev-1_3_1', 'a-id',
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
358
                               to_file=sio, verbose=False, full=False)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
364
                             sio.getvalue())
365
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
366
    def test_annotate_show_ids(self):
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
367
        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
368
369
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
370
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
371
                               to_file=sio, show_ids=True, full=False)
372
373
        # It looks better with real revision ids :)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
380
                             sio.getvalue())
381
382
        sio = StringIO()
4454.3.24 by John Arbash Meinel
update BranchBuilder to support 'committer'
383
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
384
                               to_file=sio, show_ids=True, full=True)
385
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
392
                             sio.getvalue())
1551.9.19 by Aaron Bentley
Merge from bzr.dev
393
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
394
    def test_annotate_unicode_author(self):
395
        tree1 = self.make_branch_and_tree('tree1')
396
397
        self.build_tree_contents([('tree1/a', 'adi\xc3\xb3s')])
398
        tree1.add(['a'], ['a-id'])
399
        tree1.commit('a', rev_id='rev-1',
400
                     committer=u'Pepe P\xe9rez <pperez@ejemplo.com>',
401
                     timestamp=1166046000.00, timezone=0)
402
403
        self.build_tree_contents([('tree1/b', 'bye')])
404
        tree1.add(['b'], ['b-id'])
405
        tree1.commit('b', rev_id='rev-2',
406
                     committer=u'p\xe9rez',
407
                     timestamp=1166046000.00, timezone=0)
408
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.
409
        tree1.lock_read()
410
        self.addCleanup(tree1.unlock)
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
411
        # this passes if no exception is raised
412
        to_file = StringIO()
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
413
        annotate.annotate_file(tree1.branch, 'rev-1', 'a-id', to_file=to_file)
414
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
415
        sio = StringIO()
416
        to_file = codecs.getwriter('ascii')(sio)
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
417
        to_file.encoding = 'ascii' # codecs does not set it
418
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
419
        self.assertEqualDiff('2   p?rez   | bye\n', sio.getvalue())
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
420
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
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)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
425
        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.
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)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
430
        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.
431
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
432
    def test_annotate_author_or_committer(self):
433
        tree1 = self.make_branch_and_tree('tree1')
434
435
        self.build_tree_contents([('tree1/a', 'hello')])
436
        tree1.add(['a'], ['a-id'])
437
        tree1.commit('a', rev_id='rev-1',
438
                     committer='Committer <committer@example.com>',
439
                     timestamp=1166046000.00, timezone=0)
440
441
        self.build_tree_contents([('tree1/b', 'bye')])
442
        tree1.add(['b'], ['b-id'])
443
        tree1.commit('b', rev_id='rev-2',
444
                     committer='Committer <committer@example.com>',
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
445
                     authors=['Author <author@example.com>'],
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
446
                     timestamp=1166046000.00, timezone=0)
447
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.
448
        tree1.lock_read()
449
        self.addCleanup(tree1.unlock)
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
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())
457
1551.9.19 by Aaron Bentley
Merge from bzr.dev
458
459
class TestReannotate(tests.TestCase):
460
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
461
    def annotateEqual(self, expected, parents, newlines, revision_id,
462
                      blocks=None):
1551.9.19 by Aaron Bentley
Merge from bzr.dev
463
        annotate_list = list(annotate.reannotate(parents, newlines,
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
464
                             revision_id, blocks))
1551.9.19 by Aaron Bentley
Merge from bzr.dev
465
        self.assertEqual(len(expected), len(annotate_list))
466
        for e, a in zip(expected, annotate_list):
467
            self.assertEqual(e, a)
468
469
    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')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
472
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2,
1551.9.19 by Aaron Bentley
Merge from bzr.dev
473
                           'blahblah')
2770.1.1 by Aaron Bentley
Initial implmentation of plain knit annotation
474
475
    def test_reannotate_no_parents(self):
476
        self.annotateEqual(expected_1, [], new_1, 'blahblah')
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
477
478
    def test_reannotate_left_matching_blocks(self):
479
        """Ensure that left_matching_blocks has an impact.
480
481
        In this case, the annotation is ambiguous, so the hint isn't actually
482
        lying.
483
        """
484
        parent = [('rev1', 'a\n')]
485
        new_text = ['a\n', 'a\n']
486
        blocks = [(0, 0, 1), (1, 2, 0)]
487
        self.annotateEqual([('rev1', 'a\n'), ('rev2', 'a\n')], [parent],
488
                           new_text, 'rev2', blocks)
489
        blocks = [(0, 1, 1), (1, 2, 0)]
490
        self.annotateEqual([('rev2', 'a\n'), ('rev1', 'a\n')], [parent],
491
                           new_text, 'rev2', blocks)