libyear-bundler 0.7.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4f90004a4a8f93453f73361a0e3415344017e83f55d10d625b0a3b69f1db74b
4
- data.tar.gz: 55d91c831ae79f5b44c6de0bcd2f68e550590d73d5004646c1da0163abbcebea
3
+ metadata.gz: 0423ad3e6d453baa3bc6bc93e49a3aa72fa7918a81d6b2403fb6546a8d078193
4
+ data.tar.gz: 56e00c648efe514f290533f33921d1da2b3c460702721a6b402b03c09a953813
5
5
  SHA512:
6
- metadata.gz: e3b1346dbdc4986e539fba595f18e01a46fd03d647210b34a6810e2bd9ae61028ffa00eae7e4e2c4088f524368a2cc74950f5d79610ab6aa2bd93d5c4cdd9e6a
7
- data.tar.gz: 2196cc0fe1a16f2fd9ea4646eb7d07a227d58f07dc5f2cca3724c8ae4b08d4386adbdbc51f3364f2891745e7202b106348dabefed1734a6eb3b11c38823e4f17
6
+ metadata.gz: 694fbd117515873bacb006cac6f10442170c7439b82ea861dcd02e56128589d8c88e38c3cef1b09e9eff93e4c938c50e900a8845f1e09a8e87376e5dac2a4e9f
7
+ data.tar.gz: ef72774c6db0dbb48ae72ec3c0ff52bc56912aa7915637843db8bc7b7608db188232f3dab1da308f714312e552da1e4c955f54fba6061e45d64b7e60b42f5798
@@ -3,7 +3,8 @@ require "bundler/cli/outdated"
3
3
  require "libyear_bundler/bundle_outdated"
4
4
  require "libyear_bundler/options"
5
5
  require "libyear_bundler/release_date_cache"
6
- require "libyear_bundler/report"
6
+ require "libyear_bundler/reports/console"
7
+ require "libyear_bundler/reports/json"
7
8
  require 'libyear_bundler/models/ruby'
8
9
 
9
10
  module LibyearBundler
@@ -73,7 +74,10 @@ module LibyearBundler
73
74
  end
74
75
 
75
76
  def report
76
- @_report ||= Report.new(bundle_outdated, ruby, @options, $stdout)
77
+ @_report ||= begin
78
+ reporter_class = @options.json? ? Reports::JSON : Reports::Console
79
+ reporter_class.new(bundle_outdated, ruby, @options, $stdout)
80
+ end
77
81
  end
78
82
 
79
83
  def ruby
@@ -23,23 +23,32 @@ module LibyearBundler
23
23
  begin
24
24
  dep = ::Bundler::Dependency.new(gem_name, gem_version)
25
25
  rescue ::Gem::Requirement::BadRequirementError => e
26
- $stderr.puts "Could not find release date for: #{gem_name}"
27
- $stderr.puts(e)
28
- $stderr.puts(
29
- "Maybe you used git in your Gemfile, which libyear doesn't support " \
30
- "yet. Contributions welcome."
31
- )
26
+ report_problem(gem_name, <<-MSG)
27
+ Could not find release date for: #{gem_name}
28
+ #{e}
29
+ Maybe you used git in your Gemfile, which libyear doesn't support yet. Contributions welcome.
30
+ MSG
32
31
  return nil
33
32
  end
34
33
  tuples, _errors = ::Gem::SpecFetcher.fetcher.search_for_dependency(dep)
35
34
  if tuples.empty?
36
- $stderr.puts "Could not find release date for: #{gem_name}"
35
+ report_problem(gem_name, "Could not find release date for: #{gem_name}")
37
36
  return nil
38
37
  end
39
38
  tup, source = tuples.first # Gem::NameTuple
40
39
  spec = source.fetch_spec(tup) # raises Gem::RemoteFetcher::FetchError
41
40
  spec.date.to_date
42
41
  end
42
+
43
+ private
44
+
45
+ def report_problem(gem_name, message)
46
+ @reported_gems ||= {}
47
+ @reported_gems[gem_name] ||= begin
48
+ $stderr.puts(message)
49
+ true
50
+ end
51
+ end
43
52
  end
44
53
 
45
54
  def installed_version
@@ -62,7 +62,7 @@ module LibyearBundler
62
62
 
63
63
  # YAML#safe_load provides an already-parsed Date object, so the following
64
64
  # is a Date object
65
- v['date']
65
+ @_version_data[v]['date']
66
66
  end
67
67
 
68
68
  private
@@ -84,7 +84,9 @@ module LibyearBundler
84
84
  con.request_get(uri.path)
85
85
  end
86
86
  if response.is_a?(::Net::HTTPSuccess)
87
- YAMLLoader.safe_load(response.body).map { |release| release['version'] }
87
+ @_version_data = YAMLLoader.safe_load(response.body)
88
+ .map { |release| [release['version'], release] }.to_h
89
+ @_version_data.keys
88
90
  else
89
91
  warn format('Unable to get Ruby version list: response code: %s', response.code)
90
92
  []
@@ -52,6 +52,14 @@ https://github.com/jaredbeck/libyear-bundler/
52
52
  opts.on('--grand-total', 'Return value for given metric(s)') do
53
53
  @options.send('grand_total?=', true)
54
54
  end
55
+
56
+ opts.on('--sort', 'Sort by selected metric(s), in descending order') do
57
+ @options.send('sort?=', true)
58
+ end
59
+
60
+ opts.on('--json', 'Output JSON') do
61
+ @options.send('json?=', true)
62
+ end
55
63
  end
56
64
  end
57
65
 
@@ -0,0 +1,87 @@
1
+ module LibyearBundler
2
+ module Reports
3
+ # Base class for all reporters. Should only be concerned with presentation, nothing else.
4
+ #
5
+ # Subclasses should implement the `#write` method.
6
+ class Base
7
+ # `gems` - Array of `::LibyearBundler::Models::Gem` instances
8
+ # `options` - Instance of `::LibyearBundler::Options`
9
+ def initialize(gems, ruby, options, io)
10
+ @gems = gems
11
+ @ruby = ruby
12
+ @options = options
13
+ @io = io
14
+ end
15
+
16
+ def write
17
+ raise NoMethodError, "Implement in subclass"
18
+ end
19
+
20
+ def to_h
21
+ @_to_h ||=
22
+ begin
23
+ gems = sorted_gems(@gems)
24
+ summary = {
25
+ gems: gems,
26
+ sum_libyears: 0.0
27
+ }
28
+ gems.each { |gem| increment_metrics_summary(gem, summary) }
29
+
30
+ begin
31
+ increment_metrics_summary(@ruby, summary) if @ruby.outdated?
32
+ rescue StandardError => e
33
+ warn "Unable to calculate libyears for ruby itself: #{e}"
34
+ end
35
+
36
+ summary
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def sorted_gems(gems)
43
+ if @options.sort?
44
+ gems.sort_by do |gem|
45
+ [
46
+ (gem.libyears if @options.libyears?),
47
+ (gem.version_sequence_delta if @options.releases?),
48
+ (gem.version_number_delta if @options.versions?)
49
+ ].compact
50
+ end.reverse
51
+ else
52
+ gems
53
+ end
54
+ end
55
+
56
+ def increment_metrics_summary(model, summary)
57
+ increment_libyears(model, summary) if @options.libyears?
58
+ increment_version_deltas(model, summary) if @options.versions?
59
+ increment_seq_deltas(model, summary) if @options.releases?
60
+ end
61
+
62
+ def increment_libyears(model, memo)
63
+ memo[:sum_libyears] += model.libyears
64
+ rescue StandardError => e
65
+ warn "Unable to calculate libyears for #{model.name}: #{e}"
66
+ end
67
+
68
+ def increment_seq_deltas(model, memo)
69
+ memo[:sum_seq_delta] ||= 0
70
+ memo[:sum_seq_delta] += model.version_sequence_delta
71
+ rescue StandardError => e
72
+ warn "Unable to calculate seq deltas for #{model.name}: #{e}"
73
+ end
74
+
75
+ def increment_version_deltas(model, memo)
76
+ memo[:sum_major_version] ||= 0
77
+ memo[:sum_major_version] += model.version_number_delta[0]
78
+ memo[:sum_minor_version] ||= 0
79
+ memo[:sum_minor_version] += model.version_number_delta[1]
80
+ memo[:sum_patch_version] ||= 0
81
+ memo[:sum_patch_version] += model.version_number_delta[2]
82
+ rescue StandardError => e
83
+ warn "Unable to calculate version deltas for #{model.name}: #{e}"
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,102 @@
1
+ require "libyear_bundler/reports/base"
2
+
3
+ module LibyearBundler
4
+ module Reports
5
+ # Responsible presenting data from the `::LibyearBundler::Models`. Should only
6
+ # be concerned with presentation, nothing else.
7
+ class Console < Base
8
+ FMT_LIBYEARS_COLUMN = "%10.1f".freeze
9
+ FMT_RELEASES_COLUMN = "%10d".freeze
10
+ FMT_VERSIONS_COLUMN = "%15s".freeze
11
+ FMT_SUMMARY_COLUMNS = "%30s%15s%15s%15s%15s".freeze
12
+
13
+ def write
14
+ to_h[:gems].each { |gem| put_line_summary(gem) }
15
+
16
+ begin
17
+ put_line_summary(@ruby) if @ruby.outdated?
18
+ rescue StandardError => e
19
+ warn "Unable to calculate libyears for ruby itself: #{e} (line summary)"
20
+ end
21
+
22
+ put_summary(to_h)
23
+ end
24
+
25
+ private
26
+
27
+ def put_line_summary(gem_or_ruby)
28
+ meta = meta_line_summary(gem_or_ruby)
29
+
30
+ if @options.releases?
31
+ releases = format(FMT_RELEASES_COLUMN, gem_or_ruby.version_sequence_delta)
32
+ meta << releases
33
+ end
34
+
35
+ if @options.versions?
36
+ versions = format(FMT_VERSIONS_COLUMN, gem_or_ruby.version_number_delta)
37
+ meta << versions
38
+ end
39
+
40
+ if @options.libyears?
41
+ libyears = format(FMT_LIBYEARS_COLUMN, gem_or_ruby.libyears)
42
+ meta << libyears
43
+ end
44
+
45
+ @io.puts meta
46
+ end
47
+
48
+ def meta_line_summary(gem_or_ruby)
49
+ format(
50
+ FMT_SUMMARY_COLUMNS,
51
+ gem_or_ruby.name,
52
+ gem_or_ruby.installed_version.to_s,
53
+ gem_or_ruby.installed_version_release_date,
54
+ gem_or_ruby.newest_version.to_s,
55
+ gem_or_ruby.newest_version_release_date
56
+ )
57
+ end
58
+
59
+ def put_libyear_summary(sum_libyears)
60
+ @io.puts format("System is %.1f libyears behind", sum_libyears)
61
+ end
62
+
63
+ def put_version_delta_summary(sum_major_version, sum_minor_version, sum_patch_version)
64
+ @io.puts format(
65
+ "Major, minor, patch versions behind: %<major>d, %<minor>d, %<patch>d",
66
+ major: sum_major_version || 0,
67
+ minor: sum_minor_version || 0,
68
+ patch: sum_patch_version || 0
69
+ )
70
+ end
71
+
72
+ def put_sum_seq_delta_summary(sum_seq_delta)
73
+ @io.puts format(
74
+ "Total releases behind: %<seq_delta>d",
75
+ seq_delta: sum_seq_delta || 0
76
+ )
77
+ end
78
+
79
+ def put_summary(summary)
80
+ if [:libyears?, :releases?, :versions?].all? { |opt| @options.send(opt) }
81
+ put_libyear_summary(summary[:sum_libyears])
82
+ put_sum_seq_delta_summary(summary[:sum_seq_delta])
83
+ put_version_delta_summary(
84
+ summary[:sum_major_version],
85
+ summary[:sum_minor_version],
86
+ summary[:sum_patch_version]
87
+ )
88
+ elsif @options.versions?
89
+ put_version_delta_summary(
90
+ summary[:sum_major_version],
91
+ summary[:sum_minor_version],
92
+ summary[:sum_patch_version]
93
+ )
94
+ elsif @options.releases?
95
+ put_sum_seq_delta_summary(summary[:sum_seq_delta])
96
+ elsif @options.libyears?
97
+ put_libyear_summary(summary[:sum_libyears])
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,52 @@
1
+ require 'json'
2
+ require 'libyear_bundler/reports/base'
3
+
4
+ module LibyearBundler
5
+ module Reports
6
+ # Responsible for generating data from the `::LibyearBundler::Models` in JSON format.
7
+ # Should only be concerned with presentation, nothing else.
8
+ class JSON < Base
9
+ def write
10
+ data = {
11
+ gems: to_h[:gems].map { |gem| gem_info(gem) },
12
+ ruby: gem_info(@ruby)
13
+ }
14
+ data[:sum_libyears] = to_h[:sum_libyears].round(1) if @options.libyears?
15
+ data[:sum_seq_delta] = to_h[:sum_seq_delta].round(1) if @options.releases?
16
+ if @options.versions?
17
+ data[:sum_major_version] = to_h[:sum_major_version].round(1)
18
+ data[:sum_minor_version] = to_h[:sum_minor_version].round(1)
19
+ data[:sum_patch_version] = to_h[:sum_patch_version].round(1)
20
+ end
21
+
22
+ @io.puts ::JSON.pretty_generate(data)
23
+ end
24
+
25
+ private
26
+
27
+ def gem_info(gem_or_ruby)
28
+ info = {
29
+ name: gem_or_ruby.name,
30
+ installed_version: gem_or_ruby.installed_version.to_s,
31
+ installed_version_release_date: gem_or_ruby.installed_version_release_date,
32
+ newest_version: gem_or_ruby.newest_version.to_s,
33
+ newest_version_release_date: gem_or_ruby.newest_version_release_date
34
+ }
35
+
36
+ if @options.releases?
37
+ info[:releases] = gem_or_ruby.version_sequence_delta
38
+ end
39
+
40
+ if @options.versions?
41
+ info[:versions] = [:major, :minor, :patch].zip(gem_or_ruby.version_number_delta).to_h
42
+ end
43
+
44
+ if @options.libyears?
45
+ info[:libyears] = gem_or_ruby.libyears.round(1)
46
+ end
47
+
48
+ info
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module LibyearBundler
2
- VERSION = "0.7.0".freeze
2
+ VERSION = "0.9.0".freeze
3
3
  end
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ["jared@jaredbeck.com"]
12
12
  spec.summary = "A simple measure of dependency freshness"
13
13
  spec.homepage = "https://libyear.com"
14
- spec.licenses = ["GPL-3.0"]
14
+ spec.licenses = ["GPL-3.0-only"]
15
15
  spec.files = `git ls-files -z`.split("\x0").select do |f|
16
16
  f.start_with?('lib/') ||
17
17
  [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libyear-bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared Beck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-11 00:00:00.000000000 Z
11
+ date: 2025-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -50,13 +50,15 @@ files:
50
50
  - lib/libyear_bundler/models/ruby.rb
51
51
  - lib/libyear_bundler/options.rb
52
52
  - lib/libyear_bundler/release_date_cache.rb
53
- - lib/libyear_bundler/report.rb
53
+ - lib/libyear_bundler/reports/base.rb
54
+ - lib/libyear_bundler/reports/console.rb
55
+ - lib/libyear_bundler/reports/json.rb
54
56
  - lib/libyear_bundler/version.rb
55
57
  - lib/libyear_bundler/yaml_loader.rb
56
58
  - libyear-bundler.gemspec
57
59
  homepage: https://libyear.com
58
60
  licenses:
59
- - GPL-3.0
61
+ - GPL-3.0-only
60
62
  metadata: {}
61
63
  post_install_message:
62
64
  rdoc_options: []
@@ -1,156 +0,0 @@
1
- module LibyearBundler
2
- # Responsible presenting data from the `::LibyearBundler::Models`. Should only
3
- # be concerned with presentation, nothing else.
4
- class Report
5
- FMT_LIBYEARS_COLUMN = "%10.1f".freeze
6
- FMT_RELEASES_COLUMN = "%10d".freeze
7
- FMT_VERSIONS_COLUMN = "%15s".freeze
8
- FMT_SUMMARY_COLUMNS = "%30s%15s%15s%15s%15s".freeze
9
-
10
- # `gems` - Array of `::LibyearBundler::Models::Gem` instances
11
- # `options` - Instance of `::LibyearBundler::Options`
12
- def initialize(gems, ruby, options, io)
13
- @gems = gems
14
- @ruby = ruby
15
- @options = options
16
- @io = io
17
- end
18
-
19
- def write
20
- to_h[:gems].each { |gem| put_line_summary(gem) }
21
-
22
- begin
23
- put_line_summary(@ruby) if @ruby.outdated?
24
- rescue StandardError => e
25
- warn "Unable to calculate libyears for ruby itself: #{e} (line summary)"
26
- end
27
-
28
- put_summary(to_h)
29
- end
30
-
31
- def to_h
32
- @_to_h ||=
33
- begin
34
- summary = {
35
- gems: @gems,
36
- sum_libyears: 0.0
37
- }
38
- @gems.each { |gem| increment_metrics_summary(gem, summary) }
39
-
40
- begin
41
- increment_metrics_summary(@ruby, summary) if @ruby.outdated?
42
- rescue StandardError => e
43
- warn "Unable to calculate libyears for ruby itself: #{e}"
44
- end
45
-
46
- summary
47
- end
48
- end
49
-
50
- private
51
-
52
- def increment_metrics_summary(model, summary)
53
- increment_libyears(model, summary) if @options.libyears?
54
- increment_version_deltas(model, summary) if @options.versions?
55
- increment_seq_deltas(model, summary) if @options.releases?
56
- end
57
-
58
- def put_line_summary(gem_or_ruby)
59
- meta = meta_line_summary(gem_or_ruby)
60
-
61
- if @options.releases?
62
- releases = format(FMT_RELEASES_COLUMN, gem_or_ruby.version_sequence_delta)
63
- meta << releases
64
- end
65
-
66
- if @options.versions?
67
- versions = format(FMT_VERSIONS_COLUMN, gem_or_ruby.version_number_delta)
68
- meta << versions
69
- end
70
-
71
- if @options.libyears?
72
- libyears = format(FMT_LIBYEARS_COLUMN, gem_or_ruby.libyears)
73
- meta << libyears
74
- end
75
-
76
- @io.puts meta
77
- end
78
-
79
- def meta_line_summary(gem_or_ruby)
80
- format(
81
- FMT_SUMMARY_COLUMNS,
82
- gem_or_ruby.name,
83
- gem_or_ruby.installed_version.to_s,
84
- gem_or_ruby.installed_version_release_date,
85
- gem_or_ruby.newest_version.to_s,
86
- gem_or_ruby.newest_version_release_date
87
- )
88
- end
89
-
90
- def put_libyear_summary(sum_libyears)
91
- @io.puts format("System is %.1f libyears behind", sum_libyears)
92
- end
93
-
94
- def put_version_delta_summary(sum_major_version, sum_minor_version, sum_patch_version)
95
- @io.puts format(
96
- "Major, minor, patch versions behind: %<major>d, %<minor>d, %<patch>d",
97
- major: sum_major_version || 0,
98
- minor: sum_minor_version || 0,
99
- patch: sum_patch_version || 0
100
- )
101
- end
102
-
103
- def put_sum_seq_delta_summary(sum_seq_delta)
104
- @io.puts format(
105
- "Total releases behind: %<seq_delta>d",
106
- seq_delta: sum_seq_delta || 0
107
- )
108
- end
109
-
110
- def put_summary(summary)
111
- if [:libyears?, :releases?, :versions?].all? { |opt| @options.send(opt) }
112
- put_libyear_summary(summary[:sum_libyears])
113
- put_sum_seq_delta_summary(summary[:sum_seq_delta])
114
- put_version_delta_summary(
115
- summary[:sum_major_version],
116
- summary[:sum_minor_version],
117
- summary[:sum_patch_version]
118
- )
119
- elsif @options.versions?
120
- put_version_delta_summary(
121
- summary[:sum_major_version],
122
- summary[:sum_minor_version],
123
- summary[:sum_patch_version]
124
- )
125
- elsif @options.releases?
126
- put_sum_seq_delta_summary(summary[:sum_seq_delta])
127
- elsif @options.libyears?
128
- put_libyear_summary(summary[:sum_libyears])
129
- end
130
- end
131
-
132
- def increment_libyears(model, memo)
133
- memo[:sum_libyears] += model.libyears
134
- rescue StandardError => e
135
- warn "Unable to calculate libyears for #{model.name}: #{e}"
136
- end
137
-
138
- def increment_seq_deltas(model, memo)
139
- memo[:sum_seq_delta] ||= 0
140
- memo[:sum_seq_delta] += model.version_sequence_delta
141
- rescue StandardError => e
142
- warn "Unable to calculate seq deltas for #{model.name}: #{e}"
143
- end
144
-
145
- def increment_version_deltas(model, memo)
146
- memo[:sum_major_version] ||= 0
147
- memo[:sum_major_version] += model.version_number_delta[0]
148
- memo[:sum_minor_version] ||= 0
149
- memo[:sum_minor_version] += model.version_number_delta[1]
150
- memo[:sum_patch_version] ||= 0
151
- memo[:sum_patch_version] += model.version_number_delta[2]
152
- rescue StandardError => e
153
- warn "Unable to calculate version deltas for #{model.name}: #{e}"
154
- end
155
- end
156
- end