2168
2168
This can be useful in debugging; it shouldn't be necessary in
2171
This must be called with a lock held.
2173
# NOTE: This must always raise AssertionError not just assert,
2174
# otherwise it may not behave properly under python -O
2176
# TODO: All entries must have some content that's not 'a' or 'r',
2177
# otherwise it could just be removed.
2179
# TODO: All relocations must point directly to a real entry.
2181
# TODO: No repeated keys.
2171
2184
from pprint import pformat
2185
self._read_dirblocks_if_needed()
2172
2186
if len(self._dirblocks) > 0:
2173
assert self._dirblocks[0][0] == '', \
2187
if not self._dirblocks[0][0] == '':
2188
raise AssertionError(
2174
2189
"dirblocks don't start with root block:\n" + \
2176
2191
if len(self._dirblocks) > 1:
2177
assert self._dirblocks[1][0] == '', \
2192
if not self._dirblocks[1][0] == '':
2193
raise AssertionError(
2178
2194
"dirblocks missing root directory:\n" + \
2180
2196
# the dirblocks are sorted by their path components, name, and dir id
2181
2197
dir_names = [d[0].split('/')
2182
2198
for d in self._dirblocks[1:]]
2189
2205
for dirblock in self._dirblocks:
2190
2206
# within each dirblock, the entries are sorted by filename and
2192
assert dirblock[1] == sorted(dirblock[1]), \
2193
"dirblock for %r is not sorted:\n%s" % \
2194
(dirblock[0], pformat(dirblock))
2208
for entry in dirblock[1]:
2209
if dirblock[0] != entry[0][0]:
2210
raise AssertionError(
2212
"doesn't match directory name in\n%r" %
2213
(entry, pformat(dirblock)))
2214
if dirblock[1] != sorted(dirblock[1]):
2215
raise AssertionError(
2216
"dirblock for %r is not sorted:\n%s" % \
2217
(dirblock[0], pformat(dirblock)))
2219
# For each file id, for each tree: either
2220
# the file id is not present at all; all rows with that id in the
2221
# key have it marked as 'absent'
2222
# OR the file id is present under exactly one name; any other entries
2223
# that mention that id point to the correct name.
2225
# We check this with a dict per tree pointing either to the present
2226
# name, or None if absent.
2227
tree_count = self._num_present_parents() + 1
2228
id_path_maps = [dict() for i in range(tree_count)]
2229
# Make sure that all renamed entries point to the correct location.
2230
for entry in self._iter_entries():
2231
file_id = entry[0][2]
2232
this_path = osutils.pathjoin(entry[0][0], entry[0][1])
2233
if len(entry[1]) != tree_count:
2234
raise AssertionError(
2235
"wrong number of entry details for row\n%s" \
2236
",\nexpected %d" % \
2237
(pformat(entry), tree_count))
2238
for tree_index, tree_state in enumerate(entry[1]):
2239
this_tree_map = id_path_maps[tree_index]
2240
minikind = tree_state[0]
2241
# have we seen this id before in this column?
2242
if file_id in this_tree_map:
2243
previous_path = this_tree_map[file_id]
2244
# any later mention of this file must be consistent with
2245
# what was said before
2247
if previous_path is not None:
2248
raise AssertionError(
2249
"file %s is absent in row %r but also present " \
2251
(file_id, entry, previous_path))
2252
elif minikind == 'r':
2253
target_location = tree_state[1]
2254
if previous_path != target_location:
2255
raise AssertionError(
2256
"file %s relocation in row %r but also at %r" \
2257
% (file_id, entry, previous_path))
2259
# a file, directory, etc - may have been previously
2260
# pointed to by a relocation, which must point here
2261
if previous_path != this_path:
2262
raise AssertionError(
2263
"entry %r inconsistent with previous path %r" % \
2264
(entry, previous_path))
2267
# absent; should not occur anywhere else
2268
this_tree_map[file_id] = None
2269
elif minikind == 'r':
2270
# relocation, must occur at expected location
2271
this_tree_map[file_id] = tree_state[1]
2273
this_tree_map[file_id] = this_path
2196
2275
def _wipe_state(self):
2197
2276
"""Forget all state information about the dirstate."""
2292
2371
# well within the noise margin
2294
2373
# base64.encode always adds a final newline, so strip it off
2295
return _encode(_pack('>llllll'
2374
return _encode(_pack('>LLLLLL'
2296
2375
, st.st_size, int(st.st_mtime), int(st.st_ctime)
2297
, st.st_dev, st.st_ino, st.st_mode))[:-1]
2376
, st.st_dev, st.st_ino & 0xFFFFFFFF, st.st_mode))[:-1]