Rev 4517: Copy the implementation over to the Pyrex version. in http://bazaar.launchpad.net/~jameinel/bzr/1.17-rework-annotate

John Arbash Meinel john at arbash-meinel.com
Mon Jul 6 20:16:48 BST 2009


At http://bazaar.launchpad.net/~jameinel/bzr/1.17-rework-annotate

------------------------------------------------------------
revno: 4517
revision-id: john at arbash-meinel.com-20090706191619-lycpcdwo73j2g1cg
parent: john at arbash-meinel.com-20090706190526-4rn5l49rigy4wia2
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 1.17-rework-annotate
timestamp: Mon 2009-07-06 14:16:19 -0500
message:
  Copy the implementation over to the Pyrex version.
-------------- next part --------------
=== modified file 'bzrlib/_annotator_py.py'
--- a/bzrlib/_annotator_py.py	2009-07-06 18:59:24 +0000
+++ b/bzrlib/_annotator_py.py	2009-07-06 19:16:19 +0000
@@ -35,7 +35,6 @@
     def __init__(self, vf):
         """Create a new Annotator from a VersionedFile."""
         self._vf = vf
-        self._special_keys = set()
         self._parent_map = {}
         self._text_cache = {}
         # Map from key => number of nexts that will be built from this key
@@ -93,7 +92,6 @@
             # _heads_provider does some graph caching, so it is only valid while
             # self._parent_map hasn't changed
             self._heads_provider = None
-        # self._parent_map.update(parent_map)
         return vf_keys_needed, ann_keys_needed
 
     def _get_needed_texts(self, key, pb=None):
@@ -226,7 +224,6 @@
 
     def add_special_text(self, key, parent_keys, text):
         """Add a specific text to the graph."""
-        self._special_keys.add(key)
         self._parent_map[key] = parent_keys
         self._text_cache[key] = osutils.split_lines(text)
         self._heads_provider = None

=== modified file 'bzrlib/_annotator_pyx.pyx'
--- a/bzrlib/_annotator_pyx.pyx	2009-07-06 18:59:24 +0000
+++ b/bzrlib/_annotator_pyx.pyx	2009-07-06 19:16:19 +0000
@@ -63,24 +63,47 @@
     cdef object counter
     cdef object text_cache
     cdef object stream
+    cdef object ann_keys
     cdef object stream_len
     cdef object pb
+    cdef int stream_is_consumed
+    cdef int ann_key_pos
 
-    def __init__(self, stream, text_cache, stream_len, pb=None):
+    def __init__(self, stream, text_cache, stream_len, ann_keys, pb=None):
         self.counter = 0
         self.stream = stream
         self.stream_len = stream_len
         self.text_cache = text_cache
         self.stream_len = stream_len
+        self.ann_keys = list(ann_keys)
         self.pb = pb
+        self.stream_is_consumed = 0
+        self.ann_key_pos = 0
 
     def __iter__(self):
         return self
 
+    cdef _get_ann_text(self):
+        if self.ann_key_pos >= len(self.ann_keys):
+            raise StopIteration
+        key = self.ann_keys[self.ann_key_pos]
+        self.ann_key_pos = self.ann_key_pos + 1
+        lines = self.text_cache[key]
+        num_lines = len(lines)
+        return key, lines, num_lines
+
     def __next__(self):
-        record = self.stream.next()
+        if self.stream_is_consumed:
+            return self._get_ann_text()
+        try:
+            record = self.stream.next()
+        except StopIteration:
+            self.stream_is_consumed = 1
+            return self._get_ann_text()
         if self.pb is not None:
             self.pb.update('extracting', self.counter, self.stream_len)
+        if record.storage_kind == 'absent':
+            raise errors.RevisionNotPresent(record.key, None)
         self.counter = self.counter + 1
         lines = osutils.chunks_to_lines(record.get_bytes_as('chunked'))
         num_lines = len(lines)
@@ -222,27 +245,59 @@
         self._heads_provider = None
         self._ann_tuple_cache = {}
 
+
+    def _update_needed_children(self, key, parent_keys):
+        for parent_key in parent_keys:
+            if parent_key in self._num_needed_children:
+                self._num_needed_children[parent_key] += 1
+            else:
+                self._num_needed_children[parent_key] = 1
+
     def _get_needed_keys(self, key):
-        graph = _mod_graph.Graph(self._vf)
-        parent_map = {}
+        """Determine the texts we need to get from the backing vf.
+
+        :return: (vf_keys_needed, ann_keys_needed)
+            vf_keys_needed  These are keys that we need to get from the vf
+            ann_keys_needed Texts which we have in self._text_cache but we
+                            don't have annotations for. We need to yield these
+                            in the proper order so that we can get proper
+                            annotations.
+        """
+        parent_map = self._parent_map
         # We need 1 extra copy of the node we will be looking at when we are
         # done
         self._num_needed_children[key] = 1
-        for key, parent_keys in graph.iter_ancestry([key]):
-            if parent_keys is None:
-                continue
-            parent_map[key] = parent_keys
-            for parent_key in parent_keys:
-                if parent_key in self._num_needed_children:
-                    self._num_needed_children[parent_key] += 1
+        vf_keys_needed = set()
+        ann_keys_needed = set()
+        needed_keys = set([key])
+        while needed_keys:
+            parent_lookup = []
+            next_parent_map = {}
+            for key in needed_keys:
+                if key in self._parent_map:
+                    # We don't need to lookup this key in the vf
+                    if key not in self._text_cache:
+                        # Extract this text from the vf
+                        vf_keys_needed.add(key)
+                    elif key not in self._annotations_cache:
+                        # We do need to annotate
+                        ann_keys_needed.add(key)
+                        next_parent_map[key] = self._parent_map[key]
                 else:
-                    self._num_needed_children[parent_key] = 1
-        self._parent_map.update(parent_map)
-        # _heads_provider does some graph caching, so it is only valid while
-        # self._parent_map hasn't changed
-        self._heads_provider = None
-        keys = parent_map.keys()
-        return keys
+                    parent_lookup.append(key)
+                    vf_keys_needed.add(key)
+            needed_keys = set()
+            next_parent_map.update(self._vf.get_parent_map(parent_lookup))
+            for key, parent_keys in next_parent_map.iteritems():
+                self._update_needed_children(key, parent_keys)
+                for key in parent_keys:
+                    if key not in parent_map:
+                        needed_keys.add(key)
+            parent_map.update(next_parent_map)
+            # _heads_provider does some graph caching, so it is only valid while
+            # self._parent_map hasn't changed
+            self._heads_provider = None
+        return vf_keys_needed, ann_keys_needed
 
     def _get_needed_texts(self, key, pb=None):
         """Get the texts we need to properly annotate key.
@@ -253,11 +308,12 @@
             matcher object we are using. Currently it is always 'lines' but
             future improvements may change this to a simple text string.
         """
-        keys = self._get_needed_keys(key)
+        keys, ann_keys = self._get_needed_keys(key)
         if pb is not None:
             pb.update('getting stream', 0, len(keys))
         stream  = self._vf.get_record_stream(keys, 'topological', True)
-        iterator = _NeededTextIterator(stream, self._text_cache, len(keys), pb)
+        iterator = _NeededTextIterator(stream, self._text_cache, len(keys),
+                                       ann_keys, pb)
         return iterator
 
     def _get_parent_annotations_and_matches(self, key, text, parent_key):
@@ -364,6 +420,9 @@
 
     def add_special_text(self, key, parent_keys, text):
         """Add a specific text to the graph."""
+        self._parent_map[key] = parent_keys
+        self._text_cache[key] = osutils.split_lines(text)
+        self._heads_provider = None
 
     def annotate(self, key):
         """Return annotated fulltext for the given key."""



More information about the bazaar-commits mailing list