summaryrefslogtreecommitdiff
path: root/lib/bundler/graph.rb
diff options
context:
space:
mode:
authorKevin Moore <kevin@thinkpixellab.com>2010-05-13 01:31:24 -0700
committerKevin Moore <kevin@thinkpixellab.com>2010-05-24 00:16:38 -0500
commitf4148898f614032dbadfbd3b0aa9cbd1a757a489 (patch)
tree3f4846294136e81466d70a3bf2d046a213019e49 /lib/bundler/graph.rb
parent7ef704d19604f1b60b482badc3a4fb6ef2e32488 (diff)
downloadbundler-f4148898f614032dbadfbd3b0aa9cbd1a757a489.tar.gz
'bundle viz'
Removed silly 'puts' in cli Fake Gem::Requirement.none? [not in Gem < 1.3.7]
Diffstat (limited to 'lib/bundler/graph.rb')
-rw-r--r--lib/bundler/graph.rb130
1 files changed, 130 insertions, 0 deletions
diff --git a/lib/bundler/graph.rb b/lib/bundler/graph.rb
new file mode 100644
index 0000000000..0e8e28a6aa
--- /dev/null
+++ b/lib/bundler/graph.rb
@@ -0,0 +1,130 @@
+module Bundler
+ class Graph
+
+ USER_OPTIONS = {:style => 'filled, bold', :fillcolor => '#cccccc'}.freeze
+
+ def initialize(env)
+ @env = env
+ end
+
+ def nodes
+ populate
+ @nodes
+ end
+
+ def groups
+ populate
+ @groups
+ end
+
+ def viz(output_file, show_gem_versions = false, show_dependency_requirements = false)
+ require 'graphviz'
+ populate
+
+ graph_viz = GraphViz::new('Gemfile', {:concentrate => true, :dpi => 65 } )
+ graph_viz.edge[:fontname] = graph_viz.node[:fontname] = 'Arial, Helvetica, SansSerif'
+ graph_viz.edge[:fontsize] = 12
+
+ viz_nodes = {}
+
+ # populate all of the nodes
+ nodes.each do |name, node|
+ label = name.dup
+ label << "\n#{node.version}" if show_gem_versions
+ options = { :label => label }
+ options.merge!( USER_OPTIONS ) if node.is_user
+ viz_nodes[name] = graph_viz.add_node( name, options )
+ end
+
+ group_nodes = {}
+ @groups.each do |name, dependencies|
+ group_nodes[name] = graph_viz.add_node(name.to_s, { :shape => 'folder', :fontsize => 16 }.merge(USER_OPTIONS))
+ dependencies.each do |dependency|
+ options = { :weight => 2 }
+ if show_dependency_requirements && (dependency.requirement.to_s != ">= 0")
+ options[:label] = dependency.requirement.to_s
+ end
+ graph_viz.add_edge( group_nodes[name], viz_nodes[dependency.name], options )
+ end
+ end
+
+ @groups.keys.select { |group| group != :default }.each do |group|
+ graph_viz.add_edge( group_nodes[group], group_nodes[:default], { :weight => 2 } )
+ end
+
+ viz_nodes.each do |name, node|
+ nodes[name].dependencies.each do |dependency|
+ options = { }
+ if nodes[dependency.name].is_user
+ options[:constraint] = false
+ end
+ if show_dependency_requirements && (dependency.requirement.to_s != ">= 0")
+ options[:label] = dependency.requirement.to_s
+ end
+
+ graph_viz.add_edge( node, viz_nodes[dependency.name], options )
+ end
+ end
+
+ graph_viz.output( :png => output_file )
+ end
+
+ private
+
+ def populate
+ return if @populated
+
+ # hash of name => GraphNode
+ @nodes = {}
+ @groups = {}
+
+ # Populate @nodes
+ @env.specs.each { |spec| @nodes[spec.name] = GraphNode.new(spec.name, spec.version) }
+
+ # For gems in Gemfile, add details
+ @env.dependencies.each do |dependency|
+ node = @nodes[dependency.name]
+ node.is_user = true
+
+ dependency.groups.each do |group|
+ if @groups.has_key? group
+ group = @groups[group]
+ else
+ group = @groups[group] = []
+ end
+ group << dependency
+ end
+ end
+
+ # walk though a final time and add edges
+ @env.specs.each do |spec|
+
+ from = @nodes[spec.name]
+ spec.runtime_dependencies.each do |dependency|
+ from.dependencies << dependency
+ end
+
+ end
+
+ @nodes.freeze
+ @groups.freeze
+ @populated = true
+ end
+
+ end
+
+ # Add version info
+ class GraphNode
+
+ def initialize(name, version)
+ @name = name
+ @version = version
+ @is_user = false
+ @dependencies = []
+ end
+
+ attr_reader :name, :dependencies, :version
+ attr_accessor :is_user
+
+ end
+end