class Chef::Provider::Package::Rubygems::GemEnvironment
Constants
- DEFAULT_UNINSTALLER_OPTS
Public Class Methods
Source
# File lib/chef/provider/package/rubygems.rb, line 48 def initialize(*args) super # HACK: trigger gem config load early. Otherwise it can get lazy # loaded during operations where we've set Gem.sources to an # alternate value and overwrite it with the defaults. Gem.configuration end
Public Instance Methods
Source
# File lib/chef/provider/package/rubygems.rb, line 155 def candidate_version_from_file(gem_dependency, source) spec = spec_from_file(source) if spec.satisfies_requirement?(gem_dependency) logger.trace { "found candidate gem version #{spec.version} from local gem package #{source}" } spec.version else # This is probably going to end badly... logger.warn { "gem package #{source} does not satisfy the requirements #{gem_dependency}" } nil end end
Determines the candidate version for a gem from a .gem file on disk and checks if it matches the version constraints in gem_dependency
Returns¶ ↑
Gem::Version a singular gem version object is returned if the gem
is available
nil returns nil if the gem on disk doesn’t match the
version constraints for +gem_dependency+
Source
# File lib/chef/provider/package/rubygems.rb, line 176 def candidate_version_from_remote(gem_dependency, *sources) raise NotImplementedError end
Finds the newest version that satisfies the constraints of gem_dependency
. The version is determined from the cache or a round-trip to the server as needed. The architecture and gem sources will be set before making the query.
Returns¶ ↑
Gem::Version a singular gem version object is returned if the gem
is available
nil returns nil if the gem could not be found
Source
# File lib/chef/provider/package/rubygems.rb, line 247 def dependency_installer(**opts) Gem::DependencyInstaller.new(**opts) end
Source
# File lib/chef/provider/package/rubygems.rb, line 183 def find_newest_remote_version(gem_dependency, *sources) spec, source = if Chef::Config[:rubygems_cache_enabled] # This code caches every gem on rubygems.org and uses lots of RAM available_gems = dependency_installer.find_gems_with_sources(gem_dependency) available_gems.pick_best! best_gem = available_gems.set.first best_gem && [best_gem.spec, best_gem.source] else # Use the API that 'gem install' calls which does not pull down the rubygems universe begin rs = dependency_installer.resolve_dependencies gem_dependency.name, gem_dependency.requirement rs.specs.find { |s| s.name == gem_dependency.name } # ruby-3.0.0 versions of rubygems-3.x throws NoMethodError when the dep is not found rescue Gem::UnsatisfiableDependencyError, NoMethodError nil end end version = spec && spec.version if version logger.trace { "found gem #{spec.name} version #{version} for platform #{spec.platform} from #{source}" } version else source_list = sources.compact.empty? ? "[#{Gem.sources.to_a.join(", ")}]" : "[#{sources.join(", ")}]" logger.warn { "failed to find gem #{gem_dependency} from #{source_list}" } nil end end
Find the newest gem version available from Gem.sources that satisfies the constraints of gem_dependency
Source
# File lib/chef/provider/package/rubygems.rb, line 58 def gem_paths raise NotImplementedError end
The paths where rubygems should search for installed gems. Implemented by subclasses.
Source
# File lib/chef/provider/package/rubygems.rb, line 68 def gem_source_index raise NotImplementedError end
A rubygems source index containing the list of gemspecs for all available gems in the gem installation. Implemented by subclasses
@return [Gem::SourceIndex]
Source
# File lib/chef/provider/package/rubygems.rb, line 78 def gem_specification raise NotImplementedError end
A rubygems specification object containing the list of gemspecs for all available gems in the gem installation. Implemented by subclasses
@return [Gem::Specification]
Source
# File lib/chef/provider/package/rubygems.rb, line 218 def install(gem_dependency, options = {}) with_gem_sources(*options.delete(:sources)) do with_correct_verbosity do dependency_installer(**options).install(gem_dependency) end end end
Installs a gem via the rubygems ruby API.
Options¶ ↑
:sources rubygems servers to use Other options are passed to Gem::DependencyInstaller.new
Source
# File lib/chef/provider/package/rubygems.rb, line 93 def installed_versions(gem_dep) rubygems_version = Gem::Version.new(Gem::VERSION) if rubygems_version >= Gem::Version.new("3.1") # In newer Rubygems, bundler is now a "default gem" which means # even with AlternateGemEnvironment when you try to get the # installed versions, you get the one from Chef's Ruby's default # gems. This workaround ignores default gems entirely so we see # only the installed gems. stubs = gem_specification.send(:installed_stubs, gem_specification.dirs, "#{gem_dep.name}-*.gemspec") # Filter down to only to only stubs we actually want. The name # filter is needed in case of things like `foo-*.gemspec` also # matching a gem named `foo-bar`. stubs.select! { |stub| stub.name == gem_dep.name && gem_dep.requirement.satisfied_by?(stub.version) } # This isn't sorting before returning because the only code that # uses this method calls `max_by` so it doesn't need to be sorted. stubs else # >= rubygems 1.8 behavior gem_specification.find_all_by_name(gem_dep.name, gem_dep.requirement) end end
Lists the installed versions of gem_name
, constrained by the version spec in gem_dep
@param gem_dep [Gem::Dependency] the version specification that constrains
which gems are used.
@return [Array<Gem::Specification>] an array of Gem::Specification objects
Source
# File lib/chef/provider/package/rubygems.rb, line 82 def rubygems_version raise NotImplementedError end
Source
# File lib/chef/provider/package/rubygems.rb, line 135 def spec_from_file(file) if defined?(Gem::Format) && Gem::Package.respond_to?(:open) Gem::Format.from_file_by_path(file).spec else # Gem::Package is getting defined as an empty class as of bundler 2.5.23 # and therefore won't autoload # ["bundler-2.5.23/lib/bundler/rubygems_ext.rb", 457] require "rubygems/package" if Gem::Package.method(:new).source_location.nil? Gem::Package.new(file).spec end end
Extracts the gemspec from a (on-disk) gem package.
Returns¶ ↑
Gem::Specification
Source
# File lib/chef/provider/package/rubygems.rb, line 232 def uninstall(gem_name, gem_version = nil, opts = {}) gem_version ? opts[:version] = gem_version : opts[:all] = true with_correct_verbosity do uninstaller(gem_name, **opts).uninstall end end
Uninstall the gem gem_name
via the rubygems ruby API. If gem_version
is provided, only that version will be uninstalled. Otherwise, all versions are uninstalled.
Options¶ ↑
Options are passed to Gem::Uninstaller.new
Source
# File lib/chef/provider/package/rubygems.rb, line 251 def uninstaller(gem_name, **opts) Gem::Uninstaller.new(gem_name, **DEFAULT_UNINSTALLER_OPTS.merge(opts)) end
Source
# File lib/chef/provider/package/rubygems.rb, line 242 def with_correct_verbosity Gem::DefaultUserInteraction.ui = logger.trace? ? Gem::ConsoleUI.new : Gem::SilentUI.new yield end
Set rubygems’ user interaction to ConsoleUI or SilentUI depending on our current debug level
Source
# File lib/chef/provider/package/rubygems.rb, line 118 def with_gem_sources(*sources) sources.compact! original_sources = Gem.sources Gem.sources = sources unless sources.empty? yield ensure Gem.sources = original_sources end
Yields to the provided block with rubygems’ source list set to the list provided. Always resets the list when the block returns or raises an exception.
Private Instance Methods
Source
# File lib/chef/provider/package/rubygems.rb, line 257 def logger Chef::Log.with_child({ subsystem: "gem_installer_environment" }) end