45
from bzrlib.revision import NULL_REVISION
45
from bzrlib.revision import ensure_null, NULL_REVISION
46
46
from bzrlib.trace import mutter, note, warning
48
48
# Note: RemoteBzrDirFormat is in bzrdir.py
62
62
self._real_bzrdir = None
64
64
if _client is None:
65
self._shared_medium = transport.get_shared_medium()
66
self._client = client._SmartClient(self._shared_medium)
65
medium = transport.get_smart_medium()
66
self._client = client._SmartClient(medium, transport.base)
68
68
self._client = _client
69
self._shared_medium = None
72
71
path = self._path_for_remote_call(self._client)
150
149
def open_repository(self):
151
150
path = self._path_for_remote_call(self._client)
152
151
verb = 'BzrDir.find_repositoryV2'
153
response = self._client.call(verb, path)
154
if (response == ('error', "Generic bzr smart protocol error: "
155
"bad request '%s'" % verb) or
156
response == ('error', "Generic bzr smart protocol error: "
157
"bad request u'%s'" % verb)):
153
response = self._client.call(verb, path)
154
except errors.UnknownSmartMethod:
158
155
verb = 'BzrDir.find_repository'
159
156
response = self._client.call(verb, path)
160
157
assert response[0] in ('ok', 'norepository'), \
361
358
self._ensure_real()
362
359
return self._real_repository._generate_text_key_index()
361
@symbol_versioning.deprecated_method(symbol_versioning.one_four)
364
362
def get_revision_graph(self, revision_id=None):
365
363
"""See Repository.get_revision_graph()."""
364
return self._get_revision_graph(revision_id)
366
def _get_revision_graph(self, revision_id):
367
"""Private method for using with old (< 1.2) servers to fallback."""
366
368
if revision_id is None:
368
370
elif revision.is_null(revision_id):
632
634
path = self.bzrdir._path_for_remote_call(self._client)
633
response, protocol = self._client.call_expecting_body(
634
'Repository.tarball', path, compression)
636
response, protocol = self._client.call_expecting_body(
637
'Repository.tarball', path, compression)
638
except errors.UnknownSmartMethod:
639
protocol.cancel_read_body()
635
641
if response[0] == 'ok':
636
642
# Extract the tarball and return it
637
643
t = tempfile.NamedTemporaryFile()
639
645
t.write(protocol.read_body_bytes())
642
if (response == ('error', "Generic bzr smart protocol error: "
643
"bad request 'Repository.tarball'") or
644
response == ('error', "Generic bzr smart protocol error: "
645
"bad request u'Repository.tarball'")):
646
protocol.cancel_read_body()
648
648
raise errors.UnexpectedSmartServerResponse(response)
650
650
def sprout(self, to_bzrdir, revision_id=None):
714
714
return self._real_repository.clone(a_bzrdir, revision_id=revision_id)
716
716
def make_working_trees(self):
717
"""RemoteRepositories never create working trees by default."""
717
"""See Repository.make_working_trees"""
719
return self._real_repository.make_working_trees()
720
721
def revision_ids_to_search_result(self, result_set):
721
722
"""Convert a set of revision ids to a graph SearchResult."""
811
812
100.0 * len(self._requested_parents) / len(ancestry))
812
813
return dict((k, ancestry[k]) for k in present_keys)
814
def _response_is_unknown_method(self, response, verb):
815
"""Return True if response is an unknonwn method response to verb.
817
:param response: The response from a smart client call_expecting_body
819
:param verb: The verb used in that call.
820
:return: True if an unknown method was encountered.
822
# This might live better on
823
# bzrlib.smart.protocol.SmartClientRequestProtocolOne
824
if (response[0] == ('error', "Generic bzr smart protocol error: "
825
"bad request '%s'" % verb) or
826
response[0] == ('error', "Generic bzr smart protocol error: "
827
"bad request u'%s'" % verb)):
828
response[1].cancel_read_body()
832
815
def _get_parent_map(self, keys):
833
816
"""Helper for get_parent_map that performs the RPC."""
834
medium = self._client.get_smart_medium()
817
medium = self._client._medium
835
818
if not medium._remote_is_at_least_1_2:
836
819
# We already found out that the server can't understand
837
820
# Repository.get_parent_map requests, so just fetch the whole
822
# XXX: Note that this will issue a deprecation warning. This is ok
823
# :- its because we're working with a deprecated server anyway, and
824
# the user will almost certainly have seen a warning about the
825
# server version already.
839
826
return self.get_revision_graph()
875
862
assert type(key) is str
876
863
verb = 'Repository.get_parent_map'
877
864
args = (path,) + tuple(keys)
878
response = self._client.call_with_body_bytes_expecting_body(
879
verb, args, self._serialise_search_recipe(recipe))
880
if self._response_is_unknown_method(response, verb):
866
response = self._client.call_with_body_bytes_expecting_body(
867
verb, args, self._serialise_search_recipe(recipe))
868
except errors.UnknownSmartMethod:
881
869
# Server does not support this method, so get the whole graph.
882
870
# Worse, we have to force a disconnection, because the server now
883
871
# doesn't realise it has a body on the wire to consume, so the
889
877
# To avoid having to disconnect repeatedly, we keep track of the
890
878
# fact the server doesn't understand remote methods added in 1.2.
891
879
medium._remote_is_at_least_1_2 = False
892
return self.get_revision_graph()
893
elif response[0][0] not in ['ok']:
894
reponse[1].cancel_read_body()
880
return self.get_revision_graph(None)
881
if response[0][0] not in ['ok']:
882
response[1].cancel_read_body()
895
883
raise errors.UnexpectedSmartServerResponse(response[0])
896
884
if response[0][0] == 'ok':
897
885
coded = bz2.decompress(response[1].read_body_bytes())
1007
995
return self._real_repository.pack()
1009
997
def set_make_working_trees(self, new_value):
1010
raise NotImplementedError(self.set_make_working_trees)
999
self._real_repository.set_make_working_trees(new_value)
1012
1001
@needs_write_lock
1013
1002
def sign_revision(self, revision_id, gpg_strategy):
1046
1035
return self._real_repository.has_signature_for_revision_id(revision_id)
1048
1037
def get_data_stream_for_search(self, search):
1049
medium = self._client.get_smart_medium()
1038
medium = self._client._medium
1050
1039
if not medium._remote_is_at_least_1_2:
1051
1040
self._ensure_real()
1052
1041
return self._real_repository.get_data_stream_for_search(search)
1053
1042
REQUEST_NAME = 'Repository.stream_revisions_chunked'
1054
1043
path = self.bzrdir._path_for_remote_call(self._client)
1055
1044
body = self._serialise_search_recipe(search.get_recipe())
1056
response, protocol = self._client.call_with_body_bytes_expecting_body(
1057
REQUEST_NAME, (path,), body)
1059
if self._response_is_unknown_method((response, protocol), REQUEST_NAME):
1046
result = self._client.call_with_body_bytes_expecting_body(
1047
REQUEST_NAME, (path,), body)
1048
response, protocol = result
1049
except errors.UnknownSmartMethod:
1060
1050
# Server does not support this method, so fall back to VFS.
1061
1051
# Worse, we have to force a disconnection, because the server now
1062
1052
# doesn't realise it has a body on the wire to consume, so the
1220
1210
if _client is not None:
1221
1211
self._client = _client
1223
self._client = client._SmartClient(self.bzrdir._shared_medium)
1213
self._client = remote_bzrdir._client
1224
1214
self.repository = remote_repository
1225
1215
if real_branch is not None:
1226
1216
self._real_branch = real_branch
1500
1491
def is_locked(self):
1501
1492
return self._lock_count >= 1
1503
1495
def set_last_revision_info(self, revno, revision_id):
1505
self._clear_cached_state()
1506
return self._real_branch.set_last_revision_info(revno, revision_id)
1496
assert type(revno) is int
1497
revision_id = ensure_null(revision_id)
1498
path = self.bzrdir._path_for_remote_call(self._client)
1500
response = self._client.call('Branch.set_last_revision_info',
1501
path, self._lock_token, self._repo_lock_token, str(revno), revision_id)
1502
except errors.UnknownSmartMethod:
1504
self._clear_cached_state()
1505
return self._real_branch.set_last_revision_info(revno, revision_id)
1506
if response == ('ok',):
1507
self._clear_cached_state()
1508
elif response[0] == 'NoSuchRevision':
1509
raise NoSuchRevision(self, response[1])
1511
raise errors.UnexpectedSmartServerResponse(response)
1508
1513
def generate_revision_history(self, revision_id, last_rev=None,
1509
1514
other_branch=None):