~bzr-pqm/bzr/bzr.dev

5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2006-2011 Canonical Ltd
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
2
#
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
7
#
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
12
#
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
16
17
"""Tests for the Branch facility that are not interface  tests.
18
4523.1.1 by Martin Pool
Rename tests.branch_implementations to per_branch
19
For interface tests see tests/per_branch/*.py.
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
20
21
For concrete class tests see this file, and for meta-branch tests
22
also see this file.
23
"""
24
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
25
from cStringIO import StringIO
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
26
2230.3.3 by Aaron Bentley
Add more config testing
27
from bzrlib import (
28
    branch as _mod_branch,
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
29
    bzrdir,
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
30
    config,
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
31
    errors,
5348.1.2 by Martin Pool
Deprecate casting PushResult and PullResult to int to get the relative revno change
32
    symbol_versioning,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
33
    tests,
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
34
    trace,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
35
    transport,
2230.3.3 by Aaron Bentley
Add more config testing
36
    urlutils,
37
    )
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
38
3445.2.1 by John Arbash Meinel
Add tests for Branch.missing_revisions and deprecate it.
39
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
40
class TestDefaultFormat(tests.TestCase):
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
41
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
42
    def test_default_format(self):
43
        # update this if you change the default branch format
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
44
        self.assertIsInstance(_mod_branch.BranchFormat.get_default_format(),
45
                _mod_branch.BzrBranchFormat7)
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
46
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
47
    def test_default_format_is_same_as_bzrdir_default(self):
48
        # XXX: it might be nice if there was only one place the default was
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
49
        # set, but at the moment that's not true -- mbp 20070814 --
2696.3.8 by Martin Pool
doc
50
        # https://bugs.launchpad.net/bzr/+bug/132376
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
51
        self.assertEqual(
52
            _mod_branch.BranchFormat.get_default_format(),
53
            bzrdir.BzrDirFormat.get_default_format().get_branch_format())
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
54
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
55
    def test_get_set_default_format(self):
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
56
        # set the format and then set it back again
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
57
        old_format = _mod_branch.BranchFormat.get_default_format()
58
        _mod_branch.BranchFormat.set_default_format(SampleBranchFormat())
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
59
        try:
60
            # the default branch format is used by the meta dir format
61
            # which is not the default bzrdir format at this point
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
62
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
63
            result = dir.create_branch()
64
            self.assertEqual(result, 'A branch')
65
        finally:
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
66
            _mod_branch.BranchFormat.set_default_format(old_format)
67
        self.assertEqual(old_format,
68
                         _mod_branch.BranchFormat.get_default_format())
1508.1.25 by Robert Collins
Update per review comments.
69
70
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
71
class TestBranchFormat5(tests.TestCaseWithTransport):
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
72
    """Tests specific to branch format 5"""
73
74
    def test_branch_format_5_uses_lockdir(self):
75
        url = self.get_url()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
76
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
77
        bdir.create_repository()
78
        branch = bdir.create_branch()
1553.5.72 by Martin Pool
Clean up test for Branch5 lockdirs
79
        t = self.get_transport()
80
        self.log("branch instance is %r" % branch)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
81
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
1553.5.72 by Martin Pool
Clean up test for Branch5 lockdirs
82
        self.assertIsDirectory('.', t)
83
        self.assertIsDirectory('.bzr/branch', t)
84
        self.assertIsDirectory('.bzr/branch/lock', t)
1553.5.73 by Martin Pool
Additional test that Branch5 uses lockdir properly
85
        branch.lock_write()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
86
        self.addCleanup(branch.unlock)
87
        self.assertIsDirectory('.bzr/branch/lock/held', t)
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
88
2230.3.3 by Aaron Bentley
Add more config testing
89
    def test_set_push_location(self):
5345.1.26 by Vincent Ladeuil
Merge lockable-config-files into remove-gratuitous-ensure-config-dir-exist-calls resolving conflicts
90
        conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
2839.3.1 by Alexander Belchenko
provide non-empty locations.conf for test_branch.TestBranchFormat5.test_set_push_location
91
2230.3.3 by Aaron Bentley
Add more config testing
92
        branch = self.make_branch('.', format='knit')
93
        branch.set_push_location('foo')
94
        local_path = urlutils.local_path_from_url(branch.base[:-1])
2839.3.1 by Alexander Belchenko
provide non-empty locations.conf for test_branch.TestBranchFormat5.test_set_push_location
95
        self.assertFileEqual("# comment\n"
96
                             "[%s]\n"
2230.3.3 by Aaron Bentley
Add more config testing
97
                             "push_location = foo\n"
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
98
                             "push_location:policy = norecurse\n" % local_path,
5345.1.11 by Vincent Ladeuil
Cleanup bt.test_branch.
99
                             config.locations_config_filename())
2230.3.3 by Aaron Bentley
Add more config testing
100
2230.3.12 by Aaron Bentley
Clean up trailing whitespace
101
    # TODO RBC 20051029 test getting a push location from a branch in a
2230.3.3 by Aaron Bentley
Add more config testing
102
    # recursive section - that is, it appends the branch name.
103
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
104
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
105
class SampleBranchFormat(_mod_branch.BranchFormat):
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
106
    """A sample format
107
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
108
    this format is initializable, unsupported to aid in testing the
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
109
    open and open_downlevel routines.
110
    """
111
112
    def get_format_string(self):
113
        """See BzrBranchFormat.get_format_string()."""
114
        return "Sample branch format."
115
5535.3.19 by Andrew Bennetts
Fix a test failure.
116
    def initialize(self, a_bzrdir, name=None, repository=None):
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
117
        """Format 4 branches cannot be created."""
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
118
        t = a_bzrdir.get_branch_transport(self, name=name)
1955.3.9 by John Arbash Meinel
Find more occurrances of put() and replace with put_file or put_bytes
119
        t.put_bytes('format', self.get_format_string())
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
120
        return 'A branch'
121
122
    def is_supported(self):
123
        return False
124
5051.3.16 by Jelmer Vernooij
Fix tests - missing argument.
125
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
126
        return "opened branch."
127
128
5305.1.2 by Robert Collins
More clarity about how to use the lazy registration feature.
129
# Demonstrating how lazy loading is often implemented:
130
# A constant string is created.
131
SampleSupportedBranchFormatString = "Sample supported branch format."
132
133
# And the format class can then reference the constant to avoid skew.
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
134
class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
135
    """A sample supported format."""
136
137
    def get_format_string(self):
138
        """See BzrBranchFormat.get_format_string()."""
5305.1.2 by Robert Collins
More clarity about how to use the lazy registration feature.
139
        return SampleSupportedBranchFormatString
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
140
141
    def initialize(self, a_bzrdir, name=None):
142
        t = a_bzrdir.get_branch_transport(self, name=name)
143
        t.put_bytes('format', self.get_format_string())
144
        return 'A branch'
145
146
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
147
        return "opened supported branch."
148
149
5642.2.1 by Jelmer Vernooij
Allow the registration of non-metadir branch formats.
150
class SampleExtraBranchFormat(_mod_branch.BranchFormat):
151
    """A sample format that is not usable in a metadir."""
152
153
    def get_format_string(self):
154
        # This format is not usable in a metadir.
155
        return None
156
157
    def network_name(self):
158
        # Network name always has to be provided.
159
        return "extra"
160
161
    def initialize(self, a_bzrdir, name=None):
162
        raise NotImplementedError(self.initialize)
163
164
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
165
        raise NotImplementedError(self.open)
166
167
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
168
class TestBzrBranchFormat(tests.TestCaseWithTransport):
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
169
    """Tests for the BzrBranchFormat facility."""
170
171
    def test_find_format(self):
172
        # is the right format object found for a branch?
173
        # create a branch with a few known format objects.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
174
        # this is not quite the same as
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
175
        self.build_tree(["foo/", "bar/"])
176
        def check_format(format, url):
177
            dir = format._matchingbzrdir.initialize(url)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
178
            dir.create_repository()
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
179
            format.initialize(dir)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
180
            found_format = _mod_branch.BranchFormat.find_format(dir)
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
181
            self.failUnless(isinstance(found_format, format.__class__))
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
182
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
183
5642.2.1 by Jelmer Vernooij
Allow the registration of non-metadir branch formats.
184
    def test_extra_format(self):
185
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
186
        SampleSupportedBranchFormat().initialize(dir)
187
        format = SampleExtraBranchFormat()
188
        _mod_branch.BranchFormat.register_extra_format(format)
189
        self.addCleanup(_mod_branch.BranchFormat.unregister_extra_format,
190
            format)
191
        self.assertTrue(format in _mod_branch.BranchFormat.get_formats())
192
        self.assertEquals(format,
193
            _mod_branch.network_format_registry.get("extra"))
194
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
195
    def test_find_format_factory(self):
196
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
197
        SampleSupportedBranchFormat().initialize(dir)
198
        factory = _mod_branch.MetaDirBranchFormatFactory(
5305.1.2 by Robert Collins
More clarity about how to use the lazy registration feature.
199
            SampleSupportedBranchFormatString,
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
200
            "bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
201
        _mod_branch.BranchFormat.register_format(factory)
202
        self.addCleanup(_mod_branch.BranchFormat.unregister_format, factory)
203
        b = _mod_branch.Branch.open(self.get_url())
204
        self.assertEqual(b, "opened supported branch.")
205
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
206
    def test_find_format_not_branch(self):
207
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
208
        self.assertRaises(errors.NotBranchError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
209
                          _mod_branch.BranchFormat.find_format,
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
210
                          dir)
211
212
    def test_find_format_unknown_format(self):
213
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
214
        SampleBranchFormat().initialize(dir)
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
215
        self.assertRaises(errors.UnknownFormatError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
216
                          _mod_branch.BranchFormat.find_format,
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
217
                          dir)
218
219
    def test_register_unregister_format(self):
220
        format = SampleBranchFormat()
221
        # make a control dir
222
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
223
        # make a branch
224
        format.initialize(dir)
225
        # register a format for it.
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
226
        _mod_branch.BranchFormat.register_format(format)
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
227
        # which branch.Open will refuse (not supported)
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
228
        self.assertRaises(errors.UnsupportedFormatError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
229
                          _mod_branch.Branch.open, self.get_url())
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
230
        self.make_branch_and_tree('foo')
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
231
        # but open_downlevel will work
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
232
        self.assertEqual(
233
            format.open(dir),
234
            bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
235
        # unregister the format
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
236
        _mod_branch.BranchFormat.unregister_format(format)
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
237
        self.make_branch_and_tree('bar')
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
238
239
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
240
#Used by TestMetaDirBranchFormatFactory 
241
FakeLazyFormat = None
242
243
244
class TestMetaDirBranchFormatFactory(tests.TestCase):
245
246
    def test_get_format_string_does_not_load(self):
247
        """Formats have a static format string."""
248
        factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
249
        self.assertEqual("yo", factory.get_format_string())
250
251
    def test_call_loads(self):
252
        # __call__ is used by the network_format_registry interface to get a
253
        # Format.
254
        global FakeLazyFormat
255
        del FakeLazyFormat
256
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
257
            "bzrlib.tests.test_branch", "FakeLazyFormat")
258
        self.assertRaises(AttributeError, factory)
259
260
    def test_call_returns_call_of_referenced_object(self):
261
        global FakeLazyFormat
262
        FakeLazyFormat = lambda:'called'
263
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
264
            "bzrlib.tests.test_branch", "FakeLazyFormat")
265
        self.assertEqual('called', factory())
266
267
3221.11.2 by Robert Collins
Create basic stackable branch facility.
268
class TestBranch67(object):
269
    """Common tests for both branch 6 and 7 which are mostly the same."""
270
271
    def get_format_name(self):
272
        raise NotImplementedError(self.get_format_name)
273
274
    def get_format_name_subtree(self):
275
        raise NotImplementedError(self.get_format_name)
276
277
    def get_class(self):
278
        raise NotImplementedError(self.get_class)
2230.3.1 by Aaron Bentley
Get branch6 creation working
279
280
    def test_creation(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
281
        format = bzrdir.BzrDirMetaFormat1()
2230.3.55 by Aaron Bentley
Updates from review
282
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
2230.3.1 by Aaron Bentley
Get branch6 creation working
283
        branch = self.make_branch('a', format=format)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
284
        self.assertIsInstance(branch, self.get_class())
285
        branch = self.make_branch('b', format=self.get_format_name())
286
        self.assertIsInstance(branch, self.get_class())
2230.3.1 by Aaron Bentley
Get branch6 creation working
287
        branch = _mod_branch.Branch.open('a')
3221.11.2 by Robert Collins
Create basic stackable branch facility.
288
        self.assertIsInstance(branch, self.get_class())
2230.3.1 by Aaron Bentley
Get branch6 creation working
289
290
    def test_layout(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
291
        branch = self.make_branch('a', format=self.get_format_name())
2230.3.1 by Aaron Bentley
Get branch6 creation working
292
        self.failUnlessExists('a/.bzr/branch/last-revision')
293
        self.failIfExists('a/.bzr/branch/revision-history')
4273.1.12 by Aaron Bentley
Don't create reference files for older formats.
294
        self.failIfExists('a/.bzr/branch/references')
2230.3.1 by Aaron Bentley
Get branch6 creation working
295
2230.3.3 by Aaron Bentley
Add more config testing
296
    def test_config(self):
297
        """Ensure that all configuration data is stored in the branch"""
3221.11.2 by Robert Collins
Create basic stackable branch facility.
298
        branch = self.make_branch('a', format=self.get_format_name())
5560.2.1 by Vincent Ladeuil
Fix the remaining references to http://bazaar-vcs.org (except the explicitly historical ones).
299
        branch.set_parent('http://example.com')
2230.3.3 by Aaron Bentley
Add more config testing
300
        self.failIfExists('a/.bzr/branch/parent')
5560.2.1 by Vincent Ladeuil
Fix the remaining references to http://bazaar-vcs.org (except the explicitly historical ones).
301
        self.assertEqual('http://example.com', branch.get_parent())
302
        branch.set_push_location('sftp://example.com')
2230.3.3 by Aaron Bentley
Add more config testing
303
        config = branch.get_config()._get_branch_data_config()
5560.2.1 by Vincent Ladeuil
Fix the remaining references to http://bazaar-vcs.org (except the explicitly historical ones).
304
        self.assertEqual('sftp://example.com',
2230.3.3 by Aaron Bentley
Add more config testing
305
                         config.get_user_option('push_location'))
5560.2.1 by Vincent Ladeuil
Fix the remaining references to http://bazaar-vcs.org (except the explicitly historical ones).
306
        branch.set_bound_location('ftp://example.com')
2230.3.3 by Aaron Bentley
Add more config testing
307
        self.failIfExists('a/.bzr/branch/bound')
5560.2.1 by Vincent Ladeuil
Fix the remaining references to http://bazaar-vcs.org (except the explicitly historical ones).
308
        self.assertEqual('ftp://example.com', branch.get_bound_location())
2230.3.3 by Aaron Bentley
Add more config testing
309
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
310
    def test_set_revision_history(self):
3567.4.16 by John Arbash Meinel
Use the new BranchBuilder api in a Branch test
311
        builder = self.make_branch_builder('.', format=self.get_format_name())
312
        builder.build_snapshot('foo', None,
313
            [('add', ('', None, 'directory', None))],
314
            message='foo')
315
        builder.build_snapshot('bar', None, [], message='bar')
316
        branch = builder.get_branch()
317
        branch.lock_write()
318
        self.addCleanup(branch.unlock)
319
        branch.set_revision_history(['foo', 'bar'])
320
        branch.set_revision_history(['foo'])
321
        self.assertRaises(errors.NotLefthandHistory,
322
                          branch.set_revision_history, ['bar'])
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
323
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
324
    def do_checkout_test(self, lightweight=False):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
325
        tree = self.make_branch_and_tree('source',
326
            format=self.get_format_name_subtree())
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
327
        subtree = self.make_branch_and_tree('source/subtree',
3221.11.2 by Robert Collins
Create basic stackable branch facility.
328
            format=self.get_format_name_subtree())
2100.3.25 by Aaron Bentley
add subsubtree to test
329
        subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
3221.11.2 by Robert Collins
Create basic stackable branch facility.
330
            format=self.get_format_name_subtree())
2100.3.25 by Aaron Bentley
add subsubtree to test
331
        self.build_tree(['source/subtree/file',
332
                         'source/subtree/subsubtree/file'])
333
        subsubtree.add('file')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
334
        subtree.add('file')
2100.3.25 by Aaron Bentley
add subsubtree to test
335
        subtree.add_reference(subsubtree)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
336
        tree.add_reference(subtree)
337
        tree.commit('a revision')
2100.3.23 by Aaron Bentley
Nested checkouts kinda work
338
        subtree.commit('a subtree file')
2100.3.25 by Aaron Bentley
add subsubtree to test
339
        subsubtree.commit('a subsubtree file')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
340
        tree.branch.create_checkout('target', lightweight=lightweight)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
341
        self.failUnlessExists('target')
342
        self.failUnlessExists('target/subtree')
343
        self.failUnlessExists('target/subtree/file')
2100.3.25 by Aaron Bentley
add subsubtree to test
344
        self.failUnlessExists('target/subtree/subsubtree/file')
2100.3.31 by Aaron Bentley
Merged bzr.dev (17 tests failing)
345
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
346
        if lightweight:
347
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
348
        else:
349
            self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
350
351
    def test_checkout_with_references(self):
352
        self.do_checkout_test()
353
354
    def test_light_checkout_with_references(self):
355
        self.do_checkout_test(lightweight=True)
2230.3.51 by Aaron Bentley
Store revno for Branch6, set_last_revision -> set_last_revision_info
356
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
357
    def test_set_push(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
358
        branch = self.make_branch('source', format=self.get_format_name())
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
359
        branch.get_config().set_user_option('push_location', 'old',
360
            store=config.STORE_LOCATION)
361
        warnings = []
362
        def warning(*args):
363
            warnings.append(args[0] % args[1:])
364
        _warning = trace.warning
365
        trace.warning = warning
366
        try:
367
            branch.set_push_location('new')
368
        finally:
369
            trace.warning = _warning
370
        self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
371
                         'locations.conf')
372
3445.2.1 by John Arbash Meinel
Add tests for Branch.missing_revisions and deprecate it.
373
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
374
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
375
376
    def get_class(self):
377
        return _mod_branch.BzrBranch6
378
379
    def get_format_name(self):
380
        return "dirstate-tags"
381
382
    def get_format_name_subtree(self):
383
        return "dirstate-with-subtree"
384
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
385
    def test_set_stacked_on_url_errors(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
386
        branch = self.make_branch('a', format=self.get_format_name())
387
        self.assertRaises(errors.UnstackableBranchFormat,
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
388
            branch.set_stacked_on_url, None)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
389
390
    def test_default_stacked_location(self):
391
        branch = self.make_branch('a', format=self.get_format_name())
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
392
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
393
394
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
395
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
396
397
    def get_class(self):
398
        return _mod_branch.BzrBranch7
399
400
    def get_format_name(self):
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
401
        return "1.9"
3221.11.2 by Robert Collins
Create basic stackable branch facility.
402
403
    def get_format_name_subtree(self):
404
        return "development-subtree"
405
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
406
    def test_set_stacked_on_url_unstackable_repo(self):
3221.11.6 by Robert Collins
Stackable branch fixes.
407
        repo = self.make_repository('a', format='dirstate-tags')
408
        control = repo.bzrdir
409
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
410
        target = self.make_branch('b')
411
        self.assertRaises(errors.UnstackableRepositoryFormat,
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
412
            branch.set_stacked_on_url, target.base)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
413
3242.3.21 by Jonathan Lange
Preserve stacking in clone
414
    def test_clone_stacked_on_unstackable_repo(self):
415
        repo = self.make_repository('a', format='dirstate-tags')
416
        control = repo.bzrdir
417
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
418
        # Calling clone should not raise UnstackableRepositoryFormat.
419
        cloned_bzrdir = control.clone('cloned')
420
3221.11.2 by Robert Collins
Create basic stackable branch facility.
421
    def _test_default_stacked_location(self):
422
        branch = self.make_branch('a', format=self.get_format_name())
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
423
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
424
3221.11.8 by Robert Collins
Minimally test stacking and unstacking a repository.
425
    def test_stack_and_unstack(self):
426
        branch = self.make_branch('a', format=self.get_format_name())
3221.11.10 by Robert Collins
Extend set_stacked_on to update the repository with the right external references.
427
        target = self.make_branch_and_tree('b', format=self.get_format_name())
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
428
        branch.set_stacked_on_url(target.branch.base)
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
429
        self.assertEqual(target.branch.base, branch.get_stacked_on_url())
3221.11.10 by Robert Collins
Extend set_stacked_on to update the repository with the right external references.
430
        revid = target.commit('foo')
431
        self.assertTrue(branch.repository.has_revision(revid))
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
432
        branch.set_stacked_on_url(None)
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
433
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
3221.11.10 by Robert Collins
Extend set_stacked_on to update the repository with the right external references.
434
        self.assertFalse(branch.repository.has_revision(revid))
3221.11.8 by Robert Collins
Minimally test stacking and unstacking a repository.
435
3221.11.11 by Robert Collins
Ensure opening a stacked branch gives a ready to use repository.
436
    def test_open_opens_stacked_reference(self):
437
        branch = self.make_branch('a', format=self.get_format_name())
438
        target = self.make_branch_and_tree('b', format=self.get_format_name())
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
439
        branch.set_stacked_on_url(target.branch.base)
3221.11.11 by Robert Collins
Ensure opening a stacked branch gives a ready to use repository.
440
        branch = branch.bzrdir.open_branch()
441
        revid = target.commit('foo')
442
        self.assertTrue(branch.repository.has_revision(revid))
443
3221.11.2 by Robert Collins
Create basic stackable branch facility.
444
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
445
class BzrBranch8(tests.TestCaseWithTransport):
4273.1.15 by Aaron Bentley
Add reference_info caching.
446
447
    def make_branch(self, location, format=None):
448
        if format is None:
449
            format = bzrdir.format_registry.make_bzrdir('1.9')
450
            format.set_branch_format(_mod_branch.BzrBranchFormat8())
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
451
        return tests.TestCaseWithTransport.make_branch(
452
            self, location, format=format)
4273.1.15 by Aaron Bentley
Add reference_info caching.
453
454
    def create_branch_with_reference(self):
455
        branch = self.make_branch('branch')
456
        branch._set_all_reference_info({'file-id': ('path', 'location')})
457
        return branch
458
459
    @staticmethod
460
    def instrument_branch(branch, gets):
461
        old_get = branch._transport.get
462
        def get(*args, **kwargs):
463
            gets.append((args, kwargs))
464
            return old_get(*args, **kwargs)
465
        branch._transport.get = get
466
467
    def test_reference_info_caching_read_locked(self):
468
        gets = []
469
        branch = self.create_branch_with_reference()
470
        branch.lock_read()
471
        self.addCleanup(branch.unlock)
472
        self.instrument_branch(branch, gets)
473
        branch.get_reference_info('file-id')
474
        branch.get_reference_info('file-id')
475
        self.assertEqual(1, len(gets))
476
477
    def test_reference_info_caching_read_unlocked(self):
478
        gets = []
479
        branch = self.create_branch_with_reference()
480
        self.instrument_branch(branch, gets)
481
        branch.get_reference_info('file-id')
482
        branch.get_reference_info('file-id')
483
        self.assertEqual(2, len(gets))
484
485
    def test_reference_info_caching_write_locked(self):
486
        gets = []
487
        branch = self.make_branch('branch')
488
        branch.lock_write()
489
        self.instrument_branch(branch, gets)
490
        self.addCleanup(branch.unlock)
491
        branch._set_all_reference_info({'file-id': ('path2', 'location2')})
492
        path, location = branch.get_reference_info('file-id')
493
        self.assertEqual(0, len(gets))
494
        self.assertEqual('path2', path)
495
        self.assertEqual('location2', location)
496
497
    def test_reference_info_caches_cleared(self):
498
        branch = self.make_branch('branch')
499
        branch.lock_write()
500
        branch.set_reference_info('file-id', 'path2', 'location2')
501
        branch.unlock()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
502
        doppelganger = _mod_branch.Branch.open('branch')
4273.1.15 by Aaron Bentley
Add reference_info caching.
503
        doppelganger.set_reference_info('file-id', 'path3', 'location3')
504
        self.assertEqual(('path3', 'location3'),
505
                         branch.get_reference_info('file-id'))
506
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
507
class TestBranchReference(tests.TestCaseWithTransport):
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
508
    """Tests for the branch reference facility."""
509
510
    def test_create_open_reference(self):
511
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
5609.9.4 by Vincent Ladeuil
Use self.get_transport instead of transport.get_transport where possible.
512
        t = self.get_transport()
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
513
        t.mkdir('repo')
514
        dir = bzrdirformat.initialize(self.get_url('repo'))
515
        dir.create_repository()
516
        target_branch = dir.create_branch()
517
        t.mkdir('branch')
518
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
519
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
520
            branch_dir, target_branch=target_branch)
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
521
        self.assertEqual(made_branch.base, target_branch.base)
522
        opened_branch = branch_dir.open_branch()
523
        self.assertEqual(opened_branch.base, target_branch.base)
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
524
525
    def test_get_reference(self):
526
        """For a BranchReference, get_reference should reutrn the location."""
527
        branch = self.make_branch('target')
528
        checkout = branch.create_checkout('checkout', lightweight=True)
529
        reference_url = branch.bzrdir.root_transport.abspath('') + '/'
530
        # if the api for create_checkout changes to return different checkout types
531
        # then this file read will fail.
532
        self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
533
        self.assertEqual(reference_url,
2018.5.97 by Andrew Bennetts
Fix more tests.
534
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
2018.5.45 by Andrew Bennetts
Merge from bzr.dev
535
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
536
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
537
class TestHooks(tests.TestCaseWithTransport):
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
538
2245.1.2 by Robert Collins
Remove the static DefaultHooks method from Branch, replacing it with a derived dict BranchHooks object, which is easier to use and provides a place to put the policy-checking add method discussed on list.
539
    def test_constructor(self):
540
        """Check that creating a BranchHooks instance has the right defaults."""
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
541
        hooks = _mod_branch.BranchHooks()
2245.1.2 by Robert Collins
Remove the static DefaultHooks method from Branch, replacing it with a derived dict BranchHooks object, which is easier to use and provides a place to put the policy-checking add method discussed on list.
542
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
543
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
544
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
545
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
546
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
547
        self.assertTrue("post_uncommit" in hooks,
548
                        "post_uncommit not in %s" % hooks)
3331.1.4 by James Henstridge
Adjust my tests to pass with Ian's API.
549
        self.assertTrue("post_change_branch_tip" in hooks,
550
                        "post_change_branch_tip not in %s" % hooks)
5107.3.2 by Marco Pantaleoni
Renamed 'post_branch' hook to 'post_branch_init', for more consistency,
551
        self.assertTrue("post_branch_init" in hooks,
552
                        "post_branch_init not in %s" % hooks)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
553
        self.assertTrue("post_switch" in hooks,
554
                        "post_switch not in %s" % hooks)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
555
2245.1.2 by Robert Collins
Remove the static DefaultHooks method from Branch, replacing it with a derived dict BranchHooks object, which is easier to use and provides a place to put the policy-checking add method discussed on list.
556
    def test_installed_hooks_are_BranchHooks(self):
557
        """The installed hooks object should be a BranchHooks."""
558
        # the installed hooks are saved in self._preserved_hooks.
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
559
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
560
                              _mod_branch.BranchHooks)
2245.1.3 by Robert Collins
Add install_hook to the BranchHooks class as the official means for installing a hook.
561
5107.3.2 by Marco Pantaleoni
Renamed 'post_branch' hook to 'post_branch_init', for more consistency,
562
    def test_post_branch_init_hook(self):
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
563
        calls = []
5107.3.4 by Marco Pantaleoni
Applied suggestions from merge reviewer (John A Meinel):
564
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
565
            calls.append, None)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
566
        self.assertLength(0, calls)
567
        branch = self.make_branch('a')
568
        self.assertLength(1, calls)
569
        params = calls[0]
5107.3.2 by Marco Pantaleoni
Renamed 'post_branch' hook to 'post_branch_init', for more consistency,
570
        self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
571
        self.assertTrue(hasattr(params, 'bzrdir'))
572
        self.assertTrue(hasattr(params, 'branch'))
573
5050.21.1 by Andrew Bennetts
Remove broken and apparently unused code path from BranchInitHookParams.__repr__.
574
    def test_post_branch_init_hook_repr(self):
575
        param_reprs = []
576
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
577
            lambda params: param_reprs.append(repr(params)), None)
578
        branch = self.make_branch('a')
579
        self.assertLength(1, param_reprs)
580
        param_repr = param_reprs[0]
581
        self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
582
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
583
    def test_post_switch_hook(self):
584
        from bzrlib import switch
585
        calls = []
5107.3.4 by Marco Pantaleoni
Applied suggestions from merge reviewer (John A Meinel):
586
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
587
            calls.append, None)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
588
        tree = self.make_branch_and_tree('branch-1')
589
        self.build_tree(['branch-1/file-1'])
590
        tree.add('file-1')
591
        tree.commit('rev1')
592
        to_branch = tree.bzrdir.sprout('branch-2').open_branch()
593
        self.build_tree(['branch-1/file-2'])
594
        tree.add('file-2')
595
        tree.remove('file-1')
596
        tree.commit('rev2')
597
        checkout = tree.branch.create_checkout('checkout')
598
        self.assertLength(0, calls)
599
        switch.switch(checkout.bzrdir, to_branch)
600
        self.assertLength(1, calls)
601
        params = calls[0]
602
        self.assertIsInstance(params, _mod_branch.SwitchHookParams)
603
        self.assertTrue(hasattr(params, 'to_branch'))
604
        self.assertTrue(hasattr(params, 'revision_id'))
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
605
5176.1.1 by Vincent Ladeuil
Warn if a config variable can't be interpreted as a boolean
606
607
class TestBranchOptions(tests.TestCaseWithTransport):
4989.2.1 by Brian de Alwis
The 'append_revisions_only' option is now case-insensitive,
608
4989.2.5 by Vincent Ladeuil
Clarify tests.
609
    def setUp(self):
610
        super(TestBranchOptions, self).setUp()
611
        self.branch = self.make_branch('.')
612
        self.config = self.branch.get_config()
613
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
614
    def check_append_revisions_only(self, expected_value, value=None):
615
        """Set append_revisions_only in config and check its interpretation."""
4989.2.5 by Vincent Ladeuil
Clarify tests.
616
        if value is not None:
617
            self.config.set_user_option('append_revisions_only', value)
618
        self.assertEqual(expected_value,
619
                         self.branch._get_append_revisions_only())
620
621
    def test_valid_append_revisions_only(self):
622
        self.assertEquals(None,
623
                          self.config.get_user_option('append_revisions_only'))
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
624
        self.check_append_revisions_only(None)
625
        self.check_append_revisions_only(False, 'False')
626
        self.check_append_revisions_only(True, 'True')
4989.2.13 by Vincent Ladeuil
append_revisions_only accept all valid booleans, update doc to
627
        # The following values will cause compatibility problems on projects
628
        # using older bzr versions (<2.2) but are accepted
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
629
        self.check_append_revisions_only(False, 'false')
630
        self.check_append_revisions_only(True, 'true')
4989.2.5 by Vincent Ladeuil
Clarify tests.
631
632
    def test_invalid_append_revisions_only(self):
4989.2.9 by Brian de Alwis
Revert append_revisions_only to only allow 'True' and 'False' to
633
        """Ensure warning is noted on invalid settings"""
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
634
        self.warnings = []
635
        def warning(*args):
636
            self.warnings.append(args[0] % args[1:])
637
        self.overrideAttr(trace, 'warning', warning)
638
        self.check_append_revisions_only(None, 'not-a-bool')
639
        self.assertLength(1, self.warnings)
640
        self.assertEqual(
641
            'Value "not-a-bool" is not a boolean for "append_revisions_only"',
642
            self.warnings[0])
4989.2.5 by Vincent Ladeuil
Clarify tests.
643
4989.2.1 by Brian de Alwis
The 'append_revisions_only' option is now case-insensitive,
644
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
645
class TestPullResult(tests.TestCase):
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
646
647
    def test_pull_result_to_int(self):
648
        # to support old code, the pull result can be used as an int
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
649
        r = _mod_branch.PullResult()
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
650
        r.old_revno = 10
651
        r.new_revno = 20
652
        # this usage of results is not recommended for new code (because it
653
        # doesn't describe very well what happened), but for api stability
654
        # it's still supported
5348.1.2 by Martin Pool
Deprecate casting PushResult and PullResult to int to get the relative revno change
655
        self.assertEqual(self.applyDeprecated(
656
            symbol_versioning.deprecated_in((2, 3, 0)),
657
            r.__int__),
658
            10)
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
659
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
660
    def test_report_changed(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
661
        r = _mod_branch.PullResult()
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
662
        r.old_revid = "old-revid"
663
        r.old_revno = 10
664
        r.new_revid = "new-revid"
665
        r.new_revno = 20
666
        f = StringIO()
667
        r.report(f)
668
        self.assertEqual("Now on revision 20.\n", f.getvalue())
669
670
    def test_report_unchanged(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
671
        r = _mod_branch.PullResult()
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
672
        r.old_revid = "same-revid"
673
        r.new_revid = "same-revid"
674
        f = StringIO()
675
        r.report(f)
676
        self.assertEqual("No revisions to pull.\n", f.getvalue())
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
677
678
679
class _StubLockable(object):
680
    """Helper for TestRunWithWriteLockedTarget."""
681
682
    def __init__(self, calls, unlock_exc=None):
683
        self.calls = calls
684
        self.unlock_exc = unlock_exc
685
686
    def lock_write(self):
687
        self.calls.append('lock_write')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
688
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
689
    def unlock(self):
690
        self.calls.append('unlock')
691
        if self.unlock_exc is not None:
692
            raise self.unlock_exc
693
694
695
class _ErrorFromCallable(Exception):
696
    """Helper for TestRunWithWriteLockedTarget."""
697
698
699
class _ErrorFromUnlock(Exception):
700
    """Helper for TestRunWithWriteLockedTarget."""
701
702
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
703
class TestRunWithWriteLockedTarget(tests.TestCase):
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
704
    """Tests for _run_with_write_locked_target."""
705
706
    def setUp(self):
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
707
        tests.TestCase.setUp(self)
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
708
        self._calls = []
709
710
    def func_that_returns_ok(self):
711
        self._calls.append('func called')
712
        return 'ok'
713
714
    def func_that_raises(self):
715
        self._calls.append('func called')
716
        raise _ErrorFromCallable()
717
718
    def test_success_unlocks(self):
719
        lockable = _StubLockable(self._calls)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
720
        result = _mod_branch._run_with_write_locked_target(
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
721
            lockable, self.func_that_returns_ok)
722
        self.assertEqual('ok', result)
723
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
724
725
    def test_exception_unlocks_and_propagates(self):
726
        lockable = _StubLockable(self._calls)
727
        self.assertRaises(_ErrorFromCallable,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
728
                          _mod_branch._run_with_write_locked_target,
729
                          lockable, self.func_that_raises)
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
730
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
731
732
    def test_callable_succeeds_but_error_during_unlock(self):
733
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
734
        self.assertRaises(_ErrorFromUnlock,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
735
                          _mod_branch._run_with_write_locked_target,
736
                          lockable, self.func_that_returns_ok)
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
737
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
738
739
    def test_error_during_unlock_does_not_mask_original_error(self):
740
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
741
        self.assertRaises(_ErrorFromCallable,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
742
                          _mod_branch._run_with_write_locked_target,
743
                          lockable, self.func_that_raises)
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
744
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
745
746