~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: John Arbash Meinel
  • Date: 2006-08-18 16:48:53 UTC
  • mto: (1946.2.6 reduce-knit-churn)
  • mto: This revision was merged to the branch mainline in revision 1948.
  • Revision ID: john@arbash-meinel.com-20060818164853-eb25e4db3385e216
Add a couple more sftp benchmarks

Show diffs side-by-side

added added

removed removed

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