331
334
_mod_bzrdir.BzrDirMetaFormat1._set_repository_format) #.im_func)
337
class RemoteControlStore(config.IniFileStore):
338
"""Control store which attempts to use HPSS calls to retrieve control store.
340
Note that this is specific to bzr-based formats.
343
def __init__(self, bzrdir):
344
super(RemoteControlStore, self).__init__()
346
self._real_store = None
348
def lock_write(self, token=None):
350
return self._real_store.lock_write(token)
354
return self._real_store.unlock()
358
# We need to be able to override the undecorated implementation
359
self.save_without_locking()
361
def save_without_locking(self):
362
super(RemoteControlStore, self).save()
364
def _ensure_real(self):
365
self.bzrdir._ensure_real()
366
if self._real_store is None:
367
self._real_store = config.ControlStore(self.bzrdir)
369
def external_url(self):
370
return self.bzrdir.user_url
372
def _load_content(self):
373
medium = self.bzrdir._client._medium
374
path = self.bzrdir._path_for_remote_call(self.bzrdir._client)
376
response, handler = self.bzrdir._call_expecting_body(
377
'BzrDir.get_config_file', path)
378
except errors.UnknownSmartMethod:
380
return self._real_store._load_content()
381
if len(response) and response[0] != 'ok':
382
raise errors.UnexpectedSmartServerResponse(response)
383
return handler.read_body_bytes()
385
def _save_content(self, content):
386
# FIXME JRV 2011-11-22: Ideally this should use a
387
# HPSS call too, but at the moment it is not possible
388
# to write lock control directories.
390
return self._real_store._save_content(content)
334
393
class RemoteBzrDir(_mod_bzrdir.BzrDir, _RpcHelper):
335
394
"""Control directory on a remote server, accessed via bzr:// or similar."""
1020
1125
for older plugins that don't use e.g. the CommitBuilder
1024
return self._real_repository.commit_write_group()
1128
if self._real_repository:
1130
return self._real_repository.commit_write_group()
1131
if not self.is_in_write_group():
1132
raise errors.BzrError("not in write group")
1133
path = self.bzrdir._path_for_remote_call(self._client)
1134
response = self._call('Repository.commit_write_group', path,
1135
self._lock_token, self._write_group_tokens)
1136
if response != ('ok', ):
1137
raise errors.UnexpectedSmartServerResponse(response)
1138
self._write_group_tokens = None
1026
1140
def resume_write_group(self, tokens):
1028
return self._real_repository.resume_write_group(tokens)
1141
if self._real_repository:
1142
return self._real_repository.resume_write_group(tokens)
1143
path = self.bzrdir._path_for_remote_call(self._client)
1145
response = self._call('Repository.check_write_group', path,
1146
self._lock_token, tokens)
1147
except errors.UnknownSmartMethod:
1149
return self._real_repository.resume_write_group(tokens)
1150
if response != ('ok', ):
1151
raise errors.UnexpectedSmartServerResponse(response)
1152
self._write_group_tokens = tokens
1030
1154
def suspend_write_group(self):
1032
return self._real_repository.suspend_write_group()
1155
if self._real_repository:
1156
return self._real_repository.suspend_write_group()
1157
ret = self._write_group_tokens or []
1158
self._write_group_tokens = None
1034
1161
def get_missing_parent_inventories(self, check_for_missing_texts=True):
1035
1162
self._ensure_real()
1480
1642
raise errors.UnexpectedSmartServerResponse(response)
1482
1645
def sprout(self, to_bzrdir, revision_id=None):
1483
# TODO: Option to control what format is created?
1485
dest_repo = self._real_repository._format.initialize(to_bzrdir,
1646
"""Create a descendent repository for new development.
1648
Unlike clone, this does not copy the settings of the repository.
1650
dest_repo = self._create_sprouting_repo(to_bzrdir, shared=False)
1487
1651
dest_repo.fetch(self, revision_id=revision_id)
1488
1652
return dest_repo
1654
def _create_sprouting_repo(self, a_bzrdir, shared):
1655
if not isinstance(a_bzrdir._format, self.bzrdir._format.__class__):
1656
# use target default format.
1657
dest_repo = a_bzrdir.create_repository()
1659
# Most control formats need the repository to be specifically
1660
# created, but on some old all-in-one formats it's not needed
1662
dest_repo = self._format.initialize(a_bzrdir, shared=shared)
1663
except errors.UninitializableFormat:
1664
dest_repo = a_bzrdir.open_repository()
1490
1667
### These methods are just thin shims to the VFS object for now.
1492
1670
def revision_tree(self, revision_id):
1494
return self._real_repository.revision_tree(revision_id)
1671
revision_id = _mod_revision.ensure_null(revision_id)
1672
if revision_id == _mod_revision.NULL_REVISION:
1673
return InventoryRevisionTree(self,
1674
Inventory(root_id=None), _mod_revision.NULL_REVISION)
1676
return list(self.revision_trees([revision_id]))[0]
1496
1678
def get_serializer_format(self):
1498
return self._real_repository.get_serializer_format()
1679
path = self.bzrdir._path_for_remote_call(self._client)
1681
response = self._call('VersionedFileRepository.get_serializer_format',
1683
except errors.UnknownSmartMethod:
1685
return self._real_repository.get_serializer_format()
1686
if response[0] != 'ok':
1687
raise errors.UnexpectedSmartServerResponse(response)
1500
1690
def get_commit_builder(self, branch, parents, config, timestamp=None,
1501
1691
timezone=None, committer=None, revprops=None,
1994
2207
def _serializer(self):
1995
2208
return self._format._serializer
1997
2211
def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
1999
return self._real_repository.store_revision_signature(
2000
gpg_strategy, plaintext, revision_id)
2212
signature = gpg_strategy.sign(plaintext)
2213
self.add_signature_text(revision_id, signature)
2002
2215
def add_signature_text(self, revision_id, signature):
2003
2216
self._ensure_real()
2004
2217
return self._real_repository.add_signature_text(revision_id, signature)
2006
2219
def has_signature_for_revision_id(self, revision_id):
2220
path = self.bzrdir._path_for_remote_call(self._client)
2222
response = self._call('Repository.has_signature_for_revision_id',
2224
except errors.UnknownSmartMethod:
2226
return self._real_repository.has_signature_for_revision_id(
2228
if response[0] not in ('yes', 'no'):
2229
raise SmartProtocolError('unexpected response code %s' % (response,))
2230
return (response[0] == 'yes')
2232
def verify_revision_signature(self, revision_id, gpg_strategy):
2007
2233
self._ensure_real()
2008
return self._real_repository.has_signature_for_revision_id(revision_id)
2234
return self._real_repository.verify_revision_signature(
2235
revision_id, gpg_strategy)
2010
2237
def item_keys_introduced_by(self, revision_ids, _files_pb=None):
2011
2238
self._ensure_real()
2712
class RemoteBranchStore(config.IniFileStore):
2713
"""Branch store which attempts to use HPSS calls to retrieve branch store.
2715
Note that this is specific to bzr-based formats.
2718
def __init__(self, branch):
2719
super(RemoteBranchStore, self).__init__()
2720
self.branch = branch
2722
self._real_store = None
2724
def lock_write(self, token=None):
2725
return self.branch.lock_write(token)
2728
return self.branch.unlock()
2732
# We need to be able to override the undecorated implementation
2733
self.save_without_locking()
2735
def save_without_locking(self):
2736
super(RemoteBranchStore, self).save()
2738
def external_url(self):
2739
return self.branch.user_url
2741
def _load_content(self):
2742
path = self.branch._remote_path()
2744
response, handler = self.branch._call_expecting_body(
2745
'Branch.get_config_file', path)
2746
except errors.UnknownSmartMethod:
2748
return self._real_store._load_content()
2749
if len(response) and response[0] != 'ok':
2750
raise errors.UnexpectedSmartServerResponse(response)
2751
return handler.read_body_bytes()
2753
def _save_content(self, content):
2754
path = self.branch._remote_path()
2756
response, handler = self.branch._call_with_body_bytes_expecting_body(
2757
'Branch.put_config_file', (path,
2758
self.branch._lock_token, self.branch._repo_lock_token),
2760
except errors.UnknownSmartMethod:
2762
return self._real_store._save_content(content)
2763
handler.cancel_read_body()
2764
if response != ('ok', ):
2765
raise errors.UnexpectedSmartServerResponse(response)
2767
def _ensure_real(self):
2768
self.branch._ensure_real()
2769
if self._real_store is None:
2770
self._real_store = config.BranchStore(self.branch)
2484
2773
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
2485
2774
"""Branch stored on a server accessed by HPSS RPC.
3029
3333
return self._lock_count >= 1
3031
3335
@needs_read_lock
3336
def revision_id_to_dotted_revno(self, revision_id):
3337
"""Given a revision id, return its dotted revno.
3339
:return: a tuple like (1,) or (400,1,3).
3342
response = self._call('Branch.revision_id_to_revno',
3343
self._remote_path(), revision_id)
3344
except errors.UnknownSmartMethod:
3346
return self._real_branch.revision_id_to_revno(revision_id)
3347
if response[0] == 'ok':
3348
return tuple([int(x) for x in response[1:]])
3350
raise errors.UnexpectedSmartServerResponse(response)
3032
3353
def revision_id_to_revno(self, revision_id):
3034
return self._real_branch.revision_id_to_revno(revision_id)
3354
"""Given a revision id on the branch mainline, return its revno.
3359
response = self._call('Branch.revision_id_to_revno',
3360
self._remote_path(), revision_id)
3361
except errors.UnknownSmartMethod:
3363
return self._real_branch.revision_id_to_revno(revision_id)
3364
if response[0] == 'ok':
3365
if len(response) == 2:
3366
return int(response[1])
3367
raise NoSuchRevision(self, revision_id)
3369
raise errors.UnexpectedSmartServerResponse(response)
3036
3371
@needs_write_lock
3037
3372
def set_last_revision_info(self, revno, revision_id):
3310
3649
'Missing key %r in context %r', key_err.args[0], context)
3313
if err.error_verb == 'NoSuchRevision':
3314
raise NoSuchRevision(find('branch'), err.error_args[0])
3315
elif err.error_verb == 'nosuchrevision':
3316
raise NoSuchRevision(find('repository'), err.error_args[0])
3317
elif err.error_verb == 'nobranch':
3318
if len(err.error_args) >= 1:
3319
extra = err.error_args[0]
3322
raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
3324
elif err.error_verb == 'norepository':
3325
raise errors.NoRepositoryPresent(find('bzrdir'))
3326
elif err.error_verb == 'UnlockableTransport':
3327
raise errors.UnlockableTransport(find('bzrdir').root_transport)
3328
elif err.error_verb == 'TokenMismatch':
3329
raise errors.TokenMismatch(find('token'), '(remote token)')
3330
elif err.error_verb == 'Diverged':
3331
raise errors.DivergedBranches(find('branch'), find('other_branch'))
3332
elif err.error_verb == 'NotStacked':
3333
raise errors.NotStacked(branch=find('branch'))
3334
elif err.error_verb == 'PermissionDenied':
3336
if len(err.error_args) >= 2:
3337
extra = err.error_args[1]
3340
raise errors.PermissionDenied(path, extra=extra)
3341
elif err.error_verb == 'ReadError':
3343
raise errors.ReadError(path)
3344
elif err.error_verb == 'NoSuchFile':
3346
raise errors.NoSuchFile(path)
3347
_translate_error_without_context(err)
3350
def _translate_error_without_context(err):
3351
"""Translate any ErrorFromSmartServer values that don't require context"""
3352
if err.error_verb == 'IncompatibleRepositories':
3353
raise errors.IncompatibleRepositories(err.error_args[0],
3354
err.error_args[1], err.error_args[2])
3355
elif err.error_verb == 'LockContention':
3356
raise errors.LockContention('(remote lock)')
3357
elif err.error_verb == 'LockFailed':
3358
raise errors.LockFailed(err.error_args[0], err.error_args[1])
3359
elif err.error_verb == 'TipChangeRejected':
3360
raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
3361
elif err.error_verb == 'UnstackableBranchFormat':
3362
raise errors.UnstackableBranchFormat(*err.error_args)
3363
elif err.error_verb == 'UnstackableRepositoryFormat':
3364
raise errors.UnstackableRepositoryFormat(*err.error_args)
3365
elif err.error_verb == 'FileExists':
3366
raise errors.FileExists(err.error_args[0])
3367
elif err.error_verb == 'DirectoryNotEmpty':
3368
raise errors.DirectoryNotEmpty(err.error_args[0])
3369
elif err.error_verb == 'ShortReadvError':
3370
args = err.error_args
3371
raise errors.ShortReadvError(
3372
args[0], int(args[1]), int(args[2]), int(args[3]))
3373
elif err.error_verb in ('UnicodeEncodeError', 'UnicodeDecodeError'):
3653
translator = error_translators.get(err.error_verb)
3657
raise translator(err, find, get_path)
3659
translator = no_context_error_translators.get(err.error_verb)
3661
raise errors.UnknownErrorFromSmartServer(err)
3663
raise translator(err)
3666
error_translators.register('NoSuchRevision',
3667
lambda err, find, get_path: NoSuchRevision(
3668
find('branch'), err.error_args[0]))
3669
error_translators.register('nosuchrevision',
3670
lambda err, find, get_path: NoSuchRevision(
3671
find('repository'), err.error_args[0]))
3673
def _translate_nobranch_error(err, find, get_path):
3674
if len(err.error_args) >= 1:
3675
extra = err.error_args[0]
3678
return errors.NotBranchError(path=find('bzrdir').root_transport.base,
3681
error_translators.register('nobranch', _translate_nobranch_error)
3682
error_translators.register('norepository',
3683
lambda err, find, get_path: errors.NoRepositoryPresent(
3685
error_translators.register('UnlockableTransport',
3686
lambda err, find, get_path: errors.UnlockableTransport(
3687
find('bzrdir').root_transport))
3688
error_translators.register('TokenMismatch',
3689
lambda err, find, get_path: errors.TokenMismatch(
3690
find('token'), '(remote token)'))
3691
error_translators.register('Diverged',
3692
lambda err, find, get_path: errors.DivergedBranches(
3693
find('branch'), find('other_branch')))
3694
error_translators.register('NotStacked',
3695
lambda err, find, get_path: errors.NotStacked(branch=find('branch')))
3697
def _translate_PermissionDenied(err, find, get_path):
3699
if len(err.error_args) >= 2:
3700
extra = err.error_args[1]
3703
return errors.PermissionDenied(path, extra=extra)
3705
error_translators.register('PermissionDenied', _translate_PermissionDenied)
3706
error_translators.register('ReadError',
3707
lambda err, find, get_path: errors.ReadError(get_path()))
3708
error_translators.register('NoSuchFile',
3709
lambda err, find, get_path: errors.NoSuchFile(get_path()))
3710
no_context_error_translators.register('IncompatibleRepositories',
3711
lambda err: errors.IncompatibleRepositories(
3712
err.error_args[0], err.error_args[1], err.error_args[2]))
3713
no_context_error_translators.register('LockContention',
3714
lambda err: errors.LockContention('(remote lock)'))
3715
no_context_error_translators.register('LockFailed',
3716
lambda err: errors.LockFailed(err.error_args[0], err.error_args[1]))
3717
no_context_error_translators.register('TipChangeRejected',
3718
lambda err: errors.TipChangeRejected(err.error_args[0].decode('utf8')))
3719
no_context_error_translators.register('UnstackableBranchFormat',
3720
lambda err: errors.UnstackableBranchFormat(*err.error_args))
3721
no_context_error_translators.register('UnstackableRepositoryFormat',
3722
lambda err: errors.UnstackableRepositoryFormat(*err.error_args))
3723
no_context_error_translators.register('FileExists',
3724
lambda err: errors.FileExists(err.error_args[0]))
3725
no_context_error_translators.register('DirectoryNotEmpty',
3726
lambda err: errors.DirectoryNotEmpty(err.error_args[0]))
3728
def _translate_short_readv_error(err):
3729
args = err.error_args
3730
return errors.ShortReadvError(args[0], int(args[1]), int(args[2]),
3733
no_context_error_translators.register('ShortReadvError',
3734
_translate_short_readv_error)
3736
def _translate_unicode_error(err):
3374
3737
encoding = str(err.error_args[0]) # encoding must always be a string
3375
3738
val = err.error_args[1]
3376
3739
start = int(err.error_args[2])
3384
3747
raise UnicodeDecodeError(encoding, val, start, end, reason)
3385
3748
elif err.error_verb == 'UnicodeEncodeError':
3386
3749
raise UnicodeEncodeError(encoding, val, start, end, reason)
3387
elif err.error_verb == 'ReadOnlyError':
3388
raise errors.TransportNotPossible('readonly transport')
3389
elif err.error_verb == 'MemoryError':
3390
raise errors.BzrError("remote server out of memory\n"
3391
"Retry non-remotely, or contact the server admin for details.")
3392
raise errors.UnknownErrorFromSmartServer(err)
3751
no_context_error_translators.register('UnicodeEncodeError',
3752
_translate_unicode_error)
3753
no_context_error_translators.register('UnicodeDecodeError',
3754
_translate_unicode_error)
3755
no_context_error_translators.register('ReadOnlyError',
3756
lambda err: errors.TransportNotPossible('readonly transport'))
3757
no_context_error_translators.register('MemoryError',
3758
lambda err: errors.BzrError("remote server out of memory\n"
3759
"Retry non-remotely, or contact the server admin for details."))
3761
no_context_error_translators.register('BzrCheckError',
3762
lambda err: errors.BzrCheckError(msg=err.error_args[0]))
3764
error_translators.register('UnsuspendableWriteGroup',
3765
lambda err, find, get_path: errors.UnsuspendableWriteGroup(
3766
repository=find('repository')))
3767
error_translators.register('UnresumableWriteGroup',
3768
lambda err, find, get_path: errors.UnresumableWriteGroup(
3769
repository=find('repository'), write_groups=err.error_args[0],
3770
reason=err.error_args[1]))