Check if plugin install provides specification

During a plugin install, if the plugin is already installed and
activated, no specification will be returned as there was nothing
new installed. In this situation, look for the requested plugin
within the activated specifications. If it is found, then proceed
since the plugin is installed. If it is not found, return an error.
This commit is contained in:
Chris Roberts 2020-05-06 15:38:44 -07:00
parent e34835fa35
commit 5195bee9ea
5 changed files with 53 additions and 15 deletions

View File

@ -480,7 +480,7 @@ module Vagrant
if update[:gems] == true || (update[:gems].respond_to?(:include?) && update[:gems].include?(name))
if Gem::Requirement.new(gem_version).exact?
gem_version = "> 0"
@logger.debug("Detected exact version match for `#{name}` plugin update. Reset to loose constraint #{gem_version.inspect}.")
@logger.debug("Detected exact version match for `#{name}` plugin update. Reset to loosen constraint #{gem_version.inspect}.")
end
skips << name
end
@ -565,10 +565,10 @@ module Vagrant
activate_solution(solution)
# Remove gems which are already installed
request_set.sorted_requests.delete_if do |activation_req|
rs_spec = activation_req.spec
if vagrant_internal_specs.detect{|ispec| ispec.name == rs_spec.name && ispec.version == rs_spec.version }
@logger.debug("Removing activation request from install. Already installed. (#{rs_spec.spec.full_name})")
request_set.sorted_requests.delete_if do |act_req|
rs = act_req.spec
if vagrant_internal_specs.detect{ |i| i.name == rs.name && i.version == rs.version }
@logger.debug("Removing activation request from install. Already installed. (#{rs.spec.full_name})")
true
end
end

View File

@ -628,6 +628,10 @@ module Vagrant
error_key(:plugin_install_license_not_found)
end
class PluginInstallFailed < VagrantError
error_key(:plugin_install_failed)
end
class PluginInstallSpace < VagrantError
error_key(:plugin_install_space)
end

View File

@ -150,17 +150,28 @@ module Vagrant
else
result = local_spec
end
# Add the plugin to the state file
plugin_file = opts[:env_local] ? @local_file : @user_file
plugin_file.add_plugin(
result.name,
version: opts[:version],
require: opts[:require],
sources: opts[:sources],
env_local: !!opts[:env_local],
installed_gem_version: result.version.to_s
)
if result
# Add the plugin to the state file
plugin_file = opts[:env_local] ? @local_file : @user_file
plugin_file.add_plugin(
result.name,
version: opts[:version],
require: opts[:require],
sources: opts[:sources],
env_local: !!opts[:env_local],
installed_gem_version: result.version.to_s
)
else
r = Gem::Dependency.new(name, opts[:version])
result = Gem::Specification.find { |s|
s.satisfies_requirement?(r) &&
s.activated?
}
raise Errors::PluginInstallFailed,
name: name if result.nil?
@logger.warn("Plugin install returned no result as no new plugins were installed.")
end
# After install clean plugin gems to remove any cruft. This is useful
# for removing outdated dependencies or other versions of an installed
# plugin if the plugin is upgraded/downgraded

View File

@ -1130,6 +1130,10 @@ en:
The license file to install could not be found. Please verify
the path you gave is correct. The path to the license file given
was: '%{path}'
plugin_install_failed: |-
Vagrant was unable to install the requested plugin: '%{name}'
Please try to install this plugin again. If Vagrant is still unable
to install the requested plugin, please report this error.
plugin_install_space: |-
The directory where plugins are installed (the Vagrant home directory)
has a space in it. On Windows, there is a bug in Ruby when compiling

View File

@ -265,6 +265,25 @@ describe Vagrant::Plugin::Manager do
expect(plugins["bar"]["gem_version"]).to eql("1.0")
end
context "with existing activation" do
let(:value) { double("value") }
before do
expect(bundler).to receive(:install).and_return([])
allow(bundler).to receive(:clean)
end
it "should locate existing activation if available" do
expect(Gem::Specification).to receive(:find).and_return(value)
expect(subject.install_plugin("foo")).to eq(value)
end
it "should raise an error if no activation is located" do
expect(Gem::Specification).to receive(:find).and_return(nil)
expect { subject.install_plugin("foo") }.to raise_error(Vagrant::Errors::PluginInstallFailed)
end
end
describe "installation options" do
let(:specs) do
specs = Array.new(5) { Gem::Specification.new }