diff --git a/git_handler.py b/git_handler.py index 7d5fbed25b36d86dc55d3354ca51e0269161a28d_Z2l0X2hhbmRsZXIucHk=..466ebe5a157dc1ab1c8964cdddb555870e539c65_Z2l0X2hhbmRsZXIucHk= 100644 --- a/git_handler.py +++ b/git_handler.py @@ -359,8 +359,8 @@ 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: @@ -363,7 +363,7 @@ while next: if next in have: graph_walker.ack(next) else: - shas.append(next) + shas.add(next) next = graph_walker.next() @@ -368,5 +368,7 @@ 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,4 +378,7 @@ 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) @@ -379,4 +384,5 @@ 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): @@ -381,6 +387,6 @@ 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,7 +609,9 @@ 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. @@ -609,5 +617,3 @@ - graph should be a dictionary mapping node names to - lists of successor nodes. - """ + References: @@ -613,5 +619,4 @@ - result = [ ] - stack = [ ] - low = { } + R. Tarjan (1972). Depth-first search and linear graph algorithms. + SIAM Journal of Computing 1(2):146-160. @@ -617,4 +622,5 @@ - 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. @@ -620,25 +626,47 @@ - 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 = { }