/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 bzr.dev (via NO_SMART_VFS branch).

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