From 96064e6f1ce100a37680dc8f9509f06b3350e9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 24 Mar 2020 07:39:24 +0100 Subject: Sync rubygems with current master (#2889) --- lib/rubygems.rb | 62 +++++++++--- lib/rubygems/bundler_version_finder.rb | 17 +++- lib/rubygems/command.rb | 8 +- lib/rubygems/commands/contents_command.rb | 2 +- lib/rubygems/commands/update_command.rb | 4 +- lib/rubygems/core_ext/kernel_require.rb | 31 +++--- lib/rubygems/dependency_installer.rb | 148 ---------------------------- lib/rubygems/ext/builder.rb | 4 +- lib/rubygems/install_update_options.rb | 4 +- lib/rubygems/installer.rb | 37 ++++--- lib/rubygems/installer_uninstaller_utils.rb | 8 +- lib/rubygems/source_specific_file.rb | 6 -- lib/rubygems/spec_fetcher.rb | 23 +++-- lib/rubygems/specification.rb | 14 +-- lib/rubygems/test_case.rb | 19 +++- lib/rubygems/uninstaller.rb | 5 +- 16 files changed, 144 insertions(+), 248 deletions(-) delete mode 100644 lib/rubygems/source_specific_file.rb (limited to 'lib') diff --git a/lib/rubygems.rb b/lib/rubygems.rb index f7380c7154..9bd4e9be20 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -190,6 +190,8 @@ module Gem @pre_reset_hooks ||= [] @post_reset_hooks ||= [] + @default_source_date_epoch = nil + ## # Try to activate a gem containing +path+. Returns true if # activation succeeded or wasn't needed because it was already @@ -316,6 +318,13 @@ module Gem Gem.default_bindir end + ## + # The path were rubygems plugins are to be installed. + + def self.plugindir(install_dir=Gem.dir) + File.join install_dir, 'plugins' + end + ## # Reset the +dir+ and +path+ values. The next time +dir+ or +path+ # is requested, the values will be calculated from scratch. This is @@ -423,10 +432,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} paths.spec_cache_dir end - def self.plugins_dir - File.join(dir, "plugins") - end - ## # Quietly ensure the Gem directory +dir+ contains all the proper # subdirectories. If we can't create a directory due to a permission @@ -466,7 +471,10 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} subdirs.each do |name| subdir = File.join dir, name next if File.exist? subdir - FileUtils.mkdir_p subdir, **options rescue nil + begin + FileUtils.mkdir_p subdir, **options + rescue Errno::EACCES + end end ensure File.umask old_umask @@ -863,8 +871,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} def self.ruby if @ruby.nil? - @ruby = File.join(RbConfig::CONFIG['bindir'], - "#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}") + @ruby = RbConfig.ruby @ruby = "\"#{@ruby}\"" if @ruby =~ /\s/ end @@ -1099,7 +1106,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} # Find rubygems plugin files in the standard location and load them def self.load_plugins - load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugins_dir) + load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir) end ## @@ -1182,20 +1189,43 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} end ## - # The SOURCE_DATE_EPOCH environment variable (or, if that's not set, the current time), converted to Time object. - # This is used throughout RubyGems for enabling reproducible builds. + # If the SOURCE_DATE_EPOCH environment variable is set, returns it's value. + # Otherwise, returns the time that `Gem.source_date_epoch_string` was + # first called in the same format as SOURCE_DATE_EPOCH. + # + # NOTE(@duckinator): The implementation is a tad weird because we want to: + # 1. Make builds reproducible by default, by having this function always + # return the same result during a given run. + # 2. Allow changing ENV['SOURCE_DATE_EPOCH'] at runtime, since multiple + # tests that set this variable will be run in a single process. # - # If it is not set as an environment variable already, this also sets it. + # If you simplify this function and a lot of tests fail, that is likely + # due to #2 above. # # Details on SOURCE_DATE_EPOCH: # https://reproducible-builds.org/specs/source-date-epoch/ - def self.source_date_epoch - if ENV["SOURCE_DATE_EPOCH"].nil? || ENV["SOURCE_DATE_EPOCH"].empty? - ENV["SOURCE_DATE_EPOCH"] = Time.now.to_i.to_s - end + def self.source_date_epoch_string + # The value used if $SOURCE_DATE_EPOCH is not set. + @default_source_date_epoch ||= Time.now.to_i.to_s + + specified_epoch = ENV["SOURCE_DATE_EPOCH"] + + # If it's empty or just whitespace, treat it like it wasn't set at all. + specified_epoch = nil if !specified_epoch.nil? && specified_epoch.strip.empty? + + epoch = specified_epoch || @default_source_date_epoch + + epoch.strip + end - Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc.freeze + ## + # Returns the value of Gem.source_date_epoch_string, as a Time object. + # + # This is used throughout RubyGems for enabling reproducible builds. + + def self.source_date_epoch + Time.at(self.source_date_epoch_string.to_i).utc.freeze end # FIX: Almost everywhere else we use the `def self.` way of defining class diff --git a/lib/rubygems/bundler_version_finder.rb b/lib/rubygems/bundler_version_finder.rb index 38da7738a8..ea6698f26e 100644 --- a/lib/rubygems/bundler_version_finder.rb +++ b/lib/rubygems/bundler_version_finder.rb @@ -82,12 +82,19 @@ To install the missing version, run `gem install bundler:#{vr.first}` def self.lockfile_contents gemfile = ENV["BUNDLE_GEMFILE"] gemfile = nil if gemfile && gemfile.empty? - Gem::Util.traverse_parents Dir.pwd do |directory| - next unless gemfile = Gem::GEM_DEP_FILES.find { |f| File.file?(f.tap(&Gem::UNTAINT)) } - gemfile = File.join directory, gemfile - break - end unless gemfile + unless gemfile + begin + Gem::Util.traverse_parents(Dir.pwd) do |directory| + next unless gemfile = Gem::GEM_DEP_FILES.find { |f| File.file?(f.tap(&Gem::UNTAINT)) } + + gemfile = File.join directory, gemfile + break + end + rescue Errno::ENOENT + return + end + end return unless gemfile diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb index 11b6645e9d..9b7b41d3a7 100644 --- a/lib/rubygems/command.rb +++ b/lib/rubygems/command.rb @@ -77,7 +77,7 @@ class Gem::Command when Array @extra_args = value when String - @extra_args = value.split(' ') + @extra_args = value.split end end @@ -174,8 +174,7 @@ class Gem::Command alert_error msg unless suppress_suggestions - suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name gem_name - + suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name(gem_name, :latest, 10) unless suggestions.empty? alert_error "Possible alternatives: #{suggestions.join(", ")}" end @@ -625,8 +624,7 @@ class Gem::Command # :stopdoc: HELP = <<-HELP.freeze -RubyGems is a sophisticated package manager for Ruby. This is a -basic help message containing pointers to more information. +RubyGems is a package manager for Ruby. Usage: gem -h/--help diff --git a/lib/rubygems/commands/contents_command.rb b/lib/rubygems/commands/contents_command.rb index 26d6828fe6..989ca5855c 100644 --- a/lib/rubygems/commands/contents_command.rb +++ b/lib/rubygems/commands/contents_command.rb @@ -167,7 +167,7 @@ prefix or only the files that are requireable. end def spec_for(name) - spec = Gem::Specification.find_all_by_name(name, @version).last + spec = Gem::Specification.find_all_by_name(name, @version).first return spec if spec diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index 7031ac0dd0..494b3eef67 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -184,14 +184,14 @@ command to remove old versions. else require "tmpdir" tmpdir = Dir.mktmpdir - FileUtils.mv Gem.plugins_dir, tmpdir + FileUtils.mv Gem.plugindir, tmpdir status = yield if status FileUtils.rm_rf tmpdir else - FileUtils.mv File.join(tmpdir, "plugins"), Gem.plugins_dir + FileUtils.mv File.join(tmpdir, "plugins"), Gem.plugindir end status diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index 60f4d18712..a8d170f13a 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -43,18 +43,21 @@ module Kernel # https://github.com/rubygems/rubygems/pull/1868 resolved_path = begin rp = nil - $LOAD_PATH[0...Gem.load_path_insert_index || -1].each do |lp| - safe_lp = lp.dup.tap(&Gem::UNTAINT) - begin - if File.symlink? safe_lp # for backward compatibility - next + Gem.suffixes.each do |s| + load_path_insert_index = Gem.load_path_insert_index + break unless load_path_insert_index + + $LOAD_PATH[0...load_path_insert_index].each do |lp| + safe_lp = lp.dup.tap(&Gem::UNTAINT) + begin + if File.symlink? safe_lp # for backward compatibility + next + end + rescue SecurityError + RUBYGEMS_ACTIVATION_MONITOR.exit + raise end - rescue SecurityError - RUBYGEMS_ACTIVATION_MONITOR.exit - raise - end - Gem.suffixes.each do |s| full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}")) if File.file?(full_path) rp = full_path @@ -67,12 +70,8 @@ module Kernel end if resolved_path - begin - RUBYGEMS_ACTIVATION_MONITOR.exit - return gem_original_require(resolved_path) - rescue LoadError - RUBYGEMS_ACTIVATION_MONITOR.enter - end + RUBYGEMS_ACTIVATION_MONITOR.exit + return gem_original_require(resolved_path) end if spec = Gem.find_unresolved_default_spec(path) diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb index 6d45688888..14ff8beab2 100644 --- a/lib/rubygems/dependency_installer.rb +++ b/lib/rubygems/dependency_installer.rb @@ -7,7 +7,6 @@ require 'rubygems/spec_fetcher' require 'rubygems/user_interaction' require 'rubygems/source' require 'rubygems/available_set' -require 'rubygems/deprecate' ## # Installs a gem along with all its dependencies from local and remote gems. @@ -15,7 +14,6 @@ require 'rubygems/deprecate' class Gem::DependencyInstaller include Gem::UserInteraction - extend Gem::Deprecate DEFAULT_OPTIONS = { # :nodoc: :env_shebang => false, @@ -106,27 +104,6 @@ class Gem::DependencyInstaller @errors = [] end - ## - # Creates an AvailableSet to install from based on +dep_or_name+ and - # +version+ - - def available_set_for(dep_or_name, version) # :nodoc: - if String === dep_or_name - Gem::Deprecate.skip_during do - find_spec_by_name_and_version dep_or_name, version, @prerelease - end - else - dep = dep_or_name.dup - dep.prerelease = @prerelease - @available = Gem::Deprecate.skip_during do - find_gems_with_sources dep - end - end - - @available.pick_best! - end - deprecate :available_set_for, :none, 2019, 12 - ## # Indicated, based on the requested domain, if local # gems should be considered. @@ -143,131 +120,6 @@ class Gem::DependencyInstaller @domain == :both or @domain == :remote end - ## - # Returns a list of pairs of gemspecs and source_uris that match - # Gem::Dependency +dep+ from both local (Dir.pwd) and remote (Gem.sources) - # sources. Gems are sorted with newer gems preferred over older gems, and - # local gems preferred over remote gems. - - def find_gems_with_sources(dep, best_only=false) # :nodoc: - set = Gem::AvailableSet.new - - if consider_local? - sl = Gem::Source::Local.new - - if spec = sl.find_gem(dep.name) - if dep.matches_spec? spec - set.add spec, sl - end - end - end - - if consider_remote? - begin - # This is pulled from #spec_for_dependency to allow - # us to filter tuples before fetching specs. - tuples, errors = Gem::SpecFetcher.fetcher.search_for_dependency dep - - if best_only && !tuples.empty? - tuples.sort! do |a,b| - if b[0].version == a[0].version - if b[0].platform != Gem::Platform::RUBY - 1 - else - -1 - end - else - b[0].version <=> a[0].version - end - end - tuples = [tuples.first] - end - - specs = [] - tuples.each do |tup, source| - begin - spec = source.fetch_spec(tup) - rescue Gem::RemoteFetcher::FetchError => e - errors << Gem::SourceFetchProblem.new(source, e) - else - specs << [spec, source] - end - end - - if @errors - @errors += errors - else - @errors = errors - end - - set << specs - - rescue Gem::RemoteFetcher::FetchError => e - # FIX if there is a problem talking to the network, we either need to always tell - # the user (no really_verbose) or fail hard, not silently tell them that we just - # couldn't find their requested gem. - verbose do - "Error fetching remote data:\t\t#{e.message}\n" \ - "Falling back to local-only install" - end - @domain = :local - end - end - - set - end - deprecate :find_gems_with_sources, :none, 2019, 12 - - ## - # Finds a spec and the source_uri it came from for gem +gem_name+ and - # +version+. Returns an Array of specs and sources required for - # installation of the gem. - - def find_spec_by_name_and_version(gem_name, - version = Gem::Requirement.default, - prerelease = false) - set = Gem::AvailableSet.new - - if consider_local? - if gem_name =~ /\.gem$/ and File.file? gem_name - src = Gem::Source::SpecificFile.new(gem_name) - set.add src.spec, src - elsif gem_name =~ /\.gem$/ - Dir[gem_name].each do |name| - begin - src = Gem::Source::SpecificFile.new name - set.add src.spec, src - rescue Gem::Package::FormatError - end - end - else - local = Gem::Source::Local.new - - if s = local.find_gem(gem_name, version) - set.add s, local - end - end - end - - if set.empty? - dep = Gem::Dependency.new gem_name, version - dep.prerelease = true if prerelease - - set = Gem::Deprecate.skip_during do - find_gems_with_sources(dep, true) - end - - set.match_platform! - end - - if set.empty? - raise Gem::SpecificGemNotFoundException.new(gem_name, version, @errors) - end - - @available = set - end - deprecate :find_spec_by_name_and_version, :none, 2019, 12 - def in_background(what) # :nodoc: fork_happened = false if @build_docs_in_background and Process.respond_to?(:fork) diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index 2fc1074d92..a8bd4c8d1b 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -68,7 +68,9 @@ class Gem::Ext::Builder results << (command.respond_to?(:shelljoin) ? command.shelljoin : command) require "open3" - output, status = Open3.capture2e(*command) + # Set $SOURCE_DATE_EPOCH for the subprocess. + env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string} + output, status = Open3.capture2e(env, *command) if verbose puts output else diff --git a/lib/rubygems/install_update_options.rb b/lib/rubygems/install_update_options.rb index 38a0682958..dbf787c7ba 100644 --- a/lib/rubygems/install_update_options.rb +++ b/lib/rubygems/install_update_options.rb @@ -25,8 +25,8 @@ module Gem::InstallUpdateOptions end add_option(:"Install/Update", '-n', '--bindir DIR', - 'Directory where executables are', - 'located') do |value, options| + 'Directory where executables will be', + 'placed when the gem is installed') do |value, options| options[:bin_dir] = File.expand_path(value) end diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 2ba92482cc..abb7048b00 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -46,11 +46,6 @@ class Gem::Installer include Gem::InstallerUninstallerUtils - ## - # Filename of the gem being installed. - - attr_reader :gem - ## # The directory a gem's executables will be installed into @@ -487,13 +482,7 @@ class Gem::Installer def generate_bin # :nodoc: return if spec.executables.nil? or spec.executables.empty? - begin - Dir.mkdir @bin_dir, *[options[:dir_mode] && 0755].compact - rescue SystemCallError - raise unless File.directory? @bin_dir - end - - raise Gem::FilePermissionError.new(@bin_dir) unless File.writable? @bin_dir + ensure_writable_dir @bin_dir spec.executables.each do |filename| filename.tap(&Gem::UNTAINT) @@ -523,10 +512,12 @@ class Gem::Installer latest = Gem::Specification.latest_spec_for(spec.name) return if latest && latest.version > spec.version + ensure_writable_dir @plugins_dir + if spec.plugins.empty? - remove_plugins_for(spec) + remove_plugins_for(spec, @plugins_dir) else - regenerate_plugins_for(spec) + regenerate_plugins_for(spec, @plugins_dir) end end @@ -690,6 +681,7 @@ class Gem::Installer @force = options[:force] @install_dir = options[:install_dir] @gem_home = options[:install_dir] || Gem.dir + @plugins_dir = Gem.plugindir(@gem_home) @ignore_dependencies = options[:ignore_dependencies] @format_executable = options[:format_executable] @wrappers = options[:wrappers] @@ -889,6 +881,13 @@ TEXT gem_dir.to_s end + ## + # Filename of the gem being installed. + + def gem + @package.gem.path + end + ## # Performs various checks before installing the gem such as the install # repository is writable and its directories exist, required Ruby and @@ -953,4 +952,14 @@ TEXT @package.copy_to cache_file end + def ensure_writable_dir(dir) # :nodoc: + begin + Dir.mkdir dir, *[options[:dir_mode] && 0755].compact + rescue SystemCallError + raise unless File.directory? dir + end + + raise Gem::FilePermissionError.new(dir) unless File.writable? dir + end + end diff --git a/lib/rubygems/installer_uninstaller_utils.rb b/lib/rubygems/installer_uninstaller_utils.rb index b8436f4f0a..e81ed4cba3 100644 --- a/lib/rubygems/installer_uninstaller_utils.rb +++ b/lib/rubygems/installer_uninstaller_utils.rb @@ -5,9 +5,9 @@ module Gem::InstallerUninstallerUtils - def regenerate_plugins_for(spec) + def regenerate_plugins_for(spec, plugins_dir) spec.plugins.each do |plugin| - plugin_script_path = File.join Gem.plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}" + plugin_script_path = File.join plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}" File.open plugin_script_path, 'wb' do |file| file.puts "require '#{plugin}'" @@ -17,8 +17,8 @@ module Gem::InstallerUninstallerUtils end end - def remove_plugins_for(spec) - FileUtils.rm_f Gem::Util.glob_files_in_dir("#{spec.name}#{Gem.plugin_suffix_pattern}", Gem.plugins_dir) + def remove_plugins_for(spec, plugins_dir) + FileUtils.rm_f Gem::Util.glob_files_in_dir("#{spec.name}#{Gem.plugin_suffix_pattern}", plugins_dir) end end diff --git a/lib/rubygems/source_specific_file.rb b/lib/rubygems/source_specific_file.rb deleted file mode 100644 index b676b1d3a2..0000000000 --- a/lib/rubygems/source_specific_file.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true -require 'rubygems/source/specific_file' - -unless Gem::Deprecate.skip - Kernel.warn "#{Gem.location_of_caller(3).join(':')}: Warning: Requiring rubygems/source_specific_file is deprecated; please use rubygems/source/specific_file instead." -end diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb index cf86b72188..56ccaea84d 100644 --- a/lib/rubygems/spec_fetcher.rb +++ b/lib/rubygems/spec_fetcher.rb @@ -171,30 +171,33 @@ class Gem::SpecFetcher # Suggests gems based on the supplied +gem_name+. Returns an array of # alternative gem names. - def suggest_gems_from_name(gem_name, type = :latest) + def suggest_gems_from_name(gem_name, type = :latest, num_results = 5) gem_name = gem_name.downcase.tr('_-', '') max = gem_name.size / 2 names = available_specs(type).first.values.flatten(1) matches = names.map do |n| next unless n.match_platform? - - distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '') - - next if distance >= max - - return [n.name] if distance == 0 - - [n.name, distance] + [n.name, 0] if n.name.downcase.tr('_-', '').include?(gem_name) end.compact + if matches.length < num_results + matches += names.map do |n| + next unless n.match_platform? + distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '') + next if distance >= max + return [n.name] if distance == 0 + [n.name, distance] + end.compact + end + matches = if matches.empty? && type != :prerelease suggest_gems_from_name gem_name, :prerelease else matches.uniq.sort_by { |name, dist| dist } end - matches.first(5).map { |name, dist| name } + matches.map { |name, dist| name }.uniq.first(num_results) end ## diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index ad43a63e80..3181303c30 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -790,16 +790,6 @@ class Gem::Specification < Gem::BasicSpecification end private_class_method :map_stubs - def self.uniq_by(list, &block) # :nodoc: - list.uniq(&block) - end - private_class_method :uniq_by - - def self.sort_by!(list, &block) - list.sort_by!(&block) - end - private_class_method :sort_by! - def self.each_spec(dirs) # :nodoc: each_gemspec(dirs) do |path| spec = self.load path @@ -814,7 +804,7 @@ class Gem::Specification < Gem::BasicSpecification @@stubs ||= begin pattern = "*.gemspec" stubs = Gem.loaded_specs.values + installed_stubs(dirs, pattern) + default_stubs(pattern) - stubs = uniq_by(stubs) { |stub| stub.full_name } + stubs = stubs.uniq { |stub| stub.full_name } _resort!(stubs) @@stubs_by_name = stubs.select { |s| Gem::Platform.match s.platform }.group_by(&:name) @@ -847,7 +837,7 @@ class Gem::Specification < Gem::BasicSpecification stubs = Gem.loaded_specs.values + installed_stubs(dirs, pattern).select { |s| Gem::Platform.match s.platform } + default_stubs(pattern) - stubs = uniq_by(stubs) { |stub| stub.full_name }.group_by(&:name) + stubs = stubs.uniq { |stub| stub.full_name }.group_by(&:name) stubs.each_value { |v| _resort!(v) } @@stubs_by_name.merge! stubs diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb index 691985dcd2..ebfe979a1b 100644 --- a/lib/rubygems/test_case.rb +++ b/lib/rubygems/test_case.rb @@ -78,6 +78,20 @@ module Gem end end +require "rubygems/command" + +class Gem::Command + + ## + # Allows resetting the hash of specific args per command. This method is + # available when requiring 'rubygems/test_case' + + def self.specific_extra_args_hash=(value) + @specific_extra_args_hash = value + end + +end + ## # RubyGemTestCase provides a variety of methods for testing rubygems and # gem-related behavior in a sandbox. Through RubyGemTestCase you can install @@ -1246,10 +1260,7 @@ Also, a list: end begin - require "rbconfig" - File.join(RbConfig::CONFIG["bindir"], - RbConfig::CONFIG["ruby_install_name"] + - RbConfig::CONFIG["EXEEXT"]) + Gem.ruby rescue LoadError "ruby" end diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index 1766423429..69893dfb76 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -50,6 +50,7 @@ class Gem::Uninstaller @gem = gem @version = options[:version] || Gem::Requirement.default @gem_home = File.realpath(options[:install_dir] || Gem.dir) + @plugins_dir = Gem.plugindir(@gem_home) @force_executables = options[:executables] @force_all = options[:all] @force_ignore = options[:ignore] @@ -281,7 +282,7 @@ class Gem::Uninstaller def remove_plugins(spec) # :nodoc: return if spec.plugins.empty? - remove_plugins_for(spec) + remove_plugins_for(spec, @plugins_dir) end ## @@ -291,7 +292,7 @@ class Gem::Uninstaller latest = Gem::Specification.latest_spec_for(@spec.name) return if latest.nil? - regenerate_plugins_for(latest) + regenerate_plugins_for(latest, @plugins_dir) end ## -- cgit v1.2.3