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 |
||
5121.2.4
by Jelmer Vernooij
Remove more unused imports. |
49 |
from bzrlib import errors |
3015.3.2
by Daniel Watkins
Check.check now takes a path rather than a branch. |
50 |
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. |
51 |
from bzrlib.bzrdir import BzrDir |
4332.3.15
by Robert Collins
Keep an ancestors dict in check rather than recreating one multiple times. |
52 |
from bzrlib.revision import NULL_REVISION |
3015.3.59
by Daniel Watkins
Further tweaks as requested on-list. |
53 |
from bzrlib.symbol_versioning import deprecated_function, deprecated_in |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
54 |
from bzrlib.trace import note |
1104
by Martin Pool
- Add a simple UIFactory |
55 |
import bzrlib.ui |
3015.3.11
by Daniel Watkins
Move WT checking from builtins to check. |
56 |
from bzrlib.workingtree import WorkingTree |
1104
by Martin Pool
- Add a simple UIFactory |
57 |
|
1347
by Martin Pool
- refactor check code into method object |
58 |
class Check(object): |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
59 |
"""Check a repository"""
|
1449
by Robert Collins
teach check about ghosts |
60 |
|
1616.1.5
by Martin Pool
Cleanup and document some check code |
61 |
# The Check object interacts with InventoryEntry.check, etc.
|
62 |
||
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
63 |
def __init__(self, repository, check_repo=True): |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
64 |
self.repository = repository |
1383
by Martin Pool
- untabify only |
65 |
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. |
66 |
self.ghosts = set() |
1449
by Robert Collins
teach check about ghosts |
67 |
self.missing_parent_links = {} |
1348
by Martin Pool
- more refactoring of check code |
68 |
self.missing_inventory_sha_cnt = 0 |
69 |
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. |
70 |
self.checked_weaves = set() |
2988.1.8
by Robert Collins
Change check and reconcile to use the new _generate_text_key_index rather |
71 |
self.unreferenced_versions = set() |
2745.6.33
by Andrew Bennetts
Add VersionedFile.check_parents, and use it instead of find_bad_ancestors in reconcile. |
72 |
self.inconsistent_parents = [] |
4145.2.1
by Ian Clatworthy
faster check |
73 |
self.rich_roots = repository.supports_rich_root() |
74 |
self.text_key_references = {} |
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
75 |
self.check_repo = check_repo |
76 |
self.other_results = [] |
|
4332.3.17
by Robert Collins
Check revisions as we cross check the revision index, rather than in a separate pass. |
77 |
# Plain text lines to include in the report
|
78 |
self._report_items = [] |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
79 |
# Keys we are looking for; may be large and need spilling to disk.
|
80 |
# key->(type(revision/inventory/text/signature/map), sha1, first-referer)
|
|
81 |
self.pending_keys = {} |
|
4332.3.15
by Robert Collins
Keep an ancestors dict in check rather than recreating one multiple times. |
82 |
# Ancestors map for all of revisions being checked; while large helper
|
83 |
# functions we call would create it anyway, so better to have once and
|
|
84 |
# keep.
|
|
85 |
self.ancestors = {} |
|
676
by Martin Pool
- lock branch while checking |
86 |
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
87 |
def check(self, callback_refs=None, check_repo=True): |
88 |
if callback_refs is None: |
|
89 |
callback_refs = {} |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
90 |
self.repository.lock_read() |
1594.1.3
by Robert Collins
Fixup pb usage to use nested_progress_bar. |
91 |
self.progress = bzrlib.ui.ui_factory.nested_progress_bar() |
1449
by Robert Collins
teach check about ghosts |
92 |
try: |
4332.3.20
by Robert Collins
Cleanup progress reporting for check to go left to right once and only once. |
93 |
self.progress.update('check', 0, 4) |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
94 |
if self.check_repo: |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
95 |
self.progress.update('checking revisions', 0) |
96 |
self.check_revisions() |
|
4332.3.29
by Robert Collins
Better descriptions. |
97 |
self.progress.update('checking commit contents', 1) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
98 |
self.repository._check_inventories(self) |
4332.3.29
by Robert Collins
Better descriptions. |
99 |
self.progress.update('checking file graphs', 2) |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
100 |
# check_weaves is done after the revision scan so that
|
101 |
# revision index is known to be valid.
|
|
102 |
self.check_weaves() |
|
4332.3.20
by Robert Collins
Cleanup progress reporting for check to go left to right once and only once. |
103 |
self.progress.update('checking branches and trees', 3) |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
104 |
if callback_refs: |
105 |
repo = self.repository |
|
106 |
# calculate all refs, and callback the objects requesting them.
|
|
107 |
refs = {} |
|
108 |
wanting_items = set() |
|
109 |
# Current crude version calculates everything and calls
|
|
110 |
# everything at once. Doing a queue and popping as things are
|
|
111 |
# satisfied would be cheaper on memory [but few people have
|
|
112 |
# huge numbers of working trees today. TODO: fix before
|
|
113 |
# landing].
|
|
114 |
distances = set() |
|
115 |
existences = set() |
|
116 |
for ref, wantlist in callback_refs.iteritems(): |
|
117 |
wanting_items.update(wantlist) |
|
118 |
kind, value = ref |
|
119 |
if kind == 'trees': |
|
120 |
refs[ref] = repo.revision_tree(value) |
|
121 |
elif kind == 'lefthand-distance': |
|
122 |
distances.add(value) |
|
123 |
elif kind == 'revision-existence': |
|
124 |
existences.add(value) |
|
125 |
else: |
|
126 |
raise AssertionError( |
|
127 |
'unknown ref kind for ref %s' % ref) |
|
128 |
node_distances = repo.get_graph().find_lefthand_distances(distances) |
|
129 |
for key, distance in node_distances.iteritems(): |
|
130 |
refs[('lefthand-distance', key)] = distance |
|
131 |
if key in existences and distance > 0: |
|
132 |
refs[('revision-existence', key)] = True |
|
133 |
existences.remove(key) |
|
134 |
parent_map = repo.get_graph().get_parent_map(existences) |
|
135 |
for key in parent_map: |
|
136 |
refs[('revision-existence', key)] = True |
|
137 |
existences.remove(key) |
|
138 |
for key in existences: |
|
139 |
refs[('revision-existence', key)] = False |
|
140 |
for item in wanting_items: |
|
141 |
if isinstance(item, WorkingTree): |
|
142 |
item._check(refs) |
|
143 |
if isinstance(item, Branch): |
|
144 |
self.other_results.append(item.check(refs)) |
|
1185.35.34
by Aaron Bentley
Made bzr check for stored revisions missing from ancestry |
145 |
finally: |
1594.1.3
by Robert Collins
Fixup pb usage to use nested_progress_bar. |
146 |
self.progress.finished() |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
147 |
self.repository.unlock() |
1449
by Robert Collins
teach check about ghosts |
148 |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
149 |
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. |
150 |
"""Check revision objects by decorating a generator.
|
151 |
||
152 |
:param revisions_iterator: An iterator of(revid, Revision-or-None).
|
|
153 |
:return: A generator of the contents of revisions_iterator.
|
|
154 |
"""
|
|
155 |
self.planned_revisions = set() |
|
156 |
for revid, revision in revisions_iterator: |
|
157 |
yield revid, revision |
|
158 |
self._check_one_rev(revid, revision) |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
159 |
# Flatten the revisions we found to guarantee consistent later
|
160 |
# iteration.
|
|
4332.3.21
by Robert Collins
Clearer code. |
161 |
self.planned_revisions = list(self.planned_revisions) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
162 |
# 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. |
163 |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
164 |
def check_revisions(self): |
165 |
"""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. |
166 |
revision_iterator = self.repository._iter_revisions(None) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
167 |
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. |
168 |
# We read the all revisions here:
|
169 |
# - doing this allows later code to depend on the revision index.
|
|
170 |
# - we can fill out existence flags at this point
|
|
171 |
# - we can read the revision inventory sha at this point
|
|
172 |
# - we can check properties and serialisers etc.
|
|
2819.2.4
by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository. |
173 |
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. |
174 |
# 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. |
175 |
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. |
176 |
for thing in revision_iterator: |
177 |
pass
|
|
178 |
else: |
|
179 |
bad_revisions = self.repository._find_inconsistent_revision_parents( |
|
180 |
revision_iterator) |
|
181 |
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. |
182 |
|
1449
by Robert Collins
teach check about ghosts |
183 |
def report_results(self, verbose): |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
184 |
if self.check_repo: |
185 |
self._report_repo_results(verbose) |
|
186 |
for result in self.other_results: |
|
187 |
result.report_results(verbose) |
|
188 |
||
189 |
def _report_repo_results(self, verbose): |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
190 |
note('checked repository %s format %s', |
5158.6.10
by Martin Pool
Update more code to use user_transport when it should |
191 |
self.repository.user_url, |
192 |
self.repository._format) |
|
1365
by Martin Pool
- try to avoid checking texts repeatedly |
193 |
note('%6d revisions', self.checked_rev_cnt) |
2745.6.47
by Andrew Bennetts
Move check_parents out of VersionedFile. |
194 |
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. |
195 |
if verbose: |
196 |
note('%6d unreferenced text versions', |
|
197 |
len(self.unreferenced_versions)) |
|
198 |
if verbose and len(self.unreferenced_versions): |
|
199 |
for file_id, revision_id in self.unreferenced_versions: |
|
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
200 |
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. |
201 |
file_id) |
1348
by Martin Pool
- more refactoring of check code |
202 |
if self.missing_inventory_sha_cnt: |
1449
by Robert Collins
teach check about ghosts |
203 |
note('%6d revisions are missing inventory_sha1', |
1383
by Martin Pool
- untabify only |
204 |
self.missing_inventory_sha_cnt) |
1348
by Martin Pool
- more refactoring of check code |
205 |
if self.missing_revision_cnt: |
1449
by Robert Collins
teach check about ghosts |
206 |
note('%6d revisions are mentioned but not present', |
1383
by Martin Pool
- untabify only |
207 |
self.missing_revision_cnt) |
1449
by Robert Collins
teach check about ghosts |
208 |
if len(self.ghosts): |
209 |
note('%6d ghost revisions', len(self.ghosts)) |
|
210 |
if verbose: |
|
211 |
for ghost in self.ghosts: |
|
212 |
note(' %s', ghost) |
|
213 |
if len(self.missing_parent_links): |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
214 |
note('%6d revisions missing parents in ancestry', |
1449
by Robert Collins
teach check about ghosts |
215 |
len(self.missing_parent_links)) |
216 |
if verbose: |
|
217 |
for link, linkers in self.missing_parent_links.items(): |
|
218 |
note(' %s should be in the ancestry for:', link) |
|
219 |
for linker in linkers: |
|
220 |
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. |
221 |
if len(self.inconsistent_parents): |
222 |
note('%6d inconsistent parents', len(self.inconsistent_parents)) |
|
223 |
if verbose: |
|
224 |
for info in self.inconsistent_parents: |
|
225 |
revision_id, file_id, found_parents, correct_parents = info |
|
226 |
note(' * %s version %s has parents %r ' |
|
227 |
'but should have %r' |
|
228 |
% (file_id, revision_id, found_parents, |
|
229 |
correct_parents)) |
|
2819.2.3
by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph. |
230 |
if self.revs_with_bad_parents_in_index: |
231 |
note('%6d revisions have incorrect parents in the revision index', |
|
232 |
len(self.revs_with_bad_parents_in_index)) |
|
233 |
if verbose: |
|
234 |
for item in self.revs_with_bad_parents_in_index: |
|
235 |
revision_id, index_parents, actual_parents = item |
|
236 |
note( |
|
237 |
' %s has wrong parents in index: ' |
|
238 |
'%r should be %r', |
|
239 |
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. |
240 |
for item in self._report_items: |
241 |
note(item) |
|
242 |
||
243 |
def _check_one_rev(self, rev_id, rev): |
|
244 |
"""Cross-check one revision.
|
|
245 |
||
246 |
:param rev_id: A revision id to check.
|
|
247 |
:param rev: A revision or None to indicate a missing revision.
|
|
1383
by Martin Pool
- untabify only |
248 |
"""
|
249 |
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. |
250 |
self._report_items.append( |
251 |
'Mismatched internal revid {%s} and index revid {%s}' % ( |
|
252 |
rev.revision_id, rev_id)) |
|
253 |
rev_id = rev.revision_id |
|
254 |
# Check this revision tree etc, and count as seen when we encounter a
|
|
255 |
# reference to it.
|
|
256 |
self.planned_revisions.add(rev_id) |
|
257 |
# It is not a ghost
|
|
258 |
self.ghosts.discard(rev_id) |
|
259 |
# 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 |
260 |
for parent in rev.parent_ids: |
261 |
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. |
262 |
self.ghosts.add(parent) |
263 |
||
4332.3.15
by Robert Collins
Keep an ancestors dict in check rather than recreating one multiple times. |
264 |
self.ancestors[rev_id] = tuple(rev.parent_ids) or (NULL_REVISION,) |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
265 |
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. |
266 |
rev.inventory_sha1) |
1362
by Martin Pool
- keep track of number of checked revisions |
267 |
self.checked_rev_cnt += 1 |
1349
by Martin Pool
- more refactoring of check code |
268 |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
269 |
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. |
270 |
"""Add a reference to a sha1 to be cross checked against a key.
|
271 |
||
272 |
:param referer: The referer that expects key to have sha1.
|
|
273 |
:param key: A storage key e.g. ('texts', 'foo@bar-20040504-1234')
|
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
274 |
:param kind: revision/inventory/text/map/signature
|
275 |
: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. |
276 |
"""
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
277 |
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. |
278 |
if existing: |
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
279 |
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. |
280 |
self._report_items.append('Multiple expected sha1s for %s. {%s}' |
281 |
' expects {%s}, {%s} expects {%s}', ( |
|
282 |
key, referer, sha1, existing[1], existing[0])) |
|
283 |
else: |
|
4332.3.25
by Robert Collins
Checkpointing refactoring of inventory/file checks. |
284 |
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. |
285 |
|
1185.50.28
by John Arbash Meinel
Lots of updates for 'bzr check' |
286 |
def check_weaves(self): |
287 |
"""Check all the weaves we can get our hands on.
|
|
288 |
"""
|
|
289 |
weave_ids = [] |
|
4332.3.20
by Robert Collins
Cleanup progress reporting for check to go left to right once and only once. |
290 |
storebar = bzrlib.ui.ui_factory.nested_progress_bar() |
291 |
try: |
|
292 |
self._check_weaves(storebar) |
|
293 |
finally: |
|
294 |
storebar.finished() |
|
295 |
||
296 |
def _check_weaves(self, storebar): |
|
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
297 |
storebar.update('text-index', 0, 2) |
298 |
if self.repository._format.fast_deltas: |
|
299 |
# We haven't considered every fileid instance so far.
|
|
4332.3.30
by Robert Collins
Fix check_weaves. |
300 |
weave_checker = self.repository._get_versioned_file_checker( |
301 |
ancestors=self.ancestors) |
|
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
302 |
else: |
4332.3.30
by Robert Collins
Fix check_weaves. |
303 |
weave_checker = self.repository._get_versioned_file_checker( |
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
304 |
text_key_references=self.text_key_references, |
4332.3.30
by Robert Collins
Fix check_weaves. |
305 |
ancestors=self.ancestors) |
306 |
storebar.update('file-graph', 1) |
|
307 |
result = weave_checker.check_file_version_parents( |
|
308 |
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. |
309 |
self.checked_weaves = weave_checker.file_ids |
310 |
bad_parents, unused_versions = result |
|
311 |
bad_parents = bad_parents.items() |
|
312 |
for text_key, (stored_parents, correct_parents) in bad_parents: |
|
313 |
# XXX not ready for id join/split operations.
|
|
314 |
weave_id = text_key[0] |
|
315 |
revision_id = text_key[-1] |
|
316 |
weave_parents = tuple([parent[-1] for parent in stored_parents]) |
|
317 |
correct_parents = tuple([parent[-1] for parent in correct_parents]) |
|
318 |
self.inconsistent_parents.append( |
|
319 |
(revision_id, weave_id, weave_parents, correct_parents)) |
|
320 |
self.unreferenced_versions.update(unused_versions) |
|
1185.50.28
by John Arbash Meinel
Lots of updates for 'bzr check' |
321 |
|
4145.2.1
by Ian Clatworthy
faster check |
322 |
def _add_entry_to_text_key_references(self, inv, entry): |
4332.3.28
by Robert Collins
Start checking file texts in a single pass. |
323 |
if not self.rich_roots and entry.name == '': |
4145.2.1
by Ian Clatworthy
faster check |
324 |
return
|
325 |
key = (entry.file_id, entry.revision) |
|
326 |
self.text_key_references.setdefault(key, False) |
|
327 |
if entry.revision == inv.revision_id: |
|
328 |
self.text_key_references[key] = True |
|
1349
by Martin Pool
- more refactoring of check code |
329 |
|
1347
by Martin Pool
- refactor check code into method object |
330 |
|
3015.3.59
by Daniel Watkins
Further tweaks as requested on-list. |
331 |
@deprecated_function(deprecated_in((1,6,0))) |
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
332 |
def check(branch, verbose): |
333 |
"""Run consistency checks on a branch.
|
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
334 |
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
335 |
Results are reported through logging.
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
336 |
|
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
337 |
Deprecated in 1.6. Please use check_dwim instead.
|
3015.3.37
by Daniel Watkins
Added deprecation comment to docstring. |
338 |
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
339 |
:raise BzrCheckError: if there's a consistency error.
|
340 |
"""
|
|
341 |
check_branch(branch, verbose) |
|
342 |
||
343 |
||
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
344 |
@deprecated_function(deprecated_in((1,16,0))) |
3015.3.7
by Daniel Watkins
Fixed failing tests. |
345 |
def check_branch(branch, verbose): |
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
346 |
"""Run consistency checks on a branch.
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
347 |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
348 |
Results are reported through logging.
|
3015.3.35
by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning. |
349 |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
350 |
:raise BzrCheckError: if there's a consistency error.
|
351 |
"""
|
|
352 |
branch.lock_read() |
|
353 |
try: |
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
354 |
needed_refs = {} |
355 |
for ref in branch._get_check_refs(): |
|
356 |
needed_refs.setdefault(ref, []).append(branch) |
|
357 |
result = branch.repository.check([branch.last_revision()], needed_refs) |
|
358 |
branch_result = result.other_results[0] |
|
1732.2.4
by Martin Pool
Split check into Branch.check and Repository.check |
359 |
finally: |
360 |
branch.unlock() |
|
361 |
branch_result.report_results(verbose) |
|
2745.6.47
by Andrew Bennetts
Move check_parents out of VersionedFile. |
362 |
|
363 |
||
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
364 |
def scan_branch(branch, needed_refs, to_unlock): |
365 |
"""Scan a branch for refs.
|
|
366 |
||
367 |
:param branch: The branch to schedule for checking.
|
|
368 |
:param needed_refs: Refs we are accumulating.
|
|
369 |
:param to_unlock: The unlock list accumulating.
|
|
370 |
"""
|
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
371 |
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. |
372 |
branch.lock_read() |
373 |
to_unlock.append(branch) |
|
374 |
branch_refs = branch._get_check_refs() |
|
375 |
for ref in branch_refs: |
|
376 |
reflist = needed_refs.setdefault(ref, []) |
|
377 |
reflist.append(branch) |
|
378 |
||
379 |
||
380 |
def scan_tree(base_tree, tree, needed_refs, to_unlock): |
|
381 |
"""Scan a tree for refs.
|
|
382 |
||
383 |
:param base_tree: The original tree check opened, used to detect duplicate
|
|
384 |
tree checks.
|
|
385 |
:param tree: The tree to schedule for checking.
|
|
386 |
:param needed_refs: Refs we are accumulating.
|
|
387 |
:param to_unlock: The unlock list accumulating.
|
|
388 |
"""
|
|
389 |
if base_tree is not None and tree.basedir == base_tree.basedir: |
|
390 |
return
|
|
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
391 |
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. |
392 |
tree.lock_read() |
393 |
to_unlock.append(tree) |
|
394 |
tree_refs = tree._get_check_refs() |
|
395 |
for ref in tree_refs: |
|
396 |
reflist = needed_refs.setdefault(ref, []) |
|
397 |
reflist.append(tree) |
|
398 |
||
399 |
||
3015.4.5
by Daniel Watkins
Each option selects only the specific thing to be checked. |
400 |
def check_dwim(path, verbose, do_branch=False, do_repo=False, do_tree=False): |
4332.3.35
by Robert Collins
Fix failing tests. |
401 |
"""Check multiple objects.
|
402 |
||
403 |
If errors occur they are accumulated and reported as far as possible, and
|
|
404 |
an exception raised at the end of the process.
|
|
405 |
"""
|
|
3015.4.16
by Daniel Watkins
Added implementation of error reporting when objects are missing. |
406 |
try: |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
407 |
base_tree, branch, repo, relpath = \ |
3015.4.11
by Daniel Watkins
Fixed long line. |
408 |
BzrDir.open_containing_tree_branch_or_repository(path) |
3015.4.16
by Daniel Watkins
Added implementation of error reporting when objects are missing. |
409 |
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. |
410 |
base_tree = branch = repo = None |
3015.3.23
by Daniel Watkins
Abstracted discovery of elements away. |
411 |
|
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
412 |
to_unlock = [] |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
413 |
needed_refs= {} |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
414 |
try: |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
415 |
if base_tree is not None: |
416 |
# If the tree is a lightweight checkout we won't see it in
|
|
417 |
# repo.find_branches - add now.
|
|
418 |
if do_tree: |
|
419 |
scan_tree(None, base_tree, needed_refs, to_unlock) |
|
420 |
branch = base_tree.branch |
|
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
421 |
if branch is not None: |
422 |
# We have a branch
|
|
423 |
if repo is None: |
|
424 |
# The branch is in a shared repository
|
|
425 |
repo = branch.repository |
|
426 |
if repo is not None: |
|
427 |
repo.lock_read() |
|
428 |
to_unlock.append(repo) |
|
429 |
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. |
430 |
saw_tree = False |
431 |
if do_branch or do_tree: |
|
432 |
for branch in branches: |
|
433 |
if do_tree: |
|
434 |
try: |
|
435 |
tree = branch.bzrdir.open_workingtree() |
|
436 |
saw_tree = True |
|
437 |
except (errors.NotLocalUrl, errors.NoWorkingTree): |
|
438 |
pass
|
|
439 |
else: |
|
440 |
scan_tree(base_tree, tree, needed_refs, to_unlock) |
|
441 |
if do_branch: |
|
442 |
scan_branch(branch, needed_refs, to_unlock) |
|
443 |
if do_branch and not branches: |
|
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
444 |
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. |
445 |
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 |
446 |
note("No working tree found at specified location.") |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
447 |
if do_repo or do_branch or do_tree: |
448 |
if do_repo: |
|
449 |
note("Checking repository at '%s'." |
|
5158.6.9
by Martin Pool
Simplify various code to use user_url |
450 |
% (repo.user_url,)) |
4332.3.11
by Robert Collins
Move tree and back callbacks into the repository check core. |
451 |
result = repo.check(None, callback_refs=needed_refs, |
452 |
check_repo=do_repo) |
|
3015.4.3
by Daniel Watkins
Implemented CLI options. |
453 |
result.report_results(verbose) |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
454 |
else: |
4332.3.10
by Robert Collins
Invert control of check so that trees and branches are checked by calling back into them. |
455 |
if do_tree: |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
456 |
note("No working tree found at specified location.") |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
457 |
if do_branch: |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
458 |
note("No branch found at specified location.") |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
459 |
if do_repo: |
4695.5.4
by Martin Pool
Remove uses of trace.log_error in check |
460 |
note("No repository found at specified location.") |
4332.3.9
by Robert Collins
Less lock thrashing in check.py. |
461 |
finally: |
462 |
for thing in to_unlock: |
|
463 |
thing.unlock() |