~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,
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
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
116
    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.
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
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
150
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.
151
    """Tests for the BzrBranchFormat facility."""
152
153
    def test_find_format(self):
154
        # is the right format object found for a branch?
155
        # create a branch with a few known format objects.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
156
        # 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.
157
        self.build_tree(["foo/", "bar/"])
158
        def check_format(format, url):
159
            dir = format._matchingbzrdir.initialize(url)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
160
            dir.create_repository()
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
161
            format.initialize(dir)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
162
            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.
163
            self.failUnless(isinstance(found_format, format.__class__))
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
164
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
165
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
166
    def test_find_format_factory(self):
167
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
168
        SampleSupportedBranchFormat().initialize(dir)
169
        factory = _mod_branch.MetaDirBranchFormatFactory(
5305.1.2 by Robert Collins
More clarity about how to use the lazy registration feature.
170
            SampleSupportedBranchFormatString,
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
171
            "bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
172
        _mod_branch.BranchFormat.register_format(factory)
173
        self.addCleanup(_mod_branch.BranchFormat.unregister_format, factory)
174
        b = _mod_branch.Branch.open(self.get_url())
175
        self.assertEqual(b, "opened supported branch.")
176
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
177
    def test_find_format_not_branch(self):
178
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
179
        self.assertRaises(errors.NotBranchError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
180
                          _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.
181
                          dir)
182
183
    def test_find_format_unknown_format(self):
184
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
185
        SampleBranchFormat().initialize(dir)
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
186
        self.assertRaises(errors.UnknownFormatError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
187
                          _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.
188
                          dir)
189
190
    def test_register_unregister_format(self):
191
        format = SampleBranchFormat()
192
        # make a control dir
193
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
194
        # make a branch
195
        format.initialize(dir)
196
        # register a format for it.
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
197
        _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.
198
        # which branch.Open will refuse (not supported)
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
199
        self.assertRaises(errors.UnsupportedFormatError,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
200
                          _mod_branch.Branch.open, self.get_url())
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
201
        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.
202
        # but open_downlevel will work
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
203
        self.assertEqual(
204
            format.open(dir),
205
            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.
206
        # unregister the format
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
207
        _mod_branch.BranchFormat.unregister_format(format)
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
208
        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.
209
210
5305.1.1 by Robert Collins
``Branch`` formats can now be loaded lazily by registering a
211
#Used by TestMetaDirBranchFormatFactory 
212
FakeLazyFormat = None
213
214
215
class TestMetaDirBranchFormatFactory(tests.TestCase):
216
217
    def test_get_format_string_does_not_load(self):
218
        """Formats have a static format string."""
219
        factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
220
        self.assertEqual("yo", factory.get_format_string())
221
222
    def test_call_loads(self):
223
        # __call__ is used by the network_format_registry interface to get a
224
        # Format.
225
        global FakeLazyFormat
226
        del FakeLazyFormat
227
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
228
            "bzrlib.tests.test_branch", "FakeLazyFormat")
229
        self.assertRaises(AttributeError, factory)
230
231
    def test_call_returns_call_of_referenced_object(self):
232
        global FakeLazyFormat
233
        FakeLazyFormat = lambda:'called'
234
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
235
            "bzrlib.tests.test_branch", "FakeLazyFormat")
236
        self.assertEqual('called', factory())
237
238
3221.11.2 by Robert Collins
Create basic stackable branch facility.
239
class TestBranch67(object):
240
    """Common tests for both branch 6 and 7 which are mostly the same."""
241
242
    def get_format_name(self):
243
        raise NotImplementedError(self.get_format_name)
244
245
    def get_format_name_subtree(self):
246
        raise NotImplementedError(self.get_format_name)
247
248
    def get_class(self):
249
        raise NotImplementedError(self.get_class)
2230.3.1 by Aaron Bentley
Get branch6 creation working
250
251
    def test_creation(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
252
        format = bzrdir.BzrDirMetaFormat1()
2230.3.55 by Aaron Bentley
Updates from review
253
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
2230.3.1 by Aaron Bentley
Get branch6 creation working
254
        branch = self.make_branch('a', format=format)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
255
        self.assertIsInstance(branch, self.get_class())
256
        branch = self.make_branch('b', format=self.get_format_name())
257
        self.assertIsInstance(branch, self.get_class())
2230.3.1 by Aaron Bentley
Get branch6 creation working
258
        branch = _mod_branch.Branch.open('a')
3221.11.2 by Robert Collins
Create basic stackable branch facility.
259
        self.assertIsInstance(branch, self.get_class())
2230.3.1 by Aaron Bentley
Get branch6 creation working
260
261
    def test_layout(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
262
        branch = self.make_branch('a', format=self.get_format_name())
2230.3.1 by Aaron Bentley
Get branch6 creation working
263
        self.failUnlessExists('a/.bzr/branch/last-revision')
264
        self.failIfExists('a/.bzr/branch/revision-history')
4273.1.12 by Aaron Bentley
Don't create reference files for older formats.
265
        self.failIfExists('a/.bzr/branch/references')
2230.3.1 by Aaron Bentley
Get branch6 creation working
266
2230.3.3 by Aaron Bentley
Add more config testing
267
    def test_config(self):
268
        """Ensure that all configuration data is stored in the branch"""
3221.11.2 by Robert Collins
Create basic stackable branch facility.
269
        branch = self.make_branch('a', format=self.get_format_name())
2230.3.3 by Aaron Bentley
Add more config testing
270
        branch.set_parent('http://bazaar-vcs.org')
271
        self.failIfExists('a/.bzr/branch/parent')
272
        self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
273
        branch.set_push_location('sftp://bazaar-vcs.org')
274
        config = branch.get_config()._get_branch_data_config()
2230.3.12 by Aaron Bentley
Clean up trailing whitespace
275
        self.assertEqual('sftp://bazaar-vcs.org',
2230.3.3 by Aaron Bentley
Add more config testing
276
                         config.get_user_option('push_location'))
277
        branch.set_bound_location('ftp://bazaar-vcs.org')
278
        self.failIfExists('a/.bzr/branch/bound')
279
        self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
280
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
281
    def test_set_revision_history(self):
3567.4.16 by John Arbash Meinel
Use the new BranchBuilder api in a Branch test
282
        builder = self.make_branch_builder('.', format=self.get_format_name())
283
        builder.build_snapshot('foo', None,
284
            [('add', ('', None, 'directory', None))],
285
            message='foo')
286
        builder.build_snapshot('bar', None, [], message='bar')
287
        branch = builder.get_branch()
288
        branch.lock_write()
289
        self.addCleanup(branch.unlock)
290
        branch.set_revision_history(['foo', 'bar'])
291
        branch.set_revision_history(['foo'])
292
        self.assertRaises(errors.NotLefthandHistory,
293
                          branch.set_revision_history, ['bar'])
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
294
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
295
    def do_checkout_test(self, lightweight=False):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
296
        tree = self.make_branch_and_tree('source',
297
            format=self.get_format_name_subtree())
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
298
        subtree = self.make_branch_and_tree('source/subtree',
3221.11.2 by Robert Collins
Create basic stackable branch facility.
299
            format=self.get_format_name_subtree())
2100.3.25 by Aaron Bentley
add subsubtree to test
300
        subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
3221.11.2 by Robert Collins
Create basic stackable branch facility.
301
            format=self.get_format_name_subtree())
2100.3.25 by Aaron Bentley
add subsubtree to test
302
        self.build_tree(['source/subtree/file',
303
                         'source/subtree/subsubtree/file'])
304
        subsubtree.add('file')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
305
        subtree.add('file')
2100.3.25 by Aaron Bentley
add subsubtree to test
306
        subtree.add_reference(subsubtree)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
307
        tree.add_reference(subtree)
308
        tree.commit('a revision')
2100.3.23 by Aaron Bentley
Nested checkouts kinda work
309
        subtree.commit('a subtree file')
2100.3.25 by Aaron Bentley
add subsubtree to test
310
        subsubtree.commit('a subsubtree file')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
311
        tree.branch.create_checkout('target', lightweight=lightweight)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
312
        self.failUnlessExists('target')
313
        self.failUnlessExists('target/subtree')
314
        self.failUnlessExists('target/subtree/file')
2100.3.25 by Aaron Bentley
add subsubtree to test
315
        self.failUnlessExists('target/subtree/subsubtree/file')
2100.3.31 by Aaron Bentley
Merged bzr.dev (17 tests failing)
316
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
317
        if lightweight:
318
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
319
        else:
320
            self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
321
322
    def test_checkout_with_references(self):
323
        self.do_checkout_test()
324
325
    def test_light_checkout_with_references(self):
326
        self.do_checkout_test(lightweight=True)
2230.3.51 by Aaron Bentley
Store revno for Branch6, set_last_revision -> set_last_revision_info
327
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
328
    def test_set_push(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
329
        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)
330
        branch.get_config().set_user_option('push_location', 'old',
331
            store=config.STORE_LOCATION)
332
        warnings = []
333
        def warning(*args):
334
            warnings.append(args[0] % args[1:])
335
        _warning = trace.warning
336
        trace.warning = warning
337
        try:
338
            branch.set_push_location('new')
339
        finally:
340
            trace.warning = _warning
341
        self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
342
                         'locations.conf')
343
3445.2.1 by John Arbash Meinel
Add tests for Branch.missing_revisions and deprecate it.
344
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
345
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
346
347
    def get_class(self):
348
        return _mod_branch.BzrBranch6
349
350
    def get_format_name(self):
351
        return "dirstate-tags"
352
353
    def get_format_name_subtree(self):
354
        return "dirstate-with-subtree"
355
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
356
    def test_set_stacked_on_url_errors(self):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
357
        branch = self.make_branch('a', format=self.get_format_name())
358
        self.assertRaises(errors.UnstackableBranchFormat,
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
359
            branch.set_stacked_on_url, None)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
360
361
    def test_default_stacked_location(self):
362
        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
363
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
364
365
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
366
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
3221.11.2 by Robert Collins
Create basic stackable branch facility.
367
368
    def get_class(self):
369
        return _mod_branch.BzrBranch7
370
371
    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)
372
        return "1.9"
3221.11.2 by Robert Collins
Create basic stackable branch facility.
373
374
    def get_format_name_subtree(self):
375
        return "development-subtree"
376
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
377
    def test_set_stacked_on_url_unstackable_repo(self):
3221.11.6 by Robert Collins
Stackable branch fixes.
378
        repo = self.make_repository('a', format='dirstate-tags')
379
        control = repo.bzrdir
380
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
381
        target = self.make_branch('b')
382
        self.assertRaises(errors.UnstackableRepositoryFormat,
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
383
            branch.set_stacked_on_url, target.base)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
384
3242.3.21 by Jonathan Lange
Preserve stacking in clone
385
    def test_clone_stacked_on_unstackable_repo(self):
386
        repo = self.make_repository('a', format='dirstate-tags')
387
        control = repo.bzrdir
388
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
389
        # Calling clone should not raise UnstackableRepositoryFormat.
390
        cloned_bzrdir = control.clone('cloned')
391
3221.11.2 by Robert Collins
Create basic stackable branch facility.
392
    def _test_default_stacked_location(self):
393
        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
394
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
3221.11.2 by Robert Collins
Create basic stackable branch facility.
395
3221.11.8 by Robert Collins
Minimally test stacking and unstacking a repository.
396
    def test_stack_and_unstack(self):
397
        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.
398
        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
399
        branch.set_stacked_on_url(target.branch.base)
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
400
        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.
401
        revid = target.commit('foo')
402
        self.assertTrue(branch.repository.has_revision(revid))
3537.3.3 by Martin Pool
Rename Branch.set_stacked_on to set_stacked_on_url
403
        branch.set_stacked_on_url(None)
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
404
        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.
405
        self.assertFalse(branch.repository.has_revision(revid))
3221.11.8 by Robert Collins
Minimally test stacking and unstacking a repository.
406
3221.11.11 by Robert Collins
Ensure opening a stacked branch gives a ready to use repository.
407
    def test_open_opens_stacked_reference(self):
408
        branch = self.make_branch('a', format=self.get_format_name())
409
        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
410
        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.
411
        branch = branch.bzrdir.open_branch()
412
        revid = target.commit('foo')
413
        self.assertTrue(branch.repository.has_revision(revid))
414
3221.11.2 by Robert Collins
Create basic stackable branch facility.
415
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
416
class BzrBranch8(tests.TestCaseWithTransport):
4273.1.15 by Aaron Bentley
Add reference_info caching.
417
418
    def make_branch(self, location, format=None):
419
        if format is None:
420
            format = bzrdir.format_registry.make_bzrdir('1.9')
421
            format.set_branch_format(_mod_branch.BzrBranchFormat8())
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
422
        return tests.TestCaseWithTransport.make_branch(
423
            self, location, format=format)
4273.1.15 by Aaron Bentley
Add reference_info caching.
424
425
    def create_branch_with_reference(self):
426
        branch = self.make_branch('branch')
427
        branch._set_all_reference_info({'file-id': ('path', 'location')})
428
        return branch
429
430
    @staticmethod
431
    def instrument_branch(branch, gets):
432
        old_get = branch._transport.get
433
        def get(*args, **kwargs):
434
            gets.append((args, kwargs))
435
            return old_get(*args, **kwargs)
436
        branch._transport.get = get
437
438
    def test_reference_info_caching_read_locked(self):
439
        gets = []
440
        branch = self.create_branch_with_reference()
441
        branch.lock_read()
442
        self.addCleanup(branch.unlock)
443
        self.instrument_branch(branch, gets)
444
        branch.get_reference_info('file-id')
445
        branch.get_reference_info('file-id')
446
        self.assertEqual(1, len(gets))
447
448
    def test_reference_info_caching_read_unlocked(self):
449
        gets = []
450
        branch = self.create_branch_with_reference()
451
        self.instrument_branch(branch, gets)
452
        branch.get_reference_info('file-id')
453
        branch.get_reference_info('file-id')
454
        self.assertEqual(2, len(gets))
455
456
    def test_reference_info_caching_write_locked(self):
457
        gets = []
458
        branch = self.make_branch('branch')
459
        branch.lock_write()
460
        self.instrument_branch(branch, gets)
461
        self.addCleanup(branch.unlock)
462
        branch._set_all_reference_info({'file-id': ('path2', 'location2')})
463
        path, location = branch.get_reference_info('file-id')
464
        self.assertEqual(0, len(gets))
465
        self.assertEqual('path2', path)
466
        self.assertEqual('location2', location)
467
468
    def test_reference_info_caches_cleared(self):
469
        branch = self.make_branch('branch')
470
        branch.lock_write()
471
        branch.set_reference_info('file-id', 'path2', 'location2')
472
        branch.unlock()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
473
        doppelganger = _mod_branch.Branch.open('branch')
4273.1.15 by Aaron Bentley
Add reference_info caching.
474
        doppelganger.set_reference_info('file-id', 'path3', 'location3')
475
        self.assertEqual(('path3', 'location3'),
476
                         branch.get_reference_info('file-id'))
477
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
478
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.
479
    """Tests for the branch reference facility."""
480
481
    def test_create_open_reference(self):
482
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
483
        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.
484
        t.mkdir('repo')
485
        dir = bzrdirformat.initialize(self.get_url('repo'))
486
        dir.create_repository()
487
        target_branch = dir.create_branch()
488
        t.mkdir('branch')
489
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
490
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
491
            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.
492
        self.assertEqual(made_branch.base, target_branch.base)
493
        opened_branch = branch_dir.open_branch()
494
        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.
495
496
    def test_get_reference(self):
497
        """For a BranchReference, get_reference should reutrn the location."""
498
        branch = self.make_branch('target')
499
        checkout = branch.create_checkout('checkout', lightweight=True)
500
        reference_url = branch.bzrdir.root_transport.abspath('') + '/'
501
        # if the api for create_checkout changes to return different checkout types
502
        # then this file read will fail.
503
        self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
504
        self.assertEqual(reference_url,
2018.5.97 by Andrew Bennetts
Fix more tests.
505
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
2018.5.45 by Andrew Bennetts
Merge from bzr.dev
506
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
507
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
508
class TestHooks(tests.TestCaseWithTransport):
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
509
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.
510
    def test_constructor(self):
511
        """Check that creating a BranchHooks instance has the right defaults."""
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
512
        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.
513
        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
514
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
515
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
516
        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
517
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
518
        self.assertTrue("post_uncommit" in hooks,
519
                        "post_uncommit not in %s" % hooks)
3331.1.4 by James Henstridge
Adjust my tests to pass with Ian's API.
520
        self.assertTrue("post_change_branch_tip" in hooks,
521
                        "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,
522
        self.assertTrue("post_branch_init" in hooks,
523
                        "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',
524
        self.assertTrue("post_switch" in hooks,
525
                        "post_switch not in %s" % hooks)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
526
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.
527
    def test_installed_hooks_are_BranchHooks(self):
528
        """The installed hooks object should be a BranchHooks."""
529
        # the installed hooks are saved in self._preserved_hooks.
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
530
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
531
                              _mod_branch.BranchHooks)
2245.1.3 by Robert Collins
Add install_hook to the BranchHooks class as the official means for installing a hook.
532
5107.3.2 by Marco Pantaleoni
Renamed 'post_branch' hook to 'post_branch_init', for more consistency,
533
    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',
534
        calls = []
5107.3.4 by Marco Pantaleoni
Applied suggestions from merge reviewer (John A Meinel):
535
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
536
            calls.append, None)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
537
        self.assertLength(0, calls)
538
        branch = self.make_branch('a')
539
        self.assertLength(1, calls)
540
        params = calls[0]
5107.3.2 by Marco Pantaleoni
Renamed 'post_branch' hook to 'post_branch_init', for more consistency,
541
        self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
542
        self.assertTrue(hasattr(params, 'bzrdir'))
543
        self.assertTrue(hasattr(params, 'branch'))
544
5050.21.1 by Andrew Bennetts
Remove broken and apparently unused code path from BranchInitHookParams.__repr__.
545
    def test_post_branch_init_hook_repr(self):
546
        param_reprs = []
547
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
548
            lambda params: param_reprs.append(repr(params)), None)
549
        branch = self.make_branch('a')
550
        self.assertLength(1, param_reprs)
551
        param_repr = param_reprs[0]
552
        self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
553
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
554
    def test_post_switch_hook(self):
555
        from bzrlib import switch
556
        calls = []
5107.3.4 by Marco Pantaleoni
Applied suggestions from merge reviewer (John A Meinel):
557
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
558
            calls.append, None)
5107.3.1 by Marco Pantaleoni
Added the new hooks 'post_branch', 'post_switch' and 'post_repo_init',
559
        tree = self.make_branch_and_tree('branch-1')
560
        self.build_tree(['branch-1/file-1'])
561
        tree.add('file-1')
562
        tree.commit('rev1')
563
        to_branch = tree.bzrdir.sprout('branch-2').open_branch()
564
        self.build_tree(['branch-1/file-2'])
565
        tree.add('file-2')
566
        tree.remove('file-1')
567
        tree.commit('rev2')
568
        checkout = tree.branch.create_checkout('checkout')
569
        self.assertLength(0, calls)
570
        switch.switch(checkout.bzrdir, to_branch)
571
        self.assertLength(1, calls)
572
        params = calls[0]
573
        self.assertIsInstance(params, _mod_branch.SwitchHookParams)
574
        self.assertTrue(hasattr(params, 'to_branch'))
575
        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()
576
5176.1.1 by Vincent Ladeuil
Warn if a config variable can't be interpreted as a boolean
577
578
class TestBranchOptions(tests.TestCaseWithTransport):
4989.2.1 by Brian de Alwis
The 'append_revisions_only' option is now case-insensitive,
579
4989.2.5 by Vincent Ladeuil
Clarify tests.
580
    def setUp(self):
581
        super(TestBranchOptions, self).setUp()
582
        self.branch = self.make_branch('.')
583
        self.config = self.branch.get_config()
584
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
585
    def check_append_revisions_only(self, expected_value, value=None):
586
        """Set append_revisions_only in config and check its interpretation."""
4989.2.5 by Vincent Ladeuil
Clarify tests.
587
        if value is not None:
588
            self.config.set_user_option('append_revisions_only', value)
589
        self.assertEqual(expected_value,
590
                         self.branch._get_append_revisions_only())
591
592
    def test_valid_append_revisions_only(self):
593
        self.assertEquals(None,
594
                          self.config.get_user_option('append_revisions_only'))
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
595
        self.check_append_revisions_only(None)
596
        self.check_append_revisions_only(False, 'False')
597
        self.check_append_revisions_only(True, 'True')
4989.2.13 by Vincent Ladeuil
append_revisions_only accept all valid booleans, update doc to
598
        # The following values will cause compatibility problems on projects
599
        # using older bzr versions (<2.2) but are accepted
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
600
        self.check_append_revisions_only(False, 'false')
601
        self.check_append_revisions_only(True, 'true')
4989.2.5 by Vincent Ladeuil
Clarify tests.
602
603
    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
604
        """Ensure warning is noted on invalid settings"""
4989.2.15 by Vincent Ladeuil
Fixed as per Andrew's review.
605
        self.warnings = []
606
        def warning(*args):
607
            self.warnings.append(args[0] % args[1:])
608
        self.overrideAttr(trace, 'warning', warning)
609
        self.check_append_revisions_only(None, 'not-a-bool')
610
        self.assertLength(1, self.warnings)
611
        self.assertEqual(
612
            'Value "not-a-bool" is not a boolean for "append_revisions_only"',
613
            self.warnings[0])
4989.2.5 by Vincent Ladeuil
Clarify tests.
614
4989.2.1 by Brian de Alwis
The 'append_revisions_only' option is now case-insensitive,
615
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
616
class TestPullResult(tests.TestCase):
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
617
618
    def test_pull_result_to_int(self):
619
        # 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.
620
        r = _mod_branch.PullResult()
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
621
        r.old_revno = 10
622
        r.new_revno = 20
623
        # this usage of results is not recommended for new code (because it
624
        # doesn't describe very well what happened), but for api stability
625
        # it's still supported
5348.1.2 by Martin Pool
Deprecate casting PushResult and PullResult to int to get the relative revno change
626
        self.assertEqual(self.applyDeprecated(
627
            symbol_versioning.deprecated_in((2, 3, 0)),
628
            r.__int__),
629
            10)
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
630
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
631
    def test_report_changed(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
632
        r = _mod_branch.PullResult()
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
633
        r.old_revid = "old-revid"
634
        r.old_revno = 10
635
        r.new_revid = "new-revid"
636
        r.new_revno = 20
637
        f = StringIO()
638
        r.report(f)
639
        self.assertEqual("Now on revision 20.\n", f.getvalue())
640
641
    def test_report_unchanged(self):
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
642
        r = _mod_branch.PullResult()
4672.4.1 by Jelmer Vernooij
Add two more tests for PullResult.
643
        r.old_revid = "same-revid"
644
        r.new_revid = "same-revid"
645
        f = StringIO()
646
        r.report(f)
647
        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()
648
649
650
class _StubLockable(object):
651
    """Helper for TestRunWithWriteLockedTarget."""
652
653
    def __init__(self, calls, unlock_exc=None):
654
        self.calls = calls
655
        self.unlock_exc = unlock_exc
656
657
    def lock_write(self):
658
        self.calls.append('lock_write')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
659
3758.1.1 by Andrew Bennetts
Fix #230902 by being more careful not to squash a pre-existing exception when calling foo.unlock()
660
    def unlock(self):
661
        self.calls.append('unlock')
662
        if self.unlock_exc is not None:
663
            raise self.unlock_exc
664
665
666
class _ErrorFromCallable(Exception):
667
    """Helper for TestRunWithWriteLockedTarget."""
668
669
670
class _ErrorFromUnlock(Exception):
671
    """Helper for TestRunWithWriteLockedTarget."""
672
673
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
674
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()
675
    """Tests for _run_with_write_locked_target."""
676
677
    def setUp(self):
5010.2.1 by Vincent Ladeuil
Fiux test/test_branch.py imports.
678
        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()
679
        self._calls = []
680
681
    def func_that_returns_ok(self):
682
        self._calls.append('func called')
683
        return 'ok'
684
685
    def func_that_raises(self):
686
        self._calls.append('func called')
687
        raise _ErrorFromCallable()
688
689
    def test_success_unlocks(self):
690
        lockable = _StubLockable(self._calls)
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
691
        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()
692
            lockable, self.func_that_returns_ok)
693
        self.assertEqual('ok', result)
694
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
695
696
    def test_exception_unlocks_and_propagates(self):
697
        lockable = _StubLockable(self._calls)
698
        self.assertRaises(_ErrorFromCallable,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
699
                          _mod_branch._run_with_write_locked_target,
700
                          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()
701
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
702
703
    def test_callable_succeeds_but_error_during_unlock(self):
704
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
705
        self.assertRaises(_ErrorFromUnlock,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
706
                          _mod_branch._run_with_write_locked_target,
707
                          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()
708
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
709
710
    def test_error_during_unlock_does_not_mask_original_error(self):
711
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
712
        self.assertRaises(_ErrorFromCallable,
5010.2.26 by Vincent Ladeuil
Fix imports in test_branch.py.
713
                          _mod_branch._run_with_write_locked_target,
714
                          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()
715
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
716
717