~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/reconcile.py

  • Committer: Robert Collins
  • Date: 2007-10-17 09:39:41 UTC
  • mfrom: (2911 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2933.
  • Revision ID: robertc@robertcollins.net-20071017093941-v7d1djrt2617citb
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
    ]
27
27
 
28
28
 
29
 
from bzrlib import ui
30
 
from bzrlib.trace import mutter
 
29
from bzrlib import (
 
30
    errors,
 
31
    ui,
 
32
    repository,
 
33
    )
 
34
from bzrlib.trace import mutter, note
31
35
from bzrlib.tsort import TopoSorter
32
36
 
33
37
 
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:
 
85
            self.pb.note(
 
86
                'Reconcile aborted: revision index has inconsistent parents.')
 
87
            self.pb.note(
 
88
                'Run "bzr check" for more details.')
 
89
        else:
 
90
            self.pb.note('Reconciliation complete.')
81
91
 
82
92
 
83
93
class RepoReconciler(object):
100
110
        """
101
111
        self.garbage_inventories = 0
102
112
        self.inconsistent_parents = 0
 
113
        self.aborted = False
103
114
        self.repo = repo
104
115
        self.thorough = thorough
105
116
 
284
295
    def _reconcile_steps(self):
285
296
        """Perform the steps to reconcile this repository."""
286
297
        if self.thorough:
287
 
            self._load_indexes()
 
298
            try:
 
299
                self._load_indexes()
 
300
            except errors.BzrCheckError:
 
301
                self.aborted = True
 
302
                return
288
303
            # knits never suffer this
289
304
            self._gc_inventory()
 
305
            self._fix_text_parents()
290
306
 
291
307
    def _load_indexes(self):
292
308
        """Load indexes for the reconciliation."""
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)
299
316
 
347
364
        for revision_id in garbage:
348
365
            mutter('Garbage inventory {%s} found.', revision_id)
349
366
 
 
367
    def _fix_text_parents(self):
 
368
        """Fix bad versionedfile parent entries.
 
369
 
 
370
        It is possible for the parents entry in a versionedfile entry to be
 
371
        inconsistent with the values in the revision and inventory.
 
372
 
 
373
        This method finds entries with such inconsistencies, corrects their
 
374
        parent lists, and replaces the versionedfile with a corrected version.
 
375
        """
 
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(
 
387
                vf, file_id)
 
388
            if len(versions_with_bad_parents) == 0:
 
389
                continue
 
390
            self._fix_text_parent(file_id, vf, versions_with_bad_parents)
 
391
 
 
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,
 
395
            self.transaction)
 
396
        new_parents = {}
 
397
        for version in vf.versions():
 
398
            if version in versions_with_bad_parents:
 
399
                parents = versions_with_bad_parents[version][1]
 
400
            else:
 
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)
 
408
 
350
409
 
351
410
class PackReconciler(RepoReconciler):
352
411
    """Reconciler that reconciles a pack based repository.
357
416
 
358
417
    In future this may be a good place to hook in annotation cache checking,
359
418
    index recreation etc.
 
419
 
 
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
360
425
    """
361
426
 
362
427
    def _reconcile_steps(self):
363
428
        """Perform the steps to reconcile this repository."""
364
 
        if self.thorough:
365
 
            pass