Class: Gem::DependencyInstaller
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
Deprecate
|
|
Instance Chain:
|
|
Inherits: | Object |
Defined in: | lib/rubygems/dependency_installer.rb |
Overview
Installs a gem along with all its dependencies from local and remote gems.
Constant Summary
-
DEFAULT_OPTIONS =
Internal use only
# File 'lib/rubygems/dependency_installer.rb', line 19{ # :nodoc: :env_shebang => false, :document => %w[ri], :domain => :both, # HACK dup :force => false, :format_executable => false, # HACK dup :ignore_dependencies => false, :prerelease => false, :security_policy => nil, # HACK NoSecurity requires OpenSSL. AlmostNo? Low? :wrappers => true, :build_args => nil, :build_docs_in_background => false, :install_as_default => false }.freeze
Class Method Summary
-
.new(options = {}) ⇒ DependencyInstaller
constructor
Creates a new installer instance.
Deprecate - Extended
deprecate | Simple deprecation method that deprecates |
skip_during | Temporarily turn off warnings. |
Instance Attribute Summary
-
#consider_local? ⇒ Boolean
readonly
Indicated, based on the requested domain, if local gems should be considered.
-
#consider_remote? ⇒ Boolean
readonly
Indicated, based on the requested domain, if remote gems should be considered.
-
#document
readonly
Documentation types.
-
#errors
readonly
Errors from SpecFetcher while searching for remote specifications.
- #installed_gems readonly
- #gems_to_install readonly Internal use only
DefaultUserInteraction - Included
Instance Method Summary
-
#find_spec_by_name_and_version(gem_name, version = Gem::Requirement.default, prerelease = false)
Finds a spec and the source_uri it came from for gem
gem_name
andversion
. -
#install(dep_or_name, version = Gem::Requirement.default)
Installs the gem
dep_or_name
and all its dependencies. - #add_found_dependencies(to_do, dependency_list) Internal use only
-
#available_set_for(dep_or_name, version)
Internal use only
Creates an AvailableSet to install from based on
dep_or_name
andversion
-
#find_gems_with_sources(dep, best_only = false)
Internal use only
Returns a list of pairs of gemspecs and source_uris that match Dependency
dep
from both local (Dir.pwd) and remote (Gem.sources) sources. -
#gather_dependencies
Internal use only
Gathers all dependencies necessary for the installation from local and remote sources unless the ignore_dependencies was given.
- #in_background(what) Internal use only
- #install_development_deps Internal use only
- #resolve_dependencies(dep_or_name, version) Internal use only
UserInteraction - Included
#alert | Displays an alert |
#alert_error | Displays an error |
#alert_warning | Displays a warning |
#ask | Asks a |
#ask_for_password | Asks for a password with a |
#ask_yes_no | Asks a yes or no |
#choose_from_list | Asks the user to answer |
#say | Displays the given |
#terminate_interaction | Terminates the RubyGems process with the given |
#verbose | Calls |
DefaultUserInteraction - Included
Text - Included
#clean_text | Remove any non-printable characters and make the text suitable for printing. |
#format_text | Wraps |
#levenshtein_distance | This code is based directly on the Text gem implementation Returns a value representing the “cost” of transforming str1 into str2. |
#truncate_text, #min3 |
Constructor Details
.new(options = {}) ⇒ DependencyInstaller
Creates a new installer instance.
Options are:
- :cache_dir
-
Alternate repository path to store
.gem
files in. - :domain
-
:local
,:remote
, or:both
.:local
only searches gems in the current directory. :remote searches only gems in Gem::sources. :both searches both. - :env_shebang
-
See Installer.new.
- :force
-
See Installer#install.
- :format_executable
-
See
Gem::Installer#initialize
. - :ignore_dependencies
-
Don't install any dependencies.
- :install_dir
-
See Installer#install.
- :prerelease
-
Allow prerelease versions. See #install.
- :security_policy
-
See Installer.new and Security.
- :user_install
-
See Installer.new
- :wrappers
-
See Installer.new
- :build_args
-
See Installer.new
# File 'lib/rubygems/dependency_installer.rb', line 77
def initialize = {} @only_install_dir = !! [:install_dir] @install_dir = [:install_dir] || Gem.dir @build_root = [:build_root] = DEFAULT_OPTIONS.merge @bin_dir = [:bin_dir] @dev_shallow = [:dev_shallow] @development = [:development] @document = [:document] @domain = [:domain] @env_shebang = [:env_shebang] @force = [:force] @format_executable = [:format_executable] @ignore_dependencies = [:ignore_dependencies] @prerelease = [:prerelease] @security_policy = [:security_policy] @user_install = [:user_install] @wrappers = [:wrappers] @build_args = [:build_args] @build_docs_in_background = [:build_docs_in_background] @install_as_default = [:install_as_default] # Indicates that we should not try to update any deps unless # we absolutely must. @minimal_deps = [:minimal_deps] @available = nil @installed_gems = [] @toplevel_specs = nil @cache_dir = [:cache_dir] || @install_dir @errors = [] end
Instance Attribute Details
#consider_local? ⇒ Boolean
(readonly)
Indicated, based on the requested domain, if local gems should be considered.
# File 'lib/rubygems/dependency_installer.rb', line 187
def consider_local? @domain == :both or @domain == :local end
#consider_remote? ⇒ Boolean
(readonly)
Indicated, based on the requested domain, if remote gems should be considered.
# File 'lib/rubygems/dependency_installer.rb', line 195
def consider_remote? @domain == :both or @domain == :remote end
#document (readonly)
Documentation types. For use by the Gem.done_installing hook
# File 'lib/rubygems/dependency_installer.rb', line 37
attr_reader :document
#errors (readonly)
Errors from SpecFetcher while searching for remote specifications
# File 'lib/rubygems/dependency_installer.rb', line 42
attr_reader :errors
#gems_to_install (readonly)
# File 'lib/rubygems/dependency_installer.rb', line 48
attr_reader :gems_to_install # :nodoc:
#installed_gems (readonly)
[ GitHub ]# File 'lib/rubygems/dependency_installer.rb', line 56
attr_reader :installed_gems
Instance Method Details
#add_found_dependencies(to_do, dependency_list)
# File 'lib/rubygems/dependency_installer.rb', line 118
def add_found_dependencies to_do, dependency_list # :nodoc: seen = {} dependencies = Hash.new { |h, name| h[name] = Gem::Dependency.new name } until to_do.empty? do spec = to_do.shift # HACK why is spec nil? next if spec.nil? or seen[spec.name] seen[spec.name] = true deps = spec.runtime_dependencies if @development if @dev_shallow if @toplevel_specs.include? spec.full_name deps |= spec.development_dependencies end else deps |= spec.development_dependencies end end deps.each do |dep| dependencies[dep.name] = dependencies[dep.name].merge dep if @minimal_deps next if Gem::Specification.any? do |installed_spec| dep.name == installed_spec.name and dep.requirement.satisfied_by? installed_spec.version end end results = find_gems_with_sources(dep) results.sorted.each do |t| to_do.push t.spec end results.remove_installed! dep @available << results results.inject_into_list dependency_list end end dependency_list.remove_specs_unsatisfied_by dependencies end
#available_set_for(dep_or_name, version)
Creates an AvailableSet to install from based on dep_or_name
and version
# File 'lib/rubygems/dependency_installer.rb', line 171
def available_set_for dep_or_name, version # :nodoc: if String === dep_or_name then find_spec_by_name_and_version dep_or_name, version, @prerelease else dep = dep_or_name.dup dep.prerelease = @prerelease @available = find_gems_with_sources dep end @available.pick_best! end
#find_gems_with_sources(dep, best_only = false)
Returns a list of pairs of gemspecs and source_uris that match Dependency dep
from both local (Dir.pwd) and remote (Gem.sources) sources. Gems are sorted with newer gems preferred over older gems, and local gems preferred over remote gems.
# File 'lib/rubygems/dependency_installer.rb', line 205
def find_gems_with_sources dep, best_only=false # :nodoc: set = Gem::AvailableSet.new if consider_local? sl = Gem::Source::Local.new if spec = sl.find_gem(dep.name) if dep.matches_spec? spec set.add spec, sl end end end if consider_remote? begin # TODO this is pulled from #spec_for_dependency to allow # us to filter tuples before fetching specs. # tuples, errors = Gem::SpecFetcher.fetcher.search_for_dependency dep if best_only && !tuples.empty? tuples.sort! do |a,b| if b[0].version == a[0].version if b[0].platform != Gem::Platform::RUBY 1 else -1 end else b[0].version <=> a[0].version end end tuples = [tuples.first] end specs = [] tuples.each do |tup, source| begin spec = source.fetch_spec(tup) rescue Gem::RemoteFetcher::FetchError => e errors << Gem::SourceFetchProblem.new(source, e) else specs << [spec, source] end end if @errors @errors += errors else @errors = errors end set << specs rescue Gem::RemoteFetcher::FetchError => e # FIX if there is a problem talking to the network, we either need to always tell # the user (no really_verbose) or fail hard, not silently tell them that we just # couldn't find their requested gem. verbose do "Error fetching remote data:\t\t#{e.}\n" \ "Falling back to local-only install" end @domain = :local end end set end
#find_spec_by_name_and_version(gem_name, version = Gem::Requirement.default, prerelease = false)
Finds a spec and the source_uri it came from for gem gem_name
and version
. Returns an Array of specs and sources required for installation of the gem.
# File 'lib/rubygems/dependency_installer.rb', line 279
def find_spec_by_name_and_version gem_name, version = Gem::Requirement.default, prerelease = false set = Gem::AvailableSet.new if consider_local? if gem_name =~ /\.gem$/ and File.file? gem_name then src = Gem::Source::SpecificFile.new(gem_name) set.add src.spec, src elsif gem_name =~ /\.gem$/ then Dir[gem_name].each do |name| begin src = Gem::Source::SpecificFile.new name set.add src.spec, src rescue Gem::Package::FormatError end end else local = Gem::Source::Local.new if s = local.find_gem(gem_name, version) set.add s, local end end end if set.empty? dep = Gem::Dependency.new gem_name, version dep.prerelease = true if prerelease set = find_gems_with_sources(dep, true) set.match_platform! end if set.empty? raise Gem::SpecificGemNotFoundException.new(gem_name, version, @errors) end @available = set end
#gather_dependencies
Gathers all dependencies necessary for the installation from local and remote sources unless the ignore_dependencies was given.
# File 'lib/rubygems/dependency_installer.rb', line 326
def gather_dependencies # :nodoc: specs = @available.all_specs # these gems were listed by the user, always install them keep_names = specs.map { |spec| spec.full_name } if @dev_shallow @toplevel_specs = keep_names end dependency_list = Gem::DependencyList.new @development dependency_list.add(*specs) to_do = specs.dup add_found_dependencies to_do, dependency_list unless @ignore_dependencies # REFACTOR maybe abstract away using Gem::Specification.include? so # that this isn't dependent only on the currently installed gems dependency_list.specs.reject! { |spec| not keep_names.include?(spec.full_name) and Gem::Specification.include?(spec) } unless dependency_list.ok? or @ignore_dependencies or @force then reason = dependency_list.why_not_ok?.map { |k,v| "#{k} requires #{v.join(", ")}" }.join("; ") raise Gem::DependencyError, "Unable to resolve dependencies: #{reason}" end @gems_to_install = dependency_list.dependency_order.reverse end
#in_background(what)
# File 'lib/rubygems/dependency_installer.rb', line 358
def in_background what # :nodoc: fork_happened = false if @build_docs_in_background and Process.respond_to?(:fork) begin Process.fork do yield end fork_happened = true say "#{what} in a background process." rescue NotImplementedError end end yield unless fork_happened end
#install(dep_or_name, version = Gem::Requirement.default)
Installs the gem dep_or_name
and all its dependencies. Returns an Array of installed gem specifications.
If the :prerelease
option is set and there is a prerelease for dep_or_name
the prerelease version will be installed.
Unless explicitly specified as a prerelease dependency, prerelease gems that dep_or_name
depend on will not be installed.
If c-1.a depends on b-1 and a-1.a and there is a gem b-1.a available then c-1.a, b-1 and a-1.a will be installed. b-1.a will need to be installed separately.
# File 'lib/rubygems/dependency_installer.rb', line 387
def install dep_or_name, version = Gem::Requirement.default request_set = resolve_dependencies dep_or_name, version @installed_gems = [] = { :bin_dir => @bin_dir, :build_args => @build_args, :document => @document, :env_shebang => @env_shebang, :force => @force, :format_executable => @format_executable, :ignore_dependencies => @ignore_dependencies, :prerelease => @prerelease, :security_policy => @security_policy, :user_install => @user_install, :wrappers => @wrappers, :build_root => @build_root, :install_as_default => @install_as_default } [:install_dir] = @install_dir if @only_install_dir request_set.install do |_, installer| @installed_gems << installer.spec if installer end @installed_gems.sort! # Since this is currently only called for docs, we can be lazy and just say # it's documentation. Ideally the hook adder could decide whether to be in # the background or not, and what to call it. in_background "Installing documentation" do Gem.done_installing_hooks.each do |hook| hook.call self, @installed_gems end end unless Gem.done_installing_hooks.empty? @installed_gems end
#install_development_deps
# File 'lib/rubygems/dependency_installer.rb', line 427
def install_development_deps # :nodoc: if @development and @dev_shallow then :shallow elsif @development then :all else :none end end
#resolve_dependencies(dep_or_name, version)
# File 'lib/rubygems/dependency_installer.rb', line 437
def resolve_dependencies dep_or_name, version # :nodoc: request_set = Gem::RequestSet.new request_set.development = @development request_set.development_shallow = @dev_shallow request_set.soft_missing = @force request_set.prerelease = @prerelease request_set.remote = false unless consider_remote? installer_set = Gem::Resolver::InstallerSet.new @domain installer_set.ignore_installed = @only_install_dir if consider_local? if dep_or_name =~ /\.gem$/ and File.file? dep_or_name then src = Gem::Source::SpecificFile.new dep_or_name installer_set.add_local dep_or_name, src.spec, src version = src.spec.version if version == Gem::Requirement.default elsif dep_or_name =~ /\.gem$/ then Dir[dep_or_name].each do |name| begin src = Gem::Source::SpecificFile.new name installer_set.add_local dep_or_name, src.spec, src rescue Gem::Package::FormatError end end # else This is a dependency. InstallerSet handles this case end end dependency = if spec = installer_set.local?(dep_or_name) then Gem::Dependency.new spec.name, version elsif String === dep_or_name then Gem::Dependency.new dep_or_name, version else dep_or_name end dependency.prerelease = @prerelease request_set.import [dependency] installer_set.add_always_install dependency request_set.always_install = installer_set.always_install if @ignore_dependencies then installer_set.ignore_dependencies = true request_set.ignore_dependencies = true request_set.soft_missing = true end request_set.resolve installer_set @errors.concat request_set.errors request_set end