diff options
Diffstat (limited to 'spec/bundler/install/gemfile/gemspec_spec.rb')
-rw-r--r-- | spec/bundler/install/gemfile/gemspec_spec.rb | 373 |
1 files changed, 248 insertions, 125 deletions
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb index e7cf8f08d2..63778567cf 100644 --- a/spec/bundler/install/gemfile/gemspec_spec.rb +++ b/spec/bundler/install/gemfile/gemspec_spec.rb @@ -8,8 +8,38 @@ RSpec.describe "bundle install from an existing gemspec" do end end + let(:x64_mingw_archs) do + if RUBY_PLATFORM == "x64-mingw-ucrt" + if Gem.rubygems_version >= Gem::Version.new("3.2.28") + ["x64-mingw-ucrt", "x64-mingw32"] + else + ["x64-mingw32", "x64-unknown"] + end + else + ["x64-mingw32"] + end + end + + let(:x64_mingw_gems) do + x64_mingw_archs.map {|p| "platform_specific (1.0-#{p})" }.join("\n ") + end + + let(:x64_mingw_platforms) do + x64_mingw_archs.join("\n ") + end + + def x64_mingw_checksums(checksums) + x64_mingw_archs.each do |arch| + if arch == "x64-mingw-ucrt" + checksums.no_checksum "platform_specific", "1.0", arch + else + checksums.checksum gem_repo2, "platform_specific", "1.0", arch + end + end + end + it "should install runtime and development dependencies" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.write("Gemfile", "source :rubygems\ngemspec") s.add_dependency "bar", "=1.0.0" s.add_development_dependency "bar-dev", "=1.0.0" @@ -20,11 +50,11 @@ RSpec.describe "bundle install from an existing gemspec" do G expect(the_bundle).to include_gems "bar 1.0.0" - expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development + expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development end it "that is hidden should install runtime and development dependencies" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.write("Gemfile", "source :rubygems\ngemspec") s.add_dependency "bar", "=1.0.0" s.add_development_dependency "bar-dev", "=1.0.0" @@ -37,7 +67,7 @@ RSpec.describe "bundle install from an existing gemspec" do G expect(the_bundle).to include_gems "bar 1.0.0" - expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development + expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development end it "should handle a list of requirements" do @@ -46,7 +76,7 @@ RSpec.describe "bundle install from an existing gemspec" do build_gem "baz", "1.1" end - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.write("Gemfile", "source :rubygems\ngemspec") s.add_dependency "baz", ">= 1.0", "< 1.1" end @@ -59,29 +89,29 @@ RSpec.describe "bundle install from an existing gemspec" do end it "should raise if there are no gemspecs available" do - build_lib("foo", :path => tmp.join("foo"), :gemspec => false) + build_lib("foo", path: tmp.join("foo"), gemspec: false) - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}" gemspec :path => '#{tmp.join("foo")}' G - expect(err).to match(/There are no gemspecs at #{tmp.join('foo')}/) + expect(err).to match(/There are no gemspecs at #{tmp.join("foo")}/) end it "should raise if there are too many gemspecs available" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.write("foo2.gemspec", build_spec("foo", "4.0").first.to_ruby) end - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}" gemspec :path => '#{tmp.join("foo")}' G - expect(err).to match(/There are multiple gemspecs at #{tmp.join('foo')}/) + expect(err).to match(/There are multiple gemspecs at #{tmp.join("foo")}/) end it "should pick a specific gemspec" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.write("foo2.gemspec", "") s.add_dependency "bar", "=1.0.0" s.add_development_dependency "bar-dev", "=1.0.0" @@ -93,11 +123,11 @@ RSpec.describe "bundle install from an existing gemspec" do G expect(the_bundle).to include_gems "bar 1.0.0" - expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development + expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development end it "should use a specific group for development dependencies" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.write("foo2.gemspec", "") s.add_dependency "bar", "=1.0.0" s.add_development_dependency "bar-dev", "=1.0.0" @@ -109,32 +139,32 @@ RSpec.describe "bundle install from an existing gemspec" do G expect(the_bundle).to include_gems "bar 1.0.0" - expect(the_bundle).not_to include_gems "bar-dev 1.0.0", :groups => :development - expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :dev + expect(the_bundle).not_to include_gems "bar-dev 1.0.0", groups: :development + expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :dev end it "should match a lockfile even if the gemspec defines development dependencies" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.write("Gemfile", "source '#{file_uri_for(gem_repo1)}'\ngemspec") s.add_dependency "actionpack", "=2.3.2" - s.add_development_dependency "rake", "=13.0.1" + s.add_development_dependency "rake", rake_version end - bundle "install", :dir => tmp.join("foo") + bundle "install", dir: tmp.join("foo") # This should really be able to rely on $stderr, but, it's not written # right, so we can't. In fact, this is a bug negation test, and so it'll # ghost pass in future, and will only catch a regression if the message # doesn't change. Exit codes should be used correctly (they can be more # than just 0 and 1). bundle "config set --local deployment true" - output = bundle("install", :dir => tmp.join("foo")) + output = bundle("install", dir: tmp.join("foo")) expect(output).not_to match(/You have added to the Gemfile/) expect(output).not_to match(/You have deleted from the Gemfile/) - expect(output).not_to match(/install in deployment mode after changing/) + expect(output).not_to match(/the lockfile can't be updated because frozen mode is set/) end it "should match a lockfile without needing to re-resolve" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.add_dependency "rack" end @@ -143,7 +173,7 @@ RSpec.describe "bundle install from an existing gemspec" do gemspec :path => '#{tmp.join("foo")}' G - bundle "install", :verbose => true + bundle "install", verbose: true message = "Found no changes, using resolution from the lockfile" expect(out.scan(message).size).to eq(1) @@ -152,7 +182,7 @@ RSpec.describe "bundle install from an existing gemspec" do it "should match a lockfile without needing to re-resolve with development dependencies" do simulate_platform java - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.add_dependency "rack" s.add_development_dependency "thin" end @@ -162,34 +192,34 @@ RSpec.describe "bundle install from an existing gemspec" do gemspec :path => '#{tmp.join("foo")}' G - bundle "install", :verbose => true + bundle "install", verbose: true message = "Found no changes, using resolution from the lockfile" expect(out.scan(message).size).to eq(1) end - it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby do - build_lib("foo", :path => tmp.join("foo")) do |s| + it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby_only do + build_lib("foo", path: tmp.join("foo")) do |s| s.add_dependency "platform_specific" end - system_gems "platform_specific-1.0-java", :path => default_bundle_path + system_gems "platform_specific-1.0-java", path: default_bundle_path install_gemfile <<-G gemspec :path => '#{tmp.join("foo")}' G - bundle "update --bundler", :artifice => "compact_index", :verbose => true + bundle "update --bundler", artifice: "compact_index", verbose: true expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 JAVA" end it "should evaluate the gemspec in its directory" do - build_lib("foo", :path => tmp.join("foo")) + build_lib("foo", path: tmp.join("foo")) File.open(tmp.join("foo/foo.gemspec"), "w") do |s| s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'" end - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false gemspec :path => '#{tmp.join("foo")}' G expect(last_command.stdboth).not_to include("ahh") @@ -203,7 +233,7 @@ RSpec.describe "bundle install from an existing gemspec" do # so emulate that system_gems %w[rack-1.0.0 rack-0.9.1 rack-obama-1.0] - build_lib("foo", :path => bundled_app) + build_lib("foo", path: bundled_app) gemspec = bundled_app("foo.gemspec").read bundled_app("foo.gemspec").open("w") do |f| f.write "#{gemspec.strip}.tap { gem 'rack-obama'; require 'rack/obama' }" @@ -218,14 +248,14 @@ RSpec.describe "bundle install from an existing gemspec" do end it "allows conflicts" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.version = "1.0.0" s.add_dependency "bar", "= 1.0.0" end - build_gem "deps", :to_bundle => true do |s| + build_gem "deps", to_bundle: true do |s| s.add_dependency "foo", "= 0.0.1" end - build_gem "foo", "0.0.1", :to_bundle => true + build_gem "foo", "0.0.1", to_bundle: true install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" @@ -237,7 +267,7 @@ RSpec.describe "bundle install from an existing gemspec" do end it "does not break Gem.finish_resolve with conflicts" do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.version = "1.0.0" s.add_dependency "bar", "= 1.0.0" end @@ -261,14 +291,14 @@ RSpec.describe "bundle install from an existing gemspec" do end it "handles downgrades" do - build_lib "omg", "2.0", :path => lib_path("omg") + build_lib "omg", "2.0", path: lib_path("omg") install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gemspec :path => "#{lib_path("omg")}" G - build_lib "omg", "1.0", :path => lib_path("omg") + build_lib "omg", "1.0", path: lib_path("omg") bundle :install @@ -278,7 +308,7 @@ RSpec.describe "bundle install from an existing gemspec" do context "in deployment mode" do context "when the lockfile was not updated after a change to the gemspec's dependencies" do it "reports that installation failed" do - build_lib "cocoapods", :path => bundled_app do |s| + build_lib "cocoapods", path: bundled_app do |s| s.add_dependency "activesupport", ">= 1" end @@ -289,12 +319,12 @@ RSpec.describe "bundle install from an existing gemspec" do expect(the_bundle).to include_gems("cocoapods 1.0", "activesupport 2.3.5") - build_lib "cocoapods", :path => bundled_app do |s| + build_lib "cocoapods", path: bundled_app do |s| s.add_dependency "activesupport", ">= 1.0.1" end bundle "config set --local deployment true" - bundle :install, :raise_on_error => false + bundle :install, raise_on_error: false expect(err).to include("changed") end @@ -304,13 +334,13 @@ RSpec.describe "bundle install from an existing gemspec" do context "when child gemspecs conflict with a released gemspec" do before do # build the "parent" gem that depends on another gem in the same repo - build_lib "source_conflict", :path => bundled_app do |s| + build_lib "source_conflict", path: bundled_app do |s| s.add_dependency "rack_middleware" end # build the "child" gem that is the same version as a released gem, but # has completely different and conflicting dependency requirements - build_lib "rack_middleware", "1.0", :path => bundled_app("rack_middleware") do |s| + build_lib "rack_middleware", "1.0", path: bundled_app("rack_middleware") do |s| s.add_dependency "rack", "1.0" # anything other than 0.9.1 end end @@ -328,83 +358,69 @@ RSpec.describe "bundle install from an existing gemspec" do context "with a lockfile and some missing dependencies" do let(:source_uri) { "http://localgemserver.test" } - context "previously bundled for Ruby" do - let(:platform) { "ruby" } - - before do - skip "not installing for some reason" if Gem.win_platform? - - build_lib("foo", :path => tmp.join("foo")) do |s| - s.add_dependency "rack", "=1.0.0" - end - - gemfile <<-G - source "#{source_uri}" - gemspec :path => "../foo" - G + before do + build_lib("foo", path: tmp.join("foo")) do |s| + s.add_dependency "rack", "=1.0.0" + end - lockfile <<-L - PATH - remote: ../foo - specs: - foo (1.0) - rack (= 1.0.0) + gemfile <<-G + source "#{source_uri}" + gemspec :path => "../foo" + G - GEM - remote: #{source_uri} - specs: - rack (1.0.0) + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end - PLATFORMS - #{generic_local_platform} + lockfile <<-L + PATH + remote: ../foo + specs: + foo (1.0) + rack (= 1.0.0) - DEPENDENCIES - foo! + GEM + remote: #{source_uri} + specs: + rack (1.0.0) - BUNDLED WITH - #{Bundler::VERSION} - L - end + PLATFORMS + #{generic_local_platform} - context "using JRuby with explicit platform", :jruby do - before do - create_file( - tmp.join("foo", "foo-java.gemspec"), - build_spec("foo", "1.0", "java") do - dep "rack", "=1.0.0" - @spec.authors = "authors" - @spec.summary = "summary" - end.first.to_ruby - ) - end + DEPENDENCIES + foo! + #{checksums} + BUNDLED WITH + #{Bundler::VERSION} + L + end - it "should install" do - results = bundle "install", :artifice => "endpoint" - expect(results).to include("Installing rack 1.0.0") - expect(the_bundle).to include_gems "rack 1.0.0" - end + context "using JRuby with explicit platform", :jruby_only do + before do + create_file( + tmp.join("foo", "foo-java.gemspec"), + build_spec("foo", "1.0", "java") do + dep "rack", "=1.0.0" + @spec.authors = "authors" + @spec.summary = "summary" + end.first.to_ruby + ) end - context "using JRuby", :jruby do - it "should install" do - results = bundle "install", :artifice => "endpoint" - expect(results).to include("Installing rack 1.0.0") - expect(the_bundle).to include_gems "rack 1.0.0" - end + it "should install" do + results = bundle "install", artifice: "endpoint" + expect(results).to include("Installing rack 1.0.0") + expect(the_bundle).to include_gems "rack 1.0.0" end + end - context "using Windows" do - it "should install" do - simulate_windows do - results = bundle "install", :artifice => "endpoint" - expect(results).to include("Installing rack 1.0.0") - expect(the_bundle).to include_gems "rack 1.0.0" - end - end - end + it "should install", :jruby do + results = bundle "install", artifice: "endpoint" + expect(results).to include("Installing rack 1.0.0") + expect(the_bundle).to include_gems "rack 1.0.0" end - context "bundled for ruby and jruby" do + context "bundled for multiple platforms" do let(:platform_specific_type) { :runtime } let(:dependency) { "platform_specific" } before do @@ -414,7 +430,7 @@ RSpec.describe "bundle install from an existing gemspec" do end end - build_lib "foo", :path => bundled_app do |s| + build_lib "foo", path: bundled_app do |s| if platform_specific_type == :runtime s.add_runtime_dependency dependency elsif platform_specific_type == :development @@ -429,20 +445,32 @@ RSpec.describe "bundle install from an existing gemspec" do gemspec G - simulate_platform("ruby") { bundle "install" } + bundle "config set --local force_ruby_platform true" + bundle "install" + + simulate_new_machine simulate_platform("jruby") { bundle "install" } + simulate_platform(x64_mingw32) { bundle "install" } end context "on ruby" do before do - simulate_platform("ruby") + bundle "config set --local force_ruby_platform true" bundle :install end context "as a runtime dependency" do - it "keeps java dependencies in the lockfile" do + it "keeps all platform dependencies in the lockfile" do expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY" - expect(lockfile).to eq strip_whitespace(<<-L) + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + c.checksum gem_repo2, "platform_specific", "1.0" + c.checksum gem_repo2, "platform_specific", "1.0", "java" + x64_mingw_checksums(c) + end + + expect(lockfile).to eq <<~L PATH remote: . specs: @@ -454,14 +482,16 @@ RSpec.describe "bundle install from an existing gemspec" do specs: platform_specific (1.0) platform_specific (1.0-java) + #{x64_mingw_gems} PLATFORMS java ruby + #{x64_mingw_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} L @@ -471,9 +501,17 @@ RSpec.describe "bundle install from an existing gemspec" do context "as a development dependency" do let(:platform_specific_type) { :development } - it "keeps java dependencies in the lockfile" do + it "keeps all platform dependencies in the lockfile" do expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY" - expect(lockfile).to eq strip_whitespace(<<-L) + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + c.checksum gem_repo2, "platform_specific", "1.0" + c.checksum gem_repo2, "platform_specific", "1.0", "java" + x64_mingw_checksums(c) + end + + expect(lockfile).to eq <<~L PATH remote: . specs: @@ -484,15 +522,17 @@ RSpec.describe "bundle install from an existing gemspec" do specs: platform_specific (1.0) platform_specific (1.0-java) + #{x64_mingw_gems} PLATFORMS java ruby + #{x64_mingw_platforms} DEPENDENCIES foo! platform_specific - + #{checksums} BUNDLED WITH #{Bundler::VERSION} L @@ -503,9 +543,18 @@ RSpec.describe "bundle install from an existing gemspec" do let(:platform_specific_type) { :development } let(:dependency) { "indirect_platform_specific" } - it "keeps java dependencies in the lockfile" do + it "keeps all platform dependencies in the lockfile" do expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 RUBY" - expect(lockfile).to eq strip_whitespace(<<-L) + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + c.checksum gem_repo2, "indirect_platform_specific", "1.0" + c.checksum gem_repo2, "platform_specific", "1.0" + c.checksum gem_repo2, "platform_specific", "1.0", "java" + x64_mingw_checksums(c) + end + + expect(lockfile).to eq <<~L PATH remote: . specs: @@ -518,15 +567,17 @@ RSpec.describe "bundle install from an existing gemspec" do platform_specific platform_specific (1.0) platform_specific (1.0-java) + #{x64_mingw_gems} PLATFORMS java ruby + #{x64_mingw_platforms} DEPENDENCIES foo! indirect_platform_specific - + #{checksums} BUNDLED WITH #{Bundler::VERSION} L @@ -538,7 +589,7 @@ RSpec.describe "bundle install from an existing gemspec" do context "with multiple platforms" do before do - build_lib("foo", :path => tmp.join("foo")) do |s| + build_lib("foo", path: tmp.join("foo")) do |s| s.version = "1.0.0" s.add_development_dependency "rack" s.write "foo-universal-java.gemspec", build_spec("foo", "1.0.0", "universal-java") {|sj| sj.runtime "rack", "1.0.0" }.first.to_ruby @@ -546,7 +597,7 @@ RSpec.describe "bundle install from an existing gemspec" do end it "installs the ruby platform gemspec" do - simulate_platform "ruby" + bundle "config set --local force_ruby_platform true" install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -557,7 +608,7 @@ RSpec.describe "bundle install from an existing gemspec" do end it "installs the ruby platform gemspec and skips dev deps with `without development` configured" do - simulate_platform "ruby" + bundle "config set --local force_ruby_platform true" bundle "config set --local without development" install_gemfile <<-G @@ -572,7 +623,7 @@ RSpec.describe "bundle install from an existing gemspec" do context "with multiple platforms and resolving for more specific platforms" do before do - build_lib("chef", :path => tmp.join("chef")) do |s| + build_lib("chef", path: tmp.join("chef")) do |s| s.version = "17.1.17" s.write "chef-universal-mingw32.gemspec", build_spec("chef", "17.1.17", "universal-mingw32") {|sw| sw.runtime "win32-api", "~> 1.5.3" }.first.to_ruby end @@ -590,6 +641,12 @@ RSpec.describe "bundle install from an existing gemspec" do gemspec :path => "../chef" G + checksums = checksums_section_when_existing do |c| + c.no_checksum "chef", "17.1.17" + c.no_checksum "chef", "17.1.17", "universal-mingw32" + c.checksum gem_repo4, "win32-api", "1.5.3", "universal-mingw32" + end + initial_lockfile = <<~L PATH remote: ../chef @@ -605,12 +662,12 @@ RSpec.describe "bundle install from an existing gemspec" do PLATFORMS ruby - x64-mingw32 + #{x64_mingw_platforms} x86-mingw32 DEPENDENCIES chef! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} L @@ -622,4 +679,70 @@ RSpec.describe "bundle install from an existing gemspec" do expect(lockfile).to eq initial_lockfile end end + + context "with multiple locked platforms" do + before do + build_lib("activeadmin", path: tmp.join("activeadmin")) do |s| + s.version = "2.9.0" + s.add_dependency "railties", ">= 5.2", "< 6.2" + end + + build_repo4 do + build_gem "railties", "6.1.4" + + build_gem "jruby-openssl", "0.10.7" do |s| + s.platform = "java" + end + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gemspec :path => "../activeadmin" + gem "jruby-openssl", :platform => :jruby + G + + bundle "lock --add-platform java" + end + + it "does not remove the platform specific specs from the lockfile when re-resolving due to gemspec changes" do + checksums = checksums_section_when_existing do |c| + c.no_checksum "activeadmin", "2.9.0" + c.no_checksum "jruby-openssl", "0.10.7", "java" + c.checksum gem_repo4, "railties", "6.1.4" + end + + expect(lockfile).to eq <<~L + PATH + remote: ../activeadmin + specs: + activeadmin (2.9.0) + railties (>= 5.2, < 6.2) + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + jruby-openssl (0.10.7-java) + railties (6.1.4) + + PLATFORMS + #{lockfile_platforms("java")} + + DEPENDENCIES + activeadmin! + jruby-openssl + #{checksums} + BUNDLED WITH + #{Bundler::VERSION} + L + + gemspec = tmp.join("activeadmin/activeadmin.gemspec") + File.write(gemspec, File.read(gemspec).sub(">= 5.2", ">= 6.0")) + + previous_lockfile = lockfile + + bundle "install --local" + + expect(lockfile).to eq(previous_lockfile.sub(">= 5.2", ">= 6.0")) + end + end end |