41
42
SmartProtocolError,
43
from bzrlib.i18n import gettext
44
44
from bzrlib.lockable_files import LockableFiles
45
45
from bzrlib.smart import client, vfs, repository as smart_repo
46
46
from bzrlib.smart.client import _SmartClient
49
49
from bzrlib.trace import mutter, note, warning
52
_DEFAULT_SEARCH_DEPTH = 100
55
52
class _RpcHelper(object):
56
53
"""Mixin class that helps with issuing RPCs."""
487
484
self._ensure_real()
488
485
self._real_bzrdir.destroy_repository()
490
def create_branch(self, name=None, repository=None,
491
append_revisions_only=None):
487
def create_branch(self, name=None, repository=None):
492
488
# as per meta1 formats - just delegate to the format object which may
493
489
# be parameterised.
494
490
real_branch = self._format.get_branch_format().initialize(self,
495
name=name, repository=repository,
496
append_revisions_only=append_revisions_only)
491
name=name, repository=repository)
497
492
if not isinstance(real_branch, RemoteBranch):
498
493
if not isinstance(repository, RemoteRepository):
499
494
raise AssertionError(
676
671
def _path_for_remote_call(self, client):
677
672
"""Return the path to be used for this bzrdir in a remote call."""
678
return urlutils.split_segment_parameters_raw(
679
client.remote_path_from_transport(self.root_transport))[0]
673
return client.remote_path_from_transport(self.root_transport)
681
675
def get_branch_transport(self, branch_format, name=None):
682
676
self._ensure_real()
742
736
self._supports_external_lookups = None
743
737
self._supports_tree_reference = None
744
738
self._supports_funky_characters = None
745
self._supports_nesting_repositories = None
746
739
self._rich_root_data = None
748
741
def __repr__(self):
785
778
return self._supports_funky_characters
788
def supports_nesting_repositories(self):
789
if self._supports_nesting_repositories is None:
791
self._supports_nesting_repositories = \
792
self._custom_format.supports_nesting_repositories
793
return self._supports_nesting_repositories
796
781
def supports_tree_reference(self):
797
782
if self._supports_tree_reference is None:
798
783
self._ensure_real()
1521
1506
# We need to accumulate additional repositories here, to pass them in
1522
1507
# on various RPC's.
1524
# Make the check before we lock: this raises an exception.
1525
self._check_fallback_repository(repository)
1526
1509
if self.is_locked():
1527
1510
# We will call fallback.unlock() when we transition to the unlocked
1528
1511
# state, so always add a lock here. If a caller passes us a locked
1529
1512
# repository, they are responsible for unlocking it later.
1530
1513
repository.lock_read()
1514
self._check_fallback_repository(repository)
1531
1515
self._fallback_repositories.append(repository)
1532
1516
# If self._real_repository was parameterised already (e.g. because a
1533
1517
# _real_branch had its get_stacked_on_url method called), then the
1677
1661
self._real_repository.create_bundle(target, base, fileobj, format)
1679
1663
@needs_read_lock
1680
@symbol_versioning.deprecated_method(
1681
symbol_versioning.deprecated_in((2, 4, 0)))
1682
1664
def get_ancestry(self, revision_id, topo_sorted=True):
1683
1665
self._ensure_real()
1684
1666
return self._real_repository.get_ancestry(revision_id, topo_sorted)
1698
1680
self._ensure_real()
1699
1681
return self._real_repository.iter_files_bytes(desired_files)
1701
def get_cached_parent_map(self, revision_ids):
1702
"""See bzrlib.CachingParentsProvider.get_cached_parent_map"""
1703
return self._unstacked_provider.get_cached_parent_map(revision_ids)
1705
1683
def get_parent_map(self, revision_ids):
1706
1684
"""See bzrlib.Graph.get_parent_map()."""
1707
1685
return self._make_parents_provider().get_parent_map(revision_ids)
1765
1743
if parents_map is None:
1766
1744
# Repository is not locked, so there's no cache.
1767
1745
parents_map = {}
1768
if _DEFAULT_SEARCH_DEPTH <= 0:
1769
(start_set, stop_keys,
1770
key_count) = graph.search_result_from_parent_map(
1771
parents_map, self._unstacked_provider.missing_keys)
1773
(start_set, stop_keys,
1774
key_count) = graph.limited_search_result_from_parent_map(
1775
parents_map, self._unstacked_provider.missing_keys,
1776
keys, depth=_DEFAULT_SEARCH_DEPTH)
1746
# start_set is all the keys in the cache
1747
start_set = set(parents_map)
1748
# result set is all the references to keys in the cache
1749
result_parents = set()
1750
for parents in parents_map.itervalues():
1751
result_parents.update(parents)
1752
stop_keys = result_parents.difference(start_set)
1753
# We don't need to send ghosts back to the server as a position to
1755
stop_keys.difference_update(self._unstacked_provider.missing_keys)
1756
key_count = len(parents_map)
1757
if (NULL_REVISION in result_parents
1758
and NULL_REVISION in self._unstacked_provider.missing_keys):
1759
# If we pruned NULL_REVISION from the stop_keys because it's also
1760
# in our cache of "missing" keys we need to increment our key count
1761
# by 1, because the reconsitituted SearchResult on the server will
1762
# still consider NULL_REVISION to be an included key.
1764
included_keys = start_set.intersection(result_parents)
1765
start_set.difference_update(included_keys)
1777
1766
recipe = ('manual', start_set, stop_keys, key_count)
1778
1767
body = self._serialise_search_recipe(recipe)
1779
1768
path = self.bzrdir._path_for_remote_call(self._client)
1883
1872
from bzrlib import osutils
1885
1874
# TODO: Maybe a progress bar while streaming the tarball?
1886
note(gettext("Copying repository content as tarball..."))
1875
note("Copying repository content as tarball...")
1887
1876
tar_file = self._get_tarball('bz2')
1888
1877
if tar_file is None:
1985
1974
def supports_rich_root(self):
1986
1975
return self._format.rich_root_data
1988
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1989
1977
def iter_reverse_revision_history(self, revision_id):
1990
1978
self._ensure_real()
1991
1979
return self._real_repository.iter_reverse_revision_history(revision_id)
2363
2351
return a_bzrdir.open_branch(name=name,
2364
2352
ignore_fallbacks=ignore_fallbacks)
2366
def _vfs_initialize(self, a_bzrdir, name, append_revisions_only):
2354
def _vfs_initialize(self, a_bzrdir, name):
2367
2355
# Initialisation when using a local bzrdir object, or a non-vfs init
2368
2356
# method is not available on the server.
2369
2357
# self._custom_format is always set - the start of initialize ensures
2371
2359
if isinstance(a_bzrdir, RemoteBzrDir):
2372
2360
a_bzrdir._ensure_real()
2373
2361
result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2374
name, append_revisions_only=append_revisions_only)
2376
2364
# We assume the bzrdir is parameterised; it may not be.
2377
result = self._custom_format.initialize(a_bzrdir, name,
2378
append_revisions_only=append_revisions_only)
2365
result = self._custom_format.initialize(a_bzrdir, name)
2379
2366
if (isinstance(a_bzrdir, RemoteBzrDir) and
2380
2367
not isinstance(result, RemoteBranch)):
2381
2368
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2385
def initialize(self, a_bzrdir, name=None, repository=None,
2386
append_revisions_only=None):
2372
def initialize(self, a_bzrdir, name=None, repository=None):
2387
2373
# 1) get the network name to use.
2388
2374
if self._custom_format:
2389
2375
network_name = self._custom_format.network_name()
2395
2381
network_name = reference_format.network_name()
2396
2382
# Being asked to create on a non RemoteBzrDir:
2397
2383
if not isinstance(a_bzrdir, RemoteBzrDir):
2398
return self._vfs_initialize(a_bzrdir, name=name,
2399
append_revisions_only=append_revisions_only)
2384
return self._vfs_initialize(a_bzrdir, name=name)
2400
2385
medium = a_bzrdir._client._medium
2401
2386
if medium._is_remote_before((1, 13)):
2402
return self._vfs_initialize(a_bzrdir, name=name,
2403
append_revisions_only=append_revisions_only)
2387
return self._vfs_initialize(a_bzrdir, name=name)
2404
2388
# Creating on a remote bzr dir.
2405
2389
# 2) try direct creation via RPC
2406
2390
path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2413
2397
except errors.UnknownSmartMethod:
2414
2398
# Fallback - use vfs methods
2415
2399
medium._remember_remote_is_before((1, 13))
2416
return self._vfs_initialize(a_bzrdir, name=name,
2417
append_revisions_only=append_revisions_only)
2400
return self._vfs_initialize(a_bzrdir, name=name)
2418
2401
if response[0] != 'ok':
2419
2402
raise errors.UnexpectedSmartServerResponse(response)
2420
2403
# Turn the response into a RemoteRepository object.
2441
2424
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2442
2425
remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2443
2426
format=format, setup_stacking=False, name=name)
2444
if append_revisions_only:
2445
remote_branch.set_append_revisions_only(append_revisions_only)
2446
2427
# XXX: We know this is a new branch, so it must have revno 0, revid
2447
2428
# NULL_REVISION. Creating the branch locked would make this be unable
2448
2429
# to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2643
2624
self.bzrdir, self._client)
2644
2625
return self._control_files
2646
def _get_checkout_format(self, lightweight=False):
2627
def _get_checkout_format(self):
2647
2628
self._ensure_real()
2649
format = RemoteBzrDirFormat()
2650
self.bzrdir._format._supply_sub_formats_to(format)
2651
format.workingtree_format = self._real_branch._get_checkout_format(
2652
lightweight=lightweight).workingtree_format
2655
return self._real_branch._get_checkout_format(lightweight=False)
2629
return self._real_branch._get_checkout_format()
2657
2631
def get_physical_lock_status(self):
2658
2632
"""See Branch.get_physical_lock_status()."""
3129
3103
configobj = self._get_configobj()
3131
3104
if section is None:
3132
3105
section_obj = configobj
3135
3108
section_obj = configobj[section]
3136
3109
except KeyError:
3138
if section_obj is None:
3141
value = section_obj.get(name, default)
3111
return section_obj.get(name, default)
3142
3112
except errors.UnknownSmartMethod:
3143
value = self._vfs_get_option(name, section, default)
3144
for hook in config.OldConfigHooks['get']:
3145
hook(self, name, value)
3113
return self._vfs_get_option(name, section, default)
3148
3115
def _response_to_configobj(self, response):
3149
3116
if len(response[0]) and response[0][0] != 'ok':
3150
3117
raise errors.UnexpectedSmartServerResponse(response)
3151
3118
lines = response[1].read_body_bytes().splitlines()
3152
conf = config.ConfigObj(lines, encoding='utf-8')
3153
for hook in config.OldConfigHooks['load']:
3119
return config.ConfigObj(lines, encoding='utf-8')
3158
3122
class RemoteBranchConfig(RemoteConfig):