DepGraph 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +18 -0
- data/Manifest.txt +16 -11
- data/bin/depgraph +26 -13
- data/config/hoe.rb +2 -2
- data/lib/DepGraph/version.rb +1 -1
- data/lib/{dependable_filter_manager.rb → dependency_types_manager.rb} +10 -10
- data/lib/file_system_node_finder.rb +60 -0
- data/lib/graph_creator.rb +83 -46
- data/lib/{graph.rb → graph_image_creator.rb} +48 -12
- data/lib/node.rb +44 -0
- data/lib/nodefinders/test_node_finder.rb +26 -0
- data/setup.rb +1585 -1585
- data/spec/{depgraph_spec.rb → IntegrationTests/depgraph_spec.rb} +28 -2
- data/spec/IntegrationTests/file_system_node_finder_spec.rb +57 -0
- data/spec/IntegrationTests/graph_creator_spec.rb +32 -0
- data/spec/IntegrationTests/graph_image_creator_spec.rb +53 -0
- data/spec/{dependable_filter_manager_spec.rb → UnitTests/dependency_types_manager_spec.rb} +6 -6
- data/spec/UnitTests/file_system_node_finder_spec.rb +64 -0
- data/spec/UnitTests/graph_creator_spec.rb +141 -0
- data/spec/UnitTests/graph_image_creator_spec.rb +58 -0
- data/spec/UnitTests/node_spec.rb +47 -0
- data/spec/integration_spec.opts +5 -0
- data/spec/spec_helper.rb +102 -40
- data/spec/unit_spec.opts +5 -0
- data/tasks/deployment.rake +1 -1
- data/tasks/rspec.rake +17 -5
- metadata +28 -21
- data/lib/dependent.rb +0 -73
- data/lib/file_system_dependent_finder.rb +0 -44
- data/spec/dependent_spec.rb +0 -102
- data/spec/file_system_dependent_finder_spec.rb +0 -48
- data/spec/graph_creator_spec.rb +0 -103
- data/spec/graph_spec.rb +0 -120
- data/todo.txt +0 -4
data/History.txt
CHANGED
@@ -1 +1,19 @@
|
|
1
|
+
0.9.0
|
1
2
|
|
3
|
+
* Added dynamic loading of node finders from directory lib/nodefinders.
|
4
|
+
Example:
|
5
|
+
see 'lib/nodefinders/TestNodeFinder.rb' which can be used like this:
|
6
|
+
depgraph -type test
|
7
|
+
* Added functionality to exclude the nodes the user is not interested in.
|
8
|
+
Example:
|
9
|
+
depgraph -type ruby_requires -exc "client, server"
|
10
|
+
* A transitive reduction can be applied to the graph.
|
11
|
+
Example:
|
12
|
+
depgraph -type csproj -trans
|
13
|
+
* Disconnected nodes don't show up anymore.
|
14
|
+
* The type of output can be selected by changing the file extension.
|
15
|
+
Example:
|
16
|
+
depgraph -type test -output test.dot
|
17
|
+
* Separated unit tests and integration tests in different folders.
|
18
|
+
* Renamed option -dirs to -location
|
19
|
+
* Some more refactorings.
|
data/Manifest.txt
CHANGED
@@ -7,12 +7,13 @@ bin/depgraph
|
|
7
7
|
config/hoe.rb
|
8
8
|
config/requirements.rb
|
9
9
|
lib/DepGraph/version.rb
|
10
|
-
lib/
|
10
|
+
lib/dependency_types_manager.rb
|
11
11
|
lib/dependency_types.yaml
|
12
|
-
lib/
|
13
|
-
lib/
|
14
|
-
lib/
|
12
|
+
lib/node.rb
|
13
|
+
lib/file_system_node_finder.rb
|
14
|
+
lib/graph_image_creator.rb
|
15
15
|
lib/graph_creator.rb
|
16
|
+
lib/nodefinders/test_node_finder.rb
|
16
17
|
script/destroy
|
17
18
|
script/destroy.cmd
|
18
19
|
script/generate
|
@@ -20,16 +21,20 @@ script/generate.cmd
|
|
20
21
|
script/txt2html
|
21
22
|
script/txt2html.cmd
|
22
23
|
setup.rb
|
23
|
-
spec/
|
24
|
-
spec/
|
25
|
-
spec/
|
26
|
-
spec/
|
27
|
-
spec/
|
28
|
-
spec/
|
24
|
+
spec/IntegrationTests/depgraph_spec.rb
|
25
|
+
spec/IntegrationTests/file_system_node_finder_spec.rb
|
26
|
+
spec/IntegrationTests/graph_creator_spec.rb
|
27
|
+
spec/IntegrationTests/graph_image_creator_spec.rb
|
28
|
+
spec/UnitTests/dependency_types_manager_spec.rb
|
29
|
+
spec/UnitTests/node_spec.rb
|
30
|
+
spec/UnitTests/graph_creator_spec.rb
|
31
|
+
spec/UnitTests/graph_image_creator_spec.rb
|
32
|
+
spec/UnitTests/file_system_node_finder_spec.rb
|
33
|
+
spec/integration_spec.opts
|
29
34
|
spec/spec.opts
|
30
35
|
spec/spec_helper.rb
|
36
|
+
spec/unit_spec.opts
|
31
37
|
tasks/deployment.rake
|
32
38
|
tasks/environment.rake
|
33
39
|
tasks/rspec.rake
|
34
40
|
tasks/website.rake
|
35
|
-
todo.txt
|
data/bin/depgraph
CHANGED
@@ -16,54 +16,67 @@ rescue LoadError
|
|
16
16
|
exit
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
20
|
+
|
20
21
|
require 'graph_creator'
|
21
22
|
|
23
|
+
|
22
24
|
module CommandLineParameters extend OptiFlagSet
|
23
25
|
flag "type" do
|
24
|
-
dependency_types = DepGraph::
|
26
|
+
dependency_types = DepGraph::GraphCreator.types
|
25
27
|
description "Type of dependencies to analyze: #{dependency_types.join(', ')}"
|
26
28
|
value_in_set dependency_types
|
27
29
|
end
|
28
30
|
|
31
|
+
optional_flag "exc" do
|
32
|
+
description "The node names to be excluded.\nUse double quotes and commas for multiple nodes."
|
33
|
+
end
|
34
|
+
|
29
35
|
optional_flag "output" do
|
30
|
-
description "The file name of the image."
|
36
|
+
description "The file name of the graph image."
|
31
37
|
end
|
32
38
|
|
33
|
-
|
34
39
|
optional_flag "from" do
|
35
|
-
description "Regular
|
40
|
+
description "Regular expression that must be met by the dependency source."
|
36
41
|
end
|
37
42
|
|
38
43
|
optional_flag "to" do
|
39
|
-
description "Regular
|
44
|
+
description "Regular expression that must be met by the dependency target."
|
45
|
+
end
|
46
|
+
|
47
|
+
optional_flag "location" do
|
48
|
+
description "A string defining the place where the nodes to analyse are found.\nThis are directories for most dependency types.\n
|
49
|
+
Use double quotes and commas for more than one directory."
|
40
50
|
end
|
41
51
|
|
42
|
-
|
43
|
-
description "
|
52
|
+
optional_switch_flag "trans" do
|
53
|
+
description "Applies a transitive reduction to the graph"
|
44
54
|
end
|
45
55
|
|
46
56
|
usage_flag "h","help","?"
|
47
|
-
|
48
57
|
|
49
58
|
and_process!
|
50
59
|
end
|
51
60
|
|
52
61
|
type = CommandLineParameters.flags.type
|
53
62
|
output = CommandLineParameters.flags.output || 'dependency_graph.png'
|
54
|
-
|
63
|
+
location = CommandLineParameters.flags.location || '.'
|
55
64
|
from = CommandLineParameters.flags.from if CommandLineParameters.flags.from?
|
56
65
|
to = CommandLineParameters.flags.to if CommandLineParameters.flags.to?
|
66
|
+
exc = CommandLineParameters.flags.exc || ''
|
67
|
+
trans = CommandLineParameters.flags.trans?
|
57
68
|
|
58
69
|
puts "Creating #{type} dependency graph. Please wait..."
|
59
70
|
|
60
71
|
dep_grapher = DepGraph::GraphCreator.new(type)
|
61
|
-
dep_grapher.
|
62
|
-
dep_grapher.from= from
|
72
|
+
dep_grapher.location = location.split(',')
|
73
|
+
dep_grapher.from = from
|
63
74
|
dep_grapher.to = to
|
75
|
+
dep_grapher.trans = trans
|
76
|
+
dep_grapher.excluded_nodes = exc.split(',')
|
64
77
|
|
65
78
|
if dep_grapher.create_image(output)
|
66
|
-
puts "
|
79
|
+
puts "Done.\nResults in #{output}."
|
67
80
|
else
|
68
81
|
puts "No dependency graph image created."
|
69
82
|
end
|
data/config/hoe.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'DepGraph/version'
|
2
2
|
|
3
3
|
AUTHOR = 'Daniel Cadenas Ni�n' # can also be an array of Authors
|
4
|
-
EMAIL = "
|
4
|
+
EMAIL = "dcadenas@gmail.com"
|
5
5
|
DESCRIPTION = "A tool to create dependency graph images from source code directories"
|
6
6
|
GEM_NAME = 'DepGraph' # what ppl will type to install your gem
|
7
7
|
RUBYFORGE_PROJECT = 'DepGraph' # The unix name for your project
|
8
8
|
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
9
|
-
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
9
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT.downcase}"
|
10
10
|
|
11
11
|
@config_file = "~/.rubyforge/user-config.yml"
|
12
12
|
@config = nil
|
data/lib/DepGraph/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
3
|
module DepGraph
|
4
|
-
class
|
4
|
+
class DependencyTypesManager
|
5
5
|
def self.dependency_types_file
|
6
6
|
File.join(File.dirname(__FILE__), 'dependency_types.yaml')
|
7
7
|
end
|
@@ -16,27 +16,27 @@ module DepGraph
|
|
16
16
|
@@dependable_dependency_types.map {|type, _| type.to_sym}
|
17
17
|
end
|
18
18
|
|
19
|
-
def initialize(
|
20
|
-
@
|
19
|
+
def initialize(node_type = :anything)
|
20
|
+
@node_type = node_type.to_s
|
21
21
|
end
|
22
22
|
|
23
23
|
def dependable_regexp
|
24
|
-
|
24
|
+
get_node_type_parameters(@node_type)['dependable_regexp']
|
25
25
|
end
|
26
26
|
|
27
27
|
def dependable_regexp_capture_group_index
|
28
|
-
|
28
|
+
get_node_type_parameters(@node_type)['capture_group_index']
|
29
29
|
end
|
30
30
|
|
31
31
|
def file_name_pattern
|
32
|
-
|
32
|
+
get_node_type_parameters(@node_type)['file_name_pattern']
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
|
35
|
+
def get_node_type_parameters(node_type)
|
36
|
+
node_type_parameters = @@dependable_dependency_types[node_type]
|
37
37
|
|
38
|
-
if
|
39
|
-
return
|
38
|
+
if node_type_parameters
|
39
|
+
return node_type_parameters
|
40
40
|
else
|
41
41
|
return default_parameters = {
|
42
42
|
'dependable_regexp' => /.+/,
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'node'
|
2
|
+
require 'dependency_types_manager'
|
3
|
+
|
4
|
+
module DepGraph
|
5
|
+
class FileSystemNodeFinder
|
6
|
+
attr_accessor :dependable_filter, :dependable_filter_capture_group_index, :file_name_pattern
|
7
|
+
attr_writer :location
|
8
|
+
|
9
|
+
def initialize(node_type)
|
10
|
+
|
11
|
+
dependable_filter_manager = DependencyTypesManager.new node_type
|
12
|
+
@file_name_pattern = dependable_filter_manager.file_name_pattern
|
13
|
+
@dependable_filter = dependable_filter_manager.dependable_regexp
|
14
|
+
@dependable_filter_capture_group_index = dependable_filter_manager.dependable_regexp_capture_group_index
|
15
|
+
@location = ['.']
|
16
|
+
end
|
17
|
+
|
18
|
+
def location=(locs)
|
19
|
+
@location = locs.map {|d| d.strip}
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_nodes
|
23
|
+
files = []
|
24
|
+
@location.each do |dir|
|
25
|
+
files += Dir.glob(dir.strip + '/**/' + @file_name_pattern)
|
26
|
+
end
|
27
|
+
|
28
|
+
nodes = []
|
29
|
+
files.each { |file| nodes << create_node_from_file(file) }
|
30
|
+
return nodes
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_dependencies_from_string(node, dependencies_string)
|
34
|
+
fail 'The dependable finder Regexp was not set' unless @dependable_filter
|
35
|
+
|
36
|
+
dependencies_string.scan(@dependable_filter).each do |matches|
|
37
|
+
dependable = (matches.respond_to? :to_ary) ? matches[@dependable_filter_capture_group_index] : matches
|
38
|
+
node.depends_on(dependable) unless node.depends_on? dependable
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def create_node_from_file file
|
44
|
+
node = Node.new remove_extension(file)
|
45
|
+
|
46
|
+
File.open(file) do |f|
|
47
|
+
f.each_line do |line|
|
48
|
+
load_dependencies_from_string(node, line)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
return node
|
53
|
+
end
|
54
|
+
|
55
|
+
def remove_extension file_path
|
56
|
+
file_extension_regexp = /\.[^\.]+$/
|
57
|
+
return File.basename(file_path).gsub(file_extension_regexp, '')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/graph_creator.rb
CHANGED
@@ -1,85 +1,122 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
2
|
+
require 'node'
|
3
|
+
require 'graph_image_creator'
|
4
|
+
require 'file_system_node_finder'
|
5
|
+
require 'dependency_types_manager'
|
5
6
|
|
6
7
|
module DepGraph
|
7
8
|
class GraphCreator
|
8
|
-
|
9
|
+
attr_writer :graph_image_creator_class, :from, :to, :node_finder, :trans
|
9
10
|
|
10
|
-
def initialize(
|
11
|
-
@
|
12
|
-
@
|
11
|
+
def initialize(node_type = :none)
|
12
|
+
@node_finder = get_node_finder(node_type)
|
13
|
+
@graph_image_creator_class = GraphImageCreator
|
14
|
+
@trans = false
|
13
15
|
end
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
+
def self.types
|
18
|
+
node_finders_dir = File.join(File.dirname(__FILE__), 'nodefinders')
|
19
|
+
node_finders = Dir.glob(File.join(node_finders_dir, '*_node_finder.rb'))
|
20
|
+
node_finders = node_finders.map {|nf| nf.gsub(node_finders_dir + '/', '').gsub('_node_finder.rb', '').to_sym}
|
21
|
+
return DependencyTypesManager.types + node_finders
|
17
22
|
end
|
18
23
|
|
19
|
-
def
|
20
|
-
@
|
24
|
+
def location=(loc)
|
25
|
+
@node_finder.location = loc
|
21
26
|
end
|
22
27
|
|
23
|
-
def
|
24
|
-
@
|
28
|
+
def excluded_nodes=(exc)
|
29
|
+
@excluded_nodes = exc.map {|e| e.strip}
|
25
30
|
end
|
26
31
|
|
27
|
-
def
|
28
|
-
|
32
|
+
def create_image(image_file_name = 'dependency_graph.png')
|
33
|
+
create_graph.create_image(image_file_name)
|
29
34
|
end
|
30
|
-
|
31
35
|
|
32
36
|
def create_graph
|
33
|
-
nodes = @
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
graph.add_node dependent
|
37
|
+
nodes = @node_finder.get_nodes.uniq
|
38
|
+
nodes = apply_filters(nodes)
|
39
|
+
nodes = remove_disconnected_nodes(nodes)
|
40
|
+
|
41
|
+
graph = @graph_image_creator_class.new
|
42
|
+
return graph if nodes.size < 2
|
43
|
+
|
44
|
+
nodes.each do |node|
|
45
|
+
graph.add_node(node)
|
43
46
|
end
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
graph.add_edge(
|
48
|
+
nodes.each do |node|
|
49
|
+
node.dependencies.each do |dependable|
|
50
|
+
graph.add_edge(node, dependable) if nodes.include? dependable
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
54
|
+
graph.trans = @trans
|
55
|
+
|
51
56
|
return graph
|
52
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def get_node_finder(node_type)
|
61
|
+
begin
|
62
|
+
begin
|
63
|
+
require "nodefinders/#{node_type.to_s}_node_finder"
|
64
|
+
rescue LoadError
|
65
|
+
end
|
66
|
+
|
67
|
+
node_finder_class = deep_const_get("DepGraph::NodeFinders::#{camelize(node_type.to_s)}NodeFinder")
|
68
|
+
@node_finder = node_finder_class.new
|
69
|
+
rescue
|
70
|
+
@node_finder = FileSystemNodeFinder.new(node_type)
|
71
|
+
end
|
72
|
+
end
|
53
73
|
|
54
|
-
def
|
55
|
-
|
74
|
+
def remove_disconnected_nodes(nodes)
|
75
|
+
nodes.select do |node|
|
76
|
+
nodes.any? {|n| n.depends_on?(node) or node.depends_on?(n)}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def apply_filters(nodes)
|
81
|
+
apply_exclude_filter apply_to_filter(apply_from_filter(nodes))
|
82
|
+
end
|
83
|
+
|
84
|
+
def apply_exclude_filter(nodes)
|
85
|
+
return nodes unless @excluded_nodes
|
86
|
+
|
87
|
+
regexps = Regexp.union(*@excluded_nodes)
|
56
88
|
|
57
|
-
|
58
|
-
node.name.match(
|
89
|
+
nodes.reject do |node|
|
90
|
+
node.name.match(regexps)
|
59
91
|
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def apply_from_filter(nodes)
|
95
|
+
return nodes unless @from
|
60
96
|
|
61
|
-
|
97
|
+
nodes.select do |node|
|
98
|
+
node.name.match(@from) or nodes.any?{|n| n.name.match(@from) and n.depends_on?(node)}
|
99
|
+
end
|
62
100
|
end
|
63
101
|
|
64
102
|
def apply_to_filter(nodes)
|
65
|
-
return nodes unless @
|
103
|
+
return nodes unless @to
|
66
104
|
|
67
|
-
|
68
|
-
node.name.match(@
|
105
|
+
nodes.select do |node|
|
106
|
+
node.name.match(@to) or node.dependencies.any? {|d| d.name.match(@to)}
|
69
107
|
end
|
70
|
-
|
71
|
-
return selected_dependents
|
72
108
|
end
|
73
|
-
|
74
109
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
if graph
|
79
|
-
return graph.create_image(image_file_name)
|
110
|
+
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
111
|
+
if first_letter_in_uppercase
|
112
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
80
113
|
else
|
81
|
-
|
114
|
+
lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
|
82
115
|
end
|
83
116
|
end
|
117
|
+
|
118
|
+
def deep_const_get str
|
119
|
+
return str.split("::").inject(Object) {|a,b| a.const_get(b) }
|
120
|
+
end
|
84
121
|
end
|
85
122
|
end
|
@@ -2,10 +2,13 @@ require 'rubygems'
|
|
2
2
|
require 'graphviz'
|
3
3
|
|
4
4
|
module DepGraph
|
5
|
-
class
|
5
|
+
class GraphImageCreator
|
6
|
+
attr_writer :trans
|
7
|
+
|
6
8
|
def initialize
|
7
9
|
@nodes = []
|
8
10
|
@edges = []
|
11
|
+
@trans = false
|
9
12
|
end
|
10
13
|
|
11
14
|
def node_count
|
@@ -69,21 +72,54 @@ module DepGraph
|
|
69
72
|
unless @output_generation
|
70
73
|
@output_generation = lambda {|nodes, edges, image_file_name|
|
71
74
|
#TODO: Could we catch Graphviz errors that the wrapper couldn't catch?
|
72
|
-
g = GraphViz::new( "G", :use => 'dot', :mode => 'major', :rankdir => 'LR', :concentrate => 'true', :fontname => 'Arial'
|
75
|
+
g = GraphViz::new( "G", :use => 'dot', :mode => 'major', :rankdir => 'LR', :concentrate => 'true', :fontname => 'Arial')
|
73
76
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
edges.each do |from, to|
|
80
|
-
g.add_edge(quotify(from), quotify(to))
|
81
|
-
end
|
82
|
-
|
83
|
-
g.output( :output => "png")
|
77
|
+
load_nodes(g, nodes)
|
78
|
+
load_edges(g, edges)
|
79
|
+
|
80
|
+
create_output(g, image_file_name)
|
81
|
+
|
84
82
|
return true
|
85
83
|
}
|
86
84
|
end
|
87
85
|
end
|
86
|
+
|
87
|
+
def load_nodes(g, nodes)
|
88
|
+
nodes.each do |node|
|
89
|
+
g.add_node(quotify(node))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_edges(g, edges)
|
94
|
+
edges.each do |from, to|
|
95
|
+
g.add_edge(quotify(from), quotify(to))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def create_output(g, image_file_name)
|
100
|
+
output_type = get_output_type(image_file_name)
|
101
|
+
|
102
|
+
if @trans
|
103
|
+
begin
|
104
|
+
g.output(:file => 'temp.dot', :output => 'dot')
|
105
|
+
system "tred temp.dot|dot -T#{output_type} > #{image_file_name}"
|
106
|
+
ensure
|
107
|
+
File.delete('temp.dot')
|
108
|
+
end
|
109
|
+
else
|
110
|
+
g.output(:file => image_file_name, :output => output_type)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def get_output_type(image_file_name)
|
115
|
+
#png is the default output type
|
116
|
+
output_type = 'png'
|
117
|
+
|
118
|
+
image_file_name.scan(/.+\.([^\.]*)$/) do |matches|
|
119
|
+
output_type = matches[0]
|
120
|
+
end
|
121
|
+
|
122
|
+
return output_type
|
123
|
+
end
|
88
124
|
end
|
89
125
|
end
|
data/lib/node.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module DepGraph
|
2
|
+
|
3
|
+
#A node knows its dependables
|
4
|
+
class Node
|
5
|
+
include Comparable
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(node_uri)
|
9
|
+
fail 'Empty uris are not allowed' if node_uri.empty?
|
10
|
+
@name = node_uri
|
11
|
+
@dependencies = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_str
|
15
|
+
@name
|
16
|
+
end
|
17
|
+
|
18
|
+
def <=> other_node
|
19
|
+
@name <=> other_node.to_str
|
20
|
+
end
|
21
|
+
|
22
|
+
def eql? other_node
|
23
|
+
(self <=> other_node) == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def hash
|
27
|
+
@name.hash
|
28
|
+
end
|
29
|
+
|
30
|
+
def depends_on node
|
31
|
+
node = Node.new(node) unless node.respond_to? :name
|
32
|
+
|
33
|
+
@dependencies << node
|
34
|
+
end
|
35
|
+
|
36
|
+
def depends_on? node
|
37
|
+
@dependencies.include? node
|
38
|
+
end
|
39
|
+
|
40
|
+
def dependencies
|
41
|
+
@dependencies
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'node'
|
2
|
+
|
3
|
+
module DepGraph
|
4
|
+
module NodeFinders
|
5
|
+
|
6
|
+
#This is a simple example of a custom node finder with a hard coded graph.
|
7
|
+
#Note that the file must be named [nodetype]_node_finder.rb containing a class named [Nodetype]NodeFinder
|
8
|
+
#To use this example do: depgraph -type test
|
9
|
+
class TestNodeFinder
|
10
|
+
def location=(loc)
|
11
|
+
#we will ignore location in this example
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_nodes
|
15
|
+
#let's return a hardcoded graph with 2 nodes and one dependency between them
|
16
|
+
|
17
|
+
node1 = Node.new('node1')
|
18
|
+
node2 = Node.new('node2')
|
19
|
+
|
20
|
+
node1.depends_on(node2)
|
21
|
+
|
22
|
+
return [node1, node2]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|