~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Jelmer Vernooij
  • Date: 2012-01-31 15:43:17 UTC
  • mfrom: (6437.3.28 2.5)
  • mto: (6437.23.1 2.5)
  • mto: This revision was merged to the branch mainline in revision 6458.
  • Revision ID: jelmer@samba.org-20120131154317-y028tz0r9xesvn9p
MergeĀ 2.5.

Show diffs side-by-side

added added

removed removed

Lines of Context:
355
355
            location of this control directory.
356
356
        :param create_tree_if_local: If true, a working-tree will be created
357
357
            when working locally.
 
358
        :return: The created control directory
358
359
        """
359
360
        operation = cleanup.OperationWithCleanups(self._sprout)
360
361
        return operation.run(url, revision_id=revision_id,
809
810
    present within a BzrDir.
810
811
    """
811
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
 
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)
816
858
 
817
859
    def can_convert_format(self):
818
860
        """See BzrDir.can_convert_format()."""
831
873
        """See ControlDir.destroy_branch."""
832
874
        if name is None:
833
875
            name = self._get_selected_branch()
 
876
        path = self._get_branch_path(name)
834
877
        if name != "":
835
 
            raise errors.NoColocatedBranchSupport(self)
 
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()
836
888
        try:
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)
 
892
                path), bzrdir=self)
841
893
 
842
894
    def create_repository(self, shared=False):
843
895
        """See BzrDir.create_repository."""
899
951
        """See BzrDir.get_branch_transport()."""
900
952
        if name is None:
901
953
            name = self._get_selected_branch()
902
 
        if name != "":
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)
908
959
        try:
909
960
            branch_format.get_format_string()
910
961
        except NotImplementedError:
911
962
            raise errors.IncompatibleFormat(branch_format, self._format)
 
963
        if name != "":
 
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()
 
968
                try:
 
969
                    branches = self._read_branch_list()
 
970
                    dirname = urlutils.dirname(utf8_name)
 
971
                    if dirname != "" and dirname in branches:
 
972
                        raise errors.ParentBranchExists(name)
 
973
                    child_branches = [
 
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)
 
979
                finally:
 
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)
912
984
        try:
913
 
            self.transport.mkdir('branch', mode=self._get_mkdir_mode())
 
985
            self.transport.mkdir(path, mode=mode)
914
986
        except errors.FileExists:
915
987
            pass
916
 
        return self.transport.clone('branch')
 
988
        return self.transport.clone(path)
917
989
 
918
990
    def get_repository_transport(self, repository_format):
919
991
        """See BzrDir.get_repository_transport()."""
943
1015
            pass
944
1016
        return self.transport.clone('checkout')
945
1017
 
 
1018
    def get_branches(self):
 
1019
        """See ControlDir.get_branches."""
 
1020
        ret = {}
 
1021
        try:
 
1022
            ret[""] = self.open_branch(name="")
 
1023
        except (errors.NotBranchError, errors.NoRepositoryPresent):
 
1024
            pass
 
1025
 
 
1026
        for name in self._read_branch_list():
 
1027
            ret[name] = self.open_branch(name=name.decode('utf-8'))
 
1028
 
 
1029
        return ret
 
1030
 
946
1031
    def has_workingtree(self):
947
1032
        """Tell if this bzrdir contains a working tree.
948
1033
 
1016
1101
        return config.TransportConfig(self.transport, 'control.conf')
1017
1102
 
1018
1103
 
1019
 
class BzrDirMeta1Colo(BzrDirMeta1):
1020
 
    """BzrDirMeta1 with support for colocated branches.
1021
 
 
1022
 
    This format is experimental, and will eventually be merged back into
1023
 
    BzrDirMeta1.
1024
 
    """
1025
 
 
1026
 
    def _get_branch_path(self, name):
1027
 
        """Obtain the branch path to use.
1028
 
 
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.
1032
 
 
1033
 
        :param name: Optional branch name to use
1034
 
        :return: Relative path to branch
1035
 
        """
1036
 
        if name == "":
1037
 
            return 'branch'
1038
 
        return urlutils.join('branches', name.encode("utf-8"))
1039
 
 
1040
 
    def _read_branch_list(self):
1041
 
        """Read the branch list.
1042
 
 
1043
 
        :return: List of utf-8 encoded branch names.
1044
 
        """
1045
 
        try:
1046
 
            f = self.control_transport.get('branch-list')
1047
 
        except errors.NoSuchFile:
1048
 
            return []
1049
 
 
1050
 
        ret = []
1051
 
        try:
1052
 
            for name in f:
1053
 
                ret.append(name.rstrip("\n"))
1054
 
        finally:
1055
 
            f.close()
1056
 
        return ret
1057
 
 
1058
 
    def _write_branch_list(self, branches):
1059
 
        """Write out the branch list.
1060
 
 
1061
 
        :param branches: List of utf-8 branch names to write
1062
 
        """
1063
 
        self.transport.put_bytes('branch-list',
1064
 
            "".join([name+"\n" for name in branches]))
1065
 
 
1066
 
    def destroy_branch(self, name=None):
1067
 
        """See BzrDir.create_branch."""
1068
 
        if name is None:
1069
 
            name = self._get_selected_branch()
1070
 
        path = self._get_branch_path(name)
1071
 
        if name != "":
1072
 
            self.control_files.lock_write()
1073
 
            try:
1074
 
                branches = self._read_branch_list()
1075
 
                try:
1076
 
                    branches.remove(name.encode("utf-8"))
1077
 
                except ValueError:
1078
 
                    raise errors.NotBranchError(name)
1079
 
                self._write_branch_list(branches)
1080
 
            finally:
1081
 
                self.control_files.unlock()
1082
 
        try:
1083
 
            self.transport.delete_tree(path)
1084
 
        except errors.NoSuchFile:
1085
 
            raise errors.NotBranchError(path=path, bzrdir=self)
1086
 
 
1087
 
    def get_branches(self):
1088
 
        """See ControlDir.get_branches."""
1089
 
        ret = {}
1090
 
        try:
1091
 
            ret[""] = self.open_branch(name="")
1092
 
        except (errors.NotBranchError, errors.NoRepositoryPresent):
1093
 
            pass
1094
 
 
1095
 
        for name in self._read_branch_list():
1096
 
            ret[name] = self.open_branch(name=name.decode('utf-8'))
1097
 
 
1098
 
        return ret
1099
 
 
1100
 
    def get_branch_transport(self, branch_format, name=None):
1101
 
        """See BzrDir.get_branch_transport()."""
1102
 
        if name is None:
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)
1109
 
        try:
1110
 
            branch_format.get_format_string()
1111
 
        except NotImplementedError:
1112
 
            raise errors.IncompatibleFormat(branch_format, self._format)
1113
 
        if name != "":
1114
 
            try:
1115
 
                self.transport.mkdir('branches', mode=self._get_mkdir_mode())
1116
 
            except errors.FileExists:
1117
 
                pass
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()
1122
 
                try:
1123
 
                    branches = self._read_branch_list()
1124
 
                    branches.append(utf8_name)
1125
 
                    self._write_branch_list(branches)
1126
 
                finally:
1127
 
                    self.control_files.unlock()
1128
 
        try:
1129
 
            self.transport.mkdir(path, mode=self._get_mkdir_mode())
1130
 
        except errors.FileExists:
1131
 
            pass
1132
 
        return self.transport.clone(path)
1133
 
 
1134
 
 
1135
1104
class BzrFormat(object):
1136
1105
    """Base class for all formats of things living in metadirs.
1137
1106
 
1580
1549
 
1581
1550
    fixed_components = False
1582
1551
 
1583
 
    colocated_branches = False
 
1552
    colocated_branches = True
1584
1553
 
1585
1554
    def __init__(self):
1586
1555
        BzrDirFormat.__init__(self)
1713
1682
            return ConvertMetaToColo(format)
1714
1683
        if (type(self) is BzrDirMetaFormat1Colo and
1715
1684
            type(format) is BzrDirMetaFormat1):
1716
 
            return ConvertMetaRemoveColo(format)
 
1685
            return ConvertMetaToColo(format)
1717
1686
        if not isinstance(self, format.__class__):
1718
1687
            # converting away from metadir is not implemented
1719
1688
            raise NotImplementedError(self.get_converter)
1815
1784
        # problems.
1816
1785
        format = BzrDirMetaFormat1Colo()
1817
1786
        self._supply_sub_formats_to(format)
1818
 
        return BzrDirMeta1Colo(transport, format)
 
1787
        return BzrDirMeta1(transport, format)
1819
1788
 
1820
1789
 
1821
1790
BzrProber.formats.register(BzrDirMetaFormat1Colo.get_format_string(),
1917
1886
        return BzrDir.open_from_transport(to_convert.root_transport)
1918
1887
 
1919
1888
 
1920
 
class ConvertMetaRemoveColo(controldir.Converter):
1921
 
    """Remove colocated branch support from a bzrdir."""
 
1889
class ConvertMetaToColo(controldir.Converter):
 
1890
    """Convert a 'development-colo' bzrdir to a '2a' bzrdir."""
1922
1891
 
1923
1892
    def __init__(self, target_format):
1924
 
        """Create a converter.that downgrades a colocated branch metadir
1925
 
        to a regular metadir.
 
1893
        """Create a converter that converts a 'development-colo' metadir
 
1894
        to a '2a' metadir.
1926
1895
 
1927
1896
        :param target_format: The final metadir format that is desired.
1928
1897
        """
1930
1899
 
1931
1900
    def convert(self, to_convert, pb):
1932
1901
        """See Converter.convert()."""
1933
 
        to_convert.control_files.lock_write()
1934
 
        try:
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")
1939
 
        finally:
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)