Class: Chef::Provider::Package::Rubygems::AlternateGemEnvironment

Inherits:
GemEnvironment
  • Object
show all
Includes:
Mixin::ShellOut
Defined in:
lib/chef/provider/package/rubygems.rb

Constant Summary collapse

JRUBY_PLATFORM =
/(:?universal|x86_64|x86)\-java\-[0-9\.]+/

Constants inherited from GemEnvironment

GemEnvironment::DEFAULT_UNINSTALLER_OPTS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from GemEnvironment

#candidate_version_from_file, #dependency_installer, #find_newest_remote_version, #install, #installed_versions, #spec_from_file, #uninstall, #uninstaller, #with_correct_verbosity, #with_gem_sources

Constructor Details

#initialize(gem_binary_location) ⇒ AlternateGemEnvironment



313
314
315
# File 'lib/chef/provider/package/rubygems.rb', line 313

def initialize(gem_binary_location)
  @gem_binary_location = gem_binary_location
end

Instance Attribute Details

#gem_binary_locationObject (readonly)

Returns the value of attribute gem_binary_location.



311
312
313
# File 'lib/chef/provider/package/rubygems.rb', line 311

def gem_binary_location
  @gem_binary_location
end

Class Method Details

.gempath_cacheObject



301
302
303
# File 'lib/chef/provider/package/rubygems.rb', line 301

def self.gempath_cache
  @gempath_cache ||= {}
end

.platform_cacheObject



305
306
307
# File 'lib/chef/provider/package/rubygems.rb', line 305

def self.platform_cache
  @platform_cache ||= {}
end

Instance Method Details

#candidate_version_from_remote(gem_dependency, *sources) ⇒ Object



389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
# File 'lib/chef/provider/package/rubygems.rb', line 389

def candidate_version_from_remote(gem_dependency, *sources)
  source_args = sources.compact.map { |s| "--source=#{s}" }.join(" ")
  cmd = "#{@gem_binary_location} list #{gem_dependency.name} --remote --all #{source_args}"
  result = shell_out!(cmd)

  versions = []
  result.stdout.each_line do |line|
    next unless line.start_with?("#{gem_dependency.name} (")

    version_string = line[/\((.*)\)/, 1]
    next unless version_string

    version_string.split(/,\s*/).each do |v|
      version = Gem::Version.new(v.strip)
      versions << version if gem_dependency.requirement.satisfied_by?(version)
    rescue ArgumentError
      # Skip invalid versions
    end
  end

  versions.max
rescue Mixlib::ShellOut::ShellCommandFailed
  with_gem_sources(*sources) do
    with_gem_platforms(*gem_platforms) do
      find_newest_remote_version(gem_dependency, *sources)
    end
  end
end

#gem_pathsObject



321
322
323
324
325
326
327
328
329
330
331
# File 'lib/chef/provider/package/rubygems.rb', line 321

def gem_paths
  if self.class.gempath_cache.key?(@gem_binary_location)
    self.class.gempath_cache[@gem_binary_location]
  else
    # shellout! is a fork/exec which won't work on windows
    shell_style_paths = shell_out!("#{@gem_binary_location} env gempath").stdout
    # on windows, the path separator is (usually? always?) semicolon
    paths = shell_style_paths.split(::File::PATH_SEPARATOR).map(&:strip)
    self.class.gempath_cache[@gem_binary_location] = paths
  end
end

#gem_platformsObject

Attempt to detect the correct platform settings for the target gem environment.

In practice, this only makes a difference if different versions are available depending on platform, and only if the target gem environment has a radically different platform (i.e., jruby), so we just try to detect jruby and fall back to the current platforms (Gem.platforms) if we don't detect it.

=== Returns [String|Gem::Platform] returns an array of Gem::Platform-compatible objects, i.e., Strings that are valid for Gem::Platform or actual Gem::Platform objects.



367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/chef/provider/package/rubygems.rb', line 367

def gem_platforms
  if self.class.platform_cache.key?(@gem_binary_location)
    self.class.platform_cache[@gem_binary_location]
  else
    gem_environment = shell_out!("#{@gem_binary_location} env").stdout
    self.class.platform_cache[@gem_binary_location] = if jruby = gem_environment[JRUBY_PLATFORM]
                                                        ["ruby", Gem::Platform.new(jruby)]
                                                      else
                                                        Gem.platforms
                                                      end
  end
end

#gem_source_indexObject



333
334
335
# File 'lib/chef/provider/package/rubygems.rb', line 333

def gem_source_index
  @source_index ||= Gem::SourceIndex.from_gems_in(*gem_paths.map { |p| p + "/specifications" })
end

#gem_specificationObject



337
338
339
340
341
342
343
344
# File 'lib/chef/provider/package/rubygems.rb', line 337

def gem_specification
  # Only once, dirs calls a reset
  unless @specification
    Gem::Specification.dirs = gem_paths
    @specification = Gem::Specification
  end
  @specification
end

#gem_specification_recordObject



346
347
348
349
350
351
# File 'lib/chef/provider/package/rubygems.rb', line 346

def gem_specification_record
  unless @specification_record
    @specification_record = Gem::SpecificationRecord.new(gem_specification.dirs)
  end
  @specification_record
end

#rubygems_versionObject



317
318
319
# File 'lib/chef/provider/package/rubygems.rb', line 317

def rubygems_version
  @rubygems_version ||= shell_out!("#{@gem_binary_location} --version").stdout.chomp
end

#with_gem_platforms(*alt_gem_platforms) ⇒ Object



380
381
382
383
384
385
386
387
# File 'lib/chef/provider/package/rubygems.rb', line 380

def with_gem_platforms(*alt_gem_platforms)
  alt_gem_platforms.flatten!
  original_gem_platforms = Gem.platforms
  Gem.platforms = alt_gem_platforms
  yield
ensure
  Gem.platforms = original_gem_platforms
end