15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
# TODO: Check ancestries are correct for every revision: includes
19
# every committed so far, and in a reasonable order.
22
from bzrlib.trace import note, warning
23
from bzrlib.osutils import rename, sha_string
19
25
def _update_store_entry(obj, obj_id, branch, store_name, store):
20
26
"""This is just a meta-function, which handles both revision entries
70
75
:param inv_id: The inventory id for this inventory
71
76
:param branch: The Branch where this entry will be stored.
73
_update_store_entry(inv, inv_id, branch,
74
'inventory-store', branch.inventory_store)
78
raise NotImplementedError("can't update existing inventory entry")
77
82
"""Run consistency checks on a branch.
81
86
TODO: Check for extra files in the control directory.
83
88
from bzrlib.trace import mutter
84
from bzrlib.errors import BzrCheckError
89
from bzrlib.errors import BzrCheckError, NoSuchRevision
85
90
from bzrlib.osutils import fingerprint_file
86
from bzrlib.progress import ProgressBar
87
91
from bzrlib.inventory import ROOT_ID
88
92
from bzrlib.branch import gen_root_id
93
pb = ProgressBar(show_spinner=True)
96
99
missing_inventory_sha_cnt = 0
97
100
missing_revision_sha_cnt = 0
101
missing_revision_cnt = 0
99
103
history = branch.revision_history()
101
105
revcount = len(history)
104
# for all texts checked, text_id -> sha1
107
checked_text_count = 0
109
progress = bzrlib.ui.ui_factory.progress_bar()
107
111
for rev_id in history:
109
pb.update('checking revision', revno, revcount)
110
mutter(' revision {%s}' % rev_id)
113
progress.update('checking revision', revno, revcount)
114
# mutter(' revision {%s}' % rev_id)
111
115
rev = branch.get_revision(rev_id)
112
116
if rev.revision_id != rev_id:
113
117
raise BzrCheckError('wrong internal revision id in revision {%s}'
116
120
# check the previous history entry is a parent of this entry
118
122
if last_rev_id is None:
119
123
raise BzrCheckError("revision {%s} has %d parents, but is the "
120
124
"start of the branch"
121
% (rev_id, len(rev.parents)))
122
for prr in rev.parents:
123
if prr.revision_id == last_rev_id:
125
% (rev_id, len(rev.parent_ids)))
126
for parent_id in rev.parent_ids:
127
if parent_id == last_rev_id:
126
130
raise BzrCheckError("previous revision {%s} not listed among "
127
131
"parents of {%s}"
128
132
% (last_rev_id, rev_id))
130
for prr in rev.parents:
131
if prr.revision_sha1 is None:
132
missing_revision_sha_cnt += 1
134
prid = prr.revision_id
135
actual_sha = branch.get_revision_sha1(prid)
136
if prr.revision_sha1 != actual_sha:
137
raise BzrCheckError("mismatched revision sha1 for "
138
"parent {%s} of {%s}: %s vs %s"
140
prr.revision_sha1, actual_sha))
141
133
elif last_rev_id:
142
raise BzrCheckError("revision {%s} has no parents listed but preceded "
134
raise BzrCheckError("revision {%s} has no parents listed "
135
"but preceded by {%s}"
144
136
% (rev_id, last_rev_id))
146
if rev.inventory_id != rev_id:
147
mismatch_inv_id.append(rev_id)
149
138
## TODO: Check all the required fields are present on the revision.
151
140
if rev.inventory_sha1:
152
inv_sha1 = branch.get_inventory_sha1(rev.inventory_id)
141
inv_sha1 = branch.get_inventory_sha1(rev_id)
153
142
if inv_sha1 != rev.inventory_sha1:
154
143
raise BzrCheckError('Inventory sha1 hash doesn\'t match'
155
144
' value in revision {%s}' % rev_id)
183
173
% (ie.parent_id, rev_id))
185
175
if ie.kind == 'file':
186
if ie.text_id in checked_texts:
187
fp = checked_texts[ie.text_id]
189
if not ie.text_id in branch.text_store:
190
raise BzrCheckError('text {%s} not in text_store' % ie.text_id)
192
tf = branch.text_store[ie.text_id]
193
fp = fingerprint_file(tf)
194
checked_texts[ie.text_id] = fp
196
if ie.text_size != fp['size']:
176
text = tree.get_file_text(file_id)
177
checked_text_count += 1
178
if ie.text_size != len(text):
197
179
raise BzrCheckError('text {%s} wrong size' % ie.text_id)
198
if ie.text_sha1 != fp['sha1']:
180
if ie.text_sha1 != sha_string(text):
199
181
raise BzrCheckError('text {%s} wrong sha1' % ie.text_id)
200
182
elif ie.kind == 'directory':
201
183
if ie.text_sha1 != None or ie.text_size != None or ie.text_id != None:
202
184
raise BzrCheckError('directory {%s} has text in revision {%s}'
203
185
% (file_id, rev_id))
206
188
for path, ie in inv.iter_entries():
207
189
if path in seen_names:
208
190
raise BzrCheckError('duplicated path %s '
209
191
'in inventory for revision {%s}'
210
192
% (path, rev_id))
211
seen_names[path] = True
193
seen_names[path] = True
212
194
last_rev_id = rev_id
219
print 'checked %d revisions, %d file texts' % (revcount, len(checked_texts))
201
note('checked %d revisions, %d file texts' % (revcount, checked_text_count))
221
203
if missing_inventory_sha_cnt:
222
print '%d revisions are missing inventory_sha1' % missing_inventory_sha_cnt
224
if missing_revision_sha_cnt:
225
print '%d parent links are missing revision_sha1' % missing_revision_sha_cnt
227
if (missing_inventory_sha_cnt
228
or missing_revision_sha_cnt):
229
print ' (use "bzr upgrade" to fix them)'
232
print '%d revisions have mismatched inventory ids:' % len(mismatch_inv_id)
233
for rev_id in mismatch_inv_id:
204
note('%d revisions are missing inventory_sha1' % missing_inventory_sha_cnt)
206
##if missing_revision_sha_cnt:
207
## note('%d parent links are missing revision_sha1' % missing_revision_sha_cnt)
209
if missing_revision_cnt:
210
note('%d revisions are mentioned but not present' % missing_revision_cnt)
212
if missing_revision_cnt:
213
print '%d revisions are mentioned but not present' % missing_revision_cnt
215
# stub this out for now because the main bzr branch has references
216
# to revisions that aren't present in the store -- mbp 20050804
217
# if (missing_inventory_sha_cnt
218
# or missing_revision_sha_cnt):
219
# print ' (use "bzr upgrade" to fix them)'