17
17
"""Tests for Branch.get_stacked_on_url and set_stacked_on_url."""
19
19
from bzrlib import (
23
24
from bzrlib.revision import NULL_REVISION
24
from bzrlib.tests import TestNotApplicable, KnownFailure
25
from bzrlib.smart import server
26
from bzrlib.tests import TestNotApplicable, KnownFailure, transport_util
25
27
from bzrlib.tests.branch_implementations import TestCaseWithBranch
28
from bzrlib.transport import get_transport
31
unstackable_format_errors = (
32
errors.UnstackableBranchFormat,
33
errors.UnstackableRepositoryFormat,
28
37
class TestStacking(TestCaseWithBranch):
39
def check_lines_added_or_present(self, stacked_branch, revid):
40
# similar to a failure seen in bug 288751 by mbp 20081120
41
stacked_repo = stacked_branch.repository
42
stacked_repo.lock_read()
44
list(stacked_repo.inventories.iter_lines_added_or_present_in_keys(
30
49
def test_get_set_stacked_on_url(self):
31
50
# branches must either:
32
51
# raise UnstackableBranchFormat or
34
53
# permit stacking to be done and then return the stacked location.
35
54
branch = self.make_branch('branch')
36
55
target = self.make_branch('target')
38
errors.UnstackableBranchFormat,
39
errors.UnstackableRepositoryFormat,
42
57
branch.set_stacked_on_url(target.base)
43
except old_format_errors:
58
except unstackable_format_errors:
44
59
# if the set failed, so must the get
45
self.assertRaises(old_format_errors, branch.get_stacked_on_url)
60
self.assertRaises(unstackable_format_errors, branch.get_stacked_on_url)
61
self.assertFalse(branch._format.supports_stacking())
63
self.assertTrue(branch._format.supports_stacking())
47
64
# now we have a stacked branch:
48
65
self.assertEqual(target.base, branch.get_stacked_on_url())
49
66
branch.set_stacked_on_url(None)
53
70
# Branches can be stacked on other branches using relative paths.
54
71
branch = self.make_branch('branch')
55
72
target = self.make_branch('target')
57
errors.UnstackableBranchFormat,
58
errors.UnstackableRepositoryFormat,
61
74
branch.set_stacked_on_url('../target')
62
except old_format_errors:
75
except unstackable_format_errors:
63
76
# if the set failed, so must the get
64
self.assertRaises(old_format_errors, branch.get_stacked_on_url)
77
self.assertRaises(unstackable_format_errors, branch.get_stacked_on_url)
66
79
self.assertEqual('../target', branch.get_stacked_on_url())
105
117
# and make branch from it which is stacked
107
119
new_dir = trunk_tree.bzrdir.sprout('newbranch', stacked=True)
108
except (errors.UnstackableBranchFormat,
109
errors.UnstackableRepositoryFormat), e:
110
raise TestNotApplicable(e)
120
except unstackable_format_errors, e:
121
raise TestNotApplicable(e)
123
self.assertRevisionNotInRepository('newbranch', trunk_revid)
124
new_tree = new_dir.open_workingtree()
125
new_branch_revid = new_tree.commit('something local')
126
self.assertRevisionNotInRepository('mainline', new_branch_revid)
127
self.assertRevisionInRepository('newbranch', new_branch_revid)
129
# XXX: this helper probably belongs on TestCaseWithTransport
130
def make_smart_server(self, path):
131
smart_server = server.SmartTCPServer_for_testing()
132
smart_server.setUp(self.get_server())
133
remote_transport = get_transport(smart_server.get_url()).clone(path)
134
self.addCleanup(smart_server.tearDown)
135
return remote_transport
137
def test_sprout_stacked_from_smart_server(self):
138
if isinstance(self.branch_format, branch.BzrBranchFormat4):
139
raise TestNotApplicable('Branch format 4 is not usable via HPSS.')
141
trunk_tree = self.make_branch_and_tree('mainline')
142
trunk_revid = trunk_tree.commit('mainline')
143
# Make sure that we can make a stacked branch from it
145
trunk_tree.bzrdir.sprout('testbranch', stacked=True)
146
except unstackable_format_errors, e:
147
raise TestNotApplicable(e)
148
# Now serve the original mainline from a smart server
149
remote_transport = self.make_smart_server('mainline')
150
remote_bzrdir = bzrdir.BzrDir.open_from_transport(remote_transport)
151
# and make branch from the smart server which is stacked
152
new_dir = remote_bzrdir.sprout('newbranch', stacked=True)
111
153
# stacked repository
112
154
self.assertRevisionNotInRepository('newbranch', trunk_revid)
113
155
new_tree = new_dir.open_workingtree()
163
204
# same branch as the original.
165
206
stacked_bzrdir = self.make_stacked_bzrdir()
166
except (errors.UnstackableBranchFormat,
167
errors.UnstackableRepositoryFormat), e:
168
# not a testable combination.
207
except unstackable_format_errors, e:
169
208
raise TestNotApplicable(e)
170
209
cloned_bzrdir = stacked_bzrdir.clone('cloned', preserve_stacking=True)
172
211
self.assertEqual(
173
212
stacked_bzrdir.open_branch().get_stacked_on_url(),
174
213
cloned_bzrdir.open_branch().get_stacked_on_url())
175
except (errors.UnstackableBranchFormat,
176
errors.UnstackableRepositoryFormat):
214
except unstackable_format_errors, e:
179
217
def test_clone_from_branch_stacked_on_relative_url_preserve_stacking(self):
182
220
# on an appropriately adjusted relative url.
184
222
stacked_bzrdir = self.make_stacked_bzrdir(in_directory='dir')
185
except (errors.UnstackableBranchFormat,
186
errors.UnstackableRepositoryFormat), e:
187
# not a testable combination.
223
except unstackable_format_errors, e:
188
224
raise TestNotApplicable(e)
189
225
stacked_bzrdir.open_branch().set_stacked_on_url('../stacked-on')
190
226
cloned_bzrdir = stacked_bzrdir.clone('cloned', preserve_stacking=True)
219
254
parent_bzrdir.get_config().set_default_stack_on('stack-on')
220
255
source = self.make_branch('source')
221
256
target = source.bzrdir.sprout('target').open_branch()
257
if self.branch_format.supports_stacking():
223
258
self.assertEqual('../stack-on', target.get_stacked_on_url())
224
except errors.UnstackableBranchFormat:
261
errors.UnstackableBranchFormat, target.get_stacked_on_url)
227
263
def test_clone_stacking_policy_handling(self):
228
264
"""Obey policy where possible, ignore otherwise."""
231
267
parent_bzrdir.get_config().set_default_stack_on('stack-on')
232
268
source = self.make_branch('source')
233
269
target = source.bzrdir.clone('target').open_branch()
235
self.assertEqual('../stack-on', target.get_stacked_on_url())
236
except errors.UnstackableBranchFormat:
270
if self.branch_format.supports_stacking():
271
self.assertEqual('../stack-on', target.get_stacked_on_url())
274
errors.UnstackableBranchFormat, target.get_stacked_on_url)
276
def test_sprout_to_smart_server_stacking_policy_handling(self):
277
"""Obey policy where possible, ignore otherwise."""
278
if isinstance(self.branch_format, branch.BzrBranchFormat4):
279
raise TestNotApplicable('Branch format 4 is not usable via HPSS.')
280
stack_on = self.make_branch('stack-on')
281
parent_bzrdir = self.make_bzrdir('.', format='default')
282
parent_bzrdir.get_config().set_default_stack_on('stack-on')
283
source = self.make_branch('source')
284
url = self.make_smart_server('target').base
285
target = source.bzrdir.sprout(url).open_branch()
286
if self.branch_format.supports_stacking():
287
self.assertEqual('../stack-on', target.get_stacked_on_url())
290
errors.UnstackableBranchFormat, target.get_stacked_on_url)
239
292
def prepare_stacked_on_fetch(self):
240
293
stack_on = self.make_branch_and_tree('stack-on')
241
294
stack_on.commit('first commit', rev_id='rev1')
243
296
stacked_dir = stack_on.bzrdir.sprout('stacked', stacked=True)
244
except (errors.UnstackableRepositoryFormat,
245
errors.UnstackableBranchFormat):
297
except unstackable_format_errors, e:
246
298
raise TestNotApplicable('Format does not support stacking.')
247
299
unstacked = self.make_repository('unstacked')
248
300
return stacked_dir.open_workingtree(), unstacked
299
353
other_tree = other_dir.open_workingtree()
300
354
text_lines[9] = 'changed in other\n'
301
355
self.build_tree_contents([('other/a', ''.join(text_lines))])
302
other_tree.commit('commit in other')
356
stacked_revid = other_tree.commit('commit in other')
303
357
# this should have generated a delta; try to pull that across
304
358
# bug 252821 caused a RevisionNotPresent here...
305
359
stacked_tree.pull(other_tree.branch)
306
360
stacked_tree.branch.repository.pack()
307
361
stacked_tree.branch.check()
362
self.check_lines_added_or_present(stacked_tree.branch, stacked_revid)
309
364
def test_fetch_revisions_with_file_changes(self):
310
365
# Fetching revisions including file changes into a stacked branch
336
390
rtree.lock_read()
337
391
self.addCleanup(rtree.unlock)
338
392
self.assertEqual('new content', rtree.get_file_by_path('a').read())
393
self.check_lines_added_or_present(target, 'rev2')
395
def test_transform_fallback_location_hook(self):
396
# The 'transform_fallback_location' branch hook allows us to inspect
397
# and transform the URL of the fallback location for the branch.
398
stack_on = self.make_branch('stack-on')
399
stacked = self.make_branch('stacked')
401
stacked.set_stacked_on_url('../stack-on')
402
except unstackable_format_errors, e:
403
raise TestNotApplicable('Format does not support stacking.')
404
self.get_transport().rename('stack-on', 'new-stack-on')
406
def hook(stacked_branch, url):
407
hook_calls.append(url)
408
return '../new-stack-on'
409
branch.Branch.hooks.install_named_hook(
410
'transform_fallback_location', hook, None)
411
branch.Branch.open('stacked')
412
self.assertEqual(['../stack-on'], hook_calls)
414
def test_stack_on_repository_branch(self):
415
# Stacking should work when the repo isn't co-located with the
418
repo = self.make_repository('repo', shared=True)
419
except errors.IncompatibleFormat:
420
raise TestNotApplicable()
421
# Avoid make_branch, which produces standalone branches.
422
bzrdir = self.make_bzrdir('repo/stack-on')
424
b = bzrdir.create_branch()
425
except errors.UninitializableFormat:
426
raise TestNotApplicable()
427
transport = self.get_transport('stacked')
428
b.bzrdir.clone_on_transport(transport, stacked_on=b.base)
429
# Ensure that opening the branch doesn't raise.
430
branch.Branch.open(transport.base)
433
class TestStackingConnections(
434
transport_util.TestCaseWithConnectionHookedTransport):
437
super(TestStackingConnections, self).setUp()
439
base_tree = self.make_branch_and_tree('base',
440
format=self.bzrdir_format)
441
except errors.UninitializableFormat, e:
442
raise TestNotApplicable(e)
443
stacked = self.make_branch('stacked', format=self.bzrdir_format)
445
stacked.set_stacked_on_url(base_tree.branch.base)
446
except unstackable_format_errors, e:
447
raise TestNotApplicable(e)
448
base_tree.commit('first', rev_id='rev-base')
449
stacked.set_last_revision_info(1, 'rev-base')
450
stacked_relative = self.make_branch('stacked_relative',
451
format=self.bzrdir_format)
452
stacked_relative.set_stacked_on_url('../base')
453
stacked.set_last_revision_info(1, 'rev-base')
454
self.start_logging_connections()
456
def test_open_stacked(self):
457
b = branch.Branch.open(self.get_url('stacked'))
458
rev = b.repository.get_revision('rev-base')
459
self.assertEqual(1, len(self.connections))
461
def test_open_stacked_relative(self):
462
b = branch.Branch.open(self.get_url('stacked_relative'))
463
rev = b.repository.get_revision('rev-base')
464
self.assertEqual(1, len(self.connections))