ruby-graphviz 0.9.7 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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