17
17
"""Reconcilers are able to fix some potential data errors in a branch."""
20
__all__ = ['reconcile', 'Reconciler', 'RepoReconciler', 'KnitReconciler']
29
from bzrlib import errors
28
30
from bzrlib import ui
29
from bzrlib.trace import mutter
30
from bzrlib.tsort import TopoSorter
31
from bzrlib.trace import mutter, note
32
from bzrlib.tsort import TopoSorter, topo_sort
33
35
def reconcile(dir, other=None):
76
78
repo_reconciler = self.repo.reconcile(thorough=True)
77
79
self.inconsistent_parents = repo_reconciler.inconsistent_parents
78
80
self.garbage_inventories = repo_reconciler.garbage_inventories
79
self.pb.note('Reconciliation complete.')
81
if repo_reconciler.aborted:
83
'Reconcile aborted: revision index has inconsistent parents.')
85
'Run "bzr check" for more details.')
87
self.pb.note('Reconciliation complete.')
82
90
class RepoReconciler(object):
293
307
self.pb.update('Reading indexes.', 0, 2)
294
308
self.inventory = self.repo.get_inventory_weave()
295
309
self.pb.update('Reading indexes.', 1, 2)
310
self.repo._check_for_inconsistent_revision_parents()
296
311
self.revisions = self.repo._revision_store.get_revision_file(self.transaction)
297
312
self.pb.update('Reading indexes.', 2, 2)
345
360
self.garbage_inventories = len(garbage)
346
361
for revision_id in garbage:
347
362
mutter('Garbage inventory {%s} found.', revision_id)
364
def _fix_text_parents(self):
365
"""Fix bad versionedfile parent entries.
367
It is possible for the parents entry in a versionedfile entry to be
368
inconsistent with the values in the revision and inventory.
370
This method finds entries with such inconsistencies, corrects their
371
parent lists, and replaces the versionedfile with a corrected version.
373
transaction = self.repo.get_transaction()
374
revision_versions = repository._RevisionTextVersionCache(self.repo)
375
for num, file_id in enumerate(self.repo.weave_store):
376
self.pb.update('Fixing text parents', num,
377
len(self.repo.weave_store))
378
vf = self.repo.weave_store.get_weave(file_id, transaction)
379
vf_checker = self.repo.get_versioned_file_checker(
380
self.revisions.versions(), revision_versions)
381
versions_with_bad_parents = vf_checker.check_file_version_parents(
383
if len(versions_with_bad_parents) == 0:
385
self._fix_text_parent(file_id, vf, versions_with_bad_parents)
387
def _fix_text_parent(self, file_id, vf, versions_with_bad_parents):
388
"""Fix bad versionedfile entries in a single versioned file."""
389
new_vf = self.repo.weave_store.get_empty('temp:%s' % file_id,
392
for version in vf.versions():
393
if version in versions_with_bad_parents:
394
parents = versions_with_bad_parents[version][1]
396
parents = vf.get_parents(version)
397
new_parents[version] = parents
398
for version in topo_sort(new_parents.items()):
399
new_vf.add_lines(version, new_parents[version],
400
vf.get_lines(version))
401
self.repo.weave_store.copy(new_vf, file_id, self.transaction)
402
self.repo.weave_store.delete('temp:%s' % file_id, self.transaction)