1 # frozen_string_literal: true
8 def initialize(env, output_file, show_version = false, show_requirements = false, output_format = "png", without = [])
10 @output_file = output_file
11 @show_version = show_version
12 @show_requirements = show_requirements
13 @output_format = output_format
14 @without_groups = without.map(&:to_sym)
17 @relations = Hash.new {|h, k| h[k] = Set.new }
24 attr_reader :groups, :relations, :node_options, :edge_options, :output_file, :output_format
27 GraphVizClient.new(self).run
32 def _populate_relations
33 parent_dependencies = _groups.values.to_set.flatten
35 break if parent_dependencies.empty?
38 parent_dependencies.each do |dependency|
39 child_dependencies = spec_for_dependency(dependency).runtime_dependencies.to_set
40 @relations[dependency.name] += child_dependencies.map(&:name).to_set
41 tmp += child_dependencies
43 @node_options[dependency.name] = _make_label(dependency, :node)
44 child_dependencies.each do |c_dependency|
45 @edge_options["#{dependency.name}_#{c_dependency.name}"] = _make_label(c_dependency, :edge)
48 parent_dependencies = tmp
53 relations = Hash.new {|h, k| h[k] = Set.new }
54 @env.current_dependencies.each do |dependency|
55 dependency.groups.each do |group|
56 next if @without_groups.include?(group)
58 relations[group.to_s].add(dependency)
59 @relations[group.to_s].add(dependency.name)
61 @node_options[group.to_s] ||= _make_label(group, :node)
62 @edge_options["#{group}_#{dependency.name}"] = _make_label(dependency, :edge)
65 @groups = relations.keys
69 def _make_label(symbol_or_string_or_dependency, element_type)
70 case element_type.to_sym
72 if symbol_or_string_or_dependency.is_a?(Gem::Dependency)
73 label = symbol_or_string_or_dependency.name.dup
74 label << "\n#{spec_for_dependency(symbol_or_string_or_dependency).version}" if @show_version
76 label = symbol_or_string_or_dependency.to_s
80 if symbol_or_string_or_dependency.respond_to?(:requirements_list) && @show_requirements
81 tmp = symbol_or_string_or_dependency.requirements_list.join(", ")
82 label = tmp if tmp != ">= 0"
85 raise ArgumentError, "2nd argument is invalid"
87 label.nil? ? {} : { label: label }
90 def spec_for_dependency(dependency)
91 @env.requested_specs.find {|s| s.name == dependency.name }
95 def initialize(graph_instance)
96 @graph_name = graph_instance.class::GRAPH_NAME
97 @groups = graph_instance.groups
98 @relations = graph_instance.relations
99 @node_options = graph_instance.node_options
100 @edge_options = graph_instance.edge_options
101 @output_file = graph_instance.output_file
102 @output_format = graph_instance.output_format
106 @g ||= ::GraphViz.digraph(@graph_name, concentrate: true, normalize: true, nodesep: 0.55) do |g|
108 g.edge[:fontname] = g.node[:fontname] = "Arial, Helvetica, SansSerif"
109 g.edge[:fontsize] = 12
114 @groups.each do |group|
118 fillcolor: "#B9B9D5",
121 }.merge(@node_options[group])
125 @relations.each do |parent, children|
126 children.each do |child|
127 if @groups.include?(parent)
128 g.add_nodes(child, { style: "filled", fillcolor: "#B9B9D5" }.merge(@node_options[child]))
129 g.add_edges(parent, child, { constraint: false }.merge(@edge_options["#{parent}_#{child}"]))
131 g.add_nodes(child, @node_options[child])
132 g.add_edges(parent, child, @edge_options["#{parent}_#{child}"])
137 if @output_format.to_s == "debug"
138 $stdout.puts g.output none: String
139 Bundler.ui.info "debugging bundle viz..."
142 g.output @output_format.to_sym => "#{@output_file}.#{@output_format}"
143 Bundler.ui.info "#{@output_file}.#{@output_format}"
144 rescue ArgumentError => e
145 warn "Unsupported output format. See Ruby-Graphviz/lib/graphviz/constants.rb"