/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 Canonical Ltd
 
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
 
 
17
# TODO: At some point, handle upgrades by just passing the whole request
 
18
# across to run on the server.
 
19
 
 
20
from urlparse import urlparse
 
21
 
 
22
from bzrlib import branch, errors, repository
 
23
from bzrlib.bzrdir import BzrDir, BzrDirFormat, RemoteBzrDirFormat
 
24
from bzrlib.branch import BranchReferenceFormat
 
25
from bzrlib.smart import client, vfs
 
26
from bzrlib.urlutils import unescape
 
27
 
 
28
# Note: RemoteBzrDirFormat is in bzrdir.py
 
29
 
 
30
class RemoteBzrDir(BzrDir):
 
31
    """Control directory on a remote server, accessed by HPSS."""
 
32
 
 
33
    def __init__(self, transport):
 
34
        BzrDir.__init__(self, transport, RemoteBzrDirFormat())
 
35
        self.client = transport.get_smart_client()
 
36
        # this object holds a delegated bzrdir that uses file-level operations
 
37
        # to talk to the other side
 
38
        # XXX: We should go into find_format, but not allow it to find
 
39
        # RemoteBzrDirFormat and make sure it finds the real underlying format.
 
40
        
 
41
        # THIS IS A COMPLETE AND UTTER LIE.
 
42
        # XXX: XXX: XXX: must be removed before merging to mainline
 
43
        # SMART_SERVER_MERGE_BLOCKER
 
44
        default_format = BzrDirFormat.get_default_format()
 
45
        self._real_bzrdir = default_format.open(transport, _found=True)
 
46
        smartclient = client.SmartClient(self.client)
 
47
        path = self._path_for_remote_call(smartclient)
 
48
        #self._real_bzrdir._format.probe_transport(transport)
 
49
        response = smartclient.call('probe_dont_use', path)
 
50
        if response == ('no',):
 
51
            raise errors.NotBranchError(path=transport.base)
 
52
        self._branch = None
 
53
 
 
54
    def create_repository(self, shared=False):
 
55
        return RemoteRepository(
 
56
            self, self._real_bzrdir.create_repository(shared=shared))
 
57
 
 
58
    def create_branch(self):
 
59
        real_branch = self._real_bzrdir.create_branch()
 
60
        real_repository = real_branch.repository
 
61
        remote_repository = RemoteRepository(self, real_repository)
 
62
        return RemoteBranch(self, remote_repository, real_branch)
 
63
 
 
64
    def create_workingtree(self, revision_id=None):
 
65
        real_workingtree = self._real_bzrdir.create_workingtree(revision_id=revision_id)
 
66
        return RemoteWorkingTree(self, real_workingtree)
 
67
 
 
68
    def open_branch(self, _unsupported=False):
 
69
        assert _unsupported == False, 'unsupported flag support not implemented yet.'
 
70
        smartclient = client.SmartClient(self.client)
 
71
        path = self._path_for_remote_call(smartclient)
 
72
        response = smartclient.call('BzrDir.open_branch', path)
 
73
        assert response[0] == 'ok', 'unexpected response code %s' % response[0]
 
74
        if response[0] != 'ok':
 
75
            # this should probably be a regular translate no ?
 
76
            raise errors.NotBranchError(path=self.root_transport.base)
 
77
        if response[1] == '':
 
78
            # branch at this location.
 
79
            if vfs.vfs_enabled():
 
80
                # if the VFS is enabled, create a local object using the VFS.
 
81
                real_branch = self._real_bzrdir.open_branch(unsupported=_unsupported)
 
82
                # This branch accessed through the smart server, so wrap the
 
83
                # file-level objects.
 
84
                real_repository = real_branch.repository
 
85
                remote_repository = RemoteRepository(self, real_repository)
 
86
                return RemoteBranch(self, remote_repository, real_branch)
 
87
            else:
 
88
                # otherwise just create a proxy for the branch.
 
89
                return RemoteBranch(self, self.find_repository())
 
90
        else:
 
91
            # a branch reference, use the existing BranchReference logic.
 
92
            format = BranchReferenceFormat()
 
93
            return format.open(self, _found=True, location=response[1])
 
94
 
 
95
    def open_repository(self):
 
96
        smartclient = client.SmartClient(self.client)
 
97
        path = self._path_for_remote_call(smartclient)
 
98
        response = smartclient.call('BzrDir.find_repository', path)
 
99
        assert response[0] in ('ok', 'norepository'), \
 
100
            'unexpected response code %s' % response[0]
 
101
        if response[0] == 'norepository':
 
102
            raise errors.NoRepositoryPresent(self)
 
103
        if response[1] == '':
 
104
            if vfs.vfs_enabled():
 
105
                return RemoteRepository(self, self._real_bzrdir.open_repository())
 
106
            else:
 
107
                return RemoteRepository(self)
 
108
        else:
 
109
            raise errors.NoRepositoryPresent(self)
 
110
 
 
111
    def open_workingtree(self):
 
112
        return RemoteWorkingTree(self, self._real_bzrdir.open_workingtree())
 
113
 
 
114
    def _path_for_remote_call(self, client):
 
115
        """Return the path to be used for this bzrdir in a remote call."""
 
116
        return client.remote_path_from_transport(self.root_transport)
 
117
 
 
118
    def get_branch_transport(self, branch_format):
 
119
        return self._real_bzrdir.get_branch_transport(branch_format)
 
120
 
 
121
    def get_repository_transport(self, repository_format):
 
122
        return self._real_bzrdir.get_repository_transport(repository_format)
 
123
 
 
124
    def get_workingtree_transport(self, workingtree_format):
 
125
        return self._real_bzrdir.get_workingtree_transport(workingtree_format)
 
126
 
 
127
    def can_convert_format(self):
 
128
        """Upgrading of remote bzrdirs is not supported yet."""
 
129
        return False
 
130
 
 
131
    def needs_format_conversion(self, format=None):
 
132
        """Upgrading of remote bzrdirs is not supported yet."""
 
133
        return False
 
134
 
 
135
 
 
136
class RemoteRepositoryFormat(repository.RepositoryFormat):
 
137
    """Format for repositories accessed over rpc.
 
138
 
 
139
    Instances of this repository are represented by RemoteRepository
 
140
    instances.
 
141
    """
 
142
 
 
143
    _matchingbzrdir = RemoteBzrDirFormat
 
144
 
 
145
    def initialize(self, a_bzrdir, shared=False):
 
146
        assert isinstance(a_bzrdir, RemoteBzrDir)
 
147
        return a_bzrdir.create_repository(shared=shared)
 
148
    
 
149
    def open(self, a_bzrdir):
 
150
        assert isinstance(a_bzrdir, RemoteBzrDir)
 
151
        return a_bzrdir.open_repository()
 
152
 
 
153
    def get_format_description(self):
 
154
        return 'bzr remote repository'
 
155
 
 
156
    def __eq__(self, other):
 
157
        return self.__class__ == other.__class__
 
158
 
 
159
    rich_root_data = False
 
160
 
 
161
 
 
162
class RemoteRepository(object):
 
163
    """Repository accessed over rpc.
 
164
 
 
165
    For the moment everything is delegated to IO-like operations over
 
166
    the transport.
 
167
    """
 
168
 
 
169
    def __init__(self, remote_bzrdir, real_repository=None):
 
170
        """Create a RemoteRepository instance.
 
171
        
 
172
        :param remote_bzrdir: The bzrdir hosting this repository.
 
173
        :param real_repository: If not None, a local implementation of the
 
174
            repository logic for the repository, usually accessing the data
 
175
            via the VFS.
 
176
        """
 
177
        if real_repository:
 
178
            self._real_repository = real_repository
 
179
        self.bzrdir = remote_bzrdir
 
180
        self._client = client.SmartClient(self.bzrdir.client)
 
181
        self._format = RemoteRepositoryFormat()
 
182
 
 
183
    def has_revision(self, revision_id):
 
184
        """See Repository.has_revision()."""
 
185
        path = self.bzrdir._path_for_remote_call(self._client)
 
186
        response = self._client.call('Repository.has_revision', path, revision_id.encode('utf8'))
 
187
        assert response[0] in ('ok', 'no'), 'unexpected response code %s' % response[0]
 
188
        return response[0] == 'ok'
 
189
 
 
190
 
 
191
class RemoteBranchFormat(branch.BranchFormat):
 
192
 
 
193
    def open(self, a_bzrdir):
 
194
        assert isinstance(a_bzrdir, RemoteBzrDir)
 
195
        return a_bzrdir.open_branch()
 
196
 
 
197
    def initialize(self, a_bzrdir):
 
198
        assert isinstance(a_bzrdir, RemoteBzrDir)
 
199
        return a_bzrdir.create_branch()
 
200
 
 
201
 
 
202
class RemoteBranch(branch.Branch):
 
203
    """Branch stored on a server accessed by HPSS RPC.
 
204
 
 
205
    At the moment most operations are mapped down to simple file operations.
 
206
    """
 
207
 
 
208
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None):
 
209
        """Create a RemoteBranch instance.
 
210
 
 
211
        :param real_branch: An optional local implementation of the branch
 
212
            format, usually accessing the data via the VFS.
 
213
        """
 
214
        self.bzrdir = remote_bzrdir
 
215
        self._client = client.SmartClient(self.bzrdir.client)
 
216
        self.repository = remote_repository
 
217
        if real_branch is not None:
 
218
            self._real_branch = real_branch
 
219
        self._format = RemoteBranchFormat()
 
220
 
 
221
    def lock_read(self):
 
222
        return self._real_branch.lock_read()
 
223
 
 
224
    def lock_write(self):
 
225
        return self._real_branch.lock_write()
 
226
 
 
227
    def unlock(self):
 
228
        return self._real_branch.unlock()
 
229
 
 
230
    def break_lock(self):
 
231
        return self._real_branch.break_lock()
 
232
 
 
233
    def revision_history(self):
 
234
        """See Branch.revision_history()."""
 
235
        # XXX: TODO: this does not cache the revision history for the duration
 
236
        # of a lock, which is a bug - see the code for regular branches
 
237
        # for details.
 
238
        path = self.bzrdir._path_for_remote_call(self._client)
 
239
        response = self._client.call2('Branch.revision_history', path)
 
240
        assert response[0][0] == 'ok', 'unexpected response code %s' % response[0]
 
241
        result = response[1].read_body_bytes().decode('utf8').split('\x00')
 
242
        if result == ['']:
 
243
            return []
 
244
        return result
 
245
 
 
246
    def set_revision_history(self, rev_history):
 
247
        return self._real_branch.set_revision_history(rev_history)
 
248
 
 
249
    def get_parent(self):
 
250
        return self._real_branch.get_parent()
 
251
        
 
252
    def set_parent(self, url):
 
253
        return self._real_branch.set_parent(url)
 
254
        
 
255
 
 
256
class RemoteWorkingTree(object):
 
257
 
 
258
    def __init__(self, remote_bzrdir, real_workingtree):
 
259
        self.real_workingtree = real_workingtree
 
260
        self.bzrdir = remote_bzrdir
 
261
 
 
262
    def __getattr__(self, name):
 
263
        # XXX: temporary way to lazily delegate everything to the real
 
264
        # workingtree
 
265
        return getattr(self.real_workingtree, name)
 
266
 
 
267