~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: 2011-03-11 20:21:17 UTC
  • mfrom: (5712.3.23 lazy-bzrdir)
  • Revision ID: pqm@pqm.ubuntu.com-20110311202117-tvicdu07o2x7jh8b
(jelmer) Add Prober.known_formats() in favour of
 BzrDirFormat.register_format() and ControlDirFormat.register_format().
 (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
    xml5,
60
60
    )
61
61
from bzrlib.repofmt import pack_repo
62
 
from bzrlib.smart.client import _SmartClient
63
62
from bzrlib.store.versioned import VersionedFileStore
64
63
from bzrlib.transactions import WriteTransaction
65
64
from bzrlib.transport import (
80
79
 
81
80
from bzrlib import (
82
81
    hooks,
 
82
    registry,
83
83
    )
84
84
from bzrlib.symbol_versioning import (
85
85
    deprecated_in,
1473
1473
class BzrProber(controldir.Prober):
1474
1474
    """Prober for formats that use a .bzr/ control directory."""
1475
1475
 
1476
 
    _formats = {}
 
1476
    formats = registry.FormatRegistry(controldir.network_format_registry)
1477
1477
    """The known .bzr formats."""
1478
1478
 
1479
1479
    @classmethod
 
1480
    @deprecated_method(deprecated_in((2, 4, 0)))
1480
1481
    def register_bzrdir_format(klass, format):
1481
 
        klass._formats[format.get_format_string()] = format
 
1482
        klass.formats.register(format.get_format_string(), format)
1482
1483
 
1483
1484
    @classmethod
 
1485
    @deprecated_method(deprecated_in((2, 4, 0)))
1484
1486
    def unregister_bzrdir_format(klass, format):
1485
 
        del klass._formats[format.get_format_string()]
 
1487
        klass.formats.remove(format.get_format_string())
1486
1488
 
1487
1489
    @classmethod
1488
1490
    def probe_transport(klass, transport):
1492
1494
        except errors.NoSuchFile:
1493
1495
            raise errors.NotBranchError(path=transport.base)
1494
1496
        try:
1495
 
            return klass._formats[format_string]
 
1497
            return klass.formats.get(format_string)
1496
1498
        except KeyError:
1497
1499
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1498
1500
 
 
1501
    @classmethod
 
1502
    def known_formats(cls):
 
1503
        result = set()
 
1504
        for name, format in cls.formats.iteritems():
 
1505
            if callable(format):
 
1506
                format = format()
 
1507
            result.add(format)
 
1508
        return result
 
1509
 
1499
1510
 
1500
1511
controldir.ControlDirFormat.register_prober(BzrProber)
1501
1512
 
1525
1536
                    raise errors.NotBranchError(path=transport.base)
1526
1537
                if server_version != '2':
1527
1538
                    raise errors.NotBranchError(path=transport.base)
 
1539
            from bzrlib.remote import RemoteBzrDirFormat
1528
1540
            return RemoteBzrDirFormat()
1529
1541
 
 
1542
    @classmethod
 
1543
    def known_formats(cls):
 
1544
        from bzrlib.remote import RemoteBzrDirFormat
 
1545
        return set([RemoteBzrDirFormat()])
 
1546
 
1530
1547
 
1531
1548
class BzrDirFormat(controldir.ControlDirFormat):
1532
1549
    """ControlDirFormat base class for .bzr/ directories.
1545
1562
    # _lock_class must be set in subclasses to the lock type, typ.
1546
1563
    # TransportLock or LockDir
1547
1564
 
1548
 
    def get_format_string(self):
 
1565
    @classmethod
 
1566
    def get_format_string(cls):
1549
1567
        """Return the ASCII format string that identifies this format."""
1550
1568
        raise NotImplementedError(self.get_format_string)
1551
1569
 
1563
1581
            # metadir1
1564
1582
            if type(self) != BzrDirMetaFormat1:
1565
1583
                return self._initialize_on_transport_vfs(transport)
 
1584
            from bzrlib.remote import RemoteBzrDirFormat
1566
1585
            remote_format = RemoteBzrDirFormat()
1567
1586
            self._supply_sub_formats_to(remote_format)
1568
1587
            return remote_format.initialize_on_transport(transport)
1606
1625
            except errors.NoSmartMedium:
1607
1626
                pass
1608
1627
            else:
 
1628
                from bzrlib.remote import RemoteBzrDirFormat
1609
1629
                # TODO: lookup the local format from a server hint.
1610
1630
                remote_dir_format = RemoteBzrDirFormat()
1611
1631
                remote_dir_format._network_name = self.network_name()
1726
1746
        """
1727
1747
        raise NotImplementedError(self._open)
1728
1748
 
1729
 
    @classmethod
1730
 
    def register_format(klass, format):
1731
 
        BzrProber.register_bzrdir_format(format)
1732
 
        # bzr native formats have a network name of their format string.
1733
 
        controldir.network_format_registry.register(format.get_format_string(), format.__class__)
1734
 
        controldir.ControlDirFormat.register_format(format)
1735
 
 
1736
1749
    def _supply_sub_formats_to(self, other_format):
1737
1750
        """Give other_format the same values for sub formats as this has.
1738
1751
 
1745
1758
        :return: None.
1746
1759
        """
1747
1760
 
1748
 
    @classmethod
1749
 
    def unregister_format(klass, format):
1750
 
        BzrProber.unregister_bzrdir_format(format)
1751
 
        controldir.ControlDirFormat.unregister_format(format)
1752
 
        controldir.network_format_registry.remove(format.get_format_string())
1753
 
 
1754
1761
 
1755
1762
class BzrDirFormat4(BzrDirFormat):
1756
1763
    """Bzr dir format 4.
1769
1776
 
1770
1777
    fixed_components = True
1771
1778
 
1772
 
    def get_format_string(self):
 
1779
    @classmethod
 
1780
    def get_format_string(cls):
1773
1781
        """See BzrDirFormat.get_format_string()."""
1774
1782
        return "Bazaar-NG branch, format 0.0.4\n"
1775
1783
 
1849
1857
 
1850
1858
    _lock_class = lockable_files.TransportLock
1851
1859
 
1852
 
    def get_format_string(self):
 
1860
    @classmethod
 
1861
    def get_format_string(cls):
1853
1862
        """See BzrDirFormat.get_format_string()."""
1854
1863
        return "Bazaar-NG branch, format 5\n"
1855
1864
 
1910
1919
 
1911
1920
    _lock_class = lockable_files.TransportLock
1912
1921
 
1913
 
    def get_format_string(self):
 
1922
    @classmethod
 
1923
    def get_format_string(cls):
1914
1924
        """See BzrDirFormat.get_format_string()."""
1915
1925
        return "Bazaar-NG branch, format 6\n"
1916
1926
 
2102
2112
            raise NotImplementedError(self.get_converter)
2103
2113
        return ConvertMetaToMeta(format)
2104
2114
 
2105
 
    def get_format_string(self):
 
2115
    @classmethod
 
2116
    def get_format_string(cls):
2106
2117
        """See BzrDirFormat.get_format_string()."""
2107
2118
        return "Bazaar-NG meta directory, format 1\n"
2108
2119
 
2170
2181
 
2171
2182
 
2172
2183
# Register bzr formats
2173
 
BzrDirFormat.register_format(BzrDirFormat4())
2174
 
BzrDirFormat.register_format(BzrDirFormat5())
2175
 
BzrDirFormat.register_format(BzrDirFormat6())
2176
 
__default_format = BzrDirMetaFormat1()
2177
 
BzrDirFormat.register_format(__default_format)
2178
 
controldir.ControlDirFormat._default_format = __default_format
 
2184
BzrProber.formats.register(BzrDirFormat4.get_format_string(), BzrDirFormat4())
 
2185
BzrProber.formats.register(BzrDirFormat5.get_format_string(), BzrDirFormat5())
 
2186
BzrProber.formats.register(BzrDirFormat6.get_format_string(), BzrDirFormat6())
 
2187
BzrProber.formats.register(BzrDirMetaFormat1.get_format_string(),
 
2188
    BzrDirMetaFormat1)
 
2189
controldir.ControlDirFormat._default_format = BzrDirMetaFormat1()
2179
2190
 
2180
2191
 
2181
2192
class ConvertBzrDir4To5(controldir.Converter):
2695
2706
        return to_convert
2696
2707
 
2697
2708
 
2698
 
# This is not in remote.py because it's relatively small, and needs to be
2699
 
# registered. Putting it in remote.py creates a circular import problem.
2700
 
# we can make it a lazy object if the control formats is turned into something
2701
 
# like a registry.
2702
 
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2703
 
    """Format representing bzrdirs accessed via a smart server"""
2704
 
 
2705
 
    supports_workingtrees = False
2706
 
 
2707
 
    def __init__(self):
2708
 
        BzrDirMetaFormat1.__init__(self)
2709
 
        # XXX: It's a bit ugly that the network name is here, because we'd
2710
 
        # like to believe that format objects are stateless or at least
2711
 
        # immutable,  However, we do at least avoid mutating the name after
2712
 
        # it's returned.  See <https://bugs.launchpad.net/bzr/+bug/504102>
2713
 
        self._network_name = None
2714
 
 
2715
 
    def __repr__(self):
2716
 
        return "%s(_network_name=%r)" % (self.__class__.__name__,
2717
 
            self._network_name)
2718
 
 
2719
 
    def get_format_description(self):
2720
 
        if self._network_name:
2721
 
            real_format = controldir.network_format_registry.get(self._network_name)
2722
 
            return 'Remote: ' + real_format.get_format_description()
2723
 
        return 'bzr remote bzrdir'
2724
 
 
2725
 
    def get_format_string(self):
2726
 
        raise NotImplementedError(self.get_format_string)
2727
 
 
2728
 
    def network_name(self):
2729
 
        if self._network_name:
2730
 
            return self._network_name
2731
 
        else:
2732
 
            raise AssertionError("No network name set.")
2733
 
 
2734
 
    def initialize_on_transport(self, transport):
2735
 
        try:
2736
 
            # hand off the request to the smart server
2737
 
            client_medium = transport.get_smart_medium()
2738
 
        except errors.NoSmartMedium:
2739
 
            # TODO: lookup the local format from a server hint.
2740
 
            local_dir_format = BzrDirMetaFormat1()
2741
 
            return local_dir_format.initialize_on_transport(transport)
2742
 
        client = _SmartClient(client_medium)
2743
 
        path = client.remote_path_from_transport(transport)
2744
 
        try:
2745
 
            response = client.call('BzrDirFormat.initialize', path)
2746
 
        except errors.ErrorFromSmartServer, err:
2747
 
            remote._translate_error(err, path=path)
2748
 
        if response[0] != 'ok':
2749
 
            raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2750
 
        format = RemoteBzrDirFormat()
2751
 
        self._supply_sub_formats_to(format)
2752
 
        return remote.RemoteBzrDir(transport, format)
2753
 
 
2754
 
    def parse_NoneTrueFalse(self, arg):
2755
 
        if not arg:
2756
 
            return None
2757
 
        if arg == 'False':
2758
 
            return False
2759
 
        if arg == 'True':
2760
 
            return True
2761
 
        raise AssertionError("invalid arg %r" % arg)
2762
 
 
2763
 
    def _serialize_NoneTrueFalse(self, arg):
2764
 
        if arg is False:
2765
 
            return 'False'
2766
 
        if arg:
2767
 
            return 'True'
2768
 
        return ''
2769
 
 
2770
 
    def _serialize_NoneString(self, arg):
2771
 
        return arg or ''
2772
 
 
2773
 
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
2774
 
        create_prefix=False, force_new_repo=False, stacked_on=None,
2775
 
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
2776
 
        shared_repo=False):
2777
 
        try:
2778
 
            # hand off the request to the smart server
2779
 
            client_medium = transport.get_smart_medium()
2780
 
        except errors.NoSmartMedium:
2781
 
            do_vfs = True
2782
 
        else:
2783
 
            # Decline to open it if the server doesn't support our required
2784
 
            # version (3) so that the VFS-based transport will do it.
2785
 
            if client_medium.should_probe():
2786
 
                try:
2787
 
                    server_version = client_medium.protocol_version()
2788
 
                    if server_version != '2':
2789
 
                        do_vfs = True
2790
 
                    else:
2791
 
                        do_vfs = False
2792
 
                except errors.SmartProtocolError:
2793
 
                    # Apparently there's no usable smart server there, even though
2794
 
                    # the medium supports the smart protocol.
2795
 
                    do_vfs = True
2796
 
            else:
2797
 
                do_vfs = False
2798
 
        if not do_vfs:
2799
 
            client = _SmartClient(client_medium)
2800
 
            path = client.remote_path_from_transport(transport)
2801
 
            if client_medium._is_remote_before((1, 16)):
2802
 
                do_vfs = True
2803
 
        if do_vfs:
2804
 
            # TODO: lookup the local format from a server hint.
2805
 
            local_dir_format = BzrDirMetaFormat1()
2806
 
            self._supply_sub_formats_to(local_dir_format)
2807
 
            return local_dir_format.initialize_on_transport_ex(transport,
2808
 
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2809
 
                force_new_repo=force_new_repo, stacked_on=stacked_on,
2810
 
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2811
 
                make_working_trees=make_working_trees, shared_repo=shared_repo,
2812
 
                vfs_only=True)
2813
 
        return self._initialize_on_transport_ex_rpc(client, path, transport,
2814
 
            use_existing_dir, create_prefix, force_new_repo, stacked_on,
2815
 
            stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
2816
 
 
2817
 
    def _initialize_on_transport_ex_rpc(self, client, path, transport,
2818
 
        use_existing_dir, create_prefix, force_new_repo, stacked_on,
2819
 
        stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
2820
 
        args = []
2821
 
        args.append(self._serialize_NoneTrueFalse(use_existing_dir))
2822
 
        args.append(self._serialize_NoneTrueFalse(create_prefix))
2823
 
        args.append(self._serialize_NoneTrueFalse(force_new_repo))
2824
 
        args.append(self._serialize_NoneString(stacked_on))
2825
 
        # stack_on_pwd is often/usually our transport
2826
 
        if stack_on_pwd:
2827
 
            try:
2828
 
                stack_on_pwd = transport.relpath(stack_on_pwd)
2829
 
                if not stack_on_pwd:
2830
 
                    stack_on_pwd = '.'
2831
 
            except errors.PathNotChild:
2832
 
                pass
2833
 
        args.append(self._serialize_NoneString(stack_on_pwd))
2834
 
        args.append(self._serialize_NoneString(repo_format_name))
2835
 
        args.append(self._serialize_NoneTrueFalse(make_working_trees))
2836
 
        args.append(self._serialize_NoneTrueFalse(shared_repo))
2837
 
        request_network_name = self._network_name or \
2838
 
            BzrDirFormat.get_default_format().network_name()
2839
 
        try:
2840
 
            response = client.call('BzrDirFormat.initialize_ex_1.16',
2841
 
                request_network_name, path, *args)
2842
 
        except errors.UnknownSmartMethod:
2843
 
            client._medium._remember_remote_is_before((1,16))
2844
 
            local_dir_format = BzrDirMetaFormat1()
2845
 
            self._supply_sub_formats_to(local_dir_format)
2846
 
            return local_dir_format.initialize_on_transport_ex(transport,
2847
 
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2848
 
                force_new_repo=force_new_repo, stacked_on=stacked_on,
2849
 
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2850
 
                make_working_trees=make_working_trees, shared_repo=shared_repo,
2851
 
                vfs_only=True)
2852
 
        except errors.ErrorFromSmartServer, err:
2853
 
            remote._translate_error(err, path=path)
2854
 
        repo_path = response[0]
2855
 
        bzrdir_name = response[6]
2856
 
        require_stacking = response[7]
2857
 
        require_stacking = self.parse_NoneTrueFalse(require_stacking)
2858
 
        format = RemoteBzrDirFormat()
2859
 
        format._network_name = bzrdir_name
2860
 
        self._supply_sub_formats_to(format)
2861
 
        bzrdir = remote.RemoteBzrDir(transport, format, _client=client)
2862
 
        if repo_path:
2863
 
            repo_format = remote.response_tuple_to_repo_format(response[1:])
2864
 
            if repo_path == '.':
2865
 
                repo_path = ''
2866
 
            if repo_path:
2867
 
                repo_bzrdir_format = RemoteBzrDirFormat()
2868
 
                repo_bzrdir_format._network_name = response[5]
2869
 
                repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
2870
 
                    repo_bzrdir_format)
2871
 
            else:
2872
 
                repo_bzr = bzrdir
2873
 
            final_stack = response[8] or None
2874
 
            final_stack_pwd = response[9] or None
2875
 
            if final_stack_pwd:
2876
 
                final_stack_pwd = urlutils.join(
2877
 
                    transport.base, final_stack_pwd)
2878
 
            remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
2879
 
            if len(response) > 10:
2880
 
                # Updated server verb that locks remotely.
2881
 
                repo_lock_token = response[10] or None
2882
 
                remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
2883
 
                if repo_lock_token:
2884
 
                    remote_repo.dont_leave_lock_in_place()
2885
 
            else:
2886
 
                remote_repo.lock_write()
2887
 
            policy = UseExistingRepository(remote_repo, final_stack,
2888
 
                final_stack_pwd, require_stacking)
2889
 
            policy.acquire_repository()
2890
 
        else:
2891
 
            remote_repo = None
2892
 
            policy = None
2893
 
        bzrdir._format.set_branch_format(self.get_branch_format())
2894
 
        if require_stacking:
2895
 
            # The repo has already been created, but we need to make sure that
2896
 
            # we'll make a stackable branch.
2897
 
            bzrdir._format.require_stacking(_skip_repo=True)
2898
 
        return remote_repo, bzrdir, require_stacking, policy
2899
 
 
2900
 
    def _open(self, transport):
2901
 
        return remote.RemoteBzrDir(transport, self)
2902
 
 
2903
 
    def __eq__(self, other):
2904
 
        if not isinstance(other, RemoteBzrDirFormat):
2905
 
            return False
2906
 
        return self.get_format_description() == other.get_format_description()
2907
 
 
2908
 
    def __return_repository_format(self):
2909
 
        # Always return a RemoteRepositoryFormat object, but if a specific bzr
2910
 
        # repository format has been asked for, tell the RemoteRepositoryFormat
2911
 
        # that it should use that for init() etc.
2912
 
        result = remote.RemoteRepositoryFormat()
2913
 
        custom_format = getattr(self, '_repository_format', None)
2914
 
        if custom_format:
2915
 
            if isinstance(custom_format, remote.RemoteRepositoryFormat):
2916
 
                return custom_format
2917
 
            else:
2918
 
                # We will use the custom format to create repositories over the
2919
 
                # wire; expose its details like rich_root_data for code to
2920
 
                # query
2921
 
                result._custom_format = custom_format
2922
 
        return result
2923
 
 
2924
 
    def get_branch_format(self):
2925
 
        result = BzrDirMetaFormat1.get_branch_format(self)
2926
 
        if not isinstance(result, remote.RemoteBranchFormat):
2927
 
            new_result = remote.RemoteBranchFormat()
2928
 
            new_result._custom_format = result
2929
 
            # cache the result
2930
 
            self.set_branch_format(new_result)
2931
 
            result = new_result
2932
 
        return result
2933
 
 
2934
 
    repository_format = property(__return_repository_format,
2935
 
        BzrDirMetaFormat1._set_repository_format) #.im_func)
2936
 
 
2937
 
 
2938
2709
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
2939
2710
 
2940
2711