55
62
from bzrlib.tests.test_http import TestWithTransport_pycurl
56
63
from bzrlib.transport import (
61
67
from bzrlib.transport.http._urllib import HttpTransport_urllib
62
68
from bzrlib.transport.nosmart import NoSmartTransportDecorator
63
69
from bzrlib.transport.readonly import ReadonlyTransportDecorator
64
from bzrlib.repofmt import knitrepo, weaverepo, pack_repo
70
from bzrlib.repofmt import knitrepo, knitpack_repo
67
73
class TestDefaultFormat(TestCase):
69
75
def test_get_set_default_format(self):
70
76
old_format = bzrdir.BzrDirFormat.get_default_format()
71
# default is BzrDirFormat6
72
self.failUnless(isinstance(old_format, bzrdir.BzrDirMetaFormat1))
77
# default is BzrDirMetaFormat1
78
self.assertIsInstance(old_format, bzrdir.BzrDirMetaFormat1)
73
79
controldir.ControlDirFormat._set_default_format(SampleBzrDirFormat())
74
80
# creating a bzr dir should now create an instrumented dir.
76
82
result = bzrdir.BzrDir.create('memory:///')
77
self.failUnless(isinstance(result, SampleBzrDir))
83
self.assertIsInstance(result, SampleBzrDir)
79
85
controldir.ControlDirFormat._set_default_format(old_format)
80
86
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
89
class DeprecatedBzrDirFormat(bzrdir.BzrDirFormat):
90
"""A deprecated bzr dir format."""
83
93
class TestFormatRegistry(TestCase):
85
95
def make_format_registry(self):
86
96
my_format_registry = controldir.ControlDirFormatRegistry()
87
my_format_registry.register('weave', bzrdir.BzrDirFormat6,
88
'Pre-0.8 format. Slower and does not support checkouts or shared'
89
' repositories', deprecated=True)
90
my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
91
'BzrDirFormat6', 'Format registered lazily', deprecated=True)
97
my_format_registry.register('deprecated', DeprecatedBzrDirFormat,
98
'Some format. Slower and unawesome and deprecated.',
100
my_format_registry.register_lazy('lazy', 'bzrlib.tests.test_bzrdir',
101
'DeprecatedBzrDirFormat', 'Format registered lazily',
92
103
bzrdir.register_metadir(my_format_registry, 'knit',
93
104
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
94
105
'Format using knits',
105
116
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
106
117
'Experimental successor to knit. Use at your own risk.',
107
118
branch_format='bzrlib.branch.BzrBranchFormat6', hidden=True)
108
my_format_registry.register('hiddenweave', bzrdir.BzrDirFormat6,
109
'Pre-0.8 format. Slower and does not support checkouts or shared'
110
' repositories', hidden=True)
111
my_format_registry.register_lazy('hiddenlazy', 'bzrlib.bzrdir',
112
'BzrDirFormat6', 'Format registered lazily', deprecated=True,
119
my_format_registry.register('hiddendeprecated', DeprecatedBzrDirFormat,
120
'Old format. Slower and does not support things. ', hidden=True)
121
my_format_registry.register_lazy('hiddenlazy', 'bzrlib.tests.test_bzrdir',
122
'DeprecatedBzrDirFormat', 'Format registered lazily',
123
deprecated=True, hidden=True)
114
124
return my_format_registry
116
126
def test_format_registry(self):
117
127
my_format_registry = self.make_format_registry()
118
128
my_bzrdir = my_format_registry.make_bzrdir('lazy')
119
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
120
my_bzrdir = my_format_registry.make_bzrdir('weave')
121
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
129
self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
130
my_bzrdir = my_format_registry.make_bzrdir('deprecated')
131
self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
122
132
my_bzrdir = my_format_registry.make_bzrdir('default')
123
133
self.assertIsInstance(my_bzrdir.repository_format,
124
134
knitrepo.RepositoryFormatKnit1)
169
178
self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
170
179
bzrdir.format_registry.get('default'))
172
repository.RepositoryFormat.get_default_format().__class__,
181
repository.format_registry.get_default().__class__,
173
182
knitrepo.RepositoryFormatKnit3)
175
184
bzrdir.format_registry.set_default_repository(old_default)
177
186
def test_aliases(self):
178
187
a_registry = controldir.ControlDirFormatRegistry()
179
a_registry.register('weave', bzrdir.BzrDirFormat6,
180
'Pre-0.8 format. Slower and does not support checkouts or shared'
181
' repositories', deprecated=True)
182
a_registry.register('weavealias', bzrdir.BzrDirFormat6,
183
'Pre-0.8 format. Slower and does not support checkouts or shared'
184
' repositories', deprecated=True, alias=True)
185
self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
188
a_registry.register('deprecated', DeprecatedBzrDirFormat,
189
'Old format. Slower and does not support stuff',
191
a_registry.register('deprecatedalias', DeprecatedBzrDirFormat,
192
'Old format. Slower and does not support stuff',
193
deprecated=True, alias=True)
194
self.assertEqual(frozenset(['deprecatedalias']), a_registry.aliases())
188
197
class SampleBranch(bzrlib.branch.Branch):
245
254
return "opened branch."
257
class BzrDirFormatTest1(bzrdir.BzrDirMetaFormat1):
260
def get_format_string():
261
return "Test format 1"
264
class BzrDirFormatTest2(bzrdir.BzrDirMetaFormat1):
267
def get_format_string():
268
return "Test format 2"
248
271
class TestBzrDirFormat(TestCaseWithTransport):
249
272
"""Tests for the BzrDirFormat facility."""
251
274
def test_find_format(self):
252
275
# is the right format object found for a branch?
253
276
# create a branch with a few known format objects.
254
# this is not quite the same as
255
t = get_transport(self.get_url())
277
bzrdir.BzrProber.formats.register(BzrDirFormatTest1.get_format_string(),
279
self.addCleanup(bzrdir.BzrProber.formats.remove,
280
BzrDirFormatTest1.get_format_string())
281
bzrdir.BzrProber.formats.register(BzrDirFormatTest2.get_format_string(),
283
self.addCleanup(bzrdir.BzrProber.formats.remove,
284
BzrDirFormatTest2.get_format_string())
285
t = self.get_transport()
256
286
self.build_tree(["foo/", "bar/"], transport=t)
257
287
def check_format(format, url):
258
288
format.initialize(url)
259
t = get_transport(url)
289
t = _mod_transport.get_transport_from_path(url)
260
290
found_format = bzrdir.BzrDirFormat.find_format(t)
261
self.failUnless(isinstance(found_format, format.__class__))
262
check_format(bzrdir.BzrDirFormat5(), "foo")
263
check_format(bzrdir.BzrDirFormat6(), "bar")
291
self.assertIsInstance(found_format, format.__class__)
292
check_format(BzrDirFormatTest1(), "foo")
293
check_format(BzrDirFormatTest2(), "bar")
265
295
def test_find_format_nothing_there(self):
266
296
self.assertRaises(NotBranchError,
267
297
bzrdir.BzrDirFormat.find_format,
298
_mod_transport.get_transport_from_path('.'))
270
300
def test_find_format_unknown_format(self):
271
t = get_transport(self.get_url())
301
t = self.get_transport()
273
303
t.put_bytes('.bzr/branch-format', '')
274
304
self.assertRaises(UnknownFormatError,
275
305
bzrdir.BzrDirFormat.find_format,
306
_mod_transport.get_transport_from_path('.'))
278
308
def test_register_unregister_format(self):
279
309
format = SampleBzrDirFormat()
282
312
format.initialize(url)
283
313
# register a format for it.
284
bzrdir.BzrDirFormat.register_format(format)
314
bzrdir.BzrProber.formats.register(format.get_format_string(), format)
285
315
# which bzrdir.Open will refuse (not supported)
286
316
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
287
317
# which bzrdir.open_containing will refuse (not supported)
288
318
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
289
319
# but open_downlevel will work
290
t = get_transport(url)
320
t = _mod_transport.get_transport_from_url(url)
291
321
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
292
322
# unregister the format
293
bzrdir.BzrDirFormat.unregister_format(format)
323
bzrdir.BzrProber.formats.remove(format.get_format_string())
294
324
# now open_downlevel should fail too.
295
325
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
679
709
self.assertEqual(relpath, 'baz')
681
711
def test_open_containing_from_transport(self):
682
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
683
get_transport(self.get_readonly_url('')))
684
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
685
get_transport(self.get_readonly_url('g/p/q')))
712
self.assertRaises(NotBranchError,
713
bzrdir.BzrDir.open_containing_from_transport,
714
_mod_transport.get_transport_from_url(self.get_readonly_url('')))
715
self.assertRaises(NotBranchError,
716
bzrdir.BzrDir.open_containing_from_transport,
717
_mod_transport.get_transport_from_url(
718
self.get_readonly_url('g/p/q')))
686
719
control = bzrdir.BzrDir.create(self.get_url())
687
720
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
688
get_transport(self.get_readonly_url('')))
721
_mod_transport.get_transport_from_url(
722
self.get_readonly_url('')))
689
723
self.assertEqual('', relpath)
690
724
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
691
get_transport(self.get_readonly_url('g/p/q')))
725
_mod_transport.get_transport_from_url(
726
self.get_readonly_url('g/p/q')))
692
727
self.assertEqual('g/p/q', relpath)
694
729
def test_open_containing_tree_or_branch(self):
738
773
# transport pointing at bzrdir should give a bzrdir with root transport
739
774
# set to the given transport
740
775
control = bzrdir.BzrDir.create(self.get_url())
741
transport = get_transport(self.get_url())
742
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
743
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
776
t = self.get_transport()
777
opened_bzrdir = bzrdir.BzrDir.open_from_transport(t)
778
self.assertEqual(t.base, opened_bzrdir.root_transport.base)
744
779
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
746
781
def test_open_from_transport_no_bzrdir(self):
747
transport = get_transport(self.get_url())
748
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
782
t = self.get_transport()
783
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
751
785
def test_open_from_transport_bzrdir_in_parent(self):
752
786
control = bzrdir.BzrDir.create(self.get_url())
753
transport = get_transport(self.get_url())
754
transport.mkdir('subdir')
755
transport = transport.clone('subdir')
756
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
787
t = self.get_transport()
789
t = t.clone('subdir')
790
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
759
792
def test_sprout_recursive(self):
760
793
tree = self.make_branch_and_tree('tree1',
790
823
self.build_tree(['tree1/subtree/file'])
791
824
sub_tree.add('file')
792
825
tree.commit('Initial commit')
826
# The following line force the orhaning to reveal bug #634470
827
tree.branch.get_config().set_user_option(
828
'bzr.transform.orphan_policy', 'move')
793
829
tree.bzrdir.destroy_workingtree()
830
# FIXME: subtree/.bzr is left here which allows the test to pass (or
831
# fail :-( ) -- vila 20100909
794
832
repo = self.make_repository('repo', shared=True,
795
833
format='dirstate-with-subtree')
796
834
repo.set_make_working_trees(False)
797
tree.bzrdir.sprout('repo/tree2')
798
self.failUnlessExists('repo/tree2/subtree')
799
self.failIfExists('repo/tree2/subtree/file')
835
# FIXME: we just deleted the workingtree and now we want to use it ????
836
# At a minimum, we should use tree.branch below (but this fails too
837
# currently) or stop calling this test 'treeless'. Specifically, I've
838
# turn the line below into an assertRaises when 'subtree/.bzr' is
839
# orphaned and sprout tries to access the branch there (which is left
840
# by bzrdir.BzrDirMeta1.destroy_workingtree when it ignores the
841
# [DeletingParent('Not deleting', u'subtree', None)] conflict). See bug
842
# #634470. -- vila 20100909
843
self.assertRaises(errors.NotBranchError,
844
tree.bzrdir.sprout, 'repo/tree2')
845
# self.assertPathExists('repo/tree2/subtree')
846
# self.assertPathDoesNotExist('repo/tree2/subtree/file')
801
848
def make_foo_bar_baz(self):
802
849
foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
847
893
return [s for s in transport.list_dir('') if s != 'baz']
849
895
foo, bar, baz = self.make_foo_bar_baz()
850
transport = get_transport(self.get_url())
851
self.assertEqualBzrdirs([foo, bar],
852
bzrdir.BzrDir.find_bzrdirs(transport,
853
list_current=list_current))
896
t = self.get_transport()
897
self.assertEqualBzrdirs(
899
bzrdir.BzrDir.find_bzrdirs(t, list_current=list_current))
855
901
def test_find_bzrdirs_evaluate(self):
856
902
def evaluate(bzrdir):
858
904
repo = bzrdir.open_repository()
859
except NoRepositoryPresent:
905
except errors.NoRepositoryPresent:
860
906
return True, bzrdir.root_transport.base
862
908
return False, bzrdir.root_transport.base
864
910
foo, bar, baz = self.make_foo_bar_baz()
865
transport = get_transport(self.get_url())
911
t = self.get_transport()
866
912
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
867
list(bzrdir.BzrDir.find_bzrdirs(transport,
913
list(bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate)))
870
915
def assertEqualBzrdirs(self, first, second):
871
916
first = list(first)
878
923
root = self.make_repository('', shared=True)
879
924
foo, bar, baz = self.make_foo_bar_baz()
880
925
qux = self.make_bzrdir('foo/qux')
881
transport = get_transport(self.get_url())
882
branches = bzrdir.BzrDir.find_branches(transport)
926
t = self.get_transport()
927
branches = bzrdir.BzrDir.find_branches(t)
883
928
self.assertEqual(baz.root_transport.base, branches[0].base)
884
929
self.assertEqual(foo.root_transport.base, branches[1].base)
885
930
self.assertEqual(bar.root_transport.base, branches[2].base)
887
932
# ensure this works without a top-level repo
888
branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
933
branches = bzrdir.BzrDir.find_branches(t.clone('foo'))
889
934
self.assertEqual(foo.root_transport.base, branches[0].base)
890
935
self.assertEqual(bar.root_transport.base, branches[1].base)
917
962
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
918
963
repository_base = t.clone('repository').base
919
964
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
965
repository_format = repository.format_registry.get_default()
920
966
self.assertEqual(repository_base,
921
dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
967
dir.get_repository_transport(repository_format).base)
922
968
checkout_base = t.clone('checkout').base
923
969
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
924
970
self.assertEqual(checkout_base,
925
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
971
dir.get_workingtree_transport(workingtree_3.WorkingTreeFormat3()).base)
927
973
def test_meta1dir_uses_lockdir(self):
928
974
"""Meta1 format uses a LockDir to guard the whole directory, not a file."""
970
1016
self.assertEqual(2, rpc_count)
973
class TestFormat5(TestCaseWithTransport):
974
"""Tests specific to the version 5 bzrdir format."""
976
def test_same_lockfiles_between_tree_repo_branch(self):
977
# this checks that only a single lockfiles instance is created
978
# for format 5 objects
979
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
980
def check_dir_components_use_same_lock(dir):
981
ctrl_1 = dir.open_repository().control_files
982
ctrl_2 = dir.open_branch().control_files
983
ctrl_3 = dir.open_workingtree()._control_files
984
self.assertTrue(ctrl_1 is ctrl_2)
985
self.assertTrue(ctrl_2 is ctrl_3)
986
check_dir_components_use_same_lock(dir)
987
# and if we open it normally.
988
dir = bzrdir.BzrDir.open(self.get_url())
989
check_dir_components_use_same_lock(dir)
991
def test_can_convert(self):
992
# format 5 dirs are convertable
993
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
994
self.assertTrue(dir.can_convert_format())
996
def test_needs_conversion(self):
997
# format 5 dirs need a conversion if they are not the default,
999
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
1000
# don't need to convert it to itself
1001
self.assertFalse(dir.needs_format_conversion(bzrdir.BzrDirFormat5()))
1002
# do need to convert it to the current default
1003
self.assertTrue(dir.needs_format_conversion(
1004
bzrdir.BzrDirFormat.get_default_format()))
1007
class TestFormat6(TestCaseWithTransport):
1008
"""Tests specific to the version 6 bzrdir format."""
1010
def test_same_lockfiles_between_tree_repo_branch(self):
1011
# this checks that only a single lockfiles instance is created
1012
# for format 6 objects
1013
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
1014
def check_dir_components_use_same_lock(dir):
1015
ctrl_1 = dir.open_repository().control_files
1016
ctrl_2 = dir.open_branch().control_files
1017
ctrl_3 = dir.open_workingtree()._control_files
1018
self.assertTrue(ctrl_1 is ctrl_2)
1019
self.assertTrue(ctrl_2 is ctrl_3)
1020
check_dir_components_use_same_lock(dir)
1021
# and if we open it normally.
1022
dir = bzrdir.BzrDir.open(self.get_url())
1023
check_dir_components_use_same_lock(dir)
1025
def test_can_convert(self):
1026
# format 6 dirs are convertable
1027
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
1028
self.assertTrue(dir.can_convert_format())
1030
def test_needs_conversion(self):
1031
# format 6 dirs need an conversion if they are not the default.
1032
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
1033
self.assertTrue(dir.needs_format_conversion(
1034
bzrdir.BzrDirFormat.get_default_format()))
1037
class NotBzrDir(bzrlib.bzrdir.BzrDir):
1038
"""A non .bzr based control directory."""
1040
def __init__(self, transport, format):
1041
self._format = format
1042
self.root_transport = transport
1043
self.transport = transport.clone('.not')
1046
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
1047
"""A test class representing any non-.bzr based disk format."""
1049
def initialize_on_transport(self, transport):
1050
"""Initialize a new .not dir in the base directory of a Transport."""
1051
transport.mkdir('.not')
1052
return self.open(transport)
1054
def open(self, transport):
1055
"""Open this directory."""
1056
return NotBzrDir(transport, self)
1059
def _known_formats(self):
1060
return set([NotBzrDirFormat()])
1063
class NotBzrDirProber(controldir.Prober):
1065
def probe_transport(self, transport):
1066
"""Our format is present if the transport ends in '.not/'."""
1067
if transport.has('.not'):
1068
return NotBzrDirFormat()
1071
class TestNotBzrDir(TestCaseWithTransport):
1072
"""Tests for using the bzrdir api with a non .bzr based disk format.
1074
If/when one of these is in the core, we can let the implementation tests
1078
def test_create_and_find_format(self):
1079
# create a .notbzr dir
1080
format = NotBzrDirFormat()
1081
dir = format.initialize(self.get_url())
1082
self.assertIsInstance(dir, NotBzrDir)
1084
controldir.ControlDirFormat.register_prober(NotBzrDirProber)
1086
found = bzrlib.bzrdir.BzrDirFormat.find_format(
1087
get_transport(self.get_url()))
1088
self.assertIsInstance(found, NotBzrDirFormat)
1090
controldir.ControlDirFormat.unregister_prober(NotBzrDirProber)
1092
def test_included_in_known_formats(self):
1093
not_format = NotBzrDirFormat()
1094
bzrlib.controldir.ControlDirFormat.register_format(not_format)
1096
formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
1097
for format in formats:
1098
if isinstance(format, NotBzrDirFormat):
1100
self.fail("No NotBzrDirFormat in %s" % formats)
1102
bzrlib.controldir.ControlDirFormat.unregister_format(not_format)
1105
1019
class NonLocalTests(TestCaseWithTransport):
1106
1020
"""Tests for bzrdir static behaviour on non local paths."""
1315
1229
class _TestBranch(bzrlib.branch.Branch):
1316
1230
"""Test Branch implementation for TestBzrDirSprout."""
1318
def __init__(self, *args, **kwargs):
1232
def __init__(self, transport, *args, **kwargs):
1319
1233
self._format = _TestBranchFormat()
1234
self._transport = transport
1235
self.base = transport.base
1320
1236
super(_TestBranch, self).__init__(*args, **kwargs)
1321
1237
self.calls = []
1322
1238
self._parent = None
1324
1240
def sprout(self, *args, **kwargs):
1325
1241
self.calls.append('sprout')
1326
return _TestBranch()
1242
return _TestBranch(self._transport)
1328
1244
def copy_content_into(self, destination, revision_id=None):
1329
1245
self.calls.append('copy_content_into')
1247
def last_revision(self):
1248
return _mod_revision.NULL_REVISION
1331
1250
def get_parent(self):
1332
1251
return self._parent
1253
def _get_config(self):
1254
return config.TransportConfig(self._transport, 'branch.conf')
1334
1256
def set_parent(self, parent):
1335
1257
self._parent = parent
1259
def lock_read(self):
1260
return lock.LogicalLockResult(self.unlock)
1338
1266
class TestBzrDirSprout(TestCaseWithMemoryTransport):
1419
1347
class TestGenerateBackupName(TestCaseWithMemoryTransport):
1348
# FIXME: This may need to be unified with test_osutils.TestBackupNames or
1349
# moved to per_bzrdir or per_transport for better coverage ?
1421
1352
def setUp(self):
1422
1353
super(TestGenerateBackupName, self).setUp()
1423
self._transport = get_transport(self.get_url())
1354
self._transport = self.get_transport()
1424
1355
bzrdir.BzrDir.create(self.get_url(),
1425
1356
possible_transports=[self._transport])
1426
1357
self._bzrdir = bzrdir.BzrDir.open_from_transport(self._transport)
1359
def test_deprecated_generate_backup_name(self):
1360
res = self.applyDeprecated(
1361
symbol_versioning.deprecated_in((2, 3, 0)),
1362
self._bzrdir.generate_backup_name, 'whatever')
1428
1364
def test_new(self):
1429
self.assertEqual("a.~1~", self._bzrdir.generate_backup_name("a"))
1365
self.assertEqual("a.~1~", self._bzrdir._available_backup_name("a"))
1431
1367
def test_exiting(self):
1432
1368
self._transport.put_bytes("a.~1~", "some content")
1433
self.assertEqual("a.~2~", self._bzrdir.generate_backup_name("a"))
1369
self.assertEqual("a.~2~", self._bzrdir._available_backup_name("a"))