class Gem::Resolver

def self.compose_sets(*sets)

def self.compose_sets(*sets)
  sets.compact!
  sets = sets.map do |set|
    case set
    when Gem::Resolver::BestSet then
      set
    when Gem::Resolver::ComposedSet then
      set.sets
    else
      set
    end
  end.flatten
  case sets.length
  when 0 then
    raise ArgumentError, 'one set in the composition must be non-nil'
  when 1 then
    sets.first
  else
    Gem::Resolver::ComposedSet.new(*sets)
  end
end

def self.for_current_gems(needed)

def self.for_current_gems(needed)
  new needed, Gem::Resolver::CurrentSet.new
end

def activation_request(dep, possible) # :nodoc:

:nodoc:
def activation_request(dep, possible) # :nodoc:
  spec = possible.pop
  explain :activate, [spec.full_name, possible.size]
  explain :possible, possible
  activation_request =
    Gem::Resolver::ActivationRequest.new spec, dep, possible
  return spec, activation_request
end

def allow_missing?(dependency)

def allow_missing?(dependency)
  @missing << dependency
  @soft_missing
end

def amount_constrained(dependency)

before dependencies that are unconstrained
are given very negative values, so they _always_ sort first,
dependencies w/ 0 or 1 possibilities (ignoring version requirements)

a number closer to 0 means the dependency is less constraining
returns an integer \in (-\infty, 0]
def amount_constrained(dependency)
  @amount_constrained ||= {}
  @amount_constrained[dependency.name] ||= begin
    name_dependency = Gem::Dependency.new(dependency.name)
    dependency_request_for_name = Gem::Resolver::DependencyRequest.new(name_dependency, dependency.requester)
    all = @set.find_all(dependency_request_for_name).size
    if all <= 1
      all - SINGLE_POSSIBILITY_CONSTRAINT_PENALTY
    else
      search = search_for(dependency).size
      search - all
    end
  end
end

def debug?

def debug?
  DEBUG_RESOLVER
end

def dependencies_for(specification)

def dependencies_for(specification)
  return [] if @ignore_dependencies
  spec = specification.spec
  requests(spec, specification)
end

def explain(stage, *data) # :nodoc:

:nodoc:
def explain(stage, *data) # :nodoc:
  return unless DEBUG_RESOLVER
  d = data.map {|x| x.pretty_inspect }.join(", ")
  $stderr.printf "%10s %s\n", stage.to_s.upcase, d
end

def explain_list(stage) # :nodoc:

:nodoc:
def explain_list(stage) # :nodoc:
  return unless DEBUG_RESOLVER
  data = yield
  $stderr.printf "%10s (%d entries)\n", stage.to_s.upcase, data.size
  unless data.empty?
    require 'pp'
    PP.pp data, $stderr
  end
end

def find_possible(dependency) # :nodoc:

:nodoc:
def find_possible(dependency) # :nodoc:
  all = @set.find_all dependency
  if (skip_dep_gems = skip_gems[dependency.name]) && !skip_dep_gems.empty?
    matching = all.select do |api_spec|
      skip_dep_gems.any? {|s| api_spec.version == s.version }
    end
    all = matching unless matching.empty?
  end
  matching_platform = select_local_platforms all
  return matching_platform, all
end

def initialize(needed, set = nil)

def initialize(needed, set = nil)
  @set = set || Gem::Resolver::IndexSet.new
  @needed = needed
  @development         = false
  @development_shallow = false
  @ignore_dependencies = false
  @missing             = []
  @skip_gems           = {}
  @soft_missing        = false
  @stats               = Gem::Resolver::Stats.new
end

def name_for(dependency)

def name_for(dependency)
  dependency.name
end

def output

def output
  @output ||= debug? ? $stdout : File.open(IO::NULL, 'w')
end

def requests(s, act, reqs=[]) # :nodoc:

:nodoc:
def requests(s, act, reqs=[]) # :nodoc:
  return reqs if @ignore_dependencies
  s.fetch_development_dependencies if @development
  s.dependencies.reverse_each do |d|
    next if d.type == :development and not @development
    next if d.type == :development and @development_shallow and
            act.development?
    next if d.type == :development and @development_shallow and
            act.parent
    reqs << Gem::Resolver::DependencyRequest.new(d, act)
    @stats.requirement!
  end
  @set.prefetch reqs
  @stats.record_requirements reqs
  reqs
end

def requirement_satisfied_by?(requirement, activated, spec)

def requirement_satisfied_by?(requirement, activated, spec)
  matches_spec = requirement.matches_spec? spec
  return matches_spec if @soft_missing
  matches_spec &&
    spec.spec.required_ruby_version.satisfied_by?(Gem.ruby_version) &&
    spec.spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version)
end

def resolve

def resolve
  locking_dg = Molinillo::DependencyGraph.new
  Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }, locking_dg).tsort.map(&:payload).compact
rescue Molinillo::VersionConflict => e
  conflict = e.conflicts.values.first
  raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement)
ensure
  @output.close if defined?(@output) and !debug?
end

def search_for(dependency)

def search_for(dependency)
  possibles, all = find_possible(dependency)
  if !@soft_missing && possibles.empty?
    @missing << dependency
    exc = Gem::UnsatisfiableDependencyError.new dependency, all
    exc.errors = @set.errors
    raise exc
  end
  groups = Hash.new {|hash, key| hash[key] = [] }
  # create groups & sources in the same loop
  sources = possibles.map do |spec|
    source = spec.source
    groups[source] << spec
    source
  end.uniq.reverse
  activation_requests = []
  sources.each do |source|
    groups[source].
      sort_by {|spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }.
      map {|spec| ActivationRequest.new spec, dependency }.
      each {|activation_request| activation_requests << activation_request }
  end
  activation_requests
end

def select_local_platforms(specs) # :nodoc:

:nodoc:
def select_local_platforms(specs) # :nodoc:
  specs.select do |spec|
    Gem::Platform.installable? spec
  end
end

def sort_dependencies(dependencies, activated, conflicts)

def sort_dependencies(dependencies, activated, conflicts)
  dependencies.sort_by.with_index do |dependency, i|
    name = name_for(dependency)
    [
      activated.vertex_named(name).payload ? 0 : 1,
      amount_constrained(dependency),
      conflicts[name] ? 0 : 1,
      activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
      i, # for stable sort
    ]
  end
end