77
81
repo_reconciler = self.repo.reconcile(thorough=True)
78
82
self.inconsistent_parents = repo_reconciler.inconsistent_parents
79
83
self.garbage_inventories = repo_reconciler.garbage_inventories
80
self.pb.note('Reconciliation complete.')
84
if repo_reconciler.aborted:
86
'Reconcile aborted: revision index has inconsistent parents.')
88
'Run "bzr check" for more details.')
90
self.pb.note('Reconciliation complete.')
83
93
class RepoReconciler(object):
294
310
self.pb.update('Reading indexes.', 0, 2)
295
311
self.inventory = self.repo.get_inventory_weave()
296
312
self.pb.update('Reading indexes.', 1, 2)
313
self.repo._check_for_inconsistent_revision_parents()
297
314
self.revisions = self.repo._revision_store.get_revision_file(self.transaction)
298
315
self.pb.update('Reading indexes.', 2, 2)
347
364
for revision_id in garbage:
348
365
mutter('Garbage inventory {%s} found.', revision_id)
367
def _fix_text_parents(self):
368
"""Fix bad versionedfile parent entries.
370
It is possible for the parents entry in a versionedfile entry to be
371
inconsistent with the values in the revision and inventory.
373
This method finds entries with such inconsistencies, corrects their
374
parent lists, and replaces the versionedfile with a corrected version.
376
transaction = self.repo.get_transaction()
377
revision_versions = repository._RevisionTextVersionCache(self.repo)
378
versions = self.revisions.versions()
379
revision_versions.prepopulate_revs(versions)
380
for num, file_id in enumerate(self.repo.weave_store):
381
self.pb.update('Fixing text parents', num,
382
len(self.repo.weave_store))
383
vf = self.repo.weave_store.get_weave(file_id, transaction)
384
vf_checker = self.repo.get_versioned_file_checker(
385
versions, revision_versions)
386
versions_with_bad_parents = vf_checker.check_file_version_parents(
388
if len(versions_with_bad_parents) == 0:
390
self._fix_text_parent(file_id, vf, versions_with_bad_parents)
392
def _fix_text_parent(self, file_id, vf, versions_with_bad_parents):
393
"""Fix bad versionedfile entries in a single versioned file."""
394
new_vf = self.repo.weave_store.get_empty('temp:%s' % file_id,
397
for version in vf.versions():
398
if version in versions_with_bad_parents:
399
parents = versions_with_bad_parents[version][1]
401
parents = vf.get_parents(version)
402
new_parents[version] = parents
403
for version in TopoSorter(new_parents.items()).iter_topo_order():
404
new_vf.add_lines(version, new_parents[version],
405
vf.get_lines(version))
406
self.repo.weave_store.copy(new_vf, file_id, self.transaction)
407
self.repo.weave_store.delete('temp:%s' % file_id, self.transaction)
351
410
class PackReconciler(RepoReconciler):
352
411
"""Reconciler that reconciles a pack based repository.
358
417
In future this may be a good place to hook in annotation cache checking,
359
418
index recreation etc.
420
XXX: The index corruption that _fix_text_parents performs is needed for
421
packs, but not yet implemented. The basic approach is to:
422
- lock the names list
423
- perform a customised pack() that regenerates data as needed
424
- unlock the names list
362
427
def _reconcile_steps(self):
363
428
"""Perform the steps to reconcile this repository."""