libyear-bundler 0.3.0 → 0.4.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: 734b3af6eedfa8bd832666a33e04ccf4d36dbcec
4
- data.tar.gz: 70d4f09011a3102403bec195b4638d7dbbbc73d8
3
+ metadata.gz: 2bc00352e31430c9a27e420073d5284a343a840a
4
+ data.tar.gz: 10d60b3b473df24f7a7a6140a22d4ed8bfe7f8a8
5
5
  SHA512:
6
- metadata.gz: cb0e53a70abcd38aba307d8ea2dac3ffbace0192cd26a8f2b2de960a42c36e6aa4fbae86d951dbfa9eab27796dddbd73d10e8fa7fbfb952dc3e3795bcc595e61
7
- data.tar.gz: 65b896dcdbbbc1feea606390b5a20b54680c95e8feb763989a651d1e646f11c2799d83c0e7c54c9c40ca1d464d67fcec3932eb15c2e058b08ad30384d28d8a31
6
+ metadata.gz: ec414ad1bb5b06517e6fa39fd7ebf1265a8ea42c36f1a9bf225d16bac46fcb61df3f97506725204bd3563b5425f02e28ff5e847bbfbdf8fcc0eaf1a06373be92
7
+ data.tar.gz: 0e3f53fc0fa0a497abd545e4e91eaa1d82e399d54401cf982393c6db3ff3b28c248a20f4e9d68e8b08d68d3f27e6b4daff1e88ac9bb7e5e82c240eb00d8d2ca9
@@ -0,0 +1,11 @@
1
+ Metrics/AbcSize:
2
+ Max: 27
3
+
4
+ Metrics/LineLength:
5
+ Max: 100
6
+
7
+ Metrics/MethodLength:
8
+ Enabled: false
9
+
10
+ Style/StringLiterals:
11
+ Enabled: false
@@ -17,6 +17,21 @@ Fixed:
17
17
 
18
18
  - None
19
19
 
20
+ ## 0.4.0 (2017-07-07)
21
+
22
+ Breaking changes:
23
+
24
+ - None
25
+
26
+ Added:
27
+
28
+ - [#3](https://github.com/jaredbeck/libyear-bundler/pull/3)
29
+ Add --versions and --releases
30
+
31
+ Fixed:
32
+
33
+ - None
34
+
20
35
  ## 0.3.0 (2017-03-24)
21
36
 
22
37
  Breaking changes:
data/asd ADDED
File without changes
@@ -0,0 +1,50 @@
1
+ module Calculators
2
+ # A libyear is the difference in time between releases of the newest and
3
+ # installed versions of the gem in years
4
+ class Libyear
5
+ class << self
6
+ def calculate(gem)
7
+ di = release_date(gem[:name], gem[:installed][:version])
8
+ dn = release_date(gem[:name], gem[:newest][:version])
9
+ gem[:installed][:date] = di
10
+ gem[:newest][:date] = dn
11
+ if di.nil? || dn.nil? || dn <= di
12
+ # Known issue: Backports and maintenance releases of older minor versions.
13
+ # Example: json 1.8.6 (2017-01-13) was released *after* 2.0.3 (2017-01-12)
14
+ years = 0.0
15
+ else
16
+ days = (dn - di).to_f
17
+ years = days / 365.0
18
+ end
19
+ years
20
+ end
21
+
22
+ private
23
+
24
+ # Known issue: Probably performs a network request every time, unless
25
+ # there's some kind of caching.
26
+ def release_date(gem_name, gem_version)
27
+ dep = nil
28
+ begin
29
+ dep = ::Bundler::Dependency.new(gem_name, gem_version)
30
+ rescue ::Gem::Requirement::BadRequirementError => e
31
+ $stderr.puts "Could not find release date for: #{gem_name}"
32
+ $stderr.puts(e)
33
+ $stderr.puts(
34
+ "Maybe you used git in your Gemfile, which libyear doesn't support " \
35
+ "yet. Contributions welcome."
36
+ )
37
+ return nil
38
+ end
39
+ tuples, _errors = ::Gem::SpecFetcher.fetcher.search_for_dependency(dep)
40
+ if tuples.empty?
41
+ $stderr.puts "Could not find release date for: #{gem_name}"
42
+ return nil
43
+ end
44
+ tup, source = tuples.first # Gem::NameTuple
45
+ spec = source.fetch_spec(tup) # raises Gem::RemoteFetcher::FetchError
46
+ spec.date.to_date
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ module Calculators
2
+ # The version number delta is the absolute difference between the highest-
3
+ # order version number of the installed and newest releases
4
+ class VersionNumberDelta
5
+ class << self
6
+ def calculate(gem)
7
+ newest_version_tuple = version_tuple(gem[:newest][:version].split('.'))
8
+ installed_version_tuple = version_tuple(gem[:installed][:version].split('.'))
9
+ major_version_delta = version_delta(
10
+ newest_version_tuple.major, installed_version_tuple.major
11
+ )
12
+ minor_version_delta = version_delta(
13
+ newest_version_tuple.minor, installed_version_tuple.minor
14
+ )
15
+ patch_version_delta = version_delta(
16
+ newest_version_tuple.patch, installed_version_tuple.patch
17
+ )
18
+ highest_order([major_version_delta, minor_version_delta, patch_version_delta])
19
+ end
20
+
21
+ private
22
+
23
+ def highest_order(arr)
24
+ arr[1] = arr[2] = 0 if arr[0] > 0
25
+ arr[2] = 0 if arr[1] > 0
26
+ arr
27
+ end
28
+
29
+ def version_delta(newest_version, installed_version)
30
+ delta = newest_version - installed_version
31
+ delta < 0 ? 0 : delta
32
+ end
33
+
34
+ def version_tuple(version_array)
35
+ version_struct = Struct.new(:major, :minor, :patch)
36
+ version_struct.new(
37
+ version_array[0].to_i,
38
+ version_array[1].to_i,
39
+ version_array[2].to_i
40
+ )
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,20 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+
5
+ module Calculators
6
+ # The version sequence delta is the number of releases between the newest and
7
+ # installed versions of the gem
8
+ class VersionSequenceDelta
9
+ class << self
10
+ def calculate(gem)
11
+ uri = URI.parse("https://rubygems.org/api/v1/versions/#{gem[:name]}.json")
12
+ response = Net::HTTP.get_response(uri)
13
+ versions = JSON.parse(response.body).map { |version| version["number"] }
14
+ newest_seq = versions.index(gem[:newest][:version])
15
+ installed_seq = versions.index(gem[:installed][:version])
16
+ installed_seq - newest_seq
17
+ end
18
+ end
19
+ end
20
+ end
@@ -4,10 +4,15 @@ require "libyear_bundler/report"
4
4
  require "libyear_bundler/query"
5
5
 
6
6
  module LibyearBundler
7
+ # The `libyear-bundler` command line program
7
8
  class CLI
8
- OPTIONS = %w(
9
+ OPTIONS = %w[
10
+ --all
9
11
  --grand-total
10
- ).freeze
12
+ --libyears
13
+ --releases
14
+ --versions
15
+ ].freeze
11
16
 
12
17
  E_BUNDLE_OUTDATED_FAILED = 1
13
18
  E_NO_GEMFILE = 2
@@ -22,7 +27,7 @@ module LibyearBundler
22
27
  if @argv.include?("--grand-total")
23
28
  grand_total
24
29
  else
25
- print Report.new(query).to_s
30
+ print report.to_s
26
31
  end
27
32
  end
28
33
 
@@ -51,7 +56,11 @@ module LibyearBundler
51
56
  end
52
57
 
53
58
  def query
54
- Query.new(@gemfile_path).execute
59
+ Query.new(@gemfile_path, @argv).execute
60
+ end
61
+
62
+ def report
63
+ @_report ||= Report.new(query)
55
64
  end
56
65
 
57
66
  def unexpected_options
@@ -64,16 +73,46 @@ module LibyearBundler
64
73
  end
65
74
 
66
75
  def validate_arguments
67
- unless unexpected_options.empty?
68
- puts "Unexpected args: #{unexpected_options.join(", ")}"
69
- puts "Allowed args: #{OPTIONS.join(", ")}"
70
- exit E_NO_GEMFILE
71
- end
76
+ return if unexpected_options.empty?
77
+ puts "Unexpected args: #{unexpected_options.join(', ')}"
78
+ puts "Allowed args: #{OPTIONS.join(', ')}"
79
+ exit E_NO_GEMFILE
72
80
  end
73
81
 
74
82
  def grand_total
75
- sum_years = query.map { |gem| gem[:libyears] }.inject(0.0, :+)
76
- puts format("%.1f", sum_years)
83
+ puts calculate_grand_total
84
+ end
85
+
86
+ def calculate_grand_total
87
+ if report.to_h.key?(:sum_seq_delta) && report.to_h.key?(:sum_major_version)
88
+ [
89
+ libyears_grand_total,
90
+ releases_grand_total,
91
+ versions_grand_total
92
+ ].join("\n")
93
+ elsif report.to_h.key?(:sum_seq_delta)
94
+ releases_grand_total
95
+ elsif report.to_h.key?(:sum_major_version)
96
+ versions_grand_total
97
+ else
98
+ libyears_grand_total
99
+ end
100
+ end
101
+
102
+ def libyears_grand_total
103
+ report.to_h[:sum_years].truncate(1)
104
+ end
105
+
106
+ def releases_grand_total
107
+ report.to_h[:sum_seq_delta]
108
+ end
109
+
110
+ def versions_grand_total
111
+ [
112
+ report.to_h[:sum_major_version],
113
+ report.to_h[:sum_minor_version],
114
+ report.to_h[:sum_patch_version]
115
+ ].to_s
77
116
  end
78
117
  end
79
118
  end
@@ -1,5 +1,8 @@
1
1
  require "English"
2
2
  require "open3"
3
+ require 'libyear_bundler/calculators/libyear'
4
+ require 'libyear_bundler/calculators/version_number_delta'
5
+ require 'libyear_bundler/calculators/version_sequence_delta'
3
6
 
4
7
  module LibyearBundler
5
8
  # Responsible for getting all the data that goes into the `Report`.
@@ -7,8 +10,9 @@ module LibyearBundler
7
10
  # Format of `bundle outdated --parseable` (BOP)
8
11
  BOP_FMT = /\A(?<name>[^ ]+) \(newest (?<newest>[^,]+), installed (?<installed>[^,)]+)/
9
12
 
10
- def initialize(gemfile_path)
13
+ def initialize(gemfile_path, argv)
11
14
  @gemfile_path = gemfile_path
15
+ @argv = argv
12
16
  end
13
17
 
14
18
  def execute
@@ -23,19 +27,15 @@ module LibyearBundler
23
27
  )
24
28
  end
25
29
  gems.each do |gem|
26
- di = release_date(gem[:name], gem[:installed][:version])
27
- dn = release_date(gem[:name], gem[:newest][:version])
28
- gem[:installed][:date] = di
29
- gem[:newest][:date] = dn
30
- if di.nil? || dn.nil? || dn <= di
31
- # Known issue: Backports and maintenance releases of older minor versions.
32
- # Example: json 1.8.6 (2017-01-13) was released *after* 2.0.3 (2017-01-12)
33
- years = 0.0
34
- else
35
- days = (dn - di).to_f
36
- years = days / 365.0
30
+ if @argv.include?("--versions") || @argv.include?("--all")
31
+ gem[:version_number_delta] = ::Calculators::VersionNumberDelta.calculate(gem)
37
32
  end
38
- gem[:libyears] = years
33
+
34
+ if @argv.include?("--releases") || @argv.include?("--all")
35
+ gem[:version_sequence_delta] = ::Calculators::VersionSequenceDelta.calculate(gem)
36
+ end
37
+
38
+ gem[:libyears] = ::Calculators::Libyear.calculate(gem)
39
39
  end
40
40
  gems
41
41
  end
@@ -44,7 +44,7 @@ module LibyearBundler
44
44
 
45
45
  def bundle_outdated
46
46
  stdout, stderr, status = Open3.capture3(
47
- %Q(BUNDLE_GEMFILE="#{@gemfile_path}" bundle outdated --parseable)
47
+ %(BUNDLE_GEMFILE="#{@gemfile_path}" bundle outdated --parseable)
48
48
  )
49
49
  # Known statuses:
50
50
  # 0 - Nothing is outdated
@@ -59,30 +59,5 @@ module LibyearBundler
59
59
  end
60
60
  stdout
61
61
  end
62
-
63
- # Known issue: Probably performs a network request every time, unless
64
- # there's some kind of caching.
65
- def release_date(gem_name, gem_version)
66
- dep = nil
67
- begin
68
- dep = ::Bundler::Dependency.new(gem_name, gem_version)
69
- rescue ::Gem::Requirement::BadRequirementError => e
70
- $stderr.puts "Could not find release date for: #{gem_name}"
71
- $stderr.puts(e)
72
- $stderr.puts(
73
- "Maybe you used git in your Gemfile, which libyear doesn't support " \
74
- "yet. Contributions welcome."
75
- )
76
- return nil
77
- end
78
- tuples, _errors = ::Gem::SpecFetcher.fetcher.search_for_dependency(dep)
79
- if tuples.empty?
80
- $stderr.puts "Could not find release date for: #{gem_name}"
81
- return nil
82
- end
83
- tup, source = tuples.first # Gem::NameTuple
84
- spec = source.fetch_spec(tup) # raises Gem::RemoteFetcher::FetchError
85
- spec.date.to_date
86
- end
87
62
  end
88
63
  end
@@ -2,29 +2,115 @@ module LibyearBundler
2
2
  # Responsible presenting data from the `Query`. Should only be concerned
3
3
  # with presentation, nothing else.
4
4
  class Report
5
+ FMT_RELEASES_COLUMN = "%10d".freeze
6
+ FMT_VERSIONS_COLUMN = "%15s".freeze
7
+
5
8
  # `gems` - Array of hashes.
6
9
  def initialize(gems)
7
10
  @gems = gems
8
11
  end
9
12
 
10
13
  def to_s
11
- sum_years = 0.0
12
- @gems.each do |gem|
13
- years = gem[:libyears]
14
- sum_years += years
15
- puts(
16
- format(
17
- "%30s%15s%15s%15s%15s%10.1f",
18
- gem[:name],
19
- gem[:installed][:version],
20
- gem[:installed][:date],
21
- gem[:newest][:version],
22
- gem[:newest][:date],
23
- years
24
- )
25
- )
14
+ to_h[:gems].each { |gem| put_gem_summary(gem) }
15
+ put_summary(to_h)
16
+ end
17
+
18
+ def to_h
19
+ @_to_h ||=
20
+ begin
21
+ summary = {
22
+ gems: @gems,
23
+ sum_years: 0.0
24
+ }
25
+ @gems.each_with_object(summary) do |gem, memo|
26
+ memo[:sum_years] += gem[:libyears]
27
+
28
+ if gem.key?(:version_number_delta)
29
+ memo[:sum_major_version] ||= 0
30
+ memo[:sum_major_version] += gem[:version_number_delta][0]
31
+ memo[:sum_minor_version] ||= 0
32
+ memo[:sum_minor_version] += gem[:version_number_delta][1]
33
+ memo[:sum_patch_version] ||= 0
34
+ memo[:sum_patch_version] += gem[:version_number_delta][2]
35
+ end
36
+
37
+ if gem.key?(:version_sequence_delta)
38
+ memo[:sum_seq_delta] ||= 0
39
+ memo[:sum_seq_delta] += gem[:version_sequence_delta]
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def put_gem_summary(gem)
48
+ meta = meta_gem_summary(gem)
49
+ libyear = format("%10.1f", gem[:libyears])
50
+
51
+ if gem.key?(:version_sequence_delta) && gem.key?(:version_number_delta)
52
+ releases = format(FMT_RELEASES_COLUMN, gem[:version_sequence_delta])
53
+ versions = format(FMT_VERSIONS_COLUMN, gem[:version_number_delta])
54
+ puts meta << libyear << releases << versions
55
+ elsif gem.key?(:version_sequence_delta)
56
+ releases = format(FMT_RELEASES_COLUMN, gem[:version_sequence_delta])
57
+ puts meta << releases
58
+ elsif gem.key?(:version_number_delta)
59
+ versions = format(FMT_VERSIONS_COLUMN, gem[:version_number_delta])
60
+ puts meta << versions
61
+ else
62
+ puts meta << libyear
26
63
  end
64
+ end
65
+
66
+ def meta_gem_summary(gem)
67
+ format(
68
+ "%30s%15s%15s%15s%15s",
69
+ gem[:name],
70
+ gem[:installed][:version],
71
+ gem[:installed][:date],
72
+ gem[:newest][:version],
73
+ gem[:newest][:date]
74
+ )
75
+ end
76
+
77
+ def put_libyear_summary(sum_years)
27
78
  puts format("System is %.1f libyears behind", sum_years)
28
79
  end
80
+
81
+ def put_version_delta_summary(sum_major_version, sum_minor_version, sum_patch_version)
82
+ puts format(
83
+ "Major, minor, patch versions behind: %d, %d, %d",
84
+ sum_major_version,
85
+ sum_minor_version,
86
+ sum_patch_version
87
+ )
88
+ end
89
+
90
+ def put_sum_seq_delta_summary(sum_seq_delta)
91
+ puts format("Total releases behind: %d", sum_seq_delta)
92
+ end
93
+
94
+ def put_summary(summary)
95
+ if summary.key?(:sum_seq_delta) && summary.key?(:sum_major_version)
96
+ put_libyear_summary(summary[:sum_years])
97
+ put_sum_seq_delta_summary(summary[:sum_seq_delta])
98
+ put_version_delta_summary(
99
+ summary[:sum_major_version],
100
+ summary[:sum_minor_version],
101
+ summary[:sum_patch_version]
102
+ )
103
+ elsif summary.key?(:sum_major_version)
104
+ put_version_delta_summary(
105
+ summary[:sum_major_version],
106
+ summary[:sum_minor_version],
107
+ summary[:sum_patch_version]
108
+ )
109
+ elsif summary.key?(:sum_seq_delta)
110
+ put_sum_seq_delta_summary(summary[:sum_seq_delta])
111
+ else
112
+ put_libyear_summary(summary[:sum_years])
113
+ end
114
+ end
29
115
  end
30
116
  end
@@ -1,3 +1,3 @@
1
1
  module LibyearBundler
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0".freeze
3
3
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'libyear_bundler/version'
@@ -19,4 +20,5 @@ Gem::Specification.new do |spec|
19
20
  spec.require_paths = ["lib"]
20
21
  spec.required_ruby_version = ">= 2.1"
21
22
  spec.add_dependency "bundler", "~> 1.14"
23
+ spec.add_development_dependency "rubocop"
22
24
  end
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.3.0
4
+ version: 0.4.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: 2017-03-24 00:00:00.000000000 Z
11
+ date: 2017-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description:
28
42
  email:
29
43
  - jared@jaredbeck.com
@@ -33,12 +47,17 @@ extensions: []
33
47
  extra_rdoc_files: []
34
48
  files:
35
49
  - ".gitignore"
50
+ - ".rubocop.yml"
36
51
  - CHANGELOG.md
37
52
  - Gemfile
38
53
  - LICENSE.txt
39
54
  - README.md
55
+ - asd
40
56
  - bin/libyear-bundler
41
57
  - lib/libyear_bundler.rb
58
+ - lib/libyear_bundler/calculators/libyear.rb
59
+ - lib/libyear_bundler/calculators/version_number_delta.rb
60
+ - lib/libyear_bundler/calculators/version_sequence_delta.rb
42
61
  - lib/libyear_bundler/cli.rb
43
62
  - lib/libyear_bundler/query.rb
44
63
  - lib/libyear_bundler/report.rb
@@ -64,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
83
  version: '0'
65
84
  requirements: []
66
85
  rubyforge_project:
67
- rubygems_version: 2.6.11
86
+ rubygems_version: 2.6.12
68
87
  signing_key:
69
88
  specification_version: 4
70
89
  summary: A simple measure of dependency freshness