Move most of Bundler::GemHelpers to Gem::Platform
This will help centralize wheel platform selection logic eventually Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
This commit is contained in:
parent
6a9af9f0b5
commit
c0a1e877b3
@ -53,7 +53,6 @@ module Bundler
|
|||||||
autoload :FeatureFlag, File.expand_path("bundler/feature_flag", __dir__)
|
autoload :FeatureFlag, File.expand_path("bundler/feature_flag", __dir__)
|
||||||
autoload :FREEBSD, File.expand_path("bundler/constants", __dir__)
|
autoload :FREEBSD, File.expand_path("bundler/constants", __dir__)
|
||||||
autoload :GemHelper, File.expand_path("bundler/gem_helper", __dir__)
|
autoload :GemHelper, File.expand_path("bundler/gem_helper", __dir__)
|
||||||
autoload :GemHelpers, File.expand_path("bundler/gem_helpers", __dir__)
|
|
||||||
autoload :GemVersionPromoter, File.expand_path("bundler/gem_version_promoter", __dir__)
|
autoload :GemVersionPromoter, File.expand_path("bundler/gem_version_promoter", __dir__)
|
||||||
autoload :Graph, File.expand_path("bundler/graph", __dir__)
|
autoload :Graph, File.expand_path("bundler/graph", __dir__)
|
||||||
autoload :Index, File.expand_path("bundler/index", __dir__)
|
autoload :Index, File.expand_path("bundler/index", __dir__)
|
||||||
@ -459,6 +458,10 @@ module Bundler
|
|||||||
Gem::Platform.local
|
Gem::Platform.local
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generic_local_platform
|
||||||
|
Gem::Platform.generic(local_platform)
|
||||||
|
end
|
||||||
|
|
||||||
def default_gemfile
|
def default_gemfile
|
||||||
SharedHelpers.default_gemfile
|
SharedHelpers.default_gemfile
|
||||||
end
|
end
|
||||||
|
@ -155,7 +155,7 @@ module Bundler
|
|||||||
|
|
||||||
return active_spec if strict
|
return active_spec if strict
|
||||||
|
|
||||||
active_specs = active_spec.source.specs.search(current_spec.name).select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
|
active_specs = active_spec.source.specs.search(current_spec.name).select {|spec| spec.installable_on_platform?(current_spec.platform) }.sort_by(&:version)
|
||||||
if !current_spec.version.prerelease? && !options[:pre] && active_specs.size > 1
|
if !current_spec.version.prerelease? && !options[:pre] && active_specs.size > 1
|
||||||
active_specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? }
|
active_specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? }
|
||||||
end
|
end
|
||||||
|
@ -92,7 +92,7 @@ module Bundler
|
|||||||
locked_spec = locked_info[:spec]
|
locked_spec = locked_info[:spec]
|
||||||
new_spec = Bundler.definition.specs[name].first
|
new_spec = Bundler.definition.specs[name].first
|
||||||
unless new_spec
|
unless new_spec
|
||||||
unless locked_spec.match_platform(Bundler.local_platform)
|
unless locked_spec.installable_on_platform?(Bundler.local_platform)
|
||||||
Bundler.ui.warn "Bundler attempted to update #{name} but it was not considered because it is for a different platform from the current one"
|
Bundler.ui.warn "Bundler attempted to update #{name} but it was not considered because it is for a different platform from the current one"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ module Bundler
|
|||||||
end.freeze
|
end.freeze
|
||||||
|
|
||||||
def ruby?
|
def ruby?
|
||||||
return true if Bundler::GemHelpers.generic_local_platform_is_ruby?
|
return true if Bundler::MatchPlatform.generic_local_platform_is_ruby?
|
||||||
|
|
||||||
!windows? && (RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev" || RUBY_ENGINE == "truffleruby")
|
!windows? && (RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev" || RUBY_ENGINE == "truffleruby")
|
||||||
end
|
end
|
||||||
|
@ -4,8 +4,6 @@ require_relative "lockfile_parser"
|
|||||||
|
|
||||||
module Bundler
|
module Bundler
|
||||||
class Definition
|
class Definition
|
||||||
include GemHelpers
|
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
# Do not create or modify a lockfile (Makes #lock a noop)
|
# Do not create or modify a lockfile (Makes #lock a noop)
|
||||||
attr_accessor :no_lock
|
attr_accessor :no_lock
|
||||||
@ -282,7 +280,7 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def filter_relevant(dependencies)
|
def filter_relevant(dependencies)
|
||||||
platforms_array = [generic_local_platform].freeze
|
platforms_array = [Bundler.generic_local_platform].freeze
|
||||||
dependencies.select do |d|
|
dependencies.select do |d|
|
||||||
d.should_include? && !d.gem_platforms(platforms_array).empty?
|
d.should_include? && !d.gem_platforms(platforms_array).empty?
|
||||||
end
|
end
|
||||||
@ -456,8 +454,8 @@ module Bundler
|
|||||||
return if current_platform_locked? || @platforms.include?(Gem::Platform::RUBY)
|
return if current_platform_locked? || @platforms.include?(Gem::Platform::RUBY)
|
||||||
|
|
||||||
raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
|
raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
|
||||||
"but your local platform is #{local_platform}. " \
|
"but your local platform is #{Bundler.local_platform}. " \
|
||||||
"Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
|
"Add the current platform to the lockfile with\n`bundle lock --add-platform #{Bundler.local_platform}` and try again."
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_platforms
|
def normalize_platforms
|
||||||
@ -568,7 +566,7 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def should_add_extra_platforms?
|
def should_add_extra_platforms?
|
||||||
!lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
|
!lockfile_exists? && Bundler::MatchPlatform.generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
|
||||||
end
|
end
|
||||||
|
|
||||||
def lockfile_exists?
|
def lockfile_exists?
|
||||||
@ -632,7 +630,7 @@ module Bundler
|
|||||||
@resolution_base ||= begin
|
@resolution_base ||= begin
|
||||||
last_resolve = converge_locked_specs
|
last_resolve = converge_locked_specs
|
||||||
remove_invalid_platforms!
|
remove_invalid_platforms!
|
||||||
new_resolution_platforms = @current_platform_missing ? @new_platforms + [local_platform] : @new_platforms
|
new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
|
||||||
base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
|
base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
|
||||||
base = additional_base_requirements_to_prevent_downgrades(base)
|
base = additional_base_requirements_to_prevent_downgrades(base)
|
||||||
base = additional_base_requirements_to_force_updates(base)
|
base = additional_base_requirements_to_force_updates(base)
|
||||||
@ -738,8 +736,8 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def start_resolution
|
def start_resolution
|
||||||
local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(local_platform)
|
local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(Bundler.local_platform)
|
||||||
@platforms << local_platform if local_platform_needed_for_resolvability
|
@platforms << Bundler.local_platform if local_platform_needed_for_resolvability
|
||||||
add_platform(Gem::Platform::RUBY) if RUBY_ENGINE == "truffleruby"
|
add_platform(Gem::Platform::RUBY) if RUBY_ENGINE == "truffleruby"
|
||||||
|
|
||||||
result = SpecSet.new(resolver.start)
|
result = SpecSet.new(resolver.start)
|
||||||
@ -758,7 +756,7 @@ module Bundler
|
|||||||
if result.incomplete_for_platform?(current_dependencies, @most_specific_non_local_locked_platform)
|
if result.incomplete_for_platform?(current_dependencies, @most_specific_non_local_locked_platform)
|
||||||
@platforms.delete(@most_specific_non_local_locked_platform)
|
@platforms.delete(@most_specific_non_local_locked_platform)
|
||||||
elsif local_platform_needed_for_resolvability
|
elsif local_platform_needed_for_resolvability
|
||||||
@platforms.delete(local_platform)
|
@platforms.delete(Bundler.local_platform)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -777,17 +775,17 @@ module Bundler
|
|||||||
|
|
||||||
def current_platform_locked?
|
def current_platform_locked?
|
||||||
@platforms.any? do |bundle_platform|
|
@platforms.any? do |bundle_platform|
|
||||||
generic_local_platform == bundle_platform || local_platform === bundle_platform
|
Bundler.generic_local_platform == bundle_platform || Bundler.local_platform === bundle_platform
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_current_platform
|
def add_current_platform
|
||||||
return if @platforms.include?(local_platform)
|
return if @platforms.include?(Bundler.local_platform)
|
||||||
|
|
||||||
@most_specific_non_local_locked_platform = find_most_specific_locked_platform
|
@most_specific_non_local_locked_platform = find_most_specific_locked_platform
|
||||||
return if @most_specific_non_local_locked_platform
|
return if @most_specific_non_local_locked_platform
|
||||||
|
|
||||||
@platforms << local_platform
|
@platforms << Bundler.local_platform
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1167,7 +1165,7 @@ module Bundler
|
|||||||
def remove_invalid_platforms!
|
def remove_invalid_platforms!
|
||||||
return if Bundler.frozen_bundle?
|
return if Bundler.frozen_bundle?
|
||||||
|
|
||||||
skips = (@new_platforms + [local_platform]).uniq
|
skips = (@new_platforms + [Bundler.local_platform]).uniq
|
||||||
|
|
||||||
# We should probably avoid removing non-ruby platforms, since that means
|
# We should probably avoid removing non-ruby platforms, since that means
|
||||||
# lockfile will no longer install on those platforms, so a error to give
|
# lockfile will no longer install on those platforms, so a error to give
|
||||||
|
@ -99,7 +99,7 @@ module Bundler
|
|||||||
return RUBY_PLATFORM_ARRAY if force_ruby_platform
|
return RUBY_PLATFORM_ARRAY if force_ruby_platform
|
||||||
return valid_platforms if platforms.empty?
|
return valid_platforms if platforms.empty?
|
||||||
|
|
||||||
valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) }
|
valid_platforms.select {|p| expanded_platforms.include?(Gem::Platform.generic(p)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def expanded_platforms
|
def expanded_platforms
|
||||||
|
@ -73,7 +73,7 @@ module Bundler
|
|||||||
case specs_by_name_and_version.size
|
case specs_by_name_and_version.size
|
||||||
when 1
|
when 1
|
||||||
specs = specs_by_name_and_version.values.first
|
specs = specs_by_name_and_version.values.first
|
||||||
spec = specs.find {|s| s.match_platform(Bundler.local_platform) } || specs.first
|
spec = specs.find {|s| s.installable_on_platform?(Bundler.local_platform) } || specs.first
|
||||||
|
|
||||||
@gemspecs << spec
|
@gemspecs << spec
|
||||||
|
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Bundler
|
|
||||||
module GemHelpers
|
|
||||||
GENERIC_CACHE = { Gem::Platform::RUBY => Gem::Platform::RUBY } # rubocop:disable Style/MutableConstant
|
|
||||||
GENERICS = [
|
|
||||||
Gem::Platform::JAVA,
|
|
||||||
*Gem::Platform::WINDOWS,
|
|
||||||
].freeze
|
|
||||||
|
|
||||||
def generic(p)
|
|
||||||
GENERIC_CACHE[p] ||= begin
|
|
||||||
found = GENERICS.find do |match|
|
|
||||||
p === match
|
|
||||||
end
|
|
||||||
found || Gem::Platform::RUBY
|
|
||||||
end
|
|
||||||
end
|
|
||||||
module_function :generic
|
|
||||||
|
|
||||||
def generic_local_platform
|
|
||||||
generic(local_platform)
|
|
||||||
end
|
|
||||||
module_function :generic_local_platform
|
|
||||||
|
|
||||||
def local_platform
|
|
||||||
Bundler.local_platform
|
|
||||||
end
|
|
||||||
module_function :local_platform
|
|
||||||
|
|
||||||
def generic_local_platform_is_ruby?
|
|
||||||
generic_local_platform == Gem::Platform::RUBY
|
|
||||||
end
|
|
||||||
module_function :generic_local_platform_is_ruby?
|
|
||||||
|
|
||||||
def platform_specificity_match(spec_platform, user_platform)
|
|
||||||
spec_platform = Gem::Platform.new(spec_platform)
|
|
||||||
|
|
||||||
PlatformMatch.specificity_score(spec_platform, user_platform)
|
|
||||||
end
|
|
||||||
module_function :platform_specificity_match
|
|
||||||
|
|
||||||
def select_all_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
|
|
||||||
matching = if force_ruby
|
|
||||||
specs.select {|spec| spec.match_platform(Gem::Platform::RUBY) && spec.force_ruby_platform! }
|
|
||||||
else
|
|
||||||
specs.select {|spec| spec.match_platform(platform) }
|
|
||||||
end
|
|
||||||
|
|
||||||
if prefer_locked
|
|
||||||
locked_originally = matching.select {|spec| spec.is_a?(LazySpecification) }
|
|
||||||
return locked_originally if locked_originally.any?
|
|
||||||
end
|
|
||||||
|
|
||||||
matching
|
|
||||||
end
|
|
||||||
module_function :select_all_platform_match
|
|
||||||
|
|
||||||
def select_best_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
|
|
||||||
matching = select_all_platform_match(specs, platform, force_ruby: force_ruby, prefer_locked: prefer_locked)
|
|
||||||
|
|
||||||
sort_and_filter_best_platform_match(matching, platform)
|
|
||||||
end
|
|
||||||
module_function :select_best_platform_match
|
|
||||||
|
|
||||||
def select_best_local_platform_match(specs, force_ruby: false)
|
|
||||||
matching = select_all_platform_match(specs, local_platform, force_ruby: force_ruby).filter_map(&:materialized_for_installation)
|
|
||||||
|
|
||||||
sort_best_platform_match(matching, local_platform)
|
|
||||||
end
|
|
||||||
module_function :select_best_local_platform_match
|
|
||||||
|
|
||||||
def sort_and_filter_best_platform_match(matching, platform)
|
|
||||||
return matching if matching.one?
|
|
||||||
|
|
||||||
exact = matching.select {|spec| spec.platform == platform }
|
|
||||||
return exact if exact.any?
|
|
||||||
|
|
||||||
sorted_matching = sort_best_platform_match(matching, platform)
|
|
||||||
exemplary_spec = sorted_matching.first
|
|
||||||
|
|
||||||
sorted_matching.take_while {|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) }
|
|
||||||
end
|
|
||||||
module_function :sort_and_filter_best_platform_match
|
|
||||||
|
|
||||||
def sort_best_platform_match(matching, platform)
|
|
||||||
matching.sort_by {|spec| platform_specificity_match(spec.platform, platform) }
|
|
||||||
end
|
|
||||||
module_function :sort_best_platform_match
|
|
||||||
|
|
||||||
class PlatformMatch
|
|
||||||
def self.specificity_score(spec_platform, user_platform)
|
|
||||||
return -1 if spec_platform == user_platform
|
|
||||||
return 1_000_000 if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
|
|
||||||
|
|
||||||
os_match(spec_platform, user_platform) +
|
|
||||||
cpu_match(spec_platform, user_platform) * 10 +
|
|
||||||
platform_version_match(spec_platform, user_platform) * 100
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.os_match(spec_platform, user_platform)
|
|
||||||
if spec_platform.os == user_platform.os
|
|
||||||
0
|
|
||||||
else
|
|
||||||
1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.cpu_match(spec_platform, user_platform)
|
|
||||||
if spec_platform.cpu == user_platform.cpu
|
|
||||||
0
|
|
||||||
elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
|
|
||||||
0
|
|
||||||
elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
|
|
||||||
1
|
|
||||||
else
|
|
||||||
2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.platform_version_match(spec_platform, user_platform)
|
|
||||||
if spec_platform.version == user_platform.version
|
|
||||||
0
|
|
||||||
elsif spec_platform.version.nil?
|
|
||||||
1
|
|
||||||
else
|
|
||||||
2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def same_specificity(platform, spec, exemplary_spec)
|
|
||||||
platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform)
|
|
||||||
end
|
|
||||||
module_function :same_specificity
|
|
||||||
|
|
||||||
def same_deps(spec, exemplary_spec)
|
|
||||||
same_runtime_deps = spec.dependencies.sort == exemplary_spec.dependencies.sort
|
|
||||||
same_metadata_deps = spec.required_ruby_version == exemplary_spec.required_ruby_version && spec.required_rubygems_version == exemplary_spec.required_rubygems_version
|
|
||||||
same_runtime_deps && same_metadata_deps
|
|
||||||
end
|
|
||||||
module_function :same_deps
|
|
||||||
end
|
|
||||||
end
|
|
@ -142,15 +142,15 @@ module Bundler
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
materialize([name, version]) do |matching_specs|
|
materialize([name, version]) do |matching_specs|
|
||||||
target_platform = source.is_a?(Source::Path) ? platform : local_platform
|
target_platform = source.is_a?(Source::Path) ? platform : Bundler.local_platform
|
||||||
|
|
||||||
installable_candidates = GemHelpers.select_best_platform_match(matching_specs, target_platform)
|
installable_candidates = MatchPlatform.select_best_platform_match(matching_specs, target_platform)
|
||||||
|
|
||||||
specification = choose_compatible(installable_candidates, fallback_to_non_installable: false)
|
specification = choose_compatible(installable_candidates, fallback_to_non_installable: false)
|
||||||
return specification unless specification.nil?
|
return specification unless specification.nil?
|
||||||
|
|
||||||
if target_platform != platform
|
if target_platform != platform
|
||||||
installable_candidates = GemHelpers.select_best_platform_match(matching_specs, platform)
|
installable_candidates = MatchPlatform.select_best_platform_match(matching_specs, platform)
|
||||||
end
|
end
|
||||||
|
|
||||||
choose_compatible(installable_candidates)
|
choose_compatible(installable_candidates)
|
||||||
@ -190,7 +190,7 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def ruby_platform_materializes_to_ruby_platform?
|
def ruby_platform_materializes_to_ruby_platform?
|
||||||
generic_platform = generic_local_platform == Gem::Platform::JAVA ? Gem::Platform::JAVA : Gem::Platform::RUBY
|
generic_platform = Bundler.generic_local_platform == Gem::Platform::JAVA ? Gem::Platform::JAVA : Gem::Platform::RUBY
|
||||||
|
|
||||||
(most_specific_locked_platform != generic_platform) || force_ruby_platform || Bundler.settings[:force_ruby_platform]
|
(most_specific_locked_platform != generic_platform) || force_ruby_platform || Bundler.settings[:force_ruby_platform]
|
||||||
end
|
end
|
||||||
|
@ -4,8 +4,6 @@ require_relative "shared_helpers"
|
|||||||
|
|
||||||
module Bundler
|
module Bundler
|
||||||
class LockfileParser
|
class LockfileParser
|
||||||
include GemHelpers
|
|
||||||
|
|
||||||
class Position
|
class Position
|
||||||
attr_reader :line, :column
|
attr_reader :line, :column
|
||||||
def initialize(line, column)
|
def initialize(line, column)
|
||||||
@ -157,7 +155,7 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
@most_specific_locked_platform = @platforms.min_by do |bundle_platform|
|
@most_specific_locked_platform = @platforms.min_by do |bundle_platform|
|
||||||
platform_specificity_match(bundle_platform, local_platform)
|
Gem::Platform.platform_specificity_match(bundle_platform, Bundler.local_platform)
|
||||||
end
|
end
|
||||||
@specs = @specs.values.sort_by!(&:full_name).each do |spec|
|
@specs = @specs.values.sort_by!(&:full_name).each do |spec|
|
||||||
spec.most_specific_locked_platform = @most_specific_locked_platform
|
spec.most_specific_locked_platform = @most_specific_locked_platform
|
||||||
|
@ -1,23 +1,42 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "gem_helpers"
|
|
||||||
|
|
||||||
module Bundler
|
module Bundler
|
||||||
module MatchPlatform
|
module MatchPlatform
|
||||||
include GemHelpers
|
def installable_on_platform?(target_platform) # :nodoc:
|
||||||
|
return true if [Gem::Platform::RUBY, nil, target_platform].include?(platform)
|
||||||
def match_platform(p)
|
return true if Gem::Platform.new(platform) === target_platform
|
||||||
MatchPlatform.platforms_match?(platform, p)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.platforms_match?(gemspec_platform, local_platform)
|
|
||||||
return true if gemspec_platform.nil?
|
|
||||||
return true if gemspec_platform == Gem::Platform::RUBY
|
|
||||||
return true if local_platform == gemspec_platform
|
|
||||||
gemspec_platform = Gem::Platform.new(gemspec_platform)
|
|
||||||
return true if gemspec_platform === local_platform
|
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.select_best_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
|
||||||
|
matching = select_all_platform_match(specs, platform, force_ruby: force_ruby, prefer_locked: prefer_locked)
|
||||||
|
|
||||||
|
Gem::Platform.sort_and_filter_best_platform_match(matching, platform)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.select_best_local_platform_match(specs, force_ruby: false)
|
||||||
|
local = Bundler.local_platform
|
||||||
|
matching = select_all_platform_match(specs, local, force_ruby: force_ruby).filter_map(&:materialized_for_installation)
|
||||||
|
|
||||||
|
Gem::Platform.sort_best_platform_match(matching, local)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.select_all_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
|
||||||
|
matching = specs.select {|spec| spec.installable_on_platform?(force_ruby ? Gem::Platform::RUBY : platform) }
|
||||||
|
|
||||||
|
specs.each(&:force_ruby_platform!) if force_ruby
|
||||||
|
|
||||||
|
if prefer_locked
|
||||||
|
locked_originally = matching.select {|spec| spec.is_a?(::Bundler::LazySpecification) }
|
||||||
|
return locked_originally if locked_originally.any?
|
||||||
|
end
|
||||||
|
|
||||||
|
matching
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.generic_local_platform_is_ruby?
|
||||||
|
Bundler.generic_local_platform == Gem::Platform::RUBY
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -22,9 +22,9 @@ module Bundler
|
|||||||
@specs ||= if @candidates.nil?
|
@specs ||= if @candidates.nil?
|
||||||
[]
|
[]
|
||||||
elsif platform
|
elsif platform
|
||||||
GemHelpers.select_best_platform_match(@candidates, platform, force_ruby: dep.force_ruby_platform)
|
MatchPlatform.select_best_platform_match(@candidates, platform, force_ruby: dep.force_ruby_platform)
|
||||||
else
|
else
|
||||||
GemHelpers.select_best_local_platform_match(@candidates, force_ruby: dep.force_ruby_platform || dep.default_force_ruby_platform)
|
MatchPlatform.select_best_local_platform_match(@candidates, force_ruby: dep.force_ruby_platform || dep.default_force_ruby_platform)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,8 +14,6 @@ module Bundler
|
|||||||
require_relative "resolver/root"
|
require_relative "resolver/root"
|
||||||
require_relative "resolver/strategy"
|
require_relative "resolver/strategy"
|
||||||
|
|
||||||
include GemHelpers
|
|
||||||
|
|
||||||
def initialize(base, gem_version_promoter, most_specific_locked_platform = nil)
|
def initialize(base, gem_version_promoter, most_specific_locked_platform = nil)
|
||||||
@source_requirements = base.source_requirements
|
@source_requirements = base.source_requirements
|
||||||
@base = base
|
@base = base
|
||||||
@ -273,7 +271,7 @@ module Bundler
|
|||||||
next groups if platform_specs.all?(&:empty?)
|
next groups if platform_specs.all?(&:empty?)
|
||||||
end
|
end
|
||||||
|
|
||||||
ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
|
ruby_specs = MatchPlatform.select_best_platform_match(specs, Gem::Platform::RUBY)
|
||||||
ruby_group = Resolver::SpecGroup.new(ruby_specs)
|
ruby_group = Resolver::SpecGroup.new(ruby_specs)
|
||||||
|
|
||||||
unless ruby_group.empty?
|
unless ruby_group.empty?
|
||||||
|
@ -30,7 +30,7 @@ module Bundler
|
|||||||
def platform_specs(specs)
|
def platform_specs(specs)
|
||||||
platforms.map do |platform|
|
platforms.map do |platform|
|
||||||
prefer_locked = @new_platforms.include?(platform) ? false : !unlock?
|
prefer_locked = @new_platforms.include?(platform) ? false : !unlock?
|
||||||
GemHelpers.select_best_platform_match(specs, platform, prefer_locked: prefer_locked)
|
MatchPlatform.select_best_platform_match(specs, platform, prefer_locked: prefer_locked)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,16 +52,123 @@ module Gem
|
|||||||
require "rubygems/platform"
|
require "rubygems/platform"
|
||||||
|
|
||||||
class Platform
|
class Platform
|
||||||
JAVA = Gem::Platform.new("java")
|
# Can be removed once RubyGems 3.6.9 support is dropped
|
||||||
MSWIN = Gem::Platform.new("mswin32")
|
unless respond_to?(:generic)
|
||||||
MSWIN64 = Gem::Platform.new("mswin64")
|
JAVA = Gem::Platform.new("java") # :nodoc:
|
||||||
MINGW = Gem::Platform.new("x86-mingw32")
|
MSWIN = Gem::Platform.new("mswin32") # :nodoc:
|
||||||
X64_MINGW_LEGACY = Gem::Platform.new("x64-mingw32")
|
MSWIN64 = Gem::Platform.new("mswin64") # :nodoc:
|
||||||
X64_MINGW = Gem::Platform.new("x64-mingw-ucrt")
|
MINGW = Gem::Platform.new("x86-mingw32") # :nodoc:
|
||||||
UNIVERSAL_MINGW = Gem::Platform.new("universal-mingw")
|
X64_MINGW_LEGACY = Gem::Platform.new("x64-mingw32") # :nodoc:
|
||||||
WINDOWS = [MSWIN, MSWIN64, UNIVERSAL_MINGW].flatten.freeze
|
X64_MINGW = Gem::Platform.new("x64-mingw-ucrt") # :nodoc:
|
||||||
X64_LINUX = Gem::Platform.new("x86_64-linux")
|
UNIVERSAL_MINGW = Gem::Platform.new("universal-mingw") # :nodoc:
|
||||||
X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl")
|
WINDOWS = [MSWIN, MSWIN64, UNIVERSAL_MINGW].freeze # :nodoc:
|
||||||
|
X64_LINUX = Gem::Platform.new("x86_64-linux") # :nodoc:
|
||||||
|
X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl") # :nodoc:
|
||||||
|
|
||||||
|
GENERICS = [JAVA, *WINDOWS].freeze # :nodoc:
|
||||||
|
private_constant :GENERICS
|
||||||
|
|
||||||
|
GENERIC_CACHE = GENERICS.each_with_object({}) {|g, h| h[g] = g } # :nodoc:
|
||||||
|
private_constant :GENERIC_CACHE
|
||||||
|
|
||||||
|
class << self
|
||||||
|
##
|
||||||
|
# Returns the generic platform for the given platform.
|
||||||
|
|
||||||
|
def generic(platform)
|
||||||
|
return Gem::Platform::RUBY if platform.nil? || platform == Gem::Platform::RUBY
|
||||||
|
|
||||||
|
GENERIC_CACHE[platform] ||= begin
|
||||||
|
found = GENERICS.find do |match|
|
||||||
|
platform === match
|
||||||
|
end
|
||||||
|
found || Gem::Platform::RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns the platform specificity match for the given spec platform and user platform.
|
||||||
|
|
||||||
|
def platform_specificity_match(spec_platform, user_platform)
|
||||||
|
return -1 if spec_platform == user_platform
|
||||||
|
return 1_000_000 if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
|
||||||
|
|
||||||
|
os_match(spec_platform, user_platform) +
|
||||||
|
cpu_match(spec_platform, user_platform) * 10 +
|
||||||
|
version_match(spec_platform, user_platform) * 100
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sorts and filters the best platform match for the given matching specs and platform.
|
||||||
|
|
||||||
|
def sort_and_filter_best_platform_match(matching, platform)
|
||||||
|
return matching if matching.one?
|
||||||
|
|
||||||
|
exact = matching.select {|spec| spec.platform == platform }
|
||||||
|
return exact if exact.any?
|
||||||
|
|
||||||
|
sorted_matching = sort_best_platform_match(matching, platform)
|
||||||
|
exemplary_spec = sorted_matching.first
|
||||||
|
|
||||||
|
sorted_matching.take_while {|spec| same_specificity?(platform, spec, exemplary_spec) && same_deps?(spec, exemplary_spec) }
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sorts the best platform match for the given matching specs and platform.
|
||||||
|
|
||||||
|
def sort_best_platform_match(matching, platform)
|
||||||
|
matching.sort_by.with_index do |spec, i|
|
||||||
|
[
|
||||||
|
platform_specificity_match(spec.platform, platform),
|
||||||
|
i, # for stable sort
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def same_specificity?(platform, spec, exemplary_spec)
|
||||||
|
platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform)
|
||||||
|
end
|
||||||
|
|
||||||
|
def same_deps?(spec, exemplary_spec)
|
||||||
|
spec.required_ruby_version == exemplary_spec.required_ruby_version &&
|
||||||
|
spec.required_rubygems_version == exemplary_spec.required_rubygems_version &&
|
||||||
|
spec.dependencies.sort == exemplary_spec.dependencies.sort
|
||||||
|
end
|
||||||
|
|
||||||
|
def os_match(spec_platform, user_platform)
|
||||||
|
if spec_platform.os == user_platform.os
|
||||||
|
0
|
||||||
|
else
|
||||||
|
1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cpu_match(spec_platform, user_platform)
|
||||||
|
if spec_platform.cpu == user_platform.cpu
|
||||||
|
0
|
||||||
|
elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
|
||||||
|
0
|
||||||
|
elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
|
||||||
|
1
|
||||||
|
else
|
||||||
|
2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def version_match(spec_platform, user_platform)
|
||||||
|
if spec_platform.version == user_platform.version
|
||||||
|
0
|
||||||
|
elsif spec_platform.version.nil?
|
||||||
|
1
|
||||||
|
else
|
||||||
|
2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require "rubygems/specification"
|
require "rubygems/specification"
|
||||||
@ -80,7 +187,6 @@ module Gem
|
|||||||
require_relative "match_platform"
|
require_relative "match_platform"
|
||||||
|
|
||||||
include ::Bundler::MatchMetadata
|
include ::Bundler::MatchMetadata
|
||||||
include ::Bundler::MatchPlatform
|
|
||||||
|
|
||||||
attr_accessor :remote, :relative_loaded_from
|
attr_accessor :remote, :relative_loaded_from
|
||||||
|
|
||||||
@ -285,6 +391,11 @@ module Gem
|
|||||||
@ignored = missing_extensions?
|
@ignored = missing_extensions?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Can be removed once RubyGems 3.6.9 support is dropped
|
||||||
|
unless new.respond_to?(:installable_on_platform?)
|
||||||
|
include(::Bundler::MatchPlatform)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require "rubygems/name_tuple"
|
require "rubygems/name_tuple"
|
||||||
|
@ -76,7 +76,7 @@ module Bundler
|
|||||||
|
|
||||||
new_platforms = all_platforms.select do |platform|
|
new_platforms = all_platforms.select do |platform|
|
||||||
next if platforms.include?(platform)
|
next if platforms.include?(platform)
|
||||||
next unless GemHelpers.generic(platform) == Gem::Platform::RUBY
|
next unless Gem::Platform.generic(platform) == Gem::Platform::RUBY
|
||||||
|
|
||||||
complete_platform(platform)
|
complete_platform(platform)
|
||||||
end
|
end
|
||||||
@ -183,7 +183,7 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_by_name_and_platform(name, platform)
|
def find_by_name_and_platform(name, platform)
|
||||||
@specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
|
@specs.detect {|spec| spec.name == name && spec.installable_on_platform?(platform) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def specs_with_additional_variants_from(other)
|
def specs_with_additional_variants_from(other)
|
||||||
@ -280,7 +280,7 @@ module Bundler
|
|||||||
valid_platform = lookup.all? do |_, specs|
|
valid_platform = lookup.all? do |_, specs|
|
||||||
spec = specs.first
|
spec = specs.first
|
||||||
matching_specs = spec.source.specs.search([spec.name, spec.version])
|
matching_specs = spec.source.specs.search([spec.name, spec.version])
|
||||||
platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
|
platform_spec = MatchPlatform.select_best_platform_match(matching_specs, platform).find do |s|
|
||||||
valid?(s)
|
valid?(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -256,6 +256,13 @@ class Gem::BasicSpecification
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def installable_on_platform?(target_platform) # :nodoc:
|
||||||
|
return true if [Gem::Platform::RUBY, nil, target_platform].include?(platform)
|
||||||
|
return true if Gem::Platform.new(platform) === target_platform
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def raw_require_paths # :nodoc:
|
def raw_require_paths # :nodoc:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
@ -255,4 +255,118 @@ class Gem::Platform
|
|||||||
# This will be replaced with Gem::Platform::local.
|
# This will be replaced with Gem::Platform::local.
|
||||||
|
|
||||||
CURRENT = "current"
|
CURRENT = "current"
|
||||||
|
|
||||||
|
JAVA = Gem::Platform.new("java") # :nodoc:
|
||||||
|
MSWIN = Gem::Platform.new("mswin32") # :nodoc:
|
||||||
|
MSWIN64 = Gem::Platform.new("mswin64") # :nodoc:
|
||||||
|
MINGW = Gem::Platform.new("x86-mingw32") # :nodoc:
|
||||||
|
X64_MINGW_LEGACY = Gem::Platform.new("x64-mingw32") # :nodoc:
|
||||||
|
X64_MINGW = Gem::Platform.new("x64-mingw-ucrt") # :nodoc:
|
||||||
|
UNIVERSAL_MINGW = Gem::Platform.new("universal-mingw") # :nodoc:
|
||||||
|
WINDOWS = [MSWIN, MSWIN64, UNIVERSAL_MINGW].freeze # :nodoc:
|
||||||
|
X64_LINUX = Gem::Platform.new("x86_64-linux") # :nodoc:
|
||||||
|
X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl") # :nodoc:
|
||||||
|
|
||||||
|
GENERICS = [JAVA, *WINDOWS].freeze # :nodoc:
|
||||||
|
private_constant :GENERICS
|
||||||
|
|
||||||
|
GENERIC_CACHE = GENERICS.each_with_object({}) {|g, h| h[g] = g } # :nodoc:
|
||||||
|
private_constant :GENERIC_CACHE
|
||||||
|
|
||||||
|
class << self
|
||||||
|
##
|
||||||
|
# Returns the generic platform for the given platform.
|
||||||
|
|
||||||
|
def generic(platform)
|
||||||
|
return Gem::Platform::RUBY if platform.nil? || platform == Gem::Platform::RUBY
|
||||||
|
|
||||||
|
GENERIC_CACHE[platform] ||= begin
|
||||||
|
found = GENERICS.find do |match|
|
||||||
|
platform === match
|
||||||
|
end
|
||||||
|
found || Gem::Platform::RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns the platform specificity match for the given spec platform and user platform.
|
||||||
|
|
||||||
|
def platform_specificity_match(spec_platform, user_platform)
|
||||||
|
return -1 if spec_platform == user_platform
|
||||||
|
return 1_000_000 if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
|
||||||
|
|
||||||
|
os_match(spec_platform, user_platform) +
|
||||||
|
cpu_match(spec_platform, user_platform) * 10 +
|
||||||
|
version_match(spec_platform, user_platform) * 100
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sorts and filters the best platform match for the given matching specs and platform.
|
||||||
|
|
||||||
|
def sort_and_filter_best_platform_match(matching, platform)
|
||||||
|
return matching if matching.one?
|
||||||
|
|
||||||
|
exact = matching.select {|spec| spec.platform == platform }
|
||||||
|
return exact if exact.any?
|
||||||
|
|
||||||
|
sorted_matching = sort_best_platform_match(matching, platform)
|
||||||
|
exemplary_spec = sorted_matching.first
|
||||||
|
|
||||||
|
sorted_matching.take_while {|spec| same_specificity?(platform, spec, exemplary_spec) && same_deps?(spec, exemplary_spec) }
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sorts the best platform match for the given matching specs and platform.
|
||||||
|
|
||||||
|
def sort_best_platform_match(matching, platform)
|
||||||
|
matching.sort_by.with_index do |spec, i|
|
||||||
|
[
|
||||||
|
platform_specificity_match(spec.platform, platform),
|
||||||
|
i, # for stable sort
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def same_specificity?(platform, spec, exemplary_spec)
|
||||||
|
platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform)
|
||||||
|
end
|
||||||
|
|
||||||
|
def same_deps?(spec, exemplary_spec)
|
||||||
|
spec.required_ruby_version == exemplary_spec.required_ruby_version &&
|
||||||
|
spec.required_rubygems_version == exemplary_spec.required_rubygems_version &&
|
||||||
|
spec.dependencies.sort == exemplary_spec.dependencies.sort
|
||||||
|
end
|
||||||
|
|
||||||
|
def os_match(spec_platform, user_platform)
|
||||||
|
if spec_platform.os == user_platform.os
|
||||||
|
0
|
||||||
|
else
|
||||||
|
1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cpu_match(spec_platform, user_platform)
|
||||||
|
if spec_platform.cpu == user_platform.cpu
|
||||||
|
0
|
||||||
|
elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
|
||||||
|
0
|
||||||
|
elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
|
||||||
|
1
|
||||||
|
else
|
||||||
|
2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def version_match(spec_platform, user_platform)
|
||||||
|
if spec_platform.version == user_platform.version
|
||||||
|
0
|
||||||
|
elsif spec_platform.version.nil?
|
||||||
|
1
|
||||||
|
else
|
||||||
|
2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,57 +1,20 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
RSpec.describe "Gem::Specification#match_platform" do
|
RSpec.describe "Gem::Specification#installable_on_platform?" do
|
||||||
it "does not match platforms other than the gem platform" do
|
it "does not match platforms other than the gem platform" do
|
||||||
darwin = gem "lol", "1.0", "platform_specific-1.0-x86-darwin-10"
|
darwin = gem "lol", "1.0", "platform_specific-1.0-x86-darwin-10"
|
||||||
expect(darwin.match_platform(pl("java"))).to eq(false)
|
expect(darwin.installable_on_platform?(pl("java"))).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when platform is a string" do
|
context "when platform is a string" do
|
||||||
it "matches when platform is a string" do
|
it "matches when platform is a string" do
|
||||||
lazy_spec = Bundler::LazySpecification.new("lol", "1.0", "universal-mingw32")
|
lazy_spec = Bundler::LazySpecification.new("lol", "1.0", "universal-mingw32")
|
||||||
expect(lazy_spec.match_platform(pl("x86-mingw32"))).to eq(true)
|
expect(lazy_spec.installable_on_platform?(pl("x86-mingw32"))).to eq(true)
|
||||||
expect(lazy_spec.match_platform(pl("x64-mingw32"))).to eq(true)
|
expect(lazy_spec.installable_on_platform?(pl("x64-mingw32"))).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
RSpec.describe "Bundler::GemHelpers#generic" do
|
|
||||||
include Bundler::GemHelpers
|
|
||||||
|
|
||||||
it "converts non-windows platforms into ruby" do
|
|
||||||
expect(generic(pl("x86-darwin-10"))).to eq(pl("ruby"))
|
|
||||||
expect(generic(pl("ruby"))).to eq(pl("ruby"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "converts java platform variants into java" do
|
|
||||||
expect(generic(pl("universal-java-17"))).to eq(pl("java"))
|
|
||||||
expect(generic(pl("java"))).to eq(pl("java"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "converts mswin platform variants into x86-mswin32" do
|
|
||||||
expect(generic(pl("mswin32"))).to eq(pl("x86-mswin32"))
|
|
||||||
expect(generic(pl("i386-mswin32"))).to eq(pl("x86-mswin32"))
|
|
||||||
expect(generic(pl("x86-mswin32"))).to eq(pl("x86-mswin32"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "converts 32-bit mingw platform variants into universal-mingw" do
|
|
||||||
expect(generic(pl("i386-mingw32"))).to eq(pl("universal-mingw"))
|
|
||||||
expect(generic(pl("x86-mingw32"))).to eq(pl("universal-mingw"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "converts 64-bit mingw platform variants into universal-mingw" do
|
|
||||||
expect(generic(pl("x64-mingw32"))).to eq(pl("universal-mingw"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "converts x64 mingw UCRT platform variants into universal-mingw" do
|
|
||||||
expect(generic(pl("x64-mingw-ucrt"))).to eq(pl("universal-mingw"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "converts aarch64 mingw UCRT platform variants into universal-mingw" do
|
|
||||||
expect(generic(pl("aarch64-mingw-ucrt"))).to eq(pl("universal-mingw"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
RSpec.describe "Gem::SourceIndex#refresh!" do
|
RSpec.describe "Gem::SourceIndex#refresh!" do
|
||||||
before do
|
before do
|
||||||
install_gemfile <<-G
|
install_gemfile <<-G
|
||||||
|
@ -2,12 +2,18 @@
|
|||||||
|
|
||||||
module Spec
|
module Spec
|
||||||
module Platforms
|
module Platforms
|
||||||
include Bundler::GemHelpers
|
|
||||||
|
|
||||||
def not_local
|
def not_local
|
||||||
generic_local_platform == Gem::Platform::RUBY ? "java" : Gem::Platform::RUBY
|
generic_local_platform == Gem::Platform::RUBY ? "java" : Gem::Platform::RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def local_platform
|
||||||
|
Bundler.local_platform
|
||||||
|
end
|
||||||
|
|
||||||
|
def generic_local_platform
|
||||||
|
Gem::Platform.generic(local_platform)
|
||||||
|
end
|
||||||
|
|
||||||
def local_tag
|
def local_tag
|
||||||
if Gem.java_platform?
|
if Gem.java_platform?
|
||||||
:jruby
|
:jruby
|
||||||
@ -61,7 +67,7 @@ module Spec
|
|||||||
end
|
end
|
||||||
|
|
||||||
def generic_default_locked_platform
|
def generic_default_locked_platform
|
||||||
return unless generic_local_platform_is_ruby?
|
return unless Bundler::MatchPlatform.generic_local_platform_is_ruby?
|
||||||
|
|
||||||
Gem::Platform::RUBY
|
Gem::Platform::RUBY
|
||||||
end
|
end
|
||||||
|
@ -418,6 +418,9 @@ class Gem::TestCase < Test::Unit::TestCase
|
|||||||
@orig_hooks[name] = Gem.send(name).dup
|
@orig_hooks[name] = Gem.send(name).dup
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Gem::Platform.const_get(:GENERIC_CACHE).clear
|
||||||
|
Gem::Platform.const_get(:GENERICS).each {|g| Gem::Platform.const_get(:GENERIC_CACHE)[g] = g }
|
||||||
|
|
||||||
@marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
|
@marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
|
||||||
@orig_loaded_features = $LOADED_FEATURES.dup
|
@orig_loaded_features = $LOADED_FEATURES.dup
|
||||||
end
|
end
|
||||||
|
@ -509,6 +509,171 @@ class TestGemPlatform < Gem::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_constants
|
||||||
|
assert_equal [nil, "java", nil], Gem::Platform::JAVA.to_a
|
||||||
|
assert_equal ["x86", "mswin32", nil], Gem::Platform::MSWIN.to_a
|
||||||
|
assert_equal [nil, "mswin64", nil], Gem::Platform::MSWIN64.to_a
|
||||||
|
assert_equal ["x86", "mingw32", nil], Gem::Platform::MINGW.to_a
|
||||||
|
assert_equal ["x64", "mingw", "ucrt"], Gem::Platform::X64_MINGW.to_a
|
||||||
|
assert_equal ["universal", "mingw", nil], Gem::Platform::UNIVERSAL_MINGW.to_a
|
||||||
|
assert_equal [["x86", "mswin32", nil], [nil, "mswin64", nil], ["universal", "mingw", nil]], Gem::Platform::WINDOWS.map(&:to_a)
|
||||||
|
assert_equal ["x86_64", "linux", nil], Gem::Platform::X64_LINUX.to_a
|
||||||
|
assert_equal ["x86_64", "linux", "musl"], Gem::Platform::X64_LINUX_MUSL.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_generic
|
||||||
|
# converts non-windows platforms into ruby
|
||||||
|
assert_equal Gem::Platform::RUBY, Gem::Platform.generic(Gem::Platform.new("x86-darwin-10"))
|
||||||
|
assert_equal Gem::Platform::RUBY, Gem::Platform.generic(Gem::Platform::RUBY)
|
||||||
|
|
||||||
|
# converts java platform variants into java
|
||||||
|
assert_equal Gem::Platform::JAVA, Gem::Platform.generic(Gem::Platform.new("java"))
|
||||||
|
assert_equal Gem::Platform::JAVA, Gem::Platform.generic(Gem::Platform.new("universal-java-17"))
|
||||||
|
|
||||||
|
# converts mswin platform variants into x86-mswin32
|
||||||
|
assert_equal Gem::Platform::MSWIN, Gem::Platform.generic(Gem::Platform.new("mswin32"))
|
||||||
|
assert_equal Gem::Platform::MSWIN, Gem::Platform.generic(Gem::Platform.new("i386-mswin32"))
|
||||||
|
assert_equal Gem::Platform::MSWIN, Gem::Platform.generic(Gem::Platform.new("x86-mswin32"))
|
||||||
|
|
||||||
|
# converts 32-bit mingw platform variants into universal-mingw
|
||||||
|
assert_equal Gem::Platform::UNIVERSAL_MINGW, Gem::Platform.generic(Gem::Platform.new("i386-mingw32"))
|
||||||
|
assert_equal Gem::Platform::UNIVERSAL_MINGW, Gem::Platform.generic(Gem::Platform.new("x86-mingw32"))
|
||||||
|
|
||||||
|
# converts 64-bit mingw platform variants into universal-mingw
|
||||||
|
assert_equal Gem::Platform::UNIVERSAL_MINGW, Gem::Platform.generic(Gem::Platform.new("x64-mingw32"))
|
||||||
|
|
||||||
|
# converts x64 mingw UCRT platform variants into universal-mingw
|
||||||
|
assert_equal Gem::Platform::UNIVERSAL_MINGW, Gem::Platform.generic(Gem::Platform.new("x64-mingw-ucrt"))
|
||||||
|
|
||||||
|
# converts aarch64 mingw UCRT platform variants into universal-mingw
|
||||||
|
assert_equal Gem::Platform::UNIVERSAL_MINGW, Gem::Platform.generic(Gem::Platform.new("aarch64-mingw-ucrt"))
|
||||||
|
|
||||||
|
assert_equal Gem::Platform::RUBY, Gem::Platform.generic(Gem::Platform.new("unknown"))
|
||||||
|
assert_equal Gem::Platform::RUBY, Gem::Platform.generic(nil)
|
||||||
|
assert_equal Gem::Platform::MSWIN64, Gem::Platform.generic(Gem::Platform.new("mswin64"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_platform_specificity_match
|
||||||
|
[
|
||||||
|
["ruby", "ruby", -1, -1],
|
||||||
|
["x86_64-linux-musl", "x86_64-linux-musl", -1, -1],
|
||||||
|
["x86_64-linux", "x86_64-linux-musl", 100, 200],
|
||||||
|
["universal-darwin", "x86-darwin", 10, 20],
|
||||||
|
["universal-darwin-19", "x86-darwin", 210, 120],
|
||||||
|
["universal-darwin-19", "universal-darwin-20", 200, 200],
|
||||||
|
["arm-darwin-19", "arm64-darwin-19", 0, 20],
|
||||||
|
].each do |spec_platform, user_platform, s1, s2|
|
||||||
|
spec_platform = Gem::Platform.new(spec_platform)
|
||||||
|
user_platform = Gem::Platform.new(user_platform)
|
||||||
|
assert_equal s1, Gem::Platform.platform_specificity_match(spec_platform, user_platform),
|
||||||
|
"Gem::Platform.platform_specificity_match(#{spec_platform.to_s.inspect}, #{user_platform.to_s.inspect})"
|
||||||
|
assert_equal s2, Gem::Platform.platform_specificity_match(user_platform, spec_platform),
|
||||||
|
"Gem::Platform.platform_specificity_match(#{user_platform.to_s.inspect}, #{spec_platform.to_s.inspect})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sort_and_filter_best_platform_match
|
||||||
|
a_1 = util_spec "a", "1"
|
||||||
|
a_1_java = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform::JAVA
|
||||||
|
end
|
||||||
|
a_1_universal_darwin = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("universal-darwin")
|
||||||
|
end
|
||||||
|
a_1_universal_darwin_19 = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("universal-darwin-19")
|
||||||
|
end
|
||||||
|
a_1_universal_darwin_20 = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("universal-darwin-20")
|
||||||
|
end
|
||||||
|
a_1_arm_darwin_19 = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("arm64-darwin-19")
|
||||||
|
end
|
||||||
|
a_1_x86_darwin = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("x86-darwin")
|
||||||
|
end
|
||||||
|
specs = [a_1, a_1_java, a_1_universal_darwin, a_1_universal_darwin_19, a_1_universal_darwin_20, a_1_arm_darwin_19, a_1_x86_darwin]
|
||||||
|
assert_equal [a_1], Gem::Platform.sort_and_filter_best_platform_match(specs, "ruby")
|
||||||
|
assert_equal [a_1_java], Gem::Platform.sort_and_filter_best_platform_match(specs, Gem::Platform::JAVA)
|
||||||
|
assert_equal [a_1_arm_darwin_19], Gem::Platform.sort_and_filter_best_platform_match(specs, Gem::Platform.new("arm64-darwin-19"))
|
||||||
|
assert_equal [a_1_universal_darwin_20], Gem::Platform.sort_and_filter_best_platform_match(specs, Gem::Platform.new("arm64-darwin-20"))
|
||||||
|
assert_equal [a_1_universal_darwin_19], Gem::Platform.sort_and_filter_best_platform_match(specs, Gem::Platform.new("x86-darwin-19"))
|
||||||
|
assert_equal [a_1_universal_darwin_20], Gem::Platform.sort_and_filter_best_platform_match(specs, Gem::Platform.new("x86-darwin-20"))
|
||||||
|
assert_equal [a_1_x86_darwin], Gem::Platform.sort_and_filter_best_platform_match(specs, Gem::Platform.new("x86-darwin-21"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sort_best_platform_match
|
||||||
|
a_1 = util_spec "a", "1"
|
||||||
|
a_1_java = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform::JAVA
|
||||||
|
end
|
||||||
|
a_1_universal_darwin = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("universal-darwin")
|
||||||
|
end
|
||||||
|
a_1_universal_darwin_19 = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("universal-darwin-19")
|
||||||
|
end
|
||||||
|
a_1_universal_darwin_20 = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("universal-darwin-20")
|
||||||
|
end
|
||||||
|
a_1_arm_darwin_19 = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("arm64-darwin-19")
|
||||||
|
end
|
||||||
|
a_1_x86_darwin = util_spec "a", "1" do |s|
|
||||||
|
s.platform = Gem::Platform.new("x86-darwin")
|
||||||
|
end
|
||||||
|
specs = [a_1, a_1_java, a_1_universal_darwin, a_1_universal_darwin_19, a_1_universal_darwin_20, a_1_arm_darwin_19, a_1_x86_darwin]
|
||||||
|
assert_equal ["ruby",
|
||||||
|
"java",
|
||||||
|
"universal-darwin",
|
||||||
|
"universal-darwin-19",
|
||||||
|
"universal-darwin-20",
|
||||||
|
"arm64-darwin-19",
|
||||||
|
"x86-darwin"], Gem::Platform.sort_best_platform_match(specs, "ruby").map {|s| s.platform.to_s }
|
||||||
|
assert_equal ["java",
|
||||||
|
"universal-darwin",
|
||||||
|
"x86-darwin",
|
||||||
|
"universal-darwin-19",
|
||||||
|
"universal-darwin-20",
|
||||||
|
"arm64-darwin-19",
|
||||||
|
"ruby"], Gem::Platform.sort_best_platform_match(specs, Gem::Platform::JAVA).map {|s| s.platform.to_s }
|
||||||
|
assert_equal ["arm64-darwin-19",
|
||||||
|
"universal-darwin-19",
|
||||||
|
"universal-darwin",
|
||||||
|
"java",
|
||||||
|
"x86-darwin",
|
||||||
|
"universal-darwin-20",
|
||||||
|
"ruby"], Gem::Platform.sort_best_platform_match(specs, Gem::Platform.new("arm64-darwin-19")).map {|s| s.platform.to_s }
|
||||||
|
assert_equal ["universal-darwin-20",
|
||||||
|
"universal-darwin",
|
||||||
|
"java",
|
||||||
|
"x86-darwin",
|
||||||
|
"arm64-darwin-19",
|
||||||
|
"universal-darwin-19",
|
||||||
|
"ruby"], Gem::Platform.sort_best_platform_match(specs, Gem::Platform.new("arm64-darwin-20")).map {|s| s.platform.to_s }
|
||||||
|
assert_equal ["universal-darwin-19",
|
||||||
|
"arm64-darwin-19",
|
||||||
|
"x86-darwin",
|
||||||
|
"universal-darwin",
|
||||||
|
"java",
|
||||||
|
"universal-darwin-20",
|
||||||
|
"ruby"], Gem::Platform.sort_best_platform_match(specs, Gem::Platform.new("x86-darwin-19")).map {|s| s.platform.to_s }
|
||||||
|
assert_equal ["universal-darwin-20",
|
||||||
|
"x86-darwin",
|
||||||
|
"universal-darwin",
|
||||||
|
"java",
|
||||||
|
"universal-darwin-19",
|
||||||
|
"arm64-darwin-19",
|
||||||
|
"ruby"], Gem::Platform.sort_best_platform_match(specs, Gem::Platform.new("x86-darwin-20")).map {|s| s.platform.to_s }
|
||||||
|
assert_equal ["x86-darwin",
|
||||||
|
"universal-darwin",
|
||||||
|
"java",
|
||||||
|
"universal-darwin-19",
|
||||||
|
"universal-darwin-20",
|
||||||
|
"arm64-darwin-19",
|
||||||
|
"ruby"], Gem::Platform.sort_best_platform_match(specs, Gem::Platform.new("x86-darwin-21")).map {|s| s.platform.to_s }
|
||||||
|
end
|
||||||
|
|
||||||
def assert_local_match(name)
|
def assert_local_match(name)
|
||||||
assert_match Gem::Platform.local, name
|
assert_match Gem::Platform.local, name
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user