installing gems works
This commit is contained in:
parent
1eef75a715
commit
86610bf735
|
@ -18,7 +18,7 @@ require_relative "vagrant/shared_helpers"
|
|||
if Vagrant.plugins_enabled?
|
||||
# Initialize Bundler before we load _any_ RubyGems.
|
||||
require_relative "vagrant/bundler"
|
||||
require_relative "vagrant/plugin_manager"
|
||||
require_relative "vagrant/plugin/manager"
|
||||
Vagrant::Bundler.instance.init!(Vagrant::Plugin::Manager.instance.installed_plugins)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require "pathname"
|
||||
require "tempfile"
|
||||
|
||||
require_relative "shared_helpers"
|
||||
|
@ -12,6 +13,11 @@ module Vagrant
|
|||
@bundler ||= self.new
|
||||
end
|
||||
|
||||
def initialize
|
||||
@gem_home = ENV["GEM_HOME"]
|
||||
@gem_path = ENV["GEM_PATH"]
|
||||
end
|
||||
|
||||
# Initializes Bundler and the various gem paths so that we can begin
|
||||
# loading gems. This must only be called once.
|
||||
def init!(plugins)
|
||||
|
@ -24,23 +30,117 @@ module Vagrant
|
|||
# Build up the Gemfile for our Bundler context. We make sure to
|
||||
# lock Vagrant to our current Vagrant version. In addition to that,
|
||||
# we add all our plugin dependencies.
|
||||
@gemfile = Tempfile.new("vagrant-gemfile")
|
||||
@gemfile.puts(%Q[gem "vagrant", "= #{Vagrant::VERSION}"])
|
||||
plugins.each do |plugin|
|
||||
@gemfile.puts(%Q[gem "#{plugin}"])
|
||||
end
|
||||
@gemfile.close
|
||||
@gemfile = build_gemfile(plugins)
|
||||
|
||||
# Set the environmental variables for Bundler
|
||||
ENV["BUNDLE_CONFIG"] = @configfile.path
|
||||
ENV["BUNDLE_GEMFILE"] = @gemfile.path
|
||||
ENV["GEM_PATH"] =
|
||||
"#{Vagrant.user_data_path.join("gems")}#{::File::PATH_SEPARATOR}#{ENV["GEM_PATH"]}"
|
||||
"#{Vagrant.user_data_path.join("gems")}#{::File::PATH_SEPARATOR}#{@gem_path}"
|
||||
Gem.clear_paths
|
||||
|
||||
# Load Bundler and setup our paths
|
||||
require "bundler"
|
||||
::Bundler.setup
|
||||
|
||||
# Do some additional Bundler initialization
|
||||
::Bundler.ui = ::Bundler::UI.new
|
||||
if !::Bundler.ui.respond_to?(:silence)
|
||||
ui = ::Bundler.ui
|
||||
def ui.silence(*args)
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Installs the list of plugins.
|
||||
#
|
||||
# @return [Array<Gem::Specification>]
|
||||
def install(plugins)
|
||||
gemfile = build_gemfile(plugins)
|
||||
lockfile = "#{gemfile.path}.lock"
|
||||
definition = ::Bundler::Definition.build(gemfile, lockfile, nil)
|
||||
root = File.dirname(gemfile.path)
|
||||
opts = {}
|
||||
opts["update"] = true
|
||||
|
||||
with_isolated_gem do
|
||||
::Bundler::Installer.install(root, definition, opts)
|
||||
end
|
||||
|
||||
# Clean up any unused/old gems
|
||||
runtime = ::Bundler::Runtime.new(root, definition)
|
||||
runtime.clean
|
||||
|
||||
definition.specs
|
||||
end
|
||||
|
||||
# Builds a valid Gemfile for use with Bundler given the list of
|
||||
# plugins.
|
||||
#
|
||||
# @return [Tempfile]
|
||||
def build_gemfile(plugins)
|
||||
Tempfile.new("vagrant-gemfile").tap do |gemfile|
|
||||
gemfile.puts(%Q[source "https://rubygems.org"])
|
||||
gemfile.puts(%Q[source "http://gems.hashicorp.com"])
|
||||
gemfile.puts(%Q[gem "vagrant", "= #{Vagrant::VERSION}"])
|
||||
plugins.each do |plugin|
|
||||
gemfile.puts(%Q[gem "#{plugin}"])
|
||||
end
|
||||
gemfile.close
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def with_isolated_gem
|
||||
# Remove bundler settings so that Bundler isn't loaded when building
|
||||
# native extensions because it causes all sorts of problems.
|
||||
old_rubyopt = ENV["RUBYOPT"]
|
||||
old_gemfile = ENV["BUNDLE_GEMFILE"]
|
||||
ENV["BUNDLE_GEMFILE"] = nil
|
||||
ENV["RUBYOPT"] = (ENV["RUBYOPT"] || "").gsub(/-rbundler\/setup\s*/, "")
|
||||
|
||||
# Set the GEM_HOME so gems are installed only to our local gem dir
|
||||
ENV["GEM_HOME"] = Vagrant.user_data_path.join("gems").to_s
|
||||
|
||||
# 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 = Gem.configuration
|
||||
Gem.configuration = NilGemConfig.new
|
||||
|
||||
# Use a silent UI so that we have no output
|
||||
Gem::DefaultUserInteraction.use_ui(Gem::SilentUI.new) do
|
||||
return yield
|
||||
end
|
||||
ensure
|
||||
ENV["BUNDLE_GEMFILE"] = old_gemfile
|
||||
ENV["GEM_HOME"] = @gem_home
|
||||
ENV["RUBYOPT"] = old_rubyopt
|
||||
|
||||
Gem.configuration = old_config
|
||||
Gem.paths = ENV
|
||||
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
|
||||
|
|
|
@ -66,6 +66,7 @@ end
|
|||
|
||||
# We need these components always so instead of an autoload we
|
||||
# just require them explicitly here.
|
||||
require "vagrant/plugin"
|
||||
require "vagrant/registry"
|
||||
|
||||
module Vagrant
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
require_relative "../bundler"
|
||||
require_relative "../shared_helpers"
|
||||
require_relative "state_file"
|
||||
|
||||
module Vagrant
|
||||
module Plugin
|
||||
|
@ -20,6 +22,20 @@ module Vagrant
|
|||
@global_file = StateFile.new(global_file)
|
||||
end
|
||||
|
||||
# Installs another plugin into our gem directory.
|
||||
#
|
||||
# @param [String] name Name of the plugin (gem)
|
||||
def install_plugin(name)
|
||||
result = nil
|
||||
Vagrant::Bundler.instance.install(installed_plugins.push(name)).each do |spec|
|
||||
next if spec.name != name
|
||||
next if result && result.version >= spec.version
|
||||
result = spec
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
# This returns the list of plugins that should be enabled.
|
||||
#
|
||||
# @return [Array<String>]
|
||||
|
|
|
@ -9,7 +9,6 @@ module VagrantPlugins
|
|||
def self.action_install
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use InstallGem
|
||||
b.use PruneGems
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -31,7 +30,6 @@ module VagrantPlugins
|
|||
def self.action_uninstall
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use UninstallPlugin
|
||||
b.use PruneGems
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,7 +38,6 @@ module VagrantPlugins
|
|||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use PluginExistsCheck
|
||||
b.use InstallGem
|
||||
b.use PruneGems
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ rescue LoadError
|
|||
end
|
||||
|
||||
require "log4r"
|
||||
require "vagrant/plugin/manager"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPlugin
|
||||
|
@ -49,40 +50,10 @@ module VagrantPlugins
|
|||
plugin_name_label += " --version '#{version}'" if version
|
||||
env[:ui].info(I18n.t("vagrant.commands.plugin.installing",
|
||||
:name => plugin_name_label))
|
||||
installed_gems = env[:gem_helper].with_environment do
|
||||
# Override the list of sources by the ones set as a parameter if given
|
||||
if env[:plugin_sources]
|
||||
@logger.info("Custom plugin sources: #{env[:plugin_sources]}")
|
||||
Gem.sources = env[:plugin_sources]
|
||||
end
|
||||
|
||||
installer = Gem::DependencyInstaller.new(:document => [], :prerelease => prerelease)
|
||||
|
||||
# If we don't have a version, use the default version
|
||||
version ||= Gem::Requirement.default
|
||||
|
||||
begin
|
||||
installer.install(plugin_name, version)
|
||||
rescue Gem::GemNotFoundException
|
||||
raise Vagrant::Errors::PluginInstallNotFound,
|
||||
:name => plugin_name
|
||||
end
|
||||
end
|
||||
|
||||
# The plugin spec is the last installed gem since RubyGems
|
||||
# currently always installed the requested gem last.
|
||||
@logger.debug("Installed #{installed_gems.length} gems.")
|
||||
plugin_spec = installed_gems.find do |gem|
|
||||
gem.name.downcase == find_plugin_name.downcase
|
||||
end
|
||||
|
||||
# Store the installed name so we can uninstall it if things go
|
||||
# wrong.
|
||||
@installed_plugin_name = plugin_spec.name
|
||||
|
||||
# Mark that we installed the gem
|
||||
@logger.info("Adding the plugin to the state file...")
|
||||
env[:plugin_state_file].add_plugin(plugin_spec.name)
|
||||
# TODO: support version, pre-release, custom sources
|
||||
manager = Vagrant::Plugin::Manager.instance
|
||||
plugin_spec = manager.install_plugin(plugin_name)
|
||||
|
||||
# Tell the user
|
||||
env[:ui].success(I18n.t("vagrant.commands.plugin.installed",
|
||||
|
|
Loading…
Reference in New Issue