~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:33:10 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-20070813143310-twhj4la0qnupvze8
Added Quick Start Summary

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,
116
 
                   append_revisions_only=None):
 
121
    def initialize(self, a_bzrdir):
117
122
        """Format 4 branches cannot be created."""
118
 
        t = a_bzrdir.get_branch_transport(self, name=name)
 
123
        t = a_bzrdir.get_branch_transport(self)
119
124
        t.put_bytes('format', self.get_format_string())
120
125
        return 'A branch'
121
126
 
122
127
    def is_supported(self):
123
128
        return False
124
129
 
125
 
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
 
130
    def open(self, transport, _found=False):
126
131
        return "opened branch."
127
132
 
128
133
 
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.
134
 
class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
135
 
    """A sample supported format."""
136
 
 
137
 
    def get_format_string(self):
138
 
        """See BzrBranchFormat.get_format_string()."""
139
 
        return SampleSupportedBranchFormatString
140
 
 
141
 
    def initialize(self, a_bzrdir, name=None, append_revisions_only=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
 
 
150
 
class SampleExtraBranchFormat(_mod_branch.BranchFormat):
151
 
    """A sample format that is not usable in a metadir."""
152
 
 
153
 
    def get_format_string(self):
154
 
        # This format is not usable in a metadir.
155
 
        return None
156
 
 
157
 
    def network_name(self):
158
 
        # Network name always has to be provided.
159
 
        return "extra"
160
 
 
161
 
    def initialize(self, a_bzrdir, name=None):
162
 
        raise NotImplementedError(self.initialize)
163
 
 
164
 
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
165
 
        raise NotImplementedError(self.open)
166
 
 
167
 
 
168
 
class TestBzrBranchFormat(tests.TestCaseWithTransport):
 
134
class TestBzrBranchFormat(TestCaseWithTransport):
169
135
    """Tests for the BzrBranchFormat facility."""
170
136
 
171
137
    def test_find_format(self):
172
138
        # is the right format object found for a branch?
173
139
        # create a branch with a few known format objects.
174
 
        # this is not quite the same as
 
140
        # this is not quite the same as 
175
141
        self.build_tree(["foo/", "bar/"])
176
142
        def check_format(format, url):
177
143
            dir = format._matchingbzrdir.initialize(url)
178
144
            dir.create_repository()
179
145
            format.initialize(dir)
180
 
            found_format = _mod_branch.BranchFormat.find_format(dir)
181
 
            self.assertIsInstance(found_format, format.__class__)
182
 
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
183
 
 
184
 
    def test_find_format_factory(self):
185
 
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
186
 
        SampleSupportedBranchFormat().initialize(dir)
187
 
        factory = _mod_branch.MetaDirBranchFormatFactory(
188
 
            SampleSupportedBranchFormatString,
189
 
            "bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
190
 
        _mod_branch.format_registry.register(factory)
191
 
        self.addCleanup(_mod_branch.format_registry.remove, factory)
192
 
        b = _mod_branch.Branch.open(self.get_url())
193
 
        self.assertEqual(b, "opened supported branch.")
194
 
 
 
146
            found_format = BranchFormat.find_format(dir)
 
147
            self.failUnless(isinstance(found_format, format.__class__))
 
148
        check_format(BzrBranchFormat5(), "bar")
 
149
        
195
150
    def test_find_format_not_branch(self):
196
151
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
197
 
        self.assertRaises(errors.NotBranchError,
198
 
                          _mod_branch.BranchFormat.find_format,
 
152
        self.assertRaises(NotBranchError,
 
153
                          BranchFormat.find_format,
199
154
                          dir)
200
155
 
201
156
    def test_find_format_unknown_format(self):
202
157
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
203
158
        SampleBranchFormat().initialize(dir)
204
 
        self.assertRaises(errors.UnknownFormatError,
205
 
                          _mod_branch.BranchFormat.find_format,
 
159
        self.assertRaises(UnknownFormatError,
 
160
                          BranchFormat.find_format,
206
161
                          dir)
207
162
 
208
163
    def test_register_unregister_format(self):
209
 
        # Test the deprecated format registration functions
210
164
        format = SampleBranchFormat()
211
165
        # make a control dir
212
166
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
213
167
        # make a branch
214
168
        format.initialize(dir)
215
169
        # register a format for it.
216
 
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
217
 
            _mod_branch.BranchFormat.register_format, format)
 
170
        BranchFormat.register_format(format)
218
171
        # which branch.Open will refuse (not supported)
219
 
        self.assertRaises(errors.UnsupportedFormatError,
220
 
                          _mod_branch.Branch.open, self.get_url())
 
172
        self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
221
173
        self.make_branch_and_tree('foo')
222
174
        # but open_downlevel will work
223
 
        self.assertEqual(
224
 
            format.open(dir),
225
 
            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))
226
176
        # unregister the format
227
 
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
228
 
            _mod_branch.BranchFormat.unregister_format, format)
 
177
        BranchFormat.unregister_format(format)
229
178
        self.make_branch_and_tree('bar')
230
179
 
231
180
 
232
 
class TestBranchFormatRegistry(tests.TestCase):
233
 
 
234
 
    def setUp(self):
235
 
        super(TestBranchFormatRegistry, self).setUp()
236
 
        self.registry = _mod_branch.BranchFormatRegistry()
237
 
 
238
 
    def test_default(self):
239
 
        self.assertIs(None, self.registry.get_default())
240
 
        format = SampleBranchFormat()
241
 
        self.registry.set_default(format)
242
 
        self.assertEquals(format, self.registry.get_default())
243
 
 
244
 
    def test_register_unregister_format(self):
245
 
        format = SampleBranchFormat()
246
 
        self.registry.register(format)
247
 
        self.assertEquals(format,
248
 
            self.registry.get("Sample branch format."))
249
 
        self.registry.remove(format)
250
 
        self.assertRaises(KeyError, self.registry.get,
251
 
            "Sample branch format.")
252
 
 
253
 
    def test_get_all(self):
254
 
        format = SampleBranchFormat()
255
 
        self.assertEquals([], self.registry._get_all())
256
 
        self.registry.register(format)
257
 
        self.assertEquals([format], self.registry._get_all())
258
 
 
259
 
    def test_register_extra(self):
260
 
        format = SampleExtraBranchFormat()
261
 
        self.assertEquals([], self.registry._get_all())
262
 
        self.registry.register_extra(format)
263
 
        self.assertEquals([format], self.registry._get_all())
264
 
 
265
 
    def test_register_extra_lazy(self):
266
 
        self.assertEquals([], self.registry._get_all())
267
 
        self.registry.register_extra_lazy("bzrlib.tests.test_branch",
268
 
            "SampleExtraBranchFormat")
269
 
        formats = self.registry._get_all()
270
 
        self.assertEquals(1, len(formats))
271
 
        self.assertIsInstance(formats[0], SampleExtraBranchFormat)
272
 
 
273
 
 
274
 
#Used by TestMetaDirBranchFormatFactory 
275
 
FakeLazyFormat = None
276
 
 
277
 
 
278
 
class TestMetaDirBranchFormatFactory(tests.TestCase):
279
 
 
280
 
    def test_get_format_string_does_not_load(self):
281
 
        """Formats have a static format string."""
282
 
        factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
283
 
        self.assertEqual("yo", factory.get_format_string())
284
 
 
285
 
    def test_call_loads(self):
286
 
        # __call__ is used by the network_format_registry interface to get a
287
 
        # Format.
288
 
        global FakeLazyFormat
289
 
        del FakeLazyFormat
290
 
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
291
 
            "bzrlib.tests.test_branch", "FakeLazyFormat")
292
 
        self.assertRaises(AttributeError, factory)
293
 
 
294
 
    def test_call_returns_call_of_referenced_object(self):
295
 
        global FakeLazyFormat
296
 
        FakeLazyFormat = lambda:'called'
297
 
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
298
 
            "bzrlib.tests.test_branch", "FakeLazyFormat")
299
 
        self.assertEqual('called', factory())
300
 
 
301
 
 
302
 
class TestBranch67(object):
303
 
    """Common tests for both branch 6 and 7 which are mostly the same."""
304
 
 
305
 
    def get_format_name(self):
306
 
        raise NotImplementedError(self.get_format_name)
307
 
 
308
 
    def get_format_name_subtree(self):
309
 
        raise NotImplementedError(self.get_format_name)
310
 
 
311
 
    def get_class(self):
312
 
        raise NotImplementedError(self.get_class)
 
181
class TestBranch6(TestCaseWithTransport):
313
182
 
314
183
    def test_creation(self):
315
 
        format = bzrdir.BzrDirMetaFormat1()
 
184
        format = BzrDirMetaFormat1()
316
185
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
317
186
        branch = self.make_branch('a', format=format)
318
 
        self.assertIsInstance(branch, self.get_class())
319
 
        branch = self.make_branch('b', format=self.get_format_name())
320
 
        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)
321
190
        branch = _mod_branch.Branch.open('a')
322
 
        self.assertIsInstance(branch, self.get_class())
 
191
        self.assertIsInstance(branch, _mod_branch.BzrBranch6)
323
192
 
324
193
    def test_layout(self):
325
 
        branch = self.make_branch('a', format=self.get_format_name())
326
 
        self.assertPathExists('a/.bzr/branch/last-revision')
327
 
        self.assertPathDoesNotExist('a/.bzr/branch/revision-history')
328
 
        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')
329
197
 
330
198
    def test_config(self):
331
199
        """Ensure that all configuration data is stored in the branch"""
332
 
        branch = self.make_branch('a', format=self.get_format_name())
333
 
        branch.set_parent('http://example.com')
334
 
        self.assertPathDoesNotExist('a/.bzr/branch/parent')
335
 
        self.assertEqual('http://example.com', branch.get_parent())
336
 
        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')
337
205
        config = branch.get_config()._get_branch_data_config()
338
 
        self.assertEqual('sftp://example.com',
 
206
        self.assertEqual('sftp://bazaar-vcs.org',
339
207
                         config.get_user_option('push_location'))
340
 
        branch.set_bound_location('ftp://example.com')
341
 
        self.assertPathDoesNotExist('a/.bzr/branch/bound')
342
 
        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())
343
211
 
344
212
    def test_set_revision_history(self):
345
 
        builder = self.make_branch_builder('.', format=self.get_format_name())
346
 
        builder.build_snapshot('foo', None,
347
 
            [('add', ('', None, 'directory', None))],
348
 
            message='foo')
349
 
        builder.build_snapshot('bar', None, [], message='bar')
350
 
        branch = builder.get_branch()
351
 
        branch.lock_write()
352
 
        self.addCleanup(branch.unlock)
353
 
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
354
 
            branch.set_revision_history, ['foo', 'bar'])
355
 
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
356
 
                branch.set_revision_history, ['foo'])
357
 
        self.assertRaises(errors.NotLefthandHistory,
358
 
            self.applyDeprecated, symbol_versioning.deprecated_in((2, 4, 0)),
359
 
            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()
360
252
 
361
253
    def do_checkout_test(self, lightweight=False):
362
 
        tree = self.make_branch_and_tree('source',
363
 
            format=self.get_format_name_subtree())
 
254
        tree = self.make_branch_and_tree('source', format='dirstate-with-subtree')
364
255
        subtree = self.make_branch_and_tree('source/subtree',
365
 
            format=self.get_format_name_subtree())
 
256
            format='dirstate-with-subtree')
366
257
        subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
367
 
            format=self.get_format_name_subtree())
 
258
            format='dirstate-with-subtree')
368
259
        self.build_tree(['source/subtree/file',
369
260
                         'source/subtree/subsubtree/file'])
370
261
        subsubtree.add('file')
375
266
        subtree.commit('a subtree file')
376
267
        subsubtree.commit('a subsubtree file')
377
268
        tree.branch.create_checkout('target', lightweight=lightweight)
378
 
        self.assertPathExists('target')
379
 
        self.assertPathExists('target/subtree')
380
 
        self.assertPathExists('target/subtree/file')
381
 
        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')
382
273
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
383
274
        if lightweight:
384
275
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
385
276
        else:
386
277
            self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
387
278
 
 
279
 
388
280
    def test_checkout_with_references(self):
389
281
        self.do_checkout_test()
390
282
 
392
284
        self.do_checkout_test(lightweight=True)
393
285
 
394
286
    def test_set_push(self):
395
 
        branch = self.make_branch('source', format=self.get_format_name())
 
287
        branch = self.make_branch('source', format='dirstate-tags')
396
288
        branch.get_config().set_user_option('push_location', 'old',
397
289
            store=config.STORE_LOCATION)
398
290
        warnings = []
407
299
        self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
408
300
                         'locations.conf')
409
301
 
410
 
 
411
 
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
412
 
 
413
 
    def get_class(self):
414
 
        return _mod_branch.BzrBranch6
415
 
 
416
 
    def get_format_name(self):
417
 
        return "dirstate-tags"
418
 
 
419
 
    def get_format_name_subtree(self):
420
 
        return "dirstate-with-subtree"
421
 
 
422
 
    def test_set_stacked_on_url_errors(self):
423
 
        branch = self.make_branch('a', format=self.get_format_name())
424
 
        self.assertRaises(errors.UnstackableBranchFormat,
425
 
            branch.set_stacked_on_url, None)
426
 
 
427
 
    def test_default_stacked_location(self):
428
 
        branch = self.make_branch('a', format=self.get_format_name())
429
 
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
430
 
 
431
 
 
432
 
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
433
 
 
434
 
    def get_class(self):
435
 
        return _mod_branch.BzrBranch7
436
 
 
437
 
    def get_format_name(self):
438
 
        return "1.9"
439
 
 
440
 
    def get_format_name_subtree(self):
441
 
        return "development-subtree"
442
 
 
443
 
    def test_set_stacked_on_url_unstackable_repo(self):
444
 
        repo = self.make_repository('a', format='dirstate-tags')
445
 
        control = repo.bzrdir
446
 
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
447
 
        target = self.make_branch('b')
448
 
        self.assertRaises(errors.UnstackableRepositoryFormat,
449
 
            branch.set_stacked_on_url, target.base)
450
 
 
451
 
    def test_clone_stacked_on_unstackable_repo(self):
452
 
        repo = self.make_repository('a', format='dirstate-tags')
453
 
        control = repo.bzrdir
454
 
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
455
 
        # Calling clone should not raise UnstackableRepositoryFormat.
456
 
        cloned_bzrdir = control.clone('cloned')
457
 
 
458
 
    def _test_default_stacked_location(self):
459
 
        branch = self.make_branch('a', format=self.get_format_name())
460
 
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
461
 
 
462
 
    def test_stack_and_unstack(self):
463
 
        branch = self.make_branch('a', format=self.get_format_name())
464
 
        target = self.make_branch_and_tree('b', format=self.get_format_name())
465
 
        branch.set_stacked_on_url(target.branch.base)
466
 
        self.assertEqual(target.branch.base, branch.get_stacked_on_url())
467
 
        revid = target.commit('foo')
468
 
        self.assertTrue(branch.repository.has_revision(revid))
469
 
        branch.set_stacked_on_url(None)
470
 
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
471
 
        self.assertFalse(branch.repository.has_revision(revid))
472
 
 
473
 
    def test_open_opens_stacked_reference(self):
474
 
        branch = self.make_branch('a', format=self.get_format_name())
475
 
        target = self.make_branch_and_tree('b', format=self.get_format_name())
476
 
        branch.set_stacked_on_url(target.branch.base)
477
 
        branch = branch.bzrdir.open_branch()
478
 
        revid = target.commit('foo')
479
 
        self.assertTrue(branch.repository.has_revision(revid))
480
 
 
481
 
 
482
 
class BzrBranch8(tests.TestCaseWithTransport):
483
 
 
484
 
    def make_branch(self, location, format=None):
485
 
        if format is None:
486
 
            format = bzrdir.format_registry.make_bzrdir('1.9')
487
 
            format.set_branch_format(_mod_branch.BzrBranchFormat8())
488
 
        return tests.TestCaseWithTransport.make_branch(
489
 
            self, location, format=format)
490
 
 
491
 
    def create_branch_with_reference(self):
492
 
        branch = self.make_branch('branch')
493
 
        branch._set_all_reference_info({'file-id': ('path', 'location')})
494
 
        return branch
495
 
 
496
 
    @staticmethod
497
 
    def instrument_branch(branch, gets):
498
 
        old_get = branch._transport.get
499
 
        def get(*args, **kwargs):
500
 
            gets.append((args, kwargs))
501
 
            return old_get(*args, **kwargs)
502
 
        branch._transport.get = get
503
 
 
504
 
    def test_reference_info_caching_read_locked(self):
505
 
        gets = []
506
 
        branch = self.create_branch_with_reference()
507
 
        branch.lock_read()
508
 
        self.addCleanup(branch.unlock)
509
 
        self.instrument_branch(branch, gets)
510
 
        branch.get_reference_info('file-id')
511
 
        branch.get_reference_info('file-id')
512
 
        self.assertEqual(1, len(gets))
513
 
 
514
 
    def test_reference_info_caching_read_unlocked(self):
515
 
        gets = []
516
 
        branch = self.create_branch_with_reference()
517
 
        self.instrument_branch(branch, gets)
518
 
        branch.get_reference_info('file-id')
519
 
        branch.get_reference_info('file-id')
520
 
        self.assertEqual(2, len(gets))
521
 
 
522
 
    def test_reference_info_caching_write_locked(self):
523
 
        gets = []
524
 
        branch = self.make_branch('branch')
525
 
        branch.lock_write()
526
 
        self.instrument_branch(branch, gets)
527
 
        self.addCleanup(branch.unlock)
528
 
        branch._set_all_reference_info({'file-id': ('path2', 'location2')})
529
 
        path, location = branch.get_reference_info('file-id')
530
 
        self.assertEqual(0, len(gets))
531
 
        self.assertEqual('path2', path)
532
 
        self.assertEqual('location2', location)
533
 
 
534
 
    def test_reference_info_caches_cleared(self):
535
 
        branch = self.make_branch('branch')
536
 
        branch.lock_write()
537
 
        branch.set_reference_info('file-id', 'path2', 'location2')
538
 
        branch.unlock()
539
 
        doppelganger = _mod_branch.Branch.open('branch')
540
 
        doppelganger.set_reference_info('file-id', 'path3', 'location3')
541
 
        self.assertEqual(('path3', 'location3'),
542
 
                         branch.get_reference_info('file-id'))
543
 
 
544
 
class TestBranchReference(tests.TestCaseWithTransport):
 
302
class TestBranchReference(TestCaseWithTransport):
545
303
    """Tests for the branch reference facility."""
546
304
 
547
305
    def test_create_open_reference(self):
548
306
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
549
 
        t = self.get_transport()
 
307
        t = get_transport(self.get_url('.'))
550
308
        t.mkdir('repo')
551
309
        dir = bzrdirformat.initialize(self.get_url('repo'))
552
310
        dir.create_repository()
553
311
        target_branch = dir.create_branch()
554
312
        t.mkdir('branch')
555
313
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
556
 
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
557
 
            branch_dir, target_branch=target_branch)
 
314
        made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
558
315
        self.assertEqual(made_branch.base, target_branch.base)
559
316
        opened_branch = branch_dir.open_branch()
560
317
        self.assertEqual(opened_branch.base, target_branch.base)
571
328
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
572
329
 
573
330
 
574
 
class TestHooks(tests.TestCaseWithTransport):
 
331
class TestHooks(TestCase):
575
332
 
576
333
    def test_constructor(self):
577
334
        """Check that creating a BranchHooks instance has the right defaults."""
578
 
        hooks = _mod_branch.BranchHooks()
 
335
        hooks = BranchHooks()
579
336
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
580
337
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
581
338
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
582
 
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
583
339
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
584
 
        self.assertTrue("post_uncommit" in hooks,
585
 
                        "post_uncommit not in %s" % hooks)
586
 
        self.assertTrue("post_change_branch_tip" in hooks,
587
 
                        "post_change_branch_tip not in %s" % hooks)
588
 
        self.assertTrue("post_branch_init" in hooks,
589
 
                        "post_branch_init not in %s" % hooks)
590
 
        self.assertTrue("post_switch" in hooks,
591
 
                        "post_switch not in %s" % hooks)
 
340
        self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
592
341
 
593
342
    def test_installed_hooks_are_BranchHooks(self):
594
343
        """The installed hooks object should be a BranchHooks."""
595
344
        # the installed hooks are saved in self._preserved_hooks.
596
 
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
597
 
                              _mod_branch.BranchHooks)
598
 
 
599
 
    def test_post_branch_init_hook(self):
600
 
        calls = []
601
 
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
602
 
            calls.append, None)
603
 
        self.assertLength(0, calls)
604
 
        branch = self.make_branch('a')
605
 
        self.assertLength(1, calls)
606
 
        params = calls[0]
607
 
        self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
608
 
        self.assertTrue(hasattr(params, 'bzrdir'))
609
 
        self.assertTrue(hasattr(params, 'branch'))
610
 
 
611
 
    def test_post_branch_init_hook_repr(self):
612
 
        param_reprs = []
613
 
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
614
 
            lambda params: param_reprs.append(repr(params)), None)
615
 
        branch = self.make_branch('a')
616
 
        self.assertLength(1, param_reprs)
617
 
        param_repr = param_reprs[0]
618
 
        self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
619
 
 
620
 
    def test_post_switch_hook(self):
621
 
        from bzrlib import switch
622
 
        calls = []
623
 
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
624
 
            calls.append, None)
625
 
        tree = self.make_branch_and_tree('branch-1')
626
 
        self.build_tree(['branch-1/file-1'])
627
 
        tree.add('file-1')
628
 
        tree.commit('rev1')
629
 
        to_branch = tree.bzrdir.sprout('branch-2').open_branch()
630
 
        self.build_tree(['branch-1/file-2'])
631
 
        tree.add('file-2')
632
 
        tree.remove('file-1')
633
 
        tree.commit('rev2')
634
 
        checkout = tree.branch.create_checkout('checkout')
635
 
        self.assertLength(0, calls)
636
 
        switch.switch(checkout.bzrdir, to_branch)
637
 
        self.assertLength(1, calls)
638
 
        params = calls[0]
639
 
        self.assertIsInstance(params, _mod_branch.SwitchHookParams)
640
 
        self.assertTrue(hasattr(params, 'to_branch'))
641
 
        self.assertTrue(hasattr(params, 'revision_id'))
642
 
 
643
 
 
644
 
class TestBranchOptions(tests.TestCaseWithTransport):
645
 
 
646
 
    def setUp(self):
647
 
        super(TestBranchOptions, self).setUp()
648
 
        self.branch = self.make_branch('.')
649
 
        self.config = self.branch.get_config()
650
 
 
651
 
    def check_append_revisions_only(self, expected_value, value=None):
652
 
        """Set append_revisions_only in config and check its interpretation."""
653
 
        if value is not None:
654
 
            self.config.set_user_option('append_revisions_only', value)
655
 
        self.assertEqual(expected_value,
656
 
                         self.branch.get_append_revisions_only())
657
 
 
658
 
    def test_valid_append_revisions_only(self):
659
 
        self.assertEquals(None,
660
 
                          self.config.get_user_option('append_revisions_only'))
661
 
        self.check_append_revisions_only(None)
662
 
        self.check_append_revisions_only(False, 'False')
663
 
        self.check_append_revisions_only(True, 'True')
664
 
        # The following values will cause compatibility problems on projects
665
 
        # using older bzr versions (<2.2) but are accepted
666
 
        self.check_append_revisions_only(False, 'false')
667
 
        self.check_append_revisions_only(True, 'true')
668
 
 
669
 
    def test_invalid_append_revisions_only(self):
670
 
        """Ensure warning is noted on invalid settings"""
671
 
        self.warnings = []
672
 
        def warning(*args):
673
 
            self.warnings.append(args[0] % args[1:])
674
 
        self.overrideAttr(trace, 'warning', warning)
675
 
        self.check_append_revisions_only(None, 'not-a-bool')
676
 
        self.assertLength(1, self.warnings)
677
 
        self.assertEqual(
678
 
            'Value "not-a-bool" is not a boolean for "append_revisions_only"',
679
 
            self.warnings[0])
680
 
 
681
 
 
682
 
class TestPullResult(tests.TestCase):
 
345
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch], BranchHooks)
 
346
 
 
347
 
 
348
class TestPullResult(TestCase):
683
349
 
684
350
    def test_pull_result_to_int(self):
685
351
        # to support old code, the pull result can be used as an int
686
 
        r = _mod_branch.PullResult()
 
352
        r = PullResult()
687
353
        r.old_revno = 10
688
354
        r.new_revno = 20
689
355
        # this usage of results is not recommended for new code (because it
690
356
        # doesn't describe very well what happened), but for api stability
691
357
        # it's still supported
692
 
        self.assertEqual(self.applyDeprecated(
693
 
            symbol_versioning.deprecated_in((2, 3, 0)),
694
 
            r.__int__),
695
 
            10)
696
 
 
697
 
    def test_report_changed(self):
698
 
        r = _mod_branch.PullResult()
699
 
        r.old_revid = "old-revid"
700
 
        r.old_revno = 10
701
 
        r.new_revid = "new-revid"
702
 
        r.new_revno = 20
703
 
        f = StringIO()
704
 
        r.report(f)
705
 
        self.assertEqual("Now on revision 20.\n", f.getvalue())
706
 
 
707
 
    def test_report_unchanged(self):
708
 
        r = _mod_branch.PullResult()
709
 
        r.old_revid = "same-revid"
710
 
        r.new_revid = "same-revid"
711
 
        f = StringIO()
712
 
        r.report(f)
713
 
        self.assertEqual("No revisions or tags to pull.\n", f.getvalue())
714
 
 
 
358
        a = "%d revisions pulled" % r
 
359
        self.assertEqual(a, "10 revisions pulled")