~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-11 00:23:23 UTC
  • mfrom: (2070 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061011002323-82ba88c293d7caff
[merge] bzr.dev 2070

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 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
30
30
 
31
31
from cStringIO import StringIO
32
32
import os
33
 
import textwrap
34
33
 
35
34
from bzrlib.lazy_import import lazy_import
36
35
lazy_import(globals(), """
43
42
    errors,
44
43
    lockable_files,
45
44
    lockdir,
46
 
    registry,
47
45
    revision as _mod_revision,
48
 
    symbol_versioning,
49
46
    urlutils,
50
47
    xml4,
51
48
    xml5,
52
 
    workingtree,
53
 
    workingtree_4,
54
49
    )
55
50
from bzrlib.osutils import (
56
51
    safe_unicode,
65
60
from bzrlib.weave import Weave
66
61
""")
67
62
 
68
 
from bzrlib.trace import mutter, note
 
63
from bzrlib.trace import mutter
69
64
from bzrlib.transport.local import LocalTransport
70
65
 
71
66
 
206
201
 
207
202
    # TODO: Should take a Transport
208
203
    @classmethod
209
 
    def create(cls, base, format=None):
 
204
    def create(cls, base):
210
205
        """Create a new BzrDir at the url 'base'.
211
206
        
212
207
        This will call the current default formats initialize with base
213
208
        as the only parameter.
214
209
 
215
 
        :param format: If supplied, the format of branch to create.  If not
216
 
            supplied, the default is used.
 
210
        If you need a specific format, consider creating an instance
 
211
        of that and calling initialize().
217
212
        """
218
213
        if cls is not BzrDir:
219
 
            raise AssertionError("BzrDir.create always creates the default"
220
 
                " format, not one of %r" % cls)
 
214
            raise AssertionError("BzrDir.create always creates the default format, "
 
215
                    "not one of %r" % cls)
221
216
        head, tail = urlutils.split(base)
222
217
        if tail and tail != '.':
223
218
            t = get_transport(head)
225
220
                t.mkdir(tail)
226
221
            except errors.FileExists:
227
222
                pass
228
 
        if format is None:
229
 
            format = BzrDirFormat.get_default_format()
230
 
        return format.initialize(safe_unicode(base))
 
223
        return BzrDirFormat.get_default_format().initialize(safe_unicode(base))
231
224
 
232
225
    def create_branch(self):
233
226
        """Create a branch in this BzrDir.
238
231
        raise NotImplementedError(self.create_branch)
239
232
 
240
233
    @staticmethod
241
 
    def create_branch_and_repo(base, force_new_repo=False, format=None):
 
234
    def create_branch_and_repo(base, force_new_repo=False):
242
235
        """Create a new BzrDir, Branch and Repository at the url 'base'.
243
236
 
244
237
        This will use the current default BzrDirFormat, and use whatever 
251
244
        :param base: The URL to create the branch at.
252
245
        :param force_new_repo: If True a new repository is always created.
253
246
        """
254
 
        bzrdir = BzrDir.create(base, format)
 
247
        bzrdir = BzrDir.create(base)
255
248
        bzrdir._find_or_create_repository(force_new_repo)
256
249
        return bzrdir.create_branch()
257
250
 
295
288
            t = get_transport(safe_unicode(base))
296
289
            if not isinstance(t, LocalTransport):
297
290
                raise errors.NotLocalUrl(base)
298
 
        bzrdir = BzrDir.create(base, format)
 
291
        if format is None:
 
292
            bzrdir = BzrDir.create(base)
 
293
        else:
 
294
            bzrdir = format.initialize(base)
299
295
        repo = bzrdir._find_or_create_repository(force_new_repo)
300
296
        result = bzrdir.create_branch()
301
297
        if force_new_tree or (repo.make_working_trees() and 
307
303
        return result
308
304
        
309
305
    @staticmethod
310
 
    def create_repository(base, shared=False, format=None):
 
306
    def create_repository(base, shared=False):
311
307
        """Create a new BzrDir and Repository at the url 'base'.
312
308
 
313
 
        If no format is supplied, this will default to the current default
314
 
        BzrDirFormat by default, and use whatever repository format that that
315
 
        uses for bzrdirformat.create_repository.
 
309
        This will use the current default BzrDirFormat, and use whatever 
 
310
        repository format that that uses for bzrdirformat.create_repository.
316
311
 
317
312
        :param shared: Create a shared repository rather than a standalone
318
313
                       repository.
322
317
        it should take no parameters and construct whatever repository format
323
318
        that child class desires.
324
319
        """
325
 
        bzrdir = BzrDir.create(base, format)
 
320
        bzrdir = BzrDir.create(base)
326
321
        return bzrdir.create_repository(shared)
327
322
 
328
323
    @staticmethod
329
 
    def create_standalone_workingtree(base, format=None):
 
324
    def create_standalone_workingtree(base):
330
325
        """Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
331
326
 
332
327
        'base' must be a local path or a file:// url.
341
336
        if not isinstance(t, LocalTransport):
342
337
            raise errors.NotLocalUrl(base)
343
338
        bzrdir = BzrDir.create_branch_and_repo(safe_unicode(base),
344
 
                                               force_new_repo=True,
345
 
                                               format=format).bzrdir
 
339
                                               force_new_repo=True).bzrdir
346
340
        return bzrdir.create_workingtree()
347
341
 
348
342
    def create_workingtree(self, revision_id=None):
352
346
        """
353
347
        raise NotImplementedError(self.create_workingtree)
354
348
 
355
 
    def retire_bzrdir(self):
356
 
        """Permanently disable the bzrdir.
357
 
 
358
 
        This is done by renaming it to give the user some ability to recover
359
 
        if there was a problem.
360
 
 
361
 
        This will have horrible consequences if anyone has anything locked or
362
 
        in use.
363
 
        """
364
 
        for i in xrange(10000):
365
 
            try:
366
 
                to_path = '.bzr.retired.%d' % i
367
 
                self.root_transport.rename('.bzr', to_path)
368
 
                note("renamed %s to %s"
369
 
                    % (self.root_transport.abspath('.bzr'), to_path))
370
 
                break
371
 
            except (errors.TransportError, IOError, errors.PathError):
372
 
                pass
373
 
 
374
349
    def destroy_workingtree(self):
375
350
        """Destroy the working tree at this BzrDir.
376
351
 
453
428
        """Get the transport for use by workingtree format in this BzrDir.
454
429
 
455
430
        Note that bzr dirs that do not support format strings will raise
456
 
        IncompatibleFormat if the workingtree format they are given has a
457
 
        format string, and vice versa.
 
431
        IncompatibleFormat if the workingtree format they are given has
 
432
        a format string, and vice versa.
458
433
 
459
434
        If workingtree_format is None, the transport is returned with no 
460
435
        checking. if it is not None, then the returned transport is
578
553
                raise errors.NotBranchError(path=url)
579
554
            a_transport = new_t
580
555
 
581
 
    @classmethod
582
 
    def open_containing_tree_or_branch(klass, location):
583
 
        """Return the branch and working tree contained by a location.
584
 
 
585
 
        Returns (tree, branch, relpath).
586
 
        If there is no tree at containing the location, tree will be None.
587
 
        If there is no branch containing the location, an exception will be
588
 
        raised
589
 
        relpath is the portion of the path that is contained by the branch.
590
 
        """
591
 
        bzrdir, relpath = klass.open_containing(location)
592
 
        try:
593
 
            tree = bzrdir.open_workingtree()
594
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
595
 
            tree = None
596
 
            branch = bzrdir.open_branch()
597
 
        else:
598
 
            branch = tree.branch
599
 
        return tree, branch, relpath
600
 
 
601
556
    def open_repository(self, _unsupported=False):
602
557
        """Open the repository object at this BzrDir if one is present.
603
558
 
646
601
        except errors.NoWorkingTree:
647
602
            return False
648
603
 
649
 
    def _cloning_metadir(self, basis=None):
 
604
    def cloning_metadir(self, basis=None):
 
605
        """Produce a metadir suitable for cloning with"""
650
606
        def related_repository(bzrdir):
651
607
            try:
652
608
                branch = bzrdir.open_branch()
664
620
                source_repository = related_repository(self)
665
621
            result_format.repository_format = source_repository._format
666
622
        except errors.NoRepositoryPresent:
667
 
            source_repository = None
668
 
        try:
669
 
            tree = self.open_workingtree()
670
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
671
 
            result_format.workingtree_format = None
672
 
        else:
673
 
            result_format.workingtree_format = tree._format.__class__()
674
 
        return result_format, source_repository
675
 
 
676
 
    def cloning_metadir(self, basis=None):
677
 
        """Produce a metadir suitable for cloning or sprouting with.
678
 
 
679
 
        These operations may produce workingtrees (yes, even though they're
680
 
        "cloning" something that doesn't have a tree, so a viable workingtree
681
 
        format must be selected.
682
 
        """
683
 
        format, repository = self._cloning_metadir()
684
 
        if format._workingtree_format is None:
685
 
            if repository is None:
686
 
                return format
687
 
            tree_format = repository._format._matchingbzrdir.workingtree_format
688
 
            format.workingtree_format = tree_format.__class__()
689
 
        return format
690
 
 
691
 
    def checkout_metadir(self):
692
 
        return self.cloning_metadir()
693
 
 
694
 
    def sprout(self, url, revision_id=None, basis=None, force_new_repo=False,
695
 
               recurse='down'):
 
623
            pass
 
624
        return result_format
 
625
 
 
626
    def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
696
627
        """Create a copy of this bzrdir prepared for use as a new line of
697
628
        development.
698
629
 
754
685
        # TODO: jam 20060426 we probably need a test in here in the
755
686
        #       case that the newly sprouted branch is a remote one
756
687
        if result_repo is None or result_repo.make_working_trees():
757
 
            wt = result.create_workingtree()
758
 
            wt.lock_write()
759
 
            try:
760
 
                if wt.path2id('') is None:
761
 
                    try:
762
 
                        wt.set_root_id(self.open_workingtree.get_root_id())
763
 
                    except errors.NoWorkingTree:
764
 
                        pass
765
 
            finally:
766
 
                wt.unlock()
767
 
        else:
768
 
            wt = None
769
 
        if recurse == 'down':
770
 
            if wt is not None:
771
 
                basis = wt.basis_tree()
772
 
                basis.lock_read()
773
 
                subtrees = basis.iter_references()
774
 
                recurse_branch = wt.branch
775
 
            elif source_branch is not None:
776
 
                basis = source_branch.basis_tree()
777
 
                basis.lock_read()
778
 
                subtrees = basis.iter_references()
779
 
                recurse_branch = source_branch
780
 
            else:
781
 
                subtrees = []
782
 
                basis = None
783
 
            try:
784
 
                for path, file_id in subtrees:
785
 
                    target = urlutils.join(url, urlutils.escape(path))
786
 
                    sublocation = source_branch.reference_parent(file_id, path)
787
 
                    sublocation.bzrdir.sprout(target,
788
 
                        basis.get_reference_revision(file_id, path),
789
 
                        force_new_repo=force_new_repo, recurse=recurse)
790
 
            finally:
791
 
                if basis is not None:
792
 
                    basis.unlock()
 
688
            result.create_workingtree()
793
689
        return result
794
690
 
795
691
 
947
843
 
948
844
    def open_repository(self):
949
845
        """See BzrDir.open_repository."""
950
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat4
 
846
        from bzrlib.repository import RepositoryFormat4
951
847
        return RepositoryFormat4().open(self, _found=True)
952
848
 
953
849
 
959
855
 
960
856
    def open_repository(self):
961
857
        """See BzrDir.open_repository."""
962
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
 
858
        from bzrlib.repository import RepositoryFormat5
963
859
        return RepositoryFormat5().open(self, _found=True)
964
860
 
965
861
    def open_workingtree(self, _unsupported=False):
976
872
 
977
873
    def open_repository(self):
978
874
        """See BzrDir.open_repository."""
979
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
 
875
        from bzrlib.repository import RepositoryFormat6
980
876
        return RepositoryFormat6().open(self, _found=True)
981
877
 
982
878
    def open_workingtree(self, _unsupported=False):
1000
896
 
1001
897
    def create_branch(self):
1002
898
        """See BzrDir.create_branch."""
1003
 
        return self._format.get_branch_format().initialize(self)
 
899
        from bzrlib.branch import BranchFormat
 
900
        return BranchFormat.get_default_format().initialize(self)
1004
901
 
1005
902
    def create_repository(self, shared=False):
1006
903
        """See BzrDir.create_repository."""
1009
906
    def create_workingtree(self, revision_id=None):
1010
907
        """See BzrDir.create_workingtree."""
1011
908
        from bzrlib.workingtree import WorkingTreeFormat
1012
 
        return self._format.workingtree_format.initialize(self, revision_id)
 
909
        return WorkingTreeFormat.get_default_format().initialize(self, revision_id)
1013
910
 
1014
911
    def destroy_workingtree(self):
1015
912
        """See BzrDir.destroy_workingtree."""
1016
913
        wt = self.open_workingtree()
1017
914
        repository = wt.branch.repository
1018
 
        empty = repository.revision_tree(_mod_revision.NULL_REVISION)
 
915
        empty = repository.revision_tree(bzrlib.revision.NULL_REVISION)
1019
916
        wt.revert([], old_tree=empty)
1020
917
        self.destroy_workingtree_metadata()
1021
918
 
1085
982
                return True
1086
983
        except errors.NoRepositoryPresent:
1087
984
            pass
1088
 
        try:
1089
 
            if not isinstance(self.open_branch()._format,
1090
 
                              format.get_branch_format().__class__):
1091
 
                # the branch needs an upgrade.
1092
 
                return True
1093
 
        except errors.NotBranchError:
1094
 
            pass
1095
 
        try:
1096
 
            if not isinstance(self.open_workingtree()._format,
1097
 
                              format.workingtree_format.__class__):
1098
 
                # the workingtree needs an upgrade.
1099
 
                return True
1100
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
1101
 
            pass
 
985
        # currently there are no other possible conversions for meta1 formats.
1102
986
        return False
1103
987
 
1104
988
    def open_branch(self, unsupported=False):
1285
1169
        _found is a private parameter, do not use it.
1286
1170
        """
1287
1171
        if not _found:
1288
 
            found_format = BzrDirFormat.find_format(transport)
1289
 
            if not isinstance(found_format, self.__class__):
1290
 
                raise AssertionError("%s was asked to open %s, but it seems to need "
1291
 
                        "format %s" 
1292
 
                        % (self, transport, found_format))
 
1172
            assert isinstance(BzrDirFormat.find_format(transport),
 
1173
                              self.__class__)
1293
1174
        return self._open(transport)
1294
1175
 
1295
1176
    def _open(self, transport):
1316
1197
        klass._control_formats.append(format)
1317
1198
 
1318
1199
    @classmethod
1319
 
    @symbol_versioning.deprecated_method(symbol_versioning.zero_fourteen)
1320
1200
    def set_default_format(klass, format):
1321
 
        klass._set_default_format(format)
1322
 
 
1323
 
    @classmethod
1324
 
    def _set_default_format(klass, format):
1325
 
        """Set default format (for testing behavior of defaults only)"""
1326
1201
        klass._default_format = format
1327
1202
 
1328
1203
    def __str__(self):
1389
1264
 
1390
1265
    def __return_repository_format(self):
1391
1266
        """Circular import protection."""
1392
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat4
 
1267
        from bzrlib.repository import RepositoryFormat4
1393
1268
        return RepositoryFormat4()
1394
1269
    repository_format = property(__return_repository_format)
1395
1270
 
1429
1304
        Except when they are being cloned.
1430
1305
        """
1431
1306
        from bzrlib.branch import BzrBranchFormat4
1432
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
 
1307
        from bzrlib.repository import RepositoryFormat5
1433
1308
        from bzrlib.workingtree import WorkingTreeFormat2
1434
1309
        result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1435
1310
        RepositoryFormat5().initialize(result, _internal=True)
1449
1324
 
1450
1325
    def __return_repository_format(self):
1451
1326
        """Circular import protection."""
1452
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
 
1327
        from bzrlib.repository import RepositoryFormat5
1453
1328
        return RepositoryFormat5()
1454
1329
    repository_format = property(__return_repository_format)
1455
1330
 
1488
1363
        Except when they are being cloned.
1489
1364
        """
1490
1365
        from bzrlib.branch import BzrBranchFormat4
1491
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
 
1366
        from bzrlib.repository import RepositoryFormat6
1492
1367
        from bzrlib.workingtree import WorkingTreeFormat2
1493
1368
        result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1494
1369
        RepositoryFormat6().initialize(result, _internal=True)
1508
1383
 
1509
1384
    def __return_repository_format(self):
1510
1385
        """Circular import protection."""
1511
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
 
1386
        from bzrlib.repository import RepositoryFormat6
1512
1387
        return RepositoryFormat6()
1513
1388
    repository_format = property(__return_repository_format)
1514
1389
 
1526
1401
 
1527
1402
    _lock_class = lockdir.LockDir
1528
1403
 
1529
 
    def __init__(self):
1530
 
        self._workingtree_format = None
1531
 
        self._branch_format = None
1532
 
 
1533
 
    def __eq__(self, other):
1534
 
        if other.__class__ is not self.__class__:
1535
 
            return False
1536
 
        if other.repository_format != self.repository_format:
1537
 
            return False
1538
 
        if other.workingtree_format != self.workingtree_format:
1539
 
            return False
1540
 
        return True
1541
 
 
1542
 
    def __ne__(self, other):
1543
 
        return not self == other
1544
 
 
1545
 
    def get_branch_format(self):
1546
 
        if self._branch_format is None:
1547
 
            from bzrlib.branch import BranchFormat
1548
 
            self._branch_format = BranchFormat.get_default_format()
1549
 
        return self._branch_format
1550
 
 
1551
 
    def set_branch_format(self, format):
1552
 
        self._branch_format = format
1553
 
 
1554
1404
    def get_converter(self, format=None):
1555
1405
        """See BzrDirFormat.get_converter()."""
1556
1406
        if format is None:
1585
1435
 
1586
1436
    repository_format = property(__return_repository_format, __set_repository_format)
1587
1437
 
1588
 
    def __get_workingtree_format(self):
1589
 
        if self._workingtree_format is None:
1590
 
            from bzrlib.workingtree import WorkingTreeFormat
1591
 
            self._workingtree_format = WorkingTreeFormat.get_default_format()
1592
 
        return self._workingtree_format
1593
 
 
1594
 
    def __set_workingtree_format(self, wt_format):
1595
 
        self._workingtree_format = wt_format
1596
 
 
1597
 
    workingtree_format = property(__get_workingtree_format,
1598
 
                                  __set_workingtree_format)
1599
 
 
1600
1438
 
1601
1439
BzrDirFormat.register_format(BzrDirFormat4())
1602
1440
BzrDirFormat.register_format(BzrDirFormat5())
1603
1441
BzrDirFormat.register_format(BzrDirFormat6())
1604
1442
__default_format = BzrDirMetaFormat1()
1605
1443
BzrDirFormat.register_format(__default_format)
1606
 
BzrDirFormat._default_format = __default_format
 
1444
BzrDirFormat.set_default_format(__default_format)
1607
1445
 
1608
1446
 
1609
1447
class BzrDirTestProviderAdapter(object):
1863
1701
                                                  entry_vf=w)
1864
1702
        for old_revision in previous_entries:
1865
1703
                # if this fails, its a ghost ?
1866
 
                assert old_revision in self.converted_revs, \
1867
 
                    "Revision {%s} not in converted_revs" % old_revision
 
1704
                assert old_revision in self.converted_revs 
1868
1705
        self.snapshot_ie(previous_entries, ie, w, rev_id)
1869
1706
        del ie.text_id
1870
1707
        assert getattr(ie, 'revision', None) is not None
1957
1794
 
1958
1795
    def convert(self, to_convert, pb):
1959
1796
        """See Converter.convert()."""
1960
 
        from bzrlib.repofmt.weaverepo import RepositoryFormat7
1961
 
        from bzrlib.branch import BzrBranchFormat5
1962
1797
        self.bzrdir = to_convert
1963
1798
        self.pb = pb
1964
1799
        self.count = 0
1993
1828
        # we hard code the formats here because we are converting into
1994
1829
        # the meta format. The meta format upgrader can take this to a 
1995
1830
        # future format within each component.
1996
 
        self.put_format('repository', RepositoryFormat7())
 
1831
        self.put_format('repository', bzrlib.repository.RepositoryFormat7())
1997
1832
        for entry in repository_names:
1998
1833
            self.move_entry('repository', entry)
1999
1834
 
2000
1835
        self.step('Upgrading branch      ')
2001
1836
        self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2002
1837
        self.make_lock('branch')
2003
 
        self.put_format('branch', BzrBranchFormat5())
 
1838
        self.put_format('branch', bzrlib.branch.BzrBranchFormat5())
2004
1839
        branch_files = [('revision-history', True),
2005
1840
                        ('branch-name', True),
2006
1841
                        ('parent', False)]
2026
1861
                if name in bzrcontents:
2027
1862
                    self.bzrdir.transport.delete(name)
2028
1863
        else:
2029
 
            from bzrlib.workingtree import WorkingTreeFormat3
2030
1864
            self.step('Upgrading working tree')
2031
1865
            self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2032
1866
            self.make_lock('checkout')
2033
1867
            self.put_format(
2034
 
                'checkout', WorkingTreeFormat3())
 
1868
                'checkout', bzrlib.workingtree.WorkingTreeFormat3())
2035
1869
            self.bzrdir.transport.delete_multi(
2036
1870
                self.garbage_inventories, self.pb)
2037
1871
            for entry in checkout_files:
2094
1928
                self.pb.note('starting repository conversion')
2095
1929
                converter = CopyConverter(self.target_format.repository_format)
2096
1930
                converter.convert(repo, pb)
2097
 
        try:
2098
 
            branch = self.bzrdir.open_branch()
2099
 
        except errors.NotBranchError:
2100
 
            pass
2101
 
        else:
2102
 
            # TODO: conversions of Branch and Tree should be done by
2103
 
            # InterXFormat lookups
2104
 
            # Avoid circular imports
2105
 
            from bzrlib import branch as _mod_branch
2106
 
            if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2107
 
                self.target_format.get_branch_format().__class__ is
2108
 
                _mod_branch.BzrBranchFormat6):
2109
 
                branch_converter = _mod_branch.Converter5to6()
2110
 
                branch_converter.convert(branch)
2111
 
        try:
2112
 
            tree = self.bzrdir.open_workingtree()
2113
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
2114
 
            pass
2115
 
        else:
2116
 
            # TODO: conversions of Branch and Tree should be done by
2117
 
            # InterXFormat lookups
2118
 
            if (isinstance(tree, workingtree.WorkingTree3) and
2119
 
                not isinstance(tree, workingtree_4.WorkingTree4) and
2120
 
                isinstance(self.target_format.workingtree_format,
2121
 
                    workingtree_4.WorkingTreeFormat4)):
2122
 
                workingtree_4.Converter3to4().convert(tree)
2123
1931
        return to_convert
2124
 
 
2125
 
 
2126
 
class BzrDirFormatInfo(object):
2127
 
 
2128
 
    def __init__(self, native, deprecated):
2129
 
        self.deprecated = deprecated
2130
 
        self.native = native
2131
 
 
2132
 
 
2133
 
class BzrDirFormatRegistry(registry.Registry):
2134
 
    """Registry of user-selectable BzrDir subformats.
2135
 
    
2136
 
    Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2137
 
    e.g. BzrDirMeta1 with weave repository.  Also, it's more user-oriented.
2138
 
    """
2139
 
 
2140
 
    def register_metadir(self, key,
2141
 
             repository_format, help, native=True, deprecated=False,
2142
 
             branch_format=None,
2143
 
             tree_format=None):
2144
 
        """Register a metadir subformat.
2145
 
 
2146
 
        These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2147
 
        by the Repository format.
2148
 
 
2149
 
        :param repository_format: The fully-qualified repository format class
2150
 
            name as a string.
2151
 
        :param branch_format: Fully-qualified branch format class name as
2152
 
            a string.
2153
 
        :param tree_format: Fully-qualified tree format class name as
2154
 
            a string.
2155
 
        """
2156
 
        # This should be expanded to support setting WorkingTree and Branch
2157
 
        # formats, once BzrDirMetaFormat1 supports that.
2158
 
        def _load(full_name):
2159
 
            mod_name, factory_name = full_name.rsplit('.', 1)
2160
 
            try:
2161
 
                mod = __import__(mod_name, globals(), locals(),
2162
 
                        [factory_name])
2163
 
            except ImportError, e:
2164
 
                raise ImportError('failed to load %s: %s' % (full_name, e))
2165
 
            try:
2166
 
                factory = getattr(mod, factory_name)
2167
 
            except AttributeError:
2168
 
                raise AttributeError('no factory %s in module %r'
2169
 
                    % (full_name, mod))
2170
 
            return factory()
2171
 
 
2172
 
        def helper():
2173
 
            bd = BzrDirMetaFormat1()
2174
 
            if branch_format is not None:
2175
 
                bd.set_branch_format(_load(branch_format))
2176
 
            if tree_format is not None:
2177
 
                bd.workingtree_format = _load(tree_format)
2178
 
            if repository_format is not None:
2179
 
                bd.repository_format = _load(repository_format)
2180
 
            return bd
2181
 
        self.register(key, helper, help, native, deprecated)
2182
 
 
2183
 
    def register(self, key, factory, help, native=True, deprecated=False):
2184
 
        """Register a BzrDirFormat factory.
2185
 
        
2186
 
        The factory must be a callable that takes one parameter: the key.
2187
 
        It must produce an instance of the BzrDirFormat when called.
2188
 
 
2189
 
        This function mainly exists to prevent the info object from being
2190
 
        supplied directly.
2191
 
        """
2192
 
        registry.Registry.register(self, key, factory, help, 
2193
 
            BzrDirFormatInfo(native, deprecated))
2194
 
 
2195
 
    def register_lazy(self, key, module_name, member_name, help, native=True,
2196
 
                      deprecated=False):
2197
 
        registry.Registry.register_lazy(self, key, module_name, member_name, 
2198
 
            help, BzrDirFormatInfo(native, deprecated))
2199
 
 
2200
 
    def set_default(self, key):
2201
 
        """Set the 'default' key to be a clone of the supplied key.
2202
 
        
2203
 
        This method must be called once and only once.
2204
 
        """
2205
 
        registry.Registry.register(self, 'default', self.get(key), 
2206
 
            self.get_help(key), info=self.get_info(key))
2207
 
 
2208
 
    def set_default_repository(self, key):
2209
 
        """Set the FormatRegistry default and Repository default.
2210
 
        
2211
 
        This is a transitional method while Repository.set_default_format
2212
 
        is deprecated.
2213
 
        """
2214
 
        if 'default' in self:
2215
 
            self.remove('default')
2216
 
        self.set_default(key)
2217
 
        format = self.get('default')()
2218
 
        assert isinstance(format, BzrDirMetaFormat1)
2219
 
 
2220
 
    def make_bzrdir(self, key):
2221
 
        return self.get(key)()
2222
 
 
2223
 
    def help_topic(self, topic):
2224
 
        output = textwrap.dedent("""\
2225
 
            Bazaar directory formats
2226
 
            ------------------------
2227
 
 
2228
 
            These formats can be used for creating branches, working trees, and
2229
 
            repositories.
2230
 
 
2231
 
            """)
2232
 
        default_help = self.get_help('default')
2233
 
        help_pairs = []
2234
 
        for key in self.keys():
2235
 
            if key == 'default':
2236
 
                continue
2237
 
            help = self.get_help(key)
2238
 
            if help == default_help:
2239
 
                default_realkey = key
2240
 
            else:
2241
 
                help_pairs.append((key, help))
2242
 
 
2243
 
        def wrapped(key, help, info):
2244
 
            if info.native:
2245
 
                help = '(native) ' + help
2246
 
            return '  %s:\n%s\n\n' % (key, 
2247
 
                    textwrap.fill(help, initial_indent='    ', 
2248
 
                    subsequent_indent='    '))
2249
 
        output += wrapped('%s/default' % default_realkey, default_help,
2250
 
                          self.get_info('default'))
2251
 
        deprecated_pairs = []
2252
 
        for key, help in help_pairs:
2253
 
            info = self.get_info(key)
2254
 
            if info.deprecated:
2255
 
                deprecated_pairs.append((key, help))
2256
 
            else:
2257
 
                output += wrapped(key, help, info)
2258
 
        if len(deprecated_pairs) > 0:
2259
 
            output += "Deprecated formats\n------------------\n\n"
2260
 
            for key, help in deprecated_pairs:
2261
 
                info = self.get_info(key)
2262
 
                output += wrapped(key, help, info)
2263
 
 
2264
 
        return output
2265
 
 
2266
 
 
2267
 
format_registry = BzrDirFormatRegistry()
2268
 
format_registry.register('weave', BzrDirFormat6,
2269
 
    'Pre-0.8 format.  Slower than knit and does not'
2270
 
    ' support checkouts or shared repositories.',
2271
 
    deprecated=True)
2272
 
format_registry.register_metadir('knit',
2273
 
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2274
 
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
2275
 
    branch_format='bzrlib.branch.BzrBranchFormat5',
2276
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2277
 
format_registry.register_metadir('metaweave',
2278
 
    'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2279
 
    'Transitional format in 0.8.  Slower than knit.',
2280
 
    branch_format='bzrlib.branch.BzrBranchFormat5',
2281
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2282
 
    deprecated=True)
2283
 
format_registry.register_metadir('dirstate',
2284
 
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2285
 
    help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2286
 
        'above when accessed over the network.',
2287
 
    branch_format='bzrlib.branch.BzrBranchFormat5',
2288
 
    # this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
2289
 
    # directly from workingtree_4 triggers a circular import.
2290
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2291
 
    )
2292
 
format_registry.register_metadir('dirstate-with-subtree',
2293
 
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
2294
 
    help='New in 0.15: Fast local operations and improved scaling for '
2295
 
        'network operations. Additionally adds support for versioning nested '
2296
 
        'bzr branches. Incompatible with bzr < 0.15.',
2297
 
    branch_format='bzrlib.branch.BzrBranchFormat6',
2298
 
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2299
 
    )
2300
 
format_registry.set_default('dirstate')