~bzr-pqm/bzr/bzr.dev

4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2006-2010 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,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
32
    tests,
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
33
    trace,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
34
    transport,
2230.3.3 by Aaron Bentley
Add more config testing
35
    urlutils,
36
    )
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
37
3445.2.1 by John Arbash Meinel
Add tests for Branch.missing_revisions and deprecate it.
38
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
39
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.
40
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
41
    def test_default_format(self):
42
        # update this if you change the default branch format
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
43
        self.assertIsInstance(_mod_branch.BranchFormat.get_default_format(),
44
                _mod_branch.BzrBranchFormat7)
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
45
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
46
    def test_default_format_is_same_as_bzrdir_default(self):
47
        # 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
48
        # set, but at the moment that's not true -- mbp 20070814 --
2696.3.8 by Martin Pool
doc
49
        # https://bugs.launchpad.net/bzr/+bug/132376
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
50
        self.assertEqual(
51
            _mod_branch.BranchFormat.get_default_format(),
52
            bzrdir.BzrDirFormat.get_default_format().get_branch_format())
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
53
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
54
    def test_get_set_default_format(self):
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
55
        # set the format and then set it back again
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
56
        old_format = _mod_branch.BranchFormat.get_default_format()
57
        _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.
58
        try:
59
            # the default branch format is used by the meta dir format
60
            # which is not the default bzrdir format at this point
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
61
            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.
62
            result = dir.create_branch()
63
            self.assertEqual(result, 'A branch')
64
        finally:
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
65
            _mod_branch.BranchFormat.set_default_format(old_format)
66
        self.assertEqual(old_format,
67
                         _mod_branch.BranchFormat.get_default_format())
1508.1.25 by Robert Collins
Update per review comments.
68
69
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
70
class TestBranchFormat5(tests.TestCaseWithTransport):
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
71
    """Tests specific to branch format 5"""
72
73
    def test_branch_format_5_uses_lockdir(self):
74
        url = self.get_url()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
75
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
76
        bdir.create_repository()
77
        branch = bdir.create_branch()
1553.5.72 by Martin Pool
Clean up test for Branch5 lockdirs
78
        t = self.get_transport()
79
        self.log("branch instance is %r" % branch)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
80
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
1553.5.72 by Martin Pool
Clean up test for Branch5 lockdirs
81
        self.assertIsDirectory('.', t)
82
        self.assertIsDirectory('.bzr/branch', t)
83
        self.assertIsDirectory('.bzr/branch/lock', t)
1553.5.73 by Martin Pool
Additional test that Branch5 uses lockdir properly
84
        branch.lock_write()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
85
        self.addCleanup(branch.unlock)
86
        self.assertIsDirectory('.bzr/branch/lock/held', t)
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
87
2230.3.3 by Aaron Bentley
Add more config testing
88
    def test_set_push_location(self):
89
        from bzrlib.config import (locations_config_filename,
90
                                   ensure_config_dir_exists)
91
        ensure_config_dir_exists()
92
        fn = locations_config_filename()
2839.3.1 by Alexander Belchenko
provide non-empty locations.conf for test_branch.TestBranchFormat5.test_set_push_location
93
        # write correct newlines to locations.conf
94
        # by default ConfigObj uses native line-endings for new files
95
        # but uses already existing line-endings if file is not empty
96
        f = open(fn, 'wb')
97
        try:
98
            f.write('# comment\n')
99
        finally:
100
            f.close()
101
2230.3.3 by Aaron Bentley
Add more config testing
102
        branch = self.make_branch('.', format='knit')
103
        branch.set_push_location('foo')
104
        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
105
        self.assertFileEqual("# comment\n"
106
                             "[%s]\n"
2230.3.3 by Aaron Bentley
Add more config testing
107
                             "push_location = foo\n"
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
108
                             "push_location:policy = norecurse\n" % local_path,
2230.3.3 by Aaron Bentley
Add more config testing
109
                             fn)
110
2230.3.12 by Aaron Bentley
Clean up trailing whitespace
111
    # TODO RBC 20051029 test getting a push location from a branch in a
2230.3.3 by Aaron Bentley
Add more config testing
112
    # recursive section - that is, it appends the branch name.
113
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
114
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
115
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.
116
    """A sample format
117
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
118
    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.
119
    open and open_downlevel routines.
120
    """
121
122
    def get_format_string(self):
123
        """See BzrBranchFormat.get_format_string()."""
124
        return "Sample branch format."
125
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
126
    def initialize(self, a_bzrdir, name=None):
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
127
        """Format 4 branches cannot be created."""
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
128
        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
129
        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.
130
        return 'A branch'
131
132
    def is_supported(self):
133
        return False
134
5051.3.16 by Jelmer Vernooij
Fix tests - missing argument.
135
    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.
136
        return "opened branch."
137
138
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
139
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.
140
    """Tests for the BzrBranchFormat facility."""
141
142
    def test_find_format(self):
143
        # is the right format object found for a branch?
144
        # create a branch with a few known format objects.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
145
        # 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.
146
        self.build_tree(["foo/", "bar/"])
147
        def check_format(format, url):
148
            dir = format._matchingbzrdir.initialize(url)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
149
            dir.create_repository()
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
150
            format.initialize(dir)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
151
            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.
152
            self.failUnless(isinstance(found_format, format.__class__))
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
153
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
154
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
155
    def test_find_format_not_branch(self):
156
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
157
        self.assertRaises(errors.NotBranchError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
158
                          _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.
159
                          dir)
160
161
    def test_find_format_unknown_format(self):
162
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
163
        SampleBranchFormat().initialize(dir)
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
164
        self.assertRaises(errors.UnknownFormatError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
165
                          _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.
166
                          dir)
167
168
    def test_register_unregister_format(self):
169
        format = SampleBranchFormat()
170
        # make a control dir
171
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
172
        # make a branch
173
        format.initialize(dir)
174
        # register a format for it.
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
175
        _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.
176
        # which branch.Open will refuse (not supported)
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
177
        self.assertRaises(errors.UnsupportedFormatError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
178
                          _mod_branch.Branch.open, self.get_url())
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
179
        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.
180
        # but open_downlevel will work
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
181
        self.assertEqual(
182
            format.open(dir),
183
            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.
184
        # unregister the format
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
185
        _mod_branch.BranchFormat.unregister_format(format)
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
186
        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.
187
188
3221.11.2 by Robert Collins
Create basic stackable branch facility.
189
class TestBranch67(object):
190
    """Common tests for both branch 6 and 7 which are mostly the same."""
191
192
    def get_format_name(self):
193
        raise NotImplementedError(self.get_format_name)
194
195
    def get_format_name_subtree(self):
196
        raise NotImplementedError(self.get_format_name)
197
198
    def get_class(self):
199
        raise NotImplementedError(self.get_class)
2230.3.1 by Aaron Bentley
Get branch6 creation working
200
201
    def test_creation(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
202
        format = bzrdir.BzrDirMetaFormat1()
2230.3.55 by Aaron Bentley
Updates from review
203
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
2230.3.1 by Aaron Bentley
Get branch6 creation working
204
        branch = self.make_branch('a', format=format)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
205
        self.assertIsInstance(branch, self.get_class())
206
        branch = self.make_branch('b', format=self.get_format_name())
207
        self.assertIsInstance(branch, self.get_class())
2230.3.1 by Aaron Bentley
Get branch6 creation working
208
        branch = _mod_branch.Branch.open('a')
3221.11.2 by Robert Collins
Create basic stackable branch facility.
209
        self.assertIsInstance(branch, self.get_class())
2230.3.1 by Aaron Bentley
Get branch6 creation working
210
211
    def test_layout(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
212
        branch = self.make_branch('a', format=self.get_format_name())
2230.3.1 by Aaron Bentley
Get branch6 creation working
213
        self.failUnlessExists('a/.bzr/branch/last-revision')
214
        self.failIfExists('a/.bzr/branch/revision-history')
4273.1.12 by Aaron Bentley
Don't create reference files for older formats.
215
        self.failIfExists('a/.bzr/branch/references')
2230.3.1 by Aaron Bentley
Get branch6 creation working
216
2230.3.3 by Aaron Bentley
Add more config testing
217
    def test_config(self):
218
        """Ensure that all configuration data is stored in the branch"""
3221.11.2 by Robert Collins
Create basic stackable branch facility.
219
        branch = self.make_branch('a', format=self.get_format_name())
2230.3.3 by Aaron Bentley
Add more config testing
220
        branch.set_parent('http://bazaar-vcs.org')
221
        self.failIfExists('a/.bzr/branch/parent')
222
        self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
223
        branch.set_push_location('sftp://bazaar-vcs.org')
224
        config = branch.get_config()._get_branch_data_config()
2230.3.12 by Aaron Bentley
Clean up trailing whitespace
225
        self.assertEqual('sftp://bazaar-vcs.org',
2230.3.3 by Aaron Bentley
Add more config testing
226
                         config.get_user_option('push_location'))
227
        branch.set_bound_location('ftp://bazaar-vcs.org')
228
        self.failIfExists('a/.bzr/branch/bound')
229
        self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
230
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
231
    def test_set_revision_history(self):
3567.4.16 by John Arbash Meinel
Use the new BranchBuilder api in a Branch test
232
        builder = self.make_branch_builder('.', format=self.get_format_name())
233
        builder.build_snapshot('foo', None,
234
            [('add', ('', None, 'directory', None))],
235
            message='foo')
236
        builder.build_snapshot('bar', None, [], message='bar')
237
        branch = builder.get_branch()
238
        branch.lock_write()
239
        self.addCleanup(branch.unlock)
240
        branch.set_revision_history(['foo', 'bar'])
241
        branch.set_revision_history(['foo'])
242
        self.assertRaises(errors.NotLefthandHistory,
243
                          branch.set_revision_history, ['bar'])
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
244
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
245
    def do_checkout_test(self, lightweight=False):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
246
        tree = self.make_branch_and_tree('source',
247
            format=self.get_format_name_subtree())
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
248
        subtree = self.make_branch_and_tree('source/subtree',
3221.11.2 by Robert Collins
Create basic stackable branch facility.
249
            format=self.get_format_name_subtree())
2100.3.25 by Aaron Bentley
add subsubtree to test
250
        subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
3221.11.2 by Robert Collins
Create basic stackable branch facility.
251
            format=self.get_format_name_subtree())
2100.3.25 by Aaron Bentley
add subsubtree to test
252
        self.build_tree(['source/subtree/file',
253
                         'source/subtree/subsubtree/file'])
254
        subsubtree.add('file')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
255
        subtree.add('file')
2100.3.25 by Aaron Bentley
add subsubtree to test
256
        subtree.add_reference(subsubtree)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
257
        tree.add_reference(subtree)
258
        tree.commit('a revision')
2100.3.23 by Aaron Bentley
Nested checkouts kinda work
259
        subtree.commit('a subtree file')
2100.3.25 by Aaron Bentley
add subsubtree to test
260
        subsubtree.commit('a subsubtree file')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
261
        tree.branch.create_checkout('target', lightweight=lightweight)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
262
        self.failUnlessExists('target')
263
        self.failUnlessExists('target/subtree')
264
        self.failUnlessExists('target/subtree/file')
2100.3.25 by Aaron Bentley
add subsubtree to test
265
        self.failUnlessExists('target/subtree/subsubtree/file')
2100.3.31 by Aaron Bentley
Merged bzr.dev (17 tests failing)
266
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
267
        if lightweight:
268
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
269
        else:
270
            self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
271
272
    def test_checkout_with_references(self):
273
        self.do_checkout_test()
274
275
    def test_light_checkout_with_references(self):
276
        self.do_checkout_test(lightweight=True)
2230.3.51 by Aaron Bentley
Store revno for Branch6, set_last_revision -> set_last_revision_info
277
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
278
    def test_set_push(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
279
        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)
280
        branch.get_config().set_user_option('push_location', 'old',
281
            store=config.STORE_LOCATION)
282
        warnings = []
283
        def warning(*args):
284
            warnings.append(args[0] % args[1:])
285
        _warning = trace.warning
286
        trace.warning = warning
287
        try:
288
            branch.set_push_location('new')
289
        finally:
290
            trace.warning = _warning
291
        self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
292
                         'locations.conf')
293
3445.2.1 by John Arbash Meinel
Add tests for Branch.missing_revisions and deprecate it.
294
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
295
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
296
297
    def get_class(self):
298
        return _mod_branch.BzrBranch6
299
300
    def get_format_name(self):
301
        return "dirstate-tags"
302
303
    def get_format_name_subtree(self):
304
        return "dirstate-with-subtree"
305
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
306
    def test_set_stacked_on_url_errors(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
307
        branch = self.make_branch('a', format=self.get_format_name())
308
        self.assertRaises(errors.UnstackableBranchFormat,
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
309
            branch.set_stacked_on_url, None)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
310
311
    def test_default_stacked_location(self):
312
        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
313
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
314
315
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
316
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
317
318
    def get_class(self):
319
        return _mod_branch.BzrBranch7
320
321
    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)
322
        return "1.9"
3221.11.2 by Robert Collins
Create basic stackable branch facility.
323
324
    def get_format_name_subtree(self):
325
        return "development-subtree"
326
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
327
    def test_set_stacked_on_url_unstackable_repo(self):
3221.11.6 by Robert Collins
Stackable branch fixes.
328
        repo = self.make_repository('a', format='dirstate-tags')
329
        control = repo.bzrdir
330
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
331
        target = self.make_branch('b')
332
        self.assertRaises(errors.UnstackableRepositoryFormat,
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
333
            branch.set_stacked_on_url, target.base)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
334
3242.3.21 by Jonathan Lange
Preserve stacking in clone
335
    def test_clone_stacked_on_unstackable_repo(self):
336
        repo = self.make_repository('a', format='dirstate-tags')
337
        control = repo.bzrdir
338
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
339
        # Calling clone should not raise UnstackableRepositoryFormat.
340
        cloned_bzrdir = control.clone('cloned')
341
3221.11.2 by Robert Collins
Create basic stackable branch facility.
342
    def _test_default_stacked_location(self):
343
        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
344
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
345
3221.11.8 by Robert Collins
Minimally test stacking and unstacking a repository.
346
    def test_stack_and_unstack(self):
347
        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.
348
        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
349
        branch.set_stacked_on_url(target.branch.base)
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
350
        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.
351
        revid = target.commit('foo')
352
        self.assertTrue(branch.repository.has_revision(revid))
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
353
        branch.set_stacked_on_url(None)
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
354
        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.
355
        self.assertFalse(branch.repository.has_revision(revid))
3221.11.8 by Robert Collins
Minimally test stacking and unstacking a repository.
356
3221.11.11 by Robert Collins
Ensure opening a stacked branch gives a ready to use repository.
357
    def test_open_opens_stacked_reference(self):
358
        branch = self.make_branch('a', format=self.get_format_name())
359
        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
360
        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.
361
        branch = branch.bzrdir.open_branch()
362
        revid = target.commit('foo')
363
        self.assertTrue(branch.repository.has_revision(revid))
364
3221.11.2 by Robert Collins
Create basic stackable branch facility.
365
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
366
class BzrBranch8(tests.TestCaseWithTransport):
4273.1.15 by Aaron Bentley
Add reference_info caching.
367
368
    def make_branch(self, location, format=None):
369
        if format is None:
370
            format = bzrdir.format_registry.make_bzrdir('1.9')
371
            format.set_branch_format(_mod_branch.BzrBranchFormat8())
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
372
        return tests.TestCaseWithTransport.make_branch(
373
            self, location, format=format)
4273.1.15 by Aaron Bentley
Add reference_info caching.
374
375
    def create_branch_with_reference(self):
376
        branch = self.make_branch('branch')
377
        branch._set_all_reference_info({'file-id': ('path', 'location')})
378
        return branch
379
380
    @staticmethod
381
    def instrument_branch(branch, gets):
382
        old_get = branch._transport.get
383
        def get(*args, **kwargs):
384
            gets.append((args, kwargs))
385
            return old_get(*args, **kwargs)
386
        branch._transport.get = get
387
388
    def test_reference_info_caching_read_locked(self):
389
        gets = []
390
        branch = self.create_branch_with_reference()
391
        branch.lock_read()
392
        self.addCleanup(branch.unlock)
393
        self.instrument_branch(branch, gets)
394
        branch.get_reference_info('file-id')
395
        branch.get_reference_info('file-id')
396
        self.assertEqual(1, len(gets))
397
398
    def test_reference_info_caching_read_unlocked(self):
399
        gets = []
400
        branch = self.create_branch_with_reference()
401
        self.instrument_branch(branch, gets)
402
        branch.get_reference_info('file-id')
403
        branch.get_reference_info('file-id')
404
        self.assertEqual(2, len(gets))
405
406
    def test_reference_info_caching_write_locked(self):
407
        gets = []
408
        branch = self.make_branch('branch')
409
        branch.lock_write()
410
        self.instrument_branch(branch, gets)
411
        self.addCleanup(branch.unlock)
412
        branch._set_all_reference_info({'file-id': ('path2', 'location2')})
413
        path, location = branch.get_reference_info('file-id')
414
        self.assertEqual(0, len(gets))
415
        self.assertEqual('path2', path)
416
        self.assertEqual('location2', location)
417
418
    def test_reference_info_caches_cleared(self):
419
        branch = self.make_branch('branch')
420
        branch.lock_write()
421
        branch.set_reference_info('file-id', 'path2', 'location2')
422
        branch.unlock()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
423
        doppelganger = _mod_branch.Branch.open('branch')
4273.1.15 by Aaron Bentley
Add reference_info caching.
424
        doppelganger.set_reference_info('file-id', 'path3', 'location3')
425
        self.assertEqual(('path3', 'location3'),
426
                         branch.get_reference_info('file-id'))
427
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
428
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.
429
    """Tests for the branch reference facility."""
430
431
    def test_create_open_reference(self):
432
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
433
        t = transport.get_transport(self.get_url('.'))
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.
434
        t.mkdir('repo')
435
        dir = bzrdirformat.initialize(self.get_url('repo'))
436
        dir.create_repository()
437
        target_branch = dir.create_branch()
438
        t.mkdir('branch')
439
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
440
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
441
            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.
442
        self.assertEqual(made_branch.base, target_branch.base)
443
        opened_branch = branch_dir.open_branch()
444
        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.
445
446
    def test_get_reference(self):
447
        """For a BranchReference, get_reference should reutrn the location."""
448
        branch = self.make_branch('target')
449
        checkout = branch.create_checkout('checkout', lightweight=True)
450
        reference_url = branch.bzrdir.root_transport.abspath('') + '/'
451
        # if the api for create_checkout changes to return different checkout types
452
        # then this file read will fail.
453
        self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
454
        self.assertEqual(reference_url,
2018.5.97 by Andrew Bennetts
Fix more tests.
455
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
2018.5.45 by Andrew Bennetts
Merge from bzr.dev
456
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
457
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
458
class TestHooks(tests.TestCaseWithTransport):
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
459
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.
460
    def test_constructor(self):
461
        """Check that creating a BranchHooks instance has the right defaults."""
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
462
        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.
463
        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
464
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
465
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
466
        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
467
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
468
        self.assertTrue("post_uncommit" in hooks,
469
                        "post_uncommit not in %s" % hooks)
3331.1.4 by James Henstridge
Adjust my tests to pass with Ian's API.
470
        self.assertTrue("post_change_branch_tip" in hooks,
471
                        "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,
472
        self.assertTrue("post_branch_init" in hooks,
473
                        "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',
474
        self.assertTrue("post_switch" in hooks,
475
                        "post_switch not in %s" % hooks)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
476
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.
477
    def test_installed_hooks_are_BranchHooks(self):
478
        """The installed hooks object should be a BranchHooks."""
479
        # the installed hooks are saved in self._preserved_hooks.
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
480
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
481
                              _mod_branch.BranchHooks)
2245.1.3 by Robert Collins
Add install_hook to the BranchHooks class as the official means for installing a hook.
482
5107.3.2 by Marco Pantaleoni
Renamed 'post_branch' hook to 'post_branch_init', for more consistency,
483
    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',
484
        calls = []
5107.3.4 by Marco Pantaleoni
Applied suggestions from merge reviewer (John A Meinel):
485
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
486
            calls.append, None)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
487
        self.assertLength(0, calls)
488
        branch = self.make_branch('a')
489
        self.assertLength(1, calls)
490
        params = calls[0]
5107.3.2 by Marco Pantaleoni
Renamed 'post_branch' hook to 'post_branch_init', for more consistency,
491
        self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
492
        self.assertTrue(hasattr(params, 'bzrdir'))
493
        self.assertTrue(hasattr(params, 'branch'))
494
495
    def test_post_switch_hook(self):
496
        from bzrlib import switch
497
        calls = []
5107.3.4 by Marco Pantaleoni
Applied suggestions from merge reviewer (John A Meinel):
498
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
499
            calls.append, None)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
500
        tree = self.make_branch_and_tree('branch-1')
501
        self.build_tree(['branch-1/file-1'])
502
        tree.add('file-1')
503
        tree.commit('rev1')
504
        to_branch = tree.bzrdir.sprout('branch-2').open_branch()
505
        self.build_tree(['branch-1/file-2'])
506
        tree.add('file-2')
507
        tree.remove('file-1')
508
        tree.commit('rev2')
509
        checkout = tree.branch.create_checkout('checkout')
510
        self.assertLength(0, calls)
511
        switch.switch(checkout.bzrdir, to_branch)
512
        self.assertLength(1, calls)
513
        params = calls[0]
514
        self.assertIsInstance(params, _mod_branch.SwitchHookParams)
515
        self.assertTrue(hasattr(params, 'to_branch'))
516
        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()
517
5176.1.1 by Vincent Ladeuil
Warn if a config variable can't be interpreted as a boolean
518
519
class TestBranchOptions(tests.TestCaseWithTransport):
4989.2.1 by Brian de Alwis
The 'append_revisions_only' option is now case-insensitive,
520
4989.2.5 by Vincent Ladeuil
Clarify tests.
521
    def setUp(self):
522
        super(TestBranchOptions, self).setUp()
523
        self.branch = self.make_branch('.')
524
        self.config = self.branch.get_config()
525
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
526
    def check_append_revisions_only(self, expected_value, value=None):
527
        """Set append_revisions_only in config and check its interpretation."""
4989.2.5 by Vincent Ladeuil
Clarify tests.
528
        if value is not None:
529
            self.config.set_user_option('append_revisions_only', value)
530
        self.assertEqual(expected_value,
531
                         self.branch._get_append_revisions_only())
532
533
    def test_valid_append_revisions_only(self):
534
        self.assertEquals(None,
535
                          self.config.get_user_option('append_revisions_only'))
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
536
        self.check_append_revisions_only(None)
537
        self.check_append_revisions_only(False, 'False')
538
        self.check_append_revisions_only(True, 'True')
4989.2.13 by Vincent Ladeuil
append_revisions_only accept all valid booleans, update doc to
539
        # The following values will cause compatibility problems on projects
540
        # using older bzr versions (<2.2) but are accepted
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
541
        self.check_append_revisions_only(False, 'false')
542
        self.check_append_revisions_only(True, 'true')
4989.2.5 by Vincent Ladeuil
Clarify tests.
543
544
    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
545
        """Ensure warning is noted on invalid settings"""
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
546
        self.warnings = []
547
        def warning(*args):
548
            self.warnings.append(args[0] % args[1:])
549
        self.overrideAttr(trace, 'warning', warning)
550
        self.check_append_revisions_only(None, 'not-a-bool')
551
        self.assertLength(1, self.warnings)
552
        self.assertEqual(
553
            'Value "not-a-bool" is not a boolean for "append_revisions_only"',
554
            self.warnings[0])
4989.2.5 by Vincent Ladeuil
Clarify tests.
555
4989.2.1 by Brian de Alwis
The 'append_revisions_only' option is now case-insensitive,
556
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
557
class TestPullResult(tests.TestCase):
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
558
559
    def test_pull_result_to_int(self):
560
        # 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.
561
        r = _mod_branch.PullResult()
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
562
        r.old_revno = 10
563
        r.new_revno = 20
564
        # this usage of results is not recommended for new code (because it
565
        # doesn't describe very well what happened), but for api stability
566
        # it's still supported
567
        a = "%d revisions pulled" % r
568
        self.assertEqual(a, "10 revisions pulled")
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
569
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
570
    def test_report_changed(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
571
        r = _mod_branch.PullResult()
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
572
        r.old_revid = "old-revid"
573
        r.old_revno = 10
574
        r.new_revid = "new-revid"
575
        r.new_revno = 20
576
        f = StringIO()
577
        r.report(f)
578
        self.assertEqual("Now on revision 20.\n", f.getvalue())
579
580
    def test_report_unchanged(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
581
        r = _mod_branch.PullResult()
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
582
        r.old_revid = "same-revid"
583
        r.new_revid = "same-revid"
584
        f = StringIO()
585
        r.report(f)
586
        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()
587
588
589
class _StubLockable(object):
590
    """Helper for TestRunWithWriteLockedTarget."""
591
592
    def __init__(self, calls, unlock_exc=None):
593
        self.calls = calls
594
        self.unlock_exc = unlock_exc
595
596
    def lock_write(self):
597
        self.calls.append('lock_write')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
598
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
599
    def unlock(self):
600
        self.calls.append('unlock')
601
        if self.unlock_exc is not None:
602
            raise self.unlock_exc
603
604
605
class _ErrorFromCallable(Exception):
606
    """Helper for TestRunWithWriteLockedTarget."""
607
608
609
class _ErrorFromUnlock(Exception):
610
    """Helper for TestRunWithWriteLockedTarget."""
611
612
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
613
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()
614
    """Tests for _run_with_write_locked_target."""
615
616
    def setUp(self):
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
617
        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()
618
        self._calls = []
619
620
    def func_that_returns_ok(self):
621
        self._calls.append('func called')
622
        return 'ok'
623
624
    def func_that_raises(self):
625
        self._calls.append('func called')
626
        raise _ErrorFromCallable()
627
628
    def test_success_unlocks(self):
629
        lockable = _StubLockable(self._calls)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
630
        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()
631
            lockable, self.func_that_returns_ok)
632
        self.assertEqual('ok', result)
633
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
634
635
    def test_exception_unlocks_and_propagates(self):
636
        lockable = _StubLockable(self._calls)
637
        self.assertRaises(_ErrorFromCallable,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
638
                          _mod_branch._run_with_write_locked_target,
639
                          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()
640
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
641
642
    def test_callable_succeeds_but_error_during_unlock(self):
643
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
644
        self.assertRaises(_ErrorFromUnlock,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
645
                          _mod_branch._run_with_write_locked_target,
646
                          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()
647
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
648
649
    def test_error_during_unlock_does_not_mask_original_error(self):
650
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
651
        self.assertRaises(_ErrorFromCallable,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
652
                          _mod_branch._run_with_write_locked_target,
653
                          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()
654
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
655
656