bundler-stats 1.3.2 → 2.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 +4 -4
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +67 -4
- data/Guardfile +0 -12
- data/README.md +95 -62
- data/bin/bundler-stats +1 -0
- data/bundler-stats.gemspec +2 -0
- data/lib/bundler/stats/calculator.rb +1 -1
- data/lib/bundler/stats/cli.rb +38 -29
- data/lib/bundler/stats/printer.rb +143 -0
- data/lib/bundler/stats/remover.rb +10 -6
- data/lib/bundler/stats/tree.rb +3 -0
- data/lib/bundler/stats/version.rb +1 -1
- data/lib/bundler/stats.rb +4 -3
- data/spec/lib/bundler/stats/calculator_spec.rb +18 -0
- data/spec/lib/bundler/stats/printer_spec.rb +225 -0
- data/spec/lib/bundler/stats/remover_spec.rb +2 -2
- metadata +36 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ce461ba8ff653585236394b5427033c2a5c8411d3a47d880a39f8d48925c0723
|
|
4
|
+
data.tar.gz: '058da5ce7a60f9ac7fc3e2f37fd56ac86466665bbea1cd95af61ce37db2ebd66'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c44cc31e39f9be21950ef7a5c1146f30d22ba40314b267cc1621397c8259ea024cb96f9f79e139d7fbe4c9650e66d4b1b484e5e8d8e41092f9f4c286a0b13438
|
|
7
|
+
data.tar.gz: 44f2713ef76cab6726489481ba5322acee80feb571177608fa8267d920ce67992650da9ee2bcb2d32973ffdc70fa1851d009e347e526f0648bce93dcb1ed6f45
|
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--color
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,19 +1,82 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=============
|
|
3
3
|
|
|
4
|
-
## [
|
|
4
|
+
## [2.1.0] - 2021-11-29
|
|
5
|
+
|
|
6
|
+
### Changed
|
|
7
|
+
- Add Travis targets for more modern rubies, by @etagwerker.
|
|
8
|
+
- Make sorting predictable across platforms, by @etagwerker.
|
|
9
|
+
|
|
5
10
|
### Fixed
|
|
11
|
+
- Fix error in CI when `tput` isn't available, by @etagwerker.
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
## [2.0.1] - 2018-05-04
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Complete custom table printer for some nicer output.
|
|
17
|
+
|
|
18
|
+
## [2.0.0] - 2018-05-04
|
|
19
|
+
Broken as hell.
|
|
20
|
+
|
|
21
|
+
## [1.3.4] - 2019-04-18
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Allow use of either `bundle-stats` or `bundler-stats` since the gem name was
|
|
25
|
+
a confusing choice. Live and learn.
|
|
8
26
|
|
|
9
|
-
## [1.1.0] - 2018-03-15
|
|
10
27
|
### Added
|
|
28
|
+
- Display resolved version of a gem when using `bundler-stats show`.
|
|
29
|
+
|
|
30
|
+
## [1.3.3] - 2019-04-18
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- Only print missing system dependency warning once per target gem, rather than
|
|
34
|
+
blowing up the console when a complicated gem is affected.
|
|
35
|
+
|
|
36
|
+
## [1.3.2] - 2019-04-17
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- Fix issue when testing removability and a system gem from another platform
|
|
40
|
+
is "required", thx @rwojnarowski.
|
|
41
|
+
|
|
42
|
+
## [1.3.1] - 2019-04-05
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
- Nicer table printing, still committed to not adding a table printing gem.
|
|
46
|
+
|
|
47
|
+
## [1.3.0] - 2019-04-05
|
|
11
48
|
|
|
49
|
+
### Changed
|
|
50
|
+
- Reversed the order in which gems are printed to worst-offenders-first.
|
|
51
|
+
|
|
52
|
+
## [1.2.1] - 2019-04-05
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
- When a system gem is missing from the lockfile (but is depended upon), warn
|
|
56
|
+
the user rather than exploding.
|
|
57
|
+
|
|
58
|
+
## [1.2.0] - 2019-04-05
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
- Loosen dependency on thor gem, by localhostdotdev.
|
|
62
|
+
|
|
63
|
+
## [1.1.2] - 2018-03-16
|
|
64
|
+
Wonkiness w/ versioning. Apparently I was bad at this.
|
|
65
|
+
|
|
66
|
+
## [1.1.0] - 2018-03-16
|
|
67
|
+
Eventually superseded by 1.1.2 for reasons.
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
- Remove unintentional inclusion of pry outside of dev environment, per @Tuxified
|
|
71
|
+
|
|
72
|
+
## [1.1.0] - 2018-03-15
|
|
73
|
+
|
|
74
|
+
### Added
|
|
12
75
|
- Adds a way to view dependency version restrictions for a given gem, by @olivierlacan
|
|
13
76
|
|
|
14
77
|
## [1.0.0] - 2016-04-13
|
|
15
|
-
### Added
|
|
16
78
|
|
|
79
|
+
### Added
|
|
17
80
|
- Base library, woo!
|
|
18
81
|
- List all transitive dependencies and how many other deps rely on them
|
|
19
82
|
- View list of Github-specified dependencies
|
data/Guardfile
CHANGED
|
@@ -15,18 +15,6 @@
|
|
|
15
15
|
#
|
|
16
16
|
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
|
17
17
|
|
|
18
|
-
guard :bundler do
|
|
19
|
-
require 'guard/bundler'
|
|
20
|
-
require 'guard/bundler/verify'
|
|
21
|
-
helper = Guard::Bundler::Verify.new
|
|
22
|
-
|
|
23
|
-
files = ['Gemfile']
|
|
24
|
-
files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }
|
|
25
|
-
|
|
26
|
-
# Assume files are symlinked from somewhere
|
|
27
|
-
files.each { |file| watch(helper.real_path(file)) }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
18
|
guard :rspec, cmd: 'rspec' do
|
|
31
19
|
watch(%r{^spec/.+_spec\.rb$})
|
|
32
20
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
data/README.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
Bundler Stats
|
|
2
2
|
=============
|
|
3
3
|
|
|
4
|
-
You remember that time [someone yanked their
|
|
5
|
-
and
|
|
4
|
+
You remember that time [someone yanked their
|
|
5
|
+
library](http://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm) and the
|
|
6
|
+
entire Node universe fell apart? Yeah, me too. And all the
|
|
6
7
|
[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
|
-
|
|
8
|
+
that came out just afterward were right: you should be careful about what
|
|
9
|
+
dependencies you include in your project.
|
|
9
10
|
|
|
10
11
|
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
|
-
|
|
12
|
+
determine which gems are including long trees of their own dependencies, and
|
|
13
|
+
which you can potentially remove.
|
|
13
14
|
|
|
14
15
|
This is an exploratory tool, and I'd be interested to hear what other criteria
|
|
15
16
|
would be useful in determining what tools to remove.
|
|
@@ -33,75 +34,106 @@ Usage
|
|
|
33
34
|
bundle-stats version # Prints the bundler-stats version
|
|
34
35
|
bundle-stats versions TARGET # Shows versions requirements for target in other dependencies
|
|
35
36
|
|
|
36
|
-
The most obvious thing to do is run the command by itself, which should help
|
|
37
|
+
The most obvious thing to do is run the command by itself, which should help
|
|
38
|
+
identify problem areas:
|
|
37
39
|
|
|
38
40
|
> bundle-stats
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
42
|
+
+----------------------------|------------|----------------+
|
|
43
|
+
| Name | Total Deps | 1st Level Deps |
|
|
44
|
+
+----------------------------|------------|----------------+
|
|
45
|
+
| rails_admin | 60 | 12 |
|
|
46
|
+
| rails | 40 | 12 |
|
|
47
|
+
| compass-rails | 35 | 3 |
|
|
48
|
+
| haml-rails | 29 | 5 |
|
|
49
|
+
| rspec-rails | 27 | 7 |
|
|
50
|
+
| sass-rails | 26 | 5 |
|
|
51
|
+
| devise | 26 | 5 |
|
|
52
|
+
| scenic | 25 | 2 |
|
|
53
|
+
| coffee-rails | 25 | 2 |
|
|
54
|
+
| guard-rubocop | 24 | 2 |
|
|
55
|
+
| versionist | 23 | 3 |
|
|
56
|
+
| factory_bot_rails | 23 | 2 |
|
|
57
|
+
| ... omitted stuff here ... |
|
|
58
|
+
+----------------------------|------------|----------------+
|
|
59
|
+
|
|
60
|
+
Declared Gems 56
|
|
61
|
+
Total Gems 170
|
|
62
|
+
Unpinned Versions 54
|
|
63
|
+
Github Refs 0
|
|
64
|
+
|
|
65
|
+
It looks like rails_admin is a huge problem. Use `show` to investigate:
|
|
66
|
+
|
|
67
|
+
> bundle-stats show rails_admin
|
|
68
|
+
bundle-stats for rails_admin
|
|
69
|
+
|
|
70
|
+
+--------------------------------|----------------------------------------+
|
|
71
|
+
| Depended Upon By (0) | |
|
|
72
|
+
| Depends On (60) | builder, coffee-rails |
|
|
73
|
+
| | font-awesome-rails, haml, jquery-rails |
|
|
74
|
+
| | jquery-ui-rails, kaminari, nested_form |
|
|
75
|
+
| | rack-pjax, rails, remotipart |
|
|
76
|
+
| | sass-rails, coffee-script, railties |
|
|
77
|
+
| | coffee-script-source, execjs |
|
|
78
|
+
| | actionpack, activesupport |
|
|
79
|
+
| | method_source, rake, thor, actionview |
|
|
80
|
+
| | rack, rack-test, rails-dom-testing |
|
|
81
|
+
| | rails-html-sanitizer, erubi |
|
|
82
|
+
| | concurrent-ruby, i18n, minitest |
|
|
83
|
+
| | tzinfo, thread_safe, nokogiri |
|
|
84
|
+
| | mini_portile2, loofah, crass, temple |
|
|
85
|
+
| | tilt, kaminari-actionview |
|
|
86
|
+
| | kaminari-activerecord, kaminari-core |
|
|
87
|
+
| | activerecord, activemodel, arel |
|
|
88
|
+
| | actioncable, actionmailer, activejob |
|
|
89
|
+
| | activestorage, bundler |
|
|
90
|
+
| | sprockets-rails, nio4r |
|
|
91
|
+
| | websocket-driver, websocket-extensions |
|
|
92
|
+
| | mail, globalid, mini_mime, marcel |
|
|
93
|
+
| | mimemagic, sprockets, sass |
|
|
94
|
+
| Unique to This (9) | font-awesome-rails, kaminari |
|
|
95
|
+
| | nested_form, rack-pjax, remotipart |
|
|
96
|
+
| | kaminari-actionview |
|
|
97
|
+
| | kaminari-activerecord, kaminari-core |
|
|
98
|
+
| | bundler |
|
|
99
|
+
+--------------------------------|----------------------------------------+
|
|
100
|
+
|
|
101
|
+
Removing the dep will only actually remove 9 gems. The rest are shared
|
|
102
|
+
dependencies with other gems like rails. We can also omit trees we aren't going
|
|
103
|
+
to remove (hi rails) by not following them:
|
|
75
104
|
|
|
76
105
|
> bundle-stats show sass-rails --nofollow="railties,activesupport,actionpack"
|
|
77
106
|
bundle-stats for sass-rails
|
|
78
107
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
108
|
+
+--------------------------------|----------------------------------------+
|
|
109
|
+
| Depended Upon By (2) | compass-rails, rails_admin |
|
|
110
|
+
| Depends On (9) | railties, sass, sprockets |
|
|
111
|
+
| | sprockets-rails, tilt, concurrent-ruby |
|
|
112
|
+
| | rack, actionpack, activesupport |
|
|
113
|
+
| Unique to This (0) | |
|
|
114
|
+
+--------------------------------|----------------------------------------+
|
|
82
115
|
|
|
83
116
|
To consume information with a build job or somesuch, all commands can emit JSON:
|
|
84
117
|
|
|
85
118
|
> bundle-stats show sass-rails --nofollow="railties,activesupport,actionpack" -f json
|
|
86
119
|
{
|
|
87
120
|
"name": "sass-rails",
|
|
88
|
-
"total_dependencies":
|
|
89
|
-
"first_level_dependencies":
|
|
121
|
+
"total_dependencies": 9,
|
|
122
|
+
"first_level_dependencies": 5,
|
|
90
123
|
"top_level_dependencies": {
|
|
91
|
-
"
|
|
92
|
-
"
|
|
124
|
+
"compass-rails": "compass-rails (3.1.0)",
|
|
125
|
+
"rails_admin": "rails_admin (1.3.0)"
|
|
93
126
|
},
|
|
94
127
|
"transitive_dependencies": [
|
|
95
|
-
"railties (<
|
|
96
|
-
"sass (~> 3.
|
|
97
|
-
"sprockets (
|
|
98
|
-
"sprockets-rails (
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"rack (
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"activesupport (>= 3.0)"
|
|
128
|
+
"railties (< 6, >= 4.0.0)",
|
|
129
|
+
"sass (~> 3.1)",
|
|
130
|
+
"sprockets (< 4.0, >= 2.8)",
|
|
131
|
+
"sprockets-rails (< 4.0, >= 2.0)",
|
|
132
|
+
"tilt (< 3, >= 1.1)",
|
|
133
|
+
"concurrent-ruby (~> 1.0)",
|
|
134
|
+
"rack (< 3, > 1)",
|
|
135
|
+
"actionpack (>= 4.0)",
|
|
136
|
+
"activesupport (>= 4.0)"
|
|
105
137
|
],
|
|
106
138
|
"potential_removals": [
|
|
107
139
|
|
|
@@ -119,12 +151,13 @@ Contribution is expected to conform to the [Contributor Covenant](https://github
|
|
|
119
151
|
Credits
|
|
120
152
|
-------
|
|
121
153
|
|
|
122
|
-
Thanks to the many kind people at [RailsCamp East
|
|
123
|
-
for the help, the ideas, and the support.
|
|
154
|
+
Thanks to the many kind people at [RailsCamp East
|
|
155
|
+
2016](http://east.railscamp.com) for the help, the ideas, and the support.
|
|
124
156
|
|
|
125
157
|
Thanks to Isaac Bowen for being pedantic about speeling.
|
|
126
158
|
|
|
127
159
|
License
|
|
128
160
|
-------
|
|
129
161
|
|
|
130
|
-
This software is released under the [MIT
|
|
162
|
+
This software is released under the [MIT
|
|
163
|
+
License](https://github.com/jmmastey/bundler-stats/blob/master/MIT-LICENSE).
|
data/bin/bundler-stats
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bin/bundle-stats
|
data/bundler-stats.gemspec
CHANGED
|
@@ -40,5 +40,7 @@ Gem::Specification.new do |gem|
|
|
|
40
40
|
|
|
41
41
|
gem.add_development_dependency "rspec", "~> 3.4"
|
|
42
42
|
gem.add_development_dependency "guard", "~> 2.13"
|
|
43
|
+
gem.add_development_dependency "guard-rspec"
|
|
43
44
|
gem.add_development_dependency "pry", "~> 0.10"
|
|
45
|
+
gem.add_development_dependency "rb-readline"
|
|
44
46
|
end
|
data/lib/bundler/stats/cli.rb
CHANGED
|
@@ -59,52 +59,61 @@ module Bundler
|
|
|
59
59
|
|
|
60
60
|
private
|
|
61
61
|
|
|
62
|
-
# TODO: just install table_print, 'eh?
|
|
63
62
|
def draw_stats(gem_stats, summary)
|
|
64
63
|
max_name_length = gem_stats.map { |gem| gem[:name].length }.max
|
|
65
64
|
|
|
66
|
-
say
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
say Printer.new(
|
|
66
|
+
headers: ["Name", "Total Deps", "1st Level Deps"],
|
|
67
|
+
data: gem_stats.map { |stat_line|
|
|
68
|
+
[stat_line[:name], stat_line[:total_dependencies], stat_line[:first_level_dependencies]]
|
|
69
|
+
}).to_s
|
|
70
|
+
|
|
71
|
+
say Printer.new(
|
|
72
|
+
headers: nil,
|
|
73
|
+
borders: false,
|
|
74
|
+
data: [
|
|
75
|
+
["Declared Gems", summary[:declared]],
|
|
76
|
+
["Total Gems", summary[:total]],
|
|
77
|
+
["", ""],
|
|
78
|
+
["Unpinned Versions", summary[:unpinned]],
|
|
79
|
+
["Github Refs", summary[:github]],
|
|
80
|
+
]).to_s
|
|
77
81
|
say ""
|
|
78
|
-
say "Unpinned Versions: #{summary[:unpinned]}"
|
|
79
|
-
say "Github Refs: #{summary[:github]}"
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
def draw_show(stats, target)
|
|
83
85
|
say "bundle-stats for #{target}"
|
|
84
86
|
say ""
|
|
85
|
-
|
|
86
|
-
say
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
|
|
88
|
+
say Printer.new(
|
|
89
|
+
data: [
|
|
90
|
+
["Depended Upon By (#{stats[:top_level_dependencies].count})", stats[:top_level_dependencies].values.map(&:name)],
|
|
91
|
+
["Depends On (#{stats[:transitive_dependencies].count})", stats[:transitive_dependencies].map(&:name)],
|
|
92
|
+
["Unique to This (#{stats[:potential_removals].count})", stats[:potential_removals].map(&:name)],
|
|
93
|
+
]).to_s
|
|
89
94
|
end
|
|
90
95
|
|
|
91
96
|
def draw_versions(stats, target)
|
|
92
97
|
dependers = stats[:top_level_dependencies] # they do the depending
|
|
93
98
|
say "bundle-stats for #{target}"
|
|
94
|
-
say
|
|
95
|
-
|
|
99
|
+
say Printer.new(
|
|
100
|
+
headers: nil,
|
|
101
|
+
borders: false,
|
|
102
|
+
data: [
|
|
103
|
+
["Depended Upon By", stats[:top_level_dependencies].count],
|
|
104
|
+
["Resolved Version", stats[:resolved_version]],
|
|
105
|
+
]).to_s
|
|
106
|
+
|
|
96
107
|
if dependers.count > 0
|
|
97
|
-
max_name_length = dependers.map { |gem| gem[:name].length }.max
|
|
98
|
-
|
|
99
|
-
say "+-#{"-" * max_name_length}-|-------------------+"
|
|
100
|
-
say "| %-#{max_name_length}s | Required Version |" % ["Name"]
|
|
101
|
-
say "+-#{"-" * max_name_length}-|-------------------+"
|
|
102
|
-
dependers.each do |stat_line|
|
|
103
|
-
say "| %-#{max_name_length}s | %-17s |" % [stat_line[:name], stat_line[:version]]
|
|
104
|
-
end
|
|
105
|
-
say "+-#{"-" * max_name_length}-|-------------------+"
|
|
106
108
|
say ""
|
|
109
|
+
say Printer.new(
|
|
110
|
+
headers: ["Name", "Required Version"],
|
|
111
|
+
data: dependers.map { |stat_line|
|
|
112
|
+
[stat_line[:name], stat_line[:version]]
|
|
113
|
+
}).to_s
|
|
107
114
|
end
|
|
115
|
+
|
|
116
|
+
say ""
|
|
108
117
|
end
|
|
109
118
|
|
|
110
119
|
def build_calculator(options)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# this is somewhat duplicative of the table_print gem, but tbh I like that we
|
|
2
|
+
# don't have many dependencies yet, so I'd rather keep it this way.
|
|
3
|
+
class Bundler::Stats::Printer
|
|
4
|
+
attr_accessor :headers, :data, :borders
|
|
5
|
+
|
|
6
|
+
MIN_COL_SIZE = 10
|
|
7
|
+
|
|
8
|
+
BORDERS = {
|
|
9
|
+
on: { corner: "+", horizontal: "-", vertical: "|" },
|
|
10
|
+
off: { corner: " ", horizontal: " ", vertical: " " },
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def initialize(headers: nil, data: [], borders: true)
|
|
14
|
+
@headers = headers
|
|
15
|
+
@data = data
|
|
16
|
+
@borders = borders ? BORDERS[:on] : BORDERS[:off]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
table_data = ([headers] + data).compact
|
|
21
|
+
col_widths = column_widths(table_data)
|
|
22
|
+
|
|
23
|
+
lines = []
|
|
24
|
+
lines << separator_row(col_widths)
|
|
25
|
+
|
|
26
|
+
if headers
|
|
27
|
+
lines << aligned_row(headers, col_widths)
|
|
28
|
+
lines << separator_row(col_widths)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
data.each do |row|
|
|
32
|
+
lines += split_rows(row, col_widths)
|
|
33
|
+
end
|
|
34
|
+
lines << separator_row(col_widths)
|
|
35
|
+
|
|
36
|
+
lines.join("\n")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def terminal_width
|
|
40
|
+
Integer(Kernel.send(:"`", "tput cols"))
|
|
41
|
+
rescue StandardError
|
|
42
|
+
80
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def column_widths(table_data)
|
|
46
|
+
num_cols = table_data.first.length
|
|
47
|
+
chrome = 2 + 2 + (num_cols - 1) * 3
|
|
48
|
+
|
|
49
|
+
# doesn't fit at all
|
|
50
|
+
if chrome + (num_cols * MIN_COL_SIZE) > terminal_width
|
|
51
|
+
raise ArgumentError, "Table smooshed. Refusing to print table."
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
data_widths = 0.upto(num_cols - 1).map do |idx|
|
|
55
|
+
max_width(table_data.map { |row| row[idx] })
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# fits comfortably
|
|
59
|
+
if data_widths.inject(&:+) + chrome < terminal_width
|
|
60
|
+
return data_widths
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
free_space = terminal_width
|
|
64
|
+
free_space -= chrome
|
|
65
|
+
free_space -= MIN_COL_SIZE * num_cols
|
|
66
|
+
|
|
67
|
+
# fit uncomfortably
|
|
68
|
+
widths = [MIN_COL_SIZE] * num_cols
|
|
69
|
+
data_widths.each_with_index do |width, idx|
|
|
70
|
+
next unless width > widths[idx]
|
|
71
|
+
|
|
72
|
+
allocated = [width, free_space].min
|
|
73
|
+
|
|
74
|
+
if allocated > 0
|
|
75
|
+
widths[idx] += allocated
|
|
76
|
+
free_space -= allocated
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
widths
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def max_width(data)
|
|
86
|
+
data.map do |value|
|
|
87
|
+
Array(value).join(", ").length
|
|
88
|
+
end.max
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def separator_row(col_widths)
|
|
92
|
+
sep = "#{borders[:horizontal]}#{borders[:vertical]}#{borders[:horizontal]}"
|
|
93
|
+
|
|
94
|
+
"#{borders[:corner]}#{borders[:horizontal]}" +
|
|
95
|
+
col_widths.map { |width| borders[:horizontal] * width }.join(sep) +
|
|
96
|
+
"#{borders[:horizontal]}#{borders[:corner]}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def split_rows(row, col_widths)
|
|
100
|
+
return [] unless row.find { |v| v && v.length > 0 }
|
|
101
|
+
|
|
102
|
+
rows_with_splits = [row]
|
|
103
|
+
next_row = []
|
|
104
|
+
|
|
105
|
+
joined_data = row.each_with_index.map do |val, idx|
|
|
106
|
+
words = Array(val).map(&:to_s)
|
|
107
|
+
target_width = col_widths[idx]
|
|
108
|
+
|
|
109
|
+
(cell, remainder) = row_and_remainder(words, target_width)
|
|
110
|
+
|
|
111
|
+
next_row[idx] = remainder
|
|
112
|
+
cell
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
([aligned_row(joined_data, col_widths)] +
|
|
116
|
+
split_rows(next_row, col_widths)).compact
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def row_and_remainder(words, target_width)
|
|
120
|
+
if(words.join(", ").length < target_width)
|
|
121
|
+
return [words.join(", "), nil]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
this_row = []
|
|
125
|
+
while words.length > 0 && (this_row.join(", ").length + words[0].length) <= target_width
|
|
126
|
+
this_row << words.shift
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
[this_row.join(", "), words]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def aligned_row(row, col_widths)
|
|
133
|
+
aligned_values = row.each_with_index.map do |data, idx|
|
|
134
|
+
if idx == 0
|
|
135
|
+
data.rjust(col_widths[idx])
|
|
136
|
+
else
|
|
137
|
+
data.ljust(col_widths[idx])
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
"#{borders[:vertical]} " + aligned_values.join(" #{borders[:vertical]} ") + " #{borders[:vertical]}"
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
class Bundler::Stats::Remover
|
|
2
|
-
ERR_MESSAGE = "Trying to check whether
|
|
2
|
+
ERR_MESSAGE = "Trying to check whether dep can be removed, but was unable " \
|
|
3
3
|
"to resolve whether it is used by `%s`. It may not be in your Gemfile.lock. " \
|
|
4
4
|
"This often happens when a dependency isn't installed on your platform."
|
|
5
5
|
|
|
6
6
|
def initialize(tree, top_level)
|
|
7
|
-
@tree
|
|
8
|
-
@top_level
|
|
7
|
+
@tree = tree
|
|
8
|
+
@top_level = top_level
|
|
9
|
+
@trace_warnings = []
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def potential_removals(target)
|
|
@@ -33,7 +34,7 @@ class Bundler::Stats::Remover
|
|
|
33
34
|
return true if candidate == target
|
|
34
35
|
|
|
35
36
|
if modified_tree[candidate].nil?
|
|
36
|
-
|
|
37
|
+
warn_of_bad_tracing(candidate)
|
|
37
38
|
else
|
|
38
39
|
deps_to_check += modified_tree[candidate].dependencies
|
|
39
40
|
end
|
|
@@ -44,7 +45,10 @@ class Bundler::Stats::Remover
|
|
|
44
45
|
|
|
45
46
|
private
|
|
46
47
|
|
|
47
|
-
def
|
|
48
|
-
|
|
48
|
+
def warn_of_bad_tracing(candidate)
|
|
49
|
+
return if @trace_warnings.include? candidate
|
|
50
|
+
|
|
51
|
+
STDERR.puts(ERR_MESSAGE % [candidate])
|
|
52
|
+
@trace_warnings << candidate
|
|
49
53
|
end
|
|
50
54
|
end
|
data/lib/bundler/stats/tree.rb
CHANGED
|
@@ -25,7 +25,10 @@ class Bundler::Stats::Tree
|
|
|
25
25
|
|
|
26
26
|
def version_requirements(target)
|
|
27
27
|
transitive_dependencies = transitive_dependencies(target)
|
|
28
|
+
resolved_version = @tree[target].version if @tree.has_key?(target)
|
|
29
|
+
|
|
28
30
|
{ name: target,
|
|
31
|
+
resolved_version: resolved_version,
|
|
29
32
|
total_dependencies: transitive_dependencies.count,
|
|
30
33
|
first_level_dependencies: first_level_dependencies(target).count,
|
|
31
34
|
top_level_dependencies: reverse_dependencies_with_versions(target),
|
data/lib/bundler/stats.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
require_relative 'stats/version'
|
|
2
|
-
require_relative 'stats/tree'
|
|
3
|
-
require_relative 'stats/remover'
|
|
4
1
|
require_relative 'stats/calculator'
|
|
2
|
+
require_relative 'stats/printer'
|
|
3
|
+
require_relative 'stats/remover'
|
|
4
|
+
require_relative 'stats/tree'
|
|
5
|
+
require_relative 'stats/version'
|
|
@@ -77,6 +77,16 @@ describe Bundler::Stats::Calculator do
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
context "#gem_stats" do
|
|
80
|
+
let(:partial_sorted_result) do
|
|
81
|
+
[
|
|
82
|
+
["will_paginate", 0],
|
|
83
|
+
["rolify", 0],
|
|
84
|
+
["rubocop-rspec", 0],
|
|
85
|
+
["spring", 0],
|
|
86
|
+
["state_machine", 0],
|
|
87
|
+
]
|
|
88
|
+
end
|
|
89
|
+
|
|
80
90
|
it "includes entries for each gem" do
|
|
81
91
|
calculator = subject.new(gemfile_path, lockfile_path)
|
|
82
92
|
|
|
@@ -85,6 +95,14 @@ describe Bundler::Stats::Calculator do
|
|
|
85
95
|
expect(target).to be_a(Array)
|
|
86
96
|
expect(target.length).to eq(calculator.gemfile.length)
|
|
87
97
|
end
|
|
98
|
+
|
|
99
|
+
it "sorts entries by total dependencies descending and name ascending" do
|
|
100
|
+
calculator = subject.new(gemfile_path, lockfile_path)
|
|
101
|
+
|
|
102
|
+
target = calculator.gem_stats
|
|
103
|
+
tuple = target.map {|x| [x[:name], x[:total_dependencies]] }
|
|
104
|
+
expect(tuple).to end_with(*partial_sorted_result)
|
|
105
|
+
end
|
|
88
106
|
end
|
|
89
107
|
|
|
90
108
|
context "#summary" do
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
require 'bundler/stats'
|
|
3
|
+
|
|
4
|
+
describe Bundler::Stats::Printer do
|
|
5
|
+
subject { described_class }
|
|
6
|
+
|
|
7
|
+
def set_term_width(width)
|
|
8
|
+
allow(Kernel).to receive(:"`").and_return(width)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "#terminal_width" do
|
|
12
|
+
context "*nix systems" do
|
|
13
|
+
it "return the kernel width" do
|
|
14
|
+
set_term_width(180)
|
|
15
|
+
|
|
16
|
+
printer = subject.new
|
|
17
|
+
response = printer.terminal_width
|
|
18
|
+
|
|
19
|
+
expect(response).to eq(180)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "non-*nix systems" do
|
|
24
|
+
it "always returns a small number" do
|
|
25
|
+
set_term_width(nil)
|
|
26
|
+
|
|
27
|
+
printer = subject.new
|
|
28
|
+
response = printer.terminal_width
|
|
29
|
+
|
|
30
|
+
expect(response).to eq(80)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "tput returns an error" do
|
|
35
|
+
it "returns the default value" do
|
|
36
|
+
allow(Kernel).to receive(:send).and_return("tput: No value for $TERM and no -T specified")
|
|
37
|
+
|
|
38
|
+
printer = subject.new
|
|
39
|
+
response = printer.terminal_width
|
|
40
|
+
|
|
41
|
+
expect(response).to eq(80)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#column_widths" do
|
|
47
|
+
it "comfortably prints tables of comfortable data" do
|
|
48
|
+
set_term_width(80)
|
|
49
|
+
printer = subject.new
|
|
50
|
+
table_data = [
|
|
51
|
+
[ "name", "data" ],
|
|
52
|
+
[ "*" * 10, "*" * 20 ],
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
widths = printer.column_widths(table_data)
|
|
56
|
+
|
|
57
|
+
expect(widths).to eq([10, 20])
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "smooshes uncomfortably long data" do
|
|
61
|
+
set_term_width(60)
|
|
62
|
+
printer = subject.new
|
|
63
|
+
table_data = [
|
|
64
|
+
[ "name", "data" ],
|
|
65
|
+
[ "*" * 10, "*" * 60 ],
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
widths = printer.column_widths(table_data)
|
|
69
|
+
|
|
70
|
+
target_widths = [10, 43] # 7 for gutters
|
|
71
|
+
expect(widths).to eq(target_widths)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "always allows some amount of space for data" do
|
|
75
|
+
set_term_width(60)
|
|
76
|
+
printer = subject.new
|
|
77
|
+
table_data = [
|
|
78
|
+
[ "name", "data1", "data2", "data3" ],
|
|
79
|
+
[ "*" * 10, "*" * 60, "*" * 60, "*" * 60 ],
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
widths = printer.column_widths(table_data)
|
|
83
|
+
|
|
84
|
+
target_widths = [10, 17, 10, 10] # 13 for gutters
|
|
85
|
+
expect(widths).to eq(target_widths)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "bails if it can't handle that data" do
|
|
89
|
+
set_term_width(10)
|
|
90
|
+
printer = subject.new
|
|
91
|
+
table_data = [
|
|
92
|
+
[ "name", "data" ],
|
|
93
|
+
[ "*" * 10, "*" * 20 ],
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
expect {
|
|
97
|
+
printer.column_widths(table_data)
|
|
98
|
+
}.to raise_error(ArgumentError)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe "#to_s" do
|
|
103
|
+
it "prints a pretty table" do
|
|
104
|
+
set_term_width(80)
|
|
105
|
+
printer = subject.new(headers: ["stars", "stripes"],
|
|
106
|
+
data: [["*****", "*****"]]
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
output = printer.to_s
|
|
110
|
+
table = <<-TABLE
|
|
111
|
+
+-------|---------+
|
|
112
|
+
| stars | stripes |
|
|
113
|
+
+-------|---------+
|
|
114
|
+
| ***** | ***** |
|
|
115
|
+
+-------|---------+
|
|
116
|
+
TABLE
|
|
117
|
+
|
|
118
|
+
expect(output).to eq(table.chomp)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "deals with data alignment" do
|
|
122
|
+
set_term_width(80)
|
|
123
|
+
printer = subject.new(headers: ["name", "value"],
|
|
124
|
+
data: [
|
|
125
|
+
["one", "*****"],
|
|
126
|
+
["seventeen", "///////////////"]
|
|
127
|
+
])
|
|
128
|
+
|
|
129
|
+
output = printer.to_s
|
|
130
|
+
table = <<-TABLE
|
|
131
|
+
+-----------|-----------------+
|
|
132
|
+
| name | value |
|
|
133
|
+
+-----------|-----------------+
|
|
134
|
+
| one | ***** |
|
|
135
|
+
| seventeen | /////////////// |
|
|
136
|
+
+-----------|-----------------+
|
|
137
|
+
TABLE
|
|
138
|
+
|
|
139
|
+
expect(output).to eq(table.chomp)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "wraps data as necessary" do
|
|
143
|
+
set_term_width(35)
|
|
144
|
+
printer = subject.new(headers: ["name", "value"],
|
|
145
|
+
data: [
|
|
146
|
+
["words", ["one", "two", "three", "four", "five"]],
|
|
147
|
+
])
|
|
148
|
+
|
|
149
|
+
output = printer.to_s
|
|
150
|
+
table = <<-TABLE
|
|
151
|
+
+------------|--------------------+
|
|
152
|
+
| name | value |
|
|
153
|
+
+------------|--------------------+
|
|
154
|
+
| words | one, two, three |
|
|
155
|
+
| | four, five |
|
|
156
|
+
+------------|--------------------+
|
|
157
|
+
TABLE
|
|
158
|
+
|
|
159
|
+
expect(output).to eq(table.chomp)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "can wrap multiple columns" do
|
|
163
|
+
set_term_width(45)
|
|
164
|
+
printer = subject.new(headers: ["name", "value", "other value"],
|
|
165
|
+
data: [
|
|
166
|
+
[ "words",
|
|
167
|
+
["one", "two", "three", "four", "five"],
|
|
168
|
+
["six", "seven", "eight", "nine", "ten"],
|
|
169
|
+
]
|
|
170
|
+
])
|
|
171
|
+
|
|
172
|
+
output = printer.to_s
|
|
173
|
+
table = <<-TABLE
|
|
174
|
+
+------------|-----------------|------------+
|
|
175
|
+
| name | value | other value |
|
|
176
|
+
+------------|-----------------|------------+
|
|
177
|
+
| words | one, two, three | six, seven |
|
|
178
|
+
| | four, five | eight, nine |
|
|
179
|
+
| | | ten |
|
|
180
|
+
+------------|-----------------|------------+
|
|
181
|
+
TABLE
|
|
182
|
+
|
|
183
|
+
expect(output).to eq(table.chomp)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "can print without a header" do
|
|
187
|
+
set_term_width(80)
|
|
188
|
+
printer = subject.new(headers: nil,
|
|
189
|
+
data: [
|
|
190
|
+
["*****", "********"],
|
|
191
|
+
["++++++++", "+++++"],
|
|
192
|
+
])
|
|
193
|
+
|
|
194
|
+
output = printer.to_s
|
|
195
|
+
table = <<-TABLE
|
|
196
|
+
+----------|----------+
|
|
197
|
+
| ***** | ******** |
|
|
198
|
+
| ++++++++ | +++++ |
|
|
199
|
+
+----------|----------+
|
|
200
|
+
TABLE
|
|
201
|
+
|
|
202
|
+
expect(output).to eq(table.chomp)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "can print without separators at all!" do
|
|
206
|
+
set_term_width(80)
|
|
207
|
+
printer = subject.new(headers: nil,
|
|
208
|
+
borders: false,
|
|
209
|
+
data: [
|
|
210
|
+
["*****", "********"],
|
|
211
|
+
["++++++++", "+++++"],
|
|
212
|
+
])
|
|
213
|
+
|
|
214
|
+
output = printer.to_s
|
|
215
|
+
table = <<-TABLE
|
|
216
|
+
|
|
217
|
+
***** ********
|
|
218
|
+
++++++++ +++++
|
|
219
|
+
|
|
220
|
+
TABLE
|
|
221
|
+
|
|
222
|
+
expect(output).to eq(table.chomp)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
@@ -106,11 +106,11 @@ describe Bundler::Stats::Remover do
|
|
|
106
106
|
it "raises an error if the top level dependency isn't in the lockfile" do
|
|
107
107
|
top_level << dep("tzinfo")
|
|
108
108
|
remover = subject.new(tree, top_level)
|
|
109
|
-
allow(remover).to receive(:
|
|
109
|
+
allow(remover).to receive(:warn_of_bad_tracing)
|
|
110
110
|
|
|
111
111
|
remover.still_used?("actionview", deleted: "rails")
|
|
112
112
|
|
|
113
|
-
expect(remover).to have_received(:
|
|
113
|
+
expect(remover).to have_received(:warn_of_bad_tracing)
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bundler-stats
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 2.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: 2021-11-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -66,6 +66,20 @@ dependencies:
|
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '2.13'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: guard-rspec
|
|
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'
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
84
|
name: pry
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,11 +94,26 @@ dependencies:
|
|
|
80
94
|
- - "~>"
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
96
|
version: '0.10'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rb-readline
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
83
111
|
description: Looks through your lockfile and tries to identify problematic use of
|
|
84
112
|
dependencies
|
|
85
113
|
email: jmmastey@gmail.com
|
|
86
114
|
executables:
|
|
87
115
|
- bundle-stats
|
|
116
|
+
- bundler-stats
|
|
88
117
|
extensions: []
|
|
89
118
|
extra_rdoc_files:
|
|
90
119
|
- CHANGELOG.md
|
|
@@ -92,6 +121,7 @@ extra_rdoc_files:
|
|
|
92
121
|
- README.md
|
|
93
122
|
files:
|
|
94
123
|
- ".gitignore"
|
|
124
|
+
- ".rspec"
|
|
95
125
|
- ".travis.yml"
|
|
96
126
|
- CHANGELOG.md
|
|
97
127
|
- CODE_OF_CONDUCT.md
|
|
@@ -100,14 +130,17 @@ files:
|
|
|
100
130
|
- MIT-LICENSE
|
|
101
131
|
- README.md
|
|
102
132
|
- bin/bundle-stats
|
|
133
|
+
- bin/bundler-stats
|
|
103
134
|
- bundler-stats.gemspec
|
|
104
135
|
- lib/bundler/stats.rb
|
|
105
136
|
- lib/bundler/stats/calculator.rb
|
|
106
137
|
- lib/bundler/stats/cli.rb
|
|
138
|
+
- lib/bundler/stats/printer.rb
|
|
107
139
|
- lib/bundler/stats/remover.rb
|
|
108
140
|
- lib/bundler/stats/tree.rb
|
|
109
141
|
- lib/bundler/stats/version.rb
|
|
110
142
|
- spec/lib/bundler/stats/calculator_spec.rb
|
|
143
|
+
- spec/lib/bundler/stats/printer_spec.rb
|
|
111
144
|
- spec/lib/bundler/stats/remover_spec.rb
|
|
112
145
|
- spec/lib/bundler/stats/tree_spec.rb
|
|
113
146
|
- spec/test_gemfile
|
|
@@ -134,8 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
167
|
- !ruby/object:Gem::Version
|
|
135
168
|
version: '0'
|
|
136
169
|
requirements: []
|
|
137
|
-
|
|
138
|
-
rubygems_version: 2.7.3
|
|
170
|
+
rubygems_version: 3.0.3
|
|
139
171
|
signing_key:
|
|
140
172
|
specification_version: 4
|
|
141
173
|
summary: Dependency investigation for Bundler
|