outdated 0.1.0 → 0.2.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
  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