32
32
# raising them. If there's more than one exception it'd be good to see them
35
from bzrlib import errors, osutils
35
from bzrlib import errors
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
40
38
from bzrlib.errors import BzrCheckError
41
from bzrlib.repository import Repository
42
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
43
40
from bzrlib.trace import log_error, note
45
from bzrlib.workingtree import WorkingTree
47
42
class Check(object):
48
43
"""Check a repository"""
71
68
self.progress.update('retrieving inventory', 0, 2)
72
69
# do not put in init, as it should be done with progess,
73
70
# and inside the lock.
74
self.inventory_weave = self.repository.inventories
71
self.inventory_weave = self.repository.get_inventory_weave()
75
72
self.progress.update('checking revision graph', 1)
76
73
self.check_revision_graph()
77
74
self.plan_revisions()
115
112
note('%6d file-ids', len(self.checked_weaves))
116
113
note('%6d unique file texts', self.checked_text_cnt)
117
114
note('%6d repeated file texts', self.repeated_text_cnt)
118
note('%6d unreferenced text versions',
119
len(self.unreferenced_versions))
115
note('%6d unreferenced text ancestors',
116
len(self.unreferenced_ancestors))
120
117
if self.missing_inventory_sha_cnt:
121
118
note('%6d revisions are missing inventory_sha1',
122
119
self.missing_inventory_sha_cnt)
137
134
for linker in linkers:
138
135
note(' * %s', linker)
140
for file_id, revision_id in self.unreferenced_versions:
141
log_error('unreferenced version: {%s} in %s', revision_id,
137
for file_id, revision_id in self.unreferenced_ancestors:
138
log_error('unreferenced ancestor: {%s} in %s', revision_id,
143
140
if len(self.inconsistent_parents):
144
141
note('%6d inconsistent parents', len(self.inconsistent_parents))
198
195
def check_weaves(self):
199
196
"""Check all the weaves we can get our hands on.
202
self.progress.update('checking inventory', 0, 2)
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)
203
204
self.inventory_weave.check(progress_bar=self.progress)
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)
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
222
227
def _check_revision_tree(self, rev_id):
223
228
tree = self.repository.revision_tree(rev_id)
229
self.revision_versions.add_revision_text_versions(tree)
224
230
inv = tree.inventory
226
232
for file_id in inv:
241
247
seen_names[path] = True
244
@deprecated_function(deprecated_in((1,6,0)))
245
250
def check(branch, verbose):
246
251
"""Run consistency checks on a branch.
248
253
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.
262
255
:raise BzrCheckError: if there's a consistency error.
264
257
branch.lock_read()
266
259
branch_result = branch.check()
260
repo_result = branch.repository.check([branch.last_revision()])
269
263
branch_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.")
264
repo_result.report_results(verbose)