32
32
# raising them. If there's more than one exception it'd be good to see them
35
from bzrlib import errors
35
from bzrlib import errors, osutils
36
36
from bzrlib import repository as _mod_repository
37
37
from bzrlib import revision
38
from bzrlib.branch import Branch
39
from bzrlib.bzrdir import BzrDir
38
40
from bzrlib.errors import BzrCheckError
41
from bzrlib.repository import Repository
42
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
43
from bzrlib.trace import log_error, note
40
from bzrlib.trace import log_error, note
45
from bzrlib.workingtree import WorkingTree
42
47
class Check(object):
43
48
"""Check a repository"""
68
71
self.progress.update('retrieving inventory', 0, 2)
69
72
# do not put in init, as it should be done with progess,
70
73
# and inside the lock.
71
self.inventory_weave = self.repository.get_inventory_weave()
74
self.inventory_weave = self.repository.inventories
72
75
self.progress.update('checking revision graph', 1)
73
76
self.check_revision_graph()
74
77
self.plan_revisions()
112
115
note('%6d file-ids', len(self.checked_weaves))
113
116
note('%6d unique file texts', self.checked_text_cnt)
114
117
note('%6d repeated file texts', self.repeated_text_cnt)
115
note('%6d unreferenced text ancestors',
116
len(self.unreferenced_ancestors))
118
note('%6d unreferenced text versions',
119
len(self.unreferenced_versions))
117
120
if self.missing_inventory_sha_cnt:
118
121
note('%6d revisions are missing inventory_sha1',
119
122
self.missing_inventory_sha_cnt)
134
137
for linker in linkers:
135
138
note(' * %s', linker)
137
for file_id, revision_id in self.unreferenced_ancestors:
138
log_error('unreferenced ancestor: {%s} in %s', revision_id,
140
for file_id, revision_id in self.unreferenced_versions:
141
log_error('unreferenced version: {%s} in %s', revision_id,
140
143
if len(self.inconsistent_parents):
141
144
note('%6d inconsistent parents', len(self.inconsistent_parents))
195
198
def check_weaves(self):
196
199
"""Check all the weaves we can get our hands on.
200
if self.repository.weave_store.listable():
201
weave_ids = list(self.repository.weave_store)
202
n_weaves = len(weave_ids) + 1
203
self.progress.update('checking versionedfile', 0, n_weaves)
202
self.progress.update('checking inventory', 0, 2)
204
203
self.inventory_weave.check(progress_bar=self.progress)
205
files_in_revisions = {}
206
revisions_of_files = {}
207
for i, weave_id in enumerate(weave_ids):
208
self.progress.update('checking versionedfile', i, n_weaves)
209
w = self.repository.weave_store.get_weave(weave_id,
210
self.repository.get_transaction())
211
# No progress here, because it looks ugly.
214
weave_checker = self.repository.get_versioned_file_checker(
215
self.planned_revisions, self.revision_versions)
216
result = weave_checker.check_file_version_parents(w, weave_id)
218
for revision_id, (weave_parents,correct_parents) in result.items():
219
self.inconsistent_parents.append(
220
(revision_id, weave_id, weave_parents, correct_parents))
221
unreferenced_parents = set(weave_parents)-set(correct_parents)
222
for unreferenced_parent in unreferenced_parents:
223
self.unreferenced_ancestors.add(
224
(weave_id, unreferenced_parent))
225
self.checked_weaves[weave_id] = True
204
self.progress.update('checking text storage', 1, 2)
205
self.repository.texts.check(progress_bar=self.progress)
206
weave_checker = self.repository._get_versioned_file_checker()
207
result = weave_checker.check_file_version_parents(
208
self.repository.texts, progress_bar=self.progress)
209
self.checked_weaves = weave_checker.file_ids
210
bad_parents, unused_versions = result
211
bad_parents = bad_parents.items()
212
for text_key, (stored_parents, correct_parents) in bad_parents:
213
# XXX not ready for id join/split operations.
214
weave_id = text_key[0]
215
revision_id = text_key[-1]
216
weave_parents = tuple([parent[-1] for parent in stored_parents])
217
correct_parents = tuple([parent[-1] for parent in correct_parents])
218
self.inconsistent_parents.append(
219
(revision_id, weave_id, weave_parents, correct_parents))
220
self.unreferenced_versions.update(unused_versions)
227
222
def _check_revision_tree(self, rev_id):
228
223
tree = self.repository.revision_tree(rev_id)
229
self.revision_versions.add_revision_text_versions(tree)
230
224
inv = tree.inventory
232
226
for file_id in inv:
247
241
seen_names[path] = True
244
@deprecated_function(deprecated_in((1,6,0)))
250
245
def check(branch, verbose):
251
246
"""Run consistency checks on a branch.
253
248
Results are reported through logging.
250
Deprecated in 1.6. Please use check_branch instead.
252
:raise BzrCheckError: if there's a consistency error.
254
check_branch(branch, verbose)
257
def check_branch(branch, verbose):
258
"""Run consistency checks on a branch.
260
Results are reported through logging.
255
262
:raise BzrCheckError: if there's a consistency error.
257
264
branch.lock_read()
259
266
branch_result = branch.check()
260
repo_result = branch.repository.check([branch.last_revision()])
263
269
branch_result.report_results(verbose)
264
repo_result.report_results(verbose)
272
def check_dwim(path, verbose, do_branch=False, do_repo=False, do_tree=False):
274
tree, branch, repo, relpath = \
275
BzrDir.open_containing_tree_branch_or_repository(path)
276
except errors.NotBranchError:
277
tree = branch = repo = None
281
note("Checking working tree at '%s'."
282
% (tree.bzrdir.root_transport.base,))
285
log_error("No working tree found at specified location.")
287
if branch is not None:
290
# The branch is in a shared repository
291
repo = branch.repository
293
elif repo is not None:
294
branches = repo.find_branches(using=True)
300
note("Checking repository at '%s'."
301
% (repo.bzrdir.root_transport.base,))
302
result = repo.check()
303
result.report_results(verbose)
306
log_error("No branch found at specified location.")
308
for branch in branches:
309
note("Checking branch at '%s'."
310
% (branch.bzrdir.root_transport.base,))
311
check_branch(branch, verbose)
316
log_error("No branch found at specified location.")
318
log_error("No repository found at specified location.")