~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: Aaron Bentley
  • Date: 2007-02-06 14:52:16 UTC
  • mfrom: (2266 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2268.
  • Revision ID: abentley@panoramicfeedback.com-20070206145216-fcpi8o3ufvuzwbp9
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 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
24
24
 
25
25
from StringIO import StringIO
26
26
 
27
 
from bzrlib import (
28
 
    branch as _mod_branch,
29
 
    bzrdir,
30
 
    config,
31
 
    errors,
32
 
    trace,
33
 
    urlutils,
34
 
    )
35
 
from bzrlib.branch import (
36
 
    Branch,
37
 
    BranchHooks,
38
 
    BranchFormat,
39
 
    BranchReferenceFormat,
40
 
    BzrBranch5,
41
 
    BzrBranchFormat5,
42
 
    BzrBranchFormat6,
43
 
    PullResult,
44
 
    )
 
27
import bzrlib.branch
 
28
from bzrlib.branch import (BzrBranch5, 
 
29
                           BzrBranchFormat5)
 
30
import bzrlib.bzrdir as bzrdir
45
31
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1, 
46
32
                           BzrDir, BzrDirFormat)
47
33
from bzrlib.errors import (NotBranchError,
53
39
from bzrlib.tests import TestCase, TestCaseWithTransport
54
40
from bzrlib.transport import get_transport
55
41
 
56
 
 
57
42
class TestDefaultFormat(TestCase):
58
43
 
59
 
    def test_default_format(self):
60
 
        # update this if you change the default branch format
61
 
        self.assertIsInstance(BranchFormat.get_default_format(),
62
 
                BzrBranchFormat6)
63
 
 
64
 
    def test_default_format_is_same_as_bzrdir_default(self):
65
 
        # XXX: it might be nice if there was only one place the default was
66
 
        # set, but at the moment that's not true -- mbp 20070814 -- 
67
 
        # https://bugs.launchpad.net/bzr/+bug/132376
68
 
        self.assertEqual(BranchFormat.get_default_format(),
69
 
                BzrDirFormat.get_default_format().get_branch_format())
70
 
 
71
44
    def test_get_set_default_format(self):
72
 
        # set the format and then set it back again
73
 
        old_format = BranchFormat.get_default_format()
74
 
        BranchFormat.set_default_format(SampleBranchFormat())
 
45
        old_format = bzrlib.branch.BranchFormat.get_default_format()
 
46
        # default is 5
 
47
        self.assertTrue(isinstance(old_format, bzrlib.branch.BzrBranchFormat5))
 
48
        bzrlib.branch.BranchFormat.set_default_format(SampleBranchFormat())
75
49
        try:
76
50
            # the default branch format is used by the meta dir format
77
51
            # which is not the default bzrdir format at this point
79
53
            result = dir.create_branch()
80
54
            self.assertEqual(result, 'A branch')
81
55
        finally:
82
 
            BranchFormat.set_default_format(old_format)
83
 
        self.assertEqual(old_format, BranchFormat.get_default_format())
 
56
            bzrlib.branch.BranchFormat.set_default_format(old_format)
 
57
        self.assertEqual(old_format, bzrlib.branch.BranchFormat.get_default_format())
84
58
 
85
59
 
86
60
class TestBranchFormat5(TestCaseWithTransport):
103
77
        finally:
104
78
            branch.unlock()
105
79
 
106
 
    def test_set_push_location(self):
107
 
        from bzrlib.config import (locations_config_filename,
108
 
                                   ensure_config_dir_exists)
109
 
        ensure_config_dir_exists()
110
 
        fn = locations_config_filename()
111
 
        # write correct newlines to locations.conf
112
 
        # by default ConfigObj uses native line-endings for new files
113
 
        # but uses already existing line-endings if file is not empty
114
 
        f = open(fn, 'wb')
115
 
        try:
116
 
            f.write('# comment\n')
117
 
        finally:
118
 
            f.close()
119
 
 
120
 
        branch = self.make_branch('.', format='knit')
121
 
        branch.set_push_location('foo')
122
 
        local_path = urlutils.local_path_from_url(branch.base[:-1])
123
 
        self.assertFileEqual("# comment\n"
124
 
                             "[%s]\n"
125
 
                             "push_location = foo\n"
126
 
                             "push_location:policy = norecurse\n" % local_path,
127
 
                             fn)
128
 
 
129
 
    # TODO RBC 20051029 test getting a push location from a branch in a
130
 
    # recursive section - that is, it appends the branch name.
131
 
 
132
 
 
133
 
class SampleBranchFormat(BranchFormat):
 
80
 
 
81
class SampleBranchFormat(bzrlib.branch.BranchFormat):
134
82
    """A sample format
135
83
 
136
84
    this format is initializable, unsupported to aid in testing the 
166
114
            dir = format._matchingbzrdir.initialize(url)
167
115
            dir.create_repository()
168
116
            format.initialize(dir)
169
 
            found_format = BranchFormat.find_format(dir)
 
117
            found_format = bzrlib.branch.BranchFormat.find_format(dir)
170
118
            self.failUnless(isinstance(found_format, format.__class__))
171
 
        check_format(BzrBranchFormat5(), "bar")
 
119
        check_format(bzrlib.branch.BzrBranchFormat5(), "bar")
172
120
        
173
121
    def test_find_format_not_branch(self):
174
122
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
175
123
        self.assertRaises(NotBranchError,
176
 
                          BranchFormat.find_format,
 
124
                          bzrlib.branch.BranchFormat.find_format,
177
125
                          dir)
178
126
 
179
127
    def test_find_format_unknown_format(self):
180
128
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
181
129
        SampleBranchFormat().initialize(dir)
182
130
        self.assertRaises(UnknownFormatError,
183
 
                          BranchFormat.find_format,
 
131
                          bzrlib.branch.BranchFormat.find_format,
184
132
                          dir)
185
133
 
186
134
    def test_register_unregister_format(self):
190
138
        # make a branch
191
139
        format.initialize(dir)
192
140
        # register a format for it.
193
 
        BranchFormat.register_format(format)
 
141
        bzrlib.branch.BranchFormat.register_format(format)
194
142
        # which branch.Open will refuse (not supported)
195
 
        self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
196
 
        self.make_branch_and_tree('foo')
 
143
        self.assertRaises(UnsupportedFormatError, bzrlib.branch.Branch.open, self.get_url())
197
144
        # but open_downlevel will work
198
145
        self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
199
146
        # unregister the format
200
 
        BranchFormat.unregister_format(format)
201
 
        self.make_branch_and_tree('bar')
202
 
 
203
 
 
204
 
class TestBranch67(object):
205
 
    """Common tests for both branch 6 and 7 which are mostly the same."""
206
 
 
207
 
    def get_format_name(self):
208
 
        raise NotImplementedError(self.get_format_name)
209
 
 
210
 
    def get_format_name_subtree(self):
211
 
        raise NotImplementedError(self.get_format_name)
212
 
 
213
 
    def get_class(self):
214
 
        raise NotImplementedError(self.get_class)
215
 
 
216
 
    def test_creation(self):
217
 
        format = BzrDirMetaFormat1()
218
 
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
219
 
        branch = self.make_branch('a', format=format)
220
 
        self.assertIsInstance(branch, self.get_class())
221
 
        branch = self.make_branch('b', format=self.get_format_name())
222
 
        self.assertIsInstance(branch, self.get_class())
223
 
        branch = _mod_branch.Branch.open('a')
224
 
        self.assertIsInstance(branch, self.get_class())
225
 
 
226
 
    def test_layout(self):
227
 
        branch = self.make_branch('a', format=self.get_format_name())
228
 
        self.failUnlessExists('a/.bzr/branch/last-revision')
229
 
        self.failIfExists('a/.bzr/branch/revision-history')
230
 
 
231
 
    def test_config(self):
232
 
        """Ensure that all configuration data is stored in the branch"""
233
 
        branch = self.make_branch('a', format=self.get_format_name())
234
 
        branch.set_parent('http://bazaar-vcs.org')
235
 
        self.failIfExists('a/.bzr/branch/parent')
236
 
        self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
237
 
        branch.set_push_location('sftp://bazaar-vcs.org')
238
 
        config = branch.get_config()._get_branch_data_config()
239
 
        self.assertEqual('sftp://bazaar-vcs.org',
240
 
                         config.get_user_option('push_location'))
241
 
        branch.set_bound_location('ftp://bazaar-vcs.org')
242
 
        self.failIfExists('a/.bzr/branch/bound')
243
 
        self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
244
 
 
245
 
    def test_set_revision_history(self):
246
 
        builder = self.make_branch_builder('.', format=self.get_format_name())
247
 
        builder.build_snapshot('foo', None,
248
 
            [('add', ('', None, 'directory', None))],
249
 
            message='foo')
250
 
        builder.build_snapshot('bar', None, [], message='bar')
251
 
        branch = builder.get_branch()
252
 
        branch.lock_write()
253
 
        self.addCleanup(branch.unlock)
254
 
        branch.set_revision_history(['foo', 'bar'])
255
 
        branch.set_revision_history(['foo'])
256
 
        self.assertRaises(errors.NotLefthandHistory,
257
 
                          branch.set_revision_history, ['bar'])
258
 
 
259
 
    def do_checkout_test(self, lightweight=False):
260
 
        tree = self.make_branch_and_tree('source',
261
 
            format=self.get_format_name_subtree())
262
 
        subtree = self.make_branch_and_tree('source/subtree',
263
 
            format=self.get_format_name_subtree())
264
 
        subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
265
 
            format=self.get_format_name_subtree())
266
 
        self.build_tree(['source/subtree/file',
267
 
                         'source/subtree/subsubtree/file'])
268
 
        subsubtree.add('file')
269
 
        subtree.add('file')
270
 
        subtree.add_reference(subsubtree)
271
 
        tree.add_reference(subtree)
272
 
        tree.commit('a revision')
273
 
        subtree.commit('a subtree file')
274
 
        subsubtree.commit('a subsubtree file')
275
 
        tree.branch.create_checkout('target', lightweight=lightweight)
276
 
        self.failUnlessExists('target')
277
 
        self.failUnlessExists('target/subtree')
278
 
        self.failUnlessExists('target/subtree/file')
279
 
        self.failUnlessExists('target/subtree/subsubtree/file')
280
 
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
281
 
        if lightweight:
282
 
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
283
 
        else:
284
 
            self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
285
 
 
286
 
    def test_checkout_with_references(self):
287
 
        self.do_checkout_test()
288
 
 
289
 
    def test_light_checkout_with_references(self):
290
 
        self.do_checkout_test(lightweight=True)
291
 
 
292
 
    def test_set_push(self):
293
 
        branch = self.make_branch('source', format=self.get_format_name())
294
 
        branch.get_config().set_user_option('push_location', 'old',
295
 
            store=config.STORE_LOCATION)
296
 
        warnings = []
297
 
        def warning(*args):
298
 
            warnings.append(args[0] % args[1:])
299
 
        _warning = trace.warning
300
 
        trace.warning = warning
301
 
        try:
302
 
            branch.set_push_location('new')
303
 
        finally:
304
 
            trace.warning = _warning
305
 
        self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
306
 
                         'locations.conf')
307
 
 
308
 
 
309
 
class TestBranch6(TestBranch67, TestCaseWithTransport):
310
 
 
311
 
    def get_class(self):
312
 
        return _mod_branch.BzrBranch6
313
 
 
314
 
    def get_format_name(self):
315
 
        return "dirstate-tags"
316
 
 
317
 
    def get_format_name_subtree(self):
318
 
        return "dirstate-with-subtree"
319
 
 
320
 
    def test_set_stacked_on_url_errors(self):
321
 
        branch = self.make_branch('a', format=self.get_format_name())
322
 
        self.assertRaises(errors.UnstackableBranchFormat,
323
 
            branch.set_stacked_on_url, None)
324
 
 
325
 
    def test_default_stacked_location(self):
326
 
        branch = self.make_branch('a', format=self.get_format_name())
327
 
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
328
 
 
329
 
 
330
 
class TestBranch7(TestBranch67, TestCaseWithTransport):
331
 
 
332
 
    def get_class(self):
333
 
        return _mod_branch.BzrBranch7
334
 
 
335
 
    def get_format_name(self):
336
 
        return "development"
337
 
 
338
 
    def get_format_name_subtree(self):
339
 
        return "development-subtree"
340
 
 
341
 
    def test_set_stacked_on_url_unstackable_repo(self):
342
 
        repo = self.make_repository('a', format='dirstate-tags')
343
 
        control = repo.bzrdir
344
 
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
345
 
        target = self.make_branch('b')
346
 
        self.assertRaises(errors.UnstackableRepositoryFormat,
347
 
            branch.set_stacked_on_url, target.base)
348
 
 
349
 
    def test_clone_stacked_on_unstackable_repo(self):
350
 
        repo = self.make_repository('a', format='dirstate-tags')
351
 
        control = repo.bzrdir
352
 
        branch = _mod_branch.BzrBranchFormat7().initialize(control)
353
 
        # Calling clone should not raise UnstackableRepositoryFormat.
354
 
        cloned_bzrdir = control.clone('cloned')
355
 
 
356
 
    def _test_default_stacked_location(self):
357
 
        branch = self.make_branch('a', format=self.get_format_name())
358
 
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
359
 
 
360
 
    def test_stack_and_unstack(self):
361
 
        branch = self.make_branch('a', format=self.get_format_name())
362
 
        target = self.make_branch_and_tree('b', format=self.get_format_name())
363
 
        branch.set_stacked_on_url(target.branch.base)
364
 
        self.assertEqual(target.branch.base, branch.get_stacked_on_url())
365
 
        revid = target.commit('foo')
366
 
        self.assertTrue(branch.repository.has_revision(revid))
367
 
        branch.set_stacked_on_url(None)
368
 
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
369
 
        self.assertFalse(branch.repository.has_revision(revid))
370
 
 
371
 
    def test_open_opens_stacked_reference(self):
372
 
        branch = self.make_branch('a', format=self.get_format_name())
373
 
        target = self.make_branch_and_tree('b', format=self.get_format_name())
374
 
        branch.set_stacked_on_url(target.branch.base)
375
 
        branch = branch.bzrdir.open_branch()
376
 
        revid = target.commit('foo')
377
 
        self.assertTrue(branch.repository.has_revision(revid))
 
147
        bzrlib.branch.BranchFormat.unregister_format(format)
378
148
 
379
149
 
380
150
class TestBranchReference(TestCaseWithTransport):
389
159
        target_branch = dir.create_branch()
390
160
        t.mkdir('branch')
391
161
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
392
 
        made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
 
162
        made_branch = bzrlib.branch.BranchReferenceFormat().initialize(branch_dir, target_branch)
393
163
        self.assertEqual(made_branch.base, target_branch.base)
394
164
        opened_branch = branch_dir.open_branch()
395
165
        self.assertEqual(opened_branch.base, target_branch.base)
396
166
 
397
 
    def test_get_reference(self):
398
 
        """For a BranchReference, get_reference should reutrn the location."""
399
 
        branch = self.make_branch('target')
400
 
        checkout = branch.create_checkout('checkout', lightweight=True)
401
 
        reference_url = branch.bzrdir.root_transport.abspath('') + '/'
402
 
        # if the api for create_checkout changes to return different checkout types
403
 
        # then this file read will fail.
404
 
        self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
405
 
        self.assertEqual(reference_url,
406
 
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
407
 
 
408
167
 
409
168
class TestHooks(TestCase):
410
169
 
411
170
    def test_constructor(self):
412
171
        """Check that creating a BranchHooks instance has the right defaults."""
413
 
        hooks = BranchHooks()
 
172
        hooks = bzrlib.branch.BranchHooks()
414
173
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
415
 
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
416
 
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
417
 
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
418
 
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
419
 
        self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
420
 
        self.assertTrue("post_change_branch_tip" in hooks,
421
 
                        "post_change_branch_tip not in %s" % hooks)
422
174
 
423
175
    def test_installed_hooks_are_BranchHooks(self):
424
176
        """The installed hooks object should be a BranchHooks."""
425
177
        # the installed hooks are saved in self._preserved_hooks.
426
 
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch], BranchHooks)
427
 
 
428
 
 
429
 
class TestPullResult(TestCase):
430
 
 
431
 
    def test_pull_result_to_int(self):
432
 
        # to support old code, the pull result can be used as an int
433
 
        r = PullResult()
434
 
        r.old_revno = 10
435
 
        r.new_revno = 20
436
 
        # this usage of results is not recommended for new code (because it
437
 
        # doesn't describe very well what happened), but for api stability
438
 
        # it's still supported
439
 
        a = "%d revisions pulled" % r
440
 
        self.assertEqual(a, "10 revisions pulled")
 
178
        self.assertIsInstance(self._preserved_hooks, bzrlib.branch.BranchHooks)
 
179
 
 
180
    def test_install_hook_raises_unknown_hook(self):
 
181
        """install_hook should raise UnknownHook if a hook is unknown."""
 
182
        hooks = bzrlib.branch.BranchHooks()
 
183
        self.assertRaises(UnknownHook, hooks.install_hook, 'silly', None)
 
184
 
 
185
    def test_install_hook_appends_known_hook(self):
 
186
        """install_hook should append the callable for known hooks."""
 
187
        hooks = bzrlib.branch.BranchHooks()
 
188
        hooks.install_hook('set_rh', None)
 
189
        self.assertEqual(hooks['set_rh'], [None])