changeset 75:466ebe5a157d

merged awesome changes from chris
author Scott Chacon <schacon@gmail.com>
date Fri, 01 May 2009 07:01:27 -0700
parents 7d5fbed25b36 (current diff) 805a42e84605 (diff)
children aa2dadf04144
files git_handler.py
diffstat 1 files changed, 64 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/git_handler.py
+++ b/git_handler.py
@@ -359,14 +359,16 @@
     def generate_pack_contents(self, want, have):
         graph_walker = SimpleFetchGraphWalker(want, self.git.get_parents)
         next = graph_walker.next()
-        shas = []
+        shas = set()
         while next:
             if next in have:
                 graph_walker.ack(next)
             else:
-                shas.append(next)
+                shas.add(next)
             next = graph_walker.next()
 
+        seen = []
+
         # so now i have the shas, need to turn them into a list of
         # tuples (sha, path) for ALL the objects i'm sending
         # TODO : don't send blobs or trees they already have
@@ -376,11 +378,15 @@
             for (mode, name, sha) in tree.entries():
                 if mode == 57344: # TODO : properly handle submodules
                     continue
+                if sha in seen:
+                    continue
+
                 obj = self.git.get_object(sha)
-                if isinstance (obj, Blob):
+                seen.append(sha)
+                if isinstance(obj, Blob):
                     changes.append((obj, path + name))
                 elif isinstance(obj, Tree):
-                    changes.extend (get_objects (obj, path + name + '/'))
+                    changes.extend(get_objects (obj, path + name + '/'))
             return changes
 
         objects = []
@@ -603,42 +609,64 @@
         self._shas.reverse()
         return self._shas
 
-    def strongly_connected_components(self, graph):
-        """ Find the strongly connected components in a graph using
-            Tarjan's algorithm.
+    def strongly_connected_components(self, G):
+        """Returns a list of strongly connected components in G.
+
+         Uses Tarjan's algorithm with Nuutila's modifications.
+         Nonrecursive version of algorithm.
 
-            graph should be a dictionary mapping node names to
-            lists of successor nodes.
-            """
+         References:
 
-        result = [ ]
-        stack = [ ]
-        low = { }
+          R. Tarjan (1972). Depth-first search and linear graph algorithms.
+          SIAM Journal of Computing 1(2):146-160.
 
-        def visit(node):
-            if node in low: return
+          E. Nuutila and E. Soisalon-Soinen (1994).
+          On finding the strongly connected components in a directed graph.
+          Information Processing Letters 49(1): 9-14.
 
-            num = len(low)
-            low[node] = num
-            stack_pos = len(stack)
-            stack.append(node)
-
-            for successor in graph[node].parents:
-                visit(successor)
-                low[node] = min(low[node], low[successor])
-
-            if num == low[node]:
-                component = tuple(stack[stack_pos:])
-                del stack[stack_pos:]
-                result.append(component)
-                for item in component:
-                    low[item] = len(graph)
-
-        for node in graph:
-            visit(node)
-
-        return result
-
+         """
+        preorder={}
+        lowlink={}
+        scc_found={}
+        scc_queue = []
+        scc_list=[]
+        i=0     # Preorder counter
+        for source in G:
+            if source not in scc_found:
+                queue=[source]
+                while queue:
+                    v=queue[-1]
+                    if v not in preorder:
+                        i=i+1
+                        preorder[v]=i
+                    done=1
+                    v_nbrs=G[v]
+                    for w in v_nbrs:
+                        if w not in preorder:
+                            queue.append(w)
+                            done=0
+                            break
+                    if done==1:
+                        lowlink[v]=preorder[v]
+                        for w in v_nbrs:
+                            if w not in scc_found:
+                                if preorder[w]>preorder[v]:
+                                    lowlink[v]=min([lowlink[v],lowlink[w]])
+                                else:
+                                    lowlink[v]=min([lowlink[v],preorder[w]])
+                        queue.pop()
+                        if lowlink[v]==preorder[v]:
+                            scc_found[v]=True
+                            scc=[v]
+                            while scc_queue and preorder[scc_queue[-1]]>preorder[v]:
+                                k=scc_queue.pop()
+                                scc_found[k]=True
+                                scc.append(k)
+                            scc_list.append(scc)
+                        else:
+                            scc_queue.append(v)
+        scc_list.sort(lambda x, y: cmp(len(y),len(x)))
+        return scc_list
 
     def topological_sort(self, graph):
         count = { }