~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-06-30 18:28:17 UTC
  • mfrom: (5967.10.2 test-cat)
  • Revision ID: pqm@pqm.ubuntu.com-20110630182817-83a5q9r9rxfkdn8r
(mbp) don't use subprocesses for testing cat (Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
24
24
    registry,
25
25
    revision,
26
26
    revisionspec,
 
27
    symbol_versioning,
27
28
    tests,
28
 
    gpg,
29
 
    trace,
30
29
    )
31
30
 
32
31
 
252
251
        wt.commit(message='add file1 and file2')
253
252
        self.run_bzr('branch parent child')
254
253
        os.unlink('child/file1')
255
 
        with file('child/file2', 'wb') as f: f.write('hello\n')
 
254
        file('child/file2', 'wb').write('hello\n')
256
255
        self.run_bzr(['commit', '-m', 'remove file1 and modify file2',
257
256
            'child'])
258
257
        os.chdir('parent')
283
282
        self.checkDelta(logentry.delta, added=['file1', 'file2'])
284
283
 
285
284
 
286
 
class TestFormatSignatureValidity(tests.TestCaseWithTransport):
287
 
    class UTFLoopbackGPGStrategy(gpg.LoopbackGPGStrategy):
288
 
        def verify(self, content, testament):
289
 
            return (gpg.SIGNATURE_VALID,
290
 
                u'UTF8 Test \xa1\xb1\xc1\xd1\xe1\xf1 <jrandom@example.com>')
291
 
 
292
 
    def has_signature_for_revision_id(self, revision_id):
293
 
        return True
294
 
 
295
 
    def get_signature_text(self, revision_id):
296
 
        return ''
297
 
 
298
 
    def test_format_signature_validity_utf(self):
299
 
        """Check that GPG signatures containing UTF-8 names are formatted
300
 
        correctly."""
301
 
        # Monkey patch to use our UTF-8 generating GPGStrategy
302
 
        self.overrideAttr(gpg, 'GPGStrategy', self.UTFLoopbackGPGStrategy)
303
 
        wt = self.make_branch_and_tree('.')
304
 
        revid = wt.commit('empty commit')
305
 
        repo = wt.branch.repository
306
 
        # Monkey patch out checking if this rev is actually signed, since we
307
 
        # can't sign it without a heavier TestCase and LoopbackGPGStrategy
308
 
        # doesn't care anyways.
309
 
        self.overrideAttr(repo, 'has_signature_for_revision_id',
310
 
                self.has_signature_for_revision_id)
311
 
        self.overrideAttr(repo, 'get_signature_text', self.get_signature_text)
312
 
        out = log.format_signature_validity(revid, repo)
313
 
        self.assertEqual(
314
 
u'valid signature from UTF8 Test \xa1\xb1\xc1\xd1\xe1\xf1 <jrandom@example.com>',
315
 
                out)
316
 
 
317
 
 
318
285
class TestShortLogFormatter(TestCaseForLogFormatter):
319
286
 
320
287
    def test_trailing_newlines(self):
356
323
    1 Joe Foo\t2005-11-22
357
324
      rev-1
358
325
 
359
 
Use --include-merged or -n0 to see merged revisions.
 
326
Use --include-merges or -n0 to see merged revisions.
360
327
""",
361
328
            wt.branch, log.ShortLogFormatter,
362
329
            formatter_kwargs=dict(show_advice=True))
1016
983
            wt.branch, log.GnuChangelogLogFormatter,
1017
984
            show_log_kwargs=dict(verbose=True))
1018
985
 
 
986
class TestGetViewRevisions(tests.TestCaseWithTransport, TestLogMixin):
 
987
 
 
988
    def _get_view_revisions(self, *args, **kwargs):
 
989
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
 
990
                                    log.get_view_revisions, *args, **kwargs)
 
991
 
 
992
    def make_tree_with_commits(self):
 
993
        """Create a tree with well-known revision ids"""
 
994
        wt = self.make_branch_and_tree('tree1')
 
995
        self.wt_commit(wt, 'commit one', rev_id='1')
 
996
        self.wt_commit(wt, 'commit two', rev_id='2')
 
997
        self.wt_commit(wt, 'commit three', rev_id='3')
 
998
        mainline_revs = [None, '1', '2', '3']
 
999
        rev_nos = {'1': 1, '2': 2, '3': 3}
 
1000
        return mainline_revs, rev_nos, wt
 
1001
 
 
1002
    def make_tree_with_merges(self):
 
1003
        """Create a tree with well-known revision ids and a merge"""
 
1004
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
 
1005
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
 
1006
        self.wt_commit(tree2, 'four-a', rev_id='4a')
 
1007
        wt.merge_from_branch(tree2.branch)
 
1008
        self.wt_commit(wt, 'four-b', rev_id='4b')
 
1009
        mainline_revs.append('4b')
 
1010
        rev_nos['4b'] = 4
 
1011
        # 4a: 3.1.1
 
1012
        return mainline_revs, rev_nos, wt
 
1013
 
 
1014
    def make_branch_with_many_merges(self):
 
1015
        """Create a tree with well-known revision ids"""
 
1016
        builder = self.make_branch_builder('tree1')
 
1017
        builder.start_series()
 
1018
        builder.build_snapshot('1', None, [
 
1019
            ('add', ('', 'TREE_ROOT', 'directory', '')),
 
1020
            ('add', ('f', 'f-id', 'file', '1\n'))])
 
1021
        builder.build_snapshot('2', ['1'], [])
 
1022
        builder.build_snapshot('3a', ['2'], [
 
1023
            ('modify', ('f-id', '1\n2\n3a\n'))])
 
1024
        builder.build_snapshot('3b', ['2', '3a'], [
 
1025
            ('modify', ('f-id', '1\n2\n3a\n'))])
 
1026
        builder.build_snapshot('3c', ['2', '3b'], [
 
1027
            ('modify', ('f-id', '1\n2\n3a\n'))])
 
1028
        builder.build_snapshot('4a', ['3b'], [])
 
1029
        builder.build_snapshot('4b', ['3c', '4a'], [])
 
1030
        builder.finish_series()
 
1031
 
 
1032
        # 1
 
1033
        # |
 
1034
        # 2-.
 
1035
        # |\ \
 
1036
        # | | 3a
 
1037
        # | |/
 
1038
        # | 3b
 
1039
        # |/|
 
1040
        # 3c4a
 
1041
        # |/
 
1042
        # 4b
 
1043
 
 
1044
        mainline_revs = [None, '1', '2', '3c', '4b']
 
1045
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
 
1046
        full_rev_nos_for_reference = {
 
1047
            '1': '1',
 
1048
            '2': '2',
 
1049
            '3a': '2.1.1', #first commit tree 3
 
1050
            '3b': '2.2.1', # first commit tree 2
 
1051
            '3c': '3', #merges 3b to main
 
1052
            '4a': '2.2.2', # second commit tree 2
 
1053
            '4b': '4', # merges 4a to main
 
1054
            }
 
1055
        return mainline_revs, rev_nos, builder.get_branch()
 
1056
 
 
1057
    def test_get_view_revisions_forward(self):
 
1058
        """Test the get_view_revisions method"""
 
1059
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
 
1060
        wt.lock_read()
 
1061
        self.addCleanup(wt.unlock)
 
1062
        revisions = list(self._get_view_revisions(
 
1063
                mainline_revs, rev_nos, wt.branch, 'forward'))
 
1064
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
 
1065
                         revisions)
 
1066
        revisions2 = list(self._get_view_revisions(
 
1067
                mainline_revs, rev_nos, wt.branch, 'forward',
 
1068
                include_merges=False))
 
1069
        self.assertEqual(revisions, revisions2)
 
1070
 
 
1071
    def test_get_view_revisions_reverse(self):
 
1072
        """Test the get_view_revisions with reverse"""
 
1073
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
 
1074
        wt.lock_read()
 
1075
        self.addCleanup(wt.unlock)
 
1076
        revisions = list(self._get_view_revisions(
 
1077
                mainline_revs, rev_nos, wt.branch, 'reverse'))
 
1078
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
 
1079
                         revisions)
 
1080
        revisions2 = list(self._get_view_revisions(
 
1081
                mainline_revs, rev_nos, wt.branch, 'reverse',
 
1082
                include_merges=False))
 
1083
        self.assertEqual(revisions, revisions2)
 
1084
 
 
1085
    def test_get_view_revisions_merge(self):
 
1086
        """Test get_view_revisions when there are merges"""
 
1087
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
 
1088
        wt.lock_read()
 
1089
        self.addCleanup(wt.unlock)
 
1090
        revisions = list(self._get_view_revisions(
 
1091
                mainline_revs, rev_nos, wt.branch, 'forward'))
 
1092
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
 
1093
                          ('4b', '4', 0), ('4a', '3.1.1', 1)],
 
1094
                         revisions)
 
1095
        revisions = list(self._get_view_revisions(
 
1096
                mainline_revs, rev_nos, wt.branch, 'forward',
 
1097
                include_merges=False))
 
1098
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
 
1099
                          ('4b', '4', 0)],
 
1100
                         revisions)
 
1101
 
 
1102
    def test_get_view_revisions_merge_reverse(self):
 
1103
        """Test get_view_revisions in reverse when there are merges"""
 
1104
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
 
1105
        wt.lock_read()
 
1106
        self.addCleanup(wt.unlock)
 
1107
        revisions = list(self._get_view_revisions(
 
1108
                mainline_revs, rev_nos, wt.branch, 'reverse'))
 
1109
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
 
1110
                          ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
 
1111
                         revisions)
 
1112
        revisions = list(self._get_view_revisions(
 
1113
                mainline_revs, rev_nos, wt.branch, 'reverse',
 
1114
                include_merges=False))
 
1115
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
 
1116
                          ('1', '1', 0)],
 
1117
                         revisions)
 
1118
 
 
1119
    def test_get_view_revisions_merge2(self):
 
1120
        """Test get_view_revisions when there are merges"""
 
1121
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
 
1122
        b.lock_read()
 
1123
        self.addCleanup(b.unlock)
 
1124
        revisions = list(self._get_view_revisions(
 
1125
                mainline_revs, rev_nos, b, 'forward'))
 
1126
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
 
1127
                    ('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
 
1128
                    ('4a', '2.2.2', 1)]
 
1129
        self.assertEqual(expected, revisions)
 
1130
        revisions = list(self._get_view_revisions(
 
1131
                mainline_revs, rev_nos, b, 'forward',
 
1132
                include_merges=False))
 
1133
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
 
1134
                          ('4b', '4', 0)],
 
1135
                         revisions)
 
1136
 
 
1137
    def test_file_id_for_range(self):
 
1138
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
 
1139
        b.lock_read()
 
1140
        self.addCleanup(b.unlock)
 
1141
 
 
1142
        def rev_from_rev_id(revid, branch):
 
1143
            revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
 
1144
            return revspec.in_history(branch)
 
1145
 
 
1146
        def view_revs(start_rev, end_rev, file_id, direction):
 
1147
            revs = self.applyDeprecated(
 
1148
                symbol_versioning.deprecated_in((2, 2, 0)),
 
1149
                log.calculate_view_revisions,
 
1150
                b,
 
1151
                start_rev, # start_revision
 
1152
                end_rev, # end_revision
 
1153
                direction, # direction
 
1154
                file_id, # specific_fileid
 
1155
                True, # generate_merge_revisions
 
1156
                )
 
1157
            return revs
 
1158
 
 
1159
        rev_3a = rev_from_rev_id('3a', b)
 
1160
        rev_4b = rev_from_rev_id('4b', b)
 
1161
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
 
1162
                          ('3a', '2.1.1', 2)],
 
1163
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
 
1164
        # Note: 3c still appears before 3a here because of depth-based sorting
 
1165
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
 
1166
                          ('3a', '2.1.1', 2)],
 
1167
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
 
1168
 
 
1169
 
 
1170
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
 
1171
 
 
1172
    def get_view_revisions(self, *args):
 
1173
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
 
1174
                                    log.get_view_revisions, *args)
 
1175
 
 
1176
    def create_tree_with_single_merge(self):
 
1177
        """Create a branch with a moderate layout.
 
1178
 
 
1179
        The revision graph looks like:
 
1180
 
 
1181
           A
 
1182
           |\
 
1183
           B C
 
1184
           |/
 
1185
           D
 
1186
 
 
1187
        In this graph, A introduced files f1 and f2 and f3.
 
1188
        B modifies f1 and f3, and C modifies f2 and f3.
 
1189
        D merges the changes from B and C and resolves the conflict for f3.
 
1190
        """
 
1191
        # TODO: jam 20070218 This seems like it could really be done
 
1192
        #       with make_branch_and_memory_tree() if we could just
 
1193
        #       create the content of those files.
 
1194
        # TODO: jam 20070218 Another alternative is that we would really
 
1195
        #       like to only create this tree 1 time for all tests that
 
1196
        #       use it. Since 'log' only uses the tree in a readonly
 
1197
        #       fashion, it seems a shame to regenerate an identical
 
1198
        #       tree for each test.
 
1199
        # TODO: vila 20100122 One way to address the shame above will be to
 
1200
        #       create a memory tree during test parametrization and give a
 
1201
        #       *copy* of this tree to each test. Copying a memory tree ought
 
1202
        #       to be cheap, at least cheaper than creating them with such
 
1203
        #       complex setups.
 
1204
        tree = self.make_branch_and_tree('tree')
 
1205
        tree.lock_write()
 
1206
        self.addCleanup(tree.unlock)
 
1207
 
 
1208
        self.build_tree_contents([('tree/f1', 'A\n'),
 
1209
                                  ('tree/f2', 'A\n'),
 
1210
                                  ('tree/f3', 'A\n'),
 
1211
                                 ])
 
1212
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
 
1213
        tree.commit('A', rev_id='A')
 
1214
 
 
1215
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
 
1216
                                  ('tree/f3', 'A\nC\n'),
 
1217
                                 ])
 
1218
        tree.commit('C', rev_id='C')
 
1219
        # Revert back to A to build the other history.
 
1220
        tree.set_last_revision('A')
 
1221
        tree.branch.set_last_revision_info(1, 'A')
 
1222
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
 
1223
                                  ('tree/f2', 'A\n'),
 
1224
                                  ('tree/f3', 'A\nB\n'),
 
1225
                                 ])
 
1226
        tree.commit('B', rev_id='B')
 
1227
        tree.set_parent_ids(['B', 'C'])
 
1228
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
 
1229
                                  ('tree/f2', 'A\nC\n'),
 
1230
                                  ('tree/f3', 'A\nB\nC\n'),
 
1231
                                 ])
 
1232
        tree.commit('D', rev_id='D')
 
1233
 
 
1234
        # Switch to a read lock for this tree.
 
1235
        # We still have an addCleanup(tree.unlock) pending
 
1236
        tree.unlock()
 
1237
        tree.lock_read()
 
1238
        return tree
 
1239
 
 
1240
    def check_delta(self, delta, **kw):
 
1241
        """Check the filenames touched by a delta are as expected.
 
1242
 
 
1243
        Caller only have to pass in the list of files for each part, all
 
1244
        unspecified parts are considered empty (and checked as such).
 
1245
        """
 
1246
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
 
1247
            # By default we expect an empty list
 
1248
            expected = kw.get(n, [])
 
1249
            # strip out only the path components
 
1250
            got = [x[0] for x in getattr(delta, n)]
 
1251
            self.assertEqual(expected, got)
 
1252
 
 
1253
    def test_tree_with_single_merge(self):
 
1254
        """Make sure the tree layout is correct."""
 
1255
        tree = self.create_tree_with_single_merge()
 
1256
        rev_A_tree = tree.branch.repository.revision_tree('A')
 
1257
        rev_B_tree = tree.branch.repository.revision_tree('B')
 
1258
        rev_C_tree = tree.branch.repository.revision_tree('C')
 
1259
        rev_D_tree = tree.branch.repository.revision_tree('D')
 
1260
 
 
1261
        self.check_delta(rev_B_tree.changes_from(rev_A_tree),
 
1262
                         modified=['f1', 'f3'])
 
1263
 
 
1264
        self.check_delta(rev_C_tree.changes_from(rev_A_tree),
 
1265
                         modified=['f2', 'f3'])
 
1266
 
 
1267
        self.check_delta(rev_D_tree.changes_from(rev_B_tree),
 
1268
                         modified=['f2', 'f3'])
 
1269
 
 
1270
        self.check_delta(rev_D_tree.changes_from(rev_C_tree),
 
1271
                         modified=['f1', 'f3'])
 
1272
 
 
1273
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
 
1274
        """Ensure _filter_revisions_touching_file_id returns the right values.
 
1275
 
 
1276
        Get the return value from _filter_revisions_touching_file_id and make
 
1277
        sure they are correct.
 
1278
        """
 
1279
        # The api for _filter_revisions_touching_file_id is a little crazy.
 
1280
        # So we do the setup here.
 
1281
        mainline = tree.branch.revision_history()
 
1282
        mainline.insert(0, None)
 
1283
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
 
1284
        view_revs_iter = self.get_view_revisions(
 
1285
            mainline, revnos, tree.branch, 'reverse', True)
 
1286
        actual_revs = log._filter_revisions_touching_file_id(
 
1287
            tree.branch, file_id, list(view_revs_iter))
 
1288
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
 
1289
 
 
1290
    def test_file_id_f1(self):
 
1291
        tree = self.create_tree_with_single_merge()
 
1292
        # f1 should be marked as modified by revisions A and B
 
1293
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
 
1294
 
 
1295
    def test_file_id_f2(self):
 
1296
        tree = self.create_tree_with_single_merge()
 
1297
        # f2 should be marked as modified by revisions A, C, and D
 
1298
        # because D merged the changes from C.
 
1299
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
 
1300
 
 
1301
    def test_file_id_f3(self):
 
1302
        tree = self.create_tree_with_single_merge()
 
1303
        # f3 should be marked as modified by revisions A, B, C, and D
 
1304
        self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
 
1305
 
 
1306
    def test_file_id_with_ghosts(self):
 
1307
        # This is testing bug #209948, where having a ghost would cause
 
1308
        # _filter_revisions_touching_file_id() to fail.
 
1309
        tree = self.create_tree_with_single_merge()
 
1310
        # We need to add a revision, so switch back to a write-locked tree
 
1311
        # (still a single addCleanup(tree.unlock) pending).
 
1312
        tree.unlock()
 
1313
        tree.lock_write()
 
1314
        first_parent = tree.last_revision()
 
1315
        tree.set_parent_ids([first_parent, 'ghost-revision-id'])
 
1316
        self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
 
1317
        tree.commit('commit with a ghost', rev_id='XX')
 
1318
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
 
1319
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
 
1320
 
 
1321
    def test_unknown_file_id(self):
 
1322
        tree = self.create_tree_with_single_merge()
 
1323
        self.assertAllRevisionsForFileID(tree, 'unknown', [])
 
1324
 
 
1325
    def test_empty_branch_unknown_file_id(self):
 
1326
        tree = self.make_branch_and_tree('tree')
 
1327
        self.assertAllRevisionsForFileID(tree, 'unknown', [])
 
1328
 
1019
1329
 
1020
1330
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1021
1331
 
1343
1653
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
1344
1654
 
1345
1655
    def setUp(self):
1346
 
        super(TestLogWithBugs, self).setUp()
 
1656
        TestCaseForLogFormatter.setUp(self)
1347
1657
        log.properties_handler_registry.register(
1348
1658
            'bugs_properties_handler',
1349
1659
            log._bugs_properties_handler)
1368
1678
        self.assertFormatterResult("""\
1369
1679
------------------------------------------------------------
1370
1680
revno: 2
1371
 
fixes bugs: test://bug/id test://bug/2
 
1681
fixes bug(s): test://bug/id test://bug/2
1372
1682
author: Joe Bar <joe@bar.com>
1373
1683
committer: Joe Foo <joe@foo.com>
1374
1684
branch nick: work
1379
1689
  message
1380
1690
------------------------------------------------------------
1381
1691
revno: 1
1382
 
fixes bug: test://bug/id
 
1692
fixes bug(s): test://bug/id
1383
1693
committer: Joe Foo <joe@foo.com>
1384
1694
branch nick: work
1385
1695
timestamp: Tue 2005-11-22 00:00:00 +0000
1392
1702
        tree = self.make_commits_with_bugs()
1393
1703
        self.assertFormatterResult("""\
1394
1704
    2 Joe Bar\t2005-11-22
1395
 
      fixes bugs: test://bug/id test://bug/2
 
1705
      fixes bug(s): test://bug/id test://bug/2
1396
1706
      multiline
1397
1707
      log
1398
1708
      message
1399
1709
 
1400
1710
    1 Joe Foo\t2005-11-22
1401
 
      fixes bug: test://bug/id
 
1711
      fixes bug(s): test://bug/id
1402
1712
      simple log message
1403
1713
 
1404
1714
""",
1423
1733
class TestLogForAuthors(TestCaseForLogFormatter):
1424
1734
 
1425
1735
    def setUp(self):
1426
 
        super(TestLogForAuthors, self).setUp()
 
1736
        TestCaseForLogFormatter.setUp(self)
1427
1737
        self.wt = self.make_standard_commit('nicky',
1428
1738
            authors=['John Doe <jdoe@example.com>',
1429
1739
                     'Jane Rey <jrey@example.com>'])
1570
1880
    def make_branch_with_alternate_ancestries(self, relpath='.'):
1571
1881
        # See test_merge_sorted_exclude_ancestry below for the difference with
1572
1882
        # bt.per_branch.test_iter_merge_sorted_revision.
1573
 
        # TestIterMergeSortedRevisionsBushyGraph.
 
1883
        # TestIterMergeSortedRevisionsBushyGraph. 
1574
1884
        # make_branch_with_alternate_ancestries
1575
1885
        # and test_merge_sorted_exclude_ancestry
1576
1886
        # See the FIXME in assertLogRevnos too.
1603
1913
    def assertLogRevnos(self, expected_revnos, b, start, end,
1604
1914
                        exclude_common_ancestry, generate_merge_revisions=True):
1605
1915
        # FIXME: the layering in log makes it hard to test intermediate levels,
1606
 
        # I wish adding filters with their parameters was easier...
 
1916
        # I wish adding filters with their parameters were easier...
1607
1917
        # -- vila 20100413
1608
1918
        iter_revs = log._calc_view_revisions(
1609
1919
            b, start, end, direction='reverse',
1631
1941
                             b, '1', '3', exclude_common_ancestry=True,
1632
1942
                             generate_merge_revisions=True)
1633
1943
 
1634
 
 
1635
 
class TestLogDefaults(TestCaseForLogFormatter):
1636
 
    def test_default_log_level(self):
1637
 
        """
1638
 
        Test to ensure that specifying 'levels=1' to make_log_request_dict
1639
 
        doesn't get overwritten when using a LogFormatter that supports more
1640
 
        detail.
1641
 
        Fixes bug #747958.
1642
 
        """
1643
 
        wt = self._prepare_tree_with_merges()
1644
 
        b = wt.branch
1645
 
 
1646
 
        class CustomLogFormatter(log.LogFormatter):
1647
 
            def __init__(self, *args, **kwargs):
1648
 
                super(CustomLogFormatter, self).__init__(*args, **kwargs)
1649
 
                self.revisions = []
1650
 
            def get_levels(self):
1651
 
                # log formatter supports all levels:
1652
 
                return 0
1653
 
            def log_revision(self, revision):
1654
 
                self.revisions.append(revision)
1655
 
 
1656
 
        log_formatter = LogCatcher()
1657
 
        # First request we don't specify number of levels, we should get a
1658
 
        # sensible default (whatever the LogFormatter handles - which in this
1659
 
        # case is 0/everything):
1660
 
        request = log.make_log_request_dict(limit=10)
1661
 
        log.Logger(b, request).show(log_formatter)
1662
 
        # should have all three revisions:
1663
 
        self.assertEquals(len(log_formatter.revisions), 3)
1664
 
 
1665
 
        del log_formatter
1666
 
        log_formatter = LogCatcher()
1667
 
        # now explicitly request mainline revisions only:
1668
 
        request = log.make_log_request_dict(limit=10, levels=1)
1669
 
        log.Logger(b, request).show(log_formatter)
1670
 
        # should now only have 2 revisions:
1671
 
        self.assertEquals(len(log_formatter.revisions), 2)
1672