vagrant/plugins/commands/plugin/gem_helper.rb
Chris Roberts ea25996b21
Update Vagrant behavior outside of installers
Remove customized require behaviors and modify the bin executable
to check for missing tools that Vagrant expects to exist when
running outside of an installer.
2025-04-02 11:40:17 -07:00

89 lines
2.8 KiB
Ruby

# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
require "rubygems"
require "rubygems/config_file"
require "rubygems/gem_runner"
require "log4r"
module VagrantPlugins
module CommandPlugin
# This class provides methods to help with calling out to the
# `gem` command but using the RubyGems API.
class GemHelper
def initialize(gem_home)
@gem_home = gem_home.to_s
@logger = Log4r::Logger.new("vagrant::plugins::plugincommand::gemhelper")
end
# This will yield the given block with the proper ENV setup so
# that RubyGems only sees the gems in the Vagrant-managed gem
# path.
def with_environment
old_gem_home = ENV["GEM_HOME"]
old_gem_path = ENV["GEM_PATH"]
ENV["GEM_HOME"] = @gem_home
ENV["GEM_PATH"] = @gem_home
@logger.debug("Set GEM_* to: #{ENV["GEM_HOME"]}")
# Clear paths so that it reads the new GEM_HOME setting
Gem.paths = ENV
# Set a custom configuration to avoid loading ~/.gemrc loads and
# /etc/gemrc and so on.
old_config = nil
begin
old_config = Gem.configuration
rescue Psych::SyntaxError
# Just ignore this. This means that the ".gemrc" file has
# an invalid syntax and can't be loaded. We don't care, because
# when we set Gem.configuration to nil later, it'll force a reload
# if it is needed.
end
Gem.configuration = NilGemConfig.new
# Clear the sources so that installation uses custom sources
old_sources = Gem.sources
Gem.sources = Gem.default_sources
Vagrant::Bundler::DEFAULT_GEM_SOURCES.each do |source|
if !Gem.sources.include?(source)
Gem.sources << source
end
end
# Use a silent UI so that we have no output
Gem::DefaultUserInteraction.use_ui(Gem::SilentUI.new) do
return yield
end
ensure
# Restore the old GEM_* settings
ENV["GEM_HOME"] = old_gem_home
ENV["GEM_PATH"] = old_gem_path
# Reset everything
Gem.configuration = old_config
Gem.paths = ENV
Gem.sources = old_sources.to_a
end
# This is pretty hacky but it is a custom implementation of
# Gem::ConfigFile so that we don't load any gemrc files.
class NilGemConfig < Gem::ConfigFile
def initialize
# We _can not_ `super` here because that can really mess up
# some other configuration state. We need to just set everything
# directly.
@api_keys = {}
@args = []
@backtrace = false
@bulk_threshold = 1000
@hash = {}
@update_sources = true
@verbose = true
end
end
end
end
end