~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/check.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
# raising them.  If there's more than one exception it'd be good to see them
33
33
# all.
34
34
 
35
 
from bzrlib import errors
 
35
from bzrlib import errors, osutils
36
36
from bzrlib import repository as _mod_repository
37
37
from bzrlib import revision
 
38
from bzrlib.branch import Branch
 
39
from bzrlib.bzrdir import BzrDir
38
40
from bzrlib.errors import BzrCheckError
 
41
from bzrlib.repository import Repository
 
42
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
 
43
from bzrlib.trace import log_error, note
39
44
import bzrlib.ui
40
 
from bzrlib.trace import log_error, note
 
45
from bzrlib.workingtree import WorkingTree
41
46
 
42
47
class Check(object):
43
48
    """Check a repository"""
55
60
        self.missing_revision_cnt = 0
56
61
        # maps (file-id, version) -> sha1; used by InventoryFile._check
57
62
        self.checked_texts = {}
58
 
        self.checked_weaves = {}
59
 
        self.revision_versions = _mod_repository._RevisionTextVersionCache(
60
 
            self.repository)
61
 
        self.unreferenced_ancestors = set()
 
63
        self.checked_weaves = set()
 
64
        self.unreferenced_versions = set()
62
65
        self.inconsistent_parents = []
63
66
 
64
67
    def check(self):
68
71
            self.progress.update('retrieving inventory', 0, 2)
69
72
            # do not put in init, as it should be done with progess,
70
73
            # and inside the lock.
71
 
            self.inventory_weave = self.repository.get_inventory_weave()
 
74
            self.inventory_weave = self.repository.inventories
72
75
            self.progress.update('checking revision graph', 1)
73
76
            self.check_revision_graph()
74
77
            self.plan_revisions()
80
83
                revno += 1
81
84
                self.check_one_rev(rev_id)
82
85
            # check_weaves is done after the revision scan so that
83
 
            # revision_versions is pre-populated
 
86
            # revision index is known to be valid.
84
87
            self.check_weaves()
85
88
        finally:
86
89
            self.progress.finished()
98
101
        repository = self.repository
99
102
        self.planned_revisions = repository.all_revision_ids()
100
103
        self.progress.clear()
101
 
        inventoried = set(self.inventory_weave.versions())
 
104
        inventoried = set(key[-1] for key in self.inventory_weave.keys())
102
105
        awol = set(self.planned_revisions) - inventoried
103
106
        if len(awol) > 0:
104
107
            raise BzrCheckError('Stored revisions missing from inventory'
112
115
        note('%6d file-ids', len(self.checked_weaves))
113
116
        note('%6d unique file texts', self.checked_text_cnt)
114
117
        note('%6d repeated file texts', self.repeated_text_cnt)
115
 
        note('%6d unreferenced text ancestors',
116
 
             len(self.unreferenced_ancestors))
 
118
        note('%6d unreferenced text versions',
 
119
             len(self.unreferenced_versions))
117
120
        if self.missing_inventory_sha_cnt:
118
121
            note('%6d revisions are missing inventory_sha1',
119
122
                 self.missing_inventory_sha_cnt)
134
137
                    for linker in linkers:
135
138
                        note('       * %s', linker)
136
139
            if verbose:
137
 
                for file_id, revision_id in self.unreferenced_ancestors:
138
 
                    log_error('unreferenced ancestor: {%s} in %s', revision_id,
 
140
                for file_id, revision_id in self.unreferenced_versions:
 
141
                    log_error('unreferenced version: {%s} in %s', revision_id,
139
142
                        file_id)
140
143
        if len(self.inconsistent_parents):
141
144
            note('%6d inconsistent parents', len(self.inconsistent_parents))
195
198
    def check_weaves(self):
196
199
        """Check all the weaves we can get our hands on.
197
200
        """
198
 
        n_weaves = 1
199
201
        weave_ids = []
200
 
        if self.repository.weave_store.listable():
201
 
            weave_ids = list(self.repository.weave_store)
202
 
            n_weaves = len(weave_ids) + 1
203
 
        self.progress.update('checking versionedfile', 0, n_weaves)
 
202
        self.progress.update('checking inventory', 0, 2)
204
203
        self.inventory_weave.check(progress_bar=self.progress)
205
 
        files_in_revisions = {}
206
 
        revisions_of_files = {}
207
 
        for i, weave_id in enumerate(weave_ids):
208
 
            self.progress.update('checking versionedfile', i, n_weaves)
209
 
            w = self.repository.weave_store.get_weave(weave_id,
210
 
                    self.repository.get_transaction())
211
 
            # No progress here, because it looks ugly.
212
 
            w.check()
213
 
 
214
 
            weave_checker = self.repository.get_versioned_file_checker(
215
 
                self.planned_revisions, self.revision_versions)
216
 
            result = weave_checker.check_file_version_parents(w, weave_id)
217
 
 
218
 
            for revision_id, (weave_parents,correct_parents) in result.items():
219
 
                self.inconsistent_parents.append(
220
 
                    (revision_id, weave_id, weave_parents, correct_parents))
221
 
                unreferenced_parents = set(weave_parents)-set(correct_parents)
222
 
                for unreferenced_parent in unreferenced_parents:
223
 
                    self.unreferenced_ancestors.add(
224
 
                        (weave_id, unreferenced_parent))
225
 
            self.checked_weaves[weave_id] = True
 
204
        self.progress.update('checking text storage', 1, 2)
 
205
        self.repository.texts.check(progress_bar=self.progress)
 
206
        weave_checker = self.repository._get_versioned_file_checker()
 
207
        result = weave_checker.check_file_version_parents(
 
208
            self.repository.texts, progress_bar=self.progress)
 
209
        self.checked_weaves = weave_checker.file_ids
 
210
        bad_parents, unused_versions = result
 
211
        bad_parents = bad_parents.items()
 
212
        for text_key, (stored_parents, correct_parents) in bad_parents:
 
213
            # XXX not ready for id join/split operations.
 
214
            weave_id = text_key[0]
 
215
            revision_id = text_key[-1]
 
216
            weave_parents = tuple([parent[-1] for parent in stored_parents])
 
217
            correct_parents = tuple([parent[-1] for parent in correct_parents])
 
218
            self.inconsistent_parents.append(
 
219
                (revision_id, weave_id, weave_parents, correct_parents))
 
220
        self.unreferenced_versions.update(unused_versions)
226
221
 
227
222
    def _check_revision_tree(self, rev_id):
228
223
        tree = self.repository.revision_tree(rev_id)
229
 
        self.revision_versions.add_revision_text_versions(tree)
230
224
        inv = tree.inventory
231
225
        seen_ids = {}
232
226
        for file_id in inv:
247
241
            seen_names[path] = True
248
242
 
249
243
 
 
244
@deprecated_function(deprecated_in((1,6,0)))
250
245
def check(branch, verbose):
251
246
    """Run consistency checks on a branch.
252
247
    
253
248
    Results are reported through logging.
254
249
    
 
250
    Deprecated in 1.6.  Please use check_branch instead.
 
251
 
 
252
    :raise BzrCheckError: if there's a consistency error.
 
253
    """
 
254
    check_branch(branch, verbose)
 
255
 
 
256
 
 
257
def check_branch(branch, verbose):
 
258
    """Run consistency checks on a branch.
 
259
 
 
260
    Results are reported through logging.
 
261
 
255
262
    :raise BzrCheckError: if there's a consistency error.
256
263
    """
257
264
    branch.lock_read()
258
265
    try:
259
266
        branch_result = branch.check()
260
 
        repo_result = branch.repository.check([branch.last_revision()])
261
267
    finally:
262
268
        branch.unlock()
263
269
    branch_result.report_results(verbose)
264
 
    repo_result.report_results(verbose)
265
 
 
266
 
 
267
 
 
 
270
 
 
271
 
 
272
def check_dwim(path, verbose, do_branch=False, do_repo=False, do_tree=False):
 
273
    try:
 
274
        tree, branch, repo, relpath = \
 
275
                        BzrDir.open_containing_tree_branch_or_repository(path)
 
276
    except errors.NotBranchError:
 
277
        tree = branch = repo = None
 
278
 
 
279
    if do_tree:
 
280
        if tree is not None:
 
281
            note("Checking working tree at '%s'." 
 
282
                 % (tree.bzrdir.root_transport.base,))
 
283
            tree._check()
 
284
        else:
 
285
            log_error("No working tree found at specified location.")
 
286
 
 
287
    if branch is not None:
 
288
        # We have a branch
 
289
        if repo is None:
 
290
            # The branch is in a shared repository
 
291
            repo = branch.repository
 
292
        branches = [branch]
 
293
    elif repo is not None:
 
294
        branches = repo.find_branches(using=True)
 
295
 
 
296
    if repo is not None:
 
297
        repo.lock_read()
 
298
        try:
 
299
            if do_repo:
 
300
                note("Checking repository at '%s'."
 
301
                     % (repo.bzrdir.root_transport.base,))
 
302
                result = repo.check()
 
303
                result.report_results(verbose)
 
304
            if do_branch:
 
305
                if branches == []:
 
306
                    log_error("No branch found at specified location.")
 
307
                else:
 
308
                    for branch in branches:
 
309
                        note("Checking branch at '%s'."
 
310
                             % (branch.bzrdir.root_transport.base,))
 
311
                        check_branch(branch, verbose)
 
312
        finally:
 
313
            repo.unlock()
 
314
    else:
 
315
        if do_branch:
 
316
            log_error("No branch found at specified location.")
 
317
        if do_repo:
 
318
            log_error("No repository found at specified location.")