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