88
94
record_root_entry = True
89
95
# the default CommitBuilder does not manage trees whose root is versioned.
90
96
_versioned_root = False
91
# this commit builder supports the record_entry_contents interface
92
supports_record_entry_contents = True
94
98
def __init__(self, repository, parents, config, timestamp=None,
95
99
timezone=None, committer=None, revprops=None,
96
revision_id=None, lossy=False):
97
101
"""Initiate a CommitBuilder.
99
103
:param repository: Repository to commit to.
100
104
:param parents: Revision ids of the parents of the new revision.
105
:param config: Configuration to use.
101
106
:param timestamp: Optional timestamp recorded for commit.
102
107
:param timezone: Optional timezone for timestamp.
103
108
:param committer: Optional committer to set for commit.
104
109
:param revprops: Optional dictionary of revision properties.
105
110
:param revision_id: Optional revision id.
106
:param lossy: Whether to discard data that can not be natively
107
represented, when pushing to a foreign VCS
109
112
self._config = config
112
114
if committer is None:
113
115
self._committer = self._config.username()
114
elif not isinstance(committer, unicode):
115
self._committer = committer.decode() # throw if non-ascii
117
117
self._committer = committer
172
172
self._validate_unicode_text(value,
173
173
'revision property (%s)' % (key,))
175
def _ensure_fallback_inventories(self):
176
"""Ensure that appropriate inventories are available.
178
This only applies to repositories that are stacked, and is about
179
enusring the stacking invariants. Namely, that for any revision that is
180
present, we either have all of the file content, or we have the parent
181
inventory and the delta file content.
183
if not self.repository._fallback_repositories:
185
if not self.repository._format.supports_chks:
186
raise errors.BzrError("Cannot commit directly to a stacked branch"
187
" in pre-2a formats. See "
188
"https://bugs.launchpad.net/bzr/+bug/375013 for details.")
189
# This is a stacked repo, we need to make sure we have the parent
190
# inventories for the parents.
191
parent_keys = [(p,) for p in self.parents]
192
parent_map = self.repository.inventories._index.get_parent_map(parent_keys)
193
missing_parent_keys = set([pk for pk in parent_keys
194
if pk not in parent_map])
195
fallback_repos = list(reversed(self.repository._fallback_repositories))
196
missing_keys = [('inventories', pk[0])
197
for pk in missing_parent_keys]
199
while missing_keys and fallback_repos:
200
fallback_repo = fallback_repos.pop()
201
source = fallback_repo._get_source(self.repository._format)
202
sink = self.repository._get_sink()
203
stream = source.get_stream_for_missing_keys(missing_keys)
204
missing_keys = sink.insert_stream_without_locking(stream,
205
self.repository._format)
207
raise errors.BzrError('Unable to fill in parent inventories for a'
210
175
def commit(self, message):
211
176
"""Make the actual commit.
1591
1559
@needs_read_lock
1592
def search_missing_revision_ids(self, other,
1593
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1594
find_ghosts=True, revision_ids=None, if_present_ids=None):
1560
def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1595
1561
"""Return the revision ids that other has that this does not.
1597
1563
These are returned in topological order.
1599
1565
revision_id: only return revision ids included by revision_id.
1601
if symbol_versioning.deprecated_passed(revision_id):
1602
symbol_versioning.warn(
1603
'search_missing_revision_ids(revision_id=...) was '
1604
'deprecated in 2.4. Use revision_ids=[...] instead.',
1605
DeprecationWarning, stacklevel=3)
1606
if revision_ids is not None:
1607
raise AssertionError(
1608
'revision_ids is mutually exclusive with revision_id')
1609
if revision_id is not None:
1610
revision_ids = [revision_id]
1611
1567
return InterRepository.get(other, self).search_missing_revision_ids(
1612
find_ghosts=find_ghosts, revision_ids=revision_ids,
1613
if_present_ids=if_present_ids)
1568
revision_id, find_ghosts)
1616
1571
def open(base):
2059
2014
w = self.inventories
2060
2015
pb = ui.ui_factory.nested_progress_bar()
2062
return self._serializer._find_text_key_references(
2017
return self._find_text_key_references_from_xml_inventory_lines(
2063
2018
w.iter_lines_added_or_present_in_keys(revision_keys, pb=pb))
2022
def _find_text_key_references_from_xml_inventory_lines(self,
2024
"""Core routine for extracting references to texts from inventories.
2026
This performs the translation of xml lines to revision ids.
2028
:param line_iterator: An iterator of lines, origin_version_id
2029
:return: A dictionary mapping text keys ((fileid, revision_id) tuples)
2030
to whether they were referred to by the inventory of the
2031
revision_id that they contain. Note that if that revision_id was
2032
not part of the line_iterator's output then False will be given -
2033
even though it may actually refer to that key.
2035
if not self._serializer.support_altered_by_hack:
2036
raise AssertionError(
2037
"_find_text_key_references_from_xml_inventory_lines only "
2038
"supported for branches which store inventory as unnested xml"
2039
", not on %r" % self)
2042
# this code needs to read every new line in every inventory for the
2043
# inventories [revision_ids]. Seeing a line twice is ok. Seeing a line
2044
# not present in one of those inventories is unnecessary but not
2045
# harmful because we are filtering by the revision id marker in the
2046
# inventory lines : we only select file ids altered in one of those
2047
# revisions. We don't need to see all lines in the inventory because
2048
# only those added in an inventory in rev X can contain a revision=X
2050
unescape_revid_cache = {}
2051
unescape_fileid_cache = {}
2053
# jam 20061218 In a big fetch, this handles hundreds of thousands
2054
# of lines, so it has had a lot of inlining and optimizing done.
2055
# Sorry that it is a little bit messy.
2056
# Move several functions to be local variables, since this is a long
2058
search = self._file_ids_altered_regex.search
2059
unescape = _unescape_xml
2060
setdefault = result.setdefault
2061
for line, line_key in line_iterator:
2062
match = search(line)
2065
# One call to match.group() returning multiple items is quite a
2066
# bit faster than 2 calls to match.group() each returning 1
2067
file_id, revision_id = match.group('file_id', 'revision_id')
2069
# Inlining the cache lookups helps a lot when you make 170,000
2070
# lines and 350k ids, versus 8.4 unique ids.
2071
# Using a cache helps in 2 ways:
2072
# 1) Avoids unnecessary decoding calls
2073
# 2) Re-uses cached strings, which helps in future set and
2075
# (2) is enough that removing encoding entirely along with
2076
# the cache (so we are using plain strings) results in no
2077
# performance improvement.
2079
revision_id = unescape_revid_cache[revision_id]
2081
unescaped = unescape(revision_id)
2082
unescape_revid_cache[revision_id] = unescaped
2083
revision_id = unescaped
2085
# Note that unconditionally unescaping means that we deserialise
2086
# every fileid, which for general 'pull' is not great, but we don't
2087
# really want to have some many fulltexts that this matters anyway.
2090
file_id = unescape_fileid_cache[file_id]
2092
unescaped = unescape(file_id)
2093
unescape_fileid_cache[file_id] = unescaped
2096
key = (file_id, revision_id)
2097
setdefault(key, False)
2098
if revision_id == line_key[-1]:
2067
2102
def _inventory_xml_lines_for_keys(self, keys):
2068
2103
"""Get a line iterator of the sort needed for findind references.
2773
2817
except UnicodeDecodeError:
2774
2818
raise errors.NonAsciiRevisionId(method, self)
2776
def _find_inconsistent_revision_parents(self, revisions_iterator=None):
2777
"""Find revisions with different parent lists in the revision object
2778
and in the index graph.
2820
def revision_graph_can_have_wrong_parents(self):
2821
"""Is it possible for this repository to have a revision graph with
2780
:param revisions_iterator: None, or an iterator of (revid,
2781
Revision-or-None). This iterator controls the revisions checked.
2782
:returns: an iterator yielding tuples of (revison-id, parents-in-index,
2783
parents-in-revision).
2824
If True, then this repository must also implement
2825
_find_inconsistent_revision_parents so that check and reconcile can
2826
check for inconsistencies before proceeding with other checks that may
2827
depend on the revision index being consistent.
2785
if not self.is_locked():
2786
raise AssertionError()
2788
if revisions_iterator is None:
2789
revisions_iterator = self._iter_revisions(None)
2790
for revid, revision in revisions_iterator:
2791
if revision is None:
2793
parent_map = vf.get_parent_map([(revid,)])
2794
parents_according_to_index = tuple(parent[-1] for parent in
2795
parent_map[(revid,)])
2796
parents_according_to_revision = tuple(revision.parent_ids)
2797
if parents_according_to_index != parents_according_to_revision:
2798
yield (revid, parents_according_to_index,
2799
parents_according_to_revision)
2801
def _check_for_inconsistent_revision_parents(self):
2802
inconsistencies = list(self._find_inconsistent_revision_parents())
2804
raise errors.BzrCheckError(
2805
"Revision knit has inconsistent parents.")
2829
raise NotImplementedError(self.revision_graph_can_have_wrong_parents)
2832
# remove these delegates a while after bzr 0.15
2833
def __make_delegated(name, from_module):
2834
def _deprecated_repository_forwarder():
2835
symbol_versioning.warn('%s moved to %s in bzr 0.15'
2836
% (name, from_module),
2839
m = __import__(from_module, globals(), locals(), [name])
2841
return getattr(m, name)
2842
except AttributeError:
2843
raise AttributeError('module %s has no name %s'
2845
globals()[name] = _deprecated_repository_forwarder
2848
'AllInOneRepository',
2849
'WeaveMetaDirRepository',
2850
'PreSplitOutRepositoryFormat',
2851
'RepositoryFormat4',
2852
'RepositoryFormat5',
2853
'RepositoryFormat6',
2854
'RepositoryFormat7',
2856
__make_delegated(_name, 'bzrlib.repofmt.weaverepo')
2860
'RepositoryFormatKnit',
2861
'RepositoryFormatKnit1',
2863
__make_delegated(_name, 'bzrlib.repofmt.knitrepo')
2808
2866
def install_revision(repository, rev, revision_tree):
3245
3272
return self.get_format_string()
3275
# Pre-0.8 formats that don't have a disk format string (because they are
3276
# versioned by the matching control directory). We use the control directories
3277
# disk format string as a key for the network_name because they meet the
3278
# constraints (simple string, unique, immutable).
3279
network_format_registry.register_lazy(
3280
"Bazaar-NG branch, format 5\n",
3281
'bzrlib.repofmt.weaverepo',
3282
'RepositoryFormat5',
3284
network_format_registry.register_lazy(
3285
"Bazaar-NG branch, format 6\n",
3286
'bzrlib.repofmt.weaverepo',
3287
'RepositoryFormat6',
3248
3290
# formats which have no format string are not discoverable or independently
3249
3291
# creatable on disk, so are not registered in format_registry. They're
3250
# all in bzrlib.repofmt.knitreponow. When an instance of one of these is
3292
# all in bzrlib.repofmt.weaverepo now. When an instance of one of these is
3251
3293
# needed, it's constructed directly by the BzrDir. Non-native formats where
3252
3294
# the repository is not separately opened are similar.
3254
3296
format_registry.register_lazy(
3297
'Bazaar-NG Repository format 7',
3298
'bzrlib.repofmt.weaverepo',
3302
format_registry.register_lazy(
3255
3303
'Bazaar-NG Knit Repository Format 1',
3256
3304
'bzrlib.repofmt.knitrepo',
3257
3305
'RepositoryFormatKnit1',
3274
3322
# NOTE: These are experimental in 0.92. Stable in 1.0 and above
3275
3323
format_registry.register_lazy(
3276
3324
'Bazaar pack repository format 1 (needs bzr 0.92)\n',
3277
'bzrlib.repofmt.knitpack_repo',
3325
'bzrlib.repofmt.pack_repo',
3278
3326
'RepositoryFormatKnitPack1',
3280
3328
format_registry.register_lazy(
3281
3329
'Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n',
3282
'bzrlib.repofmt.knitpack_repo',
3330
'bzrlib.repofmt.pack_repo',
3283
3331
'RepositoryFormatKnitPack3',
3285
3333
format_registry.register_lazy(
3286
3334
'Bazaar pack repository format 1 with rich root (needs bzr 1.0)\n',
3287
'bzrlib.repofmt.knitpack_repo',
3335
'bzrlib.repofmt.pack_repo',
3288
3336
'RepositoryFormatKnitPack4',
3290
3338
format_registry.register_lazy(
3291
3339
'Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n',
3292
'bzrlib.repofmt.knitpack_repo',
3340
'bzrlib.repofmt.pack_repo',
3293
3341
'RepositoryFormatKnitPack5',
3295
3343
format_registry.register_lazy(
3296
3344
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6.1)\n',
3297
'bzrlib.repofmt.knitpack_repo',
3345
'bzrlib.repofmt.pack_repo',
3298
3346
'RepositoryFormatKnitPack5RichRoot',
3300
3348
format_registry.register_lazy(
3301
3349
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6)\n',
3302
'bzrlib.repofmt.knitpack_repo',
3350
'bzrlib.repofmt.pack_repo',
3303
3351
'RepositoryFormatKnitPack5RichRootBroken',
3305
3353
format_registry.register_lazy(
3306
3354
'Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n',
3307
'bzrlib.repofmt.knitpack_repo',
3355
'bzrlib.repofmt.pack_repo',
3308
3356
'RepositoryFormatKnitPack6',
3310
3358
format_registry.register_lazy(
3311
3359
'Bazaar RepositoryFormatKnitPack6RichRoot (bzr 1.9)\n',
3312
'bzrlib.repofmt.knitpack_repo',
3360
'bzrlib.repofmt.pack_repo',
3313
3361
'RepositoryFormatKnitPack6RichRoot',
3315
format_registry.register_lazy(
3316
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
3317
'bzrlib.repofmt.groupcompress_repo',
3318
'RepositoryFormat2a',
3321
3364
# Development formats.
3322
# Check their docstrings to see if/when they are obsolete.
3365
# Obsolete but kept pending a CHK based subtree format.
3323
3366
format_registry.register_lazy(
3324
3367
("Bazaar development format 2 with subtree support "
3325
3368
"(needs bzr.dev from before 1.8)\n"),
3326
'bzrlib.repofmt.knitpack_repo',
3369
'bzrlib.repofmt.pack_repo',
3327
3370
'RepositoryFormatPackDevelopment2Subtree',
3329
format_registry.register_lazy(
3330
'Bazaar development format 8\n',
3331
'bzrlib.repofmt.groupcompress_repo',
3332
'RepositoryFormat2aSubtree',
3373
# 1.14->1.16 go below here
3374
format_registry.register_lazy(
3375
'Bazaar development format - group compression and chk inventory'
3376
' (needs bzr.dev from 1.14)\n',
3377
'bzrlib.repofmt.groupcompress_repo',
3378
'RepositoryFormatCHK1',
3381
format_registry.register_lazy(
3382
'Bazaar development format - chk repository with bencode revision '
3383
'serialization (needs bzr.dev from 1.16)\n',
3384
'bzrlib.repofmt.groupcompress_repo',
3385
'RepositoryFormatCHK2',
3387
format_registry.register_lazy(
3388
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
3389
'bzrlib.repofmt.groupcompress_repo',
3390
'RepositoryFormat2a',
3446
3501
return searcher.get_result()
3448
3503
@needs_read_lock
3449
def search_missing_revision_ids(self,
3450
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
3451
find_ghosts=True, revision_ids=None, if_present_ids=None):
3504
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3452
3505
"""Return the revision ids that source has that target does not.
3454
3507
:param revision_id: only return revision ids included by this
3456
:param revision_ids: return revision ids included by these
3457
revision_ids. NoSuchRevision will be raised if any of these
3458
revisions are not present.
3459
:param if_present_ids: like revision_ids, but will not cause
3460
NoSuchRevision if any of these are absent, instead they will simply
3461
not be in the result. This is useful for e.g. finding revisions
3462
to fetch for tags, which may reference absent revisions.
3463
3509
:param find_ghosts: If True find missing revisions in deep history
3464
3510
rather than just finding the surface difference.
3465
3511
:return: A bzrlib.graph.SearchResult.
3467
if symbol_versioning.deprecated_passed(revision_id):
3468
symbol_versioning.warn(
3469
'search_missing_revision_ids(revision_id=...) was '
3470
'deprecated in 2.4. Use revision_ids=[...] instead.',
3471
DeprecationWarning, stacklevel=2)
3472
if revision_ids is not None:
3473
raise AssertionError(
3474
'revision_ids is mutually exclusive with revision_id')
3475
if revision_id is not None:
3476
revision_ids = [revision_id]
3478
3513
# stop searching at found target revisions.
3479
if not find_ghosts and (revision_ids is not None or if_present_ids is
3481
return self._walk_to_common_revisions(revision_ids,
3482
if_present_ids=if_present_ids)
3514
if not find_ghosts and revision_id is not None:
3515
return self._walk_to_common_revisions([revision_id])
3483
3516
# generic, possibly worst case, slow code path.
3484
3517
target_ids = set(self.target.all_revision_ids())
3485
source_ids = self._present_source_revisions_for(
3486
revision_ids, if_present_ids)
3518
if revision_id is not None:
3519
source_ids = self.source.get_ancestry(revision_id)
3520
if source_ids[0] is not None:
3521
raise AssertionError()
3524
source_ids = self.source.all_revision_ids()
3487
3525
result_set = set(source_ids).difference(target_ids)
3488
3526
return self.source.revision_ids_to_search_result(result_set)
3490
def _present_source_revisions_for(self, revision_ids, if_present_ids=None):
3491
"""Returns set of all revisions in ancestry of revision_ids present in
3494
:param revision_ids: if None, all revisions in source are returned.
3495
:param if_present_ids: like revision_ids, but if any/all of these are
3496
absent no error is raised.
3498
if revision_ids is not None or if_present_ids is not None:
3499
# First, ensure all specified revisions exist. Callers expect
3500
# NoSuchRevision when they pass absent revision_ids here.
3501
if revision_ids is None:
3502
revision_ids = set()
3503
if if_present_ids is None:
3504
if_present_ids = set()
3505
revision_ids = set(revision_ids)
3506
if_present_ids = set(if_present_ids)
3507
all_wanted_ids = revision_ids.union(if_present_ids)
3508
graph = self.source.get_graph()
3509
present_revs = set(graph.get_parent_map(all_wanted_ids))
3510
missing = revision_ids.difference(present_revs)
3512
raise errors.NoSuchRevision(self.source, missing.pop())
3513
found_ids = all_wanted_ids.intersection(present_revs)
3514
source_ids = [rev_id for (rev_id, parents) in
3515
graph.iter_ancestry(found_ids)
3516
if rev_id != _mod_revision.NULL_REVISION
3517
and parents is not None]
3519
source_ids = self.source.all_revision_ids()
3520
return set(source_ids)
3523
3529
def _same_model(source, target):
3524
3530
"""True if source and target have the same data representation.
3565
3571
return InterRepository._same_model(source, target)
3574
class InterWeaveRepo(InterSameDataRepository):
3575
"""Optimised code paths between Weave based repositories.
3577
This should be in bzrlib/repofmt/weaverepo.py but we have not yet
3578
implemented lazy inter-object optimisation.
3582
def _get_repo_format_to_test(self):
3583
from bzrlib.repofmt import weaverepo
3584
return weaverepo.RepositoryFormat7()
3587
def is_compatible(source, target):
3588
"""Be compatible with known Weave formats.
3590
We don't test for the stores being of specific types because that
3591
could lead to confusing results, and there is no need to be
3594
from bzrlib.repofmt.weaverepo import (
3600
return (isinstance(source._format, (RepositoryFormat5,
3602
RepositoryFormat7)) and
3603
isinstance(target._format, (RepositoryFormat5,
3605
RepositoryFormat7)))
3606
except AttributeError:
3610
def copy_content(self, revision_id=None):
3611
"""See InterRepository.copy_content()."""
3612
# weave specific optimised path:
3614
self.target.set_make_working_trees(self.source.make_working_trees())
3615
except (errors.RepositoryUpgradeRequired, NotImplemented):
3617
# FIXME do not peek!
3618
if self.source._transport.listable():
3619
pb = ui.ui_factory.nested_progress_bar()
3621
self.target.texts.insert_record_stream(
3622
self.source.texts.get_record_stream(
3623
self.source.texts.keys(), 'topological', False))
3624
pb.update('Copying inventory', 0, 1)
3625
self.target.inventories.insert_record_stream(
3626
self.source.inventories.get_record_stream(
3627
self.source.inventories.keys(), 'topological', False))
3628
self.target.signatures.insert_record_stream(
3629
self.source.signatures.get_record_stream(
3630
self.source.signatures.keys(),
3632
self.target.revisions.insert_record_stream(
3633
self.source.revisions.get_record_stream(
3634
self.source.revisions.keys(),
3635
'topological', True))
3639
self.target.fetch(self.source, revision_id=revision_id)
3642
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3643
"""See InterRepository.missing_revision_ids()."""
3644
# we want all revisions to satisfy revision_id in source.
3645
# but we don't want to stat every file here and there.
3646
# we want then, all revisions other needs to satisfy revision_id
3647
# checked, but not those that we have locally.
3648
# so the first thing is to get a subset of the revisions to
3649
# satisfy revision_id in source, and then eliminate those that
3650
# we do already have.
3651
# this is slow on high latency connection to self, but as this
3652
# disk format scales terribly for push anyway due to rewriting
3653
# inventory.weave, this is considered acceptable.
3655
if revision_id is not None:
3656
source_ids = self.source.get_ancestry(revision_id)
3657
if source_ids[0] is not None:
3658
raise AssertionError()
3661
source_ids = self.source._all_possible_ids()
3662
source_ids_set = set(source_ids)
3663
# source_ids is the worst possible case we may need to pull.
3664
# now we want to filter source_ids against what we actually
3665
# have in target, but don't try to check for existence where we know
3666
# we do not have a revision as that would be pointless.
3667
target_ids = set(self.target._all_possible_ids())
3668
possibly_present_revisions = target_ids.intersection(source_ids_set)
3669
actually_present_revisions = set(
3670
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3671
required_revisions = source_ids_set.difference(actually_present_revisions)
3672
if revision_id is not None:
3673
# we used get_ancestry to determine source_ids then we are assured all
3674
# revisions referenced are present as they are installed in topological order.
3675
# and the tip revision was validated by get_ancestry.
3676
result_set = required_revisions
3678
# if we just grabbed the possibly available ids, then
3679
# we only have an estimate of whats available and need to validate
3680
# that against the revision records.
3682
self.source._eliminate_revisions_not_present(required_revisions))
3683
return self.source.revision_ids_to_search_result(result_set)
3686
class InterKnitRepo(InterSameDataRepository):
3687
"""Optimised code paths between Knit based repositories."""
3690
def _get_repo_format_to_test(self):
3691
from bzrlib.repofmt import knitrepo
3692
return knitrepo.RepositoryFormatKnit1()
3695
def is_compatible(source, target):
3696
"""Be compatible with known Knit formats.
3698
We don't test for the stores being of specific types because that
3699
could lead to confusing results, and there is no need to be
3702
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit
3704
are_knits = (isinstance(source._format, RepositoryFormatKnit) and
3705
isinstance(target._format, RepositoryFormatKnit))
3706
except AttributeError:
3708
return are_knits and InterRepository._same_model(source, target)
3711
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3712
"""See InterRepository.missing_revision_ids()."""
3713
if revision_id is not None:
3714
source_ids = self.source.get_ancestry(revision_id)
3715
if source_ids[0] is not None:
3716
raise AssertionError()
3719
source_ids = self.source.all_revision_ids()
3720
source_ids_set = set(source_ids)
3721
# source_ids is the worst possible case we may need to pull.
3722
# now we want to filter source_ids against what we actually
3723
# have in target, but don't try to check for existence where we know
3724
# we do not have a revision as that would be pointless.
3725
target_ids = set(self.target.all_revision_ids())
3726
possibly_present_revisions = target_ids.intersection(source_ids_set)
3727
actually_present_revisions = set(
3728
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3729
required_revisions = source_ids_set.difference(actually_present_revisions)
3730
if revision_id is not None:
3731
# we used get_ancestry to determine source_ids then we are assured all
3732
# revisions referenced are present as they are installed in topological order.
3733
# and the tip revision was validated by get_ancestry.
3734
result_set = required_revisions
3736
# if we just grabbed the possibly available ids, then
3737
# we only have an estimate of whats available and need to validate
3738
# that against the revision records.
3740
self.source._eliminate_revisions_not_present(required_revisions))
3741
return self.source.revision_ids_to_search_result(result_set)
3568
3744
class InterDifferingSerializer(InterRepository):
4061
4284
is_resume = False
4063
4286
# locked_insert_stream performs a commit|suspend.
4064
missing_keys = self.insert_stream_without_locking(stream,
4065
src_format, is_resume)
4067
# suspend the write group and tell the caller what we is
4068
# missing. We know we can suspend or else we would not have
4069
# entered this code path. (All repositories that can handle
4070
# missing keys can handle suspending a write group).
4071
write_group_tokens = self.target_repo.suspend_write_group()
4072
return write_group_tokens, missing_keys
4073
hint = self.target_repo.commit_write_group()
4074
to_serializer = self.target_repo._format._serializer
4075
src_serializer = src_format._serializer
4076
if (to_serializer != src_serializer and
4077
self.target_repo._format.pack_compresses):
4078
self.target_repo.pack(hint=hint)
4287
return self._locked_insert_stream(stream, src_format,
4081
4290
self.target_repo.abort_write_group(suppress_errors=True)
4084
4293
self.target_repo.unlock()
4086
def insert_stream_without_locking(self, stream, src_format,
4088
"""Insert a stream's content into the target repository.
4090
This assumes that you already have a locked repository and an active
4093
:param src_format: a bzr repository format.
4094
:param is_resume: Passed down to get_missing_parent_inventories to
4095
indicate if we should be checking for missing texts at the same
4098
:return: A set of keys that are missing.
4100
if not self.target_repo.is_write_locked():
4101
raise errors.ObjectNotLocked(self)
4102
if not self.target_repo.is_in_write_group():
4103
raise errors.BzrError('you must already be in a write group')
4295
def _locked_insert_stream(self, stream, src_format, is_resume):
4104
4296
to_serializer = self.target_repo._format._serializer
4105
4297
src_serializer = src_format._serializer
4106
4298
new_pack = None