diff options
Diffstat (limited to 'spec/bundler/runtime')
| -rw-r--r-- | spec/bundler/runtime/env_helpers_spec.rb (renamed from spec/bundler/runtime/with_unbundled_env_spec.rb) | 110 | ||||
| -rw-r--r-- | spec/bundler/runtime/executable_spec.rb | 52 | ||||
| -rw-r--r-- | spec/bundler/runtime/gem_tasks_spec.rb | 74 | ||||
| -rw-r--r-- | spec/bundler/runtime/inline_spec.rb | 167 | ||||
| -rw-r--r-- | spec/bundler/runtime/load_spec.rb | 2 | ||||
| -rw-r--r-- | spec/bundler/runtime/platform_spec.rb | 42 | ||||
| -rw-r--r-- | spec/bundler/runtime/require_spec.rb | 69 | ||||
| -rw-r--r-- | spec/bundler/runtime/requiring_spec.rb | 8 | ||||
| -rw-r--r-- | spec/bundler/runtime/self_management_spec.rb | 152 | ||||
| -rw-r--r-- | spec/bundler/runtime/setup_spec.rb | 197 |
10 files changed, 529 insertions, 344 deletions
diff --git a/spec/bundler/runtime/with_unbundled_env_spec.rb b/spec/bundler/runtime/env_helpers_spec.rb index 8c3582f7ac..c4ebdd1fd2 100644 --- a/spec/bundler/runtime/with_unbundled_env_spec.rb +++ b/spec/bundler/runtime/env_helpers_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "Bundler.with_env helpers" do +RSpec.describe "env helpers" do def bundle_exec_ruby(args, options = {}) build_bundler_context options.dup bundle "exec '#{Gem.ruby}' #{args}", options @@ -24,7 +24,7 @@ RSpec.describe "Bundler.with_env helpers" do path = `getconf PATH`.strip + "#{File::PATH_SEPARATOR}/foo" with_path_as(path) do bundle_exec_ruby(bundled_app("source.rb").to_s) - expect(last_command.stdboth).to eq(path) + expect(stdboth).to eq(path) end end @@ -35,7 +35,7 @@ RSpec.describe "Bundler.with_env helpers" do gem_path = ENV["GEM_PATH"] + "#{File::PATH_SEPARATOR}/foo" with_gem_path_as(gem_path) do bundle_exec_ruby(bundled_app("source.rb").to_s) - expect(last_command.stdboth).to eq(gem_path) + expect(stdboth).to eq(gem_path) end end @@ -62,9 +62,6 @@ RSpec.describe "Bundler.with_env helpers" do end it "removes variables that bundler added", :ruby_repo do - # Simulate bundler has not yet been loaded - ENV.replace(ENV.to_hash.delete_if {|k, _v| k.start_with?(Bundler::EnvironmentPreserver::BUNDLER_PREFIX) }) - original = ruby('puts ENV.to_a.map {|e| e.join("=") }.sort.join("\n")', artifice: "fail") create_file("source.rb", <<-RUBY) puts Bundler.original_env.to_a.map {|e| e.join("=") }.sort.join("\n") @@ -74,68 +71,65 @@ RSpec.describe "Bundler.with_env helpers" do end end - shared_examples_for "an unbundling helper" do + describe "Bundler.unbundled_env" do it "should delete BUNDLE_PATH" do create_file("source.rb", <<-RUBY) - print #{modified_env}.has_key?('BUNDLE_PATH') + print Bundler.unbundled_env.has_key?('BUNDLE_PATH') RUBY ENV["BUNDLE_PATH"] = "./foo" bundle_exec_ruby bundled_app("source.rb") - expect(last_command.stdboth).to include "false" + expect(stdboth).to include "false" end it "should remove absolute path to 'bundler/setup' from RUBYOPT even if it was present in original env" do create_file("source.rb", <<-RUBY) - print #{modified_env}['RUBYOPT'] + print Bundler.unbundled_env['RUBYOPT'] RUBY setup_require = "-r#{lib_dir}/bundler/setup" ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 #{setup_require} #{ENV["RUBYOPT"]}" bundle_exec_ruby bundled_app("source.rb") - expect(last_command.stdboth).not_to include(setup_require) + expect(stdboth).not_to include(setup_require) end it "should remove relative path to 'bundler/setup' from RUBYOPT even if it was present in original env" do create_file("source.rb", <<-RUBY) - print #{modified_env}['RUBYOPT'] + print Bundler.unbundled_env['RUBYOPT'] RUBY ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 -rbundler/setup #{ENV["RUBYOPT"]}" bundle_exec_ruby bundled_app("source.rb") - expect(last_command.stdboth).not_to include("-rbundler/setup") + expect(stdboth).not_to include("-rbundler/setup") + end + + it "should delete BUNDLER_SETUP even if it was present in original env" do + create_file("source.rb", <<-RUBY) + print Bundler.unbundled_env.has_key?('BUNDLER_SETUP') + RUBY + ENV["BUNDLER_ORIG_BUNDLER_SETUP"] = system_gem_path("gems/bundler-#{Bundler::VERSION}/lib/bundler/setup").to_s + bundle_exec_ruby bundled_app("source.rb") + expect(stdboth).to include "false" end it "should restore RUBYLIB", :ruby_repo do create_file("source.rb", <<-RUBY) - print #{modified_env}['RUBYLIB'] + print Bundler.unbundled_env['RUBYLIB'] RUBY ENV["RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo" ENV["BUNDLER_ORIG_RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo-original" bundle_exec_ruby bundled_app("source.rb") - expect(last_command.stdboth).to include("/foo-original") + expect(stdboth).to include("/foo-original") end it "should restore the original MANPATH" do create_file("source.rb", <<-RUBY) - print #{modified_env}['MANPATH'] + print Bundler.unbundled_env['MANPATH'] RUBY ENV["MANPATH"] = "/foo" ENV["BUNDLER_ORIG_MANPATH"] = "/foo-original" bundle_exec_ruby bundled_app("source.rb") - expect(last_command.stdboth).to include("/foo-original") + expect(stdboth).to include("/foo-original") end end - describe "Bundler.unbundled_env" do - let(:modified_env) { "Bundler.unbundled_env" } - - it_behaves_like "an unbundling helper" - end - - describe "Bundler.clean_env", bundler: 2 do - let(:modified_env) { "Bundler.clean_env" } - - it_behaves_like "an unbundling helper" - end - describe "Bundler.with_original_env" do it "should set ENV to original_env in the block" do expected = Bundler.original_env @@ -152,26 +146,6 @@ RSpec.describe "Bundler.with_env helpers" do end end - describe "Bundler.with_clean_env", bundler: 2 do - it "should set ENV to unbundled_env in the block" do - expected = Bundler.unbundled_env - - actual = Bundler.ui.silence do - Bundler.with_clean_env { ENV.to_hash } - end - - expect(actual).to eq(expected) - end - - it "should restore the environment after execution" do - Bundler.ui.silence do - Bundler.with_clean_env { ENV["FOO"] = "hello" } - end - - expect(ENV).not_to have_key("FOO") - end - end - describe "Bundler.with_unbundled_env" do it "should set ENV to unbundled_env in the block" do expected = Bundler.unbundled_env @@ -203,21 +177,6 @@ RSpec.describe "Bundler.with_env helpers" do end end - describe "Bundler.clean_system", bundler: 2 do - before do - create_file("source.rb", <<-'RUBY') - Bundler.ui.silence { Bundler.clean_system("ruby", "-e", "exit(42) unless ENV['BUNDLE_FOO'] == 'bar'") } - - exit $?.exitstatus - RUBY - end - - it "runs system inside with_clean_env" do - run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) - expect($?.exitstatus).to eq(42) - end - end - describe "Bundler.unbundled_system" do before do create_file("source.rb", <<-'RUBY') @@ -254,27 +213,6 @@ RSpec.describe "Bundler.with_env helpers" do end end - describe "Bundler.clean_exec", bundler: 2 do - before do - create_file("source.rb", <<-'RUBY') - Process.fork do - exit Bundler.ui.silence { Bundler.clean_exec(%(test "\$BUNDLE_FOO" = "bar")) } - end - - _, status = Process.wait2 - - exit(status.exitstatus) - RUBY - end - - it "runs exec inside with_clean_env" do - skip "Fork not implemented" if Gem.win_platform? - - run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) - expect($?.exitstatus).to eq(1) - end - end - describe "Bundler.unbundled_exec" do before do create_file("source.rb", <<-'RUBY') @@ -288,7 +226,7 @@ RSpec.describe "Bundler.with_env helpers" do RUBY end - it "runs exec inside with_clean_env" do + it "runs exec inside with_unbundled_env" do skip "Fork not implemented" if Gem.win_platform? run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb")) diff --git a/spec/bundler/runtime/executable_spec.rb b/spec/bundler/runtime/executable_spec.rb index b11c48539a..89cee21b00 100644 --- a/spec/bundler/runtime/executable_spec.rb +++ b/spec/bundler/runtime/executable_spec.rb @@ -19,8 +19,9 @@ RSpec.describe "Running bin/* commands" do expect(out).to eq("1.0.0") end - it "allows the location of the gem stubs to be specified" do - bundle "binstubs myrack", path: "gbin" + it "allows the location of the gem stubs to be configured" do + bundle_config "bin gbin" + bundle "binstubs myrack" expect(bundled_app("bin")).not_to exist expect(bundled_app("gbin/myrackup")).to exist @@ -30,7 +31,8 @@ RSpec.describe "Running bin/* commands" do end it "allows absolute paths as a specification of where to install bin stubs" do - bundle "binstubs myrack", path: tmp("bin") + bundle_config "bin #{tmp("bin")}" + bundle "binstubs myrack" gembin tmp("bin/myrackup") expect(out).to eq("1.0.0") @@ -77,7 +79,7 @@ RSpec.describe "Running bin/* commands" do expect(out).to eq("1.0") end - it "creates a bundle binstub" do + it "does not create a bundle binstub" do gemfile <<-G source "https://gem.repo1" gem "bundler" @@ -85,7 +87,9 @@ RSpec.describe "Running bin/* commands" do bundle "binstubs bundler" - expect(bundled_app("bin/bundle")).to exist + expect(bundled_app("bin/bundle")).not_to exist + + expect(err).to include("Bundler itself does not use binstubs because its version is selected by RubyGems") end it "does not generate bin stubs if the option was not specified" do @@ -94,39 +98,7 @@ RSpec.describe "Running bin/* commands" do expect(bundled_app("bin/myrackup")).not_to exist end - it "allows you to stop installing binstubs", bundler: "< 3" do - skip "delete permission error" if Gem.win_platform? - - bundle "install --binstubs bin/" - bundled_app("bin/myrackup").rmtree - bundle "install --binstubs \"\"" - - expect(bundled_app("bin/myrackup")).not_to exist - - bundle "config bin" - expect(out).to include("You have not configured a value for `bin`") - end - - it "remembers that the option was specified", bundler: "< 3" do - gemfile <<-G - source "https://gem.repo1" - gem "activesupport" - G - - bundle :install, binstubs: "bin" - - gemfile <<-G - source "https://gem.repo1" - gem "activesupport" - gem "myrack" - G - - bundle "install" - - expect(bundled_app("bin/myrackup")).to exist - end - - it "rewrites bins on binstubs (to maintain backwards compatibility)" do + it "rewrites bins on binstubs with --force option" do install_gemfile <<-G source "https://gem.repo1" gem "myrack" @@ -134,9 +106,9 @@ RSpec.describe "Running bin/* commands" do create_file("bin/myrackup", "OMG") - bundle "binstubs myrack" + bundle "binstubs myrack", { force: true } - expect(bundled_app("bin/myrackup").read).to_not eq("OMG") + expect(bundled_app("bin/myrackup").read.strip).to_not eq("OMG") end it "use BUNDLE_GEMFILE gemfile for binstub" do diff --git a/spec/bundler/runtime/gem_tasks_spec.rb b/spec/bundler/runtime/gem_tasks_spec.rb index 1dffbd5c92..b855142e60 100644 --- a/spec/bundler/runtime/gem_tasks_spec.rb +++ b/spec/bundler/runtime/gem_tasks_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true RSpec.describe "require 'bundler/gem_tasks'" do - before :each do + let(:define_local_gem_using_gem_tasks) do bundled_app("foo.gemspec").open("w") do |f| f.write <<-GEMSPEC Gem::Specification.new do |s| @@ -26,11 +26,48 @@ RSpec.describe "require 'bundler/gem_tasks'" do G end - it "includes the relevant tasks" do - with_gem_path_as(base_system_gem_path.to_s) do - sys_exec "#{rake} -T", env: { "GEM_HOME" => system_gem_path.to_s } + let(:define_local_gem_with_extensions_using_gem_tasks_and_gemspec_dsl) do + bundled_app("foo.gemspec").open("w") do |f| + f.write <<-GEMSPEC + Gem::Specification.new do |s| + s.name = "foo" + s.version = "1.0" + s.summary = "dummy" + s.author = "Perry Mason" + s.extensions = "ext/extconf.rb" + end + GEMSPEC + end + + bundled_app("Rakefile").open("w") do |f| + f.write <<-RAKEFILE + require "bundler/gem_tasks" + RAKEFILE end + Dir.mkdir bundled_app("ext") + + bundled_app("ext/extconf.rb").open("w") do |f| + f.write <<-EXTCONF + require "mkmf" + File.write("Makefile", dummy_makefile($srcdir).join) + EXTCONF + end + + install_gemfile <<-G + source "https://gem.repo1" + + gemspec + + gem "rake" + G + end + + it "includes the relevant tasks" do + define_local_gem_using_gem_tasks + + in_bundled_app "rake -T" + expect(err).to be_empty expected_tasks = [ "rake build", @@ -44,11 +81,19 @@ RSpec.describe "require 'bundler/gem_tasks'" do end it "defines a working `rake install` task", :ruby_repo do - with_gem_path_as(base_system_gem_path.to_s) do - sys_exec "#{rake} install", env: { "GEM_HOME" => system_gem_path.to_s } - end + define_local_gem_using_gem_tasks + + in_bundled_app "rake install" + + expect(err).to be_empty + + bundle "exec rake install" expect(err).to be_empty + end + + it "defines a working `rake install` task for local gems with extensions", :ruby_repo do + define_local_gem_with_extensions_using_gem_tasks_and_gemspec_dsl bundle "exec rake install" @@ -57,6 +102,8 @@ RSpec.describe "require 'bundler/gem_tasks'" do context "rake build when path has spaces", :ruby_repo do before do + define_local_gem_using_gem_tasks + spaced_bundled_app = tmp("bundled app") FileUtils.cp_r bundled_app, spaced_bundled_app bundle "exec rake build", dir: spaced_bundled_app @@ -69,6 +116,8 @@ RSpec.describe "require 'bundler/gem_tasks'" do context "rake build when path has brackets", :ruby_repo do before do + define_local_gem_using_gem_tasks + bracketed_bundled_app = tmp("bundled[app") FileUtils.cp_r bundled_app, bracketed_bundled_app bundle "exec rake build", dir: bracketed_bundled_app @@ -81,7 +130,9 @@ RSpec.describe "require 'bundler/gem_tasks'" do context "bundle path configured locally" do before do - bundle "config set path vendor/bundle" + define_local_gem_using_gem_tasks + + bundle_config "path vendor/bundle" end it "works", :ruby_repo do @@ -98,9 +149,10 @@ RSpec.describe "require 'bundler/gem_tasks'" do end it "adds 'pkg' to rake/clean's CLOBBER" do - with_gem_path_as(base_system_gem_path.to_s) do - sys_exec %(#{rake} -e 'load "Rakefile"; puts CLOBBER.inspect'), env: { "GEM_HOME" => system_gem_path.to_s } - end + define_local_gem_using_gem_tasks + + in_bundled_app %(rake -e 'load "Rakefile"; puts CLOBBER.inspect') + expect(out).to eq '["pkg"]' end end diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index f85eaf132d..c6f9bbdbd7 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -81,7 +81,7 @@ RSpec.describe "bundler/inline#gemfile" do script <<-RUBY, artifice: "endpoint" gemfile(true) do - source "https://notaserver.com" + source "https://notaserver.test" gem "activesupport", :require => true end RUBY @@ -103,7 +103,7 @@ RSpec.describe "bundler/inline#gemfile" do my_ui = MyBundlerUI.new my_ui.level = "confirm" gemfile(true, :ui => my_ui) do - source "https://notaserver.com" + source "https://notaserver.test" gem "activesupport", :require => true end RUBY @@ -116,7 +116,7 @@ RSpec.describe "bundler/inline#gemfile" do require 'bundler/inline' gemfile(true, :quiet => true) do - source "https://notaserver.com" + source "https://notaserver.test" gem "activesupport", :require => true end RUBY @@ -363,7 +363,7 @@ RSpec.describe "bundler/inline#gemfile" do it "installs inline gems when a Gemfile.lock is present" do gemfile <<-G - source "https://notaserver.com" + source "https://notaserver.test" gem "rake" G @@ -380,7 +380,7 @@ RSpec.describe "bundler/inline#gemfile" do rake BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G script <<-RUBY @@ -397,7 +397,7 @@ RSpec.describe "bundler/inline#gemfile" do it "does not leak Gemfile.lock versions to the installation output" do gemfile <<-G - source "https://notaserver.com" + source "https://notaserver.test" gem "rake" G @@ -414,7 +414,7 @@ RSpec.describe "bundler/inline#gemfile" do rake BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G script <<-RUBY @@ -499,7 +499,7 @@ RSpec.describe "bundler/inline#gemfile" do end it "skips platform warnings" do - bundle "config set --local force_ruby_platform true" + bundle_config "force_ruby_platform true" script <<-RUBY gemfile(true) do @@ -512,7 +512,7 @@ RSpec.describe "bundler/inline#gemfile" do end it "still installs if the application has `bundle package` no_install config set" do - bundle "config set --local no_install true" + bundle_config "no_install true" script <<-RUBY gemfile do @@ -590,37 +590,10 @@ RSpec.describe "bundler/inline#gemfile" do expect(err).to be_empty end - it "when requiring fileutils after does not show redefinition warnings" do - Dir.mkdir tmp("path_without_gemfile") - - default_fileutils_version = ruby "gem 'fileutils', '< 999999'; require 'fileutils'; puts FileUtils::VERSION", raise_on_error: false - skip "fileutils isn't a default gem" if default_fileutils_version.empty? - - realworld_system_gems "fileutils --version 1.4.1" - - realworld_system_gems "pathname --version 0.2.0" - - script <<-RUBY, dir: tmp("path_without_gemfile"), env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s, "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s } - require "bundler/inline" - - gemfile(true) do - source "https://gem.repo2" - end - - require "fileutils" - RUBY - - expect(err).to eq("The Gemfile specifies no dependencies") - end - - it "does not load default timeout" do + it "does not load default timeout", rubygems: ">= 3.5.0" do default_timeout_version = ruby "gem 'timeout', '< 999999'; require 'timeout'; puts Timeout::VERSION", raise_on_error: false skip "timeout isn't a default gem" if default_timeout_version.empty? - # This only works on RubyGems 3.5.0 or higher - ruby "require 'rubygems/timeout'", raise_on_error: false - skip "rubygems under test does not yet vendor timeout" unless last_command.success? - build_repo4 do build_gem "timeout", "999" end @@ -655,4 +628,124 @@ RSpec.describe "bundler/inline#gemfile" do expect(out).to include("before: [\"Test_Variable\"]") expect(out).to include("after: [\"Test_Variable\"]") end + + it "does not create a lockfile" do + script <<-RUBY + require 'bundler/inline' + + gemfile do + source "https://gem.repo1" + end + + puts Dir.glob("Gemfile.lock") + RUBY + + expect(out).to be_empty + end + + it "does not reset ENV" do + script <<-RUBY + require 'bundler/inline' + + gemfile do + source "https://gem.repo1" + + ENV['FOO'] = 'bar' + end + + puts ENV['FOO'] + RUBY + + expect(out).to eq("bar") + end + + it "does not load specified version of psych and stringio", :ruby_repo do + build_repo4 do + build_gem "psych", "999" + build_gem "stringio", "999" + end + + script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + require "bundler/inline" + + gemfile(true) do + source "https://gem.repo4" + + gem "psych" + gem "stringio" + end + RUBY + + expect(out).to include("Installing psych 999") + expect(out).to include("Installing stringio 999") + if Gem.respond_to?(:use_psych?) && Gem.use_psych? + expect(out).to include("The psych gem was resolved to 999") + expect(out).to include("The stringio gem was resolved to 999") + end + end + + it "installs a conflicting default gem and non-default gems together" do + build_repo4 do + build_gem "securerandom", "999" + build_gem "myrack", "1.0.0" + end + + script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + gemfile(true) do + source "https://gem.repo4" + gem "securerandom" + gem "myrack" + end + + puts MYRACK + RUBY + + expect(out).to include("Installing securerandom 999") + expect(out).to include("Installing myrack 1.0.0") + expect(out).to include("1.0.0") + expect(err).to be_empty + end + + it "installs a conflicting default gem alongside git sources" do + build_repo4 do + build_gem "securerandom", "999" + end + + build_git "foo", "1.0.0" + + script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + gemfile(true) do + source "https://gem.repo4" + gem "securerandom" + gem "foo", :git => #{lib_path("foo-1.0.0").to_s.dump} + end + + puts FOO + RUBY + + expect(out).to include("Installing securerandom 999") + expect(out).to include("1.0.0") + expect(err).to be_empty + end + + it "leaves a lockfile in the same directory as the inline script alone" do + install_gemfile <<~G + source "https://gem.repo1" + gem "foo" + G + + original_lockfile = lockfile + + script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s } + require "bundler/inline" + + gemfile(true) do + source "https://gem.repo1" + + gem "myrack" + end + RUBY + + expect(lockfile).to eq(original_lockfile) + end end diff --git a/spec/bundler/runtime/load_spec.rb b/spec/bundler/runtime/load_spec.rb index 15f3d0eb5b..472cde87c5 100644 --- a/spec/bundler/runtime/load_spec.rb +++ b/spec/bundler/runtime/load_spec.rb @@ -68,7 +68,7 @@ RSpec.describe "Bundler.load" do begin expect { Bundler.load }.to raise_error(Bundler::GemfileNotFound) ensure - bundler_gemfile.rmtree if @remove_bundler_gemfile + FileUtils.rm_rf bundler_gemfile if @remove_bundler_gemfile end end end diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb index 007733d3de..6d96758956 100644 --- a/spec/bundler/runtime/platform_spec.rb +++ b/spec/bundler/runtime/platform_spec.rb @@ -100,7 +100,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do nokogiri (~> 1.11) #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L gemfile <<-G @@ -143,7 +143,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do nokogiri BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L bundle "install" @@ -219,7 +219,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do gem "platform_specific" G - bundle "config set force_ruby_platform true" + bundle_config "force_ruby_platform true" bundle "install" @@ -233,7 +233,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do gem "platform_specific" G - bundle "config set force_ruby_platform true" + bundle_config "force_ruby_platform true" bundle "install" @@ -247,7 +247,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do gem "platform_specific" G - bundle "config set force_ruby_platform true" + bundle_config "force_ruby_platform true" bundle "install" @@ -282,7 +282,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do platform_specific BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L bundle "install" @@ -316,7 +316,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do libv8 BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L bundle "install" @@ -344,7 +344,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do platform_specific BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L bundle "install" @@ -370,14 +370,14 @@ RSpec.describe "Bundler.setup with multi platform stuff" do end it "allows specifying only-ruby-platform on windows with dependency platforms" do - simulate_windows do + simulate_platform "x86-mswin32" do install_gemfile <<-G source "https://gem.repo1" - gem "nokogiri", :platforms => [:windows, :mswin, :mswin64, :mingw, :x64_mingw, :jruby] + gem "nokogiri", :platforms => [:windows, :jruby] gem "platform_specific" G - bundle "config set force_ruby_platform true" + bundle_config "force_ruby_platform true" bundle "install" @@ -397,8 +397,8 @@ RSpec.describe "Bundler.setup with multi platform stuff" do G bundle :lock - simulate_windows do - bundle "config set force_ruby_platform true" + simulate_platform "x86-mswin32" do + bundle_config "force_ruby_platform true" bundle "install" expect(the_bundle).to include_gems "myrack 1.0" @@ -411,7 +411,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do s.add_dependency "platform_specific" end end - simulate_windows x64_mingw32 do + simulate_platform "x64-mingw-ucrt" do lockfile <<-L GEM remote: https://gem.repo2/ @@ -421,7 +421,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do platform_specific PLATFORMS - x64-mingw32 + x64-mingw-ucrt x86-mingw32 DEPENDENCIES @@ -434,15 +434,13 @@ RSpec.describe "Bundler.setup with multi platform stuff" do G expect(out).to include("lockfile does not have all gems needed for the current platform") - expect(the_bundle).to include_gem "platform_specific 1.0 x64-mingw32" + expect(the_bundle).to include_gem "platform_specific 1.0 x64-mingw-ucrt" end end - %w[x86-mswin32 x64-mswin64 x86-mingw32 x64-mingw32 x64-mingw-ucrt].each do |arch| - it "allows specifying platform windows on #{arch} arch" do - platform = send(arch.tr("-", "_")) - - simulate_windows platform do + %w[x86-mswin32 x64-mswin64 x86-mingw32 x64-mingw-ucrt aarch64-mingw-ucrt].each do |platform| + it "allows specifying platform windows on #{platform} platform" do + simulate_platform platform do lockfile <<-L GEM remote: https://gem.repo1/ @@ -463,8 +461,6 @@ RSpec.describe "Bundler.setup with multi platform stuff" do gem "platform_specific", :platforms => [:windows] G - bundle "install" - expect(the_bundle).to include_gems "platform_specific 1.0 #{platform}" end end diff --git a/spec/bundler/runtime/require_spec.rb b/spec/bundler/runtime/require_spec.rb index ff45a3c5e2..46613286d2 100644 --- a/spec/bundler/runtime/require_spec.rb +++ b/spec/bundler/runtime/require_spec.rb @@ -119,11 +119,9 @@ RSpec.describe "Bundler.require" do end G - load_error_run <<-R, "fail" - Bundler.require - R + run "Bundler.require", raise_on_error: false - expect(err_without_deprecations).to eq("ZOMG LOAD ERROR") + expect(err_without_deprecations).to include("cannot load such file -- fail") end it "displays a helpful message if the required gem throws an error" do @@ -155,16 +153,9 @@ RSpec.describe "Bundler.require" do end G - cmd = <<-RUBY - begin - Bundler.require - rescue LoadError => e - warn "ZOMG LOAD ERROR: \#{e.message}" - end - RUBY - run(cmd) + run "Bundler.require", raise_on_error: false - expect(err_without_deprecations).to eq("ZOMG LOAD ERROR: cannot load such file -- load-bar") + expect(err_without_deprecations).to include("cannot load such file -- load-bar") end describe "with namespaced gems" do @@ -215,10 +206,9 @@ RSpec.describe "Bundler.require" do end G - load_error_run <<-R, "jquery-rails" - Bundler.require - R - expect(err_without_deprecations).to eq("ZOMG LOAD ERROR") + run "Bundler.require", raise_on_error: false + + expect(err_without_deprecations).to include("cannot load such file -- jquery-rails") end it "handles the case where regex fails" do @@ -233,16 +223,9 @@ RSpec.describe "Bundler.require" do end G - cmd = <<-RUBY - begin - Bundler.require - rescue LoadError => e - warn "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'") - end - RUBY - run(cmd) + run "Bundler.require", raise_on_error: false - expect(err_without_deprecations).to eq("ZOMG LOAD ERROR") + expect(err_without_deprecations).to include("libfuuu-1.0").and include("cannot open shared object file") end it "doesn't swallow the error when the library has an unrelated error" do @@ -257,16 +240,9 @@ RSpec.describe "Bundler.require" do end G - cmd = <<-RUBY - begin - Bundler.require - rescue LoadError => e - warn "ZOMG LOAD ERROR: \#{e.message}" - end - RUBY - run(cmd) + run "Bundler.require", raise_on_error: false - expect(err_without_deprecations).to eq("ZOMG LOAD ERROR: cannot load such file -- load-bar") + expect(err_without_deprecations).to include("cannot load such file -- load-bar") end end @@ -375,10 +351,9 @@ RSpec.describe "Bundler.require" do gem "busted_require" G - load_error_run <<-R, "no_such_file_omg" - Bundler.require - R - expect(err_without_deprecations).to eq("ZOMG LOAD ERROR") + run "Bundler.require", raise_on_error: false + + expect(err_without_deprecations).to include("cannot load such file -- no_such_file_omg") end end end @@ -431,6 +406,22 @@ RSpec.describe "Bundler.require" do expect(out).to eq("WIN") end + it "does not load plugins" do + install_gemfile <<-G + source "https://gem.repo1" + gem "myrack" + G + + create_file "plugins/rubygems_plugin.rb", "puts 'FAIL'" + + run <<~R, env: { "RUBYLIB" => rubylib.unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR) } + Bundler.require + puts "WIN" + R + + expect(out).to eq("WIN") + end + it "does not extract gemspecs from application cache packages" do gemfile <<-G source "https://gem.repo1" diff --git a/spec/bundler/runtime/requiring_spec.rb b/spec/bundler/runtime/requiring_spec.rb index 1f32269622..f0e0aeacaf 100644 --- a/spec/bundler/runtime/requiring_spec.rb +++ b/spec/bundler/runtime/requiring_spec.rb @@ -2,14 +2,14 @@ RSpec.describe "Requiring bundler" do it "takes care of requiring rubygems when entrypoint is bundler/setup" do - sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler/setup -e'puts true'", env: { "RUBYOPT" => opt_add("--disable=gems", ENV["RUBYOPT"]) }) + sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler/setup -e'puts true'", env: { "RUBYOPT" => "--disable=gems" }) - expect(last_command.stdboth).to eq("true") + expect(stdboth).to eq("true") end it "takes care of requiring rubygems when requiring just bundler" do - sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler -e'puts true'", env: { "RUBYOPT" => opt_add("--disable=gems", ENV["RUBYOPT"]) }) + sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler -e'puts true'", env: { "RUBYOPT" => "--disable=gems" }) - expect(last_command.stdboth).to eq("true") + expect(stdboth).to eq("true") end end diff --git a/spec/bundler/runtime/self_management_spec.rb b/spec/bundler/runtime/self_management_spec.rb index d2472dece2..176c2a3121 100644 --- a/spec/bundler/runtime/self_management_spec.rb +++ b/spec/bundler/runtime/self_management_spec.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true -RSpec.describe "Self management", rubygems: ">= 3.3.0.dev" do +RSpec.describe "Self management" do describe "auto switching" do let(:previous_minor) do - "2.3.0" + "9.3.0" end let(:current_version) do - "2.4.0" + "9.4.0" end before do @@ -24,22 +24,24 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev" do gem "myrack" G + + pristine_system_gems "bundler-#{current_version}" end it "installs locked version when using system path and uses it" do lockfile_bundled_with(previous_minor) - bundle "config set --local path.system true" - bundle "install", preserve_ruby_flags: true - expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + bundle_config "path.system true" + bundle "install" + expect(out).to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") # It uninstalls the older system bundler bundle "clean --force", artifice: nil - expect(out).to eq("Removing bundler (#{Bundler::VERSION})") + expect(out).to eq("Removing bundler (#{current_version})") # App now uses locked version bundle "-v", artifice: nil - expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor) + expect(out).to eq(previous_minor) # ruby-core test setup has always "lib" in $LOAD_PATH so `require "bundler/setup"` always activate the local version rather than using RubyGems gem activation stuff unless ruby_core? @@ -48,26 +50,26 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev" do create_file file, <<-RUBY #!#{Gem.ruby} require 'bundler/setup' - puts Bundler::VERSION + puts '#{previous_minor}' RUBY file.chmod(0o777) cmd = Gem.win_platform? ? "#{Gem.ruby} bin/bundle_version.rb" : "bin/bundle_version.rb" - sys_exec cmd, artifice: nil + in_bundled_app cmd expect(out).to eq(previous_minor) end # Subsequent installs use the locked version without reinstalling bundle "install --verbose", artifice: nil expect(out).to include("Using bundler #{previous_minor}") - expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + expect(out).not_to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") end it "installs locked version when using local path and uses it" do lockfile_bundled_with(previous_minor) - bundle "config set --local path vendor/bundle" - bundle "install", preserve_ruby_flags: true - expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + bundle_config "path vendor/bundle" + bundle "install" + expect(out).to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist # It does not uninstall the locked bundler @@ -76,7 +78,11 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev" do # App now uses locked version bundle "-v" - expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor) + expect(out).to eq(previous_minor) + + # Preserves original gem home when auto-switching + bundle "exec ruby -e 'puts Bundler.original_env[\"GEM_HOME\"]'" + expect(out).to eq(ENV["GEM_HOME"]) # ruby-core test setup has always "lib" in $LOAD_PATH so `require "bundler/setup"` always activate the local version rather than using RubyGems gem activation stuff unless ruby_core? @@ -85,26 +91,26 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev" do create_file file, <<-RUBY #!#{Gem.ruby} require 'bundler/setup' - puts Bundler::VERSION + puts '#{previous_minor}' RUBY file.chmod(0o777) cmd = Gem.win_platform? ? "#{Gem.ruby} bin/bundle_version.rb" : "bin/bundle_version.rb" - sys_exec cmd, artifice: nil + in_bundled_app cmd expect(out).to eq(previous_minor) end # Subsequent installs use the locked version without reinstalling bundle "install --verbose" expect(out).to include("Using bundler #{previous_minor}") - expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + expect(out).not_to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") end it "installs locked version when using deployment option and uses it" do lockfile_bundled_with(previous_minor) - bundle "config set --local deployment true" - bundle "install", preserve_ruby_flags: true - expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + bundle_config "deployment true" + bundle "install" + expect(out).to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist # It does not uninstall the locked bundler @@ -113,12 +119,12 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev" do # App now uses locked version bundle "-v" - expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor) + expect(out).to eq(previous_minor) # Subsequent installs use the locked version without reinstalling bundle "install --verbose" expect(out).to include("Using bundler #{previous_minor}") - expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + expect(out).not_to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") end it "does not try to install a development version" do @@ -128,48 +134,126 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev" do expect(out).not_to match(/restarting using that version/) bundle "-v" - expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION) + expect(out).to eq(current_version) + end + + it "does not try to install when --local is passed" do + lockfile_bundled_with(previous_minor) + system_gems "myrack-1.0.0", path: local_gem_path + + bundle "install --local" + expect(out).not_to match(/Installing Bundler/) + + bundle "-v" + expect(out).to eq(current_version) end it "shows a discrete message if locked bundler does not exist" do - missing_minor = "#{Bundler::VERSION[0]}.999.999" + missing_minor = "#{current_version[0]}.999.999" lockfile_bundled_with(missing_minor) bundle "install" - expect(err).to eq("Your lockfile is locked to a version of bundler (#{missing_minor}) that doesn't exist at https://rubygems.org/. Going on using #{Bundler::VERSION}") + expect(err).to eq("Your lockfile is locked to a version of bundler (#{missing_minor}) that doesn't exist at https://rubygems.org/. Going on using #{current_version}") bundle "-v" - expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION) + expect(out).to eq(current_version) end it "installs BUNDLE_VERSION version when using bundle config version x.y.z" do lockfile_bundled_with(current_version) - bundle "config set --local version #{previous_minor}" - bundle "install", preserve_ruby_flags: true - expect(out).to include("Bundler #{Bundler::VERSION} is running, but your configuration was #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") + bundle_config "version #{previous_minor}" + bundle "install" + expect(out).to include("Bundler #{current_version} is running, but your configuration was #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.") bundle "-v" - expect(out).to eq(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor) + expect(out).to eq(previous_minor) + end + + it "requires the right bundler version from the config and run bundle CLI without re-exec" do + unless Bundler.rubygems.provides?(">= 4.1.0.dev") + skip "This spec can only run when Gem::BundlerVersionFinder.bundler_versions reads bundler configs" + end + + lockfile_bundled_with(current_version) + + bundle_config "version #{previous_minor}" + bundle_config "path.system true" + bundle "install" + + script = bundled_app("script.rb") + create_file(script, "p 'executed once'") + + bundle "-v", env: { "RUBYOPT" => "-r#{script}" } + expect(out).to eq(%("executed once"\n9.3.0)) end it "does not try to install when using bundle config version global" do lockfile_bundled_with(previous_minor) - bundle "config set version system" + bundle_config "version system" bundle "install" expect(out).not_to match(/restarting using that version/) bundle "-v" - expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION) + expect(out).to eq(current_version) + end + + it "does not try to install when using bundle config version <dev-version>" do + lockfile_bundled_with(previous_minor) + + bundle_config "version #{previous_minor}.dev" + bundle "install" + expect(out).not_to match(/restarting using that version/) + + bundle "-v" + expect(out).to eq(current_version) end it "ignores malformed lockfile version" do lockfile_bundled_with("2.3.") bundle "install --verbose" - expect(out).to include("Using bundler #{Bundler::VERSION}") + expect(out).to include("Using bundler #{current_version}") + end + + it "uses the right original script when re-execing, if `$0` has been changed to something that's not a script", :ruby_repo do + system_gems "bundler-9.9.9", path: local_gem_path + + test = bundled_app("test.rb") + + create_file test, <<~RUBY + $0 = "this is the program name" + require "bundler/setup" + RUBY + + lockfile_bundled_with("9.9.9") + + in_bundled_app "#{Gem.ruby} #{test}", raise_on_error: false + expect(err).to include("Could not find myrack-1.0.0") + expect(err).not_to include("this is the program name") + end + + it "uses modified $0 when re-execing, if `$0` has been changed to a script", :ruby_repo do + system_gems "bundler-9.9.9", path: local_gem_path + + runner = bundled_app("runner.rb") + + create_file runner, <<~RUBY + $0 = ARGV.shift + load $0 + RUBY + + script = bundled_app("script.rb") + create_file script, <<~RUBY + require "bundler/setup" + RUBY + + lockfile_bundled_with("9.9.9") + + in_bundled_app "#{Gem.ruby} #{runner} #{script}", raise_on_error: false + expect(err).to include("Could not find myrack-1.0.0") end private diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb index ededaab410..ceb6fcf66a 100644 --- a/spec/bundler/runtime/setup_spec.rb +++ b/spec/bundler/runtime/setup_spec.rb @@ -135,7 +135,7 @@ RSpec.describe "Bundler.setup" do end it "orders the load path correctly when there are dependencies" do - bundle "config set path.system true" + bundle_config "path.system true" install_gemfile <<-G source "https://gem.repo1" @@ -163,7 +163,7 @@ RSpec.describe "Bundler.setup" do end it "falls back to order the load path alphabetically for backwards compatibility" do - bundle "config set path.system true" + bundle_config "path.system true" install_gemfile <<-G source "https://gem.repo1" @@ -286,7 +286,7 @@ RSpec.describe "Bundler.setup" do G bundle "install" - bundle "config set --local deployment true" + bundle_config "deployment true" ENV["BUNDLE_GEMFILE"] = "Gemfile" ruby <<-R @@ -303,6 +303,32 @@ RSpec.describe "Bundler.setup" do expect(out).to eq("WIN") end end + + context "user sets it via `config set --local gemfile`" do + it "uses the value in the config" do + gemfile <<-G + source "https://gem.repo1" + gem "myrack" + G + + gemfile bundled_app("CustomGemfile"), <<-G + source "https://gem.repo1" + gem "activesupport", "2.3.5" + G + + bundle_config "gemfile #{bundled_app("CustomGemfile")}" + bundle "install" + + ruby <<-R + require 'bundler' + Bundler.setup + require 'activesupport' + puts ACTIVESUPPORT + R + + expect(out).to eq("2.3.5") + end + end end it "prioritizes gems in BUNDLE_PATH over gems in GEM_HOME" do @@ -366,7 +392,8 @@ RSpec.describe "Bundler.setup" do it "removes system gems from Gem.source_index" do run "require 'yard'" - expect(out).to eq("bundler-#{Bundler::VERSION}\nyard-1.0") + expect(out).to include("bundler-#{Bundler::VERSION}").and include("yard-1.0") + expect(out).not_to include("activesupport-2.3.5") end context "when the ruby stdlib is a substring of Gem.path" do @@ -457,14 +484,13 @@ RSpec.describe "Bundler.setup" do end it "works even when the cache directory has been deleted" do - bundle "config set --local path vendor/bundle" bundle :install - FileUtils.rm_rf vendored_gems("cache") + FileUtils.rm_r default_cache_path expect(the_bundle).to include_gems "myrack 1.0.0" end it "does not randomly change the path when specifying --path and the bundle directory becomes read only" do - bundle "config set --local path vendor/bundle" + bundle_config "path vendor/bundle" bundle :install with_read_only("#{bundled_app}/**/*") do @@ -473,7 +499,7 @@ RSpec.describe "Bundler.setup" do end it "finds git gem when default bundle path becomes read only" do - bundle "config set --local path .bundle" + bundle_config "path .bundle" bundle "install" with_read_only("#{bundled_app(".bundle")}/**/*") do @@ -496,7 +522,7 @@ RSpec.describe "Bundler.setup" do bundle %(config set local.myrack #{lib_path("local-myrack")}) bundle :install - FileUtils.rm_rf(lib_path("local-myrack")) + FileUtils.rm_r(lib_path("local-myrack")) run "require 'myrack'", raise_on_error: false expect(err).to match(/Cannot use local override for myrack-0.8 because #{Regexp.escape(lib_path("local-myrack").to_s)} does not exist/) end @@ -568,7 +594,7 @@ RSpec.describe "Bundler.setup" do describe "when excluding groups" do it "doesn't change the resolve if --without is used" do - bundle "config set --local without rails" + bundle_config "without rails" install_gemfile <<-G source "https://gem.repo1" gem "activesupport" @@ -584,7 +610,7 @@ RSpec.describe "Bundler.setup" do end it "remembers --without and does not bail on bare Bundler.setup" do - bundle "config set --local without rails" + bundle_config "without rails" install_gemfile <<-G source "https://gem.repo1" gem "activesupport" @@ -600,7 +626,7 @@ RSpec.describe "Bundler.setup" do end it "remembers --without and does not bail on bare Bundler.setup, even in the case of path gems no longer available" do - bundle "config set --local without development" + bundle_config "without development" path = bundled_app(File.join("vendor", "foo")) build_lib "foo", path: path @@ -611,7 +637,7 @@ RSpec.describe "Bundler.setup" do gem 'foo', :path => 'vendor/foo', :group => :development G - FileUtils.rm_rf(path) + FileUtils.rm_r(path) ruby "require 'bundler'; Bundler.setup", env: { "DEBUG" => "1" } expect(out).to include("Assuming that source at `vendor/foo` has not changed since fetching its specs errored") @@ -666,7 +692,7 @@ RSpec.describe "Bundler.setup" do end it "remembers --without and does not include groups passed to Bundler.setup" do - bundle "config set --local without rails" + bundle_config "without rails" install_gemfile <<-G source "https://gem.repo1" gem "activesupport" @@ -706,6 +732,21 @@ RSpec.describe "Bundler.setup" do expect(out).to be_empty end + it "has gem_dir pointing to local repo" do + build_lib "foo", "1.0", path: bundled_app + + install_gemfile <<-G + source "https://gem.repo1" + gemspec + G + + run <<-R + puts Gem.loaded_specs['foo'].gem_dir + R + + expect(out).to eq(bundled_app.to_s) + end + it "does not load all gemspecs" do install_gemfile <<-G source "https://gem.repo1" @@ -713,46 +754,52 @@ RSpec.describe "Bundler.setup" do G run <<-R - File.open(File.join(Gem.dir, "specifications", "broken.gemspec"), "w") do |f| + File.open(File.join(Gem.dir, "specifications", "invalid.gemspec"), "w") do |f| f.write <<-RUBY # -*- encoding: utf-8 -*- -# stub: broken 1.0.0 ruby lib +# stub: invalid 1.0.0 ruby lib Gem::Specification.new do |s| - s.name = "broken" + s.name = "invalid" s.version = "1.0.0" - raise "BROKEN GEMSPEC" + s.authors = ["Invalid Author"] + s.files = ["lib/invalid.rb"] + s.add_dependency "nonexistent-gem", "~> 999.999.999" + s.validate! end RUBY end R run <<-R - File.open(File.join(Gem.dir, "specifications", "broken-ext.gemspec"), "w") do |f| + File.open(File.join(Gem.dir, "specifications", "invalid-ext.gemspec"), "w") do |f| f.write <<-RUBY # -*- encoding: utf-8 -*- -# stub: broken-ext 1.0.0 ruby lib +# stub: invalid-ext 1.0.0 ruby lib # stub: a.ext\\0b.ext Gem::Specification.new do |s| - s.name = "broken-ext" + s.name = "invalid-ext" s.version = "1.0.0" - raise "BROKEN GEMSPEC EXT" + s.authors = ["Invalid Author"] + s.files = ["lib/invalid.rb"] + s.required_ruby_version = "~> 0.8.0" + s.validate! end RUBY end # Need to write the gem.build_complete file, # otherwise the full spec is loaded to check the installed_by_version extensions_dir = Gem.default_ext_dir_for(Gem.dir) || File.join(Gem.dir, "extensions", Gem::Platform.local.to_s, Gem.extension_api_version) - Bundler::FileUtils.mkdir_p(File.join(extensions_dir, "broken-ext-1.0.0")) - File.open(File.join(extensions_dir, "broken-ext-1.0.0", "gem.build_complete"), "w") {} + Bundler::FileUtils.mkdir_p(File.join(extensions_dir, "invalid-ext-1.0.0")) + File.open(File.join(extensions_dir, "invalid-ext-1.0.0", "gem.build_complete"), "w") {} R run <<-R - puts "WIN" + puts "Success" R - expect(out).to eq("WIN") + expect(out).to eq("Success") end it "ignores empty gem paths" do @@ -865,7 +912,6 @@ end it "should clean $LOAD_PATH properly" do gem_name = "very_simple_binary" full_gem_name = gem_name + "-1.0" - ext_dir = File.join(tmp("extensions", full_gem_name)) system_gems full_gem_name @@ -874,12 +920,6 @@ end G ruby <<-R - s = Gem::Specification.find_by_name '#{gem_name}' - s.extension_dir = '#{ext_dir}' - - # Don't build extensions. - s.class.send(:define_method, :build_extensions) { nil } - require 'bundler' gem '#{gem_name}' @@ -1074,7 +1114,7 @@ end describe "with system gems in the bundle" do before :each do - bundle "config set path.system true" + bundle_config "path.system true" system_gems "myrack-1.0.0" install_gemfile <<-G @@ -1143,7 +1183,7 @@ end bundler_module = class << Bundler; self; end bundler_module.send(:remove_method, :require) def Bundler.require(path) - raise "LOSE" + raise StandardError, "didn't use binding from top level" end Bundler.load RUBY @@ -1188,7 +1228,7 @@ end end before do - bundle "config set --local path.system true" + bundle_config "path.system true" install_gemfile <<-G source "https://gem.repo1" @@ -1253,7 +1293,7 @@ end lock += <<~L BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L lock @@ -1269,7 +1309,12 @@ end end context "is not present" do - it "does not change the lock" do + # Skipped on ruby-core because `ruby "require 'bundler/setup'"` does not + # activate bundler as a gem there, so Source::Metadata falls back to a + # synthetic spec whose cache_file does not exist on disk and + # LockfileGenerator#bundler_checksum drops the bundler checksum, while + # the on-disk lockfile still has it. + it "does not change the lock", :ruby_repo do expect { ruby "require 'bundler/setup'" }.not_to change { lockfile } end end @@ -1315,7 +1360,7 @@ end gem "bar", :git => "#{lib_path("bar-1.0")}" G - bundle :install + bundle :install, env: { "BUNDLE_LOCKFILE_CHECKSUMS" => "false" } ruby <<-RUBY, artifice: nil require 'bundler/setup' @@ -1377,29 +1422,27 @@ end end it "activates default gems when they are part of the bundle, but not installed explicitly", :ruby_repo do - default_json_version = ruby "gem 'json'; require 'json'; puts JSON::VERSION" + default_delegate_version = ruby "gem 'delegate'; require 'delegate'; puts Delegator::VERSION" build_repo2 do - build_gem "json", default_json_version + build_gem "delegate", default_delegate_version end - gemfile "source \"https://gem.repo2\"; gem 'json'" + gemfile "source \"https://gem.repo2\"; gem 'delegate'" ruby <<-RUBY require "bundler/setup" - require "json" - puts defined?(::JSON) ? "JSON defined" : "JSON undefined" + require "delegate" + puts defined?(::Delegator) ? "Delegator defined" : "Delegator undefined" RUBY + expect(out).to eq("Delegator defined") expect(err).to be_empty end describe "default gem activation" do let(:exemptions) do exempts = %w[did_you_mean bundler uri pathname] - exempts << "etc" if (Gem.ruby_version < Gem::Version.new("3.2") || Gem.ruby_version >= Gem::Version.new("3.3.2")) && Gem.win_platform? - exempts << "set" unless Gem.rubygems_version >= Gem::Version.new("3.2.6") - exempts << "tsort" unless Gem.rubygems_version >= Gem::Version.new("3.2.31") exempts << "error_highlight" # added in Ruby 3.1 as a default gem exempts << "ruby2_keywords" # added in Ruby 3.1 as a default gem exempts << "syntax_suggest" # added in Ruby 3.2 as a default gem @@ -1458,7 +1501,7 @@ end install_gemfile "source 'https://gem.repo1'" create_file("script.rb", "#!/usr/bin/env ruby\n\n#{code}") FileUtils.chmod(0o777, bundled_app("script.rb")) - bundle "exec ./script.rb", artifice: nil, env: { "RUBYOPT" => activation_warning_hack_rubyopt } + bundle "exec ./script.rb", env: { "RUBYOPT" => activation_warning_hack_rubyopt } expect(out).to eq("{}") end @@ -1474,7 +1517,7 @@ end gem "net-http-pipeline", "1.0.1" G - bundle "config set --local path vendor/bundle" + bundle_config "path vendor/bundle" bundle :install @@ -1518,22 +1561,7 @@ end end describe "after setup" do - it "allows calling #gem on random objects", bundler: "< 3" do - install_gemfile <<-G - source "https://gem.repo1" - gem "myrack" - G - - ruby <<-RUBY - require "bundler/setup" - Object.new.gem "myrack" - puts Gem.loaded_specs["myrack"].full_name - RUBY - - expect(out).to eq("myrack-1.0.0") - end - - it "keeps Kernel#gem private", bundler: "3" do + it "keeps Kernel#gem private" do install_gemfile <<-G source "https://gem.repo1" gem "myrack" @@ -1545,8 +1573,8 @@ end puts "FAIL" RUBY - expect(last_command.stdboth).not_to include "FAIL" - expect(err).to include "private method `gem'" + expect(stdboth).not_to include "FAIL" + expect(err).to match(/private method [`']gem'/) end it "keeps Kernel#require private" do @@ -1561,7 +1589,7 @@ end puts "FAIL" RUBY - expect(last_command.stdboth).not_to include "FAIL" + expect(stdboth).not_to include "FAIL" expect(err).to match(/private method [`']require'/) end @@ -1640,7 +1668,7 @@ end gem "myrack", :group => :test G - bundle "config set auto_install 1" + bundle_config "auto_install 1" ruby <<-RUBY, artifice: "compact_index" require 'bundler/setup' @@ -1648,4 +1676,35 @@ end expect(err).to be_empty expect(out).to include("Installing myrack 1.0.0") end + + context "in a read-only filesystem" do + before do + gemfile <<-G + source "https://gem.repo4" + G + + lockfile <<-L + GEM + remote: https://gem.repo4/ + + PLATFORMS + x86_64-darwin-19 + + DEPENDENCIES + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "should fail loudly if the lockfile platforms don't include the current platform" do + simulate_platform "x86_64-linux" do + ruby <<-RUBY, raise_on_error: false, env: { "BUNDLER_SPEC_READ_ONLY" => "true", "BUNDLER_FORCE_TTY" => "true" } + require "bundler/setup" + RUBY + end + + expect(err).to include("Your lockfile is missing the current platform, but can't be updated because file system is read-only") + end + end end |
