bundler-dependencies 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c16e60328617e09d591746dda98147960439c09872d72f19c190cfd9db7dc507
4
- data.tar.gz: f47346858b2f17ce75367442716e57d954a858bd7bb5e41d7021b1086b4e6ea6
3
+ metadata.gz: f91f1a9abc52789ce91922327bb0841e54baad990a27d62227cf8a09b02b84f9
4
+ data.tar.gz: e6e2e5dd7229e2c24f06512086f646b96122706362489d358f6f6f971cd224d9
5
5
  SHA512:
6
- metadata.gz: '09d8abbe0cf1bc3bec621640976db86f8ce8a9b7cb1e15cfa6ea8b28721249e66f5145de0c09438cd2a556ffe232fc038cb5d9dbe79748c97a79c9ac36efc990'
7
- data.tar.gz: 01bb7b0342df912eb034bb583e5abac4c487ed60a98ea94b491ad22e8bb4c950f4a23d7768ec7b6b7139f578b6b028011423b2328cf2430f0fc8443864c075fa
6
+ metadata.gz: 5465ca3807463f565fedb2e33f776203d2fc71e94428656542c88e5f665f5c82270d31980ba7811740f5f12b70f9376e9ef421ad1411816044057451c974780c
7
+ data.tar.gz: 9197f27c934b71de5d360f8a0cd42972b20a98c0cab06a23a36a564be88abb48b10be3422d509111f599eeb804cd887b746894b22846b36eec2f3d06e9fe88c1
@@ -27,4 +27,5 @@ Style/NumericPredicate:
27
27
 
28
28
  Style/MethodCallWithArgsParentheses:
29
29
  IgnoredMethods:
30
+ - and
30
31
  - method_option
data/CHANGES.md CHANGED
@@ -1,9 +1,23 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 0.5.1 (2019-11-18)
4
- * Fix crash when called without a path argument
5
- * Fix gemspec not setting up executables properly
3
+ ## 0.6.0 (2019-11-18)
6
4
 
7
- ## 0.5.0 (2019-11-18)
5
+ ### New features
6
+ * Add `find` command to find all gems in the Gemfile which depend on a given gem.
7
+
8
+ ### Bug fixes
9
+ * Fix crash when calling `bundle dependencies graph` with a gem that isn't in the bundle.
10
+
11
+ ### Changes
12
+ * Handle invoking a command with help as the first argument (show the command's help).
13
+ * Add global `--no-color` switch to disable colorizing output.
14
+
15
+ ## 0.5.1
16
+
17
+ ### Bug fixes
18
+ * Fix crash when called without a path argument.
19
+ * Fix gemspec not setting up executables properly.
20
+
21
+ ## 0.5.0
8
22
 
9
23
  Initial version
data/README.md CHANGED
@@ -1,9 +1,14 @@
1
1
  # Bundler::Dependencies
2
2
 
3
3
  [![Build Status](https://travis-ci.org/dvandersluis/bundler-dependencies.svg?branch=master)](https://travis-ci.org/dvandersluis/bundler-dependencies)
4
+ [![Gem Version](https://badge.fury.io/rb/bundler-dependencies.svg)](https://badge.fury.io/rb/bundler-dependencies)
4
5
 
5
6
  Bundler plugin to inspect dependencies of gems used by your project.
6
7
 
8
+ A project's `Gemfile.lock` shows some basic information about what gems are directly depended on by other gems, but this extension takes it a step further and enumerates the entire dependency tree of each gem being depended on. For instance, `rails` has 12 direct dependencies, but altogether installs **40** gems.
9
+
10
+ Each dependency is a potential point of failure, vulnerability, maintenance and *complexity* for a project, so the goal of `bundle dependencies` is to shed some light on what's being installed by what. This shouldn't stop you from installing gems that are useful to your project, but to be able to make an educated decision if a gem with 25 dependencies is a worthy tradeoff, for example.
11
+
7
12
  ## Commands
8
13
 
9
14
  ### Count
@@ -14,6 +19,20 @@ Check how many dependencies each gem in the Gemfile has (use the `--minimum N` s
14
19
  bundle dependencies [count] [--minimum N]
15
20
  ```
16
21
 
22
+ ### Find
23
+
24
+ Find all the gems in the Gemfile that depend on a given gem (either directly or indirectly), as well as all the dependency paths for that gem:
25
+
26
+ ```sh
27
+ bundle dependencies find GEM
28
+ ```
29
+
30
+ Get just the number of dependent gems:
31
+
32
+ ```sh
33
+ bundle dependencies find GEM --quiet
34
+ ```
35
+
17
36
  ### Graph
18
37
 
19
38
  See a graph of all dependencies:
@@ -32,6 +51,11 @@ bundle dependencies graph GEMNAME
32
51
  * `--without foo bar baz`/`-W foo bar baz`: Exclude the listed gems from the scan. Any uses either directly in your Gemfile or as dependencies will be excluded, and not be counted.
33
52
  * `--without-rails`/`-R`: Quick option to exclude all 1st party Rails gems from the scan.
34
53
 
54
+ ### Getting Help
55
+
56
+ * `bundle dependencies help` to get an overview of all commands.
57
+ * `bundle dependencies help COMMAND` to get help for a specific command.
58
+
35
59
  ## Development
36
60
 
37
61
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
16
  # to allow pushing to a single host or delete this section to allow pushing to any host.
17
17
  if spec.respond_to?(:metadata)
18
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
18
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
19
19
 
20
20
  spec.metadata['homepage_uri'] = spec.homepage
21
21
  spec.metadata['source_code_uri'] = spec.homepage
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
32
  end
33
33
 
34
- glob = lambda { |patterns| spec.files & Dir[*patterns] }
34
+ glob = -> (patterns) { spec.files & Dir[*patterns] }
35
35
  spec.executables = glob['bin/bundle*'].map { |path| File.basename(path) }
36
36
  spec.default_executable = spec.executables.first if Gem::VERSION < '1.7.'
37
37
 
@@ -43,6 +43,4 @@ Gem::Specification.new do |spec|
43
43
  spec.add_development_dependency 'pry', '~> 0.12.2'
44
44
  spec.add_development_dependency 'rake', '~> 10.0'
45
45
  spec.add_development_dependency 'rspec', '~> 3.0'
46
- spec.add_development_dependency 'rubocop', '~> 0.76.0'
47
- spec.add_development_dependency 'rubocop-rspec', '~> 1.36.0'
48
46
  end
@@ -9,10 +9,13 @@ require 'bundler/dependencies/spec'
9
9
  require 'bundler/dependencies/visitor'
10
10
 
11
11
  require 'bundler/dependencies/cli/command'
12
+ require 'bundler/dependencies/cli/with_gem'
12
13
  require 'bundler/dependencies/cli/count'
14
+ require 'bundler/dependencies/cli/find'
13
15
  require 'bundler/dependencies/cli/graph'
14
16
 
15
17
  require 'bundler/dependencies/visitors/shell_tree'
18
+ require 'bundler/dependencies/visitors/paths'
16
19
 
17
20
  module Bundler
18
21
  module Dependencies
@@ -11,29 +11,44 @@ module Bundler
11
11
  method_option :path, type: :string, desc: 'Path to Gemfile.lock to scan'
12
12
  method_option :without, type: :array, desc: 'Gems to ignore', aliases: ['-W']
13
13
  method_option :without_rails, type: :boolean, default: false, desc: 'Ignore all Rails gems', aliases: ['-R']
14
+ method_option :color, type: :boolean, default: true, desc: 'Colorize output'
14
15
  end
15
16
 
16
17
  default_task :count
17
18
  map '--version' => :version
18
19
 
19
- desc 'count', 'Checks for gems that install too many dependencies'
20
+ desc 'version', 'Prints the bundler-dependencies version'
21
+ def version
22
+ puts "#{File.basename($PROGRAM_NAME)} #{VERSION}"
23
+ end
24
+
25
+ desc 'count', 'Count the number of dependencies each gem in the bundle relies on, recursively'
20
26
  shared_options
21
27
  method_option :minimum, type: :numeric, desc: 'Report only gems with a minimum N dependencies', aliases: ['-m'], default: 0
22
28
 
23
- def count
29
+ def count(*args)
30
+ return help(:count) if args.first == 'help'
31
+
24
32
  Count.new(options).output
25
33
  end
26
34
 
27
- desc 'graph [GEM]', 'Outputs a dependency graph'
35
+ desc 'graph [GEM]', 'Output a graph of dependencies, for all gems in the bundle or a specific gem'
28
36
  shared_options
29
37
 
30
38
  def graph(gem = nil)
39
+ return help(:graph) if gem == 'help'
40
+
31
41
  Graph.new(gem, options).output
32
42
  end
33
43
 
34
- desc 'version', 'Prints the bundler-dependencies version'
35
- def version
36
- puts "#{File.basename($PROGRAM_NAME)} #{VERSION}"
44
+ desc 'find [GEM]', 'Output gems in the bundle that depend on GEM'
45
+ shared_options
46
+ method_option :quiet, type: :boolean, default: false, desc: 'Show only the number of gems and no other output', aliases: ['-q']
47
+
48
+ def find(gem = nil)
49
+ return help(:find) if gem.nil? || gem == 'help'
50
+
51
+ Find.new(gem, options).output
37
52
  end
38
53
  end
39
54
  end
@@ -9,6 +9,7 @@ module Bundler
9
9
 
10
10
  def initialize(options)
11
11
  @options = options
12
+ self.shell = Thor::Shell::Basic.new unless options.color?
12
13
  end
13
14
 
14
15
  no_commands do
@@ -34,14 +35,21 @@ module Bundler
34
35
  def path
35
36
  return options.path if valid_gemfile?(options.path)
36
37
 
37
- SharedHelpers.chdir(File.dirname(options.path)) if options.path
38
+ dir = path_dir(options.path)
39
+ SharedHelpers.chdir(dir) if dir
38
40
  SharedHelpers.default_lockfile
39
41
  end
40
42
 
43
+ def path_dir(path)
44
+ return nil unless path
45
+
46
+ Dir.exist?(options.path) ? options.path : File.dirname(options.path)
47
+ end
48
+
41
49
  def valid_gemfile?(path)
42
50
  return false unless path && File.exist?(path)
43
51
 
44
- %w(Gemfile.lock gems.locked).include?(File.basename(path))
52
+ File.basename(path).end_with?('.lock', '.locked')
45
53
  end
46
54
 
47
55
  def without
@@ -50,12 +58,17 @@ module Bundler
50
58
  end
51
59
  end
52
60
 
61
+ def gems
62
+ @gems ||= graph.without(*without)
63
+ end
64
+
53
65
  def warn(message)
54
66
  say(message, %i(bold yellow))
55
67
  end
56
68
 
57
69
  def error(message)
58
- say(message, %i(bold red))
70
+ message = shell.send(:prepare_message, message, :red, :bold)
71
+ super(message)
59
72
  end
60
73
  end
61
74
  end
@@ -11,7 +11,7 @@ module Bundler
11
11
  end
12
12
 
13
13
  def counts
14
- @counts ||= graph.without(*without).counts(min: options.minimum)
14
+ @counts ||= gems.counts(min: options.minimum)
15
15
  end
16
16
 
17
17
  def warnings
@@ -0,0 +1,44 @@
1
+ module Bundler
2
+ module Dependencies
3
+ class CLI < ::Thor
4
+ class Find < Command
5
+ include WithGem
6
+
7
+ private
8
+
9
+ def to_s
10
+ if dependents.empty?
11
+ error("No gems in the bundle depend on #{gem}.")
12
+ exit(1)
13
+ end
14
+
15
+ banner
16
+ paths unless options.quiet
17
+ end
18
+
19
+ def dependents
20
+ Bundler::Dependencies::Visitors::Paths.new.walk(gems, gem).each_with_object({}) do |path, acc|
21
+ acc[path.first] ||= []
22
+ acc[path.first] << path.join(' → ')
23
+ end
24
+ end
25
+
26
+ def paths
27
+ dependents.each do |gem, paths|
28
+ puts
29
+ say(gem, %i(bold))
30
+ paths.each { |p| say " * #{p}" }
31
+ end
32
+ end
33
+
34
+ def banner
35
+ if options.quiet?
36
+ puts dependents.count
37
+ else
38
+ say("#{dependents.count} gems depend on #{gem}:", :bold)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -2,21 +2,21 @@ module Bundler
2
2
  module Dependencies
3
3
  class CLI < ::Thor
4
4
  class Graph < Command
5
- def initialize(gem, options)
6
- @gem = gem
7
- super(options)
8
- end
5
+ include CLI::WithGem
9
6
 
10
7
  private
11
8
 
12
- attr_reader :gem
13
-
14
9
  def to_s
15
- Visitors::ShellTree.new.walk(graph.without(*without), shell)
10
+ if gems.empty?
11
+ error("#{gem} is not present in your bundle.")
12
+ exit(1)
13
+ end
14
+
15
+ Visitors::ShellTree.new.walk(gems, shell)
16
16
  end
17
17
 
18
18
  def graph
19
- gem ? Bundler::Dependencies::Graph.new(specs: [Spec.find(gem)]) : super
19
+ gem ? Bundler::Dependencies::Graph.new(specs: [super.find(gem)]) : super
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,16 @@
1
+ module Bundler
2
+ module Dependencies
3
+ class CLI < ::Thor
4
+ module WithGem
5
+ def initialize(gem, options)
6
+ @gem = gem
7
+ super(options)
8
+ end
9
+
10
+ private
11
+
12
+ attr_reader :gem
13
+ end
14
+ end
15
+ end
16
+ end
@@ -9,7 +9,7 @@ module Bundler
9
9
  if lockfile
10
10
  load_lockfile
11
11
  else
12
- @specs = specs
12
+ @specs = specs.compact
13
13
  end
14
14
  end
15
15
 
@@ -26,6 +26,10 @@ module Bundler
26
26
  gems.each(&block)
27
27
  end
28
28
 
29
+ def find(gem)
30
+ include_dependency?(gem) ? Spec.find(gem) : nil
31
+ end
32
+
29
33
  def counts(min: 0)
30
34
  @counts ||= map do |gem|
31
35
  count = gem.dependency_count
@@ -49,7 +53,7 @@ module Bundler
49
53
 
50
54
  def include_dependency?(gem)
51
55
  gem = Spec.new(gem) unless gem.is_a?(Spec)
52
- include?(gem) || any? { |spec| spec.dependencies.include_dependency?(gem) }
56
+ include?(gem) || any? { |spec| spec.include_dependency?(gem) }
53
57
  end
54
58
 
55
59
  def without(*gems)
@@ -23,6 +23,10 @@ module Bundler
23
23
  SPECS[name] = self
24
24
  end
25
25
 
26
+ def include_dependency?(gem)
27
+ dependencies.include_dependency?(gem)
28
+ end
29
+
26
30
  def flatten
27
31
  dependencies.inject([]) do |arr, dependency|
28
32
  arr << dependency
@@ -1,5 +1,5 @@
1
1
  module Bundler
2
2
  module Dependencies
3
- VERSION = '0.5.1'.freeze
3
+ VERSION = '0.6.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,19 @@
1
+ module Bundler
2
+ module Dependencies
3
+ module Visitors
4
+ class Paths
5
+ def walk(graph, name, acc = [], key = [])
6
+ graph.each do |gem|
7
+ next unless gem.include_dependency?(name)
8
+
9
+ new_key = key.dup.push(gem.name)
10
+ walk(gem.dependencies, name, acc, new_key)
11
+ acc << (new_key << name) if gem.dependencies.include?(name)
12
+ end
13
+
14
+ acc
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler-dependencies
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Vandersluis
@@ -80,34 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 0.76.0
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 0.76.0
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop-rspec
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: 1.36.0
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: 1.36.0
111
83
  description:
112
84
  email:
113
85
  - daniel.vandersluis@gmail.com
@@ -136,12 +108,15 @@ files:
136
108
  - lib/bundler/dependencies/cli.rb
137
109
  - lib/bundler/dependencies/cli/command.rb
138
110
  - lib/bundler/dependencies/cli/count.rb
111
+ - lib/bundler/dependencies/cli/find.rb
139
112
  - lib/bundler/dependencies/cli/graph.rb
113
+ - lib/bundler/dependencies/cli/with_gem.rb
140
114
  - lib/bundler/dependencies/graph.rb
141
115
  - lib/bundler/dependencies/scanner.rb
142
116
  - lib/bundler/dependencies/spec.rb
143
117
  - lib/bundler/dependencies/version.rb
144
118
  - lib/bundler/dependencies/visitor.rb
119
+ - lib/bundler/dependencies/visitors/paths.rb
145
120
  - lib/bundler/dependencies/visitors/shell_tree.rb
146
121
  homepage: https://github.com/dvandersluis/bundler-dependencies
147
122
  licenses:
@@ -166,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
141
  - !ruby/object:Gem::Version
167
142
  version: '0'
168
143
  requirements: []
169
- rubygems_version: 3.0.3
144
+ rubygems_version: 3.0.6
170
145
  signing_key:
171
146
  specification_version: 4
172
147
  summary: Find gems in your Gemfile with too many dependencies