809
810
present within a BzrDir.
813
def _get_branch_path(self, name):
814
"""Obtain the branch path to use.
816
This uses the API specified branch name first, and then falls back to
817
the branch name specified in the URL. If neither of those is specified,
818
it uses the default branch.
820
:param name: Optional branch name to use
821
:return: Relative path to branch
825
return urlutils.join('branches', name.encode("utf-8"))
827
def _read_branch_list(self):
828
"""Read the branch list.
830
:return: List of utf-8 encoded branch names.
833
f = self.control_transport.get('branch-list')
834
except errors.NoSuchFile:
840
ret.append(name.rstrip("\n"))
845
def _write_branch_list(self, branches):
846
"""Write out the branch list.
848
:param branches: List of utf-8 branch names to write
850
self.transport.put_bytes('branch-list',
851
"".join([name+"\n" for name in branches]))
812
853
def __init__(self, _transport, _format):
813
854
super(BzrDirMeta1, self).__init__(_transport, _format)
814
self.control_files = lockable_files.LockableFiles(self.control_transport,
815
self._format._lock_file_name, self._format._lock_class)
855
self.control_files = lockable_files.LockableFiles(
856
self.control_transport, self._format._lock_file_name,
857
self._format._lock_class)
817
859
def can_convert_format(self):
818
860
"""See BzrDir.can_convert_format()."""
831
873
"""See ControlDir.destroy_branch."""
833
875
name = self._get_selected_branch()
876
path = self._get_branch_path(name)
835
raise errors.NoColocatedBranchSupport(self)
878
self.control_files.lock_write()
880
branches = self._read_branch_list()
882
branches.remove(name.encode("utf-8"))
884
raise errors.NotBranchError(name)
885
self._write_branch_list(branches)
887
self.control_files.unlock()
837
self.transport.delete_tree('branch')
889
self.transport.delete_tree(path)
838
890
except errors.NoSuchFile:
839
891
raise errors.NotBranchError(path=urlutils.join(self.transport.base,
840
'branch'), bzrdir=self)
842
894
def create_repository(self, shared=False):
843
895
"""See BzrDir.create_repository."""
899
951
"""See BzrDir.get_branch_transport()."""
901
953
name = self._get_selected_branch()
903
raise errors.NoColocatedBranchSupport(self)
954
path = self._get_branch_path(name)
904
955
# XXX: this shouldn't implicitly create the directory if it's just
905
956
# promising to get a transport -- mbp 20090727
906
957
if branch_format is None:
907
return self.transport.clone('branch')
958
return self.transport.clone(path)
909
960
branch_format.get_format_string()
910
961
except NotImplementedError:
911
962
raise errors.IncompatibleFormat(branch_format, self._format)
964
branches = self._read_branch_list()
965
utf8_name = name.encode("utf-8")
966
if not utf8_name in branches:
967
self.control_files.lock_write()
969
branches = self._read_branch_list()
970
dirname = urlutils.dirname(utf8_name)
971
if dirname != "" and dirname in branches:
972
raise errors.ParentBranchExists(name)
974
b.startswith(utf8_name+"/") for b in branches]
975
if any(child_branches):
976
raise errors.AlreadyBranchError(name)
977
branches.append(utf8_name)
978
self._write_branch_list(branches)
980
self.control_files.unlock()
981
branch_transport = self.transport.clone(path)
982
mode = self._get_mkdir_mode()
983
branch_transport.create_prefix(mode=mode)
913
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
985
self.transport.mkdir(path, mode=mode)
914
986
except errors.FileExists:
916
return self.transport.clone('branch')
988
return self.transport.clone(path)
918
990
def get_repository_transport(self, repository_format):
919
991
"""See BzrDir.get_repository_transport()."""
1016
1101
return config.TransportConfig(self.transport, 'control.conf')
1019
class BzrDirMeta1Colo(BzrDirMeta1):
1020
"""BzrDirMeta1 with support for colocated branches.
1022
This format is experimental, and will eventually be merged back into
1026
def _get_branch_path(self, name):
1027
"""Obtain the branch path to use.
1029
This uses the API specified branch name first, and then falls back to
1030
the branch name specified in the URL. If neither of those is specified,
1031
it uses the default branch.
1033
:param name: Optional branch name to use
1034
:return: Relative path to branch
1038
return urlutils.join('branches', name.encode("utf-8"))
1040
def _read_branch_list(self):
1041
"""Read the branch list.
1043
:return: List of utf-8 encoded branch names.
1046
f = self.control_transport.get('branch-list')
1047
except errors.NoSuchFile:
1053
ret.append(name.rstrip("\n"))
1058
def _write_branch_list(self, branches):
1059
"""Write out the branch list.
1061
:param branches: List of utf-8 branch names to write
1063
self.transport.put_bytes('branch-list',
1064
"".join([name+"\n" for name in branches]))
1066
def destroy_branch(self, name=None):
1067
"""See BzrDir.create_branch."""
1069
name = self._get_selected_branch()
1070
path = self._get_branch_path(name)
1072
self.control_files.lock_write()
1074
branches = self._read_branch_list()
1076
branches.remove(name.encode("utf-8"))
1078
raise errors.NotBranchError(name)
1079
self._write_branch_list(branches)
1081
self.control_files.unlock()
1083
self.transport.delete_tree(path)
1084
except errors.NoSuchFile:
1085
raise errors.NotBranchError(path=path, bzrdir=self)
1087
def get_branches(self):
1088
"""See ControlDir.get_branches."""
1091
ret[""] = self.open_branch(name="")
1092
except (errors.NotBranchError, errors.NoRepositoryPresent):
1095
for name in self._read_branch_list():
1096
ret[name] = self.open_branch(name=name.decode('utf-8'))
1100
def get_branch_transport(self, branch_format, name=None):
1101
"""See BzrDir.get_branch_transport()."""
1103
name = self._get_selected_branch()
1104
path = self._get_branch_path(name)
1105
# XXX: this shouldn't implicitly create the directory if it's just
1106
# promising to get a transport -- mbp 20090727
1107
if branch_format is None:
1108
return self.transport.clone(path)
1110
branch_format.get_format_string()
1111
except NotImplementedError:
1112
raise errors.IncompatibleFormat(branch_format, self._format)
1115
self.transport.mkdir('branches', mode=self._get_mkdir_mode())
1116
except errors.FileExists:
1118
branches = self._read_branch_list()
1119
utf8_name = name.encode("utf-8")
1120
if not utf8_name in branches:
1121
self.control_files.lock_write()
1123
branches = self._read_branch_list()
1124
branches.append(utf8_name)
1125
self._write_branch_list(branches)
1127
self.control_files.unlock()
1129
self.transport.mkdir(path, mode=self._get_mkdir_mode())
1130
except errors.FileExists:
1132
return self.transport.clone(path)
1135
1104
class BzrFormat(object):
1136
1105
"""Base class for all formats of things living in metadirs.
1931
1900
def convert(self, to_convert, pb):
1932
1901
"""See Converter.convert()."""
1933
to_convert.control_files.lock_write()
1935
branches = to_convert.list_branches()
1936
if len(branches) > 1:
1937
raise errors.BzrError("remove all but a single "
1938
"colocated branch when downgrading")
1940
to_convert.control_files.unlock()
1941
1902
to_convert.transport.put_bytes('branch-format',
1942
1903
self.target_format.as_string())
1943
1904
return BzrDir.open_from_transport(to_convert.root_transport)