diff options
author | David RodrÃguez <deivid.rodriguez@riseup.net> | 2021-02-01 16:17:16 +0100 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2021-03-08 13:47:35 +0900 |
commit | 53468cc11147b0d285fc376fc546b677dad600ca (patch) | |
tree | eb9c97f544d089be2d324126b025b11f41a22c90 /spec/bundler | |
parent | 2ab6b7a7516e1b2c48a66ce513afabb62d101461 (diff) |
Sync latest development version of bundler & rubygems
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4143
Diffstat (limited to 'spec/bundler')
49 files changed, 1456 insertions, 438 deletions
diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb index ccf957d6df..e49066f7dc 100644 --- a/spec/bundler/bundler/cli_spec.rb +++ b/spec/bundler/bundler/cli_spec.rb @@ -138,12 +138,12 @@ RSpec.describe "bundle executable" do it "doesn't print defaults" do install_gemfile "", :verbose => true - expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}") + expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}") end it "doesn't print defaults" do install_gemfile "", :verbose => true - expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}") + expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}") end end diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb index acb312edb3..cecaddfba4 100644 --- a/spec/bundler/bundler/compact_index_client/updater_spec.rb +++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb @@ -17,7 +17,6 @@ RSpec.describe Bundler::CompactIndexClient::Updater do let(:response) { double(:response, :body => "abc123") } it "treats the response as an update" do - expect(response).to receive(:[]).with("Content-Encoding") { "" } expect(response).to receive(:[]).with("ETag") { nil } expect(fetcher).to receive(:call) { response } @@ -29,8 +28,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do let(:response) { double(:response, :body => "") } it "raises HTTPError" do - expect(response).to receive(:[]).with("Content-Encoding") { "gzip" } - expect(fetcher).to receive(:call) { response } + expect(fetcher).to receive(:call).and_raise(Zlib::GzipFile::Error) expect do updater.update(local_path, remote_path) @@ -48,4 +46,25 @@ RSpec.describe Bundler::CompactIndexClient::Updater do end.to raise_error(Bundler::PermissionError) end end + + context "when receiving non UTF-8 data and default internal encoding set to ASCII" do + let(:response) { double(:response, :body => "\x8B".b) } + + it "works just fine" do + old_verbose = $VERBOSE + previous_internal_encoding = Encoding.default_internal + + begin + $VERBOSE = false + Encoding.default_internal = "ASCII" + expect(response).to receive(:[]).with("ETag") { nil } + expect(fetcher).to receive(:call) { response } + + updater.update(local_path, remote_path) + ensure + Encoding.default_internal = previous_internal_encoding + $VERBOSE = old_verbose + end + end + end end diff --git a/spec/bundler/bundler/dep_proxy_spec.rb b/spec/bundler/bundler/dep_proxy_spec.rb index 0f8d6b1076..84243d2ee2 100644 --- a/spec/bundler/bundler/dep_proxy_spec.rb +++ b/spec/bundler/bundler/dep_proxy_spec.rb @@ -2,10 +2,10 @@ RSpec.describe Bundler::DepProxy do let(:dep) { Bundler::Dependency.new("rake", ">= 0") } - subject { described_class.new(dep, Gem::Platform::RUBY) } + subject { described_class.get_proxy(dep, Gem::Platform::RUBY) } let(:same) { subject } - let(:other) { subject.dup } - let(:different) { described_class.new(dep, Gem::Platform::JAVA) } + let(:other) { described_class.get_proxy(dep, Gem::Platform::RUBY) } + let(:different) { described_class.get_proxy(dep, Gem::Platform::JAVA) } describe "#eql?" do it { expect(subject.eql?(same)).to be true } @@ -15,8 +15,18 @@ RSpec.describe Bundler::DepProxy do it { expect(subject.eql?("foobar")).to be false } end - describe "#hash" do - it { expect(subject.hash).to eq(same.hash) } - it { expect(subject.hash).to eq(other.hash) } + describe "must use factory methods" do + it { expect { described_class.new(dep, Gem::Platform::RUBY) }.to raise_error NoMethodError } + it { expect { subject.dup }.to raise_error NoMethodError } + it { expect { subject.clone }.to raise_error NoMethodError } + end + + describe "frozen" do + if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.5.0") + error = Object.const_get("FrozenError") + else + error = RuntimeError + end + it { expect { subject.instance_variable_set(:@__platform, {}) }.to raise_error error } end end diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb index ff87b57886..a47dd6e399 100644 --- a/spec/bundler/bundler/dsl_spec.rb +++ b/spec/bundler/bundler/dsl_spec.rb @@ -25,7 +25,7 @@ RSpec.describe Bundler::Dsl do expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption) end - context "default hosts", :bundler => "2" do + context "default hosts", :bundler => "< 3" do it "converts :github to URI using https" do subject.gem("sparks", :github => "indirect/sparks") github_uri = "https://github.com/indirect/sparks.git" @@ -195,19 +195,6 @@ RSpec.describe Bundler::Dsl do # gem 'spree_api' # gem 'spree_backend' # end - describe "#github", :bundler => "< 3" do - it "from github" do - spree_gems = %w[spree_core spree_api spree_backend] - subject.github "spree" do - spree_gems.each {|spree_gem| subject.send :gem, spree_gem } - end - - subject.dependencies.each do |d| - expect(d.source.uri).to eq("https://github.com/spree/spree.git") - end - end - end - describe "#github" do it "from github" do spree_gems = %w[spree_core spree_api spree_backend] diff --git a/spec/bundler/bundler/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb index 769c461911..d718615ad2 100644 --- a/spec/bundler/bundler/gem_helper_spec.rb +++ b/spec/bundler/bundler/gem_helper_spec.rb @@ -9,7 +9,8 @@ RSpec.describe Bundler::GemHelper do let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") } before(:each) do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__RUBOCOP" => "false", "BUNDLE_GEM__CI" => "false" + global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__RUBOCOP" => "false", + "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false" bundle "gem #{app_name}" prepare_gemspec(app_gemspec_path) end @@ -267,6 +268,14 @@ RSpec.describe Bundler::GemHelper do Rake.application["release"].invoke end + + it "also works with releasing from a branch not yet pushed" do + sys_exec("git checkout -b module_function", :dir => app_path) + + expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) + + Rake.application["release"].invoke + end end context "on releasing with a custom tag prefix" do diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb index 01e0232fba..43a3630bbb 100644 --- a/spec/bundler/bundler/gem_version_promoter_spec.rb +++ b/spec/bundler/bundler/gem_version_promoter_spec.rb @@ -28,7 +28,7 @@ RSpec.describe Bundler::GemVersionPromoter do def build_spec_groups(name, versions) versions.map do |v| - Bundler::Resolver::SpecGroup.new(build_spec(name, v)) + Bundler::Resolver::SpecGroup.create_for({ Gem::Platform::RUBY => build_spec(name, v) }, [Gem::Platform::RUBY], Gem::Platform::RUBY) end end @@ -170,7 +170,7 @@ RSpec.describe Bundler::GemVersionPromoter do context "debug output" do it "should not kerblooie on its own debug output" do gvp = unlocking(:level => :patch) - dep = Bundler::DepProxy.new(dep("foo", "1.2.0").first, "ruby") + dep = Bundler::DepProxy.get_proxy(dep("foo", "1.2.0").first, "ruby") result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0])) expect(result.class).to eq Array end diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb index c1c88ce480..cc28382043 100644 --- a/spec/bundler/bundler/plugin_spec.rb +++ b/spec/bundler/bundler/plugin_spec.rb @@ -110,6 +110,7 @@ RSpec.describe Bundler::Plugin do before do allow(Plugin::DSL).to receive(:new) { builder } allow(builder).to receive(:eval_gemfile).with(gemfile) + allow(builder).to receive(:check_primary_source_safety) allow(builder).to receive(:to_definition) { definition } allow(builder).to receive(:inferred_plugins) { [] } end diff --git a/spec/bundler/bundler/source/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb index 35702d7763..97f06973cb 100644 --- a/spec/bundler/bundler/source/git/git_proxy_spec.rb +++ b/spec/bundler/bundler/source/git/git_proxy_spec.rb @@ -130,18 +130,20 @@ RSpec.describe Bundler::Source::Git::GitProxy do context "when given a SHA as a revision" do let(:revision) { "abcd" * 10 } let(:command) { ["reset", "--hard", revision] } + let(:command_for_display) { "git #{command.shelljoin}" } it "fails gracefully when resetting to the revision fails" do expect(subject).to receive(:git_retry).with("clone", any_args) { destination.mkpath } expect(subject).to receive(:git_retry).with("fetch", any_args, :dir => destination) - expect(subject).to receive(:git).with(*command, :dir => destination).and_raise(Bundler::Source::Git::GitCommandError.new(command, cache, destination)) + expect(subject).to receive(:git).with(*command, :dir => destination).and_raise(Bundler::Source::Git::GitCommandError.new(command_for_display, destination)) expect(subject).not_to receive(:git) expect { subject.copy_to(destination, submodules) }. to raise_error( Bundler::Source::Git::MissingGitRevisionError, - "Git error: command `git #{command}` in directory #{destination} has failed.\n" \ - "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?" \ + "Git error: command `#{command_for_display}` in directory #{destination} has failed.\n" \ + "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?\n" \ + "If this error persists you could try removing the cache directory '#{destination}'" ) end end diff --git a/spec/bundler/bundler/source/git_spec.rb b/spec/bundler/bundler/source/git_spec.rb index f7475a35aa..6668b6e69a 100644 --- a/spec/bundler/bundler/source/git_spec.rb +++ b/spec/bundler/bundler/source/git_spec.rb @@ -14,14 +14,14 @@ RSpec.describe Bundler::Source::Git do describe "#to_s" do it "returns a description" do - expect(subject.to_s).to eq "https://github.com/foo/bar.git (at master)" + expect(subject.to_s).to eq "https://github.com/foo/bar.git" end context "when the URI contains credentials" do let(:uri) { "https://my-secret-token:x-oauth-basic@github.com/foo/bar.git" } it "filters credentials" do - expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git (at master)" + expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git" end end end diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb index 0a54f9d7b5..fb612813c2 100644 --- a/spec/bundler/bundler/stub_specification_spec.rb +++ b/spec/bundler/bundler/stub_specification_spec.rb @@ -6,6 +6,7 @@ RSpec.describe Bundler::StubSpecification do s.name = "gemname" s.version = "1.0.0" s.loaded_from = __FILE__ + s.extensions = "ext/gemname" end described_class.from_stub(gemspec) @@ -17,4 +18,30 @@ RSpec.describe Bundler::StubSpecification do expect(stub).to be(with_bundler_stub_spec) end end + + describe "#manually_installed?" do + it "returns true if installed_by_version is nil or 0" do + stub = described_class.from_stub(with_bundler_stub_spec) + expect(stub.manually_installed?).to be true + end + + it "returns false if installed_by_version is greater than 0" do + stub = described_class.from_stub(with_bundler_stub_spec) + stub.installed_by_version = Gem::Version.new(1) + expect(stub.manually_installed?).to be false + end + end + + describe "#missing_extensions?" do + it "returns false if manually_installed?" do + stub = described_class.from_stub(with_bundler_stub_spec) + expect(stub.missing_extensions?).to be false + end + + it "returns true if not manually_installed?" do + stub = described_class.from_stub(with_bundler_stub_spec) + stub.installed_by_version = Gem::Version.new(1) + expect(stub.missing_extensions?).to be true + end + end end diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb index 97d73907db..25f12a9e87 100644 --- a/spec/bundler/cache/git_spec.rb +++ b/spec/bundler/cache/git_spec.rb @@ -200,7 +200,7 @@ RSpec.describe "bundle cache with git" do gem "foo", :git => '#{lib_path("foo-1.0")}' G bundle "config set cache_all true" - bundle :cache, "all-platforms" => true, :install => false, :path => "./vendor/cache" + bundle :cache, "all-platforms" => true, :install => false simulate_new_machine with_path_as "" do diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index f4a57039ad..3b8bce4b01 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -1,6 +1,19 @@ # frozen_string_literal: true RSpec.describe "bundle cache" do + it "doesn't update the cache multiple times, even if it already exists" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + G + + bundle :cache + expect(out).to include("Updating files in vendor/cache").once + + bundle :cache + expect(out).to include("Updating files in vendor/cache").once + end + context "with --gemfile" do it "finds the gemfile" do gemfile bundled_app("NotGemfile"), <<-G diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 6485eb6a5a..0d104ad304 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -668,29 +668,40 @@ RSpec.describe "bundle exec" do subject { bundle "exec #{path} arg1 arg2", :raise_on_error => false } - shared_examples_for "it runs" do - it "like a normally executed executable" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject - expect(exitstatus).to eq(exit_code) - expect(err).to eq(expected_err) - expect(out).to eq(expected) - end + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) end - it_behaves_like "it runs" - context "the executable exits explicitly" do let(:executable) { super() << "\nexit #{exit_code}\nputs 'POST_EXIT'\n" } context "with exit 0" do - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "with exit 99" do let(:exit_code) { 99 } - it_behaves_like "it runs" + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end end @@ -707,7 +718,15 @@ RSpec.describe "bundle exec" do # this is specified by C99 128 + 15 end - it_behaves_like "it runs" + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "the executable is empty" do @@ -716,7 +735,15 @@ RSpec.describe "bundle exec" do let(:exit_code) { 0 } let(:expected_err) { "#{path} is empty" } let(:expected) { "" } - it_behaves_like "it runs" + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "the executable raises" do @@ -743,12 +770,27 @@ RSpec.describe "bundle exec" do let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\n#{system_gem_path("bin/bundle")}: Err (Err)" } let(:expected) { super() } - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when the file uses the current ruby shebang" do let(:shebang) { "#!#{Gem.ruby}" } - it_behaves_like "it runs" + + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when Bundler.setup fails", :bundler => "< 3" do @@ -762,11 +804,19 @@ 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 any of the gem sources listed in your Gemfile.\e[0m +\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 EOS - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when Bundler.setup fails", :bundler => "3" do @@ -785,14 +835,28 @@ The source contains the following versions of 'rack': 1.0.0\e[0m \e[33mRun `bundle install` to install missing gems.\e[0m EOS - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + 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 } - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when disable_exec_load is set" do @@ -803,7 +867,14 @@ The source contains the following versions of 'rack': 1.0.0\e[0m bundle "config set disable_exec_load true" end - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "regarding $0 and __FILE__" do @@ -819,12 +890,26 @@ $0: #{path.to_s.inspect} __FILE__: #{path.to_s.inspect} EOS - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end context "when the path is relative" do let(:path) { super().relative_path_from(bundled_app) } - it_behaves_like "it runs" + it "runs" do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + subject + expect(exitstatus).to eq(exit_code) + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end end context "when the path is relative with a leading ./" do diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index afc3b03a53..7724170a63 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -220,6 +220,30 @@ RSpec.describe "bundle lock" do expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq) end + it "supports adding new platforms with force_ruby_platform = true" do + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + platform_specific (1.0) + platform_specific (1.0-x86-linux) + + PLATFORMS + ruby + x86-linux + + DEPENDENCIES + platform_specific + L + + bundle "config set force_ruby_platform true" + bundle "lock --add-platform java x86-mingw32" + + allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) + lockfile = Bundler::LockfileParser.new(read_lockfile) + expect(lockfile.platforms).to contain_exactly(rb, linux, java, mingw) + end + it "supports adding the `ruby` platform" do bundle "lock --add-platform ruby" @@ -467,6 +491,51 @@ RSpec.describe "bundle lock" do end end + it "does not conflict on ruby requirements when adding new platforms" do + next_minor = Gem.ruby_version.segments[0..1].map.with_index {|s, i| i == 1 ? s + 1 : s }.join(".") + + build_repo4 do + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "x86_64-linux" + s.required_ruby_version = "< #{next_minor}.dev" + end + + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "universal-darwin" + s.required_ruby_version = "< #{next_minor}.dev" + end + + build_gem "raygun-apm", "1.0.78" do |s| + s.platform = "x64-mingw32" + s.required_ruby_version = "< #{next_minor}.dev" + end + end + + gemfile <<-G + source "https://localgemserver.test" + + gem "raygun-apm" + G + + lockfile <<-L + GEM + remote: https://localgemserver.test/ + specs: + raygun-apm (1.0.78-universal-darwin) + + PLATFORMS + x86_64-darwin-19 + + DEPENDENCIES + raygun-apm + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "lock --add-platform x86_64-linux", :artifice => :compact_index, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + end + context "when an update is available" do let(:repo) { gem_repo2 } diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb index 8aca745bef..c1d5e1814d 100644 --- a/spec/bundler/commands/newgem_spec.rb +++ b/spec/bundler/commands/newgem_spec.rb @@ -12,10 +12,10 @@ RSpec.describe "bundle gem" do def bundle_exec_rubocop prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec")) - rubocop_version = RUBY_VERSION > "2.4" ? "0.90.0" : "0.80.1" + rubocop_version = RUBY_VERSION > "2.4" ? "1.7.0" : "0.81.0" gems = ["minitest", "rake", "rake-compiler", "rspec", "rubocop -v #{rubocop_version}", "test-unit"] gems.unshift "parallel -v 1.19.2" if RUBY_VERSION < "2.5" - gems += ["rubocop-ast -v 0.4.0"] if rubocop_version == "0.90.0" + gems += ["rubocop-ast -v 1.4.0"] if rubocop_version == "1.7.0" path = Bundler.feature_flag.default_install_uses_path? ? local_gem_path(:base => bundled_app(gem_name)) : system_gem_path realworld_system_gems gems, :path => path bundle "exec rubocop --debug --config .rubocop.yml", :dir => bundled_app(gem_name) @@ -28,44 +28,9 @@ RSpec.describe "bundle gem" do let(:require_path) { "mygem" } before do - git_config_content = <<-EOF - [user] - name = "Bundler User" - email = user@example.com - [github] - user = bundleuser - EOF - @git_config_location = ENV["GIT_CONFIG"] - path = "#{tmp}/test_git_config.txt" - File.open(path, "w") {|f| f.write(git_config_content) } - ENV["GIT_CONFIG"] = path - end - - after do - FileUtils.rm(ENV["GIT_CONFIG"]) if File.exist?(ENV["GIT_CONFIG"]) - ENV["GIT_CONFIG"] = @git_config_location - end - - shared_examples_for "git config is present" do - context "git config user.{name,email} present" do - it "sets gemspec author to git user.name if available" do - expect(generated_gemspec.authors.first).to eq("Bundler User") - end - - it "sets gemspec email to git user.email if available" do - expect(generated_gemspec.email.first).to eq("user@example.com") - end - end - end - - shared_examples_for "git config is absent" do - it "sets gemspec author to default message if git user.name is not set or empty" do - expect(generated_gemspec.authors.first).to eq("TODO: Write your name") - end - - it "sets gemspec email to default message if git user.email is not set or empty" do - expect(generated_gemspec.email.first).to eq("TODO: Write your email address") - end + sys_exec("git config --global user.name 'Bundler User'") + sys_exec("git config --global user.email user@example.com") + sys_exec("git config --global github.user bundleuser") end describe "git repo initialization" do @@ -125,19 +90,24 @@ RSpec.describe "bundle gem" do end shared_examples_for "--coc flag" do - before do - bundle "gem #{gem_name} --coc" - end it "generates a gem skeleton with MIT license" do + bundle "gem #{gem_name} --coc" gem_skeleton_assertions expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to exist end - describe "README additions" do - it "generates the README with a section for the Code of Conduct" do - expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct") - expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md") - end + it "generates the README with a section for the Code of Conduct" do + bundle "gem #{gem_name} --coc" + expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct") + expect(bundled_app("#{gem_name}/README.md").read).to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md}) + end + + it "generates the README with a section for the Code of Conduct, respecting the configured git default branch" do + sys_exec("git config --global init.defaultBranch main") + bundle "gem #{gem_name} --coc" + + expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct") + expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/main/CODE_OF_CONDUCT.md") end end @@ -150,11 +120,29 @@ RSpec.describe "bundle gem" do expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to_not exist end - describe "README additions" do - it "generates the README without a section for the Code of Conduct" do - expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct") - expect(bundled_app("#{gem_name}/README.md").read).not_to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md") - end + it "generates the README without a section for the Code of Conduct" do + expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct") + expect(bundled_app("#{gem_name}/README.md").read).not_to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md}) + end + end + + shared_examples_for "--changelog flag" do + before do + bundle "gem #{gem_name} --changelog" + end + it "generates a gem skeleton with a CHANGELOG", :readline do + gem_skeleton_assertions + expect(bundled_app("#{gem_name}/CHANGELOG.md")).to exist + end + end + + shared_examples_for "--no-changelog flag" do + before do + bundle "gem #{gem_name} --no-changelog" + end + it "generates a gem skeleton without a CHANGELOG", :readline do + gem_skeleton_assertions + expect(bundled_app("#{gem_name}/CHANGELOG.md")).to_not exist end end @@ -282,7 +270,7 @@ RSpec.describe "bundle gem" do context "git config github.user is absent" do before do - sys_exec("git config --unset github.user") + sys_exec("git config --global --unset github.user") bundle "gem #{gem_name}" end @@ -393,17 +381,29 @@ RSpec.describe "bundle gem" do bundle "gem #{gem_name}" end - it_should_behave_like "git config is present" + it "sets gemspec author to git user.name if available" do + expect(generated_gemspec.authors.first).to eq("Bundler User") + end + + it "sets gemspec email to git user.email if available" do + expect(generated_gemspec.email.first).to eq("user@example.com") + end end context "git config user.{name,email} is not set" do before do - sys_exec("git config --unset user.name", :dir => bundled_app) - sys_exec("git config --unset user.email", :dir => bundled_app) + sys_exec("git config --global --unset user.name") + sys_exec("git config --global --unset user.email") bundle "gem #{gem_name}" end - it_should_behave_like "git config is absent" + it "sets gemspec author to default message if git user.name is not set or empty" do + expect(generated_gemspec.authors.first).to eq("TODO: Write your name") + end + + it "sets gemspec email to default message if git user.email is not set or empty" do + expect(generated_gemspec.email.first).to eq("TODO: Write your email address") + end end it "sets gemspec metadata['allowed_push_host']" do @@ -416,9 +416,7 @@ RSpec.describe "bundle gem" do it "sets a minimum ruby version" do bundle "gem #{gem_name}" - bundler_gemspec = Bundler::GemHelper.new(gemspec_dir).gemspec - - expect(bundler_gemspec.required_ruby_version).to eq(generated_gemspec.required_ruby_version) + expect(generated_gemspec.required_ruby_version).to eq(Gem::Requirement.new(Gem.ruby_version < Gem::Version.new("2.4.a") ? ">= 2.3.0" : ">= 2.4.0")) end it "requires the version file" do @@ -904,6 +902,22 @@ RSpec.describe "bundle gem" do it_behaves_like "--rubocop flag" it_behaves_like "--no-rubocop flag" end + + context "with changelog option in bundle config settings set to true" do + before do + global_config "BUNDLE_GEM__CHANGELOG" => "true" + end + it_behaves_like "--changelog flag" + it_behaves_like "--no-changelog flag" + end + + context "with changelog option in bundle config settings set to false" do + before do + global_config "BUNDLE_GEM__CHANGELOG" => "false" + end + it_behaves_like "--changelog flag" + it_behaves_like "--no-changelog flag" + end end context "gem naming with underscore", :readline do @@ -1089,13 +1103,24 @@ Usage: "bundle gem NAME [OPTIONS]" expect(bundled_app("foobar/CODE_OF_CONDUCT.md")).to exist end + + it "asks about CHANGELOG" do + global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__RUBOCOP" => "false", + "BUNDLE_GEM__COC" => "false" + + bundle "gem foobar" do |input, _, _| + input.puts "yes" + end + + expect(bundled_app("foobar/CHANGELOG.md")).to exist + end end context "on conflicts with a previously created file", :readline do it "should fail gracefully" do FileUtils.touch(bundled_app("conflict-foobar")) bundle "gem conflict-foobar", :raise_on_error => false - expect(err).to include("Errno::ENOTDIR") + expect(err).to eq("Couldn't create a new gem named `conflict-foobar` because there's an existing file named `conflict-foobar`.") expect(exitstatus).to eql(32) end end diff --git a/spec/bundler/commands/post_bundle_message_spec.rb b/spec/bundler/commands/post_bundle_message_spec.rb index 710152e59f..104221efbe 100644 --- a/spec/bundler/commands/post_bundle_message_spec.rb +++ b/spec/bundler/commands/post_bundle_message_spec.rb @@ -113,16 +113,7 @@ RSpec.describe "post bundle message" do bundle "config set force_ruby_platform true" end - it "should report a helpful error message", :bundler => "< 3" do - install_gemfile <<-G, :raise_on_error => false - source "#{file_uri_for(gem_repo1)}" - gem "rack" - gem "not-a-gem", :group => :development - G - expect(err).to include("Could not find gem 'not-a-gem' in any of the gem sources listed in your Gemfile.") - end - - it "should report a helpful error message", :bundler => "3" do + it "should report a helpful error message" do install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo1)}" gem "rack" diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index b8de6507f6..521c175711 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -651,6 +651,8 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler" build_gem "rails", "3.0.1" do |s| s.add_dependency "bundler", Bundler::VERSION.succ end + + build_gem "bundler", Bundler::VERSION.succ end gemfile <<-G @@ -659,18 +661,11 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler" G end - it "should explain that bundler conflicted", :bundler => "< 3" do + it "should explain that bundler conflicted and how to resolve the conflict" do bundle "update", :all => true, :raise_on_error => false expect(last_command.stdboth).not_to match(/in snapshot/i) expect(err).to match(/current Bundler version/i). - and match(/perhaps you need to update bundler/i) - end - - it "should warn that the newer version of Bundler would conflict", :bundler => "3" do - bundle "update", :all => true - expect(err).to include("rails (3.0.1) has dependency bundler"). - and include("so the dependency is being ignored") - expect(the_bundle).to include_gem "rails 3.0.1" + and match(/Install the necessary version with `gem install bundler:#{Bundler::VERSION.succ}`/i) end end diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb index af1ff7225a..963ce82db8 100644 --- a/spec/bundler/install/bundler_spec.rb +++ b/spec/bundler/install/bundler_spec.rb @@ -21,17 +21,57 @@ RSpec.describe "bundle install" do expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}" end - it "are not added if not already present" do + it "are forced to the current bundler version even if not already present" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" G - expect(the_bundle).not_to include_gems "bundler #{Bundler::VERSION}" + expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}" end - it "causes a conflict if explicitly requesting a different version" do - bundle "config set force_ruby_platform true" + it "causes a conflict if explicitly requesting a different version of bundler" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rails", "3.0" + gem "bundler", "0.9.1" + G + nice_error = <<-E.strip.gsub(/^ {8}/, "") + Bundler could not find compatible versions for gem "bundler": + In Gemfile: + bundler (= 0.9.1) + + Current Bundler version: + bundler (#{Bundler::VERSION}) + + Your bundle requires a different version of Bundler than the one you're running. + Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install` + E + expect(err).to include(nice_error) + end + + it "causes a conflict if explicitly requesting a non matching requirement on bundler" do + install_gemfile <<-G, :raise_on_error => false + source "#{file_uri_for(gem_repo2)}" + gem "rails", "3.0" + gem "bundler", "~> 0.8" + G + + nice_error = <<-E.strip.gsub(/^ {8}/, "") + Bundler could not find compatible versions for gem "bundler": + In Gemfile: + bundler (~> 0.8) + + Current Bundler version: + bundler (#{Bundler::VERSION}) + + Your bundle requires a different version of Bundler than the one you're running. + Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install` + E + expect(err).to include(nice_error) + end + + it "causes a conflict if explicitly requesting a version of bundler that doesn't exist" do install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo2)}" gem "rails", "3.0" @@ -45,10 +85,8 @@ RSpec.describe "bundle install" do Current Bundler version: bundler (#{Bundler::VERSION}) - This Gemfile requires a different version of Bundler. - Perhaps you need to update Bundler by running `gem install bundler`? - Could not find gem 'bundler (= 0.9.2)' in any + Your bundle requires a different version of Bundler than the one you're running, and that version could not be found. E expect(err).to include(nice_error) end @@ -197,27 +235,5 @@ RSpec.describe "bundle install" do bundle "check" expect(out).to include("The Gemfile's dependencies are satisfied") end - - context "with allow_bundler_dependency_conflicts set" do - before { bundle "config set allow_bundler_dependency_conflicts true" } - - it "are forced to the current bundler version with warnings when no compatible version is found" do - build_repo4 do - build_gem "requires_nonexistant_bundler" do |s| - s.add_runtime_dependency "bundler", "99.99.99.99" - end - end - - install_gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem "requires_nonexistant_bundler" - G - - expect(err).to include "requires_nonexistant_bundler (1.0) has dependency bundler (= 99.99.99.99), " \ - "which is unsatisfied by the current bundler version #{Bundler::VERSION}, so the dependency is being ignored" - - expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}", "requires_nonexistant_bundler 1.0" - end - end end end diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb index 5f4fc71499..f3898c0a65 100644 --- a/spec/bundler/install/deploy_spec.rb +++ b/spec/bundler/install/deploy_spec.rb @@ -85,6 +85,18 @@ RSpec.describe "install in deployment or frozen mode" do bundle :install end + it "works when path gems are specified twice" do + build_lib "foo", :path => lib_path("nested/foo") + gemfile <<-G + gem "foo", :path => "#{lib_path("nested/foo")}" + gem "foo", :path => "#{lib_path("nested/foo")}" + G + + bundle :install + bundle "config set --local deployment true" + bundle :install + end + it "works when there are credentials in the source URL" do install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) source "http://user:pass@localgemserver.test/" @@ -341,7 +353,7 @@ RSpec.describe "install in deployment or frozen mode" do bundle "config set --local deployment true" bundle :install, :raise_on_error => false expect(err).to include("deployment mode") - expect(err).to include("You have added to the Gemfile:\n* source: git://hubz.com (at master)") + expect(err).to include("You have added to the Gemfile:\n* source: git://hubz.com") expect(err).not_to include("You have changed in the Gemfile") end @@ -361,7 +373,7 @@ RSpec.describe "install in deployment or frozen mode" do bundle "config set --local deployment true" bundle :install, :raise_on_error => false expect(err).to include("deployment mode") - expect(err).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")} (at master@#{revision_for(lib_path("rack-1.0"))[0..6]}") + expect(err).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")}") expect(err).not_to include("You have added to the Gemfile") expect(err).not_to include("You have changed in the Gemfile") end @@ -385,7 +397,7 @@ RSpec.describe "install in deployment or frozen mode" do bundle "config set --local deployment true" bundle :install, :raise_on_error => false expect(err).to include("deployment mode") - expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")} (at master@#{revision_for(lib_path("rack"))[0..6]})`") + expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")}`") expect(err).not_to include("You have added to the Gemfile") expect(err).not_to include("You have deleted from the Gemfile") end @@ -401,7 +413,7 @@ RSpec.describe "install in deployment or frozen mode" do gem "rack-obama" G - expect(the_bundle).not_to include_gems "rack 1.0.0" + run "require 'rack'", :raise_on_error => false expect(err).to include strip_whitespace(<<-E).strip The dependencies in your gemfile changed diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb index b41a083d92..a70b950e1b 100644 --- a/spec/bundler/install/gemfile/gemspec_spec.rb +++ b/spec/bundler/install/gemfile/gemspec_spec.rb @@ -422,14 +422,13 @@ RSpec.describe "bundle install from an existing gemspec" do end end - %w[ruby jruby].each do |platform| - simulate_platform(platform) do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - gemspec - G - end - end + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gemspec + G + + simulate_platform("ruby") { bundle "install" } + simulate_platform("jruby") { bundle "install" } end context "on ruby" do diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb index 2e0c0bcf6d..ba8f253b0e 100644 --- a/spec/bundler/install/gemfile/git_spec.rb +++ b/spec/bundler/install/gemfile/git_spec.rb @@ -598,6 +598,24 @@ RSpec.describe "bundle install with git sources" do bundle :install, :raise_on_error => false expect(err).to match(/The Gemfile lock is pointing to revision \w+/) end + + it "does not explode on invalid revision on install" do + build_git "rack", "0.8" + + build_git "rack", "0.8", :path => lib_path("local-rack") do |s| + s.write "lib/rack.rb", "puts :LOCAL" + end + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master" + G + + bundle %(config set local.rack #{lib_path("local-rack")}) + bundle %(config set disable_local_revision_check true) + bundle :install + expect(out).to match(/Bundle complete!/) + end end describe "specified inline" do @@ -629,8 +647,6 @@ RSpec.describe "bundle install with git sources" do end it "installs dependencies from git even if a newer gem is available elsewhere" do - skip "override is not winning" if Gem.win_platform? - system_gems "rack-1.0.0" build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s| diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb index fc40c5e9b9..3463c5ec06 100644 --- a/spec/bundler/install/gemfile/path_spec.rb +++ b/spec/bundler/install/gemfile/path_spec.rb @@ -136,8 +136,6 @@ RSpec.describe "bundle install with explicit source paths" do end it "installs dependencies from the path even if a newer gem is available elsewhere" do - skip "override is not winning" if Gem.win_platform? - system_gems "rack-1.0.0" build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s| @@ -581,6 +579,71 @@ RSpec.describe "bundle install with explicit source paths" do expect(the_bundle).to include_gems "rack 0.9.1" end + + it "keeps using the same version even when another dependency is added" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", "0.9.1" + end + + bundle "install" + + expect(the_bundle).to include_gems "rack 0.9.1" + + lockfile_should_be <<-G + PATH + remote: #{lib_path("foo")} + specs: + foo (1.0) + rack (= 0.9.1) + + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (0.9.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + G + + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack" + s.add_dependency "rake", "13.0.1" + end + + bundle "install" + + lockfile_should_be <<-G + PATH + remote: #{lib_path("foo")} + specs: + foo (1.0) + rack + rake (= 13.0.1) + + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + rack (0.9.1) + rake (13.0.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + G + + expect(the_bundle).to include_gems "rack 0.9.1" + end end describe "switching sources" do @@ -636,8 +699,6 @@ RSpec.describe "bundle install with explicit source paths" do describe "when there are both a gemspec and remote gems" do it "doesn't query rubygems for local gemspec name" do - skip "platform issues" if Gem.win_platform? - build_lib "private_lib", "2.2", :path => lib_path("private_lib") gemfile = <<-G source "http://localgemserver.test" diff --git a/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb index 1a3794dffe..c49594183e 100644 --- a/spec/bundler/install/gemfile/platform_spec.rb +++ b/spec/bundler/install/gemfile/platform_spec.rb @@ -88,14 +88,15 @@ RSpec.describe "bundle install across platforms" do simulate_new_machine simulate_platform "ruby" - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - - gem "nokogiri" - G + bundle "install" expect(the_bundle).to include_gems "nokogiri 1.4.2" expect(the_bundle).not_to include_gems "weakling" + + simulate_platform "java" + bundle "install" + + expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3" end it "does not keep unneeded platforms for gems that are used" do @@ -241,20 +242,6 @@ RSpec.describe "bundle install across platforms" do end end - it "works the other way with gems that have different dependencies" do - simulate_platform "ruby" - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - - gem "nokogiri" - G - - simulate_platform "java" - bundle "install" - - expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3" - end - it "works with gems with platform-specific dependency having different requirements order" do simulate_platform x64_mac @@ -299,6 +286,48 @@ RSpec.describe "bundle install across platforms" do bundle :install expect(vendored_gems("gems/rack-1.0.0")).to exist end + + it "keeps existing platforms when installing with force_ruby_platform" do + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + platform_specific (1.0-java) + + PLATFORMS + java + + DEPENDENCIES + platform_specific + G + + bundle "config set --local force_ruby_platform true" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "platform_specific" + G + + expect(the_bundle).to include_gem "platform_specific 1.0 RUBY" + + lockfile_should_be <<-G + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + platform_specific (1.0) + platform_specific (1.0-java) + + PLATFORMS + java + ruby + + DEPENDENCIES + platform_specific + + BUNDLED WITH + #{Bundler::VERSION} + G + end end RSpec.describe "bundle install with platform conditionals" do diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb index 75b7b67e98..b388b17881 100644 --- a/spec/bundler/install/gemfile/sources_spec.rb +++ b/spec/bundler/install/gemfile/sources_spec.rb @@ -27,7 +27,7 @@ RSpec.describe "bundle install with gems on multiple sources" do G end - it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "2" do + it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do bundle :install expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") @@ -54,7 +54,7 @@ RSpec.describe "bundle install with gems on multiple sources" do G end - it "warns about ambiguous gems, but installs anyway", :bundler => "2" do + it "warns about ambiguous gems, but installs anyway", :bundler => "< 3" do bundle :install expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") expect(err).to include("Installed from: #{file_uri_for(gem_repo1)}") @@ -96,7 +96,7 @@ RSpec.describe "bundle install with gems on multiple sources" do it "installs the gems without any warning" do bundle :install - expect(out).not_to include("Warning") + expect(err).not_to include("Warning") expect(the_bundle).to include_gems("rack-obama 1.0.0") expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1") end @@ -128,7 +128,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - gemfile <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo3)}" gem "rack-obama" # should come from repo3! gem "rack", :source => "#{file_uri_for(gem_repo1)}" @@ -136,8 +136,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end it "installs the gems without any warning" do - bundle :install - expect(out).not_to include("Warning") + expect(err).not_to include("Warning") expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0") end end @@ -173,8 +172,8 @@ RSpec.describe "bundle install with gems on multiple sources" do it "installs from the same source without any warning" do bundle :install - expect(out).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") end end @@ -188,26 +187,19 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - context "when disable_multisource is set" do - before do - bundle "config set disable_multisource true" - end - - it "installs from the same source without any warning" do - bundle :install + it "installs from the same source without any warning" do + bundle :install - expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") - # when there is already a lock file, and the gems are missing, so try again - system_gems [] - bundle :install + # In https://github.com/bundler/bundler/issues/3585 this failed + # when there is already a lock file, and the gems are missing, so try again + system_gems [] + bundle :install - expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - end + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") end end end @@ -222,7 +214,7 @@ RSpec.describe "bundle install with gems on multiple sources" do context "and not in any other sources" do before do - gemfile <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo3)}" do gem "depends_on_rack" @@ -231,8 +223,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end it "installs from the other source without any warning" do - bundle :install - expect(out).not_to include("Warning") + expect(err).not_to include("Warning") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") end end @@ -248,7 +239,7 @@ RSpec.describe "bundle install with gems on multiple sources" do G end - it "installs from the other source and warns about ambiguous gems", :bundler => "2" do + it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do bundle :install expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") expect(err).to include("Installed from: #{file_uri_for(gem_repo2)}") @@ -280,7 +271,7 @@ RSpec.describe "bundle install with gems on multiple sources" do G end - it "installs the dependency from the pinned source without warning", :bundler => "2" do + it "installs the dependency from the pinned source without warning", :bundler => "< 3" do bundle :install expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") @@ -304,6 +295,33 @@ RSpec.describe "bundle install with gems on multiple sources" do end end + context "when a top-level gem can only be found in an scoped source" do + before do + build_repo2 + + build_repo gem_repo3 do + build_gem "private_gem_1", "1.0.0" + build_gem "private_gem_2", "1.0.0" + end + + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gem "private_gem_1" + + source "#{file_uri_for(gem_repo3)}" do + gem "private_gem_2" + end + G + end + + it "fails" do + bundle :install, :raise_on_error => false + expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally.") + expect(err).to include("The source does not contain any versions of 'private_gem_1'") + end + end + context "when a top-level gem has an indirect dependency" do context "when disable_multisource is set" do before do @@ -381,6 +399,200 @@ RSpec.describe "bundle install with gems on multiple sources" do end end end + + context "when the lockfile has aggregated rubygems sources and newer versions of dependencies are available" do + before do + build_repo gem_repo2 do + build_gem "activesupport", "6.0.3.4" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" + s.add_dependency "i18n", ">= 0.7", "< 2" + s.add_dependency "minitest", "~> 5.1" + s.add_dependency "tzinfo", "~> 1.1" + s.add_dependency "zeitwerk", "~> 2.2", ">= 2.2.2" + end + + build_gem "activesupport", "6.1.2.1" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" + s.add_dependency "i18n", ">= 1.6", "< 2" + s.add_dependency "minitest", ">= 5.1" + s.add_dependency "tzinfo", "~> 2.0" + s.add_dependency "zeitwerk", "~> 2.3" + end + + build_gem "concurrent-ruby", "1.1.8" + build_gem "concurrent-ruby", "1.1.9" + build_gem "connection_pool", "2.2.3" + + build_gem "i18n", "1.8.9" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0" + end + + build_gem "minitest", "5.14.3" + build_gem "rack", "2.2.3" + build_gem "redis", "4.2.5" + + build_gem "sidekiq", "6.1.3" do |s| + s.add_dependency "connection_pool", ">= 2.2.2" + s.add_dependency "rack", "~> 2.0" + s.add_dependency "redis", ">= 4.2.0" + end + + build_gem "thread_safe", "0.3.6" + + build_gem "tzinfo", "1.2.9" do |s| + s.add_dependency "thread_safe", "~> 0.1" + end + + build_gem "tzinfo", "2.0.4" do |s| + s.add_dependency "concurrent-ruby", "~> 1.0" + end + + build_gem "zeitwerk", "2.4.2" + end + + build_repo gem_repo3 do + build_gem "sidekiq-pro", "5.2.1" do |s| + s.add_dependency "connection_pool", ">= 2.2.3" + s.add_dependency "sidekiq", ">= 6.1.0" + end + end + + gemfile <<-G + # frozen_string_literal: true + + source "#{file_uri_for(gem_repo2)}" + + gem "activesupport" + + source "#{file_uri_for(gem_repo3)}" do + gem "sidekiq-pro" + end + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo2)}/ + remote: #{file_uri_for(gem_repo3)}/ + specs: + activesupport (6.0.3.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + concurrent-ruby (1.1.8) + connection_pool (2.2.3) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + minitest (5.14.3) + rack (2.2.3) + redis (4.2.5) + sidekiq (6.1.3) + connection_pool (>= 2.2.2) + rack (~> 2.0) + redis (>= 4.2.0) + sidekiq-pro (5.2.1) + connection_pool (>= 2.2.3) + sidekiq (>= 6.1.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + zeitwerk (2.4.2) + + PLATFORMS + #{specific_local_platform} + + DEPENDENCIES + activesupport + sidekiq-pro! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "upgrades gems when running bundle update, without printing any warnings or errors" do + bundle "update --all" + expect(err).to be_empty + end + end + end + + context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved", :bundler => "< 3" do + before do + build_lib "activesupport", "7.0.0.alpha", :path => lib_path("rails/activesupport") + build_lib "rails", "7.0.0.alpha", :path => lib_path("rails") do |s| + s.add_dependency "activesupport", "= 7.0.0.alpha" + end + + build_repo gem_repo2 do + build_gem "activesupport", "6.1.2" + + build_gem "webpacker", "5.2.1" do |s| + s.add_dependency "activesupport", ">= 5.2" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + gemspec :path => "#{lib_path("rails")}" + + gem "webpacker", "~> 5.0" + G + end + + it "installs all gems without warning" do + bundle :install + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", "rails 7.0.0.alpha") + expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", :source => "path@#{lib_path("rails/activesupport")}") + expect(the_bundle).to include_gems("rails 7.0.0.alpha", :source => "path@#{lib_path("rails")}") + end + end + + context "when a pinned gem has an indirect dependency with more than one level of indirection in the default source ", :bundler => "< 3" do + before do + build_repo gem_repo3 do + build_gem "handsoap", "0.2.5.5" do |s| + s.add_dependency "nokogiri", ">= 1.2.3" + end + end + + update_repo gem_repo2 do + build_gem "nokogiri", "1.11.1" do |s| + s.add_dependency "racca", "~> 1.4" + end + + build_gem "racca", "1.5.2" + end + + gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + + source "#{file_uri_for(gem_repo3)}" do + gem "handsoap" + end + + gem "nokogiri" + G + end + + it "installs from the proper sources without any warnings or errors" do + bundle "install --verbose" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") + expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2") + + # Even if the gems are already installed + FileUtils.rm bundled_app_lock + bundle "install --verbose" + expect(err).not_to include("Warning") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") + expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") + expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2") + end end context "with a gem that is only found in the wrong source" do @@ -389,14 +601,13 @@ RSpec.describe "bundle install with gems on multiple sources" do build_gem "not_in_repo1", "1.0.0" end - gemfile <<-G + install_gemfile <<-G, :raise_on_error => false source "#{file_uri_for(gem_repo3)}" gem "not_in_repo1", :source => "#{file_uri_for(gem_repo1)}" G end it "does not install the gem" do - bundle :install, :raise_on_error => false expect(err).to include("Could not find gem 'not_in_repo1'") end end @@ -457,14 +668,13 @@ RSpec.describe "bundle install with gems on multiple sources" do before do system_gems "rack-0.9.1" - gemfile <<-G + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" # shoud come from repo1! G end it "installs the gems without any warning" do - bundle :install expect(err).not_to include("Warning") expect(the_bundle).to include_gems("rack 1.0.0") end @@ -615,7 +825,7 @@ RSpec.describe "bundle install with gems on multiple sources" do G end - it "keeps the old version", :bundler => "2" do + it "keeps the old version", :bundler => "< 3" do expect(the_bundle).to include_gems("rack 1.0.0") end diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb index b58726064f..9e30fc4fd4 100644 --- a/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -211,37 +211,17 @@ RSpec.describe "bundle install with specific platforms" do build_repo2 do build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-linux" } build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" } build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" } build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-linux" } build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-mingw32" } build_gem("google-protobuf", "3.0.0.alpha.5.0.5") build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x64-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.4") - - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86_64-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-linux" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x64-mingw32" } - build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "universal-darwin" } build_gem("google-protobuf", "3.0.0.alpha.4.0") build_gem("google-protobuf", "3.0.0.alpha.3.1.pre") - build_gem("google-protobuf", "3.0.0.alpha.3") - build_gem("google-protobuf", "3.0.0.alpha.2.0") - build_gem("google-protobuf", "3.0.0.alpha.1.1") - build_gem("google-protobuf", "3.0.0.alpha.1.0") end end diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb index 4384a731cd..035ed9a7f3 100644 --- a/spec/bundler/install/gems/resolving_spec.rb +++ b/spec/bundler/install/gems/resolving_spec.rb @@ -88,7 +88,7 @@ RSpec.describe "bundle install with install-time dependencies" do end it "installs plugins depended on by other plugins" do - install_gemfile <<-G + install_gemfile <<-G, :env => { "DEBUG" => "1" } source "#{file_uri_for(gem_repo2)}" gem "net_a" G @@ -97,7 +97,7 @@ RSpec.describe "bundle install with install-time dependencies" do end it "installs multiple levels of dependencies" do - install_gemfile <<-G + install_gemfile <<-G, :env => { "DEBUG" => "1" } source "#{file_uri_for(gem_repo2)}" gem "net_c" gem "net_e" @@ -114,7 +114,7 @@ RSpec.describe "bundle install with install-time dependencies" do gem "net_e" G - bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1" } + bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" } expect(out).to include("BUNDLER: Starting resolution") end @@ -128,7 +128,7 @@ RSpec.describe "bundle install with install-time dependencies" do gem "net_e" G - bundle :install, :env => { "DEBUG_RESOLVER" => "1" } + bundle :install, :env => { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" } expect(out).to include("BUNDLER: Starting resolution") end @@ -142,10 +142,13 @@ RSpec.describe "bundle install with install-time dependencies" do gem "net_e" G - bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1" } + bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" } - activated_groups = "net_b (1.0) (ruby)" - activated_groups += ", net_b (1.0) (#{local_platforms.join(", ")})" if local_platforms.any? && local_platforms != ["ruby"] + activated_groups = if local_platforms.any? + "net_b (1.0) (ruby), net_b (1.0) (#{local_platforms.join(", ")})" + else + "net_b (1.0) (ruby)" + end expect(out).to include(" net_b"). and include("BUNDLER: Starting resolution"). @@ -157,10 +160,6 @@ RSpec.describe "bundle install with install-time dependencies" do describe "when a required ruby version" do context "allows only an older version" do - before do - skip "gem not found" if Gem.win_platform? - end - it "installs the older version" do build_repo2 do build_gem "rack", "1.2" do |s| @@ -239,7 +238,6 @@ RSpec.describe "bundle install with install-time dependencies" do let(:ruby_requirement) { %("#{RUBY_VERSION}") } let(:error_message_requirement) { "~> #{RUBY_VERSION}.0" } - let(:error_message_platform) { " #{Bundler.local_platform}" } shared_examples_for "ruby version conflicts" do it "raises an error during resolution" do @@ -256,9 +254,9 @@ RSpec.describe "bundle install with install-time dependencies" do nice_error = strip_whitespace(<<-E).strip Bundler found conflicting requirements for the Ruby\0 version: In Gemfile: - Ruby\0 (#{error_message_requirement})#{error_message_platform} + Ruby\0 (#{error_message_requirement}) - require_ruby#{error_message_platform} was resolved to 1.0, which depends on + require_ruby was resolved to 1.0, which depends on Ruby\0 (> 9000) Ruby\0 (> 9000), which is required by gem 'require_ruby', is not available in the local ruby installation diff --git a/spec/bundler/install/gems/standalone_spec.rb b/spec/bundler/install/gems/standalone_spec.rb index 1037a98092..08d5276a54 100644 --- a/spec/bundler/install/gems/standalone_spec.rb +++ b/spec/bundler/install/gems/standalone_spec.rb @@ -7,6 +7,12 @@ RSpec.shared_examples "bundle install --standalone" do expect(the_bundle).to include_gems(*args) end + it "still makes system gems unavailable to normal bundler" do + system_gems "rack-1.0.0" + + expect(the_bundle).to_not include_gems("rack") + end + it "generates a bundle/bundler/setup.rb" do expect(bundled_app("bundle/bundler/setup.rb")).to exist end @@ -26,6 +32,39 @@ RSpec.shared_examples "bundle install --standalone" do expect(out).to eq(expected_gems.values.join("\n")) end + it "makes the gems available without bundler via Kernel.require" do + testrb = String.new <<-RUBY + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + RUBY + expected_gems.each do |k, _| + testrb << "\nKernel.require \"#{k}\"" + testrb << "\nputs #{k.upcase}" + end + ruby testrb + + expect(out).to eq(expected_gems.values.join("\n")) + end + + it "makes system gems unavailable without bundler" do + system_gems "rack-1.0.0" + + testrb = String.new <<-RUBY + $:.unshift File.expand_path("bundle") + require "bundler/setup" + + begin + require "rack" + rescue LoadError + puts "LoadError" + end + RUBY + ruby testrb + + expect(out).to eq("LoadError") + end + it "works on a different system" do begin FileUtils.mv(bundled_app, "#{bundled_app}2") diff --git a/spec/bundler/install/gemspecs_spec.rb b/spec/bundler/install/gemspecs_spec.rb index 0db1f1985b..dc1934804d 100644 --- a/spec/bundler/install/gemspecs_spec.rb +++ b/spec/bundler/install/gemspecs_spec.rb @@ -28,8 +28,6 @@ RSpec.describe "bundle install" do end it "should use gemspecs in the system cache when available" do - skip "weird incompatible marshal file format error" if Gem.win_platform? - gemfile <<-G source "http://localtestserver.gem" gem 'rack' diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb index 31c9568f85..71771d3dc2 100644 --- a/spec/bundler/install/git_spec.rb +++ b/spec/bundler/install/git_spec.rb @@ -2,10 +2,10 @@ RSpec.describe "bundle install" do context "git sources" do - it "displays the revision hash of the gem repository", :bundler => "< 3" do + it "displays the revision hash of the gem repository" do build_git "foo", "1.0", :path => lib_path("foo") - install_gemfile <<-G + install_gemfile <<-G, :verbose => true gem "foo", :git => "#{file_uri_for(lib_path("foo"))}" G @@ -13,7 +13,18 @@ RSpec.describe "bundle install" do expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}" end - it "displays the ref of the gem repository when using branch~num as a ref", :bundler => "< 3" do + it "displays the correct default branch" do + build_git "foo", "1.0", :path => lib_path("foo"), :default_branch => "main" + + install_gemfile <<-G, :verbose => true + gem "foo", :git => "#{file_uri_for(lib_path("foo"))}" + G + + expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main@#{revision_for(lib_path("foo"))[0..6]})") + expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}" + end + + it "displays the ref of the gem repository when using branch~num as a ref" do skip "maybe branch~num notation doesn't work on Windows' git" if Gem.win_platform? build_git "foo", "1.0", :path => lib_path("foo") @@ -22,7 +33,7 @@ RSpec.describe "bundle install" do rev2 = revision_for(lib_path("foo"))[0..6] update_git "foo", "3.0", :path => lib_path("foo"), :gemspec => true - install_gemfile <<-G + install_gemfile <<-G, :verbose => true gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "master~2" G @@ -31,7 +42,7 @@ RSpec.describe "bundle install" do update_git "foo", "4.0", :path => lib_path("foo"), :gemspec => true - bundle :update, :all => true + bundle :update, :all => true, :verbose => true expect(out).to include("Using foo 2.0 (was 1.0) from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev2})") expect(the_bundle).to include_gems "foo 2.0", :source => "git@#{lib_path("foo")}" end diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index af3a10f9e9..976db33b0e 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1134,7 +1134,7 @@ RSpec.describe "the lockfile format" do G expect(bundled_app_lock).not_to exist - expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)" + expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com" end it "works correctly with multiple version dependencies" do diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb index d061ca7064..0758d29746 100644 --- a/spec/bundler/other/major_deprecation_spec.rb +++ b/spec/bundler/other/major_deprecation_spec.rb @@ -17,7 +17,7 @@ RSpec.describe "major deprecations" do bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_env", :bundler => "2" do + it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do expect(deprecations).to include \ "`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \ "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env` " \ @@ -33,7 +33,7 @@ RSpec.describe "major deprecations" do bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_env", :bundler => "2" do + it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do expect(deprecations).to include( "`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \ "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env` " \ @@ -50,7 +50,7 @@ RSpec.describe "major deprecations" do bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_system", :bundler => "2" do + it "is deprecated in favor of .unbundled_system", :bundler => "< 3" do expect(deprecations).to include( "`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \ "If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system` " \ @@ -67,7 +67,7 @@ RSpec.describe "major deprecations" do bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .unbundled_exec", :bundler => "2" do + it "is deprecated in favor of .unbundled_exec", :bundler => "< 3" do expect(deprecations).to include( "`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \ "If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec` " \ @@ -84,7 +84,7 @@ RSpec.describe "major deprecations" do bundle "exec ruby -e #{source.dump}" end - it "is deprecated in favor of .load", :bundler => "2" do + it "is deprecated in favor of .load", :bundler => "< 3" do expect(deprecations).to include "Bundler.environment has been removed in favor of Bundler.load (called at -e:1)" end @@ -109,7 +109,7 @@ RSpec.describe "major deprecations" do bundle "check --path vendor/bundle", :raise_on_error => false end - it "should print a deprecation warning", :bundler => "2" do + it "should print a deprecation warning", :bundler => "< 3" do expect(deprecations).to include( "The `--path` flag is deprecated because it relies on being " \ "remembered across bundler invocations, which bundler will no " \ @@ -118,7 +118,7 @@ RSpec.describe "major deprecations" do ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end context "bundle check --path=" do @@ -131,7 +131,7 @@ RSpec.describe "major deprecations" do bundle "check --path=vendor/bundle", :raise_on_error => false end - it "should print a deprecation warning", :bundler => "2" do + it "should print a deprecation warning", :bundler => "< 3" do expect(deprecations).to include( "The `--path` flag is deprecated because it relies on being " \ "remembered across bundler invocations, which bundler will no " \ @@ -140,7 +140,7 @@ RSpec.describe "major deprecations" do ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end context "bundle cache --all" do @@ -153,7 +153,7 @@ RSpec.describe "major deprecations" do bundle "cache --all", :raise_on_error => false end - it "should print a deprecation warning", :bundler => "2" do + it "should print a deprecation warning", :bundler => "< 3" do expect(deprecations).to include( "The `--all` flag is deprecated because it relies on being " \ "remembered across bundler invocations, which bundler will no " \ @@ -162,7 +162,7 @@ RSpec.describe "major deprecations" do ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end describe "bundle config" do @@ -292,7 +292,7 @@ RSpec.describe "major deprecations" do G end - it "should output a deprecation warning", :bundler => "2" do + it "should output a deprecation warning", :bundler => "< 3" do expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs --all`") end @@ -356,7 +356,7 @@ RSpec.describe "major deprecations" do bundle "install #{flag_name} #{value}" end - it "should print a deprecation warning", :bundler => "2" do + it "should print a deprecation warning", :bundler => "< 3" do expect(deprecations).to include( "The `#{flag_name}` flag is deprecated because it relies on " \ "being remembered across bundler invocations, which bundler " \ @@ -365,7 +365,7 @@ RSpec.describe "major deprecations" do ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end end end @@ -378,7 +378,7 @@ RSpec.describe "major deprecations" do G end - it "shows a deprecation", :bundler => "2" do + it "shows a deprecation", :bundler => "< 3" do expect(deprecations).to include( "Your Gemfile contains multiple primary sources. " \ "Using `source` more than once without a block is a security risk, and " \ @@ -389,7 +389,7 @@ RSpec.describe "major deprecations" do ) end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end context "when Bundler.setup is run in a ruby script" do @@ -422,14 +422,14 @@ RSpec.describe "major deprecations" do RUBY end - it "should print a capistrano deprecation warning", :bundler => "2" do + it "should print a capistrano deprecation warning", :bundler => "< 3" do expect(deprecations).to include("Bundler no longer integrates " \ "with Capistrano, but Capistrano provides " \ "its own integration with Bundler via the " \ "capistrano-bundler gem. Use it instead.") end - pending "should fail with a helpful error", :bundler => "3" + pending "fails with a helpful error", :bundler => "3" end describe Bundler::Dsl do @@ -439,7 +439,7 @@ RSpec.describe "major deprecations" do end context "with github gems" do - it "does not warn about removal", :bundler => "2" do + it "does not warn about removal", :bundler => "< 3" do expect(Bundler.ui).not_to receive(:warn) subject.gem("sparks", :github => "indirect/sparks") github_uri = "https://github.com/indirect/sparks.git" @@ -461,7 +461,7 @@ The :github git source is deprecated, and will be removed in the future. Change end context "with bitbucket gems" do - it "does not warn about removal", :bundler => "2" do + it "does not warn about removal", :bundler => "< 3" do expect(Bundler.ui).not_to receive(:warn) subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails") end @@ -483,7 +483,7 @@ The :bitbucket git source is deprecated, and will be removed in the future. Add end context "with gist gems" do - it "does not warn about removal", :bundler => "2" do + it "does not warn about removal", :bundler => "< 3" do expect(Bundler.ui).not_to receive(:warn) subject.gem("not-really-a-gem", :gist => "1234") end @@ -514,7 +514,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle :show end - it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do + it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do expect(deprecations).to include("use `bundle list` instead of `bundle show`") end @@ -526,7 +526,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle "show --outdated" end - it "prints a deprecation warning informing about its removal", :bundler => "2" do + it "prints a deprecation warning informing about its removal", :bundler => "< 3" do expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") end @@ -538,7 +538,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle "show --verbose" end - it "prints a deprecation warning informing about its removal", :bundler => "2" do + it "prints a deprecation warning informing about its removal", :bundler => "< 3" do expect(deprecations).to include("the `--verbose` flag to `bundle show` was undocumented and will be removed without replacement") end @@ -550,7 +550,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle "show rack" end - it "prints a deprecation warning recommending `bundle info`", :bundler => "2" do + it "prints a deprecation warning recommending `bundle info`", :bundler => "< 3" do expect(deprecations).to include("use `bundle info rack` instead of `bundle show rack`") end @@ -562,7 +562,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle "show --paths" end - it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do + it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do expect(deprecations).to include("use `bundle list` instead of `bundle show --paths`") end @@ -574,7 +574,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle "show rack --paths" end - it "prints deprecation warning recommending `bundle info`", :bundler => "2" do + it "prints deprecation warning recommending `bundle info`", :bundler => "< 3" do expect(deprecations).to include("use `bundle info rack --path` instead of `bundle show rack --paths`") end @@ -587,7 +587,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle "console", :raise_on_error => false end - it "prints a deprecation warning", :bundler => "2" do + it "prints a deprecation warning", :bundler => "< 3" do expect(deprecations).to include \ "bundle console will be replaced by `bin/console` generated by `bundle gem <name>`" end @@ -603,7 +603,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this bundle "viz" end - it "prints a deprecation warning", :bundler => "2" do + it "prints a deprecation warning", :bundler => "< 3" do expect(deprecations).to include "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz" end diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb index 405c786842..2b1e28fa30 100644 --- a/spec/bundler/quality_spec.rb +++ b/spec/bundler/quality_spec.rb @@ -220,7 +220,7 @@ RSpec.describe "The library itself" do gem_list = loaded_gemspec.files - expect(git_list.to_set).to eq(gem_list.to_set) + expect(git_list.sort).to eq(gem_list.sort) end it "does not contain any warnings" do diff --git a/spec/bundler/realworld/double_check_spec.rb b/spec/bundler/realworld/double_check_spec.rb index 0a8f5e4d9e..07697f080e 100644 --- a/spec/bundler/realworld/double_check_spec.rb +++ b/spec/bundler/realworld/double_check_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "double checking sources", :realworld => true, :sometimes => true do +RSpec.describe "double checking sources", :realworld => true do it "finds already-installed gems" do create_file("rails.gemspec", <<-RUBY) Gem::Specification.new do |s| diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb index 0f19cc7842..1925f76c06 100644 --- a/spec/bundler/realworld/edgecases_spec.rb +++ b/spec/bundler/realworld/edgecases_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do +RSpec.describe "real world edgecases", :realworld => true do def rubygems_version(name, requirement) ruby <<-RUBY require "#{spec_dir}/support/artifice/vcr" @@ -64,6 +64,8 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do # from https://github.com/rubygems/bundler/issues/5031 + system_gems "bundler-2.99.0" + gemfile <<-G source "https://rubygems.org" gem 'rails', '~> 4.2.7.1' @@ -189,7 +191,7 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do rails (~> 4.2.7.1) L - bundle "lock --update paperclip" + bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" } expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) end @@ -448,12 +450,219 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do end G + if Bundler.feature_flag.bundler_3_mode? + # Conflicts on bundler version, so fails earlier + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false + expect(out).to display_total_steps_of(435) + else + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } + expect(out).to display_total_steps_of(1025) + end + end + + it "doesn't hang on tricky gemfile" do + skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" + + gemfile <<~G + source 'https://rubygems.org' + + group :development do + gem "puppet-module-posix-default-r2.7", '~> 0.3' + gem "puppet-module-posix-dev-r2.7", '~> 0.3' + gem "beaker-rspec" + gem "beaker-puppet" + gem "beaker-docker" + gem "beaker-puppet_install_helper" + gem "beaker-module_install_helper" + end + G + + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } + + if Bundler.feature_flag.bundler_3_mode? + expect(out).to display_total_steps_of(890) + else + expect(out).to display_total_steps_of(891) + end + end + + it "doesn't hang on nix gemfile" do + skip "Only for ruby 3.0.0" if RUBY_VERSION != "3.0.0" + + gemfile <<~G + source "https://rubygems.org" do + gem "addressable" + gem "atk" + gem "awesome_print" + gem "bacon" + gem "byebug" + gem "cairo" + gem "cairo-gobject" + gem "camping" + gem "charlock_holmes" + gem "cld3" + gem "cocoapods" + gem "cocoapods-acknowledgements" + gem "cocoapods-art" + gem "cocoapods-bin" + gem "cocoapods-browser" + gem "cocoapods-bugsnag" + gem "cocoapods-check" + gem "cocoapods-clean" + gem "cocoapods-clean_build_phases_scripts" + gem "cocoapods-core" + gem "cocoapods-coverage" + gem "cocoapods-deintegrate" + gem "cocoapods-dependencies" + gem "cocoapods-deploy" + gem "cocoapods-downloader" + gem "cocoapods-expert-difficulty" + gem "cocoapods-fix-react-native" + gem "cocoapods-generate" + gem "cocoapods-git_url_rewriter" + gem "cocoapods-keys" + gem "cocoapods-no-dev-schemes" + gem "cocoapods-open" + gem "cocoapods-packager" + gem "cocoapods-playgrounds" + gem "cocoapods-plugins" + gem "cocoapods-prune-localizations" + gem "cocoapods-rome" + gem "cocoapods-search" + gem "cocoapods-sorted-search" + gem "cocoapods-static-swift-framework" + gem "cocoapods-stats" + gem "cocoapods-tdfire-binary" + gem "cocoapods-testing" + gem "cocoapods-trunk" + gem "cocoapods-try" + gem "cocoapods-try-release-fix" + gem "cocoapods-update-if-you-dare" + gem "cocoapods-whitelist" + gem "cocoapods-wholemodule" + gem "coderay" + gem "concurrent-ruby" + gem "curb" + gem "curses" + gem "daemons" + gem "dep-selector-libgecode" + gem "digest-sha3" + gem "domain_name" + gem "do_sqlite3" + gem "ethon" + gem "eventmachine" + gem "excon" + gem "faraday" + gem "ffi" + gem "ffi-rzmq-core" + gem "fog-dnsimple" + gem "gdk_pixbuf2" + gem "gio2" + gem "gitlab-markup" + gem "glib2" + gem "gpgme" + gem "gtk2" + gem "hashie" + gem "highline" + gem "hike" + gem "hitimes" + gem "hpricot" + gem "httpclient" + gem "http-cookie" + gem "iconv" + gem "idn-ruby" + gem "jbuilder" + gem "jekyll" + gem "jmespath" + gem "jwt" + gem "libv8" + gem "libxml-ruby" + gem "magic" + gem "markaby" + gem "method_source" + gem "mini_magick" + gem "msgpack" + gem "mysql2" + gem "ncursesw" + gem "netrc" + gem "net-scp" + gem "net-ssh" + gem "nokogiri" + gem "opus-ruby" + gem "ovirt-engine-sdk" + gem "pango" + gem "patron" + gem "pcaprub" + gem "pg" + gem "pry" + gem "pry-byebug" + gem "pry-doc" + gem "public_suffix" + gem "puma" + gem "rails" + gem "rainbow" + gem "rbnacl" + gem "rb-readline" + gem "re2" + gem "redis" + gem "redis-rack" + gem "rest-client" + gem "rmagick" + gem "rpam2" + gem "rspec" + gem "rubocop" + gem "rubocop-performance" + gem "ruby-libvirt" + gem "ruby-lxc" + gem "ruby-progressbar" + gem "ruby-terminfo" + gem "ruby-vips" + gem "rubyzip" + gem "rugged" + gem "sassc" + gem "scrypt" + gem "semian" + gem "sequel" + gem "sequel_pg" + gem "simplecov" + gem "sinatra" + gem "slop" + gem "snappy" + gem "sqlite3" + gem "taglib-ruby" + gem "thrift" + gem "tilt" + gem "tiny_tds" + gem "treetop" + gem "typhoeus" + gem "tzinfo" + gem "unf_ext" + gem "uuid4r" + gem "whois" + gem "zookeeper" + end + G + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (2492 steps)") + expect(out).to display_total_steps_of(1874) else - expect(out).to include("BUNDLER: Finished resolution (2722 steps)") + expect(out).to display_total_steps_of(1922) + end + end + + private + + RSpec::Matchers.define :display_total_steps_of do |expected_steps| + match do |out| + out.include?("BUNDLER: Finished resolution (#{expected_steps} steps)") + end + + failure_message do |out| + actual_steps = out.scan(/BUNDLER: Finished resolution \((\d+) steps\)/).first.first + + "Expected resolution to finish in #{expected_steps} steps, but took #{actual_steps}" end end end diff --git a/spec/bundler/realworld/parallel_spec.rb b/spec/bundler/realworld/parallel_spec.rb index 2a5154ffbf..97c0e0cab4 100644 --- a/spec/bundler/realworld/parallel_spec.rb +++ b/spec/bundler/realworld/parallel_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "parallel", :realworld => true, :sometimes => true do +RSpec.describe "parallel", :realworld => true do it "installs" do gemfile <<-G source "https://rubygems.org" diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb new file mode 100644 index 0000000000..518da2800b --- /dev/null +++ b/spec/bundler/realworld/slow_perf_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "bundle install with complex dependencies", :realworld => true do + it "resolves quickly" do + start_time = Time.now + + install_gemfile <<-G + source 'https://rubygems.org' + + gem "actionmailer" + gem "mongoid", ">= 0.10.2" + G + + duration = Time.now - start_time + + expect(duration.to_f).to be < 120 # seconds + end +end diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb index 57897f89b4..ee62dc3577 100644 --- a/spec/bundler/resolver/basic_spec.rb +++ b/spec/bundler/resolver/basic_spec.rb @@ -176,7 +176,7 @@ Bundler could not find compatible versions for gem "a": deps = [] @deps.each do |d| - deps << Bundler::DepProxy.new(d, "ruby") + deps << Bundler::DepProxy.get_proxy(d, "ruby") end should_resolve_and_include %w[foo-1.0.0 bar-1.0.0], [[]] diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb index 415c5458df..bc4081f8b5 100644 --- a/spec/bundler/resolver/platform_spec.rb +++ b/spec/bundler/resolver/platform_spec.rb @@ -28,6 +28,23 @@ RSpec.describe "Resolving platform craziness" do end end + it "resolves multiplatform gems with redundant platforms correctly" do + @index = build_index do + gem "zookeeper", "1.4.11" + gem "zookeeper", "1.4.11", "java" do + dep "slyphon-log4j", "= 1.2.15" + dep "slyphon-zookeeper_jar", "= 3.3.5" + end + gem "slyphon-log4j", "1.2.15" + gem "slyphon-zookeeper_jar", "3.3.5", "java" + end + + dep "zookeeper" + platforms "java", "ruby", "universal-java-11" + + should_resolve_as %w[zookeeper-1.4.11 zookeeper-1.4.11-java slyphon-log4j-1.2.15 slyphon-zookeeper_jar-3.3.5-java] + end + it "takes the latest ruby gem, even if an older platform specific version is available" do @index = build_index do gem "foo", "1.0.0" @@ -120,6 +137,157 @@ RSpec.describe "Resolving platform craziness" do should_resolve_as %w[foo-1.1.0] end + it "doesn't include gems not needed for none of the platforms" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + end + + dep "empyrean", "0.1.0" + dep "pry" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "includes gems needed for at least one platform" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + + gem "extra", "1.0.0" do + dep "ffi", ">= 0" + end + end + + dep "empyrean", "0.1.0" + dep "pry" + dep "extra" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "includes gems needed for at least one platform even when the platform specific requirement is processed earlier than the generic requirement" do + @index = build_index do + gem "empyrean", "0.1.0" + gem "coderay", "1.1.2" + gem "method_source", "0.9.0" + + gem "spoon", "0.0.6" do + dep "ffi", ">= 0" + end + + gem "pry", "0.11.3", "java" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + dep "spoon", "~> 0.0" + end + + gem "pry", "0.11.3" do + dep "coderay", "~> 1.1.0" + dep "method_source", "~> 0.9.0" + end + + gem "ffi", "1.9.23", "java" + gem "ffi", "1.9.23" + + gem "extra", "1.0.0" do + dep "extra2", ">= 0" + end + + gem "extra2", "1.0.0" do + dep "extra3", ">= 0" + end + + gem "extra3", "1.0.0" do + dep "ffi", ">= 0" + end + end + + dep "empyrean", "0.1.0" + dep "pry" + dep "extra" + + platforms "ruby", "java" + + should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 extra2-1.0.0 extra3-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6] + end + + it "properly adds platforms when platform requirements come from different dependencies" do + @index = build_index do + gem "ffi", "1.9.14" + gem "ffi", "1.9.14", "universal-mingw32" + + gem "gssapi", "0.1" + gem "gssapi", "0.2" + gem "gssapi", "0.3" + gem "gssapi", "1.2.0" do + dep "ffi", ">= 1.0.1" + end + + gem "mixlib-shellout", "2.2.6" + gem "mixlib-shellout", "2.2.6", "universal-mingw32" do + dep "win32-process", "~> 0.8.2" + end + + # we need all these versions to get the sorting the same as it would be + # pulling from rubygems.org + %w[0.8.3 0.8.2 0.8.1 0.8.0].each do |v| + gem "win32-process", v do + dep "ffi", ">= 1.0.0" + end + end + end + + dep "mixlib-shellout" + dep "gssapi" + + platforms "universal-mingw32", "ruby" + + should_resolve_as %w[ffi-1.9.14 ffi-1.9.14-universal-mingw32 gssapi-1.2.0 mixlib-shellout-2.2.6 mixlib-shellout-2.2.6-universal-mingw32 win32-process-0.8.3] + end + describe "with mingw32" do before :each do @index = build_index do diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index b46da20096..bd136ddcd7 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -46,8 +46,6 @@ RSpec.describe "bundler/inline#gemfile" do end it "requires the gems" do - skip "gems not found" if Gem.win_platform? - script <<-RUBY gemfile do path "#{lib_path}" do @@ -94,8 +92,6 @@ RSpec.describe "bundler/inline#gemfile" do end it "lets me use my own ui object" do - skip "prints just one CONFIRMED" if Gem.win_platform? - script <<-RUBY, :artifice => "endpoint" require '#{lib_dir}/bundler' class MyBundlerUI < Bundler::UI::Silent diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb index 215ba8628f..154d967e12 100644 --- a/spec/bundler/runtime/platform_spec.rb +++ b/spec/bundler/runtime/platform_spec.rb @@ -57,6 +57,89 @@ RSpec.describe "Bundler.setup with multi platform stuff" do expect(the_bundle).to include_gems "nokogiri 1.4.2" end + it "will keep both platforms when both ruby and a specific ruby platform are locked and the bundle is unlocked" do + build_repo4 do + build_gem "nokogiri", "1.11.1" do |s| + s.add_dependency "mini_portile2", "~> 2.5.0" + s.add_dependency "racc", "~> 1.4" + end + + build_gem "nokogiri", "1.11.1" do |s| + s.platform = Bundler.local_platform + s.add_dependency "racc", "~> 1.4" + end + + build_gem "mini_portile2", "2.5.0" + build_gem "racc", "1.5.2" + end + + good_lockfile = <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + mini_portile2 (2.5.0) + nokogiri (1.11.1) + mini_portile2 (~> 2.5.0) + racc (~> 1.4) + nokogiri (1.11.1-#{Bundler.local_platform}) + racc (~> 1.4) + racc (1.5.2) + + PLATFORMS + ruby + #{Bundler.local_platform} + + DEPENDENCIES + nokogiri (~> 1.11) + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "nokogiri", "~> 1.11" + G + + lockfile good_lockfile + + bundle "update nokogiri" + + expect(lockfile).to eq(good_lockfile) + end + + it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "nokogiri" + G + + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + nokogiri (1.4.2) + nokogiri (1.4.2-java) + weakling (>= 0.0.3) + weakling (0.0.3) + + PLATFORMS + java + ruby + + DEPENDENCIES + nokogiri + + BUNDLED WITH + 2.1.4 + G + + bundle "install" + + expect(out).to include("Fetching nokogiri 1.4.2 (java)") + expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA" + end + it "will add the resolve for the current platform" do lockfile <<-G GEM @@ -84,9 +167,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100" end - it "allows specifying only-ruby-platform" do - simulate_platform "java" - + it "allows specifying only-ruby-platform on jruby", :jruby do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "nokogiri" @@ -100,6 +181,29 @@ RSpec.describe "Bundler.setup with multi platform stuff" do expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY" end + it "allows specifying only-ruby-platform" do + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "nokogiri" + gem "platform_specific" + G + + bundle "config set force_ruby_platform true" + + bundle "install" + + expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY" + end + + it "doesn't pull platform specific gems on truffleruby", :truffleruby do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "platform_specific" + G + + expect(the_bundle).to include_gems "platform_specific 1.0 RUBY" + end + it "allows specifying only-ruby-platform on windows with dependency platforms" do simulate_windows do install_gemfile <<-G diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb index e2bed00a7f..a0036df39e 100644 --- a/spec/bundler/runtime/setup_spec.rb +++ b/spec/bundler/runtime/setup_spec.rb @@ -1252,7 +1252,7 @@ end exempts << "fiddle" if Gem.win_platform? && Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7") exempts << "uri" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7") exempts << "pathname" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0") - exempts << "set" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0") + exempts << "set" unless Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.2.6") exempts << "tsort" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0") exempts end @@ -1334,36 +1334,8 @@ end expect(out).to eq("The Gemfile's dependencies are satisfied") end - # bundler respects paths specified directly in RUBYLIB or RUBYOPT, and - # that happens when running ruby from the ruby-core setup. To - # workaround, we manually remove those for these tests when they would - # override the default gem. - def load_path_exclusions_hack_for(name) - if ruby_core? - if ENV.key?("PWD") - # .ext/common is relative from build directory - ext_folder = Pathname(ENV["PWD"]) + ".ext/common" - else - ext_folder = source_root.join(".ext/common") - end - require_name = name.tr("-", "/") - if File.exist?(ext_folder.join("#{require_name}.rb")) - { :exclude_from_load_path => ext_folder.to_s } - else - lib_folder = source_lib_dir - if File.exist?(lib_folder.join("#{require_name}.rb")) - { :exclude_from_load_path => lib_folder.to_s } - else - {} - end - end - else - {} - end - end - Gem::Specification.select(&:default_gem?).map(&:name).each do |g| - it "activates newer versions of #{g}" do + it "activates newer versions of #{g}", :ruby_repo do skip if exemptions.include?(g) build_repo4 do @@ -1375,11 +1347,10 @@ end gem "#{g}", "999999" G - opts = { :env => { "RUBYOPT" => activation_warning_hack_rubyopt } } - expect(the_bundle).to include_gem("#{g} 999999", opts.merge(load_path_exclusions_hack_for(g))) + expect(the_bundle).to include_gem("#{g} 999999", :env => { "RUBYOPT" => activation_warning_hack_rubyopt }) end - it "activates older versions of #{g}" do + it "activates older versions of #{g}", :ruby_repo do skip if exemptions.include?(g) build_repo4 do @@ -1391,8 +1362,7 @@ end gem "#{g}", "0.0.0.a" G - opts = { :env => { "RUBYOPT" => activation_warning_hack_rubyopt } } - expect(the_bundle).to include_gem("#{g} 0.0.0.a", opts.merge(load_path_exclusions_hack_for(g))) + expect(the_bundle).to include_gem("#{g} 0.0.0.a", :env => { "RUBYOPT" => activation_warning_hack_rubyopt }) end end end diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb index 7723c85ce6..a72a1f5255 100644 --- a/spec/bundler/spec_helper.rb +++ b/spec/bundler/spec_helper.rb @@ -23,7 +23,6 @@ require_relative "support/indexes" require_relative "support/matchers" require_relative "support/permissions" require_relative "support/platforms" -require_relative "support/sometimes" require_relative "support/sudo" $debug = false @@ -105,7 +104,7 @@ RSpec.configure do |config| all_output = all_commands_output if example.exception && !all_output.empty? - message = example.exception.message + all_output + message = all_output + "\n" + example.exception.message (class << example.exception; self; end).send(:define_method, :message) do message end diff --git a/spec/bundler/support/builders.rb b/spec/bundler/support/builders.rb index 02a2c0f659..c76c3f505e 100644 --- a/spec/bundler/support/builders.rb +++ b/spec/bundler/support/builders.rb @@ -547,9 +547,11 @@ module Spec class GitBuilder < LibBuilder def _build(options) + default_branch = options[:default_branch] || "master" path = options[:path] || _default_path source = options[:source] || "git@#{path}" super(options.merge(:path => path, :source => source)) + @context.git("config --global init.defaultBranch #{default_branch}", path) @context.git("init", path) @context.git("add *", path) @context.git("config user.email lol@wut.com", path) diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb index b1978e44e6..0c1f27e470 100644 --- a/spec/bundler/support/filters.rb +++ b/spec/bundler/support/filters.rb @@ -32,7 +32,8 @@ RSpec.configure do |config| config.filter_run_excluding :no_color_tty => Gem.win_platform? || !ENV["GITHUB_ACTION"].nil? config.filter_run_excluding :permissions => Gem.win_platform? config.filter_run_excluding :readline => Gem.win_platform? - config.filter_run_excluding :jruby => RUBY_PLATFORM != "java" + config.filter_run_excluding :jruby => RUBY_ENGINE != "jruby" + config.filter_run_excluding :truffleruby => RUBY_ENGINE != "truffleruby" config.filter_run_when_matching :focus unless ENV["CI"] end diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb index c4018eb818..a7cc1ce810 100644 --- a/spec/bundler/support/helpers.rb +++ b/spec/bundler/support/helpers.rb @@ -275,14 +275,12 @@ module Spec def install_gemfile(*args) gemfile(*args) opts = args.last.is_a?(Hash) ? args.last : {} - opts[:retry] ||= 0 bundle :install, opts end def lock_gemfile(*args) gemfile(*args) opts = args.last.is_a?(Hash) ? args.last : {} - opts[:retry] ||= 0 bundle :lock, opts end diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb index 7440523fc9..1f3c4ddaa6 100644 --- a/spec/bundler/support/indexes.rb +++ b/spec/bundler/support/indexes.rb @@ -22,7 +22,7 @@ module Spec @deps.each do |d| @platforms.each do |p| source_requirements[d.name] = d.source = default_source - deps << Bundler::DepProxy.new(d, p) + deps << Bundler::DepProxy.get_proxy(d, p) end end source_requirements ||= {} @@ -30,7 +30,7 @@ module Spec args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter args[2] ||= [] # additional_base_requirements args[3] ||= @platforms # platforms - Bundler::Resolver.resolve(deps, @index, source_requirements, *args) + Bundler::Resolver.resolve(deps, source_requirements, *args) end def should_resolve_as(specs) diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb index 6c9ab0d410..5d129ed849 100644 --- a/spec/bundler/support/matchers.rb +++ b/spec/bundler/support/matchers.rb @@ -115,7 +115,6 @@ module Spec opts = names.last.is_a?(Hash) ? names.pop : {} source = opts.delete(:source) groups = Array(opts[:groups]) - exclude_from_load_path = opts.delete(:exclude_from_load_path) opts[:raise_on_error] = false groups << opts @errors = names.map do |name| @@ -123,11 +122,6 @@ module Spec require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/") version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name) code = [] - if exclude_from_load_path - code << "exclude_from_load_path = File.expand_path('#{exclude_from_load_path}')" - code << "$LOAD_PATH.delete_if { |path| File.expand_path(path) == exclude_from_load_path }" - end - code << "$LOADED_FEATURES.delete_if { |feature| File.basename(feature, '.*') == '#{require_path}' }" code << "require '#{require_path}.rb'" code << "puts #{version_const}" run code.join("; "), *groups @@ -151,23 +145,34 @@ module Spec match_when_negated do opts = names.last.is_a?(Hash) ? names.pop : {} - groups = Array(opts[:groups]) || [] + groups = Array(opts.delete(:groups)).map(&:inspect).join(", ") opts[:raise_on_error] = false @errors = names.map do |name| name, version = name.split(/\s+/, 2) - run <<-R, *(groups + [opts]) + ruby <<-R, opts + begin + require '#{lib_dir}/bundler' + Bundler.setup(#{groups}) + rescue Bundler::GemNotFound, Bundler::GitError + exit 0 + end + begin require '#{name}' - puts #{Spec::Builders.constantize(name)} + name_constant = '#{Spec::Builders.constantize(name)}' + if #{version.nil?} || name_constant == '#{version}' + exit 64 + else + exit 0 + end rescue LoadError, NameError - puts "WIN" + exit 0 end R - next if out == "WIN" + next if exitstatus == 0 + next "command to check version of #{name} installed failed" unless exitstatus == 64 next "expected #{name} to not be installed, but it was" if version.nil? - if Gem::Version.new(out) == Gem::Version.new(version) - next "expected #{name} (#{version}) not to be installed, but it was" - end + next "expected #{name} (#{version}) not to be installed, but it was" end.compact @errors.empty? diff --git a/spec/bundler/support/rubygems_version_manager.rb b/spec/bundler/support/rubygems_version_manager.rb index ac02021cff..c2e5a5f484 100644 --- a/spec/bundler/support/rubygems_version_manager.rb +++ b/spec/bundler/support/rubygems_version_manager.rb @@ -78,6 +78,7 @@ class RubygemsVersionManager end def rubygems_unrequire_needed? + require "rubygems" !$LOADED_FEATURES.include?(local_copy_path.join("lib/rubygems.rb").to_s) end diff --git a/spec/bundler/support/sometimes.rb b/spec/bundler/support/sometimes.rb deleted file mode 100644 index 65a95ed59c..0000000000 --- a/spec/bundler/support/sometimes.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module Sometimes - def run_with_retries(example_to_run, retries) - example = RSpec.current_example - example.metadata[:retries] ||= retries - - retries.times do |t| - example.metadata[:retried] = t + 1 - example.instance_variable_set(:@exception, nil) - example_to_run.run - break unless example.exception - end - - if e = example.exception - new_exception = e.exception(e.message + "[Retried #{retries} times]") - new_exception.set_backtrace e.backtrace - example.instance_variable_set(:@exception, new_exception) - end - end -end - -RSpec.configure do |config| - config.include Sometimes - config.alias_example_to :sometimes, :sometimes => true - config.add_setting :sometimes_retry_count, :default => 5 - - config.around(:each, :sometimes => true) do |example| - retries = example.metadata[:retries] || RSpec.configuration.sometimes_retry_count - run_with_retries(example, retries) - end - - config.after(:suite) do - message = proc do |color, text| - colored = RSpec::Core::Formatters::ConsoleCodes.wrap(text, color) - notification = RSpec::Core::Notifications::MessageNotification.new(colored) - formatter = RSpec.configuration.formatters.first - formatter.message(notification) if formatter.respond_to?(:message) - end - - retried_examples = RSpec.world.example_groups.map do |g| - g.descendants.map do |d| - d.filtered_examples.select do |e| - e.metadata[:sometimes] && e.metadata.fetch(:retried, 1) > 1 - end - end - end.flatten - - message.call(retried_examples.empty? ? :green : :yellow, "\n\nRetried examples: #{retried_examples.count}") - - retried_examples.each do |e| - message.call(:cyan, " #{e.full_description}") - path = RSpec::Core::Metadata.relative_path(e.location) - message.call(:cyan, " [#{e.metadata[:retried]}/#{e.metadata[:retries]}] " + path) - end - end -end |