47
46
indicating that the revision was found/not found.
49
from bzrlib import errors
54
50
from bzrlib.branch import Branch
55
from bzrlib.controldir import ControlDir
51
from bzrlib.bzrdir import BzrDir
56
52
from bzrlib.revision import NULL_REVISION
53
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
57
54
from bzrlib.trace import note
58
56
from bzrlib.workingtree import WorkingTree
59
from bzrlib.i18n import gettext
61
58
class Check(object):
62
59
"""Check a repository"""
64
def __init__(self, repository, check_repo=True):
65
self.repository = repository
67
def report_results(self, verbose):
68
raise NotImplementedError(self.report_results)
71
class VersionedFileCheck(Check):
72
"""Check a versioned file repository"""
74
61
# The Check object interacts with InventoryEntry.check, etc.
76
63
def __init__(self, repository, check_repo=True):
101
88
if callback_refs is None:
102
89
callback_refs = {}
103
90
self.repository.lock_read()
104
self.progress = ui.ui_factory.nested_progress_bar()
91
self.progress = bzrlib.ui.ui_factory.nested_progress_bar()
106
self.progress.update(gettext('check'), 0, 4)
93
self.progress.update('check', 0, 4)
107
94
if self.check_repo:
108
self.progress.update(gettext('checking revisions'), 0)
95
self.progress.update('checking revisions', 0)
109
96
self.check_revisions()
110
self.progress.update(gettext('checking commit contents'), 1)
97
self.progress.update('checking commit contents', 1)
111
98
self.repository._check_inventories(self)
112
self.progress.update(gettext('checking file graphs'), 2)
99
self.progress.update('checking file graphs', 2)
113
100
# check_weaves is done after the revision scan so that
114
101
# revision index is known to be valid.
115
102
self.check_weaves()
116
self.progress.update(gettext('checking branches and trees'), 3)
103
self.progress.update('checking branches and trees', 3)
117
104
if callback_refs:
118
105
repo = self.repository
119
106
# calculate all refs, and callback the objects requesting them.
200
187
result.report_results(verbose)
202
189
def _report_repo_results(self, verbose):
203
note(gettext('checked repository {0} format {1}').format(
190
note('checked repository %s format %s',
204
191
self.repository.user_url,
205
self.repository._format))
206
note(gettext('%6d revisions'), self.checked_rev_cnt)
207
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))
209
note(gettext('%6d unreferenced text versions'),
196
note('%6d unreferenced text versions',
210
197
len(self.unreferenced_versions))
211
198
if verbose and len(self.unreferenced_versions):
212
199
for file_id, revision_id in self.unreferenced_versions:
213
note(gettext('unreferenced version: {{{0}}} in {1}').format(revision_id,
200
note('unreferenced version: {%s} in %s', revision_id,
215
202
if self.missing_inventory_sha_cnt:
216
note(gettext('%6d revisions are missing inventory_sha1'),
203
note('%6d revisions are missing inventory_sha1',
217
204
self.missing_inventory_sha_cnt)
218
205
if self.missing_revision_cnt:
219
note(gettext('%6d revisions are mentioned but not present'),
206
note('%6d revisions are mentioned but not present',
220
207
self.missing_revision_cnt)
221
208
if len(self.ghosts):
222
note(gettext('%6d ghost revisions'), len(self.ghosts))
209
note('%6d ghost revisions', len(self.ghosts))
224
211
for ghost in self.ghosts:
225
212
note(' %s', ghost)
226
213
if len(self.missing_parent_links):
227
note(gettext('%6d revisions missing parents in ancestry'),
214
note('%6d revisions missing parents in ancestry',
228
215
len(self.missing_parent_links))
230
217
for link, linkers in self.missing_parent_links.items():
231
note(gettext(' %s should be in the ancestry for:'), link)
218
note(' %s should be in the ancestry for:', link)
232
219
for linker in linkers:
233
220
note(' * %s', linker)
234
221
if len(self.inconsistent_parents):
235
note(gettext('%6d inconsistent parents'), len(self.inconsistent_parents))
222
note('%6d inconsistent parents', len(self.inconsistent_parents))
237
224
for info in self.inconsistent_parents:
238
225
revision_id, file_id, found_parents, correct_parents = info
239
note(gettext(' * {0} version {1} has parents {2!r} '
240
'but should have {3!r}').format(
241
file_id, revision_id, found_parents,
226
note(' * %s version %s has parents %r '
228
% (file_id, revision_id, found_parents,
242
229
correct_parents))
243
230
if self.revs_with_bad_parents_in_index:
245
'%6d revisions have incorrect parents in the revision index'),
231
note('%6d revisions have incorrect parents in the revision index',
246
232
len(self.revs_with_bad_parents_in_index))
248
234
for item in self.revs_with_bad_parents_in_index:
249
235
revision_id, index_parents, actual_parents = item
251
' {0} has wrong parents in index: '
252
'{1!r} should be {2!r}').format(
253
revision_id, index_parents, actual_parents))
237
' %s has wrong parents in index: '
239
revision_id, index_parents, actual_parents)
254
240
for item in self._report_items:
342
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)
345
364
def scan_branch(branch, needed_refs, to_unlock):
346
365
"""Scan a branch for refs.
423
442
scan_branch(branch, needed_refs, to_unlock)
424
443
if do_branch and not branches:
425
note(gettext("No branch found at specified location."))
444
note("No branch found at specified location.")
426
445
if do_tree and base_tree is None and not saw_tree:
427
note(gettext("No working tree found at specified location."))
446
note("No working tree found at specified location.")
428
447
if do_repo or do_branch or do_tree:
430
note(gettext("Checking repository at '%s'.")
449
note("Checking repository at '%s'."
431
450
% (repo.user_url,))
432
451
result = repo.check(None, callback_refs=needed_refs,
433
452
check_repo=do_repo)
434
453
result.report_results(verbose)
437
note(gettext("No working tree found at specified location."))
456
note("No working tree found at specified location.")
439
note(gettext("No branch found at specified location."))
458
note("No branch found at specified location.")
441
note(gettext("No repository found at specified location."))
460
note("No repository found at specified location.")
443
462
for thing in to_unlock: