91
76
wt.commit('empty commit')
92
log.show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
94
# Since there is a single revision in the branch all the combinations
96
self.assertInvalidRevisonNumber(b, 2, 1)
97
self.assertInvalidRevisonNumber(b, 1, 2)
98
self.assertInvalidRevisonNumber(b, 0, 2)
99
self.assertInvalidRevisonNumber(b, 1, 0)
100
self.assertInvalidRevisonNumber(b, -1, 1)
101
self.assertInvalidRevisonNumber(b, 1, -1)
103
def test_empty_branch(self):
77
show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
78
self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
79
start_revision=2, end_revision=1)
80
self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
81
start_revision=1, end_revision=2)
82
self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
83
start_revision=0, end_revision=2)
84
self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
85
start_revision=1, end_revision=0)
86
self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
87
start_revision=-1, end_revision=1)
88
self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
89
start_revision=1, end_revision=-1)
91
def test_simple_log(self):
92
eq = self.assertEquals
104
94
wt = self.make_branch_and_tree('.')
107
log.show_log(wt.branch, lf)
109
self.assertEqual([], lf.logs)
111
def test_empty_commit(self):
112
wt = self.make_branch_and_tree('.')
114
102
wt.commit('empty commit')
115
103
lf = LogCatcher()
116
log.show_log(wt.branch, lf, verbose=True)
117
self.assertEqual(1, len(lf.logs))
118
self.assertEqual('1', lf.logs[0].revno)
119
self.assertEqual('empty commit', lf.logs[0].rev.message)
120
self.checkDelta(lf.logs[0].delta)
104
show_log(b, lf, verbose=True)
106
eq(lf.logs[0].revno, '1')
107
eq(lf.logs[0].rev.message, 'empty commit')
109
self.log('log delta: %r' % d)
122
def test_simple_commit(self):
123
wt = self.make_branch_and_tree('.')
124
wt.commit('empty commit')
125
112
self.build_tree(['hello'])
127
114
wt.commit('add one file',
128
115
committer=u'\u013d\xf3r\xe9m \xcdp\u0161\xfam '
129
116
u'<test@example.com>')
118
lf = self.make_utf8_encoded_stringio()
119
# log using regular thing
120
show_log(b, LongLogFormatter(lf))
122
for l in lf.readlines():
125
# get log as data structure
130
126
lf = LogCatcher()
131
log.show_log(wt.branch, lf, verbose=True)
132
self.assertEqual(2, len(lf.logs))
127
show_log(b, lf, verbose=True)
129
self.log('log entries:')
130
for logentry in lf.logs:
131
self.log('%4s %s' % (logentry.revno, logentry.rev.message))
133
133
# first one is most recent
134
log_entry = lf.logs[0]
135
self.assertEqual('2', log_entry.revno)
136
self.assertEqual('add one file', log_entry.rev.message)
137
self.checkDelta(log_entry.delta, added=['hello'])
139
def test_commit_message_with_control_chars(self):
140
wt = self.make_branch_and_tree('.')
141
msg = u"All 8-bit chars: " + ''.join([unichr(x) for x in range(256)])
142
msg = msg.replace(u'\r', u'\n')
134
logentry = lf.logs[0]
135
eq(logentry.revno, '2')
136
eq(logentry.rev.message, 'add one file')
138
self.log('log 2 delta: %r' % d)
139
self.checkDelta(d, added=['hello'])
141
# commit a log message with control characters
142
msg = "All 8-bit chars: " + ''.join([unichr(x) for x in range(256)])
143
self.log("original commit message: %r", msg)
144
145
lf = LogCatcher()
145
log.show_log(wt.branch, lf, verbose=True)
146
show_log(b, lf, verbose=True)
146
147
committed_msg = lf.logs[0].rev.message
147
self.assertNotEqual(msg, committed_msg)
148
self.assertTrue(len(committed_msg) > len(msg))
148
self.log("escaped commit message: %r", committed_msg)
149
self.assert_(msg != committed_msg)
150
self.assert_(len(committed_msg) > len(msg))
150
def test_commit_message_without_control_chars(self):
151
wt = self.make_branch_and_tree('.')
152
# Check that log message with only XML-valid characters isn't
152
153
# escaped. As ElementTree apparently does some kind of
153
154
# newline conversion, neither LF (\x0A) nor CR (\x0D) are
154
155
# included in the test commit message, even though they are
155
156
# valid XML 1.0 characters.
156
157
msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
158
self.log("original commit message: %r", msg)
158
160
lf = LogCatcher()
159
log.show_log(wt.branch, lf, verbose=True)
161
show_log(b, lf, verbose=True)
160
162
committed_msg = lf.logs[0].rev.message
161
self.assertEqual(msg, committed_msg)
163
self.log("escaped commit message: %r", committed_msg)
164
self.assert_(msg == committed_msg)
163
166
def test_deltas_in_merge_revisions(self):
164
167
"""Check deltas created for both mainline and merge revisions"""
168
eq = self.assertEquals
165
169
wt = self.make_branch_and_tree('parent')
166
170
self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
180
184
lf = LogCatcher()
181
185
lf.supports_merge_revisions = True
182
log.show_log(b, lf, verbose=True)
184
self.assertEqual(3, len(lf.logs))
186
show_log(b, lf, verbose=True)
186
188
logentry = lf.logs[0]
187
self.assertEqual('2', logentry.revno)
188
self.assertEqual('merge child branch', logentry.rev.message)
189
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
189
eq(logentry.revno, '2')
190
eq(logentry.rev.message, 'merge child branch')
192
self.checkDelta(d, removed=['file1'], modified=['file2'])
191
193
logentry = lf.logs[1]
192
self.assertEqual('1.1.1', logentry.revno)
193
self.assertEqual('remove file1 and modify file2', logentry.rev.message)
194
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
194
eq(logentry.revno, '1.1.1')
195
eq(logentry.rev.message, 'remove file1 and modify file2')
197
self.checkDelta(d, removed=['file1'], modified=['file2'])
196
198
logentry = lf.logs[2]
197
self.assertEqual('1', logentry.revno)
198
self.assertEqual('add file1 and file2', logentry.rev.message)
199
self.checkDelta(logentry.delta, added=['file1', 'file2'])
199
eq(logentry.revno, '1')
200
eq(logentry.rev.message, 'add file1 and file2')
202
self.checkDelta(d, added=['file1', 'file2'])
201
204
def test_merges_nonsupporting_formatter(self):
202
205
"""Tests that show_log will raise if the formatter doesn't
203
206
support merge revisions."""
204
207
wt = self.make_branch_and_memory_tree('.')
206
self.addCleanup(wt.unlock)
208
wt.commit('rev-1', rev_id='rev-1',
209
timestamp=1132586655, timezone=36000,
210
committer='Joe Foo <joe@foo.com>')
211
wt.commit('rev-merged', rev_id='rev-2a',
212
timestamp=1132586700, timezone=36000,
213
committer='Joe Foo <joe@foo.com>')
214
wt.set_parent_ids(['rev-1', 'rev-2a'])
215
wt.branch.set_last_revision_info(1, 'rev-1')
216
wt.commit('rev-2', rev_id='rev-2b',
217
timestamp=1132586800, timezone=36000,
218
committer='Joe Foo <joe@foo.com>')
219
logfile = self.make_utf8_encoded_stringio()
220
formatter = log.ShortLogFormatter(to_file=logfile)
223
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
224
rev = revspec.in_history(wtb)
225
self.assertRaises(errors.BzrCommandError, log.show_log, wtb, lf,
226
start_revision=rev, end_revision=rev)
211
wt.commit('rev-1', rev_id='rev-1',
212
timestamp=1132586655, timezone=36000,
213
committer='Joe Foo <joe@foo.com>')
214
wt.commit('rev-merged', rev_id='rev-2a',
215
timestamp=1132586700, timezone=36000,
216
committer='Joe Foo <joe@foo.com>')
217
wt.set_parent_ids(['rev-1', 'rev-2a'])
218
wt.branch.set_last_revision_info(1, 'rev-1')
219
wt.commit('rev-2', rev_id='rev-2b',
220
timestamp=1132586800, timezone=36000,
221
committer='Joe Foo <joe@foo.com>')
222
logfile = self.make_utf8_encoded_stringio()
223
formatter = ShortLogFormatter(to_file=logfile)
226
revspec = RevisionSpec.from_string('1.1.1')
227
rev = revspec.in_history(wtb)
228
self.assertRaises(BzrCommandError, show_log, wtb, lf,
229
start_revision=rev, end_revision=rev)
229
234
def make_commits_with_trailing_newlines(wt):
230
"""Helper method for LogFormatter tests"""
235
"""Helper method for LogFormatter tests"""
233
238
open('a', 'wb').write('hello moto\n')
287
292
1 Joe Foo\t2005-11-21
288
293
simple log message
293
def _prepare_tree_with_merges(self, with_tags=False):
294
wt = self.make_branch_and_memory_tree('.')
296
self.addCleanup(wt.unlock)
298
wt.commit('rev-1', rev_id='rev-1',
299
timestamp=1132586655, timezone=36000,
300
committer='Joe Foo <joe@foo.com>')
301
wt.commit('rev-merged', rev_id='rev-2a',
302
timestamp=1132586700, timezone=36000,
303
committer='Joe Foo <joe@foo.com>')
304
wt.set_parent_ids(['rev-1', 'rev-2a'])
305
wt.branch.set_last_revision_info(1, 'rev-1')
306
wt.commit('rev-2', rev_id='rev-2b',
307
timestamp=1132586800, timezone=36000,
308
committer='Joe Foo <joe@foo.com>')
311
branch.tags.set_tag('v0.2', 'rev-2b')
312
wt.commit('rev-3', rev_id='rev-3',
313
timestamp=1132586900, timezone=36000,
314
committer='Jane Foo <jane@foo.com>')
315
branch.tags.set_tag('v1.0rc1', 'rev-3')
316
branch.tags.set_tag('v1.0', 'rev-3')
319
297
def test_short_log_with_merges(self):
320
wt = self._prepare_tree_with_merges()
321
logfile = self.make_utf8_encoded_stringio()
322
formatter = log.ShortLogFormatter(to_file=logfile)
323
log.show_log(wt.branch, formatter)
324
self.assertEqualDiff("""\
325
2 Joe Foo\t2005-11-22 [merge]
328
1 Joe Foo\t2005-11-22
334
def test_short_log_with_merges_and_range(self):
335
298
wt = self.make_branch_and_memory_tree('.')
337
self.addCleanup(wt.unlock)
339
wt.commit('rev-1', rev_id='rev-1',
340
timestamp=1132586655, timezone=36000,
341
committer='Joe Foo <joe@foo.com>')
342
wt.commit('rev-merged', rev_id='rev-2a',
343
timestamp=1132586700, timezone=36000,
344
committer='Joe Foo <joe@foo.com>')
345
wt.branch.set_last_revision_info(1, 'rev-1')
346
wt.set_parent_ids(['rev-1', 'rev-2a'])
347
wt.commit('rev-2b', rev_id='rev-2b',
348
timestamp=1132586800, timezone=36000,
349
committer='Joe Foo <joe@foo.com>')
350
wt.commit('rev-3a', rev_id='rev-3a',
351
timestamp=1132586800, timezone=36000,
352
committer='Joe Foo <joe@foo.com>')
353
wt.branch.set_last_revision_info(2, 'rev-2b')
354
wt.set_parent_ids(['rev-2b', 'rev-3a'])
355
wt.commit('rev-3b', rev_id='rev-3b',
356
timestamp=1132586800, timezone=36000,
357
committer='Joe Foo <joe@foo.com>')
358
logfile = self.make_utf8_encoded_stringio()
359
formatter = log.ShortLogFormatter(to_file=logfile)
360
log.show_log(wt.branch, formatter,
361
start_revision=2, end_revision=3)
362
self.assertEqualDiff("""\
363
3 Joe Foo\t2005-11-22 [merge]
302
wt.commit('rev-1', rev_id='rev-1',
303
timestamp=1132586655, timezone=36000,
304
committer='Joe Foo <joe@foo.com>')
305
wt.commit('rev-merged', rev_id='rev-2a',
306
timestamp=1132586700, timezone=36000,
307
committer='Joe Foo <joe@foo.com>')
308
wt.set_parent_ids(['rev-1', 'rev-2a'])
309
wt.branch.set_last_revision_info(1, 'rev-1')
310
wt.commit('rev-2', rev_id='rev-2b',
311
timestamp=1132586800, timezone=36000,
312
committer='Joe Foo <joe@foo.com>')
313
logfile = self.make_utf8_encoded_stringio()
314
formatter = ShortLogFormatter(to_file=logfile)
315
show_log(wt.branch, formatter)
316
self.assertEqualDiff(logfile.getvalue(), """\
366
317
2 Joe Foo\t2005-11-22 [merge]
372
def test_short_log_with_tags(self):
373
wt = self._prepare_tree_with_merges(with_tags=True)
374
logfile = self.make_utf8_encoded_stringio()
375
formatter = log.ShortLogFormatter(to_file=logfile)
376
log.show_log(wt.branch, formatter)
377
self.assertEqualDiff("""\
378
3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
381
2 Joe Foo\t2005-11-22 {v0.2} [merge]
384
320
1 Joe Foo\t2005-11-22
390
327
def test_short_log_single_merge_revision(self):
391
328
wt = self.make_branch_and_memory_tree('.')
393
self.addCleanup(wt.unlock)
395
wt.commit('rev-1', rev_id='rev-1',
396
timestamp=1132586655, timezone=36000,
397
committer='Joe Foo <joe@foo.com>')
398
wt.commit('rev-merged', rev_id='rev-2a',
399
timestamp=1132586700, timezone=36000,
400
committer='Joe Foo <joe@foo.com>')
401
wt.set_parent_ids(['rev-1', 'rev-2a'])
402
wt.branch.set_last_revision_info(1, 'rev-1')
403
wt.commit('rev-2', rev_id='rev-2b',
404
timestamp=1132586800, timezone=36000,
405
committer='Joe Foo <joe@foo.com>')
406
logfile = self.make_utf8_encoded_stringio()
407
formatter = log.ShortLogFormatter(to_file=logfile)
408
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
410
rev = revspec.in_history(wtb)
411
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
412
self.assertEqualDiff("""\
413
1.1.1 Joe Foo\t2005-11-22
420
class TestShortLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
422
def test_short_merge_revs_log_with_merges(self):
423
wt = self.make_branch_and_memory_tree('.')
425
self.addCleanup(wt.unlock)
427
wt.commit('rev-1', rev_id='rev-1',
428
timestamp=1132586655, timezone=36000,
429
committer='Joe Foo <joe@foo.com>')
430
wt.commit('rev-merged', rev_id='rev-2a',
431
timestamp=1132586700, timezone=36000,
432
committer='Joe Foo <joe@foo.com>')
433
wt.set_parent_ids(['rev-1', 'rev-2a'])
434
wt.branch.set_last_revision_info(1, 'rev-1')
435
wt.commit('rev-2', rev_id='rev-2b',
436
timestamp=1132586800, timezone=36000,
437
committer='Joe Foo <joe@foo.com>')
438
logfile = self.make_utf8_encoded_stringio()
439
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
440
log.show_log(wt.branch, formatter)
441
# Note that the 1.1.1 indenting is in fact correct given that
442
# the revision numbers are right justified within 5 characters
443
# for mainline revnos and 9 characters for dotted revnos.
444
self.assertEqualDiff("""\
445
2 Joe Foo\t2005-11-22 [merge]
448
1.1.1 Joe Foo\t2005-11-22
451
1 Joe Foo\t2005-11-22
457
def test_short_merge_revs_log_single_merge_revision(self):
458
wt = self.make_branch_and_memory_tree('.')
460
self.addCleanup(wt.unlock)
462
wt.commit('rev-1', rev_id='rev-1',
463
timestamp=1132586655, timezone=36000,
464
committer='Joe Foo <joe@foo.com>')
465
wt.commit('rev-merged', rev_id='rev-2a',
466
timestamp=1132586700, timezone=36000,
467
committer='Joe Foo <joe@foo.com>')
468
wt.set_parent_ids(['rev-1', 'rev-2a'])
469
wt.branch.set_last_revision_info(1, 'rev-1')
470
wt.commit('rev-2', rev_id='rev-2b',
471
timestamp=1132586800, timezone=36000,
472
committer='Joe Foo <joe@foo.com>')
473
logfile = self.make_utf8_encoded_stringio()
474
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
475
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
477
rev = revspec.in_history(wtb)
478
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
479
self.assertEqualDiff("""\
480
1.1.1 Joe Foo\t2005-11-22
487
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
332
wt.commit('rev-1', rev_id='rev-1',
333
timestamp=1132586655, timezone=36000,
334
committer='Joe Foo <joe@foo.com>')
335
wt.commit('rev-merged', rev_id='rev-2a',
336
timestamp=1132586700, timezone=36000,
337
committer='Joe Foo <joe@foo.com>')
338
wt.set_parent_ids(['rev-1', 'rev-2a'])
339
wt.branch.set_last_revision_info(1, 'rev-1')
340
wt.commit('rev-2', rev_id='rev-2b',
341
timestamp=1132586800, timezone=36000,
342
committer='Joe Foo <joe@foo.com>')
343
logfile = self.make_utf8_encoded_stringio()
344
formatter = ShortLogFormatter(to_file=logfile)
345
revspec = RevisionSpec.from_string('1.1.1')
347
rev = revspec.in_history(wtb)
348
show_log(wtb, formatter, start_revision=rev, end_revision=rev)
349
self.assertEqualDiff(logfile.getvalue(), """\
350
1.1.1 Joe Foo\t2005-11-22
358
class TestLongLogFormatter(TestCaseWithTransport):
489
360
def test_verbose_log(self):
490
361
"""Verbose log includes changed files
681
548
committer='Lorem Ipsum <test@example.com>',
682
549
author='John Doe <jdoe@example.com>')
684
formatter = log.LongLogFormatter(to_file=sio)
685
log.show_log(b, formatter)
686
self.assertEqualDiff('''\
687
------------------------------------------------------------
689
author: John Doe <jdoe@example.com>
690
committer: Lorem Ipsum <test@example.com>
691
branch nick: test_author_log
692
timestamp: Wed 2005-11-23 12:08:27 +1000
698
def test_properties_in_log(self):
699
"""Log includes the custom properties returned by the registered
702
wt = self.make_branch_and_tree('.')
704
self.build_tree(['a'])
706
b.nick = 'test_properties_in_log'
707
wt.commit(message='add a',
708
timestamp=1132711707,
710
committer='Lorem Ipsum <test@example.com>',
711
author='John Doe <jdoe@example.com>')
713
formatter = log.LongLogFormatter(to_file=sio)
715
def trivial_custom_prop_handler(revision):
716
return {'test_prop':'test_value'}
718
log.properties_handler_registry.register(
719
'trivial_custom_prop_handler',
720
trivial_custom_prop_handler)
721
log.show_log(b, formatter)
723
log.properties_handler_registry.remove(
724
'trivial_custom_prop_handler')
725
self.assertEqualDiff('''\
726
------------------------------------------------------------
728
test_prop: test_value
729
author: John Doe <jdoe@example.com>
730
committer: Lorem Ipsum <test@example.com>
731
branch nick: test_properties_in_log
732
timestamp: Wed 2005-11-23 12:08:27 +1000
738
def test_properties_in_short_log(self):
739
"""Log includes the custom properties returned by the registered
742
wt = self.make_branch_and_tree('.')
744
self.build_tree(['a'])
746
b.nick = 'test_properties_in_short_log'
747
wt.commit(message='add a',
748
timestamp=1132711707,
750
committer='Lorem Ipsum <test@example.com>',
751
author='John Doe <jdoe@example.com>')
753
formatter = log.ShortLogFormatter(to_file=sio)
755
def trivial_custom_prop_handler(revision):
756
return {'test_prop':'test_value'}
758
log.properties_handler_registry.register(
759
'trivial_custom_prop_handler',
760
trivial_custom_prop_handler)
761
log.show_log(b, formatter)
763
log.properties_handler_registry.remove(
764
'trivial_custom_prop_handler')
765
self.assertEqualDiff('''\
766
1 John Doe\t2005-11-23
767
test_prop: test_value
773
def test_error_in_properties_handler(self):
774
"""Log includes the custom properties returned by the registered
777
wt = self.make_branch_and_tree('.')
779
self.build_tree(['a'])
781
b.nick = 'test_author_log'
782
wt.commit(message='add a',
783
timestamp=1132711707,
785
committer='Lorem Ipsum <test@example.com>',
786
author='John Doe <jdoe@example.com>',
787
revprops={'first_prop':'first_value'})
789
formatter = log.LongLogFormatter(to_file=sio)
791
def trivial_custom_prop_handler(revision):
792
raise StandardError("a test error")
794
log.properties_handler_registry.register(
795
'trivial_custom_prop_handler',
796
trivial_custom_prop_handler)
797
self.assertRaises(StandardError, log.show_log, b, formatter,)
799
log.properties_handler_registry.remove(
800
'trivial_custom_prop_handler')
802
def test_properties_handler_bad_argument(self):
803
wt = self.make_branch_and_tree('.')
805
self.build_tree(['a'])
807
b.nick = 'test_author_log'
808
wt.commit(message='add a',
809
timestamp=1132711707,
811
committer='Lorem Ipsum <test@example.com>',
812
author='John Doe <jdoe@example.com>',
813
revprops={'a_prop':'test_value'})
815
formatter = log.LongLogFormatter(to_file=sio)
817
def bad_argument_prop_handler(revision):
818
return {'custom_prop_name':revision.properties['a_prop']}
820
log.properties_handler_registry.register(
821
'bad_argument_prop_handler',
822
bad_argument_prop_handler)
824
self.assertRaises(AttributeError, formatter.show_properties,
827
revision = b.repository.get_revision(b.last_revision())
828
formatter.show_properties(revision, '')
829
self.assertEqualDiff('''custom_prop_name: test_value\n''',
832
log.properties_handler_registry.remove(
833
'bad_argument_prop_handler')
836
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
838
def test_long_verbose_log(self):
839
"""Verbose log includes changed files
843
wt = self.make_branch_and_tree('.')
845
self.build_tree(['a'])
847
# XXX: why does a longer nick show up?
848
b.nick = 'test_verbose_log'
849
wt.commit(message='add a',
850
timestamp=1132711707,
852
committer='Lorem Ipsum <test@example.com>')
853
logfile = file('out.tmp', 'w+')
854
formatter = log.LongLogFormatter(to_file=logfile, levels=1)
855
log.show_log(b, formatter, verbose=True)
858
log_contents = logfile.read()
859
self.assertEqualDiff('''\
860
------------------------------------------------------------
862
committer: Lorem Ipsum <test@example.com>
863
branch nick: test_verbose_log
864
timestamp: Wed 2005-11-23 12:08:27 +1000
872
def test_long_verbose_contain_deltas(self):
873
wt = self.make_branch_and_tree('parent')
874
self.build_tree(['parent/f1', 'parent/f2'])
876
wt.commit('first post')
877
self.run_bzr('branch parent child')
878
os.unlink('child/f1')
879
file('child/f2', 'wb').write('hello\n')
880
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
883
self.run_bzr('merge ../child')
884
wt.commit('merge branch 1')
886
sio = self.make_utf8_encoded_stringio()
887
lf = log.LongLogFormatter(to_file=sio, levels=1)
888
log.show_log(b, lf, verbose=True)
889
the_log = normalize_log(sio.getvalue())
890
self.assertEqualDiff("""\
891
------------------------------------------------------------
893
committer: Lorem Ipsum <test@example.com>
902
------------------------------------------------------------
904
committer: Lorem Ipsum <test@example.com>
915
def test_long_trailing_newlines(self):
916
wt = self.make_branch_and_tree('.')
917
b = make_commits_with_trailing_newlines(wt)
918
sio = self.make_utf8_encoded_stringio()
919
lf = log.LongLogFormatter(to_file=sio, levels=1)
921
self.assertEqualDiff("""\
922
------------------------------------------------------------
924
committer: Joe Foo <joe@foo.com>
926
timestamp: Mon 2005-11-21 09:32:56 -0600
928
single line with trailing newline
929
------------------------------------------------------------
931
author: Joe Bar <joe@bar.com>
932
committer: Joe Foo <joe@foo.com>
934
timestamp: Mon 2005-11-21 09:27:22 -0600
939
------------------------------------------------------------
941
committer: Joe Foo <joe@foo.com>
943
timestamp: Mon 2005-11-21 09:24:15 -0600
949
def test_long_author_in_log(self):
950
"""Log includes the author name if it's set in
951
the revision properties
953
wt = self.make_branch_and_tree('.')
955
self.build_tree(['a'])
957
b.nick = 'test_author_log'
958
wt.commit(message='add a',
959
timestamp=1132711707,
961
committer='Lorem Ipsum <test@example.com>',
962
author='John Doe <jdoe@example.com>')
964
formatter = log.LongLogFormatter(to_file=sio, levels=1)
965
log.show_log(b, formatter)
966
self.assertEqualDiff('''\
967
------------------------------------------------------------
969
author: John Doe <jdoe@example.com>
970
committer: Lorem Ipsum <test@example.com>
971
branch nick: test_author_log
972
timestamp: Wed 2005-11-23 12:08:27 +1000
978
def test_long_properties_in_log(self):
979
"""Log includes the custom properties returned by the registered
982
wt = self.make_branch_and_tree('.')
984
self.build_tree(['a'])
986
b.nick = 'test_properties_in_log'
987
wt.commit(message='add a',
988
timestamp=1132711707,
990
committer='Lorem Ipsum <test@example.com>',
991
author='John Doe <jdoe@example.com>')
993
formatter = log.LongLogFormatter(to_file=sio, levels=1)
995
def trivial_custom_prop_handler(revision):
996
return {'test_prop':'test_value'}
998
log.properties_handler_registry.register(
999
'trivial_custom_prop_handler',
1000
trivial_custom_prop_handler)
1001
log.show_log(b, formatter)
1003
log.properties_handler_registry.remove(
1004
'trivial_custom_prop_handler')
1005
self.assertEqualDiff('''\
1006
------------------------------------------------------------
1008
test_prop: test_value
1009
author: John Doe <jdoe@example.com>
1010
committer: Lorem Ipsum <test@example.com>
1011
branch nick: test_properties_in_log
1012
timestamp: Wed 2005-11-23 12:08:27 +1000
1019
class TestLineLogFormatter(tests.TestCaseWithTransport):
551
formatter = LongLogFormatter(to_file=sio)
552
show_log(b, formatter)
553
self.assertEqualDiff(sio.getvalue(), '''\
554
------------------------------------------------------------
556
author: John Doe <jdoe@example.com>
557
committer: Lorem Ipsum <test@example.com>
558
branch nick: test_author_log
559
timestamp: Wed 2005-11-23 12:08:27 +1000
566
class TestLineLogFormatter(TestCaseWithTransport):
1021
568
def test_line_log(self):
1022
569
"""Line log should show revno
1028
575
self.build_tree(['a'])
1030
577
b.nick = 'test-line-log'
1031
wt.commit(message='add a',
1032
timestamp=1132711707,
578
wt.commit(message='add a',
579
timestamp=1132711707,
1034
581
committer='Line-Log-Formatter Tester <test@line.log>')
1035
582
logfile = file('out.tmp', 'w+')
1036
formatter = log.LineLogFormatter(to_file=logfile)
1037
log.show_log(b, formatter)
583
formatter = LineLogFormatter(to_file=logfile)
584
show_log(b, formatter)
1040
587
log_contents = logfile.read()
1041
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
588
self.assertEqualDiff(log_contents,
589
'1: Line-Log-Formatte... 2005-11-23 add a\n')
1044
591
def test_trailing_newlines(self):
1045
592
wt = self.make_branch_and_tree('.')
1046
593
b = make_commits_with_trailing_newlines(wt)
1047
594
sio = self.make_utf8_encoded_stringio()
1048
lf = log.LineLogFormatter(to_file=sio)
1050
self.assertEqualDiff("""\
595
lf = LineLogFormatter(to_file=sio)
597
self.assertEqualDiff(sio.getvalue(), """\
1051
598
3: Joe Foo 2005-11-21 single line with trailing newline
1052
599
2: Joe Bar 2005-11-21 multiline
1053
600
1: Joe Foo 2005-11-21 simple log message
1057
def _prepare_tree_with_merges(self, with_tags=False):
1058
wt = self.make_branch_and_memory_tree('.')
1060
self.addCleanup(wt.unlock)
1062
wt.commit('rev-1', rev_id='rev-1',
1063
timestamp=1132586655, timezone=36000,
1064
committer='Joe Foo <joe@foo.com>')
1065
wt.commit('rev-merged', rev_id='rev-2a',
1066
timestamp=1132586700, timezone=36000,
1067
committer='Joe Foo <joe@foo.com>')
1068
wt.set_parent_ids(['rev-1', 'rev-2a'])
1069
wt.branch.set_last_revision_info(1, 'rev-1')
1070
wt.commit('rev-2', rev_id='rev-2b',
1071
timestamp=1132586800, timezone=36000,
1072
committer='Joe Foo <joe@foo.com>')
1075
branch.tags.set_tag('v0.2', 'rev-2b')
1076
wt.commit('rev-3', rev_id='rev-3',
1077
timestamp=1132586900, timezone=36000,
1078
committer='Jane Foo <jane@foo.com>')
1079
branch.tags.set_tag('v1.0rc1', 'rev-3')
1080
branch.tags.set_tag('v1.0', 'rev-3')
1083
603
def test_line_log_single_merge_revision(self):
1084
wt = self._prepare_tree_with_merges()
1085
logfile = self.make_utf8_encoded_stringio()
1086
formatter = log.LineLogFormatter(to_file=logfile)
1087
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1089
rev = revspec.in_history(wtb)
1090
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1091
self.assertEqualDiff("""\
1092
1.1.1: Joe Foo 2005-11-22 rev-merged
1096
def test_line_log_with_tags(self):
1097
wt = self._prepare_tree_with_merges(with_tags=True)
1098
logfile = self.make_utf8_encoded_stringio()
1099
formatter = log.LineLogFormatter(to_file=logfile)
1100
log.show_log(wt.branch, formatter)
1101
self.assertEqualDiff("""\
1102
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1103
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
1104
1: Joe Foo 2005-11-22 rev-1
1108
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
1110
def test_line_merge_revs_log(self):
1111
"""Line log should show revno
1115
wt = self.make_branch_and_tree('.')
1117
self.build_tree(['a'])
1119
b.nick = 'test-line-log'
1120
wt.commit(message='add a',
1121
timestamp=1132711707,
1123
committer='Line-Log-Formatter Tester <test@line.log>')
1124
logfile = file('out.tmp', 'w+')
1125
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1126
log.show_log(b, formatter)
1129
log_contents = logfile.read()
1130
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1133
def test_line_merge_revs_log_single_merge_revision(self):
1134
wt = self.make_branch_and_memory_tree('.')
1136
self.addCleanup(wt.unlock)
1138
wt.commit('rev-1', rev_id='rev-1',
1139
timestamp=1132586655, timezone=36000,
1140
committer='Joe Foo <joe@foo.com>')
1141
wt.commit('rev-merged', rev_id='rev-2a',
1142
timestamp=1132586700, timezone=36000,
1143
committer='Joe Foo <joe@foo.com>')
1144
wt.set_parent_ids(['rev-1', 'rev-2a'])
1145
wt.branch.set_last_revision_info(1, 'rev-1')
1146
wt.commit('rev-2', rev_id='rev-2b',
1147
timestamp=1132586800, timezone=36000,
1148
committer='Joe Foo <joe@foo.com>')
1149
logfile = self.make_utf8_encoded_stringio()
1150
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1151
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1153
rev = revspec.in_history(wtb)
1154
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1155
self.assertEqualDiff("""\
1156
1.1.1: Joe Foo 2005-11-22 rev-merged
1160
def test_line_merge_revs_log_with_merges(self):
1161
wt = self.make_branch_and_memory_tree('.')
1163
self.addCleanup(wt.unlock)
1165
wt.commit('rev-1', rev_id='rev-1',
1166
timestamp=1132586655, timezone=36000,
1167
committer='Joe Foo <joe@foo.com>')
1168
wt.commit('rev-merged', rev_id='rev-2a',
1169
timestamp=1132586700, timezone=36000,
1170
committer='Joe Foo <joe@foo.com>')
1171
wt.set_parent_ids(['rev-1', 'rev-2a'])
1172
wt.branch.set_last_revision_info(1, 'rev-1')
1173
wt.commit('rev-2', rev_id='rev-2b',
1174
timestamp=1132586800, timezone=36000,
1175
committer='Joe Foo <joe@foo.com>')
1176
logfile = self.make_utf8_encoded_stringio()
1177
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1178
log.show_log(wt.branch, formatter)
1179
self.assertEqualDiff("""\
1180
2: Joe Foo 2005-11-22 [merge] rev-2
1181
1.1.1: Joe Foo 2005-11-22 rev-merged
1182
1: Joe Foo 2005-11-22 rev-1
1186
class TestGetViewRevisions(tests.TestCaseWithTransport):
604
wt = self.make_branch_and_memory_tree('.')
608
wt.commit('rev-1', rev_id='rev-1',
609
timestamp=1132586655, timezone=36000,
610
committer='Joe Foo <joe@foo.com>')
611
wt.commit('rev-merged', rev_id='rev-2a',
612
timestamp=1132586700, timezone=36000,
613
committer='Joe Foo <joe@foo.com>')
614
wt.set_parent_ids(['rev-1', 'rev-2a'])
615
wt.branch.set_last_revision_info(1, 'rev-1')
616
wt.commit('rev-2', rev_id='rev-2b',
617
timestamp=1132586800, timezone=36000,
618
committer='Joe Foo <joe@foo.com>')
619
logfile = self.make_utf8_encoded_stringio()
620
formatter = LineLogFormatter(to_file=logfile)
621
revspec = RevisionSpec.from_string('1.1.1')
623
rev = revspec.in_history(wtb)
624
show_log(wtb, formatter, start_revision=rev, end_revision=rev)
625
self.assertEqualDiff(logfile.getvalue(), """\
626
1.1.1: Joe Foo 2005-11-22 rev-merged
633
class TestGetViewRevisions(TestCaseWithTransport):
1188
635
def make_tree_with_commits(self):
1189
636
"""Create a tree with well-known revision ids"""
1276
713
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1278
715
self.addCleanup(wt.unlock)
1279
revisions = list(log.get_view_revisions(
1280
mainline_revs, rev_nos, wt.branch, 'forward'))
1281
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1282
('4b', '4', 0), ('4a', '3.1.1', 1)],
1284
revisions = list(log.get_view_revisions(
1285
mainline_revs, rev_nos, wt.branch, 'forward',
1286
include_merges=False))
1287
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
716
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
718
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
719
('4b', '4', 0), ('4a', '3.1.1', 1)],
721
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
722
'forward', include_merges=False))
723
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1291
727
def test_get_view_revisions_merge_reverse(self):
1292
728
"""Test get_view_revisions in reverse when there are merges"""
1293
729
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1295
731
self.addCleanup(wt.unlock)
1296
revisions = list(log.get_view_revisions(
1297
mainline_revs, rev_nos, wt.branch, 'reverse'))
732
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
1298
734
self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
1299
('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1301
revisions = list(log.get_view_revisions(
1302
mainline_revs, rev_nos, wt.branch, 'reverse',
1303
include_merges=False))
735
('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
737
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
738
'reverse', include_merges=False))
1304
739
self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
1308
743
def test_get_view_revisions_merge2(self):
1309
744
"""Test get_view_revisions when there are merges"""
1310
745
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1312
747
self.addCleanup(wt.unlock)
1313
revisions = list(log.get_view_revisions(
1314
mainline_revs, rev_nos, wt.branch, 'forward'))
748
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
1315
750
expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1316
('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
751
('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
1318
753
self.assertEqual(expected, revisions)
1319
revisions = list(log.get_view_revisions(
1320
mainline_revs, rev_nos, wt.branch, 'forward',
1321
include_merges=False))
754
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
755
'forward', include_merges=False))
1322
756
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1327
def test_file_id_for_range(self):
1328
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1330
self.addCleanup(wt.unlock)
1332
def rev_from_rev_id(revid, branch):
1333
revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1334
return revspec.in_history(branch)
1336
def view_revs(start_rev, end_rev, file_id, direction):
1337
revs = log.calculate_view_revisions(
1339
start_rev, # start_revision
1340
end_rev, # end_revision
1341
direction, # direction
1342
file_id, # specific_fileid
1343
True, # generate_merge_revisions
1344
True, # allow_single_merge_revision
1348
rev_3a = rev_from_rev_id('3a', wt.branch)
1349
rev_4b = rev_from_rev_id('4b', wt.branch)
1350
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1351
view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1352
# Note: 3c still appears before 3a here because of depth-based sorting
1353
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1354
view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1357
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
761
class TestGetRevisionsTouchingFileID(TestCaseWithTransport):
1359
763
def create_tree_with_single_merge(self):
1360
764
"""Create a branch with a moderate layout.
1410
814
tree.commit('D', rev_id='D')
1412
816
# Switch to a read lock for this tree.
1413
# We still have an addCleanup(tree.unlock) pending
817
# We still have addCleanup(unlock)
1415
819
tree.lock_read()
1418
def check_delta(self, delta, **kw):
1419
"""Check the filenames touched by a delta are as expected.
1421
Caller only have to pass in the list of files for each part, all
1422
unspecified parts are considered empty (and checked as such).
1424
for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
1425
# By default we expect an empty list
1426
expected = kw.get(n, [])
1427
# strip out only the path components
1428
got = [x[0] for x in getattr(delta, n)]
1429
self.assertEqual(expected, got)
1431
822
def test_tree_with_single_merge(self):
1432
823
"""Make sure the tree layout is correct."""
1433
824
tree = self.create_tree_with_single_merge()
1434
825
rev_A_tree = tree.branch.repository.revision_tree('A')
1435
826
rev_B_tree = tree.branch.repository.revision_tree('B')
828
f1_changed = (u'f1', 'f1-id', 'file', True, False)
829
f2_changed = (u'f2', 'f2-id', 'file', True, False)
830
f3_changed = (u'f3', 'f3-id', 'file', True, False)
832
delta = rev_B_tree.changes_from(rev_A_tree)
833
self.assertEqual([f1_changed, f3_changed], delta.modified)
834
self.assertEqual([], delta.renamed)
835
self.assertEqual([], delta.added)
836
self.assertEqual([], delta.removed)
1436
838
rev_C_tree = tree.branch.repository.revision_tree('C')
839
delta = rev_C_tree.changes_from(rev_A_tree)
840
self.assertEqual([f2_changed, f3_changed], delta.modified)
841
self.assertEqual([], delta.renamed)
842
self.assertEqual([], delta.added)
843
self.assertEqual([], delta.removed)
1437
845
rev_D_tree = tree.branch.repository.revision_tree('D')
1439
self.check_delta(rev_B_tree.changes_from(rev_A_tree),
1440
modified=['f1', 'f3'])
1442
self.check_delta(rev_C_tree.changes_from(rev_A_tree),
1443
modified=['f2', 'f3'])
1445
self.check_delta(rev_D_tree.changes_from(rev_B_tree),
1446
modified=['f2', 'f3'])
1448
self.check_delta(rev_D_tree.changes_from(rev_C_tree),
1449
modified=['f1', 'f3'])
846
delta = rev_D_tree.changes_from(rev_B_tree)
847
self.assertEqual([f2_changed, f3_changed], delta.modified)
848
self.assertEqual([], delta.renamed)
849
self.assertEqual([], delta.added)
850
self.assertEqual([], delta.removed)
852
delta = rev_D_tree.changes_from(rev_C_tree)
853
self.assertEqual([f1_changed, f3_changed], delta.modified)
854
self.assertEqual([], delta.renamed)
855
self.assertEqual([], delta.added)
856
self.assertEqual([], delta.removed)
1451
858
def assertAllRevisionsForFileID(self, tree, file_id, revisions):
1452
"""Ensure _filter_revisions_touching_file_id returns the right values.
859
"""Make sure _filter_revisions_touching_file_id returns the right values.
1454
861
Get the return value from _filter_revisions_touching_file_id and make
1455
862
sure they are correct.
1457
# The api for _filter_revisions_touching_file_id is a little crazy.
864
# The api for _get_revisions_touching_file_id is a little crazy,
1458
865
# So we do the setup here.
1459
866
mainline = tree.branch.revision_history()
1460
867
mainline.insert(0, None)
1545
952
self.assertEqual('jsmith@example.com', lf.short_author(rev))
1546
953
rev.properties['author'] = 'John Smith jsmith@example.com'
1547
954
self.assertEqual('John Smith', lf.short_author(rev))
1550
class TestReverseByDepth(tests.TestCase):
1551
"""Test reverse_by_depth behavior.
1553
This is used to present revisions in forward (oldest first) order in a nice
1556
The tests use lighter revision description to ease reading.
1559
def assertReversed(self, forward, backward):
1560
# Transform the descriptions to suit the API: tests use (revno, depth),
1561
# while the API expects (revid, revno, depth)
1562
def complete_revisions(l):
1563
"""Transform the description to suit the API.
1565
Tests use (revno, depth) whil the API expects (revid, revno, depth).
1566
Since the revid is arbitrary, we just duplicate revno
1568
return [ (r, r, d) for r, d in l]
1569
forward = complete_revisions(forward)
1570
backward= complete_revisions(backward)
1571
self.assertEqual(forward, log.reverse_by_depth(backward))
1574
def test_mainline_revisions(self):
1575
self.assertReversed([( '1', 0), ('2', 0)],
1576
[('2', 0), ('1', 0)])
1578
def test_merged_revisions(self):
1579
self.assertReversed([('1', 0), ('2', 0), ('2.2', 1), ('2.1', 1),],
1580
[('2', 0), ('2.1', 1), ('2.2', 1), ('1', 0),])
1581
def test_shifted_merged_revisions(self):
1582
"""Test irregular layout.
1584
Requesting revisions touching a file can produce "holes" in the depths.
1586
self.assertReversed([('1', 0), ('2', 0), ('1.1', 2), ('1.2', 2),],
1587
[('2', 0), ('1.2', 2), ('1.1', 2), ('1', 0),])
1589
def test_merged_without_child_revisions(self):
1590
"""Test irregular layout.
1592
Revision ranges can produce "holes" in the depths.
1594
# When a revision of higher depth doesn't follow one of lower depth, we
1595
# assume a lower depth one is virtually there
1596
self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1597
[('4', 4), ('3', 3), ('2', 2), ('1', 2),])
1598
# So we get the same order after reversing below even if the original
1599
# revisions are not in the same order.
1600
self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1601
[('3', 3), ('4', 4), ('2', 2), ('1', 2),])
1604
class TestHistoryChange(tests.TestCaseWithTransport):
1606
def setup_a_tree(self):
1607
tree = self.make_branch_and_tree('tree')
1609
self.addCleanup(tree.unlock)
1610
tree.commit('1a', rev_id='1a')
1611
tree.commit('2a', rev_id='2a')
1612
tree.commit('3a', rev_id='3a')
1615
def setup_ab_tree(self):
1616
tree = self.setup_a_tree()
1617
tree.set_last_revision('1a')
1618
tree.branch.set_last_revision_info(1, '1a')
1619
tree.commit('2b', rev_id='2b')
1620
tree.commit('3b', rev_id='3b')
1623
def setup_ac_tree(self):
1624
tree = self.setup_a_tree()
1625
tree.set_last_revision(revision.NULL_REVISION)
1626
tree.branch.set_last_revision_info(0, revision.NULL_REVISION)
1627
tree.commit('1c', rev_id='1c')
1628
tree.commit('2c', rev_id='2c')
1629
tree.commit('3c', rev_id='3c')
1632
def test_all_new(self):
1633
tree = self.setup_ab_tree()
1634
old, new = log.get_history_change('1a', '3a', tree.branch.repository)
1635
self.assertEqual([], old)
1636
self.assertEqual(['2a', '3a'], new)
1638
def test_all_old(self):
1639
tree = self.setup_ab_tree()
1640
old, new = log.get_history_change('3a', '1a', tree.branch.repository)
1641
self.assertEqual([], new)
1642
self.assertEqual(['2a', '3a'], old)
1644
def test_null_old(self):
1645
tree = self.setup_ab_tree()
1646
old, new = log.get_history_change(revision.NULL_REVISION,
1647
'3a', tree.branch.repository)
1648
self.assertEqual([], old)
1649
self.assertEqual(['1a', '2a', '3a'], new)
1651
def test_null_new(self):
1652
tree = self.setup_ab_tree()
1653
old, new = log.get_history_change('3a', revision.NULL_REVISION,
1654
tree.branch.repository)
1655
self.assertEqual([], new)
1656
self.assertEqual(['1a', '2a', '3a'], old)
1658
def test_diverged(self):
1659
tree = self.setup_ab_tree()
1660
old, new = log.get_history_change('3a', '3b', tree.branch.repository)
1661
self.assertEqual(old, ['2a', '3a'])
1662
self.assertEqual(new, ['2b', '3b'])
1664
def test_unrelated(self):
1665
tree = self.setup_ac_tree()
1666
old, new = log.get_history_change('3a', '3c', tree.branch.repository)
1667
self.assertEqual(old, ['1a', '2a', '3a'])
1668
self.assertEqual(new, ['1c', '2c', '3c'])
1670
def test_show_branch_change(self):
1671
tree = self.setup_ab_tree()
1673
log.show_branch_change(tree.branch, s, 3, '3a')
1674
self.assertContainsRe(s.getvalue(),
1675
'[*]{60}\nRemoved Revisions:\n(.|\n)*2a(.|\n)*3a(.|\n)*'
1676
'[*]{60}\n\nAdded Revisions:\n(.|\n)*2b(.|\n)*3b')
1678
def test_show_branch_change_no_change(self):
1679
tree = self.setup_ab_tree()
1681
log.show_branch_change(tree.branch, s, 3, '3b')
1682
self.assertEqual(s.getvalue(),
1683
'Nothing seems to have changed\n')
1685
def test_show_branch_change_no_old(self):
1686
tree = self.setup_ab_tree()
1688
log.show_branch_change(tree.branch, s, 2, '2b')
1689
self.assertContainsRe(s.getvalue(), 'Added Revisions:')
1690
self.assertNotContainsRe(s.getvalue(), 'Removed Revisions:')
1692
def test_show_branch_change_no_new(self):
1693
tree = self.setup_ab_tree()
1694
tree.branch.set_last_revision_info(2, '2b')
1696
log.show_branch_change(tree.branch, s, 3, '3b')
1697
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1698
self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')