41
41
SmartProtocolError,
43
from bzrlib.i18n import gettext
43
44
from bzrlib.lockable_files import LockableFiles
44
45
from bzrlib.smart import client, vfs, repository as smart_repo
45
46
from bzrlib.smart.client import _SmartClient
48
49
from bzrlib.trace import mutter, note, warning
52
_DEFAULT_SEARCH_DEPTH = 100
51
55
class _RpcHelper(object):
52
56
"""Mixin class that helps with issuing RPCs."""
483
487
self._ensure_real()
484
488
self._real_bzrdir.destroy_repository()
486
def create_branch(self, name=None, repository=None):
490
def create_branch(self, name=None, repository=None,
491
append_revisions_only=None):
487
492
# as per meta1 formats - just delegate to the format object which may
488
493
# be parameterised.
489
494
real_branch = self._format.get_branch_format().initialize(self,
490
name=name, repository=repository)
495
name=name, repository=repository,
496
append_revisions_only=append_revisions_only)
491
497
if not isinstance(real_branch, RemoteBranch):
492
498
if not isinstance(repository, RemoteRepository):
493
499
raise AssertionError(
670
676
def _path_for_remote_call(self, client):
671
677
"""Return the path to be used for this bzrdir in a remote call."""
672
return client.remote_path_from_transport(self.root_transport)
678
return urlutils.split_segment_parameters_raw(
679
client.remote_path_from_transport(self.root_transport))[0]
674
681
def get_branch_transport(self, branch_format, name=None):
675
682
self._ensure_real()
735
742
self._supports_external_lookups = None
736
743
self._supports_tree_reference = None
737
744
self._supports_funky_characters = None
745
self._supports_nesting_repositories = None
738
746
self._rich_root_data = None
740
748
def __repr__(self):
777
785
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
780
796
def supports_tree_reference(self):
781
797
if self._supports_tree_reference is None:
782
798
self._ensure_real()
1080
1096
def find_text_key_references(self):
1081
1097
"""Find the text key references within the repository.
1083
:return: a dictionary mapping (file_id, revision_id) tuples to altered file-ids to an iterable of
1084
revision_ids. Each altered file-ids has the exact revision_ids that
1085
altered it listed explicitly.
1086
1099
:return: A dictionary mapping text keys ((fileid, revision_id) tuples)
1087
1100
to whether they were referred to by the inventory of the
1088
1101
revision_id that they contain. The inventory texts from all present
1136
1149
return RemoteStreamSource(self, to_format)
1138
1151
@needs_read_lock
1152
def get_file_graph(self):
1153
return graph.Graph(self.texts)
1139
1156
def has_revision(self, revision_id):
1140
1157
"""True if this repository has a copy of the revision."""
1141
1158
# Copy of bzrlib.repository.Repository.has_revision
1504
1521
# We need to accumulate additional repositories here, to pass them in
1505
1522
# on various RPC's.
1524
# Make the check before we lock: this raises an exception.
1525
self._check_fallback_repository(repository)
1507
1526
if self.is_locked():
1508
1527
# We will call fallback.unlock() when we transition to the unlocked
1509
1528
# state, so always add a lock here. If a caller passes us a locked
1510
1529
# repository, they are responsible for unlocking it later.
1511
1530
repository.lock_read()
1512
self._check_fallback_repository(repository)
1513
1531
self._fallback_repositories.append(repository)
1514
1532
# If self._real_repository was parameterised already (e.g. because a
1515
1533
# _real_branch had its get_stacked_on_url method called), then the
1604
1622
@needs_read_lock
1605
1623
def search_missing_revision_ids(self, other,
1606
1624
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1607
find_ghosts=True, revision_ids=None, if_present_ids=None):
1625
find_ghosts=True, revision_ids=None, if_present_ids=None,
1608
1627
"""Return the revision ids that other has that this does not.
1610
1629
These are returned in topological order.
1624
1643
inter_repo = _mod_repository.InterRepository.get(other, self)
1625
1644
return inter_repo.search_missing_revision_ids(
1626
1645
find_ghosts=find_ghosts, revision_ids=revision_ids,
1627
if_present_ids=if_present_ids)
1646
if_present_ids=if_present_ids, limit=limit)
1629
1648
def fetch(self, source, revision_id=None, find_ghosts=False,
1630
1649
fetch_spec=None):
1658
1677
self._real_repository.create_bundle(target, base, fileobj, format)
1660
1679
@needs_read_lock
1680
@symbol_versioning.deprecated_method(
1681
symbol_versioning.deprecated_in((2, 4, 0)))
1661
1682
def get_ancestry(self, revision_id, topo_sorted=True):
1662
1683
self._ensure_real()
1663
1684
return self._real_repository.get_ancestry(revision_id, topo_sorted)
1677
1698
self._ensure_real()
1678
1699
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)
1680
1705
def get_parent_map(self, revision_ids):
1681
1706
"""See bzrlib.Graph.get_parent_map()."""
1682
1707
return self._make_parents_provider().get_parent_map(revision_ids)
1740
1765
if parents_map is None:
1741
1766
# Repository is not locked, so there's no cache.
1742
1767
parents_map = {}
1743
# start_set is all the keys in the cache
1744
start_set = set(parents_map)
1745
# result set is all the references to keys in the cache
1746
result_parents = set()
1747
for parents in parents_map.itervalues():
1748
result_parents.update(parents)
1749
stop_keys = result_parents.difference(start_set)
1750
# We don't need to send ghosts back to the server as a position to
1752
stop_keys.difference_update(self._unstacked_provider.missing_keys)
1753
key_count = len(parents_map)
1754
if (NULL_REVISION in result_parents
1755
and NULL_REVISION in self._unstacked_provider.missing_keys):
1756
# If we pruned NULL_REVISION from the stop_keys because it's also
1757
# in our cache of "missing" keys we need to increment our key count
1758
# by 1, because the reconsitituted SearchResult on the server will
1759
# still consider NULL_REVISION to be an included key.
1761
included_keys = start_set.intersection(result_parents)
1762
start_set.difference_update(included_keys)
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)
1763
1777
recipe = ('manual', start_set, stop_keys, key_count)
1764
1778
body = self._serialise_search_recipe(recipe)
1765
1779
path = self.bzrdir._path_for_remote_call(self._client)
1869
1883
from bzrlib import osutils
1871
1885
# TODO: Maybe a progress bar while streaming the tarball?
1872
note("Copying repository content as tarball...")
1886
note(gettext("Copying repository content as tarball..."))
1873
1887
tar_file = self._get_tarball('bz2')
1874
1888
if tar_file is None:
1971
1985
def supports_rich_root(self):
1972
1986
return self._format.rich_root_data
1988
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1974
1989
def iter_reverse_revision_history(self, revision_id):
1975
1990
self._ensure_real()
1976
1991
return self._real_repository.iter_reverse_revision_history(revision_id)
2348
2363
return a_bzrdir.open_branch(name=name,
2349
2364
ignore_fallbacks=ignore_fallbacks)
2351
def _vfs_initialize(self, a_bzrdir, name):
2366
def _vfs_initialize(self, a_bzrdir, name, append_revisions_only):
2352
2367
# Initialisation when using a local bzrdir object, or a non-vfs init
2353
2368
# method is not available on the server.
2354
2369
# self._custom_format is always set - the start of initialize ensures
2356
2371
if isinstance(a_bzrdir, RemoteBzrDir):
2357
2372
a_bzrdir._ensure_real()
2358
2373
result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2374
name, append_revisions_only=append_revisions_only)
2361
2376
# We assume the bzrdir is parameterised; it may not be.
2362
result = self._custom_format.initialize(a_bzrdir, name)
2377
result = self._custom_format.initialize(a_bzrdir, name,
2378
append_revisions_only=append_revisions_only)
2363
2379
if (isinstance(a_bzrdir, RemoteBzrDir) and
2364
2380
not isinstance(result, RemoteBranch)):
2365
2381
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2369
def initialize(self, a_bzrdir, name=None, repository=None):
2385
def initialize(self, a_bzrdir, name=None, repository=None,
2386
append_revisions_only=None):
2370
2387
# 1) get the network name to use.
2371
2388
if self._custom_format:
2372
2389
network_name = self._custom_format.network_name()
2378
2395
network_name = reference_format.network_name()
2379
2396
# Being asked to create on a non RemoteBzrDir:
2380
2397
if not isinstance(a_bzrdir, RemoteBzrDir):
2381
return self._vfs_initialize(a_bzrdir, name=name)
2398
return self._vfs_initialize(a_bzrdir, name=name,
2399
append_revisions_only=append_revisions_only)
2382
2400
medium = a_bzrdir._client._medium
2383
2401
if medium._is_remote_before((1, 13)):
2384
return self._vfs_initialize(a_bzrdir, name=name)
2402
return self._vfs_initialize(a_bzrdir, name=name,
2403
append_revisions_only=append_revisions_only)
2385
2404
# Creating on a remote bzr dir.
2386
2405
# 2) try direct creation via RPC
2387
2406
path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2394
2413
except errors.UnknownSmartMethod:
2395
2414
# Fallback - use vfs methods
2396
2415
medium._remember_remote_is_before((1, 13))
2397
return self._vfs_initialize(a_bzrdir, name=name)
2416
return self._vfs_initialize(a_bzrdir, name=name,
2417
append_revisions_only=append_revisions_only)
2398
2418
if response[0] != 'ok':
2399
2419
raise errors.UnexpectedSmartServerResponse(response)
2400
2420
# Turn the response into a RemoteRepository object.
2421
2441
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2422
2442
remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2423
2443
format=format, setup_stacking=False, name=name)
2444
if append_revisions_only:
2445
remote_branch.set_append_revisions_only(append_revisions_only)
2424
2446
# XXX: We know this is a new branch, so it must have revno 0, revid
2425
2447
# NULL_REVISION. Creating the branch locked would make this be unable
2426
2448
# to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2621
2643
self.bzrdir, self._client)
2622
2644
return self._control_files
2624
def _get_checkout_format(self):
2646
def _get_checkout_format(self, lightweight=False):
2625
2647
self._ensure_real()
2626
return self._real_branch._get_checkout_format()
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)
2628
2657
def get_physical_lock_status(self):
2629
2658
"""See Branch.get_physical_lock_status()."""
2990
3019
_override_hook_target=self, **kwargs)
2992
3021
@needs_read_lock
2993
def push(self, target, overwrite=False, stop_revision=None):
3022
def push(self, target, overwrite=False, stop_revision=None, lossy=False):
2994
3023
self._ensure_real()
2995
3024
return self._real_branch.push(
2996
target, overwrite=overwrite, stop_revision=stop_revision,
3025
target, overwrite=overwrite, stop_revision=stop_revision, lossy=lossy,
2997
3026
_override_hook_source_branch=self)
2999
3028
def is_locked(self):
3100
3129
configobj = self._get_configobj()
3101
3131
if section is None:
3102
3132
section_obj = configobj
3105
3135
section_obj = configobj[section]
3106
3136
except KeyError:
3108
return section_obj.get(name, default)
3138
if section_obj is None:
3141
value = section_obj.get(name, default)
3109
3142
except errors.UnknownSmartMethod:
3110
return self._vfs_get_option(name, section, default)
3143
value = self._vfs_get_option(name, section, default)
3144
for hook in config.OldConfigHooks['get']:
3145
hook(self, name, value)
3112
3148
def _response_to_configobj(self, response):
3113
3149
if len(response[0]) and response[0][0] != 'ok':
3114
3150
raise errors.UnexpectedSmartServerResponse(response)
3115
3151
lines = response[1].read_body_bytes().splitlines()
3116
return config.ConfigObj(lines, encoding='utf-8')
3152
conf = config.ConfigObj(lines, encoding='utf-8')
3153
for hook in config.OldConfigHooks['load']:
3119
3158
class RemoteBranchConfig(RemoteConfig):