/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/reconcile.py

  • Committer: Andrew Bennetts
  • Date: 2007-10-12 08:18:54 UTC
  • mfrom: (2905 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2906.
  • Revision ID: andrew.bennetts@canonical.com-20071012081854-6wjgjhjjdy55s84i
Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Reconcilers are able to fix some potential data errors in a branch."""
18
18
 
19
19
 
20
 
__all__ = [
21
 
    'KnitReconciler',
22
 
    'reconcile',
23
 
    'Reconciler',
24
 
    'RepoReconciler',
25
 
    ]
26
 
 
27
 
 
 
20
__all__ = ['reconcile', 'Reconciler', 'RepoReconciler', 'KnitReconciler']
 
21
 
 
22
 
 
23
from bzrlib import (
 
24
    errors,
 
25
    graph,
 
26
    ui,
 
27
    repository,
 
28
    )
 
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
31
33
 
32
34
 
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:
 
82
            self.pb.note(
 
83
                'Reconcile aborted: revision index has inconsistent parents.')
 
84
            self.pb.note(
 
85
                'Run "bzr check" for more details.')
 
86
        else:
 
87
            self.pb.note('Reconciliation complete.')
80
88
 
81
89
 
82
90
class RepoReconciler(object):
99
107
        """
100
108
        self.garbage_inventories = 0
101
109
        self.inconsistent_parents = 0
 
110
        self.aborted = False
102
111
        self.repo = repo
103
112
        self.thorough = thorough
104
113
 
283
292
    def _reconcile_steps(self):
284
293
        """Perform the steps to reconcile this repository."""
285
294
        if self.thorough:
286
 
            self._load_indexes()
 
295
            try:
 
296
                self._load_indexes()
 
297
            except errors.BzrCheckError:
 
298
                self.aborted = True
 
299
                return
287
300
            # knits never suffer this
288
301
            self._gc_inventory()
 
302
            self._fix_text_parents()
289
303
 
290
304
    def _load_indexes(self):
291
305
        """Load indexes for the reconciliation."""
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)
298
313
 
345
360
        self.garbage_inventories = len(garbage)
346
361
        for revision_id in garbage:
347
362
            mutter('Garbage inventory {%s} found.', revision_id)
 
363
 
 
364
    def _fix_text_parents(self):
 
365
        """Fix bad versionedfile parent entries.
 
366
 
 
367
        It is possible for the parents entry in a versionedfile entry to be
 
368
        inconsistent with the values in the revision and inventory.
 
369
 
 
370
        This method finds entries with such inconsistencies, corrects their
 
371
        parent lists, and replaces the versionedfile with a corrected version.
 
372
        """
 
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(
 
382
                vf, file_id)
 
383
            if len(versions_with_bad_parents) == 0:
 
384
                continue
 
385
            self._fix_text_parent(file_id, vf, versions_with_bad_parents)
 
386
 
 
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,
 
390
            self.transaction)
 
391
        new_parents = {}
 
392
        for version in vf.versions():
 
393
            if version in versions_with_bad_parents:
 
394
                parents = versions_with_bad_parents[version][1]
 
395
            else:
 
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)
 
403