~bzr-pqm/bzr/bzr.dev

2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
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
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
17
"""Server-side bzrdir related request implmentations."""
18
19
4416.3.8 by Jonathan Lange
This makes the unit test & one of the acceptance tests pass.
20
from bzrlib import branch, errors, repository, urlutils
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
21
from bzrlib.bzrdir import (
22
    BzrDir,
23
    BzrDirFormat,
24
    BzrDirMetaFormat1,
25
    network_format_registry,
26
    )
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
27
from bzrlib.smart.request import (
28
    FailedSmartServerResponse,
29
    SmartServerRequest,
30
    SuccessfulSmartServerResponse,
31
    )
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
32
33
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
34
class SmartServerRequestOpenBzrDir(SmartServerRequest):
35
36
    def do(self, path):
37
        from bzrlib.bzrdir import BzrDirFormat
38
        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.
39
            t = self.transport_from_client_path(path)
40
        except errors.PathNotChild:
41
            # The client is trying to ask about a path that they have no access
42
            # to.
43
            # Ideally we'd return a FailedSmartServerResponse here rather than
44
            # a "successful" negative, but we want to be compatibile with
45
            # clients that don't anticipate errors from this method.
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
46
            answer = 'no'
47
        else:
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.
48
            default_format = BzrDirFormat.get_default_format()
49
            real_bzrdir = default_format.open(t, _found=True)
50
            try:
51
                real_bzrdir._format.probe_transport(t)
52
            except (errors.NotBranchError, errors.UnknownFormatError):
53
                answer = 'no'
54
            else:
55
                answer = 'yes'
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
56
        return SuccessfulSmartServerResponse((answer,))
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
57
58
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
59
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.
60
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
61
    def do(self, path, *args):
62
        """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.
63
        try:
64
            self._bzrdir = BzrDir.open_from_transport(
65
                self.transport_from_client_path(path))
66
        except errors.NotBranchError:
67
            return FailedSmartServerResponse(('nobranch', ))
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
68
        return self.do_bzrdir_request(*args)
69
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
70
    def _boolean_to_yes_no(self, a_boolean):
71
        if a_boolean:
72
            return 'yes'
73
        else:
74
            return 'no'
75
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
76
    def _format_to_capabilities(self, repo_format):
77
        rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
78
        tree_ref = self._boolean_to_yes_no(
79
            repo_format.supports_tree_reference)
80
        external_lookup = self._boolean_to_yes_no(
81
            repo_format.supports_external_lookups)
82
        return rich_root, tree_ref, external_lookup
83
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
84
    def _repo_relpath(self, current_transport, repository):
85
        """Get the relative path for repository from current_transport."""
86
        # the relpath of the bzrdir in the found repository gives us the
87
        # path segments to pop-out.
88
        relpath = repository.bzrdir.root_transport.relpath(
89
            current_transport.base)
90
        if len(relpath):
91
            segments = ['..'] * len(relpath.split('/'))
92
        else:
93
            segments = []
94
        return '/'.join(segments)
95
96
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
97
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
98
99
    def do_bzrdir_request(self, require_stacking):
4160.2.10 by Andrew Bennetts
Improve documentation of BzrDir.cloning_metadir RPC
100
        """Get the format that should be used when cloning from this dir.
101
102
        New in 1.13.
103
        
104
        :return: on success, a 3-tuple of network names for (control,
105
            repository, branch) directories, where '' signifies "not present".
106
            If this BzrDir contains a branch reference then this will fail with
107
            BranchReference; clients should resolve branch references before
108
            calling this RPC.
109
        """
4070.7.4 by Andrew Bennetts
Deal with branch references better in BzrDir.cloning_metadir RPC (changes protocol).
110
        try:
111
            branch_ref = self._bzrdir.get_branch_reference()
112
        except errors.NotBranchError:
113
            branch_ref = None
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
114
        if branch_ref is not None:
115
            # The server shouldn't try to resolve references, and it quite
116
            # possibly can't reach them anyway.  The client needs to resolve
117
            # the branch reference to determine the cloning_metadir.
118
            return FailedSmartServerResponse(('BranchReference',))
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
119
        if require_stacking == "True":
120
            require_stacking = True
121
        else:
122
            require_stacking = False
123
        control_format = self._bzrdir.cloning_metadir(
124
            require_stacking=require_stacking)
125
        control_name = control_format.network_name()
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
126
        # XXX: There should be a method that tells us that the format does/does
127
        # not have subformats.
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
128
        if isinstance(control_format, BzrDirMetaFormat1):
4160.2.9 by Andrew Bennetts
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
129
            branch_name = ('branch',
130
                control_format.get_branch_format().network_name())
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
131
            repository_name = control_format.repository_format.network_name()
132
        else:
133
            # Only MetaDir has delegated formats today.
4084.2.2 by Robert Collins
Review feedback.
134
            branch_name = ('branch', '')
4070.2.3 by Robert Collins
Get BzrDir.cloning_metadir working.
135
            repository_name = ''
136
        return SuccessfulSmartServerResponse((control_name, repository_name,
137
            branch_name))
138
139
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
140
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
141
142
    def do(self, path, network_name):
143
        """Create a branch in the bzr dir at path.
144
145
        This operates precisely like 'bzrdir.create_branch'.
146
147
        If a bzrdir is not present, an exception is propogated
148
        rather than 'no branch' because these are different conditions (and
149
        this method should only be called after establishing that a bzr dir
150
        exists anyway).
151
152
        This is the initial version of this method introduced to the smart
153
        server for 1.13.
154
155
        :param path: The path to the bzrdir.
156
        :param network_name: The network name of the branch type to create.
157
        :return: (ok, network_name)
158
        """
159
        bzrdir = BzrDir.open_from_transport(
160
            self.transport_from_client_path(path))
161
        format = branch.network_format_registry.get(network_name)
162
        bzrdir.branch_format = format
163
        result = format.initialize(bzrdir)
164
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
165
            result.repository._format)
166
        branch_format = result._format.network_name()
167
        repo_format = result.repository._format.network_name()
168
        repo_path = self._repo_relpath(bzrdir.root_transport,
169
            result.repository)
170
        # branch format, repo relpath, rich_root, tree_ref, external_lookup,
171
        # repo_network_name
172
        return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
173
            rich_root, tree_ref, external_lookup, repo_format))
174
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
175
176
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
177
178
    def do(self, path, network_name, shared):
179
        """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.
180
4017.3.2 by Robert Collins
Reduce the number of round trips required to create a repository over the network.
181
        This operates precisely like 'bzrdir.create_repository'.
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
182
4031.3.1 by Frank Aspell
Fixing various typos
183
        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.
184
        rather than 'no branch' because these are different conditions (and
185
        this method should only be called after establishing that a bzr dir
186
        exists anyway).
187
188
        This is the initial version of this method introduced to the smart
189
        server for 1.13.
190
191
        :param path: The path to the bzrdir.
192
        :param network_name: The network name of the repository type to create.
193
        :param shared: The value to pass create_repository for the shared
194
            parameter.
195
        :return: (ok, rich_root, tree_ref, external_lookup, network_name)
196
        """
197
        bzrdir = BzrDir.open_from_transport(
198
            self.transport_from_client_path(path))
199
        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.
200
        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.
201
        bzrdir.repository_format = format
202
        result = format.initialize(bzrdir, shared=shared)
203
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
204
            result._format)
205
        return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
206
            external_lookup, result._format.network_name()))
207
208
209
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
210
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
211
    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.
212
        """try to find a repository from path upwards
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
213
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
214
        This operates precisely like 'bzrdir.find_repository'.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
215
4053.1.2 by Robert Collins
Actually make this branch work.
216
        :return: (relpath, rich_root, tree_ref, external_lookup, network_name).
217
            All are strings, relpath is a / prefixed path, the next three are
218
            either 'yes' or 'no', and the last is a repository format network
219
            name.
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
220
        :raises errors.NoRepositoryPresent: When there is no repository
221
            present.
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
222
        """
2692.1.6 by Andrew Bennetts
Fix some >80 columns violations.
223
        bzrdir = BzrDir.open_from_transport(
224
            self.transport_from_client_path(path))
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
225
        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.
226
        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.
227
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
228
            repository._format)
4053.1.2 by Robert Collins
Actually make this branch work.
229
        network_name = repository._format.network_name()
230
        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
231
232
233
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
234
235
    def do(self, path):
236
        """try to find a repository from path upwards
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
237
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
238
        This operates precisely like 'bzrdir.find_repository'.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
239
4031.3.1 by Frank Aspell
Fixing various typos
240
        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
241
        rather than 'no branch' because these are different conditions.
242
243
        This is the initial version of this method introduced with the smart
244
        server. Modern clients will try the V2 method that adds support for the
245
        supports_external_lookups attribute.
246
247
        :return: norepository or ok, relpath.
248
        """
249
        try:
4053.1.2 by Robert Collins
Actually make this branch work.
250
            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
251
            return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
252
        except errors.NoRepositoryPresent:
253
            return FailedSmartServerResponse(('norepository', ))
254
255
256
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
257
258
    def do(self, path):
259
        """try to find a repository from path upwards
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
260
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
261
        This operates precisely like 'bzrdir.find_repository'.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
262
4031.3.1 by Frank Aspell
Fixing various typos
263
        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
264
        rather than 'no branch' because these are different conditions.
265
3221.3.3 by Robert Collins
* Hook up the new remote method ``RemoteBzrDir.find_repositoryV2`` so
266
        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
267
        returns information about the supports_external_lookups format
268
        attribute too.
269
4053.1.1 by Robert Collins
New version of the BzrDir.find_repository verb supporting _network_name to support removing more _ensure_real calls.
270
        :return: norepository or ok, relpath, rich_root, tree_ref,
271
            external_lookup.
272
        """
273
        try:
4053.1.2 by Robert Collins
Actually make this branch work.
274
            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.
275
            return SuccessfulSmartServerResponse(
276
                ('ok', path, rich_root, tree_ref, external_lookup))
277
        except errors.NoRepositoryPresent:
278
            return FailedSmartServerResponse(('norepository', ))
279
280
281
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
282
283
    def do(self, path):
284
        """try to find a repository from path upwards
285
286
        This operates precisely like 'bzrdir.find_repository'.
287
288
        If a bzrdir is not present, an exception is propogated
289
        rather than 'no branch' because these are different conditions.
290
291
        This is the third edition of this method introduced in bzr 1.13, which
292
        returns information about the network name of the repository format.
293
294
        :return: norepository or ok, relpath, rich_root, tree_ref,
295
            external_lookup, network_name.
3221.3.2 by Robert Collins
* New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for
296
        """
297
        try:
4053.1.2 by Robert Collins
Actually make this branch work.
298
            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
299
            return SuccessfulSmartServerResponse(
4053.1.2 by Robert Collins
Actually make this branch work.
300
                ('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.
301
        except errors.NoRepositoryPresent:
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
302
            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.
303
304
4288.1.2 by Robert Collins
Create a server verb for doing BzrDir.get_config()
305
class SmartServerBzrDirRequestConfigFile(SmartServerRequestBzrDir):
306
307
    def do_bzrdir_request(self):
308
        """Get the configuration bytes for a config file in bzrdir.
309
        
310
        The body is not utf8 decoded - it is the literal bytestream from disk.
311
        """
312
        config = self._bzrdir._get_config()
313
        if config is None:
314
            content = ''
315
        else:
316
            content = config._get_config_file().read()
317
        return SuccessfulSmartServerResponse((), content)
318
319
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
320
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
321
322
    def do(self, path):
323
        """Initialize a bzrdir at path.
324
325
        The default format of the server is used.
326
        :return: SmartServerResponse(('ok', ))
327
        """
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
328
        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 :).
329
        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.
330
        return SuccessfulSmartServerResponse(('ok', ))
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
331
332
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
333
class SmartServerRequestBzrDirInitializeEx(SmartServerRequestBzrDir):
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
334
335
    def parse_NoneTrueFalse(self, arg):
336
        if not arg:
337
            return None
338
        if arg == 'False':
339
            return False
340
        if arg == 'True':
341
            return True
342
        raise AssertionError("invalid arg %r" % arg)
343
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
344
    def parse_NoneString(self, arg):
345
        return arg or None
346
347
    def _serialize_NoneTrueFalse(self, arg):
348
        if arg is False:
349
            return 'False'
350
        if not arg:
351
            return ''
352
        return 'True'
353
354
    def do(self, bzrdir_network_name, path, use_existing_dir, create_prefix,
355
        force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
356
        make_working_trees, shared_repo):
4436.1.1 by Andrew Bennetts
Rename BzrDirFormat.initialize_ex verb to BzrDirFormat.initialize_ex_1.16.
357
        """Initialize a bzrdir at path as per
358
        BzrDirFormat.initialize_on_transport_ex.
359
360
        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.
361
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
362
        :return: return SuccessfulSmartServerResponse((repo_path, rich_root,
363
            tree_ref, external_lookup, repo_network_name,
364
            repo_bzrdir_network_name, bzrdir_format_network_name,
365
            NoneTrueFalse(stacking), final_stack, final_stack_pwd,
366
            repo_lock_token))
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
367
        """
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
368
        target_transport = self.transport_from_client_path(path)
369
        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.
370
        use_existing_dir = self.parse_NoneTrueFalse(use_existing_dir)
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
371
        create_prefix = self.parse_NoneTrueFalse(create_prefix)
372
        force_new_repo = self.parse_NoneTrueFalse(force_new_repo)
373
        stacked_on = self.parse_NoneString(stacked_on)
374
        stack_on_pwd = self.parse_NoneString(stack_on_pwd)
375
        make_working_trees = self.parse_NoneTrueFalse(make_working_trees)
376
        shared_repo = self.parse_NoneTrueFalse(shared_repo)
377
        if stack_on_pwd == '.':
378
            stack_on_pwd = target_transport.base
379
        repo_format_name = self.parse_NoneString(repo_format_name)
380
        repo, bzrdir, stacking, repository_policy = \
381
            format.initialize_on_transport_ex(target_transport,
382
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
383
            force_new_repo=force_new_repo, stacked_on=stacked_on,
384
            stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
385
            make_working_trees=make_working_trees, shared_repo=shared_repo)
386
        if repo is None:
387
            repo_path = ''
388
            repo_name = ''
389
            rich_root = tree_ref = external_lookup = ''
390
            repo_bzrdir_name = ''
391
            final_stack = None
392
            final_stack_pwd = None
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
393
            repo_lock_token = ''
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
394
        else:
395
            repo_path = self._repo_relpath(bzrdir.root_transport, repo)
396
            if repo_path == '':
397
                repo_path = '.'
398
            rich_root, tree_ref, external_lookup = self._format_to_capabilities(
399
                repo._format)
400
            repo_name = repo._format.network_name()
401
            repo_bzrdir_name = repo.bzrdir._format.network_name()
402
            final_stack = repository_policy._stack_on
4416.3.11 by Jonathan Lange
Guard in case it's none.
403
            final_stack_pwd = repository_policy._stack_on_pwd
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
404
            # It is returned locked, but we need to do the lock to get the lock
405
            # token.
406
            repo.unlock()
407
            repo_lock_token = repo.lock_write() or ''
408
            if repo_lock_token:
409
                repo.leave_lock_in_place()
410
            repo.unlock()
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
411
        final_stack = final_stack or ''
412
        final_stack_pwd = final_stack_pwd or ''
4416.3.11 by Jonathan Lange
Guard in case it's none.
413
414
        # We want this to be relative to the bzrdir.
415
        if final_stack_pwd:
416
            final_stack_pwd = urlutils.relative_url(
4416.3.12 by Jonathan Lange
This makes the test pass, but it's a bit ick.
417
                target_transport.base, final_stack_pwd)
418
419
        # Can't meaningfully return a root path.
420
        if final_stack.startswith('/'):
4416.3.13 by Jonathan Lange
full_path -> client_path, use _root_client_path rather than
421
            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.
422
            final_stack = urlutils.relative_url(
4416.3.13 by Jonathan Lange
full_path -> client_path, use _root_client_path rather than
423
                self._root_client_path, client_path)
4416.3.12 by Jonathan Lange
This makes the test pass, but it's a bit ick.
424
            final_stack_pwd = '.'
4416.3.11 by Jonathan Lange
Guard in case it's none.
425
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
426
        return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,
427
            external_lookup, repo_name, repo_bzrdir_name,
428
            bzrdir._format.network_name(),
429
            self._serialize_NoneTrueFalse(stacking), final_stack,
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
430
            final_stack_pwd, repo_lock_token))
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
431
432
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.
433
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
434
435
    def do_bzrdir_request(self):
436
        """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.
437
        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.
438
            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.
439
            if reference_url is None:
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
440
                return SuccessfulSmartServerResponse(('ok', ''))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
441
            else:
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
442
                return SuccessfulSmartServerResponse(('ok', reference_url))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
443
        except errors.NotBranchError:
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
444
            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.
445
446
447
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
448
449
    def do_bzrdir_request(self):
450
        """open a branch at path and return the reference or format."""
451
        try:
452
            reference_url = self._bzrdir.get_branch_reference()
453
            if reference_url is None:
4160.2.6 by Andrew Bennetts
Add ignore_fallbacks flag.
454
                br = self._bzrdir.open_branch(ignore_fallbacks=True)
455
                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.
456
                return SuccessfulSmartServerResponse(('branch', format))
457
            else:
458
                return SuccessfulSmartServerResponse(('ref', reference_url))
459
        except errors.NotBranchError:
460
            return FailedSmartServerResponse(('nobranch', ))