~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: Patch Queue Manager
  • Date: 2011-09-22 14:12:18 UTC
  • mfrom: (6155.3.1 jam)
  • Revision ID: pqm@pqm.ubuntu.com-20110922141218-86s4uu6nqvourw4f
(jameinel) Cleanup comments bzrlib/smart/__init__.py (John A Meinel)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2011 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for the Branch facility that are not interface  tests.
18
18
 
19
 
For interface tests see tests/branch_implementations/*.py.
 
19
For interface tests see `tests/per_branch/*.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 StringIO import StringIO
26
 
 
27
 
import bzrlib.branch
28
 
from bzrlib.branch import (BzrBranch5, 
29
 
                           BzrBranchFormat5)
30
 
import bzrlib.bzrdir as bzrdir
31
 
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1, 
32
 
                           BzrDir, BzrDirFormat)
33
 
from bzrlib.errors import (NotBranchError,
34
 
                           UnknownFormatError,
35
 
                           UnsupportedFormatError,
36
 
                           )
37
 
 
38
 
from bzrlib.tests import TestCase, TestCaseWithTransport
39
 
from bzrlib.transport import get_transport
40
 
 
41
 
class TestDefaultFormat(TestCase):
 
25
from cStringIO import StringIO
 
26
 
 
27
from bzrlib import (
 
28
    branch as _mod_branch,
 
29
    bzrdir,
 
30
    config,
 
31
    errors,
 
32
    symbol_versioning,
 
33
    tests,
 
34
    trace,
 
35
    urlutils,
 
36
    )
 
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())
42
53
 
43
54
    def test_get_set_default_format(self):
44
 
        old_format = bzrlib.branch.BranchFormat.get_default_format()
45
 
        # default is 5
46
 
        self.assertTrue(isinstance(old_format, bzrlib.branch.BzrBranchFormat5))
47
 
        bzrlib.branch.BranchFormat.set_default_format(SampleBranchFormat())
 
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())
48
58
        try:
49
59
            # the default branch format is used by the meta dir format
50
60
            # which is not the default bzrdir format at this point
51
 
            dir = BzrDirMetaFormat1().initialize('memory:///')
 
61
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
52
62
            result = dir.create_branch()
53
63
            self.assertEqual(result, 'A branch')
54
64
        finally:
55
 
            bzrlib.branch.BranchFormat.set_default_format(old_format)
56
 
        self.assertEqual(old_format, bzrlib.branch.BranchFormat.get_default_format())
57
 
 
58
 
 
59
 
class TestBranchFormat5(TestCaseWithTransport):
 
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):
60
71
    """Tests specific to branch format 5"""
61
72
 
62
73
    def test_branch_format_5_uses_lockdir(self):
63
74
        url = self.get_url()
64
 
        bzrdir = BzrDirMetaFormat1().initialize(url)
65
 
        bzrdir.create_repository()
66
 
        branch = bzrdir.create_branch()
 
75
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
 
76
        bdir.create_repository()
 
77
        branch = _mod_branch.BzrBranchFormat5().initialize(bdir)
67
78
        t = self.get_transport()
68
79
        self.log("branch instance is %r" % branch)
69
 
        self.assert_(isinstance(branch, BzrBranch5))
 
80
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
70
81
        self.assertIsDirectory('.', t)
71
82
        self.assertIsDirectory('.bzr/branch', t)
72
83
        self.assertIsDirectory('.bzr/branch/lock', t)
73
84
        branch.lock_write()
74
 
        try:
75
 
            self.assertIsDirectory('.bzr/branch/lock/held', t)
76
 
        finally:
77
 
            branch.unlock()
78
 
 
79
 
 
80
 
class TestBranchEscaping(TestCaseWithTransport):
81
 
    """Test a branch can be correctly stored and used on a vfat-like transport
82
 
    
83
 
    Makes sure we have proper escaping of invalid characters, etc.
84
 
 
85
 
    It'd be better to test all operations on the FakeVFATTransportDecorator,
86
 
    but working trees go straight to the os not through the Transport layer.
87
 
    Therefore we build some history first in the regular way and then 
88
 
    check it's safe to access for vfat.
89
 
    """
90
 
 
91
 
    FOO_ID = 'foo<:>ID'
92
 
    REV_ID = 'revid-1'
93
 
 
94
 
    def setUp(self):
95
 
        super(TestBranchEscaping, self).setUp()
96
 
        from bzrlib.repository import RepositoryFormatKnit1
97
 
        bzrdir = BzrDirMetaFormat1().initialize(self.get_url())
98
 
        repo = RepositoryFormatKnit1().initialize(bzrdir)
99
 
        branch = bzrdir.create_branch()
100
 
        wt = bzrdir.create_workingtree()
101
 
        self.build_tree_contents([("foo", "contents of foo")])
102
 
        # add file with id containing wierd characters
103
 
        wt.add(['foo'], [self.FOO_ID])
104
 
        wt.commit('this is my new commit', rev_id=self.REV_ID)
105
 
 
106
 
    def test_branch_on_vfat(self):
107
 
        from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
108
 
        # now access over vfat; should be safe
109
 
        transport = FakeVFATTransportDecorator('vfat+' + self.get_url())
110
 
        bzrdir, junk = BzrDir.open_containing_from_transport(transport)
111
 
        branch = bzrdir.open_branch()
112
 
        revtree = branch.repository.revision_tree(self.REV_ID)
113
 
        contents = revtree.get_file_text(self.FOO_ID)
114
 
        self.assertEqual(contents, 'contents of foo')
115
 
 
116
 
 
117
 
class SampleBranchFormat(bzrlib.branch.BranchFormat):
 
85
        self.addCleanup(branch.unlock)
 
86
        self.assertIsDirectory('.bzr/branch/lock/held', t)
 
87
 
 
88
    def test_set_push_location(self):
 
89
        conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
 
90
 
 
91
        branch = self.make_branch('.', format='knit')
 
92
        branch.set_push_location('foo')
 
93
        local_path = urlutils.local_path_from_url(branch.base[:-1])
 
94
        self.assertFileEqual("# comment\n"
 
95
                             "[%s]\n"
 
96
                             "push_location = foo\n"
 
97
                             "push_location:policy = norecurse\n" % local_path,
 
98
                             config.locations_config_filename())
 
99
 
 
100
    # TODO RBC 20051029 test getting a push location from a branch in a
 
101
    # recursive section - that is, it appends the branch name.
 
102
 
 
103
 
 
104
class SampleBranchFormat(_mod_branch.BranchFormat):
118
105
    """A sample format
119
106
 
120
 
    this format is initializable, unsupported to aid in testing the 
 
107
    this format is initializable, unsupported to aid in testing the
121
108
    open and open_downlevel routines.
122
109
    """
123
110
 
125
112
        """See BzrBranchFormat.get_format_string()."""
126
113
        return "Sample branch format."
127
114
 
128
 
    def initialize(self, a_bzrdir):
 
115
    def initialize(self, a_bzrdir, name=None, repository=None,
 
116
                   append_revisions_only=None):
129
117
        """Format 4 branches cannot be created."""
130
 
        t = a_bzrdir.get_branch_transport(self)
131
 
        t.put('format', StringIO(self.get_format_string()))
 
118
        t = a_bzrdir.get_branch_transport(self, name=name)
 
119
        t.put_bytes('format', self.get_format_string())
132
120
        return 'A branch'
133
121
 
134
122
    def is_supported(self):
135
123
        return False
136
124
 
137
 
    def open(self, transport, _found=False):
 
125
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
138
126
        return "opened branch."
139
127
 
140
128
 
141
 
class TestBzrBranchFormat(TestCaseWithTransport):
 
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):
142
169
    """Tests for the BzrBranchFormat facility."""
143
170
 
144
171
    def test_find_format(self):
145
172
        # is the right format object found for a branch?
146
173
        # create a branch with a few known format objects.
147
 
        # this is not quite the same as 
 
174
        # this is not quite the same as
148
175
        self.build_tree(["foo/", "bar/"])
149
176
        def check_format(format, url):
150
177
            dir = format._matchingbzrdir.initialize(url)
151
178
            dir.create_repository()
152
179
            format.initialize(dir)
153
 
            found_format = bzrlib.branch.BranchFormat.find_format(dir)
154
 
            self.failUnless(isinstance(found_format, format.__class__))
155
 
        check_format(bzrlib.branch.BzrBranchFormat5(), "bar")
156
 
        
 
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
 
157
195
    def test_find_format_not_branch(self):
158
196
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
159
 
        self.assertRaises(NotBranchError,
160
 
                          bzrlib.branch.BranchFormat.find_format,
 
197
        self.assertRaises(errors.NotBranchError,
 
198
                          _mod_branch.BranchFormat.find_format,
161
199
                          dir)
162
200
 
163
201
    def test_find_format_unknown_format(self):
164
202
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
165
203
        SampleBranchFormat().initialize(dir)
166
 
        self.assertRaises(UnknownFormatError,
167
 
                          bzrlib.branch.BranchFormat.find_format,
 
204
        self.assertRaises(errors.UnknownFormatError,
 
205
                          _mod_branch.BranchFormat.find_format,
168
206
                          dir)
169
207
 
170
208
    def test_register_unregister_format(self):
 
209
        # Test the deprecated format registration functions
171
210
        format = SampleBranchFormat()
172
211
        # make a control dir
173
212
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
174
213
        # make a branch
175
214
        format.initialize(dir)
176
215
        # register a format for it.
177
 
        bzrlib.branch.BranchFormat.register_format(format)
 
216
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
217
            _mod_branch.BranchFormat.register_format, format)
178
218
        # which branch.Open will refuse (not supported)
179
 
        self.assertRaises(UnsupportedFormatError, bzrlib.branch.Branch.open, self.get_url())
 
219
        self.assertRaises(errors.UnsupportedFormatError,
 
220
                          _mod_branch.Branch.open, self.get_url())
 
221
        self.make_branch_and_tree('foo')
180
222
        # but open_downlevel will work
181
 
        self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
 
223
        self.assertEqual(
 
224
            format.open(dir),
 
225
            bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
182
226
        # unregister the format
183
 
        bzrlib.branch.BranchFormat.unregister_format(format)
184
 
 
185
 
 
186
 
class TestBranchReference(TestCaseWithTransport):
 
227
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
228
            _mod_branch.BranchFormat.unregister_format, format)
 
229
        self.make_branch_and_tree('bar')
 
230
 
 
231
 
 
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)
 
313
 
 
314
    def test_creation(self):
 
315
        format = bzrdir.BzrDirMetaFormat1()
 
316
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
 
317
        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())
 
321
        branch = _mod_branch.Branch.open('a')
 
322
        self.assertIsInstance(branch, self.get_class())
 
323
 
 
324
    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')
 
329
 
 
330
    def test_config(self):
 
331
        """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')
 
337
        config = branch.get_config()._get_branch_data_config()
 
338
        self.assertEqual('sftp://example.com',
 
339
                         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())
 
343
 
 
344
    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'])
 
360
 
 
361
    def do_checkout_test(self, lightweight=False):
 
362
        tree = self.make_branch_and_tree('source',
 
363
            format=self.get_format_name_subtree())
 
364
        subtree = self.make_branch_and_tree('source/subtree',
 
365
            format=self.get_format_name_subtree())
 
366
        subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
 
367
            format=self.get_format_name_subtree())
 
368
        self.build_tree(['source/subtree/file',
 
369
                         'source/subtree/subsubtree/file'])
 
370
        subsubtree.add('file')
 
371
        subtree.add('file')
 
372
        subtree.add_reference(subsubtree)
 
373
        tree.add_reference(subtree)
 
374
        tree.commit('a revision')
 
375
        subtree.commit('a subtree file')
 
376
        subsubtree.commit('a subsubtree file')
 
377
        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')
 
382
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
 
383
        if lightweight:
 
384
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
 
385
        else:
 
386
            self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
 
387
 
 
388
    def test_checkout_with_references(self):
 
389
        self.do_checkout_test()
 
390
 
 
391
    def test_light_checkout_with_references(self):
 
392
        self.do_checkout_test(lightweight=True)
 
393
 
 
394
    def test_set_push(self):
 
395
        branch = self.make_branch('source', format=self.get_format_name())
 
396
        branch.get_config().set_user_option('push_location', 'old',
 
397
            store=config.STORE_LOCATION)
 
398
        warnings = []
 
399
        def warning(*args):
 
400
            warnings.append(args[0] % args[1:])
 
401
        _warning = trace.warning
 
402
        trace.warning = warning
 
403
        try:
 
404
            branch.set_push_location('new')
 
405
        finally:
 
406
            trace.warning = _warning
 
407
        self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
 
408
                         'locations.conf')
 
409
 
 
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):
187
545
    """Tests for the branch reference facility."""
188
546
 
189
547
    def test_create_open_reference(self):
190
548
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
191
 
        t = get_transport(self.get_url('.'))
 
549
        t = self.get_transport()
192
550
        t.mkdir('repo')
193
551
        dir = bzrdirformat.initialize(self.get_url('repo'))
194
552
        dir.create_repository()
195
553
        target_branch = dir.create_branch()
196
554
        t.mkdir('branch')
197
555
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
198
 
        made_branch = bzrlib.branch.BranchReferenceFormat().initialize(branch_dir, target_branch)
 
556
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
 
557
            branch_dir, target_branch=target_branch)
199
558
        self.assertEqual(made_branch.base, target_branch.base)
200
559
        opened_branch = branch_dir.open_branch()
201
560
        self.assertEqual(opened_branch.base, target_branch.base)
 
561
 
 
562
    def test_get_reference(self):
 
563
        """For a BranchReference, get_reference should reutrn the location."""
 
564
        branch = self.make_branch('target')
 
565
        checkout = branch.create_checkout('checkout', lightweight=True)
 
566
        reference_url = branch.bzrdir.root_transport.abspath('') + '/'
 
567
        # if the api for create_checkout changes to return different checkout types
 
568
        # then this file read will fail.
 
569
        self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
 
570
        self.assertEqual(reference_url,
 
571
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
 
572
 
 
573
 
 
574
class TestHooks(tests.TestCaseWithTransport):
 
575
 
 
576
    def test_constructor(self):
 
577
        """Check that creating a BranchHooks instance has the right defaults."""
 
578
        hooks = _mod_branch.BranchHooks()
 
579
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
 
580
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
 
581
        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
        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)
 
592
 
 
593
    def test_installed_hooks_are_BranchHooks(self):
 
594
        """The installed hooks object should be a BranchHooks."""
 
595
        # 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):
 
683
 
 
684
    def test_pull_result_to_int(self):
 
685
        # to support old code, the pull result can be used as an int
 
686
        r = _mod_branch.PullResult()
 
687
        r.old_revno = 10
 
688
        r.new_revno = 20
 
689
        # this usage of results is not recommended for new code (because it
 
690
        # doesn't describe very well what happened), but for api stability
 
691
        # 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