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
TSort
- Included
#each_strongly_connected_component | The iterator version of the |
#each_strongly_connected_component_from | Iterates over strongly connected component in the subgraph reachable from node. |
#strongly_connected_components | Returns strongly connected components as an array of arrays of nodes. |
#tsort | Returns a topologically sorted array of nodes. |
#tsort_each | The iterator version of the |
#tsort_each_child | Should be implemented by a extended class. |
#tsort_each_node | Should be implemented by a extended class. |
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 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
Instance Attribute Details
#always_install (rw)
Array of gems to install even if already installed
# File 'lib/rubygems/request_set.rb', line 23
attr_accessor :always_install
#dependencies (readonly)
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 25
attr_reader :dependencies
#development (rw)
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 27
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 37
attr_accessor :development_shallow
#errors (readonly)
Errors fetching gems during resolution.
# File 'lib/rubygems/request_set.rb', line 32
attr_reader :errors
#git_set (readonly)
The set of git gems imported via load_gemdeps.
# File 'lib/rubygems/request_set.rb', line 42
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 48
attr_accessor :ignore_dependencies
#install_dir (readonly)
# File 'lib/rubygems/request_set.rb', line 50
attr_reader :install_dir # :nodoc:
#prerelease (rw)
If true, allow dependencies to match prerelease gems.
# File 'lib/rubygems/request_set.rb', line 55
attr_accessor :prerelease
#remote (rw)
When false no remote sets are used for resolving gems.
# File 'lib/rubygems/request_set.rb', line 60
attr_accessor :remote
#resolver (readonly)
# File 'lib/rubygems/request_set.rb', line 62
attr_reader :resolver # :nodoc:
#sets (readonly)
Sets used for resolution
# File 'lib/rubygems/request_set.rb', line 67
attr_reader :sets # :nodoc:
#soft_missing (rw)
Treat missing dependencies as silent errors
# File 'lib/rubygems/request_set.rb', line 72
attr_accessor :soft_missing
#source_set (readonly)
The set of source gems imported via load_gemdeps.
# File 'lib/rubygems/request_set.rb', line 82
attr_reader :source_set
#vendor_set (readonly)
The set of vendor gems imported via load_gemdeps.
# File 'lib/rubygems/request_set.rb', line 77
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 121
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 134
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 145
def install(, &block) # :yields: request, installer if dir = [:install_dir] requests = install_into dir, false, , &block return requests end @prerelease = [:prerelease] requests = [] download_queue = Thread::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 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) 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 221
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 296
def install_hooks(requests, ) specs = requests.map do |request| case request when Gem::Resolver::ActivationRequest then request.spec.spec else request end end require_relative "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 256
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 318
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 339
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 385
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 422
def resolve_current resolve Gem::Resolver::CurrentSet.new end
#sorted_requests
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 426
def sorted_requests @sorted ||= strongly_connected_components.flatten end
#specs
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 430
def specs @specs ||= @requests.map {|r| r.full_spec } end
#specs_in(dir)
[ GitHub ]# File 'lib/rubygems/request_set.rb', line 434
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 444
def tsort_each_child(node) # :nodoc: node.spec.dependencies.each do |dep| next if dep.type == :development && !@development match = @requests.find do |r| dep.match? r.spec.name, r.spec.version, r.spec.is_a?(Gem::Resolver::InstalledSpecification) || @prerelease end unless match next if dep.type == :development && @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 440
def tsort_each_node(&block) # :nodoc: @requests.each(&block) end