dep_check 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4ca40a4559da05ca3d360b7086bbb736d7fa739
4
+ data.tar.gz: bbb084ba4e7f24567dd2a3f68a6fa811e43160f6
5
+ SHA512:
6
+ metadata.gz: 327601748f93d1726d9ab698db95ae49ca23e55d602f61675413682178f7c58ef2167f13a7442027994f23882b826d420b2f931b507665fead107875ea9d9a42
7
+ data.tar.gz: d66c2185ab1b869d40d6c31f5bbd44f7724f8e186d0e96c2b74581ae032d8886adfd15d0c1dded1bc91b195f90e85658ab2fad5937b99009995c1a6d82a1d01d
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ before_install: gem install bundler -v 1.11.2
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at lj94409@alipay.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dep_check.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 卡迩
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # DepCheck
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/dep_check`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'dep_check'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install dep_check
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/dep_check. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :spec
data/bin/depcheck ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "dep_check"
5
+
6
+ DepCheck::DepChecker.run(ARGV)
7
+
data/bin/setup ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
9
+ brew install graphviz
data/dep_check.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dep_check/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dep_check"
8
+ spec.version = DepCheck::VERSION
9
+ spec.authors = ["卡迩"]
10
+ spec.email = ["lj94409@alipay.com"]
11
+
12
+ spec.summary = %q{Circular depency checker for cocoapods based project. }
13
+ spec.description = %q{Circular depency checker for cocoapods based project. Use Graphviz for visualize the dependency graph.}
14
+ spec.homepage = "http://gitlab.alipay-inc.com/lj94409"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_dependency "ruby-graphviz", "~> 1.2"
24
+ spec.add_development_dependency "minitest", "~> 5.0"
25
+ spec.add_development_dependency "cocoapods"
26
+
27
+ end
data/lib/dep_check.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "dep_check/version"
2
+ require 'rubygems'
3
+
4
+ module DepCheck
5
+ # Your code goes here...
6
+ require 'dep_check/DepChecker'
7
+
8
+
9
+ end
@@ -0,0 +1,29 @@
1
+ #循环依赖检测时用到的一个异常类型,便于抛异常时传递参数
2
+ class CircularDependencyError < StandardError
3
+ attr_accessor :from
4
+ attr_accessor :to
5
+ attr_accessor :path
6
+ attr_accessor :message
7
+
8
+ # @param [String] from 循环依赖上端点
9
+ # @param [String] to 循环依赖下端点
10
+ # @param [Array<String>] path 循环依赖路径上的节点名
11
+ # @param [String] message 附加消息
12
+ def initialize(from, to , path , message = 'Circular dependency detected!')
13
+ @from = from
14
+ @to = to
15
+ @path = path
16
+ @message = message
17
+ end
18
+
19
+ def to_s
20
+ path_message = String.new
21
+ @path.each { |name|
22
+ path_message << name + '--->'
23
+ }
24
+ path_message << @to
25
+
26
+ "#{super} \n #{@message} \n #{@from} <---> #{@to} . \n Full Path: #{path_message} "
27
+ end
28
+
29
+ end
@@ -0,0 +1,203 @@
1
+ # encoding: utf-8
2
+ #依赖关系校验类
3
+
4
+ require 'cocoapods'
5
+ require "dep_check/CircularDependencyError"
6
+ require "dep_check/Node"
7
+ require 'claide'
8
+ require 'colored'
9
+
10
+ module DepCheck
11
+ class DepChecker < CLAide::Command
12
+
13
+ self.abstract_command = true
14
+
15
+ self.description = <<-DESC
16
+ cocoapods依赖关系校验. 查找循环依赖路径/构建模块依赖关系图.
17
+ DESC
18
+ self.command = 'depcheck'
19
+
20
+ self.summary = "cocoapods依赖关系校验"
21
+
22
+ def self.options
23
+ [
24
+ ['--repo=[master|other_repo_name]', 'Use a cocoapods spec repo to run the check, defaults to master'],
25
+ ['--repo-update', 'Fetch external podspecs and run `pod repo update` before calculating the dependency graph'],
26
+ ['--graphviz', 'Outputs the dependency graph in Graphviz format to <podspec name>.gv or Podfile.gv'],
27
+ ['--image', 'Outputs the dependency graph as an image to <podsepc name>.png or Podfile.png'],
28
+ ].concat(super)
29
+ end
30
+
31
+ def self.arguments
32
+ [
33
+ CLAide::Argument.new('PODSPEC', false)
34
+ ].concat(super)
35
+ end
36
+
37
+ def initialize(argv)
38
+ @podspec_name = argv.shift_argument
39
+ @repo_name = argv.option('repo', 'master')
40
+ @repo_update = argv.flag?('repo-update', false)
41
+ @produce_graphviz_output = argv.flag?('graphviz', false)
42
+ @produce_image_output = argv.flag?('image', false)
43
+ super
44
+ end
45
+
46
+ def validate!
47
+ super
48
+ if @podspec_name
49
+ require 'pathname'
50
+ path = Pathname.new(@podspec_name)
51
+ if path.exist?
52
+ @podspec = Specification.from_file(path)
53
+ else
54
+ @podspec = SourcesManager.
55
+ search(Dependency.new(@podspec_name)).
56
+ specification.
57
+ subspec_by_name(@podspec_name)
58
+ end
59
+ end
60
+ if (@produce_image_output || @produce_graphviz_output) && Executable.which('dot').nil?
61
+ raise Informative, 'GraphViz must be installed and `dot` must be in ' \
62
+ '$PATH to produce image or graphviz output.'
63
+ end
64
+ end
65
+
66
+
67
+ def run
68
+ builded = []
69
+ Pod::UI.puts "1. Buiding dependency graph for #{@podspec_name}... \n ".green
70
+ Pod::UI.puts "All dependencies : \n".blue
71
+ dep_graph_build(@repo_name,@podspec_name,builded,[])
72
+ Pod::UI.puts "Done! \n".blue
73
+
74
+
75
+ Pod::UI.puts "2. Circular dependency check #{@podspec_name}... \n".green
76
+ unresolved = []
77
+ begin
78
+ dep_resolve(builded.first,[],unresolved)
79
+ rescue Exception => e
80
+ Pod::UI.puts e.to_s.red
81
+ circular_found = true
82
+ end
83
+ if !circular_found
84
+ Pod::UI.puts "No Circular dependency found! \n".green
85
+ end
86
+ Pod::UI.puts "Done! \n".blue
87
+
88
+ if @produce_image_output || @produce_graphviz_output
89
+ Pod::UI.puts "3. Visualizing graph for #{@podspec_name}... \n".green
90
+ end
91
+ graphviz_image_output(graphviz_data(builded,@podspec_name),@podspec_name) if @produce_image_output
92
+ graph_dot_output(graphviz_data(builded,@podspec_name),@podspec_name) if @produce_graphviz_output
93
+
94
+ end
95
+
96
+
97
+
98
+
99
+ #通过模块名称或者模块podspec文件路径 得到一个spec[Specification]对象
100
+ def podspec_with_name(repo, name)
101
+ if name
102
+ path = Pathname.new(name)
103
+ if path.exist?
104
+ podspec = Pod::Specification.from_file(path)
105
+ else
106
+ podspec = repo.specification(name,repo.versions(name).first)
107
+ end
108
+ end
109
+ end
110
+
111
+ # 构建依赖关系图
112
+ # @param [Source] repo 依赖关系图建立过程中使用的podspec仓库
113
+ # @param [Specification] spec 待构建的spec
114
+ # @param [Array<Node>] builded 已经构建完成的Node数组
115
+ # @param [Array<Node>] nodes 已经存在的Node数组
116
+ def dep_graph_build(repo,spec,builded,nodes)
117
+
118
+ node = unique_node(spec.attributes_hash['name'],nodes)
119
+ # puts "resolving " + node.name
120
+ builded.push(node)
121
+
122
+ tunples = spec.all_dependencies.map { |dep|
123
+ {:node => unique_node(dep.name,nodes),:dep => dep}
124
+ }
125
+
126
+ tunples.each { |t|
127
+ node.addEdge(t[:node])
128
+ }
129
+
130
+ tunples.each { |t|
131
+ dep_spec = podspec_with_name(repo,t[:dep].name)
132
+ if builded.count(t[:node]) == 0
133
+ dep_graph_build(repo,dep_spec,builded,nodes)
134
+ end
135
+ }
136
+ return builded
137
+ end
138
+
139
+ # 循环依赖检测算法实现
140
+ def dep_resolve(node, resolved, unresolved)
141
+ unresolved.push(node)
142
+ node.edges.each { |edge|
143
+ if resolved.count(edge) == 0 #if edge not in resolved
144
+ if unresolved.count(edge) != 0 #if edge in unresolved
145
+ path = []
146
+ unresolved.each { |n| path << n.name }
147
+ Pod::UI.puts "ERROR: Circular dependency detected! #{node.name} <---> #{edge.name}".red
148
+ raise CircularDependencyError.new(node.name,edge.name,path)
149
+ end
150
+ dep_resolve(edge, resolved, unresolved)
151
+ end
152
+ }
153
+ resolved.push(node)
154
+ unresolved.delete(node)
155
+ end
156
+
157
+ # 通过节点名称获得一个唯一的节点
158
+ def unique_node(name,nodes)
159
+ exist_nodes = nodes.select { |n| n.name == name }
160
+ if exist_nodes.empty?
161
+ node = Node.new(name)
162
+ nodes.push(node)
163
+ else
164
+ node = exist_nodes.first
165
+ end
166
+ node
167
+ end
168
+
169
+
170
+ #利用 GraphViz 构建可视化图数据
171
+ def graphviz_data(builded, output_file_basename)
172
+ @graphviz ||= begin
173
+ require 'graphviz'
174
+ graph = GraphViz::new(output_file_basename, :type => :digraph)
175
+ builded.each { |node|
176
+ graph_node_from = graph.add_node(node.name)
177
+ if !node.edges.empty?
178
+ node.edges.each { |subNode|
179
+ graph_node_to = graph.add_node(subNode.name)
180
+ graph.add_edge(graph_node_from,graph_node_to)
181
+ }
182
+ end
183
+ }
184
+ graph
185
+ end
186
+ end
187
+
188
+ # 以.png格式输出一个依赖关系图
189
+ def graph_image_out(graph, output_file_basename)
190
+ graph.output( :png => "#{output_file_basename}.png")
191
+ end
192
+
193
+
194
+ # 以.gv格式输出一个依赖关系图
195
+ def graph_dot_output(graph, output_file_basename)
196
+ graph.output( :dot => "#{output_file_basename}.gv")
197
+ end
198
+
199
+ end
200
+ end
201
+
202
+
203
+
@@ -0,0 +1,27 @@
1
+ #依赖关系图中的一个Node
2
+ module DepCheck
3
+ class Node
4
+ attr_accessor :edges
5
+ attr_accessor :name
6
+ def initialize(name)
7
+ @name = name
8
+ @edges = []
9
+ end
10
+
11
+ def addEdge(node)
12
+ @edges.push(node)
13
+ end
14
+
15
+ def ==(other)
16
+ @name == other.name
17
+ end
18
+
19
+ def to_hash
20
+ {:name=>@name,:edges=>@edges}
21
+ end
22
+
23
+ def to_s
24
+ @name
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module DepCheck
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dep_check
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 卡迩
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ruby-graphviz
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: cocoapods
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Circular depency checker for cocoapods based project. Use Graphviz for
84
+ visualize the dependency graph.
85
+ email:
86
+ - lj94409@alipay.com
87
+ executables:
88
+ - depcheck
89
+ - setup
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - .gitignore
94
+ - .travis.yml
95
+ - CODE_OF_CONDUCT.md
96
+ - Gemfile
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - bin/depcheck
101
+ - bin/setup
102
+ - dep_check.gemspec
103
+ - lib/dep_check.rb
104
+ - lib/dep_check/CircularDependencyError.rb
105
+ - lib/dep_check/DepChecker.rb
106
+ - lib/dep_check/Node.rb
107
+ - lib/dep_check/version.rb
108
+ homepage: http://gitlab.alipay-inc.com/lj94409
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.0.14.1
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Circular depency checker for cocoapods based project.
132
+ test_files: []