2052.3.2
by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical |
1 |
# Copyright (C) 2005, 2006 Canonical Ltd
|
1887.1.1
by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines, |
2 |
#
|
1
by mbp at sourcefrog
import from baz patch-364 |
3 |
# This program is free software; you can redistribute it and/or modify
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
1887.1.1
by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines, |
7 |
#
|
1
by mbp at sourcefrog
import from baz patch-364 |
8 |
# This program is distributed in the hope that it will be useful,
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
1887.1.1
by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines, |
12 |
#
|
1
by mbp at sourcefrog
import from baz patch-364 |
13 |
# You should have received a copy of the GNU General Public License
|
14 |
# along with this program; if not, write to the Free Software
|
|
4183.7.1
by Sabin Iacob
update FSF mailing address |
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
1
by mbp at sourcefrog
import from baz patch-364 |
16 |
|
1335
by Martin Pool
doc |
17 |
# TODO: Check ancestries are correct for every revision: includes
|
18 |
# every committed so far, and in a reasonable order.
|
|
19 |
||
1347
by Martin Pool
- refactor check code into method object |
20 |
# TODO: Also check non-mainline revisions mentioned as parents.
|
21 |
||
22 |
# TODO: Check for extra files in the control directory.
|
|
23 |
||
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
24 |
# TODO: Check revision, inventory and entry objects have all
|
1348
by Martin Pool
- more refactoring of check code |
25 |
# required fields.
|
26 |
||
1185.16.101
by mbp at sourcefrog
todo |
27 |
# TODO: Get every revision in the revision-store even if they're not
|
28 |
# referenced by history and make sure they're all valid.
|
|
1347
by Martin Pool
- refactor check code into method object |
29 |
|
1616.1.5
by Martin Pool
Cleanup and document some check code |
30 |
# TODO: Perhaps have a way to record errors other than by raising exceptions;
|
31 |
# would perhaps be enough to accumulate exception objects in a list without
|
|
32 |
# raising them. If there's more than one exception it'd be good to see them
|
|
33 |
# all.
|
|
34 |
||
4332.3.2
by Robert Collins
Extract repository access in WorkingTree._check to be data driven, adding a new _get_check_refs method to support this. |
35 |
"""Checking of bzr objects.
|
36 |
||
37 |
check_refs is a concept used for optimising check. Objects that depend on other
|
|
38 |
objects (e.g. tree on repository) can list the objects they would be requesting
|
|
39 |
so that when the dependent object is checked, matches can be pulled out and
|
|
40 |
evaluated in-line rather than re-reading the same data many times.
|
|
41 |
check_refs are tuples (kind, value). Currently defined kinds are:
|
|
4332.3.5
by Robert Collins
Add Branch._get_check_refs. |
42 |
* 'trees', where value is a revid and the looked up objects are revision trees.
|
43 |
* 'lefthand-distance', where value is a revid and the looked up objects are the
|
|
44 |
distance along the lefthand path to NULL for that revid.
|
|
45 |
* 'revision-existence', where value is a revid, and the result is True or False
|
|
46 |
indicating that the revision was found/not found.
|
|
4332.3.2
by Robert Collins
Extract repository access in WorkingTree._check to be data driven, adding a new _get_check_refs method to support this. |
47 |
"""
|
48 |
||
3015.3.8
by Daniel Watkins
Added _scan_for_branches. |
49 |
from bzrlib import errors, osutils |
2745.6.16
by Aaron Bentley
Update from review |
50 |
from bzrlib import repository as _mod_repository |
2745.6.47
by Andrew Bennetts
Move check_parents out of VersionedFile. |
51 |
from bzrlib import revision |
3015.3.2
by Daniel Watkins
Check.check now takes a path rather than a branch. |
52 |
from bzrlib.branch import Branch |
3015.3.40
by Daniel Watkins
Modified bzrlib.check.check_dwim to use bzrlib.bzrdir.BzrDir.open_containing_tree_branch_or_repository. |
53 |
from bzrlib.bzrdir import BzrDir |
1773.4.1
by Martin Pool
Add pyflakes makefile target; fix many warnings |
54 |
from bzrlib.errors import BzrCheckError |
3015.3.3
by Daniel Watkins
Added _check_repository. |
55 |
from bzrlib.repository import Repository |
4332.3.15
by Robert Collins
Keep an ancestors dict in check rather than recreating one multiple times. |
56 |
from bzrlib.revision import NULL_REVISION |
3015.3.59
by Daniel Watkins
Further tweaks as requested on-list. |
57 |
from bzrlib.symbol_versioning import deprecated_function, deprecated_in |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
58 |
from bzrlib.trace import note |
1104
by Martin Pool
- Add a simple UIFactory |
59 |
import bzrlib.ui |
3015.3.11
by Daniel Watkins
Move WT checking from builtins to check. |
60 |
from bzrlib.workingtree import WorkingTree |
1104
by Martin Pool
- Add a simple UIFactory |
61 |
|
1347
by Martin Pool
- refactor check code into method object |
62 |
class Check(object): |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
63 |
"""Check a repository"""
|
1449
by Robert Collins
teach check about ghosts |
64 |
|
1616.1.5
by Martin Pool
Cleanup and document some check code |
65 |
# The Check object interacts with InventoryEntry.check, etc.
|
66 |
||
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
67 |
def __init__(self, repository, check_repo=True): |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
68 |
self.repository = repository |
1383
by Martin Pool
- untabify only |
69 |
self.checked_rev_cnt = 0 |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
70 |
self.ghosts = set() |
1449
by Robert Collins
teach check about ghosts |
71 |
self.missing_parent_links = {} |
1348
by Martin Pool
- more refactoring of check code |
72 |
self.missing_inventory_sha_cnt = 0 |
73 |
self.missing_revision_cnt = 0 |
|
3350.6.4
by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores. |
74 |
self.checked_weaves = set() |
2988.1.8
by Robert Collins
Change check and reconcile to use the new _generate_text_key_index rather |
75 |
self.unreferenced_versions = set() |
2745.6.33
by Andrew Bennetts
Add VersionedFile.check_parents, and use it instead of find_bad_ancestors in reconcile. |
76 |
self.inconsistent_parents = [] |
4145.2.1
by Ian Clatworthy
faster check |
77 |
self.rich_roots = repository.supports_rich_root() |
78 |
self.text_key_references = {} |
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
79 |
self.check_repo = check_repo |
80 |
self.other_results = [] |
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
81 |
# Plain text lines to include in the report
|
82 |
self._report_items = [] |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
83 |
# Keys we are looking for; may be large and need spilling to disk.
|
84 |
# key->(type(revision/inventory/text/signature/map), sha1, first-referer)
|
|
85 |
self.pending_keys = {} |
|
4332.3.15
by Robert Collins
Keep an ancestors dict in check rather than recreating one multiple times. |
86 |
# Ancestors map for all of revisions being checked; while large helper
|
87 |
# functions we call would create it anyway, so better to have once and
|
|
88 |
# keep.
|
|
89 |
self.ancestors = {} |
|
676
by Martin Pool
- lock branch while checking |
90 |
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
91 |
def check(self, callback_refs=None, check_repo=True): |
92 |
if callback_refs is None: |
|
93 |
callback_refs = {} |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
94 |
self.repository.lock_read() |
1594.1.3
by Robert Collins
Fixup pb usage to use nested_progress_bar. |
95 |
self.progress = bzrlib.ui.ui_factory.nested_progress_bar() |
1449
by Robert Collins
teach check about ghosts |
96 |
try: |
4332.3.20
by Robert Collins
Cleanup progress reporting for check to go left to right once and only once. |
97 |
self.progress.update('check', 0, 4) |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
98 |
if self.check_repo: |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
99 |
self.progress.update('checking revisions', 0) |
100 |
self.check_revisions() |
|
4332.3.29
by Robert Collins
Better descriptions. |
101 |
self.progress.update('checking commit contents', 1) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
102 |
self.repository._check_inventories(self) |
4332.3.29
by Robert Collins
Better descriptions. |
103 |
self.progress.update('checking file graphs', 2) |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
104 |
# check_weaves is done after the revision scan so that
|
105 |
# revision index is known to be valid.
|
|
106 |
self.check_weaves() |
|
4332.3.20
by Robert Collins
Cleanup progress reporting for check to go left to right once and only once. |
107 |
self.progress.update('checking branches and trees', 3) |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
108 |
if callback_refs: |
109 |
repo = self.repository |
|
110 |
# calculate all refs, and callback the objects requesting them.
|
|
111 |
refs = {} |
|
112 |
wanting_items = set() |
|
113 |
# Current crude version calculates everything and calls
|
|
114 |
# everything at once. Doing a queue and popping as things are
|
|
115 |
# satisfied would be cheaper on memory [but few people have
|
|
116 |
# huge numbers of working trees today. TODO: fix before
|
|
117 |
# landing].
|
|
118 |
distances = set() |
|
119 |
existences = set() |
|
120 |
for ref, wantlist in callback_refs.iteritems(): |
|
121 |
wanting_items.update(wantlist) |
|
122 |
kind, value = ref |
|
123 |
if kind == 'trees': |
|
124 |
refs[ref] = repo.revision_tree(value) |
|
125 |
elif kind == 'lefthand-distance': |
|
126 |
distances.add(value) |
|
127 |
elif kind == 'revision-existence': |
|
128 |
existences.add(value) |
|
129 |
else: |
|
130 |
raise AssertionError( |
|
131 |
'unknown ref kind for ref %s' % ref) |
|
132 |
node_distances = repo.get_graph().find_lefthand_distances(distances) |
|
133 |
for key, distance in node_distances.iteritems(): |
|
134 |
refs[('lefthand-distance', key)] = distance |
|
135 |
if key in existences and distance > 0: |
|
136 |
refs[('revision-existence', key)] = True |
|
137 |
existences.remove(key) |
|
138 |
parent_map = repo.get_graph().get_parent_map(existences) |
|
139 |
for key in parent_map: |
|
140 |
refs[('revision-existence', key)] = True |
|
141 |
existences.remove(key) |
|
142 |
for key in existences: |
|
143 |
refs[('revision-existence', key)] = False |
|
144 |
for item in wanting_items: |
|
145 |
if isinstance(item, WorkingTree): |
|
146 |
item._check(refs) |
|
147 |
if isinstance(item, Branch): |
|
148 |
self.other_results.append(item.check(refs)) |
|
1185.35.34
by Aaron Bentley
Made bzr check for stored revisions missing from ancestry |
149 |
finally: |
1594.1.3
by Robert Collins
Fixup pb usage to use nested_progress_bar. |
150 |
self.progress.finished() |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
151 |
self.repository.unlock() |
1449
by Robert Collins
teach check about ghosts |
152 |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
153 |
def _check_revisions(self, revisions_iterator): |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
154 |
"""Check revision objects by decorating a generator.
|
155 |
||
156 |
:param revisions_iterator: An iterator of(revid, Revision-or-None).
|
|
157 |
:return: A generator of the contents of revisions_iterator.
|
|
158 |
"""
|
|
159 |
self.planned_revisions = set() |
|
160 |
for revid, revision in revisions_iterator: |
|
161 |
yield revid, revision |
|
162 |
self._check_one_rev(revid, revision) |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
163 |
# Flatten the revisions we found to guarantee consistent later
|
164 |
# iteration.
|
|
4332.3.21
by Robert Collins
Clearer code. |
165 |
self.planned_revisions = list(self.planned_revisions) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
166 |
# TODO: extract digital signatures as items to callback on too.
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
167 |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
168 |
def check_revisions(self): |
169 |
"""Scan revisions, checking data directly available as we go."""
|
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
170 |
revision_iterator = self.repository._iter_revisions(None) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
171 |
revision_iterator = self._check_revisions(revision_iterator) |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
172 |
# We read the all revisions here:
|
173 |
# - doing this allows later code to depend on the revision index.
|
|
174 |
# - we can fill out existence flags at this point
|
|
175 |
# - we can read the revision inventory sha at this point
|
|
176 |
# - we can check properties and serialisers etc.
|
|
2819.2.4
by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository. |
177 |
if not self.repository.revision_graph_can_have_wrong_parents(): |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
178 |
# The check against the index isn't needed.
|
2819.2.3
by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph. |
179 |
self.revs_with_bad_parents_in_index = None |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
180 |
for thing in revision_iterator: |
181 |
pass
|
|
182 |
else: |
|
183 |
bad_revisions = self.repository._find_inconsistent_revision_parents( |
|
184 |
revision_iterator) |
|
185 |
self.revs_with_bad_parents_in_index = list(bad_revisions) |
|
2819.2.3
by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph. |
186 |
|
1449
by Robert Collins
teach check about ghosts |
187 |
def report_results(self, verbose): |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
188 |
if self.check_repo: |
189 |
self._report_repo_results(verbose) |
|
190 |
for result in self.other_results: |
|
191 |
result.report_results(verbose) |
|
192 |
||
193 |
def _report_repo_results(self, verbose): |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
194 |
note('checked repository %s format %s', |
195 |
self.repository.bzrdir.root_transport, |
|
196 |
self.repository._format) |
|
1365
by Martin Pool
- try to avoid checking texts repeatedly |
197 |
note('%6d revisions', self.checked_rev_cnt) |
2745.6.47
by Andrew Bennetts
Move check_parents out of VersionedFile. |
198 |
note('%6d file-ids', len(self.checked_weaves)) |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
199 |
if verbose: |
200 |
note('%6d unreferenced text versions', |
|
201 |
len(self.unreferenced_versions)) |
|
202 |
if verbose and len(self.unreferenced_versions): |
|
203 |
for file_id, revision_id in self.unreferenced_versions: |
|
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
204 |
note('unreferenced version: {%s} in %s', revision_id, |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
205 |
file_id) |
1348
by Martin Pool
- more refactoring of check code |
206 |
if self.missing_inventory_sha_cnt: |
1449
by Robert Collins
teach check about ghosts |
207 |
note('%6d revisions are missing inventory_sha1', |
1383
by Martin Pool
- untabify only |
208 |
self.missing_inventory_sha_cnt) |
1348
by Martin Pool
- more refactoring of check code |
209 |
if self.missing_revision_cnt: |
1449
by Robert Collins
teach check about ghosts |
210 |
note('%6d revisions are mentioned but not present', |
1383
by Martin Pool
- untabify only |
211 |
self.missing_revision_cnt) |
1449
by Robert Collins
teach check about ghosts |
212 |
if len(self.ghosts): |
213 |
note('%6d ghost revisions', len(self.ghosts)) |
|
214 |
if verbose: |
|
215 |
for ghost in self.ghosts: |
|
216 |
note(' %s', ghost) |
|
217 |
if len(self.missing_parent_links): |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
218 |
note('%6d revisions missing parents in ancestry', |
1449
by Robert Collins
teach check about ghosts |
219 |
len(self.missing_parent_links)) |
220 |
if verbose: |
|
221 |
for link, linkers in self.missing_parent_links.items(): |
|
222 |
note(' %s should be in the ancestry for:', link) |
|
223 |
for linker in linkers: |
|
224 |
note(' * %s', linker) |
|
2745.6.39
by Andrew Bennetts
Use scenario in test_check too, and make check actually report inconsistent parents to the end user. |
225 |
if len(self.inconsistent_parents): |
226 |
note('%6d inconsistent parents', len(self.inconsistent_parents)) |
|
227 |
if verbose: |
|
228 |
for info in self.inconsistent_parents: |
|
229 |
revision_id, file_id, found_parents, correct_parents = info |
|
230 |
note(' * %s version %s has parents %r ' |
|
231 |
'but should have %r' |
|
232 |
% (file_id, revision_id, found_parents, |
|
233 |
correct_parents)) |
|
2819.2.3
by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph. |
234 |
if self.revs_with_bad_parents_in_index: |
235 |
note('%6d revisions have incorrect parents in the revision index', |
|
236 |
len(self.revs_with_bad_parents_in_index)) |
|
237 |
if verbose: |
|
238 |
for item in self.revs_with_bad_parents_in_index: |
|
239 |
revision_id, index_parents, actual_parents = item |
|
240 |
note( |
|
241 |
' %s has wrong parents in index: ' |
|
242 |
'%r should be %r', |
|
243 |
revision_id, index_parents, actual_parents) |
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
244 |
for item in self._report_items: |
245 |
note(item) |
|
246 |
||
247 |
def _check_one_rev(self, rev_id, rev): |
|
248 |
"""Cross-check one revision.
|
|
249 |
||
250 |
:param rev_id: A revision id to check.
|
|
251 |
:param rev: A revision or None to indicate a missing revision.
|
|
1383
by Martin Pool
- untabify only |
252 |
"""
|
253 |
if rev.revision_id != rev_id: |
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
254 |
self._report_items.append( |
255 |
'Mismatched internal revid {%s} and index revid {%s}' % ( |
|
256 |
rev.revision_id, rev_id)) |
|
257 |
rev_id = rev.revision_id |
|
258 |
# Check this revision tree etc, and count as seen when we encounter a
|
|
259 |
# reference to it.
|
|
260 |
self.planned_revisions.add(rev_id) |
|
261 |
# It is not a ghost
|
|
262 |
self.ghosts.discard(rev_id) |
|
263 |
# Count all parents as ghosts if we haven't seen them yet.
|
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
264 |
for parent in rev.parent_ids: |
265 |
if not parent in self.planned_revisions: |
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
266 |
self.ghosts.add(parent) |
267 |
||
4332.3.15
by Robert Collins
Keep an ancestors dict in check rather than recreating one multiple times. |
268 |
self.ancestors[rev_id] = tuple(rev.parent_ids) or (NULL_REVISION,) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
269 |
self.add_pending_item(rev_id, ('inventories', rev_id), 'inventory', |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
270 |
rev.inventory_sha1) |
1362
by Martin Pool
- keep track of number of checked revisions |
271 |
self.checked_rev_cnt += 1 |
1349
by Martin Pool
- more refactoring of check code |
272 |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
273 |
def add_pending_item(self, referer, key, kind, sha1): |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
274 |
"""Add a reference to a sha1 to be cross checked against a key.
|
275 |
||
276 |
:param referer: The referer that expects key to have sha1.
|
|
277 |
:param key: A storage key e.g. ('texts', 'foo@bar-20040504-1234')
|
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
278 |
:param kind: revision/inventory/text/map/signature
|
279 |
:param sha1: A hex sha1 or None if no sha1 is known.
|
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
280 |
"""
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
281 |
existing = self.pending_keys.get(key) |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
282 |
if existing: |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
283 |
if sha1 != existing[1]: |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
284 |
self._report_items.append('Multiple expected sha1s for %s. {%s}' |
285 |
' expects {%s}, {%s} expects {%s}', ( |
|
286 |
key, referer, sha1, existing[1], existing[0])) |
|
287 |
else: |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
288 |
self.pending_keys[key] = (kind, sha1, referer) |
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
289 |
|
1185.50.28
by John Arbash Meinel
Lots of updates for 'bzr check' |
290 |
def check_weaves(self): |
291 |
"""Check all the weaves we can get our hands on.
|
|
292 |
"""
|
|
293 |
weave_ids = [] |
|
4332.3.20
by Robert Collins
Cleanup progress reporting for check to go left to right once and only once. |
294 |
storebar = bzrlib.ui.ui_factory.nested_progress_bar() |
295 |
try: |
|
296 |
self._check_weaves(storebar) |
|
297 |
finally: |
|
298 |
storebar.finished() |
|
299 |
||
300 |
def _check_weaves(self, storebar): |
|
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
301 |
storebar.update('text-index', 0, 2) |
302 |
if self.repository._format.fast_deltas: |
|
303 |
# We haven't considered every fileid instance so far.
|
|
4332.3.30
by Robert Collins
Fix check_weaves. |
304 |
weave_checker = self.repository._get_versioned_file_checker( |
305 |
ancestors=self.ancestors) |
|
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
306 |
else: |
4332.3.30
by Robert Collins
Fix check_weaves. |
307 |
weave_checker = self.repository._get_versioned_file_checker( |
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
308 |
text_key_references=self.text_key_references, |
4332.3.30
by Robert Collins
Fix check_weaves. |
309 |
ancestors=self.ancestors) |
310 |
storebar.update('file-graph', 1) |
|
311 |
result = weave_checker.check_file_version_parents( |
|
312 |
self.repository.texts) |
|
3350.6.4
by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores. |
313 |
self.checked_weaves = weave_checker.file_ids |
314 |
bad_parents, unused_versions = result |
|
315 |
bad_parents = bad_parents.items() |
|
316 |
for text_key, (stored_parents, correct_parents) in bad_parents: |
|
317 |
# XXX not ready for id join/split operations.
|
|
318 |
weave_id = text_key[0] |
|
319 |
revision_id = text_key[-1] |
|
320 |
weave_parents = tuple([parent[-1] for parent in stored_parents]) |
|
321 |
correct_parents = tuple([parent[-1] for parent in correct_parents]) |
|
322 |
self.inconsistent_parents.append( |
|
323 |
(revision_id, weave_id, weave_parents, correct_parents)) |
|
324 |
self.unreferenced_versions.update(unused_versions) |
|
1185.50.28
by John Arbash Meinel
Lots of updates for 'bzr check' |
325 |
|
4145.2.1
by Ian Clatworthy
faster check |
326 |
def _add_entry_to_text_key_references(self, inv, entry): |
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
327 |
if not self.rich_roots and entry.name == '': |
4145.2.1
by Ian Clatworthy
faster check |
328 |
return
|
329 |
key = (entry.file_id, entry.revision) |
|
330 |
self.text_key_references.setdefault(key, False) |
|
331 |
if entry.revision == inv.revision_id: |
|
332 |
self.text_key_references[key] = True |
|
1349
by Martin Pool
- more refactoring of check code |
333 |
|
1347
by Martin Pool
- refactor check code into method object |
334 |
|
3015.3.59
by Daniel Watkins
Further tweaks as requested on-list. |
335 |
@deprecated_function(deprecated_in((1,6,0))) |
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
336 |
def check(branch, verbose): |
337 |
"""Run consistency checks on a branch.
|
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
338 |
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
339 |
Results are reported through logging.
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
340 |
|
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
341 |
Deprecated in 1.6. Please use check_dwim instead.
|
3015.3.37
by Daniel Watkins
Added deprecation comment to docstring. |
342 |
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
343 |
:raise BzrCheckError: if there's a consistency error.
|
344 |
"""
|
|
345 |
check_branch(branch, verbose) |
|
346 |
||
347 |
||
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
348 |
@deprecated_function(deprecated_in((1,16,0))) |
3015.3.7
by Daniel Watkins
Fixed failing tests. |
349 |
def check_branch(branch, verbose): |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
350 |
"""Run consistency checks on a branch.
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
351 |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
352 |
Results are reported through logging.
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
353 |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
354 |
:raise BzrCheckError: if there's a consistency error.
|
355 |
"""
|
|
356 |
branch.lock_read() |
|
357 |
try: |
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
358 |
needed_refs = {} |
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] |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
363 |
finally: |
364 |
branch.unlock() |
|
365 |
branch_result.report_results(verbose) |
|
2745.6.47
by Andrew Bennetts
Move check_parents out of VersionedFile. |
366 |
|
367 |
||
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
368 |
def scan_branch(branch, needed_refs, to_unlock): |
369 |
"""Scan a branch for refs.
|
|
370 |
||
371 |
:param branch: The branch to schedule for checking.
|
|
372 |
:param needed_refs: Refs we are accumulating.
|
|
373 |
:param to_unlock: The unlock list accumulating.
|
|
374 |
"""
|
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
375 |
note("Checking branch at '%s'." % (branch.base,)) |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
376 |
branch.lock_read() |
377 |
to_unlock.append(branch) |
|
378 |
branch_refs = branch._get_check_refs() |
|
379 |
for ref in branch_refs: |
|
380 |
reflist = needed_refs.setdefault(ref, []) |
|
381 |
reflist.append(branch) |
|
382 |
||
383 |
||
384 |
def scan_tree(base_tree, tree, needed_refs, to_unlock): |
|
385 |
"""Scan a tree for refs.
|
|
386 |
||
387 |
:param base_tree: The original tree check opened, used to detect duplicate
|
|
388 |
tree checks.
|
|
389 |
:param tree: The tree to schedule for checking.
|
|
390 |
:param needed_refs: Refs we are accumulating.
|
|
391 |
:param to_unlock: The unlock list accumulating.
|
|
392 |
"""
|
|
393 |
if base_tree is not None and tree.basedir == base_tree.basedir: |
|
394 |
return
|
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
395 |
note("Checking working tree at '%s'." % (tree.basedir,)) |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
396 |
tree.lock_read() |
397 |
to_unlock.append(tree) |
|
398 |
tree_refs = tree._get_check_refs() |
|
399 |
for ref in tree_refs: |
|
400 |
reflist = needed_refs.setdefault(ref, []) |
|
401 |
reflist.append(tree) |
|
402 |
||
403 |
||
3015.4.5
by Daniel Watkins
Each option selects only the specific thing to be checked. |
404 |
def check_dwim(path, verbose, do_branch=False, do_repo=False, do_tree=False): |
4332.3.35
by Robert Collins
Fix failing tests. |
405 |
"""Check multiple objects.
|
406 |
||
407 |
If errors occur they are accumulated and reported as far as possible, and
|
|
408 |
an exception raised at the end of the process.
|
|
409 |
"""
|
|
3015.4.16
by Daniel Watkins
Added implementation of error reporting when objects are missing. |
410 |
try: |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
411 |
base_tree, branch, repo, relpath = \ |
3015.4.11
by Daniel Watkins
Fixed long line. |
412 |
BzrDir.open_containing_tree_branch_or_repository(path) |
3015.4.16
by Daniel Watkins
Added implementation of error reporting when objects are missing. |
413 |
except errors.NotBranchError: |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
414 |
base_tree = branch = repo = None |
3015.3.23
by Daniel Watkins
Abstracted discovery of elements away. |
415 |
|
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
416 |
to_unlock = [] |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
417 |
needed_refs= {} |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
418 |
try: |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
419 |
if base_tree is not None: |
420 |
# If the tree is a lightweight checkout we won't see it in
|
|
421 |
# repo.find_branches - add now.
|
|
422 |
if do_tree: |
|
423 |
scan_tree(None, base_tree, needed_refs, to_unlock) |
|
424 |
branch = base_tree.branch |
|
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
425 |
if branch is not None: |
426 |
# We have a branch
|
|
427 |
if repo is None: |
|
428 |
# The branch is in a shared repository
|
|
429 |
repo = branch.repository |
|
430 |
if repo is not None: |
|
431 |
repo.lock_read() |
|
432 |
to_unlock.append(repo) |
|
433 |
branches = repo.find_branches(using=True) |
|
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
434 |
saw_tree = False |
435 |
if do_branch or do_tree: |
|
436 |
for branch in branches: |
|
437 |
if do_tree: |
|
438 |
try: |
|
439 |
tree = branch.bzrdir.open_workingtree() |
|
440 |
saw_tree = True |
|
441 |
except (errors.NotLocalUrl, errors.NoWorkingTree): |
|
442 |
pass
|
|
443 |
else: |
|
444 |
scan_tree(base_tree, tree, needed_refs, to_unlock) |
|
445 |
if do_branch: |
|
446 |
scan_branch(branch, needed_refs, to_unlock) |
|
447 |
if do_branch and not branches: |
|
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
448 |
note("No branch found at specified location.") |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
449 |
if do_tree and base_tree is None and not saw_tree: |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
450 |
note("No working tree found at specified location.") |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
451 |
if do_repo or do_branch or do_tree: |
452 |
if do_repo: |
|
453 |
note("Checking repository at '%s'." |
|
454 |
% (repo.bzrdir.root_transport.base,)) |
|
455 |
result = repo.check(None, callback_refs=needed_refs, |
|
456 |
check_repo=do_repo) |
|
3015.4.3
by Daniel Watkins
Implemented CLI options. |
457 |
result.report_results(verbose) |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
458 |
else: |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
459 |
if do_tree: |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
460 |
note("No working tree found at specified location.") |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
461 |
if do_branch: |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
462 |
note("No branch found at specified location.") |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
463 |
if do_repo: |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
464 |
note("No repository found at specified location.") |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
465 |
finally: |
466 |
for thing in to_unlock: |
|
467 |
thing.unlock() |