From 679185d6c87e0f2e4f6a5da5ce50d02c80ab31b1 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 2 Aug 2021 12:06:43 +0900 Subject: Merge RubyGems 3.2.24 and Bundler 2.2.24 --- lib/bundler/cli.rb | 1 + lib/bundler/definition.rb | 59 +++++++++++++++++-------------------- lib/bundler/dsl.rb | 51 ++++++++++++++++---------------- lib/bundler/installer/standalone.rb | 2 +- lib/bundler/plugin.rb | 2 ++ lib/bundler/plugin/index.rb | 5 +++- lib/bundler/runtime.rb | 4 +-- lib/bundler/spec_set.rb | 7 ++--- lib/bundler/version.rb | 2 +- lib/rubygems.rb | 2 +- lib/rubygems/gemcutter_utilities.rb | 3 +- lib/rubygems/uninstaller.rb | 41 ++++++++++++++++++++++---- 12 files changed, 105 insertions(+), 74 deletions(-) (limited to 'lib') diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 45d4e62481..177f362070 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -14,6 +14,7 @@ module Bundler COMMAND_ALIASES = { "check" => "c", "install" => "i", + "plugin" => "", "list" => "ls", "exec" => ["e", "ex", "exe"], "cache" => ["package", "pack"], diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index e043b5c713..94b8bc4057 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -133,7 +133,7 @@ module Bundler @unlock[:gems] ||= @dependencies.map(&:name) else eager_unlock = expand_dependencies(@unlock[:gems] || [], true) - @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name) + @unlock[:gems] = @locked_specs.for(eager_unlock, false, false, false).map(&:name) end @dependency_changes = converge_dependencies @@ -185,25 +185,15 @@ module Bundler # # @return [Bundler::SpecSet] def specs - @specs ||= begin - begin - specs = resolve.materialize(requested_dependencies) - rescue GemNotFound => e # Handle yanked gem - gem_name, gem_version = extract_gem_info(e) - locked_gem = @locked_specs[gem_name].last - raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote - raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \ - "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \ - "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \ - "removed in order to install." - end - unless specs["bundler"].any? - bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last - specs["bundler"] = bundler - end - - specs - end + @specs ||= add_bundler_to(resolve.materialize(requested_dependencies)) + rescue GemNotFound => e # Handle yanked gem + gem_name, gem_version = extract_gem_info(e) + locked_gem = @locked_specs[gem_name].last + raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote + raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \ + "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \ + "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \ + "removed in order to install." end def new_specs @@ -235,17 +225,11 @@ module Bundler end def requested_specs - @requested_specs ||= begin - groups = requested_groups - groups.map!(&:to_sym) - specs_for(groups) - end + specs_for(requested_groups) end def requested_dependencies - groups = requested_groups - groups.map!(&:to_sym) - dependencies_for(groups) + dependencies_for(requested_groups) end def current_dependencies @@ -255,11 +239,13 @@ module Bundler end def specs_for(groups) + groups = requested_groups if groups.empty? deps = dependencies_for(groups) - SpecSet.new(specs.for(expand_dependencies(deps))) + add_bundler_to(resolve.materialize(expand_dependencies(deps))) end def dependencies_for(groups) + groups.map!(&:to_sym) current_dependencies.reject do |d| (d.groups & groups).empty? end @@ -507,6 +493,15 @@ module Bundler private + def add_bundler_to(specs) + unless specs["bundler"].any? + bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last + specs["bundler"] = bundler + end + + specs + end + def precompute_source_requirements_for_indirect_dependencies? sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source? end @@ -735,7 +730,7 @@ module Bundler # if we won't need the source (according to the lockfile), # don't error if the path/git source isn't available next if @locked_specs. - for(requested_dependencies, [], false, true, false). + for(requested_dependencies, false, true, false). none? {|locked_spec| locked_spec.source == s.source } raise @@ -754,8 +749,8 @@ module Bundler end resolve = SpecSet.new(converged) - @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true) - resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), [], false, false, false).reject{|s| @unlock[:gems].include?(s.name) }) + @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true) + resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false, false).reject{|s| @unlock[:gems].include?(s.name) }) diff = nil # Now, we unlock any sources that do not have anymore gems pinned to it diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 1605210e55..ac955894a7 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -102,38 +102,39 @@ module Bundler # if there's already a dependency with this name we try to prefer one if current = @dependencies.find {|d| d.name == dep.name } deleted_dep = @dependencies.delete(current) if current.type == :development - return if deleted_dep - if current.requirement != dep.requirement - return if dep.type == :development + unless deleted_dep + if current.requirement != dep.requirement + return if dep.type == :development - update_prompt = "" + update_prompt = "" - if File.basename(@gemfile) == Injector::INJECTED_GEMS - if dep.requirements_list.include?(">= 0") && !current.requirements_list.include?(">= 0") - update_prompt = ". Gem already added" - else - update_prompt = ". If you want to update the gem version, run `bundle update #{current.name}`" + if File.basename(@gemfile) == Injector::INJECTED_GEMS + if dep.requirements_list.include?(">= 0") && !current.requirements_list.include?(">= 0") + update_prompt = ". Gem already added" + else + update_prompt = ". If you want to update the gem version, run `bundle update #{current.name}`" - update_prompt += ". You may also need to change the version requirement specified in the Gemfile if it's too restrictive." unless current.requirements_list.include?(">= 0") + update_prompt += ". You may also need to change the version requirement specified in the Gemfile if it's too restrictive." unless current.requirements_list.include?(">= 0") + end end - end - raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \ - "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \ - "#{update_prompt}" - else - Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \ - "You should probably keep only one of them.\n" \ - "Remove any duplicate entries and specify the gem only once.\n" \ - "While it's not a problem now, it could cause errors if you change the version of one of them later." - end + raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \ + "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \ + "#{update_prompt}" + else + Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \ + "You should probably keep only one of them.\n" \ + "Remove any duplicate entries and specify the gem only once.\n" \ + "While it's not a problem now, it could cause errors if you change the version of one of them later." + end - if current.source != dep.source - return if dep.type == :development - raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \ - "You specified that #{dep.name} (#{dep.requirement}) should come from " \ - "#{current.source || "an unspecified source"} and #{dep.source}\n" + if current.source != dep.source + return if dep.type == :development + raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \ + "You specified that #{dep.name} (#{dep.requirement}) should come from " \ + "#{current.source || "an unspecified source"} and #{dep.source}\n" + end end end diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb index 2a3f5cfe35..f16135cb48 100644 --- a/lib/bundler/installer/standalone.rb +++ b/lib/bundler/installer/standalone.rb @@ -3,7 +3,7 @@ module Bundler class Standalone def initialize(groups, definition) - @specs = groups.empty? ? definition.requested_specs : definition.specs_for(groups.map(&:to_sym)) + @specs = definition.specs_for(groups) end def generate diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb index 023c25b33e..bfe4fd7286 100644 --- a/lib/bundler/plugin.rb +++ b/lib/bundler/plugin.rb @@ -309,6 +309,8 @@ module Bundler # # @param [String] name of the plugin def load_plugin(name) + return unless name && !name.empty? + # Need to ensure before this that plugin root where the rest of gems # are installed to be on load path to support plugin deps. Currently not # done to avoid conflicts diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb index 819bc60588..29d33be718 100644 --- a/lib/bundler/plugin/index.rb +++ b/lib/bundler/plugin/index.rb @@ -74,7 +74,10 @@ module Bundler def unregister_plugin(name) @commands.delete_if {|_, v| v == name } @sources.delete_if {|_, v| v == name } - @hooks.each {|_, plugin_names| plugin_names.delete(name) } + @hooks.each do |hook, names| + names.delete(name) + @hooks.delete(hook) if names.empty? + end @plugin_paths.delete(name) @load_paths.delete(name) save_index diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb index e259b590bf..287fa1cfe9 100644 --- a/lib/bundler/runtime.rb +++ b/lib/bundler/runtime.rb @@ -12,12 +12,10 @@ module Bundler def setup(*groups) @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle? - groups.map!(&:to_sym) - # Has to happen first clean_load_path - specs = groups.any? ? @definition.specs_for(groups) : requested_specs + specs = @definition.specs_for(groups) SharedHelpers.set_bundle_environment Bundler.rubygems.replace_entrypoints(specs) diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 2ab0386955..1a8906c47e 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -11,15 +11,14 @@ module Bundler @specs = specs end - def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true) + def for(dependencies, check = false, match_current_platform = false, raise_on_missing = true) handled = [] deps = dependencies.dup specs = [] - skip += ["bundler"] loop do break unless dep = deps.shift - next if handled.include?(dep) || skip.include?(dep.name) + next if handled.any?{|d| d.name == dep.name && (match_current_platform || d.__platform == dep.__platform) } || dep.name == "bundler" handled << dep @@ -73,7 +72,7 @@ module Bundler end def materialize(deps, missing_specs = nil) - materialized = self.for(deps, [], false, true, !missing_specs) + materialized = self.for(deps, false, true, !missing_specs) materialized.group_by(&:source).each do |source, specs| next unless specs.any?{|s| s.is_a?(LazySpecification) } diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index f6851e35d3..c4f92994ff 100644 --- a/lib/bundler/version.rb +++ b/lib/bundler/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module Bundler - VERSION = "2.2.23".freeze + VERSION = "2.2.24".freeze def self.bundler_major_version @bundler_major_version ||= VERSION.split(".").first.to_i diff --git a/lib/rubygems.rb b/lib/rubygems.rb index f369b0eb2c..2216e59d17 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -8,7 +8,7 @@ require 'rbconfig' module Gem - VERSION = "3.2.23".freeze + VERSION = "3.2.24".freeze end # Must be first since it unloads the prelude from 1.9.2 diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index 00e68916c4..f465881041 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -31,7 +31,8 @@ module Gem::GemcutterUtilities def add_otp_option add_option('--otp CODE', - 'Digit code for multifactor authentication') do |value, options| + 'Digit code for multifactor authentication', + 'You can also use the environment variable GEM_HOST_OTP_CODE') do |value, options| options[:otp] = value end end diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index 51ac3494f3..93e414b1c9 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -70,6 +70,9 @@ class Gem::Uninstaller # only add user directory if install_dir is not set @user_install = false @user_install = options[:user_install] unless options[:install_dir] + + # Optimization: populated during #uninstall + @default_specs_matching_uninstall_params = [] end ## @@ -98,10 +101,8 @@ class Gem::Uninstaller default_specs, list = list.partition do |spec| spec.default_gem? end - - default_specs.each do |default_spec| - say "Gem #{default_spec.full_name} cannot be uninstalled because it is a default gem" - end + warn_cannot_uninstall_default_gems(default_specs - list) + @default_specs_matching_uninstall_params = default_specs list, other_repo_specs = list.partition do |spec| @gem_home == spec.base_dir or @@ -270,7 +271,7 @@ class Gem::Uninstaller end safe_delete { FileUtils.rm_r gemspec } - say "Successfully uninstalled #{spec.full_name}" + announce_deletion_of(spec) Gem::Specification.reset end @@ -373,4 +374,34 @@ class Gem::Uninstaller raise e end + + private + + def announce_deletion_of(spec) + name = spec.full_name + say "Successfully uninstalled #{name}" + if default_spec_matches?(spec) + say( + "There was both a regular copy and a default copy of #{name}. The " \ + "regular copy was successfully uninstalled, but the default copy " \ + "was left around because default gems can't be removed." + ) + end + end + + # @return true if the specs of any default gems are `==` to the given `spec`. + def default_spec_matches?(spec) + !default_specs_that_match(spec).empty? + end + + # @return [Array] specs of default gems that are `==` to the given `spec`. + def default_specs_that_match(spec) + @default_specs_matching_uninstall_params.select {|default_spec| spec == default_spec } + end + + def warn_cannot_uninstall_default_gems(specs) + specs.each do |spec| + say "Gem #{spec.full_name} cannot be uninstalled because it is a default gem" + end + end end -- cgit v1.2.3