aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rubygems/resolver/api_set.rb
blob: 60bf911063ad3b17a34ffae1f3601df53236a9a1 (plain)
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
##
# The global rubygems pool, available via the rubygems.org API.
# Returns instances of APISpecification.

class Gem::Resolver::APISet < Gem::Resolver::Set

  ##
  # The URI for the dependency API this APISet uses.

  attr_reader :dep_uri # :nodoc:

  ##
  # Creates a new APISet that will retrieve gems from +uri+ using the RubyGems
  # API described at http://guides.rubygems.org/rubygems-org-api

  def initialize uri = 'https://rubygems.org/api/v1/dependencies'
    uri = URI uri unless URI === uri # for ruby 1.8
    @data = Hash.new { |h,k| h[k] = [] }
    @dep_uri = uri
  end

  ##
  # Return an array of APISpecification objects matching
  # DependencyRequest +req+.

  def find_all req
    res = []

    versions(req.name).each do |ver|
      if req.dependency.match? req.name, ver[:number]
        res << Gem::Resolver::APISpecification.new(self, ver)
      end
    end

    res
  end

  ##
  # A hint run by the resolver to allow the Set to fetch
  # data for DependencyRequests +reqs+.

  def prefetch reqs
    names = reqs.map { |r| r.dependency.name }
    needed = names.find_all { |d| !@data.key?(d) }

    return if needed.empty?

    uri = @dep_uri + "?gems=#{needed.sort.join ','}"
    str = Gem::RemoteFetcher.fetcher.fetch_path uri

    Marshal.load(str).each do |ver|
      @data[ver[:name]] << ver
    end
  end

  ##
  # Return data for all versions of the gem +name+.

  def versions name # :nodoc:
    if @data.key?(name)
      return @data[name]
    end

    uri = @dep_uri + "?gems=#{name}"
    str = Gem::RemoteFetcher.fetcher.fetch_path uri

    Marshal.load(str).each do |ver|
      @data[ver[:name]] << ver
    end

    @data[name]
  end

end