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