Skip to content

Commit

Permalink
Handle tails in dependency cycles
Browse files Browse the repository at this point in the history
  • Loading branch information
denisdefreyne committed Apr 22, 2017
1 parent bb63790 commit 6101135
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
37 changes: 26 additions & 11 deletions lib/nanoc/base/entities/directed_graph.rb
Expand Up @@ -159,17 +159,32 @@ def delete_vertex(v)
# @group Querying the graph

def any_cycle
path = [@vertices.keys.first]

loop do
nexts = direct_successors_of(path.last)
cycle_start_index = path.find_index { |node| nexts.include?(node) }
if cycle_start_index
break path[cycle_start_index..-1]
elsif nexts.empty?
break nil
else
path << nexts.sample
path_with_cycle = all_paths.lazy.find { |path| path.uniq != path }
if path_with_cycle
double_vertex = path_with_cycle.last
path_with_cycle[path_with_cycle.index(double_vertex)..-2]
end
end

def all_paths
Enumerator.new do |y|
@vertices.keys.each do |vertex|
dfs_from(vertex) do |path|
y << path
end
end
end
end

def dfs_from(vertex, path_so_far = [])
new_path = path_so_far + [vertex]
yield(new_path)

return if new_path.uniq != new_path

direct_successors_of(vertex).each do |next_vertex|
dfs_from(next_vertex, new_path) do |path|
yield(path)
end
end
end
Expand Down
12 changes: 12 additions & 0 deletions spec/nanoc/base/directed_graph_spec.rb
Expand Up @@ -27,6 +27,18 @@
it { is_expected.to eq([2, 3]) }
end

context 'one cycle with tail' do
before do
graph.add_edge(1, 2)
graph.add_edge(2, 20)
graph.add_edge(20, 21)
graph.add_edge(2, 3)
graph.add_edge(3, 1)
end

it { is_expected.to eq([1, 2, 3]) }
end

context 'large cycle' do
before do
graph.add_edge(1, 2)
Expand Down

0 comments on commit 6101135

Please sign in to comment.