DepGraph 0.8.0 → 0.9.0
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/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
         |