25
25
# TODO: Check revision, inventory and entry objects have all
28
# TODO: Get every revision in the revision-store even if they're not
29
# referenced by history and make sure they're all valid.
32
30
from bzrlib.trace import note, warning
34
32
from bzrlib.trace import mutter
35
33
from bzrlib.errors import BzrCheckError, NoSuchRevision
36
34
from bzrlib.inventory import ROOT_ID
35
from bzrlib.branch import gen_root_id
39
38
class Check(object):
55
54
self.branch.lock_read()
56
self.progress = bzrlib.ui.ui_factory.progress_bar()
58
self.progress.update('retrieving inventory', 0, 0)
59
# do not put in init, as it should be done with progess,
60
# and inside the lock.
61
self.inventory_weave = self.branch._get_inventory_weave()
62
56
self.history = self.branch.revision_history()
63
57
if not len(self.history):
64
58
# nothing to see here
60
self.planned_revisions = self.branch.get_ancestry(self.history[-1])
61
self.planned_revisions.remove(None)
64
self.progress = bzrlib.ui.ui_factory.progress_bar()
68
65
while revno < len(self.planned_revisions):
69
66
rev_id = self.planned_revisions[revno]
70
67
self.progress.update('checking revision', revno,
71
68
len(self.planned_revisions))
73
70
self.check_one_rev(rev_id)
76
73
self.branch.unlock()
78
def plan_revisions(self):
79
if not self.branch.revision_store.listable():
80
self.planned_revisions = self.branch.get_ancestry(self.history[-1])
81
self.planned_revisions.remove(None)
82
# FIXME progress bars should support this more nicely.
84
print ("Checking reachable history -"
85
" for a complete check use a local branch.")
88
self.planned_revisions = set(self.branch.revision_store)
89
inventoried = set(self.inventory_weave.names())
90
awol = self.planned_revisions - inventoried
92
raise BzrCheckError('Stored revisions missing from inventory'
93
'{%s}' % ','.join([f for f in awol]))
94
self.planned_revisions = list(self.planned_revisions)
96
75
def report_results(self, verbose):
97
76
note('checked branch %s format %d',
129
108
last_rev_id - the previous one on the mainline, if any.
132
# mutter(' revision {%s}', rev_id)
111
# mutter(' revision {%s}' % rev_id)
133
112
branch = self.branch
135
114
rev_history_position = self.history.index(rev_id)
150
129
# check the previous history entry is a parent of this entry
151
130
if rev.parent_ids:
131
if last_rev_id is None and rev_history_position is not None:
132
# what if the start is a ghost ? i.e. conceptually the
134
raise BzrCheckError("revision {%s} has %d parents, but is the "
135
"start of the branch"
136
% (rev_id, len(rev.parent_ids)))
152
137
if last_rev_id is not None:
153
138
for parent_id in rev.parent_ids:
154
139
if parent_id == last_rev_id:
162
147
missing_links = self.missing_parent_links.get(parent, [])
163
148
missing_links.append(rev_id)
164
149
self.missing_parent_links[parent] = missing_links
165
# list based so somewhat slow,
166
# TODO have a planned_revisions list and set.
150
# list based so slow, TODO have a planned_revisions list and set.
167
151
if self.branch.has_revision(parent):
168
152
missing_ancestry = self.branch.get_ancestry(parent)
169
153
for missing in missing_ancestry:
184
168
' value in revision {%s}' % rev_id)
186
170
missing_inventory_sha_cnt += 1
187
mutter("no inventory_sha1 on revision {%s}", rev_id)
171
mutter("no inventory_sha1 on revision {%s}" % rev_id)
188
172
self._check_revision_tree(rev_id)
189
173
self.checked_rev_cnt += 1