/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

(jelmer) Merge colocated branch support back into the 2a format. (Jelmer
 Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
810
810
    present within a BzrDir.
811
811
    """
812
812
 
 
813
    def _get_branch_path(self, name):
 
814
        """Obtain the branch path to use.
 
815
 
 
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.
 
819
 
 
820
        :param name: Optional branch name to use
 
821
        :return: Relative path to branch
 
822
        """
 
823
        if name == "":
 
824
            return 'branch'
 
825
        return urlutils.join('branches', name.encode("utf-8"))
 
826
 
 
827
    def _read_branch_list(self):
 
828
        """Read the branch list.
 
829
 
 
830
        :return: List of utf-8 encoded branch names.
 
831
        """
 
832
        try:
 
833
            f = self.control_transport.get('branch-list')
 
834
        except errors.NoSuchFile:
 
835
            return []
 
836
 
 
837
        ret = []
 
838
        try:
 
839
            for name in f:
 
840
                ret.append(name.rstrip("\n"))
 
841
        finally:
 
842
            f.close()
 
843
        return ret
 
844
 
 
845
    def _write_branch_list(self, branches):
 
846
        """Write out the branch list.
 
847
 
 
848
        :param branches: List of utf-8 branch names to write
 
849
        """
 
850
        self.transport.put_bytes('branch-list',
 
851
            "".join([name+"\n" for name in branches]))
 
852
 
813
853
    def __init__(self, _transport, _format):
814
854
        super(BzrDirMeta1, self).__init__(_transport, _format)
815
 
        self.control_files = lockable_files.LockableFiles(self.control_transport,
816
 
            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
858
 
818
859
    def can_convert_format(self):
819
860
        """See BzrDir.can_convert_format()."""
832
873
        """See BzrDir.create_branch."""
833
874
        if name is None:
834
875
            name = self._get_selected_branch()
 
876
        path = self._get_branch_path(name)
835
877
        if name != "":
836
 
            raise errors.NoColocatedBranchSupport(self)
837
 
        self.transport.delete_tree('branch')
 
878
            self.control_files.lock_write()
 
879
            try:
 
880
                branches = self._read_branch_list()
 
881
                try:
 
882
                    branches.remove(name.encode("utf-8"))
 
883
                except ValueError:
 
884
                    raise errors.NotBranchError(name)
 
885
                self._write_branch_list(branches)
 
886
            finally:
 
887
                self.control_files.unlock()
 
888
        self.transport.delete_tree(path)
838
889
 
839
890
    def create_repository(self, shared=False):
840
891
        """See BzrDir.create_repository."""
896
947
        """See BzrDir.get_branch_transport()."""
897
948
        if name is None:
898
949
            name = self._get_selected_branch()
899
 
        if name != "":
900
 
            raise errors.NoColocatedBranchSupport(self)
 
950
        path = self._get_branch_path(name)
901
951
        # XXX: this shouldn't implicitly create the directory if it's just
902
952
        # promising to get a transport -- mbp 20090727
903
953
        if branch_format is None:
904
 
            return self.transport.clone('branch')
 
954
            return self.transport.clone(path)
905
955
        try:
906
956
            branch_format.get_format_string()
907
957
        except NotImplementedError:
908
958
            raise errors.IncompatibleFormat(branch_format, self._format)
 
959
        if name != "":
 
960
            branches = self._read_branch_list()
 
961
            utf8_name = name.encode("utf-8")
 
962
            if not utf8_name in branches:
 
963
                self.control_files.lock_write()
 
964
                try:
 
965
                    branches = self._read_branch_list()
 
966
                    dirname = urlutils.dirname(utf8_name)
 
967
                    if dirname != "" and dirname in branches:
 
968
                        raise errors.ParentBranchExists(name)
 
969
                    child_branches = [
 
970
                        b.startswith(utf8_name+"/") for b in branches]
 
971
                    if any(child_branches):
 
972
                        raise errors.AlreadyBranchError(name)
 
973
                    branches.append(utf8_name)
 
974
                    self._write_branch_list(branches)
 
975
                finally:
 
976
                    self.control_files.unlock()
 
977
        branch_transport = self.transport.clone(path)
 
978
        mode = self._get_mkdir_mode()
 
979
        branch_transport.create_prefix(mode=mode)
909
980
        try:
910
 
            self.transport.mkdir('branch', mode=self._get_mkdir_mode())
 
981
            self.transport.mkdir(path, mode=mode)
911
982
        except errors.FileExists:
912
983
            pass
913
 
        return self.transport.clone('branch')
 
984
        return self.transport.clone(path)
914
985
 
915
986
    def get_repository_transport(self, repository_format):
916
987
        """See BzrDir.get_repository_transport()."""
940
1011
            pass
941
1012
        return self.transport.clone('checkout')
942
1013
 
 
1014
    def get_branches(self):
 
1015
        """See ControlDir.get_branches."""
 
1016
        ret = {}
 
1017
        try:
 
1018
            ret[""] = self.open_branch(name="")
 
1019
        except (errors.NotBranchError, errors.NoRepositoryPresent):
 
1020
            pass
 
1021
 
 
1022
        for name in self._read_branch_list():
 
1023
            ret[name] = self.open_branch(name=name.decode('utf-8'))
 
1024
 
 
1025
        return ret
 
1026
 
943
1027
    def has_workingtree(self):
944
1028
        """Tell if this bzrdir contains a working tree.
945
1029
 
1013
1097
        return config.TransportConfig(self.transport, 'control.conf')
1014
1098
 
1015
1099
 
1016
 
class BzrDirMeta1Colo(BzrDirMeta1):
1017
 
    """BzrDirMeta1 with support for colocated branches.
1018
 
 
1019
 
    This format is experimental, and will eventually be merged back into
1020
 
    BzrDirMeta1.
1021
 
    """
1022
 
 
1023
 
    def _get_branch_path(self, name):
1024
 
        """Obtain the branch path to use.
1025
 
 
1026
 
        This uses the API specified branch name first, and then falls back to
1027
 
        the branch name specified in the URL. If neither of those is specified,
1028
 
        it uses the default branch.
1029
 
 
1030
 
        :param name: Optional branch name to use
1031
 
        :return: Relative path to branch
1032
 
        """
1033
 
        if name == "":
1034
 
            return 'branch'
1035
 
        return urlutils.join('branches', name.encode("utf-8"))
1036
 
 
1037
 
    def _read_branch_list(self):
1038
 
        """Read the branch list.
1039
 
 
1040
 
        :return: List of utf-8 encoded branch names.
1041
 
        """
1042
 
        try:
1043
 
            f = self.control_transport.get('branch-list')
1044
 
        except errors.NoSuchFile:
1045
 
            return []
1046
 
 
1047
 
        ret = []
1048
 
        try:
1049
 
            for name in f:
1050
 
                ret.append(name.rstrip("\n"))
1051
 
        finally:
1052
 
            f.close()
1053
 
        return ret
1054
 
 
1055
 
    def _write_branch_list(self, branches):
1056
 
        """Write out the branch list.
1057
 
 
1058
 
        :param branches: List of utf-8 branch names to write
1059
 
        """
1060
 
        self.transport.put_bytes('branch-list',
1061
 
            "".join([name+"\n" for name in branches]))
1062
 
 
1063
 
    def destroy_branch(self, name=None):
1064
 
        """See BzrDir.create_branch."""
1065
 
        if name is None:
1066
 
            name = self._get_selected_branch()
1067
 
        path = self._get_branch_path(name)
1068
 
        if name != "":
1069
 
            self.control_files.lock_write()
1070
 
            try:
1071
 
                branches = self._read_branch_list()
1072
 
                try:
1073
 
                    branches.remove(name.encode("utf-8"))
1074
 
                except ValueError:
1075
 
                    raise errors.NotBranchError(name)
1076
 
                self._write_branch_list(branches)
1077
 
            finally:
1078
 
                self.control_files.unlock()
1079
 
        self.transport.delete_tree(path)
1080
 
 
1081
 
    def get_branches(self):
1082
 
        """See ControlDir.get_branches."""
1083
 
        ret = {}
1084
 
        try:
1085
 
            ret[""] = self.open_branch(name="")
1086
 
        except (errors.NotBranchError, errors.NoRepositoryPresent):
1087
 
            pass
1088
 
 
1089
 
        for name in self._read_branch_list():
1090
 
            ret[name] = self.open_branch(name=name.decode('utf-8'))
1091
 
 
1092
 
        return ret
1093
 
 
1094
 
    def get_branch_transport(self, branch_format, name=None):
1095
 
        """See BzrDir.get_branch_transport()."""
1096
 
        if name is None:
1097
 
            name = self._get_selected_branch()
1098
 
        path = self._get_branch_path(name)
1099
 
        # XXX: this shouldn't implicitly create the directory if it's just
1100
 
        # promising to get a transport -- mbp 20090727
1101
 
        if branch_format is None:
1102
 
            return self.transport.clone(path)
1103
 
        try:
1104
 
            branch_format.get_format_string()
1105
 
        except NotImplementedError:
1106
 
            raise errors.IncompatibleFormat(branch_format, self._format)
1107
 
        if name != "":
1108
 
            branches = self._read_branch_list()
1109
 
            utf8_name = name.encode("utf-8")
1110
 
            if not utf8_name in branches:
1111
 
                self.control_files.lock_write()
1112
 
                try:
1113
 
                    branches = self._read_branch_list()
1114
 
                    dirname = urlutils.dirname(utf8_name)
1115
 
                    if dirname != "" and dirname in branches:
1116
 
                        raise errors.ParentBranchExists(name)
1117
 
                    child_branches = [
1118
 
                        b.startswith(utf8_name+"/") for b in branches]
1119
 
                    if any(child_branches):
1120
 
                        raise errors.AlreadyBranchError(name)
1121
 
                    branches.append(utf8_name)
1122
 
                    self._write_branch_list(branches)
1123
 
                finally:
1124
 
                    self.control_files.unlock()
1125
 
        branch_transport = self.transport.clone(path)
1126
 
        branch_transport.create_prefix()
1127
 
        try:
1128
 
            self.transport.mkdir('.', mode=self._get_mkdir_mode())
1129
 
        except errors.FileExists:
1130
 
            pass
1131
 
        return branch_transport
1132
 
 
1133
 
 
1134
1100
class BzrFormat(object):
1135
1101
    """Base class for all formats of things living in metadirs.
1136
1102
 
1579
1545
 
1580
1546
    fixed_components = False
1581
1547
 
1582
 
    colocated_branches = False
 
1548
    colocated_branches = True
1583
1549
 
1584
1550
    def __init__(self):
1585
1551
        BzrDirFormat.__init__(self)
1712
1678
            return ConvertMetaToColo(format)
1713
1679
        if (type(self) is BzrDirMetaFormat1Colo and
1714
1680
            type(format) is BzrDirMetaFormat1):
1715
 
            return ConvertMetaRemoveColo(format)
 
1681
            return ConvertMetaToColo(format)
1716
1682
        if not isinstance(self, format.__class__):
1717
1683
            # converting away from metadir is not implemented
1718
1684
            raise NotImplementedError(self.get_converter)
1814
1780
        # problems.
1815
1781
        format = BzrDirMetaFormat1Colo()
1816
1782
        self._supply_sub_formats_to(format)
1817
 
        return BzrDirMeta1Colo(transport, format)
 
1783
        return BzrDirMeta1(transport, format)
1818
1784
 
1819
1785
 
1820
1786
BzrProber.formats.register(BzrDirMetaFormat1Colo.get_format_string(),
1916
1882
        return BzrDir.open_from_transport(to_convert.root_transport)
1917
1883
 
1918
1884
 
1919
 
class ConvertMetaRemoveColo(controldir.Converter):
1920
 
    """Remove colocated branch support from a bzrdir."""
 
1885
class ConvertMetaToColo(controldir.Converter):
 
1886
    """Convert a 'development-colo' bzrdir to a '2a' bzrdir."""
1921
1887
 
1922
1888
    def __init__(self, target_format):
1923
 
        """Create a converter.that downgrades a colocated branch metadir
1924
 
        to a regular metadir.
 
1889
        """Create a converter that converts a 'development-colo' metadir
 
1890
        to a '2a' metadir.
1925
1891
 
1926
1892
        :param target_format: The final metadir format that is desired.
1927
1893
        """
1929
1895
 
1930
1896
    def convert(self, to_convert, pb):
1931
1897
        """See Converter.convert()."""
1932
 
        to_convert.control_files.lock_write()
1933
 
        try:
1934
 
            branches = to_convert.list_branches()
1935
 
            if len(branches) > 1:
1936
 
                raise errors.BzrError("remove all but a single "
1937
 
                    "colocated branch when downgrading")
1938
 
        finally:
1939
 
            to_convert.control_files.unlock()
1940
1898
        to_convert.transport.put_bytes('branch-format',
1941
1899
            self.target_format.as_string())
1942
1900
        return BzrDir.open_from_transport(to_convert.root_transport)