diff options
Diffstat (limited to 'lib/bundler/rubygems_integration.rb')
-rw-r--r-- | lib/bundler/rubygems_integration.rb | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index f088c2fdfb..a4519246a9 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true require "monitor" -require "rubygems" -require "rubygems/config_file" module Bundler class RubygemsIntegration @@ -307,7 +305,7 @@ module Bundler gem_from_path(path, security_policies[policy]).spec rescue Gem::Package::FormatError raise GemspecError, "Could not read gem at #{path}. It may be corrupted." - rescue Exception, Gem::Exception, Gem::Security::Exception => e + rescue Exception, Gem::Exception, Gem::Security::Exception => e # rubocop:disable Lint/RescueException if e.is_a?(Gem::Security::Exception) || e.message =~ /unknown trust policy|unsigned gem/i || e.message =~ /couldn't verify (meta)?data signature/i @@ -436,40 +434,42 @@ module Bundler # Used to make bin stubs that are not created by bundler work # under bundler. The new Gem.bin_path only considers gems in # +specs+ - def replace_bin_path(specs, specs_by_name) + def replace_bin_path(specs_by_name) gem_class = (class << Gem; self; end) redefine_method(gem_class, :find_spec_for_exe) do |gem_name, *args| exec_name = args.first + raise ArgumentError, "you must supply exec_name" unless exec_name spec_with_name = specs_by_name[gem_name] - spec = if exec_name - if spec_with_name && spec_with_name.executables.include?(exec_name) - spec_with_name - else - specs.find {|s| s.executables.include?(exec_name) } - end - else - spec_with_name - end + matching_specs_by_exec_name = specs_by_name.values.select {|s| s.executables.include?(exec_name) } + spec = matching_specs_by_exec_name.delete(spec_with_name) - unless spec + unless spec || !matching_specs_by_exec_name.empty? message = "can't find executable #{exec_name} for gem #{gem_name}" - if !exec_name || spec_with_name.nil? + if spec_with_name.nil? message += ". #{gem_name} is not currently included in the bundle, " \ "perhaps you meant to add it to your #{Bundler.default_gemfile.basename}?" end raise Gem::Exception, message end - raise Gem::Exception, "no default executable for #{spec.full_name}" unless exec_name ||= spec.default_executable - - unless spec.name == gem_name - Bundler::SharedHelpers.major_deprecation 3, + unless spec + spec = matching_specs_by_exec_name.shift + warn \ "Bundler is using a binstub that was created for a different gem (#{spec.name}).\n" \ "You should run `bundle binstub #{gem_name}` " \ "to work around a system/bundle conflict." end + + unless matching_specs_by_exec_name.empty? + conflicting_names = matching_specs_by_exec_name.map(&:name).join(", ") + warn \ + "The `#{exec_name}` executable in the `#{spec.name}` gem is being loaded, but it's also present in other gems (#{conflicting_names}).\n" \ + "If you meant to run the executable for another gem, make sure you use a project specific binstub (`bundle binstub <gem_name>`).\n" \ + "If you plan to use multiple conflicting executables, generate binstubs for them and disambiguate their names." + end + spec end @@ -514,9 +514,18 @@ module Bundler h end + Bundler.rubygems.default_stubs.each do |stub| + default_spec = stub.to_spec + default_spec_name = default_spec.name + next if specs_by_name.key?(default_spec_name) + + specs << default_spec + specs_by_name[default_spec_name] = default_spec + end + replace_gem(specs, specs_by_name) stub_rubygems(specs) - replace_bin_path(specs, specs_by_name) + replace_bin_path(specs_by_name) replace_refresh Gem.clear_paths @@ -850,6 +859,16 @@ module Bundler end end + if Gem::Specification.respond_to?(:default_stubs) + def default_stubs + Gem::Specification.default_stubs("*.gemspec") + end + else + def default_stubs + Gem::Specification.send(:default_stubs, "*.gemspec") + end + end + def use_gemdeps(gemfile) ENV["BUNDLE_GEMFILE"] ||= File.expand_path(gemfile) require "bundler/gemdeps" |