~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/per_branch/test_branch.py

  • Committer: Vincent Ladeuil
  • Date: 2012-03-13 17:25:29 UTC
  • mfrom: (6499 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6501.
  • Revision ID: v.ladeuil+lp@free.fr-20120313172529-i0suyjnepsor25i7
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2012 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
18
18
 
19
19
from bzrlib import (
20
20
    branch as _mod_branch,
21
 
    bzrdir,
 
21
    controldir,
22
22
    config,
23
23
    delta as _mod_delta,
24
24
    errors,
25
 
    gpg,
26
25
    merge,
 
26
    osutils,
27
27
    urlutils,
28
28
    transport,
29
29
    remote,
76
76
        br = self.get_branch()
77
77
        br.fetch(wt.branch)
78
78
        br.generate_revision_history('rev3')
79
 
        rh = br.revision_history()
80
 
        self.assertEqual(['rev1', 'rev2', 'rev3'], rh)
81
 
        for revision_id in rh:
 
79
        for revision_id in ['rev3', 'rev2', 'rev1']:
82
80
            self.assertIsInstance(revision_id, str)
83
81
        last = br.last_revision()
84
82
        self.assertEqual('rev3', last)
114
112
        tree_a.add('vla', 'file2')
115
113
        tree_a.commit('rev2', rev_id='rev2')
116
114
 
117
 
        delta = tree_a.branch.get_revision_delta(1)
 
115
        delta = self.applyDeprecated(symbol_versioning.deprecated_in(
 
116
            (2, 5, 0)), tree_a.branch.get_revision_delta, 1)
118
117
        self.assertIsInstance(delta, _mod_delta.TreeDelta)
119
118
        self.assertEqual([('foo', 'file1', 'file')], delta.added)
120
 
        delta = tree_a.branch.get_revision_delta(2)
 
119
        delta = self.applyDeprecated(symbol_versioning.deprecated_in(
 
120
            (2, 5, 0)), tree_a.branch.get_revision_delta, 2)
121
121
        self.assertIsInstance(delta, _mod_delta.TreeDelta)
122
122
        self.assertEqual([('vla', 'file2', 'file')], delta.added)
123
123
 
215
215
    def test_record_initial_ghost(self):
216
216
        """Branches should support having ghosts."""
217
217
        wt = self.make_branch_and_tree('.')
 
218
        if not wt.branch.repository._format.supports_ghosts:
 
219
            raise tests.TestNotApplicable("repository format does not "
 
220
                "support ghosts")
218
221
        wt.set_parent_ids(['non:existent@rev--ision--0--2'],
219
222
            allow_leftmost_as_ghost=True)
220
223
        self.assertEqual(['non:existent@rev--ision--0--2'],
228
231
    def test_record_two_ghosts(self):
229
232
        """Recording with all ghosts works."""
230
233
        wt = self.make_branch_and_tree('.')
 
234
        if not wt.branch.repository._format.supports_ghosts:
 
235
            raise tests.TestNotApplicable("repository format does not "
 
236
                "support ghosts")
231
237
        wt.set_parent_ids([
232
238
                'foo@azkhazan-123123-abcabc',
233
239
                'wibble@fofof--20050401--1928390812',
245
251
                          self.get_branch().repository.get_revision,
246
252
                          None)
247
253
 
248
 
# TODO 20051003 RBC:
249
 
# compare the gpg-to-sign info for a commit with a ghost and
250
 
#     an identical tree without a ghost
251
 
# fetch missing should rewrite the TOC of weaves to list newly available parents.
252
 
 
253
 
    def test_sign_existing_revision(self):
254
 
        wt = self.make_branch_and_tree('.')
255
 
        branch = wt.branch
256
 
        wt.commit("base", allow_pointless=True, rev_id='A')
257
 
        from bzrlib.testament import Testament
258
 
        strategy = gpg.LoopbackGPGStrategy(None)
259
 
        branch.repository.lock_write()
260
 
        branch.repository.start_write_group()
261
 
        branch.repository.sign_revision('A', strategy)
262
 
        branch.repository.commit_write_group()
263
 
        branch.repository.unlock()
264
 
        self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
265
 
                         Testament.from_revision(branch.repository,
266
 
                         'A').as_short_text() +
267
 
                         '-----END PSEUDO-SIGNED CONTENT-----\n',
268
 
                         branch.repository.get_signature_text('A'))
269
 
 
270
 
    def test_store_signature(self):
271
 
        wt = self.make_branch_and_tree('.')
272
 
        branch = wt.branch
273
 
        branch.lock_write()
274
 
        try:
275
 
            branch.repository.start_write_group()
276
 
            try:
277
 
                branch.repository.store_revision_signature(
278
 
                    gpg.LoopbackGPGStrategy(None), 'FOO', 'A')
279
 
            except:
280
 
                branch.repository.abort_write_group()
281
 
                raise
282
 
            else:
283
 
                branch.repository.commit_write_group()
284
 
        finally:
285
 
            branch.unlock()
286
 
        # A signature without a revision should not be accessible.
287
 
        self.assertRaises(errors.NoSuchRevision,
288
 
                          branch.repository.has_signature_for_revision_id,
289
 
                          'A')
290
 
        wt.commit("base", allow_pointless=True, rev_id='A')
291
 
        self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n'
292
 
                         'FOO-----END PSEUDO-SIGNED CONTENT-----\n',
293
 
                         branch.repository.get_signature_text('A'))
294
 
 
295
 
    def test_branch_keeps_signatures(self):
296
 
        wt = self.make_branch_and_tree('source')
297
 
        wt.commit('A', allow_pointless=True, rev_id='A')
298
 
        repo = wt.branch.repository
299
 
        repo.lock_write()
300
 
        repo.start_write_group()
301
 
        repo.sign_revision('A', gpg.LoopbackGPGStrategy(None))
302
 
        repo.commit_write_group()
303
 
        repo.unlock()
304
 
        #FIXME: clone should work to urls,
305
 
        # wt.clone should work to disks.
306
 
        self.build_tree(['target/'])
307
 
        d2 = repo.bzrdir.clone(urlutils.local_path_to_url('target'))
308
 
        self.assertEqual(repo.get_signature_text('A'),
309
 
                         d2.open_repository().get_signature_text('A'))
310
 
 
311
 
    def test_nicks(self):
312
 
        """Test explicit and implicit branch nicknames.
 
254
    def test_nicks_bzr(self):
 
255
        """Test the behaviour of branch nicks specific to bzr branches.
313
256
 
314
257
        Nicknames are implicitly the name of the branch's directory, unless an
315
258
        explicit nickname is set.  That is, an explicit nickname always
316
259
        overrides the implicit one.
 
260
 
317
261
        """
318
262
        t = self.get_transport()
319
263
        branch = self.make_branch('bzr.dev')
 
264
        if not isinstance(branch, _mod_branch.BzrBranch):
 
265
            raise tests.TestNotApplicable("not a bzr branch format")
320
266
        # The nick will be 'bzr.dev', because there is no explicit nick set.
321
267
        self.assertEqual(branch.nick, 'bzr.dev')
322
268
        # Move the branch to a different directory, 'bzr.ab'.  Now that branch
338
284
        branch.nick = u"\u1234"
339
285
        self.assertEqual(branch.nick, u"\u1234")
340
286
 
 
287
    def test_nicks(self):
 
288
        """Test explicit and implicit branch nicknames.
 
289
 
 
290
        A nickname is always available, whether set explicitly or not.
 
291
        """
 
292
        t = self.get_transport()
 
293
        branch = self.make_branch('bzr.dev')
 
294
        # An implicit nick name is set; what it is exactly depends on the
 
295
        # format.
 
296
        self.assertIsInstance(branch.nick, basestring)
 
297
        # Set the branch nick explicitly.
 
298
        branch.nick = "Aaron's branch"
 
299
        # Because the nick has been set explicitly, the nick is now always
 
300
        # "Aaron's branch".
 
301
        self.assertEqual(branch.nick, "Aaron's branch")
 
302
        branch.nick = u"\u1234"
 
303
        self.assertEqual(branch.nick, u"\u1234")
 
304
 
341
305
    def test_commit_nicks(self):
342
306
        """Nicknames are committed to the revision"""
343
307
        wt = self.make_branch_and_tree('bzr.dev')
353
317
            repo = self.make_repository('.', shared=True)
354
318
        except errors.IncompatibleFormat:
355
319
            return
 
320
        if repo.bzrdir._format.colocated_branches:
 
321
            raise tests.TestNotApplicable(
 
322
                "control dir does not support colocated branches")
356
323
        self.assertEquals(0, len(repo.bzrdir.list_branches()))
 
324
        if not self.bzrdir_format.colocated_branches:
 
325
            raise tests.TestNotApplicable("control dir format does not support "
 
326
                "colocated branches")
357
327
        try:
358
328
            child_branch1 = self.branch_format.initialize(repo.bzrdir, 
359
329
                name='branch1')
360
 
        except (errors.UninitializableFormat, errors.NoColocatedBranchSupport):
 
330
        except errors.UninitializableFormat:
361
331
            # branch references are not default init'able and
362
332
            # not all bzrdirs support colocated branches.
363
333
            return
365
335
        self.branch_format.initialize(repo.bzrdir, name='branch2')
366
336
        self.assertEquals(2, len(repo.bzrdir.list_branches()))
367
337
 
 
338
    def test_create_append_revisions_only(self):
 
339
        try:
 
340
            repo = self.make_repository('.', shared=True)
 
341
        except errors.IncompatibleFormat:
 
342
            return
 
343
        for val in (True, False):
 
344
            try:
 
345
                branch = self.branch_format.initialize(repo.bzrdir,
 
346
                    append_revisions_only=True)
 
347
            except (errors.UninitializableFormat, errors.UpgradeRequired):
 
348
                # branch references are not default init'able and
 
349
                # not all branches support append_revisions_only
 
350
                return
 
351
            self.assertEquals(True, branch.get_append_revisions_only())
 
352
            repo.bzrdir.destroy_branch()
 
353
 
 
354
    def test_get_set_append_revisions_only(self):
 
355
        branch = self.make_branch('.')
 
356
        if branch._format.supports_set_append_revisions_only():
 
357
            branch.set_append_revisions_only(True)
 
358
            self.assertTrue(branch.get_append_revisions_only())
 
359
            branch.set_append_revisions_only(False)
 
360
            self.assertFalse(branch.get_append_revisions_only())
 
361
        else:
 
362
            self.assertRaises(errors.UpgradeRequired,
 
363
                branch.set_append_revisions_only, True)
 
364
            self.assertFalse(branch.get_append_revisions_only())
 
365
 
368
366
    def test_create_open_branch_uses_repository(self):
369
367
        try:
370
368
            repo = self.make_repository('.', shared=True)
371
369
        except errors.IncompatibleFormat:
372
 
            return
 
370
            raise tests.TestNotApplicable("requires shared repository support")
373
371
        child_transport = repo.bzrdir.root_transport.clone('child')
374
372
        child_transport.mkdir('.')
375
 
        child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
 
373
        try:
 
374
            child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
 
375
        except errors.UninitializableFormat:
 
376
            raise tests.TestNotApplicable("control dir format not initializable")
376
377
        try:
377
378
            child_branch = self.branch_format.initialize(child_dir)
378
379
        except errors.UninitializableFormat:
401
402
        """Create a fake revision history easily."""
402
403
        tree = self.make_branch_and_tree('.')
403
404
        rev1 = tree.commit('foo')
404
 
        orig_history = tree.branch.revision_history()
 
405
        tree.lock_write()
 
406
        self.addCleanup(tree.unlock)
 
407
        graph = tree.branch.repository.get_graph()
 
408
        orig_history = list(
 
409
            graph.iter_lefthand_ancestry(
 
410
                tree.branch.last_revision(), [revision.NULL_REVISION]))
405
411
        rev2 = tree.commit('bar', allow_pointless=True)
406
412
        tree.branch.generate_revision_history(rev1)
407
 
        self.assertEqual(orig_history, tree.branch.revision_history())
 
413
        self.assertEqual(orig_history, list(
 
414
            graph.iter_lefthand_ancestry(
 
415
                tree.branch.last_revision(), [revision.NULL_REVISION])))
408
416
 
409
417
    def test_generate_revision_history_NULL_REVISION(self):
410
418
        tree = self.make_branch_and_tree('.')
411
419
        rev1 = tree.commit('foo')
 
420
        tree.lock_write()
 
421
        self.addCleanup(tree.unlock)
412
422
        tree.branch.generate_revision_history(revision.NULL_REVISION)
413
 
        self.assertEqual([], tree.branch.revision_history())
 
423
        self.assertEqual(revision.NULL_REVISION, tree.branch.last_revision())
414
424
 
415
425
    def test_create_checkout(self):
416
426
        tree_a = self.make_branch_and_tree('a')
437
447
        tree_a = self.make_branch_and_tree('a')
438
448
        rev_id = tree_a.commit('put some content in the branch')
439
449
        # open the branch via a readonly transport
440
 
        source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
 
450
        url = self.get_readonly_url(urlutils.basename(tree_a.branch.base))
 
451
        t = transport.get_transport_from_url(url)
 
452
        if not tree_a.branch.bzrdir._format.supports_transport(t):
 
453
            raise tests.TestNotApplicable("format does not support transport")
 
454
        source_branch = _mod_branch.Branch.open(url)
441
455
        # sanity check that the test will be valid
442
456
        self.assertRaises((errors.LockError, errors.TransportNotPossible),
443
457
            source_branch.lock_write)
449
463
        tree_a = self.make_branch_and_tree('a')
450
464
        rev_id = tree_a.commit('put some content in the branch')
451
465
        # open the branch via a readonly transport
452
 
        source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
 
466
        url = self.get_readonly_url(
 
467
            osutils.basename(tree_a.branch.base.rstrip('/')))
 
468
        t = transport.get_transport_from_url(url)
 
469
        if not tree_a.branch.bzrdir._format.supports_transport(t):
 
470
            raise tests.TestNotApplicable("format does not support transport")
 
471
        source_branch = _mod_branch.Branch.open(url)
453
472
        # sanity check that the test will be valid
454
473
        self.assertRaises((errors.LockError, errors.TransportNotPossible),
455
474
            source_branch.lock_write)
462
481
        br = tree.branch
463
482
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
464
483
            br.set_revision_history, ["rev1"])
465
 
        self.assertEquals(br.revision_history(), ["rev1"])
 
484
        self.assertEquals(br.last_revision(), "rev1")
466
485
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
467
486
            br.set_revision_history, [])
468
 
        self.assertEquals(br.revision_history(), [])
 
487
        self.assertEquals(br.last_revision(), 'null:')
469
488
 
470
489
    def test_heads_to_fetch(self):
471
490
        # heads_to_fetch is a method that returns a collection of revids that
509
528
            looked_up_format = registry.get(network_name)
510
529
            self.assertEqual(format.__class__, looked_up_format.__class__)
511
530
 
 
531
    def test_get_config_calls(self):
 
532
        # Smoke test that all branch succeed getting a config
 
533
        br = self.make_branch('.')
 
534
        br.get_config()
 
535
        br.get_config_stack()
 
536
 
512
537
 
513
538
class ChrootedTests(per_branch.TestCaseWithBranch):
514
539
    """A support class that provides readonly urls outside the local namespace.
531
556
                          _mod_branch.Branch.open_containing,
532
557
                          self.get_readonly_url('g/p/q'))
533
558
        branch = self.make_branch('.')
 
559
        if not branch.bzrdir._format.supports_transport(
 
560
            transport.get_transport_from_url(self.get_readonly_url('.'))):
 
561
            raise tests.TestNotApplicable("format does not support transport")
534
562
        branch, relpath = _mod_branch.Branch.open_containing(
535
563
            self.get_readonly_url(''))
536
564
        self.assertEqual('', relpath)
622
650
class TestChildSubmitFormats(per_branch.TestCaseWithBranch):
623
651
 
624
652
    def test_get_child_submit_format_default(self):
625
 
        self.assertEqual(None, self.get_branch().get_child_submit_format())
 
653
        submit_format = self.get_branch().get_child_submit_format()
 
654
        self.assertTrue(submit_format is None or
 
655
                        isinstance(submit_format, str))
626
656
 
627
657
    def test_get_child_submit_format(self):
628
658
        branch = self.get_branch()
629
 
        branch.get_config().set_user_option('child_submit_format', '10')
 
659
        branch.get_config_stack().set('child_submit_format', '10')
630
660
        branch = self.get_branch()
631
661
        self.assertEqual('10', branch.get_child_submit_format())
632
662
 
673
703
            return
674
704
        # supported formats must be able to init and open
675
705
        t = self.get_transport()
676
 
        readonly_t = transport.get_transport(self.get_readonly_url())
 
706
        readonly_t = transport.get_transport_from_url(self.get_readonly_url())
677
707
        made_branch = self.make_branch('.')
678
708
        self.assertIsInstance(made_branch, _mod_branch.Branch)
679
709
 
680
710
        # find it via bzrdir opening:
681
 
        opened_control = bzrdir.BzrDir.open(readonly_t.base)
 
711
        opened_control = controldir.ControlDir.open(readonly_t.base)
682
712
        direct_opened_branch = opened_control.open_branch()
683
713
        self.assertEqual(direct_opened_branch.__class__, made_branch.__class__)
684
714
        self.assertEqual(opened_control, direct_opened_branch.bzrdir)
749
779
        branch.unbind()
750
780
        self.assertEqual(None, branch.get_master_branch())
751
781
 
752
 
    def test_unlocked_does_not_cache_master_branch(self):
753
 
        """Unlocked branches do not cache the result of get_master_branch."""
754
 
        master = self.make_branch('master')
755
 
        branch1 = self.make_branch('branch')
756
 
        try:
757
 
            branch1.bind(master)
758
 
        except errors.UpgradeRequired:
759
 
            raise tests.TestNotApplicable('Format does not support binding')
760
 
        # Open branch1 again
761
 
        branch2 = branch1.bzrdir.open_branch()
762
 
        self.assertNotEqual(None, branch1.get_master_branch())
763
 
        # Unbind the branch via branch2.  branch1 isn't locked so will
764
 
        # immediately return the new value for get_master_branch.
765
 
        branch2.unbind()
766
 
        self.assertEqual(None, branch1.get_master_branch())
767
 
 
768
782
    def test_bind_clears_cached_master_branch(self):
769
783
        """b.bind clears any cached value of b.get_master_branch."""
770
784
        master1 = self.make_branch('master1')
835
849
    def test_fallbacks_not_opened(self):
836
850
        stacked = self.make_branch_with_fallback()
837
851
        self.get_transport('').rename('fallback', 'moved')
838
 
        reopened = stacked.bzrdir.open_branch(ignore_fallbacks=True)
 
852
        reopened_dir = controldir.ControlDir.open(stacked.base)
 
853
        reopened = reopened_dir.open_branch(ignore_fallbacks=True)
839
854
        self.assertEqual([], reopened.repository._fallback_repositories)
840
855
 
841
856
    def test_fallbacks_are_opened(self):
842
857
        stacked = self.make_branch_with_fallback()
843
 
        reopened = stacked.bzrdir.open_branch(ignore_fallbacks=False)
 
858
        reopened_dir = controldir.ControlDir.open(stacked.base)
 
859
        reopened = reopened_dir.open_branch(ignore_fallbacks=False)
844
860
        self.assertLength(1, reopened.repository._fallback_repositories)
845
861
 
846
862
 
854
870
            tree.add_reference(subtree)
855
871
        except errors.UnsupportedOperation:
856
872
            raise tests.TestNotApplicable('Tree cannot hold references.')
857
 
        reference_parent = tree.branch.reference_parent('subtree-id',
858
 
                                                        'subtree')
 
873
        reference_parent = tree.branch.reference_parent(
 
874
            'subtree-id',
 
875
            urlutils.relative_url(tree.branch.user_url, subtree.branch.user_url))
859
876
        self.assertEqual(subtree.branch.base, reference_parent.base)
860
877
 
861
878
    def test_reference_parent_accepts_possible_transports(self):
867
884
        except errors.UnsupportedOperation:
868
885
            raise tests.TestNotApplicable('Tree cannot hold references.')
869
886
        reference_parent = tree.branch.reference_parent('subtree-id',
870
 
            'subtree', possible_transports=[subtree.bzrdir.root_transport])
 
887
            urlutils.relative_url(
 
888
                tree.branch.user_url, subtree.branch.user_url),
 
889
            possible_transports=[subtree.bzrdir.root_transport])
871
890
 
872
891
    def test_get_reference_info(self):
873
892
        branch = self.make_branch('branch')
1040
1059
 
1041
1060
class TestBranchControlComponent(per_branch.TestCaseWithBranch):
1042
1061
    """Branch implementations adequately implement ControlComponent."""
1043
 
    
 
1062
 
1044
1063
    def test_urls(self):
1045
1064
        br = self.make_branch('branch')
1046
1065
        self.assertIsInstance(br.user_url, str)