Instead of shelling out, use the RubyGems API to install plugins
This gets us an accurate name of the gem even if it is installed from a file.
This commit is contained in:
parent
8cde263a14
commit
1162c2dbfc
|
@ -340,6 +340,10 @@ module Vagrant
|
||||||
error_key(:plugin_gem_error)
|
error_key(:plugin_gem_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class PluginInstallBadEntryPoint < VagrantError
|
||||||
|
error_key(:plugin_install_bad_entry_point)
|
||||||
|
end
|
||||||
|
|
||||||
class PluginLoadError < VagrantError
|
class PluginLoadError < VagrantError
|
||||||
status_code(81)
|
status_code(81)
|
||||||
error_key(:plugin_load_error)
|
error_key(:plugin_load_error)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require "rubygems"
|
require "rubygems"
|
||||||
require "rubygems/gem_runner"
|
require "rubygems/dependency_installer"
|
||||||
|
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
|
@ -20,14 +20,43 @@ module VagrantPlugins
|
||||||
# Install the gem
|
# Install the gem
|
||||||
env[:ui].info(I18n.t("vagrant.commands.plugin.installing",
|
env[:ui].info(I18n.t("vagrant.commands.plugin.installing",
|
||||||
:name => plugin_name))
|
:name => plugin_name))
|
||||||
env[:gem_helper].cli(["install", plugin_name, "--no-ri", "--no-rdoc"])
|
installed_gems = env[:gem_helper].with_environment do
|
||||||
|
installer = Gem::DependencyInstaller.new(:document => [])
|
||||||
|
installer.install(plugin_name)
|
||||||
|
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.last
|
||||||
|
|
||||||
|
# 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
|
# Mark that we installed the gem
|
||||||
env[:plugin_state_file].add_plugin(plugin_name)
|
@logger.info("Adding the plugin to the state file...")
|
||||||
|
env[:plugin_state_file].add_plugin(plugin_spec.name)
|
||||||
|
|
||||||
|
# Tell the user
|
||||||
|
env[:ui].success(I18n.t("vagrant.commands.plugin.installed",
|
||||||
|
:name => plugin_spec.name))
|
||||||
|
|
||||||
# Continue
|
# Continue
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def recover(env)
|
||||||
|
# If any error happens, we uninstall it and remove it from
|
||||||
|
# the state file. We can only do this if we successfully installed
|
||||||
|
# the gem in the first place.
|
||||||
|
if @installed_plugin_name
|
||||||
|
new_env = env.dup
|
||||||
|
new_env.delete(:interrupted)
|
||||||
|
new_env[:plugin_name] = @installed_plugin_name
|
||||||
|
new_env[:action_runner].run(Action.action_uninstall, new_env)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,8 +7,16 @@ module VagrantPlugins
|
||||||
module Command
|
module Command
|
||||||
class Install < Base
|
class Install < Base
|
||||||
def execute
|
def execute
|
||||||
|
options = {}
|
||||||
|
|
||||||
opts = OptionParser.new do |o|
|
opts = OptionParser.new do |o|
|
||||||
o.banner = "Usage: vagrant plugin install <name> [-h]"
|
o.banner = "Usage: vagrant plugin install <name> [-h]"
|
||||||
|
o.separator ""
|
||||||
|
|
||||||
|
o.on("--entry-point NAME", String,
|
||||||
|
"The name of the entry point file for loading the plugin.") do |entry_point|
|
||||||
|
options[:entry_point] = entry_point
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parse the options
|
# Parse the options
|
||||||
|
@ -17,7 +25,10 @@ module VagrantPlugins
|
||||||
raise Vagrant::Errors::CLIInvalidUsage, :help => opts.help.chomp if argv.length < 1
|
raise Vagrant::Errors::CLIInvalidUsage, :help => opts.help.chomp if argv.length < 1
|
||||||
|
|
||||||
# Install the gem
|
# Install the gem
|
||||||
action(Action.action_install, :plugin_name => argv[0])
|
action(Action.action_install, {
|
||||||
|
:plugin_entry_point => options[:entry_point],
|
||||||
|
:plugin_name => argv[0]
|
||||||
|
})
|
||||||
|
|
||||||
# Success, exit status 0
|
# Success, exit status 0
|
||||||
0
|
0
|
||||||
|
|
|
@ -13,37 +13,6 @@ module VagrantPlugins
|
||||||
@logger = Log4r::Logger.new("vagrant::plugins::plugincommand::gemhelper")
|
@logger = Log4r::Logger.new("vagrant::plugins::plugincommand::gemhelper")
|
||||||
end
|
end
|
||||||
|
|
||||||
# This executes the `gem` command with the given arguments. Under
|
|
||||||
# the covers this is actually using the RubyGems API directly,
|
|
||||||
# instead of shelling out, which allows for more fine-grained control.
|
|
||||||
#
|
|
||||||
# @param [Array<String>] argv The arguments to send to the `gem` command.
|
|
||||||
def cli(argv)
|
|
||||||
# Initialize the UI to use for RubyGems. This allows us to capture
|
|
||||||
# the stdout/stderr without actually going to the real STDOUT/STDERR.
|
|
||||||
# The final "false" here tells RubyGems we're not a TTY, so don't
|
|
||||||
# ask us things.
|
|
||||||
gem_ui = Gem::StreamUI.new(StringIO.new, StringIO.new, StringIO.new, false)
|
|
||||||
|
|
||||||
# Set the GEM_HOME so that it is installed into our local gems path
|
|
||||||
with_environment do
|
|
||||||
@logger.info("Calling gem with argv: #{argv.inspect}")
|
|
||||||
Gem::DefaultUserInteraction.use_ui(gem_ui) do
|
|
||||||
Gem::GemRunner.new.run(argv)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
rescue Gem::SystemExitException => e
|
|
||||||
# This means that something forced an exit within RubyGems.
|
|
||||||
# We capture this to check whether it succeeded or not by
|
|
||||||
# checking the "exit_code"
|
|
||||||
raise Vagrant::Errors::PluginGemError,
|
|
||||||
:output => gem_ui.errs.string.chomp if e.exit_code != 0
|
|
||||||
ensure
|
|
||||||
# Log the output properly
|
|
||||||
@logger.debug("Gem STDOUT: #{gem_ui.outs.string}")
|
|
||||||
@logger.debug("Gem STDERR: #{gem_ui.errs.string}")
|
|
||||||
end
|
|
||||||
|
|
||||||
# This will yield the given block with the proper ENV setup so
|
# This will yield the given block with the proper ENV setup so
|
||||||
# that RubyGems only sees the gems in the Vagrant-managed gem
|
# that RubyGems only sees the gems in the Vagrant-managed gem
|
||||||
# path.
|
# path.
|
||||||
|
|
|
@ -170,6 +170,11 @@ en:
|
||||||
manage Vagrant plugins. The output of the errors are shown below:
|
manage Vagrant plugins. The output of the errors are shown below:
|
||||||
|
|
||||||
%{output}
|
%{output}
|
||||||
|
plugin_install_bad_entry_point: |-
|
||||||
|
Attempting to load the plugin '%{name}' failed, because
|
||||||
|
the entry point doesn't exist. The entry point attempted was
|
||||||
|
'%{entry_point}'. If this is not correct, please manually
|
||||||
|
specify an `--entry-point` when installing the plugin.
|
||||||
plugin_load_error: |-
|
plugin_load_error: |-
|
||||||
The plugin "%{plugin}" could not be found. Please make sure that it is
|
The plugin "%{plugin}" could not be found. Please make sure that it is
|
||||||
properly installed via `vagrant plugin`.
|
properly installed via `vagrant plugin`.
|
||||||
|
@ -412,6 +417,8 @@ en:
|
||||||
plugin:
|
plugin:
|
||||||
no_plugins: |-
|
no_plugins: |-
|
||||||
No plugins installed.
|
No plugins installed.
|
||||||
|
installed: |-
|
||||||
|
Installed the '%{name}' plugin!
|
||||||
installing: |-
|
installing: |-
|
||||||
Installing the '%{name}' plugin. This can take a few minutes...
|
Installing the '%{name}' plugin. This can take a few minutes...
|
||||||
uninstalling: |-
|
uninstalling: |-
|
||||||
|
|
Loading…
Reference in New Issue