~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Robert Collins
  • Date: 2005-08-23 06:52:09 UTC
  • mto: (974.1.50) (1185.1.10) (1092.3.1)
  • mto: This revision was merged to the branch mainline in revision 1139.
  • Revision ID: robertc@robertcollins.net-20050823065209-81cd5962c401751b
move io redirection into each test case from the global runner

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008 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
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
 
18
 
"""Black-box tests for bzr branch."""
19
 
 
20
 
import os
21
 
 
22
 
from bzrlib import (branch, bzrdir, errors, repository)
23
 
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
24
 
from bzrlib.tests.blackbox import ExternalBase
25
 
from bzrlib.tests import HardlinkFeature
26
 
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
27
 
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
28
 
from bzrlib.workingtree import WorkingTree
29
 
 
30
 
 
31
 
class TestBranch(ExternalBase):
32
 
 
33
 
    def example_branch(self, path='.'):
34
 
        tree = self.make_branch_and_tree(path)
35
 
        self.build_tree_contents([(path + '/hello', 'foo')])
36
 
        tree.add('hello')
37
 
        tree.commit(message='setup')
38
 
        self.build_tree_contents([(path + '/goodbye', 'baz')])
39
 
        tree.add('goodbye')
40
 
        tree.commit(message='setup')
41
 
 
42
 
    def test_branch(self):
43
 
        """Branch from one branch to another."""
44
 
        self.example_branch('a')
45
 
        self.run_bzr('branch a b')
46
 
        b = branch.Branch.open('b')
47
 
        self.run_bzr('branch a c -r 1')
48
 
        # previously was erroneously created by branching
49
 
        self.assertFalse(b._transport.has('branch-name'))
50
 
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
51
 
 
52
 
    def test_branch_only_copies_history(self):
53
 
        # Knit branches should only push the history for the current revision.
54
 
        format = bzrdir.BzrDirMetaFormat1()
55
 
        format.repository_format = RepositoryFormatKnit1()
56
 
        shared_repo = self.make_repository('repo', format=format, shared=True)
57
 
        shared_repo.set_make_working_trees(True)
58
 
 
59
 
        def make_shared_tree(path):
60
 
            shared_repo.bzrdir.root_transport.mkdir(path)
61
 
            shared_repo.bzrdir.create_branch_convenience('repo/' + path)
62
 
            return WorkingTree.open('repo/' + path)
63
 
        tree_a = make_shared_tree('a')
64
 
        self.build_tree(['repo/a/file'])
65
 
        tree_a.add('file')
66
 
        tree_a.commit('commit a-1', rev_id='a-1')
67
 
        f = open('repo/a/file', 'ab')
68
 
        f.write('more stuff\n')
69
 
        f.close()
70
 
        tree_a.commit('commit a-2', rev_id='a-2')
71
 
 
72
 
        tree_b = make_shared_tree('b')
73
 
        self.build_tree(['repo/b/file'])
74
 
        tree_b.add('file')
75
 
        tree_b.commit('commit b-1', rev_id='b-1')
76
 
 
77
 
        self.assertTrue(shared_repo.has_revision('a-1'))
78
 
        self.assertTrue(shared_repo.has_revision('a-2'))
79
 
        self.assertTrue(shared_repo.has_revision('b-1'))
80
 
 
81
 
        # Now that we have a repository with shared files, make sure
82
 
        # that things aren't copied out by a 'branch'
83
 
        self.run_bzr('branch repo/b branch-b')
84
 
        pushed_tree = WorkingTree.open('branch-b')
85
 
        pushed_repo = pushed_tree.branch.repository
86
 
        self.assertFalse(pushed_repo.has_revision('a-1'))
87
 
        self.assertFalse(pushed_repo.has_revision('a-2'))
88
 
        self.assertTrue(pushed_repo.has_revision('b-1'))
89
 
 
90
 
    def test_branch_hardlink(self):
91
 
        self.requireFeature(HardlinkFeature)
92
 
        source = self.make_branch_and_tree('source')
93
 
        self.build_tree(['source/file1'])
94
 
        source.add('file1')
95
 
        source.commit('added file')
96
 
        self.run_bzr(['branch', 'source', 'target', '--hardlink'])
97
 
        source_stat = os.stat('source/file1')
98
 
        target_stat = os.stat('target/file1')
99
 
        self.assertEqual(source_stat, target_stat)
100
 
 
101
 
    def test_branch_standalone(self):
102
 
        shared_repo = self.make_repository('repo', shared=True)
103
 
        self.example_branch('source')
104
 
        self.run_bzr('branch --standalone source repo/target')
105
 
        b = branch.Branch.open('repo/target')
106
 
        expected_repo_path = os.path.abspath('repo/target/.bzr/repository')
107
 
        self.assertEqual(strip_trailing_slash(b.repository.base),
108
 
            strip_trailing_slash(local_path_to_url(expected_repo_path)))
109
 
 
110
 
 
111
 
class TestBranchStacked(ExternalBase):
112
 
    """Tests for branch --stacked"""
113
 
 
114
 
    def check_shallow_branch(self, branch_revid, stacked_on):
115
 
        """Assert that the branch 'newbranch' has been published correctly.
116
 
 
117
 
        :param stacked_on: url of a branch this one is stacked upon.
118
 
        :param branch_revid: a revision id that should be the only
119
 
            revision present in the stacked branch, and it should not be in
120
 
            the reference branch.
121
 
        """
122
 
        new_branch = branch.Branch.open('newbranch')
123
 
        # The branch refers to the mainline
124
 
        self.assertEqual(stacked_on, new_branch.get_stacked_on_url())
125
 
        # and the branch's work was pushed
126
 
        self.assertTrue(new_branch.repository.has_revision(branch_revid))
127
 
        # The newly committed revision shoud be present in the stacked branch,
128
 
        # but not in the stacked-on branch.  Because stacking is set up by the
129
 
        # branch object, if we open the stacked branch's repository directly,
130
 
        # bypassing the branch, we see only what's in the stacked repository.
131
 
        stacked_repo = bzrdir.BzrDir.open('newbranch').open_repository()
132
 
        stacked_repo_revisions = set(stacked_repo.all_revision_ids())
133
 
        if len(stacked_repo_revisions) != 1:
134
 
            self.fail("wrong revisions in stacked repository: %r"
135
 
                % (stacked_repo_revisions,))
136
 
 
137
 
    def assertRevisionInRepository(self, repo_path, revid):
138
 
        """Check that a revision is in a repository, disregarding stacking."""
139
 
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
140
 
        self.assertTrue(repo.has_revision(revid))
141
 
 
142
 
    def assertRevisionNotInRepository(self, repo_path, revid):
143
 
        """Check that a revision is not in a repository, disregarding stacking."""
144
 
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
145
 
        self.assertFalse(repo.has_revision(revid))
146
 
 
147
 
    def assertRevisionsInBranchRepository(self, revid_list, branch_path):
148
 
        repo = branch.Branch.open(branch_path).repository
149
 
        self.assertEqual(set(revid_list),
150
 
            repo.has_revisions(revid_list))
151
 
 
152
 
    def test_branch_stacked_branch_not_stacked(self):
153
 
        """Branching a stacked branch is not stacked by default"""
154
 
        # We have a mainline
155
 
        trunk_tree = self.make_branch_and_tree('target',
156
 
            format='development')
157
 
        trunk_tree.commit('mainline')
158
 
        # and a branch from it which is stacked
159
 
        branch_tree = self.make_branch_and_tree('branch',
160
 
            format='development')
161
 
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
162
 
        # with some work on it
163
 
        branch_tree.commit('moar work plz')
164
 
        # branching our local branch gives us a new stacked branch pointing at
165
 
        # mainline.
166
 
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
167
 
        self.assertEqual('', out)
168
 
        self.assertEqual('Branched 1 revision(s).\n',
169
 
            err)
170
 
        # it should have preserved the branch format, and so it should be
171
 
        # capable of supporting stacking, but not actually have a stacked_on
172
 
        # branch configured
173
 
        self.assertRaises(errors.NotStacked,
174
 
            bzrdir.BzrDir.open('newbranch').open_branch().get_stacked_on_url)
175
 
 
176
 
    def test_branch_stacked_branch_stacked(self):
177
 
        """Asking to stack on a stacked branch does work"""
178
 
        # We have a mainline
179
 
        trunk_tree = self.make_branch_and_tree('target',
180
 
            format='development')
181
 
        trunk_revid = trunk_tree.commit('mainline')
182
 
        # and a branch from it which is stacked
183
 
        branch_tree = self.make_branch_and_tree('branch',
184
 
            format='development')
185
 
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
186
 
        # with some work on it
187
 
        branch_revid = branch_tree.commit('moar work plz')
188
 
        # you can chain branches on from there
189
 
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
190
 
        self.assertEqual('', out)
191
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
192
 
            branch_tree.branch.base, err)
193
 
        self.assertEqual(branch_tree.branch.base,
194
 
            branch.Branch.open('branch2').get_stacked_on_url())
195
 
        branch2_tree = WorkingTree.open('branch2')
196
 
        branch2_revid = branch2_tree.commit('work on second stacked branch')
197
 
        self.assertRevisionInRepository('branch2', branch2_revid)
198
 
        self.assertRevisionsInBranchRepository(
199
 
            [trunk_revid, branch_revid, branch2_revid],
200
 
            'branch2')
201
 
 
202
 
    def test_branch_stacked(self):
203
 
        # We have a mainline
204
 
        trunk_tree = self.make_branch_and_tree('mainline',
205
 
            format='development')
206
 
        original_revid = trunk_tree.commit('mainline')
207
 
        self.assertRevisionInRepository('mainline', original_revid)
208
 
        # and a branch from it which is stacked
209
 
        out, err = self.run_bzr(['branch', '--stacked', 'mainline',
210
 
            'newbranch'])
211
 
        self.assertEqual('', out)
212
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
213
 
            trunk_tree.branch.base, err)
214
 
        self.assertRevisionNotInRepository('newbranch', original_revid)
215
 
        new_tree = WorkingTree.open('newbranch')
216
 
        new_revid = new_tree.commit('new work')
217
 
        self.check_shallow_branch(new_revid, trunk_tree.branch.base)
218
 
 
219
 
    def test_branch_stacked_from_smart_server(self):
220
 
        # We can branch stacking on a smart server
221
 
        from bzrlib.smart.server import SmartTCPServer_for_testing
222
 
        self.transport_server = SmartTCPServer_for_testing
223
 
        trunk = self.make_branch('mainline', format='development')
224
 
        out, err = self.run_bzr(
225
 
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
226
 
 
227
 
    def test_branch_stacked_from_non_stacked_format(self):
228
 
        """The origin format doesn't support stacking"""
229
 
        trunk = self.make_branch('trunk', format='pack-0.92')
230
 
        out, err = self.run_bzr(
231
 
            ['branch', '--stacked', 'trunk', 'shallow'])
232
 
        # We should notify the user that we upgraded their format
233
 
        self.assertEqualDiff(
234
 
            'Source format does not support stacking, using format: \'1.6\'\n'
235
 
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
236
 
            '\n'
237
 
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
238
 
            err)
239
 
 
240
 
    def test_branch_stacked_from_rich_root_non_stackable(self):
241
 
        trunk = self.make_branch('trunk', format='rich-root-pack')
242
 
        out, err = self.run_bzr(
243
 
            ['branch', '--stacked', 'trunk', 'shallow'])
244
 
        # We should notify the user that we upgraded their format
245
 
        self.assertEqualDiff(
246
 
            'Source format does not support stacking, using format:'
247
 
            ' \'1.6.1-rich-root\'\n'
248
 
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
249
 
            '\n'
250
 
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
251
 
            err)
252
 
 
253
 
 
254
 
 
255
 
class TestRemoteBranch(TestCaseWithSFTPServer):
256
 
 
257
 
    def setUp(self):
258
 
        super(TestRemoteBranch, self).setUp()
259
 
        tree = self.make_branch_and_tree('branch')
260
 
        self.build_tree_contents([('branch/file', 'file content\n')])
261
 
        tree.add('file')
262
 
        tree.commit('file created')
263
 
 
264
 
    def test_branch_local_remote(self):
265
 
        self.run_bzr(['branch', 'branch', self.get_url('remote')])
266
 
        t = self.get_transport()
267
 
        # Ensure that no working tree what created remotely
268
 
        self.assertFalse(t.has('remote/file'))
269
 
 
270
 
    def test_branch_remote_remote(self):
271
 
        # Light cheat: we access the branch remotely
272
 
        self.run_bzr(['branch', self.get_url('branch'),
273
 
                      self.get_url('remote')])
274
 
        t = self.get_transport()
275
 
        # Ensure that no working tree what created remotely
276
 
        self.assertFalse(t.has('remote/file'))
277