~bzr-pqm/bzr/bzr.dev

4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2006-2010 Canonical Ltd
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
16
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
17
"""Server-side bzrdir related request implmentations."""
18
6379.6.3 by Jelmer Vernooij
Use absolute_import.
19
from __future__ import absolute_import
20
6436.3.2 by Jelmer Vernooij
Add HPSS call for BzrDir.get_branches.
21
from bzrlib import (
22
    bencode,
23
    branch,
24
    errors,
25
    repository,
26
    urlutils,
27
    )
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
28
from bzrlib.bzrdir import (
29
    BzrDir,
30
    BzrDirFormat,
5363.2.5 by Jelmer Vernooij
Add dummy foreign prober.
31
    BzrProber,
5363.2.25 by Jelmer Vernooij
Fix some test failures now that bzrlib.controldir.network_format_registry has moved.
32
    )
33
from bzrlib.controldir import (
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
34
    network_format_registry,
35
    )
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
36
from bzrlib.smart.request import (
37
    FailedSmartServerResponse,
38
    SmartServerRequest,
39
    SuccessfulSmartServerResponse,
40
    )
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
41
42
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
43
class SmartServerRequestOpenBzrDir(SmartServerRequest):
44
45
    def do(self, path):
46
        try:
2692.1.11 by Andrew Bennetts
Improve test coverage by making SmartTCPServer_for_testing by default create a server that does not serve the backing transport's root at its own root. This mirrors the way most HTTP smart servers are configured.
47
            t = self.transport_from_client_path(path)
48
        except errors.PathNotChild:
49
            # The client is trying to ask about a path that they have no access
50
            # to.
51
            # Ideally we'd return a FailedSmartServerResponse here rather than
52
            # a "successful" negative, but we want to be compatibile with
53
            # clients that don't anticipate errors from this method.
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
54
            answer = 'no'
55
        else:
5363.2.5 by Jelmer Vernooij
Add dummy foreign prober.
56
            bzr_prober = BzrProber()
2692.1.11 by Andrew Bennetts
Improve test coverage by making SmartTCPServer_for_testing by default create a server that does not serve the backing transport's root at its own root. This mirrors the way most HTTP smart servers are configured.
57
            try:
5363.2.5 by Jelmer Vernooij
Add dummy foreign prober.
58
                bzr_prober.probe_transport(t)
2692.1.11 by Andrew Bennetts
Improve test coverage by making SmartTCPServer_for_testing by default create a server that does not serve the backing transport's root at its own root. This mirrors the way most HTTP smart servers are configured.
59
            except (errors.NotBranchError, errors.UnknownFormatError):
60
                answer = 'no'
61
            else:
62
                answer = 'yes'
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
63
        return SuccessfulSmartServerResponse((answer,))
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
64
65
4634.47.3 by Andrew Bennetts
Add a BzrDir.open_2.1 verb that indicates if there is a workingtree present. Removes the last 2 VFS calls from incremental pushes.
66
class SmartServerRequestOpenBzrDir_2_1(SmartServerRequest):
67
68
    def do(self, path):
69
        """Is there a BzrDir present, and if so does it have a working tree?
70
71
        New in 2.1.
72
        """
4634.47.6 by Andrew Bennetts
Give 'no' response for paths outside the root_client_path.
73
        try:
74
            t = self.transport_from_client_path(path)
75
        except errors.PathNotChild:
76
            # The client is trying to ask about a path that they have no access
77
            # to.
78
            return SuccessfulSmartServerResponse(('no',))
4634.47.3 by Andrew Bennetts
Add a BzrDir.open_2.1 verb that indicates if there is a workingtree present. Removes the last 2 VFS calls from incremental pushes.
79
        try:
80
            bd = BzrDir.open_from_transport(t)
81
        except errors.NotBranchError:
82
            answer = ('no',)
83
        else:
84
            answer = ('yes',)
85
            if bd.has_workingtree():
86
                answer += ('yes',)
87
            else:
88
                answer += ('no',)
89
        return SuccessfulSmartServerResponse(answer)
90
91
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
92
class SmartServerRequestBzrDir(SmartServerRequest):
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
93
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
94
    def do(self, path, *args):
5891.1.3 by Andrew Bennetts
Move docstring formatting fixes.
95
        """Open a BzrDir at path, and return `self.do_bzrdir_request(*args)`."""
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
96
        try:
97
            self._bzrdir = BzrDir.open_from_transport(
98
                self.transport_from_client_path(path))
4734.4.3 by Brian de Alwis
Add support for the HPSS to do further probing when a the provided
99
        except errors.NotBranchError, e:
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
100
            return FailedSmartServerResponse(('nobranch',))
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
101
        return self.do_bzrdir_request(*args)
102
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
103
    def _boolean_to_yes_no(self, a_boolean):
104
        if a_boolean:
105
            return 'yes'
106
        else:
107
            return 'no'
108
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
109
    def _format_to_capabilities(self, repo_format):
110
        rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
111
        tree_ref = self._boolean_to_yes_no(
112
            repo_format.supports_tree_reference)
113
        external_lookup = self._boolean_to_yes_no(
114
            repo_format.supports_external_lookups)
115
        return rich_root, tree_ref, external_lookup
116
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
117
    def _repo_relpath(self, current_transport, repository):
118
        """Get the relative path for repository from current_transport."""
119
        # the relpath of the bzrdir in the found repository gives us the
120
        # path segments to pop-out.
5158.6.10 by Martin Pool
Update more code to use user_transport when it should
121
        relpath = repository.user_transport.relpath(
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
122
            current_transport.base)
123
        if len(relpath):
124
            segments = ['..'] * len(relpath.split('/'))
125
        else:
126
            segments = []
127
        return '/'.join(segments)
128
129
6266.4.1 by Jelmer Vernooij
HPSS call 'BzrDir.destroy_branch'.
130
class SmartServerBzrDirRequestDestroyBranch(SmartServerRequestBzrDir):
131
132
    def do_bzrdir_request(self, name=None):
133
        """Destroy the branch with the specified name.
134
135
        New in 2.5.0.
136
        :return: On success, 'ok'.
137
        """
138
        try:
139
            self._bzrdir.destroy_branch(name)
140
        except errors.NotBranchError, e:
141
            return FailedSmartServerResponse(('nobranch',))
142
        return SuccessfulSmartServerResponse(('ok',))
143
144
6266.3.1 by Jelmer Vernooij
Add HPSS call for BzrDir.has_workingtree.
145
class SmartServerBzrDirRequestHasWorkingTree(SmartServerRequestBzrDir):
146
147
    def do_bzrdir_request(self, name=None):
148
        """Check whether there is a working tree present.
149
150
        New in 2.5.0.
151
152
        :return: If there is a working tree present, 'yes'.
153
            Otherwise 'no'.
154
        """
155
        if self._bzrdir.has_workingtree():
156
            return SuccessfulSmartServerResponse(('yes', ))
157
        else:
158
            return SuccessfulSmartServerResponse(('no', ))
159
160
6266.2.1 by Jelmer Vernooij
New HPSS call BzrDir.destroy_repository.
161
class SmartServerBzrDirRequestDestroyRepository(SmartServerRequestBzrDir):
162
163
    def do_bzrdir_request(self, name=None):
164
        """Destroy the repository.
165
166
        New in 2.5.0.
167
168
        :return: On success, 'ok'.
169
        """
170
        try:
6266.2.2 by Jelmer Vernooij
Fix tests.
171
            self._bzrdir.destroy_repository()
6266.2.1 by Jelmer Vernooij
New HPSS call BzrDir.destroy_repository.
172
        except errors.NoRepositoryPresent, e:
173
            return FailedSmartServerResponse(('norepository',))
174
        return SuccessfulSmartServerResponse(('ok',))
175
176
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
177
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
178
179
    def do_bzrdir_request(self, require_stacking):
4160.2.10 by Andrew Bennetts
Improve documentation of BzrDir.cloning_metadir RPC
180
        """Get the format that should be used when cloning from this dir.
181
182
        New in 1.13.
183
        
184
        :return: on success, a 3-tuple of network names for (control,
185
            repository, branch) directories, where '' signifies "not present".
186
            If this BzrDir contains a branch reference then this will fail with
187
            BranchReference; clients should resolve branch references before
188
            calling this RPC.
189
        """
4070.7.4 by Andrew Bennetts
Deal with branch references better in BzrDir.cloning_metadir RPC (changes protocol).
190
        try:
191
            branch_ref = self._bzrdir.get_branch_reference()
192
        except errors.NotBranchError:
193
            branch_ref = None
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
194
        if branch_ref is not None:
195
            # The server shouldn't try to resolve references, and it quite
196
            # possibly can't reach them anyway.  The client needs to resolve
197
            # the branch reference to determine the cloning_metadir.
198
            return FailedSmartServerResponse(('BranchReference',))
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
199
        if require_stacking == "True":
200
            require_stacking = True
201
        else:
202
            require_stacking = False
203
        control_format = self._bzrdir.cloning_metadir(
204
            require_stacking=require_stacking)
205
        control_name = control_format.network_name()
6155.1.4 by Jelmer Vernooij
Use fixed_components setting.
206
        if not control_format.fixed_components:
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
207
            branch_name = ('branch',
208
                control_format.get_branch_format().network_name())
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
209
            repository_name = control_format.repository_format.network_name()
210
        else:
211
            # Only MetaDir has delegated formats today.
4084.2.2 by Robert Collins
Review feedback.
212
            branch_name = ('branch', '')
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
213
            repository_name = ''
214
        return SuccessfulSmartServerResponse((control_name, repository_name,
215
            branch_name))
216
217
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
218
class SmartServerBzrDirRequestCheckoutMetaDir(SmartServerRequestBzrDir):
219
    """Get the format to use for checkouts.
220
221
    New in 2.5.
6305.5.13 by Jelmer Vernooij
More documentation.
222
223
    :return: on success, a 3-tuple of network names for (control,
224
        repository, branch) directories, where '' signifies "not present".
225
        If this BzrDir contains a branch reference then this will fail with
226
        BranchReference; clients should resolve branch references before
227
        calling this RPC (they should not try to create a checkout of a
228
        checkout).
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
229
    """
230
231
    def do_bzrdir_request(self):
6305.5.13 by Jelmer Vernooij
More documentation.
232
        try:
233
            branch_ref = self._bzrdir.get_branch_reference()
234
        except errors.NotBranchError:
6305.5.16 by Jelmer Vernooij
Some test fixes.
235
            branch_ref = None
236
        if branch_ref is not None:
6305.5.13 by Jelmer Vernooij
More documentation.
237
            # The server shouldn't try to resolve references, and it quite
238
            # possibly can't reach them anyway.  The client needs to resolve
239
            # the branch reference to determine the cloning_metadir.
240
            return FailedSmartServerResponse(('BranchReference',))
6305.5.10 by Jelmer Vernooij
Move to BzrDir.checkout_metadir.
241
        control_format = self._bzrdir.checkout_metadir()
242
        control_name = control_format.network_name()
243
        if not control_format.fixed_components:
244
            branch_name = control_format.get_branch_format().network_name()
245
            repo_name = control_format.repository_format.network_name()
246
        else:
247
            branch_name = ''
248
            repo_name = ''
249
        return SuccessfulSmartServerResponse(
250
            (control_name, repo_name, branch_name))
251
252
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
253
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
254
255
    def do(self, path, network_name):
256
        """Create a branch in the bzr dir at path.
257
258
        This operates precisely like 'bzrdir.create_branch'.
259
260
        If a bzrdir is not present, an exception is propogated
261
        rather than 'no branch' because these are different conditions (and
262
        this method should only be called after establishing that a bzr dir
263
        exists anyway).
264
265
        This is the initial version of this method introduced to the smart
266
        server for 1.13.
267
268
        :param path: The path to the bzrdir.
269
        :param network_name: The network name of the branch type to create.
5609.21.1 by Andrew Bennetts
Possible fix for #726584, plus drive-by docstring fix.
270
        :return: ('ok', branch_format, repo_path, rich_root, tree_ref,
271
            external_lookup, repo_format)
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
272
        """
273
        bzrdir = BzrDir.open_from_transport(
274
            self.transport_from_client_path(path))
275
        format = branch.network_format_registry.get(network_name)
276
        bzrdir.branch_format = format
6436.1.2 by Jelmer Vernooij
Fix some tests.
277
        result = format.initialize(bzrdir, name="")
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
278
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
279
            result.repository._format)
280
        branch_format = result._format.network_name()
281
        repo_format = result.repository._format.network_name()
282
        repo_path = self._repo_relpath(bzrdir.root_transport,
283
            result.repository)
284
        # branch format, repo relpath, rich_root, tree_ref, external_lookup,
285
        # repo_network_name
286
        return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
287
            rich_root, tree_ref, external_lookup, repo_format))
288
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
289
290
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
291
292
    def do(self, path, network_name, shared):
293
        """Create a repository in the bzr dir at path.
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
294
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
295
        This operates precisely like 'bzrdir.create_repository'.
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
296
4031.3.1 by Frank Aspell
Fixing various typos
297
        If a bzrdir is not present, an exception is propagated
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
298
        rather than 'no branch' because these are different conditions (and
299
        this method should only be called after establishing that a bzr dir
300
        exists anyway).
301
302
        This is the initial version of this method introduced to the smart
303
        server for 1.13.
304
305
        :param path: The path to the bzrdir.
306
        :param network_name: The network name of the repository type to create.
307
        :param shared: The value to pass create_repository for the shared
308
            parameter.
309
        :return: (ok, rich_root, tree_ref, external_lookup, network_name)
310
        """
311
        bzrdir = BzrDir.open_from_transport(
312
            self.transport_from_client_path(path))
313
        shared = shared == 'True'
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
314
        format = repository.network_format_registry.get(network_name)
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
315
        bzrdir.repository_format = format
316
        result = format.initialize(bzrdir, shared=shared)
317
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
318
            result._format)
319
        return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
320
            external_lookup, result._format.network_name()))
321
322
323
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
324
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
325
    def _find(self, path):
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
326
        """try to find a repository from path upwards
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
327
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
328
        This operates precisely like 'bzrdir.find_repository'.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
329
4053.1.2 by Robert Collins
Actually make this branch work.
330
        :return: (relpath, rich_root, tree_ref, external_lookup, network_name).
331
            All are strings, relpath is a / prefixed path, the next three are
332
            either 'yes' or 'no', and the last is a repository format network
333
            name.
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
334
        :raises errors.NoRepositoryPresent: When there is no repository
335
            present.
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
336
        """
2692.1.6 by Andrew Bennetts
Fix some >80 columns violations.
337
        bzrdir = BzrDir.open_from_transport(
338
            self.transport_from_client_path(path))
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
339
        repository = bzrdir.find_repository()
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
340
        path = self._repo_relpath(bzrdir.root_transport, repository)
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
341
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
342
            repository._format)
4053.1.2 by Robert Collins
Actually make this branch work.
343
        network_name = repository._format.network_name()
344
        return path, rich_root, tree_ref, external_lookup, network_name
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
345
346
347
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
348
349
    def do(self, path):
350
        """try to find a repository from path upwards
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
351
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
352
        This operates precisely like 'bzrdir.find_repository'.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
353
4031.3.1 by Frank Aspell
Fixing various typos
354
        If a bzrdir is not present, an exception is propagated
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
355
        rather than 'no branch' because these are different conditions.
356
357
        This is the initial version of this method introduced with the smart
358
        server. Modern clients will try the V2 method that adds support for the
359
        supports_external_lookups attribute.
360
361
        :return: norepository or ok, relpath.
362
        """
363
        try:
4053.1.2 by Robert Collins
Actually make this branch work.
364
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
365
            return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
366
        except errors.NoRepositoryPresent:
367
            return FailedSmartServerResponse(('norepository', ))
368
369
370
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
371
372
    def do(self, path):
373
        """try to find a repository from path upwards
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
374
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
375
        This operates precisely like 'bzrdir.find_repository'.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
376
4031.3.1 by Frank Aspell
Fixing various typos
377
        If a bzrdir is not present, an exception is propagated
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
378
        rather than 'no branch' because these are different conditions.
379
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
380
        This is the second edition of this method introduced in bzr 1.3, which
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
381
        returns information about the supports_external_lookups format
382
        attribute too.
383
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
384
        :return: norepository or ok, relpath, rich_root, tree_ref,
385
            external_lookup.
386
        """
387
        try:
4053.1.2 by Robert Collins
Actually make this branch work.
388
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
389
            return SuccessfulSmartServerResponse(
390
                ('ok', path, rich_root, tree_ref, external_lookup))
391
        except errors.NoRepositoryPresent:
392
            return FailedSmartServerResponse(('norepository', ))
393
394
395
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
396
397
    def do(self, path):
398
        """try to find a repository from path upwards
399
400
        This operates precisely like 'bzrdir.find_repository'.
401
402
        If a bzrdir is not present, an exception is propogated
403
        rather than 'no branch' because these are different conditions.
404
405
        This is the third edition of this method introduced in bzr 1.13, which
406
        returns information about the network name of the repository format.
407
408
        :return: norepository or ok, relpath, rich_root, tree_ref,
409
            external_lookup, network_name.
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
410
        """
411
        try:
4053.1.2 by Robert Collins
Actually make this branch work.
412
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
413
            return SuccessfulSmartServerResponse(
4053.1.2 by Robert Collins
Actually make this branch work.
414
                ('ok', path, rich_root, tree_ref, external_lookup, name))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
415
        except errors.NoRepositoryPresent:
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
416
            return FailedSmartServerResponse(('norepository', ))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
417
418
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
419
class SmartServerBzrDirRequestConfigFile(SmartServerRequestBzrDir):
420
421
    def do_bzrdir_request(self):
422
        """Get the configuration bytes for a config file in bzrdir.
423
        
424
        The body is not utf8 decoded - it is the literal bytestream from disk.
425
        """
426
        config = self._bzrdir._get_config()
427
        if config is None:
428
            content = ''
429
        else:
430
            content = config._get_config_file().read()
431
        return SuccessfulSmartServerResponse((), content)
432
433
6436.3.2 by Jelmer Vernooij
Add HPSS call for BzrDir.get_branches.
434
class SmartServerBzrDirRequestGetBranches(SmartServerRequestBzrDir):
435
436
    def do_bzrdir_request(self):
437
        """Get the branches in a control directory.
438
        
439
        The body is a bencoded dictionary, with values similar to the return
440
        value of the open branch request.
441
        """
442
        branches = self._bzrdir.get_branches()
443
        ret = {}
444
        for name, b in branches.iteritems():
445
            if name is None:
446
                name = ""
447
            ret[name] = ("branch", b._format.network_name())
448
        return SuccessfulSmartServerResponse(
449
            ("success", ), bencode.bencode(ret))
450
451
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
452
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
453
454
    def do(self, path):
455
        """Initialize a bzrdir at path.
456
457
        The default format of the server is used.
458
        :return: SmartServerResponse(('ok', ))
459
        """
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
460
        target_transport = self.transport_from_client_path(path)
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
461
        BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
462
        return SuccessfulSmartServerResponse(('ok', ))
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
463
464
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
465
class SmartServerRequestBzrDirInitializeEx(SmartServerRequestBzrDir):
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
466
467
    def parse_NoneTrueFalse(self, arg):
468
        if not arg:
469
            return None
470
        if arg == 'False':
471
            return False
472
        if arg == 'True':
473
            return True
474
        raise AssertionError("invalid arg %r" % arg)
475
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
476
    def parse_NoneString(self, arg):
477
        return arg or None
478
479
    def _serialize_NoneTrueFalse(self, arg):
480
        if arg is False:
481
            return 'False'
482
        if not arg:
483
            return ''
484
        return 'True'
485
486
    def do(self, bzrdir_network_name, path, use_existing_dir, create_prefix,
487
        force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
488
        make_working_trees, shared_repo):
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
489
        """Initialize a bzrdir at path as per
490
        BzrDirFormat.initialize_on_transport_ex.
491
492
        New in 1.16.  (Replaces BzrDirFormat.initialize_ex verb from 1.15).
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
493
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
494
        :return: return SuccessfulSmartServerResponse((repo_path, rich_root,
495
            tree_ref, external_lookup, repo_network_name,
496
            repo_bzrdir_network_name, bzrdir_format_network_name,
497
            NoneTrueFalse(stacking), final_stack, final_stack_pwd,
498
            repo_lock_token))
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
499
        """
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
500
        target_transport = self.transport_from_client_path(path)
501
        format = network_format_registry.get(bzrdir_network_name)
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
502
        use_existing_dir = self.parse_NoneTrueFalse(use_existing_dir)
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
503
        create_prefix = self.parse_NoneTrueFalse(create_prefix)
504
        force_new_repo = self.parse_NoneTrueFalse(force_new_repo)
505
        stacked_on = self.parse_NoneString(stacked_on)
506
        stack_on_pwd = self.parse_NoneString(stack_on_pwd)
507
        make_working_trees = self.parse_NoneTrueFalse(make_working_trees)
508
        shared_repo = self.parse_NoneTrueFalse(shared_repo)
509
        if stack_on_pwd == '.':
510
            stack_on_pwd = target_transport.base
511
        repo_format_name = self.parse_NoneString(repo_format_name)
512
        repo, bzrdir, stacking, repository_policy = \
513
            format.initialize_on_transport_ex(target_transport,
514
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
515
            force_new_repo=force_new_repo, stacked_on=stacked_on,
516
            stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
517
            make_working_trees=make_working_trees, shared_repo=shared_repo)
518
        if repo is None:
519
            repo_path = ''
520
            repo_name = ''
521
            rich_root = tree_ref = external_lookup = ''
522
            repo_bzrdir_name = ''
523
            final_stack = None
524
            final_stack_pwd = None
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
525
            repo_lock_token = ''
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
526
        else:
527
            repo_path = self._repo_relpath(bzrdir.root_transport, repo)
528
            if repo_path == '':
529
                repo_path = '.'
530
            rich_root, tree_ref, external_lookup = self._format_to_capabilities(
531
                repo._format)
532
            repo_name = repo._format.network_name()
533
            repo_bzrdir_name = repo.bzrdir._format.network_name()
534
            final_stack = repository_policy._stack_on
4416.3.11 by Jonathan Lange
Guard in case it's none.
535
            final_stack_pwd = repository_policy._stack_on_pwd
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
536
            # It is returned locked, but we need to do the lock to get the lock
537
            # token.
538
            repo.unlock()
5200.3.3 by Robert Collins
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
539
            repo_lock_token = repo.lock_write().repository_token or ''
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
540
            if repo_lock_token:
541
                repo.leave_lock_in_place()
542
            repo.unlock()
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
543
        final_stack = final_stack or ''
544
        final_stack_pwd = final_stack_pwd or ''
4416.3.11 by Jonathan Lange
Guard in case it's none.
545
546
        # We want this to be relative to the bzrdir.
547
        if final_stack_pwd:
548
            final_stack_pwd = urlutils.relative_url(
4416.3.12 by Jonathan Lange
This makes the test pass, but it's a bit ick.
549
                target_transport.base, final_stack_pwd)
550
551
        # Can't meaningfully return a root path.
552
        if final_stack.startswith('/'):
4416.3.13 by Jonathan Lange
full_path -> client_path, use _root_client_path rather than
553
            client_path = self._root_client_path + final_stack[1:]
4416.3.12 by Jonathan Lange
This makes the test pass, but it's a bit ick.
554
            final_stack = urlutils.relative_url(
4416.3.13 by Jonathan Lange
full_path -> client_path, use _root_client_path rather than
555
                self._root_client_path, client_path)
4416.3.12 by Jonathan Lange
This makes the test pass, but it's a bit ick.
556
            final_stack_pwd = '.'
4416.3.11 by Jonathan Lange
Guard in case it's none.
557
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
558
        return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,
559
            external_lookup, repo_name, repo_bzrdir_name,
560
            bzrdir._format.network_name(),
561
            self._serialize_NoneTrueFalse(stacking), final_stack,
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
562
            final_stack_pwd, repo_lock_token))
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
563
564
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
565
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
566
567
    def do_bzrdir_request(self):
568
        """open a branch at path and return the branch reference or branch."""
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
569
        try:
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
570
            reference_url = self._bzrdir.get_branch_reference()
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
571
            if reference_url is None:
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
572
                return SuccessfulSmartServerResponse(('ok', ''))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
573
            else:
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
574
                return SuccessfulSmartServerResponse(('ok', reference_url))
4734.4.3 by Brian de Alwis
Add support for the HPSS to do further probing when a the provided
575
        except errors.NotBranchError, e:
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
576
            return FailedSmartServerResponse(('nobranch',))
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
577
578
579
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
580
581
    def do_bzrdir_request(self):
582
        """open a branch at path and return the reference or format."""
583
        try:
584
            reference_url = self._bzrdir.get_branch_reference()
585
            if reference_url is None:
4160.2.6 by Andrew Bennetts
Add ignore_fallbacks flag.
586
                br = self._bzrdir.open_branch(ignore_fallbacks=True)
587
                format = br._format.network_name()
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
588
                return SuccessfulSmartServerResponse(('branch', format))
589
            else:
590
                return SuccessfulSmartServerResponse(('ref', reference_url))
4734.4.3 by Brian de Alwis
Add support for the HPSS to do further probing when a the provided
591
        except errors.NotBranchError, e:
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
592
            return FailedSmartServerResponse(('nobranch',))
593
594
595
class SmartServerRequestOpenBranchV3(SmartServerRequestBzrDir):
596
597
    def do_bzrdir_request(self):
598
        """Open a branch at path and return the reference or format.
599
        
600
        This version introduced in 2.1.
601
602
        Differences to SmartServerRequestOpenBranchV2:
603
          * can return 2-element ('nobranch', extra), where 'extra' is a string
604
            with an explanation like 'location is a repository'.  Previously
605
            a 'nobranch' response would never have more than one element.
606
        """
607
        try:
608
            reference_url = self._bzrdir.get_branch_reference()
609
            if reference_url is None:
610
                br = self._bzrdir.open_branch(ignore_fallbacks=True)
611
                format = br._format.network_name()
612
                return SuccessfulSmartServerResponse(('branch', format))
613
            else:
614
                return SuccessfulSmartServerResponse(('ref', reference_url))
615
        except errors.NotBranchError, e:
4734.4.9 by Andrew Bennetts
More tests and comments.
616
            # Stringify the exception so that its .detail attribute will be
617
            # filled out.
4734.4.8 by Andrew Bennetts
Fix HPSS tests; pass 'location is a repository' message via smart server when possible (adds BzrDir.open_branchV3 verb).
618
            str(e)
619
            resp = ('nobranch',)
620
            detail = e.detail
621
            if detail:
622
                if detail.startswith(': '):
623
                    detail = detail[2:]
624
                resp += (detail,)
625
            return FailedSmartServerResponse(resp)
626