class Gem::RequestSet - RDoc Documentation

# class Gem::RequestSet

A RequestSet groups a request to activate a set of dependencies.

    nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6'
    pg = Gem::Dependency.new 'pg', '~> 0.14'

    set = Gem::RequestSet.new nokogiri, pg

    requests = set.resolve

    p requests.map { |r| r.full_name }
    #=> ["nokogiri-1.6.0", "mini_portile-0.5.1", "pg-0.17.0"]

### Attributes

always_install[RW]

Array of gems to install even if already installed

dependencies[R]
development[RW]
development_shallow[RW]

Set to true if you want to install only direct development dependencies.

errors[R]

Errors fetching gems during resolution.

ignore_dependencies[RW]

When true, dependency resolution is not performed, only the requested gems are installed.

prerelease[RW]

If true, allow dependencies to match prerelease gems.

remote[RW]

When false no remote sets are used for resolving gems.

soft_missing[RW]

Treat missing dependencies as silent errors

source_set[R]

The set of source gems imported via load_gemdeps.

### Public Class Methods

new(*deps) { |self| ... } click to toggle source

Creates a RequestSet for a list of Gem::Dependency objects, `deps`. You can then resolve and install the resolved list of dependencies.

    nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6'
    pg = Gem::Dependency.new 'pg', '~> 0.14'

    set = Gem::RequestSet.new nokogiri, pg

    # File lib/rubygems/request_set.rb, line 93
    def initialize *deps
      @dependencies = deps

      @always_install      = []
      @conservative        = false
      @dependency_names    = {}
      @development         = false
      @development_shallow = false
      @errors              = []
      @git_set             = nil
      @ignore_dependencies = false
      @install_dir         = Gem.dir
      @prerelease          = false
      @remote              = true
      @requests            = []
      @sets                = []
      @soft_missing        = false
      @sorted              = nil
      @specs               = nil
      @vendor_set          = nil
      @source_set          = nil

      yield self if block_given?
    end

### Public Instance Methods

gem(name, *reqs) click to toggle source

Declare that a gem of name `name` with `reqs` requirements is needed.

    # File lib/rubygems/request_set.rb, line 121
    def gem name, *reqs
      if dep = @dependency_names[name] then
        dep.requirement.concat reqs
      else
        dep = Gem::Dependency.new name, *reqs
        @dependency_names[name] = dep
        @dependencies << dep
      end
    end

import(deps) click to toggle source

Add `deps` Gem::Dependency objects to the set.

    # File lib/rubygems/request_set.rb, line 134
    def import deps
      @dependencies.concat deps
    end

install(options) { |request, installer| ... } click to toggle source

Installs gems for this RequestSet using the Gem::Installer `options`.

If a `block` is given an activation `request` and `installer` are yielded. The `installer` will be `nil` if a gem matching the request was already installed.

    # File lib/rubygems/request_set.rb, line 145
    def install options, &block # :yields: request, installer
      if dir = options[:install_dir]
        requests = install_into dir, false, options, &block
        return requests
      end

      @prerelease = options[:prerelease]

      requests = []

      sorted_requests.each do |req|
        if req.installed? then
          req.spec.spec.build_extensions

          if @always_install.none? { |spec| spec == req.spec.spec } then
            yield req, nil if block_given?
            next
          end
        end

        spec =
          begin
            req.spec.install options do |installer|
              yield req, installer if block_given?
            end
          rescue Gem::RuntimeRequirementNotMetError => e
            recent_match = req.spec.set.find_all(req.request).sort_by(&:version).reverse_each.find do |s|
              s = s.spec
              s.required_ruby_version.satisfied_by?(Gem.ruby_version) && s.required_rubygems_version.satisfied_by?(Gem.rubygems_version)
            end
            if recent_match
              suggestion = "The last version of #{req.request} to support your Ruby & RubyGems was #{recent_match.version}. Try installing it with `gem install #{recent_match.name} -v #{recent_match.version}`"
              suggestion += " and then running the current command again" unless @always_install.include?(req.spec.spec)
            else
              suggestion = "There are no versions of #{req.request} compatible with your Ruby & RubyGems"
              suggestion += ". Maybe try installing an older version of the gem you're looking for?" unless @always_install.include?(req.spec.spec)
            end
            e.suggestion = suggestion
            raise
          end

        requests << spec
      end

      return requests if options[:gemdeps]

      specs = requests.map do |request|
        case request
        when Gem::Resolver::ActivationRequest then
          request.spec.spec
        else
          request
        end
      end

      require 'rubygems/dependency_installer'
      inst = Gem::DependencyInstaller.new options
      inst.installed_gems.replace specs

      Gem.done_installing_hooks.each do |hook|
        hook.call inst, specs
      end unless Gem.done_installing_hooks.empty?

      requests
    end

install_from_gemdeps(options, &block) click to toggle source

Installs from the gem dependencies files in the `:gemdeps` option in `options`, yielding to the `block` as in install.

If `:without_groups` is given in the `options`, those groups in the gem dependencies file are not used. See Gem::Installer for other `options`.

    # File lib/rubygems/request_set.rb, line 218
    def install_from_gemdeps options, &block
      gemdeps = options[:gemdeps]

      @install_dir = options[:install_dir] || Gem.dir
      @prerelease  = options[:prerelease]
      @remote      = options[:domain] != :local
      @conservative = true if options[:conservative]

      gem_deps_api = load_gemdeps gemdeps, options[:without_groups], true

      resolve

      if options[:explain]
        puts "Gems to install:"

        sorted_requests.each do |spec|
          puts "  #{spec.full_name}"
        end

        if Gem.configuration.really_verbose
          @resolver.stats.display
        end
      else
        installed = install options, &block

        if options.fetch :lock, true then
          lockfile =
            Gem::RequestSet::Lockfile.build self, gemdeps, gem_deps_api.dependencies
          lockfile.write
        end

        installed
      end
    end

install_into(dir, force = true, options = {}) { |request, nil| ... } click to toggle source

    # File lib/rubygems/request_set.rb, line 253
    def install_into dir, force = true, options = {}
      gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir

      existing = force ? [] : specs_in(dir)
      existing.delete_if { |s| @always_install.include? s }

      dir = File.expand_path dir

      installed = []

      options[:development] = false
      options[:install_dir] = dir
      options[:only_install_dir] = true
      @prerelease = options[:prerelease]

      sorted_requests.each do |request|
        spec = request.spec

        if existing.find { |s| s.full_name == spec.full_name } then
          yield request, nil if block_given?
          next
        end

        spec.install options do |installer|
          yield request, installer if block_given?
        end

        installed << request
      end

      installed
    ensure
      ENV['GEM_HOME'] = gem_home
    end

load_gemdeps(path, without_groups = [], installing = false) click to toggle source

Load a dependency management file.

    # File lib/rubygems/request_set.rb, line 291
    def load_gemdeps path, without_groups = [], installing = false
      @git_set    = Gem::Resolver::GitSet.new
      @vendor_set = Gem::Resolver::VendorSet.new
      @source_set = Gem::Resolver::SourceSet.new

      @git_set.root_dir = @install_dir

      lock_file = "#{File.expand_path(path)}.lock".dup.untaint
      begin
        tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file lock_file
        parser = tokenizer.make_parser self, []
        parser.parse
      rescue Errno::ENOENT
      end

      gf = Gem::RequestSet::GemDependencyAPI.new self, path
      gf.installing = installing
      gf.without_groups = without_groups if without_groups
      gf.load
    end

resolve(set = Gem::Resolver::BestSet.new) click to toggle source

Resolve the requested dependencies and return an Array of Specification objects to be activated.

    # File lib/rubygems/request_set.rb, line 358
    def resolve set = Gem::Resolver::BestSet.new
      @sets << set
      @sets << @git_set
      @sets << @vendor_set
      @sets << @source_set

      set = Gem::Resolver.compose_sets(*@sets)
      set.remote = @remote
      set.prerelease = @prerelease

      resolver = Gem::Resolver.new @dependencies, set
      resolver.development         = @development
      resolver.development_shallow = @development_shallow
      resolver.ignore_dependencies = @ignore_dependencies
      resolver.soft_missing        = @soft_missing

      if @conservative
        installed_gems = {}
        Gem::Specification.find_all do |spec|
          (installed_gems[spec.name] ||= []) << spec
        end
        resolver.skip_gems = installed_gems
      end

      @resolver = resolver

      @requests = resolver.resolve

      @errors = set.errors

      @requests
    end

resolve_current() click to toggle source

Resolve the requested dependencies against the gems available via Gem.path and return an Array of Specification objects to be activated.

    # File lib/rubygems/request_set.rb, line 395
    def resolve_current
      resolve Gem::Resolver::CurrentSet.new
    end

sorted_requests() click to toggle source

    # File lib/rubygems/request_set.rb, line 399
    def sorted_requests
      @sorted ||= strongly_connected_components.flatten
    end

specs() click to toggle source

    # File lib/rubygems/request_set.rb, line 403
    def specs
      @specs ||= @requests.map { |r| r.full_spec }
    end

specs_in(dir) click to toggle source

    # File lib/rubygems/request_set.rb, line 407
    def specs_in dir
      Dir["#{dir}/specifications/*.gemspec"].map do |g|
        Gem::Specification.load g
      end
    end