forked from clio/ten_years_rails
-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathgem_info.rb
155 lines (127 loc) · 3.78 KB
/
gem_info.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
module NextRails
class GemInfo
class NullGemInfo < GemInfo
def initialize; end
def age
"-"
end
def created_at
Time.now
end
def up_to_date?
false
end
def version
"NOT FOUND"
end
def unsatisfied_rails_dependencies(*)
["unknown"]
end
def state(_)
:null
end
end
RAILS_GEMS = [
"rails",
"activemodel",
"activerecord",
"actionmailer",
"actioncable",
"actionpack",
"actionview",
"activejob",
"activestorage",
"activesupport",
"actionmailbox",
"actiontext",
"railties",
].freeze
def self.all
Gem::Specification.each.map do |gem_specification|
new(gem_specification)
end
end
attr_reader :gem_specification, :version, :name, :latest_compatible_version
def initialize(gem_specification)
@gem_specification = gem_specification
@version = gem_specification.version
@name = gem_specification.name
end
def age
created_at.strftime("%b %e, %Y")
end
def sourced_from_git?
!!gem_specification.git_version
end
def created_at
@created_at ||= gem_specification.date
end
def up_to_date?
version == latest_version.version
end
def from_rails?
RAILS_GEMS.include?(name)
end
def state(rails_version)
if compatible_with_rails?(rails_version: rails_version)
:compatible
elsif latest_compatible_version && latest_compatible_version.version == "NOT FOUND"
:no_new_version
elsif latest_compatible_version
:found_compatible
else
:incompatible
end
end
def latest_version
latest_gem_specification = Gem.latest_spec_for(name)
return NullGemInfo.new unless latest_gem_specification
GemInfo.new(latest_gem_specification)
rescue
NullGemInfo.new
end
def compatible_with_rails?(rails_version: nil)
unsatisfied_rails_dependencies(rails_version: rails_version).empty?
end
def unsatisfied_rails_dependencies(rails_version: nil)
spec_compatible_with_rails?(specification: gem_specification, rails_version: rails_version)
end
def find_latest_compatible(rails_version: nil)
dependency = Gem::Dependency.new(@name)
fetcher = Gem::SpecFetcher.new
# list all available data for released gems
list, errors = fetcher.available_specs(:released)
specs = []
# filter only specs for the current gem and older versions
list.each do |source, gem_tuples|
gem_tuples.each do |gem_tuple|
if gem_tuple.name == @name && gem_tuple.version > @version
specs << source.fetch_spec(gem_tuple)
end
end
end
# if nothing is found, consider gem incompatible
if specs.empty?
@latest_compatible_version = NullGemInfo.new
return
end
# if specs are found, look for the first one from that is compatible
# with the desired rails version starting from the end
specs.reverse.each do |spec|
if spec_compatible_with_rails?(specification: spec, rails_version: rails_version).empty?
@latest_compatible_version = spec
break
end
end
end
def spec_compatible_with_rails?(specification: nil, rails_version: nil)
rails_dependencies = specification.runtime_dependencies.select {|dependency| RAILS_GEMS.include?(dependency.name) }
rails_dependencies.reject do |rails_dependency|
rails_dependency.requirement.satisfied_by?(Gem::Version.new(rails_version))
end
end
def compatible_with_ruby?(ruby_version)
gem_specification.required_ruby_version.satisfied_by?(Gem::Version.new(ruby_version))
end
end
end