1
# Copyright (C) 2006 Canonical Ltd
 
 
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.
 
 
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.
 
 
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
 
 
17
"""Server-side bzrdir related request implmentations."""
 
 
20
from bzrlib import errors
 
 
21
from bzrlib.bzrdir import BzrDir, BzrDirFormat
 
 
22
from bzrlib.smart.request import (
 
 
23
    FailedSmartServerResponse,
 
 
25
    SuccessfulSmartServerResponse,
 
 
29
class SmartServerRequestOpenBzrDir(SmartServerRequest):
 
 
32
        from bzrlib.bzrdir import BzrDirFormat
 
 
34
            t = self.transport_from_client_path(path)
 
 
35
        except errors.PathNotChild:
 
 
36
            # The client is trying to ask about a path that they have no access
 
 
38
            # Ideally we'd return a FailedSmartServerResponse here rather than
 
 
39
            # a "successful" negative, but we want to be compatibile with
 
 
40
            # clients that don't anticipate errors from this method.
 
 
43
            default_format = BzrDirFormat.get_default_format()
 
 
44
            real_bzrdir = default_format.open(t, _found=True)
 
 
46
                real_bzrdir._format.probe_transport(t)
 
 
47
            except (errors.NotBranchError, errors.UnknownFormatError):
 
 
51
        return SuccessfulSmartServerResponse((answer,))
 
 
54
class SmartServerRequestFindRepository(SmartServerRequest):
 
 
56
    def _boolean_to_yes_no(self, a_boolean):
 
 
62
    def _find(self, path):
 
 
63
        """try to find a repository from path upwards
 
 
65
        This operates precisely like 'bzrdir.find_repository'.
 
 
67
        :return: (relpath, rich_root, tree_ref, external_lookup) flags. All are
 
 
68
            strings, relpath is a / prefixed path, and the other three are
 
 
70
        :raises errors.NoRepositoryPresent: When there is no repository
 
 
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 
 
 
77
        # path segments to pop-out.
 
 
78
        relpath = repository.bzrdir.root_transport.relpath(
 
 
79
            bzrdir.root_transport.base)
 
 
81
            segments = ['..'] * len(relpath.split('/'))
 
 
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
 
 
92
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
 
 
95
        """try to find a repository from path upwards
 
 
97
        This operates precisely like 'bzrdir.find_repository'.
 
 
99
        If a bzrdir is not present, an exception is propogated
 
 
100
        rather than 'no branch' because these are different conditions.
 
 
102
        This is the initial version of this method introduced with the smart
 
 
103
        server. Modern clients will try the V2 method that adds support for the
 
 
104
        supports_external_lookups attribute.
 
 
106
        :return: norepository or ok, relpath.
 
 
109
            path, rich_root, tree_ref, external_lookup = self._find(path)
 
 
110
            return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
 
 
111
        except errors.NoRepositoryPresent:
 
 
112
            return FailedSmartServerResponse(('norepository', ))
 
 
115
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
 
 
118
        """try to find a repository from path upwards
 
 
120
        This operates precisely like 'bzrdir.find_repository'.
 
 
122
        If a bzrdir is not present, an exception is propogated
 
 
123
        rather than 'no branch' because these are different conditions.
 
 
125
        This is the second edition of this method introduced in bzr 1.3, which
 
 
126
        returns information about the supports_external_lookups format
 
 
129
        :return: norepository or ok, relpath.
 
 
132
            path, rich_root, tree_ref, external_lookup = self._find(path)
 
 
133
            return SuccessfulSmartServerResponse(
 
 
134
                ('ok', path, rich_root, tree_ref, external_lookup))
 
 
135
        except errors.NoRepositoryPresent:
 
 
136
            return FailedSmartServerResponse(('norepository', ))
 
 
139
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
 
 
142
        """Initialize a bzrdir at path.
 
 
144
        The default format of the server is used.
 
 
145
        :return: SmartServerResponse(('ok', ))
 
 
147
        target_transport = self.transport_from_client_path(path)
 
 
148
        BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
 
 
149
        return SuccessfulSmartServerResponse(('ok', ))
 
 
152
class SmartServerRequestOpenBranch(SmartServerRequest):
 
 
155
        """try to open a branch at path and return ok/nobranch.
 
 
157
        If a bzrdir is not present, an exception is propogated
 
 
158
        rather than 'no branch' because these are different conditions.
 
 
160
        bzrdir = BzrDir.open_from_transport(
 
 
161
            self.transport_from_client_path(path))
 
 
163
            reference_url = bzrdir.get_branch_reference()
 
 
164
            if reference_url is None:
 
 
165
                return SuccessfulSmartServerResponse(('ok', ''))
 
 
167
                return SuccessfulSmartServerResponse(('ok', reference_url))
 
 
168
        except errors.NotBranchError:
 
 
169
            return FailedSmartServerResponse(('nobranch', ))