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
Array of gems to install even if already installed
Set to true if you want to install only direct development dependencies.
Errors fetching gems during resolution.
When true, dependency resolution is not performed, only the requested gems are installed.
If true, allow dependencies to match prerelease gems.
When false no remote sets are used for resolving gems.
Treat missing dependencies as silent errors
The set of source gems imported via load_gemdeps.
Public Class Methods
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
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
Add deps
Gem::Dependency objects
to the set.
# File lib/rubygems/request_set.rb, line 134 def import deps @dependencies.concat deps end
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
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
# 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 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 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 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
# File lib/rubygems/request_set.rb, line 399 def sorted_requests @sorted ||= strongly_connected_components.flatten end
# File lib/rubygems/request_set.rb, line 403 def specs @specs ||= @requests.map { |r| r.full_spec } end
# 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