/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3408.3.1 by Martin Pool
Remove erroneous handling of branch.conf for RemoteBranch
1
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
17
# TODO: At some point, handle upgrades by just passing the whole request
18
# across to run on the server.
19
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
20
import bz2
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
21
from cStringIO import StringIO
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
22
2490.2.5 by Aaron Bentley
Use GraphWalker.unique_ancestor to determine merge base
23
from bzrlib import (
24
    branch,
3192.1.1 by Andrew Bennetts
Add some -Dhpss debugging to get_parent_map.
25
    debug,
2490.2.5 by Aaron Bentley
Use GraphWalker.unique_ancestor to determine merge base
26
    errors,
3172.5.1 by Robert Collins
Create a RemoteRepository get_graph implementation and delegate get_parents_map to the real repository.
27
    graph,
2490.2.5 by Aaron Bentley
Use GraphWalker.unique_ancestor to determine merge base
28
    lockdir,
29
    repository,
2948.3.1 by John Arbash Meinel
Fix bug #158333, make sure that Repository.fetch(self) is properly a no-op for all Repository implementations.
30
    revision,
3228.4.11 by John Arbash Meinel
Deprecations abound.
31
    symbol_versioning,
2490.2.5 by Aaron Bentley
Use GraphWalker.unique_ancestor to determine merge base
32
)
2535.4.27 by Andrew Bennetts
Remove some unused imports.
33
from bzrlib.branch import BranchReferenceFormat
2018.5.174 by Andrew Bennetts
Various nits discovered by pyflakes.
34
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
2018.14.2 by Andrew Bennetts
All but one repository_implementation tests for RemoteRepository passing.
35
from bzrlib.config import BranchConfig, TreeConfig
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
36
from bzrlib.decorators import needs_read_lock, needs_write_lock
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
37
from bzrlib.errors import (
38
    NoSuchRevision,
39
    SmartProtocolError,
40
    )
2018.5.127 by Andrew Bennetts
Fix most of the lockable_files tests for RemoteBranchLockableFiles.
41
from bzrlib.lockable_files import LockableFiles
2535.4.20 by Andrew Bennetts
Remove unused import.
42
from bzrlib.pack import ContainerPushParser
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
43
from bzrlib.smart import client, vfs
2697.2.2 by Martin Pool
deprecate Branch.append_revision
44
from bzrlib.symbol_versioning import (
45
    deprecated_method,
46
    )
3297.4.1 by Andrew Bennetts
Merge 'Add Branch.set_last_revision_info smart method'.
47
from bzrlib.revision import ensure_null, NULL_REVISION
3213.1.6 by Andrew Bennetts
Emit warnings when forcing a reconnect.
48
from bzrlib.trace import mutter, note, warning
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
49
2018.5.25 by Andrew Bennetts
Make sure RemoteBzrDirFormat is always registered (John Arbash Meinel, Robert Collins, Andrew Bennetts).
50
# Note: RemoteBzrDirFormat is in bzrdir.py
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
51
52
class RemoteBzrDir(BzrDir):
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
53
    """Control directory on a remote server, accessed via bzr:// or similar."""
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
54
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
55
    def __init__(self, transport, _client=None):
56
        """Construct a RemoteBzrDir.
57
58
        :param _client: Private parameter for testing. Disables probing and the
59
            use of a real bzrdir.
60
        """
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
61
        BzrDir.__init__(self, transport, RemoteBzrDirFormat())
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
62
        # this object holds a delegated bzrdir that uses file-level operations
63
        # to talk to the other side
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
64
        self._real_bzrdir = None
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
65
66
        if _client is None:
3313.2.3 by Andrew Bennetts
Deprecate Transport.get_shared_medium.
67
            medium = transport.get_smart_medium()
68
            self._client = client._SmartClient(medium, transport.base)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
69
        else:
70
            self._client = _client
71
            return
72
73
        path = self._path_for_remote_call(self._client)
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
74
        response = self._client.call('BzrDir.open', path)
75
        if response not in [('yes',), ('no',)]:
76
            raise errors.UnexpectedSmartServerResponse(response)
2018.5.26 by Andrew Bennetts
Extract a simple SmartClient class from RemoteTransport, and a hack to avoid VFS operations when probing for a bzrdir over a smart transport.
77
        if response == ('no',):
78
            raise errors.NotBranchError(path=transport.base)
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
79
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
80
    def _ensure_real(self):
81
        """Ensure that there is a _real_bzrdir set.
82
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
83
        Used before calls to self._real_bzrdir.
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
84
        """
85
        if not self._real_bzrdir:
2018.5.169 by Andrew Bennetts
Add a _server_formats flag to BzrDir.open_from_transport and BzrDirFormat.find_format, make RemoteBranch.control_files into a property.
86
            self._real_bzrdir = BzrDir.open_from_transport(
87
                self.root_transport, _server_formats=False)
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
88
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
89
    def create_repository(self, shared=False):
2018.5.162 by Andrew Bennetts
Add some missing _ensure_real calls, and a missing import.
90
        self._ensure_real()
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
91
        self._real_bzrdir.create_repository(shared=shared)
92
        return self.open_repository()
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
93
2796.2.19 by Aaron Bentley
Support reconfigure --lightweight-checkout
94
    def destroy_repository(self):
95
        """See BzrDir.destroy_repository"""
96
        self._ensure_real()
97
        self._real_bzrdir.destroy_repository()
98
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
99
    def create_branch(self):
2018.5.162 by Andrew Bennetts
Add some missing _ensure_real calls, and a missing import.
100
        self._ensure_real()
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
101
        real_branch = self._real_bzrdir.create_branch()
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
102
        return RemoteBranch(self, self.find_repository(), real_branch)
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
103
2796.2.6 by Aaron Bentley
Implement destroy_branch
104
    def destroy_branch(self):
2796.2.16 by Aaron Bentley
Documentation updates from review
105
        """See BzrDir.destroy_branch"""
2796.2.6 by Aaron Bentley
Implement destroy_branch
106
        self._ensure_real()
107
        self._real_bzrdir.destroy_branch()
108
2955.5.3 by Vincent Ladeuil
Fix second unwanted connection by providing the right branch to create_checkout.
109
    def create_workingtree(self, revision_id=None, from_branch=None):
2018.5.174 by Andrew Bennetts
Various nits discovered by pyflakes.
110
        raise errors.NotLocalUrl(self.transport.base)
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
111
2018.5.124 by Robert Collins
Fix test_format_initialize_find_open by delegating Branch formt lookup to the BzrDir, where it should have stayed from the start.
112
    def find_branch_format(self):
113
        """Find the branch 'format' for this bzrdir.
114
115
        This might be a synthetic object for e.g. RemoteBranch and SVN.
116
        """
117
        b = self.open_branch()
118
        return b._format
119
2018.5.132 by Robert Collins
Make all BzrDir implementation tests pass on RemoteBzrDir - fix some things, and remove the incomplete_with_basis tests as cruft.
120
    def get_branch_reference(self):
121
        """See BzrDir.get_branch_reference()."""
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
122
        path = self._path_for_remote_call(self._client)
123
        response = self._client.call('BzrDir.open_branch', path)
124
        if response[0] == 'ok':
125
            if response[1] == '':
126
                # branch at this location.
2018.5.132 by Robert Collins
Make all BzrDir implementation tests pass on RemoteBzrDir - fix some things, and remove the incomplete_with_basis tests as cruft.
127
                return None
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
128
            else:
129
                # a branch reference, use the existing BranchReference logic.
2018.5.132 by Robert Collins
Make all BzrDir implementation tests pass on RemoteBzrDir - fix some things, and remove the incomplete_with_basis tests as cruft.
130
                return response[1]
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
131
        elif response == ('nobranch',):
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
132
            raise errors.NotBranchError(path=self.root_transport.base)
133
        else:
2555.1.1 by Martin Pool
Remove use of 'assert False' to raise an exception unconditionally
134
            raise errors.UnexpectedSmartServerResponse(response)
2018.5.132 by Robert Collins
Make all BzrDir implementation tests pass on RemoteBzrDir - fix some things, and remove the incomplete_with_basis tests as cruft.
135
3211.4.1 by Robert Collins
* ``RemoteBzrDir._get_tree_branch`` no longer triggers ``_ensure_real``,
136
    def _get_tree_branch(self):
137
        """See BzrDir._get_tree_branch()."""
138
        return None, self.open_branch()
139
2018.5.132 by Robert Collins
Make all BzrDir implementation tests pass on RemoteBzrDir - fix some things, and remove the incomplete_with_basis tests as cruft.
140
    def open_branch(self, _unsupported=False):
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
141
        if _unsupported:
142
            raise NotImplementedError('unsupported flag support not implemented yet.')
2018.5.132 by Robert Collins
Make all BzrDir implementation tests pass on RemoteBzrDir - fix some things, and remove the incomplete_with_basis tests as cruft.
143
        reference_url = self.get_branch_reference()
144
        if reference_url is None:
145
            # branch at this location.
146
            return RemoteBranch(self, self.find_repository())
147
        else:
148
            # a branch reference, use the existing BranchReference logic.
149
            format = BranchReferenceFormat()
150
            return format.open(self, _found=True, location=reference_url)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
151
                
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
152
    def open_repository(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
153
        path = self._path_for_remote_call(self._client)
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
154
        verb = 'BzrDir.find_repositoryV2'
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
155
        try:
156
            response = self._client.call(verb, path)
157
        except errors.UnknownSmartMethod:
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
158
            verb = 'BzrDir.find_repository'
159
            response = self._client.call(verb, path)
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
160
        if response[0] == 'norepository':
161
            raise errors.NoRepositoryPresent(self)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
162
        elif response[0] != 'ok':
163
            raise SmartProtocolError('unexpected response %r' 
164
                % response)
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
165
        if verb == 'BzrDir.find_repository':
166
            # servers that don't support the V2 method don't support external
167
            # references either.
168
            response = response + ('no', )
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
169
        if not (len(response) == 5):
170
            raise SmartProtocolError('incorrect response length %s' % (response,))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
171
        if response[1] == '':
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
172
            format = RemoteRepositoryFormat()
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
173
            format.rich_root_data = (response[2] == 'yes')
174
            format.supports_tree_reference = (response[3] == 'yes')
3221.3.1 by Robert Collins
* Repository formats have a new supported-feature attribute
175
            # No wire format to check this yet.
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
176
            format.supports_external_lookups = (response[4] == 'yes')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
177
            return RemoteRepository(self, format)
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
178
        else:
179
            raise errors.NoRepositoryPresent(self)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
180
2018.5.138 by Robert Collins
Merge bzr.dev.
181
    def open_workingtree(self, recommend_upgrade=True):
2445.1.1 by Andrew Bennetts
Make RemoteBzrDir.open_workingtree raise NoWorkingTree rather than NotLocalUrl
182
        self._ensure_real()
183
        if self._real_bzrdir.has_workingtree():
184
            raise errors.NotLocalUrl(self.root_transport)
185
        else:
186
            raise errors.NoWorkingTree(self.root_transport.base)
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
187
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
188
    def _path_for_remote_call(self, client):
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
189
        """Return the path to be used for this bzrdir in a remote call."""
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
190
        return client.remote_path_from_transport(self.root_transport)
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
191
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
192
    def get_branch_transport(self, branch_format):
2018.5.162 by Andrew Bennetts
Add some missing _ensure_real calls, and a missing import.
193
        self._ensure_real()
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
194
        return self._real_bzrdir.get_branch_transport(branch_format)
195
1752.2.43 by Andrew Bennetts
Fix get_{branch,repository,workingtree}_transport.
196
    def get_repository_transport(self, repository_format):
2018.5.162 by Andrew Bennetts
Add some missing _ensure_real calls, and a missing import.
197
        self._ensure_real()
1752.2.43 by Andrew Bennetts
Fix get_{branch,repository,workingtree}_transport.
198
        return self._real_bzrdir.get_repository_transport(repository_format)
199
200
    def get_workingtree_transport(self, workingtree_format):
2018.5.162 by Andrew Bennetts
Add some missing _ensure_real calls, and a missing import.
201
        self._ensure_real()
1752.2.43 by Andrew Bennetts
Fix get_{branch,repository,workingtree}_transport.
202
        return self._real_bzrdir.get_workingtree_transport(workingtree_format)
203
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
204
    def can_convert_format(self):
205
        """Upgrading of remote bzrdirs is not supported yet."""
206
        return False
207
208
    def needs_format_conversion(self, format=None):
209
        """Upgrading of remote bzrdirs is not supported yet."""
210
        return False
211
2018.5.138 by Robert Collins
Merge bzr.dev.
212
    def clone(self, url, revision_id=None, force_new_repo=False):
2018.5.94 by Andrew Bennetts
Various small changes in aid of making tests pass (including deleting one invalid test).
213
        self._ensure_real()
214
        return self._real_bzrdir.clone(url, revision_id=revision_id,
2018.5.138 by Robert Collins
Merge bzr.dev.
215
            force_new_repo=force_new_repo)
2018.5.94 by Andrew Bennetts
Various small changes in aid of making tests pass (including deleting one invalid test).
216
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
217
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
218
class RemoteRepositoryFormat(repository.RepositoryFormat):
2018.5.159 by Andrew Bennetts
Rename SmartClient to _SmartClient.
219
    """Format for repositories accessed over a _SmartClient.
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
220
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
221
    Instances of this repository are represented by RemoteRepository
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
222
    instances.
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
223
3128.1.3 by Vincent Ladeuil
Since we are there s/parameteris.*/parameteriz&/.
224
    The RemoteRepositoryFormat is parameterized during construction
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
225
    to reflect the capabilities of the real, remote format. Specifically
2018.5.138 by Robert Collins
Merge bzr.dev.
226
    the attributes rich_root_data and supports_tree_reference are set
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
227
    on a per instance basis, and are not set (and should not be) at
228
    the class level.
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
229
    """
230
231
    _matchingbzrdir = RemoteBzrDirFormat
232
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
233
    def initialize(self, a_bzrdir, shared=False):
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
234
        if not isinstance(a_bzrdir, RemoteBzrDir):
235
            raise AssertionError('%r is not a RemoteBzrDir' % (a_bzrdir,))
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
236
        return a_bzrdir.create_repository(shared=shared)
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
237
    
238
    def open(self, a_bzrdir):
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
239
        if not isinstance(a_bzrdir, RemoteBzrDir):
240
            raise AssertionError('%r is not a RemoteBzrDir' % (a_bzrdir,))
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
241
        return a_bzrdir.open_repository()
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
242
243
    def get_format_description(self):
244
        return 'bzr remote repository'
245
246
    def __eq__(self, other):
1752.2.87 by Andrew Bennetts
Make tests pass.
247
        return self.__class__ == other.__class__
248
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
249
    def check_conversion_target(self, target_format):
250
        if self.rich_root_data and not target_format.rich_root_data:
251
            raise errors.BadConversionTarget(
252
                'Does not support rich root data.', target_format)
2018.5.138 by Robert Collins
Merge bzr.dev.
253
        if (self.supports_tree_reference and
254
            not getattr(target_format, 'supports_tree_reference', False)):
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
255
            raise errors.BadConversionTarget(
256
                'Does not support nested trees', target_format)
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
257
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
258
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
259
class RemoteRepository(object):
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
260
    """Repository accessed over rpc.
261
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
262
    For the moment most operations are performed using local transport-backed
263
    Repository objects.
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
264
    """
265
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
266
    def __init__(self, remote_bzrdir, format, real_repository=None, _client=None):
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
267
        """Create a RemoteRepository instance.
268
        
269
        :param remote_bzrdir: The bzrdir hosting this repository.
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
270
        :param format: The RemoteFormat object to use.
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
271
        :param real_repository: If not None, a local implementation of the
272
            repository logic for the repository, usually accessing the data
273
            via the VFS.
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
274
        :param _client: Private testing parameter - override the smart client
275
            to be used by the repository.
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
276
        """
277
        if real_repository:
2018.5.36 by Andrew Bennetts
Fix typo, and clean up some ununsed import warnings from pyflakes at the same time.
278
            self._real_repository = real_repository
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
279
        else:
280
            self._real_repository = None
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
281
        self.bzrdir = remote_bzrdir
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
282
        if _client is None:
3313.2.1 by Andrew Bennetts
Change _SmartClient's API to accept a medium and a base, rather than a _SharedConnection.
283
            self._client = remote_bzrdir._client
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
284
        else:
285
            self._client = _client
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
286
        self._format = format
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
287
        self._lock_mode = None
288
        self._lock_token = None
289
        self._lock_count = 0
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
290
        self._leave_lock = False
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
291
        # A cache of looked up revision parent data; reset at unlock time.
292
        self._parents_map = None
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
293
        if 'hpss' in debug.debug_flags:
294
            self._requested_parents = None
2951.1.10 by Robert Collins
Peer review feedback with Ian.
295
        # For tests:
296
        # These depend on the actual remote format, so force them off for
297
        # maximum compatibility. XXX: In future these should depend on the
298
        # remote repository instance, but this is irrelevant until we perform
299
        # reconcile via an RPC call.
2951.1.5 by Robert Collins
Some work towards including the correct changes for TREE_ROOT in check parameterised tests.
300
        self._reconcile_does_inventory_gc = False
301
        self._reconcile_fixes_text_parents = False
2951.1.3 by Robert Collins
Partial support for native reconcile with packs.
302
        self._reconcile_backsup_inventory = False
2592.4.5 by Martin Pool
Add Repository.base on all repositories.
303
        self.base = self.bzrdir.transport.base
304
305
    def __str__(self):
306
        return "%s(%s)" % (self.__class__.__name__, self.base)
307
308
    __repr__ = __str__
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
309
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
310
    def abort_write_group(self):
2617.6.7 by Robert Collins
More review feedback.
311
        """Complete a write group on the decorated repository.
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
312
        
313
        Smart methods peform operations in a single step so this api
2617.6.6 by Robert Collins
Some review feedback.
314
        is not really applicable except as a compatibility thunk
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
315
        for older plugins that don't use e.g. the CommitBuilder
316
        facility.
317
        """
318
        self._ensure_real()
319
        return self._real_repository.abort_write_group()
320
321
    def commit_write_group(self):
2617.6.7 by Robert Collins
More review feedback.
322
        """Complete a write group on the decorated repository.
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
323
        
324
        Smart methods peform operations in a single step so this api
2617.6.6 by Robert Collins
Some review feedback.
325
        is not really applicable except as a compatibility thunk
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
326
        for older plugins that don't use e.g. the CommitBuilder
327
        facility.
328
        """
329
        self._ensure_real()
330
        return self._real_repository.commit_write_group()
2617.6.1 by Robert Collins
* New method on Repository - ``start_write_group``, ``end_write_group``
331
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
332
    def _ensure_real(self):
333
        """Ensure that there is a _real_repository set.
334
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
335
        Used before calls to self._real_repository.
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
336
        """
337
        if not self._real_repository:
338
            self.bzrdir._ensure_real()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
339
            #self._real_repository = self.bzrdir._real_bzrdir.open_repository()
340
            self._set_real_repository(self.bzrdir._real_bzrdir.open_repository())
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
341
2988.1.2 by Robert Collins
New Repository API find_text_key_references for use by reconcile and check.
342
    def find_text_key_references(self):
343
        """Find the text key references within the repository.
344
345
        :return: a dictionary mapping (file_id, revision_id) tuples to altered file-ids to an iterable of
346
        revision_ids. Each altered file-ids has the exact revision_ids that
347
        altered it listed explicitly.
348
        :return: A dictionary mapping text keys ((fileid, revision_id) tuples)
349
            to whether they were referred to by the inventory of the
350
            revision_id that they contain. The inventory texts from all present
351
            revision ids are assessed to generate this report.
352
        """
353
        self._ensure_real()
354
        return self._real_repository.find_text_key_references()
355
2988.1.3 by Robert Collins
Add a new repositoy method _generate_text_key_index for use by reconcile/check.
356
    def _generate_text_key_index(self):
357
        """Generate a new text key index for the repository.
358
359
        This is an expensive function that will take considerable time to run.
360
361
        :return: A dict mapping (file_id, revision_id) tuples to a list of
362
            parents, also (file_id, revision_id) tuples.
363
        """
364
        self._ensure_real()
365
        return self._real_repository._generate_text_key_index()
366
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
367
    @symbol_versioning.deprecated_method(symbol_versioning.one_four)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
368
    def get_revision_graph(self, revision_id=None):
369
        """See Repository.get_revision_graph()."""
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
370
        return self._get_revision_graph(revision_id)
371
372
    def _get_revision_graph(self, revision_id):
373
        """Private method for using with old (< 1.2) servers to fallback."""
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
374
        if revision_id is None:
375
            revision_id = ''
2948.3.1 by John Arbash Meinel
Fix bug #158333, make sure that Repository.fetch(self) is properly a no-op for all Repository implementations.
376
        elif revision.is_null(revision_id):
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
377
            return {}
378
379
        path = self.bzrdir._path_for_remote_call(self._client)
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
380
        response = self._client.call_expecting_body(
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
381
            'Repository.get_revision_graph', path, revision_id)
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
382
        if response[0][0] not in ['ok', 'nosuchrevision']:
383
            raise errors.UnexpectedSmartServerResponse(response[0])
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
384
        if response[0][0] == 'ok':
385
            coded = response[1].read_body_bytes()
2018.5.105 by Andrew Bennetts
Implement revision_history caching for RemoteBranch.
386
            if coded == '':
387
                # no revisions in this repository!
388
                return {}
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
389
            lines = coded.split('\n')
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
390
            revision_graph = {}
391
            for line in lines:
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
392
                d = tuple(line.split())
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
393
                revision_graph[d[0]] = d[1:]
394
                
395
            return revision_graph
396
        else:
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
397
            response_body = response[1].read_body_bytes()
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
398
            if response_body:
399
                raise SmartProtocolError('unexpected response body')
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
400
            raise NoSuchRevision(self, revision_id)
401
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
402
    def has_revision(self, revision_id):
403
        """See Repository.has_revision()."""
3172.3.1 by Robert Collins
Repository has a new method ``has_revisions`` which signals the presence
404
        if revision_id == NULL_REVISION:
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
405
            # The null revision is always present.
406
            return True
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
407
        path = self.bzrdir._path_for_remote_call(self._client)
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
408
        response = self._client.call('Repository.has_revision', path, revision_id)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
409
        if response[0] not in ('yes', 'no'):
410
            raise SmartProtocolError('unexpected response code %s' % (response,))
2018.5.158 by Andrew Bennetts
Return 'yes'/'no' rather than 'ok'/'no' from the Repository.has_revision smart command.
411
        return response[0] == 'yes'
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
412
3172.3.1 by Robert Collins
Repository has a new method ``has_revisions`` which signals the presence
413
    def has_revisions(self, revision_ids):
414
        """See Repository.has_revisions()."""
415
        result = set()
416
        for revision_id in revision_ids:
417
            if self.has_revision(revision_id):
418
                result.add(revision_id)
419
        return result
420
2617.6.9 by Robert Collins
Merge bzr.dev.
421
    def has_same_location(self, other):
2592.3.162 by Robert Collins
Remove some arbitrary differences from bzr.dev.
422
        return (self.__class__ == other.__class__ and
423
                self.bzrdir.transport.base == other.bzrdir.transport.base)
2617.6.9 by Robert Collins
Merge bzr.dev.
424
        
2490.2.21 by Aaron Bentley
Rename graph to deprecated_graph
425
    def get_graph(self, other_repository=None):
426
        """Return the graph for this repository format"""
3172.5.1 by Robert Collins
Create a RemoteRepository get_graph implementation and delegate get_parents_map to the real repository.
427
        parents_provider = self
428
        if (other_repository is not None and
429
            other_repository.bzrdir.transport.base !=
430
            self.bzrdir.transport.base):
431
            parents_provider = graph._StackedParentsProvider(
432
                [parents_provider, other_repository._make_parents_provider()])
433
        return graph.Graph(parents_provider)
2490.2.5 by Aaron Bentley
Use GraphWalker.unique_ancestor to determine merge base
434
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
435
    def gather_stats(self, revid=None, committers=None):
2018.5.62 by Robert Collins
Stub out RemoteRepository.gather_stats while its implemented in parallel.
436
        """See Repository.gather_stats()."""
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
437
        path = self.bzrdir._path_for_remote_call(self._client)
2948.3.4 by John Arbash Meinel
Repository.gather_stats() validly can get None for the revid.
438
        # revid can be None to indicate no revisions, not just NULL_REVISION
439
        if revid is None or revision.is_null(revid):
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
440
            fmt_revid = ''
441
        else:
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
442
            fmt_revid = revid
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
443
        if committers is None or not committers:
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
444
            fmt_committers = 'no'
445
        else:
446
            fmt_committers = 'yes'
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
447
        response = self._client.call_expecting_body(
448
            'Repository.gather_stats', path, fmt_revid, fmt_committers)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
449
        if response[0][0] != 'ok':
450
            raise SmartProtocolError('unexpected response code %s'
451
                % (response[0],))
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
452
453
        body = response[1].read_body_bytes()
454
        result = {}
455
        for line in body.split('\n'):
456
            if not line:
457
                continue
458
            key, val_text = line.split(':')
459
            if key in ('revisions', 'size', 'committers'):
460
                result[key] = int(val_text)
461
            elif key in ('firstrev', 'latestrev'):
462
                values = val_text.split(' ')[1:]
463
                result[key] = (float(values[0]), long(values[1]))
464
465
        return result
2018.5.62 by Robert Collins
Stub out RemoteRepository.gather_stats while its implemented in parallel.
466
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
467
    def find_branches(self, using=False):
468
        """See Repository.find_branches()."""
469
        # should be an API call to the server.
470
        self._ensure_real()
471
        return self._real_repository.find_branches(using=using)
472
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
473
    def get_physical_lock_status(self):
474
        """See Repository.get_physical_lock_status()."""
3015.2.10 by Robert Collins
Fix regression due to other pack related fixes in tests with packs not-default.
475
        # should be an API call to the server.
476
        self._ensure_real()
477
        return self._real_repository.get_physical_lock_status()
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
478
2617.6.1 by Robert Collins
* New method on Repository - ``start_write_group``, ``end_write_group``
479
    def is_in_write_group(self):
480
        """Return True if there is an open write group.
481
482
        write groups are only applicable locally for the smart server..
483
        """
484
        if self._real_repository:
485
            return self._real_repository.is_in_write_group()
486
487
    def is_locked(self):
488
        return self._lock_count >= 1
489
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
490
    def is_shared(self):
491
        """See Repository.is_shared()."""
492
        path = self.bzrdir._path_for_remote_call(self._client)
493
        response = self._client.call('Repository.is_shared', path)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
494
        if response[0] not in ('yes', 'no'):
495
            raise SmartProtocolError('unexpected response code %s' % (response,))
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
496
        return response[0] == 'yes'
497
2904.1.1 by Robert Collins
* New method ``bzrlib.repository.Repository.is_write_locked`` useful for
498
    def is_write_locked(self):
499
        return self._lock_mode == 'w'
500
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
501
    def lock_read(self):
502
        # wrong eventually - want a local lock cache context
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
503
        if not self._lock_mode:
504
            self._lock_mode = 'r'
505
            self._lock_count = 1
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
506
            self._parents_map = {}
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
507
            if 'hpss' in debug.debug_flags:
508
                self._requested_parents = set()
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
509
            if self._real_repository is not None:
510
                self._real_repository.lock_read()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
511
        else:
512
            self._lock_count += 1
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
513
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
514
    def _remote_lock_write(self, token):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
515
        path = self.bzrdir._path_for_remote_call(self._client)
516
        if token is None:
517
            token = ''
518
        response = self._client.call('Repository.lock_write', path, token)
519
        if response[0] == 'ok':
520
            ok, token = response
521
            return token
522
        elif response[0] == 'LockContention':
523
            raise errors.LockContention('(remote lock)')
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
524
        elif response[0] == 'UnlockableTransport':
525
            raise errors.UnlockableTransport(self.bzrdir.root_transport)
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
526
        elif response[0] == 'LockFailed':
527
            raise errors.LockFailed(response[1], response[2])
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
528
        else:
2555.1.1 by Martin Pool
Remove use of 'assert False' to raise an exception unconditionally
529
            raise errors.UnexpectedSmartServerResponse(response)
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
530
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
531
    def lock_write(self, token=None):
532
        if not self._lock_mode:
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
533
            self._lock_token = self._remote_lock_write(token)
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
534
            # if self._lock_token is None, then this is something like packs or
535
            # svn where we don't get to lock the repo, or a weave style repository
536
            # where we cannot lock it over the wire and attempts to do so will
537
            # fail.
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
538
            if self._real_repository is not None:
539
                self._real_repository.lock_write(token=self._lock_token)
540
            if token is not None:
541
                self._leave_lock = True
542
            else:
543
                self._leave_lock = False
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
544
            self._lock_mode = 'w'
545
            self._lock_count = 1
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
546
            self._parents_map = {}
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
547
            if 'hpss' in debug.debug_flags:
548
                self._requested_parents = set()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
549
        elif self._lock_mode == 'r':
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
550
            raise errors.ReadOnlyError(self)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
551
        else:
552
            self._lock_count += 1
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
553
        return self._lock_token or None
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
554
555
    def leave_lock_in_place(self):
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
556
        if not self._lock_token:
557
            raise NotImplementedError(self.leave_lock_in_place)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
558
        self._leave_lock = True
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
559
560
    def dont_leave_lock_in_place(self):
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
561
        if not self._lock_token:
3015.2.15 by Robert Collins
Review feedback.
562
            raise NotImplementedError(self.dont_leave_lock_in_place)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
563
        self._leave_lock = False
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
564
565
    def _set_real_repository(self, repository):
566
        """Set the _real_repository for this repository.
567
568
        :param repository: The repository to fallback to for non-hpss
569
            implemented operations.
570
        """
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
571
        if isinstance(repository, RemoteRepository):
572
            raise AssertionError()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
573
        self._real_repository = repository
574
        if self._lock_mode == 'w':
575
            # if we are already locked, the real repository must be able to
576
            # acquire the lock with our token.
577
            self._real_repository.lock_write(self._lock_token)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
578
        elif self._lock_mode == 'r':
579
            self._real_repository.lock_read()
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
580
2617.6.1 by Robert Collins
* New method on Repository - ``start_write_group``, ``end_write_group``
581
    def start_write_group(self):
582
        """Start a write group on the decorated repository.
583
        
584
        Smart methods peform operations in a single step so this api
2617.6.6 by Robert Collins
Some review feedback.
585
        is not really applicable except as a compatibility thunk
2617.6.1 by Robert Collins
* New method on Repository - ``start_write_group``, ``end_write_group``
586
        for older plugins that don't use e.g. the CommitBuilder
587
        facility.
588
        """
589
        self._ensure_real()
590
        return self._real_repository.start_write_group()
591
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
592
    def _unlock(self, token):
593
        path = self.bzrdir._path_for_remote_call(self._client)
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
594
        if not token:
595
            # with no token the remote repository is not persistently locked.
596
            return
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
597
        response = self._client.call('Repository.unlock', path, token)
598
        if response == ('ok',):
599
            return
600
        elif response[0] == 'TokenMismatch':
601
            raise errors.TokenMismatch(token, '(remote token)')
602
        else:
2555.1.1 by Martin Pool
Remove use of 'assert False' to raise an exception unconditionally
603
            raise errors.UnexpectedSmartServerResponse(response)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
604
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
605
    def unlock(self):
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
606
        self._lock_count -= 1
2592.3.244 by Martin Pool
unlock while in a write group now aborts the write group, unlocks, and errors.
607
        if self._lock_count > 0:
608
            return
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
609
        self._parents_map = None
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
610
        if 'hpss' in debug.debug_flags:
611
            self._requested_parents = None
2592.3.244 by Martin Pool
unlock while in a write group now aborts the write group, unlocks, and errors.
612
        old_mode = self._lock_mode
613
        self._lock_mode = None
614
        try:
615
            # The real repository is responsible at present for raising an
616
            # exception if it's in an unfinished write group.  However, it
617
            # normally will *not* actually remove the lock from disk - that's
618
            # done by the server on receiving the Repository.unlock call.
619
            # This is just to let the _real_repository stay up to date.
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
620
            if self._real_repository is not None:
621
                self._real_repository.unlock()
2592.3.244 by Martin Pool
unlock while in a write group now aborts the write group, unlocks, and errors.
622
        finally:
623
            # The rpc-level lock should be released even if there was a
624
            # problem releasing the vfs-based lock.
625
            if old_mode == 'w':
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
626
                # Only write-locked repositories need to make a remote method
627
                # call to perfom the unlock.
2592.3.244 by Martin Pool
unlock while in a write group now aborts the write group, unlocks, and errors.
628
                old_token = self._lock_token
629
                self._lock_token = None
630
                if not self._leave_lock:
631
                    self._unlock(old_token)
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
632
633
    def break_lock(self):
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
634
        # should hand off to the network
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
635
        self._ensure_real()
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
636
        return self._real_repository.break_lock()
637
2018.18.8 by Ian Clatworthy
Tarball proxy code & tests
638
    def _get_tarball(self, compression):
2814.10.2 by Andrew Bennetts
Make the fallback a little tidier.
639
        """Return a TemporaryFile containing a repository tarball.
640
        
641
        Returns None if the server does not support sending tarballs.
642
        """
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
643
        import tempfile
2018.18.8 by Ian Clatworthy
Tarball proxy code & tests
644
        path = self.bzrdir._path_for_remote_call(self._client)
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
645
        try:
646
            response, protocol = self._client.call_expecting_body(
647
                'Repository.tarball', path, compression)
648
        except errors.UnknownSmartMethod:
649
            protocol.cancel_read_body()
650
            return None
2018.18.8 by Ian Clatworthy
Tarball proxy code & tests
651
        if response[0] == 'ok':
652
            # Extract the tarball and return it
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
653
            t = tempfile.NamedTemporaryFile()
654
            # TODO: rpc layer should read directly into it...
655
            t.write(protocol.read_body_bytes())
656
            t.seek(0)
657
            return t
2814.10.1 by Andrew Bennetts
Cope gracefully if the server doesn't support the Repository.tarball smart request.
658
        raise errors.UnexpectedSmartServerResponse(response)
2018.18.8 by Ian Clatworthy
Tarball proxy code & tests
659
2440.1.1 by Martin Pool
Add new Repository.sprout,
660
    def sprout(self, to_bzrdir, revision_id=None):
661
        # TODO: Option to control what format is created?
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
662
        self._ensure_real()
3047.1.4 by Andrew Bennetts
Simplify RemoteRepository.sprout thanks to review comments.
663
        dest_repo = self._real_repository._format.initialize(to_bzrdir,
664
                                                             shared=False)
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
665
        dest_repo.fetch(self, revision_id=revision_id)
666
        return dest_repo
2440.1.1 by Martin Pool
Add new Repository.sprout,
667
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
668
    ### These methods are just thin shims to the VFS object for now.
669
670
    def revision_tree(self, revision_id):
671
        self._ensure_real()
672
        return self._real_repository.revision_tree(revision_id)
673
2520.4.113 by Aaron Bentley
Avoid peeking at Repository._serializer
674
    def get_serializer_format(self):
675
        self._ensure_real()
676
        return self._real_repository.get_serializer_format()
677
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
678
    def get_commit_builder(self, branch, parents, config, timestamp=None,
679
                           timezone=None, committer=None, revprops=None,
680
                           revision_id=None):
681
        # FIXME: It ought to be possible to call this without immediately
682
        # triggering _ensure_real.  For now it's the easiest thing to do.
683
        self._ensure_real()
684
        builder = self._real_repository.get_commit_builder(branch, parents,
685
                config, timestamp=timestamp, timezone=timezone,
686
                committer=committer, revprops=revprops, revision_id=revision_id)
687
        return builder
688
689
    def add_inventory(self, revid, inv, parents):
690
        self._ensure_real()
691
        return self._real_repository.add_inventory(revid, inv, parents)
692
693
    def add_revision(self, rev_id, rev, inv=None, config=None):
694
        self._ensure_real()
695
        return self._real_repository.add_revision(
696
            rev_id, rev, inv=inv, config=config)
697
698
    @needs_read_lock
699
    def get_inventory(self, revision_id):
700
        self._ensure_real()
701
        return self._real_repository.get_inventory(revision_id)
702
3169.2.1 by Robert Collins
New method ``iter_inventories`` on Repository for access to many
703
    def iter_inventories(self, revision_ids):
704
        self._ensure_real()
705
        return self._real_repository.iter_inventories(revision_ids)
706
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
707
    @needs_read_lock
708
    def get_revision(self, revision_id):
709
        self._ensure_real()
710
        return self._real_repository.get_revision(revision_id)
711
712
    @property
713
    def weave_store(self):
714
        self._ensure_real()
715
        return self._real_repository.weave_store
716
717
    def get_transaction(self):
718
        self._ensure_real()
719
        return self._real_repository.get_transaction()
720
721
    @needs_read_lock
2018.5.138 by Robert Collins
Merge bzr.dev.
722
    def clone(self, a_bzrdir, revision_id=None):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
723
        self._ensure_real()
2018.5.138 by Robert Collins
Merge bzr.dev.
724
        return self._real_repository.clone(a_bzrdir, revision_id=revision_id)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
725
726
    def make_working_trees(self):
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
727
        """See Repository.make_working_trees"""
728
        self._ensure_real()
729
        return self._real_repository.make_working_trees()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
730
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
731
    def revision_ids_to_search_result(self, result_set):
732
        """Convert a set of revision ids to a graph SearchResult."""
733
        result_parents = set()
734
        for parents in self.get_graph().get_parent_map(
735
            result_set).itervalues():
736
            result_parents.update(parents)
737
        included_keys = result_set.intersection(result_parents)
738
        start_keys = result_set.difference(included_keys)
739
        exclude_keys = result_parents.difference(result_set)
740
        result = graph.SearchResult(start_keys, exclude_keys,
741
            len(result_set), result_set)
742
        return result
743
744
    @needs_read_lock
745
    def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
746
        """Return the revision ids that other has that this does not.
747
        
748
        These are returned in topological order.
749
750
        revision_id: only return revision ids included by revision_id.
751
        """
752
        return repository.InterRepository.get(
753
            other, self).search_missing_revision_ids(revision_id, find_ghosts)
754
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
755
    def fetch(self, source, revision_id=None, pb=None):
2881.4.1 by Robert Collins
Move responsibility for detecting same-repo fetching from the
756
        if self.has_same_location(source):
757
            # check that last_revision is in 'from' and then return a
758
            # no-operation.
759
            if (revision_id is not None and
2948.3.1 by John Arbash Meinel
Fix bug #158333, make sure that Repository.fetch(self) is properly a no-op for all Repository implementations.
760
                not revision.is_null(revision_id)):
2881.4.1 by Robert Collins
Move responsibility for detecting same-repo fetching from the
761
                self.get_revision(revision_id)
2592.4.5 by Martin Pool
Add Repository.base on all repositories.
762
            return 0, []
2592.3.119 by Robert Collins
Merge some test fixes from Martin.
763
        self._ensure_real()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
764
        return self._real_repository.fetch(
765
            source, revision_id=revision_id, pb=pb)
766
2520.4.54 by Aaron Bentley
Hang a create_bundle method off repository
767
    def create_bundle(self, target, base, fileobj, format=None):
768
        self._ensure_real()
769
        self._real_repository.create_bundle(target, base, fileobj, format)
770
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
771
    @property
772
    def control_weaves(self):
773
        self._ensure_real()
774
        return self._real_repository.control_weaves
775
776
    @needs_read_lock
2530.1.1 by Aaron Bentley
Make topological sorting optional for get_ancestry
777
    def get_ancestry(self, revision_id, topo_sorted=True):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
778
        self._ensure_real()
2530.1.1 by Aaron Bentley
Make topological sorting optional for get_ancestry
779
        return self._real_repository.get_ancestry(revision_id, topo_sorted)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
780
781
    @needs_read_lock
782
    def get_inventory_weave(self):
783
        self._ensure_real()
784
        return self._real_repository.get_inventory_weave()
785
786
    def fileids_altered_by_revision_ids(self, revision_ids):
787
        self._ensure_real()
788
        return self._real_repository.fileids_altered_by_revision_ids(revision_ids)
789
3036.1.3 by Robert Collins
Privatise VersionedFileChecker.
790
    def _get_versioned_file_checker(self, revisions, revision_versions_cache):
2745.6.1 by Aaron Bentley
Initial checking of knit graphs
791
        self._ensure_real()
3036.1.3 by Robert Collins
Privatise VersionedFileChecker.
792
        return self._real_repository._get_versioned_file_checker(
2745.6.50 by Andrew Bennetts
Remove find_bad_ancestors; it's not needed anymore.
793
            revisions, revision_versions_cache)
794
        
2708.1.7 by Aaron Bentley
Rename extract_files_bytes to iter_files_bytes
795
    def iter_files_bytes(self, desired_files):
2708.1.9 by Aaron Bentley
Clean-up docs and imports
796
        """See Repository.iter_file_bytes.
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
797
        """
798
        self._ensure_real()
2708.1.7 by Aaron Bentley
Rename extract_files_bytes to iter_files_bytes
799
        return self._real_repository.iter_files_bytes(desired_files)
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
800
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
801
    def get_parent_map(self, keys):
802
        """See bzrlib.Graph.get_parent_map()."""
803
        # Hack to build up the caching logic.
804
        ancestry = self._parents_map
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
805
        if ancestry is None:
806
            # Repository is not locked, so there's no cache.
807
            missing_revisions = set(keys)
808
            ancestry = {}
809
        else:
810
            missing_revisions = set(key for key in keys if key not in ancestry)
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
811
        if missing_revisions:
3192.1.1 by Andrew Bennetts
Add some -Dhpss debugging to get_parent_map.
812
            parent_map = self._get_parent_map(missing_revisions)
813
            if 'hpss' in debug.debug_flags:
814
                mutter('retransmitted revisions: %d of %d',
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
815
                        len(set(ancestry).intersection(parent_map)),
3192.1.1 by Andrew Bennetts
Add some -Dhpss debugging to get_parent_map.
816
                        len(parent_map))
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
817
            ancestry.update(parent_map)
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
818
        present_keys = [k for k in keys if k in ancestry]
819
        if 'hpss' in debug.debug_flags:
820
            self._requested_parents.update(present_keys)
821
            mutter('Current RemoteRepository graph hit rate: %d%%',
3213.1.8 by Andrew Bennetts
Merge from bzr.dev.
822
                100.0 * len(self._requested_parents) / len(ancestry))
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
823
        return dict((k, ancestry[k]) for k in present_keys)
3172.5.4 by Robert Collins
Implement get_parent_map for RemoteRepository with caching, based on get_revision_graph.
824
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
825
    def _get_parent_map(self, keys):
826
        """Helper for get_parent_map that performs the RPC."""
3313.2.1 by Andrew Bennetts
Change _SmartClient's API to accept a medium and a base, rather than a _SharedConnection.
827
        medium = self._client._medium
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
828
        if not medium._remote_is_at_least_1_2:
829
            # We already found out that the server can't understand
3213.1.3 by Andrew Bennetts
Fix typo in comment.
830
            # Repository.get_parent_map requests, so just fetch the whole
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
831
            # graph.
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
832
            # XXX: Note that this will issue a deprecation warning. This is ok
833
            # :- its because we're working with a deprecated server anyway, and
834
            # the user will almost certainly have seen a warning about the
835
            # server version already.
3389.1.1 by John Arbash Meinel
Fix bug #214894. Fix RemoteRepository.get_parent_map() when server is <v1.2
836
            rg = self.get_revision_graph()
837
            # There is an api discrepency between get_parent_map and
838
            # get_revision_graph. Specifically, a "key:()" pair in
839
            # get_revision_graph just means a node has no parents. For
840
            # "get_parent_map" it means the node is a ghost. So fix up the
841
            # graph to correct this.
842
            #   https://bugs.launchpad.net/bzr/+bug/214894
843
            # There is one other "bug" which is that ghosts in
844
            # get_revision_graph() are not returned at all. But we won't worry
845
            # about that for now.
846
            for node_id, parent_ids in rg.iteritems():
847
                if parent_ids == ():
848
                    rg[node_id] = (NULL_REVISION,)
849
            rg[NULL_REVISION] = ()
850
            return rg
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
851
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
852
        keys = set(keys)
853
        if NULL_REVISION in keys:
854
            keys.discard(NULL_REVISION)
855
            found_parents = {NULL_REVISION:()}
856
            if not keys:
857
                return found_parents
858
        else:
859
            found_parents = {}
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
860
        # TODO(Needs analysis): We could assume that the keys being requested
861
        # from get_parent_map are in a breadth first search, so typically they
862
        # will all be depth N from some common parent, and we don't have to
863
        # have the server iterate from the root parent, but rather from the
864
        # keys we're searching; and just tell the server the keyspace we
865
        # already have; but this may be more traffic again.
866
867
        # Transform self._parents_map into a search request recipe.
868
        # TODO: Manage this incrementally to avoid covering the same path
869
        # repeatedly. (The server will have to on each request, but the less
870
        # work done the better).
3213.1.8 by Andrew Bennetts
Merge from bzr.dev.
871
        parents_map = self._parents_map
872
        if parents_map is None:
873
            # Repository is not locked, so there's no cache.
874
            parents_map = {}
875
        start_set = set(parents_map)
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
876
        result_parents = set()
3213.1.8 by Andrew Bennetts
Merge from bzr.dev.
877
        for parents in parents_map.itervalues():
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
878
            result_parents.update(parents)
879
        stop_keys = result_parents.difference(start_set)
880
        included_keys = start_set.intersection(result_parents)
881
        start_set.difference_update(included_keys)
3213.1.8 by Andrew Bennetts
Merge from bzr.dev.
882
        recipe = (start_set, stop_keys, len(parents_map))
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
883
        body = self._serialise_search_recipe(recipe)
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
884
        path = self.bzrdir._path_for_remote_call(self._client)
885
        for key in keys:
3360.2.8 by Martin Pool
Change assertion to a plain raise
886
            if type(key) is not str:
887
                raise ValueError(
888
                    "key %r not a plain string" % (key,))
3172.5.8 by Robert Collins
Review feedback.
889
        verb = 'Repository.get_parent_map'
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
890
        args = (path,) + tuple(keys)
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
891
        try:
892
            response = self._client.call_with_body_bytes_expecting_body(
893
                verb, args, self._serialise_search_recipe(recipe))
894
        except errors.UnknownSmartMethod:
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
895
            # Server does not support this method, so get the whole graph.
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
896
            # Worse, we have to force a disconnection, because the server now
897
            # doesn't realise it has a body on the wire to consume, so the
898
            # only way to recover is to abandon the connection.
3213.1.6 by Andrew Bennetts
Emit warnings when forcing a reconnect.
899
            warning(
900
                'Server is too old for fast get_parent_map, reconnecting.  '
901
                '(Upgrade the server to Bazaar 1.2 to avoid this)')
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
902
            medium.disconnect()
903
            # To avoid having to disconnect repeatedly, we keep track of the
904
            # fact the server doesn't understand remote methods added in 1.2.
905
            medium._remote_is_at_least_1_2 = False
3297.3.4 by Andrew Bennetts
Merge from bzr.dev.
906
            return self.get_revision_graph(None)
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
907
        if response[0][0] not in ['ok']:
3297.2.1 by Andrew Bennetts
Fix 'reponse' typo.
908
            response[1].cancel_read_body()
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
909
            raise errors.UnexpectedSmartServerResponse(response[0])
910
        if response[0][0] == 'ok':
3211.5.2 by Robert Collins
Change RemoteRepository.get_parent_map to use bz2 not gzip for compression.
911
            coded = bz2.decompress(response[1].read_body_bytes())
3172.5.6 by Robert Collins
Create new smart server verb Repository.get_parent_map.
912
            if coded == '':
913
                # no revisions found
914
                return {}
915
            lines = coded.split('\n')
916
            revision_graph = {}
917
            for line in lines:
918
                d = tuple(line.split())
919
                if len(d) > 1:
920
                    revision_graph[d[0]] = d[1:]
921
                else:
922
                    # No parents - so give the Graph result (NULL_REVISION,).
923
                    revision_graph[d[0]] = (NULL_REVISION,)
924
            return revision_graph
925
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
926
    @needs_read_lock
927
    def get_signature_text(self, revision_id):
928
        self._ensure_real()
929
        return self._real_repository.get_signature_text(revision_id)
930
931
    @needs_read_lock
3228.4.11 by John Arbash Meinel
Deprecations abound.
932
    @symbol_versioning.deprecated_method(symbol_versioning.one_three)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
933
    def get_revision_graph_with_ghosts(self, revision_ids=None):
934
        self._ensure_real()
935
        return self._real_repository.get_revision_graph_with_ghosts(
936
            revision_ids=revision_ids)
937
938
    @needs_read_lock
939
    def get_inventory_xml(self, revision_id):
940
        self._ensure_real()
941
        return self._real_repository.get_inventory_xml(revision_id)
942
943
    def deserialise_inventory(self, revision_id, xml):
944
        self._ensure_real()
945
        return self._real_repository.deserialise_inventory(revision_id, xml)
946
947
    def reconcile(self, other=None, thorough=False):
948
        self._ensure_real()
949
        return self._real_repository.reconcile(other=other, thorough=thorough)
950
        
951
    def all_revision_ids(self):
952
        self._ensure_real()
953
        return self._real_repository.all_revision_ids()
954
    
955
    @needs_read_lock
956
    def get_deltas_for_revisions(self, revisions):
957
        self._ensure_real()
958
        return self._real_repository.get_deltas_for_revisions(revisions)
959
960
    @needs_read_lock
961
    def get_revision_delta(self, revision_id):
962
        self._ensure_real()
963
        return self._real_repository.get_revision_delta(revision_id)
964
965
    @needs_read_lock
966
    def revision_trees(self, revision_ids):
967
        self._ensure_real()
968
        return self._real_repository.revision_trees(revision_ids)
969
970
    @needs_read_lock
971
    def get_revision_reconcile(self, revision_id):
972
        self._ensure_real()
973
        return self._real_repository.get_revision_reconcile(revision_id)
974
975
    @needs_read_lock
2745.6.36 by Andrew Bennetts
Deprecate revision_ids arg to Repository.check and other tweaks.
976
    def check(self, revision_ids=None):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
977
        self._ensure_real()
2745.6.36 by Andrew Bennetts
Deprecate revision_ids arg to Repository.check and other tweaks.
978
        return self._real_repository.check(revision_ids=revision_ids)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
979
2018.5.138 by Robert Collins
Merge bzr.dev.
980
    def copy_content_into(self, destination, revision_id=None):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
981
        self._ensure_real()
982
        return self._real_repository.copy_content_into(
2018.5.138 by Robert Collins
Merge bzr.dev.
983
            destination, revision_id=revision_id)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
984
2814.10.2 by Andrew Bennetts
Make the fallback a little tidier.
985
    def _copy_repository_tarball(self, to_bzrdir, revision_id=None):
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
986
        # get a tarball of the remote repository, and copy from that into the
987
        # destination
988
        from bzrlib import osutils
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
989
        import tarfile
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
990
        import tempfile
2018.18.20 by Martin Pool
Route branch operations through remote copy_content_into
991
        # TODO: Maybe a progress bar while streaming the tarball?
992
        note("Copying repository content as tarball...")
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
993
        tar_file = self._get_tarball('bz2')
2814.10.2 by Andrew Bennetts
Make the fallback a little tidier.
994
        if tar_file is None:
995
            return None
996
        destination = to_bzrdir.create_repository()
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
997
        try:
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
998
            tar = tarfile.open('repository', fileobj=tar_file,
999
                mode='r|bz2')
1000
            tmpdir = tempfile.mkdtemp()
1001
            try:
1002
                _extract_tar(tar, tmpdir)
1003
                tmp_bzrdir = BzrDir.open(tmpdir)
1004
                tmp_repo = tmp_bzrdir.open_repository()
1005
                tmp_repo.copy_content_into(destination, revision_id)
1006
            finally:
1007
                osutils.rmtree(tmpdir)
2018.18.10 by Martin Pool
copy_content_into from Remote repositories by using temporary directories on both ends.
1008
        finally:
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
1009
            tar_file.close()
2814.10.2 by Andrew Bennetts
Make the fallback a little tidier.
1010
        return destination
2018.18.23 by Martin Pool
review cleanups
1011
        # TODO: Suggestion from john: using external tar is much faster than
1012
        # python's tarfile library, but it may not work on windows.
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1013
2604.2.1 by Robert Collins
(robertc) Introduce a pack command.
1014
    @needs_write_lock
1015
    def pack(self):
1016
        """Compress the data within the repository.
1017
1018
        This is not currently implemented within the smart server.
1019
        """
1020
        self._ensure_real()
1021
        return self._real_repository.pack()
1022
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1023
    def set_make_working_trees(self, new_value):
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
1024
        self._ensure_real()
1025
        self._real_repository.set_make_working_trees(new_value)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1026
1027
    @needs_write_lock
1028
    def sign_revision(self, revision_id, gpg_strategy):
1029
        self._ensure_real()
1030
        return self._real_repository.sign_revision(revision_id, gpg_strategy)
1031
1032
    @needs_read_lock
1033
    def get_revisions(self, revision_ids):
1034
        self._ensure_real()
1035
        return self._real_repository.get_revisions(revision_ids)
1036
1037
    def supports_rich_root(self):
2018.5.84 by Andrew Bennetts
Merge in supports-rich-root, another test passing.
1038
        self._ensure_real()
1039
        return self._real_repository.supports_rich_root()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1040
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
1041
    def iter_reverse_revision_history(self, revision_id):
1042
        self._ensure_real()
1043
        return self._real_repository.iter_reverse_revision_history(revision_id)
1044
2018.5.96 by Andrew Bennetts
Merge from bzr.dev, resolving the worst of the semantic conflicts, but there's
1045
    @property
1046
    def _serializer(self):
1047
        self._ensure_real()
1048
        return self._real_repository._serializer
1049
2018.5.97 by Andrew Bennetts
Fix more tests.
1050
    def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
1051
        self._ensure_real()
1052
        return self._real_repository.store_revision_signature(
1053
            gpg_strategy, plaintext, revision_id)
1054
2996.2.8 by Aaron Bentley
Fix add_signature discrepancies
1055
    def add_signature_text(self, revision_id, signature):
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
1056
        self._ensure_real()
2996.2.8 by Aaron Bentley
Fix add_signature discrepancies
1057
        return self._real_repository.add_signature_text(revision_id, signature)
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
1058
2018.5.97 by Andrew Bennetts
Fix more tests.
1059
    def has_signature_for_revision_id(self, revision_id):
1060
        self._ensure_real()
1061
        return self._real_repository.has_signature_for_revision_id(revision_id)
1062
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
1063
    def get_data_stream_for_search(self, search):
3313.2.1 by Andrew Bennetts
Change _SmartClient's API to accept a medium and a base, rather than a _SharedConnection.
1064
        medium = self._client._medium
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
1065
        if not medium._remote_is_at_least_1_2:
1066
            self._ensure_real()
1067
            return self._real_repository.get_data_stream_for_search(search)
2535.4.29 by Andrew Bennetts
Add a new smart method, Repository.stream_revisions_chunked, rather than changing the behaviour of an existing method.
1068
        REQUEST_NAME = 'Repository.stream_revisions_chunked'
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
1069
        path = self.bzrdir._path_for_remote_call(self._client)
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
1070
        body = self._serialise_search_recipe(search.get_recipe())
3297.3.3 by Andrew Bennetts
SmartClientRequestProtocol*.read_response_tuple can now raise UnknownSmartMethod. Callers no longer need to do their own ad hoc unknown smart method error detection.
1071
        try:
1072
            result = self._client.call_with_body_bytes_expecting_body(
1073
                REQUEST_NAME, (path,), body)
1074
            response, protocol = result
1075
        except errors.UnknownSmartMethod:
3213.1.2 by Andrew Bennetts
Add test for reconnection if get_parent_map is unknown by the server.
1076
            # Server does not support this method, so fall back to VFS.
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
1077
            # Worse, we have to force a disconnection, because the server now
1078
            # doesn't realise it has a body on the wire to consume, so the
1079
            # only way to recover is to abandon the connection.
3213.1.6 by Andrew Bennetts
Emit warnings when forcing a reconnect.
1080
            warning(
1081
                'Server is too old for streaming pull, reconnecting.  '
1082
                '(Upgrade the server to Bazaar 1.2 to avoid this)')
3213.1.1 by Andrew Bennetts
Recover (by reconnecting) if the server turns out not to understand the new requests in 1.2 that send bodies.
1083
            medium.disconnect()
1084
            # To avoid having to disconnect repeatedly, we keep track of the
1085
            # fact the server doesn't understand this remote method.
1086
            medium._remote_is_at_least_1_2 = False
1087
            self._ensure_real()
1088
            return self._real_repository.get_data_stream_for_search(search)
1089
2535.3.39 by Andrew Bennetts
Tidy some XXXs.
1090
        if response == ('ok',):
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
1091
            return self._deserialise_stream(protocol)
3184.1.10 by Robert Collins
Change the smart server verb for Repository.stream_revisions_chunked to use SearchResults as the request mechanism for downloads.
1092
        if response == ('NoSuchRevision', ):
1093
            # We cannot easily identify the revision that is missing in this
1094
            # situation without doing much more network IO. For now, bail.
1095
            raise NoSuchRevision(self, "unknown")
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
1096
        else:
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
1097
            raise errors.UnexpectedSmartServerResponse(response)
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
1098
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
1099
    def _deserialise_stream(self, protocol):
2535.4.11 by Andrew Bennetts
Merge from repo-refactor.
1100
        stream = protocol.read_streamed_body()
2535.4.15 by Andrew Bennetts
Remove 'PackSource' hack by using the ContainerPushParser.
1101
        container_parser = ContainerPushParser()
1102
        for bytes in stream:
1103
            container_parser.accept_bytes(bytes)
1104
            records = container_parser.read_pending_records()
1105
            for record_names, record_bytes in records:
2535.4.31 by Andrew Bennetts
Tweak in response to review comments.
1106
                if len(record_names) != 1:
2535.4.15 by Andrew Bennetts
Remove 'PackSource' hack by using the ContainerPushParser.
1107
                    # These records should have only one name, and that name
1108
                    # should be a one-element tuple.
1109
                    raise errors.SmartProtocolError(
1110
                        'Repository data stream had invalid record name %r'
1111
                        % (record_names,))
2535.4.31 by Andrew Bennetts
Tweak in response to review comments.
1112
                name_tuple = record_names[0]
2535.4.15 by Andrew Bennetts
Remove 'PackSource' hack by using the ContainerPushParser.
1113
                yield name_tuple, record_bytes
2535.3.68 by Andrew Bennetts
Backwards compatibility for new smart method.
1114
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
1115
    def insert_data_stream(self, stream):
1116
        self._ensure_real()
1117
        self._real_repository.insert_data_stream(stream)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
1118
2535.3.45 by Andrew Bennetts
Add item_keys_introduced_by to RemoteRepository.
1119
    def item_keys_introduced_by(self, revision_ids, _files_pb=None):
1120
        self._ensure_real()
1121
        return self._real_repository.item_keys_introduced_by(revision_ids,
1122
            _files_pb=_files_pb)
1123
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
1124
    def revision_graph_can_have_wrong_parents(self):
1125
        # The answer depends on the remote repo format.
1126
        self._ensure_real()
1127
        return self._real_repository.revision_graph_can_have_wrong_parents()
1128
2819.2.5 by Andrew Bennetts
Make reconcile abort gracefully if the revision index has bad parents.
1129
    def _find_inconsistent_revision_parents(self):
1130
        self._ensure_real()
1131
        return self._real_repository._find_inconsistent_revision_parents()
1132
1133
    def _check_for_inconsistent_revision_parents(self):
1134
        self._ensure_real()
1135
        return self._real_repository._check_for_inconsistent_revision_parents()
1136
3089.2.1 by Andrew Bennetts
Implement RemoteRepository._make_parents_provider.
1137
    def _make_parents_provider(self):
3172.5.1 by Robert Collins
Create a RemoteRepository get_graph implementation and delegate get_parents_map to the real repository.
1138
        return self
1139
3211.5.1 by Robert Collins
Change the smart server get_parents method to take a graph search to exclude already recieved parents from. This prevents history shortcuts causing huge numbers of duplicates.
1140
    def _serialise_search_recipe(self, recipe):
1141
        """Serialise a graph search recipe.
1142
1143
        :param recipe: A search recipe (start, stop, count).
1144
        :return: Serialised bytes.
1145
        """
1146
        start_keys = ' '.join(recipe[0])
1147
        stop_keys = ' '.join(recipe[1])
1148
        count = str(recipe[2])
1149
        return '\n'.join((start_keys, stop_keys, count))
1150
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1151
2018.5.127 by Andrew Bennetts
Fix most of the lockable_files tests for RemoteBranchLockableFiles.
1152
class RemoteBranchLockableFiles(LockableFiles):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1153
    """A 'LockableFiles' implementation that talks to a smart server.
1154
    
1155
    This is not a public interface class.
1156
    """
1157
1158
    def __init__(self, bzrdir, _client):
1159
        self.bzrdir = bzrdir
1160
        self._client = _client
2018.5.135 by Andrew Bennetts
Prevent remote branch clients from determining the 'right' mode for control files, because we don't want clients setting the mode anyway.
1161
        self._need_find_modes = True
2018.5.133 by Andrew Bennetts
All TestLockableFiles_RemoteLockDir tests passing.
1162
        LockableFiles.__init__(
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
1163
            self, bzrdir.get_branch_transport(None),
2018.5.133 by Andrew Bennetts
All TestLockableFiles_RemoteLockDir tests passing.
1164
            'lock', lockdir.LockDir)
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1165
2018.5.135 by Andrew Bennetts
Prevent remote branch clients from determining the 'right' mode for control files, because we don't want clients setting the mode anyway.
1166
    def _find_modes(self):
1167
        # RemoteBranches don't let the client set the mode of control files.
1168
        self._dir_mode = None
1169
        self._file_mode = None
1170
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1171
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1172
class RemoteBranchFormat(branch.BranchFormat):
1173
2018.5.124 by Robert Collins
Fix test_format_initialize_find_open by delegating Branch formt lookup to the BzrDir, where it should have stayed from the start.
1174
    def __eq__(self, other):
1175
        return (isinstance(other, RemoteBranchFormat) and 
1176
            self.__dict__ == other.__dict__)
1177
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
1178
    def get_format_description(self):
1179
        return 'Remote BZR Branch'
1180
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1181
    def get_format_string(self):
1182
        return 'Remote BZR Branch'
1183
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1184
    def open(self, a_bzrdir):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
1185
        return a_bzrdir.open_branch()
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1186
1187
    def initialize(self, a_bzrdir):
1188
        return a_bzrdir.create_branch()
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1189
2696.3.6 by Martin Pool
Mark RemoteBranch as (possibly) supporting tags
1190
    def supports_tags(self):
1191
        # Remote branches might support tags, but we won't know until we
1192
        # access the real remote branch.
1193
        return True
1194
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1195
1196
class RemoteBranch(branch.Branch):
1197
    """Branch stored on a server accessed by HPSS RPC.
1198
1199
    At the moment most operations are mapped down to simple file operations.
1200
    """
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
1201
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1202
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
1203
        _client=None):
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
1204
        """Create a RemoteBranch instance.
1205
1206
        :param real_branch: An optional local implementation of the branch
1207
            format, usually accessing the data via the VFS.
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1208
        :param _client: Private parameter for testing.
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
1209
        """
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
1210
        # We intentionally don't call the parent class's __init__, because it
1211
        # will try to assign to self.tags, which is a property in this subclass.
1212
        # And the parent's __init__ doesn't do much anyway.
2978.7.1 by John Arbash Meinel
Fix bug #162486, by having RemoteBranch properly initialize self._revision_id_to_revno_map.
1213
        self._revision_id_to_revno_cache = None
2018.5.105 by Andrew Bennetts
Implement revision_history caching for RemoteBranch.
1214
        self._revision_history_cache = None
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
1215
        self.bzrdir = remote_bzrdir
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1216
        if _client is not None:
1217
            self._client = _client
1218
        else:
3313.2.1 by Andrew Bennetts
Change _SmartClient's API to accept a medium and a base, rather than a _SharedConnection.
1219
            self._client = remote_bzrdir._client
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
1220
        self.repository = remote_repository
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
1221
        if real_branch is not None:
1222
            self._real_branch = real_branch
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1223
            # Give the remote repository the matching real repo.
2018.5.97 by Andrew Bennetts
Fix more tests.
1224
            real_repo = self._real_branch.repository
1225
            if isinstance(real_repo, RemoteRepository):
1226
                real_repo._ensure_real()
1227
                real_repo = real_repo._real_repository
1228
            self.repository._set_real_repository(real_repo)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1229
            # Give the branch the remote repository to let fast-pathing happen.
1230
            self._real_branch.repository = self.repository
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1231
        else:
1232
            self._real_branch = None
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
1233
        # Fill out expected attributes of branch for bzrlib api users.
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
1234
        self._format = RemoteBranchFormat()
2018.5.55 by Robert Collins
Give RemoteBranch a base url in line with the Branch protocol.
1235
        self.base = self.bzrdir.root_transport.base
2018.5.169 by Andrew Bennetts
Add a _server_formats flag to BzrDir.open_from_transport and BzrDirFormat.find_format, make RemoteBranch.control_files into a property.
1236
        self._control_files = None
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1237
        self._lock_mode = None
1238
        self._lock_token = None
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1239
        self._repo_lock_token = None
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1240
        self._lock_count = 0
1241
        self._leave_lock = False
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
1242
2477.1.1 by Martin Pool
Add RemoteBranch repr
1243
    def __str__(self):
1244
        return "%s(%s)" % (self.__class__.__name__, self.base)
1245
1246
    __repr__ = __str__
1247
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1248
    def _ensure_real(self):
1249
        """Ensure that there is a _real_branch set.
1250
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
1251
        Used before calls to self._real_branch.
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1252
        """
1253
        if not self._real_branch:
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1254
            if not vfs.vfs_enabled():
1255
                raise AssertionError('smart server vfs must be enabled '
1256
                    'to use vfs implementation')
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1257
            self.bzrdir._ensure_real()
1258
            self._real_branch = self.bzrdir._real_bzrdir.open_branch()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
1259
            # Give the remote repository the matching real repo.
2018.5.97 by Andrew Bennetts
Fix more tests.
1260
            real_repo = self._real_branch.repository
1261
            if isinstance(real_repo, RemoteRepository):
1262
                real_repo._ensure_real()
1263
                real_repo = real_repo._real_repository
1264
            self.repository._set_real_repository(real_repo)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
1265
            # Give the branch the remote repository to let fast-pathing happen.
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1266
            self._real_branch.repository = self.repository
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1267
            # XXX: deal with _lock_mode == 'w'
1268
            if self._lock_mode == 'r':
1269
                self._real_branch.lock_read()
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1270
2018.5.169 by Andrew Bennetts
Add a _server_formats flag to BzrDir.open_from_transport and BzrDirFormat.find_format, make RemoteBranch.control_files into a property.
1271
    @property
1272
    def control_files(self):
1273
        # Defer actually creating RemoteBranchLockableFiles until its needed,
1274
        # because it triggers an _ensure_real that we otherwise might not need.
1275
        if self._control_files is None:
1276
            self._control_files = RemoteBranchLockableFiles(
1277
                self.bzrdir, self._client)
1278
        return self._control_files
1279
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
1280
    def _get_checkout_format(self):
1281
        self._ensure_real()
1282
        return self._real_branch._get_checkout_format()
1283
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
1284
    def get_physical_lock_status(self):
1285
        """See Branch.get_physical_lock_status()."""
1286
        # should be an API call to the server, as branches must be lockable.
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1287
        self._ensure_real()
2018.5.60 by Robert Collins
More missing methods from RemoteBranch and RemoteRepository to let 'info' get further.
1288
        return self._real_branch.get_physical_lock_status()
1289
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1290
    def lock_read(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1291
        if not self._lock_mode:
1292
            self._lock_mode = 'r'
1293
            self._lock_count = 1
1294
            if self._real_branch is not None:
1295
                self._real_branch.lock_read()
1296
        else:
1297
            self._lock_count += 1
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1298
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1299
    def _remote_lock_write(self, token):
1300
        if token is None:
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1301
            branch_token = repo_token = ''
1302
        else:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1303
            branch_token = token
1304
            repo_token = self.repository.lock_write()
1305
            self.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1306
        path = self.bzrdir._path_for_remote_call(self._client)
1307
        response = self._client.call('Branch.lock_write', path, branch_token,
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
1308
                                     repo_token or '')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1309
        if response[0] == 'ok':
1310
            ok, branch_token, repo_token = response
1311
            return branch_token, repo_token
1312
        elif response[0] == 'LockContention':
1313
            raise errors.LockContention('(remote lock)')
1314
        elif response[0] == 'TokenMismatch':
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1315
            raise errors.TokenMismatch(token, '(remote token)')
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
1316
        elif response[0] == 'UnlockableTransport':
1317
            raise errors.UnlockableTransport(self.bzrdir.root_transport)
2018.5.123 by Robert Collins
Translate ReadOnlyError in RemoteBranch._remote_lock_write.
1318
        elif response[0] == 'ReadOnlyError':
1319
            raise errors.ReadOnlyError(self)
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
1320
        elif response[0] == 'LockFailed':
1321
            raise errors.LockFailed(response[1], response[2])
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1322
        else:
2555.1.1 by Martin Pool
Remove use of 'assert False' to raise an exception unconditionally
1323
            raise errors.UnexpectedSmartServerResponse(response)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1324
            
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1325
    def lock_write(self, token=None):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1326
        if not self._lock_mode:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1327
            remote_tokens = self._remote_lock_write(token)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1328
            self._lock_token, self._repo_lock_token = remote_tokens
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1329
            if not self._lock_token:
1330
                raise SmartProtocolError('Remote server did not return a token!')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1331
            # TODO: We really, really, really don't want to call _ensure_real
1332
            # here, but it's the easiest way to ensure coherency between the
1333
            # state of the RemoteBranch and RemoteRepository objects and the
1334
            # physical locks.  If we don't materialise the real objects here,
1335
            # then getting everything in the right state later is complex, so
1336
            # for now we just do it the lazy way.
1337
            #   -- Andrew Bennetts, 2007-02-22.
1338
            self._ensure_real()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1339
            if self._real_branch is not None:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1340
                self._real_branch.repository.lock_write(
1341
                    token=self._repo_lock_token)
1342
                try:
1343
                    self._real_branch.lock_write(token=self._lock_token)
1344
                finally:
1345
                    self._real_branch.repository.unlock()
1346
            if token is not None:
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1347
                self._leave_lock = True
1348
            else:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1349
                # XXX: this case seems to be unreachable; token cannot be None.
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1350
                self._leave_lock = False
1351
            self._lock_mode = 'w'
1352
            self._lock_count = 1
1353
        elif self._lock_mode == 'r':
1354
            raise errors.ReadOnlyTransaction
1355
        else:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
1356
            if token is not None:
1357
                # A token was given to lock_write, and we're relocking, so check
1358
                # that the given token actually matches the one we already have.
1359
                if token != self._lock_token:
1360
                    raise errors.TokenMismatch(token, self._lock_token)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1361
            self._lock_count += 1
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
1362
        return self._lock_token or None
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1363
1364
    def _unlock(self, branch_token, repo_token):
1365
        path = self.bzrdir._path_for_remote_call(self._client)
1366
        response = self._client.call('Branch.unlock', path, branch_token,
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
1367
                                     repo_token or '')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1368
        if response == ('ok',):
1369
            return
1370
        elif response[0] == 'TokenMismatch':
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1371
            raise errors.TokenMismatch(
1372
                str((branch_token, repo_token)), '(remote tokens)')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1373
        else:
2555.1.1 by Martin Pool
Remove use of 'assert False' to raise an exception unconditionally
1374
            raise errors.UnexpectedSmartServerResponse(response)
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1375
1376
    def unlock(self):
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1377
        self._lock_count -= 1
1378
        if not self._lock_count:
2018.5.105 by Andrew Bennetts
Implement revision_history caching for RemoteBranch.
1379
            self._clear_cached_state()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1380
            mode = self._lock_mode
1381
            self._lock_mode = None
1382
            if self._real_branch is not None:
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
1383
                if (not self._leave_lock and mode == 'w' and
1384
                    self._repo_lock_token):
2018.15.1 by Andrew Bennetts
All branch_implementations/test_locking tests passing.
1385
                    # If this RemoteBranch will remove the physical lock for the
1386
                    # repository, make sure the _real_branch doesn't do it
1387
                    # first.  (Because the _real_branch's repository is set to
1388
                    # be the RemoteRepository.)
1389
                    self._real_branch.repository.leave_lock_in_place()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1390
                self._real_branch.unlock()
1391
            if mode != 'w':
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
1392
                # Only write-locked branched need to make a remote method call
1393
                # to perfom the unlock.
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1394
                return
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1395
            if not self._lock_token:
1396
                raise AssertionError('Locked, but no token!')
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1397
            branch_token = self._lock_token
1398
            repo_token = self._repo_lock_token
1399
            self._lock_token = None
1400
            self._repo_lock_token = None
1401
            if not self._leave_lock:
1402
                self._unlock(branch_token, repo_token)
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1403
1404
    def break_lock(self):
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1405
        self._ensure_real()
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1406
        return self._real_branch.break_lock()
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
1407
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1408
    def leave_lock_in_place(self):
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
1409
        if not self._lock_token:
1410
            raise NotImplementedError(self.leave_lock_in_place)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1411
        self._leave_lock = True
1412
1413
    def dont_leave_lock_in_place(self):
3015.2.9 by Robert Collins
Handle repositories that do not allow remote locking, like pack repositories, in the client side remote server proxy objects.
1414
        if not self._lock_token:
3015.2.15 by Robert Collins
Review feedback.
1415
            raise NotImplementedError(self.dont_leave_lock_in_place)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
1416
        self._leave_lock = False
1417
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1418
    def last_revision_info(self):
1419
        """See Branch.last_revision_info()."""
1420
        path = self.bzrdir._path_for_remote_call(self._client)
1421
        response = self._client.call('Branch.last_revision_info', path)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1422
        if response[0] != 'ok':
1423
            raise SmartProtocolError('unexpected response code %s' % (response,))
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1424
        revno = int(response[1])
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
1425
        last_revision = response[2]
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1426
        return (revno, last_revision)
1427
2018.5.105 by Andrew Bennetts
Implement revision_history caching for RemoteBranch.
1428
    def _gen_revision_history(self):
1429
        """See Branch._gen_revision_history()."""
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
1430
        path = self.bzrdir._path_for_remote_call(self._client)
2018.5.153 by Andrew Bennetts
Rename call2 to call_expecting_body, and other small changes prompted by review.
1431
        response = self._client.call_expecting_body(
1432
            'Branch.revision_history', path)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1433
        if response[0][0] != 'ok':
1434
            raise SmartProtocolError('unexpected response code %s' % (response,))
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
1435
        result = response[1].read_body_bytes().split('\x00')
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
1436
        if result == ['']:
1437
            return []
1438
        return result
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
1439
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1440
    @needs_write_lock
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1441
    def set_revision_history(self, rev_history):
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1442
        # Send just the tip revision of the history; the server will generate
1443
        # the full history from that.  If the revision doesn't exist in this
1444
        # branch, NoSuchRevision will be raised.
1445
        path = self.bzrdir._path_for_remote_call(self._client)
1446
        if rev_history == []:
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
1447
            rev_id = 'null:'
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1448
        else:
1449
            rev_id = rev_history[-1]
2418.5.12 by John Arbash Meinel
Move functions from BzrBranch to base Branch object.
1450
        self._clear_cached_state()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1451
        response = self._client.call('Branch.set_last_revision',
1452
            path, self._lock_token, self._repo_lock_token, rev_id)
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
1453
        if response[0] == 'NoSuchRevision':
1454
            raise NoSuchRevision(self, rev_id)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
1455
        elif response[0] != 'ok':
1456
            raise SmartProtocolError('unexpected response code %s' % (response,))
2018.5.105 by Andrew Bennetts
Implement revision_history caching for RemoteBranch.
1457
        self._cache_revision_history(rev_history)
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1458
1459
    def get_parent(self):
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1460
        self._ensure_real()
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1461
        return self._real_branch.get_parent()
1462
        
1752.2.63 by Andrew Bennetts
Delegate set_parent.
1463
    def set_parent(self, url):
2018.5.70 by Robert Collins
Only try to get real repositories when an operation requires them.
1464
        self._ensure_real()
1752.2.63 by Andrew Bennetts
Delegate set_parent.
1465
        return self._real_branch.set_parent(url)
1466
        
2018.5.94 by Andrew Bennetts
Various small changes in aid of making tests pass (including deleting one invalid test).
1467
    def sprout(self, to_bzrdir, revision_id=None):
1468
        # Like Branch.sprout, except that it sprouts a branch in the default
1469
        # format, because RemoteBranches can't be created at arbitrary URLs.
1470
        # XXX: if to_bzrdir is a RemoteBranch, this should perhaps do
1471
        # to_bzrdir.create_branch...
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
1472
        self._ensure_real()
1473
        result = self._real_branch._format.initialize(to_bzrdir)
2018.18.20 by Martin Pool
Route branch operations through remote copy_content_into
1474
        self.copy_content_into(result, revision_id=revision_id)
2018.5.94 by Andrew Bennetts
Various small changes in aid of making tests pass (including deleting one invalid test).
1475
        result.set_parent(self.bzrdir.root_transport.base)
1476
        return result
1477
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1478
    @needs_write_lock
2477.1.2 by Martin Pool
Rename push/pull back to 'run_hooks' (jameinel)
1479
    def pull(self, source, overwrite=False, stop_revision=None,
2477.1.9 by Martin Pool
Review cleanups from John, mostly docs
1480
             **kwargs):
1481
        # FIXME: This asks the real branch to run the hooks, which means
1482
        # they're called with the wrong target branch parameter. 
1483
        # The test suite specifically allows this at present but it should be
1484
        # fixed.  It should get a _override_hook_target branch,
1485
        # as push does.  -- mbp 20070405
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1486
        self._ensure_real()
1487
        self._real_branch.pull(
2477.1.2 by Martin Pool
Rename push/pull back to 'run_hooks' (jameinel)
1488
            source, overwrite=overwrite, stop_revision=stop_revision,
1489
            **kwargs)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1490
2018.14.3 by Andrew Bennetts
Make a couple more branch_implementations tests pass.
1491
    @needs_read_lock
1492
    def push(self, target, overwrite=False, stop_revision=None):
1493
        self._ensure_real()
2018.5.97 by Andrew Bennetts
Fix more tests.
1494
        return self._real_branch.push(
2477.1.5 by Martin Pool
More cleanups of Branch.push to get the right behaviour with RemoteBranches
1495
            target, overwrite=overwrite, stop_revision=stop_revision,
1496
            _override_hook_source_branch=self)
2018.14.3 by Andrew Bennetts
Make a couple more branch_implementations tests pass.
1497
1498
    def is_locked(self):
1499
        return self._lock_count >= 1
1500
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1501
    @needs_write_lock
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
1502
    def set_last_revision_info(self, revno, revision_id):
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1503
        revision_id = ensure_null(revision_id)
1504
        path = self.bzrdir._path_for_remote_call(self._client)
3297.4.2 by Andrew Bennetts
Add backwards compatibility for servers older than 1.4.
1505
        try:
1506
            response = self._client.call('Branch.set_last_revision_info',
1507
                path, self._lock_token, self._repo_lock_token, str(revno), revision_id)
1508
        except errors.UnknownSmartMethod:
1509
            self._ensure_real()
1510
            self._clear_cached_state()
1511
            return self._real_branch.set_last_revision_info(revno, revision_id)
2892.2.1 by Andrew Bennetts
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
1512
        if response == ('ok',):
1513
            self._clear_cached_state()
1514
        elif response[0] == 'NoSuchRevision':
1515
            raise NoSuchRevision(self, response[1])
1516
        else:
1517
            raise errors.UnexpectedSmartServerResponse(response)
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
1518
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
1519
    def generate_revision_history(self, revision_id, last_rev=None,
1520
                                  other_branch=None):
1521
        self._ensure_real()
1522
        return self._real_branch.generate_revision_history(
1523
            revision_id, last_rev=last_rev, other_branch=other_branch)
1524
2018.5.96 by Andrew Bennetts
Merge from bzr.dev, resolving the worst of the semantic conflicts, but there's
1525
    @property
1526
    def tags(self):
1527
        self._ensure_real()
1528
        return self._real_branch.tags
1529
2018.5.97 by Andrew Bennetts
Fix more tests.
1530
    def set_push_location(self, location):
1531
        self._ensure_real()
1532
        return self._real_branch.set_push_location(location)
1533
3052.5.4 by John Arbash Meinel
If we are going to overwrite the target, we don't have to do
1534
    def update_revisions(self, other, stop_revision=None, overwrite=False):
2018.5.97 by Andrew Bennetts
Fix more tests.
1535
        self._ensure_real()
1536
        return self._real_branch.update_revisions(
3052.5.4 by John Arbash Meinel
If we are going to overwrite the target, we don't have to do
1537
            other, stop_revision=stop_revision, overwrite=overwrite)
2018.5.97 by Andrew Bennetts
Fix more tests.
1538
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
1539
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
1540
def _extract_tar(tar, to_dir):
1541
    """Extract all the contents of a tarfile object.
1542
1543
    A replacement for extractall, which is not present in python2.4
1544
    """
1545
    for tarinfo in tar:
1546
        tar.extract(tarinfo, to_dir)