~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: 2010-01-23 12:12:33 UTC
  • mfrom: (4984.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100123121233-yse96ztm8u0l3ljn
(vila) Cleanup log tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
"""Black-box tests for bzr log."""
19
19
 
 
20
from itertools import izip
20
21
import os
21
22
import re
22
23
 
23
24
from bzrlib import (
 
25
    branchbuilder,
 
26
    log,
24
27
    osutils,
25
28
    tests,
26
29
    )
27
 
from bzrlib.tests import test_log
28
 
 
29
 
 
30
 
class TestLog(tests.TestCaseWithTransport):
31
 
 
32
 
    def setUp(self):
33
 
        super(TestLog, self).setUp()
34
 
        self.timezone = 0 # UTC
35
 
        self.timestamp = 1132617600 # Mon 2005-11-22 00:00:00 +0000
 
30
from bzrlib.tests import (
 
31
    script,
 
32
    test_log,
 
33
    )
 
34
 
 
35
 
 
36
class TestLog(tests.TestCaseWithTransport, test_log.TestLogMixin):
36
37
 
37
38
    def make_minimal_branch(self, path='.', format=None):
38
39
        tree = self.make_branch_and_tree(path, format=format)
63
64
        tree.commit(message='merge')
64
65
        return tree
65
66
 
66
 
    def assertRevnos(self, log, must_have=(), must_not_have=()):
67
 
        """Check if revnos are in or not in the log output"""
68
 
        for revno in must_have:
69
 
            self.assertTrue(('revno: %s\n' % revno) in log,
70
 
                'Does not contain expected revno %s' % revno)
71
 
        for revno in must_not_have:
72
 
            self.assertFalse(('revno: %s\n' % revno) in log,
73
 
                'Contains unexpected revno %s' % revno)
74
 
 
75
 
    def commit_options(self):
76
 
        """Use some mostly fixed values for commits to simplify tests.
77
 
 
78
 
        Tests can use this function to get some commit attributes. The time
79
 
        stamp is incremented at each commit.
80
 
        """
81
 
        self.timestamp += 1 # 1 second between each commit
82
 
        return dict(committer='Lorem Ipsum <joe@foo.com>',
83
 
                 timezone=self.timezone,
84
 
                 timestamp=self.timestamp,
85
 
                 )
86
 
 
87
 
    def check_log(self, expected, args, working_dir='level0'):
88
 
        out, err = self.run_bzr(['log', '--timezone', 'utc'] + args,
89
 
                                working_dir=working_dir)
90
 
        self.assertEqual('', err)
91
 
        self.assertEqualDiff(expected, test_log.normalize_log(out))
92
 
 
93
 
 
94
 
class TestLogRevSpecs(TestLog):
 
67
 
 
68
class TestLogWithLogCatcher(TestLog):
 
69
 
 
70
    def setUp(self):
 
71
        super(TestLogWithLogCatcher, self).setUp()
 
72
        # Capture log formatter creations
 
73
        class MyLogFormatter(test_log.LogCatcher):
 
74
 
 
75
            def __new__(klass, *args, **kwargs):
 
76
                self.log_catcher = test_log.LogCatcher(*args, **kwargs)
 
77
                # Always return our own log formatter
 
78
                return self.log_catcher
 
79
 
 
80
        orig = log.log_formatter_registry.get_default
 
81
        def restore():
 
82
            log.log_formatter_registry.get_default = orig
 
83
        self.addCleanup(restore)
 
84
 
 
85
        def getme(branch):
 
86
                # Always return our own log formatter class hijacking the
 
87
                # default behavior (which requires setting up a config
 
88
                # variable)
 
89
            return MyLogFormatter
 
90
        log.log_formatter_registry.get_default = getme
 
91
 
 
92
    def get_captured_revisions(self):
 
93
        return self.log_catcher.revisions
 
94
 
 
95
    def assertLogRevnos(self, args, expected_revnos, working_dir='.'):
 
96
        self.run_bzr(['log'] + args, working_dir=working_dir)
 
97
        self.assertEqual(expected_revnos,
 
98
                         [r.revno for r in self.get_captured_revisions()])
 
99
 
 
100
    def assertLogRevnosAndDepths(self, args, expected_revnos_and_depths,
 
101
                                working_dir='.'):
 
102
        self.run_bzr(['log'] + args, working_dir=working_dir)
 
103
        self.assertEqual(expected_revnos_and_depths,
 
104
                         [(r.revno, r.merge_depth)
 
105
                           for r in self.get_captured_revisions()])
 
106
 
 
107
 
 
108
class TestLogRevSpecs(TestLogWithLogCatcher):
 
109
 
 
110
    def test_log_no_revspec(self):
 
111
        self.make_linear_branch()
 
112
        self.assertLogRevnos([], ['3', '2', '1'])
95
113
 
96
114
    def test_log_null_end_revspec(self):
97
115
        self.make_linear_branch()
98
 
        log = self.run_bzr(['log'])[0]
99
 
        self.assertTrue('revno: 1\n' in log)
100
 
        self.assertTrue('revno: 2\n' in log)
101
 
        self.assertTrue('revno: 3\n' in log)
102
 
        self.assertTrue('message:\n  message1\n' in log)
103
 
        self.assertTrue('message:\n  message2\n' in log)
104
 
        self.assertTrue('message:\n  message3\n' in log)
105
 
 
106
 
        full_log = self.run_bzr(['log'])[0]
107
 
        log = self.run_bzr("log -r 1..")[0]
108
 
        self.assertEqualDiff(log, full_log)
 
116
        self.assertLogRevnos(['-r1..'], ['3', '2', '1'])
109
117
 
110
118
    def test_log_null_begin_revspec(self):
111
119
        self.make_linear_branch()
112
 
        full_log = self.run_bzr(['log'])[0]
113
 
        log = self.run_bzr("log -r ..3")[0]
114
 
        self.assertEqualDiff(full_log, log)
 
120
        self.assertLogRevnos(['-r..3'], ['3', '2', '1'])
115
121
 
116
122
    def test_log_null_both_revspecs(self):
117
123
        self.make_linear_branch()
118
 
        full_log = self.run_bzr(['log'])[0]
119
 
        log = self.run_bzr("log -r ..")[0]
120
 
        self.assertEqualDiff(full_log, log)
121
 
 
122
 
    def test_log_zero_revspec(self):
123
 
        self.make_minimal_branch()
124
 
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
125
 
                           ['log', '-r0'])
126
 
 
127
 
    def test_log_zero_begin_revspec(self):
128
 
        self.make_linear_branch()
129
 
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
130
 
                           ['log', '-r0..2'])
131
 
 
132
 
    def test_log_zero_end_revspec(self):
133
 
        self.make_linear_branch()
134
 
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
135
 
                           ['log', '-r-2..0'])
 
124
        self.assertLogRevnos(['-r..'], ['3', '2', '1'])
136
125
 
137
126
    def test_log_negative_begin_revspec_full_log(self):
138
127
        self.make_linear_branch()
139
 
        full_log = self.run_bzr(['log'])[0]
140
 
        log = self.run_bzr("log -r -3..")[0]
141
 
        self.assertEqualDiff(full_log, log)
 
128
        self.assertLogRevnos(['-r-3..'], ['3', '2', '1'])
142
129
 
143
130
    def test_log_negative_both_revspec_full_log(self):
144
131
        self.make_linear_branch()
145
 
        full_log = self.run_bzr(['log'])[0]
146
 
        log = self.run_bzr("log -r -3..-1")[0]
147
 
        self.assertEqualDiff(full_log, log)
 
132
        self.assertLogRevnos(['-r-3..-1'], ['3', '2', '1'])
148
133
 
149
134
    def test_log_negative_both_revspec_partial(self):
150
135
        self.make_linear_branch()
151
 
        log = self.run_bzr("log -r -3..-2")[0]
152
 
        self.assertTrue('revno: 1\n' in log)
153
 
        self.assertTrue('revno: 2\n' in log)
154
 
        self.assertTrue('revno: 3\n' not in log)
 
136
        self.assertLogRevnos(['-r-3..-2'], ['2', '1'])
155
137
 
156
138
    def test_log_negative_begin_revspec(self):
157
139
        self.make_linear_branch()
158
 
        log = self.run_bzr("log -r -2..")[0]
159
 
        self.assertTrue('revno: 1\n' not in log)
160
 
        self.assertTrue('revno: 2\n' in log)
161
 
        self.assertTrue('revno: 3\n' in log)
 
140
        self.assertLogRevnos(['-r-2..'], ['3', '2'])
162
141
 
163
142
    def test_log_positive_revspecs(self):
164
143
        self.make_linear_branch()
165
 
        full_log = self.run_bzr(['log'])[0]
166
 
        log = self.run_bzr("log -r 1..3")[0]
167
 
        self.assertEqualDiff(full_log, log)
 
144
        self.assertLogRevnos(['-r1..3'], ['3', '2', '1'])
168
145
 
169
146
    def test_log_dotted_revspecs(self):
170
147
        self.make_merged_branch()
171
 
        log = self.run_bzr("log -n0 -r 1..1.1.1")[0]
172
 
        self.assertRevnos(log, (1, '1.1.1'), (2, 3, '1.1.2', 4))
173
 
 
174
 
    def test_log_reversed_revspecs(self):
175
 
        self.make_linear_branch()
176
 
        self.run_bzr_error(('bzr: ERROR: Start revision must be older than '
177
 
                            'the end revision.\n',),
178
 
                           ['log', '-r3..1'])
179
 
 
180
 
    def test_log_reversed_dotted_revspecs(self):
181
 
        self.make_merged_branch()
182
 
        self.run_bzr_error(('bzr: ERROR: Start revision not found in '
183
 
                            'left-hand history of end revision.\n',),
184
 
                           "log -r 1.1.1..1")
 
148
        self.assertLogRevnos(['-n0', '-r1..1.1.1'], ['1.1.1', '1'])
 
149
 
 
150
    def test_log_limit(self):
 
151
        tree = self.make_branch_and_tree('.')
 
152
        # We want more commits than our batch size starts at
 
153
        for pos in range(10):
 
154
            tree.commit("%s" % pos)
 
155
        self.assertLogRevnos(['--limit', '2'], ['10', '9'])
 
156
 
 
157
    def test_log_limit_short(self):
 
158
        self.make_linear_branch()
 
159
        self.assertLogRevnos(['-l', '2'], ['3', '2'])
 
160
 
 
161
    def test_log_change_revno(self):
 
162
        self.make_linear_branch()
 
163
        self.assertLogRevnos(['-c1'], ['1'])
 
164
 
 
165
 
 
166
class TestBug474807(TestLogWithLogCatcher):
 
167
 
 
168
    def setUp(self):
 
169
        super(TestBug474807, self).setUp()
 
170
        # FIXME: Using a MemoryTree would be even better here (but until we
 
171
        # stop calling run_bzr, there is no point) --vila 100118.
 
172
        builder = branchbuilder.BranchBuilder(self.get_transport())
 
173
        builder.start_series()
 
174
        # mainline
 
175
        builder.build_snapshot('1', None, [
 
176
            ('add', ('', 'root-id', 'directory', ''))])
 
177
        builder.build_snapshot('2', ['1'], [])
 
178
        # branch
 
179
        builder.build_snapshot('1.1.1', ['1'], [])
 
180
        # merge branch into mainline
 
181
        builder.build_snapshot('3', ['2', '1.1.1'], [])
 
182
        # new commits in branch
 
183
        builder.build_snapshot('1.1.2', ['1.1.1'], [])
 
184
        builder.build_snapshot('1.1.3', ['1.1.2'], [])
 
185
        # merge branch into mainline
 
186
        builder.build_snapshot('4', ['3', '1.1.3'], [])
 
187
        # merge mainline into branch
 
188
        builder.build_snapshot('1.1.4', ['1.1.3', '4'], [])
 
189
        # merge branch into mainline
 
190
        builder.build_snapshot('5', ['4', '1.1.4'], [])
 
191
        builder.finish_series()
 
192
 
 
193
    def test_n0(self):
 
194
        self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4'],
 
195
                             ['1.1.4', '4', '1.1.3', '1.1.2', '3', '1.1.1'])
 
196
    def test_n0_forward(self):
 
197
        self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4', '--forward'],
 
198
                             ['3', '1.1.1', '4', '1.1.2', '1.1.3', '1.1.4'])
 
199
 
 
200
    def test_n1(self):
 
201
        # starting from 1.1.4 we follow the left-hand ancestry
 
202
        self.assertLogRevnos(['-n1', '-r1.1.1..1.1.4'],
 
203
                             ['1.1.4', '1.1.3', '1.1.2', '1.1.1'])
 
204
 
 
205
    def test_n1_forward(self):
 
206
        self.assertLogRevnos(['-n1', '-r1.1.1..1.1.4', '--forward'],
 
207
                             ['1.1.1', '1.1.2', '1.1.3', '1.1.4'])
 
208
 
 
209
 
 
210
class TestLogRevSpecsWithPaths(TestLogWithLogCatcher):
 
211
 
 
212
    def test_log_revno_n_path_wrong_namespace(self):
 
213
        self.make_linear_branch('branch1')
 
214
        self.make_linear_branch('branch2')
 
215
        # There is no guarantee that a path exist between two arbitrary
 
216
        # revisions.
 
217
        self.run_bzr("log -r revno:2:branch1..revno:3:branch2", retcode=3)
 
218
        # But may be it's worth trying though ? -- vila 100115
 
219
 
 
220
    def test_log_revno_n_path_correct_order(self):
 
221
        self.make_linear_branch('branch2')
 
222
        self.assertLogRevnos(['-rrevno:1:branch2..revno:3:branch2'],
 
223
                             ['3', '2','1'])
185
224
 
186
225
    def test_log_revno_n_path(self):
187
 
        self.make_linear_branch('branch1')
188
226
        self.make_linear_branch('branch2')
189
 
        # Swapped revisions
190
 
        self.run_bzr("log -r revno:2:branch1..revno:3:branch2", retcode=3)[0]
191
 
        # Correct order
192
 
        log = self.run_bzr("log -r revno:1:branch2..revno:3:branch2")[0]
193
 
        full_log = self.run_bzr(['log'], working_dir='branch2')[0]
194
 
        self.assertEqualDiff(full_log, log)
195
 
        log = self.run_bzr("log -r revno:1:branch2")[0]
196
 
        self.assertTrue('revno: 1\n' in log)
197
 
        self.assertTrue('revno: 2\n' not in log)
198
 
        self.assertTrue('branch nick: branch2\n' in log)
199
 
        self.assertTrue('branch nick: branch1\n' not in log)
 
227
        self.assertLogRevnos(['-rrevno:1:branch2'],
 
228
                             ['1'])
 
229
        rev_props = self.log_catcher.revisions[0].rev.properties
 
230
        self.assertEqual('branch2', rev_props['branch-nick'])
 
231
 
 
232
 
 
233
class TestLogErrors(TestLog):
 
234
 
 
235
    def test_log_zero_revspec(self):
 
236
        self.make_minimal_branch()
 
237
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
 
238
                           ['log', '-r0'])
 
239
 
 
240
    def test_log_zero_begin_revspec(self):
 
241
        self.make_linear_branch()
 
242
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
 
243
                           ['log', '-r0..2'])
 
244
 
 
245
    def test_log_zero_end_revspec(self):
 
246
        self.make_linear_branch()
 
247
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
 
248
                           ['log', '-r-2..0'])
200
249
 
201
250
    def test_log_nonexistent_revno(self):
202
251
        self.make_minimal_branch()
203
 
        (out, err) = self.run_bzr_error(
204
 
            ["bzr: ERROR: Requested revision: '1234' "
205
 
             "does not exist in branch:"],
206
 
            ['log', '-r1234'])
 
252
        self.run_bzr_error(["bzr: ERROR: Requested revision: '1234' "
 
253
                            "does not exist in branch:"],
 
254
                           ['log', '-r1234'])
207
255
 
208
256
    def test_log_nonexistent_dotted_revno(self):
209
257
        self.make_minimal_branch()
210
 
        (out, err) = self.run_bzr_error(
211
 
            ["bzr: ERROR: Requested revision: '123.123' "
212
 
             "does not exist in branch:"],
213
 
            ['log',  '-r123.123'])
214
 
 
215
 
    def test_log_change_revno(self):
216
 
        self.make_linear_branch()
217
 
        expected_log = self.run_bzr("log -r 1")[0]
218
 
        log = self.run_bzr("log -c 1")[0]
219
 
        self.assertEqualDiff(expected_log, log)
 
258
        self.run_bzr_error(["bzr: ERROR: Requested revision: '123.123' "
 
259
                            "does not exist in branch:"],
 
260
                           ['log',  '-r123.123'])
220
261
 
221
262
    def test_log_change_nonexistent_revno(self):
222
263
        self.make_minimal_branch()
223
 
        (out, err) = self.run_bzr_error(
224
 
            ["bzr: ERROR: Requested revision: '1234' "
225
 
             "does not exist in branch:"],
226
 
            ['log',  '-c1234'])
 
264
        self.run_bzr_error(["bzr: ERROR: Requested revision: '1234' "
 
265
                            "does not exist in branch:"],
 
266
                           ['log',  '-c1234'])
227
267
 
228
268
    def test_log_change_nonexistent_dotted_revno(self):
229
269
        self.make_minimal_branch()
230
 
        (out, err) = self.run_bzr_error(
231
 
            ["bzr: ERROR: Requested revision: '123.123' "
232
 
             "does not exist in branch:"],
233
 
            ['log', '-c123.123'])
 
270
        self.run_bzr_error(["bzr: ERROR: Requested revision: '123.123' "
 
271
                            "does not exist in branch:"],
 
272
                           ['log', '-c123.123'])
234
273
 
235
274
    def test_log_change_single_revno_only(self):
236
275
        self.make_minimal_branch()
252
291
                              'Path unknown at end or start of revision range: '
253
292
                              'does-not-exist')
254
293
 
 
294
    def test_log_reversed_revspecs(self):
 
295
        self.make_linear_branch()
 
296
        self.run_bzr_error(('bzr: ERROR: Start revision must be older than '
 
297
                            'the end revision.\n',),
 
298
                           ['log', '-r3..1'])
 
299
 
 
300
    def test_log_reversed_dotted_revspecs(self):
 
301
        self.make_merged_branch()
 
302
        self.run_bzr_error(('bzr: ERROR: Start revision not found in '
 
303
                            'left-hand history of end revision.\n',),
 
304
                           "log -r 1.1.1..1")
 
305
 
 
306
    def test_log_bad_message_re(self):
 
307
        """Bad --message argument gives a sensible message
 
308
        
 
309
        See https://bugs.launchpad.net/bzr/+bug/251352
 
310
        """
 
311
        self.make_minimal_branch()
 
312
        out, err = self.run_bzr(['log', '-m', '*'], retcode=3)
 
313
        self.assertEqual("bzr: ERROR: Invalid regular expression"
 
314
            " in log message filter"
 
315
            ": '*'"
 
316
            ": nothing to repeat\n", err)
 
317
        self.assertEqual('', out)
 
318
 
 
319
    def test_log_unsupported_timezone(self):
 
320
        self.make_linear_branch()
 
321
        self.run_bzr_error(['bzr: ERROR: Unsupported timezone format "foo", '
 
322
                            'options are "utc", "original", "local".'],
 
323
                           ['log', '--timezone', 'foo'])
 
324
 
 
325
 
 
326
class TestLogTags(TestLog):
 
327
 
255
328
    def test_log_with_tags(self):
256
329
        tree = self.make_linear_branch(format='dirstate-tags')
257
330
        branch = tree.branch
282
355
        log = self.run_bzr("log -n0 -r3.1.1", working_dir='branch2')[0]
283
356
        self.assertContainsRe(log, r'tags: tag1')
284
357
 
285
 
    def test_log_limit(self):
286
 
        tree = self.make_branch_and_tree('.')
287
 
        # We want more commits than our batch size starts at
288
 
        for pos in range(10):
289
 
            tree.commit("%s" % pos)
290
 
        log = self.run_bzr("log --limit 2")[0]
291
 
        self.assertNotContainsRe(log, r'revno: 1\n')
292
 
        self.assertNotContainsRe(log, r'revno: 2\n')
293
 
        self.assertNotContainsRe(log, r'revno: 3\n')
294
 
        self.assertNotContainsRe(log, r'revno: 4\n')
295
 
        self.assertNotContainsRe(log, r'revno: 5\n')
296
 
        self.assertNotContainsRe(log, r'revno: 6\n')
297
 
        self.assertNotContainsRe(log, r'revno: 7\n')
298
 
        self.assertNotContainsRe(log, r'revno: 8\n')
299
 
        self.assertContainsRe(log, r'revno: 9\n')
300
 
        self.assertContainsRe(log, r'revno: 10\n')
301
 
 
302
 
    def test_log_limit_short(self):
303
 
        self.make_linear_branch()
304
 
        log = self.run_bzr("log -l 2")[0]
305
 
        self.assertNotContainsRe(log, r'revno: 1\n')
306
 
        self.assertContainsRe(log, r'revno: 2\n')
307
 
        self.assertContainsRe(log, r'revno: 3\n')
308
 
 
309
 
    def test_log_bad_message_re(self):
310
 
        """Bad --message argument gives a sensible message
311
 
        
312
 
        See https://bugs.launchpad.net/bzr/+bug/251352
313
 
        """
314
 
        self.make_minimal_branch()
315
 
        out, err = self.run_bzr(['log', '-m', '*'], retcode=3)
316
 
        self.assertEqual("bzr: ERROR: Invalid regular expression"
317
 
            " in log message filter"
318
 
            ": '*'"
319
 
            ": nothing to repeat\n", err)
320
 
        self.assertEqual('', out)
321
 
 
322
 
 
323
 
class TestLogTimeZone(TestLog):
324
 
 
325
 
    def test_log_unsupported_timezone(self):
326
 
        self.make_linear_branch()
327
 
        self.run_bzr_error(['bzr: ERROR: Unsupported timezone format "foo", '
328
 
                            'options are "utc", "original", "local".'],
329
 
                           ['log', '--timezone', 'foo'])
330
 
 
331
358
 
332
359
class TestLogVerbose(TestLog):
333
360
 
364
391
        self.assertUseLongDeltaFormat(['log', '--long', '-vv'])
365
392
 
366
393
 
367
 
class TestLogMerges(TestLog):
 
394
class TestLogMerges(TestLogWithLogCatcher):
368
395
 
369
396
    def setUp(self):
370
397
        super(TestLogMerges, self).setUp()
372
399
 
373
400
    def make_branches_with_merges(self):
374
401
        level0 = self.make_branch_and_tree('level0')
375
 
        level0.commit(message='in branch level0', **self.commit_options())
376
 
 
 
402
        self.wt_commit(level0, 'in branch level0')
377
403
        level1 = level0.bzrdir.sprout('level1').open_workingtree()
378
 
        level1.commit(message='in branch level1', **self.commit_options())
379
 
 
 
404
        self.wt_commit(level1, 'in branch level1')
380
405
        level2 = level1.bzrdir.sprout('level2').open_workingtree()
381
 
        level2.commit(message='in branch level2', **self.commit_options())
382
 
 
 
406
        self.wt_commit(level2, 'in branch level2')
383
407
        level1.merge_from_branch(level2.branch)
384
 
        level1.commit(message='merge branch level2', **self.commit_options())
385
 
 
 
408
        self.wt_commit(level1, 'merge branch level2')
386
409
        level0.merge_from_branch(level1.branch)
387
 
        level0.commit(message='merge branch level1', **self.commit_options())
 
410
        self.wt_commit(level0, 'merge branch level1')
388
411
 
389
412
    def test_merges_are_indented_by_level(self):
390
 
        expected = """\
391
 
------------------------------------------------------------
392
 
revno: 2 [merge]
393
 
committer: Lorem Ipsum <test@example.com>
394
 
branch nick: level0
395
 
timestamp: Just now
396
 
message:
397
 
  merge branch level1
398
 
    ------------------------------------------------------------
399
 
    revno: 1.1.2 [merge]
400
 
    committer: Lorem Ipsum <test@example.com>
401
 
    branch nick: level1
402
 
    timestamp: Just now
403
 
    message:
404
 
      merge branch level2
405
 
        ------------------------------------------------------------
406
 
        revno: 1.2.1
407
 
        committer: Lorem Ipsum <test@example.com>
408
 
        branch nick: level2
409
 
        timestamp: Just now
410
 
        message:
411
 
          in branch level2
412
 
    ------------------------------------------------------------
413
 
    revno: 1.1.1
414
 
    committer: Lorem Ipsum <test@example.com>
415
 
    branch nick: level1
416
 
    timestamp: Just now
417
 
    message:
418
 
      in branch level1
419
 
------------------------------------------------------------
420
 
revno: 1
421
 
committer: Lorem Ipsum <test@example.com>
422
 
branch nick: level0
423
 
timestamp: Just now
424
 
message:
425
 
  in branch level0
426
 
"""
427
 
        self.check_log(expected, ['-n0'])
 
413
        self.run_bzr(['log', '-n0'], working_dir='level0')
 
414
        revnos_and_depth = [(r.revno, r.merge_depth)
 
415
                            for r in self.get_captured_revisions()]
 
416
        self.assertEqual([('2', 0), ('1.1.2', 1), ('1.2.1', 2), ('1.1.1', 1),
 
417
                          ('1', 0)],
 
418
                         [(r.revno, r.merge_depth)
 
419
                            for r in self.get_captured_revisions()])
428
420
 
429
421
    def test_force_merge_revisions_off(self):
430
 
        expected = """\
431
 
------------------------------------------------------------
432
 
revno: 2 [merge]
433
 
committer: Lorem Ipsum <test@example.com>
434
 
branch nick: level0
435
 
timestamp: Just now
436
 
message:
437
 
  merge branch level1
438
 
------------------------------------------------------------
439
 
revno: 1
440
 
committer: Lorem Ipsum <test@example.com>
441
 
branch nick: level0
442
 
timestamp: Just now
443
 
message:
444
 
  in branch level0
445
 
"""
446
 
        self.check_log(expected, ['--long', '-n1'])
 
422
        self.assertLogRevnos(['-n1'], ['2', '1'], working_dir='level0')
447
423
 
448
424
    def test_force_merge_revisions_on(self):
449
 
        expected = """\
450
 
    2 Lorem Ipsum\t2005-11-22 [merge]
451
 
      merge branch level1
452
 
 
453
 
          1.1.2 Lorem Ipsum\t2005-11-22 [merge]
454
 
                merge branch level2
455
 
 
456
 
              1.2.1 Lorem Ipsum\t2005-11-22
457
 
                    in branch level2
458
 
 
459
 
          1.1.1 Lorem Ipsum\t2005-11-22
460
 
                in branch level1
461
 
 
462
 
    1 Lorem Ipsum\t2005-11-22
463
 
      in branch level0
464
 
 
465
 
"""
466
 
        self.check_log(expected, ['--short', '-n0'])
 
425
        self.assertLogRevnos(['-n0'], ['2', '1.1.2', '1.2.1', '1.1.1', '1'],
 
426
                             working_dir='level0')
467
427
 
468
428
    def test_include_merges(self):
469
429
        # Confirm --include-merges gives the same output as -n0
 
430
        self.assertLogRevnos(['--include-merges'],
 
431
                             ['2', '1.1.2', '1.2.1', '1.1.1', '1'],
 
432
                             working_dir='level0')
 
433
        self.assertLogRevnos(['--include-merges'],
 
434
                             ['2', '1.1.2', '1.2.1', '1.1.1', '1'],
 
435
                             working_dir='level0')
470
436
        out_im, err_im = self.run_bzr('log --include-merges',
471
437
                                      working_dir='level0')
472
438
        out_n0, err_n0 = self.run_bzr('log -n0', working_dir='level0')
475
441
        self.assertEqual(out_im, out_n0)
476
442
 
477
443
    def test_force_merge_revisions_N(self):
478
 
        expected = """\
479
 
    2 Lorem Ipsum\t2005-11-22 [merge]
480
 
      merge branch level1
481
 
 
482
 
          1.1.2 Lorem Ipsum\t2005-11-22 [merge]
483
 
                merge branch level2
484
 
 
485
 
          1.1.1 Lorem Ipsum\t2005-11-22
486
 
                in branch level1
487
 
 
488
 
    1 Lorem Ipsum\t2005-11-22
489
 
      in branch level0
490
 
 
491
 
"""
492
 
        self.check_log(expected, ['--short', '-n2'])
 
444
        self.assertLogRevnos(['-n2'],
 
445
                             ['2', '1.1.2', '1.1.1', '1'],
 
446
                             working_dir='level0')
493
447
 
494
448
    def test_merges_single_merge_rev(self):
495
 
        expected = """\
496
 
------------------------------------------------------------
497
 
revno: 1.1.2 [merge]
498
 
committer: Lorem Ipsum <test@example.com>
499
 
branch nick: level1
500
 
timestamp: Just now
501
 
message:
502
 
  merge branch level2
503
 
    ------------------------------------------------------------
504
 
    revno: 1.2.1
505
 
    committer: Lorem Ipsum <test@example.com>
506
 
    branch nick: level2
507
 
    timestamp: Just now
508
 
    message:
509
 
      in branch level2
510
 
"""
511
 
        self.check_log(expected, ['-n0', '-r1.1.2'])
 
449
        self.assertLogRevnosAndDepths(['-n0', '-r1.1.2'],
 
450
                                      [('1.1.2', 0), ('1.2.1', 1)],
 
451
                                      working_dir='level0')
512
452
 
513
453
    def test_merges_partial_range(self):
514
 
        expected = """\
515
 
------------------------------------------------------------
516
 
revno: 1.1.2 [merge]
517
 
committer: Lorem Ipsum <test@example.com>
518
 
branch nick: level1
519
 
timestamp: Just now
520
 
message:
521
 
  merge branch level2
522
 
    ------------------------------------------------------------
523
 
    revno: 1.2.1
524
 
    committer: Lorem Ipsum <test@example.com>
525
 
    branch nick: level2
526
 
    timestamp: Just now
527
 
    message:
528
 
      in branch level2
529
 
------------------------------------------------------------
530
 
revno: 1.1.1
531
 
committer: Lorem Ipsum <test@example.com>
532
 
branch nick: level1
533
 
timestamp: Just now
534
 
message:
535
 
  in branch level1
536
 
"""
537
 
        self.check_log(expected, ['-n0', '-r1.1.1..1.1.2'])
 
454
        self.assertLogRevnosAndDepths(
 
455
                ['-n0', '-r1.1.1..1.1.2'],
 
456
                [('1.1.2', 0), ('1.2.1', 1), ('1.1.1', 0)],
 
457
                working_dir='level0')
538
458
 
539
459
    def test_merges_partial_range_ignore_before_lower_bound(self):
540
460
        """Dont show revisions before the lower bound's merged revs"""
541
 
        expected = """\
542
 
    2 Lorem Ipsum\t2005-11-22 [merge]
543
 
      merge branch level1
544
 
 
545
 
          1.1.2 Lorem Ipsum\t2005-11-22 [merge]
546
 
                merge branch level2
547
 
 
548
 
              1.2.1 Lorem Ipsum\t2005-11-22
549
 
                    in branch level2
550
 
 
551
 
"""
552
 
        self.check_log(expected, ['--short', '-n0', '-r1.1.2..2'])
553
 
 
554
 
 
555
 
class TestLogDiff(TestLog):
 
461
        self.assertLogRevnosAndDepths(
 
462
                ['-n0', '-r1.1.2..2'],
 
463
                [('2', 0), ('1.1.2', 1), ('1.2.1', 2)],
 
464
                working_dir='level0')
 
465
 
 
466
 
 
467
class TestLogDiff(TestLogWithLogCatcher):
 
468
 
 
469
    # FIXME: We need specific tests for each LogFormatter about how the diffs
 
470
    # are displayed: --long indent them by depth, --short use a fixed
 
471
    # indent and --line does't display them. -- vila 10019
556
472
 
557
473
    def setUp(self):
558
474
        super(TestLogDiff, self).setUp()
563
479
        self.build_tree(['level0/file1', 'level0/file2'])
564
480
        level0.add('file1')
565
481
        level0.add('file2')
566
 
        level0.commit(message='in branch level0', **self.commit_options())
 
482
        self.wt_commit(level0, 'in branch level0')
567
483
 
568
484
        level1 = level0.bzrdir.sprout('level1').open_workingtree()
569
485
        self.build_tree_contents([('level1/file2', 'hello\n')])
570
 
        level1.commit(message='in branch level1', **self.commit_options())
 
486
        self.wt_commit(level1, 'in branch level1')
571
487
        level0.merge_from_branch(level1.branch)
572
 
        level0.commit(message='merge branch level1', **self.commit_options())
 
488
        self.wt_commit(level0, 'merge branch level1')
573
489
 
574
 
    def test_log_show_diff_long_with_merges(self):
575
 
        out,err = self.run_bzr('log -p -n0')
576
 
        self.assertEqual('', err)
577
 
        log = test_log.normalize_log(out)
578
 
        expected = """\
579
 
------------------------------------------------------------
580
 
revno: 2 [merge]
581
 
committer: Lorem Ipsum <test@example.com>
582
 
branch nick: level0
583
 
timestamp: Just now
584
 
message:
585
 
  merge branch level1
586
 
diff:
587
 
=== modified file 'file2'
588
 
--- file2\t2005-11-22 00:00:01 +0000
589
 
+++ file2\t2005-11-22 00:00:02 +0000
590
 
@@ -1,1 +1,1 @@
591
 
-contents of level0/file2
592
 
+hello
593
 
    ------------------------------------------------------------
594
 
    revno: 1.1.1
595
 
    committer: Lorem Ipsum <test@example.com>
596
 
    branch nick: level1
597
 
    timestamp: Just now
598
 
    message:
599
 
      in branch level1
600
 
    diff:
601
 
    === modified file 'file2'
602
 
    --- file2\t2005-11-22 00:00:01 +0000
603
 
    +++ file2\t2005-11-22 00:00:02 +0000
604
 
    @@ -1,1 +1,1 @@
605
 
    -contents of level0/file2
606
 
    +hello
607
 
------------------------------------------------------------
608
 
revno: 1
609
 
committer: Lorem Ipsum <test@example.com>
610
 
branch nick: level0
611
 
timestamp: Just now
612
 
message:
613
 
  in branch level0
614
 
diff:
615
 
=== added file 'file1'
 
490
    def _diff_file1_revno1(self):
 
491
        return """=== added file 'file1'
616
492
--- file1\t1970-01-01 00:00:00 +0000
617
 
+++ file1\t2005-11-22 00:00:01 +0000
 
493
+++ file1\t2005-11-22 00:00:00 +0000
618
494
@@ -0,0 +1,1 @@
619
495
+contents of level0/file1
620
496
 
621
 
=== added file 'file2'
 
497
"""
 
498
 
 
499
    def _diff_file2_revno2(self):
 
500
        return """=== modified file 'file2'
 
501
--- file2\t2005-11-22 00:00:00 +0000
 
502
+++ file2\t2005-11-22 00:00:01 +0000
 
503
@@ -1,1 +1,1 @@
 
504
-contents of level0/file2
 
505
+hello
 
506
 
 
507
"""
 
508
 
 
509
    def _diff_file2_revno1_1_1(self):
 
510
        return """=== modified file 'file2'
 
511
--- file2\t2005-11-22 00:00:00 +0000
 
512
+++ file2\t2005-11-22 00:00:01 +0000
 
513
@@ -1,1 +1,1 @@
 
514
-contents of level0/file2
 
515
+hello
 
516
 
 
517
"""
 
518
 
 
519
    def _diff_file2_revno1(self):
 
520
        return """=== added file 'file2'
622
521
--- file2\t1970-01-01 00:00:00 +0000
623
 
+++ file2\t2005-11-22 00:00:01 +0000
 
522
+++ file2\t2005-11-22 00:00:00 +0000
624
523
@@ -0,0 +1,1 @@
625
524
+contents of level0/file2
626
 
"""
627
 
        self.check_log(expected, ['-p', '-n0'])
628
 
 
629
 
    def test_log_show_diff_short(self):
630
 
        expected = """\
631
 
    2 Lorem Ipsum\t2005-11-22 [merge]
632
 
      merge branch level1
633
 
      === modified file 'file2'
634
 
      --- file2\t2005-11-22 00:00:01 +0000
635
 
      +++ file2\t2005-11-22 00:00:02 +0000
636
 
      @@ -1,1 +1,1 @@
637
 
      -contents of level0/file2
638
 
      +hello
639
 
 
640
 
    1 Lorem Ipsum\t2005-11-22
641
 
      in branch level0
642
 
      === added file 'file1'
643
 
      --- file1\t1970-01-01 00:00:00 +0000
644
 
      +++ file1\t2005-11-22 00:00:01 +0000
645
 
      @@ -0,0 +1,1 @@
646
 
      +contents of level0/file1
647
 
\x20\x20\x20\x20\x20\x20
648
 
      === added file 'file2'
649
 
      --- file2\t1970-01-01 00:00:00 +0000
650
 
      +++ file2\t2005-11-22 00:00:01 +0000
651
 
      @@ -0,0 +1,1 @@
652
 
      +contents of level0/file2
653
 
 
654
 
Use --include-merges or -n0 to see merged revisions.
655
 
"""
656
 
        self.check_log(expected, ['-p', '--short'])
657
 
 
658
 
    def test_log_show_diff_line(self):
659
 
        # Not supported by this formatter so expect plain output
660
 
        expected = """\
661
 
2: Lorem Ipsum 2005-11-22 [merge] merge branch level1
662
 
1: Lorem Ipsum 2005-11-22 in branch level0
663
 
"""
664
 
        self.check_log(expected, ['-p', '--line'])
665
 
 
666
 
    def test_log_show_diff_file1(self):
667
 
        """Only the diffs for the given file are to be shown"""
668
 
        expected = """\
669
 
    1 Lorem Ipsum\t2005-11-22
670
 
      in branch level0
671
 
      === added file 'file1'
672
 
      --- file1\t1970-01-01 00:00:00 +0000
673
 
      +++ file1\t2005-11-22 00:00:01 +0000
674
 
      @@ -0,0 +1,1 @@
675
 
      +contents of level0/file1
676
 
 
677
 
"""
678
 
        self.check_log(expected, ['-p', '--short', 'file1'])
679
 
 
680
 
    def test_log_show_diff_file2(self):
681
 
        """Only the diffs for the given file are to be shown"""
682
 
        expected = """\
683
 
    2 Lorem Ipsum\t2005-11-22 [merge]
684
 
      merge branch level1
685
 
      === modified file 'file2'
686
 
      --- file2\t2005-11-22 00:00:01 +0000
687
 
      +++ file2\t2005-11-22 00:00:02 +0000
688
 
      @@ -1,1 +1,1 @@
689
 
      -contents of level0/file2
690
 
      +hello
691
 
 
692
 
    1 Lorem Ipsum\t2005-11-22
693
 
      in branch level0
694
 
      === added file 'file2'
695
 
      --- file2\t1970-01-01 00:00:00 +0000
696
 
      +++ file2\t2005-11-22 00:00:01 +0000
697
 
      @@ -0,0 +1,1 @@
698
 
      +contents of level0/file2
699
 
 
700
 
Use --include-merges or -n0 to see merged revisions.
701
 
"""
702
 
        self.check_log(expected, ['-p', '--short', 'file2'])
 
525
 
 
526
"""
 
527
 
 
528
    def assertLogRevnosAndDiff(self, args, expected,
 
529
                            working_dir='.'):
 
530
        self.run_bzr(['log', '-p'] + args, working_dir=working_dir)
 
531
        expected_revnos_and_depths = [
 
532
            (revno, depth) for revno, depth, diff in expected]
 
533
        # Check the revnos and depths first to make debugging easier
 
534
        self.assertEqual(expected_revnos_and_depths,
 
535
                         [(r.revno, r.merge_depth)
 
536
                           for r in self.get_captured_revisions()])
 
537
        # Now check the diffs, adding the revno  in case of failure
 
538
        fmt = 'In revno %s\n%s'
 
539
        for expected_rev, actual_rev in izip(expected,
 
540
                                             self.get_captured_revisions()):
 
541
            revno, depth, expected_diff = expected_rev
 
542
            actual_diff = actual_rev.diff
 
543
            self.assertEqualDiff(fmt % (revno, expected_diff),
 
544
                                 fmt % (revno, actual_diff))
 
545
 
 
546
    def test_log_diff_with_merges(self):
 
547
        self.assertLogRevnosAndDiff(
 
548
            ['-n0'],
 
549
            [('2', 0, self._diff_file2_revno2()),
 
550
             ('1.1.1', 1, self._diff_file2_revno1_1_1()),
 
551
             ('1', 0, self._diff_file1_revno1()
 
552
              + self._diff_file2_revno1())],
 
553
            working_dir='level0')
 
554
 
 
555
 
 
556
    def test_log_diff_file1(self):
 
557
        self.assertLogRevnosAndDiff(['-n0', 'file1'],
 
558
                                    [('1', 0, self._diff_file1_revno1())],
 
559
                                    working_dir='level0')
 
560
 
 
561
    def test_log_diff_file2(self):
 
562
        self.assertLogRevnosAndDiff(['-n1', 'file2'],
 
563
                                    [('2', 0, self._diff_file2_revno2()),
 
564
                                     ('1', 0, self._diff_file2_revno1())],
 
565
                                    working_dir='level0')
703
566
 
704
567
 
705
568
class TestLogUnicodeDiff(TestLog):
756
619
    def create_branch(self):
757
620
        bzr = self.run_bzr
758
621
        bzr('init')
759
 
        open('a', 'wb').write('some stuff\n')
 
622
        self.build_tree_contents([('a', 'some stuff\n')])
760
623
        bzr('add a')
761
624
        bzr(['commit', '-m', self._message])
762
625
 
825
688
        self.assertEquals(-1, stdout.find(test_in_cp1251))
826
689
 
827
690
 
828
 
class TestLogFile(tests.TestCaseWithTransport):
 
691
class TestLogFile(TestLogWithLogCatcher):
829
692
 
830
693
    def test_log_local_branch_file(self):
831
694
        """We should be able to log files in local treeless branches"""
860
723
            tree.commit('remove file1')
861
724
        os.chdir('parent')
862
725
 
863
 
    def test_log_file(self):
864
 
        """The log for a particular file should only list revs for that file"""
865
 
        self.prepare_tree()
866
 
        log = self.run_bzr('log -n0 file1')[0]
867
 
        self.assertContainsRe(log, 'revno: 1\n')
868
 
        self.assertNotContainsRe(log, 'revno: 2\n')
869
 
        self.assertNotContainsRe(log, 'revno: 3\n')
870
 
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
871
 
        self.assertNotContainsRe(log, 'revno: 4 ')
872
 
        log = self.run_bzr('log -n0 file2')[0]
873
 
        self.assertNotContainsRe(log, 'revno: 1\n')
874
 
        self.assertContainsRe(log, 'revno: 2\n')
875
 
        self.assertNotContainsRe(log, 'revno: 3\n')
876
 
        self.assertContainsRe(log, 'revno: 3.1.1\n')
877
 
        self.assertContainsRe(log, 'revno: 4 ')
878
 
        log = self.run_bzr('log -n0 file3')[0]
879
 
        self.assertNotContainsRe(log, 'revno: 1\n')
880
 
        self.assertNotContainsRe(log, 'revno: 2\n')
881
 
        self.assertContainsRe(log, 'revno: 3\n')
882
 
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
883
 
        self.assertNotContainsRe(log, 'revno: 4 ')
884
 
        log = self.run_bzr('log -n0 -r3.1.1 file2')[0]
885
 
        self.assertNotContainsRe(log, 'revno: 1\n')
886
 
        self.assertNotContainsRe(log, 'revno: 2\n')
887
 
        self.assertNotContainsRe(log, 'revno: 3\n')
888
 
        self.assertContainsRe(log, 'revno: 3.1.1\n')
889
 
        self.assertNotContainsRe(log, 'revno: 4 ')
890
 
        log = self.run_bzr('log -n0 -r4 file2')[0]
891
 
        self.assertNotContainsRe(log, 'revno: 1\n')
892
 
        self.assertNotContainsRe(log, 'revno: 2\n')
893
 
        self.assertNotContainsRe(log, 'revno: 3\n')
894
 
        self.assertContainsRe(log, 'revno: 3.1.1\n')
895
 
        self.assertContainsRe(log, 'revno: 4 ')
896
 
        log = self.run_bzr('log -n0 -r3.. file2')[0]
897
 
        self.assertNotContainsRe(log, 'revno: 1\n')
898
 
        self.assertNotContainsRe(log, 'revno: 2\n')
899
 
        self.assertNotContainsRe(log, 'revno: 3\n')
900
 
        self.assertContainsRe(log, 'revno: 3.1.1\n')
901
 
        self.assertContainsRe(log, 'revno: 4 ')
902
 
        log = self.run_bzr('log -n0 -r..3 file2')[0]
903
 
        self.assertNotContainsRe(log, 'revno: 1\n')
904
 
        self.assertContainsRe(log, 'revno: 2\n')
905
 
        self.assertNotContainsRe(log, 'revno: 3\n')
906
 
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
907
 
        self.assertNotContainsRe(log, 'revno: 4 ')
 
726
    # FIXME: It would be good to parametrize the following tests against all
 
727
    # formatters. But the revisions selection is not *currently* part of the
 
728
    # LogFormatter contract, so using LogCatcher is sufficient -- vila 100118
 
729
    def test_log_file1(self):
 
730
        self.prepare_tree()
 
731
        self.assertLogRevnos(['-n0', 'file1'], ['1'])
 
732
 
 
733
    def test_log_file2(self):
 
734
        self.prepare_tree()
 
735
        # file2 full history
 
736
        self.assertLogRevnos(['-n0', 'file2'], ['4', '3.1.1', '2'])
 
737
        # file2 in a merge revision
 
738
        self.assertLogRevnos(['-n0', '-r3.1.1', 'file2'], ['3.1.1'])
 
739
        # file2 in a mainline revision
 
740
        self.assertLogRevnos(['-n0', '-r4', 'file2'], ['4', '3.1.1'])
 
741
        # file2 since a revision
 
742
        self.assertLogRevnos(['-n0', '-r3..', 'file2'], ['4', '3.1.1'])
 
743
        # file2 up to a revision
 
744
        self.assertLogRevnos(['-n0', '-r..3', 'file2'], ['2'])
 
745
 
 
746
    def test_log_file3(self):
 
747
        self.prepare_tree()
 
748
        self.assertLogRevnos(['-n0', 'file3'], ['3'])
908
749
 
909
750
    def test_log_file_historical_missing(self):
910
751
        # Check logging a deleted file gives an error if the
918
759
        # Check logging a deleted file is ok if the file existed
919
760
        # at the end the revision range
920
761
        self.prepare_tree(complex=True)
921
 
        log, err = self.run_bzr('log -n0 -r..4 file2')
922
 
        self.assertEquals('', err)
923
 
        self.assertNotContainsRe(log, 'revno: 1\n')
924
 
        self.assertContainsRe(log, 'revno: 2\n')
925
 
        self.assertNotContainsRe(log, 'revno: 3\n')
926
 
        self.assertContainsRe(log, 'revno: 3.1.1\n')
927
 
        self.assertContainsRe(log, 'revno: 4 ')
 
762
        self.assertLogRevnos(['-n0', '-r..4', 'file2'], ['4', '3.1.1', '2'])
928
763
 
929
764
    def test_log_file_historical_start(self):
930
765
        # Check logging a deleted file is ok if the file existed
931
766
        # at the start of the revision range
932
767
        self.prepare_tree(complex=True)
933
 
        log, err = self.run_bzr('log file1')
934
 
        self.assertEquals('', err)
935
 
        self.assertContainsRe(log, 'revno: 1\n')
936
 
        self.assertNotContainsRe(log, 'revno: 2\n')
937
 
        self.assertNotContainsRe(log, 'revno: 3\n')
938
 
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
939
 
        self.assertNotContainsRe(log, 'revno: 4 ')
 
768
        self.assertLogRevnos(['file1'], ['1'])
940
769
 
941
770
    def test_log_file_renamed(self):
942
771
        """File matched against revision range, not current tree."""
948
777
        self.assertContainsRe(err, err_msg)
949
778
 
950
779
        # Check we can see a renamed file if we give the right end revision
951
 
        log, err = self.run_bzr('log -r..4 file3')
952
 
        self.assertEquals('', err)
953
 
        self.assertNotContainsRe(log, 'revno: 1\n')
954
 
        self.assertNotContainsRe(log, 'revno: 2\n')
955
 
        self.assertContainsRe(log, 'revno: 3\n')
956
 
        self.assertNotContainsRe(log, 'revno: 3.1.1\n')
957
 
        self.assertNotContainsRe(log, 'revno: 4 ')
958
 
 
959
 
    def test_line_log_file(self):
960
 
        """The line log for a file should only list relevant mainline revs"""
961
 
        # Note: this also implicitly  covers the short logging case.
962
 
        # We test using --line in preference to --short because matching
963
 
        # revnos in the output of --line is more reliable.
964
 
        self.prepare_tree()
965
 
 
966
 
        # full history of file1
967
 
        log = self.run_bzr('log --line file1')[0]
968
 
        self.assertContainsRe(log, '^1:', re.MULTILINE)
969
 
        self.assertNotContainsRe(log, '^2:', re.MULTILINE)
970
 
        self.assertNotContainsRe(log, '^3:', re.MULTILINE)
971
 
        self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
972
 
        self.assertNotContainsRe(log, '^4:', re.MULTILINE)
973
 
 
974
 
        # full history of file2
975
 
        log = self.run_bzr('log --line file2')[0]
976
 
        self.assertNotContainsRe(log, '^1:', re.MULTILINE)
977
 
        self.assertContainsRe(log, '^2:', re.MULTILINE)
978
 
        self.assertNotContainsRe(log, '^3:', re.MULTILINE)
979
 
        self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
980
 
        self.assertContainsRe(log, '^4:', re.MULTILINE)
981
 
 
982
 
        # full history of file3
983
 
        log = self.run_bzr('log --line file3')[0]
984
 
        self.assertNotContainsRe(log, '^1:', re.MULTILINE)
985
 
        self.assertNotContainsRe(log, '^2:', re.MULTILINE)
986
 
        self.assertContainsRe(log, '^3:', re.MULTILINE)
987
 
        self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
988
 
        self.assertNotContainsRe(log, '^4:', re.MULTILINE)
989
 
 
990
 
        # file in a merge revision
991
 
        log = self.run_bzr('log --line -r3.1.1 file2')[0]
992
 
        self.assertNotContainsRe(log, '^1:', re.MULTILINE)
993
 
        self.assertNotContainsRe(log, '^2:', re.MULTILINE)
994
 
        self.assertNotContainsRe(log, '^3:', re.MULTILINE)
995
 
        self.assertContainsRe(log, '^3.1.1:', re.MULTILINE)
996
 
        self.assertNotContainsRe(log, '^4:', re.MULTILINE)
997
 
 
998
 
        # file in a mainline revision
999
 
        log = self.run_bzr('log --line -r4 file2')[0]
1000
 
        self.assertNotContainsRe(log, '^1:', re.MULTILINE)
1001
 
        self.assertNotContainsRe(log, '^2:', re.MULTILINE)
1002
 
        self.assertNotContainsRe(log, '^3:', re.MULTILINE)
1003
 
        self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
1004
 
        self.assertContainsRe(log, '^4:', re.MULTILINE)
1005
 
 
1006
 
        # file since a revision
1007
 
        log = self.run_bzr('log --line -r3.. file2')[0]
1008
 
        self.assertNotContainsRe(log, '^1:', re.MULTILINE)
1009
 
        self.assertNotContainsRe(log, '^2:', re.MULTILINE)
1010
 
        self.assertNotContainsRe(log, '^3:', re.MULTILINE)
1011
 
        self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
1012
 
        self.assertContainsRe(log, '^4:', re.MULTILINE)
1013
 
 
1014
 
        # file up to a revision
1015
 
        log = self.run_bzr('log --line -r..3 file2')[0]
1016
 
        self.assertNotContainsRe(log, '^1:', re.MULTILINE)
1017
 
        self.assertContainsRe(log, '^2:', re.MULTILINE)
1018
 
        self.assertNotContainsRe(log, '^3:', re.MULTILINE)
1019
 
        self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
1020
 
        self.assertNotContainsRe(log, '^4:', re.MULTILINE)
1021
 
 
1022
 
 
1023
 
class TestLogMultiple(tests.TestCaseWithTransport):
 
780
        self.assertLogRevnos(['-r..4', 'file3'], ['3'])
 
781
 
 
782
 
 
783
class TestLogMultiple(TestLogWithLogCatcher):
1024
784
 
1025
785
    def prepare_tree(self):
1026
786
        tree = self.make_branch_and_tree('parent')
1049
809
        tree.commit(message='merge child branch')
1050
810
        os.chdir('parent')
1051
811
 
1052
 
    def assertRevnos(self, paths_str, expected_revnos):
1053
 
        # confirm the revision numbers in log --line output are those expected
1054
 
        out, err = self.run_bzr('log --line -n0 %s' % (paths_str,))
1055
 
        self.assertEqual('', err)
1056
 
        revnos = [s.split(':', 1)[0].lstrip() for s in out.splitlines()]
1057
 
        self.assertEqual(expected_revnos, revnos)
1058
 
 
1059
812
    def test_log_files(self):
1060
813
        """The log for multiple file should only list revs for those files"""
1061
814
        self.prepare_tree()
1062
 
        self.assertRevnos('file1 file2 dir1/dir2/file3',
1063
 
            ['6', '5.1.1', '3', '2', '1'])
 
815
        self.assertLogRevnos(['file1', 'file2', 'dir1/dir2/file3'],
 
816
                             ['6', '5.1.1', '3', '2', '1'])
1064
817
 
1065
818
    def test_log_directory(self):
1066
819
        """The log for a directory should show all nested files."""
1067
820
        self.prepare_tree()
1068
 
        self.assertRevnos('dir1', ['5', '3'])
 
821
        self.assertLogRevnos(['dir1'], ['5', '3'])
1069
822
 
1070
823
    def test_log_nested_directory(self):
1071
824
        """The log for a directory should show all nested files."""
1072
825
        self.prepare_tree()
1073
 
        self.assertRevnos('dir1/dir2', ['3'])
 
826
        self.assertLogRevnos(['dir1/dir2'], ['3'])
1074
827
 
1075
828
    def test_log_in_nested_directory(self):
1076
829
        """The log for a directory should show all nested files."""
1077
830
        self.prepare_tree()
1078
831
        os.chdir("dir1")
1079
 
        self.assertRevnos('.', ['5', '3'])
 
832
        self.assertLogRevnos(['.'], ['5', '3'])
1080
833
 
1081
834
    def test_log_files_and_directories(self):
1082
835
        """Logging files and directories together should be fine."""
1083
836
        self.prepare_tree()
1084
 
        self.assertRevnos('file4 dir1/dir2', ['4', '3'])
 
837
        self.assertLogRevnos(['file4', 'dir1/dir2'], ['4', '3'])
1085
838
 
1086
839
    def test_log_files_and_dirs_in_nested_directory(self):
1087
840
        """The log for a directory should show all nested files."""
1088
841
        self.prepare_tree()
1089
842
        os.chdir("dir1")
1090
 
        self.assertRevnos('dir2 file5', ['5', '3'])
 
843
        self.assertLogRevnos(['dir2', 'file5'], ['5', '3'])