25
25
from StringIO import StringIO
28
from bzrlib.branch import (BzrBranch5,
30
import bzrlib.bzrdir as bzrdir
28
branch as _mod_branch,
35
from bzrlib.branch import (
39
BranchReferenceFormat,
31
45
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1,
32
46
BzrDir, BzrDirFormat)
33
47
from bzrlib.errors import (NotBranchError,
34
48
UnknownFormatError,
35
50
UnsupportedFormatError,
38
53
from bzrlib.tests import TestCase, TestCaseWithTransport
39
54
from bzrlib.transport import get_transport
41
57
class TestDefaultFormat(TestCase):
59
def test_default_format(self):
60
# update this if you change the default branch format
61
self.assertIsInstance(BranchFormat.get_default_format(),
64
def test_default_format_is_same_as_bzrdir_default(self):
65
# XXX: it might be nice if there was only one place the default was
66
# set, but at the moment that's not true -- mbp 20070814 --
67
# https://bugs.launchpad.net/bzr/+bug/132376
68
self.assertEqual(BranchFormat.get_default_format(),
69
BzrDirFormat.get_default_format().get_branch_format())
43
71
def test_get_set_default_format(self):
44
old_format = bzrlib.branch.BranchFormat.get_default_format()
46
self.assertTrue(isinstance(old_format, bzrlib.branch.BzrBranchFormat5))
47
bzrlib.branch.BranchFormat.set_default_format(SampleBranchFormat())
72
# set the format and then set it back again
73
old_format = BranchFormat.get_default_format()
74
BranchFormat.set_default_format(SampleBranchFormat())
49
76
# the default branch format is used by the meta dir format
50
77
# which is not the default bzrdir format at this point
80
class TestBranchEscaping(TestCaseWithTransport):
81
"""Test a branch can be correctly stored and used on a vfat-like transport
83
Makes sure we have proper escaping of invalid characters, etc.
85
It'd be better to test all operations on the FakeVFATTransportDecorator,
86
but working trees go straight to the os not through the Transport layer.
87
Therefore we build some history first in the regular way and then
88
check it's safe to access for vfat.
95
super(TestBranchEscaping, self).setUp()
96
from bzrlib.repository import RepositoryFormatKnit1
97
bzrdir = BzrDirMetaFormat1().initialize(self.get_url())
98
repo = RepositoryFormatKnit1().initialize(bzrdir)
99
branch = bzrdir.create_branch()
100
wt = bzrdir.create_workingtree()
101
self.build_tree_contents([("foo", "contents of foo")])
102
# add file with id containing wierd characters
103
wt.add(['foo'], [self.FOO_ID])
104
wt.commit('this is my new commit', rev_id=self.REV_ID)
106
def test_branch_on_vfat(self):
107
from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
108
# now access over vfat; should be safe
109
transport = FakeVFATTransportDecorator('vfat+' + self.get_url())
110
bzrdir, junk = BzrDir.open_containing_from_transport(transport)
111
branch = bzrdir.open_branch()
112
revtree = branch.repository.revision_tree(self.REV_ID)
113
contents = revtree.get_file_text(self.FOO_ID)
114
self.assertEqual(contents, 'contents of foo')
117
class SampleBranchFormat(bzrlib.branch.BranchFormat):
106
def test_set_push_location(self):
107
from bzrlib.config import (locations_config_filename,
108
ensure_config_dir_exists)
109
ensure_config_dir_exists()
110
fn = locations_config_filename()
111
# write correct newlines to locations.conf
112
# by default ConfigObj uses native line-endings for new files
113
# but uses already existing line-endings if file is not empty
116
f.write('# comment\n')
120
branch = self.make_branch('.', format='knit')
121
branch.set_push_location('foo')
122
local_path = urlutils.local_path_from_url(branch.base[:-1])
123
self.assertFileEqual("# comment\n"
125
"push_location = foo\n"
126
"push_location:policy = norecurse\n" % local_path,
129
# TODO RBC 20051029 test getting a push location from a branch in a
130
# recursive section - that is, it appends the branch name.
133
class SampleBranchFormat(BranchFormat):
118
134
"""A sample format
120
136
this format is initializable, unsupported to aid in testing the
175
191
format.initialize(dir)
176
192
# register a format for it.
177
bzrlib.branch.BranchFormat.register_format(format)
193
BranchFormat.register_format(format)
178
194
# which branch.Open will refuse (not supported)
179
self.assertRaises(UnsupportedFormatError, bzrlib.branch.Branch.open, self.get_url())
195
self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
196
self.make_branch_and_tree('foo')
180
197
# but open_downlevel will work
181
198
self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
182
199
# unregister the format
183
bzrlib.branch.BranchFormat.unregister_format(format)
200
BranchFormat.unregister_format(format)
201
self.make_branch_and_tree('bar')
204
class TestBranch67(object):
205
"""Common tests for both branch 6 and 7 which are mostly the same."""
207
def get_format_name(self):
208
raise NotImplementedError(self.get_format_name)
210
def get_format_name_subtree(self):
211
raise NotImplementedError(self.get_format_name)
214
raise NotImplementedError(self.get_class)
216
def test_creation(self):
217
format = BzrDirMetaFormat1()
218
format.set_branch_format(_mod_branch.BzrBranchFormat6())
219
branch = self.make_branch('a', format=format)
220
self.assertIsInstance(branch, self.get_class())
221
branch = self.make_branch('b', format=self.get_format_name())
222
self.assertIsInstance(branch, self.get_class())
223
branch = _mod_branch.Branch.open('a')
224
self.assertIsInstance(branch, self.get_class())
226
def test_layout(self):
227
branch = self.make_branch('a', format=self.get_format_name())
228
self.failUnlessExists('a/.bzr/branch/last-revision')
229
self.failIfExists('a/.bzr/branch/revision-history')
231
def test_config(self):
232
"""Ensure that all configuration data is stored in the branch"""
233
branch = self.make_branch('a', format=self.get_format_name())
234
branch.set_parent('http://bazaar-vcs.org')
235
self.failIfExists('a/.bzr/branch/parent')
236
self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
237
branch.set_push_location('sftp://bazaar-vcs.org')
238
config = branch.get_config()._get_branch_data_config()
239
self.assertEqual('sftp://bazaar-vcs.org',
240
config.get_user_option('push_location'))
241
branch.set_bound_location('ftp://bazaar-vcs.org')
242
self.failIfExists('a/.bzr/branch/bound')
243
self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
245
def test_set_revision_history(self):
246
builder = self.make_branch_builder('.', format=self.get_format_name())
247
builder.build_snapshot('foo', None,
248
[('add', ('', None, 'directory', None))],
250
builder.build_snapshot('bar', None, [], message='bar')
251
branch = builder.get_branch()
253
self.addCleanup(branch.unlock)
254
branch.set_revision_history(['foo', 'bar'])
255
branch.set_revision_history(['foo'])
256
self.assertRaises(errors.NotLefthandHistory,
257
branch.set_revision_history, ['bar'])
259
def do_checkout_test(self, lightweight=False):
260
tree = self.make_branch_and_tree('source',
261
format=self.get_format_name_subtree())
262
subtree = self.make_branch_and_tree('source/subtree',
263
format=self.get_format_name_subtree())
264
subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
265
format=self.get_format_name_subtree())
266
self.build_tree(['source/subtree/file',
267
'source/subtree/subsubtree/file'])
268
subsubtree.add('file')
270
subtree.add_reference(subsubtree)
271
tree.add_reference(subtree)
272
tree.commit('a revision')
273
subtree.commit('a subtree file')
274
subsubtree.commit('a subsubtree file')
275
tree.branch.create_checkout('target', lightweight=lightweight)
276
self.failUnlessExists('target')
277
self.failUnlessExists('target/subtree')
278
self.failUnlessExists('target/subtree/file')
279
self.failUnlessExists('target/subtree/subsubtree/file')
280
subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
282
self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
284
self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
286
def test_checkout_with_references(self):
287
self.do_checkout_test()
289
def test_light_checkout_with_references(self):
290
self.do_checkout_test(lightweight=True)
292
def test_set_push(self):
293
branch = self.make_branch('source', format=self.get_format_name())
294
branch.get_config().set_user_option('push_location', 'old',
295
store=config.STORE_LOCATION)
298
warnings.append(args[0] % args[1:])
299
_warning = trace.warning
300
trace.warning = warning
302
branch.set_push_location('new')
304
trace.warning = _warning
305
self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
309
class TestBranch6(TestBranch67, TestCaseWithTransport):
312
return _mod_branch.BzrBranch6
314
def get_format_name(self):
315
return "dirstate-tags"
317
def get_format_name_subtree(self):
318
return "dirstate-with-subtree"
320
def test_set_stacked_on_url_errors(self):
321
branch = self.make_branch('a', format=self.get_format_name())
322
self.assertRaises(errors.UnstackableBranchFormat,
323
branch.set_stacked_on_url, None)
325
def test_default_stacked_location(self):
326
branch = self.make_branch('a', format=self.get_format_name())
327
self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
330
class TestBranch7(TestBranch67, TestCaseWithTransport):
333
return _mod_branch.BzrBranch7
335
def get_format_name(self):
338
def get_format_name_subtree(self):
339
return "development-subtree"
341
def test_set_stacked_on_url_unstackable_repo(self):
342
repo = self.make_repository('a', format='dirstate-tags')
343
control = repo.bzrdir
344
branch = _mod_branch.BzrBranchFormat7().initialize(control)
345
target = self.make_branch('b')
346
self.assertRaises(errors.UnstackableRepositoryFormat,
347
branch.set_stacked_on_url, target.base)
349
def test_clone_stacked_on_unstackable_repo(self):
350
repo = self.make_repository('a', format='dirstate-tags')
351
control = repo.bzrdir
352
branch = _mod_branch.BzrBranchFormat7().initialize(control)
353
# Calling clone should not raise UnstackableRepositoryFormat.
354
cloned_bzrdir = control.clone('cloned')
356
def _test_default_stacked_location(self):
357
branch = self.make_branch('a', format=self.get_format_name())
358
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
360
def test_stack_and_unstack(self):
361
branch = self.make_branch('a', format=self.get_format_name())
362
target = self.make_branch_and_tree('b', format=self.get_format_name())
363
branch.set_stacked_on_url(target.branch.base)
364
self.assertEqual(target.branch.base, branch.get_stacked_on_url())
365
revid = target.commit('foo')
366
self.assertTrue(branch.repository.has_revision(revid))
367
branch.set_stacked_on_url(None)
368
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
369
self.assertFalse(branch.repository.has_revision(revid))
371
def test_open_opens_stacked_reference(self):
372
branch = self.make_branch('a', format=self.get_format_name())
373
target = self.make_branch_and_tree('b', format=self.get_format_name())
374
branch.set_stacked_on_url(target.branch.base)
375
branch = branch.bzrdir.open_branch()
376
revid = target.commit('foo')
377
self.assertTrue(branch.repository.has_revision(revid))
186
380
class TestBranchReference(TestCaseWithTransport):
195
389
target_branch = dir.create_branch()
196
390
t.mkdir('branch')
197
391
branch_dir = bzrdirformat.initialize(self.get_url('branch'))
198
made_branch = bzrlib.branch.BranchReferenceFormat().initialize(branch_dir, target_branch)
392
made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
199
393
self.assertEqual(made_branch.base, target_branch.base)
200
394
opened_branch = branch_dir.open_branch()
201
395
self.assertEqual(opened_branch.base, target_branch.base)
397
def test_get_reference(self):
398
"""For a BranchReference, get_reference should reutrn the location."""
399
branch = self.make_branch('target')
400
checkout = branch.create_checkout('checkout', lightweight=True)
401
reference_url = branch.bzrdir.root_transport.abspath('') + '/'
402
# if the api for create_checkout changes to return different checkout types
403
# then this file read will fail.
404
self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
405
self.assertEqual(reference_url,
406
_mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
409
class TestHooks(TestCase):
411
def test_constructor(self):
412
"""Check that creating a BranchHooks instance has the right defaults."""
413
hooks = BranchHooks()
414
self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
415
self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
416
self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
417
self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
418
self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
419
self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
420
self.assertTrue("post_change_branch_tip" in hooks,
421
"post_change_branch_tip not in %s" % hooks)
423
def test_installed_hooks_are_BranchHooks(self):
424
"""The installed hooks object should be a BranchHooks."""
425
# the installed hooks are saved in self._preserved_hooks.
426
self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch], BranchHooks)
429
class TestPullResult(TestCase):
431
def test_pull_result_to_int(self):
432
# to support old code, the pull result can be used as an int
436
# this usage of results is not recommended for new code (because it
437
# doesn't describe very well what happened), but for api stability
438
# it's still supported
439
a = "%d revisions pulled" % r
440
self.assertEqual(a, "10 revisions pulled")