Merge pull request #10165 from chrisroberts/f-has-plugin

Update Vagrant.has_plugin? helper to function prior to plugin loading
This commit is contained in:
Chris Roberts 2018-09-04 08:02:29 -07:00 committed by GitHub
commit f50bf62cd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 9 deletions

View File

@ -151,16 +151,9 @@ module Vagrant
return true if plugin("2").manager.registered.any? { |p| p.name == name }
end
# Make the requirement object
version = Gem::Requirement.new([version]) if version
# Now check the plugin gem names
require "vagrant/plugin/manager"
Plugin::Manager.instance.installed_specs.any? do |s|
match = s.name == name
next match if !version
next match && version.satisfied_by?(s.version)
end
Plugin::Manager.instance.plugin_installed?(name, version)
end
# Returns a superclass to use when creating a plugin for Vagrant.

View File

@ -41,12 +41,14 @@ module Vagrant
@system_file = StateFile.new(system_path) if system_path && system_path.file?
@local_file = nil
@globalized = @localized = false
end
# Enable global plugins
#
# @return [Hash] list of plugins
def globalize!
@globalized = true
@logger.debug("Enabling globalized plugins")
plugins = installed_plugins
bundler_init(plugins)
@ -56,8 +58,9 @@ module Vagrant
# Enable environment local plugins
#
# @param [Environment] env Vagrant environment
# @return [Hash] list of plugins
# @return [Hash, nil] list of plugins
def localize!(env)
@localized = true
if env.local_data_path
@logger.debug("Enabling localized plugins")
@local_file = StateFile.new(env.local_data_path.join("plugins.json"))
@ -68,6 +71,11 @@ module Vagrant
end
end
# @return [Boolean] local and global plugins are loaded
def ready?
@globalized && @localized
end
# Initialize bundler with given plugins
#
# @param [Hash] plugins List of plugins
@ -335,6 +343,32 @@ module Vagrant
end
nil
end
# Check if the requested plugin is installed
#
# @param [String] name Name of plugin
# @param [String] version Specific version of the plugin
# @return [Boolean]
def plugin_installed?(name, version=nil)
# Make the requirement object
version = Gem::Requirement.new([version.to_s]) if version
# If plugins are loaded, check for match in loaded specs
if ready?
return installed_specs.any? do |s|
match = s.name == name
next match if !version
next match && version.satisfied_by?(s.version)
end
end
# Plugins are not loaded yet so check installed plugin data
plugin_info = installed_plugins[name]
return false if !plugin_info
return !!plugin_info if version.nil? || plugin_info["installed_gem_version"].nil?
installed_version = Gem::Version.new(plugin_info["installed_gem_version"])
version.satisfied_by?(installed_version)
end
end
end
end

View File

@ -80,6 +80,35 @@ describe Vagrant::Plugin::Manager do
end
end
describe "#ready?" do
let(:plugins) { double("plugins") }
let(:env) { double("env", local_data_path: nil) }
before do
allow(subject).to receive(:bundler_init)
end
it "should be false by default" do
expect(subject.ready?).to be_falsey
end
it "should be false when only globalize! has been called" do
subject.globalize!
expect(subject.ready?).to be_falsey
end
it "should be false when only localize! has been called" do
subject.localize!(env)
expect(subject.ready?).to be_falsey
end
it "should be true when both localize! and globalize! have been called" do
subject.globalize!
subject.localize!(env)
expect(subject.ready?).to be_truthy
end
end
describe "#bundler_init" do
let(:plugins) { {"plugin_name" => {}} }
@ -111,6 +140,77 @@ describe Vagrant::Plugin::Manager do
end
end
describe "#plugin_installed?" do
let(:ready) { true }
let(:specs) { [] }
before do
allow(subject).to receive(:ready?).and_return(ready)
allow(subject).to receive(:installed_specs).and_return(specs)
end
context "when manager is ready" do
it "should return false when plugin is not found" do
expect(subject.plugin_installed?("vagrant-plugin")).to be_falsey
end
context "when plugin is installed" do
let(:specs) { [Gem::Specification.new("vagrant-plugin", "1.2.3")] }
it "should return true" do
expect(subject.plugin_installed?("vagrant-plugin")).to be_truthy
end
it "should return true when version matches installed version" do
expect(subject.plugin_installed?("vagrant-plugin", "1.2.3")).to be_truthy
end
it "should return true when version requirement is satisified by version" do
expect(subject.plugin_installed?("vagrant-plugin", "> 1.0")).to be_truthy
end
it "should return false when version requirement is not satisified by version" do
expect(subject.plugin_installed?("vagrant-plugin", "2.0")).to be_falsey
end
end
end
context "when manager is not ready" do
let(:ready) { false }
let(:plugins) { {} }
before { allow(subject).to receive(:installed_plugins).and_return(plugins) }
it "should check installed plugin data" do
expect(subject).to receive(:installed_plugins).and_return(plugins)
subject.plugin_installed?("vagrant-plugin")
end
it "should return false when plugin is not found" do
expect(subject.plugin_installed?("vagrant-plugin")).to be_falsey
end
context "when plugin is installed" do
let(:plugins) { {"vagrant-plugin" => {"installed_gem_version" => "1.2.3"}} }
it "should return true" do
expect(subject.plugin_installed?("vagrant-plugin")).to be_truthy
end
it "should return true when version matches installed version" do
expect(subject.plugin_installed?("vagrant-plugin", "1.2.3")).to be_truthy
end
it "should return true when version requirement is satisified by version" do
expect(subject.plugin_installed?("vagrant-plugin", "> 1.0")).to be_truthy
end
it "should return false when version requirement is not satisified by version" do
expect(subject.plugin_installed?("vagrant-plugin", "2.0")).to be_falsey
end
end
end
end
describe "#install_plugin" do
it "installs the plugin and adds it to the state file" do
specs = Array.new(5) { Gem::Specification.new }

View File

@ -70,6 +70,7 @@ describe Vagrant do
specs = [Gem::Specification.new]
specs[0].name = "foo"
allow(Vagrant::Plugin::Manager.instance).to receive(:installed_specs).and_return(specs)
allow(Vagrant::Plugin::Manager.instance).to receive(:ready?).and_return(true)
expect(described_class.has_plugin?("foo")).to be(true)
expect(described_class.has_plugin?("bar")).to be(false)
@ -79,6 +80,7 @@ describe Vagrant do
specs = [Gem::Specification.new]
specs[0].name = "foo"
specs[0].version = "1.2.3"
allow(Vagrant::Plugin::Manager.instance).to receive(:ready?).and_return(true)
allow(Vagrant::Plugin::Manager.instance).to receive(:installed_specs).and_return(specs)
expect(described_class.has_plugin?("foo", "~> 1.2.0")).to be(true)