64
63
tree.commit(message='merge')
68
class TestLogWithLogCatcher(TestLog):
71
super(TestLogWithLogCatcher, self).setUp()
72
# Capture log formatter creations
73
class MyLogFormatter(test_log.LogCatcher):
75
def __new__(klass, *args, **kwargs):
76
self.log_catcher = test_log.LogCatcher(*args, **kwargs)
77
# Always return our own log formatter
78
return self.log_catcher
79
# Break cycle with closure over self on cleanup by removing method
80
self.addCleanup(setattr, MyLogFormatter, "__new__", None)
83
# Always return our own log formatter class hijacking the
84
# default behavior (which requires setting up a config
87
self.overrideAttr(log.log_formatter_registry, 'get_default', getme)
89
def get_captured_revisions(self):
90
return self.log_catcher.revisions
92
def assertLogRevnos(self, args, expected_revnos, working_dir='.'):
93
self.run_bzr(['log'] + args, working_dir=working_dir)
94
self.assertEqual(expected_revnos,
95
[r.revno for r in self.get_captured_revisions()])
97
def assertLogRevnosAndDepths(self, args, expected_revnos_and_depths,
99
self.run_bzr(['log'] + args, working_dir=working_dir)
100
self.assertEqual(expected_revnos_and_depths,
101
[(r.revno, r.merge_depth)
102
for r in self.get_captured_revisions()])
105
class TestLogRevSpecs(TestLogWithLogCatcher):
107
def test_log_no_revspec(self):
108
self.make_linear_branch()
109
self.assertLogRevnos([], ['3', '2', '1'])
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)
75
def commit_options(self):
76
"""Use some mostly fixed values for commits to simplify tests.
78
Tests can use this function to get some commit attributes. The time
79
stamp is incremented at each commit.
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,
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))
94
class TestLogRevSpecs(TestLog):
111
96
def test_log_null_end_revspec(self):
112
97
self.make_linear_branch()
113
self.assertLogRevnos(['-r1..'], ['3', '2', '1'])
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)
106
full_log = self.run_bzr(['log'])[0]
107
log = self.run_bzr("log -r 1..")[0]
108
self.assertEqualDiff(log, full_log)
115
110
def test_log_null_begin_revspec(self):
116
111
self.make_linear_branch()
117
self.assertLogRevnos(['-r..3'], ['3', '2', '1'])
112
full_log = self.run_bzr(['log'])[0]
113
log = self.run_bzr("log -r ..3")[0]
114
self.assertEqualDiff(full_log, log)
119
116
def test_log_null_both_revspecs(self):
120
117
self.make_linear_branch()
121
self.assertLogRevnos(['-r..'], ['3', '2', '1'])
118
full_log = self.run_bzr(['log'])[0]
119
log = self.run_bzr("log -r ..")[0]
120
self.assertEqualDiff(full_log, log)
122
def test_log_zero_revspec(self):
123
self.make_minimal_branch()
124
self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
127
def test_log_zero_begin_revspec(self):
128
self.make_linear_branch()
129
self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
132
def test_log_zero_end_revspec(self):
133
self.make_linear_branch()
134
self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
123
137
def test_log_negative_begin_revspec_full_log(self):
124
138
self.make_linear_branch()
125
self.assertLogRevnos(['-r-3..'], ['3', '2', '1'])
139
full_log = self.run_bzr(['log'])[0]
140
log = self.run_bzr("log -r -3..")[0]
141
self.assertEqualDiff(full_log, log)
127
143
def test_log_negative_both_revspec_full_log(self):
128
144
self.make_linear_branch()
129
self.assertLogRevnos(['-r-3..-1'], ['3', '2', '1'])
145
full_log = self.run_bzr(['log'])[0]
146
log = self.run_bzr("log -r -3..-1")[0]
147
self.assertEqualDiff(full_log, log)
131
149
def test_log_negative_both_revspec_partial(self):
132
150
self.make_linear_branch()
133
self.assertLogRevnos(['-r-3..-2'], ['2', '1'])
151
log = self.run_bzr("log -r -3..-2")[0]
152
self.assertTrue('revno: 1\n' in log)
153
self.assertTrue('revno: 2\n' in log)
154
self.assertTrue('revno: 3\n' not in log)
135
156
def test_log_negative_begin_revspec(self):
136
157
self.make_linear_branch()
137
self.assertLogRevnos(['-r-2..'], ['3', '2'])
158
log = self.run_bzr("log -r -2..")[0]
159
self.assertTrue('revno: 1\n' not in log)
160
self.assertTrue('revno: 2\n' in log)
161
self.assertTrue('revno: 3\n' in log)
139
163
def test_log_positive_revspecs(self):
140
164
self.make_linear_branch()
141
self.assertLogRevnos(['-r1..3'], ['3', '2', '1'])
165
full_log = self.run_bzr(['log'])[0]
166
log = self.run_bzr("log -r 1..3")[0]
167
self.assertEqualDiff(full_log, log)
143
169
def test_log_dotted_revspecs(self):
144
170
self.make_merged_branch()
145
self.assertLogRevnos(['-n0', '-r1..1.1.1'], ['1.1.1', '1'])
147
def test_log_limit(self):
148
tree = self.make_branch_and_tree('.')
149
# We want more commits than our batch size starts at
150
for pos in range(10):
151
tree.commit("%s" % pos)
152
self.assertLogRevnos(['--limit', '2'], ['10', '9'])
154
def test_log_limit_short(self):
155
self.make_linear_branch()
156
self.assertLogRevnos(['-l', '2'], ['3', '2'])
158
def test_log_change_revno(self):
159
self.make_linear_branch()
160
self.assertLogRevnos(['-c1'], ['1'])
162
def test_branch_revspec(self):
163
foo = self.make_branch_and_tree('foo')
164
bar = self.make_branch_and_tree('bar')
165
self.build_tree(['foo/foo.txt', 'bar/bar.txt'])
168
foo.commit(message='foo')
169
bar.commit(message='bar')
170
self.run_bzr('log -r branch:../bar', working_dir='foo')
171
self.assertEqual([bar.branch.get_rev_id(1)],
173
for r in self.get_captured_revisions()])
176
class TestLogExcludeCommonAncestry(TestLogWithLogCatcher):
178
def test_exclude_common_ancestry_simple_revnos(self):
179
self.make_linear_branch()
180
self.assertLogRevnos(['-r1..3', '--exclude-common-ancestry'],
184
class TestLogMergedLinearAncestry(TestLogWithLogCatcher):
187
super(TestLogMergedLinearAncestry, self).setUp()
188
# FIXME: Using a MemoryTree would be even better here (but until we
189
# stop calling run_bzr, there is no point) --vila 100118.
190
builder = branchbuilder.BranchBuilder(self.get_transport())
191
builder.start_series()
205
builder.build_snapshot('1', None, [
206
('add', ('', 'root-id', 'directory', ''))])
207
builder.build_snapshot('2', ['1'], [])
209
builder.build_snapshot('1.1.1', ['1'], [])
210
# merge branch into mainline
211
builder.build_snapshot('3', ['2', '1.1.1'], [])
212
# new commits in branch
213
builder.build_snapshot('1.1.2', ['1.1.1'], [])
214
builder.build_snapshot('1.1.3', ['1.1.2'], [])
215
# merge branch into mainline
216
builder.build_snapshot('4', ['3', '1.1.3'], [])
217
# merge mainline into branch
218
builder.build_snapshot('1.1.4', ['1.1.3', '4'], [])
219
# merge branch into mainline
220
builder.build_snapshot('5', ['4', '1.1.4'], [])
221
builder.finish_series()
224
self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4'],
225
['1.1.4', '4', '1.1.3', '1.1.2', '3', '1.1.1'])
226
def test_n0_forward(self):
227
self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4', '--forward'],
228
['3', '1.1.1', '4', '1.1.2', '1.1.3', '1.1.4'])
231
# starting from 1.1.4 we follow the left-hand ancestry
232
self.assertLogRevnos(['-n1', '-r1.1.1..1.1.4'],
233
['1.1.4', '1.1.3', '1.1.2', '1.1.1'])
235
def test_n1_forward(self):
236
self.assertLogRevnos(['-n1', '-r1.1.1..1.1.4', '--forward'],
237
['1.1.1', '1.1.2', '1.1.3', '1.1.4'])
240
class Test_GenerateAllRevisions(TestLogWithLogCatcher):
243
super(Test_GenerateAllRevisions, self).setUp()
244
builder = self.make_branch_with_many_merges()
245
b = builder.get_branch()
247
self.addCleanup(b.unlock)
250
def make_branch_with_many_merges(self, path='.', format=None):
251
builder = branchbuilder.BranchBuilder(self.get_transport())
252
builder.start_series()
253
# The graph below may look a bit complicated (and it may be but I've
254
# banged my head enough on it) but the bug requires at least dotted
255
# revnos *and* merged revisions below that.
256
builder.build_snapshot('1', None, [
257
('add', ('', 'root-id', 'directory', ''))])
258
builder.build_snapshot('2', ['1'], [])
259
builder.build_snapshot('1.1.1', ['1'], [])
260
builder.build_snapshot('2.1.1', ['2'], [])
261
builder.build_snapshot('3', ['2', '1.1.1'], [])
262
builder.build_snapshot('2.1.2', ['2.1.1'], [])
263
builder.build_snapshot('2.2.1', ['2.1.1'], [])
264
builder.build_snapshot('2.1.3', ['2.1.2', '2.2.1'], [])
265
builder.build_snapshot('4', ['3', '2.1.3'], [])
266
builder.build_snapshot('5', ['4', '2.1.2'], [])
267
builder.finish_series()
270
def test_not_an_ancestor(self):
271
self.assertRaises(errors.BzrCommandError,
272
log._generate_all_revisions,
273
self.branch, '1.1.1', '2.1.3', 'reverse',
274
delayed_graph_generation=True)
276
def test_wrong_order(self):
277
self.assertRaises(errors.BzrCommandError,
278
log._generate_all_revisions,
279
self.branch, '5', '2.1.3', 'reverse',
280
delayed_graph_generation=True)
282
def test_no_start_rev_id_with_end_rev_id_being_a_merge(self):
283
revs = log._generate_all_revisions(
284
self.branch, None, '2.1.3',
285
'reverse', delayed_graph_generation=True)
288
class TestLogRevSpecsWithPaths(TestLogWithLogCatcher):
290
def test_log_revno_n_path_wrong_namespace(self):
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))
174
def test_log_reversed_revspecs(self):
175
self.make_linear_branch()
176
self.run_bzr_error(('bzr: ERROR: Start revision must be older than '
177
'the end revision.\n',),
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',),
186
def test_log_revno_n_path(self):
291
187
self.make_linear_branch('branch1')
292
188
self.make_linear_branch('branch2')
293
# There is no guarantee that a path exist between two arbitrary
295
self.run_bzr("log -r revno:2:branch1..revno:3:branch2", retcode=3)
297
def test_log_revno_n_path_correct_order(self):
298
self.make_linear_branch('branch2')
299
self.assertLogRevnos(['-rrevno:1:branch2..revno:3:branch2'],
302
def test_log_revno_n_path(self):
303
self.make_linear_branch('branch2')
304
self.assertLogRevnos(['-rrevno:1:branch2'],
306
rev_props = self.log_catcher.revisions[0].rev.properties
307
self.assertEqual('branch2', rev_props['branch-nick'])
310
class TestLogErrors(TestLog):
312
def test_log_zero_revspec(self):
313
self.make_minimal_branch()
314
self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
317
def test_log_zero_begin_revspec(self):
318
self.make_linear_branch()
319
self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
322
def test_log_zero_end_revspec(self):
323
self.make_linear_branch()
324
self.run_bzr_error(['bzr: ERROR: Logging revision 0 is invalid.'],
190
self.run_bzr("log -r revno:2:branch1..revno:3:branch2", retcode=3)[0]
192
log = self.run_bzr("log -r revno:1:branch2..revno:3:branch2")[0]
193
full_log = self.run_bzr(['log'], working_dir='branch2')[0]
194
self.assertEqualDiff(full_log, log)
195
log = self.run_bzr("log -r revno:1:branch2")[0]
196
self.assertTrue('revno: 1\n' in log)
197
self.assertTrue('revno: 2\n' not in log)
198
self.assertTrue('branch nick: branch2\n' in log)
199
self.assertTrue('branch nick: branch1\n' not in log)
327
201
def test_log_nonexistent_revno(self):
328
202
self.make_minimal_branch()
329
self.run_bzr_error(["bzr: ERROR: Requested revision: '1234' "
330
"does not exist in branch:"],
203
(out, err) = self.run_bzr_error(
204
["bzr: ERROR: Requested revision: '1234' "
205
"does not exist in branch:"],
333
208
def test_log_nonexistent_dotted_revno(self):
334
209
self.make_minimal_branch()
335
self.run_bzr_error(["bzr: ERROR: Requested revision: '123.123' "
336
"does not exist in branch:"],
337
['log', '-r123.123'])
210
(out, err) = self.run_bzr_error(
211
["bzr: ERROR: Requested revision: '123.123' "
212
"does not exist in branch:"],
213
['log', '-r123.123'])
215
def test_log_change_revno(self):
216
self.make_linear_branch()
217
expected_log = self.run_bzr("log -r 1")[0]
218
log = self.run_bzr("log -c 1")[0]
219
self.assertEqualDiff(expected_log, log)
339
221
def test_log_change_nonexistent_revno(self):
340
222
self.make_minimal_branch()
341
self.run_bzr_error(["bzr: ERROR: Requested revision: '1234' "
342
"does not exist in branch:"],
223
(out, err) = self.run_bzr_error(
224
["bzr: ERROR: Requested revision: '1234' "
225
"does not exist in branch:"],
345
228
def test_log_change_nonexistent_dotted_revno(self):
346
229
self.make_minimal_branch()
347
self.run_bzr_error(["bzr: ERROR: Requested revision: '123.123' "
348
"does not exist in branch:"],
349
['log', '-c123.123'])
230
(out, err) = self.run_bzr_error(
231
["bzr: ERROR: Requested revision: '123.123' "
232
"does not exist in branch:"],
233
['log', '-c123.123'])
351
235
def test_log_change_single_revno_only(self):
352
236
self.make_minimal_branch()
509
373
def make_branches_with_merges(self):
510
374
level0 = self.make_branch_and_tree('level0')
511
self.wt_commit(level0, 'in branch level0')
375
level0.commit(message='in branch level0', **self.commit_options())
512
377
level1 = level0.bzrdir.sprout('level1').open_workingtree()
513
self.wt_commit(level1, 'in branch level1')
378
level1.commit(message='in branch level1', **self.commit_options())
514
380
level2 = level1.bzrdir.sprout('level2').open_workingtree()
515
self.wt_commit(level2, 'in branch level2')
381
level2.commit(message='in branch level2', **self.commit_options())
516
383
level1.merge_from_branch(level2.branch)
517
self.wt_commit(level1, 'merge branch level2')
384
level1.commit(message='merge branch level2', **self.commit_options())
518
386
level0.merge_from_branch(level1.branch)
519
self.wt_commit(level0, 'merge branch level1')
387
level0.commit(message='merge branch level1', **self.commit_options())
521
389
def test_merges_are_indented_by_level(self):
522
self.run_bzr(['log', '-n0'], working_dir='level0')
523
revnos_and_depth = [(r.revno, r.merge_depth)
524
for r in self.get_captured_revisions()]
525
self.assertEqual([('2', 0), ('1.1.2', 1), ('1.2.1', 2), ('1.1.1', 1),
527
[(r.revno, r.merge_depth)
528
for r in self.get_captured_revisions()])
391
------------------------------------------------------------
393
committer: Lorem Ipsum <test@example.com>
398
------------------------------------------------------------
400
committer: Lorem Ipsum <test@example.com>
405
------------------------------------------------------------
407
committer: Lorem Ipsum <test@example.com>
412
------------------------------------------------------------
414
committer: Lorem Ipsum <test@example.com>
419
------------------------------------------------------------
421
committer: Lorem Ipsum <test@example.com>
427
self.check_log(expected, ['-n0'])
530
429
def test_force_merge_revisions_off(self):
531
self.assertLogRevnos(['-n1'], ['2', '1'], working_dir='level0')
431
------------------------------------------------------------
433
committer: Lorem Ipsum <test@example.com>
438
------------------------------------------------------------
440
committer: Lorem Ipsum <test@example.com>
446
self.check_log(expected, ['--long', '-n1'])
533
448
def test_force_merge_revisions_on(self):
534
self.assertLogRevnos(['-n0'], ['2', '1.1.2', '1.2.1', '1.1.1', '1'],
535
working_dir='level0')
450
2 Lorem Ipsum\t2005-11-22 [merge]
453
1.1.2 Lorem Ipsum\t2005-11-22 [merge]
456
1.2.1 Lorem Ipsum\t2005-11-22
459
1.1.1 Lorem Ipsum\t2005-11-22
462
1 Lorem Ipsum\t2005-11-22
466
self.check_log(expected, ['--short', '-n0'])
537
468
def test_include_merges(self):
538
469
# Confirm --include-merges gives the same output as -n0
539
self.assertLogRevnos(['--include-merges'],
540
['2', '1.1.2', '1.2.1', '1.1.1', '1'],
541
working_dir='level0')
542
self.assertLogRevnos(['--include-merges'],
543
['2', '1.1.2', '1.2.1', '1.1.1', '1'],
544
working_dir='level0')
545
470
out_im, err_im = self.run_bzr('log --include-merges',
546
471
working_dir='level0')
547
472
out_n0, err_n0 = self.run_bzr('log -n0', working_dir='level0')
588
563
self.build_tree(['level0/file1', 'level0/file2'])
589
564
level0.add('file1')
590
565
level0.add('file2')
591
self.wt_commit(level0, 'in branch level0')
566
level0.commit(message='in branch level0', **self.commit_options())
593
568
level1 = level0.bzrdir.sprout('level1').open_workingtree()
594
569
self.build_tree_contents([('level1/file2', 'hello\n')])
595
self.wt_commit(level1, 'in branch level1')
570
level1.commit(message='in branch level1', **self.commit_options())
596
571
level0.merge_from_branch(level1.branch)
597
self.wt_commit(level0, 'merge branch level1')
572
level0.commit(message='merge branch level1', **self.commit_options())
599
def _diff_file1_revno1(self):
600
return """=== added file 'file1'
574
def test_log_show_diff_long_with_merges(self):
575
out,err = self.run_bzr('log -p -n0')
576
self.assertEqual('', err)
577
log = test_log.normalize_log(out)
579
------------------------------------------------------------
581
committer: Lorem Ipsum <test@example.com>
587
=== modified file 'file2'
588
--- file2\t2005-11-22 00:00:01 +0000
589
+++ file2\t2005-11-22 00:00:02 +0000
591
-contents of level0/file2
593
------------------------------------------------------------
595
committer: Lorem Ipsum <test@example.com>
601
=== modified file 'file2'
602
--- file2\t2005-11-22 00:00:01 +0000
603
+++ file2\t2005-11-22 00:00:02 +0000
605
-contents of level0/file2
607
------------------------------------------------------------
609
committer: Lorem Ipsum <test@example.com>
615
=== added file 'file1'
601
616
--- file1\t1970-01-01 00:00:00 +0000
602
+++ file1\t2005-11-22 00:00:00 +0000
617
+++ file1\t2005-11-22 00:00:01 +0000
604
619
+contents of level0/file1
608
def _diff_file2_revno2(self):
609
return """=== modified file 'file2'
610
--- file2\t2005-11-22 00:00:00 +0000
611
+++ file2\t2005-11-22 00:00:01 +0000
613
-contents of level0/file2
618
def _diff_file2_revno1_1_1(self):
619
return """=== modified file 'file2'
620
--- file2\t2005-11-22 00:00:00 +0000
621
+++ file2\t2005-11-22 00:00:01 +0000
623
-contents of level0/file2
628
def _diff_file2_revno1(self):
629
return """=== added file 'file2'
621
=== added file 'file2'
630
622
--- file2\t1970-01-01 00:00:00 +0000
631
+++ file2\t2005-11-22 00:00:00 +0000
623
+++ file2\t2005-11-22 00:00:01 +0000
633
625
+contents of level0/file2
637
def assertLogRevnosAndDiff(self, args, expected,
639
self.run_bzr(['log', '-p'] + args, working_dir=working_dir)
640
expected_revnos_and_depths = [
641
(revno, depth) for revno, depth, diff in expected]
642
# Check the revnos and depths first to make debugging easier
643
self.assertEqual(expected_revnos_and_depths,
644
[(r.revno, r.merge_depth)
645
for r in self.get_captured_revisions()])
646
# Now check the diffs, adding the revno in case of failure
647
fmt = 'In revno %s\n%s'
648
for expected_rev, actual_rev in izip(expected,
649
self.get_captured_revisions()):
650
revno, depth, expected_diff = expected_rev
651
actual_diff = actual_rev.diff
652
self.assertEqualDiff(fmt % (revno, expected_diff),
653
fmt % (revno, actual_diff))
655
def test_log_diff_with_merges(self):
656
self.assertLogRevnosAndDiff(
658
[('2', 0, self._diff_file2_revno2()),
659
('1.1.1', 1, self._diff_file2_revno1_1_1()),
660
('1', 0, self._diff_file1_revno1()
661
+ self._diff_file2_revno1())],
662
working_dir='level0')
665
def test_log_diff_file1(self):
666
self.assertLogRevnosAndDiff(['-n0', 'file1'],
667
[('1', 0, self._diff_file1_revno1())],
668
working_dir='level0')
670
def test_log_diff_file2(self):
671
self.assertLogRevnosAndDiff(['-n1', 'file2'],
672
[('2', 0, self._diff_file2_revno2()),
673
('1', 0, self._diff_file2_revno1())],
674
working_dir='level0')
627
self.check_log(expected, ['-p', '-n0'])
629
def test_log_show_diff_short(self):
631
2 Lorem Ipsum\t2005-11-22 [merge]
633
=== modified file 'file2'
634
--- file2\t2005-11-22 00:00:01 +0000
635
+++ file2\t2005-11-22 00:00:02 +0000
637
-contents of level0/file2
640
1 Lorem Ipsum\t2005-11-22
642
=== added file 'file1'
643
--- file1\t1970-01-01 00:00:00 +0000
644
+++ file1\t2005-11-22 00:00:01 +0000
646
+contents of level0/file1
647
\x20\x20\x20\x20\x20\x20
648
=== added file 'file2'
649
--- file2\t1970-01-01 00:00:00 +0000
650
+++ file2\t2005-11-22 00:00:01 +0000
652
+contents of level0/file2
654
Use --include-merges or -n0 to see merged revisions.
656
self.check_log(expected, ['-p', '--short'])
658
def test_log_show_diff_line(self):
659
# Not supported by this formatter so expect plain output
661
2: Lorem Ipsum 2005-11-22 [merge] merge branch level1
662
1: Lorem Ipsum 2005-11-22 in branch level0
664
self.check_log(expected, ['-p', '--line'])
666
def test_log_show_diff_file1(self):
667
"""Only the diffs for the given file are to be shown"""
669
1 Lorem Ipsum\t2005-11-22
671
=== added file 'file1'
672
--- file1\t1970-01-01 00:00:00 +0000
673
+++ file1\t2005-11-22 00:00:01 +0000
675
+contents of level0/file1
678
self.check_log(expected, ['-p', '--short', 'file1'])
680
def test_log_show_diff_file2(self):
681
"""Only the diffs for the given file are to be shown"""
683
2 Lorem Ipsum\t2005-11-22 [merge]
685
=== modified file 'file2'
686
--- file2\t2005-11-22 00:00:01 +0000
687
+++ file2\t2005-11-22 00:00:02 +0000
689
-contents of level0/file2
692
1 Lorem Ipsum\t2005-11-22
694
=== added file 'file2'
695
--- file2\t1970-01-01 00:00:00 +0000
696
+++ file2\t2005-11-22 00:00:01 +0000
698
+contents of level0/file2
700
Use --include-merges or -n0 to see merged revisions.
702
self.check_log(expected, ['-p', '--short', 'file2'])
677
705
class TestLogUnicodeDiff(TestLog):
829
860
tree.commit('remove file1')
830
861
os.chdir('parent')
832
# FIXME: It would be good to parametrize the following tests against all
833
# formatters. But the revisions selection is not *currently* part of the
834
# LogFormatter contract, so using LogCatcher is sufficient -- vila 100118
835
def test_log_file1(self):
837
self.assertLogRevnos(['-n0', 'file1'], ['1'])
839
def test_log_file2(self):
842
self.assertLogRevnos(['-n0', 'file2'], ['4', '3.1.1', '2'])
843
# file2 in a merge revision
844
self.assertLogRevnos(['-n0', '-r3.1.1', 'file2'], ['3.1.1'])
845
# file2 in a mainline revision
846
self.assertLogRevnos(['-n0', '-r4', 'file2'], ['4', '3.1.1'])
847
# file2 since a revision
848
self.assertLogRevnos(['-n0', '-r3..', 'file2'], ['4', '3.1.1'])
849
# file2 up to a revision
850
self.assertLogRevnos(['-n0', '-r..3', 'file2'], ['2'])
852
def test_log_file3(self):
854
self.assertLogRevnos(['-n0', 'file3'], ['3'])
863
def test_log_file(self):
864
"""The log for a particular file should only list revs for that file"""
866
log = self.run_bzr('log -n0 file1')[0]
867
self.assertContainsRe(log, 'revno: 1\n')
868
self.assertNotContainsRe(log, 'revno: 2\n')
869
self.assertNotContainsRe(log, 'revno: 3\n')
870
self.assertNotContainsRe(log, 'revno: 3.1.1\n')
871
self.assertNotContainsRe(log, 'revno: 4 ')
872
log = self.run_bzr('log -n0 file2')[0]
873
self.assertNotContainsRe(log, 'revno: 1\n')
874
self.assertContainsRe(log, 'revno: 2\n')
875
self.assertNotContainsRe(log, 'revno: 3\n')
876
self.assertContainsRe(log, 'revno: 3.1.1\n')
877
self.assertContainsRe(log, 'revno: 4 ')
878
log = self.run_bzr('log -n0 file3')[0]
879
self.assertNotContainsRe(log, 'revno: 1\n')
880
self.assertNotContainsRe(log, 'revno: 2\n')
881
self.assertContainsRe(log, 'revno: 3\n')
882
self.assertNotContainsRe(log, 'revno: 3.1.1\n')
883
self.assertNotContainsRe(log, 'revno: 4 ')
884
log = self.run_bzr('log -n0 -r3.1.1 file2')[0]
885
self.assertNotContainsRe(log, 'revno: 1\n')
886
self.assertNotContainsRe(log, 'revno: 2\n')
887
self.assertNotContainsRe(log, 'revno: 3\n')
888
self.assertContainsRe(log, 'revno: 3.1.1\n')
889
self.assertNotContainsRe(log, 'revno: 4 ')
890
log = self.run_bzr('log -n0 -r4 file2')[0]
891
self.assertNotContainsRe(log, 'revno: 1\n')
892
self.assertNotContainsRe(log, 'revno: 2\n')
893
self.assertNotContainsRe(log, 'revno: 3\n')
894
self.assertContainsRe(log, 'revno: 3.1.1\n')
895
self.assertContainsRe(log, 'revno: 4 ')
896
log = self.run_bzr('log -n0 -r3.. file2')[0]
897
self.assertNotContainsRe(log, 'revno: 1\n')
898
self.assertNotContainsRe(log, 'revno: 2\n')
899
self.assertNotContainsRe(log, 'revno: 3\n')
900
self.assertContainsRe(log, 'revno: 3.1.1\n')
901
self.assertContainsRe(log, 'revno: 4 ')
902
log = self.run_bzr('log -n0 -r..3 file2')[0]
903
self.assertNotContainsRe(log, 'revno: 1\n')
904
self.assertContainsRe(log, 'revno: 2\n')
905
self.assertNotContainsRe(log, 'revno: 3\n')
906
self.assertNotContainsRe(log, 'revno: 3.1.1\n')
907
self.assertNotContainsRe(log, 'revno: 4 ')
856
909
def test_log_file_historical_missing(self):
857
910
# Check logging a deleted file gives an error if the
883
948
self.assertContainsRe(err, err_msg)
885
950
# Check we can see a renamed file if we give the right end revision
886
self.assertLogRevnos(['-r..4', 'file3'], ['3'])
889
class TestLogMultiple(TestLogWithLogCatcher):
951
log, err = self.run_bzr('log -r..4 file3')
952
self.assertEquals('', err)
953
self.assertNotContainsRe(log, 'revno: 1\n')
954
self.assertNotContainsRe(log, 'revno: 2\n')
955
self.assertContainsRe(log, 'revno: 3\n')
956
self.assertNotContainsRe(log, 'revno: 3.1.1\n')
957
self.assertNotContainsRe(log, 'revno: 4 ')
959
def test_line_log_file(self):
960
"""The line log for a file should only list relevant mainline revs"""
961
# Note: this also implicitly covers the short logging case.
962
# We test using --line in preference to --short because matching
963
# revnos in the output of --line is more reliable.
966
# full history of file1
967
log = self.run_bzr('log --line file1')[0]
968
self.assertContainsRe(log, '^1:', re.MULTILINE)
969
self.assertNotContainsRe(log, '^2:', re.MULTILINE)
970
self.assertNotContainsRe(log, '^3:', re.MULTILINE)
971
self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
972
self.assertNotContainsRe(log, '^4:', re.MULTILINE)
974
# full history of file2
975
log = self.run_bzr('log --line file2')[0]
976
self.assertNotContainsRe(log, '^1:', re.MULTILINE)
977
self.assertContainsRe(log, '^2:', re.MULTILINE)
978
self.assertNotContainsRe(log, '^3:', re.MULTILINE)
979
self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
980
self.assertContainsRe(log, '^4:', re.MULTILINE)
982
# full history of file3
983
log = self.run_bzr('log --line file3')[0]
984
self.assertNotContainsRe(log, '^1:', re.MULTILINE)
985
self.assertNotContainsRe(log, '^2:', re.MULTILINE)
986
self.assertContainsRe(log, '^3:', re.MULTILINE)
987
self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
988
self.assertNotContainsRe(log, '^4:', re.MULTILINE)
990
# file in a merge revision
991
log = self.run_bzr('log --line -r3.1.1 file2')[0]
992
self.assertNotContainsRe(log, '^1:', re.MULTILINE)
993
self.assertNotContainsRe(log, '^2:', re.MULTILINE)
994
self.assertNotContainsRe(log, '^3:', re.MULTILINE)
995
self.assertContainsRe(log, '^3.1.1:', re.MULTILINE)
996
self.assertNotContainsRe(log, '^4:', re.MULTILINE)
998
# file in a mainline revision
999
log = self.run_bzr('log --line -r4 file2')[0]
1000
self.assertNotContainsRe(log, '^1:', re.MULTILINE)
1001
self.assertNotContainsRe(log, '^2:', re.MULTILINE)
1002
self.assertNotContainsRe(log, '^3:', re.MULTILINE)
1003
self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
1004
self.assertContainsRe(log, '^4:', re.MULTILINE)
1006
# file since a revision
1007
log = self.run_bzr('log --line -r3.. file2')[0]
1008
self.assertNotContainsRe(log, '^1:', re.MULTILINE)
1009
self.assertNotContainsRe(log, '^2:', re.MULTILINE)
1010
self.assertNotContainsRe(log, '^3:', re.MULTILINE)
1011
self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
1012
self.assertContainsRe(log, '^4:', re.MULTILINE)
1014
# file up to a revision
1015
log = self.run_bzr('log --line -r..3 file2')[0]
1016
self.assertNotContainsRe(log, '^1:', re.MULTILINE)
1017
self.assertContainsRe(log, '^2:', re.MULTILINE)
1018
self.assertNotContainsRe(log, '^3:', re.MULTILINE)
1019
self.assertNotContainsRe(log, '^3.1.1:', re.MULTILINE)
1020
self.assertNotContainsRe(log, '^4:', re.MULTILINE)
1023
class TestLogMultiple(tests.TestCaseWithTransport):
891
1025
def prepare_tree(self):
892
1026
tree = self.make_branch_and_tree('parent')
915
1049
tree.commit(message='merge child branch')
916
1050
os.chdir('parent')
1052
def assertRevnos(self, paths_str, expected_revnos):
1053
# confirm the revision numbers in log --line output are those expected
1054
out, err = self.run_bzr('log --line -n0 %s' % (paths_str,))
1055
self.assertEqual('', err)
1056
revnos = [s.split(':', 1)[0].lstrip() for s in out.splitlines()]
1057
self.assertEqual(expected_revnos, revnos)
918
1059
def test_log_files(self):
919
1060
"""The log for multiple file should only list revs for those files"""
920
1061
self.prepare_tree()
921
self.assertLogRevnos(['file1', 'file2', 'dir1/dir2/file3'],
922
['6', '5.1.1', '3', '2', '1'])
1062
self.assertRevnos('file1 file2 dir1/dir2/file3',
1063
['6', '5.1.1', '3', '2', '1'])
924
1065
def test_log_directory(self):
925
1066
"""The log for a directory should show all nested files."""
926
1067
self.prepare_tree()
927
self.assertLogRevnos(['dir1'], ['5', '3'])
1068
self.assertRevnos('dir1', ['5', '3'])
929
1070
def test_log_nested_directory(self):
930
1071
"""The log for a directory should show all nested files."""
931
1072
self.prepare_tree()
932
self.assertLogRevnos(['dir1/dir2'], ['3'])
1073
self.assertRevnos('dir1/dir2', ['3'])
934
1075
def test_log_in_nested_directory(self):
935
1076
"""The log for a directory should show all nested files."""
936
1077
self.prepare_tree()
937
1078
os.chdir("dir1")
938
self.assertLogRevnos(['.'], ['5', '3'])
1079
self.assertRevnos('.', ['5', '3'])
940
1081
def test_log_files_and_directories(self):
941
1082
"""Logging files and directories together should be fine."""
942
1083
self.prepare_tree()
943
self.assertLogRevnos(['file4', 'dir1/dir2'], ['4', '3'])
1084
self.assertRevnos('file4 dir1/dir2', ['4', '3'])
945
1086
def test_log_files_and_dirs_in_nested_directory(self):
946
1087
"""The log for a directory should show all nested files."""
947
1088
self.prepare_tree()
948
1089
os.chdir("dir1")
949
self.assertLogRevnos(['dir2', 'file5'], ['5', '3'])
952
class MainlineGhostTests(TestLogWithLogCatcher):
955
super(MainlineGhostTests, self).setUp()
956
tree = self.make_branch_and_tree('')
957
tree.set_parent_ids(["spooky"], allow_leftmost_as_ghost=True)
959
tree.commit('msg1', rev_id='rev1')
960
tree.commit('msg2', rev_id='rev2')
962
def test_log_range(self):
963
self.assertLogRevnos(["-r1..2"], ["2", "1"])
965
def test_log_norange(self):
966
self.assertLogRevnos([], ["2", "1"])
968
def test_log_range_open_begin(self):
969
self.knownFailure("log with ghosts fails. bug #726466")
970
(stdout, stderr) = self.run_bzr(['log', '-r..2'], retcode=3)
971
self.assertEqual(["2", "1"],
972
[r.revno for r in self.get_captured_revisions()])
973
self.assertEquals("bzr: ERROR: Further revision history missing.", stderr)
975
def test_log_range_open_end(self):
976
self.assertLogRevnos(["-r1.."], ["2", "1"])
978
class TestLogMatch(TestLogWithLogCatcher):
979
def prepare_tree(self):
980
tree = self.make_branch_and_tree('')
982
['/hello.txt', '/goodbye.txt'])
983
tree.add('hello.txt')
984
tree.commit(message='message1', committer='committer1', authors=['author1'])
985
tree.add('goodbye.txt')
986
tree.commit(message='message2', committer='committer2', authors=['author2'])
988
def test_message(self):
990
self.assertLogRevnos(["-m", "message1"], ["1"])
991
self.assertLogRevnos(["-m", "message2"], ["2"])
992
self.assertLogRevnos(["-m", "message"], ["2", "1"])
993
self.assertLogRevnos(["-m", "message1", "-m", "message2"], ["2", "1"])
994
self.assertLogRevnos(["--match-message", "message1"], ["1"])
995
self.assertLogRevnos(["--match-message", "message2"], ["2"])
996
self.assertLogRevnos(["--match-message", "message"], ["2", "1"])
997
self.assertLogRevnos(["--match-message", "message1",
998
"--match-message", "message2"], ["2", "1"])
999
self.assertLogRevnos(["--message", "message1"], ["1"])
1000
self.assertLogRevnos(["--message", "message2"], ["2"])
1001
self.assertLogRevnos(["--message", "message"], ["2", "1"])
1002
self.assertLogRevnos(["--match-message", "message1",
1003
"--message", "message2"], ["2", "1"])
1004
self.assertLogRevnos(["--message", "message1",
1005
"--match-message", "message2"], ["2", "1"])
1007
def test_committer(self):
1009
self.assertLogRevnos(["-m", "committer1"], ["1"])
1010
self.assertLogRevnos(["-m", "committer2"], ["2"])
1011
self.assertLogRevnos(["-m", "committer"], ["2", "1"])
1012
self.assertLogRevnos(["-m", "committer1", "-m", "committer2"],
1014
self.assertLogRevnos(["--match-committer", "committer1"], ["1"])
1015
self.assertLogRevnos(["--match-committer", "committer2"], ["2"])
1016
self.assertLogRevnos(["--match-committer", "committer"], ["2", "1"])
1017
self.assertLogRevnos(["--match-committer", "committer1",
1018
"--match-committer", "committer2"], ["2", "1"])
1020
def test_author(self):
1022
self.assertLogRevnos(["-m", "author1"], ["1"])
1023
self.assertLogRevnos(["-m", "author2"], ["2"])
1024
self.assertLogRevnos(["-m", "author"], ["2", "1"])
1025
self.assertLogRevnos(["-m", "author1", "-m", "author2"],
1027
self.assertLogRevnos(["--match-author", "author1"], ["1"])
1028
self.assertLogRevnos(["--match-author", "author2"], ["2"])
1029
self.assertLogRevnos(["--match-author", "author"], ["2", "1"])
1030
self.assertLogRevnos(["--match-author", "author1",
1031
"--match-author", "author2"], ["2", "1"])
1090
self.assertRevnos('dir2 file5', ['5', '3'])