/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: John Arbash Meinel
  • Date: 2007-03-20 00:49:11 UTC
  • mto: This revision was merged to the branch mainline in revision 2366.
  • Revision ID: john@arbash-meinel.com-20070320004911-0qajqnddr3rf9r2e
Simplify the test even further....
Basically, if you have a file deleted as removed, and then you unversion its directory
it deletes all records in the dirblock, not realizing that some of them might
already be marked as removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Whitebox tests for annotate functionality."""
18
18
 
19
 
import codecs
20
19
from cStringIO import StringIO
21
20
 
22
21
from bzrlib import (
87
86
e
88
87
""".splitlines(True)
89
88
 
90
 
expected_1 = annotation("""\
91
 
blahblah a
92
 
blahblah b
93
 
blahblah c
94
 
blahblah d
95
 
blahblah e
96
 
""")
97
 
 
98
89
 
99
90
new_2 = """\
100
91
a
107
98
""".splitlines(True)
108
99
 
109
100
 
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
 
#  |\|
119
 
#  C D  # line should 'converge' and say A
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
153
 
rev-A alt-second
154
 
rev-base third
155
 
rev-D fourth-D
156
 
""")
157
 
 
158
 
duplicate_E = annotation("""\
159
 
rev-base first
160
 
rev-A alt-second
161
 
rev-base third
162
 
rev-E fourth-E
163
 
""")
164
 
 
165
 
 
166
101
class TestAnnotate(tests.TestCaseWithTransport):
167
102
 
168
103
    def create_merged_trees(self):
176
111
         |
177
112
        rev-3
178
113
        """
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')),
185
 
            ], timestamp=1166046000.00, timezone=0, committer="joe@foo.com")
186
 
        builder.build_snapshot('rev-2', ['rev-1'], [
187
 
            ('modify', ('a-id', 'first\nsecond\n')),
188
 
            ], timestamp=1166046001.00, timezone=0, committer="joe@foo.com")
189
 
        builder.build_snapshot('rev-1_1_1', ['rev-1'], [
190
 
            ('modify', ('a-id', 'first\nthird\n')),
191
 
            ], timestamp=1166046002.00, timezone=0, committer="barry@foo.com")
192
 
        builder.build_snapshot('rev-3', ['rev-2', 'rev-1_1_1'], [
193
 
            ('modify', ('a-id', 'first\nsecond\nthird\n')),
194
 
            ], timestamp=1166046003.00, timezone=0, committer="sal@foo.com")
195
 
        return builder
 
114
 
 
115
        tree1 = self.make_branch_and_tree('tree1')
 
116
        self.build_tree_contents([('tree1/a', 'first\n')])
 
117
        tree1.add(['a'], ['a-id'])
 
118
        tree1.commit('a', rev_id='rev-1',
 
119
                     committer="joe@foo.com",
 
120
                     timestamp=1166046000.00, timezone=0)
 
121
 
 
122
        tree2 = tree1.bzrdir.clone('tree2').open_workingtree()
 
123
 
 
124
        self.build_tree_contents([('tree1/a', 'first\nsecond\n')])
 
125
        tree1.commit('b', rev_id='rev-2',
 
126
                     committer='joe@foo.com',
 
127
                     timestamp=1166046001.00, timezone=0)
 
128
 
 
129
        self.build_tree_contents([('tree2/a', 'first\nthird\n')])
 
130
        tree2.commit('c', rev_id='rev-1_1_1',
 
131
                     committer="barry@foo.com",
 
132
                     timestamp=1166046002.00, timezone=0)
 
133
 
 
134
        num_conflicts = tree1.merge_from_branch(tree2.branch)
 
135
        self.assertEqual(1, num_conflicts)
 
136
 
 
137
        self.build_tree_contents([('tree1/a',
 
138
                                 'first\nsecond\nthird\n')])
 
139
        tree1.set_conflicts(conflicts.ConflictList())
 
140
        tree1.commit('merge 2', rev_id='rev-3',
 
141
                     committer='sal@foo.com',
 
142
                     timestamp=1166046003.00, timezone=0)
 
143
        return tree1, tree2
196
144
 
197
145
    def create_deeply_merged_trees(self):
198
146
        """Create some trees with a more complex merge history.
203
151
         |      |          |
204
152
         +------+          |
205
153
         |      |          |
206
 
        rev-3  rev-1_1_2  rev-1_2_1 ------+
 
154
        rev-3  rev-1_1_2  rev-1_1_1_1_1 --+
207
155
         |      |          |              |
208
156
         +------+          |              |
209
157
         |                 |              |
210
 
        rev-4             rev-1_2_2  rev-1_3_1
 
158
        rev-4             rev-1_1_1_1_2  rev-1_1_1_1_1_1_1
211
159
         |                 |              |
212
160
         +-----------------+              |
213
161
         |                                |
217
165
         |
218
166
        rev-6
219
167
        """
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')),
225
 
            ], timestamp=1166046003.00, timezone=0, committer="jerry@foo.com")
226
 
        builder.build_snapshot('rev-1_2_2', ['rev-1_2_1'], [],
227
 
            timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
228
 
        builder.build_snapshot('rev-5', ['rev-4', 'rev-1_2_2'], [
229
 
            ('modify', ('a-id', 'first\nsecond\nthird\nfourth\n')),
230
 
            ], timestamp=1166046004.00, timezone=0, committer="jerry@foo.com")
231
 
        builder.build_snapshot('rev-1_3_1', ['rev-1_2_1'], [
232
 
            ('modify', ('a-id', 'first\nthird\nfourth\nfifth\nsixth\n')),
233
 
            ], timestamp=1166046005.00, timezone=0, committer="george@foo.com")
234
 
        builder.build_snapshot('rev-6', ['rev-5', 'rev-1_3_1'], [
235
 
            ('modify', ('a-id',
236
 
                        'first\nsecond\nthird\nfourth\nfifth\nsixth\n')),
237
 
            ])
238
 
        return builder
239
 
 
240
 
    def create_duplicate_lines_tree(self):
241
 
        builder = self.make_branch_builder('branch')
242
 
        builder.start_series()
243
 
        self.addCleanup(builder.finish_series)
244
 
        base_text = ''.join(l for r, l in duplicate_base)
245
 
        a_text = ''.join(l for r, l in duplicate_A)
246
 
        b_text = ''.join(l for r, l in duplicate_B)
247
 
        c_text = ''.join(l for r, l in duplicate_C)
248
 
        d_text = ''.join(l for r, l in duplicate_D)
249
 
        e_text = ''.join(l for r, l in duplicate_E)
250
 
        builder.build_snapshot('rev-base', None, [
251
 
            ('add', ('', 'root-id', 'directory', None)),
252
 
            ('add', ('file', 'file-id', 'file', base_text)),
253
 
            ])
254
 
        builder.build_snapshot('rev-A', ['rev-base'], [
255
 
            ('modify', ('file-id', a_text))])
256
 
        builder.build_snapshot('rev-B', ['rev-base'], [
257
 
            ('modify', ('file-id', b_text))])
258
 
        builder.build_snapshot('rev-C', ['rev-A'], [
259
 
            ('modify', ('file-id', c_text))])
260
 
        builder.build_snapshot('rev-D', ['rev-B', 'rev-A'], [
261
 
            ('modify', ('file-id', d_text))])
262
 
        builder.build_snapshot('rev-E', ['rev-C', 'rev-D'], [
263
 
            ('modify', ('file-id', e_text))])
264
 
        return builder
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):
276
 
        # XXX: Should this be a per_repository test?
277
 
        builder = self.create_duplicate_lines_tree()
278
 
        repo = builder.get_branch().repository
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')
 
168
        tree1, tree2 = self.create_merged_trees()
 
169
 
 
170
        tree3 = tree2.bzrdir.clone('tree3').open_workingtree()
 
171
 
 
172
        tree2.commit('noop', rev_id='rev-1_1_2')
 
173
        self.assertEqual(0, tree1.merge_from_branch(tree2.branch))
 
174
        tree1.commit('noop merge', rev_id='rev-4')
 
175
 
 
176
        self.build_tree_contents([('tree3/a', 'first\nthird\nfourth\n')])
 
177
        tree3.commit('four', rev_id='rev-1_1_1_1_1',
 
178
                     committer='jerry@foo.com',
 
179
                     timestamp=1166046003.00, timezone=0)
 
180
 
 
181
        tree4 = tree3.bzrdir.clone('tree4').open_workingtree()
 
182
 
 
183
        tree3.commit('noop', rev_id='rev-1_1_1_1_2',
 
184
                     committer='jerry@foo.com',
 
185
                     timestamp=1166046004.00, timezone=0)
 
186
        self.assertEqual(0, tree1.merge_from_branch(tree3.branch))
 
187
        tree1.commit('merge four', rev_id='rev-5')
 
188
 
 
189
        self.build_tree_contents([('tree4/a',
 
190
                                   'first\nthird\nfourth\nfifth\nsixth\n')])
 
191
        tree4.commit('five and six', rev_id='rev-1_1_1_1_1_1_1',
 
192
                     committer='george@foo.com',
 
193
                     timestamp=1166046005.00, timezone=0)
 
194
        self.assertEqual(0, tree1.merge_from_branch(tree4.branch))
 
195
        tree1.commit('merge five and six', rev_id='rev-6')
 
196
        return tree1
287
197
 
288
198
    def test_annotate_shows_dotted_revnos(self):
289
 
        builder = self.create_merged_trees()
 
199
        tree1, tree2 = self.create_merged_trees()
290
200
 
291
201
        sio = StringIO()
292
 
        annotate.annotate_file(builder.get_branch(), 'rev-3', 'a-id',
 
202
        annotate.annotate_file(tree1.branch, 'rev-3', 'a-id',
293
203
                               to_file=sio)
294
204
        self.assertEqualDiff('1     joe@foo | first\n'
295
205
                             '2     joe@foo | second\n'
298
208
 
299
209
    def test_annotate_limits_dotted_revnos(self):
300
210
        """Annotate should limit dotted revnos to a depth of 12"""
301
 
        builder = self.create_deeply_merged_trees()
 
211
        tree1 = self.create_deeply_merged_trees()
302
212
 
303
213
        sio = StringIO()
304
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
 
214
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
305
215
                               to_file=sio, verbose=False, full=False)
306
 
        self.assertEqualDiff('1     joe@foo | first\n'
307
 
                             '2     joe@foo | second\n'
308
 
                             '1.1.1 barry@f | third\n'
309
 
                             '1.2.1 jerry@f | fourth\n'
310
 
                             '1.3.1 george@ | fifth\n'
311
 
                             '              | sixth\n',
 
216
        self.assertEqualDiff('1            joe@foo | first\n'
 
217
                             '2            joe@foo | second\n'
 
218
                             '1.1.1        barry@f | third\n'
 
219
                             '1.1.1.1.1    jerry@f | fourth\n'
 
220
                             '1.1.1.1.1.1> george@ | fifth\n'
 
221
                             '                     | sixth\n',
312
222
                             sio.getvalue())
313
223
 
314
224
        sio = StringIO()
315
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
 
225
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
316
226
                               to_file=sio, verbose=False, full=True)
317
 
        self.assertEqualDiff('1     joe@foo | first\n'
318
 
                             '2     joe@foo | second\n'
319
 
                             '1.1.1 barry@f | third\n'
320
 
                             '1.2.1 jerry@f | fourth\n'
321
 
                             '1.3.1 george@ | fifth\n'
322
 
                             '1.3.1 george@ | sixth\n',
 
227
        self.assertEqualDiff('1            joe@foo | first\n'
 
228
                             '2            joe@foo | second\n'
 
229
                             '1.1.1        barry@f | third\n'
 
230
                             '1.1.1.1.1    jerry@f | fourth\n'
 
231
                             '1.1.1.1.1.1> george@ | fifth\n'
 
232
                             '1.1.1.1.1.1> george@ | sixth\n',
323
233
                             sio.getvalue())
324
234
 
325
235
        # verbose=True shows everything, the full revno, user id, and date
326
236
        sio = StringIO()
327
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
 
237
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
328
238
                               to_file=sio, verbose=True, full=False)
329
 
        self.assertEqualDiff('1     joe@foo.com    20061213 | first\n'
330
 
                             '2     joe@foo.com    20061213 | second\n'
331
 
                             '1.1.1 barry@foo.com  20061213 | third\n'
332
 
                             '1.2.1 jerry@foo.com  20061213 | fourth\n'
333
 
                             '1.3.1 george@foo.com 20061213 | fifth\n'
334
 
                             '                              | sixth\n',
 
239
        self.assertEqualDiff('1             joe@foo.com    20061213 | first\n'
 
240
                             '2             joe@foo.com    20061213 | second\n'
 
241
                             '1.1.1         barry@foo.com  20061213 | third\n'
 
242
                             '1.1.1.1.1     jerry@foo.com  20061213 | fourth\n'
 
243
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | fifth\n'
 
244
                             '                                      | sixth\n',
335
245
                             sio.getvalue())
336
246
 
337
247
        sio = StringIO()
338
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
 
248
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
339
249
                               to_file=sio, verbose=True, full=True)
340
 
        self.assertEqualDiff('1     joe@foo.com    20061213 | first\n'
341
 
                             '2     joe@foo.com    20061213 | second\n'
342
 
                             '1.1.1 barry@foo.com  20061213 | third\n'
343
 
                             '1.2.1 jerry@foo.com  20061213 | fourth\n'
344
 
                             '1.3.1 george@foo.com 20061213 | fifth\n'
345
 
                             '1.3.1 george@foo.com 20061213 | sixth\n',
 
250
        self.assertEqualDiff('1             joe@foo.com    20061213 | first\n'
 
251
                             '2             joe@foo.com    20061213 | second\n'
 
252
                             '1.1.1         barry@foo.com  20061213 | third\n'
 
253
                             '1.1.1.1.1     jerry@foo.com  20061213 | fourth\n'
 
254
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | fifth\n'
 
255
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | sixth\n',
346
256
                             sio.getvalue())
347
257
 
348
258
    def test_annotate_uses_branch_context(self):
351
261
        When annotating a non-mainline revision, the annotation should still
352
262
        use dotted revnos from the mainline.
353
263
        """
354
 
        builder = self.create_deeply_merged_trees()
 
264
        tree1 = self.create_deeply_merged_trees()
355
265
 
356
266
        sio = StringIO()
357
 
        annotate.annotate_file(builder.get_branch(), 'rev-1_3_1', 'a-id',
 
267
        annotate.annotate_file(tree1.branch, 'rev-1_1_1_1_1_1_1', 'a-id',
358
268
                               to_file=sio, verbose=False, full=False)
359
 
        self.assertEqualDiff('1     joe@foo | first\n'
360
 
                             '1.1.1 barry@f | third\n'
361
 
                             '1.2.1 jerry@f | fourth\n'
362
 
                             '1.3.1 george@ | fifth\n'
363
 
                             '              | sixth\n',
 
269
        self.assertEqualDiff('1            joe@foo | first\n'
 
270
                             '1.1.1        barry@f | third\n'
 
271
                             '1.1.1.1.1    jerry@f | fourth\n'
 
272
                             '1.1.1.1.1.1> george@ | fifth\n'
 
273
                             '                     | sixth\n',
364
274
                             sio.getvalue())
365
275
 
366
276
    def test_annotate_show_ids(self):
367
 
        builder = self.create_deeply_merged_trees()
 
277
        tree1 = self.create_deeply_merged_trees()
368
278
 
369
279
        sio = StringIO()
370
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
 
280
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
371
281
                               to_file=sio, show_ids=True, full=False)
372
282
 
373
283
        # It looks better with real revision ids :)
374
 
        self.assertEqualDiff('    rev-1 | first\n'
375
 
                             '    rev-2 | second\n'
376
 
                             'rev-1_1_1 | third\n'
377
 
                             'rev-1_2_1 | fourth\n'
378
 
                             'rev-1_3_1 | fifth\n'
379
 
                             '          | sixth\n',
 
284
        self.assertEqualDiff('            rev-1 | first\n'
 
285
                             '            rev-2 | second\n'
 
286
                             '        rev-1_1_1 | third\n'
 
287
                             '    rev-1_1_1_1_1 | fourth\n'
 
288
                             'rev-1_1_1_1_1_1_1 | fifth\n'
 
289
                             '                  | sixth\n',
380
290
                             sio.getvalue())
381
291
 
382
292
        sio = StringIO()
383
 
        annotate.annotate_file(builder.get_branch(), 'rev-6', 'a-id',
 
293
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
384
294
                               to_file=sio, show_ids=True, full=True)
385
295
 
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',
 
296
        self.assertEqualDiff('            rev-1 | first\n'
 
297
                             '            rev-2 | second\n'
 
298
                             '        rev-1_1_1 | third\n'
 
299
                             '    rev-1_1_1_1_1 | fourth\n'
 
300
                             'rev-1_1_1_1_1_1_1 | fifth\n'
 
301
                             'rev-1_1_1_1_1_1_1 | sixth\n',
392
302
                             sio.getvalue())
393
303
 
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
 
 
409
 
        tree1.lock_read()
410
 
        self.addCleanup(tree1.unlock)
411
 
        # this passes if no exception is raised
412
 
        to_file = StringIO()
413
 
        annotate.annotate_file(tree1.branch, 'rev-1', 'a-id', to_file=to_file)
414
 
 
415
 
        sio = StringIO()
416
 
        to_file = codecs.getwriter('ascii')(sio)
417
 
        to_file.encoding = 'ascii' # codecs does not set it
418
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
419
 
        self.assertEqualDiff('2   p?rez   | bye\n', sio.getvalue())
420
 
 
421
 
        # test now with to_file.encoding = None
422
 
        to_file = tests.StringIOWrapper()
423
 
        to_file.encoding = None
424
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
425
 
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
426
 
 
427
 
        # and when it does not exist
428
 
        to_file = StringIO()
429
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
430
 
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
431
 
 
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>',
445
 
                     authors=['Author <author@example.com>'],
446
 
                     timestamp=1166046000.00, timezone=0)
447
 
 
448
 
        tree1.lock_read()
449
 
        self.addCleanup(tree1.unlock)
450
 
        to_file = StringIO()
451
 
        annotate.annotate_file(tree1.branch, 'rev-1', 'a-id', to_file=to_file)
452
 
        self.assertEqual('1   committ | hello\n', to_file.getvalue())
453
 
 
454
 
        to_file = StringIO()
455
 
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
456
 
        self.assertEqual('2   author@ | bye\n', to_file.getvalue())
457
 
 
458
304
 
459
305
class TestReannotate(tests.TestCase):
460
306
 
461
 
    def annotateEqual(self, expected, parents, newlines, revision_id,
462
 
                      blocks=None):
 
307
    def annotateEqual(self, expected, parents, newlines, revision_id):
463
308
        annotate_list = list(annotate.reannotate(parents, newlines,
464
 
                             revision_id, blocks))
 
309
                             revision_id))
465
310
        self.assertEqual(len(expected), len(annotate_list))
466
311
        for e, a in zip(expected, annotate_list):
467
312
            self.assertEqual(e, a)
469
314
    def test_reannotate(self):
470
315
        self.annotateEqual(parent_1, [parent_1], new_1, 'blahblah')
471
316
        self.annotateEqual(expected_2_1, [parent_2], new_1, 'blahblah')
472
 
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2,
 
317
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2, 
473
318
                           'blahblah')
474
 
 
475
 
    def test_reannotate_no_parents(self):
476
 
        self.annotateEqual(expected_1, [], new_1, 'blahblah')
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)