~bzr-pqm/bzr/bzr.dev

4044.1.1 by Robert Collins
Create Branch.create_clone_on_transport helper method to combine bzr and branch creation for push.
1
# Copyright (C) 2009 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4044.1.1 by Robert Collins
Create Branch.create_clone_on_transport helper method to combine bzr and branch creation for push.
16
17
"""Tests for branch.create_clone behaviour."""
18
4050.1.1 by Robert Collins
Fix race condition with branch hooks during cloning when the new branch is stacked.
19
from bzrlib.branch import Branch
4053.2.2 by Andrew Bennetts
Better fix, with test.
20
from bzrlib import errors
4053.2.5 by Andrew Bennetts
Merge from bzr.dev.
21
from bzrlib import remote
4053.2.2 by Andrew Bennetts
Better fix, with test.
22
from bzrlib import tests
4044.1.1 by Robert Collins
Create Branch.create_clone_on_transport helper method to combine bzr and branch creation for push.
23
from bzrlib.tests.branch_implementations.test_branch import TestCaseWithBranch
24
25
26
class TestCreateClone(TestCaseWithBranch):
27
4294.2.1 by Robert Collins
Move directory checking for bzr push options into Branch.create_clone_on_transport.
28
    def test_create_clone_on_transport_missing_parent_dir(self):
29
        tree = self.make_branch_and_tree('source')
30
        tree.commit('a commit')
31
        source = tree.branch
32
        target_transport = self.get_transport('subdir').clone('target')
4294.2.9 by Robert Collins
Fixup tests broken by cleaning up the layering.
33
        self.assertRaises(errors.NoSuchFile,
4294.2.1 by Robert Collins
Move directory checking for bzr push options into Branch.create_clone_on_transport.
34
            tree.branch.create_clone_on_transport, target_transport)
35
        self.assertFalse(self.get_transport('.').has('subdir'))
36
37
    def test_create_clone_on_transport_missing_parent_dir_create(self):
38
        tree = self.make_branch_and_tree('source')
39
        tree.commit('a commit')
40
        source = tree.branch
41
        target_transport = self.get_transport('subdir').clone('target')
42
        result = tree.branch.create_clone_on_transport(target_transport,
43
            create_prefix=True)
44
        self.assertEqual(source.last_revision(), result.last_revision())
45
        self.assertEqual(target_transport.base,
46
            result.bzrdir.root_transport.base)
47
48
    def test_create_clone_on_transport_use_existing_dir_false(self):
49
        tree = self.make_branch_and_tree('source')
50
        tree.commit('a commit')
51
        source = tree.branch
52
        target_transport = self.get_transport('target')
53
        target_transport.create_prefix()
4294.2.9 by Robert Collins
Fixup tests broken by cleaning up the layering.
54
        self.assertRaises(errors.FileExists,
4294.2.1 by Robert Collins
Move directory checking for bzr push options into Branch.create_clone_on_transport.
55
            tree.branch.create_clone_on_transport, target_transport)
56
        self.assertFalse(target_transport.has(".bzr"))
57
58
    def test_create_clone_on_transport_use_existing_dir_true(self):
59
        tree = self.make_branch_and_tree('source')
60
        tree.commit('a commit')
61
        source = tree.branch
62
        target_transport = self.get_transport('target')
63
        target_transport.create_prefix()
64
        result = tree.branch.create_clone_on_transport(target_transport,
65
            use_existing_dir=True)
66
        self.assertEqual(source.last_revision(), result.last_revision())
67
4044.1.1 by Robert Collins
Create Branch.create_clone_on_transport helper method to combine bzr and branch creation for push.
68
    def test_create_clone_on_transport_no_revision_id(self):
69
        tree = self.make_branch_and_tree('source')
70
        tree.commit('a commit')
71
        source = tree.branch
72
        target_transport = self.get_transport('target')
73
        result = tree.branch.create_clone_on_transport(target_transport)
74
        self.assertEqual(source.last_revision(), result.last_revision())
75
76
    def test_create_clone_on_transport_revision_id(self):
77
        tree = self.make_branch_and_tree('source')
78
        old_revid = tree.commit('a commit')
79
        source_tip = tree.commit('a second commit')
80
        source = tree.branch
81
        target_transport = self.get_transport('target')
82
        result = tree.branch.create_clone_on_transport(target_transport,
83
            revision_id=old_revid)
84
        self.assertEqual(old_revid, result.last_revision())
85
        result.lock_read()
86
        self.addCleanup(result.unlock)
87
        self.assertFalse(result.repository.has_revision(source_tip))
88
89
    def test_create_clone_on_transport_stacked(self):
90
        tree = self.make_branch_and_tree('source')
91
        tree.commit('a commit')
92
        trunk = tree.branch.create_clone_on_transport(
93
            self.get_transport('trunk'))
94
        revid = tree.commit('a second commit')
95
        source = tree.branch
96
        target_transport = self.get_transport('target')
97
        result = tree.branch.create_clone_on_transport(target_transport,
98
            stacked_on=trunk.base)
99
        self.assertEqual(revid, result.last_revision())
100
        self.assertEqual(trunk.base, result.get_stacked_on_url())
4053.2.2 by Andrew Bennetts
Better fix, with test.
101
4053.2.3 by Andrew Bennetts
Fix some nits.
102
    def test_create_clone_of_multiple_roots(self):
4053.2.2 by Andrew Bennetts
Better fix, with test.
103
        try:
104
            builder = self.make_branch_builder('local')
105
        except (errors.TransportNotPossible, errors.UninitializableFormat):
106
            raise tests.TestNotApplicable('format not directly constructable')
107
        builder.start_series()
108
        builder.build_snapshot('rev1', None, [
109
            ('add', ('', 'root-id', 'directory', ''))])
110
        builder.build_snapshot('rev2', ['rev1'], [])
111
        builder.build_snapshot('other', None, [
112
            ('add', ('', 'root-id', 'directory', ''))])
113
        builder.build_snapshot('rev3', ['rev2', 'other'], [])
114
        builder.finish_series()
115
        local = builder.get_branch()
116
        local.bzrdir.clone(self.get_url('remote'), revision_id='rev3')
117
4050.1.1 by Robert Collins
Fix race condition with branch hooks during cloning when the new branch is stacked.
118
    def assertBranchHookBranchIsStacked(self, pre_change_params):
119
        # Just calling will either succeed or fail.
120
        pre_change_params.branch.get_stacked_on_url()
121
        self.hook_calls.append(pre_change_params)
122
123
    def test_create_clone_on_transport_stacked_hooks_get_stacked_branch(self):
124
        tree = self.make_branch_and_tree('source')
125
        tree.commit('a commit')
126
        trunk = tree.branch.create_clone_on_transport(
127
            self.get_transport('trunk'))
128
        revid = tree.commit('a second commit')
129
        source = tree.branch
130
        target_transport = self.get_transport('target')
131
        self.hook_calls = []
132
        Branch.hooks.install_named_hook("pre_change_branch_tip",
133
            self.assertBranchHookBranchIsStacked, None)
134
        result = tree.branch.create_clone_on_transport(target_transport,
135
            stacked_on=trunk.base)
136
        self.assertEqual(revid, result.last_revision())
137
        self.assertEqual(trunk.base, result.get_stacked_on_url())
138
        # Smart servers invoke hooks on both sides
139
        if isinstance(result, remote.RemoteBranch):
140
            expected_calls = 2
141
        else:
142
            expected_calls = 1
143
        self.assertEqual(expected_calls, len(self.hook_calls))