47
46
indicating that the revision was found/not found.
50
from __future__ import absolute_import
49
from bzrlib import errors
56
50
from bzrlib.branch import Branch
57
from bzrlib.controldir import ControlDir
51
from bzrlib.bzrdir import BzrDir
58
52
from bzrlib.revision import NULL_REVISION
53
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
59
54
from bzrlib.trace import note
60
56
from bzrlib.workingtree import WorkingTree
61
from bzrlib.i18n import gettext
63
58
class Check(object):
64
59
"""Check a repository"""
66
def __init__(self, repository, check_repo=True):
67
self.repository = repository
69
def report_results(self, verbose):
70
raise NotImplementedError(self.report_results)
73
class VersionedFileCheck(Check):
74
"""Check a versioned file repository"""
76
61
# The Check object interacts with InventoryEntry.check, etc.
78
63
def __init__(self, repository, check_repo=True):
103
88
if callback_refs is None:
104
89
callback_refs = {}
105
90
self.repository.lock_read()
106
self.progress = ui.ui_factory.nested_progress_bar()
91
self.progress = bzrlib.ui.ui_factory.nested_progress_bar()
108
self.progress.update(gettext('check'), 0, 4)
93
self.progress.update('check', 0, 4)
109
94
if self.check_repo:
110
self.progress.update(gettext('checking revisions'), 0)
95
self.progress.update('checking revisions', 0)
111
96
self.check_revisions()
112
self.progress.update(gettext('checking commit contents'), 1)
97
self.progress.update('checking commit contents', 1)
113
98
self.repository._check_inventories(self)
114
self.progress.update(gettext('checking file graphs'), 2)
99
self.progress.update('checking file graphs', 2)
115
100
# check_weaves is done after the revision scan so that
116
101
# revision index is known to be valid.
117
102
self.check_weaves()
118
self.progress.update(gettext('checking branches and trees'), 3)
103
self.progress.update('checking branches and trees', 3)
119
104
if callback_refs:
120
105
repo = self.repository
121
106
# calculate all refs, and callback the objects requesting them.
202
187
result.report_results(verbose)
204
189
def _report_repo_results(self, verbose):
205
note(gettext('checked repository {0} format {1}').format(
190
note('checked repository %s format %s',
206
191
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))
192
self.repository._format)
193
note('%6d revisions', self.checked_rev_cnt)
194
note('%6d file-ids', len(self.checked_weaves))
211
note(gettext('%6d unreferenced text versions'),
196
note('%6d unreferenced text versions',
212
197
len(self.unreferenced_versions))
213
198
if verbose and len(self.unreferenced_versions):
214
199
for file_id, revision_id in self.unreferenced_versions:
215
note(gettext('unreferenced version: {{{0}}} in {1}').format(revision_id,
200
note('unreferenced version: {%s} in %s', revision_id,
217
202
if self.missing_inventory_sha_cnt:
218
note(gettext('%6d revisions are missing inventory_sha1'),
203
note('%6d revisions are missing inventory_sha1',
219
204
self.missing_inventory_sha_cnt)
220
205
if self.missing_revision_cnt:
221
note(gettext('%6d revisions are mentioned but not present'),
206
note('%6d revisions are mentioned but not present',
222
207
self.missing_revision_cnt)
223
208
if len(self.ghosts):
224
note(gettext('%6d ghost revisions'), len(self.ghosts))
209
note('%6d ghost revisions', len(self.ghosts))
226
211
for ghost in self.ghosts:
227
212
note(' %s', ghost)
228
213
if len(self.missing_parent_links):
229
note(gettext('%6d revisions missing parents in ancestry'),
214
note('%6d revisions missing parents in ancestry',
230
215
len(self.missing_parent_links))
232
217
for link, linkers in self.missing_parent_links.items():
233
note(gettext(' %s should be in the ancestry for:'), link)
218
note(' %s should be in the ancestry for:', link)
234
219
for linker in linkers:
235
220
note(' * %s', linker)
236
221
if len(self.inconsistent_parents):
237
note(gettext('%6d inconsistent parents'), len(self.inconsistent_parents))
222
note('%6d inconsistent parents', len(self.inconsistent_parents))
239
224
for info in self.inconsistent_parents:
240
225
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,
226
note(' * %s version %s has parents %r '
228
% (file_id, revision_id, found_parents,
244
229
correct_parents))
245
230
if self.revs_with_bad_parents_in_index:
247
'%6d revisions have incorrect parents in the revision index'),
231
note('%6d revisions have incorrect parents in the revision index',
248
232
len(self.revs_with_bad_parents_in_index))
250
234
for item in self.revs_with_bad_parents_in_index:
251
235
revision_id, index_parents, actual_parents = item
253
' {0} has wrong parents in index: '
254
'{1!r} should be {2!r}').format(
255
revision_id, index_parents, actual_parents))
237
' %s has wrong parents in index: '
239
revision_id, index_parents, actual_parents)
256
240
for item in self._report_items:
344
328
self.text_key_references[key] = True
331
@deprecated_function(deprecated_in((1,6,0)))
332
def check(branch, verbose):
333
"""Run consistency checks on a branch.
335
Results are reported through logging.
337
Deprecated in 1.6. Please use check_dwim instead.
339
:raise BzrCheckError: if there's a consistency error.
341
check_branch(branch, verbose)
344
@deprecated_function(deprecated_in((1,16,0)))
345
def check_branch(branch, verbose):
346
"""Run consistency checks on a branch.
348
Results are reported through logging.
350
:raise BzrCheckError: if there's a consistency error.
355
for ref in branch._get_check_refs():
356
needed_refs.setdefault(ref, []).append(branch)
357
result = branch.repository.check([branch.last_revision()], needed_refs)
358
branch_result = result.other_results[0]
361
branch_result.report_results(verbose)
347
364
def scan_branch(branch, needed_refs, to_unlock):
348
365
"""Scan a branch for refs.
425
442
scan_branch(branch, needed_refs, to_unlock)
426
443
if do_branch and not branches:
427
note(gettext("No branch found at specified location."))
444
note("No branch found at specified location.")
428
445
if do_tree and base_tree is None and not saw_tree:
429
note(gettext("No working tree found at specified location."))
446
note("No working tree found at specified location.")
430
447
if do_repo or do_branch or do_tree:
432
note(gettext("Checking repository at '%s'.")
449
note("Checking repository at '%s'."
433
450
% (repo.user_url,))
434
451
result = repo.check(None, callback_refs=needed_refs,
435
452
check_repo=do_repo)
436
453
result.report_results(verbose)
439
note(gettext("No working tree found at specified location."))
456
note("No working tree found at specified location.")
441
note(gettext("No branch found at specified location."))
458
note("No branch found at specified location.")
443
note(gettext("No repository found at specified location."))
460
note("No repository found at specified location.")
445
462
for thing in to_unlock: