1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[rubygems/rubygems] Make plugin installation idempotent

The error had not be caught be specs because `bundle install` was
returning a zero exit code when plugin installation errors happened. So
I fixed that issue too.

https://github.com/rubygems/rubygems/commit/90cde87856
This commit is contained in:
David Rodríguez 2021-08-19 11:57:16 +02:00 committed by Hiroshi SHIBATA
parent 3a9dd795a7
commit f934096638
Notes: git 2021-08-31 19:07:03 +09:00
4 changed files with 20 additions and 11 deletions

View file

@ -13,6 +13,7 @@ module Bundler
class MalformattedPlugin < PluginError; end
class UndefinedCommandError < PluginError; end
class UnknownSourceError < PluginError; end
class PluginInstallError < PluginError; end
PLUGIN_FILE_NAME = "plugins.rb".freeze
@ -38,12 +39,11 @@ module Bundler
specs = Installer.new.install(names, options)
save_plugins names, specs
rescue PluginError => e
rescue PluginError
specs_to_delete = specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }
specs_to_delete.each_value {|spec| Bundler.rm_rf(spec.full_gem_path) }
names_list = names.map {|name| "`#{name}`" }.join(", ")
Bundler.ui.error "Failed to install the following plugins: #{names_list}. The underlying error was: #{e.message}.\n #{e.backtrace.join("\n ")}"
raise
end
# Uninstalls plugins by the given names
@ -245,6 +245,8 @@ module Bundler
# @param [Array<String>] names of inferred source plugins that can be ignored
def save_plugins(plugins, specs, optional_plugins = [])
plugins.each do |name|
next if index.installed?(name)
spec = specs[name]
save_plugin(name, spec, optional_plugins.include?(name))
@ -269,11 +271,13 @@ module Bundler
# @param [Boolean] optional_plugin, removed if there is conflict with any
# other plugin (used for default source plugins)
#
# @raise [MalformattedPlugin] if validation or registration raises any error
# @raise [PluginInstallError] if validation or registration raises any error
def save_plugin(name, spec, optional_plugin = false)
validate_plugin! Pathname.new(spec.full_gem_path)
installed = register_plugin(name, spec, optional_plugin)
Bundler.ui.info "Installed plugin #{name}" if installed
rescue PluginError => e
raise PluginInstallError, "Failed to install plugin `#{spec.name}`, due to #{e.class} (#{e.message})"
end
# Runs the plugins.rb file in an isolated namespace, records the plugin

View file

@ -65,6 +65,8 @@ RSpec.describe Bundler::Plugin do
end
it "passes the name and options to installer" do
allow(index).to receive(:installed?).
with("new-plugin")
allow(installer).to receive(:install).with(["new-plugin"], opts) do
{ "new-plugin" => spec }
end.once
@ -73,6 +75,8 @@ RSpec.describe Bundler::Plugin do
end
it "validates the installed plugin" do
allow(index).to receive(:installed?).
with("new-plugin")
allow(subject).
to receive(:validate_plugin!).with(lib_path("new-plugin")).once
@ -80,6 +84,8 @@ RSpec.describe Bundler::Plugin do
end
it "registers the plugin with index" do
allow(index).to receive(:installed?).
with("new-plugin")
allow(index).to receive(:register_plugin).
with("new-plugin", lib_path("new-plugin").to_s, [lib_path("new-plugin").join("lib").to_s], []).once
subject.install ["new-plugin"], opts
@ -96,6 +102,7 @@ RSpec.describe Bundler::Plugin do
end.once
allow(subject).to receive(:validate_plugin!).twice
allow(index).to receive(:installed?).twice
allow(index).to receive(:register_plugin).twice
subject.install ["new-plugin", "another-plugin"], opts
end

View file

@ -69,12 +69,10 @@ RSpec.describe "command plugins" do
end
end
bundle "plugin install copycat --source #{file_uri_for(gem_repo2)}"
bundle "plugin install copycat --source #{file_uri_for(gem_repo2)}", :raise_on_error => false
expect(out).not_to include("Installed plugin copycat")
expect(err).to include("Failed to install the following plugins: `copycat`")
expect(err).to include("Command(s) `mahcommand` declared by copycat are already registered.")
expect(err).to include("Failed to install plugin `copycat`, due to Bundler::Plugin::Index::CommandConflict (Command(s) `mahcommand` declared by copycat are already registered.)")
end
end

View file

@ -109,9 +109,9 @@ RSpec.describe "bundler plugin install" do
build_gem "charlie"
end
bundle "plugin install charlie --source #{file_uri_for(gem_repo2)}"
bundle "plugin install charlie --source #{file_uri_for(gem_repo2)}", :raise_on_error => false
expect(err).to include("Failed to install the following plugins: `charlie`. The underlying error was: plugins.rb was not found")
expect(err).to include("Failed to install plugin `charlie`, due to Bundler::Plugin::MalformattedPlugin (plugins.rb was not found in the plugin.)")
expect(global_plugin_gem("charlie-1.0")).not_to be_directory
@ -128,7 +128,7 @@ RSpec.describe "bundler plugin install" do
end
end
bundle "plugin install chaplin --source #{file_uri_for(gem_repo2)}"
bundle "plugin install chaplin --source #{file_uri_for(gem_repo2)}", :raise_on_error => false
expect(global_plugin_gem("chaplin-1.0")).not_to be_directory