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