13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
"""Black-box tests for bzr branch."""
22
from bzrlib import (branch, bzrdir, errors, repository)
22
from bzrlib import branch, bzrdir
23
23
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
24
24
from bzrlib.tests.blackbox import ExternalBase
25
from bzrlib.tests import (
29
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
30
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
31
25
from bzrlib.workingtree import WorkingTree
34
28
class TestBranch(ExternalBase):
36
def example_branch(self, path='.'):
37
tree = self.make_branch_and_tree(path)
38
self.build_tree_contents([(path + '/hello', 'foo')])
40
tree.commit(message='setup')
41
self.build_tree_contents([(path + '/goodbye', 'baz')])
43
tree.commit(message='setup')
30
def example_branch(test):
32
file('hello', 'wt').write('foo')
33
test.runbzr('add hello')
34
test.runbzr('commit -m setup hello')
35
file('goodbye', 'wt').write('baz')
36
test.runbzr('add goodbye')
37
test.runbzr('commit -m setup goodbye')
45
39
def test_branch(self):
46
40
"""Branch from one branch to another."""
47
self.example_branch('a')
48
self.run_bzr('branch a b')
45
self.runbzr('branch a b')
49
46
b = branch.Branch.open('b')
50
self.run_bzr('branch a c -r 1')
51
# previously was erroneously created by branching
52
self.assertFalse(b._transport.has('branch-name'))
53
b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
47
self.assertEqual('b\n', b.control_files.get_utf8('branch-name').read())
48
self.runbzr('branch a c -r 1')
50
self.runbzr('commit -m foo --unchanged')
53
def test_branch_basis(self):
54
# ensure that basis really does grab from the basis by having incomplete source
55
tree = self.make_branch_and_tree('commit_tree')
56
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
58
tree.commit('revision 1', rev_id='1')
59
source = self.make_branch_and_tree('source')
60
# this gives us an incomplete repository
61
tree.bzrdir.open_repository().copy_content_into(source.branch.repository)
62
tree.commit('revision 2', rev_id='2', allow_pointless=True)
63
tree.bzrdir.open_branch().copy_content_into(source.branch)
64
tree.copy_content_into(source)
65
self.assertFalse(source.branch.repository.has_revision('2'))
67
self.runbzr('branch source target --basis commit_tree')
68
target = bzrdir.BzrDir.open('target')
69
self.assertEqual('2', target.open_branch().last_revision())
70
self.assertEqual(['2'], target.open_workingtree().get_parent_ids())
71
self.assertTrue(target.open_branch().repository.has_revision('2'))
55
73
def test_branch_only_copies_history(self):
56
74
# Knit branches should only push the history for the current revision.
84
102
# Now that we have a repository with shared files, make sure
85
103
# that things aren't copied out by a 'branch'
86
self.run_bzr('branch repo/b branch-b')
104
self.run_bzr('branch', 'repo/b', 'branch-b')
87
105
pushed_tree = WorkingTree.open('branch-b')
88
106
pushed_repo = pushed_tree.branch.repository
89
107
self.assertFalse(pushed_repo.has_revision('a-1'))
90
108
self.assertFalse(pushed_repo.has_revision('a-2'))
91
109
self.assertTrue(pushed_repo.has_revision('b-1'))
93
def test_branch_hardlink(self):
94
self.requireFeature(HardlinkFeature)
95
source = self.make_branch_and_tree('source')
96
self.build_tree(['source/file1'])
98
source.commit('added file')
99
out, err = self.run_bzr(['branch', 'source', 'target', '--hardlink'])
100
source_stat = os.stat('source/file1')
101
target_stat = os.stat('target/file1')
102
same_file = (source_stat == target_stat)
106
# https://bugs.edge.launchpad.net/bzr/+bug/408193
107
self.assertContainsRe(err, "hardlinking working copy files is "
108
"not currently supported")
109
raise KnownFailure("--hardlink doesn't work in formats "
110
"that support content filtering (#408193)")
112
def test_branch_standalone(self):
113
shared_repo = self.make_repository('repo', shared=True)
114
self.example_branch('source')
115
self.run_bzr('branch --standalone source repo/target')
116
b = branch.Branch.open('repo/target')
117
expected_repo_path = os.path.abspath('repo/target/.bzr/repository')
118
self.assertEqual(strip_trailing_slash(b.repository.base),
119
strip_trailing_slash(local_path_to_url(expected_repo_path)))
121
def test_branch_no_tree(self):
122
self.example_branch('source')
123
self.run_bzr('branch --no-tree source target')
124
self.failIfExists('target/hello')
125
self.failIfExists('target/goodbye')
127
def test_branch_into_existing_dir(self):
128
self.example_branch('a')
129
# existing dir with similar files but no .bzr dir
130
self.build_tree_contents([('b/',)])
131
self.build_tree_contents([('b/hello', 'bar')]) # different content
132
self.build_tree_contents([('b/goodbye', 'baz')])# same content
133
# fails without --use-existing-dir
134
out,err = self.run_bzr('branch a b', retcode=3)
135
self.assertEqual('', out)
136
self.assertEqual('bzr: ERROR: Target directory "b" already exists.\n',
139
self.run_bzr('branch a b --use-existing-dir')
141
self.failUnlessExists('b/hello.moved')
142
self.failIfExists('b/godbye.moved')
143
# we can't branch into branch
144
out,err = self.run_bzr('branch a b --use-existing-dir', retcode=3)
145
self.assertEqual('', out)
146
self.assertEqual('bzr: ERROR: Already a branch: "b".\n', err)
149
class TestBranchStacked(ExternalBase):
150
"""Tests for branch --stacked"""
152
def assertRevisionInRepository(self, repo_path, revid):
153
"""Check that a revision is in a repository, disregarding stacking."""
154
repo = bzrdir.BzrDir.open(repo_path).open_repository()
155
self.assertTrue(repo.has_revision(revid))
157
def assertRevisionNotInRepository(self, repo_path, revid):
158
"""Check that a revision is not in a repository, disregarding stacking."""
159
repo = bzrdir.BzrDir.open(repo_path).open_repository()
160
self.assertFalse(repo.has_revision(revid))
162
def assertRevisionsInBranchRepository(self, revid_list, branch_path):
163
repo = branch.Branch.open(branch_path).repository
164
self.assertEqual(set(revid_list),
165
repo.has_revisions(revid_list))
167
def test_branch_stacked_branch_not_stacked(self):
168
"""Branching a stacked branch is not stacked by default"""
170
trunk_tree = self.make_branch_and_tree('target',
172
trunk_tree.commit('mainline')
173
# and a branch from it which is stacked
174
branch_tree = self.make_branch_and_tree('branch',
176
branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
177
# with some work on it
178
work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
179
work_tree.commit('moar work plz')
180
work_tree.branch.push(branch_tree.branch)
181
# branching our local branch gives us a new stacked branch pointing at
183
out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
184
self.assertEqual('', out)
185
self.assertEqual('Branched 2 revision(s).\n',
187
# it should have preserved the branch format, and so it should be
188
# capable of supporting stacking, but not actually have a stacked_on
190
self.assertRaises(errors.NotStacked,
191
bzrdir.BzrDir.open('newbranch').open_branch().get_stacked_on_url)
193
def test_branch_stacked_branch_stacked(self):
194
"""Asking to stack on a stacked branch does work"""
196
trunk_tree = self.make_branch_and_tree('target',
198
trunk_revid = trunk_tree.commit('mainline')
199
# and a branch from it which is stacked
200
branch_tree = self.make_branch_and_tree('branch',
202
branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
203
# with some work on it
204
work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
205
branch_revid = work_tree.commit('moar work plz')
206
work_tree.branch.push(branch_tree.branch)
207
# you can chain branches on from there
208
out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
209
self.assertEqual('', out)
210
self.assertEqual('Created new stacked branch referring to %s.\n' %
211
branch_tree.branch.base, err)
212
self.assertEqual(branch_tree.branch.base,
213
branch.Branch.open('branch2').get_stacked_on_url())
214
branch2_tree = WorkingTree.open('branch2')
215
branch2_revid = work_tree.commit('work on second stacked branch')
216
work_tree.branch.push(branch2_tree.branch)
217
self.assertRevisionInRepository('branch2', branch2_revid)
218
self.assertRevisionsInBranchRepository(
219
[trunk_revid, branch_revid, branch2_revid],
222
def test_branch_stacked(self):
224
trunk_tree = self.make_branch_and_tree('mainline',
226
original_revid = trunk_tree.commit('mainline')
227
self.assertRevisionInRepository('mainline', original_revid)
228
# and a branch from it which is stacked
229
out, err = self.run_bzr(['branch', '--stacked', 'mainline',
231
self.assertEqual('', out)
232
self.assertEqual('Created new stacked branch referring to %s.\n' %
233
trunk_tree.branch.base, err)
234
self.assertRevisionNotInRepository('newbranch', original_revid)
235
new_branch = branch.Branch.open('newbranch')
236
self.assertEqual(trunk_tree.branch.base, new_branch.get_stacked_on_url())
238
def test_branch_stacked_from_smart_server(self):
239
# We can branch stacking on a smart server
240
from bzrlib.smart.server import SmartTCPServer_for_testing
241
self.transport_server = SmartTCPServer_for_testing
242
trunk = self.make_branch('mainline', format='1.9')
243
out, err = self.run_bzr(
244
['branch', '--stacked', self.get_url('mainline'), 'shallow'])
246
def test_branch_stacked_from_non_stacked_format(self):
247
"""The origin format doesn't support stacking"""
248
trunk = self.make_branch('trunk', format='pack-0.92')
249
out, err = self.run_bzr(
250
['branch', '--stacked', 'trunk', 'shallow'])
251
# We should notify the user that we upgraded their format
252
self.assertEqualDiff(
253
'Source repository format does not support stacking, using format:\n'
254
' Packs 5 (adds stacking support, requires bzr 1.6)\n'
255
'Source branch format does not support stacking, using format:\n'
257
'Created new stacked branch referring to %s.\n' % (trunk.base,),
260
def test_branch_stacked_from_rich_root_non_stackable(self):
261
trunk = self.make_branch('trunk', format='rich-root-pack')
262
out, err = self.run_bzr(
263
['branch', '--stacked', 'trunk', 'shallow'])
264
# We should notify the user that we upgraded their format
265
self.assertEqualDiff(
266
'Source repository format does not support stacking, using format:\n'
267
' Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
268
'Source branch format does not support stacking, using format:\n'
270
'Created new stacked branch referring to %s.\n' % (trunk.base,),
274
class TestSmartServerBranching(ExternalBase):
276
def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
277
self.setup_smart_server_with_call_log()
278
t = self.make_branch_and_tree('from')
279
for count in range(9):
280
t.commit(message='commit %d' % count)
281
self.reset_smart_call_log()
282
out, err = self.run_bzr(['branch', self.get_url('from'),
283
self.get_url('target')])
284
# This figure represent the amount of work to perform this use case. It
285
# is entirely ok to reduce this number if a test fails due to rpc_count
286
# being too low. If rpc_count increases, more network roundtrips have
287
# become necessary for this use case. Please do not adjust this number
288
# upwards without agreement from bzr's network support maintainers.
289
self.assertLength(38, self.hpss_calls)
291
def test_branch_from_trivial_branch_streaming_acceptance(self):
292
self.setup_smart_server_with_call_log()
293
t = self.make_branch_and_tree('from')
294
for count in range(9):
295
t.commit(message='commit %d' % count)
296
self.reset_smart_call_log()
297
out, err = self.run_bzr(['branch', self.get_url('from'),
299
# This figure represent the amount of work to perform this use case. It
300
# is entirely ok to reduce this number if a test fails due to rpc_count
301
# being too low. If rpc_count increases, more network roundtrips have
302
# become necessary for this use case. Please do not adjust this number
303
# upwards without agreement from bzr's network support maintainers.
304
self.assertLength(10, self.hpss_calls)
306
def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
307
self.setup_smart_server_with_call_log()
308
t = self.make_branch_and_tree('trunk')
309
for count in range(8):
310
t.commit(message='commit %d' % count)
311
tree2 = t.branch.bzrdir.sprout('feature', stacked=True
313
local_tree = t.branch.bzrdir.sprout('local-working').open_workingtree()
314
local_tree.commit('feature change')
315
local_tree.branch.push(tree2.branch)
316
self.reset_smart_call_log()
317
out, err = self.run_bzr(['branch', self.get_url('feature'),
319
# This figure represent the amount of work to perform this use case. It
320
# is entirely ok to reduce this number if a test fails due to rpc_count
321
# being too low. If rpc_count increases, more network roundtrips have
322
# become necessary for this use case. Please do not adjust this number
323
# upwards without agreement from bzr's network support maintainers.
324
self.assertLength(15, self.hpss_calls)
327
class TestRemoteBranch(TestCaseWithSFTPServer):
330
super(TestRemoteBranch, self).setUp()
331
tree = self.make_branch_and_tree('branch')
332
self.build_tree_contents([('branch/file', 'file content\n')])
334
tree.commit('file created')
336
def test_branch_local_remote(self):
337
self.run_bzr(['branch', 'branch', self.get_url('remote')])
338
t = self.get_transport()
339
# Ensure that no working tree what created remotely
340
self.assertFalse(t.has('remote/file'))
342
def test_branch_remote_remote(self):
343
# Light cheat: we access the branch remotely
344
self.run_bzr(['branch', self.get_url('branch'),
345
self.get_url('remote')])
346
t = self.get_transport()
347
# Ensure that no working tree what created remotely
348
self.assertFalse(t.has('remote/file'))