~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-03-07 10:45:44 UTC
  • mfrom: (2321.1.2 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20070307104544-59e3e6358e4bdb29
(robertc) Merge dirstate and subtrees. (Robert Collins, Martin Pool, Aaaron Bentley, John A Meinel, James Westby)

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
    urlutils,
50
50
    xml4,
51
51
    xml5,
 
52
    workingtree,
 
53
    workingtree_4,
52
54
    )
53
55
from bzrlib.osutils import (
54
56
    safe_unicode,
63
65
from bzrlib.weave import Weave
64
66
""")
65
67
 
66
 
from bzrlib.trace import mutter
 
68
from bzrlib.trace import mutter, note
67
69
from bzrlib.transport.local import LocalTransport
68
70
 
69
71
 
350
352
        """
351
353
        raise NotImplementedError(self.create_workingtree)
352
354
 
 
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
 
353
374
    def destroy_workingtree(self):
354
375
        """Destroy the working tree at this BzrDir.
355
376
 
432
453
        """Get the transport for use by workingtree format in this BzrDir.
433
454
 
434
455
        Note that bzr dirs that do not support format strings will raise
435
 
        IncompatibleFormat if the workingtree format they are given has
436
 
        a format string, and vice versa.
 
456
        IncompatibleFormat if the workingtree format they are given has a
 
457
        format string, and vice versa.
437
458
 
438
459
        If workingtree_format is None, the transport is returned with no 
439
460
        checking. if it is not None, then the returned transport is
625
646
        except errors.NoWorkingTree:
626
647
            return False
627
648
 
628
 
    def cloning_metadir(self, basis=None):
629
 
        """Produce a metadir suitable for cloning with"""
 
649
    def _cloning_metadir(self, basis=None):
630
650
        def related_repository(bzrdir):
631
651
            try:
632
652
                branch = bzrdir.open_branch()
644
664
                source_repository = related_repository(self)
645
665
            result_format.repository_format = source_repository._format
646
666
        except errors.NoRepositoryPresent:
647
 
            pass
648
 
        return result_format
649
 
 
650
 
    def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
 
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'):
651
696
        """Create a copy of this bzrdir prepared for use as a new line of
652
697
        development.
653
698
 
710
755
        #       case that the newly sprouted branch is a remote one
711
756
        if result_repo is None or result_repo.make_working_trees():
712
757
            wt = result.create_workingtree()
713
 
            if wt.inventory.root is None:
714
 
                try:
715
 
                    wt.set_root_id(self.open_workingtree.get_root_id())
716
 
                except errors.NoWorkingTree:
717
 
                    pass
 
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()
718
793
        return result
719
794
 
720
795
 
934
1009
    def create_workingtree(self, revision_id=None):
935
1010
        """See BzrDir.create_workingtree."""
936
1011
        from bzrlib.workingtree import WorkingTreeFormat
937
 
        return WorkingTreeFormat.get_default_format().initialize(self, revision_id)
 
1012
        return self._format.workingtree_format.initialize(self, revision_id)
938
1013
 
939
1014
    def destroy_workingtree(self):
940
1015
        """See BzrDir.destroy_workingtree."""
1013
1088
        try:
1014
1089
            if not isinstance(self.open_branch()._format,
1015
1090
                              format.get_branch_format().__class__):
1016
 
                # the repository needs an upgrade.
 
1091
                # the branch needs an upgrade.
1017
1092
                return True
1018
1093
        except errors.NotBranchError:
1019
1094
            pass
1020
 
        # currently there are no other possible conversions for meta1 formats.
 
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
1021
1102
        return False
1022
1103
 
1023
1104
    def open_branch(self, unsupported=False):
1446
1527
    _lock_class = lockdir.LockDir
1447
1528
 
1448
1529
    def __init__(self):
 
1530
        self._workingtree_format = None
1449
1531
        self._branch_format = None
1450
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
 
1451
1545
    def get_branch_format(self):
1452
1546
        if self._branch_format is None:
1453
1547
            from bzrlib.branch import BranchFormat
1491
1585
 
1492
1586
    repository_format = property(__return_repository_format, __set_repository_format)
1493
1587
 
 
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
 
1494
1600
 
1495
1601
BzrDirFormat.register_format(BzrDirFormat4())
1496
1602
BzrDirFormat.register_format(BzrDirFormat5())
1993
2099
        except errors.NotBranchError:
1994
2100
            pass
1995
2101
        else:
 
2102
            # TODO: conversions of Branch and Tree should be done by
 
2103
            # InterXFormat lookups
1996
2104
            # Avoid circular imports
1997
2105
            from bzrlib import branch as _mod_branch
1998
2106
            if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2000
2108
                _mod_branch.BzrBranchFormat6):
2001
2109
                branch_converter = _mod_branch.Converter5to6()
2002
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)
2003
2123
        return to_convert
2004
2124
 
2005
2125
 
2017
2137
    e.g. BzrDirMeta1 with weave repository.  Also, it's more user-oriented.
2018
2138
    """
2019
2139
 
2020
 
    def register_metadir(self, key, repo, help, native=True, deprecated=False,
2021
 
                         branch_format=None):
 
2140
    def register_metadir(self, key,
 
2141
             repository_format, help, native=True, deprecated=False,
 
2142
             branch_format=None,
 
2143
             tree_format=None):
2022
2144
        """Register a metadir subformat.
2023
2145
 
2024
2146
        These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2025
2147
        by the Repository format.
2026
2148
 
2027
 
        :param repo: The fully-qualified repository format class name as a
2028
 
        string.
 
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.
2029
2155
        """
2030
2156
        # This should be expanded to support setting WorkingTree and Branch
2031
2157
        # formats, once BzrDirMetaFormat1 supports that.
2032
 
        def helper():
2033
 
            import bzrlib.branch
2034
 
            mod_name, repo_factory_name = repo.rsplit('.', 1)
 
2158
        def _load(full_name):
 
2159
            mod_name, factory_name = full_name.rsplit('.', 1)
2035
2160
            try:
2036
2161
                mod = __import__(mod_name, globals(), locals(),
2037
 
                        [repo_factory_name])
 
2162
                        [factory_name])
2038
2163
            except ImportError, e:
2039
 
                raise ImportError('failed to load repository %s: %s'
2040
 
                    % (repo, e))
 
2164
                raise ImportError('failed to load %s: %s' % (full_name, e))
2041
2165
            try:
2042
 
                repo_format_class = getattr(mod, repo_factory_name)
 
2166
                factory = getattr(mod, factory_name)
2043
2167
            except AttributeError:
2044
 
                raise AttributeError('no repository format %r in module %r' 
2045
 
                    % (repo, mod))
 
2168
                raise AttributeError('no factory %s in module %r'
 
2169
                    % (full_name, mod))
 
2170
            return factory()
 
2171
 
 
2172
        def helper():
2046
2173
            bd = BzrDirMetaFormat1()
2047
 
            bd.repository_format = repo_format_class()
2048
2174
            if branch_format is not None:
2049
 
                bd.set_branch_format(getattr(bzrlib.branch, branch_format)())
 
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)
2050
2180
            return bd
2051
2181
        self.register(key, helper, help, native, deprecated)
2052
2182
 
2141
2271
    deprecated=True)
2142
2272
format_registry.register_metadir('knit',
2143
2273
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2144
 
    'Format using knits.  Recommended.',
2145
 
    branch_format='BzrBranchFormat5')
2146
 
format_registry.set_default('knit')
 
2274
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
 
2275
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
2276
    tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2147
2277
format_registry.register_metadir('metaweave',
2148
2278
    'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2149
2279
    'Transitional format in 0.8.  Slower than knit.',
2150
 
    deprecated=True,
2151
 
    )
2152
 
format_registry.register_metadir('experimental-knit2',
2153
 
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit2',
2154
 
    'Experimental successor to knit.  Use at your own risk.',
2155
 
    branch_format='BzrBranchFormat5')
2156
 
format_registry.register_metadir('experimental-branch6',
 
2280
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
2281
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
 
2282
    deprecated=True)
 
2283
format_registry.register_metadir('dirstate',
2157
2284
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2158
 
    'Experimental successor to knit.  Use at your own risk.',
2159
 
    branch_format='BzrBranchFormat6')
 
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')