1
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
1
# Copyright (C) 2008-2012, 2016 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
19
19
from bzrlib import (
25
25
from bzrlib.revision import NULL_REVISION
26
from bzrlib.tests import TestNotApplicable, transport_util
26
from bzrlib.tests import fixtures, TestNotApplicable, transport_util
27
27
from bzrlib.tests.per_branch import TestCaseWithBranch
108
108
def assertRevisionInRepository(self, repo_path, revid):
109
109
"""Check that a revision is in a repository, disregarding stacking."""
110
repo = bzrdir.BzrDir.open(repo_path).open_repository()
110
repo = controldir.ControlDir.open(repo_path).open_repository()
111
111
self.assertTrue(repo.has_revision(revid))
113
113
def assertRevisionNotInRepository(self, repo_path, revid):
114
114
"""Check that a revision is not in a repository, disregarding stacking."""
115
repo = bzrdir.BzrDir.open(repo_path).open_repository()
115
repo = controldir.ControlDir.open(repo_path).open_repository()
116
116
self.assertFalse(repo.has_revision(revid))
118
118
def test_get_graph_stacked(self):
150
150
self.assertRevisionNotInRepository('newbranch', trunk_revid)
151
151
tree = new_dir.open_branch().create_checkout('local')
152
152
new_branch_revid = tree.commit('something local')
153
self.assertRevisionNotInRepository('mainline', new_branch_revid)
153
self.assertRevisionNotInRepository(
154
trunk_tree.branch.base, new_branch_revid)
154
155
self.assertRevisionInRepository('newbranch', new_branch_revid)
156
157
def test_sprout_stacked_from_smart_server(self):
157
if isinstance(self.branch_format, branch.BzrBranchFormat4):
158
raise TestNotApplicable('Branch format 4 is not usable via HPSS.')
159
158
# We have a mainline
160
159
trunk_tree = self.make_branch_and_tree('mainline')
161
160
trunk_revid = trunk_tree.commit('mainline')
166
165
raise TestNotApplicable(e)
167
166
# Now serve the original mainline from a smart server
168
167
remote_transport = self.make_smart_server('mainline')
169
remote_bzrdir = bzrdir.BzrDir.open_from_transport(remote_transport)
168
remote_bzrdir = controldir.ControlDir.open_from_transport(remote_transport)
170
169
# and make branch from the smart server which is stacked
171
170
new_dir = remote_bzrdir.sprout('newbranch', stacked=True)
172
171
# stacked repository
173
172
self.assertRevisionNotInRepository('newbranch', trunk_revid)
174
173
tree = new_dir.open_branch().create_checkout('local')
175
174
new_branch_revid = tree.commit('something local')
176
self.assertRevisionNotInRepository('mainline', new_branch_revid)
175
self.assertRevisionNotInRepository(trunk_tree.branch.user_url,
177
177
self.assertRevisionInRepository('newbranch', new_branch_revid)
179
179
def test_unstack_fetches(self):
180
180
"""Removing the stacked-on branch pulls across all data"""
182
builder = self.make_branch_builder('trunk')
183
except errors.UninitializableFormat:
184
raise TestNotApplicable('uninitializeable format')
181
185
# We have a mainline
182
trunk_tree = self.make_branch_and_tree('mainline')
183
trunk_revid = trunk_tree.commit('revision on mainline')
184
# and make branch from it which is stacked
186
trunk = fixtures.build_branch_with_non_ancestral_rev(builder)
187
mainline_revid = 'rev-1'
188
# and make branch from it which is stacked (with no tags)
186
new_dir = trunk_tree.bzrdir.sprout(self.get_url('newbranch'),
190
new_dir = trunk.bzrdir.sprout(self.get_url('newbranch'), stacked=True)
188
191
except unstackable_format_errors, e:
189
192
raise TestNotApplicable(e)
190
193
# stacked repository
191
self.assertRevisionNotInRepository('newbranch', trunk_revid)
194
self.assertRevisionNotInRepository('newbranch', mainline_revid)
192
195
# TODO: we'd like to commit in the stacked repository; that requires
193
196
# some care (maybe a BranchBuilder) if it's remote and has no
197
200
# now when we unstack that should implicitly fetch, to make sure that
198
201
# the branch will still work
199
202
new_branch = new_dir.open_branch()
204
new_branch.tags.set_tag('tag-a', 'rev-2')
205
except errors.TagsNotSupported:
206
tags_supported = False
208
tags_supported = True
200
209
new_branch.set_stacked_on_url(None)
201
self.assertRevisionInRepository('newbranch', trunk_revid)
210
self.assertRevisionInRepository('newbranch', mainline_revid)
202
211
# of course it's still in the mainline
203
self.assertRevisionInRepository('mainline', trunk_revid)
212
self.assertRevisionInRepository('trunk', mainline_revid)
214
# the tagged revision in trunk is now in newbranch too
215
self.assertRevisionInRepository('newbranch', 'rev-2')
204
216
# and now we're no longer stacked
205
self.assertRaises(errors.NotStacked,
206
new_branch.get_stacked_on_url)
217
self.assertRaises(errors.NotStacked, new_branch.get_stacked_on_url)
208
219
def test_unstack_already_locked(self):
209
220
"""Removing the stacked-on branch with an already write-locked branch
321
332
def test_sprout_stacking_policy_handling(self):
322
333
"""Obey policy where possible, ignore otherwise."""
323
if isinstance(self.branch_format, branch.BzrBranchFormat4):
334
if self.bzrdir_format.fixed_components:
324
335
raise TestNotApplicable('Branch format 4 does not autoupgrade.')
325
336
source = self.make_branch('source')
326
337
stack_on = self.make_stacked_on_matching(source)
338
349
def test_clone_stacking_policy_handling(self):
339
350
"""Obey policy where possible, ignore otherwise."""
340
if isinstance(self.branch_format, branch.BzrBranchFormat4):
351
if self.bzrdir_format.fixed_components:
341
352
raise TestNotApplicable('Branch format 4 does not autoupgrade.')
342
353
source = self.make_branch('source')
343
354
stack_on = self.make_stacked_on_matching(source)
355
366
def test_sprout_to_smart_server_stacking_policy_handling(self):
356
367
"""Obey policy where possible, ignore otherwise."""
357
if isinstance(self.branch_format, branch.BzrBranchFormat4):
358
raise TestNotApplicable('Branch format 4 is not usable via HPSS.')
368
if not self.branch_format.supports_leaving_lock():
369
raise TestNotApplicable('Branch format is not usable via HPSS.')
359
370
source = self.make_branch('source')
360
371
stack_on = self.make_stacked_on_matching(source)
361
372
parent_bzrdir = self.make_bzrdir('.', format='default')
473
484
rtree = target.repository.revision_tree('rev2')
474
485
rtree.lock_read()
475
486
self.addCleanup(rtree.unlock)
476
self.assertEqual('new content', rtree.get_file_by_path('a').read())
489
rtree.get_file_text(rtree.path2id('a'), 'a'))
477
490
self.check_lines_added_or_present(target, 'rev2')
479
492
def test_transform_fallback_location_hook(self):
502
515
repo = self.make_repository('repo', shared=True)
503
516
except errors.IncompatibleFormat:
504
517
raise TestNotApplicable()
518
if not repo._format.supports_nesting_repositories:
519
raise TestNotApplicable()
505
520
# Avoid make_branch, which produces standalone branches.
506
521
bzrdir = self.make_bzrdir('repo/stack-on')
537
552
self.assertEqual({}, repo.get_parent_map(['rev1']))
538
553
# revision_history should work, even though the history is spread over
539
554
# multiple repositories.
540
self.assertLength(2, stacked.branch.revision_history())
555
self.assertEqual((2, 'rev2'), stacked.branch.last_revision_info())
543
558
class TestStackingConnections(
559
574
stacked.set_last_revision_info(1, 'rev-base')
560
575
stacked_relative = self.make_branch('stacked_relative',
561
576
format=self.bzrdir_format)
562
stacked_relative.set_stacked_on_url('../base')
577
stacked_relative.set_stacked_on_url(base_tree.branch.user_url)
563
578
stacked.set_last_revision_info(1, 'rev-base')
564
579
self.start_logging_connections()