commands/plugin: vagrant update is fancier now (see website docs)

This commit is contained in:
Mitchell Hashimoto 2014-01-05 22:33:05 -08:00
parent 576075f1ac
commit 0117521744
6 changed files with 108 additions and 29 deletions

View File

@ -52,25 +52,22 @@ module Vagrant
# Installs the list of plugins. # Installs the list of plugins.
# #
# @param [Hash] plugins
# @return [Array<Gem::Specification>] # @return [Array<Gem::Specification>]
def install(plugins) def install(plugins)
gemfile = build_gemfile(plugins) internal_install(plugins, nil)
lockfile = "#{gemfile.path}.lock" end
definition = ::Bundler::Definition.build(gemfile, lockfile, nil)
root = File.dirname(gemfile.path)
opts = {}
with_isolated_gem do # Update updates the given plugins, or every plugin if none is given.
::Bundler::Installer.install(root, definition, opts) #
end # @param [Hash] plugins
# @param [Array<String>] specific Specific plugin names to update. If
# TODO(mitchellh): clean gems here... for some reason when I put # empty or nil, all plugins will be updated.
# it in on install, we get a GemNotFound exception. Gotta investigate. def update(plugins, specific)
specific ||= []
definition.specs update = true
rescue ::Bundler::VersionConflict => e update = { gems: specific } if !specific.empty?
raise Errors::PluginInstallVersionConflict, internal_install(plugins, update)
conflicts: e.to_s.gsub("Bundler", "Vagrant")
end end
# Clean removes any unused gems. # Clean removes any unused gems.
@ -86,6 +83,8 @@ module Vagrant
end end
end end
protected
# Builds a valid Gemfile for use with Bundler given the list of # Builds a valid Gemfile for use with Bundler given the list of
# plugins. # plugins.
# #
@ -115,7 +114,31 @@ module Vagrant
end end
end end
protected # This installs a set of plugins and optionally updates those gems.
#
# @param [Hash] plugins
# @param [Hash, Boolean] update If true, updates all plugins, otherwise
# can be a hash of options. See Bundler.definition.
# @return [Array<Gem::Specification>]
def internal_install(plugins, update)
gemfile = build_gemfile(plugins)
lockfile = "#{gemfile.path}.lock"
definition = ::Bundler::Definition.build(gemfile, lockfile, update)
root = File.dirname(gemfile.path)
opts = {}
with_isolated_gem do
::Bundler::Installer.install(root, definition, opts)
end
# TODO(mitchellh): clean gems here... for some reason when I put
# it in on install, we get a GemNotFound exception. Gotta investigate.
definition.specs
rescue ::Bundler::VersionConflict => e
raise Errors::PluginInstallVersionConflict,
conflicts: e.to_s.gsub("Bundler", "Vagrant")
end
def with_isolated_gem def with_isolated_gem
# Remove bundler settings so that Bundler isn't loaded when building # Remove bundler settings so that Bundler isn't loaded when building

View File

@ -61,6 +61,11 @@ module Vagrant
Vagrant::Bundler.instance.clean(installed_plugins) Vagrant::Bundler.instance.clean(installed_plugins)
end end
# Updates all or a specific set of plugins.
def update_plugins(specific)
Vagrant::Bundler.instance.update(installed_plugins, specific)
end
# This returns the list of plugins that should be enabled. # This returns the list of plugins that should be enabled.
# #
# @return [Hash] # @return [Hash]

View File

@ -38,8 +38,7 @@ module VagrantPlugins
# This middleware sequence will update a plugin. # This middleware sequence will update a plugin.
def self.action_update def self.action_update
Vagrant::Action::Builder.new.tap do |b| Vagrant::Action::Builder.new.tap do |b|
b.use PluginExistsCheck b.use UpdateGems
b.use InstallGem
end end
end end
@ -50,6 +49,7 @@ module VagrantPlugins
autoload :ListPlugins, action_root.join("list_plugins") autoload :ListPlugins, action_root.join("list_plugins")
autoload :PluginExistsCheck, action_root.join("plugin_exists_check") autoload :PluginExistsCheck, action_root.join("plugin_exists_check")
autoload :UninstallPlugin, action_root.join("uninstall_plugin") autoload :UninstallPlugin, action_root.join("uninstall_plugin")
autoload :UpdateGems, action_root.join("update_gems")
end end
end end
end end

View File

@ -0,0 +1,51 @@
require "vagrant/plugin/manager"
module VagrantPlugins
module CommandPlugin
module Action
class UpdateGems
def initialize(app, env)
@app = app
end
def call(env)
names = env[:plugin_name] || []
if names.empty?
env[:ui].info(I18n.t("vagrant.commands.plugin.updating"))
else
env[:ui].info(I18n.t("vagrant.commands.plugin.updating_specific",
names: names.join(", ")))
end
manager = Vagrant::Plugin::Manager.instance
installed_specs = manager.installed_specs
new_specs = manager.update_plugins(names)
updated = {}
installed_specs.each do |ispec|
new_specs.each do |uspec|
next if uspec.name != ispec.name
next if ispec.version >= uspec.version
next if updated[uspec.name] && updated[uspec.name].version >= uspec.version
updated[uspec.name] = uspec
end
end
if updated.empty?
env[:ui].success(I18n.t("vagrant.commands.plugin.up_to_date"))
end
updated.values.each do |spec|
env[:ui].success(I18n.t("vagrant.commands.plugin.updated",
name: spec.name, version: spec.version.to_s))
end
# Continue
@app.call(env)
end
end
end
end
end

View File

@ -10,26 +10,18 @@ module VagrantPlugins
include MixinInstallOpts include MixinInstallOpts
def execute def execute
options = {}
opts = OptionParser.new do |o| opts = OptionParser.new do |o|
o.banner = "Usage: vagrant plugin update <name> [-h]" o.banner = "Usage: vagrant plugin update [names...] [-h]"
o.separator "" o.separator ""
build_install_opts(o, options)
end end
# Parse the options # Parse the options
argv = parse_options(opts) argv = parse_options(opts)
return if !argv return if !argv
raise Vagrant::Errors::CLIInvalidUsage, :help => opts.help.chomp if argv.length < 1
# Update the gem # Update the gem
action(Action.action_update, { action(Action.action_update, {
:plugin_entry_point => options[:entry_point], :plugin_name => argv,
:plugin_prerelease => options[:plugin_prerelease],
:plugin_version => options[:plugin_version],
:plugin_sources => options[:plugin_sources],
:plugin_name => argv[0]
}) })
# Success, exit status 0 # Success, exit status 0

View File

@ -927,6 +927,14 @@ en:
Installing the '%{name}' plugin. This can take a few minutes... Installing the '%{name}' plugin. This can take a few minutes...
uninstalling: |- uninstalling: |-
Uninstalling the '%{name}' plugin... Uninstalling the '%{name}' plugin...
up_to_date: |-
All plugins are up to date.
updated: |-
Updated '%{name}' to version '%{version}'!
updating: |-
Updating installed plugins...
updating_specific: |-
Updating plugins: %{names}. This may take a few minutes...
post_install: |- post_install: |-
Post install message from the '%{name}' plugin: Post install message from the '%{name}' plugin: