~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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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
        """
179
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
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',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
184
                     committer="joe@foo.com",
185
                     timestamp=1166046000.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
186
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
187
        tree2 = tree1.bzrdir.sprout('tree2').open_workingtree()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
188
189
        self.build_tree_contents([('tree1/a', 'first\nsecond\n')])
190
        tree1.commit('b', rev_id='rev-2',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
191
                     committer='joe@foo.com',
192
                     timestamp=1166046001.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
193
194
        self.build_tree_contents([('tree2/a', 'first\nthird\n')])
195
        tree2.commit('c', rev_id='rev-1_1_1',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
196
                     committer="barry@foo.com",
197
                     timestamp=1166046002.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
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',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
206
                     committer='sal@foo.com',
207
                     timestamp=1166046003.00, timezone=0)
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.
208
        tree1.lock_read()
209
        self.addCleanup(tree1.unlock)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
210
        return tree1, tree2
211
212
    def create_deeply_merged_trees(self):
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
213
        """Create some trees with a more complex merge history.
214
215
        rev-1 --+
216
         |      |
217
        rev-2  rev-1_1_1 --+
218
         |      |          |
219
         +------+          |
220
         |      |          |
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
221
        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.
222
         |      |          |              |
223
         +------+          |              |
224
         |                 |              |
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
225
        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.
226
         |                 |              |
227
         +-----------------+              |
228
         |                                |
229
        rev-5                             |
230
         |                                |
231
         +--------------------------------+
232
         |
233
        rev-6
234
        """
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
235
        tree1, tree2 = self.create_merged_trees()
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.
236
        tree1.unlock()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
237
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
238
        tree3 = tree2.bzrdir.sprout('tree3').open_workingtree()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
239
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
240
        tree2.commit('noop', rev_id='rev-1_1_2')
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
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')])
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
245
        tree3.commit('four', rev_id='rev-1_2_1',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
246
                     committer='jerry@foo.com',
247
                     timestamp=1166046003.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
248
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
249
        tree4 = tree3.bzrdir.sprout('tree4').open_workingtree()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
250
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
251
        tree3.commit('noop', rev_id='rev-1_2_2',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
252
                     committer='jerry@foo.com',
253
                     timestamp=1166046004.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
254
        self.assertEqual(0, tree1.merge_from_branch(tree3.branch))
255
        tree1.commit('merge four', rev_id='rev-5')
256
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
257
        self.build_tree_contents([('tree4/a',
258
                                   'first\nthird\nfourth\nfifth\nsixth\n')])
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
259
        tree4.commit('five and six', rev_id='rev-1_3_1',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
260
                     committer='george@foo.com',
261
                     timestamp=1166046005.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
262
        self.assertEqual(0, tree1.merge_from_branch(tree4.branch))
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
263
        tree1.commit('merge five and six', rev_id='rev-6')
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.
264
        tree1.lock_read()
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
265
        return tree1
266
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.
267
    def create_duplicate_lines_tree(self):
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')
3588.3.1 by John Arbash Meinel
Simple patch to the annotate logic to handle bug #232188
278
        tree2 = tree1.bzrdir.sprout('tree2').open_workingtree()
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
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))
302
        if actual != expected:
303
            # Create an easier to understand diff when the lines don't actually
304
            # match
305
            self.assertEqualDiff(''.join('\t'.join(l) for l in expected),
306
                                 ''.join('\t'.join(l) for l in actual))
307
308
    def test_annotate_duplicate_lines(self):
3689.1.4 by John Arbash Meinel
Doc strings that reference repository_implementations
309
        # XXX: Should this be a per_repository test?
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.
310
        tree1 = self.create_duplicate_lines_tree()
311
        repo = tree1.branch.repository
312
        repo.lock_read()
313
        self.addCleanup(repo.unlock)
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')
320
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
321
    def test_annotate_shows_dotted_revnos(self):
322
        tree1, tree2 = self.create_merged_trees()
323
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())
331
332
    def test_annotate_limits_dotted_revnos(self):
333
        """Annotate should limit dotted revnos to a depth of 12"""
334
        tree1 = self.create_deeply_merged_trees()
335
336
        sio = StringIO()
337
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
338
                               to_file=sio, verbose=False, full=False)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
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)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
356
                             sio.getvalue())
357
358
        # verbose=True shows everything, the full revno, user id, and date
359
        sio = StringIO()
360
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
361
                               to_file=sio, verbose=True, full=False)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
368
                             sio.getvalue())
369
370
        sio = StringIO()
371
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
372
                               to_file=sio, verbose=True, full=True)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
379
                             sio.getvalue())
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
380
381
    def test_annotate_uses_branch_context(self):
382
        """Dotted revnos should use the Branch context.
383
384
        When annotating a non-mainline revision, the annotation should still
385
        use dotted revnos from the mainline.
386
        """
387
        tree1 = self.create_deeply_merged_trees()
388
389
        sio = StringIO()
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
390
        annotate.annotate_file(tree1.branch, 'rev-1_3_1', 'a-id',
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
391
                               to_file=sio, verbose=False, full=False)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
397
                             sio.getvalue())
398
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
399
    def test_annotate_show_ids(self):
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)
405
406
        # It looks better with real revision ids :)
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
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
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
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',
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
425
                             sio.getvalue())
1551.9.19 by Aaron Bentley
Merge from bzr.dev
426
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
427
    def test_annotate_unicode_author(self):
428
        tree1 = self.make_branch_and_tree('tree1')
429
430
        self.build_tree_contents([('tree1/a', 'adi\xc3\xb3s')])
431
        tree1.add(['a'], ['a-id'])
432
        tree1.commit('a', rev_id='rev-1',
433
                     committer=u'Pepe P\xe9rez <pperez@ejemplo.com>',
434
                     timestamp=1166046000.00, timezone=0)
435
436
        self.build_tree_contents([('tree1/b', 'bye')])
437
        tree1.add(['b'], ['b-id'])
438
        tree1.commit('b', rev_id='rev-2',
439
                     committer=u'p\xe9rez',
440
                     timestamp=1166046000.00, timezone=0)
441
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.
442
        tree1.lock_read()
443
        self.addCleanup(tree1.unlock)
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
444
        # this passes if no exception is raised
445
        to_file = StringIO()
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
446
        annotate.annotate_file(tree1.branch, 'rev-1', 'a-id', to_file=to_file)
447
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
448
        sio = StringIO()
449
        to_file = codecs.getwriter('ascii')(sio)
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
450
        to_file.encoding = 'ascii' # codecs does not set it
451
        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.
452
        self.assertEqualDiff('2   p?rez   | bye\n', sio.getvalue())
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
453
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
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)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
458
        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.
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)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
463
        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.
464
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
465
    def test_annotate_author_or_committer(self):
466
        tree1 = self.make_branch_and_tree('tree1')
467
468
        self.build_tree_contents([('tree1/a', 'hello')])
469
        tree1.add(['a'], ['a-id'])
470
        tree1.commit('a', rev_id='rev-1',
471
                     committer='Committer <committer@example.com>',
472
                     timestamp=1166046000.00, timezone=0)
473
474
        self.build_tree_contents([('tree1/b', 'bye')])
475
        tree1.add(['b'], ['b-id'])
476
        tree1.commit('b', rev_id='rev-2',
477
                     committer='Committer <committer@example.com>',
478
                     author='Author <author@example.com>',
479
                     timestamp=1166046000.00, timezone=0)
480
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.
481
        tree1.lock_read()
482
        self.addCleanup(tree1.unlock)
2671.5.3 by Lukáš Lalinsky
Use the author name in annotate.
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())
490
1551.9.19 by Aaron Bentley
Merge from bzr.dev
491
492
class TestReannotate(tests.TestCase):
493
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
494
    def annotateEqual(self, expected, parents, newlines, revision_id,
495
                      blocks=None):
1551.9.19 by Aaron Bentley
Merge from bzr.dev
496
        annotate_list = list(annotate.reannotate(parents, newlines,
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
497
                             revision_id, blocks))
1551.9.19 by Aaron Bentley
Merge from bzr.dev
498
        self.assertEqual(len(expected), len(annotate_list))
499
        for e, a in zip(expected, annotate_list):
500
            self.assertEqual(e, a)
501
502
    def test_reannotate(self):
503
        self.annotateEqual(parent_1, [parent_1], new_1, 'blahblah')
504
        self.annotateEqual(expected_2_1, [parent_2], new_1, 'blahblah')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
505
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2,
1551.9.19 by Aaron Bentley
Merge from bzr.dev
506
                           'blahblah')
2770.1.1 by Aaron Bentley
Initial implmentation of plain knit annotation
507
508
    def test_reannotate_no_parents(self):
509
        self.annotateEqual(expected_1, [], new_1, 'blahblah')
2770.1.5 by Aaron Bentley
Clean up docs, test matching blocks for reannotate
510
511
    def test_reannotate_left_matching_blocks(self):
512
        """Ensure that left_matching_blocks has an impact.
513
514
        In this case, the annotation is ambiguous, so the hint isn't actually
515
        lying.
516
        """
517
        parent = [('rev1', 'a\n')]
518
        new_text = ['a\n', 'a\n']
519
        blocks = [(0, 0, 1), (1, 2, 0)]
520
        self.annotateEqual([('rev1', 'a\n'), ('rev2', 'a\n')], [parent],
521
                           new_text, 'rev2', blocks)
522
        blocks = [(0, 1, 1), (1, 2, 0)]
523
        self.annotateEqual([('rev2', 'a\n'), ('rev1', 'a\n')], [parent],
524
                           new_text, 'rev2', blocks)