Class: Gem::RequestSet
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
self,
TSort
|
|
Inherits: | Object |
Defined in: | lib/rubygems/request_set.rb |
Overview
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"]
Class Method Summary
-
.new(*deps) {|_self| ... } ⇒ RequestSet
constructor
Creates a
RequestSet
for a list ofDependency
objects,deps
.
Instance Attribute Summary
-
#always_install
rw
Array of gems to install even if already installed.
- #dependencies readonly
- #development rw
-
#development_shallow
rw
Set to true if you want to install only direct development dependencies.
-
#errors
readonly
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
readonly
The set of source gems imported via load_gemdeps.
-
#git_set
readonly
Internal use only
The set of git gems imported via load_gemdeps.
- #install_dir readonly Internal use only
- #resolver readonly Internal use only
-
#sets
readonly
Internal use only
Sets used for resolution.
-
#vendor_set
readonly
Internal use only
The set of vendor gems imported via load_gemdeps.
Instance Method Summary
-
#gem(name, *reqs)
Declare that a gem of name
name
withreqs
requirements is needed. -
#import(deps)
Add
deps
Dependency
objects to the set. -
#install(options, &block)
Installs gems for this
RequestSet
using theInstaller
options
. -
#install_from_gemdeps(options, &block)
Installs from the gem dependencies files in the
:gemdeps
option inoptions
, yielding to theblock
as in #install. -
#install_hooks(requests, options)
Call hooks on installed gems.
- #install_into(dir, force = true, options = {})
-
#load_gemdeps(path, without_groups = [], installing = false)
Load a dependency management file.
-
#resolve(set = Gem::Resolver::BestSet.new)
Resolve the requested dependencies and return an Array of
Specification
objects to be activated. -
#resolve_current
Resolve the requested dependencies against the gems available via path and return an Array of
Specification
objects to be activated. - #sorted_requests
- #specs
- #specs_in(dir)
- #pretty_print(q) Internal use only
- #tsort_each_child(node) Internal use only
- #tsort_each_node(&block) Internal use only
Constructor Details
.new(*deps) {|_self| ... } ⇒ RequestSet
Creates a RequestSet
for a list of 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 94
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
Instance Attribute Details
#always_install (rw)
Array of gems to install even if already installed
# File 'lib/rubygems/request_set.rb', line 24
attr_accessor :always_install
#dependencies (readonly)
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 26
attr_reader :dependencies
#development (rw)
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 28
attr_accessor :development
#development_shallow (rw)
Set to true if you want to install only direct development dependencies.
# File 'lib/rubygems/request_set.rb', line 38
attr_accessor :development_shallow
#errors (readonly)
Errors fetching gems during resolution.
# File 'lib/rubygems/request_set.rb', line 33
attr_reader :errors
#git_set (readonly)
The set of git gems imported via load_gemdeps.
# File 'lib/rubygems/request_set.rb', line 43
attr_reader :git_set # :nodoc:
#ignore_dependencies (rw)
When true, dependency resolution is not performed, only the requested gems are installed.
# File 'lib/rubygems/request_set.rb', line 49
attr_accessor :ignore_dependencies
#install_dir (readonly)
# File 'lib/rubygems/request_set.rb', line 51
attr_reader :install_dir # :nodoc:
#prerelease (rw)
If true, allow dependencies to match prerelease gems.
# File 'lib/rubygems/request_set.rb', line 56
attr_accessor :prerelease
#remote (rw)
When false no remote sets are used for resolving gems.
# File 'lib/rubygems/request_set.rb', line 61
attr_accessor :remote
#resolver (readonly)
# File 'lib/rubygems/request_set.rb', line 63
attr_reader :resolver # :nodoc:
#sets (readonly)
Sets used for resolution
# File 'lib/rubygems/request_set.rb', line 68
attr_reader :sets # :nodoc:
#soft_missing (rw)
Treat missing dependencies as silent errors
# File 'lib/rubygems/request_set.rb', line 73
attr_accessor :soft_missing
#source_set (readonly)
The set of source gems imported via load_gemdeps.
# File 'lib/rubygems/request_set.rb', line 83
attr_reader :source_set
#vendor_set (readonly)
The set of vendor gems imported via load_gemdeps.
# File 'lib/rubygems/request_set.rb', line 78
attr_reader :vendor_set # :nodoc:
Instance Method Details
#gem(name, *reqs)
Declare that a gem of name name
with reqs
requirements is needed.
# File 'lib/rubygems/request_set.rb', line 122
def gem(name, *reqs) if dep = @dependency_names[name] dep.requirement.concat reqs else dep = Gem::Dependency.new name, *reqs @dependency_names[name] = dep @dependencies << dep end end
#import(deps)
Add deps
Dependency
objects to the set.
# File 'lib/rubygems/request_set.rb', line 135
def import(deps) @dependencies.concat deps end
#install(options, &block)
Installs gems for this RequestSet
using the 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 146
def install(, &block) # :yields: request, installer if dir = [:install_dir] requests = install_into dir, false, , &block return requests end @prerelease = [:prerelease] requests = [] download_queue = Queue.new # Create a thread-safe list of gems to download sorted_requests.each do |req| download_queue << req end # Create N threads in a pool, have them download all the gems threads = Gem.configuration.concurrent_downloads.times.map do # When a thread pops this item, it knows to stop running. The symbol # is queued here so that there will be one symbol per thread. download_queue << :stop Thread.new do # The pop method will block waiting for items, so the only way # to stop a thread from running is to provide a final item that # means the thread should stop. while req = download_queue.pop break if req == :stop req.spec.download unless req.installed? end end end # Wait for all the downloads to finish before continuing threads.each(&:value) # Install requested gems after they have been downloaded sorted_requests.each do |req| if req.installed? req.spec.spec.build_extensions if @always_install.none? { |spec| spec == req.spec.spec } yield req, nil if block_given? next end end spec = begin req.spec.install 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) && Gem::Platform.installable?(s) 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 [:gemdeps] install_hooks requests, requests end
#install_from_gemdeps(options, &block)
# File 'lib/rubygems/request_set.rb', line 233
def install_from_gemdeps(, &block) gemdeps = [:gemdeps] @install_dir = [:install_dir] || Gem.dir @prerelease = [:prerelease] @remote = [:domain] != :local @conservative = true if [:conservative] gem_deps_api = load_gemdeps gemdeps, [:without_groups], true resolve if [: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 , &block if .fetch :lock, true lockfile = Gem::RequestSet::Lockfile.build self, gemdeps, gem_deps_api.dependencies lockfile.write end installed end end
#install_hooks(requests, options)
Call hooks on installed gems
# File 'lib/rubygems/request_set.rb', line 308
def install_hooks(requests, ) 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 inst.installed_gems.replace specs Gem.done_installing_hooks.each do |hook| hook.call inst, specs end unless Gem.done_installing_hooks.empty? end
#install_into(dir, force = true, options = {})
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 268
def install_into(dir, force = true, = {}) gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir existing = force ? [] : specs_in(dir) existing.delete_if { |s| @always_install.include? s } dir = File. dir installed = [] [:development] = false [:install_dir] = dir [:only_install_dir] = true @prerelease = [:prerelease] sorted_requests.each do |request| spec = request.spec if existing.find { |s| s.full_name == spec.full_name } yield request, nil if block_given? next end spec.install do |installer| yield request, installer if block_given? end installed << request end install_hooks installed, installed ensure ENV['GEM_HOME'] = gem_home end
#load_gemdeps(path, without_groups = [], installing = false)
Load a dependency management file.
# File 'lib/rubygems/request_set.rb', line 330
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. (path)}.lock".dup.tap(&Gem::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
#pretty_print(q)
# File 'lib/rubygems/request_set.rb', line 351
def pretty_print(q) # :nodoc: q.group 2, '[RequestSet:', ']' do q.breakable if @remote q.text 'remote' q.breakable end if @prerelease q.text 'prerelease' q.breakable end if @development_shallow q.text 'shallow development' q.breakable elsif @development q.text 'development' q.breakable end if @soft_missing q.text 'soft missing' end q.group 2, '[dependencies:', ']' do q.breakable @dependencies.map do |dep| q.text dep.to_s q.breakable end end q.breakable q.text 'sets:' q.breakable q.pp @sets.map { |set| set.class } end end
#resolve(set = Gem::Resolver::BestSet.new)
Resolve the requested dependencies and return an Array of Specification
objects to be activated.
# File 'lib/rubygems/request_set.rb', line 397
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
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 434
def resolve_current resolve Gem::Resolver::CurrentSet.new end
#sorted_requests
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 438
def sorted_requests @sorted ||= strongly_connected_components.flatten end
#specs
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 442
def specs @specs ||= @requests.map { |r| r.full_spec } end
#specs_in(dir)
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 446
def specs_in(dir) Gem::Util.glob_files_in_dir("*.gemspec", File.join(dir, "specifications")).map do |g| Gem::Specification.load g end end
#tsort_each_child(node)
# File 'lib/rubygems/request_set.rb', line 456
def tsort_each_child(node) # :nodoc: node.spec.dependencies.each do |dep| next if dep.type == :development and not @development match = @requests.find do |r| dep.match? r.spec.name, r.spec.version, @prerelease end unless match next if dep.type == :development and @development_shallow next if @soft_missing raise Gem::DependencyError, "Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})" end yield match end end
#tsort_each_node(&block)
# File 'lib/rubygems/request_set.rb', line 452
def tsort_each_node(&block) # :nodoc: @requests.each(&block) end