1# Copyright (C) 2010, 2011, 2012, 2016 Canonical Ltd 2# 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. 7# 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. 12# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 16 17"""Tests for bzr directories that support colocated branches.""" 18 19from breezy.branch import Branch 20from breezy.controldir import BranchReferenceLoop 21from breezy import ( 22 branchbuilder, 23 errors, 24 tests, 25 urlutils, 26 ) 27from breezy.tests import ( 28 per_controldir, 29 ) 30from breezy.tests.features import ( 31 UnicodeFilenameFeature, 32 ) 33 34 35class TestColocatedBranchSupport(per_controldir.TestCaseWithControlDir): 36 37 def create_branch(self, bzrdir, name=None): 38 branch = bzrdir.create_branch(name=name) 39 # Create a commit on the branch, just because some formats 40 # have nascent branches that don't hit disk. 41 bb = branchbuilder.BranchBuilder(branch=branch) 42 bb.build_commit() 43 return branch 44 45 def test_destroy_colocated_branch(self): 46 branch = self.make_branch('branch') 47 bzrdir = branch.controldir 48 colo_branch = self.create_branch(bzrdir, 'colo') 49 try: 50 bzrdir.destroy_branch("colo") 51 except (errors.UnsupportedOperation, errors.TransportNotPossible): 52 raise tests.TestNotApplicable( 53 'Format does not support destroying branch') 54 self.assertRaises(errors.NotBranchError, bzrdir.open_branch, 55 "colo") 56 57 def test_create_colo_branch(self): 58 # a bzrdir can construct a branch and repository for itself. 59 if not self.bzrdir_format.is_supported(): 60 # unsupported formats are not loopback testable 61 # because the default open will not open them and 62 # they may not be initializable. 63 raise tests.TestNotApplicable('Control dir format not supported') 64 t = self.get_transport() 65 try: 66 made_control = self.bzrdir_format.initialize(t.base) 67 except errors.UninitializableFormat: 68 raise tests.TestNotApplicable( 69 'Control dir does not support creating new branches.') 70 made_control.create_repository() 71 made_branch = made_control.create_branch("colo") 72 self.assertIsInstance(made_branch, Branch) 73 self.assertEqual("colo", made_branch.name) 74 self.assertEqual(made_control, made_branch.controldir) 75 76 def test_open_by_url(self): 77 # a bzrdir can construct a branch and repository for itself. 78 if not self.bzrdir_format.is_supported(): 79 # unsupported formats are not loopback testable 80 # because the default open will not open them and 81 # they may not be initializable. 82 raise tests.TestNotApplicable('Control dir format not supported') 83 t = self.get_transport() 84 try: 85 made_control = self.bzrdir_format.initialize(t.base) 86 except errors.UninitializableFormat: 87 raise tests.TestNotApplicable( 88 'Control dir does not support creating new branches.') 89 made_control.create_repository() 90 made_branch = self.create_branch(made_control, name="colo") 91 other_branch = self.create_branch(made_control, name="othercolo") 92 self.assertIsInstance(made_branch, Branch) 93 self.assertEqual(made_control, made_branch.controldir) 94 self.assertNotEqual(made_branch.user_url, other_branch.user_url) 95 self.assertNotEqual(made_branch.control_url, other_branch.control_url) 96 re_made_branch = Branch.open(made_branch.user_url) 97 self.assertEqual(re_made_branch.name, "colo") 98 self.assertEqual(made_branch.control_url, re_made_branch.control_url) 99 self.assertEqual(made_branch.user_url, re_made_branch.user_url) 100 101 def test_sprout_into_colocated(self): 102 # a bzrdir can construct a branch and repository for itself. 103 if not self.bzrdir_format.is_supported(): 104 # unsupported formats are not loopback testable 105 # because the default open will not open them and 106 # they may not be initializable. 107 raise tests.TestNotApplicable('Control dir format not supported') 108 from_tree = self.make_branch_and_tree('from') 109 revid = from_tree.commit("rev1") 110 try: 111 other_branch = self.make_branch("to") 112 except errors.UninitializableFormat: 113 raise tests.TestNotApplicable( 114 'Control dir does not support creating new branches.') 115 to_dir = from_tree.controldir.sprout( 116 urlutils.join_segment_parameters( 117 other_branch.user_url, {"branch": "target"})) 118 to_branch = to_dir.open_branch(name="target") 119 self.assertEqual(revid, to_branch.last_revision()) 120 121 def test_sprout_into_colocated_leaves_workingtree(self): 122 # a bzrdir can construct a branch and repository for itself. 123 if not self.bzrdir_format.is_supported(): 124 # unsupported formats are not loopback testable 125 # because the default open will not open them and 126 # they may not be initializable. 127 raise tests.TestNotApplicable('Control dir format not supported') 128 if not self.bzrdir_format.supports_workingtrees: 129 raise tests.TestNotApplicable( 130 'Control dir format does not support working trees') 131 from_tree = self.make_branch_and_tree('from') 132 self.build_tree_contents([('from/foo', 'contents')]) 133 from_tree.add(['foo']) 134 revid1 = from_tree.commit("rev1") 135 self.build_tree_contents([('from/foo', 'new contents')]) 136 revid2 = from_tree.commit("rev2") 137 try: 138 other_branch = self.make_branch_and_tree("to") 139 except errors.UninitializableFormat: 140 raise tests.TestNotApplicable( 141 'Control dir does not support creating new branches.') 142 143 result = other_branch.controldir.push_branch( 144 from_tree.branch, revision_id=revid1) 145 self.assertTrue(result.workingtree_updated) 146 self.assertFileEqual('contents', 'to/foo') 147 148 from_tree.controldir.sprout( 149 urlutils.join_segment_parameters( 150 other_branch.user_url, {"branch": "target"}), 151 revision_id=revid2) 152 active_branch = other_branch.controldir.open_branch(name="") 153 self.assertEqual(revid1, active_branch.last_revision()) 154 to_branch = other_branch.controldir.open_branch(name="target") 155 self.assertEqual(revid2, to_branch.last_revision()) 156 self.assertFileEqual('contents', 'to/foo') 157 158 def test_unicode(self): 159 self.requireFeature(UnicodeFilenameFeature) 160 if not self.bzrdir_format.is_supported(): 161 # unsupported formats are not loopback testable 162 # because the default open will not open them and 163 # they may not be initializable. 164 raise tests.TestNotApplicable('Control dir format not supported') 165 t = self.get_transport() 166 try: 167 made_control = self.bzrdir_format.initialize(t.base) 168 except errors.UninitializableFormat: 169 raise tests.TestNotApplicable( 170 'Control dir does not support creating new branches.') 171 made_control.create_repository() 172 made_branch = self.create_branch(made_control, name=u"col\xe9") 173 self.assertIn( 174 u"col\xe9", [b.name for b in made_control.list_branches()]) 175 made_branch = Branch.open(made_branch.user_url) 176 self.assertEqual(u"col\xe9", made_branch.name) 177 made_control.destroy_branch(u"col\xe9") 178 179 def test_get_branches(self): 180 repo = self.make_repository('branch-1') 181 self.assertNotIn('foo', list(repo.controldir.get_branches())) 182 target_branch = self.create_branch(repo.controldir, name='foo') 183 self.assertIn('foo', list(repo.controldir.get_branches())) 184 self.assertEqual(target_branch.base, 185 repo.controldir.get_branches()['foo'].base) 186 187 def test_branch_names(self): 188 repo = self.make_repository('branch-1') 189 target_branch = self.create_branch(repo.controldir, name='foo') 190 self.assertIn('foo', repo.controldir.branch_names()) 191 192 def test_branch_name_with_slash(self): 193 repo = self.make_repository('branch-1') 194 try: 195 target_branch = self.create_branch(repo.controldir, name='foo/bar') 196 except errors.InvalidBranchName: 197 raise tests.TestNotApplicable( 198 "format does not support branches with / in their name") 199 self.assertIn('foo/bar', list(repo.controldir.get_branches())) 200 self.assertEqual( 201 target_branch.base, repo.controldir.open_branch(name='foo/bar').base) 202 203 def test_branch_reference(self): 204 referenced = self.make_branch('referenced') 205 repo = self.make_repository('repo') 206 try: 207 repo.controldir.set_branch_reference(referenced, name='foo') 208 except errors.IncompatibleFormat: 209 raise tests.TestNotApplicable( 210 'Control dir does not support creating branch references.') 211 self.assertEqual(referenced.user_url, 212 repo.controldir.get_branch_reference('foo')) 213 214 def test_branch_reference_loop(self): 215 repo = self.make_repository('repo') 216 to_branch = self.create_branch(repo.controldir, name='somebranch') 217 try: 218 self.assertRaises( 219 BranchReferenceLoop, 220 repo.controldir.set_branch_reference, 221 to_branch, name='somebranch') 222 except errors.IncompatibleFormat: 223 raise tests.TestNotApplicable( 224 'Control dir does not support creating branch references.') 225