38
37
from bzrlib.decorators import needs_read_lock, needs_write_lock
39
38
from bzrlib.repository import (
42
MetaDirRepositoryFormat,
43
from bzrlib.vf_repository import (
44
InterSameDataRepository,
45
MetaDirVersionedFileRepository,
46
MetaDirVersionedFileRepositoryFormat,
47
VersionedFileCommitBuilder,
48
VersionedFileRootCommitBuilder,
50
from bzrlib import symbol_versioning
48
53
class _KnitParentsProvider(object):
115
120
def __init__(self, _format, a_bzrdir, control_files, _commit_builder_class,
117
MetaDirRepository.__init__(self, _format, a_bzrdir, control_files)
122
super(KnitRepository, self).__init__(_format, a_bzrdir, control_files)
118
123
self._commit_builder_class = _commit_builder_class
119
124
self._serializer = _serializer
120
125
self._reconcile_fixes_text_parents = True
229
236
def _make_parents_provider(self):
230
237
return _KnitsParentsProvider(self.revisions)
232
def _find_inconsistent_revision_parents(self, revisions_iterator=None):
233
"""Find revisions with different parent lists in the revision object
234
and in the index graph.
236
:param revisions_iterator: None, or an iterator of (revid,
237
Revision-or-None). This iterator controls the revisions checked.
238
:returns: an iterator yielding tuples of (revison-id, parents-in-index,
239
parents-in-revision).
241
if not self.is_locked():
242
raise AssertionError()
244
if revisions_iterator is None:
245
revisions_iterator = self._iter_revisions(None)
246
for revid, revision in revisions_iterator:
249
parent_map = vf.get_parent_map([(revid,)])
250
parents_according_to_index = tuple(parent[-1] for parent in
251
parent_map[(revid,)])
252
parents_according_to_revision = tuple(revision.parent_ids)
253
if parents_according_to_index != parents_according_to_revision:
254
yield (revid, parents_according_to_index,
255
parents_according_to_revision)
257
def _check_for_inconsistent_revision_parents(self):
258
inconsistencies = list(self._find_inconsistent_revision_parents())
260
raise errors.BzrCheckError(
261
"Revision knit has inconsistent parents.")
263
def revision_graph_can_have_wrong_parents(self):
264
# The revision.kndx could potentially claim a revision has a different
265
# parent to the revision text.
269
class RepositoryFormatKnit(MetaDirRepositoryFormat):
240
class RepositoryFormatKnit(MetaDirVersionedFileRepositoryFormat):
270
241
"""Bzr repository knit format (generalized).
272
243
This repository format has:
301
272
_fetch_order = 'topological'
302
273
_fetch_uses_deltas = True
303
274
fast_deltas = False
275
supports_funky_characters = True
276
# The revision.kndx could potentially claim a revision has a different
277
# parent to the revision text.
278
revision_graph_can_have_wrong_parents = True
305
280
def _get_inventories(self, repo_transport, repo, name='inventory'):
306
281
mapper = versionedfile.ConstantMapper(name)
507
482
def get_format_description(self):
508
483
"""See RepositoryFormat.get_format_description()."""
509
484
return "Knit repository format 4"
487
class InterKnitRepo(InterSameDataRepository):
488
"""Optimised code paths between Knit based repositories."""
491
def _get_repo_format_to_test(self):
492
return RepositoryFormatKnit1()
495
def is_compatible(source, target):
496
"""Be compatible with known Knit formats.
498
We don't test for the stores being of specific types because that
499
could lead to confusing results, and there is no need to be
503
are_knits = (isinstance(source._format, RepositoryFormatKnit) and
504
isinstance(target._format, RepositoryFormatKnit))
505
except AttributeError:
507
return are_knits and InterRepository._same_model(source, target)
510
def search_missing_revision_ids(self,
511
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
512
find_ghosts=True, revision_ids=None, if_present_ids=None,
514
"""See InterRepository.search_missing_revision_ids()."""
515
if symbol_versioning.deprecated_passed(revision_id):
516
symbol_versioning.warn(
517
'search_missing_revision_ids(revision_id=...) was '
518
'deprecated in 2.4. Use revision_ids=[...] instead.',
519
DeprecationWarning, stacklevel=2)
520
if revision_ids is not None:
521
raise AssertionError(
522
'revision_ids is mutually exclusive with revision_id')
523
if revision_id is not None:
524
revision_ids = [revision_id]
526
source_ids_set = self._present_source_revisions_for(
527
revision_ids, if_present_ids)
528
# source_ids is the worst possible case we may need to pull.
529
# now we want to filter source_ids against what we actually
530
# have in target, but don't try to check for existence where we know
531
# we do not have a revision as that would be pointless.
532
target_ids = set(self.target.all_revision_ids())
533
possibly_present_revisions = target_ids.intersection(source_ids_set)
534
actually_present_revisions = set(
535
self.target._eliminate_revisions_not_present(possibly_present_revisions))
536
required_revisions = source_ids_set.difference(actually_present_revisions)
537
if revision_ids is not None:
538
# we used get_ancestry to determine source_ids then we are assured all
539
# revisions referenced are present as they are installed in topological order.
540
# and the tip revision was validated by get_ancestry.
541
result_set = required_revisions
543
# if we just grabbed the possibly available ids, then
544
# we only have an estimate of whats available and need to validate
545
# that against the revision records.
547
self.source._eliminate_revisions_not_present(required_revisions))
548
if limit is not None:
549
topo_ordered = self.source.get_graph().iter_topo_order(result_set)
550
result_set = set(itertools.islice(topo_ordered, limit))
551
return self.source.revision_ids_to_search_result(result_set)
554
InterRepository.register_optimiser(InterKnitRepo)