Class: Chef::Provider::Package::Rubygems::GemEnvironment
- Inherits:
-
Object
- Object
- Chef::Provider::Package::Rubygems::GemEnvironment
- Defined in:
- lib/chef/provider/package/rubygems.rb
Direct Known Subclasses
Constant Summary collapse
- DEFAULT_UNINSTALLER_OPTS =
{ ignore: true, executables: true }.freeze
Instance Method Summary collapse
-
#candidate_version_from_file(gem_dependency, source) ⇒ Object
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 forgem_dependency
. -
#candidate_version_from_remote(gem_dependency, *sources) ⇒ Object
Finds the newest version that satisfies the constraints of
gem_dependency
. - #dependency_installer(**opts) ⇒ Object
-
#find_newest_remote_version(gem_dependency, *sources) ⇒ Object
Find the newest gem version available from Gem.sources that satisfies the constraints of
gem_dependency
. -
#gem_paths ⇒ Object
The paths where rubygems should search for installed gems.
-
#gem_source_index ⇒ Gem::SourceIndex
A rubygems source index containing the list of gemspecs for all available gems in the gem installation.
-
#gem_specification ⇒ Gem::Specification
A rubygems specification object containing the list of gemspecs for all available gems in the gem installation.
-
#initialize(*args) ⇒ GemEnvironment
constructor
A new instance of GemEnvironment.
-
#install(gem_dependency, options = {}) ⇒ Object
Installs a gem via the rubygems ruby API.
-
#installed_versions(gem_dep) ⇒ Array<Gem::Specification>
Lists the installed versions of
gem_name
, constrained by the version spec ingem_dep
. - #rubygems_version ⇒ Object
-
#spec_from_file(file) ⇒ Object
Extracts the gemspec from a (on-disk) gem package.
-
#uninstall(gem_name, gem_version = nil, opts = {}) ⇒ Object
Uninstall the gem
gem_name
via the rubygems ruby API. - #uninstaller(gem_name, **opts) ⇒ Object
-
#with_correct_verbosity ⇒ Object
Set rubygems’ user interaction to ConsoleUI or SilentUI depending on our current debug level.
-
#with_gem_sources(*sources) ⇒ Object
Yields to the provided block with rubygems’ source list set to the list provided.
Constructor Details
#initialize(*args) ⇒ GemEnvironment
Returns a new instance of GemEnvironment.
48 49 50 51 52 53 54 |
# 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 |
Instance Method Details
#candidate_version_from_file(gem_dependency, source) ⇒ Object
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+
155 156 157 158 159 160 161 162 163 164 165 |
# 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 |
#candidate_version_from_remote(gem_dependency, *sources) ⇒ Object
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
176 177 178 |
# File 'lib/chef/provider/package/rubygems.rb', line 176 def candidate_version_from_remote(gem_dependency, *sources) raise NotImplementedError end |
#dependency_installer(**opts) ⇒ Object
247 248 249 |
# File 'lib/chef/provider/package/rubygems.rb', line 247 def dependency_installer(**opts) Gem::DependencyInstaller.new(**opts) end |
#find_newest_remote_version(gem_dependency, *sources) ⇒ Object
Find the newest gem version available from Gem.sources that satisfies the constraints of gem_dependency
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# 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 |
#gem_paths ⇒ Object
The paths where rubygems should search for installed gems. Implemented by subclasses.
58 59 60 |
# File 'lib/chef/provider/package/rubygems.rb', line 58 def gem_paths raise NotImplementedError end |
#gem_source_index ⇒ Gem::SourceIndex
A rubygems source index containing the list of gemspecs for all available gems in the gem installation. Implemented by subclasses
68 69 70 |
# File 'lib/chef/provider/package/rubygems.rb', line 68 def gem_source_index raise NotImplementedError end |
#gem_specification ⇒ Gem::Specification
A rubygems specification object containing the list of gemspecs for all available gems in the gem installation. Implemented by subclasses
78 79 80 |
# File 'lib/chef/provider/package/rubygems.rb', line 78 def gem_specification raise NotImplementedError end |
#install(gem_dependency, options = {}) ⇒ Object
Installs a gem via the rubygems ruby API.
Options
:sources rubygems servers to use Other options are passed to Gem::DependencyInstaller.new
218 219 220 221 222 223 224 |
# File 'lib/chef/provider/package/rubygems.rb', line 218 def install(gem_dependency, = {}) with_gem_sources(*.delete(:sources)) do with_correct_verbosity do dependency_installer(**).install(gem_dependency) end end end |
#installed_versions(gem_dep) ⇒ Array<Gem::Specification>
Lists the installed versions of gem_name
, constrained by the version spec in gem_dep
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# 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 |
#rubygems_version ⇒ Object
82 83 84 |
# File 'lib/chef/provider/package/rubygems.rb', line 82 def rubygems_version raise NotImplementedError end |
#spec_from_file(file) ⇒ Object
Extracts the gemspec from a (on-disk) gem package.
Returns
Gem::Specification
– Compatibility note: Rubygems 1.x uses Gem::Format, 2.0 moved this code into Gem::Package.
135 136 137 138 139 140 141 142 143 144 145 |
# 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 |
#uninstall(gem_name, gem_version = nil, opts = {}) ⇒ Object
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
232 233 234 235 236 237 |
# 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 |
#uninstaller(gem_name, **opts) ⇒ Object
251 252 253 |
# 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 |
#with_correct_verbosity ⇒ Object
Set rubygems’ user interaction to ConsoleUI or SilentUI depending on our current debug level
242 243 244 245 |
# 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 |
#with_gem_sources(*sources) ⇒ Object
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.
118 119 120 121 122 123 124 125 |
# 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 |