~bzr-pqm/bzr/bzr.dev

4988.10.3 by John Arbash Meinel
Merge bzr.dev 5007, resolve conflict, update NEWS
1
# Copyright (C) 2006-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
16
17
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
18
"""Black-box tests for bzr log."""
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
19
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
20
from itertools import izip
4325.4.3 by Vincent Ladeuil
More cleanups.
21
import os
22
import re
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
23
4325.4.3 by Vincent Ladeuil
More cleanups.
24
from bzrlib import (
4955.4.6 by Vincent Ladeuil
Switch to branchbuilder to avoid the cost of test.script.
25
    branchbuilder,
4955.7.3 by Vincent Ladeuil
Check ancestry so we don't output random revisions.
26
    errors,
4955.5.2 by Vincent Ladeuil
Simplify tests.
27
    log,
4325.4.3 by Vincent Ladeuil
More cleanups.
28
    osutils,
29
    tests,
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
30
    )
4955.4.5 by Vincent Ladeuil
Start reproducing the problems reported in the bug.
31
from bzrlib.tests import (
32
    script,
33
    test_log,
34
    )
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
35
36
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
37
class TestLog(tests.TestCaseWithTransport, test_log.TestLogMixin):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
38
39
    def make_minimal_branch(self, path='.', format=None):
40
        tree = self.make_branch_and_tree(path, format=format)
41
        self.build_tree([path + '/hello.txt'])
42
        tree.add('hello.txt')
43
        tree.commit(message='message1')
44
        return tree
45
46
    def make_linear_branch(self, path='.', format=None):
2809.1.2 by Daniel Watkins
Removed unnecessary check as per abentley's on-list comments.
47
        tree = self.make_branch_and_tree(path, format=format)
2664.14.1 by Daniel Watkins
Fixed tests.blackbox.test_log to use internals where appropriate.
48
        self.build_tree(
49
            [path + '/hello.txt', path + '/goodbye.txt', path + '/meep.txt'])
50
        tree.add('hello.txt')
51
        tree.commit(message='message1')
52
        tree.add('goodbye.txt')
53
        tree.commit(message='message2')
54
        tree.add('meep.txt')
55
        tree.commit(message='message3')
56
        return tree
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
57
4369.2.1 by Marius Kruger
add some leftover log tests
58
    def make_merged_branch(self, path='.', format=None):
4369.2.2 by Marius Kruger
use make_linear_branch in make_merged_branch
59
        tree = self.make_linear_branch(path, format)
60
        tree2 = tree.bzrdir.sprout('tree2',
61
            revision_id=tree.branch.get_rev_id(1)).open_workingtree()
4369.2.1 by Marius Kruger
add some leftover log tests
62
        tree2.commit(message='tree2 message2')
63
        tree2.commit(message='tree2 message3')
64
        tree.merge_from_branch(tree2.branch)
65
        tree.commit(message='merge')
66
        return tree
67
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
68
4955.5.2 by Vincent Ladeuil
Simplify tests.
69
class TestLogWithLogCatcher(TestLog):
70
71
    def setUp(self):
72
        super(TestLogWithLogCatcher, self).setUp()
4955.4.5 by Vincent Ladeuil
Start reproducing the problems reported in the bug.
73
        # Capture log formatter creations
4955.5.2 by Vincent Ladeuil
Simplify tests.
74
        class MyLogFormatter(test_log.LogCatcher):
75
76
            def __new__(klass, *args, **kwargs):
4955.4.5 by Vincent Ladeuil
Start reproducing the problems reported in the bug.
77
                self.log_catcher = test_log.LogCatcher(*args, **kwargs)
78
                # Always return our own log formatter
4955.5.2 by Vincent Ladeuil
Simplify tests.
79
                return self.log_catcher
80
81
        def getme(branch):
82
                # Always return our own log formatter class hijacking the
83
                # default behavior (which requires setting up a config
84
                # variable)
85
            return MyLogFormatter
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
86
        self.overrideAttr(log.log_formatter_registry, 'get_default', getme)
4955.5.2 by Vincent Ladeuil
Simplify tests.
87
4955.4.8 by Vincent Ladeuil
Simplify more tests.
88
    def get_captured_revisions(self):
89
        return self.log_catcher.revisions
90
91
    def assertLogRevnos(self, args, expected_revnos, working_dir='.'):
92
        self.run_bzr(['log'] + args, working_dir=working_dir)
93
        self.assertEqual(expected_revnos,
94
                         [r.revno for r in self.get_captured_revisions()])
95
96
    def assertLogRevnosAndDepths(self, args, expected_revnos_and_depths,
97
                                working_dir='.'):
98
        self.run_bzr(['log'] + args, working_dir=working_dir)
99
        self.assertEqual(expected_revnos_and_depths,
100
                         [(r.revno, r.merge_depth)
101
                           for r in self.get_captured_revisions()])
4955.5.2 by Vincent Ladeuil
Simplify tests.
102
103
104
class TestLogRevSpecs(TestLogWithLogCatcher):
105
106
    def test_log_no_revspec(self):
107
        self.make_linear_branch()
108
        self.assertLogRevnos([], ['3', '2', '1'])
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
109
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
110
    def test_log_null_end_revspec(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
111
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
112
        self.assertLogRevnos(['-r1..'], ['3', '2', '1'])
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
113
114
    def test_log_null_begin_revspec(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
115
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
116
        self.assertLogRevnos(['-r..3'], ['3', '2', '1'])
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
117
118
    def test_log_null_both_revspecs(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
119
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
120
        self.assertLogRevnos(['-r..'], ['3', '2', '1'])
2978.4.1 by Kent Gibson
Logging revision 0 returns error.
121
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
122
    def test_log_negative_begin_revspec_full_log(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
123
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
124
        self.assertLogRevnos(['-r-3..'], ['3', '2', '1'])
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
125
126
    def test_log_negative_both_revspec_full_log(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
127
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
128
        self.assertLogRevnos(['-r-3..-1'], ['3', '2', '1'])
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
129
130
    def test_log_negative_both_revspec_partial(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
131
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
132
        self.assertLogRevnos(['-r-3..-2'], ['2', '1'])
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
133
134
    def test_log_negative_begin_revspec(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
135
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
136
        self.assertLogRevnos(['-r-2..'], ['3', '2'])
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
137
2978.4.1 by Kent Gibson
Logging revision 0 returns error.
138
    def test_log_positive_revspecs(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
139
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
140
        self.assertLogRevnos(['-r1..3'], ['3', '2', '1'])
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
141
4369.2.1 by Marius Kruger
add some leftover log tests
142
    def test_log_dotted_revspecs(self):
143
        self.make_merged_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
144
        self.assertLogRevnos(['-n0', '-r1..1.1.1'], ['1.1.1', '1'])
3734.1.1 by Vincent Ladeuil
Fix bug #248427 by adding a --change option to log.
145
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
146
    def test_log_limit(self):
147
        tree = self.make_branch_and_tree('.')
148
        # We want more commits than our batch size starts at
149
        for pos in range(10):
150
            tree.commit("%s" % pos)
4955.5.2 by Vincent Ladeuil
Simplify tests.
151
        self.assertLogRevnos(['--limit', '2'], ['10', '9'])
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
152
153
    def test_log_limit_short(self):
154
        self.make_linear_branch()
4955.5.2 by Vincent Ladeuil
Simplify tests.
155
        self.assertLogRevnos(['-l', '2'], ['3', '2'])
156
4955.4.7 by Vincent Ladeuil
Some more cleanup.
157
    def test_log_change_revno(self):
158
        self.make_linear_branch()
159
        self.assertLogRevnos(['-c1'], ['1'])
160
5318.1.2 by Martin von Gagern
Add blackbox test for "bzr log -r branch:../bar".
161
    def test_branch_revspec(self):
162
        foo = self.make_branch_and_tree('foo')
163
        bar = self.make_branch_and_tree('bar')
164
        self.build_tree(['foo/foo.txt', 'bar/bar.txt'])
165
        foo.add('foo.txt')
166
        bar.add('bar.txt')
167
        foo.commit(message='foo')
168
        bar.commit(message='bar')
169
        self.run_bzr('log -r branch:../bar', working_dir='foo')
170
        self.assertEqual([bar.branch.get_rev_id(1)],
171
                         [r.rev.revision_id
172
                          for r in self.get_captured_revisions()])
173
4955.4.6 by Vincent Ladeuil
Switch to branchbuilder to avoid the cost of test.script.
174
5268.4.1 by Vincent Ladeuil
Failing test for bug #575631.
175
class TestLogExcludeCommonAncestry(TestLogWithLogCatcher):
176
177
    def test_exclude_common_ancestry_simple_revnos(self):
178
        self.make_linear_branch()
179
        self.assertLogRevnos(['-r1..3', '--exclude-common-ancestry'],
180
                             ['3', '2'])
181
182
4955.7.5 by Vincent Ladeuil
Fixed as per Ian's review.
183
class TestLogMergedLinearAncestry(TestLogWithLogCatcher):
4955.4.5 by Vincent Ladeuil
Start reproducing the problems reported in the bug.
184
185
    def setUp(self):
4955.7.5 by Vincent Ladeuil
Fixed as per Ian's review.
186
        super(TestLogMergedLinearAncestry, self).setUp()
4955.4.6 by Vincent Ladeuil
Switch to branchbuilder to avoid the cost of test.script.
187
        # FIXME: Using a MemoryTree would be even better here (but until we
188
        # stop calling run_bzr, there is no point) --vila 100118.
189
        builder = branchbuilder.BranchBuilder(self.get_transport())
190
        builder.start_series()
5268.4.1 by Vincent Ladeuil
Failing test for bug #575631.
191
        # 1
192
        # | \
193
        # 2  1.1.1
194
        # | / |
195
        # 3  1.1.2
196
        # |   |
197
        # |  1.1.3
198
        # | / |
199
        # 4  1.1.4
200
        # | /
201
        # 5
202
4955.4.6 by Vincent Ladeuil
Switch to branchbuilder to avoid the cost of test.script.
203
        # mainline
204
        builder.build_snapshot('1', None, [
205
            ('add', ('', 'root-id', 'directory', ''))])
206
        builder.build_snapshot('2', ['1'], [])
207
        # branch
208
        builder.build_snapshot('1.1.1', ['1'], [])
209
        # merge branch into mainline
210
        builder.build_snapshot('3', ['2', '1.1.1'], [])
211
        # new commits in branch
212
        builder.build_snapshot('1.1.2', ['1.1.1'], [])
213
        builder.build_snapshot('1.1.3', ['1.1.2'], [])
214
        # merge branch into mainline
215
        builder.build_snapshot('4', ['3', '1.1.3'], [])
216
        # merge mainline into branch
217
        builder.build_snapshot('1.1.4', ['1.1.3', '4'], [])
218
        # merge branch into mainline
219
        builder.build_snapshot('5', ['4', '1.1.4'], [])
220
        builder.finish_series()
4955.4.5 by Vincent Ladeuil
Start reproducing the problems reported in the bug.
221
222
    def test_n0(self):
223
        self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4'],
224
                             ['1.1.4', '4', '1.1.3', '1.1.2', '3', '1.1.1'])
225
    def test_n0_forward(self):
226
        self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4', '--forward'],
227
                             ['3', '1.1.1', '4', '1.1.2', '1.1.3', '1.1.4'])
228
229
    def test_n1(self):
4955.4.6 by Vincent Ladeuil
Switch to branchbuilder to avoid the cost of test.script.
230
        # starting from 1.1.4 we follow the left-hand ancestry
4955.4.5 by Vincent Ladeuil
Start reproducing the problems reported in the bug.
231
        self.assertLogRevnos(['-n1', '-r1.1.1..1.1.4'],
232
                             ['1.1.4', '1.1.3', '1.1.2', '1.1.1'])
233
234
    def test_n1_forward(self):
235
        self.assertLogRevnos(['-n1', '-r1.1.1..1.1.4', '--forward'],
236
                             ['1.1.1', '1.1.2', '1.1.3', '1.1.4'])
237
4955.5.2 by Vincent Ladeuil
Simplify tests.
238
4955.7.5 by Vincent Ladeuil
Fixed as per Ian's review.
239
class Test_GenerateAllRevisions(TestLogWithLogCatcher):
4955.7.3 by Vincent Ladeuil
Check ancestry so we don't output random revisions.
240
5092.1.1 by Vincent Ladeuil
Reproduce bug #519862.
241
    def setUp(self):
242
        super(Test_GenerateAllRevisions, self).setUp()
243
        builder = self.make_branch_with_many_merges()
244
        b = builder.get_branch()
245
        b.lock_read()
246
        self.addCleanup(b.unlock)
247
        self.branch = b
248
4955.7.5 by Vincent Ladeuil
Fixed as per Ian's review.
249
    def make_branch_with_many_merges(self, path='.', format=None):
4955.7.3 by Vincent Ladeuil
Check ancestry so we don't output random revisions.
250
        builder = branchbuilder.BranchBuilder(self.get_transport())
251
        builder.start_series()
252
        # The graph below may look a bit complicated (and it may be but I've
253
        # banged my head enough on it) but the bug requires at least dotted
254
        # revnos *and* merged revisions below that.
255
        builder.build_snapshot('1', None, [
256
            ('add', ('', 'root-id', 'directory', ''))])
257
        builder.build_snapshot('2', ['1'], [])
258
        builder.build_snapshot('1.1.1', ['1'], [])
259
        builder.build_snapshot('2.1.1', ['2'], [])
260
        builder.build_snapshot('3', ['2', '1.1.1'], [])
261
        builder.build_snapshot('2.1.2', ['2.1.1'], [])
262
        builder.build_snapshot('2.2.1', ['2.1.1'], [])
263
        builder.build_snapshot('2.1.3', ['2.1.2', '2.2.1'], [])
264
        builder.build_snapshot('4', ['3', '2.1.3'], [])
265
        builder.build_snapshot('5', ['4', '2.1.2'], [])
266
        builder.finish_series()
267
        return builder
268
269
    def test_not_an_ancestor(self):
270
        self.assertRaises(errors.BzrCommandError,
271
                          log._generate_all_revisions,
5092.1.1 by Vincent Ladeuil
Reproduce bug #519862.
272
                          self.branch, '1.1.1', '2.1.3', 'reverse',
4955.7.3 by Vincent Ladeuil
Check ancestry so we don't output random revisions.
273
                          delayed_graph_generation=True)
274
275
    def test_wrong_order(self):
276
        self.assertRaises(errors.BzrCommandError,
277
                          log._generate_all_revisions,
5092.1.1 by Vincent Ladeuil
Reproduce bug #519862.
278
                          self.branch, '5', '2.1.3', 'reverse',
4955.7.3 by Vincent Ladeuil
Check ancestry so we don't output random revisions.
279
                          delayed_graph_generation=True)
280
5092.1.1 by Vincent Ladeuil
Reproduce bug #519862.
281
    def test_no_start_rev_id_with_end_rev_id_being_a_merge(self):
282
        revs = log._generate_all_revisions(
283
            self.branch, None, '2.1.3',
284
            'reverse', delayed_graph_generation=True)
285
4955.7.3 by Vincent Ladeuil
Check ancestry so we don't output random revisions.
286
4955.5.2 by Vincent Ladeuil
Simplify tests.
287
class TestLogRevSpecsWithPaths(TestLogWithLogCatcher):
288
289
    def test_log_revno_n_path_wrong_namespace(self):
290
        self.make_linear_branch('branch1')
291
        self.make_linear_branch('branch2')
292
        # There is no guarantee that a path exist between two arbitrary
293
        # revisions.
294
        self.run_bzr("log -r revno:2:branch1..revno:3:branch2", retcode=3)
295
296
    def test_log_revno_n_path_correct_order(self):
297
        self.make_linear_branch('branch2')
298
        self.assertLogRevnos(['-rrevno:1:branch2..revno:3:branch2'],
299
                             ['3', '2','1'])
300
301
    def test_log_revno_n_path(self):
302
        self.make_linear_branch('branch2')
303
        self.assertLogRevnos(['-rrevno:1:branch2'],
304
                             ['1'])
305
        rev_props = self.log_catcher.revisions[0].rev.properties
306
        self.assertEqual('branch2', rev_props['branch-nick'])
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
307
308
309
class TestLogErrors(TestLog):
310
4955.5.2 by Vincent Ladeuil
Simplify tests.
311
    def test_log_zero_revspec(self):
312
        self.make_minimal_branch()
313
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
314
                           ['log', '-r0'])
315
316
    def test_log_zero_begin_revspec(self):
317
        self.make_linear_branch()
318
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
319
                           ['log', '-r0..2'])
320
321
    def test_log_zero_end_revspec(self):
322
        self.make_linear_branch()
323
        self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
324
                           ['log', '-r-2..0'])
325
3878.3.3 by Marius Kruger
Add tests for log -r with non-exising revno's
326
    def test_log_nonexistent_revno(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
327
        self.make_minimal_branch()
5105.1.4 by Vincent Ladeuil
Use single quotes so that no test need to be updated.
328
        self.run_bzr_error(["bzr: ERROR: Requested revision: '1234' "
4955.4.7 by Vincent Ladeuil
Some more cleanup.
329
                            "does not exist in branch:"],
330
                           ['log', '-r1234'])
3878.3.3 by Marius Kruger
Add tests for log -r with non-exising revno's
331
332
    def test_log_nonexistent_dotted_revno(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
333
        self.make_minimal_branch()
5105.1.4 by Vincent Ladeuil
Use single quotes so that no test need to be updated.
334
        self.run_bzr_error(["bzr: ERROR: Requested revision: '123.123' "
4955.4.7 by Vincent Ladeuil
Some more cleanup.
335
                            "does not exist in branch:"],
336
                           ['log',  '-r123.123'])
3734.1.1 by Vincent Ladeuil
Fix bug #248427 by adding a --change option to log.
337
3878.3.2 by Marius Kruger
Add tests for log -c with non-exising revno's
338
    def test_log_change_nonexistent_revno(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
339
        self.make_minimal_branch()
5105.1.4 by Vincent Ladeuil
Use single quotes so that no test need to be updated.
340
        self.run_bzr_error(["bzr: ERROR: Requested revision: '1234' "
4955.4.7 by Vincent Ladeuil
Some more cleanup.
341
                            "does not exist in branch:"],
342
                           ['log',  '-c1234'])
3878.3.2 by Marius Kruger
Add tests for log -c with non-exising revno's
343
344
    def test_log_change_nonexistent_dotted_revno(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
345
        self.make_minimal_branch()
5105.1.4 by Vincent Ladeuil
Use single quotes so that no test need to be updated.
346
        self.run_bzr_error(["bzr: ERROR: Requested revision: '123.123' "
4955.4.7 by Vincent Ladeuil
Some more cleanup.
347
                            "does not exist in branch:"],
348
                           ['log', '-c123.123'])
3878.3.2 by Marius Kruger
Add tests for log -c with non-exising revno's
349
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
350
    def test_log_change_single_revno_only(self):
351
        self.make_minimal_branch()
4325.4.6 by Vincent Ladeuil
Fixed as per John's and Markus reviews.
352
        self.run_bzr_error(['bzr: ERROR: Option --change does not'
353
                           ' accept revision ranges'],
3734.1.1 by Vincent Ladeuil
Fix bug #248427 by adding a --change option to log.
354
                           ['log', '--change', '2..3'])
355
356
    def test_log_change_incompatible_with_revision(self):
4325.4.6 by Vincent Ladeuil
Fixed as per John's and Markus reviews.
357
        self.run_bzr_error(['bzr: ERROR: --revision and --change'
358
                           ' are mutually exclusive'],
3734.1.1 by Vincent Ladeuil
Fix bug #248427 by adding a --change option to log.
359
                           ['log', '--change', '2', '--revision', '3'])
360
2100.1.1 by wang
Running ``bzr log`` on nonexistent file gives an error instead of the
361
    def test_log_nonexistent_file(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
362
        self.make_minimal_branch()
2100.1.1 by wang
Running ``bzr log`` on nonexistent file gives an error instead of the
363
        # files that don't exist in either the basis tree or working tree
364
        # should give an error
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
365
        out, err = self.run_bzr('log does-not-exist', retcode=3)
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
366
        self.assertContainsRe(err,
367
                              'Path unknown at end or start of revision range: '
368
                              'does-not-exist')
2388.1.11 by Alexander Belchenko
changes after John's review
369
4955.5.2 by Vincent Ladeuil
Simplify tests.
370
    def test_log_reversed_revspecs(self):
371
        self.make_linear_branch()
372
        self.run_bzr_error(('bzr: ERROR: Start revision must be older than '
373
                            'the end revision.\n',),
374
                           ['log', '-r3..1'])
375
376
    def test_log_reversed_dotted_revspecs(self):
377
        self.make_merged_branch()
378
        self.run_bzr_error(('bzr: ERROR: Start revision not found in '
379
                            'left-hand history of end revision.\n',),
380
                           "log -r 1.1.1..1")
381
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
382
    def test_log_bad_message_re(self):
383
        """Bad --message argument gives a sensible message
5326.2.1 by Parth Malwankar
added InvalidPattern error.
384
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
385
        See https://bugs.launchpad.net/bzr/+bug/251352
386
        """
387
        self.make_minimal_branch()
388
        out, err = self.run_bzr(['log', '-m', '*'], retcode=3)
5326.2.1 by Parth Malwankar
added InvalidPattern error.
389
        self.assertContainsRe(err, "ERROR.*Invalid pattern.*nothing to repeat")
5339.1.1 by Parth Malwankar
fixes errors.InvalidPattern to work on Python2.5
390
        self.assertNotContainsRe(err, "Unprintable exception")
5326.2.1 by Parth Malwankar
added InvalidPattern error.
391
        self.assertEqual(out, '')
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
392
4955.4.7 by Vincent Ladeuil
Some more cleanup.
393
    def test_log_unsupported_timezone(self):
394
        self.make_linear_branch()
395
        self.run_bzr_error(['bzr: ERROR: Unsupported timezone format "foo", '
396
                            'options are "utc", "original", "local".'],
397
                           ['log', '--timezone', 'foo'])
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
398
5097.1.13 by Vincent Ladeuil
Add more tests.
399
    def test_log_exclude_ancestry_no_range(self):
400
        self.make_linear_branch()
401
        self.run_bzr_error(['bzr: ERROR: --exclude-common-ancestry'
402
                            ' requires -r with two revisions'],
403
                           ['log', '--exclude-common-ancestry'])
404
405
    def test_log_exclude_ancestry_single_revision(self):
406
        self.make_merged_branch()
407
        self.run_bzr_error(['bzr: ERROR: --exclude-common-ancestry'
408
                            ' requires two different revisions'],
409
                           ['log', '--exclude-common-ancestry',
410
                            '-r1.1.1..1.1.1'])
4955.5.1 by Vincent Ladeuil
Split some tests to better characterize the classes
411
412
class TestLogTags(TestLog):
413
2388.1.3 by Erik Bagfors
tests for tags in log output
414
    def test_log_with_tags(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
415
        tree = self.make_linear_branch(format='dirstate-tags')
2664.14.1 by Daniel Watkins
Fixed tests.blackbox.test_log to use internals where appropriate.
416
        branch = tree.branch
417
        branch.tags.set_tag('tag1', branch.get_rev_id(1))
418
        branch.tags.set_tag('tag1.1', branch.get_rev_id(1))
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
419
        branch.tags.set_tag('tag3', branch.last_revision())
420
2530.3.1 by Martin Pool
Cleanup old variations on run_bzr in the test suite
421
        log = self.run_bzr("log -r-1")[0]
2388.1.3 by Erik Bagfors
tests for tags in log output
422
        self.assertTrue('tags: tag3' in log)
423
2530.3.1 by Martin Pool
Cleanup old variations on run_bzr in the test suite
424
        log = self.run_bzr("log -r1")[0]
2388.1.3 by Erik Bagfors
tests for tags in log output
425
        # I guess that we can't know the order of tags in the output
426
        # since dicts are unordered, need to check both possibilities
2388.1.11 by Alexander Belchenko
changes after John's review
427
        self.assertContainsRe(log, r'tags: (tag1, tag1\.1|tag1\.1, tag1)')
428
2388.1.9 by Erik Bagfors
test for merges with tags in log
429
    def test_merged_log_with_tags(self):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
430
        branch1_tree = self.make_linear_branch('branch1',
431
                                               format='dirstate-tags')
2664.14.1 by Daniel Watkins
Fixed tests.blackbox.test_log to use internals where appropriate.
432
        branch1 = branch1_tree.branch
433
        branch2_tree = branch1_tree.bzrdir.sprout('branch2').open_workingtree()
434
        branch1_tree.commit(message='foobar', allow_pointless=True)
435
        branch1.tags.set_tag('tag1', branch1.last_revision())
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
436
        # tags don't propagate if we don't merge
437
        self.run_bzr('merge ../branch1', working_dir='branch2')
2664.14.1 by Daniel Watkins
Fixed tests.blackbox.test_log to use internals where appropriate.
438
        branch2_tree.commit(message='merge branch 1')
4511.3.11 by Marius Kruger
* fix tests again
439
        log = self.run_bzr("log -n0 -r-1", working_dir='branch2')[0]
2388.1.11 by Alexander Belchenko
changes after John's review
440
        self.assertContainsRe(log, r'    tags: tag1')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
441
        log = self.run_bzr("log -n0 -r3.1.1", working_dir='branch2')[0]
2466.12.2 by Kent Gibson
shift log output with only merge revisions to the left margin
442
        self.assertContainsRe(log, r'tags: tag1')
2388.1.3 by Erik Bagfors
tests for tags in log output
443
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
444
445
class TestLogVerbose(TestLog):
3874.1.8 by Vincent Ladeuil
Fixed as ber Robert's review.
446
447
    def setUp(self):
448
        super(TestLogVerbose, self).setUp()
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
449
        self.make_minimal_branch()
3874.1.8 by Vincent Ladeuil
Fixed as ber Robert's review.
450
451
    def assertUseShortDeltaFormat(self, cmd):
452
        log = self.run_bzr(cmd)[0]
453
        # Check that we use the short status format
3947.1.7 by Ian Clatworthy
tweak indenting/offsetting for --short given dotted revno lengths
454
        self.assertContainsRe(log, '(?m)^\s*A  hello.txt$')
455
        self.assertNotContainsRe(log, '(?m)^\s*added:$')
3874.1.4 by Vincent Ladeuil
Fixed as per Aarons' comment.
456
3874.1.8 by Vincent Ladeuil
Fixed as ber Robert's review.
457
    def assertUseLongDeltaFormat(self, cmd):
458
        log = self.run_bzr(cmd)[0]
459
        # Check that we use the long status format
3947.1.7 by Ian Clatworthy
tweak indenting/offsetting for --short given dotted revno lengths
460
        self.assertNotContainsRe(log, '(?m)^\s*A  hello.txt$')
461
        self.assertContainsRe(log, '(?m)^\s*added:$')
3874.1.8 by Vincent Ladeuil
Fixed as ber Robert's review.
462
463
    def test_log_short_verbose(self):
464
        self.assertUseShortDeltaFormat(['log', '--short', '-v'])
465
3874.1.4 by Vincent Ladeuil
Fixed as per Aarons' comment.
466
    def test_log_short_verbose_verbose(self):
3874.1.8 by Vincent Ladeuil
Fixed as ber Robert's review.
467
        self.assertUseLongDeltaFormat(['log', '--short', '-vv'])
3874.1.4 by Vincent Ladeuil
Fixed as per Aarons' comment.
468
469
    def test_log_long_verbose(self):
3874.1.7 by Vincent Ladeuil
Restrict '-v' change to log --short only.
470
        # Check that we use the long status format, ignoring the verbosity
471
        # level
3874.1.8 by Vincent Ladeuil
Fixed as ber Robert's review.
472
        self.assertUseLongDeltaFormat(['log', '--long', '-v'])
3874.1.4 by Vincent Ladeuil
Fixed as per Aarons' comment.
473
474
    def test_log_long_verbose_verbose(self):
3874.1.7 by Vincent Ladeuil
Restrict '-v' change to log --short only.
475
        # Check that we use the long status format, ignoring the verbosity
476
        # level
3874.1.8 by Vincent Ladeuil
Fixed as ber Robert's review.
477
        self.assertUseLongDeltaFormat(['log', '--long', '-vv'])
3874.1.1 by Vincent Ladeuil
Fix #87179 by using the short status format when the short format is used for log.
478
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
479
4955.4.8 by Vincent Ladeuil
Simplify more tests.
480
class TestLogMerges(TestLogWithLogCatcher):
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
481
482
    def setUp(self):
483
        super(TestLogMerges, self).setUp()
484
        self.make_branches_with_merges()
485
486
    def make_branches_with_merges(self):
487
        level0 = self.make_branch_and_tree('level0')
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
488
        self.wt_commit(level0, 'in branch level0')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
489
        level1 = level0.bzrdir.sprout('level1').open_workingtree()
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
490
        self.wt_commit(level1, 'in branch level1')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
491
        level2 = level1.bzrdir.sprout('level2').open_workingtree()
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
492
        self.wt_commit(level2, 'in branch level2')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
493
        level1.merge_from_branch(level2.branch)
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
494
        self.wt_commit(level1, 'merge branch level2')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
495
        level0.merge_from_branch(level1.branch)
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
496
        self.wt_commit(level0, 'merge branch level1')
3947.1.3 by Ian Clatworthy
blackbox tests
497
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
498
    def test_merges_are_indented_by_level(self):
4955.4.8 by Vincent Ladeuil
Simplify more tests.
499
        self.run_bzr(['log', '-n0'], working_dir='level0')
500
        revnos_and_depth = [(r.revno, r.merge_depth)
501
                            for r in self.get_captured_revisions()]
502
        self.assertEqual([('2', 0), ('1.1.2', 1), ('1.2.1', 2), ('1.1.1', 1),
503
                          ('1', 0)],
504
                         [(r.revno, r.merge_depth)
505
                            for r in self.get_captured_revisions()])
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
506
3947.1.3 by Ian Clatworthy
blackbox tests
507
    def test_force_merge_revisions_off(self):
4955.4.8 by Vincent Ladeuil
Simplify more tests.
508
        self.assertLogRevnos(['-n1'], ['2', '1'], working_dir='level0')
3947.1.3 by Ian Clatworthy
blackbox tests
509
510
    def test_force_merge_revisions_on(self):
4955.4.8 by Vincent Ladeuil
Simplify more tests.
511
        self.assertLogRevnos(['-n0'], ['2', '1.1.2', '1.2.1', '1.1.1', '1'],
512
                             working_dir='level0')
3947.1.7 by Ian Clatworthy
tweak indenting/offsetting for --short given dotted revno lengths
513
4221.2.1 by Ian Clatworthy
--include-merges as an alias for --levels 0 in log
514
    def test_include_merges(self):
515
        # Confirm --include-merges gives the same output as -n0
4955.4.8 by Vincent Ladeuil
Simplify more tests.
516
        self.assertLogRevnos(['--include-merges'],
517
                             ['2', '1.1.2', '1.2.1', '1.1.1', '1'],
518
                             working_dir='level0')
519
        self.assertLogRevnos(['--include-merges'],
520
                             ['2', '1.1.2', '1.2.1', '1.1.1', '1'],
521
                             working_dir='level0')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
522
        out_im, err_im = self.run_bzr('log --include-merges',
523
                                      working_dir='level0')
524
        out_n0, err_n0 = self.run_bzr('log -n0', working_dir='level0')
525
        self.assertEqual('', err_im)
526
        self.assertEqual('', err_n0)
4221.2.1 by Ian Clatworthy
--include-merges as an alias for --levels 0 in log
527
        self.assertEqual(out_im, out_n0)
528
3947.1.7 by Ian Clatworthy
tweak indenting/offsetting for --short given dotted revno lengths
529
    def test_force_merge_revisions_N(self):
4955.4.8 by Vincent Ladeuil
Simplify more tests.
530
        self.assertLogRevnos(['-n2'],
531
                             ['2', '1.1.2', '1.1.1', '1'],
532
                             working_dir='level0')
3947.1.3 by Ian Clatworthy
blackbox tests
533
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
534
    def test_merges_single_merge_rev(self):
4955.4.8 by Vincent Ladeuil
Simplify more tests.
535
        self.assertLogRevnosAndDepths(['-n0', '-r1.1.2'],
536
                                      [('1.1.2', 0), ('1.2.1', 1)],
537
                                      working_dir='level0')
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
538
539
    def test_merges_partial_range(self):
4955.4.8 by Vincent Ladeuil
Simplify more tests.
540
        self.assertLogRevnosAndDepths(
541
                ['-n0', '-r1.1.1..1.1.2'],
542
                [('1.1.2', 0), ('1.2.1', 1), ('1.1.1', 0)],
543
                working_dir='level0')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
544
4511.3.1 by Marius Kruger
add test_merges_partial_range_ignore_before_lower_bound
545
    def test_merges_partial_range_ignore_before_lower_bound(self):
4511.3.11 by Marius Kruger
* fix tests again
546
        """Dont show revisions before the lower bound's merged revs"""
4955.4.8 by Vincent Ladeuil
Simplify more tests.
547
        self.assertLogRevnosAndDepths(
548
                ['-n0', '-r1.1.2..2'],
549
                [('2', 0), ('1.1.2', 1), ('1.2.1', 2)],
550
                working_dir='level0')
4511.3.1 by Marius Kruger
add test_merges_partial_range_ignore_before_lower_bound
551
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
552
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
553
class TestLogDiff(TestLogWithLogCatcher):
554
555
    # FIXME: We need specific tests for each LogFormatter about how the diffs
556
    # are displayed: --long indent them by depth, --short use a fixed
557
    # indent and --line does't display them. -- vila 10019
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
558
559
    def setUp(self):
560
        super(TestLogDiff, self).setUp()
561
        self.make_branch_with_diffs()
562
563
    def make_branch_with_diffs(self):
564
        level0 = self.make_branch_and_tree('level0')
565
        self.build_tree(['level0/file1', 'level0/file2'])
566
        level0.add('file1')
567
        level0.add('file2')
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
568
        self.wt_commit(level0, 'in branch level0')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
569
570
        level1 = level0.bzrdir.sprout('level1').open_workingtree()
571
        self.build_tree_contents([('level1/file2', 'hello\n')])
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
572
        self.wt_commit(level1, 'in branch level1')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
573
        level0.merge_from_branch(level1.branch)
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
574
        self.wt_commit(level0, 'merge branch level1')
3943.5.3 by Ian Clatworthy
add tests
575
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
576
    def _diff_file1_revno1(self):
577
        return """=== added file 'file1'
4325.4.6 by Vincent Ladeuil
Fixed as per John's and Markus reviews.
578
--- file1\t1970-01-01 00:00:00 +0000
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
579
+++ file1\t2005-11-22 00:00:00 +0000
3943.5.6 by Ian Clatworthy
feedback from jam's review
580
@@ -0,0 +1,1 @@
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
581
+contents of level0/file1
3943.5.6 by Ian Clatworthy
feedback from jam's review
582
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
583
"""
584
585
    def _diff_file2_revno2(self):
586
        return """=== modified file 'file2'
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
587
--- file2\t2005-11-22 00:00:00 +0000
588
+++ file2\t2005-11-22 00:00:01 +0000
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
589
@@ -1,1 +1,1 @@
590
-contents of level0/file2
591
+hello
592
593
"""
594
595
    def _diff_file2_revno1_1_1(self):
596
        return """=== modified file 'file2'
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
597
--- file2\t2005-11-22 00:00:00 +0000
598
+++ file2\t2005-11-22 00:00:01 +0000
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
599
@@ -1,1 +1,1 @@
600
-contents of level0/file2
601
+hello
602
603
"""
604
605
    def _diff_file2_revno1(self):
606
        return """=== added file 'file2'
4325.4.6 by Vincent Ladeuil
Fixed as per John's and Markus reviews.
607
--- file2\t1970-01-01 00:00:00 +0000
4955.4.17 by Vincent Ladeuil
Use a data factory for commit properties and reduce code duplication.
608
+++ file2\t2005-11-22 00:00:00 +0000
3943.5.6 by Ian Clatworthy
feedback from jam's review
609
@@ -0,0 +1,1 @@
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
610
+contents of level0/file2
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
611
612
"""
613
4955.4.13 by Vincent Ladeuil
Remove dead code.
614
    def assertLogRevnosAndDiff(self, args, expected,
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
615
                            working_dir='.'):
616
        self.run_bzr(['log', '-p'] + args, working_dir=working_dir)
617
        expected_revnos_and_depths = [
618
            (revno, depth) for revno, depth, diff in expected]
619
        # Check the revnos and depths first to make debugging easier
620
        self.assertEqual(expected_revnos_and_depths,
621
                         [(r.revno, r.merge_depth)
622
                           for r in self.get_captured_revisions()])
623
        # Now check the diffs, adding the revno  in case of failure
624
        fmt = 'In revno %s\n%s'
625
        for expected_rev, actual_rev in izip(expected,
626
                                             self.get_captured_revisions()):
627
            revno, depth, expected_diff = expected_rev
628
            actual_diff = actual_rev.diff
629
            self.assertEqualDiff(fmt % (revno, expected_diff),
630
                                 fmt % (revno, actual_diff))
631
632
    def test_log_diff_with_merges(self):
4955.4.13 by Vincent Ladeuil
Remove dead code.
633
        self.assertLogRevnosAndDiff(
634
            ['-n0'],
635
            [('2', 0, self._diff_file2_revno2()),
636
             ('1.1.1', 1, self._diff_file2_revno1_1_1()),
637
             ('1', 0, self._diff_file1_revno1()
638
              + self._diff_file2_revno1())],
639
            working_dir='level0')
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
640
641
642
    def test_log_diff_file1(self):
4955.4.13 by Vincent Ladeuil
Remove dead code.
643
        self.assertLogRevnosAndDiff(['-n0', 'file1'],
644
                                    [('1', 0, self._diff_file1_revno1())],
645
                                    working_dir='level0')
4955.4.11 by Vincent Ladeuil
Give some tests a better focus and simplify them accordingly.
646
647
    def test_log_diff_file2(self):
4955.4.13 by Vincent Ladeuil
Remove dead code.
648
        self.assertLogRevnosAndDiff(['-n1', 'file2'],
649
                                    [('2', 0, self._diff_file2_revno2()),
650
                                     ('1', 0, self._diff_file2_revno1())],
651
                                    working_dir='level0')
4325.4.5 by Vincent Ladeuil
Some cleanup in blackbox log tests.
652
653
654
class TestLogUnicodeDiff(TestLog):
3943.5.4 by Ian Clatworthy
filter diff by file
655
4110.1.1 by Alexander Belchenko
Fixed problem with `log -p` and non-ascii content of files: show_diff should write the diff to exact [stdout] stream.
656
    def test_log_show_diff_non_ascii(self):
657
        # Smoke test for bug #328007 UnicodeDecodeError on 'log -p'
658
        message = u'Message with \xb5'
659
        body = 'Body with \xb5\n'
660
        wt = self.make_branch_and_tree('.')
661
        self.build_tree_contents([('foo', body)])
662
        wt.add('foo')
663
        wt.commit(message=message)
664
        # check that command won't fail with unicode error
665
        # don't care about exact output because we have other tests for this
666
        out,err = self.run_bzr('log -p --long')
667
        self.assertNotEqual('', out)
668
        self.assertEqual('', err)
669
        out,err = self.run_bzr('log -p --short')
670
        self.assertNotEqual('', out)
671
        self.assertEqual('', err)
672
        out,err = self.run_bzr('log -p --line')
673
        self.assertNotEqual('', out)
674
        self.assertEqual('', err)
675
3943.5.3 by Ian Clatworthy
add tests
676
4325.4.3 by Vincent Ladeuil
More cleanups.
677
class TestLogEncodings(tests.TestCaseInTempDir):
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
678
679
    _mu = u'\xb5'
680
    _message = u'Message with \xb5'
681
682
    # Encodings which can encode mu
683
    good_encodings = [
684
        'utf-8',
685
        'latin-1',
686
        'iso-8859-1',
687
        'cp437', # Common windows encoding
4110.1.1 by Alexander Belchenko
Fixed problem with `log -p` and non-ascii content of files: show_diff should write the diff to exact [stdout] stream.
688
        'cp1251', # Russian windows encoding
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
689
        'cp1258', # Common windows encoding
690
    ]
691
    # Encodings which cannot encode mu
692
    bad_encodings = [
693
        'ascii',
694
        'iso-8859-2',
695
        'koi8_r',
696
    ]
697
698
    def setUp(self):
4325.4.3 by Vincent Ladeuil
More cleanups.
699
        super(TestLogEncodings, self).setUp()
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
700
        self.overrideAttr(osutils, '_cached_user_encoding')
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
701
702
    def create_branch(self):
703
        bzr = self.run_bzr
704
        bzr('init')
4955.4.16 by Vincent Ladeuil
Be windows-friendly and don't left opened files behind.
705
        self.build_tree_contents([('a', 'some stuff\n')])
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
706
        bzr('add a')
707
        bzr(['commit', '-m', self._message])
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
708
709
    def try_encoding(self, encoding, fail=False):
710
        bzr = self.run_bzr
711
        if fail:
712
            self.assertRaises(UnicodeEncodeError,
713
                self._mu.encode, encoding)
714
            encoded_msg = self._message.encode(encoding, 'replace')
715
        else:
716
            encoded_msg = self._message.encode(encoding)
717
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
718
        old_encoding = osutils._cached_user_encoding
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
719
        # This test requires that 'run_bzr' uses the current
720
        # bzrlib, because we override user_encoding, and expect
721
        # it to be used
722
        try:
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
723
            osutils._cached_user_encoding = 'ascii'
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
724
            # We should be able to handle any encoding
725
            out, err = bzr('log', encoding=encoding)
726
            if not fail:
727
                # Make sure we wrote mu as we expected it to exist
728
                self.assertNotEqual(-1, out.find(encoded_msg))
729
                out_unicode = out.decode(encoding)
730
                self.assertNotEqual(-1, out_unicode.find(self._message))
731
            else:
732
                self.assertNotEqual(-1, out.find('Message with ?'))
733
        finally:
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
734
            osutils._cached_user_encoding = old_encoding
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
735
736
    def test_log_handles_encoding(self):
737
        self.create_branch()
738
739
        for encoding in self.good_encodings:
740
            self.try_encoding(encoding)
741
742
    def test_log_handles_bad_encoding(self):
743
        self.create_branch()
744
745
        for encoding in self.bad_encodings:
746
            self.try_encoding(encoding, fail=True)
747
748
    def test_stdout_encoding(self):
749
        bzr = self.run_bzr
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
750
        osutils._cached_user_encoding = "cp1251"
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
751
752
        bzr('init')
753
        self.build_tree(['a'])
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
754
        bzr('add a')
755
        bzr(['commit', '-m', u'\u0422\u0435\u0441\u0442'])
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
756
        stdout, stderr = self.run_bzr('log', encoding='cp866')
757
758
        message = stdout.splitlines()[-1]
759
760
        # explanation of the check:
761
        # u'\u0422\u0435\u0441\u0442' is word 'Test' in russian
762
        # in cp866  encoding this is string '\x92\xa5\xe1\xe2'
763
        # in cp1251 encoding this is string '\xd2\xe5\xf1\xf2'
764
        # This test should check that output of log command
765
        # encoded to sys.stdout.encoding
766
        test_in_cp866 = '\x92\xa5\xe1\xe2'
767
        test_in_cp1251 = '\xd2\xe5\xf1\xf2'
768
        # Make sure the log string is encoded in cp866
769
        self.assertEquals(test_in_cp866, message[2:])
770
        # Make sure the cp1251 string is not found anywhere
771
        self.assertEquals(-1, stdout.find(test_in_cp1251))
772
1551.10.18 by Aaron Bentley
Log works in local treeless branches (#84247)
773
4955.4.9 by Vincent Ladeuil
More simplifications.
774
class TestLogFile(TestLogWithLogCatcher):
1551.10.18 by Aaron Bentley
Log works in local treeless branches (#84247)
775
776
    def test_log_local_branch_file(self):
777
        """We should be able to log files in local treeless branches"""
778
        tree = self.make_branch_and_tree('tree')
779
        self.build_tree(['tree/file'])
780
        tree.add('file')
781
        tree.commit('revision 1')
782
        tree.bzrdir.destroy_workingtree()
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
783
        self.run_bzr('log tree/file')
2359.1.1 by Kent Gibson
Fix ``bzr log <file>`` so it only logs the revisions that changed the file, and does it faster.
784
3943.6.1 by Ian Clatworthy
find file using the end revision
785
    def prepare_tree(self, complex=False):
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
786
        # The complex configuration includes deletes and renames
2359.1.1 by Kent Gibson
Fix ``bzr log <file>`` so it only logs the revisions that changed the file, and does it faster.
787
        tree = self.make_branch_and_tree('parent')
788
        self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
789
        tree.add('file1')
790
        tree.commit('add file1')
791
        tree.add('file2')
792
        tree.commit('add file2')
793
        tree.add('file3')
794
        tree.commit('add file3')
2664.14.1 by Daniel Watkins
Fixed tests.blackbox.test_log to use internals where appropriate.
795
        child_tree = tree.bzrdir.sprout('child').open_workingtree()
796
        self.build_tree_contents([('child/file2', 'hello')])
797
        child_tree.commit(message='branch 1')
798
        tree.merge_from_branch(child_tree.branch)
799
        tree.commit(message='merge child branch')
3943.6.1 by Ian Clatworthy
find file using the end revision
800
        if complex:
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
801
            tree.remove('file2')
802
            tree.commit('remove file2')
803
            tree.rename_one('file3', 'file4')
804
            tree.commit('file3 is now called file4')
3943.6.1 by Ian Clatworthy
find file using the end revision
805
            tree.remove('file1')
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
806
            tree.commit('remove file1')
2359.1.1 by Kent Gibson
Fix ``bzr log <file>`` so it only logs the revisions that changed the file, and does it faster.
807
        os.chdir('parent')
3940.1.2 by Ian Clatworthy
add test
808
4955.4.9 by Vincent Ladeuil
More simplifications.
809
    # FIXME: It would be good to parametrize the following tests against all
810
    # formatters. But the revisions selection is not *currently* part of the
811
    # LogFormatter contract, so using LogCatcher is sufficient -- vila 100118
812
    def test_log_file1(self):
813
        self.prepare_tree()
814
        self.assertLogRevnos(['-n0', 'file1'], ['1'])
815
816
    def test_log_file2(self):
817
        self.prepare_tree()
818
        # file2 full history
819
        self.assertLogRevnos(['-n0', 'file2'], ['4', '3.1.1', '2'])
820
        # file2 in a merge revision
821
        self.assertLogRevnos(['-n0', '-r3.1.1', 'file2'], ['3.1.1'])
822
        # file2 in a mainline revision
823
        self.assertLogRevnos(['-n0', '-r4', 'file2'], ['4', '3.1.1'])
824
        # file2 since a revision
825
        self.assertLogRevnos(['-n0', '-r3..', 'file2'], ['4', '3.1.1'])
826
        # file2 up to a revision
827
        self.assertLogRevnos(['-n0', '-r..3', 'file2'], ['2'])
828
829
    def test_log_file3(self):
830
        self.prepare_tree()
831
        self.assertLogRevnos(['-n0', 'file3'], ['3'])
3940.1.2 by Ian Clatworthy
add test
832
3943.6.4 by Ian Clatworthy
review feedback from vila
833
    def test_log_file_historical_missing(self):
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
834
        # Check logging a deleted file gives an error if the
835
        # file isn't found at the end or start of the revision range
3943.6.4 by Ian Clatworthy
review feedback from vila
836
        self.prepare_tree(complex=True)
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
837
        err_msg = "Path unknown at end or start of revision range: file2"
838
        err = self.run_bzr('log file2', retcode=3)[1]
3943.6.1 by Ian Clatworthy
find file using the end revision
839
        self.assertContainsRe(err, err_msg)
840
3943.6.4 by Ian Clatworthy
review feedback from vila
841
    def test_log_file_historical_end(self):
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
842
        # Check logging a deleted file is ok if the file existed
843
        # at the end the revision range
3943.6.4 by Ian Clatworthy
review feedback from vila
844
        self.prepare_tree(complex=True)
4955.4.9 by Vincent Ladeuil
More simplifications.
845
        self.assertLogRevnos(['-n0', '-r..4', 'file2'], ['4', '3.1.1', '2'])
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
846
3943.6.4 by Ian Clatworthy
review feedback from vila
847
    def test_log_file_historical_start(self):
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
848
        # Check logging a deleted file is ok if the file existed
849
        # at the start of the revision range
3943.6.4 by Ian Clatworthy
review feedback from vila
850
        self.prepare_tree(complex=True)
4955.4.9 by Vincent Ladeuil
More simplifications.
851
        self.assertLogRevnos(['file1'], ['1'])
3943.6.1 by Ian Clatworthy
find file using the end revision
852
853
    def test_log_file_renamed(self):
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
854
        """File matched against revision range, not current tree."""
3943.6.1 by Ian Clatworthy
find file using the end revision
855
        self.prepare_tree(complex=True)
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
856
3943.6.1 by Ian Clatworthy
find file using the end revision
857
        # Check logging a renamed file gives an error by default
3943.6.3 by Ian Clatworthy
search the start tree if the end tree doesn't have a file
858
        err_msg = "Path unknown at end or start of revision range: file3"
3943.6.1 by Ian Clatworthy
find file using the end revision
859
        err = self.run_bzr('log file3', retcode=3)[1]
860
        self.assertContainsRe(err, err_msg)
861
862
        # Check we can see a renamed file if we give the right end revision
4955.4.9 by Vincent Ladeuil
More simplifications.
863
        self.assertLogRevnos(['-r..4', 'file3'], ['3'])
4202.2.1 by Ian Clatworthy
get directory logging working again
864
865
4955.4.10 by Vincent Ladeuil
More simplification.
866
class TestLogMultiple(TestLogWithLogCatcher):
4202.2.1 by Ian Clatworthy
get directory logging working again
867
868
    def prepare_tree(self):
869
        tree = self.make_branch_and_tree('parent')
870
        self.build_tree([
871
            'parent/file1',
872
            'parent/file2',
873
            'parent/dir1/',
874
            'parent/dir1/file5',
875
            'parent/dir1/dir2/',
876
            'parent/dir1/dir2/file3',
877
            'parent/file4'])
878
        tree.add('file1')
4202.2.2 by Ian Clatworthy
improve signal-to-noise ratio in tests
879
        tree.commit('add file1')
4202.2.1 by Ian Clatworthy
get directory logging working again
880
        tree.add('file2')
4202.2.2 by Ian Clatworthy
improve signal-to-noise ratio in tests
881
        tree.commit('add file2')
4202.2.1 by Ian Clatworthy
get directory logging working again
882
        tree.add(['dir1', 'dir1/dir2', 'dir1/dir2/file3'])
4202.2.2 by Ian Clatworthy
improve signal-to-noise ratio in tests
883
        tree.commit('add file3')
4202.2.1 by Ian Clatworthy
get directory logging working again
884
        tree.add('file4')
4202.2.2 by Ian Clatworthy
improve signal-to-noise ratio in tests
885
        tree.commit('add file4')
4202.2.1 by Ian Clatworthy
get directory logging working again
886
        tree.add('dir1/file5')
4202.2.2 by Ian Clatworthy
improve signal-to-noise ratio in tests
887
        tree.commit('add file5')
4202.2.1 by Ian Clatworthy
get directory logging working again
888
        child_tree = tree.bzrdir.sprout('child').open_workingtree()
889
        self.build_tree_contents([('child/file2', 'hello')])
4202.2.2 by Ian Clatworthy
improve signal-to-noise ratio in tests
890
        child_tree.commit(message='branch 1')
4202.2.1 by Ian Clatworthy
get directory logging working again
891
        tree.merge_from_branch(child_tree.branch)
4202.2.2 by Ian Clatworthy
improve signal-to-noise ratio in tests
892
        tree.commit(message='merge child branch')
4202.2.1 by Ian Clatworthy
get directory logging working again
893
        os.chdir('parent')
894
895
    def test_log_files(self):
896
        """The log for multiple file should only list revs for those files"""
897
        self.prepare_tree()
4955.4.10 by Vincent Ladeuil
More simplification.
898
        self.assertLogRevnos(['file1', 'file2', 'dir1/dir2/file3'],
899
                             ['6', '5.1.1', '3', '2', '1'])
4202.2.1 by Ian Clatworthy
get directory logging working again
900
901
    def test_log_directory(self):
902
        """The log for a directory should show all nested files."""
903
        self.prepare_tree()
4955.4.10 by Vincent Ladeuil
More simplification.
904
        self.assertLogRevnos(['dir1'], ['5', '3'])
4202.2.1 by Ian Clatworthy
get directory logging working again
905
906
    def test_log_nested_directory(self):
907
        """The log for a directory should show all nested files."""
908
        self.prepare_tree()
4955.4.10 by Vincent Ladeuil
More simplification.
909
        self.assertLogRevnos(['dir1/dir2'], ['3'])
4202.2.1 by Ian Clatworthy
get directory logging working again
910
911
    def test_log_in_nested_directory(self):
912
        """The log for a directory should show all nested files."""
913
        self.prepare_tree()
914
        os.chdir("dir1")
4955.4.10 by Vincent Ladeuil
More simplification.
915
        self.assertLogRevnos(['.'], ['5', '3'])
4202.2.1 by Ian Clatworthy
get directory logging working again
916
917
    def test_log_files_and_directories(self):
918
        """Logging files and directories together should be fine."""
919
        self.prepare_tree()
4955.4.10 by Vincent Ladeuil
More simplification.
920
        self.assertLogRevnos(['file4', 'dir1/dir2'], ['4', '3'])
4202.2.1 by Ian Clatworthy
get directory logging working again
921
922
    def test_log_files_and_dirs_in_nested_directory(self):
923
        """The log for a directory should show all nested files."""
924
        self.prepare_tree()
925
        os.chdir("dir1")
4955.4.10 by Vincent Ladeuil
More simplification.
926
        self.assertLogRevnos(['dir2', 'file5'], ['5', '3'])