24
from bzrlib.repository import RepositoryFormatKnit1
22
from bzrlib import (branch, bzrdir, errors, repository)
23
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
25
24
from bzrlib.tests.blackbox import ExternalBase
25
from bzrlib.tests import HardlinkFeature
26
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
26
27
from bzrlib.workingtree import WorkingTree
29
30
class TestBranch(ExternalBase):
31
def example_branch(test):
33
file('hello', 'wt').write('foo')
34
test.runbzr('add hello')
35
test.runbzr('commit -m setup hello')
36
file('goodbye', 'wt').write('baz')
37
test.runbzr('add goodbye')
38
test.runbzr('commit -m setup goodbye')
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')
40
41
def test_branch(self):
41
42
"""Branch from one branch to another."""
46
self.runbzr('branch a b')
47
b = bzrlib.branch.Branch.open('b')
48
self.assertEqual('b\n', b.control_files.get_utf8('branch-name').read())
49
self.runbzr('branch a c -r 1')
51
self.runbzr('commit -m foo --unchanged')
54
def test_branch_basis(self):
55
# ensure that basis really does grab from the basis by having incomplete source
56
tree = self.make_branch_and_tree('commit_tree')
57
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
59
tree.commit('revision 1', rev_id='1')
60
source = self.make_branch_and_tree('source')
61
# this gives us an incomplete repository
62
tree.bzrdir.open_repository().copy_content_into(source.branch.repository)
63
tree.commit('revision 2', rev_id='2', allow_pointless=True)
64
tree.bzrdir.open_branch().copy_content_into(source.branch)
65
tree.copy_content_into(source)
66
self.assertFalse(source.branch.repository.has_revision('2'))
68
self.runbzr('branch source target --basis commit_tree')
69
target = bzrlib.bzrdir.BzrDir.open('target')
70
self.assertEqual('2', target.open_branch().last_revision())
71
self.assertEqual('2', target.open_workingtree().last_revision())
72
self.assertTrue(target.open_branch().repository.has_revision('2'))
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)
74
51
def test_branch_only_copies_history(self):
75
52
# Knit branches should only push the history for the current revision.
76
format = bzrlib.bzrdir.BzrDirMetaFormat1()
53
format = bzrdir.BzrDirMetaFormat1()
77
54
format.repository_format = RepositoryFormatKnit1()
78
55
shared_repo = self.make_repository('repo', format=format, shared=True)
79
56
shared_repo.set_make_working_trees(True)
103
80
# Now that we have a repository with shared files, make sure
104
81
# that things aren't copied out by a 'branch'
105
self.run_bzr('branch', 'repo/b', 'branch-b')
82
self.run_bzr('branch repo/b branch-b')
106
83
pushed_tree = WorkingTree.open('branch-b')
107
84
pushed_repo = pushed_tree.branch.repository
108
85
self.assertFalse(pushed_repo.has_revision('a-1'))
109
86
self.assertFalse(pushed_repo.has_revision('a-2'))
110
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
class TestBranchStacked(ExternalBase):
101
"""Tests for branch --stacked"""
103
def check_shallow_branch(self, branch_revid, stacked_on):
104
"""Assert that the branch 'newbranch' has been published correctly.
106
:param stacked_on: url of a branch this one is stacked upon.
107
:param branch_revid: a revision id that should be the only
108
revision present in the stacked branch, and it should not be in
109
the reference branch.
111
new_branch = branch.Branch.open('newbranch')
112
# The branch refers to the mainline
113
self.assertEqual(stacked_on, new_branch.get_stacked_on_url())
114
# and the branch's work was pushed
115
self.assertTrue(new_branch.repository.has_revision(branch_revid))
116
# The newly committed revision shoud be present in the stacked branch,
117
# but not in the stacked-on branch. Because stacking is set up by the
118
# branch object, if we open the stacked branch's repository directly,
119
# bypassing the branch, we see only what's in the stacked repository.
120
stacked_repo = bzrdir.BzrDir.open('newbranch').open_repository()
121
stacked_repo_revisions = set(stacked_repo.all_revision_ids())
122
if len(stacked_repo_revisions) != 1:
123
self.fail("wrong revisions in stacked repository: %r"
124
% (stacked_repo_revisions,))
126
def assertRevisionInRepository(self, repo_path, revid):
127
"""Check that a revision is in a repository, disregarding stacking."""
128
repo = bzrdir.BzrDir.open(repo_path).open_repository()
129
self.assertTrue(repo.has_revision(revid))
131
def assertRevisionNotInRepository(self, repo_path, revid):
132
"""Check that a revision is not in a repository, disregarding stacking."""
133
repo = bzrdir.BzrDir.open(repo_path).open_repository()
134
self.assertFalse(repo.has_revision(revid))
136
def assertRevisionsInBranchRepository(self, revid_list, branch_path):
137
repo = branch.Branch.open(branch_path).repository
138
self.assertEqual(set(revid_list),
139
repo.has_revisions(revid_list))
141
def test_branch_stacked_branch_not_stacked(self):
142
"""Branching a stacked branch is not stacked by default"""
144
trunk_tree = self.make_branch_and_tree('target',
145
format='development')
146
trunk_tree.commit('mainline')
147
# and a branch from it which is stacked
148
branch_tree = self.make_branch_and_tree('branch',
149
format='development')
150
branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
151
# with some work on it
152
branch_tree.commit('moar work plz')
153
# branching our local branch gives us a new stacked branch pointing at
155
out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
156
self.assertEqual('', out)
157
self.assertEqual('Branched 1 revision(s).\n',
159
# it should have preserved the branch format, and so it should be
160
# capable of supporting stacking, but not actually have a stacked_on
162
self.assertRaises(errors.NotStacked,
163
bzrdir.BzrDir.open('newbranch').open_branch().get_stacked_on_url)
165
def test_branch_stacked_branch_stacked(self):
166
"""Asking to stack on a stacked branch does work"""
168
trunk_tree = self.make_branch_and_tree('target',
169
format='development')
170
trunk_revid = trunk_tree.commit('mainline')
171
# and a branch from it which is stacked
172
branch_tree = self.make_branch_and_tree('branch',
173
format='development')
174
branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
175
# with some work on it
176
branch_revid = branch_tree.commit('moar work plz')
177
# you can chain branches on from there
178
out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
179
self.assertEqual('', out)
180
self.assertEqual('Created new stacked branch referring to %s.\n' %
181
branch_tree.branch.base, err)
182
self.assertEqual(branch_tree.branch.base,
183
branch.Branch.open('branch2').get_stacked_on_url())
184
branch2_tree = WorkingTree.open('branch2')
185
branch2_revid = branch2_tree.commit('work on second stacked branch')
186
self.assertRevisionInRepository('branch2', branch2_revid)
187
self.assertRevisionsInBranchRepository(
188
[trunk_revid, branch_revid, branch2_revid],
191
def test_branch_stacked(self):
193
trunk_tree = self.make_branch_and_tree('mainline',
194
format='development')
195
original_revid = trunk_tree.commit('mainline')
196
self.assertRevisionInRepository('mainline', original_revid)
197
# and a branch from it which is stacked
198
out, err = self.run_bzr(['branch', '--stacked', 'mainline',
200
self.assertEqual('', out)
201
self.assertEqual('Created new stacked branch referring to %s.\n' %
202
trunk_tree.branch.base, err)
203
self.assertRevisionNotInRepository('newbranch', original_revid)
204
new_tree = WorkingTree.open('newbranch')
205
new_revid = new_tree.commit('new work')
206
self.check_shallow_branch(new_revid, trunk_tree.branch.base)
208
def test_branch_stacked_from_smart_server(self):
209
# We can branch stacking on a smart server
210
from bzrlib.smart.server import SmartTCPServer_for_testing
211
self.transport_server = SmartTCPServer_for_testing
212
trunk = self.make_branch('mainline', format='development')
213
out, err = self.run_bzr(
214
['branch', '--stacked', self.get_url('mainline'), 'shallow'])
216
def test_branch_stacked_from_non_stacked_format(self):
217
"""The origin format doesn't support stacking"""
218
trunk = self.make_branch('trunk', format='pack-0.92')
219
out, err = self.run_bzr(
220
['branch', '--stacked', 'trunk', 'shallow'])
223
class TestRemoteBranch(TestCaseWithSFTPServer):
226
super(TestRemoteBranch, self).setUp()
227
tree = self.make_branch_and_tree('branch')
228
self.build_tree_contents([('branch/file', 'file content\n')])
230
tree.commit('file created')
232
def test_branch_local_remote(self):
233
self.run_bzr(['branch', 'branch', self.get_url('remote')])
234
t = self.get_transport()
235
# Ensure that no working tree what created remotely
236
self.assertFalse(t.has('remote/file'))
238
def test_branch_remote_remote(self):
239
# Light cheat: we access the branch remotely
240
self.run_bzr(['branch', self.get_url('branch'),
241
self.get_url('remote')])
242
t = self.get_transport()
243
# Ensure that no working tree what created remotely
244
self.assertFalse(t.has('remote/file'))