634
633
old_path = self.root_transport.abspath('.bzr')
635
634
backup_dir = self._available_backup_name('backup.bzr')
636
635
new_path = self.root_transport.abspath(backup_dir)
637
ui.ui_factory.note('making backup of %s\n to %s'
638
% (old_path, new_path,))
636
ui.ui_factory.note(gettext('making backup of {0}\n to {1}').format(
637
urlutils.unescape_for_display(old_path, 'utf-8'),
638
urlutils.unescape_for_display(new_path, 'utf-8')))
639
639
self.root_transport.copy_tree('.bzr', backup_dir)
640
640
return (old_path, new_path)
1146
1146
"""See BzrDir.can_convert_format()."""
1149
def create_branch(self, name=None, repository=None):
1149
def create_branch(self, name=None, repository=None,
1150
append_revisions_only=None):
1150
1151
"""See BzrDir.create_branch."""
1151
1152
return self._format.get_branch_format().initialize(self, name=name,
1152
repository=repository)
1153
repository=repository,
1154
append_revisions_only=append_revisions_only)
1154
1156
def destroy_branch(self, name=None):
1155
1157
"""See BzrDir.create_branch."""
1321
1323
return config.TransportConfig(self.transport, 'control.conf')
1326
class BzrDirMeta1Colo(BzrDirMeta1):
1327
"""BzrDirMeta1 with support for colocated branches.
1329
This format is experimental, and will eventually be merged back into
1333
def __init__(self, _transport, _format):
1334
super(BzrDirMeta1Colo, self).__init__(_transport, _format)
1335
self.control_files = lockable_files.LockableFiles(_transport,
1336
self._format._lock_file_name, self._format._lock_class)
1338
def _get_branch_path(self, name):
1339
"""Obtain the branch path to use.
1341
This uses the API specified branch name first, and then falls back to
1342
the branch name specified in the URL. If neither of those is specified,
1343
it uses the default branch.
1345
:param name: Optional branch name to use
1346
:return: Relative path to branch, branch name
1349
name = self._get_selected_branch()
1351
return 'branch', None
1352
return urlutils.join('branches', name), name
1354
def _read_branch_list(self):
1355
"""Read the branch list.
1357
:return: List of utf-8 encoded branch names.
1360
f = self.control_transport.get('branch-list')
1361
except errors.NoSuchFile:
1367
ret.append(name.rstrip("\n"))
1372
def _write_branch_list(self, branches):
1373
"""Write out the branch list.
1375
:param branches: List of utf-8 branch names to write
1377
self.transport.put_bytes('branch-list',
1378
"".join([name+"\n" for name in branches]))
1380
def destroy_branch(self, name=None):
1381
"""See BzrDir.create_branch."""
1382
path, name = self._get_branch_path(name)
1383
if name is not None:
1384
self.control_files.lock_write()
1386
branches = self._read_branch_list()
1388
branches.remove(name)
1390
raise errors.NotBranchError(name)
1391
self._write_branch_list(name)
1393
self.control_files.unlock()
1394
self.transport.delete_tree(path)
1396
def list_branches(self):
1397
"""See ControlDir.list_branches."""
1401
ret.append(self.open_branch())
1402
except (errors.NotBranchError, errors.NoRepositoryPresent):
1405
# colocated branches
1406
ret.extend([self.open_branch(name) for name in
1407
self._read_branch_list()])
1411
def get_branch_transport(self, branch_format, name=None):
1412
"""See BzrDir.get_branch_transport()."""
1413
path, name = self._get_branch_path(name)
1414
# XXX: this shouldn't implicitly create the directory if it's just
1415
# promising to get a transport -- mbp 20090727
1416
if branch_format is None:
1417
return self.transport.clone(path)
1419
branch_format.get_format_string()
1420
except NotImplementedError:
1421
raise errors.IncompatibleFormat(branch_format, self._format)
1422
if name is not None:
1424
self.transport.mkdir('branches', mode=self._get_mkdir_mode())
1425
except errors.FileExists:
1427
branches = self._read_branch_list()
1428
if not name in branches:
1429
self.control_files.lock_write()
1431
branches = self._read_branch_list()
1432
branches.append(name)
1433
self._write_branch_list(branches)
1435
self.control_files.unlock()
1437
self.transport.mkdir(path, mode=self._get_mkdir_mode())
1438
except errors.FileExists:
1440
return self.transport.clone(path)
1324
1443
class BzrProber(controldir.Prober):
1325
1444
"""Prober for formats that use a .bzr/ control directory."""
1829
1950
controldir.ControlDirFormat._default_format = BzrDirMetaFormat1()
1953
class BzrDirMetaFormat1Colo(BzrDirMetaFormat1):
1954
"""BzrDirMeta1 format with support for colocated branches."""
1956
colocated_branches = True
1959
def get_format_string(cls):
1960
"""See BzrDirFormat.get_format_string()."""
1961
return "Bazaar meta directory, format 1 (with colocated branches)\n"
1963
def get_format_description(self):
1964
"""See BzrDirFormat.get_format_description()."""
1965
return "Meta directory format 1 with support for colocated branches"
1967
def _open(self, transport):
1968
"""See BzrDirFormat._open."""
1969
# Create a new format instance because otherwise initialisation of new
1970
# metadirs share the global default format object leading to alias
1972
format = BzrDirMetaFormat1Colo()
1973
self._supply_sub_formats_to(format)
1974
return BzrDirMeta1Colo(transport, format)
1977
BzrProber.formats.register(BzrDirMetaFormat1Colo.get_format_string(),
1978
BzrDirMetaFormat1Colo)
1832
1981
class ConvertMetaToMeta(controldir.Converter):
1833
1982
"""Converts the components of metadirs."""
2415
register_metadir(controldir.format_registry, 'development-colo',
2416
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
2417
help='The 2a format with experimental support for colocated branches.\n',
2418
branch_format='bzrlib.branch.BzrBranchFormat7',
2419
tree_format='bzrlib.workingtree_4.WorkingTreeFormat6',
2421
bzrdir_format=BzrDirMetaFormat1Colo,
2264
2425
# And the development formats above will have aliased one of the following:
2266
2427
# Finally, the current format.