782
777
self._ensure_real()
783
778
self._real_repository.create_bundle(target, base, fileobj, format)
786
def control_weaves(self):
788
return self._real_repository.control_weaves
791
781
def get_ancestry(self, revision_id, topo_sorted=True):
792
782
self._ensure_real()
793
783
return self._real_repository.get_ancestry(revision_id, topo_sorted)
796
def get_inventory_weave(self):
798
return self._real_repository.get_inventory_weave()
800
785
def fileids_altered_by_revision_ids(self, revision_ids):
801
786
self._ensure_real()
802
787
return self._real_repository.fileids_altered_by_revision_ids(revision_ids)
1038
1033
self._ensure_real()
1039
1034
return self._real_repository.pack()
1037
def revisions(self):
1038
"""Decorate the real repository for now.
1040
In the short term this should become a real object to intercept graph
1043
In the long term a full blown network facility is needed.
1046
return self._real_repository.revisions
1041
1048
def set_make_working_trees(self, new_value):
1042
1049
self._ensure_real()
1043
1050
self._real_repository.set_make_working_trees(new_value)
1053
def signatures(self):
1054
"""Decorate the real repository for now.
1056
In the long term a full blown network facility is needed to avoid
1057
creating a real repository object locally.
1060
return self._real_repository.signatures
1045
1062
@needs_write_lock
1046
1063
def sign_revision(self, revision_id, gpg_strategy):
1047
1064
self._ensure_real()
1048
1065
return self._real_repository.sign_revision(revision_id, gpg_strategy)
1069
"""Decorate the real repository for now.
1071
In the long term a full blown network facility is needed to avoid
1072
creating a real repository object locally.
1075
return self._real_repository.texts
1050
1077
@needs_read_lock
1051
1078
def get_revisions(self, revision_ids):
1052
1079
self._ensure_real()
1078
1105
self._ensure_real()
1079
1106
return self._real_repository.has_signature_for_revision_id(revision_id)
1081
def get_data_stream_for_search(self, search):
1082
medium = self._client._medium
1083
if medium._is_remote_before((1, 2)):
1085
return self._real_repository.get_data_stream_for_search(search)
1086
REQUEST_NAME = 'Repository.stream_revisions_chunked'
1087
path = self.bzrdir._path_for_remote_call(self._client)
1088
body = self._serialise_search_recipe(search.get_recipe())
1090
result = self._client.call_with_body_bytes_expecting_body(
1091
REQUEST_NAME, (path,), body)
1092
response, protocol = result
1093
except errors.UnknownSmartMethod:
1094
# Server does not support this method, so fall back to VFS.
1095
# Worse, we have to force a disconnection, because the server now
1096
# doesn't realise it has a body on the wire to consume, so the
1097
# only way to recover is to abandon the connection.
1099
'Server is too old for streaming pull, reconnecting. '
1100
'(Upgrade the server to Bazaar 1.2 to avoid this)')
1102
# To avoid having to disconnect repeatedly, we keep track of the
1103
# fact the server doesn't understand this remote method.
1104
medium._remember_remote_is_before((1, 2))
1106
return self._real_repository.get_data_stream_for_search(search)
1108
if response == ('ok',):
1109
return self._deserialise_stream(protocol)
1110
if response == ('NoSuchRevision', ):
1111
# We cannot easily identify the revision that is missing in this
1112
# situation without doing much more network IO. For now, bail.
1113
raise NoSuchRevision(self, "unknown")
1115
raise errors.UnexpectedSmartServerResponse(response)
1117
def _deserialise_stream(self, protocol):
1118
stream = protocol.read_streamed_body()
1119
container_parser = ContainerPushParser()
1120
for bytes in stream:
1121
container_parser.accept_bytes(bytes)
1122
records = container_parser.read_pending_records()
1123
for record_names, record_bytes in records:
1124
if len(record_names) != 1:
1125
# These records should have only one name, and that name
1126
# should be a one-element tuple.
1127
raise errors.SmartProtocolError(
1128
'Repository data stream had invalid record name %r'
1130
name_tuple = record_names[0]
1131
yield name_tuple, record_bytes
1133
def insert_data_stream(self, stream):
1135
self._real_repository.insert_data_stream(stream)
1137
1108
def item_keys_introduced_by(self, revision_ids, _files_pb=None):
1138
1109
self._ensure_real()
1139
1110
return self._real_repository.item_keys_introduced_by(revision_ids,
1293
1265
if self._lock_mode == 'r':
1294
1266
self._real_branch.lock_read()
1268
def _clear_cached_state(self):
1269
super(RemoteBranch, self)._clear_cached_state()
1270
if self._real_branch is not None:
1271
self._real_branch._clear_cached_state()
1273
def _clear_cached_state_of_remote_branch_only(self):
1274
"""Like _clear_cached_state, but doesn't clear the cache of
1277
This is useful when falling back to calling a method of
1278
self._real_branch that changes state. In that case the underlying
1279
branch changes, so we need to invalidate this RemoteBranch's cache of
1280
it. However, there's no need to invalidate the _real_branch's cache
1281
too, in fact doing so might harm performance.
1283
super(RemoteBranch, self)._clear_cached_state()
1297
1286
def control_files(self):
1298
1287
# Defer actually creating RemoteBranchLockableFiles until its needed,
1460
1448
response_tuple, response_handler = self._client.call_expecting_body(
1461
1449
'Branch.revision_history', path)
1462
1450
if response_tuple[0] != 'ok':
1463
raise UnexpectedSmartServerResponse(response_tuple)
1451
raise errors.UnexpectedSmartServerResponse(response_tuple)
1464
1452
result = response_handler.read_body_bytes().split('\x00')
1465
1453
if result == ['']:
1457
def _set_last_revision_descendant(self, revision_id, other_branch,
1458
allow_diverged=False, allow_overwrite_descendant=False):
1459
path = self.bzrdir._path_for_remote_call(self._client)
1461
response = self._client.call('Branch.set_last_revision_ex',
1462
path, self._lock_token, self._repo_lock_token, revision_id,
1463
int(allow_diverged), int(allow_overwrite_descendant))
1464
except errors.ErrorFromSmartServer, err:
1465
if err.error_verb == 'NoSuchRevision':
1466
raise NoSuchRevision(self, revision_id)
1467
elif err.error_verb == 'Diverged':
1468
raise errors.DivergedBranches(self, other_branch)
1470
self._clear_cached_state()
1471
if len(response) != 3 and response[0] != 'ok':
1472
raise errors.UnexpectedSmartServerResponse(response)
1473
new_revno, new_revision_id = response[1:]
1474
self._last_revision_info_cache = new_revno, new_revision_id
1475
self._real_branch._last_revision_info_cache = new_revno, new_revision_id
1477
def _set_last_revision(self, revision_id):
1478
path = self.bzrdir._path_for_remote_call(self._client)
1479
self._clear_cached_state()
1481
response = self._client.call('Branch.set_last_revision',
1482
path, self._lock_token, self._repo_lock_token, revision_id)
1483
except errors.ErrorFromSmartServer, err:
1484
if err.error_verb == 'NoSuchRevision':
1485
raise NoSuchRevision(self, revision_id)
1487
if response != ('ok',):
1488
raise errors.UnexpectedSmartServerResponse(response)
1469
1490
@needs_write_lock
1470
1491
def set_revision_history(self, rev_history):
1471
1492
# Send just the tip revision of the history; the server will generate
1472
1493
# the full history from that. If the revision doesn't exist in this
1473
1494
# branch, NoSuchRevision will be raised.
1474
path = self.bzrdir._path_for_remote_call(self._client)
1475
1495
if rev_history == []:
1476
1496
rev_id = 'null:'
1478
1498
rev_id = rev_history[-1]
1479
self._clear_cached_state()
1481
response = self._client.call('Branch.set_last_revision',
1482
path, self._lock_token, self._repo_lock_token, rev_id)
1483
except errors.ErrorFromSmartServer, err:
1484
if err.error_verb == 'NoSuchRevision':
1485
raise NoSuchRevision(self, rev_id)
1487
if response != ('ok',):
1488
raise errors.UnexpectedSmartServerResponse(response)
1499
self._set_last_revision(rev_id)
1489
1500
self._cache_revision_history(rev_history)
1491
1502
def get_parent(self):
1534
1546
path, self._lock_token, self._repo_lock_token, str(revno), revision_id)
1535
1547
except errors.UnknownSmartMethod:
1536
1548
self._ensure_real()
1537
self._clear_cached_state()
1538
return self._real_branch.set_last_revision_info(revno, revision_id)
1549
self._clear_cached_state_of_remote_branch_only()
1550
self._real_branch.set_last_revision_info(revno, revision_id)
1551
self._last_revision_info_cache = revno, revision_id
1539
1553
except errors.ErrorFromSmartServer, err:
1540
1554
if err.error_verb == 'NoSuchRevision':
1541
1555
raise NoSuchRevision(self, err.error_args[0])
1543
1557
if response == ('ok',):
1544
1558
self._clear_cached_state()
1559
self._last_revision_info_cache = revno, revision_id
1560
# Update the _real_branch's cache too.
1561
if self._real_branch is not None:
1562
cache = self._last_revision_info_cache
1563
self._real_branch._last_revision_info_cache = cache
1546
1565
raise errors.UnexpectedSmartServerResponse(response)
1548
1568
def generate_revision_history(self, revision_id, last_rev=None,
1549
1569
other_branch=None):
1570
medium = self._client._medium
1571
if not medium._is_remote_before((1, 6)):
1573
self._set_last_revision_descendant(revision_id, other_branch,
1574
allow_diverged=True, allow_overwrite_descendant=True)
1576
except errors.UnknownSmartMethod:
1577
medium._remember_remote_is_before((1, 6))
1578
self._clear_cached_state_of_remote_branch_only()
1550
1579
self._ensure_real()
1551
return self._real_branch.generate_revision_history(
1580
self._real_branch.generate_revision_history(
1552
1581
revision_id, last_rev=last_rev, other_branch=other_branch)
1560
1589
self._ensure_real()
1561
1590
return self._real_branch.set_push_location(location)
1563
1593
def update_revisions(self, other, stop_revision=None, overwrite=False,
1566
return self._real_branch.update_revisions(
1567
other, stop_revision=stop_revision, overwrite=overwrite,
1595
"""See Branch.update_revisions."""
1598
if stop_revision is None:
1599
stop_revision = other.last_revision()
1600
if revision.is_null(stop_revision):
1601
# if there are no commits, we're done.
1603
self.fetch(other, stop_revision)
1606
# Just unconditionally set the new revision. We don't care if
1607
# the branches have diverged.
1608
self._set_last_revision(stop_revision)
1610
medium = self._client._medium
1611
if not medium._is_remote_before((1, 6)):
1613
self._set_last_revision_descendant(stop_revision, other)
1615
except errors.UnknownSmartMethod:
1616
medium._remember_remote_is_before((1, 6))
1617
# Fallback for pre-1.6 servers: check for divergence
1618
# client-side, then do _set_last_revision.
1619
last_rev = revision.ensure_null(self.last_revision())
1621
graph = self.repository.get_graph()
1622
if self._check_if_descendant_or_diverged(
1623
stop_revision, last_rev, graph, other):
1624
# stop_revision is a descendant of last_rev, but we aren't
1625
# overwriting, so we're done.
1627
self._set_last_revision(stop_revision)
1571
1632
def _extract_tar(tar, to_dir):