diff options
Diffstat (limited to 'lib/bundler/rubygems_ext.rb')
-rw-r--r-- | lib/bundler/rubygems_ext.rb | 160 |
1 files changed, 132 insertions, 28 deletions
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index e0582beba2..0f0680560a 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -1,11 +1,7 @@ # frozen_string_literal: true -require "pathname" - require "rubygems" unless defined?(Gem) -require "rubygems/specification" - # We can't let `Gem::Source` be autoloaded in the `Gem::Specification#source` # redefinition below, so we need to load it upfront. The reason is that if # Bundler monkeypatches are loaded before RubyGems activates an executable (for @@ -17,10 +13,6 @@ require "rubygems/specification" # `Gem::Source` from the redefined `Gem::Specification#source`. require "rubygems/source" -require_relative "match_metadata" -require_relative "force_platform" -require_relative "match_platform" - # Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler # versions and ignore patchlevels # (https://github.com/rubygems/rubygems/pull/5472, @@ -31,7 +23,60 @@ unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1 end module Gem + # Can be removed once RubyGems 3.5.11 support is dropped + unless Gem.respond_to?(:freebsd_platform?) + def self.freebsd_platform? + RbConfig::CONFIG["host_os"].to_s.include?("bsd") + end + end + + # Can be removed once RubyGems 3.5.18 support is dropped + unless Gem.respond_to?(:open_file_with_lock) + class << self + remove_method :open_file_with_flock if Gem.respond_to?(:open_file_with_flock) + + def open_file_with_flock(path, &block) + mode = IO::RDONLY | IO::APPEND | IO::CREAT | IO::BINARY + mode |= IO::SHARE_DELETE if IO.const_defined?(:SHARE_DELETE) + + File.open(path, mode) do |io| + begin + io.flock(File::LOCK_EX) + rescue Errno::ENOSYS, Errno::ENOTSUP + rescue Errno::ENOLCK # NFS + raise unless Thread.main == Thread.current + end + yield io + end + end + + def open_file_with_lock(path, &block) + file_lock = "#{path}.lock" + open_file_with_flock(file_lock, &block) + ensure + FileUtils.rm_f file_lock + end + end + end + + require "rubygems/specification" + + # Can be removed once RubyGems 3.5.14 support is dropped + VALIDATES_FOR_RESOLUTION = Specification.new.respond_to?(:validate_for_resolution).freeze + + # Can be removed once RubyGems 3.3.15 support is dropped + FLATTENS_REQUIRED_PATHS = Specification.new.respond_to?(:flatten_require_paths).freeze + class Specification + # Can be removed once RubyGems 3.5.15 support is dropped + correct_array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys + unless @@array_attributes == correct_array_attributes + @@array_attributes = correct_array_attributes # rubocop:disable Style/ClassVars + end + + require_relative "match_metadata" + require_relative "match_platform" + include ::Bundler::MatchMetadata include ::Bundler::MatchPlatform @@ -48,7 +93,7 @@ module Gem def full_gem_path if source.respond_to?(:root) - Pathname.new(loaded_from).dirname.expand_path(source.root).to_s + File.expand_path(File.dirname(loaded_from), source.root) else rg_full_gem_path end @@ -78,11 +123,6 @@ module Gem end end - remove_method :gem_dir - def gem_dir - full_gem_path - end - unless const_defined?(:LATEST_RUBY_WITHOUT_PATCH_VERSIONS) LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1") @@ -127,6 +167,33 @@ module Gem !default_gem? && !File.directory?(full_gem_path) end + unless VALIDATES_FOR_RESOLUTION + def validate_for_resolution + SpecificationPolicy.new(self).validate_for_resolution + end + end + + unless FLATTENS_REQUIRED_PATHS + def flatten_require_paths + return unless raw_require_paths.first.is_a?(Array) + + warn "#{name} #{version} includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this" + raw_require_paths.flatten! + end + + class << self + module RequirePathFlattener + def from_yaml(input) + spec = super(input) + spec.flatten_require_paths + spec + end + end + + prepend RequirePathFlattener + end + end + private def dependencies_to_gemfile(dependencies, group = nil) @@ -146,29 +213,47 @@ module Gem end end + unless VALIDATES_FOR_RESOLUTION + class SpecificationPolicy + def validate_for_resolution + validate_required! + end + end + end + + module BetterPermissionError + def data + super + rescue Errno::EACCES + raise Bundler::PermissionError.new(loaded_from, :read) + end + end + + require "rubygems/stub_specification" + + class StubSpecification + prepend BetterPermissionError + end + class Dependency + require_relative "force_platform" + include ::Bundler::ForcePlatform + attr_reader :force_ruby_platform + attr_accessor :source, :groups alias_method :eql?, :== - def force_ruby_platform - return @force_ruby_platform if defined?(@force_ruby_platform) && !@force_ruby_platform.nil? - - @force_ruby_platform = default_force_ruby_platform - end - - def encode_with(coder) - to_yaml_properties.each do |ivar| - coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar) + unless method_defined?(:encode_with, false) + def encode_with(coder) + [:@name, :@requirement, :@type, :@prerelease, :@version_requirements].each do |ivar| + coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar) + end end end - def to_yaml_properties - instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) } - end - def to_lock out = String.new(" #{name}") unless requirement.none? @@ -221,7 +306,7 @@ module Gem # cpu ([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu || - (@cpu == "arm" && other.cpu.start_with?("arm"))) && + (@cpu == "arm" && other.cpu.start_with?("armv"))) && # os @os == other.os && @@ -325,4 +410,23 @@ module Gem end end end + + unless Gem.rubygems_version >= Gem::Version.new("3.5.19") + class Resolver::ActivationRequest + remove_method :installed? + + def installed? + case @spec + when Gem::Resolver::VendorSpecification then + true + else + this_spec = full_spec + + Gem::Specification.any? do |s| + s == this_spec && s.base_dir == this_spec.base_dir + end + end + end + end + end end |