47
46
indicating that the revision was found/not found.
50
from __future__ import absolute_import
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
60
60
from bzrlib.workingtree import WorkingTree
61
from bzrlib.i18n import gettext
63
62
class Check(object):
64
63
"""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
65
# The Check object interacts with InventoryEntry.check, etc.
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()
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.
202
191
result.report_results(verbose)
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))
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,
204
note('unreferenced version: {%s} in %s', revision_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))
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))
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))
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 '
232
% (file_id, revision_id, found_parents,
244
233
correct_parents))
245
234
if self.revs_with_bad_parents_in_index:
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))
250
238
for item in self.revs_with_bad_parents_in_index:
251
239
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))
241
' %s has wrong parents in index: '
243
revision_id, index_parents, actual_parents)
256
244
for item in self._report_items:
344
332
self.text_key_references[key] = True
335
@deprecated_function(deprecated_in((1,6,0)))
336
def check(branch, verbose):
337
"""Run consistency checks on a branch.
339
Results are reported through logging.
341
Deprecated in 1.6. Please use check_dwim instead.
343
:raise BzrCheckError: if there's a consistency error.
345
check_branch(branch, verbose)
348
@deprecated_function(deprecated_in((1,16,0)))
349
def check_branch(branch, verbose):
350
"""Run consistency checks on a branch.
352
Results are reported through logging.
354
:raise BzrCheckError: if there's a consistency error.
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]
365
branch_result.report_results(verbose)
347
368
def scan_branch(branch, needed_refs, to_unlock):
348
369
"""Scan a branch for refs.
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:
432
note(gettext("Checking repository at '%s'.")
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)
439
note(gettext("No working tree found at specified location."))
460
note("No working tree found at specified location.")
441
note(gettext("No branch found at specified location."))
462
note("No branch found at specified location.")
443
note(gettext("No repository found at specified location."))
464
note("No repository found at specified location.")
445
466
for thing in to_unlock: