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
17
17
"""Tests for the Branch facility that are not interface tests.
19
For interface tests see `tests/per_branch/*.py`.
19
For interface tests see tests/branch_implementations/*.py.
21
21
For concrete class tests see this file, and for meta-branch tests
22
22
also see this file.
25
from cStringIO import StringIO
25
from StringIO import StringIO
27
27
from bzrlib import (
28
28
branch as _mod_branch,
37
from bzrlib.branchfmt.fullhistory import (
33
from bzrlib.branch import (
37
BranchReferenceFormat,
43
class TestDefaultFormat(tests.TestCase):
45
def test_default_format(self):
46
# update this if you change the default branch format
47
self.assertIsInstance(_mod_branch.format_registry.get_default(),
48
_mod_branch.BzrBranchFormat7)
50
def test_default_format_is_same_as_bzrdir_default(self):
51
# XXX: it might be nice if there was only one place the default was
52
# set, but at the moment that's not true -- mbp 20070814 --
53
# https://bugs.launchpad.net/bzr/+bug/132376
55
_mod_branch.format_registry.get_default(),
56
bzrdir.BzrDirFormat.get_default_format().get_branch_format())
42
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1,
44
from bzrlib.errors import (NotBranchError,
47
UnsupportedFormatError,
50
from bzrlib.tests import TestCase, TestCaseWithTransport
51
from bzrlib.transport import get_transport
53
class TestDefaultFormat(TestCase):
58
55
def test_get_set_default_format(self):
59
# set the format and then set it back again
60
old_format = _mod_branch.format_registry.get_default()
61
_mod_branch.format_registry.set_default(SampleBranchFormat())
56
old_format = BranchFormat.get_default_format()
58
self.assertTrue(isinstance(old_format, BzrBranchFormat5))
59
BranchFormat.set_default_format(SampleBranchFormat())
63
61
# the default branch format is used by the meta dir format
64
62
# which is not the default bzrdir format at this point
65
dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
63
dir = BzrDirMetaFormat1().initialize('memory:///')
66
64
result = dir.create_branch()
67
65
self.assertEqual(result, 'A branch')
69
_mod_branch.format_registry.set_default(old_format)
70
self.assertEqual(old_format,
71
_mod_branch.format_registry.get_default())
74
class TestBranchFormat5(tests.TestCaseWithTransport):
67
BranchFormat.set_default_format(old_format)
68
self.assertEqual(old_format, BranchFormat.get_default_format())
71
class TestBranchFormat5(TestCaseWithTransport):
75
72
"""Tests specific to branch format 5"""
77
74
def test_branch_format_5_uses_lockdir(self):
78
75
url = self.get_url()
79
bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
80
bdir.create_repository()
81
branch = BzrBranchFormat5().initialize(bdir)
76
bzrdir = BzrDirMetaFormat1().initialize(url)
77
bzrdir.create_repository()
78
branch = bzrdir.create_branch()
82
79
t = self.get_transport()
83
80
self.log("branch instance is %r" % branch)
84
self.assertTrue(isinstance(branch, BzrBranch5))
81
self.assert_(isinstance(branch, BzrBranch5))
85
82
self.assertIsDirectory('.', t)
86
83
self.assertIsDirectory('.bzr/branch', t)
87
84
self.assertIsDirectory('.bzr/branch/lock', t)
88
85
branch.lock_write()
89
self.addCleanup(branch.unlock)
90
self.assertIsDirectory('.bzr/branch/lock/held', t)
87
self.assertIsDirectory('.bzr/branch/lock/held', t)
92
91
def test_set_push_location(self):
93
conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
92
from bzrlib.config import (locations_config_filename,
93
ensure_config_dir_exists)
94
ensure_config_dir_exists()
95
fn = locations_config_filename()
95
96
branch = self.make_branch('.', format='knit')
96
97
branch.set_push_location('foo')
97
98
local_path = urlutils.local_path_from_url(branch.base[:-1])
98
self.assertFileEqual("# comment\n"
99
self.assertFileEqual("[%s]\n"
100
100
"push_location = foo\n"
101
"push_location:policy = norecurse\n" % local_path,
102
config.locations_config_filename())
101
"push_location:policy = norecurse" % local_path,
104
104
# TODO RBC 20051029 test getting a push location from a branch in a
105
105
# recursive section - that is, it appends the branch name.
108
class SampleBranchFormat(_mod_branch.BranchFormatMetadir):
108
class SampleBranchFormat(BranchFormat):
109
109
"""A sample format
111
this format is initializable, unsupported to aid in testing the
111
this format is initializable, unsupported to aid in testing the
112
112
open and open_downlevel routines.
116
def get_format_string(cls):
115
def get_format_string(self):
117
116
"""See BzrBranchFormat.get_format_string()."""
118
117
return "Sample branch format."
120
def initialize(self, a_bzrdir, name=None, repository=None,
121
append_revisions_only=None):
119
def initialize(self, a_bzrdir):
122
120
"""Format 4 branches cannot be created."""
123
t = a_bzrdir.get_branch_transport(self, name=name)
121
t = a_bzrdir.get_branch_transport(self)
124
122
t.put_bytes('format', self.get_format_string())
125
123
return 'A branch'
127
125
def is_supported(self):
130
def open(self, transport, name=None, _found=False, ignore_fallbacks=False,
131
possible_transports=None):
128
def open(self, transport, _found=False):
132
129
return "opened branch."
135
# Demonstrating how lazy loading is often implemented:
136
# A constant string is created.
137
SampleSupportedBranchFormatString = "Sample supported branch format."
139
# And the format class can then reference the constant to avoid skew.
140
class SampleSupportedBranchFormat(_mod_branch.BranchFormatMetadir):
141
"""A sample supported format."""
144
def get_format_string(cls):
145
"""See BzrBranchFormat.get_format_string()."""
146
return SampleSupportedBranchFormatString
148
def initialize(self, a_bzrdir, name=None, append_revisions_only=None):
149
t = a_bzrdir.get_branch_transport(self, name=name)
150
t.put_bytes('format', self.get_format_string())
153
def open(self, transport, name=None, _found=False, ignore_fallbacks=False,
154
possible_transports=None):
155
return "opened supported branch."
158
class SampleExtraBranchFormat(_mod_branch.BranchFormat):
159
"""A sample format that is not usable in a metadir."""
161
def get_format_string(self):
162
# This format is not usable in a metadir.
165
def network_name(self):
166
# Network name always has to be provided.
169
def initialize(self, a_bzrdir, name=None):
170
raise NotImplementedError(self.initialize)
172
def open(self, transport, name=None, _found=False, ignore_fallbacks=False,
173
possible_transports=None):
174
raise NotImplementedError(self.open)
177
class TestBzrBranchFormat(tests.TestCaseWithTransport):
132
class TestBzrBranchFormat(TestCaseWithTransport):
178
133
"""Tests for the BzrBranchFormat facility."""
180
135
def test_find_format(self):
181
136
# is the right format object found for a branch?
182
137
# create a branch with a few known format objects.
183
# this is not quite the same as
138
# this is not quite the same as
184
139
self.build_tree(["foo/", "bar/"])
185
140
def check_format(format, url):
186
141
dir = format._matchingbzrdir.initialize(url)
187
142
dir.create_repository()
188
143
format.initialize(dir)
189
found_format = _mod_branch.BranchFormatMetadir.find_format(dir)
190
self.assertIsInstance(found_format, format.__class__)
144
found_format = BranchFormat.find_format(dir)
145
self.failUnless(isinstance(found_format, format.__class__))
191
146
check_format(BzrBranchFormat5(), "bar")
193
def test_find_format_factory(self):
194
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
195
SampleSupportedBranchFormat().initialize(dir)
196
factory = _mod_branch.MetaDirBranchFormatFactory(
197
SampleSupportedBranchFormatString,
198
"bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
199
_mod_branch.format_registry.register(factory)
200
self.addCleanup(_mod_branch.format_registry.remove, factory)
201
b = _mod_branch.Branch.open(self.get_url())
202
self.assertEqual(b, "opened supported branch.")
204
def test_from_string(self):
205
self.assertIsInstance(
206
SampleBranchFormat.from_string("Sample branch format."),
208
self.assertRaises(AssertionError,
209
SampleBranchFormat.from_string, "Different branch format.")
211
148
def test_find_format_not_branch(self):
212
149
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
213
self.assertRaises(errors.NotBranchError,
214
_mod_branch.BranchFormatMetadir.find_format,
150
self.assertRaises(NotBranchError,
151
BranchFormat.find_format,
217
154
def test_find_format_unknown_format(self):
218
155
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
219
156
SampleBranchFormat().initialize(dir)
220
self.assertRaises(errors.UnknownFormatError,
221
_mod_branch.BranchFormatMetadir.find_format,
157
self.assertRaises(UnknownFormatError,
158
BranchFormat.find_format,
224
def test_find_format_with_features(self):
225
tree = self.make_branch_and_tree('.', format='2a')
226
tree.branch.update_feature_flags({"name": "optional"})
227
found_format = _mod_branch.BranchFormatMetadir.find_format(tree.bzrdir)
228
self.assertIsInstance(found_format, _mod_branch.BranchFormatMetadir)
229
self.assertEqual(found_format.features.get("name"), "optional")
230
tree.branch.update_feature_flags({"name": None})
231
branch = _mod_branch.Branch.open('.')
232
self.assertEqual(branch._format.features, {})
235
class TestBranchFormatRegistry(tests.TestCase):
238
super(TestBranchFormatRegistry, self).setUp()
239
self.registry = _mod_branch.BranchFormatRegistry()
241
def test_default(self):
242
self.assertIs(None, self.registry.get_default())
243
format = SampleBranchFormat()
244
self.registry.set_default(format)
245
self.assertEqual(format, self.registry.get_default())
247
161
def test_register_unregister_format(self):
248
162
format = SampleBranchFormat()
249
self.registry.register(format)
250
self.assertEqual(format,
251
self.registry.get("Sample branch format."))
252
self.registry.remove(format)
253
self.assertRaises(KeyError, self.registry.get,
254
"Sample branch format.")
256
def test_get_all(self):
257
format = SampleBranchFormat()
258
self.assertEqual([], self.registry._get_all())
259
self.registry.register(format)
260
self.assertEqual([format], self.registry._get_all())
262
def test_register_extra(self):
263
format = SampleExtraBranchFormat()
264
self.assertEqual([], self.registry._get_all())
265
self.registry.register_extra(format)
266
self.assertEqual([format], self.registry._get_all())
268
def test_register_extra_lazy(self):
269
self.assertEqual([], self.registry._get_all())
270
self.registry.register_extra_lazy("bzrlib.tests.test_branch",
271
"SampleExtraBranchFormat")
272
formats = self.registry._get_all()
273
self.assertEqual(1, len(formats))
274
self.assertIsInstance(formats[0], SampleExtraBranchFormat)
277
#Used by TestMetaDirBranchFormatFactory
278
FakeLazyFormat = None
281
class TestMetaDirBranchFormatFactory(tests.TestCase):
283
def test_get_format_string_does_not_load(self):
284
"""Formats have a static format string."""
285
factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
286
self.assertEqual("yo", factory.get_format_string())
288
def test_call_loads(self):
289
# __call__ is used by the network_format_registry interface to get a
291
global FakeLazyFormat
293
factory = _mod_branch.MetaDirBranchFormatFactory(None,
294
"bzrlib.tests.test_branch", "FakeLazyFormat")
295
self.assertRaises(AttributeError, factory)
297
def test_call_returns_call_of_referenced_object(self):
298
global FakeLazyFormat
299
FakeLazyFormat = lambda:'called'
300
factory = _mod_branch.MetaDirBranchFormatFactory(None,
301
"bzrlib.tests.test_branch", "FakeLazyFormat")
302
self.assertEqual('called', factory())
305
class TestBranch67(object):
306
"""Common tests for both branch 6 and 7 which are mostly the same."""
308
def get_format_name(self):
309
raise NotImplementedError(self.get_format_name)
311
def get_format_name_subtree(self):
312
raise NotImplementedError(self.get_format_name)
315
raise NotImplementedError(self.get_class)
164
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
166
format.initialize(dir)
167
# register a format for it.
168
BranchFormat.register_format(format)
169
# which branch.Open will refuse (not supported)
170
self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
171
self.make_branch_and_tree('foo')
172
# but open_downlevel will work
173
self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
174
# unregister the format
175
BranchFormat.unregister_format(format)
176
self.make_branch_and_tree('bar')
178
def test_checkout_format(self):
179
branch = self.make_repository('repository', shared=True)
180
branch = self.make_branch('repository/branch',
182
tree = branch.create_checkout('checkout')
183
self.assertIs(tree.branch.__class__, _mod_branch.BzrBranch5)
186
class TestBranch6(TestCaseWithTransport):
317
188
def test_creation(self):
318
format = bzrdir.BzrDirMetaFormat1()
189
format = BzrDirMetaFormat1()
319
190
format.set_branch_format(_mod_branch.BzrBranchFormat6())
320
191
branch = self.make_branch('a', format=format)
321
self.assertIsInstance(branch, self.get_class())
322
branch = self.make_branch('b', format=self.get_format_name())
323
self.assertIsInstance(branch, self.get_class())
192
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
193
branch = self.make_branch('b', format='dirstate-tags')
194
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
324
195
branch = _mod_branch.Branch.open('a')
325
self.assertIsInstance(branch, self.get_class())
196
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
327
198
def test_layout(self):
328
branch = self.make_branch('a', format=self.get_format_name())
329
self.assertPathExists('a/.bzr/branch/last-revision')
330
self.assertPathDoesNotExist('a/.bzr/branch/revision-history')
331
self.assertPathDoesNotExist('a/.bzr/branch/references')
199
branch = self.make_branch('a', format='dirstate-tags')
200
self.failUnlessExists('a/.bzr/branch/last-revision')
201
self.failIfExists('a/.bzr/branch/revision-history')
333
203
def test_config(self):
334
204
"""Ensure that all configuration data is stored in the branch"""
335
branch = self.make_branch('a', format=self.get_format_name())
336
branch.set_parent('http://example.com')
337
self.assertPathDoesNotExist('a/.bzr/branch/parent')
338
self.assertEqual('http://example.com', branch.get_parent())
339
branch.set_push_location('sftp://example.com')
340
conf = branch.get_config_stack()
341
self.assertEqual('sftp://example.com', conf.get('push_location'))
342
branch.set_bound_location('ftp://example.com')
343
self.assertPathDoesNotExist('a/.bzr/branch/bound')
344
self.assertEqual('ftp://example.com', branch.get_bound_location())
205
branch = self.make_branch('a', format='dirstate-tags')
206
branch.set_parent('http://bazaar-vcs.org')
207
self.failIfExists('a/.bzr/branch/parent')
208
self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
209
branch.set_push_location('sftp://bazaar-vcs.org')
210
config = branch.get_config()._get_branch_data_config()
211
self.assertEqual('sftp://bazaar-vcs.org',
212
config.get_user_option('push_location'))
213
branch.set_bound_location('ftp://bazaar-vcs.org')
214
self.failIfExists('a/.bzr/branch/bound')
215
self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
217
def test_set_revision_history(self):
218
tree = self.make_branch_and_memory_tree('.',
219
format='dirstate-tags')
223
tree.commit('foo', rev_id='foo')
224
tree.commit('bar', rev_id='bar')
225
tree.branch.set_revision_history(['foo', 'bar'])
226
tree.branch.set_revision_history(['foo'])
227
self.assertRaises(errors.NotLefthandHistory,
228
tree.branch.set_revision_history, ['bar'])
232
def test_append_revision(self):
233
tree = self.make_branch_and_tree('branch1',
234
format='dirstate-tags')
237
tree.commit('foo', rev_id='foo')
238
tree.commit('bar', rev_id='bar')
239
tree.commit('baz', rev_id='baz')
240
tree.set_last_revision('bar')
241
tree.branch.set_last_revision_info(2, 'bar')
242
tree.commit('qux', rev_id='qux')
243
tree.add_parent_tree_id('baz')
244
tree.commit('qux', rev_id='quxx')
245
tree.branch.set_last_revision_info(0, 'null:')
246
self.assertRaises(errors.NotLeftParentDescendant,
247
tree.branch.append_revision, 'bar')
248
tree.branch.append_revision('foo')
249
self.assertRaises(errors.NotLeftParentDescendant,
250
tree.branch.append_revision, 'baz')
251
tree.branch.append_revision('bar')
252
tree.branch.append_revision('baz')
253
self.assertRaises(errors.NotLeftParentDescendant,
254
tree.branch.append_revision, 'quxx')
346
258
def do_checkout_test(self, lightweight=False):
347
tree = self.make_branch_and_tree('source',
348
format=self.get_format_name_subtree())
259
tree = self.make_branch_and_tree('source', format='dirstate-with-subtree')
349
260
subtree = self.make_branch_and_tree('source/subtree',
350
format=self.get_format_name_subtree())
261
format='dirstate-with-subtree')
351
262
subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
352
format=self.get_format_name_subtree())
263
format='dirstate-with-subtree')
353
264
self.build_tree(['source/subtree/file',
354
265
'source/subtree/subsubtree/file'])
355
266
subsubtree.add('file')
360
271
subtree.commit('a subtree file')
361
272
subsubtree.commit('a subsubtree file')
362
273
tree.branch.create_checkout('target', lightweight=lightweight)
363
self.assertPathExists('target')
364
self.assertPathExists('target/subtree')
365
self.assertPathExists('target/subtree/file')
366
self.assertPathExists('target/subtree/subsubtree/file')
274
self.failUnlessExists('target')
275
self.failUnlessExists('target/subtree')
276
self.failUnlessExists('target/subtree/file')
277
self.failUnlessExists('target/subtree/subsubtree/file')
367
278
subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
369
280
self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
371
282
self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
373
285
def test_checkout_with_references(self):
374
286
self.do_checkout_test()
376
288
def test_light_checkout_with_references(self):
377
289
self.do_checkout_test(lightweight=True)
380
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
383
return _mod_branch.BzrBranch6
385
def get_format_name(self):
386
return "dirstate-tags"
388
def get_format_name_subtree(self):
389
return "dirstate-with-subtree"
391
def test_set_stacked_on_url_errors(self):
392
branch = self.make_branch('a', format=self.get_format_name())
393
self.assertRaises(errors.UnstackableBranchFormat,
394
branch.set_stacked_on_url, None)
396
def test_default_stacked_location(self):
397
branch = self.make_branch('a', format=self.get_format_name())
398
self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
401
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
404
return _mod_branch.BzrBranch7
406
def get_format_name(self):
409
def get_format_name_subtree(self):
410
return "development-subtree"
412
def test_set_stacked_on_url_unstackable_repo(self):
413
repo = self.make_repository('a', format='dirstate-tags')
414
control = repo.bzrdir
415
branch = _mod_branch.BzrBranchFormat7().initialize(control)
416
target = self.make_branch('b')
417
self.assertRaises(errors.UnstackableRepositoryFormat,
418
branch.set_stacked_on_url, target.base)
420
def test_clone_stacked_on_unstackable_repo(self):
421
repo = self.make_repository('a', format='dirstate-tags')
422
control = repo.bzrdir
423
branch = _mod_branch.BzrBranchFormat7().initialize(control)
424
# Calling clone should not raise UnstackableRepositoryFormat.
425
cloned_bzrdir = control.clone('cloned')
427
def _test_default_stacked_location(self):
428
branch = self.make_branch('a', format=self.get_format_name())
429
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
431
def test_stack_and_unstack(self):
432
branch = self.make_branch('a', format=self.get_format_name())
433
target = self.make_branch_and_tree('b', format=self.get_format_name())
434
branch.set_stacked_on_url(target.branch.base)
435
self.assertEqual(target.branch.base, branch.get_stacked_on_url())
436
revid = target.commit('foo')
437
self.assertTrue(branch.repository.has_revision(revid))
438
branch.set_stacked_on_url(None)
439
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
440
self.assertFalse(branch.repository.has_revision(revid))
442
def test_open_opens_stacked_reference(self):
443
branch = self.make_branch('a', format=self.get_format_name())
444
target = self.make_branch_and_tree('b', format=self.get_format_name())
445
branch.set_stacked_on_url(target.branch.base)
446
branch = branch.bzrdir.open_branch()
447
revid = target.commit('foo')
448
self.assertTrue(branch.repository.has_revision(revid))
451
class BzrBranch8(tests.TestCaseWithTransport):
453
def make_branch(self, location, format=None):
455
format = controldir.format_registry.make_bzrdir('1.9')
456
format.set_branch_format(_mod_branch.BzrBranchFormat8())
457
return tests.TestCaseWithTransport.make_branch(
458
self, location, format=format)
460
def create_branch_with_reference(self):
461
branch = self.make_branch('branch')
462
branch._set_all_reference_info({'file-id': ('path', 'location')})
466
def instrument_branch(branch, gets):
467
old_get = branch._transport.get
468
def get(*args, **kwargs):
469
gets.append((args, kwargs))
470
return old_get(*args, **kwargs)
471
branch._transport.get = get
473
def test_reference_info_caching_read_locked(self):
475
branch = self.create_branch_with_reference()
477
self.addCleanup(branch.unlock)
478
self.instrument_branch(branch, gets)
479
branch.get_reference_info('file-id')
480
branch.get_reference_info('file-id')
481
self.assertEqual(1, len(gets))
483
def test_reference_info_caching_read_unlocked(self):
485
branch = self.create_branch_with_reference()
486
self.instrument_branch(branch, gets)
487
branch.get_reference_info('file-id')
488
branch.get_reference_info('file-id')
489
self.assertEqual(2, len(gets))
491
def test_reference_info_caching_write_locked(self):
493
branch = self.make_branch('branch')
495
self.instrument_branch(branch, gets)
496
self.addCleanup(branch.unlock)
497
branch._set_all_reference_info({'file-id': ('path2', 'location2')})
498
path, location = branch.get_reference_info('file-id')
499
self.assertEqual(0, len(gets))
500
self.assertEqual('path2', path)
501
self.assertEqual('location2', location)
503
def test_reference_info_caches_cleared(self):
504
branch = self.make_branch('branch')
506
branch.set_reference_info('file-id', 'path2', 'location2')
508
doppelganger = _mod_branch.Branch.open('branch')
509
doppelganger.set_reference_info('file-id', 'path3', 'location3')
510
self.assertEqual(('path3', 'location3'),
511
branch.get_reference_info('file-id'))
513
def _recordParentMapCalls(self, repo):
514
self._parent_map_calls = []
515
orig_get_parent_map = repo.revisions.get_parent_map
516
def get_parent_map(q):
518
self._parent_map_calls.extend([e[0] for e in q])
519
return orig_get_parent_map(q)
520
repo.revisions.get_parent_map = get_parent_map
523
class TestBranchReference(tests.TestCaseWithTransport):
291
class TestBranchReference(TestCaseWithTransport):
524
292
"""Tests for the branch reference facility."""
526
294
def test_create_open_reference(self):
527
295
bzrdirformat = bzrdir.BzrDirMetaFormat1()
528
t = self.get_transport()
296
t = get_transport(self.get_url('.'))
530
298
dir = bzrdirformat.initialize(self.get_url('repo'))
531
299
dir.create_repository()
532
300
target_branch = dir.create_branch()
533
301
t.mkdir('branch')
534
302
branch_dir = bzrdirformat.initialize(self.get_url('branch'))
535
made_branch = _mod_branch.BranchReferenceFormat().initialize(
536
branch_dir, target_branch=target_branch)
303
made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
537
304
self.assertEqual(made_branch.base, target_branch.base)
538
305
opened_branch = branch_dir.open_branch()
539
306
self.assertEqual(opened_branch.base, target_branch.base)
541
def test_get_reference(self):
542
"""For a BranchReference, get_reference should return the location."""
543
branch = self.make_branch('target')
544
checkout = branch.create_checkout('checkout', lightweight=True)
545
reference_url = branch.bzrdir.root_transport.abspath('') + '/'
546
# if the api for create_checkout changes to return different checkout types
547
# then this file read will fail.
548
self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
549
self.assertEqual(reference_url,
550
_mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
553
class TestHooks(tests.TestCaseWithTransport):
309
class TestHooks(TestCase):
555
311
def test_constructor(self):
556
312
"""Check that creating a BranchHooks instance has the right defaults."""
557
hooks = _mod_branch.BranchHooks()
313
hooks = BranchHooks()
314
self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
558
315
self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
559
316
self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
560
self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
561
317
self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
562
self.assertTrue("post_uncommit" in hooks,
563
"post_uncommit not in %s" % hooks)
564
self.assertTrue("post_change_branch_tip" in hooks,
565
"post_change_branch_tip not in %s" % hooks)
566
self.assertTrue("post_branch_init" in hooks,
567
"post_branch_init not in %s" % hooks)
568
self.assertTrue("post_switch" in hooks,
569
"post_switch not in %s" % hooks)
318
self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
571
320
def test_installed_hooks_are_BranchHooks(self):
572
321
"""The installed hooks object should be a BranchHooks."""
573
322
# the installed hooks are saved in self._preserved_hooks.
574
self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
575
_mod_branch.BranchHooks)
577
def test_post_branch_init_hook(self):
579
_mod_branch.Branch.hooks.install_named_hook('post_branch_init',
581
self.assertLength(0, calls)
582
branch = self.make_branch('a')
583
self.assertLength(1, calls)
585
self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
586
self.assertTrue(hasattr(params, 'bzrdir'))
587
self.assertTrue(hasattr(params, 'branch'))
589
def test_post_branch_init_hook_repr(self):
591
_mod_branch.Branch.hooks.install_named_hook('post_branch_init',
592
lambda params: param_reprs.append(repr(params)), None)
593
branch = self.make_branch('a')
594
self.assertLength(1, param_reprs)
595
param_repr = param_reprs[0]
596
self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
598
def test_post_switch_hook(self):
599
from bzrlib import switch
601
_mod_branch.Branch.hooks.install_named_hook('post_switch',
603
tree = self.make_branch_and_tree('branch-1')
604
self.build_tree(['branch-1/file-1'])
607
to_branch = tree.bzrdir.sprout('branch-2').open_branch()
608
self.build_tree(['branch-1/file-2'])
610
tree.remove('file-1')
612
checkout = tree.branch.create_checkout('checkout')
613
self.assertLength(0, calls)
614
switch.switch(checkout.bzrdir, to_branch)
615
self.assertLength(1, calls)
617
self.assertIsInstance(params, _mod_branch.SwitchHookParams)
618
self.assertTrue(hasattr(params, 'to_branch'))
619
self.assertTrue(hasattr(params, 'revision_id'))
622
class TestBranchOptions(tests.TestCaseWithTransport):
625
super(TestBranchOptions, self).setUp()
626
self.branch = self.make_branch('.')
627
self.config_stack = self.branch.get_config_stack()
629
def check_append_revisions_only(self, expected_value, value=None):
630
"""Set append_revisions_only in config and check its interpretation."""
631
if value is not None:
632
self.config_stack.set('append_revisions_only', value)
633
self.assertEqual(expected_value,
634
self.branch.get_append_revisions_only())
636
def test_valid_append_revisions_only(self):
637
self.assertEqual(None,
638
self.config_stack.get('append_revisions_only'))
639
self.check_append_revisions_only(None)
640
self.check_append_revisions_only(False, 'False')
641
self.check_append_revisions_only(True, 'True')
642
# The following values will cause compatibility problems on projects
643
# using older bzr versions (<2.2) but are accepted
644
self.check_append_revisions_only(False, 'false')
645
self.check_append_revisions_only(True, 'true')
647
def test_invalid_append_revisions_only(self):
648
"""Ensure warning is noted on invalid settings"""
651
self.warnings.append(args[0] % args[1:])
652
self.overrideAttr(trace, 'warning', warning)
653
self.check_append_revisions_only(None, 'not-a-bool')
654
self.assertLength(1, self.warnings)
656
'Value "not-a-bool" is not valid for "append_revisions_only"',
659
def test_use_fresh_values(self):
660
copy = _mod_branch.Branch.open(self.branch.base)
663
copy.get_config_stack().set('foo', 'bar')
666
self.assertFalse(self.branch.is_locked())
667
# Since the branch is locked, the option value won't be saved on disk
668
# so trying to access the config of locked branch via another older
669
# non-locked branch object pointing to the same branch is not supported
670
self.assertEqual(None, self.branch.get_config_stack().get('foo'))
671
# Using a newly created branch object works as expected
672
fresh = _mod_branch.Branch.open(self.branch.base)
673
self.assertEqual('bar', fresh.get_config_stack().get('foo'))
675
def test_set_from_config_get_from_config_stack(self):
676
self.branch.lock_write()
677
self.addCleanup(self.branch.unlock)
678
self.branch.get_config().set_user_option('foo', 'bar')
679
result = self.branch.get_config_stack().get('foo')
680
# https://bugs.launchpad.net/bzr/+bug/948344
681
self.expectFailure('BranchStack uses cache after set_user_option',
682
self.assertEqual, 'bar', result)
684
def test_set_from_config_stack_get_from_config(self):
685
self.branch.lock_write()
686
self.addCleanup(self.branch.unlock)
687
self.branch.get_config_stack().set('foo', 'bar')
688
# Since the branch is locked, the option value won't be saved on disk
689
# so mixing get() and get_user_option() is broken by design.
690
self.assertEqual(None,
691
self.branch.get_config().get_user_option('foo'))
693
def test_set_delays_write_when_branch_is_locked(self):
694
self.branch.lock_write()
695
self.addCleanup(self.branch.unlock)
696
self.branch.get_config_stack().set('foo', 'bar')
697
copy = _mod_branch.Branch.open(self.branch.base)
698
result = copy.get_config_stack().get('foo')
699
# Accessing from a different branch object is like accessing from a
700
# different process: the option has not been saved yet and the new
701
# value cannot be seen.
702
self.assertIs(None, result)
705
class TestPullResult(tests.TestCase):
707
def test_report_changed(self):
708
r = _mod_branch.PullResult()
709
r.old_revid = "old-revid"
323
self.assertIsInstance(self._preserved_hooks, BranchHooks)
325
def test_install_hook_raises_unknown_hook(self):
326
"""install_hook should raise UnknownHook if a hook is unknown."""
327
hooks = BranchHooks()
328
self.assertRaises(UnknownHook, hooks.install_hook, 'silly', None)
330
def test_install_hook_appends_known_hook(self):
331
"""install_hook should append the callable for known hooks."""
332
hooks = BranchHooks()
333
hooks.install_hook('set_rh', None)
334
self.assertEqual(hooks['set_rh'], [None])
337
class TestPullResult(TestCase):
339
def test_pull_result_to_int(self):
340
# to support old code, the pull result can be used as an int
711
r.new_revid = "new-revid"
715
self.assertEqual("Now on revision 20.\n", f.getvalue())
716
self.assertEqual("Now on revision 20.\n", f.getvalue())
718
def test_report_unchanged(self):
719
r = _mod_branch.PullResult()
720
r.old_revid = "same-revid"
721
r.new_revid = "same-revid"
724
self.assertEqual("No revisions or tags to pull.\n", f.getvalue())
344
# this usage of results is not recommended for new code (because it
345
# doesn't describe very well what happened), but for api stability
346
# it's still supported
347
a = "%d revisions pulled" % r
348
self.assertEqual(a, "10 revisions pulled")