outdated 0.1.0 → 0.2.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: 5c2b48dd866fe64d213403ec5803a72057d7f4079a69cdba6700505e0ea5d1fa
4
- data.tar.gz: e2f9f9a8a6df9c58852641d09f8d78c0fef887f7ff79717bafad6535bcea38c2
3
+ metadata.gz: 2b201356ed3043dda5fc24fd4811b6aed2b24107f520bac4c47a3c253712ddae
4
+ data.tar.gz: 49300438741f16d9c260be8877bb158ec8e9e567db526f7da722a33eb360aee9
5
5
  SHA512:
6
- metadata.gz: c1a0aff5d524fd0512e31cfa72ddc7e5282d403b0f5f57572820b448666a750eec6f19e9bd0b9e36c92cdeb7a36c1c49dea5d6a15c153213435125b4101ee3ad
7
- data.tar.gz: 2208411c03af98e1c10a54bca51c0395f0f521cae76b3e740c175094136e46928760c1ca3870e3e89b56d5ad1ad0696cefbd99ce5a60ad0e587e24bcebb4cfa6
6
+ metadata.gz: e5a3f7ab8f0e9c8dbbd479cac1b036b85dcf5f690117a7aaa2fd49277673ab6e2adb853f1c4956c19f5ce1c35a58830e820c868f7060556caad706af6627f475
7
+ data.tar.gz: 2e0c9772eb5252844f87c7b4ed5718aeffdc702aee76260805761ef34d34936a65f919788218bfb43da9c29ea4722590fe84f85b3cd8bf3ad98e7eab75c0fe49
@@ -5,9 +5,13 @@ require 'pry'
5
5
 
6
6
  require_relative 'outdated/cli'
7
7
  require_relative 'outdated/ruby_gems'
8
- require_relative 'outdated/ruby_gems/spec_set'
8
+ require_relative 'outdated/ruby_gems/gem'
9
+ require_relative 'outdated/ruby_gems/spec'
9
10
  require_relative 'outdated/version'
10
11
 
11
12
  module Outdated
12
13
  class Error < StandardError; end
14
+
15
+ IMMATURE = 'Immature'
16
+ OUTDATED = 'Outdated'
13
17
  end
@@ -3,7 +3,10 @@
3
3
  module Outdated
4
4
  module CLI
5
5
  def self.run
6
- one_week_ago = Time.now - 7 * 24 * 60 * 60 # 1 week ago
6
+ filename = '.outdated.json'
7
+ options = File.exist?(filename) ? JSON.parse(File.read(filename)) : {}
8
+ exclusions = options["exclusions"] || []
9
+
7
10
  Bundler.ui = Bundler::UI::Shell.new
8
11
  current_specs = Bundler.definition.resolve
9
12
  definition = Bundler.definition(true)
@@ -19,34 +22,41 @@ module Outdated
19
22
 
20
23
  gemfile_specs.sort_by(&:name).each do |used|
21
24
  name = used.name
22
- # puts "\n" + name
23
- # next unless name == 's3_backup'
25
+ gem_exclusions = exclusions.find { |exc| exc['gem'] == name } || {}
26
+ excluded_rules = gem_exclusions['rules'] || []
27
+
28
+ gem = Outdated::RubyGems.gem(name)
29
+ next if gem.specs.empty?
24
30
 
25
- spec_set = Outdated::RubyGems.spec_set(name)
26
- next if spec_set.empty?
31
+ used = gem.get(used.version)
32
+ next unless used
27
33
 
28
- used = spec_set.get(used.version)
29
- recommended = spec_set.recommend(used, one_week_ago)
34
+ recommended_spec, code = gem.recommend(used, 1.week.ago)
30
35
 
31
- outdated = recommended.version > used.version
32
- too_new = recommended.version < used.version
36
+ if code == Outdated::OUTDATED
37
+ next if excluded_rules.include? Outdated::OUTDATED
33
38
 
34
- if outdated
35
39
  puts "\n#{name} #{used.version} is outdated. " \
36
- "#{recommended.version} published #{recommended.created_at}."
40
+ "#{recommended_spec.version} published #{recommended_spec.created_at}."
37
41
  exit_status = 1
38
- elsif too_new
42
+ next
43
+ end
44
+
45
+ if code == Outdated::IMMATURE
46
+ next if excluded_rules.include? Outdated::IMMATURE
47
+
39
48
  puts "\n#{name} #{used.version} is too new and may contain bugs or " \
40
49
  'vulnerabilities that are as yet unknown. It was published ' \
41
- "#{used.created_at}. For now use #{recommended.version} " \
42
- 'instead.'
50
+ "#{used.created_at}."
51
+ puts " For now use #{recommended_spec.version} instead." if recommended_spec.present?
43
52
  exit_status = 1
44
- else
45
- putc '.'
53
+ next
46
54
  end
55
+
56
+ putc '.'
47
57
  end
48
58
 
49
- puts "\nGem versions deemed to be sufficiently up-to-date." if exit_status == 0
59
+ puts "\nGem versions deemed to be sufficiently up-to-date." if exit_status.zero?
50
60
  exit_status
51
61
  end
52
62
  end
@@ -2,9 +2,9 @@ require 'http'
2
2
 
3
3
  module Outdated
4
4
  module RubyGems
5
- def self.spec_set(name)
5
+ def self.gem(name)
6
6
  response = HTTP.get("https://rubygems.org/api/v1/versions/#{name}.json")
7
- Outdated::RubyGems::SpecSet.from_response(response)
7
+ Outdated::RubyGems::Gem.from_response(name, response)
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,65 @@
1
+ module Outdated
2
+ module RubyGems
3
+ class Gem
4
+ def self.from_response(name, response)
5
+ return new if response.code == 404
6
+
7
+ body = response.body
8
+ specs = JSON.parse(body).map { |spec| Outdated::RubyGems::Spec.from_response_object(name, spec) }
9
+ new(specs)
10
+ end
11
+
12
+ attr_reader :specs
13
+
14
+ def initialize(specs = [])
15
+ @specs = specs
16
+
17
+ raise ArgumentError, "conflicting spec names" unless specs.uniq(&:name).count < 2
18
+ end
19
+
20
+ def name
21
+ specs.first.name
22
+ end
23
+
24
+ def empty?
25
+ specs.empty?
26
+ end
27
+
28
+ def size
29
+ specs.size
30
+ end
31
+
32
+ def first
33
+ specs.first
34
+ end
35
+
36
+ def get(version)
37
+ specs.find { |spec| spec.version == version }
38
+ end
39
+
40
+ def recommend(currently_used_spec, cut_off)
41
+ recommended_spec = specs.find do |spec|
42
+ semver = spec.version.to_s.split(/\./).map(&:to_i)
43
+ currently_used_semver = currently_used_spec.version.to_s.split(/\./).map(&:to_i)
44
+ prerelease = spec.prerelease
45
+ too_new = cut_off < spec.created_at
46
+ minor_or_major_upgrade =
47
+ semver[0] > currently_used_semver[0] || semver[1] > currently_used_semver[1]
48
+
49
+ !prerelease && !too_new && !minor_or_major_upgrade
50
+ end
51
+
52
+ code =
53
+ if recommended_spec.nil?
54
+ Outdated::IMMATURE
55
+ elsif recommended_spec > currently_used_spec
56
+ Outdated::OUTDATED
57
+ elsif recommended_spec < currently_used_spec
58
+ Outdated::IMMATURE
59
+ end
60
+
61
+ [recommended_spec, code]
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,30 @@
1
+ module Outdated
2
+ module RubyGems
3
+ class Spec
4
+ include Comparable
5
+
6
+ def self.from_response_object(name, response_object)
7
+ Outdated::RubyGems::Spec.new(created_at: response_object['created_at'].to_time,
8
+ name: name,
9
+ prerelease: response_object['prerelease'],
10
+ version: ::Gem::Version.new(response_object['number']))
11
+ end
12
+
13
+ attr_reader :created_at, :name, :prerelease, :version
14
+
15
+ def initialize(args)
16
+ @created_at = args[:created_at] or raise ArgumentError, "missing created_at"
17
+ @name = args[:name] or raise ArgumentError, "missing name"
18
+
19
+ @prerelease = args[:prerelease]
20
+ raise ArgumentError, "missing prerelease" if @prerelease.nil?
21
+
22
+ @version = args[:version] or raise ArgumentError, "missing version"
23
+ end
24
+
25
+ def <=>(other)
26
+ version <=> other.version
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Outdated
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: outdated
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keith Broughton
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-26 00:00:00.000000000 Z
11
+ date: 2019-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -119,7 +119,6 @@ files:
119
119
  - ".gitignore"
120
120
  - ".rspec"
121
121
  - ".rubocop.yml"
122
- - ".safe.yml"
123
122
  - ".travis.yml"
124
123
  - CODE_OF_CONDUCT.md
125
124
  - Gemfile
@@ -132,7 +131,8 @@ files:
132
131
  - lib/outdated.rb
133
132
  - lib/outdated/cli.rb
134
133
  - lib/outdated/ruby_gems.rb
135
- - lib/outdated/ruby_gems/spec_set.rb
134
+ - lib/outdated/ruby_gems/gem.rb
135
+ - lib/outdated/ruby_gems/spec.rb
136
136
  - lib/outdated/version.rb
137
137
  - outdated.gemspec
138
138
  homepage: https://github.com/keithbro/outdated
data/.safe.yml DELETED
@@ -1,4 +0,0 @@
1
- ---
2
-
3
- Exclude:
4
- - http
@@ -1,53 +0,0 @@
1
- module Outdated
2
- module RubyGems
3
- class SpecSet
4
- def self.from_response(response)
5
- return new if response.code == 404
6
-
7
- body = response.body
8
- specs = JSON.parse(body).map do |spec|
9
- spec['created_at'] = Time.parse(spec['created_at'])
10
- spec['version'] = Gem::Version.new(spec['number'])
11
-
12
- OpenStruct.new(spec)
13
- end
14
- new(specs)
15
- end
16
-
17
- attr_reader :specs
18
-
19
- def initialize(specs = [])
20
- @specs = specs
21
- end
22
-
23
- def empty?
24
- specs.empty?
25
- end
26
-
27
- def size
28
- specs.size
29
- end
30
-
31
- def first
32
- specs.first
33
- end
34
-
35
- def get(version)
36
- specs.find { |spec| spec.version == version }
37
- end
38
-
39
- def recommend(status_quo_spec, cut_off)
40
- specs.find do |spec|
41
- semver = spec.version.to_s.split(/\./).map(&:to_i)
42
- status_quo_semver = status_quo_spec.version.to_s.split(/\./).map(&:to_i)
43
- prerelease = spec.prerelease
44
- too_new = cut_off < spec.created_at
45
- minor_or_major_upgrade =
46
- semver[0] > status_quo_semver[0] || semver[1] > status_quo_semver[1]
47
-
48
- !prerelease && !too_new && !minor_or_major_upgrade
49
- end
50
- end
51
- end
52
- end
53
- end