/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: Andrew Bennetts
  • Date: 2010-09-06 06:13:52 UTC
  • mto: (4634.158.5 2.0)
  • mto: This revision was merged to the branch mainline in revision 5419.
  • Revision ID: andrew.bennetts@canonical.com-20100906061352-ef2rw40pa5wte5oj
Add LockCorrupt error, and use it to provide nicer handling of unparseable lock/held/info files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
51
51
    )
52
52
from bzrlib.symbol_versioning import deprecated_in, deprecated_method
53
53
from bzrlib.trace import mutter
54
 
from bzrlib.static_tuple import StaticTuple
55
54
 
56
55
 
57
56
class InventoryEntry(object):
959
958
        descend(self.root, u'')
960
959
        return accum
961
960
 
962
 
    def path2id(self, relpath):
 
961
    def path2id(self, name):
963
962
        """Walk down through directories to return entry of last component.
964
963
 
965
 
        :param relpath: may be either a list of path components, or a single
966
 
            string, in which case it is automatically split.
 
964
        names may be either a list of path components, or a single
 
965
        string, in which case it is automatically split.
967
966
 
968
967
        This returns the entry of the last component in the path,
969
968
        which may be either a file or a directory.
970
969
 
971
970
        Returns None IFF the path is not found.
972
971
        """
973
 
        if isinstance(relpath, basestring):
974
 
            names = osutils.splitpath(relpath)
975
 
        else:
976
 
            names = relpath
 
972
        if isinstance(name, basestring):
 
973
            name = osutils.splitpath(name)
 
974
 
 
975
        # mutter("lookup path %r" % name)
977
976
 
978
977
        try:
979
978
            parent = self.root
982
981
            return None
983
982
        if parent is None:
984
983
            return None
985
 
        for f in names:
 
984
        for f in name:
986
985
            try:
987
986
                children = getattr(parent, 'children', None)
988
987
                if children is None:
1282
1281
    def add(self, entry):
1283
1282
        """Add entry to inventory.
1284
1283
 
1285
 
        To add  a file to a branch ready to be committed, use Branch.add,
1286
 
        which calls this.
1287
 
 
1288
1284
        :return: entry
1289
1285
        """
1290
1286
        if entry.file_id in self._byid:
1600
1596
        interesting.add(None) # this will auto-filter it in the loop
1601
1597
        remaining_parents.discard(None) 
1602
1598
        while remaining_parents:
 
1599
            if None in remaining_parents:
 
1600
                import pdb; pdb.set_trace()
1603
1601
            next_parents = set()
1604
1602
            for entry in self._getitems(remaining_parents):
1605
1603
                next_parents.add(entry.parent_id)
1614
1612
        while directories_to_expand:
1615
1613
            # Expand directories by looking in the
1616
1614
            # parent_id_basename_to_file_id map
1617
 
            keys = [StaticTuple(f,).intern() for f in directories_to_expand]
 
1615
            keys = [(f,) for f in directories_to_expand]
1618
1616
            directories_to_expand = set()
1619
1617
            items = self.parent_id_basename_to_file_id.iteritems(keys)
1620
1618
            next_file_ids = set([item[1] for item in items])
1677
1675
        # to filter out empty names because of non rich-root...
1678
1676
        sections = bytes.split('\n')
1679
1677
        kind, file_id = sections[0].split(': ')
1680
 
        return (sections[2], intern(file_id), intern(sections[3]))
 
1678
        return (sections[2], file_id, sections[3])
1681
1679
 
1682
1680
    def _bytes_to_entry(self, bytes):
1683
1681
        """Deserialise a serialised entry."""
1705
1703
            result.reference_revision = sections[4]
1706
1704
        else:
1707
1705
            raise ValueError("Not a serialised entry %r" % bytes)
1708
 
        result.file_id = intern(result.file_id)
1709
 
        result.revision = intern(sections[3])
 
1706
        result.revision = sections[3]
1710
1707
        if result.parent_id == '':
1711
1708
            result.parent_id = None
1712
1709
        self._fileid_to_entry_cache[result.file_id] = result
1810
1807
                        pass
1811
1808
                deletes.add(file_id)
1812
1809
            else:
1813
 
                new_key = StaticTuple(file_id,)
 
1810
                new_key = (file_id,)
1814
1811
                new_value = result._entry_to_bytes(entry)
1815
1812
                # Update caches. It's worth doing this whether
1816
1813
                # we're propagating the old caches or not.
1819
1816
            if old_path is None:
1820
1817
                old_key = None
1821
1818
            else:
1822
 
                old_key = StaticTuple(file_id,)
 
1819
                old_key = (file_id,)
1823
1820
                if self.id2path(file_id) != old_path:
1824
1821
                    raise errors.InconsistentDelta(old_path, file_id,
1825
1822
                        "Entry was at wrong other path %r." %
1826
1823
                        self.id2path(file_id))
1827
1824
                altered.add(file_id)
1828
 
            id_to_entry_delta.append(StaticTuple(old_key, new_key, new_value))
 
1825
            id_to_entry_delta.append((old_key, new_key, new_value))
1829
1826
            if result.parent_id_basename_to_file_id is not None:
1830
1827
                # parent_id, basename changes
1831
1828
                if old_path is None:
1918
1915
                raise errors.BzrError('Duplicate key in inventory: %r\n%r'
1919
1916
                                      % (key, bytes))
1920
1917
            info[key] = value
1921
 
        revision_id = intern(info['revision_id'])
1922
 
        root_id = intern(info['root_id'])
1923
 
        search_key_name = intern(info.get('search_key_name', 'plain'))
1924
 
        parent_id_basename_to_file_id = intern(info.get(
1925
 
            'parent_id_basename_to_file_id', None))
1926
 
        if not parent_id_basename_to_file_id.startswith('sha1:'):
1927
 
            raise ValueError('parent_id_basename_to_file_id should be a sha1'
1928
 
                             ' key not %r' % (parent_id_basename_to_file_id,))
 
1918
        revision_id = info['revision_id']
 
1919
        root_id = info['root_id']
 
1920
        search_key_name = info.get('search_key_name', 'plain')
 
1921
        parent_id_basename_to_file_id = info.get(
 
1922
            'parent_id_basename_to_file_id', None)
1929
1923
        id_to_entry = info['id_to_entry']
1930
 
        if not id_to_entry.startswith('sha1:'):
1931
 
            raise ValueError('id_to_entry should be a sha1'
1932
 
                             ' key not %r' % (id_to_entry,))
1933
1924
 
1934
1925
        result = CHKInventory(search_key_name)
1935
1926
        result.revision_id = revision_id
1938
1929
                            result._search_key_name)
1939
1930
        if parent_id_basename_to_file_id is not None:
1940
1931
            result.parent_id_basename_to_file_id = chk_map.CHKMap(
1941
 
                chk_store, StaticTuple(parent_id_basename_to_file_id,),
 
1932
                chk_store, (parent_id_basename_to_file_id,),
1942
1933
                search_key_func=search_key_func)
1943
1934
        else:
1944
1935
            result.parent_id_basename_to_file_id = None
1945
1936
 
1946
 
        result.id_to_entry = chk_map.CHKMap(chk_store,
1947
 
                                            StaticTuple(id_to_entry,),
 
1937
        result.id_to_entry = chk_map.CHKMap(chk_store, (id_to_entry,),
1948
1938
                                            search_key_func=search_key_func)
1949
1939
        if (result.revision_id,) != expected_revision_id:
1950
1940
            raise ValueError("Mismatched revision id and expected: %r, %r" %
1972
1962
        id_to_entry_dict = {}
1973
1963
        parent_id_basename_dict = {}
1974
1964
        for path, entry in inventory.iter_entries():
1975
 
            key = StaticTuple(entry.file_id,).intern()
1976
 
            id_to_entry_dict[key] = entry_to_bytes(entry)
 
1965
            id_to_entry_dict[(entry.file_id,)] = entry_to_bytes(entry)
1977
1966
            p_id_key = parent_id_basename_key(entry)
1978
1967
            parent_id_basename_dict[p_id_key] = entry.file_id
1979
1968
 
2002
1991
            parent_id = entry.parent_id
2003
1992
        else:
2004
1993
            parent_id = ''
2005
 
        return StaticTuple(parent_id, entry.name.encode('utf8')).intern()
 
1994
        return parent_id, entry.name.encode('utf8')
2006
1995
 
2007
1996
    def __getitem__(self, file_id):
2008
1997
        """map a single file_id -> InventoryEntry."""
2013
2002
            return result
2014
2003
        try:
2015
2004
            return self._bytes_to_entry(
2016
 
                self.id_to_entry.iteritems([StaticTuple(file_id,)]).next()[1])
 
2005
                self.id_to_entry.iteritems([(file_id,)]).next()[1])
2017
2006
        except StopIteration:
2018
2007
            # really we're passing an inventory, not a tree...
2019
2008
            raise errors.NoSuchId(self, file_id)
2032
2021
                remaining.append(file_id)
2033
2022
            else:
2034
2023
                result.append(entry)
2035
 
        file_keys = [StaticTuple(f,).intern() for f in remaining]
 
2024
        file_keys = [(f,) for f in remaining]
2036
2025
        for file_key, value in self.id_to_entry.iteritems(file_keys):
2037
2026
            entry = self._bytes_to_entry(value)
2038
2027
            result.append(entry)
2043
2032
        # Perhaps have an explicit 'contains' method on CHKMap ?
2044
2033
        if self._fileid_to_entry_cache.get(file_id, None) is not None:
2045
2034
            return True
2046
 
        return len(list(
2047
 
            self.id_to_entry.iteritems([StaticTuple(file_id,)]))) == 1
 
2035
        return len(list(self.id_to_entry.iteritems([(file_id,)]))) == 1
2048
2036
 
2049
2037
    def is_root(self, file_id):
2050
2038
        return file_id == self.root_id
2179
2167
            delta.append((old_path, new_path, file_id, entry))
2180
2168
        return delta
2181
2169
 
2182
 
    def path2id(self, relpath):
 
2170
    def path2id(self, name):
2183
2171
        """See CommonInventory.path2id()."""
2184
2172
        # TODO: perhaps support negative hits?
2185
 
        result = self._path_to_fileid_cache.get(relpath, None)
 
2173
        result = self._path_to_fileid_cache.get(name, None)
2186
2174
        if result is not None:
2187
2175
            return result
2188
 
        if isinstance(relpath, basestring):
2189
 
            names = osutils.splitpath(relpath)
 
2176
        if isinstance(name, basestring):
 
2177
            names = osutils.splitpath(name)
2190
2178
        else:
2191
 
            names = relpath
 
2179
            names = name
2192
2180
        current_id = self.root_id
2193
2181
        if current_id is None:
2194
2182
            return None
2195
2183
        parent_id_index = self.parent_id_basename_to_file_id
2196
 
        cur_path = None
2197
2184
        for basename in names:
2198
 
            if cur_path is None:
2199
 
                cur_path = basename
2200
 
            else:
2201
 
                cur_path = cur_path + '/' + basename
 
2185
            # TODO: Cache each path we figure out in this function.
2202
2186
            basename_utf8 = basename.encode('utf8')
2203
 
            file_id = self._path_to_fileid_cache.get(cur_path, None)
 
2187
            key_filter = [(current_id, basename_utf8)]
 
2188
            file_id = None
 
2189
            for (parent_id, name_utf8), file_id in parent_id_index.iteritems(
 
2190
                key_filter=key_filter):
 
2191
                if parent_id != current_id or name_utf8 != basename_utf8:
 
2192
                    raise errors.BzrError("corrupt inventory lookup! "
 
2193
                        "%r %r %r %r" % (parent_id, current_id, name_utf8,
 
2194
                        basename_utf8))
2204
2195
            if file_id is None:
2205
 
                key_filter = [StaticTuple(current_id, basename_utf8)]
2206
 
                items = parent_id_index.iteritems(key_filter)
2207
 
                for (parent_id, name_utf8), file_id in items:
2208
 
                    if parent_id != current_id or name_utf8 != basename_utf8:
2209
 
                        raise errors.BzrError("corrupt inventory lookup! "
2210
 
                            "%r %r %r %r" % (parent_id, current_id, name_utf8,
2211
 
                            basename_utf8))
2212
 
                if file_id is None:
2213
 
                    return None
2214
 
                else:
2215
 
                    self._path_to_fileid_cache[cur_path] = file_id
 
2196
                return None
2216
2197
            current_id = file_id
 
2198
        self._path_to_fileid_cache[name] = current_id
2217
2199
        return current_id
2218
2200
 
2219
2201
    def to_lines(self):
2224
2206
            lines.append('search_key_name: %s\n' % (self._search_key_name,))
2225
2207
            lines.append("root_id: %s\n" % self.root_id)
2226
2208
            lines.append('parent_id_basename_to_file_id: %s\n' %
2227
 
                (self.parent_id_basename_to_file_id.key()[0],))
 
2209
                self.parent_id_basename_to_file_id.key())
2228
2210
            lines.append("revision_id: %s\n" % self.revision_id)
2229
 
            lines.append("id_to_entry: %s\n" % (self.id_to_entry.key()[0],))
 
2211
            lines.append("id_to_entry: %s\n" % self.id_to_entry.key())
2230
2212
        else:
2231
2213
            lines.append("revision_id: %s\n" % self.revision_id)
2232
2214
            lines.append("root_id: %s\n" % self.root_id)
2233
2215
            if self.parent_id_basename_to_file_id is not None:
2234
2216
                lines.append('parent_id_basename_to_file_id: %s\n' %
2235
 
                    (self.parent_id_basename_to_file_id.key()[0],))
2236
 
            lines.append("id_to_entry: %s\n" % (self.id_to_entry.key()[0],))
 
2217
                    self.parent_id_basename_to_file_id.key())
 
2218
            lines.append("id_to_entry: %s\n" % self.id_to_entry.key())
2237
2219
        return lines
2238
2220
 
2239
2221
    @property
2280
2262
        parent_id_index = self._chk_inventory.parent_id_basename_to_file_id
2281
2263
        child_keys = set()
2282
2264
        for (parent_id, name_utf8), file_id in parent_id_index.iteritems(
2283
 
            key_filter=[StaticTuple(self.file_id,)]):
2284
 
            child_keys.add(StaticTuple(file_id,))
 
2265
            key_filter=[(self.file_id,)]):
 
2266
            child_keys.add((file_id,))
2285
2267
        cached = set()
2286
2268
        for file_id_key in child_keys:
2287
2269
            entry = self._chk_inventory._fileid_to_entry_cache.get(