Class: Bundler::Resolver (Ruby 2.7.5)
Description: Class : Bundler::Resolver - Ruby 2.7.5

### Home Classes Methods

### In Files

- bundler/resolver.rb
- bundler/resolver/spec_group.rb

### Parent

Object

### Namespace

- CLASS Bundler::Resolver::SpecGroup

### Methods

- ::new
- ::platform_sort_key
- ::resolve
- ::sort_platforms
- #after_resolution
- #before_resolution
- #debug
- #debug?
- #dependencies_for
- #index_for
- #indicate_progress
- #name_for
- #name_for_explicit_dependency_source
- #name_for_locking_dependency_source
- #relevant_sources_for_vertex
- #requirement_satisfied_by?
- #search_for
- #sort_dependencies
- #start

### Included Modules

- Bundler::Molinillo::UI
- Bundler::Molinillo::SpecificationProvider

### Class/Module Index

Quicksearch

- AmbiguousCommandError
- AmbiguousTaskError
- Bundler
- Bundler::APIResponseMismatchError
- Bundler::BuildMetadata
- Bundler::BundlerError
- Bundler::CLI
- Bundler::CLI::Add
- Bundler::CLI::Binstubs
- Bundler::CLI::Cache
- Bundler::CLI::Check
- Bundler::CLI::Clean
- Bundler::CLI::Common
- Bundler::CLI::Config
- Bundler::CLI::Config::Base
- Bundler::CLI::Console
- Bundler::CLI::Doctor
- Bundler::CLI::Exec
- Bundler::CLI::Gem
- Bundler::CLI::Info
- Bundler::CLI::Init
- Bundler::CLI::Inject
- Bundler::CLI::Install
- Bundler::CLI::Issue
- Bundler::CLI::List
- Bundler::CLI::Lock
- Bundler::CLI::Open
- Bundler::CLI::Outdated
- Bundler::CLI::Package
- Bundler::CLI::Platform
- Bundler::CLI::Plugin
- Bundler::CLI::Pristine
- Bundler::CLI::Remove
- Bundler::CLI::Show
- Bundler::CLI::Update
- Bundler::CLI::Viz
- Bundler::CompactIndexClient
- Bundler::CompactIndexClient::Cache
- Bundler::CompactIndexClient::Error
- Bundler::CompactIndexClient::Updater
- Bundler::CompactIndexClient::Updater::MisMatchedChecksumError
- Bundler::ConnectionPool
- Bundler::ConnectionPool::Error
- Bundler::ConnectionPool::PoolShuttingDownError
- Bundler::ConnectionPool::TimedStack
- Bundler::ConnectionPool::Wrapper
- Bundler::CurrentRuby
- Bundler::CyclicDependencyError
- Bundler::Definition
- Bundler::DepProxy
- Bundler::Dependency
- Bundler::Deployment
- Bundler::Deprecate
- Bundler::DeprecatedError
- Bundler::Dsl
- Bundler::Dsl::DSLError
- Bundler::EndpointSpecification
- Bundler::Env
- Bundler::EnvironmentPreserver
- Bundler::FeatureFlag
- Bundler::Fetcher
- Bundler::Fetcher::AuthenticationRequiredError
- Bundler::Fetcher::BadAuthenticationError
- Bundler::Fetcher::Base
- Bundler::Fetcher::CertificateFailureError
- Bundler::Fetcher::CompactIndex
- Bundler::Fetcher::Dependency
- Bundler::Fetcher::Downloader
- Bundler::Fetcher::FallbackError
- Bundler::Fetcher::Index
- Bundler::Fetcher::NetworkDownError
- Bundler::Fetcher::SSLError
- Bundler::Fetcher::TooManyRequestsError
- Bundler::FileUtils
- Bundler::FileUtils::DryRun
- Bundler::FileUtils::NoWrite
- Bundler::FileUtils::StreamUtils_
- Bundler::FileUtils::Verbose
- Bundler::FriendlyErrors
- Bundler::GemHelper
- Bundler::GemHelpers
- Bundler::GemHelpers::PlatformMatch
- Bundler::GemInstaller
- Bundler::GemNotFound
- Bundler::GemRemoteFetcher
- Bundler::GemRequireError
- Bundler::GemVersionPromoter
- Bundler::Gemdeps
- Bundler::GemfileError
- Bundler::GemfileEvalError
- Bundler::GemfileLockNotFound
- Bundler::GemfileNotFound
- Bundler::GemspecError
- Bundler::GenericSystemCallError
- Bundler::GitError
- Bundler::Graph
- Bundler::Graph::GraphVizClient
- Bundler::HTTPError
- Bundler::Index
- Bundler::Injector
- Bundler::InstallError
- Bundler::InstallHookError
- Bundler::Installer
- Bundler::InvalidOption
- Bundler::LazySpecification
- Bundler::LazySpecification::Identifier
- Bundler::LockfileError
- Bundler::LockfileGenerator
- Bundler::LockfileParser
- Bundler::MarshalError
- Bundler::MatchPlatform
- Bundler::MirrorSockets
- Bundler::Molinillo
- Bundler::Molinillo::CircularDependencyError
- Bundler::Molinillo::Compatibility
- Bundler::Molinillo::Delegates
- Bundler::Molinillo::Delegates::ResolutionState
- Bundler::Molinillo::Delegates::SpecificationProvider
- Bundler::Molinillo::DependencyGraph
- Bundler::Molinillo::DependencyGraph::Action
- Bundler::Molinillo::DependencyGraph::AddEdgeNoCircular
- Bundler::Molinillo::DependencyGraph::DeleteEdge
- Bundler::Molinillo::DependencyGraph::DetachVertexNamed
- Bundler::Molinillo::DependencyGraph::Log
- Bundler::Molinillo::DependencyGraph::Tag
- Bundler::Molinillo::DependencyGraph::Vertex
- Bundler::Molinillo::DependencyState
- Bundler::Molinillo::NoSuchDependencyError
- Bundler::Molinillo::PossibilityState
- Bundler::Molinillo::ResolutionState
- Bundler::Molinillo::Resolver
- Bundler::Molinillo::Resolver::Resolution
- Bundler::Molinillo::Resolver::Resolution::Conflict
- Bundler::Molinillo::Resolver::Resolution::PossibilitySet
- Bundler::Molinillo::Resolver::Resolution::UnwindDetails
- Bundler::Molinillo::ResolverError
- Bundler::Molinillo::SpecificationProvider
- Bundler::Molinillo::UI
- Bundler::Molinillo::VersionConflict
- Bundler::NoSpaceOnDeviceError
- Bundler::OperationNotSupportedError
- Bundler::ParallelInstaller
- Bundler::ParallelInstaller::SpecInstallation
- Bundler::PathError
- Bundler::PermissionError
- Bundler::Persistent
- Bundler::Persistent::Net
- Bundler::Persistent::Net::HTTP
- Bundler::Persistent::Net::HTTP::Persistent
- Bundler::Persistent::Net::HTTP::Persistent::Error
- Bundler::PersistentHTTP
- Bundler::Plugin
- Bundler::Plugin::API
- Bundler::Plugin::API::Source
- Bundler::Plugin::DSL
- Bundler::Plugin::DSL::PluginGemfileError
- Bundler::Plugin::Events
- Bundler::Plugin::Index
- Bundler::Plugin::Index::CommandConflict
- Bundler::Plugin::Index::SourceConflict
- Bundler::Plugin::Installer
- Bundler::Plugin::Installer::Git
- Bundler::Plugin::Installer::Rubygems
- Bundler::Plugin::MalformattedPlugin
- Bundler::Plugin::SourceList
- Bundler::Plugin::UndefinedCommandError
- Bundler::Plugin::UnknownSourceError
- Bundler::PluginError
- Bundler::ProcessLock
- Bundler::ProductionError
- Bundler::RemoteSpecification
- Bundler::Resolver
- Bundler::Resolver::SpecGroup
- Bundler::Retry
- Bundler::RubyDsl
- Bundler::RubyGemsGemInstaller
- Bundler::RubyVersion
- Bundler::RubyVersionMismatch
- Bundler::RubygemsIntegration
- Bundler::RubygemsIntegration::Gem
- Bundler::Runtime
- Bundler::SecurityError
- Bundler::Settings
- Bundler::Settings::Mirror
- Bundler::Settings::MirrorConfig
- Bundler::Settings::Mirrors
- Bundler::Settings::TCPSocketProbe
- Bundler::Settings::Validator
- Bundler::Settings::Validator::Rule
- Bundler::SharedHelpers
- Bundler::SimilarityDetector
- Bundler::SocketAddress
- Bundler::Source
- Bundler::Source::Gemspec
- Bundler::Source::Git
- Bundler::Source::Git::GitCommandError
- Bundler::Source::Git::GitNotAllowedError
- Bundler::Source::Git::GitNotInstalledError
- Bundler::Source::Git::GitProxy
- Bundler::Source::Git::MissingGitRevisionError
- Bundler::Source::Metadata
- Bundler::Source::Path
- Bundler::Source::Path::Installer
- Bundler::Source::Rubygems
- Bundler::Source::Rubygems::Remote
- Bundler::SourceList
- Bundler::SpecSet
- Bundler::Standalone
- Bundler::StubSpecification
- Bundler::SudoNotPermittedError
- Bundler::TemporaryResourceError
- Bundler::Thor::Actions
- Bundler::Thor::Actions::CapturableERB
- Bundler::Thor::Actions::ClassMethods
- Bundler::Thor::Base
- Bundler::Thor::Base::ClassMethods
- Bundler::Thor::Command
- Bundler::Thor::CoreExt
- Bundler::Thor::CoreExt::OrderedHash
- Bundler::Thor::DynamicCommand
- Bundler::Thor::DynamicTask
- Bundler::Thor::Group
- Bundler::Thor::HiddenCommand
- Bundler::Thor::HiddenTask
- Bundler::Thor::Invocation
- Bundler::Thor::Invocation::ClassMethods
- Bundler::Thor::LineEditor
- Bundler::Thor::LineEditor::Basic
- Bundler::Thor::LineEditor::Readline
- Bundler::Thor::LineEditor::Readline::PathCompletion
- Bundler::Thor::NestedContext
- Bundler::Thor::RakeCompat
- Bundler::Thor::Shell
- Bundler::Thor::Shell::Basic
- Bundler::Thor::Shell::Color
- Bundler::Thor::Shell::HTML
- Bundler::Thor::Task
- Bundler::Thor::Util
- Bundler::ThreadCreationError
- Bundler::UI
- Bundler::UI::RGProxy
- Bundler::UI::Shell
- Bundler::UI::Silent
- Bundler::URI
- Bundler::URI::BadURIError
- Bundler::URI::Error
- Bundler::URI::Escape
- Bundler::URI::FTP
- Bundler::URI::File
- Bundler::URI::Generic
- Bundler::URI::HTTP
- Bundler::URI::HTTPS
- Bundler::URI::InvalidComponentError
- Bundler::URI::InvalidURIError
- Bundler::URI::LDAP
- Bundler::URI::LDAPS
- Bundler::URI::MailTo
- Bundler::URI::Parser
- Bundler::URI::REGEXP
- Bundler::URI::RFC2396_Parser
- Bundler::URI::RFC2396_REGEXP
- Bundler::URI::RFC2396_REGEXP::PATTERN
- Bundler::URICredentialsFilter
- Bundler::VersionConflict
- Bundler::VersionRanges
- Bundler::VersionRanges::ReqR
- Bundler::VirtualProtocolError
- Bundler::Worker
- Bundler::Worker::WrappedException
- Bundler::YAMLSerializer
- Bundler::YamlSyntaxError
- Error
- Gem
- Gem::Dependency
- Gem::Platform
- Gem::Specification
- InvocationError
- Kernel
- MalformattedArgumentError
- Object
- RequiredArgumentMissingError
- UndefinedCommandError
- UndefinedCommandError::SpellChecker
- UndefinedTaskError
- UnknownArgumentError
- UnknownArgumentError::SpellChecker

No matching classes.

# Bundler::Resolver

### Public Class Methods

new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) click to toggle source

                   # File bundler/resolver.rb, line 26
    def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
      @index = index
      @source_requirements = source_requirements
      @base = base
      @resolver = Molinillo::Resolver.new(self, self)
      @search_for = {}
      @base_dg = Molinillo::DependencyGraph.new
      @base.each do |ls|
        dep = Dependency.new(ls.name, ls.version)
        @base_dg.add_vertex(ls.name, DepProxy.new(dep, ls.platform), true)
      end
      additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
      @platforms = platforms
      @gem_version_promoter = gem_version_promoter
      @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
      @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
      @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource?
    end

platform_sort_key(platform) click to toggle source

                   # File bundler/resolver.rb, line 225
    def self.platform_sort_key(platform)
      return ["", "", ""] if Gem::Platform::RUBY == platform
      platform.to_a.map {|part| part || "" }
    end

resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil) click to toggle source

Figures out the best possible configuration of gems that satisfies the list of passed dependencies and any child dependencies without causing any gem activation errors.

#### Parameters¶ ↑

*dependencies<Gem::Dependency>

  The list of dependencies to resolve

#### Returns¶ ↑

<GemBundle>,nil

  If the list of dependencies can be resolved, a

    collection of gemspecs is returned. Otherwise, nil is returned.

                   # File bundler/resolver.rb, line 18
    def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
      platforms = Set.new(platforms) if platforms
      base = SpecSet.new(base) unless base.is_a?(SpecSet)
      resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
      result = resolver.start(requirements)
      SpecSet.new(result)
    end

sort_platforms(platforms) click to toggle source

Sort platforms from most general to most specific

                   # File bundler/resolver.rb, line 219
    def self.sort_platforms(platforms)
      platforms.sort_by do |platform|
        platform_sort_key(platform)
      end
    end

### Public Instance Methods

after_resolution() click to toggle source

                   # File bundler/resolver.rb, line 90
    def after_resolution
      Bundler.ui.info ""
    end

before_resolution() click to toggle source

                   # File bundler/resolver.rb, line 86
    def before_resolution
      Bundler.ui.info "Resolving dependencies...", debug?
    end

debug(depth = 0) click to toggle source

Conveys debug information to the user.

@param [Integer] depth the current depth of the resolution process. @return [void]

                   # File bundler/resolver.rb, line 74
    def debug(depth = 0)
      return unless debug?
      debug_info = yield
      debug_info = debug_info.inspect unless debug_info.is_a?(String)
      warn debug_info.split("\n").map {|s| "  " * depth + s }
    end

debug?() click to toggle source

                   # File bundler/resolver.rb, line 81
    def debug?
      return @debug_mode if defined?(@debug_mode)
      @debug_mode = ENV["DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER_TREE"] || false
    end

dependencies_for(specification) click to toggle source

                   # File bundler/resolver.rb, line 100
    def dependencies_for(specification)
      specification.dependencies_for_activated_platforms
    end

index_for(dependency) click to toggle source

                   # File bundler/resolver.rb, line 152
    def index_for(dependency)
      source = @source_requirements[dependency.name]
      if source
        source.specs
      elsif @lockfile_uses_separate_rubygems_sources
        Index.build do |idx|
          if dependency.all_sources
            dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
          else
            idx.add_source @source_requirements[:default].specs
          end
        end
      else
        @index
      end
    end

indicate_progress() click to toggle source

                   # File bundler/resolver.rb, line 94
    def indicate_progress
      Bundler.ui.info ".", false unless debug?
    end

name_for(dependency) click to toggle source

                   # File bundler/resolver.rb, line 169
    def name_for(dependency)
      dependency.name
    end

name_for_explicit_dependency_source() click to toggle source

                   # File bundler/resolver.rb, line 173
    def name_for_explicit_dependency_source
      Bundler.default_gemfile.basename.to_s
    rescue StandardError
      "Gemfile"
    end

name_for_locking_dependency_source() click to toggle source

                   # File bundler/resolver.rb, line 179
    def name_for_locking_dependency_source
      Bundler.default_lockfile.basename.to_s
    rescue StandardError
      "Gemfile.lock"
    end

relevant_sources_for_vertex(vertex) click to toggle source

                   # File bundler/resolver.rb, line 191
    def relevant_sources_for_vertex(vertex)
      if vertex.root?
        [@source_requirements[vertex.name]]
      elsif @lockfile_uses_separate_rubygems_sources
        vertex.recursive_predecessors.map do |v|
          @source_requirements[v.name]
        end << @source_requirements[:default]
      end
    end

requirement_satisfied_by?(requirement, activated, spec) click to toggle source

                   # File bundler/resolver.rb, line 185
    def requirement_satisfied_by?(requirement, activated, spec)
      return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
      spec.activate_platform!(requirement.__platform) if !@platforms || @platforms.include?(requirement.__platform)
      true
    end

search_for(dependency) click to toggle source

                   # File bundler/resolver.rb, line 104
    def search_for(dependency)
      platform = dependency.__platform
      dependency = dependency.dep unless dependency.is_a? Gem::Dependency
      search = @search_for[dependency] ||= begin
        index = index_for(dependency)
        results = index.search(dependency, @base[dependency.name])

        if vertex = @base_dg.vertex_named(dependency.name)
          locked_requirement = vertex.payload.requirement
        end

        if !@prerelease_specified[dependency.name] && (!@use_gvp || locked_requirement.nil?)
          # Move prereleases to the beginning of the list, so they're considered
          # last during resolution.
          pre, results = results.partition {|spec| spec.version.prerelease? }
          results = pre + results
        end

        spec_groups = if results.any?
          nested = []
          results.each do |spec|
            version, specs = nested.last
            if version == spec.version
              specs << spec
            else
              nested << [spec.version, [spec]]
            end
          end
          nested.reduce([]) do |groups, (version, specs)|
            next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
            spec_group = SpecGroup.new(specs)
            spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts
            groups << spec_group
          end
        else
          []
        end
        # GVP handles major itself, but it's still a bit risky to trust it with it
        # until we get it settled with new behavior. For 2.x it can take over all cases.
        if !@use_gvp
          spec_groups
        else
          @gem_version_promoter.sort_versions(dependency, spec_groups)
        end
      end
      search.select {|sg| sg.for?(platform) }.each {|sg| sg.activate_platform!(platform) }
    end

sort_dependencies(dependencies, activated, conflicts) click to toggle source

                   # File bundler/resolver.rb, line 201
    def sort_dependencies(dependencies, activated, conflicts)
      dependencies.sort_by do |dependency|
        dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name))
        name = name_for(dependency)
        vertex = activated.vertex_named(name)
        [
          @base_dg.vertex_named(name) ? 0 : 1,
          vertex.payload ? 0 : 1,
          vertex.root? ? 0 : 1,
          amount_constrained(dependency),
          conflicts[name] ? 0 : 1,
          vertex.payload ? 0 : search_for(dependency).count,
          self.class.platform_sort_key(dependency.__platform),
        ]
      end
    end

start(requirements) click to toggle source

                   # File bundler/resolver.rb, line 45
    def start(requirements)
      @gem_version_promoter.prerelease_specified = @prerelease_specified = {}
      requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? }

      verify_gemfile_dependencies_are_found!(requirements)
      dg = @resolver.resolve(requirements, @base_dg)
      dg.
        tap {|resolved| validate_resolved_specs!(resolved) }.
        map(&:payload).
        reject {|sg| sg.name.end_with?("\0") }.
        map(&:to_specs).
        flatten
    rescue Molinillo::VersionConflict => e
      message = version_conflict_message(e)
      raise VersionConflict.new(e.conflicts.keys.uniq, message)
    rescue Molinillo::CircularDependencyError => e
      names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
      raise CyclicDependencyError, "Your bundle requires gems that depend" \
        " on each other, creating an infinite loop. Please remove" \
        " #{names.count > 1 ? "either " : ""}#{names.join(" or ")}" \
        " and try again."
    end