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?
|
if Vagrant.plugins_enabled?
|
||||||
# Initialize Bundler before we load _any_ RubyGems.
|
# Initialize Bundler before we load _any_ RubyGems.
|
||||||
require_relative "vagrant/bundler"
|
require_relative "vagrant/bundler"
|
||||||
require_relative "vagrant/plugin_manager"
|
require_relative "vagrant/plugin/manager"
|
||||||
Vagrant::Bundler.instance.init!(Vagrant::Plugin::Manager.instance.installed_plugins)
|
Vagrant::Bundler.instance.init!(Vagrant::Plugin::Manager.instance.installed_plugins)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
require "pathname"
|
||||||
require "tempfile"
|
require "tempfile"
|
||||||
|
|
||||||
require_relative "shared_helpers"
|
require_relative "shared_helpers"
|
||||||
|
@ -12,6 +13,11 @@ module Vagrant
|
||||||
@bundler ||= self.new
|
@bundler ||= self.new
|
||||||
end
|
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
|
# Initializes Bundler and the various gem paths so that we can begin
|
||||||
# loading gems. This must only be called once.
|
# loading gems. This must only be called once.
|
||||||
def init!(plugins)
|
def init!(plugins)
|
||||||
|
@ -24,23 +30,117 @@ module Vagrant
|
||||||
# Build up the Gemfile for our Bundler context. We make sure to
|
# Build up the Gemfile for our Bundler context. We make sure to
|
||||||
# lock Vagrant to our current Vagrant version. In addition to that,
|
# lock Vagrant to our current Vagrant version. In addition to that,
|
||||||
# we add all our plugin dependencies.
|
# we add all our plugin dependencies.
|
||||||
@gemfile = Tempfile.new("vagrant-gemfile")
|
@gemfile = build_gemfile(plugins)
|
||||||
@gemfile.puts(%Q[gem "vagrant", "= #{Vagrant::VERSION}"])
|
|
||||||
plugins.each do |plugin|
|
|
||||||
@gemfile.puts(%Q[gem "#{plugin}"])
|
|
||||||
end
|
|
||||||
@gemfile.close
|
|
||||||
|
|
||||||
# Set the environmental variables for Bundler
|
# Set the environmental variables for Bundler
|
||||||
ENV["BUNDLE_CONFIG"] = @configfile.path
|
ENV["BUNDLE_CONFIG"] = @configfile.path
|
||||||
ENV["BUNDLE_GEMFILE"] = @gemfile.path
|
ENV["BUNDLE_GEMFILE"] = @gemfile.path
|
||||||
ENV["GEM_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
|
Gem.clear_paths
|
||||||
|
|
||||||
# Load Bundler and setup our paths
|
# Load Bundler and setup our paths
|
||||||
require "bundler"
|
require "bundler"
|
||||||
::Bundler.setup
|
::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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -66,6 +66,7 @@ end
|
||||||
|
|
||||||
# We need these components always so instead of an autoload we
|
# We need these components always so instead of an autoload we
|
||||||
# just require them explicitly here.
|
# just require them explicitly here.
|
||||||
|
require "vagrant/plugin"
|
||||||
require "vagrant/registry"
|
require "vagrant/registry"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
require_relative "../bundler"
|
||||||
require_relative "../shared_helpers"
|
require_relative "../shared_helpers"
|
||||||
|
require_relative "state_file"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Plugin
|
module Plugin
|
||||||
|
@ -20,6 +22,20 @@ module Vagrant
|
||||||
@global_file = StateFile.new(global_file)
|
@global_file = StateFile.new(global_file)
|
||||||
end
|
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.
|
# This returns the list of plugins that should be enabled.
|
||||||
#
|
#
|
||||||
# @return [Array<String>]
|
# @return [Array<String>]
|
||||||
|
|
|
@ -9,7 +9,6 @@ module VagrantPlugins
|
||||||
def self.action_install
|
def self.action_install
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
b.use InstallGem
|
b.use InstallGem
|
||||||
b.use PruneGems
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -31,7 +30,6 @@ module VagrantPlugins
|
||||||
def self.action_uninstall
|
def self.action_uninstall
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
b.use UninstallPlugin
|
b.use UninstallPlugin
|
||||||
b.use PruneGems
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,7 +38,6 @@ module VagrantPlugins
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
b.use PluginExistsCheck
|
b.use PluginExistsCheck
|
||||||
b.use InstallGem
|
b.use InstallGem
|
||||||
b.use PruneGems
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ rescue LoadError
|
||||||
end
|
end
|
||||||
|
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
require "vagrant/plugin/manager"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module CommandPlugin
|
module CommandPlugin
|
||||||
|
@ -49,40 +50,10 @@ module VagrantPlugins
|
||||||
plugin_name_label += " --version '#{version}'" if version
|
plugin_name_label += " --version '#{version}'" if version
|
||||||
env[:ui].info(I18n.t("vagrant.commands.plugin.installing",
|
env[:ui].info(I18n.t("vagrant.commands.plugin.installing",
|
||||||
:name => plugin_name_label))
|
: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)
|
# TODO: support version, pre-release, custom sources
|
||||||
|
manager = Vagrant::Plugin::Manager.instance
|
||||||
# If we don't have a version, use the default version
|
plugin_spec = manager.install_plugin(plugin_name)
|
||||||
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)
|
|
||||||
|
|
||||||
# Tell the user
|
# Tell the user
|
||||||
env[:ui].success(I18n.t("vagrant.commands.plugin.installed",
|
env[:ui].success(I18n.t("vagrant.commands.plugin.installed",
|
||||||
|
|
Loading…
Reference in New Issue