~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/bzrdir.py

  • Committer: Martin Pool
  • Date: 2009-03-13 07:54:48 UTC
  • mfrom: (4144 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4189.
  • Revision ID: mbp@sourcefrog.net-20090313075448-jlz1t7baz7gzipqn
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Server-side bzrdir related request implmentations."""
18
18
 
19
19
 
20
 
from bzrlib import errors
21
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat
 
20
from bzrlib import branch, errors, repository
 
21
from bzrlib.bzrdir import BzrDir, BzrDirFormat, BzrDirMetaFormat1
22
22
from bzrlib.smart.request import (
23
23
    FailedSmartServerResponse,
24
24
    SmartServerRequest,
51
51
        return SuccessfulSmartServerResponse((answer,))
52
52
 
53
53
 
54
 
class SmartServerRequestFindRepository(SmartServerRequest):
 
54
class SmartServerRequestBzrDir(SmartServerRequest):
 
55
 
 
56
    def do(self, path, *args):
 
57
        """Open a BzrDir at path, and return self.do_bzrdir_request(*args)."""
 
58
        try:
 
59
            self._bzrdir = BzrDir.open_from_transport(
 
60
                self.transport_from_client_path(path))
 
61
        except errors.NotBranchError:
 
62
            return FailedSmartServerResponse(('nobranch', ))
 
63
        return self.do_bzrdir_request(*args)
55
64
 
56
65
    def _boolean_to_yes_no(self, a_boolean):
57
66
        if a_boolean:
59
68
        else:
60
69
            return 'no'
61
70
 
62
 
    def _find(self, path):
63
 
        """try to find a repository from path upwards
64
 
        
65
 
        This operates precisely like 'bzrdir.find_repository'.
66
 
        
67
 
        :return: (relpath, rich_root, tree_ref, external_lookup) flags. All are
68
 
            strings, relpath is a / prefixed path, and the other three are
69
 
            either 'yes' or 'no'.
70
 
        :raises errors.NoRepositoryPresent: When there is no repository
71
 
            present.
72
 
        """
73
 
        bzrdir = BzrDir.open_from_transport(
74
 
            self.transport_from_client_path(path))
75
 
        repository = bzrdir.find_repository()
76
 
        # the relpath of the bzrdir in the found repository gives us the 
 
71
    def _format_to_capabilities(self, repo_format):
 
72
        rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
 
73
        tree_ref = self._boolean_to_yes_no(
 
74
            repo_format.supports_tree_reference)
 
75
        external_lookup = self._boolean_to_yes_no(
 
76
            repo_format.supports_external_lookups)
 
77
        return rich_root, tree_ref, external_lookup
 
78
 
 
79
    def _repo_relpath(self, current_transport, repository):
 
80
        """Get the relative path for repository from current_transport."""
 
81
        # the relpath of the bzrdir in the found repository gives us the
77
82
        # path segments to pop-out.
78
83
        relpath = repository.bzrdir.root_transport.relpath(
79
 
            bzrdir.root_transport.base)
 
84
            current_transport.base)
80
85
        if len(relpath):
81
86
            segments = ['..'] * len(relpath.split('/'))
82
87
        else:
83
88
            segments = []
84
 
        rich_root = self._boolean_to_yes_no(repository.supports_rich_root())
85
 
        tree_ref = self._boolean_to_yes_no(
86
 
            repository._format.supports_tree_reference)
87
 
        external_lookup = self._boolean_to_yes_no(
88
 
            repository._format.supports_external_lookups)
89
 
        return '/'.join(segments), rich_root, tree_ref, external_lookup
 
89
        return '/'.join(segments)
 
90
 
 
91
 
 
92
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
 
93
 
 
94
    def do_bzrdir_request(self, require_stacking):
 
95
        """Get the format that should be used when cloning from this dir."""
 
96
        try:
 
97
            branch_ref = self._bzrdir.get_branch_reference()
 
98
        except errors.NotBranchError:
 
99
            branch_ref = None
 
100
        if require_stacking == "True":
 
101
            require_stacking = True
 
102
        else:
 
103
            require_stacking = False
 
104
        control_format = self._bzrdir.cloning_metadir(
 
105
            require_stacking=require_stacking)
 
106
        control_name = control_format.network_name()
 
107
        # XXX: There should be a method that tells us that the format does/does not
 
108
        # have subformats.
 
109
        if isinstance(control_format, BzrDirMetaFormat1):
 
110
            if branch_ref is not None:
 
111
                # If there's a branch reference, the client will have to resolve
 
112
                # the branch reference to figure out the cloning metadir
 
113
                branch_name = ('ref', branch_ref)
 
114
            else:
 
115
                branch_name = ('branch',
 
116
                    control_format.get_branch_format().network_name())
 
117
            repository_name = control_format.repository_format.network_name()
 
118
        else:
 
119
            # Only MetaDir has delegated formats today.
 
120
            branch_name = ('branch', '')
 
121
            repository_name = ''
 
122
        return SuccessfulSmartServerResponse((control_name, repository_name,
 
123
            branch_name))
 
124
 
 
125
 
 
126
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
 
127
 
 
128
    def do(self, path, network_name):
 
129
        """Create a branch in the bzr dir at path.
 
130
 
 
131
        This operates precisely like 'bzrdir.create_branch'.
 
132
 
 
133
        If a bzrdir is not present, an exception is propogated
 
134
        rather than 'no branch' because these are different conditions (and
 
135
        this method should only be called after establishing that a bzr dir
 
136
        exists anyway).
 
137
 
 
138
        This is the initial version of this method introduced to the smart
 
139
        server for 1.13.
 
140
 
 
141
        :param path: The path to the bzrdir.
 
142
        :param network_name: The network name of the branch type to create.
 
143
        :return: (ok, network_name)
 
144
        """
 
145
        bzrdir = BzrDir.open_from_transport(
 
146
            self.transport_from_client_path(path))
 
147
        format = branch.network_format_registry.get(network_name)
 
148
        bzrdir.branch_format = format
 
149
        result = format.initialize(bzrdir)
 
150
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
151
            result.repository._format)
 
152
        branch_format = result._format.network_name()
 
153
        repo_format = result.repository._format.network_name()
 
154
        repo_path = self._repo_relpath(bzrdir.root_transport,
 
155
            result.repository)
 
156
        # branch format, repo relpath, rich_root, tree_ref, external_lookup,
 
157
        # repo_network_name
 
158
        return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
 
159
            rich_root, tree_ref, external_lookup, repo_format))
 
160
 
 
161
 
 
162
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
 
163
 
 
164
    def do(self, path, network_name, shared):
 
165
        """Create a repository in the bzr dir at path.
 
166
 
 
167
        This operates precisely like 'bzrdir.create_repository'.
 
168
 
 
169
        If a bzrdir is not present, an exception is propogated
 
170
        rather than 'no branch' because these are different conditions (and
 
171
        this method should only be called after establishing that a bzr dir
 
172
        exists anyway).
 
173
 
 
174
        This is the initial version of this method introduced to the smart
 
175
        server for 1.13.
 
176
 
 
177
        :param path: The path to the bzrdir.
 
178
        :param network_name: The network name of the repository type to create.
 
179
        :param shared: The value to pass create_repository for the shared
 
180
            parameter.
 
181
        :return: (ok, rich_root, tree_ref, external_lookup, network_name)
 
182
        """
 
183
        bzrdir = BzrDir.open_from_transport(
 
184
            self.transport_from_client_path(path))
 
185
        shared = shared == 'True'
 
186
        format = repository.network_format_registry.get(network_name)
 
187
        bzrdir.repository_format = format
 
188
        result = format.initialize(bzrdir, shared=shared)
 
189
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
190
            result._format)
 
191
        return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
 
192
            external_lookup, result._format.network_name()))
 
193
 
 
194
 
 
195
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
 
196
 
 
197
    def _find(self, path):
 
198
        """try to find a repository from path upwards
 
199
 
 
200
        This operates precisely like 'bzrdir.find_repository'.
 
201
 
 
202
        :return: (relpath, rich_root, tree_ref, external_lookup, network_name).
 
203
            All are strings, relpath is a / prefixed path, the next three are
 
204
            either 'yes' or 'no', and the last is a repository format network
 
205
            name.
 
206
        :raises errors.NoRepositoryPresent: When there is no repository
 
207
            present.
 
208
        """
 
209
        bzrdir = BzrDir.open_from_transport(
 
210
            self.transport_from_client_path(path))
 
211
        repository = bzrdir.find_repository()
 
212
        path = self._repo_relpath(bzrdir.root_transport, repository)
 
213
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
214
            repository._format)
 
215
        network_name = repository._format.network_name()
 
216
        return path, rich_root, tree_ref, external_lookup, network_name
90
217
 
91
218
 
92
219
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
93
220
 
94
221
    def do(self, path):
95
222
        """try to find a repository from path upwards
96
 
        
 
223
 
97
224
        This operates precisely like 'bzrdir.find_repository'.
98
 
        
 
225
 
99
226
        If a bzrdir is not present, an exception is propogated
100
227
        rather than 'no branch' because these are different conditions.
101
228
 
106
233
        :return: norepository or ok, relpath.
107
234
        """
108
235
        try:
109
 
            path, rich_root, tree_ref, external_lookup = self._find(path)
 
236
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
110
237
            return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
111
238
        except errors.NoRepositoryPresent:
112
239
            return FailedSmartServerResponse(('norepository', ))
116
243
 
117
244
    def do(self, path):
118
245
        """try to find a repository from path upwards
119
 
        
 
246
 
120
247
        This operates precisely like 'bzrdir.find_repository'.
121
 
        
 
248
 
122
249
        If a bzrdir is not present, an exception is propogated
123
250
        rather than 'no branch' because these are different conditions.
124
251
 
126
253
        returns information about the supports_external_lookups format
127
254
        attribute too.
128
255
 
129
 
        :return: norepository or ok, relpath.
 
256
        :return: norepository or ok, relpath, rich_root, tree_ref,
 
257
            external_lookup.
130
258
        """
131
259
        try:
132
 
            path, rich_root, tree_ref, external_lookup = self._find(path)
 
260
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
133
261
            return SuccessfulSmartServerResponse(
134
262
                ('ok', path, rich_root, tree_ref, external_lookup))
135
263
        except errors.NoRepositoryPresent:
136
264
            return FailedSmartServerResponse(('norepository', ))
137
265
 
138
266
 
 
267
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
 
268
 
 
269
    def do(self, path):
 
270
        """try to find a repository from path upwards
 
271
 
 
272
        This operates precisely like 'bzrdir.find_repository'.
 
273
 
 
274
        If a bzrdir is not present, an exception is propogated
 
275
        rather than 'no branch' because these are different conditions.
 
276
 
 
277
        This is the third edition of this method introduced in bzr 1.13, which
 
278
        returns information about the network name of the repository format.
 
279
 
 
280
        :return: norepository or ok, relpath, rich_root, tree_ref,
 
281
            external_lookup, network_name.
 
282
        """
 
283
        try:
 
284
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
 
285
            return SuccessfulSmartServerResponse(
 
286
                ('ok', path, rich_root, tree_ref, external_lookup, name))
 
287
        except errors.NoRepositoryPresent:
 
288
            return FailedSmartServerResponse(('norepository', ))
 
289
 
 
290
 
139
291
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
140
292
 
141
293
    def do(self, path):
149
301
        return SuccessfulSmartServerResponse(('ok', ))
150
302
 
151
303
 
152
 
class SmartServerRequestOpenBranch(SmartServerRequest):
 
304
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
153
305
 
154
 
    def do(self, path):
155
 
        """try to open a branch at path and return ok/nobranch.
156
 
        
157
 
        If a bzrdir is not present, an exception is propogated
158
 
        rather than 'no branch' because these are different conditions.
159
 
        """
160
 
        bzrdir = BzrDir.open_from_transport(
161
 
            self.transport_from_client_path(path))
 
306
    def do_bzrdir_request(self):
 
307
        """open a branch at path and return the branch reference or branch."""
162
308
        try:
163
 
            reference_url = bzrdir.get_branch_reference()
 
309
            reference_url = self._bzrdir.get_branch_reference()
164
310
            if reference_url is None:
165
311
                return SuccessfulSmartServerResponse(('ok', ''))
166
312
            else:
167
313
                return SuccessfulSmartServerResponse(('ok', reference_url))
168
314
        except errors.NotBranchError:
169
315
            return FailedSmartServerResponse(('nobranch', ))
 
316
 
 
317
 
 
318
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
 
319
 
 
320
    def do_bzrdir_request(self):
 
321
        """open a branch at path and return the reference or format."""
 
322
        try:
 
323
            reference_url = self._bzrdir.get_branch_reference()
 
324
            if reference_url is None:
 
325
                format = self._bzrdir.open_branch()._format.network_name()
 
326
                return SuccessfulSmartServerResponse(('branch', format))
 
327
            else:
 
328
                return SuccessfulSmartServerResponse(('ref', reference_url))
 
329
        except errors.NotBranchError:
 
330
            return FailedSmartServerResponse(('nobranch', ))