summaryrefslogtreecommitdiff
path: root/lib/rubygems.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rubygems.rb')
-rw-r--r--lib/rubygems.rb150
1 files changed, 91 insertions, 59 deletions
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 915a899f38..ad7ab10756 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -8,7 +9,7 @@
require "rbconfig"
module Gem
- VERSION = "3.4.0.dev".freeze
+ VERSION = "3.6.0.dev"
end
# Must be first since it unloads the prelude from 1.9.2
@@ -114,15 +115,6 @@ require_relative "rubygems/errors"
module Gem
RUBYGEMS_DIR = __dir__
- # Taint support is deprecated in Ruby 2.7.
- # This allows switching ".untaint" to ".tap(&Gem::UNTAINT)",
- # to avoid deprecation warnings in Ruby 2.7.
- UNTAINT = RUBY_VERSION < "2.7" ? :untaint.to_sym : proc {}
-
- # When https://bugs.ruby-lang.org/issues/17259 is available, there is no need to override Kernel#warn
- KERNEL_WARN_IGNORES_INTERNAL_ENTRIES = RUBY_ENGINE == "truffleruby" ||
- (RUBY_ENGINE == "ruby" && RUBY_VERSION >= "3.0")
-
##
# An Array of Regexps that match windows Ruby platforms.
@@ -185,6 +177,8 @@ module Gem
@default_source_date_epoch = nil
+ @discover_gems_on_require = true
+
##
# Try to activate a gem containing +path+. Returns true if
# activation succeeded or wasn't needed because it was already
@@ -212,7 +206,7 @@ module Gem
end
end
- return true
+ true
end
def self.needs
@@ -340,16 +334,6 @@ module Gem
end
##
- # The path to the data directory specified by the gem name. If the
- # package is not available as a gem, return nil.
-
- def self.datadir(gem_name)
- spec = @loaded_specs[gem_name]
- return nil if spec.nil?
- spec.datadir
- end
-
- ##
# A Zlib::Deflate.deflate wrapper
def self.deflate(data)
@@ -440,7 +424,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.ensure_subdirectories(dir, mode, subdirs) # :nodoc:
old_umask = File.umask
- File.umask old_umask | 002
+ File.umask old_umask | 0o002
options = {}
@@ -466,7 +450,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# distinction as extensions cannot be shared between the two.
def self.extension_api_version # :nodoc:
- if "no" == RbConfig::CONFIG["ENABLE_SHARED"]
+ if RbConfig::CONFIG["ENABLE_SHARED"] == "no"
"#{ruby_api_version}-static"
else
ruby_api_version
@@ -500,14 +484,14 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# the spec dirs directly, so we prune.
files.uniq! if check_load_path
- return files
+ files
end
def self.find_files_from_load_path(glob) # :nodoc:
glob_with_suffixes = "#{glob}#{Gem.suffix_pattern}"
$LOAD_PATH.map do |load_path|
Gem::Util.glob_files_in_dir(glob_with_suffixes, load_path)
- end.flatten.select {|file| File.file? file.tap(&Gem::UNTAINT) }
+ end.flatten.select {|file| File.file? file }
end
##
@@ -535,7 +519,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# the spec dirs directly, so we prune.
files.uniq! if check_load_path
- return files
+ files
end
##
@@ -583,7 +567,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
##
# The number of paths in the +$LOAD_PATH+ from activated gems. Used to
- # prioritize +-I+ and +ENV['RUBYLIB']+ entries during +require+.
+ # prioritize +-I+ and <code>ENV['RUBYLIB']</code> entries during +require+.
def self.activated_gem_paths
@activated_gem_paths ||= 0
@@ -615,6 +599,16 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
@yaml_loaded = true
end
+ @safe_marshal_loaded = false
+
+ def self.load_safe_marshal
+ return if @safe_marshal_loaded
+
+ require_relative "rubygems/safe_marshal"
+
+ @safe_marshal_loaded = true
+ end
+
##
# The file name and line number of the caller of the caller of this method.
#
@@ -743,7 +737,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
if prefix != File.expand_path(RbConfig::CONFIG["sitelibdir"]) &&
prefix != File.expand_path(RbConfig::CONFIG["libdir"]) &&
- "lib" == File.basename(RUBYGEMS_DIR)
+ File.basename(RUBYGEMS_DIR) == "lib"
prefix
end
end
@@ -759,13 +753,9 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Safely read a file in binary mode on all platforms.
def self.read_binary(path)
- open_file(path, "rb+") do |io|
- io.read
- end
+ open_file(path, "rb+", &:read)
rescue Errno::EACCES, Errno::EROFS
- open_file(path, "rb") do |io|
- io.read
- end
+ open_file(path, "rb", &:read)
end
##
@@ -774,6 +764,10 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
open_file(path, "wb") do |io|
io.write data
end
+ rescue Errno::ENOSPC
+ # If we ran out of space but the file exists, it's *guaranteed* to be corrupted.
+ File.delete(path) if File.exist?(path)
+ raise
end
##
@@ -806,7 +800,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
if @ruby.nil?
@ruby = RbConfig.ruby
- @ruby = "\"#{@ruby}\"" if @ruby =~ /\s/
+ @ruby = "\"#{@ruby}\"" if /\s/.match?(@ruby)
end
@ruby
@@ -822,7 +816,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.env_requirement(gem_name)
@env_requirements_by_name ||= {}
@env_requirements_by_name[gem_name] ||= begin
- req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || ">= 0".freeze
+ req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || ">= 0"
Gem::Requirement.create(req)
end
end
@@ -853,8 +847,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Returns the version of the latest release-version of gem +name+
def self.latest_version_for(name)
- spec = latest_spec_for name
- spec && spec.version
+ latest_spec_for(name)&.version
end
##
@@ -864,7 +857,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
return @ruby_version if defined? @ruby_version
version = RUBY_VERSION.dup
- unless defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1
+ if RUBY_PATCHLEVEL == -1
if RUBY_ENGINE == "ruby"
desc = RUBY_DESCRIPTION[/\Aruby #{Regexp.quote(RUBY_VERSION)}([^ ]+) /, 1]
else
@@ -912,7 +905,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Glob pattern for require-able path suffixes.
def self.suffix_pattern
- @suffix_pattern ||= "{#{suffixes.join(',')}}"
+ @suffix_pattern ||= "{#{suffixes.join(",")}}"
end
##
@@ -946,8 +939,14 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
val = RbConfig::CONFIG[key]
next unless val && !val.empty?
".#{val}"
- end,
- ].compact.uniq
+ end].compact.uniq
+ end
+
+ ##
+ # Suffixes for dynamic library require-able paths.
+
+ def self.dynamic_library_suffixes
+ @dynamic_library_suffixes ||= suffixes - [".rb"]
end
##
@@ -961,7 +960,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
elapsed = Time.now - now
- ui.say "%2$*1$s: %3$3.3fs" % [-width, msg, elapsed] if display
+ ui.say format("%2$*1$s: %3$3.3fs", -width, msg, elapsed) if display
value
end
@@ -993,7 +992,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.win_platform?
if @@win_platform.nil?
ruby_platform = RbConfig::CONFIG["host_os"]
- @@win_platform = !!WIN_PATTERNS.find {|r| ruby_platform =~ r }
+ @@win_platform = !WIN_PATTERNS.find {|r| ruby_platform =~ r }.nil?
end
@@win_platform
@@ -1021,11 +1020,11 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Skip older versions of the GemCutter plugin: Its commands are in
# RubyGems proper now.
- next if plugin =~ /gemcutter-0\.[0-3]/
+ next if /gemcutter-0\.[0-3]/.match?(plugin)
begin
load plugin
- rescue ::Exception => e
+ rescue ScriptError, StandardError => e
details = "#{plugin.inspect}: #{e.message} (#{e.class})"
warn "Error loading RubyGems plugin #{details}"
end
@@ -1087,8 +1086,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
end
- path.tap(&Gem::UNTAINT)
-
unless File.file? path
return unless raise_exception
@@ -1100,13 +1097,11 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
require "bundler"
begin
Gem::DefaultUserInteraction.use_ui(ui) do
- begin
- Bundler.ui.silence do
- @gemdeps = Bundler.setup
- end
- ensure
- Gem::DefaultUserInteraction.ui.close
+ Bundler.ui.silence do
+ @gemdeps = Bundler.setup
end
+ ensure
+ Gem::DefaultUserInteraction.ui.close
end
rescue Bundler::BundlerError => e
warn e.message
@@ -1152,7 +1147,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# 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
+ Time.at(source_date_epoch_string.to_i).utc.freeze
end
# FIX: Almost everywhere else we use the `def self.` way of defining class
@@ -1163,9 +1158,17 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# RubyGems distributors (like operating system package managers) can
# disable RubyGems update by setting this to error message printed to
# end-users on gem update --system instead of actual update.
+
attr_accessor :disable_system_update_message
##
+ # Whether RubyGems should enhance builtin `require` to automatically
+ # check whether the path required is present in installed gems, and
+ # automatically activate them and add them to `$LOAD_PATH`.
+
+ attr_accessor :discover_gems_on_require
+
+ ##
# Hash of loaded Gem::Specification keyed by name
attr_reader :loaded_specs
@@ -1213,9 +1216,16 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
##
# Find a Gem::Specification of default gem from +path+
+ def find_default_spec(path)
+ @path_to_default_spec_map[path]
+ end
+
+ ##
+ # Find an unresolved Gem::Specification of default gem from +path+
+
def find_unresolved_default_spec(path)
default_spec = @path_to_default_spec_map[path]
- return default_spec if default_spec && loaded_specs[default_spec.name] != default_spec
+ default_spec if default_spec && loaded_specs[default_spec.name] != default_spec
end
##
@@ -1293,8 +1303,8 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/".freeze
- autoload :BundlerVersionFinder, File.expand_path("rubygems/bundler_version_finder", __dir__)
autoload :ConfigFile, File.expand_path("rubygems/config_file", __dir__)
+ autoload :CIDetector, File.expand_path("rubygems/ci_detector", __dir__)
autoload :Dependency, File.expand_path("rubygems/dependency", __dir__)
autoload :DependencyList, File.expand_path("rubygems/dependency_list", __dir__)
autoload :Installer, File.expand_path("rubygems/installer", __dir__)
@@ -1341,10 +1351,32 @@ begin
rescue LoadError
end
+# TruffleRuby >= 24 defines REUSE_AS_BINARY_ON_TRUFFLERUBY in defaults/truffleruby.
+# However, TruffleRuby < 24 defines REUSE_AS_BINARY_ON_TRUFFLERUBY directly in its copy
+# of lib/rubygems/platform.rb, so it is not defined if RubyGems is updated (gem update --system).
+# Instead, we define it here in that case, similar to bundler/lib/bundler/rubygems_ext.rb.
+# We must define it here and not in platform.rb because platform.rb is loaded before defaults/truffleruby.
+class Gem::Platform
+ if RUBY_ENGINE == "truffleruby" && !defined?(REUSE_AS_BINARY_ON_TRUFFLERUBY)
+ REUSE_AS_BINARY_ON_TRUFFLERUBY = %w[libv8 libv8-node sorbet-static].freeze
+ end
+end
+
##
# Loads the default specs.
Gem::Specification.load_defaults
require_relative "rubygems/core_ext/kernel_gem"
-require_relative "rubygems/core_ext/kernel_require"
-require_relative "rubygems/core_ext/kernel_warn"
+
+path = File.join(__dir__, "rubygems/core_ext/kernel_require.rb")
+# When https://bugs.ruby-lang.org/issues/17259 is available, there is no need to override Kernel#warn
+if RUBY_ENGINE == "truffleruby" ||
+ RUBY_ENGINE == "ruby"
+ file = "<internal:#{path}>"
+else
+ require_relative "rubygems/core_ext/kernel_warn"
+ file = path
+end
+eval File.read(path), nil, file
+
+require ENV["BUNDLER_SETUP"] if ENV["BUNDLER_SETUP"] && !defined?(Bundler)