graph 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig ADDED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,39 @@
1
+ === 2.0.0 / 2010-12-24
2
+
3
+ * 1 major enhancement:
4
+
5
+ * Graph is completely rewritten. It is no longer a Hash subclass.
6
+ Not backwards compatible! 147.3% more awesome.
7
+
8
+ * 27 minor enhancements:
9
+
10
+ * #save now defaults type to nil, pass "png" or whatever if you want an image.
11
+ * Added DepAnalyzer#decorate
12
+ * Added DepAnalyzer#setup
13
+ * Added Graph::Node and Graph::Edge to formalize the relationships.
14
+ * Added Graph#color(name), #shape(name), #style(name).
15
+ * Added Graph#colorscheme and #fillcolor.
16
+ * Added Graph#edge(name1, name2, name3 ...)
17
+ * Added Graph#font.
18
+ * Added Graph#label(name), Node#label(name) and Edge#label(name).
19
+ * Added Graph#node(name, label = nil)
20
+ * Added Graph#node_attribs and Graph#edge_attribs.
21
+ * Added Graph#subgraphs and Graph#<<(subgraph).
22
+ * Added Graph::Attribute with ability to decorate: red << node << edge
23
+ * Added a gallery of examples and a rake task to run them all.
24
+ * Added digraph { ... subgraph { ... } ... } DSL.
25
+ * Added homebrew dependency analyzer.
26
+ * Added shortcut methods for all styles, shapes, and the major colors.
27
+ * Added support for subgraphs: graph << subgraph.
28
+ * Insert-order is no longer maintained... this _may_ cause problems.
29
+ * Node#>> defined so the arrows can point the same way as in dot: n1 >> n2
30
+ * Removed Graph#prefix in favor of the more structured accessors.
31
+ * Renamed Graph#attribs to Graph#graph_attribs and it is now graph only.
32
+ * RubygemsAnalyzer now draws developer dependencies gray.
33
+ * RubygemsAnalyzer now has -a to graph all dependencies even if not installed.
34
+ * graph tool no longer opens by default.
35
+ * graph tool now has -o to `open` the output and -d to switch to the dotfile.
36
+
1
37
  === 1.2.0 / 2010-03-30
2
38
 
3
39
  * 10 minor enhancements:
data/Manifest.txt CHANGED
@@ -4,9 +4,15 @@ Manifest.txt
4
4
  README.txt
5
5
  Rakefile
6
6
  bin/graph
7
+ gallery/cluster.rb
8
+ gallery/fsm.rb
9
+ gallery/ruby_exceptions.rb
10
+ gallery/simple_example.rb
11
+ gallery/unix.rb
7
12
  lib/dep_analyzer.rb
8
13
  lib/freebsd_analyzer.rb
9
14
  lib/graph.rb
15
+ lib/homebrew_analyzer.rb
10
16
  lib/macports_analyzer.rb
11
17
  lib/rake_analyzer.rb
12
18
  lib/rubygems/commands/graph_command.rb
data/README.txt CHANGED
@@ -8,31 +8,34 @@ Graph is a type of hash that outputs in graphviz's dot format. It
8
8
  comes with a command-line interface that is easily pluggable.
9
9
 
10
10
  It ships with plugins to graph dependencies and status of installed
11
- rubygems, mac ports, and freebsd ports, coloring leaf nodes blue,
12
- outdated nodes red, and outdated leaf nodes purple (red+blue).
11
+ rubygems, rake tasks, homebrew ports, mac ports, and freebsd ports,
12
+ coloring leaf nodes blue, outdated nodes red, and outdated leaf nodes
13
+ purple (red+blue).
13
14
 
14
15
  == FEATURES/PROBLEMS:
15
16
 
16
- * Very easy hash interface.
17
- * Saves to dot and automatically converts to png (or whatever).
18
- * edge and node attributes are easy to set.
17
+ * Very clean DSL interface and API.
18
+ * Saves to dot and can automatically convert to png (or whatever).
19
+ * graph, edge, and node attributes are easy to set.
19
20
  * bin/graph includes a caching mechanism for slower fairly static data.
20
21
 
21
22
  == SYNOPSIS:
22
23
 
23
- deps = Graph.new
24
-
25
- ObjectSpace.each_object Class do |mod|
26
- next if mod.name =~ /Errno/
27
- next unless mod < Exception
28
- deps[mod.to_s] = mod.superclass.to_s
24
+ digraph do
25
+ # many ways to access/create edges and nodes
26
+ edge "a", "b"
27
+ self["b"]["c"]
28
+ node("c") >> "a"
29
+
30
+ square << node("a")
31
+ triangle << node("b")
32
+
33
+ red << node("a") << edge("a", "b")
34
+ green << node("b") << edge("b", "c")
35
+ blue << node("c") << edge("c", "a")
36
+
37
+ save "simple_example", "png"
29
38
  end
30
-
31
- deps.attribs["StandardError"] << "color = blue"
32
- deps.attribs["RuntimeError"] << "color = red"
33
- deps.prefix << "rankdir = BT" # put Exception on top
34
-
35
- deps.save "exceptions"
36
39
 
37
40
  == REQUIREMENTS:
38
41
 
@@ -46,7 +49,7 @@ outdated nodes red, and outdated leaf nodes purple (red+blue).
46
49
 
47
50
  (The MIT License)
48
51
 
49
- Copyright (c) 2009 Ryan Davis, seattle.rb
52
+ Copyright (c) Ryan Davis, seattle.rb
50
53
 
51
54
  Permission is hereby granted, free of charge, to any person obtaining
52
55
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -12,4 +12,22 @@ Hoe.spec 'graph' do
12
12
  self.rubyforge_name = 'seattlerb'
13
13
  end
14
14
 
15
+ gallery = Dir["gallery/*.rb"]
16
+ pngs = gallery.map { |f| f.sub(/\.rb$/, ".png") }
17
+ dots = gallery.map { |f| f.sub(/\.rb$/, ".dot") }
18
+
19
+ file pngs
20
+ file dots
21
+ task :gallery => pngs
22
+
23
+ rule ".png" => ".rb" do |t|
24
+ Dir.chdir "gallery" do
25
+ ruby "-I../lib #{File.basename t.source}"
26
+ end
27
+ end
28
+
29
+ task :clean do
30
+ rm_f Dir[*pngs] + Dir[*dots]
31
+ end
32
+
15
33
  # vim: syntax=Ruby
data/bin/graph CHANGED
@@ -1,4 +1,7 @@
1
- #!/usr/bin/env ruby -w
1
+ #!/usr/bin/env ruby -ws
2
+
3
+ $o ||= false
4
+ $d ||= false
2
5
 
3
6
  type = (ARGV.shift || "macports")
4
7
 
@@ -7,3 +10,5 @@ require "#{type}_analyzer"
7
10
  klass = Object.const_get "#{type.capitalize}Analyzer"
8
11
  analyzer = klass.new
9
12
  analyzer.run
13
+
14
+ system "open #{type.capitalize}Analyzer.#{$d ? "dot" : "png"}" if $o
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ # digraph G {
4
+ #
5
+ # subgraph cluster_0 {
6
+ # style=filled;
7
+ # color=lightgrey;
8
+ # node [style=filled,color=white];
9
+ # a0 -> a1 -> a2 -> a3;
10
+ # label = "process #1";
11
+ # }
12
+ #
13
+ # subgraph cluster_1 {
14
+ # node [style=filled];
15
+ # b0 -> b1 -> b2 -> b3;
16
+ # label = "process #2";
17
+ # color=blue
18
+ # }
19
+ # start -> a0;
20
+ # start -> b0;
21
+ # a1 -> b3;
22
+ # b2 -> a3;
23
+ # a3 -> a0;
24
+ # a3 -> end;
25
+ # b3 -> end;
26
+ #
27
+ # start [shape=Mdiamond];
28
+ # end [shape=Msquare];
29
+ # }
30
+
31
+ require "graph"
32
+
33
+ digraph do
34
+ # composite styles
35
+ leaf_node = white + filled
36
+
37
+ subgraph "cluster_0" do
38
+ label "process #1"
39
+ graph_attribs << filled << lightgray
40
+ node_attribs << leaf_node
41
+
42
+ edge "a0", "a1", "a2", "a3"
43
+ end
44
+
45
+ subgraph "cluster_1" do
46
+ label "process #2"
47
+ graph_attribs << blue
48
+ node_attribs << filled
49
+
50
+ edge "b0", "b1", "b2", "b3"
51
+ end
52
+
53
+ edge "start", "a0"
54
+ edge "start", "b0"
55
+ edge "a1", "b3"
56
+ edge "b2", "a3"
57
+ edge "a3", "a0"
58
+ edge "a3", "end"
59
+ edge "b3", "end"
60
+
61
+ mdiamond << node("start")
62
+ msquare << node("end")
63
+
64
+ save "cluster", "png"
65
+ end
66
+
data/gallery/fsm.rb ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # digraph finite_state_machine {
4
+ # rankdir=LR;
5
+ # size="8,5"
6
+ # node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
7
+ # node [shape = circle];
8
+ # LR_0 -> LR_2 [ label = "SS(B)" ];
9
+ # LR_0 -> LR_1 [ label = "SS(S)" ];
10
+ # LR_1 -> LR_3 [ label = "S($end)" ];
11
+ # LR_2 -> LR_6 [ label = "SS(b)" ];
12
+ # LR_2 -> LR_5 [ label = "SS(a)" ];
13
+ # LR_2 -> LR_4 [ label = "S(A)" ];
14
+ # LR_5 -> LR_7 [ label = "S(b)" ];
15
+ # LR_5 -> LR_5 [ label = "S(a)" ];
16
+ # LR_6 -> LR_6 [ label = "S(b)" ];
17
+ # LR_6 -> LR_5 [ label = "S(a)" ];
18
+ # LR_7 -> LR_8 [ label = "S(b)" ];
19
+ # LR_7 -> LR_5 [ label = "S(a)" ];
20
+ # LR_8 -> LR_6 [ label = "S(b)" ];
21
+ # LR_8 -> LR_5 [ label = "S(a)" ];
22
+ # }
23
+
24
+ require "graph"
25
+
26
+ digraph do
27
+ rotate
28
+ graph_attribs << 'size="8,5"'
29
+
30
+ node_attribs << circle
31
+ doublecircle << node("LR_0") << node("LR_3") << node("LR_4") << node("LR_8")
32
+
33
+ edge("LR_0", "LR_2").label "SS(B)"
34
+ edge("LR_0", "LR_1").label "SS(S)"
35
+ edge("LR_1", "LR_3").label "S($end)"
36
+ edge("LR_2", "LR_6").label "SS(b)"
37
+ edge("LR_2", "LR_5").label "SS(a)"
38
+ edge("LR_2", "LR_4").label "S(A)"
39
+ edge("LR_5", "LR_7").label "S(b)"
40
+ edge("LR_5", "LR_5").label "S(a)"
41
+ edge("LR_6", "LR_6").label "S(b)"
42
+ edge("LR_6", "LR_5").label "S(a)"
43
+ edge("LR_7", "LR_8").label "S(b)"
44
+ edge("LR_7", "LR_5").label "S(a)"
45
+ edge("LR_8", "LR_6").label "S(b)"
46
+ edge("LR_8", "LR_5").label "S(a)"
47
+
48
+ save "fsm", "png"
49
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ require "graph"
4
+
5
+ digraph do
6
+ rotate
7
+ boxes
8
+
9
+ ObjectSpace.each_object Class do |mod|
10
+ next if mod.name =~ /Errno/
11
+ next unless mod < Exception
12
+
13
+ edge mod.superclass.to_s, mod.to_s
14
+ end
15
+
16
+ blue << node("StandardError")
17
+ red << node("RuntimeError")
18
+
19
+ save "ruby_exceptions", "png"
20
+ end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ require 'graph'
4
+
5
+ digraph do
6
+ # many ways to access/create edges and nodes
7
+ edge "a", "b"
8
+ self["b"]["c"]
9
+ node("c") >> "a"
10
+
11
+ square << node("a")
12
+ triangle << node("b")
13
+
14
+ red << node("a") << edge("a", "b")
15
+ green << node("b") << edge("b", "c")
16
+ blue << node("c") << edge("c", "a")
17
+
18
+ save "simple_example", "png"
19
+ end
data/gallery/unix.rb ADDED
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ # /* courtesy Ian Darwin and Geoff Collyer, Softquad Inc. */
4
+ # digraph unix {
5
+ # size="6,6";
6
+ # node [color=lightblue2, style=filled];
7
+ # "5th Edition" -> "6th Edition";
8
+ # "5th Edition" -> "PWB 1.0";
9
+ # "6th Edition" -> "LSX";
10
+ # "6th Edition" -> "1 BSD";
11
+ # "6th Edition" -> "Mini Unix";
12
+ # "6th Edition" -> "Wollongong";
13
+ # "6th Edition" -> "Interdata";
14
+ # "Interdata" -> "Unix/TS 3.0";
15
+ # "Interdata" -> "PWB 2.0";
16
+ # "Interdata" -> "7th Edition";
17
+ # "7th Edition" -> "8th Edition";
18
+ # "7th Edition" -> "32V";
19
+ # "7th Edition" -> "V7M";
20
+ # "7th Edition" -> "Ultrix-11";
21
+ # "7th Edition" -> "Xenix";
22
+ # "7th Edition" -> "UniPlus+";
23
+ # "V7M" -> "Ultrix-11";
24
+ # "8th Edition" -> "9th Edition";
25
+ # "1 BSD" -> "2 BSD";
26
+ # "2 BSD" -> "2.8 BSD";
27
+ # "2.8 BSD" -> "Ultrix-11";
28
+ # "2.8 BSD" -> "2.9 BSD";
29
+ # "32V" -> "3 BSD";
30
+ # "3 BSD" -> "4 BSD";
31
+ # "4 BSD" -> "4.1 BSD";
32
+ # "4.1 BSD" -> "4.2 BSD";
33
+ # "4.1 BSD" -> "2.8 BSD";
34
+ # "4.1 BSD" -> "8th Edition";
35
+ # "4.2 BSD" -> "4.3 BSD";
36
+ # "4.2 BSD" -> "Ultrix-32";
37
+ # "PWB 1.0" -> "PWB 1.2";
38
+ # "PWB 1.0" -> "USG 1.0";
39
+ # "PWB 1.2" -> "PWB 2.0";
40
+ # "USG 1.0" -> "CB Unix 1";
41
+ # "USG 1.0" -> "USG 2.0";
42
+ # "CB Unix 1" -> "CB Unix 2";
43
+ # "CB Unix 2" -> "CB Unix 3";
44
+ # "CB Unix 3" -> "Unix/TS++";
45
+ # "CB Unix 3" -> "PDP-11 Sys V";
46
+ # "USG 2.0" -> "USG 3.0";
47
+ # "USG 3.0" -> "Unix/TS 3.0";
48
+ # "PWB 2.0" -> "Unix/TS 3.0";
49
+ # "Unix/TS 1.0" -> "Unix/TS 3.0";
50
+ # "Unix/TS 3.0" -> "TS 4.0";
51
+ # "Unix/TS++" -> "TS 4.0";
52
+ # "CB Unix 3" -> "TS 4.0";
53
+ # "TS 4.0" -> "System V.0";
54
+ # "System V.0" -> "System V.2";
55
+ # "System V.2" -> "System V.3";
56
+ # }
57
+
58
+ require "graph"
59
+
60
+ digraph "unix" do
61
+ graph_attribs << 'size="6,6"'
62
+ node_attribs << lightblue << filled
63
+
64
+ edge "5th Edition", "6th Edition"
65
+ edge "5th Edition", "PWB 1.0"
66
+ edge "6th Edition", "LSX"
67
+ edge "6th Edition", "1 BSD"
68
+ edge "6th Edition", "Mini Unix"
69
+ edge "6th Edition", "Wollongong"
70
+ edge "6th Edition", "Interdata"
71
+ edge "Interdata", "Unix/TS 3.0"
72
+ edge "Interdata", "PWB 2.0"
73
+ edge "Interdata", "7th Edition"
74
+ edge "7th Edition", "8th Edition"
75
+ edge "7th Edition", "32V"
76
+ edge "7th Edition", "V7M"
77
+ edge "7th Edition", "Ultrix-11"
78
+ edge "7th Edition", "Xenix"
79
+ edge "7th Edition", "UniPlus+"
80
+ edge "V7M", "Ultrix-11"
81
+ edge "8th Edition", "9th Edition"
82
+ edge "1 BSD", "2 BSD"
83
+ edge "2 BSD", "2.8 BSD"
84
+ edge "2.8 BSD", "Ultrix-11"
85
+ edge "2.8 BSD", "2.9 BSD"
86
+ edge "32V", "3 BSD"
87
+ edge "3 BSD", "4 BSD"
88
+ edge "4 BSD", "4.1 BSD"
89
+ edge "4.1 BSD", "4.2 BSD"
90
+ edge "4.1 BSD", "2.8 BSD"
91
+ edge "4.1 BSD", "8th Edition"
92
+ edge "4.2 BSD", "4.3 BSD"
93
+ edge "4.2 BSD", "Ultrix-32"
94
+ edge "PWB 1.0", "PWB 1.2"
95
+ edge "PWB 1.0", "USG 1.0"
96
+ edge "PWB 1.2", "PWB 2.0"
97
+ edge "USG 1.0", "CB Unix 1"
98
+ edge "USG 1.0", "USG 2.0"
99
+ edge "CB Unix 1", "CB Unix 2"
100
+ edge "CB Unix 2", "CB Unix 3"
101
+ edge "CB Unix 3", "Unix/TS++"
102
+ edge "CB Unix 3", "PDP-11 Sys V"
103
+ edge "USG 2.0", "USG 3.0"
104
+ edge "USG 3.0", "Unix/TS 3.0"
105
+ edge "PWB 2.0", "Unix/TS 3.0"
106
+ edge "Unix/TS 1.0", "Unix/TS 3.0"
107
+ edge "Unix/TS 3.0", "TS 4.0"
108
+ edge "Unix/TS++", "TS 4.0"
109
+ edge "CB Unix 3", "TS 4.0"
110
+ edge "TS 4.0", "System V.0"
111
+ edge "System V.0", "System V.2"
112
+ edge "System V.2", "System V.3"
113
+
114
+ save "unix", "png"
115
+ end
data/lib/dep_analyzer.rb CHANGED
@@ -76,12 +76,32 @@ class Hash
76
76
  end
77
77
 
78
78
  class DepAnalyzer < Cache
79
+ attr_accessor :g
80
+
79
81
  def initialize
80
82
  super ".#{self.class}.cache"
83
+ @g = Graph.new
84
+ end
85
+
86
+ def decorate
87
+ # nothing to do by default
88
+ end
89
+
90
+ def deps port
91
+ raise NotImplementedError, "subclass responsibility"
92
+ end
93
+
94
+ def installed
95
+ raise NotImplementedError, "subclass responsibility"
96
+ end
97
+
98
+ def outdated
99
+ raise NotImplementedError, "subclass responsibility"
81
100
  end
82
101
 
83
102
  def run(argv = ARGV)
84
- g = Graph.new
103
+ setup
104
+
85
105
  ports = {}
86
106
  installed.each do |port|
87
107
  ports[port] = nil
@@ -104,18 +124,25 @@ class DepAnalyzer < Cache
104
124
  ports[port] = deps
105
125
  end
106
126
 
127
+ blue = g.color "blue"
128
+ purple = g.color "purple4"
129
+ red = g.color "red"
130
+
107
131
  indies = ports.keys - ports.minvert.keys
108
132
  indies.each do |k|
109
- g.attribs[k] << "color = blue"
133
+ blue << g[k]
110
134
  end
135
+
111
136
  old.each do |k,v|
112
137
  if indies.include? k then
113
- g.attribs[k] << "color = purple4"
138
+ purple << g[k]
114
139
  else
115
- g.attribs[k] << "color = red"
140
+ red << g[k]
116
141
  end
117
142
  end
118
143
 
144
+ decorate
145
+
119
146
  puts "Looks like you can nuke:\n\t#{indies.sort.join("\n\t")}"
120
147
 
121
148
  unless argv.empty? then
@@ -133,8 +160,11 @@ class DepAnalyzer < Cache
133
160
  end
134
161
  end
135
162
 
136
- g.save "#{self.class}"
137
- system "open #{self.class}.png"
163
+ g.save "#{self.class}", "png"
164
+ end
165
+
166
+ def setup
167
+ # nothing to do by default
138
168
  end
139
169
  end
140
170