summaryrefslogtreecommitdiff
path: root/lib/bundler/resolver.rb
blob: 1b0c0ce98dd6180a95fb27dccb22a0deb3fca527 (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
module Bundler

  class Resolver
    def self.resolve(requirements, index = Gem.source_index)
      result = catch(:success) do
        new(index).resolve(requirements, {})
      end
      result && result.values
    end

    def initialize(index)
      @index = index
    end

    def resolve(reqs, activated)
      return activated if reqs.empty?

      reqs = reqs.sort_by {|dep| @index.search(dep).size }
      activated = activated.dup
      current   = reqs.shift

      if existing = activated[current.name]
        if current.version_requirements.satisfied_by?(existing.version)
          resolve(reqs, activated)
        end
      else
        specs = @index.search(current)
        specs.reverse!
        specs.each do |spec|
          activated[spec.name] = spec
          new_reqs = reqs + spec.dependencies.select do |d|
            d.type != :development
          end
          retval = resolve(new_reqs, activated)
          throw :success, retval if retval
        end
        nil
      end
    end
  end
end