Given a set of Gem::Dependency objects as needed and a way to query the set of available specs via set, calculates a set of ActivationRequest objects which indicate all the specs that should be activated to meet the all the requirements.
If the DEBUG_RESOLVER environment variable is set then debugging mode is enabled for the resolver.  This will display information about the state of the resolver while a set of dependencies is being resolved.
Hash of gems to skip resolution.  Keyed by gem name, with arrays of gem specifications as values.
Combines sets into a ComposedSet that allows specification lookup in a uniform manner.  If one of the sets is itself a ComposedSet its sets are flattened into the result ComposedSet.
 
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 61
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
             
            Creates a Resolver that queries only against the already installed gems for the needed dependencies.
 
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 89
def self.for_current_gems(needed)
  new needed, Gem::Resolver::CurrentSet.new
end
             
            Create Resolver object which will resolve the tree starting with needed Dependency objects.
set is an object that provides where to look for specifications to satisfy the Dependencies. This defaults to IndexSet, which will query rubygems.org.
 
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 101
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
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 276
def allow_missing?(dependency)
  @missing << dependency
  @soft_missing
end
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 179
def debug?
  DEBUG_RESOLVER
end
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 257
def dependencies_for(specification)
  return [] if @ignore_dependencies
  spec = specification.spec
  requests(spec, specification)
end
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 272
def name_for(dependency)
  dependency.name
end
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 175
def output
  @output ||= debug? ? $stdout : File.open(IO::NULL, 'w')
end
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 263
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
             
            Proceed with resolution! Returns an array of ActivationRequest objects.
 
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 188
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
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 227
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
             
             
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 281
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
             
            returns an integer in (-infty, 0] a number closer to 0 means the dependency is less constraining
dependencies w/ 0 or 1 possibilities (ignoring version requirements) are given very negative values, so they always sort first, before dependencies that are unconstrained
 
               # File ruby-3.1.2/lib/rubygems/resolver.rb, line 303
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