lib/codependency/graph.rb in codependency-0.3.1 vs lib/codependency/graph.rb in codependency-1.0.0
- old
+ new
@@ -1,46 +1,63 @@
-require 'open3'
+require 'tsort'
module Codependency
- class Graph
- def initialize( start, options={} )
- @options = options
- @nodes = Hash.new { |h, k| h[ k ] = Node.new( k, parser ) }
- @start = @nodes[ start ]
+ class Graph < Hash
+ def initialize( path, options={} )
+ @path, @options = path, options
+
+ super( ){ |h, k| h[ k ] = parser.parse( k ) }
end
+ attr_reader :path, :options
+ include TSort
+
##
- # a topologically sorted list of all dependencies of the `start` file.
- def files
- deps = resolve( @start, [ ] ).map( &:dependencies ).join ' '
+ # the dirname to use for this graph, based on the path
+ def dirname
+ File.dirname path
+ end
- cmd, out, err = Open3.popen3 "echo '#{deps}' | tsort"
-
- if msg = err.gets
- raise CircularDependencyError, msg
- end
-
- out.readlines.map( &:chomp ).reverse
+ ##
+ # the extname to use for this graph, based on the path
+ def extname
+ File.extname path
end
- protected
-
##
- # adds a node's dependencies to a list (memo).
- # intended to be used recursively.
- def resolve( node, list )
- list << node
+ # walk the entire graph and return self
+ def populate
+ walk path
+ self
+ end
- node.edges.map { |filename| @nodes[ filename ] }.each do |dep|
- resolve dep, list unless list.include?( dep )
- end
-
- list
+ ##
+ # discover all nodes in this graph by walking it
+ def walk( path )
+ self[ path ].each { |path| walk( path ) unless has_key?( path ) }
end
##
# the parser to use for this graph. shared by all nodes.
def parser
- @parser ||= Parser.new @options
+ @parser ||= begin
+ Parser.new options.merge( :dirname => dirname, :extname => extname )
+ end
+ end
+
+ ##
+ # a topologically sorted list of all dependencies of the `start` file.
+ def files
+ populate.tsort
+ end
+
+ private
+
+ # tsort interface
+ alias :tsort_each_node :each_key
+
+ # tsort interface
+ def tsort_each_child( node, &block )
+ fetch( node ).each( &block )
end
end
end