bundler-stats 1.0.0 → 1.1.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
  SHA1:
3
- metadata.gz: 2759369de6f085751c3c523a46b935fe5a5d9ca6
4
- data.tar.gz: 1889fbb9f46a05b076af3ce0522bcb32b811ac8f
3
+ metadata.gz: 650453abe6418815db38bb8315026008b6282a2e
4
+ data.tar.gz: e0c227cb7275fe768990d93289880ddcf8474733
5
5
  SHA512:
6
- metadata.gz: b500aed73652a0c28d8fc6558d96a37ebcf6b1c5df86b7ae5e7b335acd6326d122c7e101f99f46ae3e7c5954c10406bd0ad579a07a3c7e60093c6b701be3ac08
7
- data.tar.gz: af29e97ae66a15ac098558f834d505e34286267be9ba9acf3650da791135a13b036b1c5cc1b69ade3c9d9e0d8a312a061f22736473070c31e5df0efca9f80d3b
6
+ metadata.gz: f3b6a623d44ea2ccdd2abc04baf6fc9867ff08f9d47349238fe2491f8167c4cc9223752bb4a0a811dfcda412710f201392ea586a81f27410e9b919bf248b0320
7
+ data.tar.gz: 17293fae4fb428291ef79c7a37183ae865a24a3f65e63fca364e01cb6f2f89af29825cb9f7e897ac9ddb1cd09dc0c55cc7b1660cb1e1fdb540fe5e08b9d0b87c
@@ -0,0 +1,16 @@
1
+ Changelog
2
+ =============
3
+
4
+ ## [1.1.0] - 2018-03-15
5
+ ### Added
6
+
7
+ - Adds a way to view dependency version restrictions for a given gem, by @olivierlacan
8
+
9
+ ## [1.0.0] - 2016-04-13
10
+ ### Added
11
+
12
+ - Base library, woo!
13
+ - List all transitive dependencies and how many other deps rely on them
14
+ - View list of Github-specified dependencies
15
+ - Traverses from your current location to the Gemfile
16
+ - JSON and table outputters
data/README.md CHANGED
@@ -1,21 +1,25 @@
1
1
  Bundler Stats
2
2
  =============
3
3
 
4
- You remember that time someone yanked their library and the entire Node
5
- universe fell apart? Yeah, me too. And all the thinkpieces that came out just
6
- aftward were right: you should be careful about what you include in your
7
- project.
4
+ You remember that time [someone yanked their library](http://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm)
5
+ and the entire Node universe fell apart? Yeah, me too. And all the
6
+ [thinkpieces](http://www.haneycodes.net/npm-left-pad-have-we-forgotten-how-to-program/)
7
+ that came out just afterward were right: you should be careful about
8
+ what dependencies you include in your project.
8
9
 
9
- This project gives you some tools you can use with your existing Gemfile to
10
- determine which gems are including long trees of data, and which you can
11
- potentially remove.
10
+ This project gives you some tools you can use with an existing Gemfile to
11
+ determine which gems are including long trees of their own dependencies,
12
+ and which you can potentially remove.
13
+
14
+ This is an exploratory tool, and I'd be interested to hear what other criteria
15
+ would be useful in determining what tools to remove.
12
16
 
13
17
  Installation
14
18
  ------------
15
19
 
16
20
  You don't need to include `bundler-stats` in your Gemfile, just
17
21
  `gem install bundler-stats`. Unless you wanted to build automation around its
18
- usage, in which case, add it to your Gemfile instead.
22
+ usage, in which case, add it to your Gemfile instead.
19
23
 
20
24
 
21
25
  Usage
@@ -23,14 +27,86 @@ Usage
23
27
 
24
28
  > bundle-stats help
25
29
  Commands:
26
- bundle-stats help [COMMAND] # Describe available commands or one specific command
27
- bundle-stats show TARGET # Prints the dependency tree for a single gem in your Gemfile
28
- bundle-stats stats # Displays basic stats about the gems in your Gemfile
29
- bundle-stats version # Prints the bundler-stats version
30
-
31
- Or just run `bundle-stats` anywhere within your ruby project. You can emit JSON
32
- for automatic consumption with `-f json`.
33
-
30
+ bundle-stats help [COMMAND] # Describe available commands or one specific command
31
+ bundle-stats show TARGET # Prints the dependency tree for a single gem in your Gemfile
32
+ bundle-stats stats # Displays basic stats about the gems in your Gemfile
33
+ bundle-stats version # Prints the bundler-stats version
34
+ bundle-stats versions TARGET # Shows versions requirements for target in other dependencies
35
+
36
+ The most obvious thing to do is run the command by itself, which should help identify problem areas:
37
+
38
+ > bundle-stats
39
+
40
+ +------------------------------|-----------------|-----------------+
41
+ | Name | Total Deps | 1st Level Deps |
42
+ +------------------------------|-----------------|-----------------+
43
+ ... omitted stuff here ...
44
+ | fog | 15 | 6 |
45
+ | fancybox2-rails | 15 | 1 |
46
+ | quiet_assets | 15 | 1 |
47
+ | coffee-rails | 18 | 2 |
48
+ | angular-rails-templates | 19 | 3 |
49
+ | devise | 19 | 6 |
50
+ | rspec-rails | 20 | 7 |
51
+ | sass-rails | 21 | 4 |
52
+ | foundation-icons-sass-rails | 22 | 2 |
53
+ | rails | 29 | 9 |
54
+ | angular_rails_csrf | 30 | 1 |
55
+ | ngannotate-rails | 31 | 2 |
56
+ | activeadmin | 48 | 12 |
57
+ +------------------------------|-----------------|-----------------+
58
+
59
+ Declared Gems: 35
60
+ Total Gems: 113
61
+
62
+ Unpinned Versions: 30
63
+ Github Refs: 1
64
+
65
+ It looks like activeadmin is a huge problem. Use `show` to investigate:
66
+
67
+ > bundle-stats show activeadmin
68
+ bundle-stats for activeadmin
69
+
70
+ depended upon by (0) |
71
+ depends on (48) | arbre, bourbon, coffee-rails, formtastic, formtastic_i18n, inherited_resources, jquery-rails, jquery-ui-rails, kaminari, rails, ransack, sass-rails, activesupport, i18n, json, minitest, thread_safe, tzinfo, sass, thor, coffee-script, railties, coffee-script-source, execjs, actionpack, rake, actionview, rack, rack-test, builder, erubis, has_scope, responders, actionmailer, activemodel, activerecord, bundler, sprockets-rails, mail, mime-types, treetop, polyglot, arel, sprockets, hike, multi_json, tilt, polyamorous
72
+ unique to this (12) | arbre, bourbon, formtastic, formtastic_i18n, inherited_resources, jquery-rails, jquery-ui-rails, kaminari, ransack, has_scope, bundler, polyamorous
73
+
74
+ Removing the dep will only actually remove 12 gems. The rest are shared dependencies with rails. We can also omit trees we aren't going to remove (hi rails) by not following them:
75
+
76
+ > bundle-stats show sass-rails --nofollow="railties,activesupport,actionpack"
77
+ bundle-stats for sass-rails
78
+
79
+ depended upon by (2) | activeadmin, foundation-icons-sass-rails
80
+ depends on (10) | railties, sass, sprockets, sprockets-rails, hike, multi_json, rack, tilt, actionpack, activesupport
81
+ unique to this (0) |
82
+
83
+ To consume information with a build job or somesuch, all commands can emit JSON:
84
+
85
+ > bundle-stats show sass-rails --nofollow="railties,activesupport,actionpack" -f json
86
+ {
87
+ "name": "sass-rails",
88
+ "total_dependencies": 10,
89
+ "first_level_dependencies": 4,
90
+ "top_level_dependencies": {
91
+ "activeadmin": "activeadmin (1.0.0.pre)",
92
+ "foundation-icons-sass-rails": "foundation-icons-sass-rails (3.0.0)"
93
+ },
94
+ "transitive_dependencies": [
95
+ "railties (< 5.0, >= 4.0.0)",
96
+ "sass (~> 3.2.0)",
97
+ "sprockets (<= 2.11.0, ~> 2.8)",
98
+ "sprockets-rails (~> 2.0)",
99
+ "hike (~> 1.2)",
100
+ "multi_json (~> 1.0)",
101
+ "rack (~> 1.0)",
102
+ "tilt (!= 1.3.0, ~> 1.1)",
103
+ "actionpack (>= 3.0)",
104
+ "activesupport (>= 3.0)"
105
+ ],
106
+ "potential_removals": [
107
+
108
+ ]
109
+ }
34
110
 
35
111
  Contributing
36
112
  ------------
@@ -46,6 +122,7 @@ Credits
46
122
  Thanks to the many kind people at [RailsCamp East 2016](http://east.railscamp.com)
47
123
  for the help, the ideas, and the support.
48
124
 
125
+ Thanks to Isaac Bowen for being pedantic about speeling.
49
126
 
50
127
  License
51
128
  -------
@@ -29,6 +29,12 @@ module Bundler
29
29
  })
30
30
  end
31
31
 
32
+ def versions(target)
33
+ @tree.version_requirements(target).merge({
34
+ potential_removals: @remover.potential_removals(target)
35
+ })
36
+ end
37
+
32
38
  def stats
33
39
  { summary: summary,
34
40
  gems: gem_stats
@@ -38,6 +38,20 @@ module Bundler
38
38
  end
39
39
  end
40
40
 
41
+ desc 'versions TARGET', 'Shows versions requirements for target in other dependencies'
42
+ method_option :format, aliases: "-f", description: "Output format, either JSON or text"
43
+ method_option :nofollow, description: "A comma delimited list of dependencies not to follow."
44
+ def versions(target)
45
+ calculator = build_calculator(options)
46
+ stats = calculator.versions(target)
47
+
48
+ if options[:format] =~ /json/i
49
+ say JSON.pretty_generate(stats)
50
+ else
51
+ draw_versions(stats, target)
52
+ end
53
+ end
54
+
41
55
  desc 'version', 'Prints the bundler-stats version'
42
56
  def version
43
57
  say "bundler-stats #{VERSION}"
@@ -70,6 +84,20 @@ module Bundler
70
84
  say ""
71
85
  end
72
86
 
87
+ def draw_versions(stats, target)
88
+ say "bundle-stats for #{target}"
89
+ say ""
90
+ say "depended upon by (#{stats[:top_level_dependencies].count}):\n"
91
+ say "+------------------------------|-------------------+"
92
+ say "| Name | Required Version |"
93
+ say "+------------------------------|-------------------+"
94
+ stats[:top_level_dependencies].each do |stat_line|
95
+ say "| %-28s | %-17s |" % [stat_line[:name], stat_line[:version]]
96
+ end
97
+ say "+------------------------------|-------------------+"
98
+ say ""
99
+ end
100
+
73
101
  def build_calculator(options)
74
102
  if !options[:nofollow].nil?
75
103
  skiplist = options[:nofollow].gsub(/\s+/, '').split(",")
@@ -21,6 +21,16 @@ class Bundler::Stats::Tree
21
21
  }
22
22
  end
23
23
 
24
+ def version_requirements(target)
25
+ transitive_dependencies = transitive_dependencies(target)
26
+ { name: target,
27
+ total_dependencies: transitive_dependencies.count,
28
+ first_level_dependencies: first_level_dependencies(target).count,
29
+ top_level_dependencies: reverse_dependencies_with_versions(target),
30
+ transitive_dependencies: transitive_dependencies,
31
+ }
32
+ end
33
+
24
34
  def first_level_dependencies(target)
25
35
  raise ArgumentError, "Unknown gem #{target}" unless @tree.has_key? target
26
36
  @tree[target].dependencies
@@ -50,6 +60,24 @@ class Bundler::Stats::Tree
50
60
  end
51
61
  end
52
62
 
63
+ def reverse_dependencies_with_versions(target)
64
+ @tree.map do |name, dep|
65
+ transitive_dependencies(name).map do |transitive_dependency|
66
+ if transitive_dependency.name == target
67
+ {
68
+ name: dep.name,
69
+ version: transitive_dependency.requirement.to_s,
70
+ requirement: transitive_dependency.requirement
71
+ }
72
+ else
73
+ nil
74
+ end
75
+ end
76
+ end.flatten.compact.sort do |a,b|
77
+ a[:requirement].as_list <=> b[:requirement].as_list
78
+ end
79
+ end
80
+
53
81
  private
54
82
 
55
83
  def specs_as_tree(specs)
@@ -1,6 +1,6 @@
1
1
  module Bundler
2
2
  module Stats
3
3
  # bundler-stats version
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
6
6
  end
@@ -100,4 +100,22 @@ describe Bundler::Stats::Calculator do
100
100
  expect(target).to include(:github)
101
101
  end
102
102
  end
103
+
104
+ context "#versions" do
105
+ it "is a hash" do
106
+ calculator = subject.new(gemfile_path, lockfile_path)
107
+ versions = calculator.versions("depth-one")
108
+
109
+ expect(versions).to be_a(Hash)
110
+ expect(versions[:top_level_dependencies]).to eq([])
111
+ end
112
+
113
+ it "returns for second-level deps" do
114
+ calculator = subject.new(gemfile_path, lockfile_path)
115
+ versions = calculator.versions("depth-two")
116
+
117
+ expect(versions).to be_a(Hash)
118
+ expect(versions[:top_level_dependencies].map(&:name)).to include("depth-one")
119
+ end
120
+ end
103
121
  end
@@ -124,6 +124,16 @@ describe Bundler::Stats::Tree do
124
124
  end
125
125
  end
126
126
 
127
+ context "#version_requirements" do
128
+ it "is a hash with some keys" do
129
+ tree = subject.new(parser)
130
+
131
+ target = tree.version_requirements("depth-one")
132
+
133
+ expect(target).to be_a(Hash)
134
+ end
135
+ end
136
+
127
137
  context "skip lists" do
128
138
  it "still includes the skipped entry" do
129
139
  tree = subject.new(parser, skiplist: ["depth-three"])
metadata CHANGED
@@ -1,83 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler-stats
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Mastey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-11 00:00:00.000000000 Z
11
+ date: 2018-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.9'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.9'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0.19'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.19'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.4'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.4'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: guard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '2.13'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.13'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pry
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0.10'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.10'
83
83
  description: Looks through your lockfile and tries to identify problematic use of
@@ -87,10 +87,12 @@ executables:
87
87
  - bundle-stats
88
88
  extensions: []
89
89
  extra_rdoc_files:
90
+ - CHANGELOG.md
90
91
  - CODE_OF_CONDUCT.md
91
92
  - README.md
92
93
  files:
93
- - .gitignore
94
+ - ".gitignore"
95
+ - CHANGELOG.md
94
96
  - CODE_OF_CONDUCT.md
95
97
  - Gemfile
96
98
  - Guardfile
@@ -119,17 +121,17 @@ require_paths:
119
121
  - lib
120
122
  required_ruby_version: !ruby/object:Gem::Requirement
121
123
  requirements:
122
- - - '>='
124
+ - - ">="
123
125
  - !ruby/object:Gem::Version
124
126
  version: '0'
125
127
  required_rubygems_version: !ruby/object:Gem::Requirement
126
128
  requirements:
127
- - - '>='
129
+ - - ">="
128
130
  - !ruby/object:Gem::Version
129
131
  version: '0'
130
132
  requirements: []
131
133
  rubyforge_project:
132
- rubygems_version: 2.0.14
134
+ rubygems_version: 2.6.13
133
135
  signing_key:
134
136
  specification_version: 4
135
137
  summary: Dependency investigation for Bundler