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
2806
except UnicodeDecodeError:
2774
2807
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.
2809
def revision_graph_can_have_wrong_parents(self):
2810
"""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).
2813
If True, then this repository must also implement
2814
_find_inconsistent_revision_parents so that check and reconcile can
2815
check for inconsistencies before proceeding with other checks that may
2816
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.")
2818
raise NotImplementedError(self.revision_graph_can_have_wrong_parents)
2821
# remove these delegates a while after bzr 0.15
2822
def __make_delegated(name, from_module):
2823
def _deprecated_repository_forwarder():
2824
symbol_versioning.warn('%s moved to %s in bzr 0.15'
2825
% (name, from_module),
2828
m = __import__(from_module, globals(), locals(), [name])
2830
return getattr(m, name)
2831
except AttributeError:
2832
raise AttributeError('module %s has no name %s'
2834
globals()[name] = _deprecated_repository_forwarder
2837
'AllInOneRepository',
2838
'WeaveMetaDirRepository',
2839
'PreSplitOutRepositoryFormat',
2840
'RepositoryFormat4',
2841
'RepositoryFormat5',
2842
'RepositoryFormat6',
2843
'RepositoryFormat7',
2845
__make_delegated(_name, 'bzrlib.repofmt.weaverepo')
2849
'RepositoryFormatKnit',
2850
'RepositoryFormatKnit1',
2852
__make_delegated(_name, 'bzrlib.repofmt.knitrepo')
2808
2855
def install_revision(repository, rev, revision_tree):
3245
3261
return self.get_format_string()
3264
# Pre-0.8 formats that don't have a disk format string (because they are
3265
# versioned by the matching control directory). We use the control directories
3266
# disk format string as a key for the network_name because they meet the
3267
# constraints (simple string, unique, immutable).
3268
network_format_registry.register_lazy(
3269
"Bazaar-NG branch, format 5\n",
3270
'bzrlib.repofmt.weaverepo',
3271
'RepositoryFormat5',
3273
network_format_registry.register_lazy(
3274
"Bazaar-NG branch, format 6\n",
3275
'bzrlib.repofmt.weaverepo',
3276
'RepositoryFormat6',
3248
3279
# formats which have no format string are not discoverable or independently
3249
3280
# 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
3281
# all in bzrlib.repofmt.weaverepo now. When an instance of one of these is
3251
3282
# needed, it's constructed directly by the BzrDir. Non-native formats where
3252
3283
# the repository is not separately opened are similar.
3254
3285
format_registry.register_lazy(
3286
'Bazaar-NG Repository format 7',
3287
'bzrlib.repofmt.weaverepo',
3291
format_registry.register_lazy(
3255
3292
'Bazaar-NG Knit Repository Format 1',
3256
3293
'bzrlib.repofmt.knitrepo',
3257
3294
'RepositoryFormatKnit1',
3274
3311
# NOTE: These are experimental in 0.92. Stable in 1.0 and above
3275
3312
format_registry.register_lazy(
3276
3313
'Bazaar pack repository format 1 (needs bzr 0.92)\n',
3277
'bzrlib.repofmt.knitpack_repo',
3314
'bzrlib.repofmt.pack_repo',
3278
3315
'RepositoryFormatKnitPack1',
3280
3317
format_registry.register_lazy(
3281
3318
'Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n',
3282
'bzrlib.repofmt.knitpack_repo',
3319
'bzrlib.repofmt.pack_repo',
3283
3320
'RepositoryFormatKnitPack3',
3285
3322
format_registry.register_lazy(
3286
3323
'Bazaar pack repository format 1 with rich root (needs bzr 1.0)\n',
3287
'bzrlib.repofmt.knitpack_repo',
3324
'bzrlib.repofmt.pack_repo',
3288
3325
'RepositoryFormatKnitPack4',
3290
3327
format_registry.register_lazy(
3291
3328
'Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n',
3292
'bzrlib.repofmt.knitpack_repo',
3329
'bzrlib.repofmt.pack_repo',
3293
3330
'RepositoryFormatKnitPack5',
3295
3332
format_registry.register_lazy(
3296
3333
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6.1)\n',
3297
'bzrlib.repofmt.knitpack_repo',
3334
'bzrlib.repofmt.pack_repo',
3298
3335
'RepositoryFormatKnitPack5RichRoot',
3300
3337
format_registry.register_lazy(
3301
3338
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6)\n',
3302
'bzrlib.repofmt.knitpack_repo',
3339
'bzrlib.repofmt.pack_repo',
3303
3340
'RepositoryFormatKnitPack5RichRootBroken',
3305
3342
format_registry.register_lazy(
3306
3343
'Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n',
3307
'bzrlib.repofmt.knitpack_repo',
3344
'bzrlib.repofmt.pack_repo',
3308
3345
'RepositoryFormatKnitPack6',
3310
3347
format_registry.register_lazy(
3311
3348
'Bazaar RepositoryFormatKnitPack6RichRoot (bzr 1.9)\n',
3312
'bzrlib.repofmt.knitpack_repo',
3349
'bzrlib.repofmt.pack_repo',
3313
3350
'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
3353
# Development formats.
3322
# Check their docstrings to see if/when they are obsolete.
3354
# Obsolete but kept pending a CHK based subtree format.
3323
3355
format_registry.register_lazy(
3324
3356
("Bazaar development format 2 with subtree support "
3325
3357
"(needs bzr.dev from before 1.8)\n"),
3326
'bzrlib.repofmt.knitpack_repo',
3358
'bzrlib.repofmt.pack_repo',
3327
3359
'RepositoryFormatPackDevelopment2Subtree',
3362
# 1.14->1.16 go below here
3363
format_registry.register_lazy(
3364
'Bazaar development format - group compression and chk inventory'
3365
' (needs bzr.dev from 1.14)\n',
3366
'bzrlib.repofmt.groupcompress_repo',
3367
'RepositoryFormatCHK1',
3370
format_registry.register_lazy(
3371
'Bazaar development format - chk repository with bencode revision '
3372
'serialization (needs bzr.dev from 1.16)\n',
3373
'bzrlib.repofmt.groupcompress_repo',
3374
'RepositoryFormatCHK2',
3376
format_registry.register_lazy(
3377
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
3378
'bzrlib.repofmt.groupcompress_repo',
3379
'RepositoryFormat2a',
3329
3381
format_registry.register_lazy(
3330
3382
'Bazaar development format 8\n',
3331
3383
'bzrlib.repofmt.groupcompress_repo',
3446
3495
return searcher.get_result()
3448
3497
@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):
3498
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3452
3499
"""Return the revision ids that source has that target does not.
3454
3501
: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
3503
:param find_ghosts: If True find missing revisions in deep history
3464
3504
rather than just finding the surface difference.
3465
3505
: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
3507
# 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)
3508
if not find_ghosts and revision_id is not None:
3509
return self._walk_to_common_revisions([revision_id])
3483
3510
# generic, possibly worst case, slow code path.
3484
3511
target_ids = set(self.target.all_revision_ids())
3485
source_ids = self._present_source_revisions_for(
3486
revision_ids, if_present_ids)
3512
if revision_id is not None:
3513
source_ids = self.source.get_ancestry(revision_id)
3514
if source_ids[0] is not None:
3515
raise AssertionError()
3518
source_ids = self.source.all_revision_ids()
3487
3519
result_set = set(source_ids).difference(target_ids)
3488
3520
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
3523
def _same_model(source, target):
3524
3524
"""True if source and target have the same data representation.
3565
3565
return InterRepository._same_model(source, target)
3568
class InterWeaveRepo(InterSameDataRepository):
3569
"""Optimised code paths between Weave based repositories.
3571
This should be in bzrlib/repofmt/weaverepo.py but we have not yet
3572
implemented lazy inter-object optimisation.
3576
def _get_repo_format_to_test(self):
3577
from bzrlib.repofmt import weaverepo
3578
return weaverepo.RepositoryFormat7()
3581
def is_compatible(source, target):
3582
"""Be compatible with known Weave formats.
3584
We don't test for the stores being of specific types because that
3585
could lead to confusing results, and there is no need to be
3588
from bzrlib.repofmt.weaverepo import (
3594
return (isinstance(source._format, (RepositoryFormat5,
3596
RepositoryFormat7)) and
3597
isinstance(target._format, (RepositoryFormat5,
3599
RepositoryFormat7)))
3600
except AttributeError:
3604
def copy_content(self, revision_id=None):
3605
"""See InterRepository.copy_content()."""
3606
# weave specific optimised path:
3608
self.target.set_make_working_trees(self.source.make_working_trees())
3609
except (errors.RepositoryUpgradeRequired, NotImplemented):
3611
# FIXME do not peek!
3612
if self.source._transport.listable():
3613
pb = ui.ui_factory.nested_progress_bar()
3615
self.target.texts.insert_record_stream(
3616
self.source.texts.get_record_stream(
3617
self.source.texts.keys(), 'topological', False))
3618
pb.update('Copying inventory', 0, 1)
3619
self.target.inventories.insert_record_stream(
3620
self.source.inventories.get_record_stream(
3621
self.source.inventories.keys(), 'topological', False))
3622
self.target.signatures.insert_record_stream(
3623
self.source.signatures.get_record_stream(
3624
self.source.signatures.keys(),
3626
self.target.revisions.insert_record_stream(
3627
self.source.revisions.get_record_stream(
3628
self.source.revisions.keys(),
3629
'topological', True))
3633
self.target.fetch(self.source, revision_id=revision_id)
3636
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3637
"""See InterRepository.missing_revision_ids()."""
3638
# we want all revisions to satisfy revision_id in source.
3639
# but we don't want to stat every file here and there.
3640
# we want then, all revisions other needs to satisfy revision_id
3641
# checked, but not those that we have locally.
3642
# so the first thing is to get a subset of the revisions to
3643
# satisfy revision_id in source, and then eliminate those that
3644
# we do already have.
3645
# this is slow on high latency connection to self, but as this
3646
# disk format scales terribly for push anyway due to rewriting
3647
# inventory.weave, this is considered acceptable.
3649
if revision_id is not None:
3650
source_ids = self.source.get_ancestry(revision_id)
3651
if source_ids[0] is not None:
3652
raise AssertionError()
3655
source_ids = self.source._all_possible_ids()
3656
source_ids_set = set(source_ids)
3657
# source_ids is the worst possible case we may need to pull.
3658
# now we want to filter source_ids against what we actually
3659
# have in target, but don't try to check for existence where we know
3660
# we do not have a revision as that would be pointless.
3661
target_ids = set(self.target._all_possible_ids())
3662
possibly_present_revisions = target_ids.intersection(source_ids_set)
3663
actually_present_revisions = set(
3664
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3665
required_revisions = source_ids_set.difference(actually_present_revisions)
3666
if revision_id is not None:
3667
# we used get_ancestry to determine source_ids then we are assured all
3668
# revisions referenced are present as they are installed in topological order.
3669
# and the tip revision was validated by get_ancestry.
3670
result_set = required_revisions
3672
# if we just grabbed the possibly available ids, then
3673
# we only have an estimate of whats available and need to validate
3674
# that against the revision records.
3676
self.source._eliminate_revisions_not_present(required_revisions))
3677
return self.source.revision_ids_to_search_result(result_set)
3680
class InterKnitRepo(InterSameDataRepository):
3681
"""Optimised code paths between Knit based repositories."""
3684
def _get_repo_format_to_test(self):
3685
from bzrlib.repofmt import knitrepo
3686
return knitrepo.RepositoryFormatKnit1()
3689
def is_compatible(source, target):
3690
"""Be compatible with known Knit formats.
3692
We don't test for the stores being of specific types because that
3693
could lead to confusing results, and there is no need to be
3696
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit
3698
are_knits = (isinstance(source._format, RepositoryFormatKnit) and
3699
isinstance(target._format, RepositoryFormatKnit))
3700
except AttributeError:
3702
return are_knits and InterRepository._same_model(source, target)
3705
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3706
"""See InterRepository.missing_revision_ids()."""
3707
if revision_id is not None:
3708
source_ids = self.source.get_ancestry(revision_id)
3709
if source_ids[0] is not None:
3710
raise AssertionError()
3713
source_ids = self.source.all_revision_ids()
3714
source_ids_set = set(source_ids)
3715
# source_ids is the worst possible case we may need to pull.
3716
# now we want to filter source_ids against what we actually
3717
# have in target, but don't try to check for existence where we know
3718
# we do not have a revision as that would be pointless.
3719
target_ids = set(self.target.all_revision_ids())
3720
possibly_present_revisions = target_ids.intersection(source_ids_set)
3721
actually_present_revisions = set(
3722
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3723
required_revisions = source_ids_set.difference(actually_present_revisions)
3724
if revision_id is not None:
3725
# we used get_ancestry to determine source_ids then we are assured all
3726
# revisions referenced are present as they are installed in topological order.
3727
# and the tip revision was validated by get_ancestry.
3728
result_set = required_revisions
3730
# if we just grabbed the possibly available ids, then
3731
# we only have an estimate of whats available and need to validate
3732
# that against the revision records.
3734
self.source._eliminate_revisions_not_present(required_revisions))
3735
return self.source.revision_ids_to_search_result(result_set)
3568
3738
class InterDifferingSerializer(InterRepository):
4061
4271
is_resume = False
4063
4273
# 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)
4274
return self._locked_insert_stream(stream, src_format,
4081
4277
self.target_repo.abort_write_group(suppress_errors=True)
4084
4280
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')
4282
def _locked_insert_stream(self, stream, src_format, is_resume):
4104
4283
to_serializer = self.target_repo._format._serializer
4105
4284
src_serializer = src_format._serializer
4106
4285
new_pack = None