/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1
# Copyright (C) 2006, 2007 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
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.
20
from urlparse import urlparse
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
21
2018.5.25 by Andrew Bennetts
Make sure RemoteBzrDirFormat is always registered (John Arbash Meinel, Robert Collins, Andrew Bennetts).
22
from bzrlib import branch, errors, repository
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
23
from bzrlib.branch import BranchReferenceFormat
2018.5.25 by Andrew Bennetts
Make sure RemoteBzrDirFormat is always registered (John Arbash Meinel, Robert Collins, Andrew Bennetts).
24
from bzrlib.bzrdir import BzrDir, BzrDirFormat, RemoteBzrDirFormat
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
25
from bzrlib.revision import NULL_REVISION
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
26
from bzrlib.smart import client, vfs
2018.5.32 by Robert Collins
Unescape urls before handing over the wire to the smart server for the probe_transport method.
27
from bzrlib.urlutils import unescape
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
28
2018.5.25 by Andrew Bennetts
Make sure RemoteBzrDirFormat is always registered (John Arbash Meinel, Robert Collins, Andrew Bennetts).
29
# Note: RemoteBzrDirFormat is in bzrdir.py
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
30
31
class RemoteBzrDir(BzrDir):
32
    """Control directory on a remote server, accessed by HPSS."""
33
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
34
    def __init__(self, transport, _client=None):
35
        """Construct a RemoteBzrDir.
36
37
        :param _client: Private parameter for testing. Disables probing and the
38
            use of a real bzrdir.
39
        """
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
40
        BzrDir.__init__(self, transport, RemoteBzrDirFormat())
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
41
        if _client is not None:
42
            self.client = _client
43
            return
44
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
45
        self.client = transport.get_smart_client()
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
46
        # this object holds a delegated bzrdir that uses file-level operations
47
        # to talk to the other side
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
48
        # XXX: We should go into find_format, but not allow it to find
49
        # RemoteBzrDirFormat and make sure it finds the real underlying format.
50
        
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
51
        # THIS IS A COMPLETE AND UTTER LIE.
52
        # XXX: XXX: XXX: must be removed before merging to mainline
53
        # SMART_SERVER_MERGE_BLOCKER
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
54
        default_format = BzrDirFormat.get_default_format()
55
        self._real_bzrdir = default_format.open(transport, _found=True)
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
56
        smartclient = client.SmartClient(self.client)
57
        path = self._path_for_remote_call(smartclient)
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.
58
        #self._real_bzrdir._format.probe_transport(transport)
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
59
        response = smartclient.call('probe_dont_use', path)
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.
60
        if response == ('no',):
61
            raise errors.NotBranchError(path=transport.base)
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
62
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
63
    def create_repository(self, shared=False):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
64
        return RemoteRepository(
65
            self, self._real_bzrdir.create_repository(shared=shared))
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
66
67
    def create_branch(self):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
68
        real_branch = self._real_bzrdir.create_branch()
69
        real_repository = real_branch.repository
70
        remote_repository = RemoteRepository(self, real_repository)
71
        return RemoteBranch(self, remote_repository, real_branch)
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
72
73
    def create_workingtree(self, revision_id=None):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
74
        real_workingtree = self._real_bzrdir.create_workingtree(revision_id=revision_id)
75
        return RemoteWorkingTree(self, real_workingtree)
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
76
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
77
    def open_branch(self, _unsupported=False):
78
        assert _unsupported == False, 'unsupported flag support not implemented yet.'
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
79
        smartclient = client.SmartClient(self.client)
80
        path = self._path_for_remote_call(smartclient)
81
        response = smartclient.call('BzrDir.open_branch', path)
2018.5.52 by Wouter van Heyst
Provide more information when encountering unexpected responses from a smart
82
        assert response[0] == 'ok', 'unexpected response code %s' % (response,)
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
83
        if response[0] != 'ok':
84
            # this should probably be a regular translate no ?
85
            raise errors.NotBranchError(path=self.root_transport.base)
86
        if response[1] == '':
87
            # branch at this location.
88
            if vfs.vfs_enabled():
89
                # if the VFS is enabled, create a local object using the VFS.
90
                real_branch = self._real_bzrdir.open_branch(unsupported=_unsupported)
91
                # This branch accessed through the smart server, so wrap the
92
                # file-level objects.
93
                real_repository = real_branch.repository
94
                remote_repository = RemoteRepository(self, real_repository)
95
                return RemoteBranch(self, remote_repository, real_branch)
96
            else:
97
                # otherwise just create a proxy for the branch.
98
                return RemoteBranch(self, self.find_repository())
99
        else:
100
            # a branch reference, use the existing BranchReference logic.
101
            format = BranchReferenceFormat()
102
            return format.open(self, _found=True, location=response[1])
103
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
104
    def open_repository(self):
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
105
        smartclient = client.SmartClient(self.client)
106
        path = self._path_for_remote_call(smartclient)
107
        response = smartclient.call('BzrDir.find_repository', path)
108
        assert response[0] in ('ok', 'norepository'), \
2018.5.52 by Wouter van Heyst
Provide more information when encountering unexpected responses from a smart
109
            'unexpected response code %s' % (response,)
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
110
        if response[0] == 'norepository':
111
            raise errors.NoRepositoryPresent(self)
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
112
        if response[1] == '':
113
            if vfs.vfs_enabled():
114
                return RemoteRepository(self, self._real_bzrdir.open_repository())
115
            else:
116
                return RemoteRepository(self)
117
        else:
118
            raise errors.NoRepositoryPresent(self)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
119
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
120
    def open_workingtree(self):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
121
        return RemoteWorkingTree(self, self._real_bzrdir.open_workingtree())
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
122
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
123
    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.
124
        """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 :).
125
        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.
126
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
127
    def get_branch_transport(self, branch_format):
128
        return self._real_bzrdir.get_branch_transport(branch_format)
129
1752.2.43 by Andrew Bennetts
Fix get_{branch,repository,workingtree}_transport.
130
    def get_repository_transport(self, repository_format):
131
        return self._real_bzrdir.get_repository_transport(repository_format)
132
133
    def get_workingtree_transport(self, workingtree_format):
134
        return self._real_bzrdir.get_workingtree_transport(workingtree_format)
135
1752.2.39 by Martin Pool
[broken] implement upgrade apis on remote bzrdirs
136
    def can_convert_format(self):
137
        """Upgrading of remote bzrdirs is not supported yet."""
138
        return False
139
140
    def needs_format_conversion(self, format=None):
141
        """Upgrading of remote bzrdirs is not supported yet."""
142
        return False
143
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
144
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
145
class RemoteRepositoryFormat(repository.RepositoryFormat):
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
146
    """Format for repositories accessed over rpc.
147
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
148
    Instances of this repository are represented by RemoteRepository
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
149
    instances.
150
    """
151
152
    _matchingbzrdir = RemoteBzrDirFormat
153
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
154
    def initialize(self, a_bzrdir, shared=False):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
155
        assert isinstance(a_bzrdir, RemoteBzrDir)
156
        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.
157
    
158
    def open(self, a_bzrdir):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
159
        assert isinstance(a_bzrdir, RemoteBzrDir)
160
        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.
161
162
    def get_format_description(self):
163
        return 'bzr remote repository'
164
165
    def __eq__(self, other):
1752.2.87 by Andrew Bennetts
Make tests pass.
166
        return self.__class__ == other.__class__
167
168
    rich_root_data = False
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
169
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
170
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
171
class RemoteRepository(object):
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
172
    """Repository accessed over rpc.
173
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
174
    For the moment everything is delegated to IO-like operations over
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
175
    the transport.
176
    """
177
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
178
    def __init__(self, remote_bzrdir, real_repository=None):
179
        """Create a RemoteRepository instance.
180
        
181
        :param remote_bzrdir: The bzrdir hosting this repository.
182
        :param real_repository: If not None, a local implementation of the
183
            repository logic for the repository, usually accessing the data
184
            via the VFS.
185
        """
186
        if real_repository:
2018.5.36 by Andrew Bennetts
Fix typo, and clean up some ununsed import warnings from pyflakes at the same time.
187
            self._real_repository = real_repository
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
188
        self.bzrdir = remote_bzrdir
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
189
        self._client = client.SmartClient(self.bzrdir.client)
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
190
        self._format = RemoteRepositoryFormat()
191
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
192
    def has_revision(self, revision_id):
193
        """See Repository.has_revision()."""
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
194
        path = self.bzrdir._path_for_remote_call(self._client)
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
195
        response = self._client.call('Repository.has_revision', path, revision_id.encode('utf8'))
2018.5.52 by Wouter van Heyst
Provide more information when encountering unexpected responses from a smart
196
        assert response[0] in ('ok', 'no'), 'unexpected response code %s' % (response,)
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
197
        return response[0] == 'ok'
198
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
199
200
class RemoteBranchFormat(branch.BranchFormat):
201
202
    def open(self, a_bzrdir):
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
203
        assert isinstance(a_bzrdir, RemoteBzrDir)
204
        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.
205
206
    def initialize(self, a_bzrdir):
207
        assert isinstance(a_bzrdir, RemoteBzrDir)
208
        return a_bzrdir.create_branch()
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
209
210
211
class RemoteBranch(branch.Branch):
212
    """Branch stored on a server accessed by HPSS RPC.
213
214
    At the moment most operations are mapped down to simple file operations.
215
    """
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
216
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
217
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
218
        _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.
219
        """Create a RemoteBranch instance.
220
221
        :param real_branch: An optional local implementation of the branch
222
            format, usually accessing the data via the VFS.
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
223
        :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.
224
        """
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
225
        self.bzrdir = remote_bzrdir
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
226
        if _client is not None:
227
            self._client = _client
228
        else:
229
            self._client = client.SmartClient(self.bzrdir.client)
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
230
        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.
231
        if real_branch is not None:
232
            self._real_branch = real_branch
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
233
        self._format = RemoteBranchFormat()
2018.5.55 by Robert Collins
Give RemoteBranch a base url in line with the Branch protocol.
234
        self.base = self.bzrdir.root_transport.base
1752.2.64 by Andrew Bennetts
Improve how RemoteBzrDir.open_branch works to handle references and not double-open repositories.
235
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
236
    def lock_read(self):
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
237
        return self._real_branch.lock_read()
238
239
    def lock_write(self):
240
        return self._real_branch.lock_write()
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
241
242
    def unlock(self):
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
243
        return self._real_branch.unlock()
244
245
    def break_lock(self):
246
        return self._real_branch.break_lock()
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
247
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
248
    def last_revision_info(self):
249
        """See Branch.last_revision_info()."""
250
        path = self.bzrdir._path_for_remote_call(self._client)
251
        response = self._client.call('Branch.last_revision_info', path)
2018.5.52 by Wouter van Heyst
Provide more information when encountering unexpected responses from a smart
252
        assert response[0] == 'ok', 'unexpected response code %s' % (response,)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
253
        revno = int(response[1])
254
        last_revision = response[2].decode('utf8')
255
        if last_revision == '':
256
            last_revision = NULL_REVISION
257
        return (revno, last_revision)
258
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
259
    def revision_history(self):
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
260
        """See Branch.revision_history()."""
261
        # XXX: TODO: this does not cache the revision history for the duration
262
        # of a lock, which is a bug - see the code for regular branches
263
        # for details.
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
264
        path = self.bzrdir._path_for_remote_call(self._client)
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
265
        response = self._client.call2('Branch.revision_history', path)
2018.5.52 by Wouter van Heyst
Provide more information when encountering unexpected responses from a smart
266
        assert response[0][0] == 'ok', 'unexpected response code %s' % (response[0],)
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
267
        result = response[1].read_body_bytes().decode('utf8').split('\x00')
268
        if result == ['']:
269
            return []
270
        return result
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
271
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
272
    def set_revision_history(self, rev_history):
273
        return self._real_branch.set_revision_history(rev_history)
274
275
    def get_parent(self):
276
        return self._real_branch.get_parent()
277
        
1752.2.63 by Andrew Bennetts
Delegate set_parent.
278
    def set_parent(self, url):
279
        return self._real_branch.set_parent(url)
280
        
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
281
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
282
class RemoteWorkingTree(object):
283
1752.2.72 by Andrew Bennetts
Make Remote* classes in remote.py more consistent and remove some dead code.
284
    def __init__(self, remote_bzrdir, real_workingtree):
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
285
        self.real_workingtree = real_workingtree
286
        self.bzrdir = remote_bzrdir
287
288
    def __getattr__(self, name):
289
        # XXX: temporary way to lazily delegate everything to the real
290
        # workingtree
291
        return getattr(self.real_workingtree, name)
292
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
293