~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Patch Queue Manager
  • Date: 2014-04-09 13:36:25 UTC
  • mfrom: (6592.1.2 1303879-py27-issues)
  • Revision ID: pqm@pqm.ubuntu.com-20140409133625-s24spv3kha2w2860
(vila) Fix python-2.7.6 test failures. (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
objects returned.
26
26
"""
27
27
 
 
28
from __future__ import absolute_import
 
29
 
28
30
import sys
29
31
 
30
32
from bzrlib.lazy_import import lazy_import
46
48
    transport as _mod_transport,
47
49
    ui,
48
50
    urlutils,
 
51
    vf_search,
49
52
    win32utils,
50
53
    workingtree_3,
51
54
    workingtree_4,
52
55
    )
 
56
from bzrlib.branchfmt import fullhistory as fullhistorybranch
53
57
from bzrlib.repofmt import knitpack_repo
54
58
from bzrlib.transport import (
55
59
    do_catching_redirections,
200
204
                if (result_repo.user_url == result.user_url
201
205
                    and not require_stacking and
202
206
                    revision_id is not None):
203
 
                    fetch_spec = graph.PendingAncestryResult(
 
207
                    fetch_spec = vf_search.PendingAncestryResult(
204
208
                        [revision_id], local_repo)
205
209
                    result_repo.fetch(local_repo, fetch_spec=fetch_spec)
206
210
                else:
352
356
            location of this control directory.
353
357
        :param create_tree_if_local: If true, a working-tree will be created
354
358
            when working locally.
 
359
        :return: The created control directory
355
360
        """
356
361
        operation = cleanup.OperationWithCleanups(self._sprout)
357
362
        return operation.run(url, revision_id=revision_id,
370
375
        if revision_id is not None:
371
376
            fetch_spec_factory.add_revision_ids([revision_id])
372
377
            fetch_spec_factory.source_branch_stop_revision_id = revision_id
 
378
        if possible_transports is None:
 
379
            possible_transports = []
 
380
        else:
 
381
            possible_transports = list(possible_transports) + [
 
382
                self.root_transport]
373
383
        target_transport = _mod_transport.get_transport(url,
374
384
            possible_transports)
375
385
        target_transport.ensure_base()
376
386
        cloning_format = self.cloning_metadir(stacked)
377
387
        # Create/update the result branch
378
 
        result = cloning_format.initialize_on_transport(target_transport)
 
388
        try:
 
389
            result = controldir.ControlDir.open_from_transport(target_transport)
 
390
        except errors.NotBranchError:
 
391
            result = cloning_format.initialize_on_transport(target_transport)
379
392
        source_branch, source_repository = self._find_source_repo(
380
393
            add_cleanup, source_branch)
381
394
        fetch_spec_factory.source_branch = source_branch
387
400
            stacked_branch_url = None
388
401
        repository_policy = result.determine_repository_policy(
389
402
            force_new_repo, stacked_branch_url, require_stacking=stacked)
390
 
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
403
        result_repo, is_new_repo = repository_policy.acquire_repository(
 
404
            possible_transports=possible_transports)
391
405
        add_cleanup(result_repo.lock_write().unlock)
392
406
        fetch_spec_factory.source_repo = source_repository
393
407
        fetch_spec_factory.target_repo = result_repo
414
428
        mutter("created new branch %r" % (result_branch,))
415
429
 
416
430
        # Create/update the result working tree
417
 
        if (create_tree_if_local and
 
431
        if (create_tree_if_local and not result.has_workingtree() and
418
432
            isinstance(target_transport, local.LocalTransport) and
419
433
            (result_repo is None or result_repo.make_working_trees())):
420
434
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
452
466
                    stacked=stacked)
453
467
        return result
454
468
 
455
 
    @deprecated_method(deprecated_in((2, 3, 0)))
456
 
    def generate_backup_name(self, base):
457
 
        return self._available_backup_name(base)
458
 
 
459
469
    def _available_backup_name(self, base):
460
470
        """Find a non-existing backup file name based on base.
461
471
 
771
781
        return controldir.ControlDir.create(base, format=format,
772
782
                possible_transports=possible_transports)
773
783
 
 
784
    def __repr__(self):
 
785
        return "<%s at %r>" % (self.__class__.__name__, self.user_url)
 
786
 
 
787
    def update_feature_flags(self, updated_flags):
 
788
        """Update the features required by this bzrdir.
 
789
 
 
790
        :param updated_flags: Dictionary mapping feature names to necessities
 
791
            A necessity can be None to indicate the feature should be removed
 
792
        """
 
793
        self.control_files.lock_write()
 
794
        try:
 
795
            self._format._update_feature_flags(updated_flags)
 
796
            self.transport.put_bytes('branch-format', self._format.as_string())
 
797
        finally:
 
798
            self.control_files.unlock()
 
799
 
774
800
 
775
801
class BzrDirMeta1(BzrDir):
776
802
    """A .bzr meta version 1 control object.
781
807
    present within a BzrDir.
782
808
    """
783
809
 
 
810
    def _get_branch_path(self, name):
 
811
        """Obtain the branch path to use.
 
812
 
 
813
        This uses the API specified branch name first, and then falls back to
 
814
        the branch name specified in the URL. If neither of those is specified,
 
815
        it uses the default branch.
 
816
 
 
817
        :param name: Optional branch name to use
 
818
        :return: Relative path to branch
 
819
        """
 
820
        if name == "":
 
821
            return 'branch'
 
822
        return urlutils.join('branches', name.encode("utf-8"))
 
823
 
 
824
    def _read_branch_list(self):
 
825
        """Read the branch list.
 
826
 
 
827
        :return: List of utf-8 encoded branch names.
 
828
        """
 
829
        try:
 
830
            f = self.control_transport.get('branch-list')
 
831
        except errors.NoSuchFile:
 
832
            return []
 
833
 
 
834
        ret = []
 
835
        try:
 
836
            for name in f:
 
837
                ret.append(name.rstrip("\n"))
 
838
        finally:
 
839
            f.close()
 
840
        return ret
 
841
 
 
842
    def _write_branch_list(self, branches):
 
843
        """Write out the branch list.
 
844
 
 
845
        :param branches: List of utf-8 branch names to write
 
846
        """
 
847
        self.transport.put_bytes('branch-list',
 
848
            "".join([name+"\n" for name in branches]))
 
849
 
 
850
    def __init__(self, _transport, _format):
 
851
        super(BzrDirMeta1, self).__init__(_transport, _format)
 
852
        self.control_files = lockable_files.LockableFiles(
 
853
            self.control_transport, self._format._lock_file_name,
 
854
            self._format._lock_class)
 
855
 
784
856
    def can_convert_format(self):
785
857
        """See BzrDir.can_convert_format()."""
786
858
        return True
787
859
 
788
860
    def create_branch(self, name=None, repository=None,
789
861
            append_revisions_only=None):
790
 
        """See BzrDir.create_branch."""
 
862
        """See ControlDir.create_branch."""
 
863
        if name is None:
 
864
            name = self._get_selected_branch()
791
865
        return self._format.get_branch_format().initialize(self, name=name,
792
866
                repository=repository,
793
867
                append_revisions_only=append_revisions_only)
794
868
 
795
869
    def destroy_branch(self, name=None):
796
 
        """See BzrDir.create_branch."""
797
 
        if name is not None:
798
 
            raise errors.NoColocatedBranchSupport(self)
799
 
        self.transport.delete_tree('branch')
 
870
        """See ControlDir.destroy_branch."""
 
871
        if name is None:
 
872
            name = self._get_selected_branch()
 
873
        path = self._get_branch_path(name)
 
874
        if name != "":
 
875
            self.control_files.lock_write()
 
876
            try:
 
877
                branches = self._read_branch_list()
 
878
                try:
 
879
                    branches.remove(name.encode("utf-8"))
 
880
                except ValueError:
 
881
                    raise errors.NotBranchError(name)
 
882
                self._write_branch_list(branches)
 
883
            finally:
 
884
                self.control_files.unlock()
 
885
        try:
 
886
            self.transport.delete_tree(path)
 
887
        except errors.NoSuchFile:
 
888
            raise errors.NotBranchError(path=urlutils.join(self.transport.base,
 
889
                path), bzrdir=self)
800
890
 
801
891
    def create_repository(self, shared=False):
802
892
        """See BzrDir.create_repository."""
804
894
 
805
895
    def destroy_repository(self):
806
896
        """See BzrDir.destroy_repository."""
807
 
        self.transport.delete_tree('repository')
 
897
        try:
 
898
            self.transport.delete_tree('repository')
 
899
        except errors.NoSuchFile:
 
900
            raise errors.NoRepositoryPresent(self)
808
901
 
809
902
    def create_workingtree(self, revision_id=None, from_branch=None,
810
903
                           accelerator_tree=None, hardlink=False):
832
925
 
833
926
        This might be a synthetic object for e.g. RemoteBranch and SVN.
834
927
        """
835
 
        from bzrlib.branch import BranchFormat
836
 
        return BranchFormat.find_format(self, name=name)
 
928
        from bzrlib.branch import BranchFormatMetadir
 
929
        return BranchFormatMetadir.find_format(self, name=name)
837
930
 
838
931
    def _get_mkdir_mode(self):
839
932
        """Figure out the mode to use when creating a bzrdir subdir."""
843
936
 
844
937
    def get_branch_reference(self, name=None):
845
938
        """See BzrDir.get_branch_reference()."""
846
 
        from bzrlib.branch import BranchFormat
847
 
        format = BranchFormat.find_format(self, name=name)
 
939
        from bzrlib.branch import BranchFormatMetadir
 
940
        format = BranchFormatMetadir.find_format(self, name=name)
848
941
        return format.get_reference(self, name=name)
849
942
 
 
943
    def set_branch_reference(self, target_branch, name=None):
 
944
        format = _mod_branch.BranchReferenceFormat()
 
945
        return format.initialize(self, target_branch=target_branch, name=name)
 
946
 
850
947
    def get_branch_transport(self, branch_format, name=None):
851
948
        """See BzrDir.get_branch_transport()."""
852
 
        if name is not None:
853
 
            raise errors.NoColocatedBranchSupport(self)
 
949
        if name is None:
 
950
            name = self._get_selected_branch()
 
951
        path = self._get_branch_path(name)
854
952
        # XXX: this shouldn't implicitly create the directory if it's just
855
953
        # promising to get a transport -- mbp 20090727
856
954
        if branch_format is None:
857
 
            return self.transport.clone('branch')
 
955
            return self.transport.clone(path)
858
956
        try:
859
957
            branch_format.get_format_string()
860
958
        except NotImplementedError:
861
959
            raise errors.IncompatibleFormat(branch_format, self._format)
 
960
        if name != "":
 
961
            branches = self._read_branch_list()
 
962
            utf8_name = name.encode("utf-8")
 
963
            if not utf8_name in branches:
 
964
                self.control_files.lock_write()
 
965
                try:
 
966
                    branches = self._read_branch_list()
 
967
                    dirname = urlutils.dirname(utf8_name)
 
968
                    if dirname != "" and dirname in branches:
 
969
                        raise errors.ParentBranchExists(name)
 
970
                    child_branches = [
 
971
                        b.startswith(utf8_name+"/") for b in branches]
 
972
                    if any(child_branches):
 
973
                        raise errors.AlreadyBranchError(name)
 
974
                    branches.append(utf8_name)
 
975
                    self._write_branch_list(branches)
 
976
                finally:
 
977
                    self.control_files.unlock()
 
978
        branch_transport = self.transport.clone(path)
 
979
        mode = self._get_mkdir_mode()
 
980
        branch_transport.create_prefix(mode=mode)
862
981
        try:
863
 
            self.transport.mkdir('branch', mode=self._get_mkdir_mode())
 
982
            self.transport.mkdir(path, mode=mode)
864
983
        except errors.FileExists:
865
984
            pass
866
 
        return self.transport.clone('branch')
 
985
        return self.transport.clone(path)
867
986
 
868
987
    def get_repository_transport(self, repository_format):
869
988
        """See BzrDir.get_repository_transport()."""
893
1012
            pass
894
1013
        return self.transport.clone('checkout')
895
1014
 
 
1015
    def get_branches(self):
 
1016
        """See ControlDir.get_branches."""
 
1017
        ret = {}
 
1018
        try:
 
1019
            ret[""] = self.open_branch(name="")
 
1020
        except (errors.NotBranchError, errors.NoRepositoryPresent):
 
1021
            pass
 
1022
 
 
1023
        for name in self._read_branch_list():
 
1024
            ret[name] = self.open_branch(name=name.decode('utf-8'))
 
1025
 
 
1026
        return ret
 
1027
 
896
1028
    def has_workingtree(self):
897
1029
        """Tell if this bzrdir contains a working tree.
898
1030
 
899
1031
        Note: if you're going to open the working tree, you should just go
900
1032
        ahead and try, and not ask permission first.
901
1033
        """
902
 
        from bzrlib.workingtree import WorkingTreeFormat
 
1034
        from bzrlib.workingtree import WorkingTreeFormatMetaDir
903
1035
        try:
904
 
            WorkingTreeFormat.find_format_string(self)
 
1036
            WorkingTreeFormatMetaDir.find_format_string(self)
905
1037
        except errors.NoWorkingTree:
906
1038
            return False
907
1039
        return True
936
1068
        return False
937
1069
 
938
1070
    def open_branch(self, name=None, unsupported=False,
939
 
                    ignore_fallbacks=False):
940
 
        """See BzrDir.open_branch."""
 
1071
                    ignore_fallbacks=False, possible_transports=None):
 
1072
        """See ControlDir.open_branch."""
 
1073
        if name is None:
 
1074
            name = self._get_selected_branch()
941
1075
        format = self.find_branch_format(name=name)
942
1076
        format.check_support_status(unsupported)
943
1077
        return format.open(self, name=name,
944
 
            _found=True, ignore_fallbacks=ignore_fallbacks)
 
1078
            _found=True, ignore_fallbacks=ignore_fallbacks,
 
1079
            possible_transports=possible_transports)
945
1080
 
946
1081
    def open_repository(self, unsupported=False):
947
1082
        """See BzrDir.open_repository."""
948
 
        from bzrlib.repository import RepositoryFormat
949
 
        format = RepositoryFormat.find_format(self)
 
1083
        from bzrlib.repository import RepositoryFormatMetaDir
 
1084
        format = RepositoryFormatMetaDir.find_format(self)
950
1085
        format.check_support_status(unsupported)
951
1086
        return format.open(self, _found=True)
952
1087
 
953
1088
    def open_workingtree(self, unsupported=False,
954
1089
            recommend_upgrade=True):
955
1090
        """See BzrDir.open_workingtree."""
956
 
        from bzrlib.workingtree import WorkingTreeFormat
957
 
        format = WorkingTreeFormat.find_format(self)
 
1091
        from bzrlib.workingtree import WorkingTreeFormatMetaDir
 
1092
        format = WorkingTreeFormatMetaDir.find_format(self)
958
1093
        format.check_support_status(unsupported, recommend_upgrade,
959
1094
            basedir=self.root_transport.base)
960
1095
        return format.open(self, _found=True)
963
1098
        return config.TransportConfig(self.transport, 'control.conf')
964
1099
 
965
1100
 
966
 
class BzrDirMeta1Colo(BzrDirMeta1):
967
 
    """BzrDirMeta1 with support for colocated branches.
968
 
 
969
 
    This format is experimental, and will eventually be merged back into
970
 
    BzrDirMeta1.
 
1101
class BzrFormat(object):
 
1102
    """Base class for all formats of things living in metadirs.
 
1103
 
 
1104
    This class manages the format string that is stored in the 'format'
 
1105
    or 'branch-format' file.
 
1106
 
 
1107
    All classes for (branch-, repository-, workingtree-) formats that
 
1108
    live in meta directories and have their own 'format' file
 
1109
    (i.e. different from .bzr/branch-format) derive from this class,
 
1110
    as well as the relevant base class for their kind
 
1111
    (BranchFormat, WorkingTreeFormat, RepositoryFormat).
 
1112
 
 
1113
    Each format is identified by a "format" or "branch-format" file with a
 
1114
    single line containing the base format name and then an optional list of
 
1115
    feature flags.
 
1116
 
 
1117
    Feature flags are supported as of bzr 2.5. Setting feature flags on formats
 
1118
    will render them inaccessible to older versions of bzr.
 
1119
 
 
1120
    :ivar features: Dictionary mapping feature names to their necessity
971
1121
    """
972
1122
 
973
 
    def __init__(self, _transport, _format):
974
 
        super(BzrDirMeta1Colo, self).__init__(_transport, _format)
975
 
        self.control_files = lockable_files.LockableFiles(_transport,
976
 
            self._format._lock_file_name, self._format._lock_class)
977
 
 
978
 
    def _get_branch_path(self, name):
979
 
        """Obtain the branch path to use.
980
 
 
981
 
        This uses the API specified branch name first, and then falls back to
982
 
        the branch name specified in the URL. If neither of those is specified,
983
 
        it uses the default branch.
984
 
 
985
 
        :param name: Optional branch name to use
986
 
        :return: Relative path to branch, branch name
987
 
        """
988
 
        if name is None:
989
 
            name = self._get_selected_branch()
990
 
        if name is None:
991
 
            return 'branch', None
992
 
        return urlutils.join('branches', name), name
993
 
 
994
 
    def _read_branch_list(self):
995
 
        """Read the branch list.
996
 
 
997
 
        :return: List of utf-8 encoded branch names.
998
 
        """
999
 
        try:
1000
 
            f = self.control_transport.get('branch-list')
1001
 
        except errors.NoSuchFile:
1002
 
            return []
1003
 
 
1004
 
        ret = []
1005
 
        try:
1006
 
            for name in f:
1007
 
                ret.append(name.rstrip("\n"))
1008
 
        finally:
1009
 
            f.close()
1010
 
        return ret
1011
 
 
1012
 
    def _write_branch_list(self, branches):
1013
 
        """Write out the branch list.
1014
 
 
1015
 
        :param branches: List of utf-8 branch names to write
1016
 
        """
1017
 
        self.transport.put_bytes('branch-list',
1018
 
            "".join([name+"\n" for name in branches]))
1019
 
 
1020
 
    def destroy_branch(self, name=None):
1021
 
        """See BzrDir.create_branch."""
1022
 
        path, name = self._get_branch_path(name)
1023
 
        if name is not None:
1024
 
            self.control_files.lock_write()
1025
 
            try:
1026
 
                branches = self._read_branch_list()
1027
 
                try:
1028
 
                    branches.remove(name)
1029
 
                except ValueError:
1030
 
                    raise errors.NotBranchError(name)
1031
 
                self._write_branch_list(name)
1032
 
            finally:
1033
 
                self.control_files.unlock()
1034
 
        self.transport.delete_tree(path)
1035
 
 
1036
 
    def list_branches(self):
1037
 
        """See ControlDir.list_branches."""
1038
 
        ret = []
1039
 
        # Default branch
1040
 
        try:
1041
 
            ret.append(self.open_branch())
1042
 
        except (errors.NotBranchError, errors.NoRepositoryPresent):
1043
 
            pass
1044
 
 
1045
 
        # colocated branches
1046
 
        ret.extend([self.open_branch(name) for name in
1047
 
                    self._read_branch_list()])
1048
 
 
1049
 
        return ret
1050
 
 
1051
 
    def get_branch_transport(self, branch_format, name=None):
1052
 
        """See BzrDir.get_branch_transport()."""
1053
 
        path, name = self._get_branch_path(name)
1054
 
        # XXX: this shouldn't implicitly create the directory if it's just
1055
 
        # promising to get a transport -- mbp 20090727
1056
 
        if branch_format is None:
1057
 
            return self.transport.clone(path)
1058
 
        try:
1059
 
            branch_format.get_format_string()
1060
 
        except NotImplementedError:
1061
 
            raise errors.IncompatibleFormat(branch_format, self._format)
1062
 
        if name is not None:
1063
 
            try:
1064
 
                self.transport.mkdir('branches', mode=self._get_mkdir_mode())
1065
 
            except errors.FileExists:
1066
 
                pass
1067
 
            branches = self._read_branch_list()
1068
 
            if not name in branches:
1069
 
                self.control_files.lock_write()
1070
 
                try:
1071
 
                    branches = self._read_branch_list()
1072
 
                    branches.append(name)
1073
 
                    self._write_branch_list(branches)
1074
 
                finally:
1075
 
                    self.control_files.unlock()
1076
 
        try:
1077
 
            self.transport.mkdir(path, mode=self._get_mkdir_mode())
1078
 
        except errors.FileExists:
1079
 
            pass
1080
 
        return self.transport.clone(path)
 
1123
    _present_features = set()
 
1124
 
 
1125
    def __init__(self):
 
1126
        self.features = {}
 
1127
 
 
1128
    @classmethod
 
1129
    def register_feature(cls, name):
 
1130
        """Register a feature as being present.
 
1131
 
 
1132
        :param name: Name of the feature
 
1133
        """
 
1134
        if " " in name:
 
1135
            raise ValueError("spaces are not allowed in feature names")
 
1136
        if name in cls._present_features:
 
1137
            raise errors.FeatureAlreadyRegistered(name)
 
1138
        cls._present_features.add(name)
 
1139
 
 
1140
    @classmethod
 
1141
    def unregister_feature(cls, name):
 
1142
        """Unregister a feature."""
 
1143
        cls._present_features.remove(name)
 
1144
 
 
1145
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
 
1146
            basedir=None):
 
1147
        for name, necessity in self.features.iteritems():
 
1148
            if name in self._present_features:
 
1149
                continue
 
1150
            if necessity == "optional":
 
1151
                mutter("ignoring optional missing feature %s", name)
 
1152
                continue
 
1153
            elif necessity == "required":
 
1154
                raise errors.MissingFeature(name)
 
1155
            else:
 
1156
                mutter("treating unknown necessity as require for %s",
 
1157
                       name)
 
1158
                raise errors.MissingFeature(name)
 
1159
 
 
1160
    @classmethod
 
1161
    def get_format_string(cls):
 
1162
        """Return the ASCII format string that identifies this format."""
 
1163
        raise NotImplementedError(cls.get_format_string)
 
1164
 
 
1165
    @classmethod
 
1166
    def from_string(cls, text):
 
1167
        format_string = cls.get_format_string()
 
1168
        if not text.startswith(format_string):
 
1169
            raise AssertionError("Invalid format header %r for %r" % (text, cls))
 
1170
        lines = text[len(format_string):].splitlines()
 
1171
        ret = cls()
 
1172
        for lineno, line in enumerate(lines):
 
1173
            try:
 
1174
                (necessity, feature) = line.split(" ", 1)
 
1175
            except ValueError:
 
1176
                raise errors.ParseFormatError(format=cls, lineno=lineno+2,
 
1177
                    line=line, text=text)
 
1178
            ret.features[feature] = necessity
 
1179
        return ret
 
1180
 
 
1181
    def as_string(self):
 
1182
        """Return the string representation of this format.
 
1183
        """
 
1184
        lines = [self.get_format_string()]
 
1185
        lines.extend([("%s %s\n" % (item[1], item[0])) for item in
 
1186
            self.features.iteritems()])
 
1187
        return "".join(lines)
 
1188
 
 
1189
    @classmethod
 
1190
    def _find_format(klass, registry, kind, format_string):
 
1191
        try:
 
1192
            first_line = format_string[:format_string.index("\n")+1]
 
1193
        except ValueError:
 
1194
            first_line = format_string
 
1195
        try:
 
1196
            cls = registry.get(first_line)
 
1197
        except KeyError:
 
1198
            raise errors.UnknownFormatError(format=first_line, kind=kind)
 
1199
        return cls.from_string(format_string)
 
1200
 
 
1201
    def network_name(self):
 
1202
        """A simple byte string uniquely identifying this format for RPC calls.
 
1203
 
 
1204
        Metadir branch formats use their format string.
 
1205
        """
 
1206
        return self.as_string()
 
1207
 
 
1208
    def __eq__(self, other):
 
1209
        return (self.__class__ is other.__class__ and
 
1210
                self.features == other.features)
 
1211
 
 
1212
    def _update_feature_flags(self, updated_flags):
 
1213
        """Update the feature flags in this format.
 
1214
 
 
1215
        :param updated_flags: Updated feature flags
 
1216
        """
 
1217
        for name, necessity in updated_flags.iteritems():
 
1218
            if necessity is None:
 
1219
                try:
 
1220
                    del self.features[name]
 
1221
                except KeyError:
 
1222
                    pass
 
1223
            else:
 
1224
                self.features[name] = necessity
1081
1225
 
1082
1226
 
1083
1227
class BzrProber(controldir.Prober):
1087
1231
    """The known .bzr formats."""
1088
1232
 
1089
1233
    @classmethod
1090
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1091
 
    def register_bzrdir_format(klass, format):
1092
 
        klass.formats.register(format.get_format_string(), format)
1093
 
 
1094
 
    @classmethod
1095
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1096
 
    def unregister_bzrdir_format(klass, format):
1097
 
        klass.formats.remove(format.get_format_string())
1098
 
 
1099
 
    @classmethod
1100
1234
    def probe_transport(klass, transport):
1101
1235
        """Return the .bzrdir style format present in a directory."""
1102
1236
        try:
1104
1238
        except errors.NoSuchFile:
1105
1239
            raise errors.NotBranchError(path=transport.base)
1106
1240
        try:
1107
 
            return klass.formats.get(format_string)
 
1241
            first_line = format_string[:format_string.index("\n")+1]
 
1242
        except ValueError:
 
1243
            first_line = format_string
 
1244
        try:
 
1245
            cls = klass.formats.get(first_line)
1108
1246
        except KeyError:
1109
 
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
 
1247
            raise errors.UnknownFormatError(format=first_line, kind='bzrdir')
 
1248
        return cls.from_string(format_string)
1110
1249
 
1111
1250
    @classmethod
1112
1251
    def known_formats(cls):
1155
1294
        return set([RemoteBzrDirFormat()])
1156
1295
 
1157
1296
 
1158
 
class BzrDirFormat(controldir.ControlDirFormat):
 
1297
class BzrDirFormat(BzrFormat, controldir.ControlDirFormat):
1159
1298
    """ControlDirFormat base class for .bzr/ directories.
1160
1299
 
1161
1300
    Formats are placed in a dict by their format string for reference
1172
1311
    # _lock_class must be set in subclasses to the lock type, typ.
1173
1312
    # TransportLock or LockDir
1174
1313
 
1175
 
    @classmethod
1176
 
    def get_format_string(cls):
1177
 
        """Return the ASCII format string that identifies this format."""
1178
 
        raise NotImplementedError(cls.get_format_string)
1179
 
 
1180
1314
    def initialize_on_transport(self, transport):
1181
1315
        """Initialize a new bzrdir in the base directory of a Transport."""
1182
1316
        try:
1223
1357
        :param shared_repo: Control whether made repositories are shared or
1224
1358
            not.
1225
1359
        :param vfs_only: If True do not attempt to use a smart server
1226
 
        :return: repo, bzrdir, require_stacking, repository_policy. repo is
 
1360
        :return: repo, controldir, require_stacking, repository_policy. repo is
1227
1361
            None if none was created or found, bzrdir is always valid.
1228
1362
            require_stacking is the result of examining the stacked_on
1229
1363
            parameter and any stacking policy found for the target.
1304
1438
        # mode from the root directory
1305
1439
        temp_control = lockable_files.LockableFiles(transport,
1306
1440
                            '', lockable_files.TransportLock)
1307
 
        temp_control._transport.mkdir('.bzr',
1308
 
                                      # FIXME: RBC 20060121 don't peek under
1309
 
                                      # the covers
1310
 
                                      mode=temp_control._dir_mode)
 
1441
        try:
 
1442
            temp_control._transport.mkdir('.bzr',
 
1443
                # FIXME: RBC 20060121 don't peek under
 
1444
                # the covers
 
1445
                mode=temp_control._dir_mode)
 
1446
        except errors.FileExists:
 
1447
            raise errors.AlreadyControlDirError(transport.base)
1311
1448
        if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1312
1449
            win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1313
1450
        file_mode = temp_control._file_mode
1317
1454
                       "This is a Bazaar control directory.\n"
1318
1455
                       "Do not change any files in this directory.\n"
1319
1456
                       "See http://bazaar.canonical.com/ for more information about Bazaar.\n"),
1320
 
                      ('branch-format', self.get_format_string()),
 
1457
                      ('branch-format', self.as_string()),
1321
1458
                      ]
1322
1459
        # NB: no need to escape relative paths that are url safe.
1323
1460
        control_files = lockable_files.LockableFiles(bzrdir_transport,
1367
1504
            compatible with whatever sub formats are supported by self.
1368
1505
        :return: None.
1369
1506
        """
 
1507
        other_format.features = dict(self.features)
1370
1508
 
1371
1509
    def supports_transport(self, transport):
1372
1510
        # bzr formats can be opened over all known transports
1373
1511
        return True
1374
1512
 
 
1513
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
 
1514
            basedir=None):
 
1515
        controldir.ControlDirFormat.check_support_status(self,
 
1516
            allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
 
1517
            basedir=basedir)
 
1518
        BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
 
1519
            recommend_upgrade=recommend_upgrade, basedir=basedir)
 
1520
 
1375
1521
 
1376
1522
class BzrDirMetaFormat1(BzrDirFormat):
1377
1523
    """Bzr meta control format 1
1390
1536
 
1391
1537
    fixed_components = False
1392
1538
 
1393
 
    colocated_branches = False
 
1539
    colocated_branches = True
1394
1540
 
1395
1541
    def __init__(self):
 
1542
        BzrDirFormat.__init__(self)
1396
1543
        self._workingtree_format = None
1397
1544
        self._branch_format = None
1398
1545
        self._repository_format = None
1404
1551
            return False
1405
1552
        if other.workingtree_format != self.workingtree_format:
1406
1553
            return False
 
1554
        if other.features != self.features:
 
1555
            return False
1407
1556
        return True
1408
1557
 
1409
1558
    def __ne__(self, other):
1520
1669
            return ConvertMetaToColo(format)
1521
1670
        if (type(self) is BzrDirMetaFormat1Colo and
1522
1671
            type(format) is BzrDirMetaFormat1):
1523
 
            return ConvertMetaRemoveColo(format)
 
1672
            return ConvertMetaToColo(format)
1524
1673
        if not isinstance(self, format.__class__):
1525
1674
            # converting away from metadir is not implemented
1526
1675
            raise NotImplementedError(self.get_converter)
1535
1684
        """See BzrDirFormat.get_format_description()."""
1536
1685
        return "Meta directory format 1"
1537
1686
 
1538
 
    def network_name(self):
1539
 
        return self.get_format_string()
1540
 
 
1541
1687
    def _open(self, transport):
1542
1688
        """See BzrDirFormat._open."""
1543
1689
        # Create a new format instance because otherwise initialisation of new
1572
1718
            compatible with whatever sub formats are supported by self.
1573
1719
        :return: None.
1574
1720
        """
 
1721
        super(BzrDirMetaFormat1, self)._supply_sub_formats_to(other_format)
1575
1722
        if getattr(self, '_repository_format', None) is not None:
1576
1723
            other_format.repository_format = self.repository_format
1577
1724
        if self._branch_format is not None:
1590
1737
    def __set_workingtree_format(self, wt_format):
1591
1738
        self._workingtree_format = wt_format
1592
1739
 
 
1740
    def __repr__(self):
 
1741
        return "<%r>" % (self.__class__.__name__,)
 
1742
 
1593
1743
    workingtree_format = property(__get_workingtree_format,
1594
1744
                                  __set_workingtree_format)
1595
1745
 
1621
1771
        # problems.
1622
1772
        format = BzrDirMetaFormat1Colo()
1623
1773
        self._supply_sub_formats_to(format)
1624
 
        return BzrDirMeta1Colo(transport, format)
 
1774
        return BzrDirMeta1(transport, format)
1625
1775
 
1626
1776
 
1627
1777
BzrProber.formats.register(BzrDirMetaFormat1Colo.get_format_string(),
1662
1812
            old = branch._format.__class__
1663
1813
            new = self.target_format.get_branch_format().__class__
1664
1814
            while old != new:
1665
 
                if (old == _mod_branch.BzrBranchFormat5 and
 
1815
                if (old == fullhistorybranch.BzrBranchFormat5 and
1666
1816
                    new in (_mod_branch.BzrBranchFormat6,
1667
1817
                        _mod_branch.BzrBranchFormat7,
1668
1818
                        _mod_branch.BzrBranchFormat8)):
1719
1869
    def convert(self, to_convert, pb):
1720
1870
        """See Converter.convert()."""
1721
1871
        to_convert.transport.put_bytes('branch-format',
1722
 
            self.target_format.get_format_string())
 
1872
            self.target_format.as_string())
1723
1873
        return BzrDir.open_from_transport(to_convert.root_transport)
1724
1874
 
1725
1875
 
1726
 
class ConvertMetaRemoveColo(controldir.Converter):
1727
 
    """Remove colocated branch support from a bzrdir."""
 
1876
class ConvertMetaToColo(controldir.Converter):
 
1877
    """Convert a 'development-colo' bzrdir to a '2a' bzrdir."""
1728
1878
 
1729
1879
    def __init__(self, target_format):
1730
 
        """Create a converter.that downgrades a colocated branch metadir
1731
 
        to a regular metadir.
 
1880
        """Create a converter that converts a 'development-colo' metadir
 
1881
        to a '2a' metadir.
1732
1882
 
1733
1883
        :param target_format: The final metadir format that is desired.
1734
1884
        """
1736
1886
 
1737
1887
    def convert(self, to_convert, pb):
1738
1888
        """See Converter.convert()."""
1739
 
        to_convert.control_files.lock_write()
1740
 
        try:
1741
 
            branches = to_convert.list_branches()
1742
 
            if len(branches) > 1:
1743
 
                raise errors.BzrError("remove all but a single "
1744
 
                    "colocated branch when downgrading")
1745
 
        finally:
1746
 
            to_convert.control_files.unlock()
1747
1889
        to_convert.transport.put_bytes('branch-format',
1748
 
            self.target_format.get_format_string())
 
1890
            self.target_format.as_string())
1749
1891
        return BzrDir.open_from_transport(to_convert.root_transport)
1750
1892
 
1751
1893
 
1831
1973
        else:
1832
1974
            self._require_stacking = True
1833
1975
 
1834
 
    def acquire_repository(self, make_working_trees=None, shared=False):
 
1976
    def acquire_repository(self, make_working_trees=None, shared=False,
 
1977
            possible_transports=None):
1835
1978
        """Acquire a repository for this bzrdir.
1836
1979
 
1837
1980
        Implementations may create a new repository or use a pre-exising
1843
1986
        :return: A repository, is_new_flag (True if the repository was
1844
1987
            created).
1845
1988
        """
1846
 
        raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
 
1989
        raise NotImplementedError(RepositoryAcquisitionPolicy.acquire_repository)
1847
1990
 
1848
1991
 
1849
1992
class CreateRepository(RepositoryAcquisitionPolicy):
1862
2005
                                             require_stacking)
1863
2006
        self._bzrdir = bzrdir
1864
2007
 
1865
 
    def acquire_repository(self, make_working_trees=None, shared=False):
 
2008
    def acquire_repository(self, make_working_trees=None, shared=False,
 
2009
            possible_transports=None):
1866
2010
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
1867
2011
 
1868
2012
        Creates the desired repository in the bzrdir we already have.
1869
2013
        """
 
2014
        if possible_transports is None:
 
2015
            possible_transports = []
 
2016
        else:
 
2017
            possible_transports = list(possible_transports)
 
2018
        possible_transports.append(self._bzrdir.root_transport)
1870
2019
        stack_on = self._get_full_stack_on()
1871
2020
        if stack_on:
1872
2021
            format = self._bzrdir._format
1873
2022
            format.require_stacking(stack_on=stack_on,
1874
 
                                    possible_transports=[self._bzrdir.root_transport])
 
2023
                                    possible_transports=possible_transports)
1875
2024
            if not self._require_stacking:
1876
2025
                # We have picked up automatic stacking somewhere.
1877
2026
                note(gettext('Using default stacking branch {0} at {1}').format(
1878
2027
                    self._stack_on, self._stack_on_pwd))
1879
2028
        repository = self._bzrdir.create_repository(shared=shared)
1880
2029
        self._add_fallback(repository,
1881
 
                           possible_transports=[self._bzrdir.transport])
 
2030
                           possible_transports=possible_transports)
1882
2031
        if make_working_trees is not None:
1883
2032
            repository.set_make_working_trees(make_working_trees)
1884
2033
        return repository, True
1900
2049
                                             require_stacking)
1901
2050
        self._repository = repository
1902
2051
 
1903
 
    def acquire_repository(self, make_working_trees=None, shared=False):
 
2052
    def acquire_repository(self, make_working_trees=None, shared=False,
 
2053
            possible_transports=None):
1904
2054
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
1905
2055
 
1906
2056
        Returns an existing repository to use.
1907
2057
        """
 
2058
        if possible_transports is None:
 
2059
            possible_transports = []
 
2060
        else:
 
2061
            possible_transports = list(possible_transports)
 
2062
        possible_transports.append(self._repository.bzrdir.transport)
1908
2063
        self._add_fallback(self._repository,
1909
 
                       possible_transports=[self._repository.bzrdir.transport])
 
2064
                       possible_transports=possible_transports)
1910
2065
        return self._repository, False
1911
2066
 
1912
2067
 
1959
2114
register_metadir(controldir.format_registry, 'knit',
1960
2115
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
1961
2116
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
1962
 
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
2117
    branch_format='bzrlib.branchfmt.fullhistory.BzrBranchFormat5',
1963
2118
    tree_format='bzrlib.workingtree_3.WorkingTreeFormat3',
1964
2119
    hidden=True,
1965
2120
    deprecated=True)
1966
2121
register_metadir(controldir.format_registry, 'dirstate',
1967
2122
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
1968
 
    help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
1969
 
        'above when accessed over the network.',
1970
 
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
2123
    help='Format using dirstate for working trees. '
 
2124
        'Compatible with bzr 0.8 and '
 
2125
        'above when accessed over the network. Introduced in bzr 0.15.',
 
2126
    branch_format='bzrlib.branchfmt.fullhistory.BzrBranchFormat5',
1971
2127
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
1972
2128
    hidden=True,
1973
2129
    deprecated=True)
1974
2130
register_metadir(controldir.format_registry, 'dirstate-tags',
1975
2131
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
1976
 
    help='New in 0.15: Fast local operations and improved scaling for '
1977
 
        'network operations. Additionally adds support for tags.'
1978
 
        ' Incompatible with bzr < 0.15.',
 
2132
    help='Variant of dirstate with support for tags. '
 
2133
        'Introduced in bzr 0.15.',
1979
2134
    branch_format='bzrlib.branch.BzrBranchFormat6',
1980
2135
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
1981
2136
    hidden=True,
1982
2137
    deprecated=True)
1983
2138
register_metadir(controldir.format_registry, 'rich-root',
1984
2139
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
1985
 
    help='New in 1.0.  Better handling of tree roots.  Incompatible with'
1986
 
        ' bzr < 1.0.',
 
2140
    help='Variant of dirstate with better handling of tree roots. '
 
2141
        'Introduced in bzr 1.0',
1987
2142
    branch_format='bzrlib.branch.BzrBranchFormat6',
1988
2143
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
1989
2144
    hidden=True,
1990
2145
    deprecated=True)
1991
2146
register_metadir(controldir.format_registry, 'dirstate-with-subtree',
1992
2147
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
1993
 
    help='New in 0.15: Fast local operations and improved scaling for '
1994
 
        'network operations. Additionally adds support for versioning nested '
1995
 
        'bzr branches. Incompatible with bzr < 0.15.',
 
2148
    help='Variant of dirstate with support for nested trees. '
 
2149
         'Introduced in 0.15.',
1996
2150
    branch_format='bzrlib.branch.BzrBranchFormat6',
1997
2151
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
1998
2152
    experimental=True,
2000
2154
    )
2001
2155
register_metadir(controldir.format_registry, 'pack-0.92',
2002
2156
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack1',
2003
 
    help='New in 0.92: Pack-based format with data compatible with '
2004
 
        'dirstate-tags format repositories. Interoperates with '
2005
 
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
 
2157
    help='Pack-based format used in 1.x series. Introduced in 0.92. '
 
2158
        'Interoperates with bzr repositories before 0.92 but cannot be '
 
2159
        'read by bzr < 0.92. '
2006
2160
        ,
2007
2161
    branch_format='bzrlib.branch.BzrBranchFormat6',
2008
2162
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
 
2163
    deprecated=True,
2009
2164
    )
2010
2165
register_metadir(controldir.format_registry, 'pack-0.92-subtree',
2011
2166
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack3',
2012
 
    help='New in 0.92: Pack-based format with data compatible with '
2013
 
        'dirstate-with-subtree format repositories. Interoperates with '
 
2167
    help='Pack-based format used in 1.x series, with subtree support. '
 
2168
        'Introduced in 0.92. Interoperates with '
2014
2169
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
2015
2170
        ,
2016
2171
    branch_format='bzrlib.branch.BzrBranchFormat6',
2017
2172
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2018
2173
    hidden=True,
 
2174
    deprecated=True,
2019
2175
    experimental=True,
2020
2176
    )
2021
2177
register_metadir(controldir.format_registry, 'rich-root-pack',
2022
2178
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack4',
2023
 
    help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
2024
 
         '(needed for bzr-svn and bzr-git).',
 
2179
    help='A variant of pack-0.92 that supports rich-root data '
 
2180
         '(needed for bzr-svn and bzr-git). Introduced in 1.0.',
2025
2181
    branch_format='bzrlib.branch.BzrBranchFormat6',
2026
2182
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2027
2183
    hidden=True,
 
2184
    deprecated=True,
2028
2185
    )
2029
2186
register_metadir(controldir.format_registry, '1.6',
2030
2187
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5',
2034
2191
    branch_format='bzrlib.branch.BzrBranchFormat7',
2035
2192
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2036
2193
    hidden=True,
 
2194
    deprecated=True,
2037
2195
    )
2038
2196
register_metadir(controldir.format_registry, '1.6.1-rich-root',
2039
2197
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5RichRoot',
2042
2200
    branch_format='bzrlib.branch.BzrBranchFormat7',
2043
2201
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2044
2202
    hidden=True,
 
2203
    deprecated=True,
2045
2204
    )
2046
2205
register_metadir(controldir.format_registry, '1.9',
2047
2206
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
2051
2210
    branch_format='bzrlib.branch.BzrBranchFormat7',
2052
2211
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2053
2212
    hidden=True,
 
2213
    deprecated=True,
2054
2214
    )
2055
2215
register_metadir(controldir.format_registry, '1.9-rich-root',
2056
2216
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
2059
2219
    branch_format='bzrlib.branch.BzrBranchFormat7',
2060
2220
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2061
2221
    hidden=True,
 
2222
    deprecated=True,
2062
2223
    )
2063
2224
register_metadir(controldir.format_registry, '1.14',
2064
2225
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
2065
2226
    help='A working-tree format that supports content filtering.',
2066
2227
    branch_format='bzrlib.branch.BzrBranchFormat7',
2067
2228
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
 
2229
    hidden=True,
 
2230
    deprecated=True,
2068
2231
    )
2069
2232
register_metadir(controldir.format_registry, '1.14-rich-root',
2070
2233
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
2072
2235
         '(needed for bzr-svn and bzr-git).',
2073
2236
    branch_format='bzrlib.branch.BzrBranchFormat7',
2074
2237
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
 
2238
    hidden=True,
 
2239
    deprecated=True,
2075
2240
    )
2076
2241
# The following un-numbered 'development' formats should always just be aliases.
2077
2242
register_metadir(controldir.format_registry, 'development-subtree',
2110
2275
    help='The 2a format with experimental support for colocated branches.\n',
2111
2276
    branch_format='bzrlib.branch.BzrBranchFormat7',
2112
2277
    tree_format='bzrlib.workingtree_4.WorkingTreeFormat6',
2113
 
    experimental=False,
 
2278
    experimental=True,
2114
2279
    bzrdir_format=BzrDirMetaFormat1Colo,
2115
2280
    )
2116
2281
 
2120
2285
# Finally, the current format.
2121
2286
register_metadir(controldir.format_registry, '2a',
2122
2287
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
2123
 
    help='First format for bzr 2.0 series.\n'
 
2288
    help='Format for the bzr 2.0 series.\n'
2124
2289
        'Uses group-compress storage.\n'
2125
2290
        'Provides rich roots which are a one-way transition.\n',
2126
2291
        # 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '