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 +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +93 -16
- data/lib/bundler/stats/calculator.rb +6 -0
- data/lib/bundler/stats/cli.rb +28 -0
- data/lib/bundler/stats/tree.rb +28 -0
- data/lib/bundler/stats/version.rb +1 -1
- data/spec/lib/bundler/stats/calculator_spec.rb +18 -0
- data/spec/lib/bundler/stats/tree_spec.rb +10 -0
- metadata +18 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 650453abe6418815db38bb8315026008b6282a2e
|
4
|
+
data.tar.gz: e0c227cb7275fe768990d93289880ddcf8474733
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3b6a623d44ea2ccdd2abc04baf6fc9867ff08f9d47349238fe2491f8167c4cc9223752bb4a0a811dfcda412710f201392ea586a81f27410e9b919bf248b0320
|
7
|
+
data.tar.gz: 17293fae4fb428291ef79c7a37183ae865a24a3f65e63fca364e01cb6f2f89af29825cb9f7e897ac9ddb1cd09dc0c55cc7b1660cb1e1fdb540fe5e08b9d0b87c
|
data/CHANGELOG.md
ADDED
@@ -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
|
5
|
-
universe fell apart? Yeah, me too. And all the
|
6
|
-
|
7
|
-
|
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
|
10
|
-
determine which gems are including long trees of
|
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]
|
27
|
-
bundle-stats show TARGET
|
28
|
-
bundle-stats stats
|
29
|
-
bundle-stats version
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-------
|
data/lib/bundler/stats/cli.rb
CHANGED
@@ -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(",")
|
data/lib/bundler/stats/tree.rb
CHANGED
@@ -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)
|
@@ -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.
|
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:
|
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.
|
134
|
+
rubygems_version: 2.6.13
|
133
135
|
signing_key:
|
134
136
|
specification_version: 4
|
135
137
|
summary: Dependency investigation for Bundler
|