diff options
Diffstat (limited to 'spec/bundler/commands/install_spec.rb')
-rw-r--r-- | spec/bundler/commands/install_spec.rb | 539 |
1 files changed, 475 insertions, 64 deletions
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index 56f657521f..f0c9aaea8e 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -12,7 +12,7 @@ RSpec.describe "bundle install with gem sources" do end it "does not make a lockfile if the install fails" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false raise StandardError, "FAIL" G @@ -29,7 +29,7 @@ RSpec.describe "bundle install with gem sources" do expect(bundled_app_lock).to exist end - it "does not create ./.bundle by default", :bundler => "< 3" do + it "does not create ./.bundle by default", bundler: "< 3" do gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -45,7 +45,7 @@ RSpec.describe "bundle install with gem sources" do gem "rack" G - bundle :install, :env => { "BUNDLE_PATH__SYSTEM" => "true" } # can't use install_gemfile since it sets retry + bundle :install, env: { "BUNDLE_PATH__SYSTEM" => "true" } # can't use install_gemfile since it sets retry expect(bundled_app(".bundle")).not_to exist end @@ -68,7 +68,7 @@ RSpec.describe "bundle install with gem sources" do lockfile = File.read(bundled_app_lock) - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false raise StandardError, "FAIL" G @@ -130,7 +130,7 @@ RSpec.describe "bundle install with gem sources" do end it "raises an appropriate error when gems are specified using symbols" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo1)}" gem :rack G @@ -197,7 +197,7 @@ RSpec.describe "bundle install with gem sources" do end it "does not reinstall any gem that is already available locally" do - system_gems "activesupport-2.3.2", :path => default_bundle_path + system_gems "activesupport-2.3.2", path: default_bundle_path build_repo2 do build_gem "activesupport", "2.3.2" do |s| @@ -214,7 +214,7 @@ RSpec.describe "bundle install with gem sources" do end it "works when the gemfile specifies gems that only exist in the system" do - build_gem "foo", :to_bundle => true + build_gem "foo", to_bundle: true install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -225,7 +225,7 @@ RSpec.describe "bundle install with gem sources" do end it "prioritizes local gems over remote gems" do - build_gem "rack", "1.0.0", :to_bundle => true do |s| + build_gem "rack", "1.0.0", to_bundle: true do |s| s.add_dependency "activesupport", "2.3.5" end @@ -241,7 +241,7 @@ RSpec.describe "bundle install with gem sources" do plugin_msg = "hello from an env plugin!" create_file "plugins/rubygems_plugin.rb", "puts '#{plugin_msg}'" rubylib = ENV["RUBYLIB"].to_s.split(File::PATH_SEPARATOR).unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR) - install_gemfile <<-G, :env => { "RUBYLIB" => rubylib } + install_gemfile <<-G, env: { "RUBYLIB" => rubylib } source "#{file_uri_for(gem_repo1)}" gem "rack" G @@ -285,7 +285,7 @@ RSpec.describe "bundle install with gem sources" do end it "installs gems for windows" do - simulate_platform mswin + simulate_platform x86_mswin32 install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -293,7 +293,7 @@ RSpec.describe "bundle install with gem sources" do G run "require 'platform_specific' ; puts PLATFORM_SPECIFIC" - expect(out).to eq("1.0.0 MSWIN") + expect(out).to eq("1.0 x86-mswin32") end end @@ -311,14 +311,14 @@ RSpec.describe "bundle install with gem sources" do expect(the_bundle).to include_gems "rack 1.0" end - it "allows running bundle install --system without deleting foo", :bundler => "< 3" do + it "allows running bundle install --system without deleting foo", bundler: "< 3" do bundle "install --path vendor" bundle "install --system" FileUtils.rm_rf(bundled_app("vendor")) expect(the_bundle).to include_gems "rack 1.0" end - it "allows running bundle install --system after deleting foo", :bundler => "< 3" do + it "allows running bundle install --system after deleting foo", bundler: "< 3" do bundle "install --path vendor" FileUtils.rm_rf(bundled_app("vendor")) bundle "install --system" @@ -326,7 +326,7 @@ RSpec.describe "bundle install with gem sources" do end end - it "finds gems in multiple sources", :bundler => "< 3" do + it "finds gems in multiple sources", bundler: "< 3" do build_repo2 do build_gem "rack", "1.2" do |s| s.executables = "rackup" @@ -345,7 +345,7 @@ RSpec.describe "bundle install with gem sources" do end it "gives a useful error if no sources are set" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false gem "rack" G @@ -408,7 +408,7 @@ RSpec.describe "bundle install with gem sources" do end it "does not throw a warning if a gem is added once in Gemfile and also inside a gemspec as a development dependency" do - build_lib "my-gem", :path => bundled_app do |s| + build_lib "my-gem", path: bundled_app do |s| s.add_development_dependency "my-private-gem" end @@ -430,8 +430,155 @@ RSpec.describe "bundle install with gem sources" do expect(the_bundle).to include_gems("my-private-gem 1.0") end + it "throws a warning if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with different requirements" do + build_lib "my-gem", path: bundled_app do |s| + s.add_development_dependency "rubocop", "~> 1.36.0" + end + + build_repo4 do + build_gem "rubocop", "1.36.0" + build_gem "rubocop", "1.37.1" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gemspec + + gem "rubocop", group: :development + G + + bundle :install + + expect(err).to include("A gemspec development dependency (rubocop, ~> 1.36.0) is being overridden by a Gemfile dependency (rubocop, >= 0).") + expect(err).to include("This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement") + + # This is not the best behavior I believe, it would be better if both + # requirements are considered if they are compatible, and a version + # satisfying both is chosen. But not sure about changing it right now, so + # I went with a warning for the time being. + expect(the_bundle).to include_gems("rubocop 1.37.1") + end + + it "includes the gem without warning if two gemspecs add it with the same requirement" do + gem1 = tmp.join("my-gem-1") + gem2 = tmp.join("my-gem-2") + + build_lib "my-gem", path: gem1 do |s| + s.add_development_dependency "rubocop", "~> 1.36.0" + end + + build_lib "my-gem-2", path: gem2 do |s| + s.add_development_dependency "rubocop", "~> 1.36.0" + end + + build_repo4 do + build_gem "rubocop", "1.36.0" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gemspec path: "#{gem1}" + gemspec path: "#{gem2}" + G + + bundle :install + + expect(err).to be_empty + expect(the_bundle).to include_gems("rubocop 1.36.0") + end + + it "warns when a Gemfile dependency is overriding a gemspec development dependency, with different requirements" do + build_lib "my-gem", path: bundled_app do |s| + s.add_development_dependency "rails", ">= 5" + end + + build_repo4 do + build_gem "rails", "7.0.8" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "rails", "~> 7.0.8" + + gemspec + G + + bundle :install + + expect(err).to include("A gemspec development dependency (rails, >= 5) is being overridden by a Gemfile dependency (rails, ~> 7.0.8).") + expect(err).to include("This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement") + + # This is not the best behavior I believe, it would be better if both + # requirements are considered if they are compatible, and a version + # satisfying both is chosen. But not sure about changing it right now, so + # I went with a warning for the time being. + expect(the_bundle).to include_gems("rails 7.0.8") + end + + it "does not warn if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with same requirements, and different sources" do + build_lib "my-gem", path: bundled_app do |s| + s.add_development_dependency "activesupport" + end + + build_repo4 do + build_gem "activesupport" + end + + build_git "activesupport", "1.0", path: lib_path("activesupport") + + install_gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gemspec + + gem "activesupport", :git => "#{file_uri_for(lib_path("activesupport"))}" + G + + expect(err).to be_empty + expect(the_bundle).to include_gems "activesupport 1.0", source: "git@#{lib_path("activesupport")}" + + # if the Gemfile dependency is specified first + install_gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "activesupport", :git => "#{file_uri_for(lib_path("activesupport"))}" + + gemspec + G + + expect(err).to be_empty + expect(the_bundle).to include_gems "activesupport 1.0", source: "git@#{lib_path("activesupport")}" + end + + it "considers both dependencies for resolution if a gem is added once in Gemfile and also inside a local gemspec as a runtime dependency, with different requirements" do + build_lib "my-gem", path: bundled_app do |s| + s.add_dependency "rubocop", "~> 1.36.0" + end + + build_repo4 do + build_gem "rubocop", "1.36.0" + build_gem "rubocop", "1.37.1" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gemspec + + gem "rubocop" + G + + bundle :install + + expect(err).to be_empty + expect(the_bundle).to include_gems("rubocop 1.36.0") + end + it "throws an error if a gem is added twice in Gemfile when version of one dependency is not specified" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}" gem "rack" gem "rack", "1.0" @@ -442,7 +589,7 @@ RSpec.describe "bundle install with gem sources" do end it "throws an error if a gem is added twice in Gemfile when different versions of both dependencies are specified" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}" gem "rack", "1.0" gem "rack", "1.1" @@ -455,7 +602,7 @@ RSpec.describe "bundle install with gem sources" do it "gracefully handles error when rubygems server is unavailable" do skip "networking issue" if Gem.win_platform? - install_gemfile <<-G, :artifice => nil, :raise_on_error => false + install_gemfile <<-G, artifice: nil, raise_on_error: false source "#{file_uri_for(gem_repo1)}" source "http://0.0.0.0:9384" do gem 'foo' @@ -467,8 +614,8 @@ RSpec.describe "bundle install with gem sources" do end it "fails gracefully when downloading an invalid specification from the full index" do - build_repo2 do - build_gem "ajp-rails", "0.0.0", :gemspec => false, :skip_validation => true do |s| + build_repo2(build_compact_index: false) do + build_gem "ajp-rails", "0.0.0", gemspec: false, skip_validation: true do |s| bad_deps = [["ruby-ajp", ">= 0.2.0"], ["rails", ">= 0.14"]] s. instance_variable_get(:@spec). @@ -479,7 +626,7 @@ RSpec.describe "bundle install with gem sources" do build_gem "ruby-ajp", "1.0.0" end - install_gemfile <<-G, :full_index => true, :raise_on_error => false + install_gemfile <<-G, full_index: true, raise_on_error: false source "#{file_uri_for(gem_repo2)}" gem "ajp-rails", "0.0.0" @@ -514,27 +661,26 @@ RSpec.describe "bundle install with gem sources" do end describe "Ruby version in Gemfile.lock" do - include Bundler::GemHelpers - context "and using an unsupported Ruby version" do it "prints an error" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false ruby '~> 1.2' source "#{file_uri_for(gem_repo1)}" G - expect(err).to include("Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified ~> 1.2") + expect(err).to include("Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified ~> 1.2") end end context "and using a supported Ruby version" do before do install_gemfile <<-G - ruby '~> #{RUBY_VERSION}' + ruby '~> #{Gem.ruby_version}' source "#{file_uri_for(gem_repo1)}" G end it "writes current Ruby version to Gemfile.lock" do + checksums = checksums_section_when_existing expect(lockfile).to eq <<~L GEM remote: #{file_uri_for(gem_repo1)}/ @@ -544,7 +690,7 @@ RSpec.describe "bundle install with gem sources" do #{lockfile_platforms} DEPENDENCIES - + #{checksums} RUBY VERSION #{Bundler::RubyVersion.system} @@ -555,10 +701,12 @@ RSpec.describe "bundle install with gem sources" do it "updates Gemfile.lock with updated yet still compatible ruby version" do install_gemfile <<-G - ruby '~> #{RUBY_VERSION[0..2]}' + ruby '~> #{current_ruby_minor}' source "#{file_uri_for(gem_repo1)}" G + checksums = checksums_section_when_existing + expect(lockfile).to eq <<~L GEM remote: #{file_uri_for(gem_repo1)}/ @@ -568,7 +716,7 @@ RSpec.describe "bundle install with gem sources" do #{lockfile_platforms} DEPENDENCIES - + #{checksums} RUBY VERSION #{Bundler::RubyVersion.system} @@ -605,7 +753,7 @@ RSpec.describe "bundle install with gem sources" do file.puts gemfile end - bundle :install, :dir => root_dir + bundle :install, dir: root_dir end it "doesn't blow up when using the `gemspec` DSL" do @@ -613,7 +761,7 @@ RSpec.describe "bundle install with gem sources" do FileUtils.mkdir_p(root_dir) - build_lib "foo", :path => root_dir + build_lib "foo", path: root_dir gemfile = <<-G source "#{file_uri_for(gem_repo1)}" gemspec @@ -622,7 +770,7 @@ RSpec.describe "bundle install with gem sources" do file.puts gemfile end - bundle :install, :dir => root_dir + bundle :install, dir: root_dir end end @@ -635,7 +783,7 @@ RSpec.describe "bundle install with gem sources" do gem 'rack' G - bundle :install, :quiet => true + bundle :install, quiet: true expect(out).to be_empty expect(err).to be_empty end @@ -665,7 +813,7 @@ RSpec.describe "bundle install with gem sources" do gem 'non-existing-gem' G - bundle :install, :quiet => true, :raise_on_error => false, :env => { "RUBYOPT" => "-r#{bundled_app("install_with_warning.rb")}" } + bundle :install, quiet: true, raise_on_error: false, env: { "RUBYOPT" => "-r#{bundled_app("install_with_warning.rb")}" } expect(out).to be_empty expect(err).to include("Could not find gem 'non-existing-gem'") expect(err).to include("BOOOOO") @@ -687,7 +835,7 @@ RSpec.describe "bundle install with gem sources" do FileUtils.chmod(0o500, bundle_path) bundle "config set --local path vendor" - bundle :install, :raise_on_error => false + bundle :install, raise_on_error: false expect(err).to include(bundle_path.to_s) expect(err).to include("grant write permissions") end @@ -709,7 +857,7 @@ RSpec.describe "bundle install with gem sources" do bundle "config set --local path vendor" begin - bundle :install, :raise_on_error => false + bundle :install, raise_on_error: false ensure FileUtils.chmod("+x", gems_path) end @@ -723,6 +871,36 @@ RSpec.describe "bundle install with gem sources" do end end + describe "when bundle extensions path does not have write access", :permissions do + let(:extensions_path) { bundled_app("vendor/#{Bundler.ruby_scope}/extensions/#{Gem::Platform.local}/#{Gem.extension_api_version}") } + + before do + FileUtils.mkdir_p(extensions_path) + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'simple_binary' + G + end + + it "should display a proper message to explain the problem" do + FileUtils.chmod("-x", extensions_path) + bundle "config set --local path vendor" + + begin + bundle :install, raise_on_error: false + ensure + FileUtils.chmod("+x", extensions_path) + end + + expect(err).not_to include("ERROR REPORT TEMPLATE") + + expect(err).to include( + "There was an error while trying to create `#{extensions_path.join("simple_binary-1.0")}`. " \ + "It is likely that you need to grant executable permissions for all parent directories and write permissions for `#{extensions_path}`." + ) + end + end + describe "when the path of a specific gem is not writable", :permissions do let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") } let(:foo_path) { gems_path.join("foo-1.0.0") } @@ -749,18 +927,79 @@ RSpec.describe "bundle install with gem sources" do FileUtils.chmod("-x", foo_path) begin - bundle "install --redownload", :raise_on_error => false + bundle "install --redownload", raise_on_error: false ensure FileUtils.chmod("+x", foo_path) end expect(err).not_to include("ERROR REPORT TEMPLATE") + expect(err).to include("Could not delete previous installation of `#{foo_path}`.") + expect(err).to include("The underlying error was Errno::EACCES") + end + end - expect(err).to include( - "There was an error while trying to delete `#{foo_path}`. " \ - "It is likely that you need to grant executable permissions for all parent directories " \ - "and write permissions for `#{gems_path}`, and the same thing for all subdirectories inside #{foo_path}." - ) + describe "when gem home does not have the writable bit set, yet it's still writable", :permissions do + let(:gem_home) { bundled_app("vendor/#{Bundler.ruby_scope}") } + + before do + build_repo4 do + build_gem "foo", "1.0.0" do |s| + s.write "CHANGELOG.md", "foo" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem 'foo' + G + end + + it "should display a proper message to explain the problem" do + bundle "config set --local path vendor" + bundle :install + expect(out).to include("Bundle complete!") + expect(err).to be_empty + + FileUtils.chmod("-w", gem_home) + + begin + bundle "install --redownload" + ensure + FileUtils.chmod("+w", gem_home) + end + + expect(out).to include("Bundle complete!") + expect(err).to be_empty + end + end + + describe "when gems path is world writable (no sticky bit set)", :permissions do + let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") } + + before do + build_repo4 do + build_gem "foo", "1.0.0" do |s| + s.write "CHANGELOG.md", "foo" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem 'foo' + G + end + + it "should display a proper message to explain the problem" do + bundle "config set --local path vendor" + bundle :install + expect(out).to include("Bundle complete!") + expect(err).to be_empty + + FileUtils.chmod(0o777, gems_path) + + bundle "install --redownload", raise_on_error: false + + expect(err).to include("The installation path is insecure. Bundler cannot continue.") end end @@ -779,7 +1018,7 @@ RSpec.describe "bundle install with gem sources" do FileUtils.chmod(0o500, cache_path) bundle "config set --local path vendor" - bundle :install, :raise_on_error => false + bundle :install, raise_on_error: false expect(err).to include(cache_path.to_s) expect(err).to include("grant write permissions") end @@ -792,13 +1031,13 @@ RSpec.describe "bundle install with gem sources" do gem "rack" G bundle "config set --local path bundle" - bundle "install", :standalone => true + bundle "install", standalone: true end it "includes the standalone path" do - bundle "binstubs rack", :standalone => true + bundle "binstubs rack", standalone: true standalone_line = File.read(bundled_app("bin/rackup")).each_line.find {|line| line.include? "$:.unshift" }.strip - expect(standalone_line).to eq %($:.unshift File.expand_path "../../bundle", path.realpath) + expect(standalone_line).to eq %($:.unshift File.expand_path "../bundle", __dir__) end end @@ -811,7 +1050,7 @@ RSpec.describe "bundle install with gem sources" do end it "should display a helpful message explaining how to fix it" do - bundle :install, :env => { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }, :raise_on_error => false + bundle :install, env: { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }, raise_on_error: false expect(exitstatus).to eq(17) expect(err).to eq("Please CGI escape your usernames and passwords before " \ "setting them for authentication.") @@ -852,11 +1091,11 @@ RSpec.describe "bundle install with gem sources" do end it "should fail loudly if the lockfile platforms don't include the current platform" do - simulate_platform(Gem::Platform.new("x86_64-linux")) { bundle "install", :raise_on_error => false } + simulate_platform(Gem::Platform.new("x86_64-linux")) { bundle "install", raise_on_error: false } expect(err).to eq( "Your bundle only supports platforms [\"x86_64-darwin-19\"] but your local platform is x86_64-linux. " \ - "Add the current platform to the lockfile with `bundle lock --add-platform x86_64-linux` and try again." + "Add the current platform to the lockfile with\n`bundle lock --add-platform x86_64-linux` and try again." ) end end @@ -864,16 +1103,16 @@ RSpec.describe "bundle install with gem sources" do context "with missing platform specific gems in lockfile" do before do build_repo4 do - build_gem "racc", "1.5.2" + build_gem "racca", "1.5.2" build_gem "nokogiri", "1.12.4" do |s| s.platform = "x86_64-darwin" - s.add_runtime_dependency "racc", "~> 1.4" + s.add_runtime_dependency "racca", "~> 1.4" end build_gem "nokogiri", "1.12.4" do |s| s.platform = "x86_64-linux" - s.add_runtime_dependency "racc", "~> 1.4" + s.add_runtime_dependency "racca", "~> 1.4" end build_gem "crass", "1.0.6" @@ -887,11 +1126,18 @@ RSpec.describe "bundle install with gem sources" do gemfile <<-G source "https://gem.repo4" - ruby "#{RUBY_VERSION}" + ruby "#{Gem.ruby_version}" gem "loofah", "~> 2.12.0" G + checksums = checksums_section do |c| + c.checksum gem_repo4, "crass", "1.0.6" + c.checksum gem_repo4, "loofah", "2.12.0" + c.checksum gem_repo4, "nokogiri", "1.12.4", "x86_64-darwin" + c.checksum gem_repo4, "racca", "1.5.2" + end + lockfile <<-L GEM remote: https://gem.repo4/ @@ -901,8 +1147,8 @@ RSpec.describe "bundle install with gem sources" do crass (~> 1.0.2) nokogiri (>= 1.5.9) nokogiri (1.12.4-x86_64-darwin) - racc (~> 1.4) - racc (1.5.2) + racca (~> 1.4) + racca (1.5.2) PLATFORMS x86_64-darwin-20 @@ -910,7 +1156,7 @@ RSpec.describe "bundle install with gem sources" do DEPENDENCIES loofah (~> 2.12.0) - + #{checksums} RUBY VERSION #{Bundler::RubyVersion.system} @@ -923,7 +1169,15 @@ RSpec.describe "bundle install with gem sources" do bundle "config set --local path vendor/bundle" simulate_platform "x86_64-linux" do - bundle "install", :artifice => "compact_index" + bundle "install", artifice: "compact_index" + end + + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo4, "crass", "1.0.6" + c.checksum gem_repo4, "loofah", "2.12.0" + c.checksum gem_repo4, "nokogiri", "1.12.4", "x86_64-darwin" + c.checksum gem_repo4, "racca", "1.5.2" + c.checksum gem_repo4, "nokogiri", "1.12.4", "x86_64-linux" end expect(lockfile).to eq <<~L @@ -935,10 +1189,10 @@ RSpec.describe "bundle install with gem sources" do crass (~> 1.0.2) nokogiri (>= 1.5.9) nokogiri (1.12.4-x86_64-darwin) - racc (~> 1.4) + racca (~> 1.4) nokogiri (1.12.4-x86_64-linux) - racc (~> 1.4) - racc (1.5.2) + racca (~> 1.4) + racca (1.5.2) PLATFORMS x86_64-darwin-20 @@ -946,7 +1200,7 @@ RSpec.describe "bundle install with gem sources" do DEPENDENCIES loofah (~> 2.12.0) - + #{checksums} RUBY VERSION #{Bundler::RubyVersion.system} @@ -958,11 +1212,11 @@ RSpec.describe "bundle install with gem sources" do context "with --local flag" do before do - system_gems "rack-1.0.0", :path => default_bundle_path + system_gems "rack-1.0.0", path: default_bundle_path end it "respects installed gems without fetching any remote sources" do - install_gemfile <<-G, :local => true + install_gemfile <<-G, local: true source "#{file_uri_for(gem_repo1)}" source "https://not-existing-source" do @@ -973,4 +1227,161 @@ RSpec.describe "bundle install with gem sources" do expect(last_command).to be_success end end + + context "with only option" do + before do + bundle "config set only a:b" + end + + it "installs only gems of the specified groups" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rails" + gem "rack", group: :a + gem "rake", group: :b + gem "yard", group: :c + G + + expect(out).to include("Installing rack") + expect(out).to include("Installing rake") + expect(out).not_to include("Installing yard") + end + end + + context "with --prefer-local flag" do + before do + build_repo4 do + build_gem "foo", "1.0.1" + build_gem "foo", "1.0.0" + build_gem "bar", "1.0.0" + end + + system_gems "foo-1.0.0", path: default_bundle_path, gem_repo: gem_repo4 + end + + it "fetches remote sources only when not available locally" do + install_gemfile <<-G, "prefer-local": true, verbose: true + source "#{file_uri_for(gem_repo4)}" + + gem "foo" + gem "bar" + G + + expect(out).to include("Using foo 1.0.0").and include("Fetching bar 1.0.0").and include("Installing bar 1.0.0") + expect(last_command).to be_success + end + end + + context "with a symlinked configured as bundle path and a gem with symlinks" do + before do + symlinked_bundled_app = tmp("bundled_app-symlink") + File.symlink(bundled_app, symlinked_bundled_app) + bundle "config path #{File.join(symlinked_bundled_app, ".vendor")}" + + binman_path = tmp("binman") + FileUtils.mkdir_p binman_path + + readme_path = File.join(binman_path, "README.markdown") + FileUtils.touch(readme_path) + + man_path = File.join(binman_path, "man", "man0") + FileUtils.mkdir_p man_path + + File.symlink("../../README.markdown", File.join(man_path, "README.markdown")) + + build_repo4 do + build_gem "binman", path: gem_repo4("gems"), lib_path: binman_path, no_default: true do |s| + s.files = ["README.markdown", "man/man0/README.markdown"] + end + end + end + + it "installs fine" do + install_gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "binman" + G + end + end + + context "when a gem has equivalent versions with inconsistent dependencies" do + before do + build_repo4 do + build_gem "autobuild", "1.10.rc2" do |s| + s.add_dependency "utilrb", ">= 1.6.0" + end + + build_gem "autobuild", "1.10.0.rc2" do |s| + s.add_dependency "utilrb", ">= 2.0" + end + end + end + + it "does not crash unexpectedly" do + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "autobuild", "1.10.rc2" + G + + bundle "install --jobs 1", raise_on_error: false + + expect(err).not_to include("ERROR REPORT TEMPLATE") + expect(err).to include("Could not find compatible versions") + end + end + + context "when a lockfile has unmet dependencies, and the Gemfile has no resolution" do + before do + build_repo4 do + build_gem "aaa", "0.2.0" do |s| + s.add_dependency "zzz", "< 0.2.0" + end + + build_gem "zzz", "0.2.0" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "aaa" + gem "zzz" + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + aaa (0.2.0) + zzz (< 0.2.0) + zzz (0.2.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + aaa! + zzz! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "does not install, but raises a resolution error" do + bundle "install", raise_on_error: false + expect(err).to include("Could not find compatible versions") + end + end + + context "when --jobs option given" do + before do + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", jobs: 1 + end + + it "does not save the flag to config" do + expect(bundled_app(".bundle/config")).not_to exist + end + end end |