summaryrefslogtreecommitdiff
path: root/lib/rubygems/resolver/api_set.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rubygems/resolver/api_set.rb')
-rw-r--r--lib/rubygems/resolver/api_set.rb87
1 files changed, 50 insertions, 37 deletions
diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb
index ee3046af63..3f443519d8 100644
--- a/lib/rubygems/resolver/api_set.rb
+++ b/lib/rubygems/resolver/api_set.rb
@@ -1,12 +1,14 @@
# frozen_string_literal: true
+
##
-# The global rubygems pool, available via the rubygems.org API.
+# The global rubygems pool, available via the Compact Index API.
# Returns instances of APISpecification.
class Gem::Resolver::APISet < Gem::Resolver::Set
+ autoload :GemParser, File.expand_path("api_set/gem_parser", __dir__)
##
- # The URI for the dependency API this APISet uses.
+ # The URI for the Compact Index API this APISet uses.
attr_reader :dep_uri # :nodoc:
@@ -21,19 +23,19 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
attr_reader :uri
##
- # Creates a new APISet that will retrieve gems from +uri+ using the RubyGems
- # API URL +dep_uri+ which is described at
- # http://guides.rubygems.org/rubygems-org-api
+ # Creates a new APISet that will retrieve gems from +uri+ using the Compact
+ # Index API URL +dep_uri+ which is described at
+ # https://guides.rubygems.org/rubygems-org-compact-index-api
- def initialize dep_uri = 'https://rubygems.org/api/v1/dependencies'
+ def initialize(dep_uri = "https://index.rubygems.org/info/")
super()
- dep_uri = URI dep_uri unless URI === dep_uri # for ruby 1.8
+ dep_uri = Gem::URI dep_uri unless Gem::URI === dep_uri
@dep_uri = dep_uri
- @uri = dep_uri + '../..'
+ @uri = dep_uri + ".."
- @data = Hash.new { |h,k| h[k] = [] }
+ @data = Hash.new {|h,k| h[k] = [] }
@source = Gem::Source.new @uri
@to_fetch = []
@@ -43,7 +45,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
# Return an array of APISpecification objects matching
# DependencyRequest +req+.
- def find_all req
+ def find_all(req)
res = []
return res unless @remote
@@ -53,7 +55,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
end
versions(req.name).each do |ver|
- if req.dependency.match? req.name, ver[:number]
+ if req.dependency.match? req.name, ver[:number], @prerelease
res << Gem::Resolver::APISpecification.new(self, ver)
end
end
@@ -65,41 +67,30 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
# A hint run by the resolver to allow the Set to fetch
# data for DependencyRequests +reqs+.
- def prefetch reqs
+ def prefetch(reqs)
return unless @remote
- names = reqs.map { |r| r.dependency.name }
+ names = reqs.map {|r| r.dependency.name }
needed = names - @data.keys - @to_fetch
@to_fetch += needed
end
def prefetch_now # :nodoc:
- needed, @to_fetch = @to_fetch, []
-
- uri = @dep_uri + "?gems=#{needed.sort.join ','}"
- str = Gem::RemoteFetcher.fetcher.fetch_path uri
-
- loaded = []
-
- Marshal.load(str).each do |ver|
- name = ver[:name]
-
- @data[name] << ver
- loaded << name
- end
+ needed = @to_fetch
+ @to_fetch = []
- (needed - loaded).each do |missing|
- @data[missing] = []
+ needed.sort.each do |name|
+ versions(name)
end
end
- def pretty_print q # :nodoc:
- q.group 2, '[APISet', ']' do
+ def pretty_print(q) # :nodoc:
+ q.group 2, "[APISet", "]" do
q.breakable
q.text "URI: #{@dep_uri}"
q.breakable
- q.text 'gem names:'
+ q.text "gem names:"
q.pp @data.keys
end
end
@@ -107,20 +98,42 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
##
# Return data for all versions of the gem +name+.
- def versions name # :nodoc:
+ def versions(name) # :nodoc:
if @data.key?(name)
return @data[name]
end
- uri = @dep_uri + "?gems=#{name}"
- str = Gem::RemoteFetcher.fetcher.fetch_path uri
+ uri = @dep_uri + name
+
+ begin
+ str = Gem::RemoteFetcher.fetcher.fetch_path uri
+ rescue Gem::RemoteFetcher::FetchError
+ @data[name] = []
+ else
+ lines(str).each do |ver|
+ number, platform, dependencies, requirements = parse_gem(ver)
- Marshal.load(str).each do |ver|
- @data[ver[:name]] << ver
+ platform ||= "ruby"
+ dependencies = dependencies.map {|dep_name, reqs| [dep_name, reqs.join(", ")] }
+ requirements = requirements.map {|req_name, reqs| [req_name.to_sym, reqs] }.to_h
+
+ @data[name] << { name: name, number: number, platform: platform, dependencies: dependencies, requirements: requirements }
+ end
end
@data[name]
end
-end
+ private
+ def lines(str)
+ lines = str.split("\n")
+ header = lines.index("---")
+ header ? lines[header + 1..-1] : lines
+ end
+
+ def parse_gem(string)
+ @gem_parser ||= GemParser.new
+ @gem_parser.parse(string)
+ end
+end