class Chef::Provider::Package::Rubygems::GemEnvironment
Constants
- DEFAULT_UNINSTALLER_OPTS
Public Class Methods
# 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
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+
# File lib/chef/provider/package/rubygems.rb, line 151 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
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
# File lib/chef/provider/package/rubygems.rb, line 172 def candidate_version_from_remote(gem_dependency, *sources) raise NotImplementedError end
# File lib/chef/provider/package/rubygems.rb, line 243 def dependency_installer(opts = {}) Gem::DependencyInstaller.new(opts) end
Find the newest gem version available from Gem.sources that satisfies the constraints of gem_dependency
# File lib/chef/provider/package/rubygems.rb, line 179 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
The paths where rubygems should search for installed gems. Implemented by subclasses.
# File lib/chef/provider/package/rubygems.rb, line 58 def gem_paths 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]
# File lib/chef/provider/package/rubygems.rb, line 68 def gem_source_index 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]
# File lib/chef/provider/package/rubygems.rb, line 78 def gem_specification raise NotImplementedError end
Installs a gem via the rubygems ruby API.
Options¶ ↑
:sources rubygems servers to use Other options are passed to Gem::DependencyInstaller.new
# File lib/chef/provider/package/rubygems.rb, line 214 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
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
# 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("2.7") # 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
# File lib/chef/provider/package/rubygems.rb, line 82 def rubygems_version raise NotImplementedError end
Extracts the gemspec from a (on-disk) gem package.
Returns¶ ↑
Gem::Specification
# 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.new(file).spec 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
# File lib/chef/provider/package/rubygems.rb, line 228 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
# File lib/chef/provider/package/rubygems.rb, line 247 def uninstaller(gem_name, opts = {}) Gem::Uninstaller.new(gem_name, DEFAULT_UNINSTALLER_OPTS.merge(opts)) end
Set rubygems' user interaction to ConsoleUI or SilentUI depending on our current debug level
# File lib/chef/provider/package/rubygems.rb, line 238 def with_correct_verbosity Gem::DefaultUserInteraction.ui = logger.trace? ? Gem::ConsoleUI.new : Gem::SilentUI.new yield 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.
# 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
Private Instance Methods
# File lib/chef/provider/package/rubygems.rb, line 253 def logger Chef::Log.with_child({ subsystem: "gem_installer_environment" }) end