41
41
from bzrlib.lockable_files import LockableFiles
42
42
from bzrlib.pack import ContainerPushParser
43
43
from bzrlib.smart import client, vfs
44
from bzrlib.symbol_versioning import (
47
44
from bzrlib.revision import ensure_null, NULL_REVISION
48
45
from bzrlib.trace import mutter, note, warning
120
117
def get_branch_reference(self):
121
118
"""See BzrDir.get_branch_reference()."""
122
119
path = self._path_for_remote_call(self._client)
123
response = self._client.call('BzrDir.open_branch', path)
121
response = self._client.call('BzrDir.open_branch', path)
122
except errors.ErrorFromSmartServer, err:
123
if err.error_tuple == ('nobranch',):
124
raise errors.NotBranchError(path=self.root_transport.base)
124
126
if response[0] == 'ok':
125
127
if response[1] == '':
126
128
# branch at this location.
129
131
# a branch reference, use the existing BranchReference logic.
130
132
return response[1]
131
elif response == ('nobranch',):
132
raise errors.NotBranchError(path=self.root_transport.base)
134
134
raise errors.UnexpectedSmartServerResponse(response)
153
153
path = self._path_for_remote_call(self._client)
154
154
verb = 'BzrDir.find_repositoryV2'
156
response = self._client.call(verb, path)
157
except errors.UnknownSmartMethod:
158
verb = 'BzrDir.find_repository'
159
response = self._client.call(verb, path)
160
if response[0] == 'norepository':
161
raise errors.NoRepositoryPresent(self)
162
elif response[0] != 'ok':
163
raise SmartProtocolError('unexpected response %r'
157
response = self._client.call(verb, path)
158
except errors.UnknownSmartMethod:
159
verb = 'BzrDir.find_repository'
160
response = self._client.call(verb, path)
161
except errors.ErrorFromSmartServer, err:
162
if err.error_verb == 'norepository':
163
raise errors.NoRepositoryPresent(self)
165
if response[0] != 'ok':
166
raise errors.UnexpectedSmartServerResponse(response)
165
167
if verb == 'BzrDir.find_repository':
166
168
# servers that don't support the V2 method don't support external
167
169
# references either.
379
381
path = self.bzrdir._path_for_remote_call(self._client)
380
response = self._client.call_expecting_body(
381
'Repository.get_revision_graph', path, revision_id)
382
if response[0][0] not in ['ok', 'nosuchrevision']:
383
raise errors.UnexpectedSmartServerResponse(response[0])
384
if response[0][0] == 'ok':
385
coded = response[1].read_body_bytes()
387
# no revisions in this repository!
389
lines = coded.split('\n')
392
d = tuple(line.split())
393
revision_graph[d[0]] = d[1:]
395
return revision_graph
397
response_body = response[1].read_body_bytes()
399
raise SmartProtocolError('unexpected response body')
400
raise NoSuchRevision(self, revision_id)
383
response = self._client.call_expecting_body(
384
'Repository.get_revision_graph', path, revision_id)
385
except errors.ErrorFromSmartServer, err:
386
if err.error_verb == 'nosuchrevision':
387
raise NoSuchRevision(self, revision_id)
389
response_tuple, response_handler = response
390
if response_tuple[0] != 'ok':
391
raise errors.UnexpectedSmartServerResponse(response_tuple)
392
coded = response_handler.read_body_bytes()
394
# no revisions in this repository!
396
lines = coded.split('\n')
399
d = tuple(line.split())
400
revision_graph[d[0]] = d[1:]
402
return revision_graph
402
404
def has_revision(self, revision_id):
403
405
"""See Repository.has_revision()."""
405
407
# The null revision is always present.
407
409
path = self.bzrdir._path_for_remote_call(self._client)
408
response = self._client.call('Repository.has_revision', path, revision_id)
410
response = self._client.call(
411
'Repository.has_revision', path, revision_id)
409
412
if response[0] not in ('yes', 'no'):
410
raise SmartProtocolError('unexpected response code %s' % (response,))
413
raise errors.UnexpectedSmartServerResponse(response)
411
414
return response[0] == 'yes'
413
416
def has_revisions(self, revision_ids):
444
447
fmt_committers = 'no'
446
449
fmt_committers = 'yes'
447
response = self._client.call_expecting_body(
450
response_tuple, response_handler = self._client.call_expecting_body(
448
451
'Repository.gather_stats', path, fmt_revid, fmt_committers)
449
if response[0][0] != 'ok':
450
raise SmartProtocolError('unexpected response code %s'
452
if response_tuple[0] != 'ok':
453
raise errors.UnexpectedSmartServerResponse(response_tuple)
453
body = response[1].read_body_bytes()
455
body = response_handler.read_body_bytes()
455
457
for line in body.split('\n'):
515
517
path = self.bzrdir._path_for_remote_call(self._client)
516
518
if token is None:
518
response = self._client.call('Repository.lock_write', path, token)
521
response = self._client.call('Repository.lock_write', path, token)
522
except errors.ErrorFromSmartServer, err:
523
if err.error_verb == 'LockContention':
524
raise errors.LockContention('(remote lock)')
525
elif err.error_verb == 'UnlockableTransport':
526
raise errors.UnlockableTransport(self.bzrdir.root_transport)
527
elif err.error_verb == 'LockFailed':
528
raise errors.LockFailed(err.error_args[0], err.error_args[1])
519
531
if response[0] == 'ok':
520
532
ok, token = response
522
elif response[0] == 'LockContention':
523
raise errors.LockContention('(remote lock)')
524
elif response[0] == 'UnlockableTransport':
525
raise errors.UnlockableTransport(self.bzrdir.root_transport)
526
elif response[0] == 'LockFailed':
527
raise errors.LockFailed(response[1], response[2])
529
535
raise errors.UnexpectedSmartServerResponse(response)
595
601
# with no token the remote repository is not persistently locked.
597
response = self._client.call('Repository.unlock', path, token)
604
response = self._client.call('Repository.unlock', path, token)
605
except errors.ErrorFromSmartServer, err:
606
if err.error_verb == 'TokenMismatch':
607
raise errors.TokenMismatch(token, '(remote token)')
598
609
if response == ('ok',):
600
elif response[0] == 'TokenMismatch':
601
raise errors.TokenMismatch(token, '(remote token)')
603
612
raise errors.UnexpectedSmartServerResponse(response)
817
826
ancestry.update(parent_map)
818
827
present_keys = [k for k in keys if k in ancestry]
819
828
if 'hpss' in debug.debug_flags:
820
self._requested_parents.update(present_keys)
821
mutter('Current RemoteRepository graph hit rate: %d%%',
822
100.0 * len(self._requested_parents) / len(ancestry))
829
if self._requested_parents is not None and len(ancestry) != 0:
830
self._requested_parents.update(present_keys)
831
mutter('Current RemoteRepository graph hit rate: %d%%',
832
100.0 * len(self._requested_parents) / len(ancestry))
823
833
return dict((k, ancestry[k]) for k in present_keys)
825
835
def _get_parent_map(self, keys):
904
914
# fact the server doesn't understand remote methods added in 1.2.
905
915
medium._remote_is_at_least_1_2 = False
906
916
return self.get_revision_graph(None)
907
if response[0][0] not in ['ok']:
908
response[1].cancel_read_body()
909
raise errors.UnexpectedSmartServerResponse(response[0])
910
if response[0][0] == 'ok':
911
coded = bz2.decompress(response[1].read_body_bytes())
917
response_tuple, response_handler = response
918
if response_tuple[0] not in ['ok']:
919
response_handler.cancel_read_body()
920
raise errors.UnexpectedSmartServerResponse(response_tuple)
921
if response_tuple[0] == 'ok':
922
coded = bz2.decompress(response_handler.read_body_bytes())
913
924
# no revisions found
1304
1315
repo_token = self.repository.lock_write()
1305
1316
self.repository.unlock()
1306
1317
path = self.bzrdir._path_for_remote_call(self._client)
1307
response = self._client.call('Branch.lock_write', path, branch_token,
1309
if response[0] == 'ok':
1310
ok, branch_token, repo_token = response
1311
return branch_token, repo_token
1312
elif response[0] == 'LockContention':
1313
raise errors.LockContention('(remote lock)')
1314
elif response[0] == 'TokenMismatch':
1315
raise errors.TokenMismatch(token, '(remote token)')
1316
elif response[0] == 'UnlockableTransport':
1317
raise errors.UnlockableTransport(self.bzrdir.root_transport)
1318
elif response[0] == 'ReadOnlyError':
1319
raise errors.ReadOnlyError(self)
1320
elif response[0] == 'LockFailed':
1321
raise errors.LockFailed(response[1], response[2])
1319
response = self._client.call(
1320
'Branch.lock_write', path, branch_token, repo_token or '')
1321
except errors.ErrorFromSmartServer, err:
1322
if err.error_verb == 'LockContention':
1323
raise errors.LockContention('(remote lock)')
1324
elif err.error_verb == 'TokenMismatch':
1325
raise errors.TokenMismatch(token, '(remote token)')
1326
elif err.error_verb == 'UnlockableTransport':
1327
raise errors.UnlockableTransport(self.bzrdir.root_transport)
1328
elif err.error_verb == 'ReadOnlyError':
1329
raise errors.ReadOnlyError(self)
1330
elif err.error_verb == 'LockFailed':
1331
raise errors.LockFailed(err.error_args[0], err.error_args[1])
1333
if response[0] != 'ok':
1323
1334
raise errors.UnexpectedSmartServerResponse(response)
1335
ok, branch_token, repo_token = response
1336
return branch_token, repo_token
1325
1338
def lock_write(self, token=None):
1326
1339
if not self._lock_mode:
1364
1377
def _unlock(self, branch_token, repo_token):
1365
1378
path = self.bzrdir._path_for_remote_call(self._client)
1366
response = self._client.call('Branch.unlock', path, branch_token,
1380
response = self._client.call('Branch.unlock', path, branch_token,
1382
except errors.ErrorFromSmartServer, err:
1383
if err.error_verb == 'TokenMismatch':
1384
raise errors.TokenMismatch(
1385
str((branch_token, repo_token)), '(remote tokens)')
1368
1387
if response == ('ok',):
1370
elif response[0] == 'TokenMismatch':
1371
raise errors.TokenMismatch(
1372
str((branch_token, repo_token)), '(remote tokens)')
1374
raise errors.UnexpectedSmartServerResponse(response)
1389
raise errors.UnexpectedSmartServerResponse(response)
1376
1391
def unlock(self):
1377
1392
self._lock_count -= 1
1428
1443
def _gen_revision_history(self):
1429
1444
"""See Branch._gen_revision_history()."""
1430
1445
path = self.bzrdir._path_for_remote_call(self._client)
1431
response = self._client.call_expecting_body(
1446
response_tuple, response_handler = self._client.call_expecting_body(
1432
1447
'Branch.revision_history', path)
1433
if response[0][0] != 'ok':
1434
raise SmartProtocolError('unexpected response code %s' % (response,))
1435
result = response[1].read_body_bytes().split('\x00')
1448
if response_tuple[0] != 'ok':
1449
raise UnexpectedSmartServerResponse(response_tuple)
1450
result = response_handler.read_body_bytes().split('\x00')
1436
1451
if result == ['']:
1449
1464
rev_id = rev_history[-1]
1450
1465
self._clear_cached_state()
1451
response = self._client.call('Branch.set_last_revision',
1452
path, self._lock_token, self._repo_lock_token, rev_id)
1453
if response[0] == 'NoSuchRevision':
1454
raise NoSuchRevision(self, rev_id)
1455
elif response[0] != 'ok':
1456
raise SmartProtocolError('unexpected response code %s' % (response,))
1467
response = self._client.call('Branch.set_last_revision',
1468
path, self._lock_token, self._repo_lock_token, rev_id)
1469
except errors.ErrorFromSmartServer, err:
1470
if err.error_verb == 'NoSuchRevision':
1471
raise NoSuchRevision(self, rev_id)
1473
if response != ('ok',):
1474
raise errors.UnexpectedSmartServerResponse(response)
1457
1475
self._cache_revision_history(rev_history)
1459
1477
def get_parent(self):
1509
1527
self._ensure_real()
1510
1528
self._clear_cached_state()
1511
1529
return self._real_branch.set_last_revision_info(revno, revision_id)
1530
except errors.ErrorFromSmartServer, err:
1531
if err.error_verb == 'NoSuchRevision':
1532
raise NoSuchRevision(self, err.error_args[0])
1512
1534
if response == ('ok',):
1513
1535
self._clear_cached_state()
1514
elif response[0] == 'NoSuchRevision':
1515
raise NoSuchRevision(self, response[1])
1517
1537
raise errors.UnexpectedSmartServerResponse(response)