~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/dirstate.py

  • Committer: Martin Pool
  • Date: 2007-04-01 06:19:16 UTC
  • mfrom: (2323.5.20 0.15-integration)
  • mto: This revision was merged to the branch mainline in revision 2390.
  • Revision ID: mbp@sourcefrog.net-20070401061916-plpgsxdf8g7gll9o
Merge 0.15 final release back to trunk, including: recommend upgrades of old workingtrees, handle multiple http redirections, some dirstate fixes, 

Show diffs side-by-side

added added

removed removed

Lines of Context:
2167
2167
 
2168
2168
        This can be useful in debugging; it shouldn't be necessary in 
2169
2169
        normal code.
 
2170
 
 
2171
        This must be called with a lock held.
2170
2172
        """
 
2173
        # NOTE: This must always raise AssertionError not just assert,
 
2174
        # otherwise it may not behave properly under python -O
 
2175
        #
 
2176
        # TODO: All entries must have some content that's not 'a' or 'r',
 
2177
        # otherwise it could just be removed.
 
2178
        #
 
2179
        # TODO: All relocations must point directly to a real entry.
 
2180
        #
 
2181
        # TODO: No repeated keys.
 
2182
        #
 
2183
        # -- mbp 20070325
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" + \
2175
 
                    pformat(dirblocks)
 
2190
                    pformat(dirblocks))
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" + \
2179
 
                    pformat(dirblocks)
 
2195
                    pformat(dirblocks))
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
2191
2207
            # then by id.
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(
 
2211
                        "entry key for %r"
 
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)))
 
2218
 
 
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.
 
2224
        #
 
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
 
2246
                    if minikind == 'a':
 
2247
                        if previous_path is not None:
 
2248
                            raise AssertionError(
 
2249
                            "file %s is absent in row %r but also present " \
 
2250
                            "at %r"% \
 
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))
 
2258
                    else:
 
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))
 
2265
                else:
 
2266
                    if minikind == 'a':
 
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]
 
2272
                    else:
 
2273
                        this_tree_map[file_id] = this_path
2195
2274
 
2196
2275
    def _wipe_state(self):
2197
2276
        """Forget all state information about the dirstate."""
2292
2371
    # well within the noise margin
2293
2372
 
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]