~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

Rework test_script a little bit.


Don't allow someone to request a stdin request to echo.
Echo never reads from stdin, it just echos its arguments.
You use 'cat' if you want to read from stdin.

A few other fixes because the tests were using filenames
that are actually illegal on Windows, rather than just
nonexistant.


Change the exception handling for commands so that
unknown errors don't get silently squashed and then
turn into hard-to-debug errors later.

test_script now passes on Windows.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
54
55
 
55
56
 
56
57
class InventoryEntry(object):
958
959
        descend(self.root, u'')
959
960
        return accum
960
961
 
961
 
    def path2id(self, name):
 
962
    def path2id(self, relpath):
962
963
        """Walk down through directories to return entry of last component.
963
964
 
964
 
        names may be either a list of path components, or a single
965
 
        string, in which case it is automatically split.
 
965
        :param relpath: may be either a list of path components, or a single
 
966
            string, in which case it is automatically split.
966
967
 
967
968
        This returns the entry of the last component in the path,
968
969
        which may be either a file or a directory.
969
970
 
970
971
        Returns None IFF the path is not found.
971
972
        """
972
 
        if isinstance(name, basestring):
973
 
            name = osutils.splitpath(name)
974
 
 
975
 
        # mutter("lookup path %r" % name)
 
973
        if isinstance(relpath, basestring):
 
974
            names = osutils.splitpath(relpath)
 
975
        else:
 
976
            names = relpath
976
977
 
977
978
        try:
978
979
            parent = self.root
981
982
            return None
982
983
        if parent is None:
983
984
            return None
984
 
        for f in name:
 
985
        for f in names:
985
986
            try:
986
987
                children = getattr(parent, 'children', None)
987
988
                if children is None:
1599
1600
        interesting.add(None) # this will auto-filter it in the loop
1600
1601
        remaining_parents.discard(None) 
1601
1602
        while remaining_parents:
1602
 
            if None in remaining_parents:
1603
 
                import pdb; pdb.set_trace()
1604
1603
            next_parents = set()
1605
1604
            for entry in self._getitems(remaining_parents):
1606
1605
                next_parents.add(entry.parent_id)
1615
1614
        while directories_to_expand:
1616
1615
            # Expand directories by looking in the
1617
1616
            # parent_id_basename_to_file_id map
1618
 
            keys = [(f,) for f in directories_to_expand]
 
1617
            keys = [StaticTuple(f,).intern() for f in directories_to_expand]
1619
1618
            directories_to_expand = set()
1620
1619
            items = self.parent_id_basename_to_file_id.iteritems(keys)
1621
1620
            next_file_ids = set([item[1] for item in items])
1810
1809
                        pass
1811
1810
                deletes.add(file_id)
1812
1811
            else:
1813
 
                new_key = (file_id,)
 
1812
                new_key = StaticTuple(file_id,)
1814
1813
                new_value = result._entry_to_bytes(entry)
1815
1814
                # Update caches. It's worth doing this whether
1816
1815
                # we're propagating the old caches or not.
1819
1818
            if old_path is None:
1820
1819
                old_key = None
1821
1820
            else:
1822
 
                old_key = (file_id,)
 
1821
                old_key = StaticTuple(file_id,)
1823
1822
                if self.id2path(file_id) != old_path:
1824
1823
                    raise errors.InconsistentDelta(old_path, file_id,
1825
1824
                        "Entry was at wrong other path %r." %
1826
1825
                        self.id2path(file_id))
1827
1826
                altered.add(file_id)
1828
 
            id_to_entry_delta.append((old_key, new_key, new_value))
 
1827
            id_to_entry_delta.append(StaticTuple(old_key, new_key, new_value))
1829
1828
            if result.parent_id_basename_to_file_id is not None:
1830
1829
                # parent_id, basename changes
1831
1830
                if old_path is None:
1918
1917
                raise errors.BzrError('Duplicate key in inventory: %r\n%r'
1919
1918
                                      % (key, bytes))
1920
1919
            info[key] = value
1921
 
        revision_id = info['revision_id']
1922
 
        root_id = info['root_id']
1923
 
        search_key_name = info.get('search_key_name', 'plain')
1924
 
        parent_id_basename_to_file_id = info.get(
1925
 
            'parent_id_basename_to_file_id', None)
 
1920
        revision_id = intern(info['revision_id'])
 
1921
        root_id = intern(info['root_id'])
 
1922
        search_key_name = intern(info.get('search_key_name', 'plain'))
 
1923
        parent_id_basename_to_file_id = intern(info.get(
 
1924
            'parent_id_basename_to_file_id', None))
 
1925
        if not parent_id_basename_to_file_id.startswith('sha1:'):
 
1926
            raise ValueError('parent_id_basename_to_file_id should be a sha1'
 
1927
                             ' key not %r' % (parent_id_basename_to_file_id,))
1926
1928
        id_to_entry = info['id_to_entry']
 
1929
        if not id_to_entry.startswith('sha1:'):
 
1930
            raise ValueError('id_to_entry should be a sha1'
 
1931
                             ' key not %r' % (id_to_entry,))
1927
1932
 
1928
1933
        result = CHKInventory(search_key_name)
1929
1934
        result.revision_id = revision_id
1932
1937
                            result._search_key_name)
1933
1938
        if parent_id_basename_to_file_id is not None:
1934
1939
            result.parent_id_basename_to_file_id = chk_map.CHKMap(
1935
 
                chk_store, (parent_id_basename_to_file_id,),
 
1940
                chk_store, StaticTuple(parent_id_basename_to_file_id,),
1936
1941
                search_key_func=search_key_func)
1937
1942
        else:
1938
1943
            result.parent_id_basename_to_file_id = None
1939
1944
 
1940
 
        result.id_to_entry = chk_map.CHKMap(chk_store, (id_to_entry,),
 
1945
        result.id_to_entry = chk_map.CHKMap(chk_store,
 
1946
                                            StaticTuple(id_to_entry,),
1941
1947
                                            search_key_func=search_key_func)
1942
1948
        if (result.revision_id,) != expected_revision_id:
1943
1949
            raise ValueError("Mismatched revision id and expected: %r, %r" %
1965
1971
        id_to_entry_dict = {}
1966
1972
        parent_id_basename_dict = {}
1967
1973
        for path, entry in inventory.iter_entries():
1968
 
            id_to_entry_dict[(entry.file_id,)] = entry_to_bytes(entry)
 
1974
            key = StaticTuple(entry.file_id,).intern()
 
1975
            id_to_entry_dict[key] = entry_to_bytes(entry)
1969
1976
            p_id_key = parent_id_basename_key(entry)
1970
1977
            parent_id_basename_dict[p_id_key] = entry.file_id
1971
1978
 
1994
2001
            parent_id = entry.parent_id
1995
2002
        else:
1996
2003
            parent_id = ''
1997
 
        return parent_id, entry.name.encode('utf8')
 
2004
        return StaticTuple(parent_id, entry.name.encode('utf8')).intern()
1998
2005
 
1999
2006
    def __getitem__(self, file_id):
2000
2007
        """map a single file_id -> InventoryEntry."""
2005
2012
            return result
2006
2013
        try:
2007
2014
            return self._bytes_to_entry(
2008
 
                self.id_to_entry.iteritems([(file_id,)]).next()[1])
 
2015
                self.id_to_entry.iteritems([StaticTuple(file_id,)]).next()[1])
2009
2016
        except StopIteration:
2010
2017
            # really we're passing an inventory, not a tree...
2011
2018
            raise errors.NoSuchId(self, file_id)
2024
2031
                remaining.append(file_id)
2025
2032
            else:
2026
2033
                result.append(entry)
2027
 
        file_keys = [(f,) for f in remaining]
 
2034
        file_keys = [StaticTuple(f,).intern() for f in remaining]
2028
2035
        for file_key, value in self.id_to_entry.iteritems(file_keys):
2029
2036
            entry = self._bytes_to_entry(value)
2030
2037
            result.append(entry)
2035
2042
        # Perhaps have an explicit 'contains' method on CHKMap ?
2036
2043
        if self._fileid_to_entry_cache.get(file_id, None) is not None:
2037
2044
            return True
2038
 
        return len(list(self.id_to_entry.iteritems([(file_id,)]))) == 1
 
2045
        return len(list(
 
2046
            self.id_to_entry.iteritems([StaticTuple(file_id,)]))) == 1
2039
2047
 
2040
2048
    def is_root(self, file_id):
2041
2049
        return file_id == self.root_id
2170
2178
            delta.append((old_path, new_path, file_id, entry))
2171
2179
        return delta
2172
2180
 
2173
 
    def path2id(self, name):
 
2181
    def path2id(self, relpath):
2174
2182
        """See CommonInventory.path2id()."""
2175
2183
        # TODO: perhaps support negative hits?
2176
 
        result = self._path_to_fileid_cache.get(name, None)
 
2184
        result = self._path_to_fileid_cache.get(relpath, None)
2177
2185
        if result is not None:
2178
2186
            return result
2179
 
        if isinstance(name, basestring):
2180
 
            names = osutils.splitpath(name)
 
2187
        if isinstance(relpath, basestring):
 
2188
            names = osutils.splitpath(relpath)
2181
2189
        else:
2182
 
            names = name
 
2190
            names = relpath
2183
2191
        current_id = self.root_id
2184
2192
        if current_id is None:
2185
2193
            return None
2186
2194
        parent_id_index = self.parent_id_basename_to_file_id
 
2195
        cur_path = None
2187
2196
        for basename in names:
2188
 
            # TODO: Cache each path we figure out in this function.
 
2197
            if cur_path is None:
 
2198
                cur_path = basename
 
2199
            else:
 
2200
                cur_path = cur_path + '/' + basename
2189
2201
            basename_utf8 = basename.encode('utf8')
2190
 
            key_filter = [(current_id, basename_utf8)]
2191
 
            file_id = None
2192
 
            for (parent_id, name_utf8), file_id in parent_id_index.iteritems(
2193
 
                key_filter=key_filter):
2194
 
                if parent_id != current_id or name_utf8 != basename_utf8:
2195
 
                    raise errors.BzrError("corrupt inventory lookup! "
2196
 
                        "%r %r %r %r" % (parent_id, current_id, name_utf8,
2197
 
                        basename_utf8))
 
2202
            file_id = self._path_to_fileid_cache.get(cur_path, None)
2198
2203
            if file_id is None:
2199
 
                return None
 
2204
                key_filter = [StaticTuple(current_id, basename_utf8)]
 
2205
                items = parent_id_index.iteritems(key_filter)
 
2206
                for (parent_id, name_utf8), file_id in items:
 
2207
                    if parent_id != current_id or name_utf8 != basename_utf8:
 
2208
                        raise errors.BzrError("corrupt inventory lookup! "
 
2209
                            "%r %r %r %r" % (parent_id, current_id, name_utf8,
 
2210
                            basename_utf8))
 
2211
                if file_id is None:
 
2212
                    return None
 
2213
                else:
 
2214
                    self._path_to_fileid_cache[cur_path] = file_id
2200
2215
            current_id = file_id
2201
 
        self._path_to_fileid_cache[name] = current_id
2202
2216
        return current_id
2203
2217
 
2204
2218
    def to_lines(self):
2209
2223
            lines.append('search_key_name: %s\n' % (self._search_key_name,))
2210
2224
            lines.append("root_id: %s\n" % self.root_id)
2211
2225
            lines.append('parent_id_basename_to_file_id: %s\n' %
2212
 
                self.parent_id_basename_to_file_id.key())
 
2226
                (self.parent_id_basename_to_file_id.key()[0],))
2213
2227
            lines.append("revision_id: %s\n" % self.revision_id)
2214
 
            lines.append("id_to_entry: %s\n" % self.id_to_entry.key())
 
2228
            lines.append("id_to_entry: %s\n" % (self.id_to_entry.key()[0],))
2215
2229
        else:
2216
2230
            lines.append("revision_id: %s\n" % self.revision_id)
2217
2231
            lines.append("root_id: %s\n" % self.root_id)
2218
2232
            if self.parent_id_basename_to_file_id is not None:
2219
2233
                lines.append('parent_id_basename_to_file_id: %s\n' %
2220
 
                    self.parent_id_basename_to_file_id.key())
2221
 
            lines.append("id_to_entry: %s\n" % self.id_to_entry.key())
 
2234
                    (self.parent_id_basename_to_file_id.key()[0],))
 
2235
            lines.append("id_to_entry: %s\n" % (self.id_to_entry.key()[0],))
2222
2236
        return lines
2223
2237
 
2224
2238
    @property
2265
2279
        parent_id_index = self._chk_inventory.parent_id_basename_to_file_id
2266
2280
        child_keys = set()
2267
2281
        for (parent_id, name_utf8), file_id in parent_id_index.iteritems(
2268
 
            key_filter=[(self.file_id,)]):
2269
 
            child_keys.add((file_id,))
 
2282
            key_filter=[StaticTuple(self.file_id,)]):
 
2283
            child_keys.add(StaticTuple(file_id,))
2270
2284
        cached = set()
2271
2285
        for file_id_key in child_keys:
2272
2286
            entry = self._chk_inventory._fileid_to_entry_cache.get(