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,
39
class TestDefaultFormat(tests.TestCase):
41
def test_default_format(self):
42
# update this if you change the default branch format
43
self.assertIsInstance(_mod_branch.format_registry.get_default(),
44
_mod_branch.BzrBranchFormat7)
46
def test_default_format_is_same_as_bzrdir_default(self):
47
# XXX: it might be nice if there was only one place the default was
48
# set, but at the moment that's not true -- mbp 20070814 --
49
# https://bugs.launchpad.net/bzr/+bug/132376
51
_mod_branch.format_registry.get_default(),
52
bzrdir.BzrDirFormat.get_default_format().get_branch_format())
33
from bzrlib.branch import (
37
BranchReferenceFormat,
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):
54
55
def test_get_set_default_format(self):
55
# set the format and then set it back again
56
old_format = _mod_branch.format_registry.get_default()
57
_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())
59
61
# the default branch format is used by the meta dir format
60
62
# which is not the default bzrdir format at this point
61
dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
63
dir = BzrDirMetaFormat1().initialize('memory:///')
62
64
result = dir.create_branch()
63
65
self.assertEqual(result, 'A branch')
65
_mod_branch.format_registry.set_default(old_format)
66
self.assertEqual(old_format,
67
_mod_branch.format_registry.get_default())
70
class TestBranchFormat5(tests.TestCaseWithTransport):
67
BranchFormat.set_default_format(old_format)
68
self.assertEqual(old_format, BranchFormat.get_default_format())
71
class TestBranchFormat5(TestCaseWithTransport):
71
72
"""Tests specific to branch format 5"""
73
74
def test_branch_format_5_uses_lockdir(self):
74
75
url = self.get_url()
75
bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
76
bdir.create_repository()
77
branch = _mod_branch.BzrBranchFormat5().initialize(bdir)
76
bzrdir = BzrDirMetaFormat1().initialize(url)
77
bzrdir.create_repository()
78
branch = bzrdir.create_branch()
78
79
t = self.get_transport()
79
80
self.log("branch instance is %r" % branch)
80
self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
81
self.assert_(isinstance(branch, BzrBranch5))
81
82
self.assertIsDirectory('.', t)
82
83
self.assertIsDirectory('.bzr/branch', t)
83
84
self.assertIsDirectory('.bzr/branch/lock', t)
84
85
branch.lock_write()
85
self.addCleanup(branch.unlock)
86
self.assertIsDirectory('.bzr/branch/lock/held', t)
87
self.assertIsDirectory('.bzr/branch/lock/held', t)
88
91
def test_set_push_location(self):
89
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()
91
96
branch = self.make_branch('.', format='knit')
92
97
branch.set_push_location('foo')
93
98
local_path = urlutils.local_path_from_url(branch.base[:-1])
94
self.assertFileEqual("# comment\n"
99
self.assertFileEqual("[%s]\n"
96
100
"push_location = foo\n"
97
"push_location:policy = norecurse\n" % local_path,
98
config.locations_config_filename())
101
"push_location:policy = norecurse" % local_path,
100
104
# TODO RBC 20051029 test getting a push location from a branch in a
101
105
# recursive section - that is, it appends the branch name.
104
class SampleBranchFormat(_mod_branch.BranchFormat):
108
class SampleBranchFormat(BranchFormat):
105
109
"""A sample format
107
this format is initializable, unsupported to aid in testing the
111
this format is initializable, unsupported to aid in testing the
108
112
open and open_downlevel routines.
112
116
"""See BzrBranchFormat.get_format_string()."""
113
117
return "Sample branch format."
115
def initialize(self, a_bzrdir, name=None, repository=None):
119
def initialize(self, a_bzrdir):
116
120
"""Format 4 branches cannot be created."""
117
t = a_bzrdir.get_branch_transport(self, name=name)
121
t = a_bzrdir.get_branch_transport(self)
118
122
t.put_bytes('format', self.get_format_string())
119
123
return 'A branch'
121
125
def is_supported(self):
124
def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
128
def open(self, transport, _found=False):
125
129
return "opened branch."
128
# Demonstrating how lazy loading is often implemented:
129
# A constant string is created.
130
SampleSupportedBranchFormatString = "Sample supported branch format."
132
# And the format class can then reference the constant to avoid skew.
133
class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
134
"""A sample supported format."""
136
def get_format_string(self):
137
"""See BzrBranchFormat.get_format_string()."""
138
return SampleSupportedBranchFormatString
140
def initialize(self, a_bzrdir, name=None):
141
t = a_bzrdir.get_branch_transport(self, name=name)
142
t.put_bytes('format', self.get_format_string())
145
def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
146
return "opened supported branch."
149
class SampleExtraBranchFormat(_mod_branch.BranchFormat):
150
"""A sample format that is not usable in a metadir."""
152
def get_format_string(self):
153
# This format is not usable in a metadir.
156
def network_name(self):
157
# Network name always has to be provided.
160
def initialize(self, a_bzrdir, name=None):
161
raise NotImplementedError(self.initialize)
163
def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
164
raise NotImplementedError(self.open)
167
class TestBzrBranchFormat(tests.TestCaseWithTransport):
132
class TestBzrBranchFormat(TestCaseWithTransport):
168
133
"""Tests for the BzrBranchFormat facility."""
170
135
def test_find_format(self):
171
136
# is the right format object found for a branch?
172
137
# create a branch with a few known format objects.
173
# this is not quite the same as
138
# this is not quite the same as
174
139
self.build_tree(["foo/", "bar/"])
175
140
def check_format(format, url):
176
141
dir = format._matchingbzrdir.initialize(url)
177
142
dir.create_repository()
178
143
format.initialize(dir)
179
found_format = _mod_branch.BranchFormat.find_format(dir)
180
self.assertIsInstance(found_format, format.__class__)
181
check_format(_mod_branch.BzrBranchFormat5(), "bar")
183
def test_find_format_factory(self):
184
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
185
SampleSupportedBranchFormat().initialize(dir)
186
factory = _mod_branch.MetaDirBranchFormatFactory(
187
SampleSupportedBranchFormatString,
188
"bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
189
_mod_branch.format_registry.register(factory)
190
self.addCleanup(_mod_branch.format_registry.remove, factory)
191
b = _mod_branch.Branch.open(self.get_url())
192
self.assertEqual(b, "opened supported branch.")
144
found_format = BranchFormat.find_format(dir)
145
self.failUnless(isinstance(found_format, format.__class__))
146
check_format(BzrBranchFormat5(), "bar")
194
148
def test_find_format_not_branch(self):
195
149
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
196
self.assertRaises(errors.NotBranchError,
197
_mod_branch.BranchFormat.find_format,
150
self.assertRaises(NotBranchError,
151
BranchFormat.find_format,
200
154
def test_find_format_unknown_format(self):
201
155
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
202
156
SampleBranchFormat().initialize(dir)
203
self.assertRaises(errors.UnknownFormatError,
204
_mod_branch.BranchFormat.find_format,
157
self.assertRaises(UnknownFormatError,
158
BranchFormat.find_format,
207
161
def test_register_unregister_format(self):
208
# Test the deprecated format registration functions
209
162
format = SampleBranchFormat()
210
163
# make a control dir
211
164
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
213
166
format.initialize(dir)
214
167
# register a format for it.
215
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
216
_mod_branch.BranchFormat.register_format, format)
168
BranchFormat.register_format(format)
217
169
# which branch.Open will refuse (not supported)
218
self.assertRaises(errors.UnsupportedFormatError,
219
_mod_branch.Branch.open, self.get_url())
170
self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
220
171
self.make_branch_and_tree('foo')
221
172
# but open_downlevel will work
224
bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
173
self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
225
174
# unregister the format
226
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
227
_mod_branch.BranchFormat.unregister_format, format)
175
BranchFormat.unregister_format(format)
228
176
self.make_branch_and_tree('bar')
231
class TestBranchFormatRegistry(tests.TestCase):
234
super(TestBranchFormatRegistry, self).setUp()
235
self.registry = _mod_branch.BranchFormatRegistry()
237
def test_default(self):
238
self.assertIs(None, self.registry.get_default())
239
format = SampleBranchFormat()
240
self.registry.set_default(format)
241
self.assertEquals(format, self.registry.get_default())
243
def test_register_unregister_format(self):
244
format = SampleBranchFormat()
245
self.registry.register(format)
246
self.assertEquals(format,
247
self.registry.get("Sample branch format."))
248
self.registry.remove(format)
249
self.assertRaises(KeyError, self.registry.get,
250
"Sample branch format.")
252
def test_get_all(self):
253
format = SampleBranchFormat()
254
self.assertEquals([], self.registry._get_all())
255
self.registry.register(format)
256
self.assertEquals([format], self.registry._get_all())
258
def test_register_extra(self):
259
format = SampleExtraBranchFormat()
260
self.assertEquals([], self.registry._get_all())
261
self.registry.register_extra(format)
262
self.assertEquals([format], self.registry._get_all())
264
def test_register_extra_lazy(self):
265
self.assertEquals([], self.registry._get_all())
266
self.registry.register_extra_lazy("bzrlib.tests.test_branch",
267
"SampleExtraBranchFormat")
268
formats = self.registry._get_all()
269
self.assertEquals(1, len(formats))
270
self.assertIsInstance(formats[0], SampleExtraBranchFormat)
273
#Used by TestMetaDirBranchFormatFactory
274
FakeLazyFormat = None
277
class TestMetaDirBranchFormatFactory(tests.TestCase):
279
def test_get_format_string_does_not_load(self):
280
"""Formats have a static format string."""
281
factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
282
self.assertEqual("yo", factory.get_format_string())
284
def test_call_loads(self):
285
# __call__ is used by the network_format_registry interface to get a
287
global FakeLazyFormat
289
factory = _mod_branch.MetaDirBranchFormatFactory(None,
290
"bzrlib.tests.test_branch", "FakeLazyFormat")
291
self.assertRaises(AttributeError, factory)
293
def test_call_returns_call_of_referenced_object(self):
294
global FakeLazyFormat
295
FakeLazyFormat = lambda:'called'
296
factory = _mod_branch.MetaDirBranchFormatFactory(None,
297
"bzrlib.tests.test_branch", "FakeLazyFormat")
298
self.assertEqual('called', factory())
301
class TestBranch67(object):
302
"""Common tests for both branch 6 and 7 which are mostly the same."""
304
def get_format_name(self):
305
raise NotImplementedError(self.get_format_name)
307
def get_format_name_subtree(self):
308
raise NotImplementedError(self.get_format_name)
311
raise NotImplementedError(self.get_class)
179
class TestBranch6(TestCaseWithTransport):
313
181
def test_creation(self):
314
format = bzrdir.BzrDirMetaFormat1()
182
format = BzrDirMetaFormat1()
315
183
format.set_branch_format(_mod_branch.BzrBranchFormat6())
316
184
branch = self.make_branch('a', format=format)
317
self.assertIsInstance(branch, self.get_class())
318
branch = self.make_branch('b', format=self.get_format_name())
319
self.assertIsInstance(branch, self.get_class())
185
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
186
branch = self.make_branch('b', format='dirstate-tags')
187
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
320
188
branch = _mod_branch.Branch.open('a')
321
self.assertIsInstance(branch, self.get_class())
189
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
323
191
def test_layout(self):
324
branch = self.make_branch('a', format=self.get_format_name())
325
self.assertPathExists('a/.bzr/branch/last-revision')
326
self.assertPathDoesNotExist('a/.bzr/branch/revision-history')
327
self.assertPathDoesNotExist('a/.bzr/branch/references')
192
branch = self.make_branch('a', format='dirstate-tags')
193
self.failUnlessExists('a/.bzr/branch/last-revision')
194
self.failIfExists('a/.bzr/branch/revision-history')
329
196
def test_config(self):
330
197
"""Ensure that all configuration data is stored in the branch"""
331
branch = self.make_branch('a', format=self.get_format_name())
332
branch.set_parent('http://example.com')
333
self.assertPathDoesNotExist('a/.bzr/branch/parent')
334
self.assertEqual('http://example.com', branch.get_parent())
335
branch.set_push_location('sftp://example.com')
198
branch = self.make_branch('a', format='dirstate-tags')
199
branch.set_parent('http://bazaar-vcs.org')
200
self.failIfExists('a/.bzr/branch/parent')
201
self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
202
branch.set_push_location('sftp://bazaar-vcs.org')
336
203
config = branch.get_config()._get_branch_data_config()
337
self.assertEqual('sftp://example.com',
204
self.assertEqual('sftp://bazaar-vcs.org',
338
205
config.get_user_option('push_location'))
339
branch.set_bound_location('ftp://example.com')
340
self.assertPathDoesNotExist('a/.bzr/branch/bound')
341
self.assertEqual('ftp://example.com', branch.get_bound_location())
206
branch.set_bound_location('ftp://bazaar-vcs.org')
207
self.failIfExists('a/.bzr/branch/bound')
208
self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
343
210
def test_set_revision_history(self):
344
builder = self.make_branch_builder('.', format=self.get_format_name())
345
builder.build_snapshot('foo', None,
346
[('add', ('', None, 'directory', None))],
348
builder.build_snapshot('bar', None, [], message='bar')
349
branch = builder.get_branch()
351
self.addCleanup(branch.unlock)
352
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
353
branch.set_revision_history, ['foo', 'bar'])
354
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
355
branch.set_revision_history, ['foo'])
356
self.assertRaises(errors.NotLefthandHistory,
357
self.applyDeprecated, symbol_versioning.deprecated_in((2, 4, 0)),
358
branch.set_revision_history, ['bar'])
211
tree = self.make_branch_and_memory_tree('.',
212
format='dirstate-tags')
216
tree.commit('foo', rev_id='foo')
217
tree.commit('bar', rev_id='bar')
218
tree.branch.set_revision_history(['foo', 'bar'])
219
tree.branch.set_revision_history(['foo'])
220
self.assertRaises(errors.NotLefthandHistory,
221
tree.branch.set_revision_history, ['bar'])
225
def test_append_revision(self):
226
tree = self.make_branch_and_tree('branch1',
227
format='dirstate-tags')
230
tree.commit('foo', rev_id='foo')
231
tree.commit('bar', rev_id='bar')
232
tree.commit('baz', rev_id='baz')
233
tree.set_last_revision('bar')
234
tree.branch.set_last_revision_info(2, 'bar')
235
tree.commit('qux', rev_id='qux')
236
tree.add_parent_tree_id('baz')
237
tree.commit('qux', rev_id='quxx')
238
tree.branch.set_last_revision_info(0, 'null:')
239
self.assertRaises(errors.NotLeftParentDescendant,
240
tree.branch.append_revision, 'bar')
241
tree.branch.append_revision('foo')
242
self.assertRaises(errors.NotLeftParentDescendant,
243
tree.branch.append_revision, 'baz')
244
tree.branch.append_revision('bar')
245
tree.branch.append_revision('baz')
246
self.assertRaises(errors.NotLeftParentDescendant,
247
tree.branch.append_revision, 'quxx')
360
251
def do_checkout_test(self, lightweight=False):
361
tree = self.make_branch_and_tree('source',
362
format=self.get_format_name_subtree())
252
tree = self.make_branch_and_tree('source', format='dirstate-with-subtree')
363
253
subtree = self.make_branch_and_tree('source/subtree',
364
format=self.get_format_name_subtree())
254
format='dirstate-with-subtree')
365
255
subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
366
format=self.get_format_name_subtree())
256
format='dirstate-with-subtree')
367
257
self.build_tree(['source/subtree/file',
368
258
'source/subtree/subsubtree/file'])
369
259
subsubtree.add('file')
374
264
subtree.commit('a subtree file')
375
265
subsubtree.commit('a subsubtree file')
376
266
tree.branch.create_checkout('target', lightweight=lightweight)
377
self.assertPathExists('target')
378
self.assertPathExists('target/subtree')
379
self.assertPathExists('target/subtree/file')
380
self.assertPathExists('target/subtree/subsubtree/file')
267
self.failUnlessExists('target')
268
self.failUnlessExists('target/subtree')
269
self.failUnlessExists('target/subtree/file')
270
self.failUnlessExists('target/subtree/subsubtree/file')
381
271
subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
383
273
self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
385
275
self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
387
278
def test_checkout_with_references(self):
388
279
self.do_checkout_test()
390
281
def test_light_checkout_with_references(self):
391
282
self.do_checkout_test(lightweight=True)
393
def test_set_push(self):
394
branch = self.make_branch('source', format=self.get_format_name())
395
branch.get_config().set_user_option('push_location', 'old',
396
store=config.STORE_LOCATION)
399
warnings.append(args[0] % args[1:])
400
_warning = trace.warning
401
trace.warning = warning
403
branch.set_push_location('new')
405
trace.warning = _warning
406
self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
410
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
413
return _mod_branch.BzrBranch6
415
def get_format_name(self):
416
return "dirstate-tags"
418
def get_format_name_subtree(self):
419
return "dirstate-with-subtree"
421
def test_set_stacked_on_url_errors(self):
422
branch = self.make_branch('a', format=self.get_format_name())
423
self.assertRaises(errors.UnstackableBranchFormat,
424
branch.set_stacked_on_url, None)
426
def test_default_stacked_location(self):
427
branch = self.make_branch('a', format=self.get_format_name())
428
self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
431
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
434
return _mod_branch.BzrBranch7
436
def get_format_name(self):
439
def get_format_name_subtree(self):
440
return "development-subtree"
442
def test_set_stacked_on_url_unstackable_repo(self):
443
repo = self.make_repository('a', format='dirstate-tags')
444
control = repo.bzrdir
445
branch = _mod_branch.BzrBranchFormat7().initialize(control)
446
target = self.make_branch('b')
447
self.assertRaises(errors.UnstackableRepositoryFormat,
448
branch.set_stacked_on_url, target.base)
450
def test_clone_stacked_on_unstackable_repo(self):
451
repo = self.make_repository('a', format='dirstate-tags')
452
control = repo.bzrdir
453
branch = _mod_branch.BzrBranchFormat7().initialize(control)
454
# Calling clone should not raise UnstackableRepositoryFormat.
455
cloned_bzrdir = control.clone('cloned')
457
def _test_default_stacked_location(self):
458
branch = self.make_branch('a', format=self.get_format_name())
459
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
461
def test_stack_and_unstack(self):
462
branch = self.make_branch('a', format=self.get_format_name())
463
target = self.make_branch_and_tree('b', format=self.get_format_name())
464
branch.set_stacked_on_url(target.branch.base)
465
self.assertEqual(target.branch.base, branch.get_stacked_on_url())
466
revid = target.commit('foo')
467
self.assertTrue(branch.repository.has_revision(revid))
468
branch.set_stacked_on_url(None)
469
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
470
self.assertFalse(branch.repository.has_revision(revid))
472
def test_open_opens_stacked_reference(self):
473
branch = self.make_branch('a', format=self.get_format_name())
474
target = self.make_branch_and_tree('b', format=self.get_format_name())
475
branch.set_stacked_on_url(target.branch.base)
476
branch = branch.bzrdir.open_branch()
477
revid = target.commit('foo')
478
self.assertTrue(branch.repository.has_revision(revid))
481
class BzrBranch8(tests.TestCaseWithTransport):
483
def make_branch(self, location, format=None):
485
format = bzrdir.format_registry.make_bzrdir('1.9')
486
format.set_branch_format(_mod_branch.BzrBranchFormat8())
487
return tests.TestCaseWithTransport.make_branch(
488
self, location, format=format)
490
def create_branch_with_reference(self):
491
branch = self.make_branch('branch')
492
branch._set_all_reference_info({'file-id': ('path', 'location')})
496
def instrument_branch(branch, gets):
497
old_get = branch._transport.get
498
def get(*args, **kwargs):
499
gets.append((args, kwargs))
500
return old_get(*args, **kwargs)
501
branch._transport.get = get
503
def test_reference_info_caching_read_locked(self):
505
branch = self.create_branch_with_reference()
507
self.addCleanup(branch.unlock)
508
self.instrument_branch(branch, gets)
509
branch.get_reference_info('file-id')
510
branch.get_reference_info('file-id')
511
self.assertEqual(1, len(gets))
513
def test_reference_info_caching_read_unlocked(self):
515
branch = self.create_branch_with_reference()
516
self.instrument_branch(branch, gets)
517
branch.get_reference_info('file-id')
518
branch.get_reference_info('file-id')
519
self.assertEqual(2, len(gets))
521
def test_reference_info_caching_write_locked(self):
523
branch = self.make_branch('branch')
525
self.instrument_branch(branch, gets)
526
self.addCleanup(branch.unlock)
527
branch._set_all_reference_info({'file-id': ('path2', 'location2')})
528
path, location = branch.get_reference_info('file-id')
529
self.assertEqual(0, len(gets))
530
self.assertEqual('path2', path)
531
self.assertEqual('location2', location)
533
def test_reference_info_caches_cleared(self):
534
branch = self.make_branch('branch')
536
branch.set_reference_info('file-id', 'path2', 'location2')
538
doppelganger = _mod_branch.Branch.open('branch')
539
doppelganger.set_reference_info('file-id', 'path3', 'location3')
540
self.assertEqual(('path3', 'location3'),
541
branch.get_reference_info('file-id'))
543
class TestBranchReference(tests.TestCaseWithTransport):
284
class TestBranchReference(TestCaseWithTransport):
544
285
"""Tests for the branch reference facility."""
546
287
def test_create_open_reference(self):
547
288
bzrdirformat = bzrdir.BzrDirMetaFormat1()
548
t = self.get_transport()
289
t = get_transport(self.get_url('.'))
550
291
dir = bzrdirformat.initialize(self.get_url('repo'))
551
292
dir.create_repository()
552
293
target_branch = dir.create_branch()
553
294
t.mkdir('branch')
554
295
branch_dir = bzrdirformat.initialize(self.get_url('branch'))
555
made_branch = _mod_branch.BranchReferenceFormat().initialize(
556
branch_dir, target_branch=target_branch)
296
made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
557
297
self.assertEqual(made_branch.base, target_branch.base)
558
298
opened_branch = branch_dir.open_branch()
559
299
self.assertEqual(opened_branch.base, target_branch.base)
561
def test_get_reference(self):
562
"""For a BranchReference, get_reference should reutrn the location."""
563
branch = self.make_branch('target')
564
checkout = branch.create_checkout('checkout', lightweight=True)
565
reference_url = branch.bzrdir.root_transport.abspath('') + '/'
566
# if the api for create_checkout changes to return different checkout types
567
# then this file read will fail.
568
self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
569
self.assertEqual(reference_url,
570
_mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
573
class TestHooks(tests.TestCaseWithTransport):
302
class TestHooks(TestCase):
575
304
def test_constructor(self):
576
305
"""Check that creating a BranchHooks instance has the right defaults."""
577
hooks = _mod_branch.BranchHooks()
306
hooks = BranchHooks()
578
307
self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
579
308
self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
580
309
self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
581
self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
582
310
self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
583
self.assertTrue("post_uncommit" in hooks,
584
"post_uncommit not in %s" % hooks)
585
self.assertTrue("post_change_branch_tip" in hooks,
586
"post_change_branch_tip not in %s" % hooks)
587
self.assertTrue("post_branch_init" in hooks,
588
"post_branch_init not in %s" % hooks)
589
self.assertTrue("post_switch" in hooks,
590
"post_switch not in %s" % hooks)
311
self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
592
313
def test_installed_hooks_are_BranchHooks(self):
593
314
"""The installed hooks object should be a BranchHooks."""
594
315
# the installed hooks are saved in self._preserved_hooks.
595
self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
596
_mod_branch.BranchHooks)
598
def test_post_branch_init_hook(self):
600
_mod_branch.Branch.hooks.install_named_hook('post_branch_init',
602
self.assertLength(0, calls)
603
branch = self.make_branch('a')
604
self.assertLength(1, calls)
606
self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
607
self.assertTrue(hasattr(params, 'bzrdir'))
608
self.assertTrue(hasattr(params, 'branch'))
610
def test_post_branch_init_hook_repr(self):
612
_mod_branch.Branch.hooks.install_named_hook('post_branch_init',
613
lambda params: param_reprs.append(repr(params)), None)
614
branch = self.make_branch('a')
615
self.assertLength(1, param_reprs)
616
param_repr = param_reprs[0]
617
self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
619
def test_post_switch_hook(self):
620
from bzrlib import switch
622
_mod_branch.Branch.hooks.install_named_hook('post_switch',
624
tree = self.make_branch_and_tree('branch-1')
625
self.build_tree(['branch-1/file-1'])
628
to_branch = tree.bzrdir.sprout('branch-2').open_branch()
629
self.build_tree(['branch-1/file-2'])
631
tree.remove('file-1')
633
checkout = tree.branch.create_checkout('checkout')
634
self.assertLength(0, calls)
635
switch.switch(checkout.bzrdir, to_branch)
636
self.assertLength(1, calls)
638
self.assertIsInstance(params, _mod_branch.SwitchHookParams)
639
self.assertTrue(hasattr(params, 'to_branch'))
640
self.assertTrue(hasattr(params, 'revision_id'))
643
class TestBranchOptions(tests.TestCaseWithTransport):
646
super(TestBranchOptions, self).setUp()
647
self.branch = self.make_branch('.')
648
self.config = self.branch.get_config()
650
def check_append_revisions_only(self, expected_value, value=None):
651
"""Set append_revisions_only in config and check its interpretation."""
652
if value is not None:
653
self.config.set_user_option('append_revisions_only', value)
654
self.assertEqual(expected_value,
655
self.branch._get_append_revisions_only())
657
def test_valid_append_revisions_only(self):
658
self.assertEquals(None,
659
self.config.get_user_option('append_revisions_only'))
660
self.check_append_revisions_only(None)
661
self.check_append_revisions_only(False, 'False')
662
self.check_append_revisions_only(True, 'True')
663
# The following values will cause compatibility problems on projects
664
# using older bzr versions (<2.2) but are accepted
665
self.check_append_revisions_only(False, 'false')
666
self.check_append_revisions_only(True, 'true')
668
def test_invalid_append_revisions_only(self):
669
"""Ensure warning is noted on invalid settings"""
672
self.warnings.append(args[0] % args[1:])
673
self.overrideAttr(trace, 'warning', warning)
674
self.check_append_revisions_only(None, 'not-a-bool')
675
self.assertLength(1, self.warnings)
677
'Value "not-a-bool" is not a boolean for "append_revisions_only"',
681
class TestPullResult(tests.TestCase):
316
self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch], BranchHooks)
318
def test_install_hook_raises_unknown_hook(self):
319
"""install_hook should raise UnknownHook if a hook is unknown."""
320
hooks = BranchHooks()
321
self.assertRaises(UnknownHook, hooks.install_hook, 'silly', None)
323
def test_install_hook_appends_known_hook(self):
324
"""install_hook should append the callable for known hooks."""
325
hooks = BranchHooks()
326
hooks.install_hook('set_rh', None)
327
self.assertEqual(hooks['set_rh'], [None])
330
class TestPullResult(TestCase):
683
332
def test_pull_result_to_int(self):
684
333
# to support old code, the pull result can be used as an int
685
r = _mod_branch.PullResult()
688
337
# this usage of results is not recommended for new code (because it
689
338
# doesn't describe very well what happened), but for api stability
690
339
# it's still supported
691
self.assertEqual(self.applyDeprecated(
692
symbol_versioning.deprecated_in((2, 3, 0)),
696
def test_report_changed(self):
697
r = _mod_branch.PullResult()
698
r.old_revid = "old-revid"
700
r.new_revid = "new-revid"
704
self.assertEqual("Now on revision 20.\n", f.getvalue())
706
def test_report_unchanged(self):
707
r = _mod_branch.PullResult()
708
r.old_revid = "same-revid"
709
r.new_revid = "same-revid"
712
self.assertEqual("No revisions to pull.\n", f.getvalue())
340
a = "%d revisions pulled" % r
341
self.assertEqual(a, "10 revisions pulled")