2151
2151
repo_format = response_tuple_to_repo_format(response[3:])
2152
2152
repo_path = response[2]
2153
2153
if repository is not None:
2154
remote_repo_url = urlutils.join(medium.base, repo_path)
2154
remote_repo_url = urlutils.join(a_bzrdir.user_url, repo_path)
2155
2155
url_diff = urlutils.relative_url(repository.user_url,
2156
2156
remote_repo_url)
2157
2157
if url_diff != '.':
2158
2158
raise AssertionError(
2159
2159
'repository.user_url %r does not match URL from server '
2160
2160
'response (%r + %r)'
2161
% (repository.user_url, medium.base, repo_path))
2161
% (repository.user_url, a_bzrdir.user_url, repo_path))
2162
2162
remote_repo = repository
2164
2164
if repo_path == '':
2194
2194
self._ensure_real()
2195
2195
return self._custom_format.supports_set_append_revisions_only()
2197
def _use_default_local_heads_to_fetch(self):
2198
# If the branch format is a metadir format *and* its heads_to_fetch
2199
# implementation is not overridden vs the base class, we can use the
2200
# base class logic rather than use the heads_to_fetch RPC. This is
2201
# usually cheaper in terms of net round trips, as the last-revision and
2202
# tags info fetched is cached and would be fetched anyway.
2204
if isinstance(self._custom_format, branch.BranchFormatMetadir):
2205
branch_class = self._custom_format._branch_class()
2206
heads_to_fetch_impl = branch_class.heads_to_fetch.im_func
2207
if heads_to_fetch_impl is branch.Branch.heads_to_fetch.im_func:
2198
2211
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
2199
2212
"""Branch stored on a server accessed by HPSS RPC.
2781
2794
self._ensure_real()
2782
2795
return self._real_branch.set_push_location(location)
2797
def heads_to_fetch(self):
2798
if self._format._use_default_local_heads_to_fetch():
2799
# We recognise this format, and its heads-to-fetch implementation
2800
# is the default one (tip + tags). In this case it's cheaper to
2801
# just use the default implementation rather than a special RPC as
2802
# the tip and tags data is cached.
2803
return branch.Branch.heads_to_fetch(self)
2804
medium = self._client._medium
2805
if medium._is_remote_before((2, 4)):
2806
return self._vfs_heads_to_fetch()
2808
return self._rpc_heads_to_fetch()
2809
except errors.UnknownSmartMethod:
2810
medium._remember_remote_is_before((2, 4))
2811
return self._vfs_heads_to_fetch()
2813
def _rpc_heads_to_fetch(self):
2814
response = self._call('Branch.heads_to_fetch', self._remote_path())
2815
if len(response) != 2:
2816
raise errors.UnexpectedSmartServerResponse(response)
2817
must_fetch, if_present_fetch = response
2818
return set(must_fetch), set(if_present_fetch)
2820
def _vfs_heads_to_fetch(self):
2822
return self._real_branch.heads_to_fetch()
2785
2825
class RemoteConfig(object):
2786
2826
"""A Config that reads and writes from smart verbs.
2973
3013
'Missing key %r in context %r', key_err.args[0], context)
2976
if err.error_verb == 'IncompatibleRepositories':
2977
raise errors.IncompatibleRepositories(err.error_args[0],
2978
err.error_args[1], err.error_args[2])
2979
elif err.error_verb == 'NoSuchRevision':
3016
if err.error_verb == 'NoSuchRevision':
2980
3017
raise NoSuchRevision(find('branch'), err.error_args[0])
2981
3018
elif err.error_verb == 'nosuchrevision':
2982
3019
raise NoSuchRevision(find('repository'), err.error_args[0])
2990
3027
elif err.error_verb == 'norepository':
2991
3028
raise errors.NoRepositoryPresent(find('bzrdir'))
2992
elif err.error_verb == 'LockContention':
2993
raise errors.LockContention('(remote lock)')
2994
3029
elif err.error_verb == 'UnlockableTransport':
2995
3030
raise errors.UnlockableTransport(find('bzrdir').root_transport)
2996
elif err.error_verb == 'LockFailed':
2997
raise errors.LockFailed(err.error_args[0], err.error_args[1])
2998
3031
elif err.error_verb == 'TokenMismatch':
2999
3032
raise errors.TokenMismatch(find('token'), '(remote token)')
3000
3033
elif err.error_verb == 'Diverged':
3001
3034
raise errors.DivergedBranches(find('branch'), find('other_branch'))
3002
elif err.error_verb == 'TipChangeRejected':
3003
raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
3004
elif err.error_verb == 'UnstackableBranchFormat':
3005
raise errors.UnstackableBranchFormat(*err.error_args)
3006
elif err.error_verb == 'UnstackableRepositoryFormat':
3007
raise errors.UnstackableRepositoryFormat(*err.error_args)
3008
3035
elif err.error_verb == 'NotStacked':
3009
3036
raise errors.NotStacked(branch=find('branch'))
3010
3037
elif err.error_verb == 'PermissionDenied':
3020
3047
elif err.error_verb == 'NoSuchFile':
3021
3048
path = get_path()
3022
3049
raise errors.NoSuchFile(path)
3050
_translate_error_without_context(err)
3053
def _translate_error_without_context(err):
3054
"""Translate any ErrorFromSmartServer values that don't require context"""
3055
if err.error_verb == 'IncompatibleRepositories':
3056
raise errors.IncompatibleRepositories(err.error_args[0],
3057
err.error_args[1], err.error_args[2])
3058
elif err.error_verb == 'LockContention':
3059
raise errors.LockContention('(remote lock)')
3060
elif err.error_verb == 'LockFailed':
3061
raise errors.LockFailed(err.error_args[0], err.error_args[1])
3062
elif err.error_verb == 'TipChangeRejected':
3063
raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
3064
elif err.error_verb == 'UnstackableBranchFormat':
3065
raise errors.UnstackableBranchFormat(*err.error_args)
3066
elif err.error_verb == 'UnstackableRepositoryFormat':
3067
raise errors.UnstackableRepositoryFormat(*err.error_args)
3023
3068
elif err.error_verb == 'FileExists':
3024
3069
raise errors.FileExists(err.error_args[0])
3025
3070
elif err.error_verb == 'DirectoryNotEmpty':
3044
3089
raise UnicodeEncodeError(encoding, val, start, end, reason)
3045
3090
elif err.error_verb == 'ReadOnlyError':
3046
3091
raise errors.TransportNotPossible('readonly transport')
3092
elif err.error_verb == 'MemoryError':
3093
raise errors.BzrError("remote server out of memory\n"
3094
"Retry non-remotely, or contact the server admin for details.")
3047
3095
raise errors.UnknownErrorFromSmartServer(err)