/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

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

  • Committer: Andrew Bennetts
  • Date: 2009-06-17 02:02:44 UTC
  • mfrom: (4449 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4452.
  • Revision ID: andrew.bennetts@canonical.com-20090617020244-50aantdf95aakvjx
Merge bzr.dev, resolving NEWS conflict.

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
 
import os, re
 
20
import os
 
21
import re
21
22
 
22
 
from bzrlib import osutils
23
 
from bzrlib.tests.blackbox import ExternalBase
24
 
from bzrlib.tests import KnownFailure, TestCaseInTempDir, TestCaseWithTransport
25
 
from bzrlib.tests.test_log import (
26
 
    normalize_log,
 
23
from bzrlib import (
 
24
    osutils,
 
25
    tests,
27
26
    )
28
27
from bzrlib.tests import test_log
29
28
 
30
29
 
31
 
class TestCaseWithoutPropsHandler(ExternalBase,
32
 
                                  test_log.TestCaseWithoutPropsHandler):
33
 
    pass
34
 
 
35
 
 
36
 
class TestLog(ExternalBase):
37
 
 
38
 
    def _prepare(self, path='.', format=None):
 
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
 
36
 
 
37
    def make_minimal_branch(self, path='.', format=None):
 
38
        tree = self.make_branch_and_tree(path, format=format)
 
39
        self.build_tree([path + '/hello.txt'])
 
40
        tree.add('hello.txt')
 
41
        tree.commit(message='message1')
 
42
        return tree
 
43
 
 
44
    def make_linear_branch(self, path='.', format=None):
39
45
        tree = self.make_branch_and_tree(path, format=format)
40
46
        self.build_tree(
41
47
            [path + '/hello.txt', path + '/goodbye.txt', path + '/meep.txt'])
45
51
        tree.commit(message='message2')
46
52
        tree.add('meep.txt')
47
53
        tree.commit(message='message3')
48
 
        self.full_log = self.run_bzr(["log", path])[0]
49
 
        return tree
 
54
        return tree
 
55
 
 
56
    def make_merged_branch(self, path='.', format=None):
 
57
        tree = self.make_linear_branch(path, format)
 
58
        tree2 = tree.bzrdir.sprout('tree2',
 
59
            revision_id=tree.branch.get_rev_id(1)).open_workingtree()
 
60
        tree2.commit(message='tree2 message2')
 
61
        tree2.commit(message='tree2 message3')
 
62
        tree.merge_from_branch(tree2.branch)
 
63
        tree.commit(message='merge')
 
64
        return tree
 
65
 
 
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):
50
95
 
51
96
    def test_log_null_end_revspec(self):
52
 
        self._prepare()
53
 
        self.assertTrue('revno: 1\n' in self.full_log)
54
 
        self.assertTrue('revno: 2\n' in self.full_log)
55
 
        self.assertTrue('revno: 3\n' in self.full_log)
56
 
        self.assertTrue('message:\n  message1\n' in self.full_log)
57
 
        self.assertTrue('message:\n  message2\n' in self.full_log)
58
 
        self.assertTrue('message:\n  message3\n' in self.full_log)
 
97
        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)
59
105
 
 
106
        full_log = self.run_bzr(['log'])[0]
60
107
        log = self.run_bzr("log -r 1..")[0]
61
 
        self.assertEqualDiff(log, self.full_log)
 
108
        self.assertEqualDiff(log, full_log)
62
109
 
63
110
    def test_log_null_begin_revspec(self):
64
 
        self._prepare()
 
111
        self.make_linear_branch()
 
112
        full_log = self.run_bzr(['log'])[0]
65
113
        log = self.run_bzr("log -r ..3")[0]
66
 
        self.assertEqualDiff(self.full_log, log)
 
114
        self.assertEqualDiff(full_log, log)
67
115
 
68
116
    def test_log_null_both_revspecs(self):
69
 
        self._prepare()
 
117
        self.make_linear_branch()
 
118
        full_log = self.run_bzr(['log'])[0]
70
119
        log = self.run_bzr("log -r ..")[0]
71
 
        self.assertEqualDiff(self.full_log, log)
 
120
        self.assertEqualDiff(full_log, log)
72
121
 
73
122
    def test_log_zero_revspec(self):
74
 
        self._prepare()
75
 
        self.run_bzr_error('bzr: ERROR: Logging revision 0 is invalid.',
 
123
        self.make_minimal_branch()
 
124
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
76
125
                           ['log', '-r0'])
77
126
 
78
127
    def test_log_zero_begin_revspec(self):
79
 
        self._prepare()
80
 
        self.run_bzr_error('bzr: ERROR: Logging revision 0 is invalid.',
 
128
        self.make_linear_branch()
 
129
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
81
130
                           ['log', '-r0..2'])
82
131
 
83
132
    def test_log_zero_end_revspec(self):
84
 
        self._prepare()
85
 
        self.run_bzr_error('bzr: ERROR: Logging revision 0 is invalid.',
 
133
        self.make_linear_branch()
 
134
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
86
135
                           ['log', '-r-2..0'])
87
136
 
88
 
    def test_log_unsupported_timezone(self):
89
 
        self._prepare()
90
 
        self.run_bzr_error('bzr: ERROR: Unsupported timezone format "foo", '
91
 
                           'options are "utc", "original", "local".',
92
 
                           ['log', '--timezone', 'foo'])
93
 
 
94
137
    def test_log_negative_begin_revspec_full_log(self):
95
 
        self._prepare()
 
138
        self.make_linear_branch()
 
139
        full_log = self.run_bzr(['log'])[0]
96
140
        log = self.run_bzr("log -r -3..")[0]
97
 
        self.assertEqualDiff(self.full_log, log)
 
141
        self.assertEqualDiff(full_log, log)
98
142
 
99
143
    def test_log_negative_both_revspec_full_log(self):
100
 
        self._prepare()
 
144
        self.make_linear_branch()
 
145
        full_log = self.run_bzr(['log'])[0]
101
146
        log = self.run_bzr("log -r -3..-1")[0]
102
 
        self.assertEqualDiff(self.full_log, log)
 
147
        self.assertEqualDiff(full_log, log)
103
148
 
104
149
    def test_log_negative_both_revspec_partial(self):
105
 
        self._prepare()
 
150
        self.make_linear_branch()
106
151
        log = self.run_bzr("log -r -3..-2")[0]
107
152
        self.assertTrue('revno: 1\n' in log)
108
153
        self.assertTrue('revno: 2\n' in log)
109
154
        self.assertTrue('revno: 3\n' not in log)
110
155
 
111
156
    def test_log_negative_begin_revspec(self):
112
 
        self._prepare()
 
157
        self.make_linear_branch()
113
158
        log = self.run_bzr("log -r -2..")[0]
114
159
        self.assertTrue('revno: 1\n' not in log)
115
160
        self.assertTrue('revno: 2\n' in log)
116
161
        self.assertTrue('revno: 3\n' in log)
117
162
 
118
163
    def test_log_positive_revspecs(self):
119
 
        self._prepare()
 
164
        self.make_linear_branch()
 
165
        full_log = self.run_bzr(['log'])[0]
120
166
        log = self.run_bzr("log -r 1..3")[0]
121
 
        self.assertEqualDiff(self.full_log, log)
 
167
        self.assertEqualDiff(full_log, log)
 
168
 
 
169
    def test_log_dotted_revspecs(self):
 
170
        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))
122
173
 
123
174
    def test_log_reversed_revspecs(self):
124
 
        self._prepare()
 
175
        self.make_linear_branch()
125
176
        self.run_bzr_error(('bzr: ERROR: Start revision must be older than '
126
177
                            'the end revision.\n',),
127
178
                           ['log', '-r3..1'])
128
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")
 
185
 
129
186
    def test_log_revno_n_path(self):
130
 
        self._prepare(path='branch1')
131
 
        self._prepare(path='branch2')
132
 
        log = self.run_bzr("log -r revno:2:branch1..revno:3:branch2",
133
 
                          retcode=3)[0]
 
187
        self.make_linear_branch('branch1')
 
188
        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
134
192
        log = self.run_bzr("log -r revno:1:branch2..revno:3:branch2")[0]
135
 
        self.assertEqualDiff(self.full_log, log)
 
193
        full_log = self.run_bzr(['log'], working_dir='branch2')[0]
 
194
        self.assertEqualDiff(full_log, log)
136
195
        log = self.run_bzr("log -r revno:1:branch2")[0]
137
196
        self.assertTrue('revno: 1\n' in log)
138
197
        self.assertTrue('revno: 2\n' not in log)
140
199
        self.assertTrue('branch nick: branch1\n' not in log)
141
200
 
142
201
    def test_log_nonexistent_revno(self):
143
 
        self._prepare()
144
 
        (out, err) = self.run_bzr_error(args="log -r 1234",
145
 
            error_regexes=["bzr: ERROR: Requested revision: '1234' "
146
 
                "does not exist in branch:"])
 
202
        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'])
147
207
 
148
208
    def test_log_nonexistent_dotted_revno(self):
149
 
        self._prepare()
150
 
        (out, err) = self.run_bzr_error(args="log -r 123.123",
151
 
            error_regexes=["bzr: ERROR: Requested revision: '123.123' "
152
 
                "does not exist in branch:"])
 
209
        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'])
153
214
 
154
215
    def test_log_change_revno(self):
155
 
        self._prepare()
 
216
        self.make_linear_branch()
156
217
        expected_log = self.run_bzr("log -r 1")[0]
157
218
        log = self.run_bzr("log -c 1")[0]
158
219
        self.assertEqualDiff(expected_log, log)
159
220
 
160
221
    def test_log_change_nonexistent_revno(self):
161
 
        self._prepare()
162
 
        (out, err) = self.run_bzr_error(args="log -c 1234",
163
 
            error_regexes=["bzr: ERROR: Requested revision: '1234' "
164
 
                "does not exist in branch:"])
 
222
        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'])
165
227
 
166
228
    def test_log_change_nonexistent_dotted_revno(self):
167
 
        self._prepare()
168
 
        (out, err) = self.run_bzr_error(args="log -c 123.123",
169
 
            error_regexes=["bzr: ERROR: Requested revision: '123.123' "
170
 
                "does not exist in branch:"])
 
229
        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'])
171
234
 
172
 
    def test_log_change_single_revno(self):
173
 
        self._prepare()
174
 
        self.run_bzr_error('bzr: ERROR: Option --change does not'
175
 
                           ' accept revision ranges',
 
235
    def test_log_change_single_revno_only(self):
 
236
        self.make_minimal_branch()
 
237
        self.run_bzr_error(['bzr: ERROR: Option --change does not'
 
238
                           ' accept revision ranges'],
176
239
                           ['log', '--change', '2..3'])
177
240
 
178
241
    def test_log_change_incompatible_with_revision(self):
179
 
        self._prepare()
180
 
        self.run_bzr_error('bzr: ERROR: --revision and --change'
181
 
                           ' are mutually exclusive',
 
242
        self.run_bzr_error(['bzr: ERROR: --revision and --change'
 
243
                           ' are mutually exclusive'],
182
244
                           ['log', '--change', '2', '--revision', '3'])
183
245
 
184
246
    def test_log_nonexistent_file(self):
 
247
        self.make_minimal_branch()
185
248
        # files that don't exist in either the basis tree or working tree
186
249
        # should give an error
187
 
        wt = self.make_branch_and_tree('.')
188
250
        out, err = self.run_bzr('log does-not-exist', retcode=3)
189
 
        self.assertContainsRe(
190
 
            err, 'Path unknown at end or start of revision range: does-not-exist')
 
251
        self.assertContainsRe(err,
 
252
                              'Path unknown at end or start of revision range: '
 
253
                              'does-not-exist')
191
254
 
192
255
    def test_log_with_tags(self):
193
 
        tree = self._prepare(format='dirstate-tags')
 
256
        tree = self.make_linear_branch(format='dirstate-tags')
194
257
        branch = tree.branch
195
258
        branch.tags.set_tag('tag1', branch.get_rev_id(1))
196
259
        branch.tags.set_tag('tag1.1', branch.get_rev_id(1))
205
268
        self.assertContainsRe(log, r'tags: (tag1, tag1\.1|tag1\.1, tag1)')
206
269
 
207
270
    def test_merged_log_with_tags(self):
208
 
        branch1_tree = self._prepare(path='branch1', format='dirstate-tags')
 
271
        branch1_tree = self.make_linear_branch('branch1',
 
272
                                               format='dirstate-tags')
209
273
        branch1 = branch1_tree.branch
210
274
        branch2_tree = branch1_tree.bzrdir.sprout('branch2').open_workingtree()
211
275
        branch1_tree.commit(message='foobar', allow_pointless=True)
212
276
        branch1.tags.set_tag('tag1', branch1.last_revision())
213
 
        os.chdir('branch2')
214
 
        self.run_bzr('merge ../branch1') # tags don't propagate otherwise
 
277
        # tags don't propagate if we don't merge
 
278
        self.run_bzr('merge ../branch1', working_dir='branch2')
215
279
        branch2_tree.commit(message='merge branch 1')
216
 
        log = self.run_bzr("log -n0 -r-1")[0]
 
280
        log = self.run_bzr("log -n0 -r-1", working_dir='branch2')[0]
217
281
        self.assertContainsRe(log, r'    tags: tag1')
218
 
        log = self.run_bzr("log -n0 -r3.1.1")[0]
 
282
        log = self.run_bzr("log -n0 -r3.1.1", working_dir='branch2')[0]
219
283
        self.assertContainsRe(log, r'tags: tag1')
220
284
 
221
285
    def test_log_limit(self):
236
300
        self.assertContainsRe(log, r'revno: 10\n')
237
301
 
238
302
    def test_log_limit_short(self):
239
 
        self._prepare()
 
303
        self.make_linear_branch()
240
304
        log = self.run_bzr("log -l 2")[0]
241
305
        self.assertNotContainsRe(log, r'revno: 1\n')
242
306
        self.assertContainsRe(log, r'revno: 2\n')
247
311
        
248
312
        See https://bugs.launchpad.net/bzr/+bug/251352
249
313
        """
250
 
        self._prepare()
 
314
        self.make_minimal_branch()
251
315
        out, err = self.run_bzr(['log', '-m', '*'], retcode=3)
252
316
        self.assertEqual("bzr: ERROR: Invalid regular expression"
253
317
            " in log message filter"
256
320
        self.assertEqual('', out)
257
321
 
258
322
 
259
 
class TestLogVerbose(TestCaseWithTransport):
 
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
 
 
332
class TestLogVerbose(TestLog):
260
333
 
261
334
    def setUp(self):
262
335
        super(TestLogVerbose, self).setUp()
263
 
        tree = self.make_branch_and_tree('.')
264
 
        self.build_tree(['hello.txt'])
265
 
        tree.add('hello.txt')
266
 
        tree.commit(message='message1')
 
336
        self.make_minimal_branch()
267
337
 
268
338
    def assertUseShortDeltaFormat(self, cmd):
269
339
        log = self.run_bzr(cmd)[0]
294
364
        self.assertUseLongDeltaFormat(['log', '--long', '-vv'])
295
365
 
296
366
 
297
 
class TestLogMerges(TestCaseWithoutPropsHandler):
298
 
 
299
 
    def _prepare(self):
300
 
        parent_tree = self.make_branch_and_tree('parent')
301
 
        parent_tree.commit(message='first post', allow_pointless=True)
302
 
        child_tree = parent_tree.bzrdir.sprout('child').open_workingtree()
303
 
        child_tree.commit(message='branch 1', allow_pointless=True)
304
 
        smaller_tree = \
305
 
                child_tree.bzrdir.sprout('smallerchild').open_workingtree()
306
 
        smaller_tree.commit(message='branch 2', allow_pointless=True)
307
 
        child_tree.merge_from_branch(smaller_tree.branch)
308
 
        child_tree.commit(message='merge branch 2')
309
 
        parent_tree.merge_from_branch(child_tree.branch)
310
 
        parent_tree.commit(message='merge branch 1')
311
 
        os.chdir('parent')
312
 
 
313
 
    def _prepare_short(self):
314
 
        parent_tree = self.make_branch_and_tree('parent')
315
 
        parent_tree.commit(message='first post',
316
 
            timestamp=1132586700, timezone=36000,
317
 
            committer='Joe Foo <joe@foo.com>')
318
 
        child_tree = parent_tree.bzrdir.sprout('child').open_workingtree()
319
 
        child_tree.commit(message='branch 1',
320
 
            timestamp=1132586800, timezone=36000,
321
 
            committer='Joe Foo <joe@foo.com>')
322
 
        smaller_tree = \
323
 
                child_tree.bzrdir.sprout('smallerchild').open_workingtree()
324
 
        smaller_tree.commit(message='branch 2',
325
 
            timestamp=1132586900, timezone=36000,
326
 
            committer='Joe Foo <joe@foo.com>')
327
 
        child_tree.merge_from_branch(smaller_tree.branch)
328
 
        child_tree.commit(message='merge branch 2',
329
 
            timestamp=1132587000, timezone=36000,
330
 
            committer='Joe Foo <joe@foo.com>')
331
 
        parent_tree.merge_from_branch(child_tree.branch)
332
 
        parent_tree.commit(message='merge branch 1',
333
 
            timestamp=1132587100, timezone=36000,
334
 
            committer='Joe Foo <joe@foo.com>')
335
 
        os.chdir('parent')
 
367
class TestLogMerges(TestLog):
 
368
 
 
369
    def setUp(self):
 
370
        super(TestLogMerges, self).setUp()
 
371
        self.make_branches_with_merges()
 
372
 
 
373
    def make_branches_with_merges(self):
 
374
        level0 = self.make_branch_and_tree('level0')
 
375
        level0.commit(message='in branch level0', **self.commit_options())
 
376
 
 
377
        level1 = level0.bzrdir.sprout('level1').open_workingtree()
 
378
        level1.commit(message='in branch level1', **self.commit_options())
 
379
 
 
380
        level2 = level1.bzrdir.sprout('level2').open_workingtree()
 
381
        level2.commit(message='in branch level2', **self.commit_options())
 
382
 
 
383
        level1.merge_from_branch(level2.branch)
 
384
        level1.commit(message='merge branch level2', **self.commit_options())
 
385
 
 
386
        level0.merge_from_branch(level1.branch)
 
387
        level0.commit(message='merge branch level1', **self.commit_options())
336
388
 
337
389
    def test_merges_are_indented_by_level(self):
338
 
        self._prepare()
339
 
        out,err = self.run_bzr('log -n0')
340
 
        self.assertEqual('', err)
341
 
        log = normalize_log(out)
342
 
        self.assertEqualDiff(log, """\
 
390
        expected = """\
343
391
------------------------------------------------------------
344
392
revno: 2 [merge]
345
393
committer: Lorem Ipsum <test@example.com>
346
 
branch nick: parent
 
394
branch nick: level0
347
395
timestamp: Just now
348
396
message:
349
 
  merge branch 1
 
397
  merge branch level1
350
398
    ------------------------------------------------------------
351
399
    revno: 1.1.2 [merge]
352
400
    committer: Lorem Ipsum <test@example.com>
353
 
    branch nick: child
 
401
    branch nick: level1
354
402
    timestamp: Just now
355
403
    message:
356
 
      merge branch 2
 
404
      merge branch level2
357
405
        ------------------------------------------------------------
358
406
        revno: 1.2.1
359
407
        committer: Lorem Ipsum <test@example.com>
360
 
        branch nick: smallerchild
 
408
        branch nick: level2
361
409
        timestamp: Just now
362
410
        message:
363
 
          branch 2
 
411
          in branch level2
364
412
    ------------------------------------------------------------
365
413
    revno: 1.1.1
366
414
    committer: Lorem Ipsum <test@example.com>
367
 
    branch nick: child
 
415
    branch nick: level1
368
416
    timestamp: Just now
369
417
    message:
370
 
      branch 1
 
418
      in branch level1
371
419
------------------------------------------------------------
372
420
revno: 1
373
421
committer: Lorem Ipsum <test@example.com>
374
 
branch nick: parent
 
422
branch nick: level0
375
423
timestamp: Just now
376
424
message:
377
 
  first post
378
 
""")
 
425
  in branch level0
 
426
"""
 
427
        self.check_log(expected, ['-n0'])
379
428
 
380
429
    def test_force_merge_revisions_off(self):
381
 
        self._prepare()
382
 
        out,err = self.run_bzr('log --long -n1')
383
 
        self.assertEqual('', err)
384
 
        log = normalize_log(out)
385
 
        self.assertEqualDiff(log, """\
 
430
        expected = """\
386
431
------------------------------------------------------------
387
432
revno: 2 [merge]
388
433
committer: Lorem Ipsum <test@example.com>
389
 
branch nick: parent
 
434
branch nick: level0
390
435
timestamp: Just now
391
436
message:
392
 
  merge branch 1
 
437
  merge branch level1
393
438
------------------------------------------------------------
394
439
revno: 1
395
440
committer: Lorem Ipsum <test@example.com>
396
 
branch nick: parent
 
441
branch nick: level0
397
442
timestamp: Just now
398
443
message:
399
 
  first post
400
 
""")
 
444
  in branch level0
 
445
"""
 
446
        self.check_log(expected, ['--long', '-n1'])
401
447
 
402
448
    def test_force_merge_revisions_on(self):
403
 
        self._prepare_short()
404
 
        out,err = self.run_bzr('log --short -n0')
405
 
        self.assertEqual('', err)
406
 
        log = normalize_log(out)
407
 
        self.assertEqualDiff(log, """\
408
 
    2 Joe Foo\t2005-11-22 [merge]
409
 
      merge branch 1
410
 
 
411
 
          1.1.2 Joe Foo\t2005-11-22 [merge]
412
 
                merge branch 2
413
 
 
414
 
              1.2.1 Joe Foo\t2005-11-22
415
 
                    branch 2
416
 
 
417
 
          1.1.1 Joe Foo\t2005-11-22
418
 
                branch 1
419
 
 
420
 
    1 Joe Foo\t2005-11-22
421
 
      first post
422
 
 
423
 
""")
 
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'])
424
467
 
425
468
    def test_include_merges(self):
426
469
        # Confirm --include-merges gives the same output as -n0
427
 
        self._prepare_short()
428
 
        out_im, err_im = self.run_bzr('log --include-merges')
429
 
        out_n0, err_n0 = self.run_bzr('log -n0')
430
 
        self.assertEqual(err_im, err_n0)
 
470
        out_im, err_im = self.run_bzr('log --include-merges',
 
471
                                      working_dir='level0')
 
472
        out_n0, err_n0 = self.run_bzr('log -n0', working_dir='level0')
 
473
        self.assertEqual('', err_im)
 
474
        self.assertEqual('', err_n0)
431
475
        self.assertEqual(out_im, out_n0)
432
476
 
433
477
    def test_force_merge_revisions_N(self):
434
 
        self._prepare_short()
435
 
        out,err = self.run_bzr('log --short -n2')
436
 
        self.assertEqual('', err)
437
 
        log = normalize_log(out)
438
 
        self.assertEqualDiff(log, """\
439
 
    2 Joe Foo\t2005-11-22 [merge]
440
 
      merge branch 1
441
 
 
442
 
          1.1.2 Joe Foo\t2005-11-22 [merge]
443
 
                merge branch 2
444
 
 
445
 
          1.1.1 Joe Foo\t2005-11-22
446
 
                branch 1
447
 
 
448
 
    1 Joe Foo\t2005-11-22
449
 
      first post
450
 
 
451
 
""")
 
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'])
452
493
 
453
494
    def test_merges_single_merge_rev(self):
454
 
        self._prepare()
455
 
        out,err = self.run_bzr('log -n0 -r1.1.2')
456
 
        self.assertEqual('', err)
457
 
        log = normalize_log(out)
458
 
        self.assertEqualDiff(log, """\
 
495
        expected = """\
459
496
------------------------------------------------------------
460
497
revno: 1.1.2 [merge]
461
498
committer: Lorem Ipsum <test@example.com>
462
 
branch nick: child
 
499
branch nick: level1
463
500
timestamp: Just now
464
501
message:
465
 
  merge branch 2
 
502
  merge branch level2
466
503
    ------------------------------------------------------------
467
504
    revno: 1.2.1
468
505
    committer: Lorem Ipsum <test@example.com>
469
 
    branch nick: smallerchild
 
506
    branch nick: level2
470
507
    timestamp: Just now
471
508
    message:
472
 
      branch 2
473
 
""")
 
509
      in branch level2
 
510
"""
 
511
        self.check_log(expected, ['-n0', '-r1.1.2'])
474
512
 
475
513
    def test_merges_partial_range(self):
476
 
        self._prepare()
477
 
        out, err = self.run_bzr('log -n0 -r1.1.1..1.1.2')
478
 
        self.assertEqual('', err)
479
 
        log = normalize_log(out)
480
 
        self.assertEqualDiff(log, """\
 
514
        expected = """\
481
515
------------------------------------------------------------
482
516
revno: 1.1.2 [merge]
483
517
committer: Lorem Ipsum <test@example.com>
484
 
branch nick: child
 
518
branch nick: level1
485
519
timestamp: Just now
486
520
message:
487
 
  merge branch 2
 
521
  merge branch level2
488
522
    ------------------------------------------------------------
489
523
    revno: 1.2.1
490
524
    committer: Lorem Ipsum <test@example.com>
491
 
    branch nick: smallerchild
 
525
    branch nick: level2
492
526
    timestamp: Just now
493
527
    message:
494
 
      branch 2
 
528
      in branch level2
495
529
------------------------------------------------------------
496
530
revno: 1.1.1
497
531
committer: Lorem Ipsum <test@example.com>
498
 
branch nick: child
 
532
branch nick: level1
499
533
timestamp: Just now
500
534
message:
501
 
  branch 1
502
 
""")
503
 
 
504
 
 
505
 
def subst_dates(string):
506
 
    """Replace date strings with constant values."""
507
 
    return re.sub(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]\d{4}',
508
 
                  'YYYY-MM-DD HH:MM:SS +ZZZZ', string)
509
 
 
510
 
 
511
 
class TestLogDiff(TestCaseWithoutPropsHandler):
512
 
 
513
 
    def _prepare(self):
514
 
        parent_tree = self.make_branch_and_tree('parent')
515
 
        self.build_tree(['parent/file1', 'parent/file2'])
516
 
        parent_tree.add('file1')
517
 
        parent_tree.add('file2')
518
 
        parent_tree.commit(message='first post',
519
 
            timestamp=1132586655, timezone=36000,
520
 
            committer='Lorem Ipsum <test@example.com>')
521
 
        child_tree = parent_tree.bzrdir.sprout('child').open_workingtree()
522
 
        self.build_tree_contents([('child/file2', 'hello\n')])
523
 
        child_tree.commit(message='branch 1',
524
 
            timestamp=1132586700, timezone=36000,
525
 
            committer='Lorem Ipsum <test@example.com>')
526
 
        parent_tree.merge_from_branch(child_tree.branch)
527
 
        parent_tree.commit(message='merge branch 1',
528
 
            timestamp=1132586800, timezone=36000,
529
 
            committer='Lorem Ipsum <test@example.com>')
530
 
        os.chdir('parent')
 
535
  in branch level1
 
536
"""
 
537
        self.check_log(expected, ['-n0', '-r1.1.1..1.1.2'])
 
538
 
 
539
 
 
540
class TestLogDiff(TestLog):
 
541
 
 
542
    def setUp(self):
 
543
        super(TestLogDiff, self).setUp()
 
544
        self.make_branch_with_diffs()
 
545
 
 
546
    def make_branch_with_diffs(self):
 
547
        level0 = self.make_branch_and_tree('level0')
 
548
        self.build_tree(['level0/file1', 'level0/file2'])
 
549
        level0.add('file1')
 
550
        level0.add('file2')
 
551
        level0.commit(message='in branch level0', **self.commit_options())
 
552
 
 
553
        level1 = level0.bzrdir.sprout('level1').open_workingtree()
 
554
        self.build_tree_contents([('level1/file2', 'hello\n')])
 
555
        level1.commit(message='in branch level1', **self.commit_options())
 
556
        level0.merge_from_branch(level1.branch)
 
557
        level0.commit(message='merge branch level1', **self.commit_options())
531
558
 
532
559
    def test_log_show_diff_long_with_merges(self):
533
 
        self._prepare()
534
560
        out,err = self.run_bzr('log -p -n0')
535
561
        self.assertEqual('', err)
536
 
        log = normalize_log(out)
537
 
        self.assertEqualDiff(subst_dates(log), """\
 
562
        log = test_log.normalize_log(out)
 
563
        expected = """\
538
564
------------------------------------------------------------
539
565
revno: 2 [merge]
540
566
committer: Lorem Ipsum <test@example.com>
541
 
branch nick: parent
 
567
branch nick: level0
542
568
timestamp: Just now
543
569
message:
544
 
  merge branch 1
 
570
  merge branch level1
545
571
diff:
546
572
=== modified file 'file2'
547
 
--- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
548
 
+++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
573
--- file2\t2005-11-22 00:00:01 +0000
 
574
+++ file2\t2005-11-22 00:00:02 +0000
549
575
@@ -1,1 +1,1 @@
550
 
-contents of parent/file2
 
576
-contents of level0/file2
551
577
+hello
552
578
    ------------------------------------------------------------
553
579
    revno: 1.1.1
554
580
    committer: Lorem Ipsum <test@example.com>
555
 
    branch nick: child
 
581
    branch nick: level1
556
582
    timestamp: Just now
557
583
    message:
558
 
      branch 1
 
584
      in branch level1
559
585
    diff:
560
586
    === modified file 'file2'
561
 
    --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
562
 
    +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
587
    --- file2\t2005-11-22 00:00:01 +0000
 
588
    +++ file2\t2005-11-22 00:00:02 +0000
563
589
    @@ -1,1 +1,1 @@
564
 
    -contents of parent/file2
 
590
    -contents of level0/file2
565
591
    +hello
566
592
------------------------------------------------------------
567
593
revno: 1
568
594
committer: Lorem Ipsum <test@example.com>
569
 
branch nick: parent
 
595
branch nick: level0
570
596
timestamp: Just now
571
597
message:
572
 
  first post
 
598
  in branch level0
573
599
diff:
574
600
=== added file 'file1'
575
 
--- file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
576
 
+++ file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
601
--- file1\t1970-01-01 00:00:00 +0000
 
602
+++ file1\t2005-11-22 00:00:01 +0000
577
603
@@ -0,0 +1,1 @@
578
 
+contents of parent/file1
 
604
+contents of level0/file1
579
605
 
580
606
=== added file 'file2'
581
 
--- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
582
 
+++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
607
--- file2\t1970-01-01 00:00:00 +0000
 
608
+++ file2\t2005-11-22 00:00:01 +0000
583
609
@@ -0,0 +1,1 @@
584
 
+contents of parent/file2
585
 
""")
 
610
+contents of level0/file2
 
611
"""
 
612
        self.check_log(expected, ['-p', '-n0'])
586
613
 
587
614
    def test_log_show_diff_short(self):
588
 
        self._prepare()
589
 
        out,err = self.run_bzr('log -p --short')
590
 
        self.assertEqual('', err)
591
 
        log = normalize_log(out)
592
 
        self.assertEqualDiff(subst_dates(log), """\
 
615
        expected = """\
593
616
    2 Lorem Ipsum\t2005-11-22 [merge]
594
 
      merge branch 1
 
617
      merge branch level1
595
618
      === modified file 'file2'
596
 
      --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
597
 
      +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
619
      --- file2\t2005-11-22 00:00:01 +0000
 
620
      +++ file2\t2005-11-22 00:00:02 +0000
598
621
      @@ -1,1 +1,1 @@
599
 
      -contents of parent/file2
 
622
      -contents of level0/file2
600
623
      +hello
601
624
 
602
625
    1 Lorem Ipsum\t2005-11-22
603
 
      first post
 
626
      in branch level0
604
627
      === added file 'file1'
605
 
      --- file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
606
 
      +++ file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
628
      --- file1\t1970-01-01 00:00:00 +0000
 
629
      +++ file1\t2005-11-22 00:00:01 +0000
607
630
      @@ -0,0 +1,1 @@
608
 
      +contents of parent/file1
 
631
      +contents of level0/file1
609
632
\x20\x20\x20\x20\x20\x20
610
633
      === added file 'file2'
611
 
      --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
612
 
      +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
634
      --- file2\t1970-01-01 00:00:00 +0000
 
635
      +++ file2\t2005-11-22 00:00:01 +0000
613
636
      @@ -0,0 +1,1 @@
614
 
      +contents of parent/file2
 
637
      +contents of level0/file2
615
638
 
616
639
Use --include-merges or -n0 to see merged revisions.
617
 
""")
 
640
"""
 
641
        self.check_log(expected, ['-p', '--short'])
618
642
 
619
643
    def test_log_show_diff_line(self):
620
 
        self._prepare()
621
 
        out,err = self.run_bzr('log -p --line')
622
 
        self.assertEqual('', err)
623
 
        log = normalize_log(out)
624
644
        # Not supported by this formatter so expect plain output
625
 
        self.assertEqualDiff(subst_dates(log), """\
626
 
2: Lorem Ipsum 2005-11-22 [merge] merge branch 1
627
 
1: Lorem Ipsum 2005-11-22 first post
628
 
""")
629
 
 
630
 
    def test_log_show_diff_file(self):
631
 
        """Only the diffs for the given file are to be shown"""
632
 
        self._prepare()
633
 
        out,err = self.run_bzr('log -p --short file2')
634
 
        self.assertEqual('', err)
635
 
        log = normalize_log(out)
636
 
        self.assertEqualDiff(subst_dates(log), """\
 
645
        expected = """\
 
646
2: Lorem Ipsum 2005-11-22 [merge] merge branch level1
 
647
1: Lorem Ipsum 2005-11-22 in branch level0
 
648
"""
 
649
        self.check_log(expected, ['-p', '--line'])
 
650
 
 
651
    def test_log_show_diff_file1(self):
 
652
        """Only the diffs for the given file are to be shown"""
 
653
        expected = """\
 
654
    1 Lorem Ipsum\t2005-11-22
 
655
      in branch level0
 
656
      === added file 'file1'
 
657
      --- file1\t1970-01-01 00:00:00 +0000
 
658
      +++ file1\t2005-11-22 00:00:01 +0000
 
659
      @@ -0,0 +1,1 @@
 
660
      +contents of level0/file1
 
661
 
 
662
"""
 
663
        self.check_log(expected, ['-p', '--short', 'file1'])
 
664
 
 
665
    def test_log_show_diff_file2(self):
 
666
        """Only the diffs for the given file are to be shown"""
 
667
        expected = """\
637
668
    2 Lorem Ipsum\t2005-11-22 [merge]
638
 
      merge branch 1
 
669
      merge branch level1
639
670
      === modified file 'file2'
640
 
      --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
641
 
      +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
671
      --- file2\t2005-11-22 00:00:01 +0000
 
672
      +++ file2\t2005-11-22 00:00:02 +0000
642
673
      @@ -1,1 +1,1 @@
643
 
      -contents of parent/file2
 
674
      -contents of level0/file2
644
675
      +hello
645
676
 
646
677
    1 Lorem Ipsum\t2005-11-22
647
 
      first post
 
678
      in branch level0
648
679
      === added file 'file2'
649
 
      --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
650
 
      +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
 
680
      --- file2\t1970-01-01 00:00:00 +0000
 
681
      +++ file2\t2005-11-22 00:00:01 +0000
651
682
      @@ -0,0 +1,1 @@
652
 
      +contents of parent/file2
 
683
      +contents of level0/file2
653
684
 
654
685
Use --include-merges or -n0 to see merged revisions.
655
 
""")
656
 
        out,err = self.run_bzr('log -p --short file1')
657
 
        self.assertEqual('', err)
658
 
        log = normalize_log(out)
659
 
        self.assertEqualDiff(subst_dates(log), """\
660
 
    1 Lorem Ipsum\t2005-11-22
661
 
      first post
662
 
      === added file 'file1'
663
 
      --- file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
664
 
      +++ file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
665
 
      @@ -0,0 +1,1 @@
666
 
      +contents of parent/file1
667
 
 
668
 
""")
 
686
"""
 
687
        self.check_log(expected, ['-p', '--short', 'file2'])
 
688
 
 
689
 
 
690
class TestLogUnicodeDiff(TestLog):
669
691
 
670
692
    def test_log_show_diff_non_ascii(self):
671
693
        # Smoke test for bug #328007 UnicodeDecodeError on 'log -p'
688
710
        self.assertEqual('', err)
689
711
 
690
712
 
691
 
class TestLogEncodings(TestCaseInTempDir):
 
713
class TestLogEncodings(tests.TestCaseInTempDir):
692
714
 
693
715
    _mu = u'\xb5'
694
716
    _message = u'Message with \xb5'
710
732
    ]
711
733
 
712
734
    def setUp(self):
713
 
        TestCaseInTempDir.setUp(self)
 
735
        super(TestLogEncodings, self).setUp()
714
736
        self.user_encoding = osutils._cached_user_encoding
715
 
 
716
 
    def tearDown(self):
717
 
        osutils._cached_user_encoding = self.user_encoding
718
 
        TestCaseInTempDir.tearDown(self)
 
737
        def restore():
 
738
            osutils._cached_user_encoding = self.user_encoding
 
739
        self.addCleanup(restore)
719
740
 
720
741
    def create_branch(self):
721
742
        bzr = self.run_bzr
789
810
        self.assertEquals(-1, stdout.find(test_in_cp1251))
790
811
 
791
812
 
792
 
class TestLogFile(TestCaseWithTransport):
 
813
class TestLogFile(tests.TestCaseWithTransport):
793
814
 
794
815
    def test_log_local_branch_file(self):
795
816
        """We should be able to log files in local treeless branches"""
984
1005
        self.assertNotContainsRe(log, '^4:', re.MULTILINE)
985
1006
 
986
1007
 
987
 
class TestLogMultiple(TestCaseWithTransport):
 
1008
class TestLogMultiple(tests.TestCaseWithTransport):
988
1009
 
989
1010
    def prepare_tree(self):
990
1011
        tree = self.make_branch_and_tree('parent')