class Gem::DependencyResolver


that should be activated to meet the all the requirements.
a set of ActivationRequest objects which indicate all the specs
to query the set of available specs via set, calculates
Given a set of Gem::Dependency objects as needed and a way

def self.for_current_gems(needed)


the already installed gems.
Provide a DependencyResolver that queries only against
def self.for_current_gems(needed)
  new needed, CurrentSet.new
end

def initialize(needed, set=IndexSet.new)


defaults to IndexSet, which will query rubygems.org.
specifications to satisify the Dependencies. This
+set+ is an object that provides where to look for

the tree starting with +needed+ Depedency objects.
Create DependencyResolver object which will resolve
def initialize(needed, set=IndexSet.new)
  @set = set || IndexSet.new # Allow nil to mean IndexSet
  @needed = needed
  @conflicts = nil
end

def requests(s, act)

def requests(s, act)
  reqs = []
  s.dependencies.each do |d|
    next unless d.type == :runtime
    reqs << DependencyRequest.new(d, act)
  end
  @set.prefetch(reqs)
  reqs
end

def resolve


objects.
Proceed with resolution! Returns an array of ActivationRequest
def resolve
  @conflicts = []
  needed = @needed.map { |n| DependencyRequest.new(n, nil) }
  res = resolve_for needed, []
  if res.kind_of? DependencyConflict
    raise DependencyResolutionError.new(res)
  end
  res
end

def resolve_for(needed, specs)


of ActivationRequest objects.
and +specs+ being a list to ActivationRequest, calculate a new list
The meat of the algorithm. Given +needed+ DependencyRequest objects
def resolve_for(needed, specs)
  until needed.empty?
    dep = needed.shift
    # If there is already a spec activated for the requested name...
    if existing = specs.find { |s| dep.name == s.name }
      # then we're done since this new dep matches the
      # existing spec.
      next if dep.matches_spec? existing
      # There is a conflict! We return the conflict
      # object which will be seen by the caller and be
      # handled at the right level.
      # If the existing activation indicates that there
      # are other possibles for it, then issue the conflict
      # on the dep for the activation itself. Otherwise, issue
      # it on the requester's request itself.
      #
      if existing.others_possible?
        conflict = DependencyConflict.new(dep, existing)
      else
        depreq = existing.request.requester.request
        conflict = DependencyConflict.new(depreq, existing, dep)
      end
      @conflicts << conflict
      return conflict
    end
    # Get a list of all specs that satisfy dep
    possible = @set.find_all(dep)
    case possible.size
    when 0
      # If there are none, then our work here is done.
      raise UnsatisfiableDepedencyError.new(dep)
    when 1
      # If there is one, then we just add it to specs
      # and process the specs dependencies by adding
      # them to needed.
      spec = possible.first
      act =  ActivationRequest.new(spec, dep, false)
      specs << act
      # Put the deps for at the beginning of needed
      # rather than the end to match the depth first
      # searching done by the multiple case code below.
      #
      # This keeps the error messages consistent.
      needed = requests(spec, act) + needed
    else
      # There are multiple specs for this dep. This is
      # the case that this class is built to handle.
      # Sort them so that we try the highest versions
      # first.
      possible = possible.sort_by { |s| s.version }
      # We track the conflicts seen so that we can report them
      # to help the user figure out how to fix the situation.
      conflicts = []
      # To figure out which to pick, we keep resolving
      # given each one being activated and if there isn't
      # a conflict, we know we've found a full set.
      #
      # We use an until loop rather than #reverse_each
      # to keep the stack short since we're using a recursive
      # algorithm.
      #
      until possible.empty?
        s = possible.pop
        # Recursively call #resolve_for with this spec
        # and add it's dependencies into the picture...
        act = ActivationRequest.new(s, dep)
        try = requests(s, act) + needed
        res = resolve_for(try, specs + [act])
        # While trying to resolve these dependencies, there may
        # be a conflict!
        if res.kind_of? DependencyConflict
          # The conflict might be created not by this invocation
          # but rather one up the stack, so if we can't attempt
          # to resolve this conflict (conflict isn't with the spec +s+)
          # then just return it so the caller can try to sort it out.
          return res unless res.for_spec? s
          # Otherwise, this is a conflict that we can attempt to fix
          conflicts << [s, res]
          # Optimization:
          #
          # Because the conflict indicates the dependency that trigger
          # it, we can prune possible based on this new information.
          #
          # This cuts down on the number of iterations needed.
          possible.delete_if { |x| !res.dependency.matches_spec? x }
        else
          # No conflict, return the specs
          return res
        end
      end
      # We tried all possibles and nothing worked, so we let the user
      # know and include as much information about the problem since
      # the user is going to have to take action to fix this.
      raise ImpossibleDependenciesError.new(dep, conflicts)
    end
  end
  specs
end