14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
from __future__ import absolute_import
19
17
from bzrlib.lazy_import import lazy_import
20
18
lazy_import(globals(), """
23
19
from bzrlib import (
30
26
revision as _mod_revision,
39
37
from bzrlib.decorators import needs_read_lock, needs_write_lock
40
38
from bzrlib.repository import (
43
RepositoryFormatMetaDir,
45
from bzrlib.vf_repository import (
46
InterSameDataRepository,
47
MetaDirVersionedFileRepository,
48
MetaDirVersionedFileRepositoryFormat,
49
VersionedFileCommitBuilder,
50
VersionedFileRootCommitBuilder,
52
from bzrlib import symbol_versioning
41
MetaDirRepositoryFormat,
45
from bzrlib.trace import mutter, mutter_callsite
55
48
class _KnitParentsProvider(object):
122
115
def __init__(self, _format, a_bzrdir, control_files, _commit_builder_class,
124
super(KnitRepository, self).__init__(_format, a_bzrdir, control_files)
117
MetaDirRepository.__init__(self, _format, a_bzrdir, control_files)
125
118
self._commit_builder_class = _commit_builder_class
126
119
self._serializer = _serializer
127
120
self._reconcile_fixes_text_parents = True
183
176
result.get_parent_map([('A',)])
179
def fileid_involved_between_revs(self, from_revid, to_revid):
180
"""Find file_id(s) which are involved in the changes between revisions.
182
This determines the set of revisions which are involved, and then
183
finds all file ids affected by those revisions.
185
vf = self._get_revision_vf()
186
from_set = set(vf.get_ancestry(from_revid))
187
to_set = set(vf.get_ancestry(to_revid))
188
changed = to_set.difference(from_set)
189
return self._fileid_involved_by_set(changed)
191
def fileid_involved(self, last_revid=None):
192
"""Find all file_ids modified in the ancestry of last_revid.
194
:param last_revid: If None, last_revision() will be used.
197
changed = set(self.all_revision_ids())
199
changed = set(self.get_ancestry(last_revid))
202
return self._fileid_involved_by_set(changed)
187
205
def get_revision(self, revision_id):
188
206
"""Return the Revision object for a named revision"""
213
229
def _make_parents_provider(self):
214
230
return _KnitsParentsProvider(self.revisions)
217
class RepositoryFormatKnit(MetaDirVersionedFileRepositoryFormat):
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):
218
270
"""Bzr repository knit format (generalized).
220
272
This repository format has:
249
301
_fetch_order = 'topological'
250
302
_fetch_uses_deltas = True
251
303
fast_deltas = False
252
supports_funky_characters = True
253
# The revision.kndx could potentially claim a revision has a different
254
# parent to the revision text.
255
revision_graph_can_have_wrong_parents = True
257
305
def _get_inventories(self, repo_transport, repo, name='inventory'):
258
306
mapper = versionedfile.ConstantMapper(name)
405
451
return xml7.serializer_v7
407
453
def _get_matching_bzrdir(self):
408
return controldir.format_registry.make_bzrdir('dirstate-with-subtree')
454
return bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
410
456
def _ignore_setting_bzrdir(self, format):
413
459
_matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
416
def get_format_string(cls):
461
def get_format_string(self):
417
462
"""See RepositoryFormat.get_format_string()."""
418
463
return "Bazaar Knit Repository Format 3 (bzr 0.15)\n"
447
492
return xml6.serializer_v6
449
494
def _get_matching_bzrdir(self):
450
return controldir.format_registry.make_bzrdir('rich-root')
495
return bzrdir.format_registry.make_bzrdir('rich-root')
452
497
def _ignore_setting_bzrdir(self, format):
455
500
_matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
458
def get_format_string(cls):
502
def get_format_string(self):
459
503
"""See RepositoryFormat.get_format_string()."""
460
504
return 'Bazaar Knit Repository Format 4 (bzr 1.0)\n'
462
506
def get_format_description(self):
463
507
"""See RepositoryFormat.get_format_description()."""
464
508
return "Knit repository format 4"
467
class InterKnitRepo(InterSameDataRepository):
468
"""Optimised code paths between Knit based repositories."""
471
def _get_repo_format_to_test(self):
472
return RepositoryFormatKnit1()
475
def is_compatible(source, target):
476
"""Be compatible with known Knit formats.
478
We don't test for the stores being of specific types because that
479
could lead to confusing results, and there is no need to be
483
are_knits = (isinstance(source._format, RepositoryFormatKnit) and
484
isinstance(target._format, RepositoryFormatKnit))
485
except AttributeError:
487
return are_knits and InterRepository._same_model(source, target)
490
def search_missing_revision_ids(self,
491
find_ghosts=True, revision_ids=None, if_present_ids=None,
493
"""See InterRepository.search_missing_revision_ids()."""
494
source_ids_set = self._present_source_revisions_for(
495
revision_ids, if_present_ids)
496
# source_ids is the worst possible case we may need to pull.
497
# now we want to filter source_ids against what we actually
498
# have in target, but don't try to check for existence where we know
499
# we do not have a revision as that would be pointless.
500
target_ids = set(self.target.all_revision_ids())
501
possibly_present_revisions = target_ids.intersection(source_ids_set)
502
actually_present_revisions = set(
503
self.target._eliminate_revisions_not_present(possibly_present_revisions))
504
required_revisions = source_ids_set.difference(actually_present_revisions)
505
if revision_ids is not None:
506
# we used get_ancestry to determine source_ids then we are assured all
507
# revisions referenced are present as they are installed in topological order.
508
# and the tip revision was validated by get_ancestry.
509
result_set = required_revisions
511
# if we just grabbed the possibly available ids, then
512
# we only have an estimate of whats available and need to validate
513
# that against the revision records.
515
self.source._eliminate_revisions_not_present(required_revisions))
516
if limit is not None:
517
topo_ordered = self.source.get_graph().iter_topo_order(result_set)
518
result_set = set(itertools.islice(topo_ordered, limit))
519
return self.source.revision_ids_to_search_result(result_set)
522
InterRepository.register_optimiser(InterKnitRepo)