Rev 2671: Pull in pre-requisite index changes. in http://people.ubuntu.com/~robertc/baz2.0/knits

Robert Collins robertc at robertcollins.net
Fri Aug 3 00:06:11 BST 2007


At http://people.ubuntu.com/~robertc/baz2.0/knits

------------------------------------------------------------
revno: 2671
revision-id: robertc at robertcollins.net-20070802230604-pbpbsl4y1wyr1dvm
parent: pqm at pqm.ubuntu.com-20070802221338-9333q05a8caaciwo
parent: robertc at robertcollins.net-20070801075314-2maihdqr02hah1t3
committer: Robert Collins <robertc at robertcollins.net>
branch nick: knits
timestamp: Fri 2007-08-03 09:06:04 +1000
message:
  Pull in pre-requisite index changes.
modified:
  bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
  bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
  bzrlib/tests/test_index.py     test_index.py-20070712131115-lolkarso50vjr64s-2
  bzrlib/tests/test_knit.py      test_knit.py-20051212171302-95d4c00dd5f11f2b
    ------------------------------------------------------------
    revno: 2624.2.14
    revision-id: robertc at robertcollins.net-20070801075314-2maihdqr02hah1t3
    parent: robertc at robertcollins.net-20070730041421-1jt0kd6ggvlm0jdn
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: index
    timestamp: Wed 2007-08-01 17:53:14 +1000
    message:
      Add source index to the index iteration API to allow mapping back to the origin of retrieved data.
    modified:
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
      bzrlib/tests/test_index.py     test_index.py-20070712131115-lolkarso50vjr64s-2
      bzrlib/tests/test_knit.py      test_knit.py-20051212171302-95d4c00dd5f11f2b
    ------------------------------------------------------------
    revno: 2624.2.13
    revision-id: robertc at robertcollins.net-20070730041421-1jt0kd6ggvlm0jdn
    parent: robertc at robertcollins.net-20070729233741-tp1d2j06b7zde9j3
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: index
    timestamp: Mon 2007-07-30 14:14:21 +1000
    message:
      Implement add_node/add_nodes to the GraphIndexPrefixAdapter.
    modified:
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/tests/test_index.py     test_index.py-20070712131115-lolkarso50vjr64s-2
    ------------------------------------------------------------
    revno: 2624.2.12
    revision-id: robertc at robertcollins.net-20070729233741-tp1d2j06b7zde9j3
    parent: robertc at robertcollins.net-20070728013353-qk7394wehmg2iiph
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: index
    timestamp: Mon 2007-07-30 09:37:41 +1000
    message:
      Create an adapter between indices with differing key lengths.
    modified:
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/tests/test_index.py     test_index.py-20070712131115-lolkarso50vjr64s-2
=== modified file 'bzrlib/index.py'
--- a/bzrlib/index.py	2007-07-28 01:33:53 +0000
+++ b/bzrlib/index.py	2007-08-01 07:53:14 +0000
@@ -20,6 +20,7 @@
     'CombinedGraphIndex',
     'GraphIndex',
     'GraphIndexBuilder',
+    'GraphIndexPrefixAdapter',
     'InMemoryGraphIndex',
     ]
 
@@ -313,10 +314,10 @@
             self._buffer_all()
         if self.node_ref_lists:
             for key, (value, node_ref_lists) in self._nodes.iteritems():
-                yield key, value, node_ref_lists
+                yield self, key, value, node_ref_lists
         else:
             for key, value in self._nodes.iteritems():
-                yield key, value
+                yield self, key, value
 
     def _read_prefix(self, stream):
         signature = stream.read(len(self._signature()))
@@ -354,10 +355,10 @@
         if self.node_ref_lists:
             for key in keys:
                 value, node_refs = self._nodes[key]
-                yield key, value, node_refs
+                yield self, key, value, node_refs
         else:
             for key in keys:
-                yield key, self._nodes[key]
+                yield self, key, self._nodes[key]
 
     def iter_entries_prefix(self, keys):
         """Iterate over keys within the index using prefix matching.
@@ -391,9 +392,9 @@
                     raise errors.BadIndexKey(key)
                 if self.node_ref_lists:
                     value, node_refs = self._nodes[key]
-                    yield key, value, node_refs
+                    yield self, key, value, node_refs
                 else:
-                    yield key, self._nodes[key]
+                    yield self, key, self._nodes[key]
             return
         for key in keys:
             # sanity check
@@ -426,10 +427,10 @@
                         for value in key_dict.itervalues():
                             # each value is the key:value:node refs tuple
                             # ready to yield.
-                            yield value
+                            yield (self, ) + value
             else:
                 # the last thing looked up was a terminal element
-                yield key_dict
+                yield (self, ) + key_dict
 
     def _signature(self):
         """The file signature for this index type."""
@@ -483,9 +484,9 @@
         seen_keys = set()
         for index in self._indices:
             for node in index.iter_all_entries():
-                if node[0] not in seen_keys:
+                if node[1] not in seen_keys:
                     yield node
-                    seen_keys.add(node[0])
+                    seen_keys.add(node[1])
 
     def iter_entries(self, keys):
         """Iterate over keys within the index.
@@ -503,7 +504,7 @@
             if not keys:
                 return
             for node in index.iter_entries(keys):
-                keys.remove(node[0])
+                keys.remove(node[1])
                 yield node
 
     def iter_entries_prefix(self, keys):
@@ -532,9 +533,9 @@
         seen_keys = set()
         for index in self._indices:
             for node in index.iter_entries_prefix(keys):
-                if node[0] in seen_keys:
+                if node[1] in seen_keys:
                     continue
-                seen_keys.add(node[0])
+                seen_keys.add(node[1])
                 yield node
 
     def validate(self):
@@ -573,11 +574,11 @@
         if self.reference_lists:
             for key, (absent, references, value) in self._nodes.iteritems():
                 if not absent:
-                    yield key, value, references
+                    yield self, key, value, references
         else:
             for key, (absent, references, value) in self._nodes.iteritems():
                 if not absent:
-                    yield key, value
+                    yield self, key, value
 
     def iter_entries(self, keys):
         """Iterate over keys within the index.
@@ -592,12 +593,12 @@
             for key in keys.intersection(self._nodes):
                 node = self._nodes[key]
                 if not node[0]:
-                    yield key, node[2], node[1]
+                    yield self, key, node[2], node[1]
         else:
             for key in keys.intersection(self._nodes):
                 node = self._nodes[key]
                 if not node[0]:
-                    yield key, node[2]
+                    yield self, key, node[2]
 
     def iter_entries_prefix(self, keys):
         """Iterate over keys within the index using prefix matching.
@@ -632,9 +633,9 @@
                 if node[0]:
                     continue 
                 if self.reference_lists:
-                    yield key, node[2], node[1]
+                    yield self, key, node[2], node[1]
                 else:
-                    yield key, node[2]
+                    yield self ,key, node[2]
             return
         for key in keys:
             # sanity check
@@ -665,9 +666,125 @@
                     else:
                         # yield keys
                         for value in key_dict.itervalues():
-                            yield value
+                            yield (self, ) + value
             else:
-                yield key_dict
+                yield (self, ) + key_dict
 
     def validate(self):
         """In memory index's have no known corruption at the moment."""
+
+
+class GraphIndexPrefixAdapter(object):
+    """An adapter between GraphIndex with different key lengths.
+
+    Queries against this will emit queries against the adapted Graph with the
+    prefix added, queries for all items use iter_entries_prefix. The returned
+    nodes will have their keys and node references adjusted to remove the 
+    prefix. Finally, an add_nodes_callback can be supplied - when called the
+    nodes and references being added will have prefix prepended.
+    """
+
+    def __init__(self, adapted, prefix, missing_key_length, add_nodes_callback=None):
+        """Construct an adapter against adapted with prefix."""
+        self.adapted = adapted
+        self.prefix = prefix + (None,)*missing_key_length
+        self.prefix_key = prefix
+        self.prefix_len = len(prefix)
+        self.add_nodes_callback = add_nodes_callback
+
+    def add_nodes(self, nodes):
+        """Add nodes to the index.
+
+        :param nodes: An iterable of (key, node_refs, value) entries to add.
+        """
+        # save nodes in case its an iterator
+        nodes = tuple(nodes)
+        translated_nodes = []
+        try:
+            for (key, value, node_refs) in nodes:
+                adjusted_references = (
+                    tuple(tuple(self.prefix_key + ref_node for ref_node in ref_list)
+                        for ref_list in node_refs))
+                translated_nodes.append((self.prefix_key + key, value,
+                    adjusted_references))
+        except ValueError:
+            # XXX: TODO add an explicit interface for getting the reference list
+            # status, to handle this bit of user-friendliness in the API more 
+            # explicitly.
+            for (key, value) in nodes:
+                translated_nodes.append((self.prefix_key + key, value))
+        self.add_nodes_callback(translated_nodes)
+
+    def add_node(self, key, value, references=()):
+        """Add a node to the index.
+
+        :param key: The key. keys are non-empty tuples containing
+            as many whitespace-free utf8 bytestrings as the key length
+            defined for this index.
+        :param references: An iterable of iterables of keys. Each is a
+            reference to another key.
+        :param value: The value to associate with the key. It may be any
+            bytes as long as it does not contain \0 or \n.
+        """
+        self.add_nodes(((key, value, references), ))
+
+    def _strip_prefix(self, an_iter):
+        """Strip prefix data from nodes and return it."""
+        for node in an_iter:
+            # cross checks
+            if node[1][:self.prefix_len] != self.prefix_key:
+                raise errors.BadIndexData(self)
+            for ref_list in node[3]:
+                for ref_node in ref_list:
+                    if ref_node[:self.prefix_len] != self.prefix_key:
+                        raise errors.BadIndexData(self)
+            yield node[0], node[1][self.prefix_len:], node[2], (
+                tuple(tuple(ref_node[self.prefix_len:] for ref_node in ref_list)
+                for ref_list in node[3]))
+
+    def iter_all_entries(self):
+        """Iterate over all keys within the index
+
+        iter_all_entries is implemented against the adapted index using
+        iter_entries_prefix.
+
+        :return: An iterable of (key, reference_lists, value). There is no
+            defined order for the result iteration - it will be in the most
+            efficient order for the index (in this case dictionary hash order).
+        """
+        return self._strip_prefix(self.adapted.iter_entries_prefix([self.prefix]))
+
+    def iter_entries(self, keys):
+        """Iterate over keys within the index.
+
+        :param keys: An iterable providing the keys to be retrieved.
+        :return: An iterable of (key, reference_lists, value). There is no
+            defined order for the result iteration - it will be in the most
+            efficient order for the index (keys iteration order in this case).
+        """
+        return self._strip_prefix(self.adapted.iter_entries(
+            self.prefix_key + key for key in keys))
+
+    def iter_entries_prefix(self, keys):
+        """Iterate over keys within the index using prefix matching.
+
+        Prefix matching is applied within the tuple of a key, not to within
+        the bytestring of each key element. e.g. if you have the keys ('foo',
+        'bar'), ('foobar', 'gam') and do a prefix search for ('foo', None) then
+        only the former key is returned.
+
+        :param keys: An iterable providing the key prefixes to be retrieved.
+            Each key prefix takes the form of a tuple the length of a key, but
+            with the last N elements 'None' rather than a regular bytestring.
+            The first element cannot be 'None'.
+        :return: An iterable as per iter_all_entries, but restricted to the
+            keys with a matching prefix to those supplied. No additional keys
+            will be returned, and every match that is in the index will be
+            returned.
+        """
+        return self._strip_prefix(self.adapted.iter_entries_prefix(
+            self.prefix_key + key for key in keys))
+
+    def validate(self):
+        """Call the adapted's validate."""
+        self.adapted.validate()

=== modified file 'bzrlib/knit.py'
--- a/bzrlib/knit.py	2007-07-30 05:02:10 +0000
+++ b/bzrlib/knit.py	2007-08-02 23:06:04 +0000
@@ -1386,12 +1386,12 @@
         if self._parents:
             for node in self._graph_index.iter_entries(keys):
                 yield node
-                found_keys.add(node[0])
+                found_keys.add(node[1])
         else:
             # adapt parentless index to the rest of the code.
             for node in self._graph_index.iter_entries(keys):
-                yield node[0], node[1], ()
-                found_keys.add(node[0])
+                yield node[0], node[1], node[2], ()
+                found_keys.add(node[1])
         if check_present:
             missing_keys = keys.difference(found_keys)
             if missing_keys:
@@ -1399,7 +1399,7 @@
 
     def _present_keys(self, version_ids):
         return set([
-            node[0] for node in self._get_entries(version_ids)])
+            node[1] for node in self._get_entries(version_ids)])
 
     def _parentless_ancestry(self, versions):
         """Honour the get_ancestry API for parentless knit indices."""
@@ -1427,7 +1427,7 @@
             new_nodes = self._get_entries(this_iteration)
             found = set()
             pending = set()
-            for (key, value, node_refs) in new_nodes:
+            for (index, key, value, node_refs) in new_nodes:
                 # dont ask for ghosties - otherwise
                 # we we can end up looping with pending
                 # being entirely ghosted.
@@ -1464,7 +1464,7 @@
             this_iteration = pending
             new_nodes = self._get_entries(this_iteration)
             pending = set()
-            for (key, value, node_refs) in new_nodes:
+            for (index, key, value, node_refs) in new_nodes:
                 graph[key] = node_refs[0]
                 # queue parents 
                 for parent in graph[key]:
@@ -1488,7 +1488,7 @@
         if not self._parents:
             return [(key, ()) for key in self.get_versions()]
         result = []
-        for key, value, refs in self._graph_index.iter_all_entries():
+        for index, key, value, refs in self._graph_index.iter_all_entries():
             result.append((key[0], tuple([ref[0] for ref in refs[0]])))
         return result
 
@@ -1506,20 +1506,20 @@
             all_parents = set()
             present_parents = set()
             for node in all_nodes:
-                all_parents.update(node[2][0])
+                all_parents.update(node[3][0])
                 # any node we are querying must be present
-                present_parents.add(node[0])
+                present_parents.add(node[1])
             unknown_parents = all_parents.difference(present_parents)
             present_parents.update(self._present_keys(unknown_parents))
             for node in all_nodes:
                 parents = []
-                for parent in node[2][0]:
+                for parent in node[3][0]:
                     if parent in present_parents:
                         parents.append(parent[0])
-                yield node[0][0], tuple(parents)
+                yield node[1][0], tuple(parents)
         else:
             for node in self._get_entries(self._version_ids_to_keys(version_ids)):
-                yield node[0][0], ()
+                yield node[1][0], ()
 
     def num_versions(self):
         return len(list(self._graph_index.iter_all_entries()))
@@ -1528,7 +1528,7 @@
 
     def get_versions(self):
         """Get all the versions in the file. not topologically sorted."""
-        return [node[0][0] for node in self._graph_index.iter_all_entries()]
+        return [node[1][0] for node in self._graph_index.iter_all_entries()]
     
     def has_version(self, version_id):
         """True if the version is in the index."""
@@ -1539,14 +1539,14 @@
 
     def get_position(self, version_id):
         """Return data position and size of specified version."""
-        bits = self._get_node(version_id)[1][1:].split(' ')
+        bits = self._get_node(version_id)[2][1:].split(' ')
         return int(bits[0]), int(bits[1])
 
     def get_method(self, version_id):
         """Return compression method of specified version."""
         if not self._deltas:
             return 'fulltext'
-        return self._parent_compression(self._get_node(version_id)[2][1])
+        return self._parent_compression(self._get_node(version_id)[3][1])
 
     def _parent_compression(self, reference_list):
         # use the second reference list to decide if this is delta'd or not.
@@ -1567,8 +1567,8 @@
         if not self._deltas:
             options = ['fulltext']
         else:
-            options = [self._parent_compression(node[2][1])]
-        if node[1][0] == 'N':
+            options = [self._parent_compression(node[3][1])]
+        if node[2][0] == 'N':
             options.append('no-eol')
         return options
 
@@ -1586,7 +1586,7 @@
             check_present=True))
         if not self._parents:
             return ()
-        return self._keys_to_version_ids(nodes[0][2][0])
+        return self._keys_to_version_ids(nodes[0][3][0])
 
     def check_versions_present(self, version_ids):
         """Check that all specified versions are present."""
@@ -1645,7 +1645,7 @@
                 node_refs = ()
             keys[key] = (value, node_refs)
         present_nodes = self._get_entries(keys)
-        for (key, value, node_refs) in present_nodes:
+        for (index, key, value, node_refs) in present_nodes:
             if (value, node_refs) != keys[key]:
                 raise KnitCorrupt(self, "inconsistent details in add_versions"
                     ": %s %s" % ((value, node_refs), keys[key]))

=== modified file 'bzrlib/tests/test_index.py'
--- a/bzrlib/tests/test_index.py	2007-07-28 01:33:53 +0000
+++ b/bzrlib/tests/test_index.py	2007-08-01 07:53:14 +0000
@@ -349,38 +349,38 @@
 
     def test_iter_all_entries_simple(self):
         index = self.make_index(nodes=[(('name', ), 'data', ())])
-        self.assertEqual([(('name', ), 'data')],
+        self.assertEqual([(index, ('name', ), 'data')],
             list(index.iter_all_entries()))
 
     def test_iter_all_entries_simple_2_elements(self):
         index = self.make_index(key_elements=2,
             nodes=[(('name', 'surname'), 'data', ())])
-        self.assertEqual([(('name', 'surname'), 'data')],
+        self.assertEqual([(index, ('name', 'surname'), 'data')],
             list(index.iter_all_entries()))
 
     def test_iter_all_entries_references_resolved(self):
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], )),
             (('ref', ), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),)),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
+            (index, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_all_entries()))
 
     def test_iteration_absent_skipped(self):
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
             set(index.iter_all_entries()))
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
             set(index.iter_entries([('name', )])))
         self.assertEqual([], list(index.iter_entries([('ref', )])))
 
     def test_iteration_absent_skipped_2_element_keys(self):
         index = self.make_index(1, key_elements=2, nodes=[
             (('name', 'fin'), 'data', ([('ref', 'erence')], ))])
-        self.assertEqual(set([(('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
+        self.assertEqual(set([(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
             set(index.iter_all_entries()))
-        self.assertEqual(set([(('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
+        self.assertEqual(set([(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
             set(index.iter_entries([('name', 'fin')])))
         self.assertEqual([], list(index.iter_entries([('ref', 'erence')])))
 
@@ -388,8 +388,8 @@
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], )),
             (('ref', ), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),)),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
+            (index, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_entries([('name', ), ('ref', )])))
 
     def test_iter_nothing_empty(self):
@@ -419,16 +419,16 @@
         index = self.make_index( nodes=[
             (('name', ), 'data', ()),
             (('ref', ), 'refdata', ())])
-        self.assertEqual(set([(('name', ), 'data'),
-            (('ref', ), 'refdata')]),
+        self.assertEqual(set([(index, ('name', ), 'data'),
+            (index, ('ref', ), 'refdata')]),
             set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
     def test_iter_key_prefix_1_key_element_refs(self):
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], )),
             (('ref', ), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),)),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
+            (index, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
     def test_iter_key_prefix_2_key_element_no_refs(self):
@@ -436,11 +436,11 @@
             (('name', 'fin1'), 'data', ()),
             (('name', 'fin2'), 'beta', ()),
             (('ref', 'erence'), 'refdata', ())])
-        self.assertEqual(set([(('name', 'fin1'), 'data'),
-            (('ref', 'erence'), 'refdata')]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
+            (index, ('ref', 'erence'), 'refdata')]),
             set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
-        self.assertEqual(set([(('name', 'fin1'), 'data'),
-            (('name', 'fin2'), 'beta')]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
+            (index, ('name', 'fin2'), 'beta')]),
             set(index.iter_entries_prefix([('name', None)])))
 
     def test_iter_key_prefix_2_key_element_refs(self):
@@ -448,11 +448,11 @@
             (('name', 'fin1'), 'data', ([('ref', 'erence')], )),
             (('name', 'fin2'), 'beta', ([], )),
             (('ref', 'erence'), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
-            (('ref', 'erence'), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
+            (index, ('ref', 'erence'), 'refdata', ((), ))]),
             set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
-        self.assertEqual(set([(('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
-            (('name', 'fin2'), 'beta', ((), ))]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
+            (index, ('name', 'fin2'), 'beta', ((), ))]),
             set(index.iter_entries_prefix([('name', None)])))
 
     def test_validate_bad_index_errors(self):
@@ -515,7 +515,7 @@
         index = CombinedGraphIndex([])
         index1 = self.make_index('name', 0, nodes=[(('key', ), '', ())])
         index.insert_index(0, index1)
-        self.assertEqual([(('key', ), '')], list(index.iter_all_entries()))
+        self.assertEqual([(index1, ('key', ), '')], list(index.iter_all_entries()))
 
     def test_iter_all_entries_empty(self):
         index = CombinedGraphIndex([])
@@ -529,29 +529,29 @@
     def test_iter_all_entries_simple(self):
         index1 = self.make_index('name', nodes=[(('name', ), 'data', ())])
         index = CombinedGraphIndex([index1])
-        self.assertEqual([(('name', ), 'data')],
+        self.assertEqual([(index1, ('name', ), 'data')],
             list(index.iter_all_entries()))
 
     def test_iter_all_entries_two_indices(self):
         index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
         index2 = self.make_index('name2', nodes=[(('2', ), '', ())])
         index = CombinedGraphIndex([index1, index2])
-        self.assertEqual([(('name', ), 'data'),
-            (('2', ), '')],
+        self.assertEqual([(index1, ('name', ), 'data'),
+            (index2, ('2', ), '')],
             list(index.iter_all_entries()))
 
     def test_iter_entries_two_indices_dup_key(self):
         index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
         index2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
         index = CombinedGraphIndex([index1, index2])
-        self.assertEqual([(('name', ), 'data')],
+        self.assertEqual([(index1, ('name', ), 'data')],
             list(index.iter_entries([('name', )])))
 
     def test_iter_all_entries_two_indices_dup_key(self):
         index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
         index2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
         index = CombinedGraphIndex([index1, index2])
-        self.assertEqual([(('name', ), 'data')],
+        self.assertEqual([(index1, ('name', ), 'data')],
             list(index.iter_all_entries()))
 
     def test_iter_key_prefix_2_key_element_refs(self):
@@ -561,11 +561,11 @@
             (('name', 'fin2'), 'beta', ([], )),
             (('ref', 'erence'), 'refdata', ([], ))])
         index = CombinedGraphIndex([index1, index2])
-        self.assertEqual(set([(('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
-            (('ref', 'erence'), 'refdata', ((), ))]),
+        self.assertEqual(set([(index1, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
+            (index2, ('ref', 'erence'), 'refdata', ((), ))]),
             set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
-        self.assertEqual(set([(('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
-            (('name', 'fin2'), 'beta', ((), ))]),
+        self.assertEqual(set([(index1, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
+            (index2, ('name', 'fin2'), 'beta', ((), ))]),
             set(index.iter_entries_prefix([('name', None)])))
 
     def test_iter_nothing_empty(self):
@@ -583,8 +583,8 @@
         index2 = self.make_index('2', 1, nodes=[
             (('ref', ), 'refdata', ((), ))])
         index = CombinedGraphIndex([index1, index2])
-        self.assertEqual(set([(('name', ), 'data', ((('ref', ), ), )),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index1, ('name', ), 'data', ((('ref', ), ), )),
+            (index2, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_entries([('name', ), ('ref', )])))
  
     def test_iter_all_keys_dup_entry(self):
@@ -594,8 +594,8 @@
         index2 = self.make_index('2', 1, nodes=[
             (('ref', ), 'refdata', ([], ))])
         index = CombinedGraphIndex([index1, index2])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),)),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index1, ('name', ), 'data', ((('ref',),),)),
+            (index1, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_entries([('name', ), ('ref', )])))
  
     def test_iter_missing_entry_empty(self):
@@ -617,11 +617,11 @@
         index1 = self.make_index('1', nodes=[(('key', ), '', ())])
         index2 = self.make_index('2', nodes=[])
         index = CombinedGraphIndex([index1, index2])
-        self.assertEqual([(('key', ), '')],
+        self.assertEqual([(index1, ('key', ), '')],
             list(index.iter_entries([('key', )])))
         # and in the other direction
         index = CombinedGraphIndex([index2, index1])
-        self.assertEqual([(('key', ), '')],
+        self.assertEqual([(index1, ('key', ), '')],
             list(index.iter_entries([('key', )])))
 
     def test_validate_bad_child_index_errors(self):
@@ -648,9 +648,9 @@
         index.add_nodes([(('name', ), 'data')])
         index.add_nodes([(('name2', ), ''), (('name3', ), '')])
         self.assertEqual(set([
-            (('name', ), 'data'),
-            (('name2', ), ''),
-            (('name3', ), ''),
+            (index, ('name', ), 'data'),
+            (index, ('name2', ), ''),
+            (index, ('name3', ), ''),
             ]), set(index.iter_all_entries()))
 
     def test_add_nodes(self):
@@ -658,9 +658,9 @@
         index.add_nodes([(('name', ), 'data', ([],))])
         index.add_nodes([(('name2', ), '', ([],)), (('name3', ), '', ([('r', )],))])
         self.assertEqual(set([
-            (('name', ), 'data', ((),)),
-            (('name2', ), '', ((),)),
-            (('name3', ), '', ((('r', ), ), )),
+            (index, ('name', ), 'data', ((),)),
+            (index, ('name2', ), '', ((),)),
+            (index, ('name3', ), '', ((('r', ), ), )),
             ]), set(index.iter_all_entries()))
 
     def test_iter_all_entries_empty(self):
@@ -669,23 +669,23 @@
 
     def test_iter_all_entries_simple(self):
         index = self.make_index(nodes=[(('name', ), 'data')])
-        self.assertEqual([(('name', ), 'data')],
+        self.assertEqual([(index, ('name', ), 'data')],
             list(index.iter_all_entries()))
 
     def test_iter_all_entries_references(self):
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], )),
             (('ref', ), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref', ),),)),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref', ),),)),
+            (index, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_all_entries()))
 
     def test_iteration_absent_skipped(self):
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
             set(index.iter_all_entries()))
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
             set(index.iter_entries([('name', )])))
         self.assertEqual([], list(index.iter_entries([('ref', )])))
 
@@ -693,24 +693,24 @@
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], )),
             (('ref', ), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),)),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
+            (index, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_entries([('name', ), ('ref', )])))
 
     def test_iter_key_prefix_1_key_element_no_refs(self):
         index = self.make_index( nodes=[
             (('name', ), 'data'),
             (('ref', ), 'refdata')])
-        self.assertEqual(set([(('name', ), 'data'),
-            (('ref', ), 'refdata')]),
+        self.assertEqual(set([(index, ('name', ), 'data'),
+            (index, ('ref', ), 'refdata')]),
             set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
     def test_iter_key_prefix_1_key_element_refs(self):
         index = self.make_index(1, nodes=[
             (('name', ), 'data', ([('ref', )], )),
             (('ref', ), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', ), 'data', ((('ref',),),)),
-            (('ref', ), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
+            (index, ('ref', ), 'refdata', ((), ))]),
             set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
     def test_iter_key_prefix_2_key_element_no_refs(self):
@@ -718,11 +718,11 @@
             (('name', 'fin1'), 'data'),
             (('name', 'fin2'), 'beta'),
             (('ref', 'erence'), 'refdata')])
-        self.assertEqual(set([(('name', 'fin1'), 'data'),
-            (('ref', 'erence'), 'refdata')]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
+            (index, ('ref', 'erence'), 'refdata')]),
             set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
-        self.assertEqual(set([(('name', 'fin1'), 'data'),
-            (('name', 'fin2'), 'beta')]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
+            (index, ('name', 'fin2'), 'beta')]),
             set(index.iter_entries_prefix([('name', None)])))
 
     def test_iter_key_prefix_2_key_element_refs(self):
@@ -730,11 +730,11 @@
             (('name', 'fin1'), 'data', ([('ref', 'erence')], )),
             (('name', 'fin2'), 'beta', ([], )),
             (('ref', 'erence'), 'refdata', ([], ))])
-        self.assertEqual(set([(('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
-            (('ref', 'erence'), 'refdata', ((), ))]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
+            (index, ('ref', 'erence'), 'refdata', ((), ))]),
             set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
-        self.assertEqual(set([(('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
-            (('name', 'fin2'), 'beta', ((), ))]),
+        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
+            (index, ('name', 'fin2'), 'beta', ((), ))]),
             set(index.iter_entries_prefix([('name', None)])))
 
     def test_iter_nothing_empty(self):
@@ -754,3 +754,90 @@
         index.validate()
 
 
+class TestGraphIndexPrefixAdapter(TestCaseWithMemoryTransport):
+
+    def make_index(self, ref_lists=1, key_elements=2, nodes=[], add_callback=False):
+        result = InMemoryGraphIndex(ref_lists, key_elements=key_elements)
+        result.add_nodes(nodes)
+        if add_callback:
+            add_nodes_callback=result.add_nodes
+        else:
+            add_nodes_callback=None
+        adapter = GraphIndexPrefixAdapter(result, ('prefix', ), key_elements - 1,
+            add_nodes_callback=add_nodes_callback)
+        return result, adapter
+
+    def test_add_node(self):
+        index, adapter = self.make_index(add_callback=True)
+        adapter.add_node(('key',), 'value', ((('ref',),),))
+        self.assertEqual(set([(index, ('prefix', 'key'), 'value', ((('prefix', 'ref'),),))]),
+            set(index.iter_all_entries()))
+
+    def test_add_nodes(self):
+        index, adapter = self.make_index(add_callback=True)
+        adapter.add_nodes((
+            (('key',), 'value', ((('ref',),),)),
+            (('key2',), 'value2', ((),)),
+            ))
+        self.assertEqual(set([
+            (index, ('prefix', 'key2'), 'value2', ((),)),
+            (index, ('prefix', 'key'), 'value', ((('prefix', 'ref'),),))
+            ]),
+            set(index.iter_all_entries()))
+
+    def test_construct(self):
+        index = InMemoryGraphIndex()
+        adapter = GraphIndexPrefixAdapter(index, ('prefix', ), 1)
+
+    def test_construct_with_callback(self):
+        index = InMemoryGraphIndex()
+        adapter = GraphIndexPrefixAdapter(index, ('prefix', ), 1, index.add_nodes)
+
+    def test_iter_all_entries_cross_prefix_map_errors(self):
+        index, adapter = self.make_index(nodes=[
+            (('prefix', 'key1'), 'data1', ((('prefixaltered', 'key2'),),))])
+        self.assertRaises(errors.BadIndexData, list, adapter.iter_all_entries())
+
+    def test_iter_all_entries(self):
+        index, adapter = self.make_index(nodes=[
+            (('notprefix', 'key1'), 'data', ((), )),
+            (('prefix', 'key1'), 'data1', ((), )),
+            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
+        self.assertEqual(set([(index, ('key1', ), 'data1', ((),)),
+            (index, ('key2', ), 'data2', ((('key1',),),))]),
+            set(adapter.iter_all_entries()))
+
+    def test_iter_entries(self):
+        index, adapter = self.make_index(nodes=[
+            (('notprefix', 'key1'), 'data', ((), )),
+            (('prefix', 'key1'), 'data1', ((), )),
+            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
+        # ask for many - get all
+        self.assertEqual(set([(index, ('key1', ), 'data1', ((),)),
+            (index, ('key2', ), 'data2', ((('key1', ),),))]),
+            set(adapter.iter_entries([('key1', ), ('key2', )])))
+        # ask for one, get one
+        self.assertEqual(set([(index, ('key1', ), 'data1', ((),))]),
+            set(adapter.iter_entries([('key1', )])))
+        # ask for missing, get none
+        self.assertEqual(set(),
+            set(adapter.iter_entries([('key3', )])))
+
+    def test_iter_entries_prefix(self):
+        index, adapter = self.make_index(key_elements=3, nodes=[
+            (('notprefix', 'foo', 'key1'), 'data', ((), )),
+            (('prefix', 'prefix2', 'key1'), 'data1', ((), )),
+            (('prefix', 'prefix2', 'key2'), 'data2', ((('prefix', 'prefix2', 'key1'),),))])
+        # ask for a prefix, get the results for just that prefix, adjusted.
+        self.assertEqual(set([(index, ('prefix2', 'key1', ), 'data1', ((),)),
+            (index, ('prefix2', 'key2', ), 'data2', ((('prefix2', 'key1', ),),))]),
+            set(adapter.iter_entries_prefix([('prefix2', None)])))
+
+    def test_validate(self):
+        index, adapter = self.make_index()
+        calls = []
+        def validate():
+            calls.append('called')
+        index.validate = validate
+        adapter.validate()
+        self.assertEqual(['called'], calls)

=== modified file 'bzrlib/tests/test_knit.py'
--- a/bzrlib/tests/test_knit.py	2007-07-30 05:02:10 +0000
+++ b/bzrlib/tests/test_knit.py	2007-08-02 23:06:04 +0000
@@ -1017,8 +1017,8 @@
         self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A)
         # check the index had the right data added.
         self.assertEqual(set([
-            (('text-1', ), ' 0 127', ((), ())),
-            (('text-1a', ), ' 127 140', ((('text-1', ),), (('text-1', ),))),
+            (index, ('text-1', ), ' 0 127', ((), ())),
+            (index, ('text-1a', ), ' 127 140', ((('text-1', ),), (('text-1', ),))),
             ]), set(index.iter_all_entries()))
         # we should not have a .kndx file
         self.assertFalse(get_transport('.').has('test.kndx'))



More information about the bazaar-commits mailing list