/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Vincent Ladeuil
  • Date: 2011-11-24 15:48:29 UTC
  • mfrom: (6289 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6337.
  • Revision ID: v.ladeuil+lp@free.fr-20111124154829-avowjpsxdl8yp2vz
merge trunk resolving conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
    NoSuchRevision,
41
41
    SmartProtocolError,
42
42
    )
 
43
from bzrlib.i18n import gettext
 
44
from bzrlib.inventory import Inventory
43
45
from bzrlib.lockable_files import LockableFiles
44
46
from bzrlib.smart import client, vfs, repository as smart_repo
45
47
from bzrlib.smart.client import _SmartClient
46
48
from bzrlib.revision import NULL_REVISION
 
49
from bzrlib.revisiontree import InventoryRevisionTree
47
50
from bzrlib.repository import RepositoryWriteLockResult, _LazyListJoin
48
51
from bzrlib.trace import mutter, note, warning
49
52
 
50
53
 
 
54
_DEFAULT_SEARCH_DEPTH = 100
 
55
 
 
56
 
51
57
class _RpcHelper(object):
52
58
    """Mixin class that helps with issuing RPCs."""
53
59
 
327
333
        _mod_bzrdir.BzrDirMetaFormat1._set_repository_format) #.im_func)
328
334
 
329
335
 
 
336
class RemoteControlStore(config.IniFileStore):
 
337
    """Control store which attempts to use HPSS calls to retrieve control store.
 
338
 
 
339
    Note that this is specific to bzr-based formats.
 
340
    """
 
341
 
 
342
    def __init__(self, bzrdir):
 
343
        super(RemoteControlStore, self).__init__()
 
344
        self.bzrdir = bzrdir
 
345
        self._real_store = None
 
346
 
 
347
    def lock_write(self, token=None):
 
348
        self._ensure_real()
 
349
        return self._real_store.lock_write(token)
 
350
 
 
351
    def unlock(self):
 
352
        self._ensure_real()
 
353
        return self._real_store.unlock()
 
354
 
 
355
    @needs_write_lock
 
356
    def save(self):
 
357
        # We need to be able to override the undecorated implementation
 
358
        self.save_without_locking()
 
359
 
 
360
    def save_without_locking(self):
 
361
        super(RemoteControlStore, self).save()
 
362
 
 
363
    def _ensure_real(self):
 
364
        self.bzrdir._ensure_real()
 
365
        if self._real_store is None:
 
366
            self._real_store = config.ControlStore(self.bzrdir)
 
367
 
 
368
    def external_url(self):
 
369
        return self.bzrdir.user_url
 
370
 
 
371
    def _load_content(self):
 
372
        medium = self.bzrdir._client._medium
 
373
        path = self.bzrdir._path_for_remote_call(self.bzrdir._client)
 
374
        try:
 
375
            response, handler = self.bzrdir._call_expecting_body(
 
376
                'BzrDir.get_config_file', path)
 
377
        except errors.UnknownSmartMethod:
 
378
            self._ensure_real()
 
379
            return self._real_store._load_content()
 
380
        if len(response) and response[0] != 'ok':
 
381
            raise errors.UnexpectedSmartServerResponse(response)
 
382
        return handler.read_body_bytes()
 
383
 
 
384
    def _save_content(self, content):
 
385
        # FIXME JRV 2011-11-22: Ideally this should use a
 
386
        # HPSS call too, but at the moment it is not possible
 
387
        # to write lock control directories.
 
388
        self._ensure_real()
 
389
        return self._real_store._save_content(content)
 
390
 
 
391
 
330
392
class RemoteBzrDir(_mod_bzrdir.BzrDir, _RpcHelper):
331
393
    """Control directory on a remote server, accessed via bzr:// or similar."""
332
394
 
480
542
 
481
543
    def destroy_repository(self):
482
544
        """See BzrDir.destroy_repository"""
483
 
        self._ensure_real()
484
 
        self._real_bzrdir.destroy_repository()
 
545
        path = self._path_for_remote_call(self._client)
 
546
        try:
 
547
            response = self._call('BzrDir.destroy_repository', path)
 
548
        except errors.UnknownSmartMethod:
 
549
            self._ensure_real()
 
550
            self._real_bzrdir.destroy_repository()
 
551
            return
 
552
        if response[0] != 'ok':
 
553
            raise SmartProtocolError('unexpected response code %s' % (response,))
485
554
 
486
 
    def create_branch(self, name=None, repository=None):
 
555
    def create_branch(self, name=None, repository=None,
 
556
                      append_revisions_only=None):
487
557
        # as per meta1 formats - just delegate to the format object which may
488
558
        # be parameterised.
489
559
        real_branch = self._format.get_branch_format().initialize(self,
490
 
            name=name, repository=repository)
 
560
            name=name, repository=repository,
 
561
            append_revisions_only=append_revisions_only)
491
562
        if not isinstance(real_branch, RemoteBranch):
492
563
            if not isinstance(repository, RemoteRepository):
493
564
                raise AssertionError(
657
728
 
658
729
    def has_workingtree(self):
659
730
        if self._has_working_tree is None:
660
 
            self._ensure_real()
661
 
            self._has_working_tree = self._real_bzrdir.has_workingtree()
 
731
            path = self._path_for_remote_call(self._client)
 
732
            try:
 
733
                response = self._call('BzrDir.has_workingtree', path)
 
734
            except errors.UnknownSmartMethod:
 
735
                self._ensure_real()
 
736
                self._has_working_tree = self._real_bzrdir.has_workingtree()
 
737
            else:
 
738
                if response[0] not in ('yes', 'no'):
 
739
                    raise SmartProtocolError('unexpected response code %s' % (response,))
 
740
                self._has_working_tree = (response[0] == 'yes')
662
741
        return self._has_working_tree
663
742
 
664
743
    def open_workingtree(self, recommend_upgrade=True):
669
748
 
670
749
    def _path_for_remote_call(self, client):
671
750
        """Return the path to be used for this bzrdir in a remote call."""
672
 
        return client.remote_path_from_transport(self.root_transport)
 
751
        return urlutils.split_segment_parameters_raw(
 
752
            client.remote_path_from_transport(self.root_transport))[0]
673
753
 
674
754
    def get_branch_transport(self, branch_format, name=None):
675
755
        self._ensure_real()
691
771
        """Upgrading of remote bzrdirs is not supported yet."""
692
772
        return False
693
773
 
694
 
    def clone(self, url, revision_id=None, force_new_repo=False,
695
 
              preserve_stacking=False):
696
 
        self._ensure_real()
697
 
        return self._real_bzrdir.clone(url, revision_id=revision_id,
698
 
            force_new_repo=force_new_repo, preserve_stacking=preserve_stacking)
699
 
 
700
774
    def _get_config(self):
701
775
        return RemoteBzrDirConfig(self)
702
776
 
 
777
    def _get_config_store(self):
 
778
        return RemoteControlStore(self)
 
779
 
703
780
 
704
781
class RemoteRepositoryFormat(vf_repository.VersionedFileRepositoryFormat):
705
782
    """Format for repositories accessed over a _SmartClient.
735
812
        self._supports_external_lookups = None
736
813
        self._supports_tree_reference = None
737
814
        self._supports_funky_characters = None
 
815
        self._supports_nesting_repositories = None
738
816
        self._rich_root_data = None
739
817
 
740
818
    def __repr__(self):
777
855
        return self._supports_funky_characters
778
856
 
779
857
    @property
 
858
    def supports_nesting_repositories(self):
 
859
        if self._supports_nesting_repositories is None:
 
860
            self._ensure_real()
 
861
            self._supports_nesting_repositories = \
 
862
                self._custom_format.supports_nesting_repositories
 
863
        return self._supports_nesting_repositories
 
864
 
 
865
    @property
780
866
    def supports_tree_reference(self):
781
867
        if self._supports_tree_reference is None:
782
868
            self._ensure_real()
1463
1549
            return t
1464
1550
        raise errors.UnexpectedSmartServerResponse(response)
1465
1551
 
 
1552
    @needs_read_lock
1466
1553
    def sprout(self, to_bzrdir, revision_id=None):
1467
 
        # TODO: Option to control what format is created?
1468
 
        self._ensure_real()
1469
 
        dest_repo = self._real_repository._format.initialize(to_bzrdir,
1470
 
                                                             shared=False)
 
1554
        """Create a descendent repository for new development.
 
1555
 
 
1556
        Unlike clone, this does not copy the settings of the repository.
 
1557
        """
 
1558
        dest_repo = self._create_sprouting_repo(to_bzrdir, shared=False)
1471
1559
        dest_repo.fetch(self, revision_id=revision_id)
1472
1560
        return dest_repo
1473
1561
 
 
1562
    def _create_sprouting_repo(self, a_bzrdir, shared):
 
1563
        if not isinstance(a_bzrdir._format, self.bzrdir._format.__class__):
 
1564
            # use target default format.
 
1565
            dest_repo = a_bzrdir.create_repository()
 
1566
        else:
 
1567
            # Most control formats need the repository to be specifically
 
1568
            # created, but on some old all-in-one formats it's not needed
 
1569
            try:
 
1570
                dest_repo = self._format.initialize(a_bzrdir, shared=shared)
 
1571
            except errors.UninitializableFormat:
 
1572
                dest_repo = a_bzrdir.open_repository()
 
1573
        return dest_repo
 
1574
 
1474
1575
    ### These methods are just thin shims to the VFS object for now.
1475
1576
 
 
1577
    @needs_read_lock
1476
1578
    def revision_tree(self, revision_id):
1477
 
        self._ensure_real()
1478
 
        return self._real_repository.revision_tree(revision_id)
 
1579
        revision_id = _mod_revision.ensure_null(revision_id)
 
1580
        if revision_id == _mod_revision.NULL_REVISION:
 
1581
            return InventoryRevisionTree(self,
 
1582
                Inventory(root_id=None), _mod_revision.NULL_REVISION)
 
1583
        else:
 
1584
            return list(self.revision_trees([revision_id]))[0]
1479
1585
 
1480
1586
    def get_serializer_format(self):
1481
1587
        self._ensure_real()
1559
1665
 
1560
1666
    @needs_read_lock
1561
1667
    def get_revision(self, revision_id):
1562
 
        self._ensure_real()
1563
 
        return self._real_repository.get_revision(revision_id)
 
1668
        return self.get_revisions([revision_id])[0]
1564
1669
 
1565
1670
    def get_transaction(self):
1566
1671
        self._ensure_real()
1568
1673
 
1569
1674
    @needs_read_lock
1570
1675
    def clone(self, a_bzrdir, revision_id=None):
1571
 
        self._ensure_real()
1572
 
        return self._real_repository.clone(a_bzrdir, revision_id=revision_id)
 
1676
        dest_repo = self._create_sprouting_repo(
 
1677
            a_bzrdir, shared=self.is_shared())
 
1678
        self.copy_content_into(dest_repo, revision_id)
 
1679
        return dest_repo
1573
1680
 
1574
1681
    def make_working_trees(self):
1575
1682
        """See Repository.make_working_trees"""
1576
 
        self._ensure_real()
1577
 
        return self._real_repository.make_working_trees()
 
1683
        path = self.bzrdir._path_for_remote_call(self._client)
 
1684
        try:
 
1685
            response = self._call('Repository.make_working_trees', path)
 
1686
        except errors.UnknownSmartMethod:
 
1687
            self._ensure_real()
 
1688
            return self._real_repository.make_working_trees()
 
1689
        if response[0] not in ('yes', 'no'):
 
1690
            raise SmartProtocolError('unexpected response code %s' % (response,))
 
1691
        return response[0] == 'yes'
1578
1692
 
1579
1693
    def refresh_data(self):
1580
1694
        """Re-read any data needed to synchronise with disk.
1682
1796
        self._ensure_real()
1683
1797
        return self._real_repository.iter_files_bytes(desired_files)
1684
1798
 
 
1799
    def get_cached_parent_map(self, revision_ids):
 
1800
        """See bzrlib.CachingParentsProvider.get_cached_parent_map"""
 
1801
        return self._unstacked_provider.get_cached_parent_map(revision_ids)
 
1802
 
1685
1803
    def get_parent_map(self, revision_ids):
1686
1804
        """See bzrlib.Graph.get_parent_map()."""
1687
1805
        return self._make_parents_provider().get_parent_map(revision_ids)
1745
1863
        if parents_map is None:
1746
1864
            # Repository is not locked, so there's no cache.
1747
1865
            parents_map = {}
1748
 
        # start_set is all the keys in the cache
1749
 
        start_set = set(parents_map)
1750
 
        # result set is all the references to keys in the cache
1751
 
        result_parents = set()
1752
 
        for parents in parents_map.itervalues():
1753
 
            result_parents.update(parents)
1754
 
        stop_keys = result_parents.difference(start_set)
1755
 
        # We don't need to send ghosts back to the server as a position to
1756
 
        # stop either.
1757
 
        stop_keys.difference_update(self._unstacked_provider.missing_keys)
1758
 
        key_count = len(parents_map)
1759
 
        if (NULL_REVISION in result_parents
1760
 
            and NULL_REVISION in self._unstacked_provider.missing_keys):
1761
 
            # If we pruned NULL_REVISION from the stop_keys because it's also
1762
 
            # in our cache of "missing" keys we need to increment our key count
1763
 
            # by 1, because the reconsitituted SearchResult on the server will
1764
 
            # still consider NULL_REVISION to be an included key.
1765
 
            key_count += 1
1766
 
        included_keys = start_set.intersection(result_parents)
1767
 
        start_set.difference_update(included_keys)
 
1866
        if _DEFAULT_SEARCH_DEPTH <= 0:
 
1867
            (start_set, stop_keys,
 
1868
             key_count) = graph.search_result_from_parent_map(
 
1869
                parents_map, self._unstacked_provider.missing_keys)
 
1870
        else:
 
1871
            (start_set, stop_keys,
 
1872
             key_count) = graph.limited_search_result_from_parent_map(
 
1873
                parents_map, self._unstacked_provider.missing_keys,
 
1874
                keys, depth=_DEFAULT_SEARCH_DEPTH)
1768
1875
        recipe = ('manual', start_set, stop_keys, key_count)
1769
1876
        body = self._serialise_search_recipe(recipe)
1770
1877
        path = self.bzrdir._path_for_remote_call(self._client)
1843
1950
 
1844
1951
    @needs_read_lock
1845
1952
    def get_revision_delta(self, revision_id, specific_fileids=None):
1846
 
        self._ensure_real()
1847
 
        return self._real_repository.get_revision_delta(revision_id,
1848
 
            specific_fileids=specific_fileids)
 
1953
        r = self.get_revision(revision_id)
 
1954
        return list(self.get_deltas_for_revisions([r],
 
1955
            specific_fileids=specific_fileids))[0]
1849
1956
 
1850
1957
    @needs_read_lock
1851
1958
    def revision_trees(self, revision_ids):
1864
1971
            callback_refs=callback_refs, check_repo=check_repo)
1865
1972
 
1866
1973
    def copy_content_into(self, destination, revision_id=None):
1867
 
        self._ensure_real()
1868
 
        return self._real_repository.copy_content_into(
1869
 
            destination, revision_id=revision_id)
 
1974
        """Make a complete copy of the content in self into destination.
 
1975
 
 
1976
        This is a destructive operation! Do not use it on existing
 
1977
        repositories.
 
1978
        """
 
1979
        interrepo = _mod_repository.InterRepository.get(self, destination)
 
1980
        return interrepo.copy_content(revision_id)
1870
1981
 
1871
1982
    def _copy_repository_tarball(self, to_bzrdir, revision_id=None):
1872
1983
        # get a tarball of the remote repository, and copy from that into the
1874
1985
        from bzrlib import osutils
1875
1986
        import tarfile
1876
1987
        # TODO: Maybe a progress bar while streaming the tarball?
1877
 
        note("Copying repository content as tarball...")
 
1988
        note(gettext("Copying repository content as tarball..."))
1878
1989
        tar_file = self._get_tarball('bz2')
1879
1990
        if tar_file is None:
1880
1991
            return None
1985
2096
    def _serializer(self):
1986
2097
        return self._format._serializer
1987
2098
 
 
2099
    @needs_write_lock
1988
2100
    def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
1989
 
        self._ensure_real()
1990
 
        return self._real_repository.store_revision_signature(
1991
 
            gpg_strategy, plaintext, revision_id)
 
2101
        signature = gpg_strategy.sign(plaintext)
 
2102
        self.add_signature_text(revision_id, signature)
1992
2103
 
1993
2104
    def add_signature_text(self, revision_id, signature):
1994
2105
        self._ensure_real()
1995
2106
        return self._real_repository.add_signature_text(revision_id, signature)
1996
2107
 
1997
2108
    def has_signature_for_revision_id(self, revision_id):
 
2109
        path = self.bzrdir._path_for_remote_call(self._client)
 
2110
        try:
 
2111
            response = self._call('Repository.has_signature_for_revision_id',
 
2112
                path, revision_id)
 
2113
        except errors.UnknownSmartMethod:
 
2114
            self._ensure_real()
 
2115
            return self._real_repository.has_signature_for_revision_id(
 
2116
                revision_id)
 
2117
        if response[0] not in ('yes', 'no'):
 
2118
            raise SmartProtocolError('unexpected response code %s' % (response,))
 
2119
        return (response[0] == 'yes')
 
2120
 
 
2121
    def verify_revision_signature(self, revision_id, gpg_strategy):
1998
2122
        self._ensure_real()
1999
 
        return self._real_repository.has_signature_for_revision_id(revision_id)
 
2123
        return self._real_repository.verify_revision_signature(
 
2124
            revision_id, gpg_strategy)
2000
2125
 
2001
2126
    def item_keys_introduced_by(self, revision_ids, _files_pb=None):
2002
2127
        self._ensure_real()
2354
2479
        return a_bzrdir.open_branch(name=name, 
2355
2480
            ignore_fallbacks=ignore_fallbacks)
2356
2481
 
2357
 
    def _vfs_initialize(self, a_bzrdir, name):
 
2482
    def _vfs_initialize(self, a_bzrdir, name, append_revisions_only):
2358
2483
        # Initialisation when using a local bzrdir object, or a non-vfs init
2359
2484
        # method is not available on the server.
2360
2485
        # self._custom_format is always set - the start of initialize ensures
2362
2487
        if isinstance(a_bzrdir, RemoteBzrDir):
2363
2488
            a_bzrdir._ensure_real()
2364
2489
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2365
 
                name)
 
2490
                name, append_revisions_only=append_revisions_only)
2366
2491
        else:
2367
2492
            # We assume the bzrdir is parameterised; it may not be.
2368
 
            result = self._custom_format.initialize(a_bzrdir, name)
 
2493
            result = self._custom_format.initialize(a_bzrdir, name,
 
2494
                append_revisions_only=append_revisions_only)
2369
2495
        if (isinstance(a_bzrdir, RemoteBzrDir) and
2370
2496
            not isinstance(result, RemoteBranch)):
2371
2497
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2372
2498
                                  name=name)
2373
2499
        return result
2374
2500
 
2375
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2501
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2502
                   append_revisions_only=None):
2376
2503
        # 1) get the network name to use.
2377
2504
        if self._custom_format:
2378
2505
            network_name = self._custom_format.network_name()
2384
2511
            network_name = reference_format.network_name()
2385
2512
        # Being asked to create on a non RemoteBzrDir:
2386
2513
        if not isinstance(a_bzrdir, RemoteBzrDir):
2387
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2514
            return self._vfs_initialize(a_bzrdir, name=name,
 
2515
                append_revisions_only=append_revisions_only)
2388
2516
        medium = a_bzrdir._client._medium
2389
2517
        if medium._is_remote_before((1, 13)):
2390
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2518
            return self._vfs_initialize(a_bzrdir, name=name,
 
2519
                append_revisions_only=append_revisions_only)
2391
2520
        # Creating on a remote bzr dir.
2392
2521
        # 2) try direct creation via RPC
2393
2522
        path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2400
2529
        except errors.UnknownSmartMethod:
2401
2530
            # Fallback - use vfs methods
2402
2531
            medium._remember_remote_is_before((1, 13))
2403
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2532
            return self._vfs_initialize(a_bzrdir, name=name,
 
2533
                    append_revisions_only=append_revisions_only)
2404
2534
        if response[0] != 'ok':
2405
2535
            raise errors.UnexpectedSmartServerResponse(response)
2406
2536
        # Turn the response into a RemoteRepository object.
2427
2557
            remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2428
2558
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2429
2559
            format=format, setup_stacking=False, name=name)
 
2560
        if append_revisions_only:
 
2561
            remote_branch.set_append_revisions_only(append_revisions_only)
2430
2562
        # XXX: We know this is a new branch, so it must have revno 0, revid
2431
2563
        # NULL_REVISION. Creating the branch locked would make this be unable
2432
2564
        # to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2465
2597
                return True
2466
2598
        return False
2467
2599
 
 
2600
 
 
2601
class RemoteBranchStore(config.IniFileStore):
 
2602
    """Branch store which attempts to use HPSS calls to retrieve branch store.
 
2603
 
 
2604
    Note that this is specific to bzr-based formats.
 
2605
    """
 
2606
 
 
2607
    def __init__(self, branch):
 
2608
        super(RemoteBranchStore, self).__init__()
 
2609
        self.branch = branch
 
2610
        self.id = "branch"
 
2611
        self._real_store = None
 
2612
 
 
2613
    def lock_write(self, token=None):
 
2614
        return self.branch.lock_write(token)
 
2615
 
 
2616
    def unlock(self):
 
2617
        return self.branch.unlock()
 
2618
 
 
2619
    @needs_write_lock
 
2620
    def save(self):
 
2621
        # We need to be able to override the undecorated implementation
 
2622
        self.save_without_locking()
 
2623
 
 
2624
    def save_without_locking(self):
 
2625
        super(RemoteBranchStore, self).save()
 
2626
 
 
2627
    def external_url(self):
 
2628
        return self.branch.user_url
 
2629
 
 
2630
    def _load_content(self):
 
2631
        path = self.branch._remote_path()
 
2632
        try:
 
2633
            response, handler = self.branch._call_expecting_body(
 
2634
                'Branch.get_config_file', path)
 
2635
        except errors.UnknownSmartMethod:
 
2636
            self._ensure_real()
 
2637
            return self._real_store._load_content()
 
2638
        if len(response) and response[0] != 'ok':
 
2639
            raise errors.UnexpectedSmartServerResponse(response)
 
2640
        return handler.read_body_bytes()
 
2641
 
 
2642
    def _save_content(self, content):
 
2643
        path = self.branch._remote_path()
 
2644
        try:
 
2645
            response, handler = self.branch._call_with_body_bytes_expecting_body(
 
2646
                'Branch.put_config_file', (path,
 
2647
                    self.branch._lock_token, self.branch._repo_lock_token),
 
2648
                content)
 
2649
        except errors.UnknownSmartMethod:
 
2650
            self._ensure_real()
 
2651
            return self._real_store._save_content(content)
 
2652
        handler.cancel_read_body()
 
2653
        if response != ('ok', ):
 
2654
            raise errors.UnexpectedSmartServerResponse(response)
 
2655
 
 
2656
    def _ensure_real(self):
 
2657
        self.branch._ensure_real()
 
2658
        if self._real_store is None:
 
2659
            self._real_store = config.BranchStore(self.branch)
 
2660
 
 
2661
 
2468
2662
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
2469
2663
    """Branch stored on a server accessed by HPSS RPC.
2470
2664
 
2559
2753
    def _get_config(self):
2560
2754
        return RemoteBranchConfig(self)
2561
2755
 
 
2756
    def _get_config_store(self):
 
2757
        return RemoteBranchStore(self)
 
2758
 
2562
2759
    def _get_real_transport(self):
2563
2760
        # if we try vfs access, return the real branch's vfs transport
2564
2761
        self._ensure_real()
2627
2824
                self.bzrdir, self._client)
2628
2825
        return self._control_files
2629
2826
 
2630
 
    def _get_checkout_format(self):
 
2827
    def _get_checkout_format(self, lightweight=False):
2631
2828
        self._ensure_real()
2632
 
        return self._real_branch._get_checkout_format()
 
2829
        if lightweight:
 
2830
            format = RemoteBzrDirFormat()
 
2831
            self.bzrdir._format._supply_sub_formats_to(format)
 
2832
            format.workingtree_format = self._real_branch._get_checkout_format(
 
2833
                lightweight=lightweight).workingtree_format
 
2834
            return format
 
2835
        else:
 
2836
            return self._real_branch._get_checkout_format(lightweight=False)
2633
2837
 
2634
2838
    def get_physical_lock_status(self):
2635
2839
        """See Branch.get_physical_lock_status()."""