1
# Copyright (C) 2005, 2006, 2008 Canonical Ltd
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.
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.
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
18
"""Black-box tests for bzr branch."""
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.workingtree import WorkingTree
30
class TestBranch(ExternalBase):
32
def example_branch(self, path='.'):
33
tree = self.make_branch_and_tree(path)
34
self.build_tree_contents([(path + '/hello', 'foo')])
36
tree.commit(message='setup')
37
self.build_tree_contents([(path + '/goodbye', 'baz')])
39
tree.commit(message='setup')
41
def test_branch(self):
42
"""Branch from one branch to another."""
43
self.example_branch('a')
44
self.run_bzr('branch a b')
45
b = branch.Branch.open('b')
46
self.run_bzr('branch a c -r 1')
47
# previously was erroneously created by branching
48
self.assertFalse(b._transport.has('branch-name'))
49
b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
51
def test_branch_only_copies_history(self):
52
# Knit branches should only push the history for the current revision.
53
format = bzrdir.BzrDirMetaFormat1()
54
format.repository_format = RepositoryFormatKnit1()
55
shared_repo = self.make_repository('repo', format=format, shared=True)
56
shared_repo.set_make_working_trees(True)
58
def make_shared_tree(path):
59
shared_repo.bzrdir.root_transport.mkdir(path)
60
shared_repo.bzrdir.create_branch_convenience('repo/' + path)
61
return WorkingTree.open('repo/' + path)
62
tree_a = make_shared_tree('a')
63
self.build_tree(['repo/a/file'])
65
tree_a.commit('commit a-1', rev_id='a-1')
66
f = open('repo/a/file', 'ab')
67
f.write('more stuff\n')
69
tree_a.commit('commit a-2', rev_id='a-2')
71
tree_b = make_shared_tree('b')
72
self.build_tree(['repo/b/file'])
74
tree_b.commit('commit b-1', rev_id='b-1')
76
self.assertTrue(shared_repo.has_revision('a-1'))
77
self.assertTrue(shared_repo.has_revision('a-2'))
78
self.assertTrue(shared_repo.has_revision('b-1'))
80
# Now that we have a repository with shared files, make sure
81
# that things aren't copied out by a 'branch'
82
self.run_bzr('branch repo/b branch-b')
83
pushed_tree = WorkingTree.open('branch-b')
84
pushed_repo = pushed_tree.branch.repository
85
self.assertFalse(pushed_repo.has_revision('a-1'))
86
self.assertFalse(pushed_repo.has_revision('a-2'))
87
self.assertTrue(pushed_repo.has_revision('b-1'))
89
def test_branch_hardlink(self):
90
self.requireFeature(HardlinkFeature)
91
source = self.make_branch_and_tree('source')
92
self.build_tree(['source/file1'])
94
source.commit('added file')
95
self.run_bzr(['branch', 'source', 'target', '--hardlink'])
96
source_stat = os.stat('source/file1')
97
target_stat = os.stat('target/file1')
98
self.assertEqual(source_stat, target_stat)
100
def check_shallow_branch(self, branch_revid, stacked_on):
101
"""Assert that the branch 'newbranch' has been published correctly.
103
:param stacked_on: url of a branch this one is stacked upon.
104
:param branch_revid: a revision id that should be the only
105
revision present in the stacked branch, and it should not be in
106
the reference branch.
108
new_branch = branch.Branch.open('newbranch')
109
# The branch refers to the mainline
110
self.assertEqual(stacked_on, new_branch.get_stacked_on_url())
111
# and the branch's work was pushed
112
self.assertTrue(new_branch.repository.has_revision(branch_revid))
113
# The newly committed revision shoud be present in the stacked branch,
114
# but not in the stacked-on branch. Because stacking is set up by the
115
# branch object, if we open the stacked branch's repository directly,
116
# bypassing the branch, we see only what's in the stacked repository.
117
stacked_repo = bzrdir.BzrDir.open('newbranch').open_repository()
118
stacked_repo_revisions = set(stacked_repo.all_revision_ids())
119
if len(stacked_repo_revisions) != 1:
120
self.fail("wrong revisions in stacked repository: %r"
121
% (stacked_repo_revisions,))
123
def assertRevisionInRepository(self, repo_path, revid):
124
"""Check that a revision is in a repository, disregarding stacking."""
125
repo = bzrdir.BzrDir.open(repo_path).open_repository()
126
self.assertTrue(repo.has_revision(revid))
128
def assertRevisionNotInRepository(self, repo_path, revid):
129
"""Check that a revision is not in a repository, disregarding stacking."""
130
repo = bzrdir.BzrDir.open(repo_path).open_repository()
131
self.assertFalse(repo.has_revision(revid))
133
def assertRevisionsInBranchRepository(self, revid_list, branch_path):
134
repo = branch.Branch.open(branch_path).repository
135
self.assertEqual(set(revid_list),
136
repo.has_revisions(revid_list))
138
def test_branch_stacked_branch_not_stacked(self):
139
"""Branching a stacked branch is not stacked by default"""
141
trunk_tree = self.make_branch_and_tree('target',
142
format='development')
143
trunk_tree.commit('mainline')
144
# and a branch from it which is stacked
145
branch_tree = self.make_branch_and_tree('branch',
146
format='development')
147
branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
148
# with some work on it
149
branch_tree.commit('moar work plz')
150
# branching our local branch gives us a new stacked branch pointing at
152
out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
153
self.assertEqual('', out)
154
self.assertEqual('Branched 1 revision(s).\n',
156
self.assertRaises(errors.NotStacked,
157
bzrdir.BzrDir.open('newbranch').open_branch().get_stacked_on_url)
159
def test_branch_stacked_branch_stacked(self):
160
"""Asking to stack on a stacked branch does work"""
162
trunk_tree = self.make_branch_and_tree('target',
163
format='development')
164
trunk_revid = trunk_tree.commit('mainline')
165
# and a branch from it which is stacked
166
branch_tree = self.make_branch_and_tree('branch',
167
format='development')
168
branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
169
# with some work on it
170
branch_revid = branch_tree.commit('moar work plz')
171
# you can chain branches on from there
172
out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
173
self.assertEqual('', out)
174
self.assertEqual('Created new stacked branch referring to %s.\n' %
175
branch_tree.branch.base, err)
176
self.assertEqual(branch_tree.branch.base,
177
branch.Branch.open('branch2').get_stacked_on_url())
178
branch2_tree = WorkingTree.open('branch2')
179
branch2_revid = branch2_tree.commit('work on second stacked branch')
180
self.assertRevisionInRepository('branch2', branch2_revid)
181
self.assertRevisionsInBranchRepository(
182
[trunk_revid, branch_revid, branch2_revid],
185
def test_branch_stacked(self):
187
trunk_tree = self.make_branch_and_tree('mainline',
188
format='development')
189
original_revid = trunk_tree.commit('mainline')
190
self.assertRevisionInRepository('mainline', original_revid)
191
# and a branch from it which is stacked
192
out, err = self.run_bzr(['branch', '--stacked', 'mainline',
194
self.assertEqual('', out)
195
self.assertEqual('Created new stacked branch referring to %s.\n' %
196
trunk_tree.branch.base, err)
197
self.assertRevisionNotInRepository('newbranch', original_revid)
198
new_tree = WorkingTree.open('newbranch')
199
new_revid = new_tree.commit('new work')
200
self.check_shallow_branch(new_revid, trunk_tree.branch.base)
202
def test_branch_stacked_from_smart_server(self):
203
# We can branch stacking on a smart server
204
from bzrlib.smart.server import SmartTCPServer_for_testing
205
self.transport_server = SmartTCPServer_for_testing
206
trunk = self.make_branch('mainline', format='development')
207
out, err = self.run_bzr(
208
['branch', '--stacked', self.get_url('mainline'), 'shallow'])
211
class TestRemoteBranch(TestCaseWithSFTPServer):
214
super(TestRemoteBranch, self).setUp()
215
tree = self.make_branch_and_tree('branch')
216
self.build_tree_contents([('branch/file', 'file content\n')])
218
tree.commit('file created')
220
def test_branch_local_remote(self):
221
self.run_bzr(['branch', 'branch', self.get_url('remote')])
222
t = self.get_transport()
223
# Ensure that no working tree what created remotely
224
self.assertFalse(t.has('remote/file'))
226
def test_branch_remote_remote(self):
227
# Light cheat: we access the branch remotely
228
self.run_bzr(['branch', self.get_url('branch'),
229
self.get_url('remote')])
230
t = self.get_transport()
231
# Ensure that no working tree what created remotely
232
self.assertFalse(t.has('remote/file'))