class Bundler::Resolver - bundler-1.9.9 Documentation

# class Bundler::Resolver

### Constants

ALL

### Public Class Methods

new(index, source_requirements, base) click to toggle source

    # File lib/bundler/resolver.rb, line 187
    def initialize(index, source_requirements, base)
      @index = index
      @source_requirements = source_requirements
      @base = base
      @resolver = Molinillo::Resolver.new(self, self)
      @search_for = {}
      @prereleases_cache = Hash.new { |h,k| h[k] = k.prerelease? }
      @base_dg = Molinillo::DependencyGraph.new
      @base.each { |ls| @base_dg.add_root_vertex ls.name, Dependency.new(ls.name, ls.version) }
    end

resolve(requirements, index, source_requirements = {}, base = []) 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 lib/bundler/resolver.rb, line 179
    def self.resolve(requirements, index, source_requirements = {}, base = [])
      base = SpecSet.new(base) unless base.is_a?(SpecSet)
      resolver = new(index, source_requirements, base)
      result = resolver.start(requirements)
      SpecSet.new(result)
    end

### Public Instance Methods

after_resolution() click to toggle source

    # File lib/bundler/resolver.rb, line 234
    def after_resolution
      Bundler.ui.info ''
    end

before_resolution() click to toggle source

    # File lib/bundler/resolver.rb, line 230
    def before_resolution
      Bundler.ui.info 'Resolving dependencies...', false
    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 lib/bundler/resolver.rb, line 218
    def debug(depth = 0)
      if debug?
        debug_info = yield
        debug_info = debug_info.inspect unless debug_info.is_a?(String)
        STDERR.puts debug_info.split("\n").map { |s| '  ' * depth + s }
      end
    end

debug?() click to toggle source

    # File lib/bundler/resolver.rb, line 226
    def debug?
      ENV['DEBUG_RESOLVER'] || ENV['DEBUG_RESOLVER_TREE']
    end

indicate_progress() click to toggle source

    # File lib/bundler/resolver.rb, line 238
    def indicate_progress
      Bundler.ui.info '.', false
    end

start(requirements) click to toggle source

    # File lib/bundler/resolver.rb, line 198
    def start(requirements)
      verify_gemfile_dependencies_are_found!(requirements)
      dg = @resolver.resolve(requirements, @base_dg)
      dg.map(&:payload).map(&:to_specs).flatten
    rescue Molinillo::VersionConflict => e
      raise VersionConflict.new(e.conflicts.keys.uniq, e.message)
    rescue Molinillo::CircularDependencyError => e
      names = e.dependencies.sort_by(&:name).map { |d| "gem '#{d.name}'"}
      raise CyclicDependencyError, "Your Gemfile requires gems that depend"          " on each other, creating an infinite loop. Please remove"          " #{names.count > 1 ? 'either ' : '' }#{names.join(' or ')}"          " and try again."
    end

### Private Instance Methods

dependencies_for(specification) click to toggle source

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

name_for(dependency) click to toggle source

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

name_for_explicit_dependency_source() click to toggle source

    # File lib/bundler/resolver.rb, line 282
    def name_for_explicit_dependency_source
      'Gemfile'
    end

name_for_locking_dependency_source() click to toggle source

    # File lib/bundler/resolver.rb, line 286
    def name_for_locking_dependency_source
      'Gemfile.lock'
    end

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

    # File lib/bundler/resolver.rb, line 290
    def requirement_satisfied_by?(requirement, activated, spec)
      requirement.matches_spec?(spec)
    end

search_for(dependency) click to toggle source

    # File lib/bundler/resolver.rb, line 250
    def search_for(dependency)
      platform = dependency.__platform
      dependency = dependency.dep unless dependency.is_a? Gem::Dependency
      search = @search_for[dependency] ||= begin
        index = @source_requirements[dependency.name] || @index
        results = index.search(dependency, @base[dependency.name])
        if vertex = @base_dg.vertex_named(dependency.name)
          locked_requirement = vertex.payload.requirement
        end
        if results.any?
          version = results.first.version
          nested  = [[]]
          results.each do |spec|
            if spec.version != version
              nested << []
              version = spec.version
            end
            nested.last << spec
          end
          groups = nested.map { |a| SpecGroup.new(a) }
          !locked_requirement ? groups : groups.select { |sg| locked_requirement.satisfied_by? sg.version }
        else
          []
        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 lib/bundler/resolver.rb, line 294
    def sort_dependencies(dependencies, activated, conflicts)
      dependencies.sort_by do |dependency|
        name = name_for(dependency)
        [
          activated.vertex_named(name).payload ? 0 : 1,
          @prereleases_cache[dependency.requirement] ? 0 : 1,
          conflicts[name] ? 0 : 1,
          activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
        ]
      end
    end

verify_gemfile_dependencies_are_found!(requirements) click to toggle source

    # File lib/bundler/resolver.rb, line 306
    def verify_gemfile_dependencies_are_found!(requirements)
      requirements.each do |requirement|
        next if requirement.name == 'bundler'
        if search_for(requirement).empty?
          if base = @base[requirement.name] and !base.empty?
            version = base.first.version
            message = "You have requested:\n"                "  #{requirement.name} #{requirement.requirement}\n\n"                "The bundle currently has #{requirement.name} locked at #{version}.\n"                "Try running `bundle update #{requirement.name}`"
          elsif requirement.source
            name = requirement.name
            versions = @source_requirements[name][name].map { |s| s.version }
            message  = "Could not find gem '#{requirement}' in #{requirement.source}.\n"
            if versions.any?
              message << "Source contains '#{name}' at: #{versions.join(', ')}"
            else
              message << "Source does not contain any versions of '#{requirement}'"
            end
          else
            message = "Could not find gem '#{requirement}' in any of the gem sources listed in your Gemfile or installed on this machine."
          end
          raise GemNotFound, message
        end
      end
    end