diff options
Diffstat (limited to 'spec/bundler/commands/exec_spec.rb')
-rw-r--r-- | spec/bundler/commands/exec_spec.rb | 226 |
1 files changed, 164 insertions, 62 deletions
diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 39430d52a4..d59b690d2f 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -2,12 +2,12 @@ RSpec.describe "bundle exec" do let(:system_gems_to_install) { %w[rack-1.0.0 rack-0.9.1] } - before :each do - system_gems(system_gems_to_install, :path => default_bundle_path) - end it "works with --gemfile flag" do + system_gems(system_gems_to_install, path: default_bundle_path) + create_file "CustomGemfile", <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "1.0.0" G @@ -16,7 +16,10 @@ RSpec.describe "bundle exec" do end it "activates the correct gem" do + system_gems(system_gems_to_install, path: default_bundle_path) + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" G @@ -25,17 +28,21 @@ RSpec.describe "bundle exec" do end it "works and prints no warnings when HOME is not writable" do + system_gems(system_gems_to_install, path: default_bundle_path) + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" G - bundle "exec rackup", :env => { "HOME" => "/" } + bundle "exec rackup", env: { "HOME" => "/" } expect(out).to eq("0.9.1") expect(err).to be_empty end it "works when the bins are in ~/.bundle" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -45,6 +52,7 @@ RSpec.describe "bundle exec" do it "works when running from a random directory" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -54,37 +62,39 @@ RSpec.describe "bundle exec" do end it "works when exec'ing something else" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec echo exec" expect(out).to eq("exec") end it "works when exec'ing to ruby" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec ruby -e 'puts %{hi}'" expect(out).to eq("hi") end it "works when exec'ing to rubygems" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec #{gem_cmd} --version" expect(out).to eq(Gem::VERSION) end it "works when exec'ing to rubygems through sh -c" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec sh -c '#{gem_cmd} --version'" expect(out).to eq(Gem::VERSION) end it "works when exec'ing back to bundler with a lockfile that doesn't include the current platform" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" G # simulate lockfile generated with old version not including specific platform lockfile <<-L GEM + remote: #{file_uri_for(gem_repo1)}/ specs: rack (0.9.1) @@ -98,7 +108,7 @@ RSpec.describe "bundle exec" do 2.1.4 L - bundle "exec bundle cache", :env => { "BUNDLER_VERSION" => Bundler::VERSION } + bundle "exec bundle cache", env: { "BUNDLER_VERSION" => Bundler::VERSION } expect(out).to include("Updating files in vendor/cache") end @@ -110,20 +120,20 @@ RSpec.describe "bundle exec" do Process.setproctitle("1-2-3-4-5-6-7") puts `ps -ocommand= -p#{$$}` RUBY - create_file "Gemfile" + create_file "Gemfile", "source \"#{file_uri_for(gem_repo1)}\"" create_file "a.rb", script_that_changes_its_own_title_and_checks_if_picked_up_by_ps_unix_utility bundle "exec ruby a.rb" expect(out).to eq("1-2-3-4-5-6-7") end it "accepts --verbose" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec --verbose echo foobar" expect(out).to eq("foobar") end it "passes --verbose to command if it is given after the command" do - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" bundle "exec echo --verbose" expect(out).to eq("--verbose") end @@ -147,7 +157,7 @@ RSpec.describe "bundle exec" do end G - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" sys_exec "#{Gem.ruby} #{command.path}" expect(out).to be_empty @@ -155,7 +165,7 @@ RSpec.describe "bundle exec" do end it "accepts --keep-file-descriptors" do - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" bundle "exec --keep-file-descriptors echo foobar" expect(err).to be_empty @@ -164,7 +174,7 @@ RSpec.describe "bundle exec" do it "can run a command named --verbose" do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - install_gemfile 'gem "rack"' + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\"" File.open(bundled_app("--verbose"), "w") do |f| f.puts "#!/bin/sh" f.puts "echo foobar" @@ -188,7 +198,7 @@ RSpec.describe "bundle exec" do gem "rack", "0.9.1" G - install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2 + install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2 source "#{file_uri_for(gem_repo2)}" gem "rack_two", "1.0.0" G @@ -197,20 +207,18 @@ RSpec.describe "bundle exec" do expect(out).to eq("0.9.1") - bundle "exec rackup", :dir => bundled_app2 + bundle "exec rackup", dir: bundled_app2 expect(out).to eq("1.0.0") end context "with default gems" do - let(:system_gems_to_install) { [] } - - let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false } + let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", raise_on_error: false } context "when not specified in Gemfile" do before do skip "irb isn't a default gem" if default_irb_version.empty? - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" end it "uses version provided by ruby" do @@ -284,14 +292,14 @@ RSpec.describe "bundle exec" do end end - bundle "config set path.system true" + bundle "config set --global path.system true" install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack", "0.9.1" G - install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2 + install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2 source "#{file_uri_for(gem_repo2)}" gem "rack_two", "1.0.0" G @@ -325,6 +333,7 @@ RSpec.describe "bundle exec" do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -335,7 +344,7 @@ RSpec.describe "bundle exec" do bundle "exec 'echo $RUBYOPT'" expect(out.split(" ").count(bundler_setup_opt)).to eq(1) - bundle "exec 'echo $RUBYOPT'", :env => { "RUBYOPT" => rubyopt } + bundle "exec 'echo $RUBYOPT'", env: { "RUBYOPT" => rubyopt } expect(out.split(" ").count(bundler_setup_opt)).to eq(1) end @@ -343,6 +352,7 @@ RSpec.describe "bundle exec" do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -353,16 +363,17 @@ RSpec.describe "bundle exec" do bundle "exec 'echo $RUBYLIB'" expect(out).to include(rubylib) - bundle "exec 'echo $RUBYLIB'", :env => { "RUBYLIB" => rubylib } + bundle "exec 'echo $RUBYLIB'", env: { "RUBYLIB" => rubylib } expect(out).to include(rubylib) end it "errors nicely when the argument doesn't exist" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G - bundle "exec foobarbaz", :raise_on_error => false + bundle "exec foobarbaz", raise_on_error: false expect(exitstatus).to eq(127) expect(err).to include("bundler: command not found: foobarbaz") expect(err).to include("Install missing gem executables with `bundle install`") @@ -370,26 +381,30 @@ RSpec.describe "bundle exec" do it "errors nicely when the argument is not executable" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G bundle "exec touch foo" - bundle "exec ./foo", :raise_on_error => false + bundle "exec ./foo", raise_on_error: false expect(exitstatus).to eq(126) expect(err).to include("bundler: not executable: ./foo") end it "errors nicely when no arguments are passed" do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G - bundle "exec", :raise_on_error => false + bundle "exec", raise_on_error: false expect(exitstatus).to eq(128) expect(err).to include("bundler: exec needs a command to run") end it "raises a helpful error when exec'ing to something outside of the bundle" do + system_gems(system_gems_to_install, path: default_bundle_path) + bundle "config set clean false" # want to keep the rackup binstub install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -397,7 +412,7 @@ RSpec.describe "bundle exec" do G [true, false].each do |l| bundle "config set disable_exec_load #{l}" - bundle "exec rackup", :raise_on_error => false + bundle "exec rackup", raise_on_error: false expect(err).to include "can't find executable rackup for gem rack. rack is not currently included in the bundle, perhaps you meant to add it to your Gemfile?" end end @@ -412,6 +427,7 @@ RSpec.describe "bundle exec" do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -496,6 +512,7 @@ RSpec.describe "bundle exec" do describe "run from a random directory" do before(:each) do install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G end @@ -514,11 +531,12 @@ RSpec.describe "bundle exec" do describe "from gems bundled via :path" do before(:each) do - build_lib "fizz", :path => home("fizz") do |s| + build_lib "fizz", path: home("fizz") do |s| s.executables = "fizz" end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "fizz", :path => "#{File.expand_path(home("fizz"))}" G end @@ -543,6 +561,7 @@ RSpec.describe "bundle exec" do end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "fizz_git", :git => "#{lib_path("fizz_git-1.0")}" G end @@ -561,11 +580,12 @@ RSpec.describe "bundle exec" do describe "from gems bundled via :git with no gemspec" do before(:each) do - build_git "fizz_no_gemspec", :gemspec => false do |s| + build_git "fizz_no_gemspec", gemspec: false do |s| s.executables = "fizz_no_gemspec" end install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "fizz_no_gemspec", "1.0", :git => "#{lib_path("fizz_no_gemspec-1.0")}" G end @@ -595,6 +615,53 @@ RSpec.describe "bundle exec" do expect(out).to include("Installing foo 1.0") end + it "performs an automatic bundle install with git gems" do + build_git "foo" do |s| + s.executables = "foo" + end + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", "0.9.1" + gem "foo", :git => "#{lib_path("foo-1.0")}" + G + + bundle "config set auto_install 1" + bundle "exec foo" + expect(out).to include("Fetching rack 0.9.1") + expect(out).to include("Fetching #{lib_path("foo-1.0")}") + expect(out.lines).to end_with("1.0") + end + + it "loads the correct optparse when `auto_install` is set, and optparse is a dependency" do + if Gem.rubygems_version < Gem::Version.new("3.3.0.a") + skip "optparse is a default gem, and rubygems loads it during install" + end + + build_repo4 do + build_gem "fastlane", "2.192.0" do |s| + s.executables = "fastlane" + s.add_dependency "optparse", "~> 999.999.999" + end + + build_gem "optparse", "999.999.998" + build_gem "optparse", "999.999.999" + end + + system_gems "optparse-999.999.998", gem_repo: gem_repo4 + + bundle "config set auto_install 1" + bundle "config set --local path vendor/bundle" + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + gem "fastlane" + G + + bundle "exec fastlane" + expect(out).to include("Installing optparse 999.999.999") + expect(out).to include("2.192.0") + end + describe "with gems bundled via :path with invalid gemspecs" do it "outputs the gemspec validation errors" do build_lib "foo" @@ -612,10 +679,11 @@ RSpec.describe "bundle exec" do end gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" G - bundle "exec irb", :raise_on_error => false + bundle "exec irb", raise_on_error: false expect(err).to match("The gemspec at #{lib_path("foo-1.0").join("foo.gemspec")} is not valid") expect(err).to match('"TODO" is not a summary') @@ -627,6 +695,8 @@ RSpec.describe "bundle exec" do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + module Monkey def bin_path(a,b,c) raise Gem::GemNotFoundException.new('Fail') @@ -636,7 +706,7 @@ RSpec.describe "bundle exec" do G bundle "config set path.system true" bundle "install" - bundle "exec ruby -e '`bundle -v`; puts $?.success?'", :env => { "BUNDLER_VERSION" => Bundler::VERSION } + bundle "exec ruby -e '`bundle -v`; puts $?.success?'", env: { "BUNDLER_VERSION" => Bundler::VERSION } expect(out).to match("true") end end @@ -644,7 +714,7 @@ RSpec.describe "bundle exec" do context "`load`ing a ruby file instead of `exec`ing" do let(:path) { bundled_app("ruby_executable") } let(:shebang) { "#!/usr/bin/env ruby" } - let(:executable) { <<-RUBY.gsub(/^ */, "").strip } + let(:executable) { <<~RUBY.strip } #{shebang} require "rack" @@ -656,10 +726,13 @@ RSpec.describe "bundle exec" do RUBY before do + system_gems(system_gems_to_install, path: default_bundle_path) + bundled_app(path).open("w") {|f| f << executable } bundled_app(path).chmod(0o755) install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "rack" G end @@ -676,7 +749,7 @@ RSpec.describe "bundle exec" do let(:expected) { [exec, args, rack, process].join("\n") } let(:expected_err) { "" } - subject { bundle "exec #{path} arg1 arg2", :raise_on_error => false } + subject { bundle "exec #{path} arg1 arg2", raise_on_error: false } it "runs" do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? @@ -724,9 +797,7 @@ RSpec.describe "bundle exec" do end let(:expected_err) { "" } let(:exit_code) do - # signal mask 128 + plus signal 15 -> TERM - # this is specified by C99 - 128 + 15 + exit_status_for_signal(Signal.list["TERM"]) end it "runs" do @@ -760,8 +831,7 @@ RSpec.describe "bundle exec" do let(:executable) { super() << "\nraise 'ERROR'" } let(:exit_code) { 1 } let(:expected_err) do - "bundler: failed to load command: #{path} (#{path})" \ - "\n#{path}:10:in `<top (required)>': ERROR (RuntimeError)" + /\Abundler: failed to load command: #{Regexp.quote(path.to_s)} \(#{Regexp.quote(path.to_s)}\)\n#{Regexp.quote(path.to_s)}:10:in [`']<top \(required\)>': ERROR \(RuntimeError\)/ end it "runs like a normally executed executable" do @@ -769,7 +839,7 @@ RSpec.describe "bundle exec" do subject expect(exitstatus).to eq(exit_code) - expect(err).to start_with(expected_err) + expect(err).to match(expected_err) expect(out).to eq(expected) end end @@ -803,9 +873,10 @@ RSpec.describe "bundle exec" do end end - context "when Bundler.setup fails", :bundler => "< 3" do + context "when Bundler.setup fails", bundler: "< 3" do before do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack', '2' G ENV["BUNDLER_FORCE_TTY"] = "true" @@ -814,9 +885,12 @@ RSpec.describe "bundle exec" do let(:exit_code) { Bundler::GemNotFound.new.status_code } let(:expected) { "" } let(:expected_err) { <<-EOS.strip } -\e[31mCould not find gem 'rack (= 2)' in locally installed gems. -The source contains the following versions of 'rack': 0.9.1, 1.0.0\e[0m -\e[33mRun `bundle install` to install missing gems.\e[0m +Could not find gem 'rack (= 2)' in cached gems or installed locally. + +The source contains the following gems matching 'rack': + * rack-0.9.1 + * rack-1.0.0 +Run `bundle install` to install missing gems. EOS it "runs" do @@ -829,9 +903,10 @@ The source contains the following versions of 'rack': 0.9.1, 1.0.0\e[0m end end - context "when Bundler.setup fails", :bundler => "3" do + context "when Bundler.setup fails", bundler: "3" do before do gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem 'rack', '2' G ENV["BUNDLER_FORCE_TTY"] = "true" @@ -840,9 +915,11 @@ The source contains the following versions of 'rack': 0.9.1, 1.0.0\e[0m let(:exit_code) { Bundler::GemNotFound.new.status_code } let(:expected) { "" } let(:expected_err) { <<-EOS.strip } -\e[31mCould not find gem 'rack (= 2)' in locally installed gems. -The source contains the following versions of 'rack': 1.0.0\e[0m -\e[33mRun `bundle install` to install missing gems.\e[0m +Could not find gem 'rack (= 2)' in cached gems or installed locally. + +The source contains the following gems matching 'rack': + * rack-1.0.0 +Run `bundle install` to install missing gems. EOS it "runs" do @@ -855,6 +932,30 @@ The source contains the following versions of 'rack': 1.0.0\e[0m end end + context "when Bundler.setup fails and Gemfile is not the default" do + before do + create_file "CustomGemfile", <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'rack', '2' + G + ENV["BUNDLER_FORCE_TTY"] = "true" + ENV["BUNDLE_GEMFILE"] = "CustomGemfile" + ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = nil + end + + let(:exit_code) { Bundler::GemNotFound.new.status_code } + let(:expected) { "" } + + it "prints proper suggestion" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to include("Run `bundle install --gemfile CustomGemfile` to install missing gems.") + expect(out).to eq(expected) + end + end + context "when the executable exits non-zero via at_exit" do let(:executable) { super() + "\n\nat_exit { $! ? raise($!) : exit(1) }" } let(:exit_code) { 1 } @@ -939,7 +1040,7 @@ __FILE__: #{path.to_s.inspect} end context "signals being trapped by bundler" do - let(:executable) { strip_whitespace <<-RUBY } + let(:executable) { <<~RUBY } #{shebang} begin Thread.new do @@ -966,7 +1067,7 @@ __FILE__: #{path.to_s.inspect} end context "signals not being trapped by bunder" do - let(:executable) { strip_whitespace <<-RUBY } + let(:executable) { <<~RUBY } #{shebang} signals = #{test_signals.inspect} @@ -1011,7 +1112,7 @@ __FILE__: #{path.to_s.inspect} puts `bundle exec echo foo` RUBY file.chmod(0o777) - bundle "exec #{file}", :env => { "PATH" => path } + bundle "exec #{file}", env: { "PATH" => path } expect(out).to eq("foo") end end @@ -1020,7 +1121,7 @@ __FILE__: #{path.to_s.inspect} before do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - install_gemfile "" + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" end it "does not undo the monkeypatches" do @@ -1079,7 +1180,7 @@ __FILE__: #{path.to_s.inspect} RUBY # A Gemfile needs to be in the root to trick bundler's root resolution - create_file(bundled_app("Gemfile")) + create_file(bundled_app("Gemfile"), "source \"#{file_uri_for(gem_repo1)}\"") bundle "install" end @@ -1104,13 +1205,13 @@ __FILE__: #{path.to_s.inspect} context "with a system gem that shadows a default gem" do let(:openssl_version) { "99.9.9" } - let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", :artifice => nil, :raise_on_error => false } + let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", artifice: nil, raise_on_error: false } it "only leaves the default gem in the stdlib available" do skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? skip "openssl isn't a default gem" if expected.empty? - install_gemfile "" # must happen before installing the broken system gem + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" # must happen before installing the broken system gem build_repo4 do build_gem "openssl", openssl_version do |s| @@ -1120,7 +1221,7 @@ __FILE__: #{path.to_s.inspect} end end - system_gems("openssl-#{openssl_version}", :gem_repo => gem_repo4) + system_gems("openssl-#{openssl_version}", gem_repo: gem_repo4) file = bundled_app("require_openssl.rb") create_file(file, <<-RUBY) @@ -1133,15 +1234,15 @@ __FILE__: #{path.to_s.inspect} env = { "PATH" => path } aggregate_failures do - expect(bundle("exec #{file}", :artifice => nil, :env => env)).to eq(expected) - expect(bundle("exec bundle exec #{file}", :artifice => nil, :env => env)).to eq(expected) - expect(bundle("exec ruby #{file}", :artifice => nil, :env => env)).to eq(expected) - expect(run(file.read, :artifice => nil, :env => env)).to eq(expected) + expect(bundle("exec #{file}", artifice: nil, env: env)).to eq(expected) + expect(bundle("exec bundle exec #{file}", artifice: nil, env: env)).to eq(expected) + expect(bundle("exec ruby #{file}", artifice: nil, env: env)).to eq(expected) + expect(run(file.read, artifice: nil, env: env)).to eq(expected) end skip "ruby_core has openssl and rubygems in the same folder, and this test needs rubygems require but default openssl not in a directly added entry in $LOAD_PATH" if ruby_core? # sanity check that we get the newer, custom version without bundler - sys_exec "#{Gem.ruby} #{file}", :env => env, :raise_on_error => false + sys_exec "#{Gem.ruby} #{file}", env: env, raise_on_error: false expect(err).to include("custom openssl should not be loaded") end end @@ -1151,6 +1252,7 @@ __FILE__: #{path.to_s.inspect} build_git "simple_git_binary", &:add_c_extension bundle "config set --local path .bundle" install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" gem "simple_git_binary", :git => '#{lib_path("simple_git_binary-1.0")}' G end |