~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/check.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-03-25 00:02:51 UTC
  • mfrom: (5106.1.1 version-bump)
  • Revision ID: pqm@pqm.ubuntu.com-20100325000251-bwsv5c5d3l9x3lnn
(Jelmer) Bump API version for 2.2.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
so that when the dependent object is checked, matches can be pulled out and
40
40
evaluated in-line rather than re-reading the same data many times.
41
41
check_refs are tuples (kind, value). Currently defined kinds are:
42
 
 
43
42
* 'trees', where value is a revid and the looked up objects are revision trees.
44
43
* 'lefthand-distance', where value is a revid and the looked up objects are the
45
44
  distance along the lefthand path to NULL for that revid.
47
46
  indicating that the revision was found/not found.
48
47
"""
49
48
 
50
 
from __future__ import absolute_import
51
 
 
52
 
from bzrlib import (
53
 
    errors,
54
 
    ui,
55
 
    )
 
49
from bzrlib import errors, osutils
 
50
from bzrlib import repository as _mod_repository
 
51
from bzrlib import revision
56
52
from bzrlib.branch import Branch
57
 
from bzrlib.controldir import ControlDir
 
53
from bzrlib.bzrdir import BzrDir
 
54
from bzrlib.errors import BzrCheckError
 
55
from bzrlib.repository import Repository
58
56
from bzrlib.revision import NULL_REVISION
 
57
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
59
58
from bzrlib.trace import note
 
59
import bzrlib.ui
60
60
from bzrlib.workingtree import WorkingTree
61
 
from bzrlib.i18n import gettext
62
61
 
63
62
class Check(object):
64
63
    """Check a repository"""
65
64
 
66
 
    def __init__(self, repository, check_repo=True):
67
 
        self.repository = repository
68
 
 
69
 
    def report_results(self, verbose):
70
 
        raise NotImplementedError(self.report_results)
71
 
 
72
 
 
73
 
class VersionedFileCheck(Check):
74
 
    """Check a versioned file repository"""
75
 
 
76
65
    # The Check object interacts with InventoryEntry.check, etc.
77
66
 
78
67
    def __init__(self, repository, check_repo=True):
103
92
        if callback_refs is None:
104
93
            callback_refs = {}
105
94
        self.repository.lock_read()
106
 
        self.progress = ui.ui_factory.nested_progress_bar()
 
95
        self.progress = bzrlib.ui.ui_factory.nested_progress_bar()
107
96
        try:
108
 
            self.progress.update(gettext('check'), 0, 4)
 
97
            self.progress.update('check', 0, 4)
109
98
            if self.check_repo:
110
 
                self.progress.update(gettext('checking revisions'), 0)
 
99
                self.progress.update('checking revisions', 0)
111
100
                self.check_revisions()
112
 
                self.progress.update(gettext('checking commit contents'), 1)
 
101
                self.progress.update('checking commit contents', 1)
113
102
                self.repository._check_inventories(self)
114
 
                self.progress.update(gettext('checking file graphs'), 2)
 
103
                self.progress.update('checking file graphs', 2)
115
104
                # check_weaves is done after the revision scan so that
116
105
                # revision index is known to be valid.
117
106
                self.check_weaves()
118
 
            self.progress.update(gettext('checking branches and trees'), 3)
 
107
            self.progress.update('checking branches and trees', 3)
119
108
            if callback_refs:
120
109
                repo = self.repository
121
110
                # calculate all refs, and callback the objects requesting them.
185
174
        # - we can fill out existence flags at this point
186
175
        # - we can read the revision inventory sha at this point
187
176
        # - we can check properties and serialisers etc.
188
 
        if not self.repository._format.revision_graph_can_have_wrong_parents:
 
177
        if not self.repository.revision_graph_can_have_wrong_parents():
189
178
            # The check against the index isn't needed.
190
179
            self.revs_with_bad_parents_in_index = None
191
180
            for thing in revision_iterator:
202
191
            result.report_results(verbose)
203
192
 
204
193
    def _report_repo_results(self, verbose):
205
 
        note(gettext('checked repository {0} format {1}').format(
206
 
            self.repository.user_url,
207
 
            self.repository._format))
208
 
        note(gettext('%6d revisions'), self.checked_rev_cnt)
209
 
        note(gettext('%6d file-ids'), len(self.checked_weaves))
 
194
        note('checked repository %s format %s',
 
195
             self.repository.bzrdir.root_transport,
 
196
             self.repository._format)
 
197
        note('%6d revisions', self.checked_rev_cnt)
 
198
        note('%6d file-ids', len(self.checked_weaves))
210
199
        if verbose:
211
 
            note(gettext('%6d unreferenced text versions'),
 
200
            note('%6d unreferenced text versions',
212
201
                len(self.unreferenced_versions))
213
202
        if verbose and len(self.unreferenced_versions):
214
203
                for file_id, revision_id in self.unreferenced_versions:
215
 
                    note(gettext('unreferenced version: {{{0}}} in {1}').format(revision_id,
216
 
                        file_id))
 
204
                    note('unreferenced version: {%s} in %s', revision_id,
 
205
                        file_id)
217
206
        if self.missing_inventory_sha_cnt:
218
 
            note(gettext('%6d revisions are missing inventory_sha1'),
 
207
            note('%6d revisions are missing inventory_sha1',
219
208
                 self.missing_inventory_sha_cnt)
220
209
        if self.missing_revision_cnt:
221
 
            note(gettext('%6d revisions are mentioned but not present'),
 
210
            note('%6d revisions are mentioned but not present',
222
211
                 self.missing_revision_cnt)
223
212
        if len(self.ghosts):
224
 
            note(gettext('%6d ghost revisions'), len(self.ghosts))
 
213
            note('%6d ghost revisions', len(self.ghosts))
225
214
            if verbose:
226
215
                for ghost in self.ghosts:
227
216
                    note('      %s', ghost)
228
217
        if len(self.missing_parent_links):
229
 
            note(gettext('%6d revisions missing parents in ancestry'),
 
218
            note('%6d revisions missing parents in ancestry',
230
219
                 len(self.missing_parent_links))
231
220
            if verbose:
232
221
                for link, linkers in self.missing_parent_links.items():
233
 
                    note(gettext('      %s should be in the ancestry for:'), link)
 
222
                    note('      %s should be in the ancestry for:', link)
234
223
                    for linker in linkers:
235
224
                        note('       * %s', linker)
236
225
        if len(self.inconsistent_parents):
237
 
            note(gettext('%6d inconsistent parents'), len(self.inconsistent_parents))
 
226
            note('%6d inconsistent parents', len(self.inconsistent_parents))
238
227
            if verbose:
239
228
                for info in self.inconsistent_parents:
240
229
                    revision_id, file_id, found_parents, correct_parents = info
241
 
                    note(gettext('      * {0} version {1} has parents {2!r} '
242
 
                         'but should have {3!r}').format(
243
 
                         file_id, revision_id, found_parents,
 
230
                    note('      * %s version %s has parents %r '
 
231
                         'but should have %r'
 
232
                         % (file_id, revision_id, found_parents,
244
233
                             correct_parents))
245
234
        if self.revs_with_bad_parents_in_index:
246
 
            note(gettext(
247
 
                 '%6d revisions have incorrect parents in the revision index'),
 
235
            note('%6d revisions have incorrect parents in the revision index',
248
236
                 len(self.revs_with_bad_parents_in_index))
249
237
            if verbose:
250
238
                for item in self.revs_with_bad_parents_in_index:
251
239
                    revision_id, index_parents, actual_parents = item
252
 
                    note(gettext(
253
 
                        '       {0} has wrong parents in index: '
254
 
                        '{1!r} should be {2!r}').format(
255
 
                        revision_id, index_parents, actual_parents))
 
240
                    note(
 
241
                        '       %s has wrong parents in index: '
 
242
                        '%r should be %r',
 
243
                        revision_id, index_parents, actual_parents)
256
244
        for item in self._report_items:
257
245
            note(item)
258
246
 
263
251
        :param rev: A revision or None to indicate a missing revision.
264
252
        """
265
253
        if rev.revision_id != rev_id:
266
 
            self._report_items.append(gettext(
267
 
                'Mismatched internal revid {{{0}}} and index revid {{{1}}}').format(
 
254
            self._report_items.append(
 
255
                'Mismatched internal revid {%s} and index revid {%s}' % (
268
256
                rev.revision_id, rev_id))
269
257
            rev_id = rev.revision_id
270
258
        # Check this revision tree etc, and count as seen when we encounter a
293
281
        existing = self.pending_keys.get(key)
294
282
        if existing:
295
283
            if sha1 != existing[1]:
296
 
                self._report_items.append(gettext('Multiple expected sha1s for {0}. {{{1}}}'
297
 
                    ' expects {{{2}}}, {{{3}}} expects {{{4}}}').format(
 
284
                self._report_items.append('Multiple expected sha1s for %s. {%s}'
 
285
                    ' expects {%s}, {%s} expects {%s}', (
298
286
                    key, referer, sha1, existing[1], existing[0]))
299
287
        else:
300
288
            self.pending_keys[key] = (kind, sha1, referer)
303
291
        """Check all the weaves we can get our hands on.
304
292
        """
305
293
        weave_ids = []
306
 
        storebar = ui.ui_factory.nested_progress_bar()
 
294
        storebar = bzrlib.ui.ui_factory.nested_progress_bar()
307
295
        try:
308
296
            self._check_weaves(storebar)
309
297
        finally:
344
332
            self.text_key_references[key] = True
345
333
 
346
334
 
 
335
@deprecated_function(deprecated_in((1,6,0)))
 
336
def check(branch, verbose):
 
337
    """Run consistency checks on a branch.
 
338
 
 
339
    Results are reported through logging.
 
340
 
 
341
    Deprecated in 1.6.  Please use check_dwim instead.
 
342
 
 
343
    :raise BzrCheckError: if there's a consistency error.
 
344
    """
 
345
    check_branch(branch, verbose)
 
346
 
 
347
 
 
348
@deprecated_function(deprecated_in((1,16,0)))
 
349
def check_branch(branch, verbose):
 
350
    """Run consistency checks on a branch.
 
351
 
 
352
    Results are reported through logging.
 
353
 
 
354
    :raise BzrCheckError: if there's a consistency error.
 
355
    """
 
356
    branch.lock_read()
 
357
    try:
 
358
        needed_refs = {}
 
359
        for ref in branch._get_check_refs():
 
360
            needed_refs.setdefault(ref, []).append(branch)
 
361
        result = branch.repository.check([branch.last_revision()], needed_refs)
 
362
        branch_result = result.other_results[0]
 
363
    finally:
 
364
        branch.unlock()
 
365
    branch_result.report_results(verbose)
 
366
 
 
367
 
347
368
def scan_branch(branch, needed_refs, to_unlock):
348
369
    """Scan a branch for refs.
349
370
 
351
372
    :param needed_refs: Refs we are accumulating.
352
373
    :param to_unlock: The unlock list accumulating.
353
374
    """
354
 
    note(gettext("Checking branch at '%s'.") % (branch.base,))
 
375
    note("Checking branch at '%s'." % (branch.base,))
355
376
    branch.lock_read()
356
377
    to_unlock.append(branch)
357
378
    branch_refs = branch._get_check_refs()
371
392
    """
372
393
    if base_tree is not None and tree.basedir == base_tree.basedir:
373
394
        return
374
 
    note(gettext("Checking working tree at '%s'.") % (tree.basedir,))
 
395
    note("Checking working tree at '%s'." % (tree.basedir,))
375
396
    tree.lock_read()
376
397
    to_unlock.append(tree)
377
398
    tree_refs = tree._get_check_refs()
388
409
    """
389
410
    try:
390
411
        base_tree, branch, repo, relpath = \
391
 
                        ControlDir.open_containing_tree_branch_or_repository(path)
 
412
                        BzrDir.open_containing_tree_branch_or_repository(path)
392
413
    except errors.NotBranchError:
393
414
        base_tree = branch = repo = None
394
415
 
424
445
                    if do_branch:
425
446
                        scan_branch(branch, needed_refs, to_unlock)
426
447
            if do_branch and not branches:
427
 
                note(gettext("No branch found at specified location."))
 
448
                note("No branch found at specified location.")
428
449
            if do_tree and base_tree is None and not saw_tree:
429
 
                note(gettext("No working tree found at specified location."))
 
450
                note("No working tree found at specified location.")
430
451
            if do_repo or do_branch or do_tree:
431
452
                if do_repo:
432
 
                    note(gettext("Checking repository at '%s'.")
433
 
                         % (repo.user_url,))
 
453
                    note("Checking repository at '%s'."
 
454
                         % (repo.bzrdir.root_transport.base,))
434
455
                result = repo.check(None, callback_refs=needed_refs,
435
456
                    check_repo=do_repo)
436
457
                result.report_results(verbose)
437
458
        else:
438
459
            if do_tree:
439
 
                note(gettext("No working tree found at specified location."))
 
460
                note("No working tree found at specified location.")
440
461
            if do_branch:
441
 
                note(gettext("No branch found at specified location."))
 
462
                note("No branch found at specified location.")
442
463
            if do_repo:
443
 
                note(gettext("No repository found at specified location."))
 
464
                note("No repository found at specified location.")
444
465
    finally:
445
466
        for thing in to_unlock:
446
467
            thing.unlock()