~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_log.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-09-20 02:40:52 UTC
  • mfrom: (2835.1.1 ianc-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20070920024052-y2l7r5o00zrpnr73
No longer propagate index differences automatically (Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
 
 
 
3
#
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
6
6
# the Free Software Foundation; either version 2 of the License, or
7
7
# (at your option) any later version.
8
 
 
 
8
#
9
9
# This program is distributed in the hope that it will be useful,
10
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
12
# GNU General Public License for more details.
13
 
 
 
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
20
 
21
21
import os
22
22
 
 
23
import bzrlib
23
24
from bzrlib.tests.blackbox import ExternalBase
 
25
from bzrlib.tests import TestCaseInTempDir, TestCaseWithTransport
24
26
 
25
27
 
26
28
class TestLog(ExternalBase):
27
29
 
28
 
    def _prepare(self):
29
 
        self.runbzr("init")
30
 
        self.build_tree(['hello.txt', 'goodbye.txt', 'meep.txt'])
31
 
        self.runbzr("add hello.txt")
32
 
        self.runbzr("commit -m message1 hello.txt")
33
 
        self.runbzr("add goodbye.txt")
34
 
        self.runbzr("commit -m message2 goodbye.txt")
35
 
        self.runbzr("add meep.txt")
36
 
        self.runbzr("commit -m message3 meep.txt")
37
 
        self.full_log = self.runbzr("log")[0]
 
30
    def _prepare(self, path='.', format=None):
 
31
        tree = self.make_branch_and_tree(path, format=format)
 
32
        self.build_tree(
 
33
            [path + '/hello.txt', path + '/goodbye.txt', path + '/meep.txt'])
 
34
        tree.add('hello.txt')
 
35
        tree.commit(message='message1')
 
36
        tree.add('goodbye.txt')
 
37
        tree.commit(message='message2')
 
38
        tree.add('meep.txt')
 
39
        tree.commit(message='message3')
 
40
        self.full_log = self.run_bzr(["log", path])[0]
 
41
        return tree
38
42
 
39
43
    def test_log_null_end_revspec(self):
40
44
        self._prepare()
45
49
        self.assertTrue('message:\n  message2\n' in self.full_log)
46
50
        self.assertTrue('message:\n  message3\n' in self.full_log)
47
51
 
48
 
        log = self.runbzr("log -r 1..")[0]
49
 
        self.assertEquals(log, self.full_log)
 
52
        log = self.run_bzr("log -r 1..")[0]
 
53
        self.assertEqualDiff(log, self.full_log)
50
54
 
51
55
    def test_log_null_begin_revspec(self):
52
56
        self._prepare()
53
 
        log = self.runbzr("log -r ..3")[0]
54
 
        self.assertEquals(self.full_log, log)
 
57
        log = self.run_bzr("log -r ..3")[0]
 
58
        self.assertEqualDiff(self.full_log, log)
55
59
 
56
60
    def test_log_null_both_revspecs(self):
57
61
        self._prepare()
58
 
        log = self.runbzr("log -r ..")[0]
 
62
        log = self.run_bzr("log -r ..")[0]
59
63
        self.assertEquals(self.full_log, log)
 
64
        self.assertEqualDiff(self.full_log, log)
60
65
 
61
66
    def test_log_negative_begin_revspec_full_log(self):
62
67
        self._prepare()
63
 
        log = self.runbzr("log -r -3..")[0]
64
 
        self.assertEquals(self.full_log, log)
 
68
        log = self.run_bzr("log -r -3..")[0]
 
69
        self.assertEqualDiff(self.full_log, log)
65
70
 
66
71
    def test_log_negative_both_revspec_full_log(self):
67
72
        self._prepare()
68
 
        log = self.runbzr("log -r -3..-1")[0]
69
 
        self.assertEquals(self.full_log, log)
 
73
        log = self.run_bzr("log -r -3..-1")[0]
 
74
        self.assertEqualDiff(self.full_log, log)
70
75
 
71
76
    def test_log_negative_both_revspec_partial(self):
72
77
        self._prepare()
73
 
        log = self.runbzr("log -r -3..-2")[0]
 
78
        log = self.run_bzr("log -r -3..-2")[0]
74
79
        self.assertTrue('revno: 1\n' in log)
75
80
        self.assertTrue('revno: 2\n' in log)
76
81
        self.assertTrue('revno: 3\n' not in log)
77
82
 
78
83
    def test_log_negative_begin_revspec(self):
79
84
        self._prepare()
80
 
        log = self.runbzr("log -r -2..")[0]
 
85
        log = self.run_bzr("log -r -2..")[0]
81
86
        self.assertTrue('revno: 1\n' not in log)
82
87
        self.assertTrue('revno: 2\n' in log)
83
88
        self.assertTrue('revno: 3\n' in log)
84
89
 
85
90
    def test_log_postive_revspecs(self):
86
91
        self._prepare()
87
 
        log = self.runbzr("log -r 1..3")[0]
88
 
        self.assertEquals(self.full_log, log)
89
 
 
 
92
        log = self.run_bzr("log -r 1..3")[0]
 
93
        self.assertEqualDiff(self.full_log, log)
 
94
 
 
95
    def test_log_reversed_revspecs(self):
 
96
        self._prepare()
 
97
        self.run_bzr_error(('bzr: ERROR: Start revision must be older than '
 
98
                            'the end revision.\n',),
 
99
                           ['log', '-r3..1'])
 
100
 
 
101
    def test_log_revno_n_path(self):
 
102
        self._prepare(path='branch1')
 
103
        self._prepare(path='branch2')
 
104
        log = self.run_bzr("log -r revno:2:branch1..revno:3:branch2",
 
105
                          retcode=3)[0]
 
106
        log = self.run_bzr("log -r revno:1:branch2..revno:3:branch2")[0]
 
107
        self.assertEqualDiff(self.full_log, log)
 
108
        log = self.run_bzr("log -r revno:1:branch2")[0]
 
109
        self.assertTrue('revno: 1\n' in log)
 
110
        self.assertTrue('revno: 2\n' not in log)
 
111
        self.assertTrue('branch nick: branch2\n' in log)
 
112
        self.assertTrue('branch nick: branch1\n' not in log)
 
113
        
 
114
    def test_log_nonexistent_file(self):
 
115
        # files that don't exist in either the basis tree or working tree
 
116
        # should give an error
 
117
        wt = self.make_branch_and_tree('.')
 
118
        out, err = self.run_bzr('log does-not-exist', retcode=3)
 
119
        self.assertContainsRe(
 
120
            err, 'Path does not have any revision history: does-not-exist')
 
121
 
 
122
    def test_log_with_tags(self):
 
123
        tree = self._prepare(format='dirstate-tags')
 
124
        branch = tree.branch
 
125
        branch.tags.set_tag('tag1', branch.get_rev_id(1))
 
126
        branch.tags.set_tag('tag1.1', branch.get_rev_id(1))
 
127
        branch.tags.set_tag('tag3', branch.last_revision()) 
 
128
        
 
129
        log = self.run_bzr("log -r-1")[0]
 
130
        self.assertTrue('tags: tag3' in log)
 
131
 
 
132
        log = self.run_bzr("log -r1")[0]
 
133
        # I guess that we can't know the order of tags in the output
 
134
        # since dicts are unordered, need to check both possibilities
 
135
        self.assertContainsRe(log, r'tags: (tag1, tag1\.1|tag1\.1, tag1)')
 
136
 
 
137
    def test_merged_log_with_tags(self):
 
138
        branch1_tree = self._prepare(path='branch1', format='dirstate-tags')
 
139
        branch1 = branch1_tree.branch
 
140
        branch2_tree = branch1_tree.bzrdir.sprout('branch2').open_workingtree()
 
141
        branch1_tree.commit(message='foobar', allow_pointless=True)
 
142
        branch1.tags.set_tag('tag1', branch1.last_revision())
 
143
        os.chdir('branch2')
 
144
        self.run_bzr('merge ../branch1') # tags don't propagate otherwise
 
145
        branch2_tree.commit(message='merge branch 1')
 
146
        log = self.run_bzr("log -r-1")[0]
 
147
        self.assertContainsRe(log, r'    tags: tag1')
 
148
        log = self.run_bzr("log -r3.1.1")[0]
 
149
        self.assertContainsRe(log, r'tags: tag1')
 
150
 
 
151
    def test_log_limit(self):
 
152
        self._prepare()
 
153
        log = self.run_bzr("log --limit 2")[0]
 
154
        self.assertTrue('revno: 1\n' not in log)
 
155
        self.assertTrue('revno: 2\n' in log)
 
156
        self.assertTrue('revno: 3\n' in log)
90
157
 
91
158
class TestLogMerges(ExternalBase):
92
159
 
 
160
    def _prepare(self):
 
161
        parent_tree = self.make_branch_and_tree('parent')
 
162
        parent_tree.commit(message='first post', allow_pointless=True)
 
163
        child_tree = parent_tree.bzrdir.sprout('child').open_workingtree()
 
164
        child_tree.commit(message='branch 1', allow_pointless=True)
 
165
        smaller_tree = \
 
166
                child_tree.bzrdir.sprout('smallerchild').open_workingtree()
 
167
        smaller_tree.commit(message='branch 2', allow_pointless=True)
 
168
        child_tree.merge_from_branch(smaller_tree.branch)
 
169
        child_tree.commit(message='merge branch 2')
 
170
        parent_tree.merge_from_branch(child_tree.branch)
 
171
        parent_tree.commit(message='merge branch 1')
 
172
        os.chdir('parent')
 
173
 
93
174
    def test_merges_are_indented_by_level(self):
94
 
        self.build_tree(['parent/'])
95
 
        self.run_bzr('init', 'parent')
96
 
        self.run_bzr('commit', '-m', 'first post', '--unchanged', 'parent')
97
 
        self.run_bzr('branch', 'parent', 'child')
98
 
        self.run_bzr('commit', '-m', 'branch 1', '--unchanged', 'child')
99
 
        self.run_bzr('branch', 'child', 'smallerchild')
100
 
        self.run_bzr('commit', '-m', 'branch 2', '--unchanged', 'smallerchild')
101
 
        os.chdir('child')
102
 
        self.run_bzr('merge', '../smallerchild')
103
 
        self.run_bzr('commit', '-m', 'merge branch 2')
104
 
        os.chdir('../parent')
105
 
        self.run_bzr('merge', '../child')
106
 
        self.run_bzr('commit', '-m', 'merge branch 1')
 
175
        self._prepare()
107
176
        out,err = self.run_bzr('log')
108
177
        # the log will look something like:
109
178
#        self.assertEqual("""\
115
184
#message:
116
185
#  merge branch 1
117
186
#    ------------------------------------------------------------
118
 
#    merged: foo@example.com-20060328113140-91f43cfb46dc2863
 
187
#    revno: 1.1.2  
119
188
#    committer: Robert Collins <foo@example.com>
120
189
#    branch nick: child
121
190
#    timestamp: Tue 2006-03-28 22:31:40 +1100
122
191
#    message:
123
192
#      merge branch 2
124
193
#        ------------------------------------------------------------
125
 
#        merged: foo@example.com-20060328113140-1ba24f850a0ef573
 
194
#        revno: 1.1.1.1
126
195
#        committer: Robert Collins <foo@example.com>
127
196
#        branch nick: smallerchild
128
197
#        timestamp: Tue 2006-03-28 22:31:40 +1100
129
198
#        message:
130
199
#          branch 2
131
200
#    ------------------------------------------------------------
132
 
#    merged: foo@example.com-20060328113140-5749a4757a8ac792
 
201
#    revno: 1.1.1
133
202
#    committer: Robert Collins <foo@example.com>
134
203
#    branch nick: child
135
204
#    timestamp: Tue 2006-03-28 22:31:40 +1100
144
213
#  first post
145
214
#""", out)
146
215
        # but we dont have a nice pattern matcher hooked up yet, so:
147
 
        # we check for the indenting of the commit message:
 
216
        # we check for the indenting of the commit message and the 
 
217
        # revision numbers 
 
218
        self.assertTrue('revno: 2' in out)
148
219
        self.assertTrue('  merge branch 1' in out)
 
220
        self.assertTrue('    revno: 1.1.2' in out)
149
221
        self.assertTrue('      merge branch 2' in out)
 
222
        self.assertTrue('        revno: 1.1.1.1' in out)
150
223
        self.assertTrue('          branch 2' in out)
 
224
        self.assertTrue('    revno: 1.1.1' in out)
151
225
        self.assertTrue('      branch 1' in out)
 
226
        self.assertTrue('revno: 1\n' in out)
152
227
        self.assertTrue('  first post' in out)
153
228
        self.assertEqual('', err)
 
229
 
 
230
    def test_merges_single_merge_rev(self):
 
231
        self._prepare()
 
232
        out,err = self.run_bzr('log -r1.1.2')
 
233
        # the log will look something like:
 
234
#        self.assertEqual("""\
 
235
#------------------------------------------------------------
 
236
#revno: 1.1.2  
 
237
#committer: Robert Collins <foo@example.com>
 
238
#branch nick: child
 
239
#timestamp: Tue 2006-03-28 22:31:40 +1100
 
240
#message:
 
241
#  merge branch 2
 
242
#    ------------------------------------------------------------
 
243
#    revno: 1.1.1.1
 
244
#    committer: Robert Collins <foo@example.com>
 
245
#    branch nick: smallerchild
 
246
#    timestamp: Tue 2006-03-28 22:31:40 +1100
 
247
#    message:
 
248
#      branch 2
 
249
#""", out)
 
250
        # but we dont have a nice pattern matcher hooked up yet, so:
 
251
        # we check for the indenting of the commit message and the 
 
252
        # revision numbers 
 
253
        self.assertTrue('revno: 2' not in out)
 
254
        self.assertTrue('  merge branch 1' not in out)
 
255
        self.assertTrue('revno: 1.1.2' in out)
 
256
        self.assertTrue('  merge branch 2' in out)
 
257
        self.assertTrue('    revno: 1.1.1.1' in out)
 
258
        self.assertTrue('      branch 2' in out)
 
259
        self.assertTrue('revno: 1.1.1\n' not in out)
 
260
        self.assertTrue('  branch 1' not in out)
 
261
        self.assertTrue('revno: 1\n' not in out)
 
262
        self.assertTrue('  first post' not in out)
 
263
        self.assertEqual('', err)
 
264
 
 
265
    def test_merges_partial_range(self):
 
266
        self._prepare()
 
267
        out,err = self.run_bzr('log -r1.1.1..1.1.2')
 
268
        # the log will look something like:
 
269
#        self.assertEqual("""\
 
270
#------------------------------------------------------------
 
271
#revno: 1.1.2  
 
272
#committer: Robert Collins <foo@example.com>
 
273
#branch nick: child
 
274
#timestamp: Tue 2006-03-28 22:31:40 +1100
 
275
#message:
 
276
#  merge branch 2
 
277
#    ------------------------------------------------------------
 
278
#    revno: 1.1.1.1
 
279
#    committer: Robert Collins <foo@example.com>
 
280
#    branch nick: smallerchild
 
281
#    timestamp: Tue 2006-03-28 22:31:40 +1100
 
282
#    message:
 
283
#      branch 2
 
284
#------------------------------------------------------------
 
285
#revno: 1.1.1
 
286
#committer: Robert Collins <foo@example.com>
 
287
#branch nick: child
 
288
#timestamp: Tue 2006-03-28 22:31:40 +1100
 
289
#message:
 
290
#  branch 1
 
291
#""", out)
 
292
        # but we dont have a nice pattern matcher hooked up yet, so:
 
293
        # we check for the indenting of the commit message and the 
 
294
        # revision numbers 
 
295
        self.assertTrue('revno: 2' not in out)
 
296
        self.assertTrue('  merge branch 1' not in out)
 
297
        self.assertTrue('revno: 1.1.2' in out)
 
298
        self.assertTrue('  merge branch 2' in out)
 
299
        self.assertTrue('    revno: 1.1.1.1' in out)
 
300
        self.assertTrue('      branch 2' in out)
 
301
        self.assertTrue('revno: 1.1.1' in out)
 
302
        self.assertTrue('  branch 1' in out)
 
303
        self.assertTrue('revno: 1\n' not in out)
 
304
        self.assertTrue('  first post' not in out)
 
305
        self.assertEqual('', err)
 
306
 
 
307
 
 
308
class TestLogEncodings(TestCaseInTempDir):
 
309
 
 
310
    _mu = u'\xb5'
 
311
    _message = u'Message with \xb5'
 
312
 
 
313
    # Encodings which can encode mu
 
314
    good_encodings = [
 
315
        'utf-8',
 
316
        'latin-1',
 
317
        'iso-8859-1',
 
318
        'cp437', # Common windows encoding
 
319
        'cp1251', # Alexander Belchenko's windows encoding
 
320
        'cp1258', # Common windows encoding
 
321
    ]
 
322
    # Encodings which cannot encode mu
 
323
    bad_encodings = [
 
324
        'ascii',
 
325
        'iso-8859-2',
 
326
        'koi8_r',
 
327
    ]
 
328
 
 
329
    def setUp(self):
 
330
        TestCaseInTempDir.setUp(self)
 
331
        self.user_encoding = bzrlib.user_encoding
 
332
 
 
333
    def tearDown(self):
 
334
        bzrlib.user_encoding = self.user_encoding
 
335
        TestCaseInTempDir.tearDown(self)
 
336
 
 
337
    def create_branch(self):
 
338
        bzr = self.run_bzr
 
339
        bzr('init')
 
340
        open('a', 'wb').write('some stuff\n')
 
341
        bzr('add a')
 
342
        bzr(['commit', '-m', self._message])
 
343
 
 
344
    def try_encoding(self, encoding, fail=False):
 
345
        bzr = self.run_bzr
 
346
        if fail:
 
347
            self.assertRaises(UnicodeEncodeError,
 
348
                self._mu.encode, encoding)
 
349
            encoded_msg = self._message.encode(encoding, 'replace')
 
350
        else:
 
351
            encoded_msg = self._message.encode(encoding)
 
352
 
 
353
        old_encoding = bzrlib.user_encoding
 
354
        # This test requires that 'run_bzr' uses the current
 
355
        # bzrlib, because we override user_encoding, and expect
 
356
        # it to be used
 
357
        try:
 
358
            bzrlib.user_encoding = 'ascii'
 
359
            # We should be able to handle any encoding
 
360
            out, err = bzr('log', encoding=encoding)
 
361
            if not fail:
 
362
                # Make sure we wrote mu as we expected it to exist
 
363
                self.assertNotEqual(-1, out.find(encoded_msg))
 
364
                out_unicode = out.decode(encoding)
 
365
                self.assertNotEqual(-1, out_unicode.find(self._message))
 
366
            else:
 
367
                self.assertNotEqual(-1, out.find('Message with ?'))
 
368
        finally:
 
369
            bzrlib.user_encoding = old_encoding
 
370
 
 
371
    def test_log_handles_encoding(self):
 
372
        self.create_branch()
 
373
 
 
374
        for encoding in self.good_encodings:
 
375
            self.try_encoding(encoding)
 
376
 
 
377
    def test_log_handles_bad_encoding(self):
 
378
        self.create_branch()
 
379
 
 
380
        for encoding in self.bad_encodings:
 
381
            self.try_encoding(encoding, fail=True)
 
382
 
 
383
    def test_stdout_encoding(self):
 
384
        bzr = self.run_bzr
 
385
        bzrlib.user_encoding = "cp1251"
 
386
 
 
387
        bzr('init')
 
388
        self.build_tree(['a'])
 
389
        bzr('add a')
 
390
        bzr(['commit', '-m', u'\u0422\u0435\u0441\u0442'])
 
391
        stdout, stderr = self.run_bzr('log', encoding='cp866')
 
392
 
 
393
        message = stdout.splitlines()[-1]
 
394
 
 
395
        # explanation of the check:
 
396
        # u'\u0422\u0435\u0441\u0442' is word 'Test' in russian
 
397
        # in cp866  encoding this is string '\x92\xa5\xe1\xe2'
 
398
        # in cp1251 encoding this is string '\xd2\xe5\xf1\xf2'
 
399
        # This test should check that output of log command
 
400
        # encoded to sys.stdout.encoding
 
401
        test_in_cp866 = '\x92\xa5\xe1\xe2'
 
402
        test_in_cp1251 = '\xd2\xe5\xf1\xf2'
 
403
        # Make sure the log string is encoded in cp866
 
404
        self.assertEquals(test_in_cp866, message[2:])
 
405
        # Make sure the cp1251 string is not found anywhere
 
406
        self.assertEquals(-1, stdout.find(test_in_cp1251))
 
407
 
 
408
 
 
409
class TestLogFile(TestCaseWithTransport):
 
410
 
 
411
    def test_log_local_branch_file(self):
 
412
        """We should be able to log files in local treeless branches"""
 
413
        tree = self.make_branch_and_tree('tree')
 
414
        self.build_tree(['tree/file'])
 
415
        tree.add('file')
 
416
        tree.commit('revision 1')
 
417
        tree.bzrdir.destroy_workingtree()
 
418
        self.run_bzr('log tree/file')
 
419
 
 
420
    def test_log_file(self):
 
421
        """The log for a particular file should only list revs for that file"""
 
422
        tree = self.make_branch_and_tree('parent')
 
423
        self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
 
424
        tree.add('file1')
 
425
        tree.commit('add file1')
 
426
        tree.add('file2')
 
427
        tree.commit('add file2')
 
428
        tree.add('file3')
 
429
        tree.commit('add file3')
 
430
        child_tree = tree.bzrdir.sprout('child').open_workingtree()
 
431
        self.build_tree_contents([('child/file2', 'hello')])
 
432
        child_tree.commit(message='branch 1')
 
433
        tree.merge_from_branch(child_tree.branch)
 
434
        tree.commit(message='merge child branch')
 
435
        os.chdir('parent')
 
436
        log = self.run_bzr('log file1')[0]
 
437
        self.assertContainsRe(log, 'revno: 1\n')
 
438
        self.assertNotContainsRe(log, 'revno: 2\n')
 
439
        self.assertNotContainsRe(log, 'revno: 3\n')
 
440
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
 
441
        self.assertNotContainsRe(log, 'revno: 4\n')
 
442
        log = self.run_bzr('log file2')[0]
 
443
        self.assertNotContainsRe(log, 'revno: 1\n')
 
444
        self.assertContainsRe(log, 'revno: 2\n')
 
445
        self.assertNotContainsRe(log, 'revno: 3\n')
 
446
        self.assertContainsRe(log, 'revno: 3.1.1\n')
 
447
        self.assertContainsRe(log, 'revno: 4\n')
 
448
        log = self.run_bzr('log file3')[0]
 
449
        self.assertNotContainsRe(log, 'revno: 1\n')
 
450
        self.assertNotContainsRe(log, 'revno: 2\n')
 
451
        self.assertContainsRe(log, 'revno: 3\n')
 
452
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
 
453
        self.assertNotContainsRe(log, 'revno: 4\n')
 
454
        log = self.run_bzr('log -r3.1.1 file2')[0]
 
455
        self.assertNotContainsRe(log, 'revno: 1\n')
 
456
        self.assertNotContainsRe(log, 'revno: 2\n')
 
457
        self.assertNotContainsRe(log, 'revno: 3\n')
 
458
        self.assertContainsRe(log, 'revno: 3.1.1\n')
 
459
        self.assertNotContainsRe(log, 'revno: 4\n')
 
460
        log = self.run_bzr('log -r4 file2')[0]
 
461
        self.assertNotContainsRe(log, 'revno: 1\n')
 
462
        self.assertNotContainsRe(log, 'revno: 2\n')
 
463
        self.assertNotContainsRe(log, 'revno: 3\n')
 
464
        self.assertContainsRe(log, 'revno: 3.1.1\n')
 
465
        self.assertContainsRe(log, 'revno: 4\n')
 
466
        log = self.run_bzr('log -r3.. file2')[0]
 
467
        self.assertNotContainsRe(log, 'revno: 1\n')
 
468
        self.assertNotContainsRe(log, 'revno: 2\n')
 
469
        self.assertNotContainsRe(log, 'revno: 3\n')
 
470
        self.assertContainsRe(log, 'revno: 3.1.1\n')
 
471
        self.assertContainsRe(log, 'revno: 4\n')
 
472
        log = self.run_bzr('log -r..3 file2')[0]
 
473
        self.assertNotContainsRe(log, 'revno: 1\n')
 
474
        self.assertContainsRe(log, 'revno: 2\n')
 
475
        self.assertNotContainsRe(log, 'revno: 3\n')
 
476
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
 
477
        self.assertNotContainsRe(log, 'revno: 4\n')