Skip to content

Commit

Permalink
Enable specific_platform by default
Browse files Browse the repository at this point in the history
To properly support gems providing native platform versions with
different dependencies than their pure ruby counterparts.

Nokogiri will start doing this soon. In particular, for each version,
the pure ruby variant will not have a `required_ruby_version` upper
bound, but the native variant will. Bundler should always install a
valid bundle in this case.
  • Loading branch information
deivid-rodriguez committed Oct 13, 2020
1 parent 4111bd2 commit 66ec766
Show file tree
Hide file tree
Showing 15 changed files with 11 additions and 196 deletions.
5 changes: 1 addition & 4 deletions bundler/lib/bundler/definition.rb
Expand Up @@ -561,10 +561,7 @@ def add_platforms
end

def current_platforms
[].tap do |platforms|
platforms << local_platform if Bundler.feature_flag.specific_platform?
platforms << generic_local_platform
end
[local_platform, generic_local_platform]
end

def change_reason
Expand Down
1 change: 0 additions & 1 deletion bundler/lib/bundler/feature_flag.rb
Expand Up @@ -41,7 +41,6 @@ def self.settings_method(name, key, &default)
settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
settings_flag(:print_only_version_number) { bundler_3_mode? }
settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? }
settings_flag(:specific_platform) { bundler_3_mode? }
settings_flag(:suppress_install_using_messages) { bundler_3_mode? }
settings_flag(:unlock_source_unlocks_spec) { !bundler_3_mode? }
settings_flag(:update_requires_all_flag) { bundler_4_mode? }
Expand Down
9 changes: 1 addition & 8 deletions bundler/lib/bundler/lazy_specification.rb
Expand Up @@ -79,19 +79,12 @@ def __materialize__
@specification = if source.is_a?(Source::Gemspec) && source.gemspec.name == name
source.gemspec.tap {|s| s.source = source }
else
search_object = Bundler.feature_flag.specific_platform? || Bundler.settings[:force_ruby_platform] ? self : Dependency.new(name, version)
platform_object = Gem::Platform.new(platform)
candidates = source.specs.search(search_object)
candidates = source.specs.search(self)
same_platform_candidates = candidates.select do |spec|
MatchPlatform.platforms_match?(spec.platform, platform_object)
end
search = same_platform_candidates.last || candidates.last
if search && Gem::Platform.new(search.platform) != platform_object && !search.runtime_dependencies.-(dependencies.reject {|d| d.type == :development }).empty?
Bundler.ui.warn "Unable to use the platform-specific (#{search.platform}) version of #{name} (#{version}) " \
"because it has different dependencies from the #{platform} version. " \
"To use the platform-specific version of the gem, run `bundle config set --local specific_platform true` and install again."
search = source.specs.search(self).last
end
search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
search
end
Expand Down
1 change: 0 additions & 1 deletion bundler/lib/bundler/settings.rb
Expand Up @@ -42,7 +42,6 @@ class Settings
setup_makes_kernel_gem_public
silence_deprecations
silence_root_warning
specific_platform
suppress_install_using_messages
unlock_source_unlocks_spec
update_requires_all_flag
Expand Down
3 changes: 0 additions & 3 deletions bundler/man/bundle-config.1
Expand Up @@ -262,9 +262,6 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBsilence_root_warning\fR (\fBBUNDLE_SILENCE_ROOT_WARNING\fR): Silence the warning Bundler prints when installing gems as root\.
.
.IP "\(bu" 4
\fBspecific_platform\fR (\fBBUNDLE_SPECIFIC_PLATFORM\fR): Allow bundler to resolve for the specific running platform and store it in the lockfile, instead of only using a generic platform\. A specific platform is the exact platform triple reported by \fBGem::Platform\.local\fR, such as \fBx86_64\-darwin\-16\fR or \fBuniversal\-java\-1\.8\fR\. On the other hand, generic platforms are those such as \fBruby\fR, \fBmswin\fR, or \fBjava\fR\. In this example, \fBx86_64\-darwin\-16\fR would map to \fBruby\fR and \fBuniversal\-java\-1\.8\fR to \fBjava\fR\.
.
.IP "\(bu" 4
\fBssl_ca_cert\fR (\fBBUNDLE_SSL_CA_CERT\fR): Path to a designated CA certificate file or folder containing multiple certificates for trusted CAs in PEM format\.
.
.IP "\(bu" 4
Expand Down
8 changes: 0 additions & 8 deletions bundler/man/bundle-config.1.ronn
Expand Up @@ -250,14 +250,6 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
be changed in the next major version.
* `silence_root_warning` (`BUNDLE_SILENCE_ROOT_WARNING`):
Silence the warning Bundler prints when installing gems as root.
* `specific_platform` (`BUNDLE_SPECIFIC_PLATFORM`):
Allow bundler to resolve for the specific running platform and store it in
the lockfile, instead of only using a generic platform.
A specific platform is the exact platform triple reported by
`Gem::Platform.local`, such as `x86_64-darwin-16` or `universal-java-1.8`.
On the other hand, generic platforms are those such as `ruby`, `mswin`, or
`java`. In this example, `x86_64-darwin-16` would map to `ruby` and
`universal-java-1.8` to `java`.
* `ssl_ca_cert` (`BUNDLE_SSL_CA_CERT`):
Path to a designated CA certificate file or folder containing multiple
certificates for trusted CAs in PEM format.
Expand Down
2 changes: 0 additions & 2 deletions bundler/spec/install/gemfile/gemspec_spec.rb
Expand Up @@ -422,8 +422,6 @@
end
end

bundle "config specific_platform false"

%w[ruby jruby].each do |platform|
simulate_platform(platform) do
install_gemfile <<-G
Expand Down
26 changes: 0 additions & 26 deletions bundler/spec/install/gemfile/platform_spec.rb
Expand Up @@ -255,32 +255,6 @@
expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
end

it "works with gems that have extra platform-specific runtime dependencies", :bundler => "< 3" do
simulate_platform x64_mac

update_repo2 do
build_gem "facter", "2.4.6"
build_gem "facter", "2.4.6" do |s|
s.platform = "universal-darwin"
s.add_runtime_dependency "CFPropertyList"
end
build_gem "CFPropertyList"
end

install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "facter"
G

expect(err).to include "Unable to use the platform-specific (universal-darwin) version of facter (2.4.6) " \
"because it has different dependencies from the ruby version. " \
"To use the platform-specific version of the gem, run `bundle config set --local specific_platform true` and install again."

expect(the_bundle).to include_gem "facter 2.4.6"
expect(the_bundle).not_to include_gem "CFPropertyList"
end

it "works with gems with platform-specific dependency having different requirements order" do
simulate_platform x64_mac

Expand Down
4 changes: 1 addition & 3 deletions bundler/spec/install/gemfile/specific_platform_spec.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true

RSpec.describe "bundle install with specific_platform enabled" do
RSpec.describe "bundle install with specific platforms" do
before do
bundle "config set specific_platform true"

build_repo2 do
build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1")
build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" }
Expand Down
8 changes: 1 addition & 7 deletions bundler/spec/install/gems/resolving_spec.rb
Expand Up @@ -239,13 +239,7 @@

let(:ruby_requirement) { %("#{RUBY_VERSION}") }
let(:error_message_requirement) { "~> #{RUBY_VERSION}.0" }
let(:error_message_platform) do
if Bundler.feature_flag.specific_platform?
" #{Bundler.local_platform}"
else
""
end
end
let(:error_message_platform) { " #{Bundler.local_platform}" }

shared_examples_for "ruby version conflicts" do
it "raises an error during resolution" do
Expand Down
76 changes: 2 additions & 74 deletions bundler/spec/lock/lockfile_spec.rb
Expand Up @@ -968,48 +968,7 @@
G
end

it "keeps existing platforms in the lockfile", :bundler => "< 3" do
lockfile <<-G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
PLATFORMS
java
DEPENDENCIES
rack
BUNDLED WITH
#{Bundler::VERSION}
G

install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}/"
gem "rack"
G

lockfile_should_be <<-G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
PLATFORMS
java
#{generic_local_platform}
DEPENDENCIES
rack
BUNDLED WITH
#{Bundler::VERSION}
G
end

it "keeps existing platforms in the lockfile", :bundler => "3" do
it "keeps existing platforms in the lockfile" do
lockfile <<-G
GEM
remote: #{file_uri_for(gem_repo2)}/
Expand Down Expand Up @@ -1051,38 +1010,7 @@
G
end

it "persists the spec's platform to the lockfile", :bundler => "< 3" do
build_repo2 do
build_gem "platform_specific", "1.0" do |s|
s.platform = Gem::Platform.new("universal-java-16")
end
end

simulate_platform "universal-java-16"

install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "platform_specific"
G

lockfile_should_be <<-G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
platform_specific (1.0-java)
PLATFORMS
java
DEPENDENCIES
platform_specific
BUNDLED WITH
#{Bundler::VERSION}
G
end

it "persists the spec's platform and specific platform to the lockfile", :bundler => "3" do
it "persists the spec's platform and specific platform to the lockfile" do
build_repo2 do
build_gem "platform_specific", "1.0" do |s|
s.platform = Gem::Platform.new("universal-java-16")
Expand Down
56 changes: 2 additions & 54 deletions bundler/spec/plugins/source/example_spec.rb
Expand Up @@ -66,32 +66,7 @@ def install(spec, opts)
expect(the_bundle).to include_gems("a-path-gem 1.0")
end

it "writes to lock file", :bundler => "< 3" do
bundle "install"

lockfile_should_be <<-G
PLUGIN SOURCE
remote: #{lib_path("a-path-gem-1.0")}
type: mpath
specs:
a-path-gem (1.0)
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
PLATFORMS
#{generic_local_platform}
DEPENDENCIES
a-path-gem!
BUNDLED WITH
#{Bundler::VERSION}
G
end

it "writes to lock file", :bundler => "3" do
it "writes to lock file" do
bundle "install"

lockfile_should_be <<-G
Expand Down Expand Up @@ -362,34 +337,7 @@ def installed?
expect(the_bundle).to include_gems("ma-gitp-gem 1.0")
end

it "writes to lock file", :bundler => "< 3" do
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
bundle "install"

lockfile_should_be <<-G
PLUGIN SOURCE
remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))}
type: gitp
revision: #{revision}
specs:
ma-gitp-gem (1.0)
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
PLATFORMS
#{generic_local_platform}
DEPENDENCIES
ma-gitp-gem!
BUNDLED WITH
#{Bundler::VERSION}
G
end

it "writes to lock file", :bundler => "3" do
it "writes to lock file" do
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
bundle "install"

Expand Down
6 changes: 1 addition & 5 deletions bundler/spec/support/platforms.rb
Expand Up @@ -94,11 +94,7 @@ def lockfile_platforms
end

def local_platforms
if Bundler.feature_flag.specific_platform?
[local, specific_local_platform]
else
[local]
end
[local, specific_local_platform]
end
end
end
1 change: 1 addition & 0 deletions bundler/test_gems.rb.lock
Expand Up @@ -24,6 +24,7 @@ GEM
PLATFORMS
java
ruby
x86_64-linux

DEPENDENCIES
artifice (~> 0.6.0)
Expand Down
1 change: 1 addition & 0 deletions dev_gems.rb.lock
Expand Up @@ -68,6 +68,7 @@ GEM
PLATFORMS
java
ruby
x86_64-linux

DEPENDENCIES
minitest (~> 5.14, >= 5.14.2)
Expand Down

0 comments on commit 66ec766

Please sign in to comment.