~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Jelmer Vernooij
  • Date: 2011-01-14 00:58:16 UTC
  • mto: (5582.12.2 weave-plugin)
  • mto: This revision was merged to the branch mainline in revision 5718.
  • Revision ID: jelmer@samba.org-20110114005816-b3g5xigfiy20s29y
Fix imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
27
27
 
28
28
# TODO: Move old formats into a plugin to make this file smaller.
29
29
 
30
 
import os
31
30
import sys
32
 
import warnings
33
31
 
34
32
from bzrlib.lazy_import import lazy_import
35
33
lazy_import(globals(), """
45
43
    lockable_files,
46
44
    lockdir,
47
45
    osutils,
 
46
    pyutils,
48
47
    remote,
49
48
    repository,
50
49
    revision as _mod_revision,
76
75
""")
77
76
 
78
77
from bzrlib.trace import (
79
 
    mutter,
80
78
    note,
81
 
    warning,
82
79
    )
83
80
 
84
81
from bzrlib import (
85
82
    hooks,
86
 
    registry,
87
83
    symbol_versioning,
88
84
    )
 
85
from bzrlib.symbol_versioning import (
 
86
    deprecated_in,
 
87
    deprecated_method,
 
88
    )
89
89
 
90
90
 
91
91
class BzrDir(controldir.ControlDir):
165
165
                format.get_format_description(),
166
166
                basedir)
167
167
 
168
 
    def clone(self, url, revision_id=None, force_new_repo=False,
169
 
              preserve_stacking=False):
170
 
        """Clone this bzrdir and its contents to url verbatim.
171
 
 
172
 
        :param url: The url create the clone at.  If url's last component does
173
 
            not exist, it will be created.
174
 
        :param revision_id: The tip revision-id to use for any branch or
175
 
            working tree.  If not None, then the clone operation may tune
176
 
            itself to download less data.
177
 
        :param force_new_repo: Do not use a shared repository for the target
178
 
                               even if one is available.
179
 
        :param preserve_stacking: When cloning a stacked branch, stack the
180
 
            new branch on top of the other branch's stacked-on branch.
181
 
        """
182
 
        return self.clone_on_transport(get_transport(url),
183
 
                                       revision_id=revision_id,
184
 
                                       force_new_repo=force_new_repo,
185
 
                                       preserve_stacking=preserve_stacking)
186
 
 
187
168
    def clone_on_transport(self, transport, revision_id=None,
188
169
        force_new_repo=False, preserve_stacking=False, stacked_on=None,
189
 
        create_prefix=False, use_existing_dir=True):
 
170
        create_prefix=False, use_existing_dir=True, no_tree=False):
190
171
        """Clone this bzrdir and its contents to transport verbatim.
191
172
 
192
173
        :param transport: The transport for the location to produce the clone
234
215
        # we should look up the policy needs first, or just use it as a hint,
235
216
        # or something.
236
217
        if local_repo:
237
 
            make_working_trees = local_repo.make_working_trees()
 
218
            make_working_trees = local_repo.make_working_trees() and not no_tree
238
219
            want_shared = local_repo.is_shared()
239
220
            repo_format_name = format.repository_format.network_name()
240
221
        else:
515
496
                                               format=format).bzrdir
516
497
        return bzrdir.create_workingtree()
517
498
 
 
499
    @deprecated_method(deprecated_in((2, 3, 0)))
518
500
    def generate_backup_name(self, base):
519
 
        """Generate a non-existing backup file name based on base."""
520
 
        counter = 1
521
 
        name = "%s.~%d~" % (base, counter)
522
 
        while self.root_transport.has(name):
523
 
            counter += 1
524
 
            name = "%s.~%d~" % (base, counter)
525
 
        return name
 
501
        return self._available_backup_name(base)
 
502
 
 
503
    def _available_backup_name(self, base):
 
504
        """Find a non-existing backup file name based on base.
 
505
 
 
506
        See bzrlib.osutils.available_backup_name about race conditions.
 
507
        """
 
508
        return osutils.available_backup_name(base, self.root_transport.has)
526
509
 
527
510
    def backup_bzrdir(self):
528
511
        """Backup this bzr control directory.
530
513
        :return: Tuple with old path name and new path name
531
514
        """
532
515
 
533
 
        backup_dir=self.generate_backup_name('backup.bzr')
534
516
        pb = ui.ui_factory.nested_progress_bar()
535
517
        try:
536
 
            # FIXME: bug 300001 -- the backup fails if the backup directory
537
 
            # already exists, but it should instead either remove it or make
538
 
            # a new backup directory.
539
 
            #
540
518
            old_path = self.root_transport.abspath('.bzr')
 
519
            backup_dir = self._available_backup_name('backup.bzr')
541
520
            new_path = self.root_transport.abspath(backup_dir)
542
 
            ui.ui_factory.note('making backup of %s\n  to %s' % (old_path, new_path,))
 
521
            ui.ui_factory.note('making backup of %s\n  to %s'
 
522
                               % (old_path, new_path,))
543
523
            self.root_transport.copy_tree('.bzr', backup_dir)
544
524
            return (old_path, new_path)
545
525
        finally:
942
922
        return format.initialize_on_transport(t)
943
923
 
944
924
 
945
 
 
946
925
class BzrDirHooks(hooks.Hooks):
947
926
    """Hooks for BzrDir operations."""
948
927
 
998
977
                self.bzrdir)
999
978
 
1000
979
 
1001
 
class BzrDirPreSplitOut(BzrDir):
1002
 
    """A common class for the all-in-one formats."""
1003
 
 
1004
 
    def __init__(self, _transport, _format):
1005
 
        """See BzrDir.__init__."""
1006
 
        super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1007
 
        self._control_files = lockable_files.LockableFiles(
1008
 
                                            self.get_branch_transport(None),
1009
 
                                            self._format._lock_file_name,
1010
 
                                            self._format._lock_class)
1011
 
 
1012
 
    def break_lock(self):
1013
 
        """Pre-splitout bzrdirs do not suffer from stale locks."""
1014
 
        raise NotImplementedError(self.break_lock)
1015
 
 
1016
 
    def cloning_metadir(self, require_stacking=False):
1017
 
        """Produce a metadir suitable for cloning with."""
1018
 
        if require_stacking:
1019
 
            return controldir.format_registry.make_bzrdir('1.6')
1020
 
        return self._format.__class__()
1021
 
 
1022
 
    def clone(self, url, revision_id=None, force_new_repo=False,
1023
 
              preserve_stacking=False):
1024
 
        """See BzrDir.clone().
1025
 
 
1026
 
        force_new_repo has no effect, since this family of formats always
1027
 
        require a new repository.
1028
 
        preserve_stacking has no effect, since no source branch using this
1029
 
        family of formats can be stacked, so there is no stacking to preserve.
1030
 
        """
1031
 
        self._make_tail(url)
1032
 
        result = self._format._initialize_for_clone(url)
1033
 
        self.open_repository().clone(result, revision_id=revision_id)
1034
 
        from_branch = self.open_branch()
1035
 
        from_branch.clone(result, revision_id=revision_id)
1036
 
        try:
1037
 
            tree = self.open_workingtree()
1038
 
        except errors.NotLocalUrl:
1039
 
            # make a new one, this format always has to have one.
1040
 
            result._init_workingtree()
1041
 
        else:
1042
 
            tree.clone(result)
1043
 
        return result
1044
 
 
1045
 
    def create_branch(self, name=None):
1046
 
        """See BzrDir.create_branch."""
1047
 
        return self._format.get_branch_format().initialize(self, name=name)
1048
 
 
1049
 
    def destroy_branch(self, name=None):
1050
 
        """See BzrDir.destroy_branch."""
1051
 
        raise errors.UnsupportedOperation(self.destroy_branch, self)
1052
 
 
1053
 
    def create_repository(self, shared=False):
1054
 
        """See BzrDir.create_repository."""
1055
 
        if shared:
1056
 
            raise errors.IncompatibleFormat('shared repository', self._format)
1057
 
        return self.open_repository()
1058
 
 
1059
 
    def destroy_repository(self):
1060
 
        """See BzrDir.destroy_repository."""
1061
 
        raise errors.UnsupportedOperation(self.destroy_repository, self)
1062
 
 
1063
 
    def create_workingtree(self, revision_id=None, from_branch=None,
1064
 
                           accelerator_tree=None, hardlink=False):
1065
 
        """See BzrDir.create_workingtree."""
1066
 
        # The workingtree is sometimes created when the bzrdir is created,
1067
 
        # but not when cloning.
1068
 
 
1069
 
        # this looks buggy but is not -really-
1070
 
        # because this format creates the workingtree when the bzrdir is
1071
 
        # created
1072
 
        # clone and sprout will have set the revision_id
1073
 
        # and that will have set it for us, its only
1074
 
        # specific uses of create_workingtree in isolation
1075
 
        # that can do wonky stuff here, and that only
1076
 
        # happens for creating checkouts, which cannot be
1077
 
        # done on this format anyway. So - acceptable wart.
1078
 
        if hardlink:
1079
 
            warning("can't support hardlinked working trees in %r"
1080
 
                % (self,))
1081
 
        try:
1082
 
            result = self.open_workingtree(recommend_upgrade=False)
1083
 
        except errors.NoSuchFile:
1084
 
            result = self._init_workingtree()
1085
 
        if revision_id is not None:
1086
 
            if revision_id == _mod_revision.NULL_REVISION:
1087
 
                result.set_parent_ids([])
1088
 
            else:
1089
 
                result.set_parent_ids([revision_id])
1090
 
        return result
1091
 
 
1092
 
    def _init_workingtree(self):
1093
 
        from bzrlib.workingtree import WorkingTreeFormat2
1094
 
        try:
1095
 
            return WorkingTreeFormat2().initialize(self)
1096
 
        except errors.NotLocalUrl:
1097
 
            # Even though we can't access the working tree, we need to
1098
 
            # create its control files.
1099
 
            return WorkingTreeFormat2()._stub_initialize_on_transport(
1100
 
                self.transport, self._control_files._file_mode)
1101
 
 
1102
 
    def destroy_workingtree(self):
1103
 
        """See BzrDir.destroy_workingtree."""
1104
 
        raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1105
 
 
1106
 
    def destroy_workingtree_metadata(self):
1107
 
        """See BzrDir.destroy_workingtree_metadata."""
1108
 
        raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1109
 
                                          self)
1110
 
 
1111
 
    def get_branch_transport(self, branch_format, name=None):
1112
 
        """See BzrDir.get_branch_transport()."""
1113
 
        if name is not None:
1114
 
            raise errors.NoColocatedBranchSupport(self)
1115
 
        if branch_format is None:
1116
 
            return self.transport
1117
 
        try:
1118
 
            branch_format.get_format_string()
1119
 
        except NotImplementedError:
1120
 
            return self.transport
1121
 
        raise errors.IncompatibleFormat(branch_format, self._format)
1122
 
 
1123
 
    def get_repository_transport(self, repository_format):
1124
 
        """See BzrDir.get_repository_transport()."""
1125
 
        if repository_format is None:
1126
 
            return self.transport
1127
 
        try:
1128
 
            repository_format.get_format_string()
1129
 
        except NotImplementedError:
1130
 
            return self.transport
1131
 
        raise errors.IncompatibleFormat(repository_format, self._format)
1132
 
 
1133
 
    def get_workingtree_transport(self, workingtree_format):
1134
 
        """See BzrDir.get_workingtree_transport()."""
1135
 
        if workingtree_format is None:
1136
 
            return self.transport
1137
 
        try:
1138
 
            workingtree_format.get_format_string()
1139
 
        except NotImplementedError:
1140
 
            return self.transport
1141
 
        raise errors.IncompatibleFormat(workingtree_format, self._format)
1142
 
 
1143
 
    def needs_format_conversion(self, format=None):
1144
 
        """See BzrDir.needs_format_conversion()."""
1145
 
        # if the format is not the same as the system default,
1146
 
        # an upgrade is needed.
1147
 
        if format is None:
1148
 
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1149
 
                % 'needs_format_conversion(format=None)')
1150
 
            format = BzrDirFormat.get_default_format()
1151
 
        return not isinstance(self._format, format.__class__)
1152
 
 
1153
 
    def open_branch(self, name=None, unsupported=False,
1154
 
                    ignore_fallbacks=False):
1155
 
        """See BzrDir.open_branch."""
1156
 
        from bzrlib.branch import BzrBranchFormat4
1157
 
        format = BzrBranchFormat4()
1158
 
        self._check_supported(format, unsupported)
1159
 
        return format.open(self, name, _found=True)
1160
 
 
1161
 
    def sprout(self, url, revision_id=None, force_new_repo=False,
1162
 
               possible_transports=None, accelerator_tree=None,
1163
 
               hardlink=False, stacked=False, create_tree_if_local=True,
1164
 
               source_branch=None):
1165
 
        """See BzrDir.sprout()."""
1166
 
        if source_branch is not None:
1167
 
            my_branch = self.open_branch()
1168
 
            if source_branch.base != my_branch.base:
1169
 
                raise AssertionError(
1170
 
                    "source branch %r is not within %r with branch %r" %
1171
 
                    (source_branch, self, my_branch))
1172
 
        if stacked:
1173
 
            raise errors.UnstackableBranchFormat(
1174
 
                self._format, self.root_transport.base)
1175
 
        if not create_tree_if_local:
1176
 
            raise errors.MustHaveWorkingTree(
1177
 
                self._format, self.root_transport.base)
1178
 
        from bzrlib.workingtree import WorkingTreeFormat2
1179
 
        self._make_tail(url)
1180
 
        result = self._format._initialize_for_clone(url)
1181
 
        try:
1182
 
            self.open_repository().clone(result, revision_id=revision_id)
1183
 
        except errors.NoRepositoryPresent:
1184
 
            pass
1185
 
        try:
1186
 
            self.open_branch().sprout(result, revision_id=revision_id)
1187
 
        except errors.NotBranchError:
1188
 
            pass
1189
 
 
1190
 
        # we always want a working tree
1191
 
        WorkingTreeFormat2().initialize(result,
1192
 
                                        accelerator_tree=accelerator_tree,
1193
 
                                        hardlink=hardlink)
1194
 
        return result
1195
 
 
1196
 
 
1197
 
class BzrDir4(BzrDirPreSplitOut):
1198
 
    """A .bzr version 4 control object.
1199
 
 
1200
 
    This is a deprecated format and may be removed after sept 2006.
1201
 
    """
1202
 
 
1203
 
    def create_repository(self, shared=False):
1204
 
        """See BzrDir.create_repository."""
1205
 
        return self._format.repository_format.initialize(self, shared)
1206
 
 
1207
 
    def needs_format_conversion(self, format=None):
1208
 
        """Format 4 dirs are always in need of conversion."""
1209
 
        if format is None:
1210
 
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1211
 
                % 'needs_format_conversion(format=None)')
1212
 
        return True
1213
 
 
1214
 
    def open_repository(self):
1215
 
        """See BzrDir.open_repository."""
1216
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat4
1217
 
        return RepositoryFormat4().open(self, _found=True)
1218
 
 
1219
 
 
1220
 
class BzrDir5(BzrDirPreSplitOut):
1221
 
    """A .bzr version 5 control object.
1222
 
 
1223
 
    This is a deprecated format and may be removed after sept 2006.
1224
 
    """
1225
 
 
1226
 
    def has_workingtree(self):
1227
 
        """See BzrDir.has_workingtree."""
1228
 
        return True
1229
 
    
1230
 
    def open_repository(self):
1231
 
        """See BzrDir.open_repository."""
1232
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
1233
 
        return RepositoryFormat5().open(self, _found=True)
1234
 
 
1235
 
    def open_workingtree(self, _unsupported=False,
1236
 
            recommend_upgrade=True):
1237
 
        """See BzrDir.create_workingtree."""
1238
 
        from bzrlib.workingtree import WorkingTreeFormat2
1239
 
        wt_format = WorkingTreeFormat2()
1240
 
        # we don't warn here about upgrades; that ought to be handled for the
1241
 
        # bzrdir as a whole
1242
 
        return wt_format.open(self, _found=True)
1243
 
 
1244
 
 
1245
 
class BzrDir6(BzrDirPreSplitOut):
1246
 
    """A .bzr version 6 control object.
1247
 
 
1248
 
    This is a deprecated format and may be removed after sept 2006.
1249
 
    """
1250
 
 
1251
 
    def has_workingtree(self):
1252
 
        """See BzrDir.has_workingtree."""
1253
 
        return True
1254
 
    
1255
 
    def open_repository(self):
1256
 
        """See BzrDir.open_repository."""
1257
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
1258
 
        return RepositoryFormat6().open(self, _found=True)
1259
 
 
1260
 
    def open_workingtree(self, _unsupported=False,
1261
 
        recommend_upgrade=True):
1262
 
        """See BzrDir.create_workingtree."""
1263
 
        # we don't warn here about upgrades; that ought to be handled for the
1264
 
        # bzrdir as a whole
1265
 
        from bzrlib.workingtree import WorkingTreeFormat2
1266
 
        return WorkingTreeFormat2().open(self, _found=True)
1267
 
 
1268
 
 
1269
980
class BzrDirMeta1(BzrDir):
1270
981
    """A .bzr meta version 1 control object.
1271
982
 
1279
990
        """See BzrDir.can_convert_format()."""
1280
991
        return True
1281
992
 
1282
 
    def create_branch(self, name=None):
 
993
    def create_branch(self, name=None, repository=None):
1283
994
        """See BzrDir.create_branch."""
1284
 
        return self._format.get_branch_format().initialize(self, name=name)
 
995
        return self._format.get_branch_format().initialize(self, name=name,
 
996
                repository=repository)
1285
997
 
1286
998
    def destroy_branch(self, name=None):
1287
999
        """See BzrDir.create_branch."""
1309
1021
        wt = self.open_workingtree(recommend_upgrade=False)
1310
1022
        repository = wt.branch.repository
1311
1023
        empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1312
 
        wt.revert(old_tree=empty)
 
1024
        # We ignore the conflicts returned by wt.revert since we're about to
 
1025
        # delete the wt metadata anyway, all that should be left here are
 
1026
        # detritus. But see bug #634470 about subtree .bzr dirs.
 
1027
        conflicts = wt.revert(old_tree=empty)
1313
1028
        self.destroy_workingtree_metadata()
1314
1029
 
1315
1030
    def destroy_workingtree_metadata(self):
1675
1390
        utf8_files = [('README',
1676
1391
                       "This is a Bazaar control directory.\n"
1677
1392
                       "Do not change any files in this directory.\n"
1678
 
                       "See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
 
1393
                       "See http://bazaar.canonical.com/ for more information about Bazaar.\n"),
1679
1394
                      ('branch-format', self.get_format_string()),
1680
1395
                      ]
1681
1396
        # NB: no need to escape relative paths that are url safe.
1719
1434
    def register_format(klass, format):
1720
1435
        BzrProber.register_bzrdir_format(format)
1721
1436
        # bzr native formats have a network name of their format string.
1722
 
        network_format_registry.register(format.get_format_string(), format.__class__)
 
1437
        controldir.network_format_registry.register(format.get_format_string(), format.__class__)
1723
1438
        controldir.ControlDirFormat.register_format(format)
1724
1439
 
1725
1440
    def _supply_sub_formats_to(self, other_format):
1738
1453
    def unregister_format(klass, format):
1739
1454
        BzrProber.unregister_bzrdir_format(format)
1740
1455
        controldir.ControlDirFormat.unregister_format(format)
1741
 
        network_format_registry.remove(format.get_format_string())
1742
 
 
1743
 
 
1744
 
class BzrDirFormat4(BzrDirFormat):
1745
 
    """Bzr dir format 4.
1746
 
 
1747
 
    This format is a combined format for working tree, branch and repository.
1748
 
    It has:
1749
 
     - Format 1 working trees [always]
1750
 
     - Format 4 branches [always]
1751
 
     - Format 4 repositories [always]
1752
 
 
1753
 
    This format is deprecated: it indexes texts using a text it which is
1754
 
    removed in format 5; write support for this format has been removed.
1755
 
    """
1756
 
 
1757
 
    _lock_class = lockable_files.TransportLock
1758
 
 
1759
 
    def get_format_string(self):
1760
 
        """See BzrDirFormat.get_format_string()."""
1761
 
        return "Bazaar-NG branch, format 0.0.4\n"
1762
 
 
1763
 
    def get_format_description(self):
1764
 
        """See BzrDirFormat.get_format_description()."""
1765
 
        return "All-in-one format 4"
1766
 
 
1767
 
    def get_converter(self, format=None):
1768
 
        """See BzrDirFormat.get_converter()."""
1769
 
        # there is one and only one upgrade path here.
1770
 
        return ConvertBzrDir4To5()
1771
 
 
1772
 
    def initialize_on_transport(self, transport):
1773
 
        """Format 4 branches cannot be created."""
1774
 
        raise errors.UninitializableFormat(self)
1775
 
 
1776
 
    def is_supported(self):
1777
 
        """Format 4 is not supported.
1778
 
 
1779
 
        It is not supported because the model changed from 4 to 5 and the
1780
 
        conversion logic is expensive - so doing it on the fly was not
1781
 
        feasible.
1782
 
        """
1783
 
        return False
1784
 
 
1785
 
    def network_name(self):
1786
 
        return self.get_format_string()
1787
 
 
1788
 
    def _open(self, transport):
1789
 
        """See BzrDirFormat._open."""
1790
 
        return BzrDir4(transport, self)
1791
 
 
1792
 
    def __return_repository_format(self):
1793
 
        """Circular import protection."""
1794
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat4
1795
 
        return RepositoryFormat4()
1796
 
    repository_format = property(__return_repository_format)
1797
 
 
1798
 
 
1799
 
class BzrDirFormatAllInOne(BzrDirFormat):
1800
 
    """Common class for formats before meta-dirs."""
1801
 
 
1802
 
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1803
 
        create_prefix=False, force_new_repo=False, stacked_on=None,
1804
 
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1805
 
        shared_repo=False):
1806
 
        """See BzrDirFormat.initialize_on_transport_ex."""
1807
 
        require_stacking = (stacked_on is not None)
1808
 
        # Format 5 cannot stack, but we've been asked to - actually init
1809
 
        # a Meta1Dir
1810
 
        if require_stacking:
1811
 
            format = BzrDirMetaFormat1()
1812
 
            return format.initialize_on_transport_ex(transport,
1813
 
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1814
 
                force_new_repo=force_new_repo, stacked_on=stacked_on,
1815
 
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1816
 
                make_working_trees=make_working_trees, shared_repo=shared_repo)
1817
 
        return BzrDirFormat.initialize_on_transport_ex(self, transport,
1818
 
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1819
 
            force_new_repo=force_new_repo, stacked_on=stacked_on,
1820
 
            stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1821
 
            make_working_trees=make_working_trees, shared_repo=shared_repo)
1822
 
 
1823
 
 
1824
 
class BzrDirFormat5(BzrDirFormatAllInOne):
1825
 
    """Bzr control format 5.
1826
 
 
1827
 
    This format is a combined format for working tree, branch and repository.
1828
 
    It has:
1829
 
     - Format 2 working trees [always]
1830
 
     - Format 4 branches [always]
1831
 
     - Format 5 repositories [always]
1832
 
       Unhashed stores in the repository.
1833
 
    """
1834
 
 
1835
 
    _lock_class = lockable_files.TransportLock
1836
 
 
1837
 
    def get_format_string(self):
1838
 
        """See BzrDirFormat.get_format_string()."""
1839
 
        return "Bazaar-NG branch, format 5\n"
1840
 
 
1841
 
    def get_branch_format(self):
1842
 
        from bzrlib import branch
1843
 
        return branch.BzrBranchFormat4()
1844
 
 
1845
 
    def get_format_description(self):
1846
 
        """See BzrDirFormat.get_format_description()."""
1847
 
        return "All-in-one format 5"
1848
 
 
1849
 
    def get_converter(self, format=None):
1850
 
        """See BzrDirFormat.get_converter()."""
1851
 
        # there is one and only one upgrade path here.
1852
 
        return ConvertBzrDir5To6()
1853
 
 
1854
 
    def _initialize_for_clone(self, url):
1855
 
        return self.initialize_on_transport(get_transport(url), _cloning=True)
1856
 
 
1857
 
    def initialize_on_transport(self, transport, _cloning=False):
1858
 
        """Format 5 dirs always have working tree, branch and repository.
1859
 
 
1860
 
        Except when they are being cloned.
1861
 
        """
1862
 
        from bzrlib.branch import BzrBranchFormat4
1863
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
1864
 
        result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1865
 
        RepositoryFormat5().initialize(result, _internal=True)
1866
 
        if not _cloning:
1867
 
            branch = BzrBranchFormat4().initialize(result)
1868
 
            result._init_workingtree()
1869
 
        return result
1870
 
 
1871
 
    def network_name(self):
1872
 
        return self.get_format_string()
1873
 
 
1874
 
    def _open(self, transport):
1875
 
        """See BzrDirFormat._open."""
1876
 
        return BzrDir5(transport, self)
1877
 
 
1878
 
    def __return_repository_format(self):
1879
 
        """Circular import protection."""
1880
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
1881
 
        return RepositoryFormat5()
1882
 
    repository_format = property(__return_repository_format)
1883
 
 
1884
 
 
1885
 
class BzrDirFormat6(BzrDirFormatAllInOne):
1886
 
    """Bzr control format 6.
1887
 
 
1888
 
    This format is a combined format for working tree, branch and repository.
1889
 
    It has:
1890
 
     - Format 2 working trees [always]
1891
 
     - Format 4 branches [always]
1892
 
     - Format 6 repositories [always]
1893
 
    """
1894
 
 
1895
 
    _lock_class = lockable_files.TransportLock
1896
 
 
1897
 
    def get_format_string(self):
1898
 
        """See BzrDirFormat.get_format_string()."""
1899
 
        return "Bazaar-NG branch, format 6\n"
1900
 
 
1901
 
    def get_format_description(self):
1902
 
        """See BzrDirFormat.get_format_description()."""
1903
 
        return "All-in-one format 6"
1904
 
 
1905
 
    def get_branch_format(self):
1906
 
        from bzrlib import branch
1907
 
        return branch.BzrBranchFormat4()
1908
 
 
1909
 
    def get_converter(self, format=None):
1910
 
        """See BzrDirFormat.get_converter()."""
1911
 
        # there is one and only one upgrade path here.
1912
 
        return ConvertBzrDir6ToMeta()
1913
 
 
1914
 
    def _initialize_for_clone(self, url):
1915
 
        return self.initialize_on_transport(get_transport(url), _cloning=True)
1916
 
 
1917
 
    def initialize_on_transport(self, transport, _cloning=False):
1918
 
        """Format 6 dirs always have working tree, branch and repository.
1919
 
 
1920
 
        Except when they are being cloned.
1921
 
        """
1922
 
        from bzrlib.branch import BzrBranchFormat4
1923
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
1924
 
        result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1925
 
        RepositoryFormat6().initialize(result, _internal=True)
1926
 
        if not _cloning:
1927
 
            branch = BzrBranchFormat4().initialize(result)
1928
 
            result._init_workingtree()
1929
 
        return result
1930
 
 
1931
 
    def network_name(self):
1932
 
        return self.get_format_string()
1933
 
 
1934
 
    def _open(self, transport):
1935
 
        """See BzrDirFormat._open."""
1936
 
        return BzrDir6(transport, self)
1937
 
 
1938
 
    def __return_repository_format(self):
1939
 
        """Circular import protection."""
1940
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
1941
 
        return RepositoryFormat6()
1942
 
    repository_format = property(__return_repository_format)
 
1456
        controldir.network_format_registry.remove(format.get_format_string())
1943
1457
 
1944
1458
 
1945
1459
class BzrDirMetaFormat1(BzrDirFormat):
2147
1661
                                  __set_workingtree_format)
2148
1662
 
2149
1663
 
2150
 
network_format_registry = registry.FormatRegistry()
2151
 
"""Registry of formats indexed by their network name.
2152
 
 
2153
 
The network name for a BzrDirFormat is an identifier that can be used when
2154
 
referring to formats with smart server operations. See
2155
 
BzrDirFormat.network_name() for more detail.
2156
 
"""
2157
 
 
2158
 
 
2159
1664
# Register bzr formats
2160
 
BzrDirFormat.register_format(BzrDirFormat4())
2161
 
BzrDirFormat.register_format(BzrDirFormat5())
2162
 
BzrDirFormat.register_format(BzrDirFormat6())
2163
1665
__default_format = BzrDirMetaFormat1()
2164
1666
BzrDirFormat.register_format(__default_format)
2165
1667
controldir.ControlDirFormat._default_format = __default_format
2181
1683
        self.pb.update(message, self.count, self.total)
2182
1684
 
2183
1685
 
2184
 
class ConvertBzrDir4To5(Converter):
2185
 
    """Converts format 4 bzr dirs to format 5."""
2186
 
 
2187
 
    def __init__(self):
2188
 
        super(ConvertBzrDir4To5, self).__init__()
2189
 
        self.converted_revs = set()
2190
 
        self.absent_revisions = set()
2191
 
        self.text_count = 0
2192
 
        self.revisions = {}
2193
 
 
2194
 
    def convert(self, to_convert, pb):
2195
 
        """See Converter.convert()."""
2196
 
        self.bzrdir = to_convert
2197
 
        if pb is not None:
2198
 
            warnings.warn("pb parameter to convert() is deprecated")
2199
 
        self.pb = ui.ui_factory.nested_progress_bar()
2200
 
        try:
2201
 
            ui.ui_factory.note('starting upgrade from format 4 to 5')
2202
 
            if isinstance(self.bzrdir.transport, local.LocalTransport):
2203
 
                self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2204
 
            self._convert_to_weaves()
2205
 
            return BzrDir.open(self.bzrdir.user_url)
2206
 
        finally:
2207
 
            self.pb.finished()
2208
 
 
2209
 
    def _convert_to_weaves(self):
2210
 
        ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
2211
 
        try:
2212
 
            # TODO permissions
2213
 
            stat = self.bzrdir.transport.stat('weaves')
2214
 
            if not S_ISDIR(stat.st_mode):
2215
 
                self.bzrdir.transport.delete('weaves')
2216
 
                self.bzrdir.transport.mkdir('weaves')
2217
 
        except errors.NoSuchFile:
2218
 
            self.bzrdir.transport.mkdir('weaves')
2219
 
        # deliberately not a WeaveFile as we want to build it up slowly.
2220
 
        self.inv_weave = Weave('inventory')
2221
 
        # holds in-memory weaves for all files
2222
 
        self.text_weaves = {}
2223
 
        self.bzrdir.transport.delete('branch-format')
2224
 
        self.branch = self.bzrdir.open_branch()
2225
 
        self._convert_working_inv()
2226
 
        rev_history = self.branch.revision_history()
2227
 
        # to_read is a stack holding the revisions we still need to process;
2228
 
        # appending to it adds new highest-priority revisions
2229
 
        self.known_revisions = set(rev_history)
2230
 
        self.to_read = rev_history[-1:]
2231
 
        while self.to_read:
2232
 
            rev_id = self.to_read.pop()
2233
 
            if (rev_id not in self.revisions
2234
 
                and rev_id not in self.absent_revisions):
2235
 
                self._load_one_rev(rev_id)
2236
 
        self.pb.clear()
2237
 
        to_import = self._make_order()
2238
 
        for i, rev_id in enumerate(to_import):
2239
 
            self.pb.update('converting revision', i, len(to_import))
2240
 
            self._convert_one_rev(rev_id)
2241
 
        self.pb.clear()
2242
 
        self._write_all_weaves()
2243
 
        self._write_all_revs()
2244
 
        ui.ui_factory.note('upgraded to weaves:')
2245
 
        ui.ui_factory.note('  %6d revisions and inventories' % len(self.revisions))
2246
 
        ui.ui_factory.note('  %6d revisions not present' % len(self.absent_revisions))
2247
 
        ui.ui_factory.note('  %6d texts' % self.text_count)
2248
 
        self._cleanup_spare_files_after_format4()
2249
 
        self.branch._transport.put_bytes(
2250
 
            'branch-format',
2251
 
            BzrDirFormat5().get_format_string(),
2252
 
            mode=self.bzrdir._get_file_mode())
2253
 
 
2254
 
    def _cleanup_spare_files_after_format4(self):
2255
 
        # FIXME working tree upgrade foo.
2256
 
        for n in 'merged-patches', 'pending-merged-patches':
2257
 
            try:
2258
 
                ## assert os.path.getsize(p) == 0
2259
 
                self.bzrdir.transport.delete(n)
2260
 
            except errors.NoSuchFile:
2261
 
                pass
2262
 
        self.bzrdir.transport.delete_tree('inventory-store')
2263
 
        self.bzrdir.transport.delete_tree('text-store')
2264
 
 
2265
 
    def _convert_working_inv(self):
2266
 
        inv = xml4.serializer_v4.read_inventory(
2267
 
                self.branch._transport.get('inventory'))
2268
 
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2269
 
        self.branch._transport.put_bytes('inventory', new_inv_xml,
2270
 
            mode=self.bzrdir._get_file_mode())
2271
 
 
2272
 
    def _write_all_weaves(self):
2273
 
        controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2274
 
        weave_transport = self.bzrdir.transport.clone('weaves')
2275
 
        weaves = WeaveStore(weave_transport, prefixed=False)
2276
 
        transaction = WriteTransaction()
2277
 
 
2278
 
        try:
2279
 
            i = 0
2280
 
            for file_id, file_weave in self.text_weaves.items():
2281
 
                self.pb.update('writing weave', i, len(self.text_weaves))
2282
 
                weaves._put_weave(file_id, file_weave, transaction)
2283
 
                i += 1
2284
 
            self.pb.update('inventory', 0, 1)
2285
 
            controlweaves._put_weave('inventory', self.inv_weave, transaction)
2286
 
            self.pb.update('inventory', 1, 1)
2287
 
        finally:
2288
 
            self.pb.clear()
2289
 
 
2290
 
    def _write_all_revs(self):
2291
 
        """Write all revisions out in new form."""
2292
 
        self.bzrdir.transport.delete_tree('revision-store')
2293
 
        self.bzrdir.transport.mkdir('revision-store')
2294
 
        revision_transport = self.bzrdir.transport.clone('revision-store')
2295
 
        # TODO permissions
2296
 
        from bzrlib.xml5 import serializer_v5
2297
 
        from bzrlib.repofmt.weaverepo import RevisionTextStore
2298
 
        revision_store = RevisionTextStore(revision_transport,
2299
 
            serializer_v5, False, versionedfile.PrefixMapper(),
2300
 
            lambda:True, lambda:True)
2301
 
        try:
2302
 
            for i, rev_id in enumerate(self.converted_revs):
2303
 
                self.pb.update('write revision', i, len(self.converted_revs))
2304
 
                text = serializer_v5.write_revision_to_string(
2305
 
                    self.revisions[rev_id])
2306
 
                key = (rev_id,)
2307
 
                revision_store.add_lines(key, None, osutils.split_lines(text))
2308
 
        finally:
2309
 
            self.pb.clear()
2310
 
 
2311
 
    def _load_one_rev(self, rev_id):
2312
 
        """Load a revision object into memory.
2313
 
 
2314
 
        Any parents not either loaded or abandoned get queued to be
2315
 
        loaded."""
2316
 
        self.pb.update('loading revision',
2317
 
                       len(self.revisions),
2318
 
                       len(self.known_revisions))
2319
 
        if not self.branch.repository.has_revision(rev_id):
2320
 
            self.pb.clear()
2321
 
            ui.ui_factory.note('revision {%s} not present in branch; '
2322
 
                         'will be converted as a ghost' %
2323
 
                         rev_id)
2324
 
            self.absent_revisions.add(rev_id)
2325
 
        else:
2326
 
            rev = self.branch.repository.get_revision(rev_id)
2327
 
            for parent_id in rev.parent_ids:
2328
 
                self.known_revisions.add(parent_id)
2329
 
                self.to_read.append(parent_id)
2330
 
            self.revisions[rev_id] = rev
2331
 
 
2332
 
    def _load_old_inventory(self, rev_id):
2333
 
        f = self.branch.repository.inventory_store.get(rev_id)
2334
 
        try:
2335
 
            old_inv_xml = f.read()
2336
 
        finally:
2337
 
            f.close()
2338
 
        inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2339
 
        inv.revision_id = rev_id
2340
 
        rev = self.revisions[rev_id]
2341
 
        return inv
2342
 
 
2343
 
    def _load_updated_inventory(self, rev_id):
2344
 
        inv_xml = self.inv_weave.get_text(rev_id)
2345
 
        inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2346
 
        return inv
2347
 
 
2348
 
    def _convert_one_rev(self, rev_id):
2349
 
        """Convert revision and all referenced objects to new format."""
2350
 
        rev = self.revisions[rev_id]
2351
 
        inv = self._load_old_inventory(rev_id)
2352
 
        present_parents = [p for p in rev.parent_ids
2353
 
                           if p not in self.absent_revisions]
2354
 
        self._convert_revision_contents(rev, inv, present_parents)
2355
 
        self._store_new_inv(rev, inv, present_parents)
2356
 
        self.converted_revs.add(rev_id)
2357
 
 
2358
 
    def _store_new_inv(self, rev, inv, present_parents):
2359
 
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2360
 
        new_inv_sha1 = sha_string(new_inv_xml)
2361
 
        self.inv_weave.add_lines(rev.revision_id,
2362
 
                                 present_parents,
2363
 
                                 new_inv_xml.splitlines(True))
2364
 
        rev.inventory_sha1 = new_inv_sha1
2365
 
 
2366
 
    def _convert_revision_contents(self, rev, inv, present_parents):
2367
 
        """Convert all the files within a revision.
2368
 
 
2369
 
        Also upgrade the inventory to refer to the text revision ids."""
2370
 
        rev_id = rev.revision_id
2371
 
        mutter('converting texts of revision {%s}',
2372
 
               rev_id)
2373
 
        parent_invs = map(self._load_updated_inventory, present_parents)
2374
 
        entries = inv.iter_entries()
2375
 
        entries.next()
2376
 
        for path, ie in entries:
2377
 
            self._convert_file_version(rev, ie, parent_invs)
2378
 
 
2379
 
    def _convert_file_version(self, rev, ie, parent_invs):
2380
 
        """Convert one version of one file.
2381
 
 
2382
 
        The file needs to be added into the weave if it is a merge
2383
 
        of >=2 parents or if it's changed from its parent.
2384
 
        """
2385
 
        file_id = ie.file_id
2386
 
        rev_id = rev.revision_id
2387
 
        w = self.text_weaves.get(file_id)
2388
 
        if w is None:
2389
 
            w = Weave(file_id)
2390
 
            self.text_weaves[file_id] = w
2391
 
        text_changed = False
2392
 
        parent_candiate_entries = ie.parent_candidates(parent_invs)
2393
 
        heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2394
 
        # XXX: Note that this is unordered - and this is tolerable because
2395
 
        # the previous code was also unordered.
2396
 
        previous_entries = dict((head, parent_candiate_entries[head]) for head
2397
 
            in heads)
2398
 
        self.snapshot_ie(previous_entries, ie, w, rev_id)
2399
 
 
2400
 
    def get_parent_map(self, revision_ids):
2401
 
        """See graph.StackedParentsProvider.get_parent_map"""
2402
 
        return dict((revision_id, self.revisions[revision_id])
2403
 
                    for revision_id in revision_ids
2404
 
                     if revision_id in self.revisions)
2405
 
 
2406
 
    def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2407
 
        # TODO: convert this logic, which is ~= snapshot to
2408
 
        # a call to:. This needs the path figured out. rather than a work_tree
2409
 
        # a v4 revision_tree can be given, or something that looks enough like
2410
 
        # one to give the file content to the entry if it needs it.
2411
 
        # and we need something that looks like a weave store for snapshot to
2412
 
        # save against.
2413
 
        #ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2414
 
        if len(previous_revisions) == 1:
2415
 
            previous_ie = previous_revisions.values()[0]
2416
 
            if ie._unchanged(previous_ie):
2417
 
                ie.revision = previous_ie.revision
2418
 
                return
2419
 
        if ie.has_text():
2420
 
            f = self.branch.repository._text_store.get(ie.text_id)
2421
 
            try:
2422
 
                file_lines = f.readlines()
2423
 
            finally:
2424
 
                f.close()
2425
 
            w.add_lines(rev_id, previous_revisions, file_lines)
2426
 
            self.text_count += 1
2427
 
        else:
2428
 
            w.add_lines(rev_id, previous_revisions, [])
2429
 
        ie.revision = rev_id
2430
 
 
2431
 
    def _make_order(self):
2432
 
        """Return a suitable order for importing revisions.
2433
 
 
2434
 
        The order must be such that an revision is imported after all
2435
 
        its (present) parents.
2436
 
        """
2437
 
        todo = set(self.revisions.keys())
2438
 
        done = self.absent_revisions.copy()
2439
 
        order = []
2440
 
        while todo:
2441
 
            # scan through looking for a revision whose parents
2442
 
            # are all done
2443
 
            for rev_id in sorted(list(todo)):
2444
 
                rev = self.revisions[rev_id]
2445
 
                parent_ids = set(rev.parent_ids)
2446
 
                if parent_ids.issubset(done):
2447
 
                    # can take this one now
2448
 
                    order.append(rev_id)
2449
 
                    todo.remove(rev_id)
2450
 
                    done.add(rev_id)
2451
 
        return order
2452
 
 
2453
 
 
2454
 
class ConvertBzrDir5To6(Converter):
2455
 
    """Converts format 5 bzr dirs to format 6."""
2456
 
 
2457
 
    def convert(self, to_convert, pb):
2458
 
        """See Converter.convert()."""
2459
 
        self.bzrdir = to_convert
2460
 
        pb = ui.ui_factory.nested_progress_bar()
2461
 
        try:
2462
 
            ui.ui_factory.note('starting upgrade from format 5 to 6')
2463
 
            self._convert_to_prefixed()
2464
 
            return BzrDir.open(self.bzrdir.user_url)
2465
 
        finally:
2466
 
            pb.finished()
2467
 
 
2468
 
    def _convert_to_prefixed(self):
2469
 
        from bzrlib.store import TransportStore
2470
 
        self.bzrdir.transport.delete('branch-format')
2471
 
        for store_name in ["weaves", "revision-store"]:
2472
 
            ui.ui_factory.note("adding prefixes to %s" % store_name)
2473
 
            store_transport = self.bzrdir.transport.clone(store_name)
2474
 
            store = TransportStore(store_transport, prefixed=True)
2475
 
            for urlfilename in store_transport.list_dir('.'):
2476
 
                filename = urlutils.unescape(urlfilename)
2477
 
                if (filename.endswith(".weave") or
2478
 
                    filename.endswith(".gz") or
2479
 
                    filename.endswith(".sig")):
2480
 
                    file_id, suffix = os.path.splitext(filename)
2481
 
                else:
2482
 
                    file_id = filename
2483
 
                    suffix = ''
2484
 
                new_name = store._mapper.map((file_id,)) + suffix
2485
 
                # FIXME keep track of the dirs made RBC 20060121
2486
 
                try:
2487
 
                    store_transport.move(filename, new_name)
2488
 
                except errors.NoSuchFile: # catches missing dirs strangely enough
2489
 
                    store_transport.mkdir(osutils.dirname(new_name))
2490
 
                    store_transport.move(filename, new_name)
2491
 
        self.bzrdir.transport.put_bytes(
2492
 
            'branch-format',
2493
 
            BzrDirFormat6().get_format_string(),
2494
 
            mode=self.bzrdir._get_file_mode())
2495
 
 
2496
 
 
2497
 
class ConvertBzrDir6ToMeta(Converter):
2498
 
    """Converts format 6 bzr dirs to metadirs."""
2499
 
 
2500
 
    def convert(self, to_convert, pb):
2501
 
        """See Converter.convert()."""
2502
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat7
2503
 
        from bzrlib.branch import BzrBranchFormat5
2504
 
        self.bzrdir = to_convert
2505
 
        self.pb = ui.ui_factory.nested_progress_bar()
2506
 
        self.count = 0
2507
 
        self.total = 20 # the steps we know about
2508
 
        self.garbage_inventories = []
2509
 
        self.dir_mode = self.bzrdir._get_dir_mode()
2510
 
        self.file_mode = self.bzrdir._get_file_mode()
2511
 
 
2512
 
        ui.ui_factory.note('starting upgrade from format 6 to metadir')
2513
 
        self.bzrdir.transport.put_bytes(
2514
 
                'branch-format',
2515
 
                "Converting to format 6",
2516
 
                mode=self.file_mode)
2517
 
        # its faster to move specific files around than to open and use the apis...
2518
 
        # first off, nuke ancestry.weave, it was never used.
2519
 
        try:
2520
 
            self.step('Removing ancestry.weave')
2521
 
            self.bzrdir.transport.delete('ancestry.weave')
2522
 
        except errors.NoSuchFile:
2523
 
            pass
2524
 
        # find out whats there
2525
 
        self.step('Finding branch files')
2526
 
        last_revision = self.bzrdir.open_branch().last_revision()
2527
 
        bzrcontents = self.bzrdir.transport.list_dir('.')
2528
 
        for name in bzrcontents:
2529
 
            if name.startswith('basis-inventory.'):
2530
 
                self.garbage_inventories.append(name)
2531
 
        # create new directories for repository, working tree and branch
2532
 
        repository_names = [('inventory.weave', True),
2533
 
                            ('revision-store', True),
2534
 
                            ('weaves', True)]
2535
 
        self.step('Upgrading repository  ')
2536
 
        self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2537
 
        self.make_lock('repository')
2538
 
        # we hard code the formats here because we are converting into
2539
 
        # the meta format. The meta format upgrader can take this to a
2540
 
        # future format within each component.
2541
 
        self.put_format('repository', RepositoryFormat7())
2542
 
        for entry in repository_names:
2543
 
            self.move_entry('repository', entry)
2544
 
 
2545
 
        self.step('Upgrading branch      ')
2546
 
        self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2547
 
        self.make_lock('branch')
2548
 
        self.put_format('branch', BzrBranchFormat5())
2549
 
        branch_files = [('revision-history', True),
2550
 
                        ('branch-name', True),
2551
 
                        ('parent', False)]
2552
 
        for entry in branch_files:
2553
 
            self.move_entry('branch', entry)
2554
 
 
2555
 
        checkout_files = [('pending-merges', True),
2556
 
                          ('inventory', True),
2557
 
                          ('stat-cache', False)]
2558
 
        # If a mandatory checkout file is not present, the branch does not have
2559
 
        # a functional checkout. Do not create a checkout in the converted
2560
 
        # branch.
2561
 
        for name, mandatory in checkout_files:
2562
 
            if mandatory and name not in bzrcontents:
2563
 
                has_checkout = False
2564
 
                break
2565
 
        else:
2566
 
            has_checkout = True
2567
 
        if not has_checkout:
2568
 
            ui.ui_factory.note('No working tree.')
2569
 
            # If some checkout files are there, we may as well get rid of them.
2570
 
            for name, mandatory in checkout_files:
2571
 
                if name in bzrcontents:
2572
 
                    self.bzrdir.transport.delete(name)
2573
 
        else:
2574
 
            from bzrlib.workingtree import WorkingTreeFormat3
2575
 
            self.step('Upgrading working tree')
2576
 
            self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2577
 
            self.make_lock('checkout')
2578
 
            self.put_format(
2579
 
                'checkout', WorkingTreeFormat3())
2580
 
            self.bzrdir.transport.delete_multi(
2581
 
                self.garbage_inventories, self.pb)
2582
 
            for entry in checkout_files:
2583
 
                self.move_entry('checkout', entry)
2584
 
            if last_revision is not None:
2585
 
                self.bzrdir.transport.put_bytes(
2586
 
                    'checkout/last-revision', last_revision)
2587
 
        self.bzrdir.transport.put_bytes(
2588
 
            'branch-format',
2589
 
            BzrDirMetaFormat1().get_format_string(),
2590
 
            mode=self.file_mode)
2591
 
        self.pb.finished()
2592
 
        return BzrDir.open(self.bzrdir.user_url)
2593
 
 
2594
 
    def make_lock(self, name):
2595
 
        """Make a lock for the new control dir name."""
2596
 
        self.step('Make %s lock' % name)
2597
 
        ld = lockdir.LockDir(self.bzrdir.transport,
2598
 
                             '%s/lock' % name,
2599
 
                             file_modebits=self.file_mode,
2600
 
                             dir_modebits=self.dir_mode)
2601
 
        ld.create()
2602
 
 
2603
 
    def move_entry(self, new_dir, entry):
2604
 
        """Move then entry name into new_dir."""
2605
 
        name = entry[0]
2606
 
        mandatory = entry[1]
2607
 
        self.step('Moving %s' % name)
2608
 
        try:
2609
 
            self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2610
 
        except errors.NoSuchFile:
2611
 
            if mandatory:
2612
 
                raise
2613
 
 
2614
 
    def put_format(self, dirname, format):
2615
 
        self.bzrdir.transport.put_bytes('%s/format' % dirname,
2616
 
            format.get_format_string(),
2617
 
            self.file_mode)
2618
 
 
2619
 
 
2620
1686
class ConvertMetaToMeta(Converter):
2621
1687
    """Converts the components of metadirs."""
2622
1688
 
2703
1769
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2704
1770
    """Format representing bzrdirs accessed via a smart server"""
2705
1771
 
 
1772
    supports_workingtrees = False
 
1773
 
2706
1774
    def __init__(self):
2707
1775
        BzrDirMetaFormat1.__init__(self)
2708
1776
        # XXX: It's a bit ugly that the network name is here, because we'd
2717
1785
 
2718
1786
    def get_format_description(self):
2719
1787
        if self._network_name:
2720
 
            real_format = network_format_registry.get(self._network_name)
 
1788
            real_format = controldir.network_format_registry.get(self._network_name)
2721
1789
            return 'Remote: ' + real_format.get_format_description()
2722
1790
        return 'bzr remote bzrdir'
2723
1791
 
3118
2186
    def _load(full_name):
3119
2187
        mod_name, factory_name = full_name.rsplit('.', 1)
3120
2188
        try:
3121
 
            mod = __import__(mod_name, globals(), locals(),
3122
 
                    [factory_name])
 
2189
            factory = pyutils.get_named_object(mod_name, factory_name)
3123
2190
        except ImportError, e:
3124
2191
            raise ImportError('failed to load %s: %s' % (full_name, e))
3125
 
        try:
3126
 
            factory = getattr(mod, factory_name)
3127
2192
        except AttributeError:
3128
2193
            raise AttributeError('no factory %s in module %r'
3129
 
                % (full_name, mod))
 
2194
                % (full_name, sys.modules[mod_name]))
3130
2195
        return factory()
3131
2196
 
3132
2197
    def helper():
3141
2206
    registry.register(key, helper, help, native, deprecated, hidden,
3142
2207
        experimental, alias)
3143
2208
 
3144
 
# The pre-0.8 formats have their repository format network name registered in
3145
 
# repository.py. MetaDir formats have their repository format network name
3146
 
# inferred from their disk format string.
3147
 
controldir.format_registry.register('weave', BzrDirFormat6,
3148
 
    'Pre-0.8 format.  Slower than knit and does not'
3149
 
    ' support checkouts or shared repositories.',
3150
 
    hidden=True,
3151
 
    deprecated=True)
3152
 
register_metadir(controldir.format_registry, 'metaweave',
3153
 
    'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3154
 
    'Transitional format in 0.8.  Slower than knit.',
3155
 
    branch_format='bzrlib.branch.BzrBranchFormat5',
3156
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3157
 
    hidden=True,
3158
 
    deprecated=True)
3159
2209
register_metadir(controldir.format_registry, 'knit',
3160
2210
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3161
2211
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
3276
2326
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3277
2327
    )
3278
2328
# The following un-numbered 'development' formats should always just be aliases.
3279
 
register_metadir(controldir.format_registry, 'development-rich-root',
3280
 
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3281
 
    help='Current development format. Supports rich roots. Can convert data '
3282
 
        'to and from rich-root-pack (and anything compatible with '
3283
 
        'rich-root-pack) format repositories. Repositories and branches in '
3284
 
        'this format can only be read by bzr.dev. Please read '
3285
 
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3286
 
        'before use.',
3287
 
    branch_format='bzrlib.branch.BzrBranchFormat7',
3288
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3289
 
    experimental=True,
3290
 
    alias=True,
3291
 
    hidden=True,
3292
 
    )
3293
2329
register_metadir(controldir.format_registry, 'development-subtree',
3294
 
    'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
 
2330
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2aSubtree',
3295
2331
    help='Current development format, subtree variant. Can convert data to and '
3296
2332
        'from pack-0.92-subtree (and anything compatible with '
3297
2333
        'pack-0.92-subtree) format repositories. Repositories and branches in '
3306
2342
                 # This current non-alias status is simply because we did not introduce a
3307
2343
                 # chk based subtree format.
3308
2344
    )
 
2345
register_metadir(controldir.format_registry, 'development5-subtree',
 
2346
    'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
 
2347
    help='Development format, subtree variant. Can convert data to and '
 
2348
        'from pack-0.92-subtree (and anything compatible with '
 
2349
        'pack-0.92-subtree) format repositories. Repositories and branches in '
 
2350
        'this format can only be read by bzr.dev. Please read '
 
2351
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
2352
        'before use.',
 
2353
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2354
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
2355
    experimental=True,
 
2356
    hidden=True,
 
2357
    alias=False,
 
2358
    )
3309
2359
 
3310
2360
# And the development formats above will have aliased one of the following:
3311
 
register_metadir(controldir.format_registry, 'development6-rich-root',
3312
 
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3313
 
    help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3314
 
        'Please read '
3315
 
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3316
 
        'before use.',
3317
 
    branch_format='bzrlib.branch.BzrBranchFormat7',
3318
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3319
 
    hidden=True,
3320
 
    experimental=True,
3321
 
    )
3322
 
 
3323
 
register_metadir(controldir.format_registry, 'development7-rich-root',
3324
 
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK2',
3325
 
    help='pack-1.9 with 255-way hashed CHK inv, bencode revision, group compress, '
3326
 
        'rich roots. Please read '
3327
 
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3328
 
        'before use.',
3329
 
    branch_format='bzrlib.branch.BzrBranchFormat7',
3330
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3331
 
    hidden=True,
3332
 
    experimental=True,
3333
 
    )
3334
 
 
 
2361
 
 
2362
# Finally, the current format.
3335
2363
register_metadir(controldir.format_registry, '2a',
3336
2364
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3337
2365
    help='First format for bzr 2.0 series.\n'
3341
2369
        # 'rich roots. Supported by bzr 1.16 and later.',
3342
2370
    branch_format='bzrlib.branch.BzrBranchFormat7',
3343
2371
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3344
 
    experimental=True,
 
2372
    experimental=False,
3345
2373
    )
3346
2374
 
3347
2375
# The following format should be an alias for the rich root equivalent 
3355
2383
    help='Same as 2a.')
3356
2384
 
3357
2385
# The current format that is made on 'bzr init'.
3358
 
controldir.format_registry.set_default('2a')
 
2386
format_name = config.GlobalConfig().get_user_option('default_format')
 
2387
if format_name is None:
 
2388
    controldir.format_registry.set_default('2a')
 
2389
else:
 
2390
    controldir.format_registry.set_default(format_name)
3359
2391
 
3360
2392
# XXX 2010-08-20 JRV: There is still a lot of code relying on
3361
2393
# bzrlib.bzrdir.format_registry existing. When BzrDir.create/BzrDir.open/etc