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