diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 01d3219de..b6dc0716d 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -488,6 +488,10 @@ module Vagrant error_key(:plugin_state_file_not_parsable) end + class PluginUninstallSystem < VagrantError + error_key(:plugin_uninstall_system) + end + class RSyncError < VagrantError error_key(:rsync_error) end diff --git a/lib/vagrant/plugin/manager.rb b/lib/vagrant/plugin/manager.rb index 456e7c6ee..b3b07a673 100644 --- a/lib/vagrant/plugin/manager.rb +++ b/lib/vagrant/plugin/manager.rb @@ -95,6 +95,13 @@ module Vagrant # # @param [String] name def uninstall_plugin(name) + if @system_file + if !@user_file.has_plugin?(name) && @system_file.has_plugin?(name) + raise Errors::PluginUninstallSystem, + name: name + end + end + @user_file.remove_plugin(name) # Clean the environment, removing any old plugins diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 291ea0b7b..56c7f5e10 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -730,6 +730,14 @@ en: Please remove the file and reinstall the plugins. If this error recurs, please report a bug. + plugin_uninstall_system: |- + The plugin you're attempting to uninstall ('%{name}') is a + system plugin. This means that the plugin is part of the installation + of Vagrant. These plugins cannot be removed. + + You can however, install a plugin with the same name to replace + these plugins. User-installed plugins take priority over + system-installed plugins. provider_not_found: |- The provider '%{provider}' could not be found, but was requested to back the machine '%{machine}'. Please use a provider that exists. diff --git a/test/unit/vagrant/plugin/manager_test.rb b/test/unit/vagrant/plugin/manager_test.rb index d9f38d0e1..f893f06c5 100644 --- a/test/unit/vagrant/plugin/manager_test.rb +++ b/test/unit/vagrant/plugin/manager_test.rb @@ -149,6 +149,39 @@ describe Vagrant::Plugin::Manager do expect { subject.uninstall_plugin("foo") }. to raise_error(Vagrant::Errors::BundlerError) end + + context "with a system file" do + let(:systems_path) { temporary_file } + + before do + systems_path.unlink + + described_class.stub(system_plugins_file: systems_path) + + sf = Vagrant::Plugin::StateFile.new(systems_path) + sf.add_plugin("foo", version: "0.2.0") + sf.add_plugin("bar") + end + + it "uninstalls the user plugin if it exists" do + sf = Vagrant::Plugin::StateFile.new(path) + sf.add_plugin("bar") + + # Test + bundler.should_receive(:clean).once.with(anything) + + # Remove it + subject.uninstall_plugin("bar") + + plugins = subject.installed_plugins + expect(plugins["foo"]["system"]).to be_true + end + + it "raises an error if uninstalling a system gem" do + expect { subject.uninstall_plugin("bar") }. + to raise_error(Vagrant::Errors::PluginUninstallSystem) + end + end end describe "#update_plugins" do