Class: DepCheck::DepChecker
- Inherits:
-
CLAide::Command
- Object
- CLAide::Command
- DepCheck::DepChecker
- Defined in:
- lib/dep_check/DepChecker.rb
Class Method Summary collapse
Instance Method Summary collapse
-
#dep_graph_build(repo, spec, builded, nodes) ⇒ Object
构建依赖关系图.
-
#dep_resolve(node, resolved, unresolved) ⇒ Object
循环依赖检测算法实现.
-
#graph_dot_output(graph, output_file_basename) ⇒ Object
以.gv格式输出一个依赖关系图.
-
#graph_image_out(graph, output_file_basename) ⇒ Object
以.png格式输出一个依赖关系图.
-
#graphviz_data(builded, output_file_basename) ⇒ Object
利用 GraphViz 构建可视化图数据.
-
#initialize(argv) ⇒ DepChecker
constructor
A new instance of DepChecker.
-
#podspec_with_name(repo, name) ⇒ Object
通过模块名称或者模块podspec文件路径 得到一个spec对象.
- #run ⇒ Object
-
#unique_node(name, nodes) ⇒ Object
通过节点名称获得一个唯一的节点.
- #validate! ⇒ Object
Constructor Details
#initialize(argv) ⇒ DepChecker
Returns a new instance of DepChecker.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/dep_check/DepChecker.rb', line 37 def initialize(argv) puts "initialize in checker" @podspec_name = argv.shift_argument @repo_name = argv.shift_argument @repo_update = argv.flag?('repo-update', false) @produce_graphviz_output = argv.flag?('graphviz', false) @produce_image_output = argv.flag?('image', false) if @repo_name @repo = Pod::SourcesManager.sources([@repo_name]).first else @repo = Pod::SourcesManager.sources(['master']).first end super end |
Class Method Details
.arguments ⇒ Object
30 31 32 33 34 35 |
# File 'lib/dep_check/DepChecker.rb', line 30 def self.arguments [ CLAide::Argument.new('PODSPEC_NAME', true), CLAide::Argument.new('REPO_NAME', false) ].concat(super) end |
.options ⇒ Object
22 23 24 25 26 27 28 |
# File 'lib/dep_check/DepChecker.rb', line 22 def self. [ ['--repo-update', 'Fetch external podspecs and run `pod repo update` before calculating the dependency graph'], ['--graphviz', 'Outputs the dependency graph in Graphviz format to <podspec name>.gv or Podfile.gv'], ['--image', 'Outputs the dependency graph as an image to <podsepc name>.png or Podfile.png'], ].concat(super) end |
Instance Method Details
#dep_graph_build(repo, spec, builded, nodes) ⇒ Object
构建依赖关系图
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/dep_check/DepChecker.rb', line 124 def dep_graph_build(repo,spec,builded,nodes) node = unique_node(spec.attributes_hash['name'],nodes) # puts "resolving " + node.name builded.push(node) tunples = spec.all_dependencies.map { |dep| {:node => unique_node(dep.name,nodes),:dep => dep} } tunples.each { |t| node.addEdge(t[:node]) } tunples.each { |t| dep_spec = podspec_with_name(repo,t[:dep].name) if builded.count(t[:node]) == 0 dep_graph_build(repo,dep_spec,builded,nodes) end } return builded end |
#dep_resolve(node, resolved, unresolved) ⇒ Object
循环依赖检测算法实现
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/dep_check/DepChecker.rb', line 148 def dep_resolve(node, resolved, unresolved) unresolved.push(node) node.edges.each { |edge| if resolved.count(edge) == 0 #if edge not in resolved if unresolved.count(edge) != 0 #if edge in unresolved path = [] unresolved.each { |n| path << n.name } Pod::UI.puts "ERROR: Circular dependency detected! #{node.name} <---> #{edge.name}".red raise CircularDependencyError.new(node.name,edge.name,path) end dep_resolve(edge, resolved, unresolved) end } resolved.push(node) unresolved.delete(node) end |
#graph_dot_output(graph, output_file_basename) ⇒ Object
以.gv格式输出一个依赖关系图
204 205 206 207 |
# File 'lib/dep_check/DepChecker.rb', line 204 def graph_dot_output(graph, output_file_basename) graph.output( :dot => "#{output_file_basename}.gv") Pod::UI.puts "Graph file: #{output_file_basename}.gv... \n" end |
#graph_image_out(graph, output_file_basename) ⇒ Object
以.png格式输出一个依赖关系图
197 198 199 200 |
# File 'lib/dep_check/DepChecker.rb', line 197 def graph_image_out(graph, output_file_basename) graph.output( :png => "#{output_file_basename}.png") Pod::UI.puts "Graph file: #{output_file_basename}.png... \n" end |
#graphviz_data(builded, output_file_basename) ⇒ Object
利用 GraphViz 构建可视化图数据
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/dep_check/DepChecker.rb', line 179 def graphviz_data(builded, output_file_basename) @graphviz ||= begin require 'graphviz' graph = GraphViz::new(output_file_basename, :type => :digraph) builded.each { |node| graph_node_from = graph.add_node(node.name) if !node.edges.empty? node.edges.each { |subNode| graph_node_to = graph.add_node(subNode.name) graph.add_edge(graph_node_from,graph_node_to) } end } graph end end |
#podspec_with_name(repo, name) ⇒ Object
通过模块名称或者模块podspec文件路径 得到一个spec对象
108 109 110 111 112 113 114 115 116 117 |
# File 'lib/dep_check/DepChecker.rb', line 108 def podspec_with_name(repo, name) if name path = Pathname.new(name) if path.exist? podspec = Pod::Specification.from_file(path) else podspec = repo.specification(name,repo.versions(name).first) end end end |
#run ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/dep_check/DepChecker.rb', line 74 def run puts "run in checker" builded = [] Pod::UI.puts "1. Buiding dependency graph for #{@podspec_name}... \n ".green Pod::UI.puts "All dependencies : \n".blue Pod::UI.puts dep_graph_build(@repo,@podspec,builded,[]) Pod::UI.puts "Done! \n".blue Pod::UI.puts "2. Circular dependency check #{@podspec_name}... \n".green unresolved = [] begin dep_resolve(builded.first,[],unresolved) rescue Exception => e Pod::UI.puts e.to_s.red circular_found = true end if !circular_found Pod::UI.puts "No Circular dependency found! \n".green end Pod::UI.puts "Done! \n".blue if @produce_image_output || @produce_graphviz_output Pod::UI.puts "3. Visualizing graph for #{@podspec_name}... \n".green end graph_image_out(graphviz_data(builded,@podspec_name),@podspec_name) if @produce_image_output graph_dot_output(graphviz_data(builded,@podspec_name),@podspec_name) if @produce_graphviz_output Pod::UI.puts "Done. \n".blue end |
#unique_node(name, nodes) ⇒ Object
通过节点名称获得一个唯一的节点
166 167 168 169 170 171 172 173 174 175 |
# File 'lib/dep_check/DepChecker.rb', line 166 def unique_node(name,nodes) exist_nodes = nodes.select { |n| n.name == name } if exist_nodes.empty? node = Node.new(name) nodes.push(node) else node = exist_nodes.first end node end |
#validate! ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/dep_check/DepChecker.rb', line 52 def validate! super if @podspec_name require 'pathname' path = Pathname.new(@podspec_name) if path.exist? @podspec = Pod::Specification.from_file(path) else @podspec = Pod::SourcesManager.search(Pod::Dependency.new(@podspec_name)).specification.subspec_by_name(@podspec_name) end Pod::UI.puts "Analyzing #{@podspec} (in repo #{@repo})..." else raise 'Nothing to check. ' end if (@produce_image_output || @produce_graphviz_output) && Pod::Executable.which('dot').nil? raise Informative, 'GraphViz must be installed and `dot` must be in ' \ '$PATH to produce image or graphviz output.' end end |