~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: INADA Naoki
  • Date: 2011-05-18 06:01:08 UTC
  • mto: This revision was merged to the branch mainline in revision 5894.
  • Revision ID: songofacandy@gmail.com-20110518060108-86t2kffcrzu0nf6i
Update Japanese docs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2006-2011 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
22
22
also see this file.
23
23
"""
24
24
 
25
 
from StringIO import StringIO
 
25
from cStringIO import StringIO
26
26
 
27
27
from bzrlib import (
28
28
    branch as _mod_branch,
29
29
    bzrdir,
30
30
    config,
31
31
    errors,
 
32
    symbol_versioning,
 
33
    tests,
32
34
    trace,
33
35
    urlutils,
34
36
    )
35
 
from bzrlib.branch import (
36
 
    Branch,
37
 
    BranchHooks,
38
 
    BranchFormat,
39
 
    BranchReferenceFormat,
40
 
    BzrBranch5,
41
 
    BzrBranchFormat5,
42
 
    BzrBranchFormat6,
43
 
    BzrBranchFormat7,
44
 
    PullResult,
45
 
    _run_with_write_locked_target,
46
 
    )
47
 
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1,
48
 
                           BzrDir, BzrDirFormat)
49
 
from bzrlib.errors import (NotBranchError,
50
 
                           UnknownFormatError,
51
 
                           UnknownHook,
52
 
                           UnsupportedFormatError,
53
 
                           )
54
 
 
55
 
from bzrlib.tests import TestCase, TestCaseWithTransport
56
 
from bzrlib.transport import get_transport
57
 
 
58
 
 
59
 
class TestDefaultFormat(TestCase):
 
37
 
 
38
 
 
39
class TestDefaultFormat(tests.TestCase):
60
40
 
61
41
    def test_default_format(self):
62
42
        # update this if you change the default branch format
63
 
        self.assertIsInstance(BranchFormat.get_default_format(),
64
 
                BzrBranchFormat7)
 
43
        self.assertIsInstance(_mod_branch.format_registry.get_default(),
 
44
                _mod_branch.BzrBranchFormat7)
65
45
 
66
46
    def test_default_format_is_same_as_bzrdir_default(self):
67
47
        # XXX: it might be nice if there was only one place the default was
68
48
        # set, but at the moment that's not true -- mbp 20070814 --
69
49
        # https://bugs.launchpad.net/bzr/+bug/132376
70
 
        self.assertEqual(BranchFormat.get_default_format(),
71
 
                BzrDirFormat.get_default_format().get_branch_format())
 
50
        self.assertEqual(
 
51
            _mod_branch.format_registry.get_default(),
 
52
            bzrdir.BzrDirFormat.get_default_format().get_branch_format())
72
53
 
73
54
    def test_get_set_default_format(self):
74
55
        # set the format and then set it back again
75
 
        old_format = BranchFormat.get_default_format()
76
 
        BranchFormat.set_default_format(SampleBranchFormat())
 
56
        old_format = _mod_branch.format_registry.get_default()
 
57
        _mod_branch.format_registry.set_default(SampleBranchFormat())
77
58
        try:
78
59
            # the default branch format is used by the meta dir format
79
60
            # which is not the default bzrdir format at this point
80
 
            dir = BzrDirMetaFormat1().initialize('memory:///')
 
61
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
81
62
            result = dir.create_branch()
82
63
            self.assertEqual(result, 'A branch')
83
64
        finally:
84
 
            BranchFormat.set_default_format(old_format)
85
 
        self.assertEqual(old_format, BranchFormat.get_default_format())
86
 
 
87
 
 
88
 
class TestBranchFormat5(TestCaseWithTransport):
 
65
            _mod_branch.format_registry.set_default(old_format)
 
66
        self.assertEqual(old_format,
 
67
                         _mod_branch.format_registry.get_default())
 
68
 
 
69
 
 
70
class TestBranchFormat5(tests.TestCaseWithTransport):
89
71
    """Tests specific to branch format 5"""
90
72
 
91
73
    def test_branch_format_5_uses_lockdir(self):
92
74
        url = self.get_url()
93
 
        bzrdir = BzrDirMetaFormat1().initialize(url)
94
 
        bzrdir.create_repository()
95
 
        branch = bzrdir.create_branch()
 
75
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
 
76
        bdir.create_repository()
 
77
        branch = _mod_branch.BzrBranchFormat5().initialize(bdir)
96
78
        t = self.get_transport()
97
79
        self.log("branch instance is %r" % branch)
98
 
        self.assert_(isinstance(branch, BzrBranch5))
 
80
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
99
81
        self.assertIsDirectory('.', t)
100
82
        self.assertIsDirectory('.bzr/branch', t)
101
83
        self.assertIsDirectory('.bzr/branch/lock', t)
102
84
        branch.lock_write()
103
 
        try:
104
 
            self.assertIsDirectory('.bzr/branch/lock/held', t)
105
 
        finally:
106
 
            branch.unlock()
 
85
        self.addCleanup(branch.unlock)
 
86
        self.assertIsDirectory('.bzr/branch/lock/held', t)
107
87
 
108
88
    def test_set_push_location(self):
109
 
        from bzrlib.config import (locations_config_filename,
110
 
                                   ensure_config_dir_exists)
111
 
        ensure_config_dir_exists()
112
 
        fn = locations_config_filename()
113
 
        # write correct newlines to locations.conf
114
 
        # by default ConfigObj uses native line-endings for new files
115
 
        # but uses already existing line-endings if file is not empty
116
 
        f = open(fn, 'wb')
117
 
        try:
118
 
            f.write('# comment\n')
119
 
        finally:
120
 
            f.close()
 
89
        conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
121
90
 
122
91
        branch = self.make_branch('.', format='knit')
123
92
        branch.set_push_location('foo')
126
95
                             "[%s]\n"
127
96
                             "push_location = foo\n"
128
97
                             "push_location:policy = norecurse\n" % local_path,
129
 
                             fn)
 
98
                             config.locations_config_filename())
130
99
 
131
100
    # TODO RBC 20051029 test getting a push location from a branch in a
132
101
    # recursive section - that is, it appends the branch name.
133
102
 
134
103
 
135
 
class SampleBranchFormat(BranchFormat):
 
104
class SampleBranchFormat(_mod_branch.BranchFormat):
136
105
    """A sample format
137
106
 
138
107
    this format is initializable, unsupported to aid in testing the
143
112
        """See BzrBranchFormat.get_format_string()."""
144
113
        return "Sample branch format."
145
114
 
146
 
    def initialize(self, a_bzrdir):
 
115
    def initialize(self, a_bzrdir, name=None, repository=None):
147
116
        """Format 4 branches cannot be created."""
148
 
        t = a_bzrdir.get_branch_transport(self)
 
117
        t = a_bzrdir.get_branch_transport(self, name=name)
149
118
        t.put_bytes('format', self.get_format_string())
150
119
        return 'A branch'
151
120
 
152
121
    def is_supported(self):
153
122
        return False
154
123
 
155
 
    def open(self, transport, _found=False, ignore_fallbacks=False):
 
124
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
156
125
        return "opened branch."
157
126
 
158
127
 
159
 
class TestBzrBranchFormat(TestCaseWithTransport):
 
128
# Demonstrating how lazy loading is often implemented:
 
129
# A constant string is created.
 
130
SampleSupportedBranchFormatString = "Sample supported branch format."
 
131
 
 
132
# And the format class can then reference the constant to avoid skew.
 
133
class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
 
134
    """A sample supported format."""
 
135
 
 
136
    def get_format_string(self):
 
137
        """See BzrBranchFormat.get_format_string()."""
 
138
        return SampleSupportedBranchFormatString
 
139
 
 
140
    def initialize(self, a_bzrdir, name=None):
 
141
        t = a_bzrdir.get_branch_transport(self, name=name)
 
142
        t.put_bytes('format', self.get_format_string())
 
143
        return 'A branch'
 
144
 
 
145
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
 
146
        return "opened supported branch."
 
147
 
 
148
 
 
149
class SampleExtraBranchFormat(_mod_branch.BranchFormat):
 
150
    """A sample format that is not usable in a metadir."""
 
151
 
 
152
    def get_format_string(self):
 
153
        # This format is not usable in a metadir.
 
154
        return None
 
155
 
 
156
    def network_name(self):
 
157
        # Network name always has to be provided.
 
158
        return "extra"
 
159
 
 
160
    def initialize(self, a_bzrdir, name=None):
 
161
        raise NotImplementedError(self.initialize)
 
162
 
 
163
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
 
164
        raise NotImplementedError(self.open)
 
165
 
 
166
 
 
167
class TestBzrBranchFormat(tests.TestCaseWithTransport):
160
168
    """Tests for the BzrBranchFormat facility."""
161
169
 
162
170
    def test_find_format(self):
168
176
            dir = format._matchingbzrdir.initialize(url)
169
177
            dir.create_repository()
170
178
            format.initialize(dir)
171
 
            found_format = BranchFormat.find_format(dir)
172
 
            self.failUnless(isinstance(found_format, format.__class__))
173
 
        check_format(BzrBranchFormat5(), "bar")
 
179
            found_format = _mod_branch.BranchFormat.find_format(dir)
 
180
            self.assertIsInstance(found_format, format.__class__)
 
181
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
 
182
 
 
183
    def test_find_format_factory(self):
 
184
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
 
185
        SampleSupportedBranchFormat().initialize(dir)
 
186
        factory = _mod_branch.MetaDirBranchFormatFactory(
 
187
            SampleSupportedBranchFormatString,
 
188
            "bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
 
189
        _mod_branch.format_registry.register(factory)
 
190
        self.addCleanup(_mod_branch.format_registry.remove, factory)
 
191
        b = _mod_branch.Branch.open(self.get_url())
 
192
        self.assertEqual(b, "opened supported branch.")
174
193
 
175
194
    def test_find_format_not_branch(self):
176
195
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
177
 
        self.assertRaises(NotBranchError,
178
 
                          BranchFormat.find_format,
 
196
        self.assertRaises(errors.NotBranchError,
 
197
                          _mod_branch.BranchFormat.find_format,
179
198
                          dir)
180
199
 
181
200
    def test_find_format_unknown_format(self):
182
201
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
183
202
        SampleBranchFormat().initialize(dir)
184
 
        self.assertRaises(UnknownFormatError,
185
 
                          BranchFormat.find_format,
 
203
        self.assertRaises(errors.UnknownFormatError,
 
204
                          _mod_branch.BranchFormat.find_format,
186
205
                          dir)
187
206
 
188
207
    def test_register_unregister_format(self):
 
208
        # Test the deprecated format registration functions
189
209
        format = SampleBranchFormat()
190
210
        # make a control dir
191
211
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
192
212
        # make a branch
193
213
        format.initialize(dir)
194
214
        # register a format for it.
195
 
        BranchFormat.register_format(format)
 
215
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
216
            _mod_branch.BranchFormat.register_format, format)
196
217
        # which branch.Open will refuse (not supported)
197
 
        self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
 
218
        self.assertRaises(errors.UnsupportedFormatError,
 
219
                          _mod_branch.Branch.open, self.get_url())
198
220
        self.make_branch_and_tree('foo')
199
221
        # but open_downlevel will work
200
 
        self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
 
222
        self.assertEqual(
 
223
            format.open(dir),
 
224
            bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
201
225
        # unregister the format
202
 
        BranchFormat.unregister_format(format)
 
226
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
227
            _mod_branch.BranchFormat.unregister_format, format)
203
228
        self.make_branch_and_tree('bar')
204
229
 
205
230
 
 
231
class TestBranchFormatRegistry(tests.TestCase):
 
232
 
 
233
    def setUp(self):
 
234
        super(TestBranchFormatRegistry, self).setUp()
 
235
        self.registry = _mod_branch.BranchFormatRegistry()
 
236
 
 
237
    def test_default(self):
 
238
        self.assertIs(None, self.registry.get_default())
 
239
        format = SampleBranchFormat()
 
240
        self.registry.set_default(format)
 
241
        self.assertEquals(format, self.registry.get_default())
 
242
 
 
243
    def test_register_unregister_format(self):
 
244
        format = SampleBranchFormat()
 
245
        self.registry.register(format)
 
246
        self.assertEquals(format,
 
247
            self.registry.get("Sample branch format."))
 
248
        self.registry.remove(format)
 
249
        self.assertRaises(KeyError, self.registry.get,
 
250
            "Sample branch format.")
 
251
 
 
252
    def test_get_all(self):
 
253
        format = SampleBranchFormat()
 
254
        self.assertEquals([], self.registry._get_all())
 
255
        self.registry.register(format)
 
256
        self.assertEquals([format], self.registry._get_all())
 
257
 
 
258
    def test_register_extra(self):
 
259
        format = SampleExtraBranchFormat()
 
260
        self.assertEquals([], self.registry._get_all())
 
261
        self.registry.register_extra(format)
 
262
        self.assertEquals([format], self.registry._get_all())
 
263
 
 
264
    def test_register_extra_lazy(self):
 
265
        self.assertEquals([], self.registry._get_all())
 
266
        self.registry.register_extra_lazy("bzrlib.tests.test_branch",
 
267
            "SampleExtraBranchFormat")
 
268
        formats = self.registry._get_all()
 
269
        self.assertEquals(1, len(formats))
 
270
        self.assertIsInstance(formats[0], SampleExtraBranchFormat)
 
271
 
 
272
 
 
273
#Used by TestMetaDirBranchFormatFactory 
 
274
FakeLazyFormat = None
 
275
 
 
276
 
 
277
class TestMetaDirBranchFormatFactory(tests.TestCase):
 
278
 
 
279
    def test_get_format_string_does_not_load(self):
 
280
        """Formats have a static format string."""
 
281
        factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
 
282
        self.assertEqual("yo", factory.get_format_string())
 
283
 
 
284
    def test_call_loads(self):
 
285
        # __call__ is used by the network_format_registry interface to get a
 
286
        # Format.
 
287
        global FakeLazyFormat
 
288
        del FakeLazyFormat
 
289
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
 
290
            "bzrlib.tests.test_branch", "FakeLazyFormat")
 
291
        self.assertRaises(AttributeError, factory)
 
292
 
 
293
    def test_call_returns_call_of_referenced_object(self):
 
294
        global FakeLazyFormat
 
295
        FakeLazyFormat = lambda:'called'
 
296
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
 
297
            "bzrlib.tests.test_branch", "FakeLazyFormat")
 
298
        self.assertEqual('called', factory())
 
299
 
 
300
 
206
301
class TestBranch67(object):
207
302
    """Common tests for both branch 6 and 7 which are mostly the same."""
208
303
 
216
311
        raise NotImplementedError(self.get_class)
217
312
 
218
313
    def test_creation(self):
219
 
        format = BzrDirMetaFormat1()
 
314
        format = bzrdir.BzrDirMetaFormat1()
220
315
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
221
316
        branch = self.make_branch('a', format=format)
222
317
        self.assertIsInstance(branch, self.get_class())
227
322
 
228
323
    def test_layout(self):
229
324
        branch = self.make_branch('a', format=self.get_format_name())
230
 
        self.failUnlessExists('a/.bzr/branch/last-revision')
231
 
        self.failIfExists('a/.bzr/branch/revision-history')
232
 
        self.failIfExists('a/.bzr/branch/references')
 
325
        self.assertPathExists('a/.bzr/branch/last-revision')
 
326
        self.assertPathDoesNotExist('a/.bzr/branch/revision-history')
 
327
        self.assertPathDoesNotExist('a/.bzr/branch/references')
233
328
 
234
329
    def test_config(self):
235
330
        """Ensure that all configuration data is stored in the branch"""
236
331
        branch = self.make_branch('a', format=self.get_format_name())
237
 
        branch.set_parent('http://bazaar-vcs.org')
238
 
        self.failIfExists('a/.bzr/branch/parent')
239
 
        self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
240
 
        branch.set_push_location('sftp://bazaar-vcs.org')
 
332
        branch.set_parent('http://example.com')
 
333
        self.assertPathDoesNotExist('a/.bzr/branch/parent')
 
334
        self.assertEqual('http://example.com', branch.get_parent())
 
335
        branch.set_push_location('sftp://example.com')
241
336
        config = branch.get_config()._get_branch_data_config()
242
 
        self.assertEqual('sftp://bazaar-vcs.org',
 
337
        self.assertEqual('sftp://example.com',
243
338
                         config.get_user_option('push_location'))
244
 
        branch.set_bound_location('ftp://bazaar-vcs.org')
245
 
        self.failIfExists('a/.bzr/branch/bound')
246
 
        self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
 
339
        branch.set_bound_location('ftp://example.com')
 
340
        self.assertPathDoesNotExist('a/.bzr/branch/bound')
 
341
        self.assertEqual('ftp://example.com', branch.get_bound_location())
247
342
 
248
343
    def test_set_revision_history(self):
249
344
        builder = self.make_branch_builder('.', format=self.get_format_name())
254
349
        branch = builder.get_branch()
255
350
        branch.lock_write()
256
351
        self.addCleanup(branch.unlock)
257
 
        branch.set_revision_history(['foo', 'bar'])
258
 
        branch.set_revision_history(['foo'])
 
352
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
353
            branch.set_revision_history, ['foo', 'bar'])
 
354
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
355
                branch.set_revision_history, ['foo'])
259
356
        self.assertRaises(errors.NotLefthandHistory,
260
 
                          branch.set_revision_history, ['bar'])
 
357
            self.applyDeprecated, symbol_versioning.deprecated_in((2, 4, 0)),
 
358
            branch.set_revision_history, ['bar'])
261
359
 
262
360
    def do_checkout_test(self, lightweight=False):
263
361
        tree = self.make_branch_and_tree('source',
276
374
        subtree.commit('a subtree file')
277
375
        subsubtree.commit('a subsubtree file')
278
376
        tree.branch.create_checkout('target', lightweight=lightweight)
279
 
        self.failUnlessExists('target')
280
 
        self.failUnlessExists('target/subtree')
281
 
        self.failUnlessExists('target/subtree/file')
282
 
        self.failUnlessExists('target/subtree/subsubtree/file')
 
377
        self.assertPathExists('target')
 
378
        self.assertPathExists('target/subtree')
 
379
        self.assertPathExists('target/subtree/file')
 
380
        self.assertPathExists('target/subtree/subsubtree/file')
283
381
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
284
382
        if lightweight:
285
383
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
309
407
                         'locations.conf')
310
408
 
311
409
 
312
 
class TestBranch6(TestBranch67, TestCaseWithTransport):
 
410
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
313
411
 
314
412
    def get_class(self):
315
413
        return _mod_branch.BzrBranch6
330
428
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
331
429
 
332
430
 
333
 
class TestBranch7(TestBranch67, TestCaseWithTransport):
 
431
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
334
432
 
335
433
    def get_class(self):
336
434
        return _mod_branch.BzrBranch7
380
478
        self.assertTrue(branch.repository.has_revision(revid))
381
479
 
382
480
 
383
 
class BzrBranch8(TestCaseWithTransport):
 
481
class BzrBranch8(tests.TestCaseWithTransport):
384
482
 
385
483
    def make_branch(self, location, format=None):
386
484
        if format is None:
387
485
            format = bzrdir.format_registry.make_bzrdir('1.9')
388
486
            format.set_branch_format(_mod_branch.BzrBranchFormat8())
389
 
        return TestCaseWithTransport.make_branch(self, location, format=format)
 
487
        return tests.TestCaseWithTransport.make_branch(
 
488
            self, location, format=format)
390
489
 
391
490
    def create_branch_with_reference(self):
392
491
        branch = self.make_branch('branch')
436
535
        branch.lock_write()
437
536
        branch.set_reference_info('file-id', 'path2', 'location2')
438
537
        branch.unlock()
439
 
        doppelganger = Branch.open('branch')
 
538
        doppelganger = _mod_branch.Branch.open('branch')
440
539
        doppelganger.set_reference_info('file-id', 'path3', 'location3')
441
540
        self.assertEqual(('path3', 'location3'),
442
541
                         branch.get_reference_info('file-id'))
443
542
 
444
 
class TestBranchReference(TestCaseWithTransport):
 
543
class TestBranchReference(tests.TestCaseWithTransport):
445
544
    """Tests for the branch reference facility."""
446
545
 
447
546
    def test_create_open_reference(self):
448
547
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
449
 
        t = get_transport(self.get_url('.'))
 
548
        t = self.get_transport()
450
549
        t.mkdir('repo')
451
550
        dir = bzrdirformat.initialize(self.get_url('repo'))
452
551
        dir.create_repository()
453
552
        target_branch = dir.create_branch()
454
553
        t.mkdir('branch')
455
554
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
456
 
        made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
 
555
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
 
556
            branch_dir, target_branch=target_branch)
457
557
        self.assertEqual(made_branch.base, target_branch.base)
458
558
        opened_branch = branch_dir.open_branch()
459
559
        self.assertEqual(opened_branch.base, target_branch.base)
470
570
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
471
571
 
472
572
 
473
 
class TestHooks(TestCase):
 
573
class TestHooks(tests.TestCaseWithTransport):
474
574
 
475
575
    def test_constructor(self):
476
576
        """Check that creating a BranchHooks instance has the right defaults."""
477
 
        hooks = BranchHooks()
 
577
        hooks = _mod_branch.BranchHooks()
478
578
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
479
579
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
480
580
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
481
581
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
482
582
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
483
 
        self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
 
583
        self.assertTrue("post_uncommit" in hooks,
 
584
                        "post_uncommit not in %s" % hooks)
484
585
        self.assertTrue("post_change_branch_tip" in hooks,
485
586
                        "post_change_branch_tip not in %s" % hooks)
 
587
        self.assertTrue("post_branch_init" in hooks,
 
588
                        "post_branch_init not in %s" % hooks)
 
589
        self.assertTrue("post_switch" in hooks,
 
590
                        "post_switch not in %s" % hooks)
486
591
 
487
592
    def test_installed_hooks_are_BranchHooks(self):
488
593
        """The installed hooks object should be a BranchHooks."""
489
594
        # the installed hooks are saved in self._preserved_hooks.
490
595
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
491
 
            BranchHooks)
492
 
 
493
 
 
494
 
class TestPullResult(TestCase):
 
596
                              _mod_branch.BranchHooks)
 
597
 
 
598
    def test_post_branch_init_hook(self):
 
599
        calls = []
 
600
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
 
601
            calls.append, None)
 
602
        self.assertLength(0, calls)
 
603
        branch = self.make_branch('a')
 
604
        self.assertLength(1, calls)
 
605
        params = calls[0]
 
606
        self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
 
607
        self.assertTrue(hasattr(params, 'bzrdir'))
 
608
        self.assertTrue(hasattr(params, 'branch'))
 
609
 
 
610
    def test_post_branch_init_hook_repr(self):
 
611
        param_reprs = []
 
612
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
 
613
            lambda params: param_reprs.append(repr(params)), None)
 
614
        branch = self.make_branch('a')
 
615
        self.assertLength(1, param_reprs)
 
616
        param_repr = param_reprs[0]
 
617
        self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
 
618
 
 
619
    def test_post_switch_hook(self):
 
620
        from bzrlib import switch
 
621
        calls = []
 
622
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
 
623
            calls.append, None)
 
624
        tree = self.make_branch_and_tree('branch-1')
 
625
        self.build_tree(['branch-1/file-1'])
 
626
        tree.add('file-1')
 
627
        tree.commit('rev1')
 
628
        to_branch = tree.bzrdir.sprout('branch-2').open_branch()
 
629
        self.build_tree(['branch-1/file-2'])
 
630
        tree.add('file-2')
 
631
        tree.remove('file-1')
 
632
        tree.commit('rev2')
 
633
        checkout = tree.branch.create_checkout('checkout')
 
634
        self.assertLength(0, calls)
 
635
        switch.switch(checkout.bzrdir, to_branch)
 
636
        self.assertLength(1, calls)
 
637
        params = calls[0]
 
638
        self.assertIsInstance(params, _mod_branch.SwitchHookParams)
 
639
        self.assertTrue(hasattr(params, 'to_branch'))
 
640
        self.assertTrue(hasattr(params, 'revision_id'))
 
641
 
 
642
 
 
643
class TestBranchOptions(tests.TestCaseWithTransport):
 
644
 
 
645
    def setUp(self):
 
646
        super(TestBranchOptions, self).setUp()
 
647
        self.branch = self.make_branch('.')
 
648
        self.config = self.branch.get_config()
 
649
 
 
650
    def check_append_revisions_only(self, expected_value, value=None):
 
651
        """Set append_revisions_only in config and check its interpretation."""
 
652
        if value is not None:
 
653
            self.config.set_user_option('append_revisions_only', value)
 
654
        self.assertEqual(expected_value,
 
655
                         self.branch._get_append_revisions_only())
 
656
 
 
657
    def test_valid_append_revisions_only(self):
 
658
        self.assertEquals(None,
 
659
                          self.config.get_user_option('append_revisions_only'))
 
660
        self.check_append_revisions_only(None)
 
661
        self.check_append_revisions_only(False, 'False')
 
662
        self.check_append_revisions_only(True, 'True')
 
663
        # The following values will cause compatibility problems on projects
 
664
        # using older bzr versions (<2.2) but are accepted
 
665
        self.check_append_revisions_only(False, 'false')
 
666
        self.check_append_revisions_only(True, 'true')
 
667
 
 
668
    def test_invalid_append_revisions_only(self):
 
669
        """Ensure warning is noted on invalid settings"""
 
670
        self.warnings = []
 
671
        def warning(*args):
 
672
            self.warnings.append(args[0] % args[1:])
 
673
        self.overrideAttr(trace, 'warning', warning)
 
674
        self.check_append_revisions_only(None, 'not-a-bool')
 
675
        self.assertLength(1, self.warnings)
 
676
        self.assertEqual(
 
677
            'Value "not-a-bool" is not a boolean for "append_revisions_only"',
 
678
            self.warnings[0])
 
679
 
 
680
 
 
681
class TestPullResult(tests.TestCase):
495
682
 
496
683
    def test_pull_result_to_int(self):
497
684
        # to support old code, the pull result can be used as an int
498
 
        r = PullResult()
 
685
        r = _mod_branch.PullResult()
499
686
        r.old_revno = 10
500
687
        r.new_revno = 20
501
688
        # this usage of results is not recommended for new code (because it
502
689
        # doesn't describe very well what happened), but for api stability
503
690
        # it's still supported
504
 
        a = "%d revisions pulled" % r
505
 
        self.assertEqual(a, "10 revisions pulled")
506
 
 
 
691
        self.assertEqual(self.applyDeprecated(
 
692
            symbol_versioning.deprecated_in((2, 3, 0)),
 
693
            r.__int__),
 
694
            10)
 
695
 
 
696
    def test_report_changed(self):
 
697
        r = _mod_branch.PullResult()
 
698
        r.old_revid = "old-revid"
 
699
        r.old_revno = 10
 
700
        r.new_revid = "new-revid"
 
701
        r.new_revno = 20
 
702
        f = StringIO()
 
703
        r.report(f)
 
704
        self.assertEqual("Now on revision 20.\n", f.getvalue())
 
705
 
 
706
    def test_report_unchanged(self):
 
707
        r = _mod_branch.PullResult()
 
708
        r.old_revid = "same-revid"
 
709
        r.new_revid = "same-revid"
 
710
        f = StringIO()
 
711
        r.report(f)
 
712
        self.assertEqual("No revisions to pull.\n", f.getvalue())
507
713
 
508
714
 
509
715
class _StubLockable(object):
530
736
    """Helper for TestRunWithWriteLockedTarget."""
531
737
 
532
738
 
533
 
class TestRunWithWriteLockedTarget(TestCase):
 
739
class TestRunWithWriteLockedTarget(tests.TestCase):
534
740
    """Tests for _run_with_write_locked_target."""
535
741
 
536
742
    def setUp(self):
537
 
        TestCase.setUp(self)
 
743
        tests.TestCase.setUp(self)
538
744
        self._calls = []
539
745
 
540
746
    def func_that_returns_ok(self):
547
753
 
548
754
    def test_success_unlocks(self):
549
755
        lockable = _StubLockable(self._calls)
550
 
        result = _run_with_write_locked_target(
 
756
        result = _mod_branch._run_with_write_locked_target(
551
757
            lockable, self.func_that_returns_ok)
552
758
        self.assertEqual('ok', result)
553
759
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
555
761
    def test_exception_unlocks_and_propagates(self):
556
762
        lockable = _StubLockable(self._calls)
557
763
        self.assertRaises(_ErrorFromCallable,
558
 
            _run_with_write_locked_target, lockable, self.func_that_raises)
 
764
                          _mod_branch._run_with_write_locked_target,
 
765
                          lockable, self.func_that_raises)
559
766
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
560
767
 
561
768
    def test_callable_succeeds_but_error_during_unlock(self):
562
769
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
563
770
        self.assertRaises(_ErrorFromUnlock,
564
 
            _run_with_write_locked_target, lockable, self.func_that_returns_ok)
 
771
                          _mod_branch._run_with_write_locked_target,
 
772
                          lockable, self.func_that_returns_ok)
565
773
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
566
774
 
567
775
    def test_error_during_unlock_does_not_mask_original_error(self):
568
776
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
569
777
        self.assertRaises(_ErrorFromCallable,
570
 
            _run_with_write_locked_target, lockable, self.func_that_raises)
 
778
                          _mod_branch._run_with_write_locked_target,
 
779
                          lockable, self.func_that_raises)
571
780
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
572
 
 
573