ruby-graphviz 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
data/AUTHORS CHANGED
@@ -4,6 +4,8 @@ Dave Burt <http://github.com/dburt>
4
4
  Miguel Cabrera <http://mfcabrera.com>
5
5
  obruening <http://github.com/obruening>
6
6
  reactive <http://github.com/reactive>
7
+ Hugh Sasse <hgs@dmu.ac.uk>
8
+ axgle <http://github.com/axgle>
7
9
 
8
10
  Thanks to :
9
11
 
data/ChangeLog.rdoc CHANGED
@@ -1,3 +1,12 @@
1
+ 0.9.8 :
2
+ * Update graph and node posibility to set properties (see sample28.rb)
3
+ * Issue #7: Path option is never being used to find the executable
4
+ * Adding classes to check if the attributes are in the correct type
5
+ * Issue #8: dots in href are escaped with backslash, which corrupts the URL (see sample29.rb)
6
+ * Add posibility to use external libraries (see sample30.rb)
7
+ * Add options -u and -s to ruby2gv
8
+ * Add gem2gv
9
+
1
10
  0.9.7 :
2
11
  * Issue #2: Small bug correction in escape_path_containing_blanks (by Andreas Ronge)
3
12
  * Issue #4: New find_executable (by reactive)
data/README.rdoc CHANGED
@@ -4,6 +4,7 @@ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Gregoire Lejeune
4
4
 
5
5
  * Doc : http://rdoc.info/projects/glejeune/Ruby-Graphviz
6
6
  * Sources : http://github.com/glejeune/Ruby-Graphviz
7
+ * Continuous Integration : http://runcoderun.com/glejeune/Ruby-Graphviz
7
8
 
8
9
  == DESCRIPTION
9
10
 
@@ -52,6 +53,16 @@ Create a graph from a file
52
53
  }
53
54
  }.output(:png => "sample.png")
54
55
 
56
+ Ruby/GraphViz also include :
57
+
58
+ * ruby2gv, a simple tool that's allow you to create a dependency graph from a ruby script. Example : http://drp.ly/dShaZ
59
+
60
+ ruby2gv -Tpng -oruby2gv.png ruby2gv
61
+
62
+ * gem2gv, a tools that's allow you to create a dependency graph between gems. Example : http://drp.ly/dSj9Y
63
+
64
+ gem2gv -Tpng -oruby-graphviz.png ruby-graphviz
65
+
55
66
  == INSTALLATION
56
67
 
57
68
  sudo gem install ruby-graphviz
data/bin/gem2gv ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (C) 2010 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require 'rubygems'
19
+ require 'graphviz'
20
+ require 'getoptlong'
21
+
22
+ class Gem2Gv
23
+ def initialize( xGVPath, xUse )
24
+ @oGraph = GraphViz::new( :G, :path => xGVPath, :use => xUse )
25
+
26
+ @nodes = []
27
+ @name = 'gem2gv'
28
+ end
29
+
30
+ def out( xFormat = "dot", xFile = nil )
31
+ if xFile.nil? == true
32
+ @oGraph.output( xFormat => String )
33
+ else
34
+ @oGraph.output( xFormat => xFile )
35
+ end
36
+ end
37
+
38
+ def go( gemName, version = ">0" )
39
+ nodes = getDependency(gemName, version)
40
+
41
+ createEdges( gemName, version, nodes )
42
+
43
+ nodes.each do |node|
44
+ unless @nodes.include?(node)
45
+ @nodes << node
46
+ go( node[:name], node[:version] )
47
+ end
48
+ end
49
+ end
50
+
51
+ def getDependency( gemName, version = ">0" )
52
+ nodes = []
53
+
54
+ dependency = Gem::Dependency.new( gemName, version )
55
+ fetcher = Gem::SpecFetcher.fetcher
56
+
57
+ fetcher.find_matching(dependency).each do |spec_tuple, source_uri|
58
+ spec = fetcher.fetch_spec spec_tuple, URI.parse(source_uri)
59
+
60
+ spec.dependencies.each do |dep|
61
+ #nodes << { :name => dep.name, :version => dep.version_requirements.to_s} unless nodes.include?({ :name => dep.name, :version => dep.version_requirements.to_s})
62
+ nodes << { :name => dep.name, :version => ">0" } unless nodes.include?({ :name => dep.name, :version => ">0" })
63
+ end
64
+ end
65
+
66
+ return nodes
67
+ end
68
+
69
+ def getNode( name, version )
70
+ #nodeName = "#{name}#{version}"
71
+ #nodeLabel = "#{name}\n#{version}"
72
+ nodeName = "#{name}"
73
+ nodeLabel = "#{name}"
74
+ return @oGraph.get_node(nodeName) || @oGraph.add_node( nodeName, "label" => nodeLabel )
75
+ end
76
+
77
+ def createEdges( gemName, version, nodes )
78
+ nodeA = getNode( gemName, version )
79
+
80
+ nodes.each do |node|
81
+ nodeB = getNode( node[:name], node[:version] )
82
+ @oGraph.add_edge( nodeA, nodeB )
83
+ end
84
+ end
85
+ end
86
+
87
+ def usage
88
+ puts "usage: gem2gv [-Tformat] [-ofile] [-h] [-V] gemname"
89
+ puts "-T, --output-format format Output format (default: PNG)"
90
+ puts "-o, --output-file file Output file (default: STDOUT)"
91
+ puts "-p, --path Graphviz path"
92
+ puts "-u, --use PROGRAM Program to use (default: dot)"
93
+ puts "-s, --stop LIB[,LIB, ...] Stop on libs"
94
+ puts "-V, --version Show version"
95
+ puts "-h, --help Show this usage message"
96
+ end
97
+
98
+ def version
99
+ puts "Gem2GraphViz v#{Constants::RGV_VERSION}, (c)2010 Gregoire Lejeune <gregoire.lejeune@free.fr>"
100
+ puts ""
101
+ puts "This program is free software; you can redistribute it and/or modify"
102
+ puts "it under the terms of the GNU General Public License as published by"
103
+ puts "the Free Software Foundation; either version 2 of the License, or"
104
+ puts "(at your option) any later version."
105
+ puts ""
106
+ puts "This program is distributed in the hope that it will be useful,"
107
+ puts "but WITHOUT ANY WARRANTY; without even the implied warranty of"
108
+ puts "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
109
+ puts "GNU General Public License for more details."
110
+ puts ""
111
+ puts "You should have received a copy of the GNU General Public License"
112
+ puts "along with this program; if not, write to the Free Software"
113
+ puts "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"
114
+ end
115
+
116
+ xOutFormat = "png"
117
+ xOutFile = nil
118
+ xGVPath = ""
119
+ xUse = "dot"
120
+ xStops = []
121
+
122
+ oOpt = GetoptLong.new(
123
+ ['--output-format', '-T', GetoptLong::REQUIRED_ARGUMENT],
124
+ ['--output-file', '-o', GetoptLong::REQUIRED_ARGUMENT],
125
+ ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT],
126
+ ['--use', '-u', GetoptLong::REQUIRED_ARGUMENT],
127
+ ['--help', '-h', GetoptLong::NO_ARGUMENT],
128
+ ['--version', '-V', GetoptLong::NO_ARGUMENT]
129
+ )
130
+
131
+ begin
132
+ oOpt.each_option do |xOpt, xValue|
133
+ case xOpt
134
+ when '--output-format'
135
+ xOutFormat = xValue
136
+ when '--output-file'
137
+ xOutFile = xValue
138
+ when '--path'
139
+ xGVPath = xValue
140
+ when '--use'
141
+ xUse = xValue
142
+ when '--help'
143
+ usage( )
144
+ exit
145
+ when '--version'
146
+ version( )
147
+ exit
148
+ end
149
+ end
150
+ rescue GetoptLong::InvalidOption => e
151
+ usage( )
152
+ exit
153
+ end
154
+
155
+ xGem = ARGV[0]
156
+
157
+ if xGem.nil? == true
158
+ usage( )
159
+ exit
160
+ end
161
+
162
+
163
+ g = Gem2Gv.new( xGVPath, xUse )
164
+ g.go( xGem )
165
+ result = g.out( xOutFormat, xOutFile )
166
+ puts result unless result.nil?
data/bin/ruby2gv CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # Copyright (C) 2005, 2006, 2007 Gregoire Lejeune <gregoire.lejeune@free.fr>
2
+ # Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Gregoire Lejeune <gregoire.lejeune@free.fr>
3
3
  #
4
4
  # This program is free software; you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -15,26 +15,29 @@
15
15
  # along with this program; if not, write to the Free Software
16
16
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
 
18
+ require 'rubygems'
18
19
  require 'getoptlong'
19
20
  require 'graphviz'
20
- require "graphviz/constants"
21
+ require 'graphviz/constants'
21
22
  require 'rbconfig'
23
+ require 'mkmf'
22
24
 
23
25
  DEBUG = false
24
26
 
25
27
  class Rb2Gv
26
- REQUIRE = /^\s*require\s*("|')([^\1]*)(\1)/
28
+ REQUIRE = /^\s*require\s*("|')([^\1\s]*)(\1)/
27
29
 
28
- def initialize( xGVPath )
29
- @oGraph = GraphViz::new( "G", :path => xGVPath )
30
- @oGraph['size'] = '10,10'
30
+ def initialize( xGVPath, xUse = "dot", xStops = [] )
31
+ @oGraph = GraphViz::new( "G", :path => xGVPath, :use => xUse )
32
+ # @oGraph['size'] = '10,10'
31
33
  @hxNodes = Hash::new( )
32
- @hxEdge = Hash::new( )
34
+ @hxEdge = Array::new( )
35
+ @lxStops = xStops
33
36
  end
34
37
 
35
38
  public
36
39
  def parse( xFile )
37
- @hxNodes[xFile] = gv_newNode( xFile )
40
+ @hxNodes[xFile] = gv_newNode( xFile, "box", "forestgreen" )
38
41
  puts "+ Node #{xFile}" if DEBUG
39
42
 
40
43
  parseFile( xFile, nil, xFile )
@@ -42,14 +45,14 @@ class Rb2Gv
42
45
 
43
46
  def out( xFormat = "dot", xFile = nil )
44
47
  if xFile.nil? == true
45
- @oGraph.output( "output" => xFormat )
48
+ @oGraph.output( xFormat => String )
46
49
  else
47
- @oGraph.output( "output" => xFormat, "file" => xFile )
50
+ @oGraph.output( xFormat => xFile )
48
51
  end
49
52
  end
50
53
 
51
54
  private
52
- def gv_newNode( xNode, xShape = "box", xColor = nil )
55
+ def gv_newNode( xNode, xShape = "box", xColor = nil )
53
56
  xNodeName = xNode.gsub( /[^a-zA-Z0-9]/, "_" )
54
57
  if xColor.nil? == true
55
58
  @oGraph.add_node( xNodeName, "label" => xNode, "shape" => xShape )
@@ -58,20 +61,43 @@ class Rb2Gv
58
61
  end
59
62
  end
60
63
 
61
- def getLibraryPath( xLib, xExt = "rb" )
64
+ def getLibraryPath( xLib, xExt = ["rb"] )
65
+
62
66
  xPath = [ "libexecdir", "libdir", "sitedir", "rubylibdir", "sitelibdir", "archdir", "sitedir", "sitearchdir" ]
63
67
  xRbLib = with_config( xLib+'lib', xLib)
64
- if /\.(rb|so)$/.match( xRbLib )
65
- xRbFile = xRbLib
68
+
69
+ if /\.(rb|so|bundle|dll)$/.match( xRbLib )
70
+ match = /^(.*)\.([^\.]*)$/.match(xRbLib)
71
+ xRbFile, xExt = match[1], [match[2]]
66
72
  else
67
- xRbFile = xRbLib + "." + xExt
73
+ xRbFile = xRbLib
68
74
  end
69
75
 
70
- xPath.each do |xDir|
71
- xCurrentPath = Config::expand( Config::CONFIG[xDir] )
72
- xFileFound = File.join( xCurrentPath, xRbFile )
73
- if File.exist?( xFileFound )
74
- return xFileFound
76
+ xExt.each do |e|
77
+ xRbFileWithExt = xRbFile + "." + e
78
+
79
+ # Search in "standard" paths
80
+ xPath.each do |xDir|
81
+ xCurrentPath = Config::expand( Config::CONFIG[xDir] )
82
+ xFileFound = File.join( xCurrentPath, xRbFileWithExt )
83
+ if File.exist?( xFileFound )
84
+ return xFileFound
85
+ end
86
+ end
87
+
88
+ # Search in "rubygems" :: This is not utile but...
89
+ spec = Gem.searcher.find(xLib)
90
+ unless spec.nil?
91
+ spec.require_paths.unshift spec.bindir if spec.bindir
92
+ xPath = spec.require_paths.map do |path|
93
+ File.join spec.full_gem_path, path
94
+ end
95
+ xPath.each do |xCurrentPath|
96
+ xFileFound = File.join( xCurrentPath, xRbFileWithExt )
97
+ if File.exist?( xFileFound )
98
+ return xFileFound
99
+ end
100
+ end
75
101
  end
76
102
  end
77
103
 
@@ -92,28 +118,34 @@ class Rb2Gv
92
118
 
93
119
  xData.each do |xLine|
94
120
  if lxLineMatch = REQUIRE.match( xLine )
95
- xRequiredLib = lxLineMatch[2]
121
+ xRequiredLib = lxLineMatch[2].gsub( /\.(rb|so)$/, "" )
96
122
 
97
123
  if @hxNodes.has_key?( xRequiredLib ) == false
98
124
  puts " + Node #{xRequiredLib}" if DEBUG
99
125
 
100
126
  xRequiredFile = getLibraryPath( xRequiredLib )
101
127
  if xRequiredFile.nil? == false
102
- @hxNodes[xRequiredLib] = gv_newNode( xRequiredLib )
103
- parseFile( xRequiredFile, xFile, xRequiredLib )
128
+ unless @lxStops.include?(xRequiredLib)
129
+ @hxNodes[xRequiredLib] = gv_newNode( xRequiredLib )
130
+ parseFile( xRequiredFile, xFile, xRequiredLib )
131
+ else
132
+ @hxNodes[xRequiredLib] = gv_newNode( xRequiredLib, "invhouse", "deepskyblue" )
133
+ end
104
134
  else
105
- if getLibraryPath( xRequiredLib, "so" ).nil? == false
106
- @hxNodes[xRequiredLib] = gv_newNode( xRequiredLib, "ellipse" )
135
+ if (v = getLibraryPath( xRequiredLib, ["so", "bundle", "dll"] )) == nil
136
+ @hxNodes[xRequiredLib] = gv_newNode( xRequiredLib, "box", "red" )
107
137
  else
108
- @hxNodes[xRequiredLib] = gv_newNode( xRequiredLib, "ellipse", "red" )
138
+ @hxNodes[xRequiredLib] = gv_newNode( xRequiredLib, "box", "grey" )
109
139
  end
110
140
  end
111
141
 
112
142
  end
113
143
 
114
144
  puts " + Edge #{xLib} -> #{xRequiredLib}" if DEBUG
115
- @oGraph.add_edge( @hxNodes[xLib], @hxNodes[xRequiredLib] )
116
-
145
+ unless @hxEdge.include?( "#{@hxNodes[xLib].name}-#{@hxNodes[xRequiredLib].name}" )
146
+ @oGraph.add_edge( @hxNodes[xLib], @hxNodes[xRequiredLib] )
147
+ @hxEdge << "#{@hxNodes[xLib].name}-#{@hxNodes[xRequiredLib].name}"
148
+ end
117
149
  end
118
150
  end
119
151
 
@@ -122,16 +154,18 @@ class Rb2Gv
122
154
  end
123
155
 
124
156
  def usage
125
- puts "usage: ruby2gv.rb [-Tformat] [-ofile] [-h] [-V] script"
157
+ puts "usage: ruby2gv [-Tformat] [-ofile] [-h] [-V] script"
126
158
  puts "-T, --output-format format Output format (default: PNG)"
127
159
  puts "-o, --output-file file Output file (default: STDOUT)"
128
160
  puts "-p, --path Graphviz path"
161
+ puts "-u, --use PROGRAM Program to use (default: dot)"
162
+ puts "-s, --stop LIB[,LIB, ...] Stop on libs"
129
163
  puts "-V, --version Show version"
130
164
  puts "-h, --help Show this usage message"
131
165
  end
132
166
 
133
167
  def version
134
- puts "Ruby2GraphViz v#{Constants::RGV_VERSION}, (c)2005 Gregoire Lejeune <gregoire.lejeune@free.fr>"
168
+ puts "Ruby2GraphViz v#{Constants::RGV_VERSION}, (c)2005, 2009, 2010 Gregoire Lejeune <gregoire.lejeune@free.fr>"
135
169
  puts ""
136
170
  puts "This program is free software; you can redistribute it and/or modify"
137
171
  puts "it under the terms of the GNU General Public License as published by"
@@ -150,12 +184,16 @@ end
150
184
 
151
185
  xOutFormat = "png"
152
186
  xOutFile = nil
153
- xGVPath = nil
187
+ xGVPath = ""
188
+ xUse = "dot"
189
+ xStops = []
154
190
 
155
191
  oOpt = GetoptLong.new(
156
192
  ['--output-format', '-T', GetoptLong::REQUIRED_ARGUMENT],
157
193
  ['--output-file', '-o', GetoptLong::REQUIRED_ARGUMENT],
158
194
  ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT],
195
+ ['--use', '-u', GetoptLong::REQUIRED_ARGUMENT],
196
+ ['--stop', '-s', GetoptLong::REQUIRED_ARGUMENT],
159
197
  ['--help', '-h', GetoptLong::NO_ARGUMENT],
160
198
  ['--version', '-V', GetoptLong::NO_ARGUMENT]
161
199
  )
@@ -169,6 +207,10 @@ begin
169
207
  xOutFile = xValue
170
208
  when '--path'
171
209
  xGVPath = xValue
210
+ when '--use'
211
+ xUse = xValue
212
+ when '--stop'
213
+ xStops = xValue.split( "," ).map{ |x| x.strip }
172
214
  when '--help'
173
215
  usage( )
174
216
  exit
@@ -189,6 +231,7 @@ if xFile.nil? == true
189
231
  exit
190
232
  end
191
233
 
192
- o = Rb2Gv::new( xGVPath )
234
+ o = Rb2Gv::new( xGVPath, xUse, xStops )
193
235
  o.parse( xFile )
194
- o.out( xOutFormat, xOutFile )
236
+ result = o.out( xOutFormat, xOutFile )
237
+ puts result unless result.nil?
@@ -7,7 +7,14 @@ g.node["shape"] = "plaintext"
7
7
 
8
8
  g.add_node( "HTML" )
9
9
 
10
- g.add_node( "struct1", "html" => '<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD>left</TD><TD PORT="f1">mid dle</TD><TD PORT="f2">right</TD></TR> </TABLE>>]; struct2 [label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD PORT="f0">one</TD><TD>two</TD></TR> </TABLE>')
10
+ g.add_node( "struct1", "html" => '
11
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
12
+ <TR>
13
+ <TD>left</TD>
14
+ <TD PORT="f1">mid dle</TD>
15
+ <TD PORT="f2">right</TD>
16
+ </TR>
17
+ </TABLE>' )
11
18
 
12
19
  g.add_node( "struct2", "html" => '<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD PORT="f0">one</TD><TD>two</TD></TR> </TABLE>' )
13
20
  g.add_node( "struct3", "html" => '<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4"> <TR> <TD ROWSPAN="3">hello<BR/>world</TD> <TD COLSPAN="3">b</TD> <TD ROWSPAN="3">g</TD> <TD ROWSPAN="3">h</TD> </TR> <TR> <TD>c</TD><TD PORT="here">d</TD><TD>e</TD> </TR> <TR> <TD COLSPAN="3">f</TD> </TR> </TABLE>' )
@@ -10,5 +10,5 @@ GraphViz.parse( "hello.dot", :path => "/usr/local/bin" ) { |g|
10
10
  g.get_node("World") { |n|
11
11
  n.label = "Le Monde"
12
12
  }
13
- }.output(:png => "sample.png")
13
+ }.output(:png => "#{$0}.png")
14
14