~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: Ian Clatworthy
  • Date: 2007-08-13 14:16:53 UTC
  • mto: (2733.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 2734.
  • Revision ID: ian.clatworthy@internode.on.net-20070813141653-3cbrp00xowq58zv1
Added mini tutorial

Show diffs side-by-side

added added

removed removed

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