cbradeps 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: 598aa087f1c0d76bf8e9964e2733830616b22d14
4
+ data.tar.gz: 61357cb006c3eacf330da000049645f8e91ab989
5
+ SHA512:
6
+ metadata.gz: 51b39c58ddb86d21926b3e1a5c11bd66e451cde05f4e17fe5c00ee0b8de509d29fadf5905eccf547d7e866cb37320d41f3c0ea9cb7a0203e3bf7f0bd99294249
7
+ data.tar.gz: f2ab318356e17cc3281ef371a6ce48eea0aa112b21a43bb6b1f89460557da0decb3698280d355e0fce1deca725b805c60d176f8a5b40cbcac96e697f9d7bc25b
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cbradeps.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Stephan Hagemann
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # cbradeps
2
+
3
+ Prints and exports the dependencies within component-based Ruby/Rails applications
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'cbradeps'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install cbradeps
18
+
19
+ ## Usage
20
+
21
+ cbradeps [application path]
22
+
23
+ Component-based Ruby/Rails dependency grapher.
24
+
25
+ Options are...
26
+ -h, -H, --help Display this help message.
27
+
28
+ ##TODOs
29
+
30
+ * optionally output dotfile for all deps
31
+ * support windows folders (searching for a couple slashes)
32
+ * support windows: don't shell out to find gemspecs and gemfiles
33
+ * info if no gem file found for gem
34
+ * warn if gem has name different than folder
35
+ * warn if same gem name is found with path and without
36
+ * error if there are multiple gem specs
37
+ * error if there is not gem file in root
38
+
39
+
40
+ ## License
41
+
42
+ Copyright (c) 2014 Stephan Hagemann
43
+ twitter.com/shageman
44
+ stephan.hagemann@gmail.com
45
+
46
+ Released under the MIT license. See LICENSE file for details.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/cbradeps ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require_relative "../lib/cbradeps"
4
+
5
+ def help_text
6
+ <<-USAGE
7
+ cbradeps [OPTION] [application path]
8
+
9
+ Component-based Ruby/Rails dependency grapher.
10
+
11
+ Options are...
12
+ -t, --text DEFAULT Outputs a textual representation of the dependencies
13
+ -g, --graph Outputs graph.png to the current directory
14
+ -d, --dot Outputs graph.dot to the current directory
15
+
16
+ -h, -H, --help Display this help message.
17
+ USAGE
18
+ end
19
+
20
+ option = "-t"
21
+ path = nil
22
+
23
+ case ARGV.size
24
+ when 0
25
+ when 1
26
+ path = ARGV[0]
27
+ when 2
28
+ option = ARGV[0]
29
+ path = ARGV[1]
30
+ else
31
+ puts "Incorrect invocation. Please see help:\n\n"
32
+ puts help_text
33
+ exit 1
34
+ end
35
+
36
+ if option
37
+ if %w(--help -h -H).include? option
38
+ puts help_text
39
+ elsif %w(-g --graph).include? option
40
+ Cbradeps.output_graph path
41
+ elsif %w(-d --dot).include? option
42
+ Cbradeps.output_dot path
43
+ else %w(-t --text).include? option
44
+ Cbradeps.output_text path
45
+ end
46
+ end
data/cbradeps.gemspec ADDED
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'cbradeps'
7
+ spec.version = '0.1.0'
8
+ spec.authors = ['Stephan Hagemann']
9
+ spec.email = ['stephan.hagemann@gmail.com']
10
+ spec.summary = %q{Prints and exports the dependencies within component-based Ruby/Rails applications}
11
+ spec.description = <<-DOC
12
+ Component-based Ruby/Rails applications use local 'path' gem references to structure an application. This gem provides
13
+ utilities for printing and exporting such dependencies.
14
+ DOC
15
+
16
+ spec.homepage = ''
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = %w(
20
+ bin/cbradeps
21
+ cbradeps.gemspec
22
+ Gemfile
23
+ lib/cbradeps/gemfile_scraper.rb
24
+ lib/cbradeps.rb
25
+ LICENSE
26
+ Rakefile
27
+ README.md
28
+ )
29
+
30
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
31
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
32
+ spec.require_paths = ['lib']
33
+
34
+ spec.add_dependency 'ruby-graphviz'
35
+
36
+ spec.add_development_dependency 'bundler', '~> 1.5'
37
+ spec.add_development_dependency 'rake'
38
+ spec.add_development_dependency 'rspec'
39
+ end
@@ -0,0 +1,93 @@
1
+ module Cbradeps
2
+ class GemfileScraper
3
+ def initialize(root_path)
4
+ @root_path = root_path
5
+ end
6
+
7
+ def name
8
+ Pathname.new(@root_path).basename.to_s
9
+ end
10
+
11
+ def to_s
12
+ cbra_dependencies
13
+ end
14
+
15
+ def cbra_dependencies
16
+ dirdep = direct_dependencies
17
+ transitive_cbra_dependencies.select do |dep|
18
+ dirdep.include?(dep[:name]) || dep[:options][:direct]
19
+ end
20
+ end
21
+
22
+ def transitive_cbra_dependencies
23
+ gem_dependencies.inject([]) do |memo, dep|
24
+ if !!dep[:options][:path]
25
+ absolute_dep = dep.clone
26
+ absolute_dep[:options][:path] = File.expand_path(File.join(@root_path, dep[:options][:path]))
27
+ memo << dep
28
+ end
29
+ memo
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def raw_gemspec
36
+ path = File.expand_path(File.join(@root_path, "#{underscore(name)}.gemspec"))
37
+ File.exist?(path) ? File.read(path) : ""
38
+ end
39
+
40
+ def direct_dependencies
41
+ raw_gemspec.split("\n").inject([]) do |memo, line|
42
+ match = line.match(/add_(?:development_)?dependency\s+["']([^'"]+)["']/)
43
+ memo << match[1] if match
44
+ memo
45
+ end
46
+ end
47
+
48
+ def raw_gemfile
49
+ path = File.expand_path(File.join(@root_path, "Gemfile"))
50
+ File.read(path)
51
+ end
52
+
53
+ def gem_dependencies
54
+ raw_gemfile.split("\n").inject([]) do |memo, line|
55
+ match = line.match(/gem\s+["']([^'"]+)["'](.*)/)
56
+ if match
57
+ memo << {name: match[1], options: OptionParser.new(match[2]).parse}
58
+ end
59
+ memo
60
+ end
61
+ end
62
+
63
+ def underscore(string)
64
+ string.gsub(/::/, '/').
65
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
66
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
67
+ tr("-", "_").
68
+ downcase
69
+ end
70
+
71
+ class OptionParser
72
+ def initialize(options)
73
+ @options = options
74
+ end
75
+
76
+ def parse
77
+ {}.merge(path).merge(direct)
78
+ end
79
+
80
+ private
81
+
82
+ def path
83
+ match = @options.match(/path(?:\s*=>|:)\s+["']([^'"]+)["']/)
84
+ match ? {path: match[1]} : {}
85
+ end
86
+
87
+ def direct
88
+ match = @options.match(/direct(?:\s*=>|:)\s+true/)
89
+ match ? {direct: true} : {}
90
+ end
91
+ end
92
+ end
93
+ end
data/lib/cbradeps.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'set'
2
+ require 'pathname'
3
+ require 'graphviz'
4
+
5
+ module Cbradeps
6
+ require_relative "cbradeps/gemfile_scraper"
7
+
8
+ def self.output_text(root_path = nil)
9
+ path = root_path || current_path
10
+ app = GemfileScraper.new(path)
11
+
12
+ outputs "APP"
13
+ outputs app.to_s
14
+
15
+ outputs "\n\nDEPENDENCIES"
16
+ cbra_deps = app.transitive_cbra_dependencies.to_set
17
+
18
+ cbra_deps.each do |dep|
19
+ outputs "\n#{dep[:options][:path]}"
20
+ gem = GemfileScraper.new(dep[:options][:path])
21
+ outputs gem.to_s
22
+
23
+ cbra_deps = cbra_deps.merge gem.cbra_dependencies
24
+ end
25
+
26
+ outputs "\n\n ALL PARTS"
27
+ outputs cbra_deps.to_a
28
+ end
29
+
30
+ def self.output_graph(root_path = nil)
31
+ path = root_path || current_path
32
+ graph(path).output(:png => "graph.png")
33
+ end
34
+
35
+ def self.output_dot(root_path = nil)
36
+ path = root_path || current_path
37
+ graph(path).output(:dot => "graph.dot")
38
+ end
39
+
40
+ def self.current_path
41
+ `pwd`.chomp
42
+ end
43
+
44
+ private_class_method :current_path
45
+
46
+ def self.graph(path)
47
+ g = GraphViz.new(:G, :type => :digraph)
48
+
49
+ app = GemfileScraper.new(path)
50
+
51
+ app_node = g.add_nodes(app.name)
52
+ outputs "Added #{app.name} node"
53
+
54
+ cbra_deps = app.transitive_cbra_dependencies.to_set
55
+ gem_nodes = {}
56
+
57
+ cbra_deps.each do |dep|
58
+ gem = GemfileScraper.new(dep[:options][:path])
59
+ gem_node = g.add_nodes(gem.name)
60
+ gem_nodes[gem.name] = gem_node
61
+ outputs "Added #{gem.name} node"
62
+ if dep[:options][:direct]
63
+ outputs "Added edge from #{app.name} to #{gem.name}"
64
+ g.add_edges(app_node, gem_node)
65
+ end
66
+ end
67
+
68
+ cbra_deps.each do |dep|
69
+ gem = GemfileScraper.new(dep[:options][:path])
70
+ gem_node = gem_nodes[gem.name]
71
+
72
+ gem_cbra_deps = gem.cbra_dependencies
73
+ gem_cbra_deps.each do |nest_dep|
74
+ nest_gem = GemfileScraper.new(nest_dep[:options][:path])
75
+ g.add_edges(gem_node, gem_nodes[nest_gem.name])
76
+ outputs "Added edge from #{gem.name} to #{nest_gem.name}"
77
+ end
78
+ end
79
+ g
80
+ end
81
+
82
+ private_class_method :graph
83
+
84
+ def self.outputs(arg)
85
+ puts arg
86
+ end
87
+
88
+ private_class_method :outputs
89
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cbradeps
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Stephan Hagemann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-graphviz
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: |
70
+ Component-based Ruby/Rails applications use local 'path' gem references to structure an application. This gem provides
71
+ utilities for printing and exporting such dependencies.
72
+ email:
73
+ - stephan.hagemann@gmail.com
74
+ executables:
75
+ - cbradeps
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - bin/cbradeps
80
+ - cbradeps.gemspec
81
+ - Gemfile
82
+ - lib/cbradeps/gemfile_scraper.rb
83
+ - lib/cbradeps.rb
84
+ - LICENSE
85
+ - Rakefile
86
+ - README.md
87
+ homepage: ''
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.0.3
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Prints and exports the dependencies within component-based Ruby/Rails applications
111
+ test_files: []