~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testlog.py

Exclude more files from dumb-rsync upload

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
 
#
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
 
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
#
 
7
 
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
17
import os
18
18
from cStringIO import StringIO
19
19
 
20
 
from bzrlib import log
21
 
from bzrlib.tests import BzrTestBase, TestCaseWithTransport
22
 
from bzrlib.log import (show_log, 
23
 
                        get_view_revisions, 
24
 
                        LogFormatter, 
25
 
                        LongLogFormatter, 
26
 
                        ShortLogFormatter, 
27
 
                        LineLogFormatter)
 
20
from bzrlib.selftest import BzrTestBase, TestCaseInTempDir
 
21
from bzrlib.log import LogFormatter, show_log, LongLogFormatter
28
22
from bzrlib.branch import Branch
29
23
from bzrlib.errors import InvalidRevisionNumber
30
24
 
31
 
 
32
25
class _LogEntry(object):
33
26
    # should probably move into bzrlib.log?
34
27
    pass
46
39
    def __init__(self):
47
40
        super(LogCatcher, self).__init__(to_file=None)
48
41
        self.logs = []
49
 
 
 
42
        
 
43
        
50
44
    def show(self, revno, rev, delta):
51
45
        le = _LogEntry()
52
46
        le.revno = revno
55
49
        self.logs.append(le)
56
50
 
57
51
 
58
 
class SimpleLogTest(TestCaseWithTransport):
 
52
class SimpleLogTest(TestCaseInTempDir):
59
53
 
60
54
    def checkDelta(self, delta, **kw):
61
55
        """Check the filenames touched by a delta are as expected."""
63
57
            expected = kw.get(n, [])
64
58
 
65
59
            # tests are written with unix paths; fix them up for windows
66
 
            #if os.sep != '/':
67
 
            #    expected = [x.replace('/', os.sep) for x in expected]
 
60
            if os.sep != '/':
 
61
                expected = [x.replace('/', os.sep) for x in expected]
68
62
 
69
63
            # strip out only the path components
70
64
            got = [x[0] for x in getattr(delta, n)]
71
65
            self.assertEquals(expected, got)
72
66
 
73
67
    def test_cur_revno(self):
74
 
        wt = self.make_branch_and_tree('.')
75
 
        b = wt.branch
76
 
 
77
 
        lf = LogCatcher()
78
 
        wt.commit('empty commit')
 
68
        b = Branch('.', init=True)
 
69
 
 
70
        lf = LogCatcher()
 
71
        b.working_tree().commit('empty commit')
 
72
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
 
73
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
74
                          start_revision=2, end_revision=1) 
 
75
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
76
                          start_revision=1, end_revision=2) 
 
77
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
78
                          start_revision=0, end_revision=2) 
 
79
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
80
                          start_revision=1, end_revision=0) 
 
81
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
82
                          start_revision=-1, end_revision=1) 
 
83
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
84
                          start_revision=1, end_revision=-1) 
 
85
 
 
86
    def test_cur_revno(self):
 
87
        b = Branch.initialize('.')
 
88
 
 
89
        lf = LogCatcher()
 
90
        b.working_tree().commit('empty commit')
79
91
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
80
92
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
81
93
                          start_revision=2, end_revision=1) 
93
105
    def test_simple_log(self):
94
106
        eq = self.assertEquals
95
107
        
96
 
        wt = self.make_branch_and_tree('.')
97
 
        b = wt.branch
 
108
        b = Branch.initialize('.')
98
109
 
99
110
        lf = LogCatcher()
100
111
        show_log(b, lf)
101
112
        # no entries yet
102
113
        eq(lf.logs, [])
103
114
 
104
 
        wt.commit('empty commit')
 
115
        b.working_tree().commit('empty commit')
105
116
        lf = LogCatcher()
106
117
        show_log(b, lf, verbose=True)
107
118
        eq(len(lf.logs), 1)
108
 
        eq(lf.logs[0].revno, '1')
 
119
        eq(lf.logs[0].revno, 1)
109
120
        eq(lf.logs[0].rev.message, 'empty commit')
110
121
        d = lf.logs[0].delta
111
122
        self.log('log delta: %r' % d)
112
123
        self.checkDelta(d)
113
124
 
114
125
        self.build_tree(['hello'])
115
 
        wt.add('hello')
116
 
        wt.commit('add one file')
 
126
        b.add('hello')
 
127
        b.working_tree().commit('add one file')
117
128
 
118
129
        lf = StringIO()
119
130
        # log using regular thing
128
139
        eq(len(lf.logs), 2)
129
140
        self.log('log entries:')
130
141
        for logentry in lf.logs:
131
 
            self.log('%4s %s' % (logentry.revno, logentry.rev.message))
 
142
            self.log('%4d %s' % (logentry.revno, logentry.rev.message))
132
143
        
133
144
        # first one is most recent
134
145
        logentry = lf.logs[0]
135
 
        eq(logentry.revno, '2')
 
146
        eq(logentry.revno, 2)
136
147
        eq(logentry.rev.message, 'add one file')
137
148
        d = logentry.delta
138
149
        self.log('log 2 delta: %r' % d)
141
152
        # commit a log message with control characters
142
153
        msg = "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
143
154
        self.log("original commit message: %r", msg)
144
 
        wt.commit(msg)
 
155
        b.working_tree().commit(msg)
145
156
        lf = LogCatcher()
146
157
        show_log(b, lf, verbose=True)
147
158
        committed_msg = lf.logs[0].rev.message
156
167
        # valid XML 1.0 characters.
157
168
        msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
158
169
        self.log("original commit message: %r", msg)
159
 
        wt.commit(msg)
 
170
        b.working_tree().commit(msg)
160
171
        lf = LogCatcher()
161
172
        show_log(b, lf, verbose=True)
162
173
        committed_msg = lf.logs[0].rev.message
163
174
        self.log("escaped commit message: %r", committed_msg)
164
175
        self.assert_(msg == committed_msg)
165
 
 
166
 
    def test_trailing_newlines(self):
167
 
        wt = self.make_branch_and_tree('.')
168
 
        b = wt.branch
169
 
        b.nick='test'
170
 
        open('a', 'wb').write('hello moto\n')
171
 
        wt.add('a')
172
 
        wt.commit('simple log message', rev_id='a1'
173
 
                , timestamp=1132586655.459960938, timezone=-6*3600
174
 
                , committer='Joe Foo <joe@foo.com>')
175
 
        open('b', 'wb').write('goodbye\n')
176
 
        wt.add('b')
177
 
        wt.commit('multiline\nlog\nmessage\n', rev_id='a2'
178
 
                , timestamp=1132586842.411175966, timezone=-6*3600
179
 
                , committer='Joe Foo <joe@foo.com>')
180
 
 
181
 
        open('c', 'wb').write('just another manic monday\n')
182
 
        wt.add('c')
183
 
        wt.commit('single line with trailing newline\n', rev_id='a3'
184
 
                , timestamp=1132587176.835228920, timezone=-6*3600
185
 
                , committer = 'Joe Foo <joe@foo.com>')
186
 
 
187
 
        sio = StringIO()
188
 
        lf = ShortLogFormatter(to_file=sio)
189
 
        show_log(b, lf)
190
 
        self.assertEquals(sio.getvalue(), """\
191
 
    3 Joe Foo\t2005-11-21
192
 
      single line with trailing newline
193
 
 
194
 
    2 Joe Foo\t2005-11-21
195
 
      multiline
196
 
      log
197
 
      message
198
 
 
199
 
    1 Joe Foo\t2005-11-21
200
 
      simple log message
201
 
 
202
 
""")
203
 
 
204
 
        sio = StringIO()
205
 
        lf = LongLogFormatter(to_file=sio)
206
 
        show_log(b, lf)
207
 
        self.assertEquals(sio.getvalue(), """\
208
 
------------------------------------------------------------
209
 
revno: 3
210
 
committer: Joe Foo <joe@foo.com>
211
 
branch nick: test
212
 
timestamp: Mon 2005-11-21 09:32:56 -0600
213
 
message:
214
 
  single line with trailing newline
215
 
------------------------------------------------------------
216
 
revno: 2
217
 
committer: Joe Foo <joe@foo.com>
218
 
branch nick: test
219
 
timestamp: Mon 2005-11-21 09:27:22 -0600
220
 
message:
221
 
  multiline
222
 
  log
223
 
  message
224
 
------------------------------------------------------------
225
 
revno: 1
226
 
committer: Joe Foo <joe@foo.com>
227
 
branch nick: test
228
 
timestamp: Mon 2005-11-21 09:24:15 -0600
229
 
message:
230
 
  simple log message
231
 
""")
232
 
        
233
 
    def test_verbose_log(self):
234
 
        """Verbose log includes changed files
235
 
        
236
 
        bug #4676
237
 
        """
238
 
        wt = self.make_branch_and_tree('.')
239
 
        b = wt.branch
240
 
        self.build_tree(['a'])
241
 
        wt.add('a')
242
 
        # XXX: why does a longer nick show up?
243
 
        b.nick = 'test_verbose_log'
244
 
        wt.commit(message='add a', 
245
 
                  timestamp=1132711707, 
246
 
                  timezone=36000,
247
 
                  committer='Lorem Ipsum <test@example.com>')
248
 
        logfile = file('out.tmp', 'w+')
249
 
        formatter = LongLogFormatter(to_file=logfile)
250
 
        show_log(b, formatter, verbose=True)
251
 
        logfile.flush()
252
 
        logfile.seek(0)
253
 
        log_contents = logfile.read()
254
 
        self.assertEqualDiff(log_contents, '''\
255
 
------------------------------------------------------------
256
 
revno: 1
257
 
committer: Lorem Ipsum <test@example.com>
258
 
branch nick: test_verbose_log
259
 
timestamp: Wed 2005-11-23 12:08:27 +1000
260
 
message:
261
 
  add a
262
 
added:
263
 
  a
264
 
''')
265
 
 
266
 
    def test_line_log(self):
267
 
        """Line log should show revno
268
 
        
269
 
        bug #5162
270
 
        """
271
 
        wt = self.make_branch_and_tree('.')
272
 
        b = wt.branch
273
 
        self.build_tree(['a'])
274
 
        wt.add('a')
275
 
        b.nick = 'test-line-log'
276
 
        wt.commit(message='add a', 
277
 
                  timestamp=1132711707, 
278
 
                  timezone=36000,
279
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
280
 
        logfile = file('out.tmp', 'w+')
281
 
        formatter = LineLogFormatter(to_file=logfile)
282
 
        show_log(b, formatter)
283
 
        logfile.flush()
284
 
        logfile.seek(0)
285
 
        log_contents = logfile.read()
286
 
        self.assertEqualDiff(log_contents, '1: Line-Log-Formatte... 2005-11-23 add a\n')
287
 
 
288
 
    def make_tree_with_commits(self):
289
 
        """Create a tree with well-known revision ids"""
290
 
        wt = self.make_branch_and_tree('tree1')
291
 
        wt.commit('commit one', rev_id='1')
292
 
        wt.commit('commit two', rev_id='2')
293
 
        wt.commit('commit three', rev_id='3')
294
 
        mainline_revs = [None, '1', '2', '3']
295
 
        rev_nos = {'1': 1, '2': 2, '3': 3}
296
 
        return mainline_revs, rev_nos, wt
297
 
 
298
 
    def make_tree_with_merges(self):
299
 
        """Create a tree with well-known revision ids and a merge"""
300
 
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
301
 
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
302
 
        tree2.commit('four-a', rev_id='4a')
303
 
        wt.merge_from_branch(tree2.branch)
304
 
        wt.commit('four-b', rev_id='4b')
305
 
        mainline_revs.append('4b')
306
 
        rev_nos['4b'] = 4
307
 
        # 4a: 3.1.1
308
 
        return mainline_revs, rev_nos, wt
309
 
 
310
 
    def make_tree_with_many_merges(self):
311
 
        """Create a tree with well-known revision ids"""
312
 
        wt = self.make_branch_and_tree('tree1')
313
 
        wt.commit('commit one', rev_id='1')
314
 
        wt.commit('commit two', rev_id='2')
315
 
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
316
 
        tree3.commit('commit three a', rev_id='3a')
317
 
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
318
 
        tree2.merge_from_branch(tree3.branch)
319
 
        tree2.commit('commit three b', rev_id='3b')
320
 
        wt.merge_from_branch(tree2.branch)
321
 
        wt.commit('commit three c', rev_id='3c')
322
 
        tree2.commit('four-a', rev_id='4a')
323
 
        wt.merge_from_branch(tree2.branch)
324
 
        wt.commit('four-b', rev_id='4b')
325
 
        mainline_revs = [None, '1', '2', '3c', '4b']
326
 
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
327
 
        full_rev_nos_for_reference = {
328
 
            '1': '1',
329
 
            '2': '2',
330
 
            '3a': '2.2.1', #first commit tree 3
331
 
            '3b': '2.1.1', # first commit tree 2
332
 
            '3c': '3', #merges 3b to main
333
 
            '4a': '2.1.2', # second commit tree 2
334
 
            '4b': '4', # merges 4a to main
335
 
            }
336
 
        return mainline_revs, rev_nos, wt
337
 
 
338
 
    def test_get_view_revisions_forward(self):
339
 
        """Test the get_view_revisions method"""
340
 
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
341
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
342
 
                                            'forward'))
343
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
344
 
            revisions)
345
 
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
346
 
                                             'forward', include_merges=False))
347
 
        self.assertEqual(revisions, revisions2)
348
 
 
349
 
    def test_get_view_revisions_reverse(self):
350
 
        """Test the get_view_revisions with reverse"""
351
 
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
352
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
353
 
                                            'reverse'))
354
 
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
355
 
            revisions)
356
 
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
357
 
                                             'reverse', include_merges=False))
358
 
        self.assertEqual(revisions, revisions2)
359
 
 
360
 
    def test_get_view_revisions_merge(self):
361
 
        """Test get_view_revisions when there are merges"""
362
 
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
363
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
364
 
                                            'forward'))
365
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
366
 
            ('4b', '4', 0), ('4a', '3.1.1', 1)],
367
 
            revisions)
368
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
369
 
                                             'forward', include_merges=False))
370
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
371
 
            ('4b', '4', 0)],
372
 
            revisions)
373
 
 
374
 
    def test_get_view_revisions_merge_reverse(self):
375
 
        """Test get_view_revisions in reverse when there are merges"""
376
 
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
377
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
378
 
                                            'reverse'))
379
 
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
380
 
            ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
381
 
            revisions)
382
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
383
 
                                             'reverse', include_merges=False))
384
 
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
385
 
            ('1', '1', 0)],
386
 
            revisions)
387
 
 
388
 
    def test_get_view_revisions_merge2(self):
389
 
        """Test get_view_revisions when there are merges"""
390
 
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
391
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
392
 
                                            'forward'))
393
 
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
394
 
            ('3a', '2.2.1', 1), ('3b', '2.1.1', 1), ('4b', '4', 0),
395
 
            ('4a', '2.1.2', 1)]
396
 
        self.assertEqual(expected, revisions)
397
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
398
 
                                             'forward', include_merges=False))
399
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
400
 
            ('4b', '4', 0)],
401
 
            revisions)
402
 
 
403
 
 
404
 
class TestGetRevisionsTouchingFileID(TestCaseWithTransport):
405
 
 
406
 
    def create_tree_with_single_merge(self):
407
 
        """Create a branch with a moderate layout.
408
 
 
409
 
        The revision graph looks like:
410
 
 
411
 
           A
412
 
           |\
413
 
           B C
414
 
           |/
415
 
           D
416
 
 
417
 
        In this graph, A introduced files f1 and f2 and f3.
418
 
        B modifies f1 and f3, and C modifies f2 and f3.
419
 
        D merges the changes from B and C and resolves the conflict for f3.
420
 
        """
421
 
        # TODO: jam 20070218 This seems like it could really be done
422
 
        #       with make_branch_and_memory_tree() if we could just
423
 
        #       create the content of those files.
424
 
        # TODO: jam 20070218 Another alternative is that we would really
425
 
        #       like to only create this tree 1 time for all tests that
426
 
        #       use it. Since 'log' only uses the tree in a readonly
427
 
        #       fashion, it seems a shame to regenerate an identical
428
 
        #       tree for each test.
429
 
        tree = self.make_branch_and_tree('tree')
430
 
        tree.lock_write()
431
 
        self.addCleanup(tree.unlock)
432
 
 
433
 
        self.build_tree_contents([('tree/f1', 'A\n'),
434
 
                                  ('tree/f2', 'A\n'),
435
 
                                  ('tree/f3', 'A\n'),
436
 
                                 ])
437
 
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
438
 
        tree.commit('A', rev_id='A')
439
 
 
440
 
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
441
 
                                  ('tree/f3', 'A\nC\n'),
442
 
                                 ])
443
 
        tree.commit('C', rev_id='C')
444
 
        # Revert back to A to build the other history.
445
 
        tree.set_last_revision('A')
446
 
        tree.branch.set_last_revision_info(1, 'A')
447
 
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
448
 
                                  ('tree/f2', 'A\n'),
449
 
                                  ('tree/f3', 'A\nB\n'),
450
 
                                 ])
451
 
        tree.commit('B', rev_id='B')
452
 
        tree.set_parent_ids(['B', 'C'])
453
 
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
454
 
                                  ('tree/f2', 'A\nC\n'),
455
 
                                  ('tree/f3', 'A\nB\nC\n'),
456
 
                                 ])
457
 
        tree.commit('D', rev_id='D')
458
 
 
459
 
        # Switch to a read lock for this tree.
460
 
        # We still have addCleanup(unlock)
461
 
        tree.unlock()
462
 
        tree.lock_read()
463
 
        return tree
464
 
 
465
 
    def test_tree_with_single_merge(self):
466
 
        """Make sure the tree layout is correct."""
467
 
        tree = self.create_tree_with_single_merge()
468
 
        rev_A_tree = tree.branch.repository.revision_tree('A')
469
 
        rev_B_tree = tree.branch.repository.revision_tree('B')
470
 
 
471
 
        f1_changed = (u'f1', 'f1-id', 'file', True, False)
472
 
        f2_changed = (u'f2', 'f2-id', 'file', True, False)
473
 
        f3_changed = (u'f3', 'f3-id', 'file', True, False)
474
 
 
475
 
        delta = rev_B_tree.changes_from(rev_A_tree)
476
 
        self.assertEqual([f1_changed, f3_changed], delta.modified)
477
 
        self.assertEqual([], delta.renamed)
478
 
        self.assertEqual([], delta.added)
479
 
        self.assertEqual([], delta.removed)
480
 
 
481
 
        rev_C_tree = tree.branch.repository.revision_tree('C')
482
 
        delta = rev_C_tree.changes_from(rev_A_tree)
483
 
        self.assertEqual([f2_changed, f3_changed], delta.modified)
484
 
        self.assertEqual([], delta.renamed)
485
 
        self.assertEqual([], delta.added)
486
 
        self.assertEqual([], delta.removed)
487
 
 
488
 
        rev_D_tree = tree.branch.repository.revision_tree('D')
489
 
        delta = rev_D_tree.changes_from(rev_B_tree)
490
 
        self.assertEqual([f2_changed, f3_changed], delta.modified)
491
 
        self.assertEqual([], delta.renamed)
492
 
        self.assertEqual([], delta.added)
493
 
        self.assertEqual([], delta.removed)
494
 
 
495
 
        delta = rev_D_tree.changes_from(rev_C_tree)
496
 
        self.assertEqual([f1_changed, f3_changed], delta.modified)
497
 
        self.assertEqual([], delta.renamed)
498
 
        self.assertEqual([], delta.added)
499
 
        self.assertEqual([], delta.removed)
500
 
 
501
 
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
502
 
        """Make sure _get_revisions_touching_file_id returns the right values.
503
 
 
504
 
        Get the return value from _get_revisions_touching_file_id and make
505
 
        sure they are correct.
506
 
        """
507
 
        # The api for _get_revisions_touching_file_id is a little crazy,
508
 
        # So we do the setup here.
509
 
        mainline = tree.branch.revision_history()
510
 
        mainline.insert(0, None)
511
 
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
512
 
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
513
 
                                                'reverse', True)
514
 
        actual_revs = log._get_revisions_touching_file_id(tree.branch, file_id,
515
 
                                                          mainline,
516
 
                                                          view_revs_iter)
517
 
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
518
 
 
519
 
    def test_file_id_f1(self):
520
 
        tree = self.create_tree_with_single_merge()
521
 
        # f1 should be marked as modified by revisions A and B
522
 
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
523
 
 
524
 
    def test_file_id_f2(self):
525
 
        tree = self.create_tree_with_single_merge()
526
 
        # f2 should be marked as modified by revisions A, C, and D
527
 
        # because D merged the changes from C.
528
 
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
529
 
 
530
 
    def test_file_id_f3(self):
531
 
        tree = self.create_tree_with_single_merge()
532
 
        # f3 should be marked as modified by revisions A, B, C, and D
533
 
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])