96
88
record_root_entry = True
97
89
# the default CommitBuilder does not manage trees whose root is versioned.
98
90
_versioned_root = False
91
# this commit builder supports the record_entry_contents interface
92
supports_record_entry_contents = True
100
94
def __init__(self, repository, parents, config, timestamp=None,
101
95
timezone=None, committer=None, revprops=None,
96
revision_id=None, lossy=False):
103
97
"""Initiate a CommitBuilder.
105
99
:param repository: Repository to commit to.
106
100
:param parents: Revision ids of the parents of the new revision.
107
:param config: Configuration to use.
108
101
:param timestamp: Optional timestamp recorded for commit.
109
102
:param timezone: Optional timezone for timestamp.
110
103
:param committer: Optional committer to set for commit.
111
104
:param revprops: Optional dictionary of revision properties.
112
105
: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
114
109
self._config = config
116
112
if committer is None:
117
113
self._committer = self._config.username()
176
172
self._validate_unicode_text(value,
177
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'
179
210
def commit(self, message):
180
211
"""Make the actual commit.
1563
1589
@needs_read_lock
1564
def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1590
def search_missing_revision_ids(self, other,
1591
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1592
find_ghosts=True, revision_ids=None, if_present_ids=None):
1565
1593
"""Return the revision ids that other has that this does not.
1567
1595
These are returned in topological order.
1569
1597
revision_id: only return revision ids included by revision_id.
1599
if symbol_versioning.deprecated_passed(revision_id):
1600
symbol_versioning.warn(
1601
'search_missing_revision_ids(revision_id=...) was '
1602
'deprecated in 2.4. Use revision_ids=[...] instead.',
1603
DeprecationWarning, stacklevel=3)
1604
if revision_ids is not None:
1605
raise AssertionError(
1606
'revision_ids is mutually exclusive with revision_id')
1607
if revision_id is not None:
1608
revision_ids = [revision_id]
1571
1609
return InterRepository.get(other, self).search_missing_revision_ids(
1572
revision_id, find_ghosts)
1610
find_ghosts=find_ghosts, revision_ids=revision_ids,
1611
if_present_ids=if_present_ids)
1575
1614
def open(base):
2018
2057
w = self.inventories
2019
2058
pb = ui.ui_factory.nested_progress_bar()
2021
return self._find_text_key_references_from_xml_inventory_lines(
2060
return self._serializer._find_text_key_references(
2022
2061
w.iter_lines_added_or_present_in_keys(revision_keys, pb=pb))
2026
def _find_text_key_references_from_xml_inventory_lines(self,
2028
"""Core routine for extracting references to texts from inventories.
2030
This performs the translation of xml lines to revision ids.
2032
:param line_iterator: An iterator of lines, origin_version_id
2033
:return: A dictionary mapping text keys ((fileid, revision_id) tuples)
2034
to whether they were referred to by the inventory of the
2035
revision_id that they contain. Note that if that revision_id was
2036
not part of the line_iterator's output then False will be given -
2037
even though it may actually refer to that key.
2039
if not self._serializer.support_altered_by_hack:
2040
raise AssertionError(
2041
"_find_text_key_references_from_xml_inventory_lines only "
2042
"supported for branches which store inventory as unnested xml"
2043
", not on %r" % self)
2046
# this code needs to read every new line in every inventory for the
2047
# inventories [revision_ids]. Seeing a line twice is ok. Seeing a line
2048
# not present in one of those inventories is unnecessary but not
2049
# harmful because we are filtering by the revision id marker in the
2050
# inventory lines : we only select file ids altered in one of those
2051
# revisions. We don't need to see all lines in the inventory because
2052
# only those added in an inventory in rev X can contain a revision=X
2054
unescape_revid_cache = {}
2055
unescape_fileid_cache = {}
2057
# jam 20061218 In a big fetch, this handles hundreds of thousands
2058
# of lines, so it has had a lot of inlining and optimizing done.
2059
# Sorry that it is a little bit messy.
2060
# Move several functions to be local variables, since this is a long
2062
search = self._file_ids_altered_regex.search
2063
unescape = _unescape_xml
2064
setdefault = result.setdefault
2065
for line, line_key in line_iterator:
2066
match = search(line)
2069
# One call to match.group() returning multiple items is quite a
2070
# bit faster than 2 calls to match.group() each returning 1
2071
file_id, revision_id = match.group('file_id', 'revision_id')
2073
# Inlining the cache lookups helps a lot when you make 170,000
2074
# lines and 350k ids, versus 8.4 unique ids.
2075
# Using a cache helps in 2 ways:
2076
# 1) Avoids unnecessary decoding calls
2077
# 2) Re-uses cached strings, which helps in future set and
2079
# (2) is enough that removing encoding entirely along with
2080
# the cache (so we are using plain strings) results in no
2081
# performance improvement.
2083
revision_id = unescape_revid_cache[revision_id]
2085
unescaped = unescape(revision_id)
2086
unescape_revid_cache[revision_id] = unescaped
2087
revision_id = unescaped
2089
# Note that unconditionally unescaping means that we deserialise
2090
# every fileid, which for general 'pull' is not great, but we don't
2091
# really want to have some many fulltexts that this matters anyway.
2094
file_id = unescape_fileid_cache[file_id]
2096
unescaped = unescape(file_id)
2097
unescape_fileid_cache[file_id] = unescaped
2100
key = (file_id, revision_id)
2101
setdefault(key, False)
2102
if revision_id == line_key[-1]:
2106
2065
def _inventory_xml_lines_for_keys(self, keys):
2107
2066
"""Get a line iterator of the sort needed for findind references.
2810
2771
except UnicodeDecodeError:
2811
2772
raise errors.NonAsciiRevisionId(method, self)
2813
def revision_graph_can_have_wrong_parents(self):
2814
"""Is it possible for this repository to have a revision graph with
2774
def _find_inconsistent_revision_parents(self, revisions_iterator=None):
2775
"""Find revisions with different parent lists in the revision object
2776
and in the index graph.
2817
If True, then this repository must also implement
2818
_find_inconsistent_revision_parents so that check and reconcile can
2819
check for inconsistencies before proceeding with other checks that may
2820
depend on the revision index being consistent.
2778
:param revisions_iterator: None, or an iterator of (revid,
2779
Revision-or-None). This iterator controls the revisions checked.
2780
:returns: an iterator yielding tuples of (revison-id, parents-in-index,
2781
parents-in-revision).
2822
raise NotImplementedError(self.revision_graph_can_have_wrong_parents)
2825
# remove these delegates a while after bzr 0.15
2826
def __make_delegated(name, from_module):
2827
def _deprecated_repository_forwarder():
2828
symbol_versioning.warn('%s moved to %s in bzr 0.15'
2829
% (name, from_module),
2833
return pyutils.get_named_object(from_module, name)
2834
except AttributeError:
2835
raise AttributeError('module %s has no name %s'
2836
% (sys.modules[from_module], name))
2837
globals()[name] = _deprecated_repository_forwarder
2840
'AllInOneRepository',
2841
'WeaveMetaDirRepository',
2842
'PreSplitOutRepositoryFormat',
2843
'RepositoryFormat4',
2844
'RepositoryFormat5',
2845
'RepositoryFormat6',
2846
'RepositoryFormat7',
2848
__make_delegated(_name, 'bzrlib.repofmt.weaverepo')
2852
'RepositoryFormatKnit',
2853
'RepositoryFormatKnit1',
2855
__make_delegated(_name, 'bzrlib.repofmt.knitrepo')
2783
if not self.is_locked():
2784
raise AssertionError()
2786
if revisions_iterator is None:
2787
revisions_iterator = self._iter_revisions(None)
2788
for revid, revision in revisions_iterator:
2789
if revision is None:
2791
parent_map = vf.get_parent_map([(revid,)])
2792
parents_according_to_index = tuple(parent[-1] for parent in
2793
parent_map[(revid,)])
2794
parents_according_to_revision = tuple(revision.parent_ids)
2795
if parents_according_to_index != parents_according_to_revision:
2796
yield (revid, parents_according_to_index,
2797
parents_according_to_revision)
2799
def _check_for_inconsistent_revision_parents(self):
2800
inconsistencies = list(self._find_inconsistent_revision_parents())
2802
raise errors.BzrCheckError(
2803
"Revision knit has inconsistent parents.")
2858
2806
def install_revision(repository, rev, revision_tree):
3264
3243
return self.get_format_string()
3267
# Pre-0.8 formats that don't have a disk format string (because they are
3268
# versioned by the matching control directory). We use the control directories
3269
# disk format string as a key for the network_name because they meet the
3270
# constraints (simple string, unique, immutable).
3271
network_format_registry.register_lazy(
3272
"Bazaar-NG branch, format 5\n",
3273
'bzrlib.repofmt.weaverepo',
3274
'RepositoryFormat5',
3276
network_format_registry.register_lazy(
3277
"Bazaar-NG branch, format 6\n",
3278
'bzrlib.repofmt.weaverepo',
3279
'RepositoryFormat6',
3282
3246
# formats which have no format string are not discoverable or independently
3283
3247
# creatable on disk, so are not registered in format_registry. They're
3284
# all in bzrlib.repofmt.weaverepo now. When an instance of one of these is
3248
# all in bzrlib.repofmt.knitreponow. When an instance of one of these is
3285
3249
# needed, it's constructed directly by the BzrDir. Non-native formats where
3286
3250
# the repository is not separately opened are similar.
3288
3252
format_registry.register_lazy(
3289
'Bazaar-NG Repository format 7',
3290
'bzrlib.repofmt.weaverepo',
3294
format_registry.register_lazy(
3295
3253
'Bazaar-NG Knit Repository Format 1',
3296
3254
'bzrlib.repofmt.knitrepo',
3297
3255
'RepositoryFormatKnit1',
3314
3272
# NOTE: These are experimental in 0.92. Stable in 1.0 and above
3315
3273
format_registry.register_lazy(
3316
3274
'Bazaar pack repository format 1 (needs bzr 0.92)\n',
3317
'bzrlib.repofmt.pack_repo',
3275
'bzrlib.repofmt.knitpack_repo',
3318
3276
'RepositoryFormatKnitPack1',
3320
3278
format_registry.register_lazy(
3321
3279
'Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n',
3322
'bzrlib.repofmt.pack_repo',
3280
'bzrlib.repofmt.knitpack_repo',
3323
3281
'RepositoryFormatKnitPack3',
3325
3283
format_registry.register_lazy(
3326
3284
'Bazaar pack repository format 1 with rich root (needs bzr 1.0)\n',
3327
'bzrlib.repofmt.pack_repo',
3285
'bzrlib.repofmt.knitpack_repo',
3328
3286
'RepositoryFormatKnitPack4',
3330
3288
format_registry.register_lazy(
3331
3289
'Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n',
3332
'bzrlib.repofmt.pack_repo',
3290
'bzrlib.repofmt.knitpack_repo',
3333
3291
'RepositoryFormatKnitPack5',
3335
3293
format_registry.register_lazy(
3336
3294
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6.1)\n',
3337
'bzrlib.repofmt.pack_repo',
3295
'bzrlib.repofmt.knitpack_repo',
3338
3296
'RepositoryFormatKnitPack5RichRoot',
3340
3298
format_registry.register_lazy(
3341
3299
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6)\n',
3342
'bzrlib.repofmt.pack_repo',
3300
'bzrlib.repofmt.knitpack_repo',
3343
3301
'RepositoryFormatKnitPack5RichRootBroken',
3345
3303
format_registry.register_lazy(
3346
3304
'Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n',
3347
'bzrlib.repofmt.pack_repo',
3305
'bzrlib.repofmt.knitpack_repo',
3348
3306
'RepositoryFormatKnitPack6',
3350
3308
format_registry.register_lazy(
3351
3309
'Bazaar RepositoryFormatKnitPack6RichRoot (bzr 1.9)\n',
3352
'bzrlib.repofmt.pack_repo',
3310
'bzrlib.repofmt.knitpack_repo',
3353
3311
'RepositoryFormatKnitPack6RichRoot',
3313
format_registry.register_lazy(
3314
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
3315
'bzrlib.repofmt.groupcompress_repo',
3316
'RepositoryFormat2a',
3356
3319
# Development formats.
3357
# Obsolete but kept pending a CHK based subtree format.
3320
# Check their docstrings to see if/when they are obsolete.
3358
3321
format_registry.register_lazy(
3359
3322
("Bazaar development format 2 with subtree support "
3360
3323
"(needs bzr.dev from before 1.8)\n"),
3361
'bzrlib.repofmt.pack_repo',
3324
'bzrlib.repofmt.knitpack_repo',
3362
3325
'RepositoryFormatPackDevelopment2Subtree',
3365
# 1.14->1.16 go below here
3366
format_registry.register_lazy(
3367
'Bazaar development format - group compression and chk inventory'
3368
' (needs bzr.dev from 1.14)\n',
3369
'bzrlib.repofmt.groupcompress_repo',
3370
'RepositoryFormatCHK1',
3373
format_registry.register_lazy(
3374
'Bazaar development format - chk repository with bencode revision '
3375
'serialization (needs bzr.dev from 1.16)\n',
3376
'bzrlib.repofmt.groupcompress_repo',
3377
'RepositoryFormatCHK2',
3379
format_registry.register_lazy(
3380
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
3381
'bzrlib.repofmt.groupcompress_repo',
3382
'RepositoryFormat2a',
3384
3327
format_registry.register_lazy(
3385
3328
'Bazaar development format 8\n',
3386
3329
'bzrlib.repofmt.groupcompress_repo',
3498
3444
return searcher.get_result()
3500
3446
@needs_read_lock
3501
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3447
def search_missing_revision_ids(self,
3448
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
3449
find_ghosts=True, revision_ids=None, if_present_ids=None):
3502
3450
"""Return the revision ids that source has that target does not.
3504
3452
:param revision_id: only return revision ids included by this
3454
:param revision_ids: return revision ids included by these
3455
revision_ids. NoSuchRevision will be raised if any of these
3456
revisions are not present.
3457
:param if_present_ids: like revision_ids, but will not cause
3458
NoSuchRevision if any of these are absent, instead they will simply
3459
not be in the result. This is useful for e.g. finding revisions
3460
to fetch for tags, which may reference absent revisions.
3506
3461
:param find_ghosts: If True find missing revisions in deep history
3507
3462
rather than just finding the surface difference.
3508
3463
:return: A bzrlib.graph.SearchResult.
3465
if symbol_versioning.deprecated_passed(revision_id):
3466
symbol_versioning.warn(
3467
'search_missing_revision_ids(revision_id=...) was '
3468
'deprecated in 2.4. Use revision_ids=[...] instead.',
3469
DeprecationWarning, stacklevel=2)
3470
if revision_ids is not None:
3471
raise AssertionError(
3472
'revision_ids is mutually exclusive with revision_id')
3473
if revision_id is not None:
3474
revision_ids = [revision_id]
3510
3476
# stop searching at found target revisions.
3511
if not find_ghosts and revision_id is not None:
3512
return self._walk_to_common_revisions([revision_id])
3477
if not find_ghosts and (revision_ids is not None or if_present_ids is
3479
return self._walk_to_common_revisions(revision_ids,
3480
if_present_ids=if_present_ids)
3513
3481
# generic, possibly worst case, slow code path.
3514
3482
target_ids = set(self.target.all_revision_ids())
3515
if revision_id is not None:
3516
source_ids = self.source.get_ancestry(revision_id)
3517
if source_ids[0] is not None:
3518
raise AssertionError()
3521
source_ids = self.source.all_revision_ids()
3483
source_ids = self._present_source_revisions_for(
3484
revision_ids, if_present_ids)
3522
3485
result_set = set(source_ids).difference(target_ids)
3523
3486
return self.source.revision_ids_to_search_result(result_set)
3488
def _present_source_revisions_for(self, revision_ids, if_present_ids=None):
3489
"""Returns set of all revisions in ancestry of revision_ids present in
3492
:param revision_ids: if None, all revisions in source are returned.
3493
:param if_present_ids: like revision_ids, but if any/all of these are
3494
absent no error is raised.
3496
if revision_ids is not None or if_present_ids is not None:
3497
# First, ensure all specified revisions exist. Callers expect
3498
# NoSuchRevision when they pass absent revision_ids here.
3499
if revision_ids is None:
3500
revision_ids = set()
3501
if if_present_ids is None:
3502
if_present_ids = set()
3503
revision_ids = set(revision_ids)
3504
if_present_ids = set(if_present_ids)
3505
all_wanted_ids = revision_ids.union(if_present_ids)
3506
graph = self.source.get_graph()
3507
present_revs = set(graph.get_parent_map(all_wanted_ids))
3508
missing = revision_ids.difference(present_revs)
3510
raise errors.NoSuchRevision(self.source, missing.pop())
3511
found_ids = all_wanted_ids.intersection(present_revs)
3512
source_ids = [rev_id for (rev_id, parents) in
3513
graph.iter_ancestry(found_ids)
3514
if rev_id != _mod_revision.NULL_REVISION
3515
and parents is not None]
3517
source_ids = self.source.all_revision_ids()
3518
return set(source_ids)
3526
3521
def _same_model(source, target):
3527
3522
"""True if source and target have the same data representation.
3568
3563
return InterRepository._same_model(source, target)
3571
class InterWeaveRepo(InterSameDataRepository):
3572
"""Optimised code paths between Weave based repositories.
3574
This should be in bzrlib/repofmt/weaverepo.py but we have not yet
3575
implemented lazy inter-object optimisation.
3579
def _get_repo_format_to_test(self):
3580
from bzrlib.repofmt import weaverepo
3581
return weaverepo.RepositoryFormat7()
3584
def is_compatible(source, target):
3585
"""Be compatible with known Weave formats.
3587
We don't test for the stores being of specific types because that
3588
could lead to confusing results, and there is no need to be
3591
from bzrlib.repofmt.weaverepo import (
3597
return (isinstance(source._format, (RepositoryFormat5,
3599
RepositoryFormat7)) and
3600
isinstance(target._format, (RepositoryFormat5,
3602
RepositoryFormat7)))
3603
except AttributeError:
3607
def copy_content(self, revision_id=None):
3608
"""See InterRepository.copy_content()."""
3609
# weave specific optimised path:
3611
self.target.set_make_working_trees(self.source.make_working_trees())
3612
except (errors.RepositoryUpgradeRequired, NotImplemented):
3614
# FIXME do not peek!
3615
if self.source._transport.listable():
3616
pb = ui.ui_factory.nested_progress_bar()
3618
self.target.texts.insert_record_stream(
3619
self.source.texts.get_record_stream(
3620
self.source.texts.keys(), 'topological', False))
3621
pb.update('Copying inventory', 0, 1)
3622
self.target.inventories.insert_record_stream(
3623
self.source.inventories.get_record_stream(
3624
self.source.inventories.keys(), 'topological', False))
3625
self.target.signatures.insert_record_stream(
3626
self.source.signatures.get_record_stream(
3627
self.source.signatures.keys(),
3629
self.target.revisions.insert_record_stream(
3630
self.source.revisions.get_record_stream(
3631
self.source.revisions.keys(),
3632
'topological', True))
3636
self.target.fetch(self.source, revision_id=revision_id)
3639
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3640
"""See InterRepository.missing_revision_ids()."""
3641
# we want all revisions to satisfy revision_id in source.
3642
# but we don't want to stat every file here and there.
3643
# we want then, all revisions other needs to satisfy revision_id
3644
# checked, but not those that we have locally.
3645
# so the first thing is to get a subset of the revisions to
3646
# satisfy revision_id in source, and then eliminate those that
3647
# we do already have.
3648
# this is slow on high latency connection to self, but as this
3649
# disk format scales terribly for push anyway due to rewriting
3650
# inventory.weave, this is considered acceptable.
3652
if revision_id is not None:
3653
source_ids = self.source.get_ancestry(revision_id)
3654
if source_ids[0] is not None:
3655
raise AssertionError()
3658
source_ids = self.source._all_possible_ids()
3659
source_ids_set = set(source_ids)
3660
# source_ids is the worst possible case we may need to pull.
3661
# now we want to filter source_ids against what we actually
3662
# have in target, but don't try to check for existence where we know
3663
# we do not have a revision as that would be pointless.
3664
target_ids = set(self.target._all_possible_ids())
3665
possibly_present_revisions = target_ids.intersection(source_ids_set)
3666
actually_present_revisions = set(
3667
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3668
required_revisions = source_ids_set.difference(actually_present_revisions)
3669
if revision_id is not None:
3670
# we used get_ancestry to determine source_ids then we are assured all
3671
# revisions referenced are present as they are installed in topological order.
3672
# and the tip revision was validated by get_ancestry.
3673
result_set = required_revisions
3675
# if we just grabbed the possibly available ids, then
3676
# we only have an estimate of whats available and need to validate
3677
# that against the revision records.
3679
self.source._eliminate_revisions_not_present(required_revisions))
3680
return self.source.revision_ids_to_search_result(result_set)
3683
class InterKnitRepo(InterSameDataRepository):
3684
"""Optimised code paths between Knit based repositories."""
3687
def _get_repo_format_to_test(self):
3688
from bzrlib.repofmt import knitrepo
3689
return knitrepo.RepositoryFormatKnit1()
3692
def is_compatible(source, target):
3693
"""Be compatible with known Knit formats.
3695
We don't test for the stores being of specific types because that
3696
could lead to confusing results, and there is no need to be
3699
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit
3701
are_knits = (isinstance(source._format, RepositoryFormatKnit) and
3702
isinstance(target._format, RepositoryFormatKnit))
3703
except AttributeError:
3705
return are_knits and InterRepository._same_model(source, target)
3708
def search_missing_revision_ids(self, revision_id=None, find_ghosts=True):
3709
"""See InterRepository.missing_revision_ids()."""
3710
if revision_id is not None:
3711
source_ids = self.source.get_ancestry(revision_id)
3712
if source_ids[0] is not None:
3713
raise AssertionError()
3716
source_ids = self.source.all_revision_ids()
3717
source_ids_set = set(source_ids)
3718
# source_ids is the worst possible case we may need to pull.
3719
# now we want to filter source_ids against what we actually
3720
# have in target, but don't try to check for existence where we know
3721
# we do not have a revision as that would be pointless.
3722
target_ids = set(self.target.all_revision_ids())
3723
possibly_present_revisions = target_ids.intersection(source_ids_set)
3724
actually_present_revisions = set(
3725
self.target._eliminate_revisions_not_present(possibly_present_revisions))
3726
required_revisions = source_ids_set.difference(actually_present_revisions)
3727
if revision_id is not None:
3728
# we used get_ancestry to determine source_ids then we are assured all
3729
# revisions referenced are present as they are installed in topological order.
3730
# and the tip revision was validated by get_ancestry.
3731
result_set = required_revisions
3733
# if we just grabbed the possibly available ids, then
3734
# we only have an estimate of whats available and need to validate
3735
# that against the revision records.
3737
self.source._eliminate_revisions_not_present(required_revisions))
3738
return self.source.revision_ids_to_search_result(result_set)
3741
3566
class InterDifferingSerializer(InterRepository):
4274
4059
is_resume = False
4276
4061
# locked_insert_stream performs a commit|suspend.
4277
return self._locked_insert_stream(stream, src_format,
4062
missing_keys = self.insert_stream_without_locking(stream,
4063
src_format, is_resume)
4065
# suspend the write group and tell the caller what we is
4066
# missing. We know we can suspend or else we would not have
4067
# entered this code path. (All repositories that can handle
4068
# missing keys can handle suspending a write group).
4069
write_group_tokens = self.target_repo.suspend_write_group()
4070
return write_group_tokens, missing_keys
4071
hint = self.target_repo.commit_write_group()
4072
to_serializer = self.target_repo._format._serializer
4073
src_serializer = src_format._serializer
4074
if (to_serializer != src_serializer and
4075
self.target_repo._format.pack_compresses):
4076
self.target_repo.pack(hint=hint)
4280
4079
self.target_repo.abort_write_group(suppress_errors=True)
4283
4082
self.target_repo.unlock()
4285
def _locked_insert_stream(self, stream, src_format, is_resume):
4084
def insert_stream_without_locking(self, stream, src_format,
4086
"""Insert a stream's content into the target repository.
4088
This assumes that you already have a locked repository and an active
4091
:param src_format: a bzr repository format.
4092
:param is_resume: Passed down to get_missing_parent_inventories to
4093
indicate if we should be checking for missing texts at the same
4096
:return: A set of keys that are missing.
4098
if not self.target_repo.is_write_locked():
4099
raise errors.ObjectNotLocked(self)
4100
if not self.target_repo.is_in_write_group():
4101
raise errors.BzrError('you must already be in a write group')
4286
4102
to_serializer = self.target_repo._format._serializer
4287
4103
src_serializer = src_format._serializer
4288
4104
new_pack = None