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