diff options
Diffstat (limited to 'spec/bundler')
-rw-r--r-- | spec/bundler/commands/lock_spec.rb | 89 | ||||
-rw-r--r-- | spec/bundler/commands/newgem_spec.rb | 112 | ||||
-rw-r--r-- | spec/bundler/commands/update_spec.rb | 10 | ||||
-rw-r--r-- | spec/bundler/install/gemfile/git_spec.rb | 23 | ||||
-rw-r--r-- | spec/bundler/install/gemfile/path_spec.rb | 63 | ||||
-rw-r--r-- | spec/bundler/lock/git_spec.rb | 38 | ||||
-rw-r--r-- | spec/bundler/support/hax.rb | 19 | ||||
-rw-r--r-- | spec/bundler/support/matchers.rb | 2 |
8 files changed, 332 insertions, 24 deletions
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index ed0c3dfadf..c80b9dc646 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -752,5 +752,94 @@ RSpec.describe "bundle lock" do version solving has failed. ERR end + + it "is able to display some explanation on crazy irresolvable cases" do + build_repo4 do + build_gem "activeadmin", "2.13.1" do |s| + s.add_dependency "ransack", "= 3.1.0" + end + + # Activemodel is missing as a dependency in lockfile + build_gem "ransack", "3.1.0" do |s| + s.add_dependency "activemodel", ">= 6.0.4" + s.add_dependency "activesupport", ">= 6.0.4" + end + + %w[6.0.4 7.0.2.3 7.0.3.1 7.0.4].each do |version| + build_gem "activesupport", version + + # Activemodel is only available on 6.0.4 + if version == "6.0.4" + build_gem "activemodel", version do |s| + s.add_dependency "activesupport", version + end + end + + build_gem "rails", version do |s| + # Depednencies of Rails 7.0.2.3 are in reverse order + if version == "7.0.2.3" + s.add_dependency "activesupport", version + s.add_dependency "activemodel", version + else + s.add_dependency "activemodel", version + s.add_dependency "activesupport", version + end + end + end + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gem "rails", ">= 7.0.2.3" + gem "activeadmin", "= 2.13.1" + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + activeadmin (2.13.1) + ransack (= 3.1.0) + ransack (3.1.0) + activemodel (>= 6.0.4) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + activeadmin (= 2.13.1) + ransack (= 3.1.0) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "lock", :raise_on_error => false + + expect(err).to eq <<~ERR.strip + Could not find compatible versions + + Because every version of activemodel depends on activesupport = 6.0.4 + and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3, + every version of activemodel is incompatible with rails >= 7.0.2.3, < 7.0.3.1. + And because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3, + rails >= 7.0.2.3, < 7.0.3.1 is forbidden. + (1) So, because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1 + and rails >= 7.0.4 depends on activemodel = 7.0.4, + rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4. + + Because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3 + and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1, + rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 or activesupport = 7.0.3.1. + And because rails >= 7.0.4 depends on activesupport = 7.0.4 + and every version of activemodel depends on activesupport = 6.0.4, + activemodel != 7.0.2.3 is incompatible with rails >= 7.0.2.3. + And because rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4 (1), + rails >= 7.0.2.3 is forbidden. + So, because Gemfile depends on rails >= 7.0.2.3, + version solving has failed. + ERR + end end end diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb index 15a75577a1..5827f7380c 100644 --- a/spec/bundler/commands/newgem_spec.rb +++ b/spec/bundler/commands/newgem_spec.rb @@ -310,28 +310,28 @@ RSpec.describe "bundle gem" do expect(last_command).to be_success end - it "has no rubocop offenses when using --ext and --linter=rubocop flag", :readline do + it "has no rubocop offenses when using --ext=c and --linter=rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? bundle "gem #{gem_name} --ext=c --linter=rubocop" bundle_exec_rubocop expect(last_command).to be_success end - it "has no rubocop offenses when using --ext, --test=minitest, and --linter=rubocop flag", :readline do + it "has no rubocop offenses when using --ext=c, --test=minitest, and --linter=rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? bundle "gem #{gem_name} --ext=c --test=minitest --linter=rubocop" bundle_exec_rubocop expect(last_command).to be_success end - it "has no rubocop offenses when using --ext, --test=rspec, and --linter=rubocop flag", :readline do + it "has no rubocop offenses when using --ext=c, --test=rspec, and --linter=rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? bundle "gem #{gem_name} --ext=c --test=rspec --linter=rubocop" bundle_exec_rubocop expect(last_command).to be_success end - it "has no rubocop offenses when using --ext, --ext=test-unit, and --linter=rubocop flag", :readline do + it "has no rubocop offenses when using --ext=c, --test=test-unit, and --linter=rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? bundle "gem #{gem_name} --ext=c --test=test-unit --linter=rubocop" bundle_exec_rubocop @@ -345,6 +345,42 @@ RSpec.describe "bundle gem" do expect(last_command).to be_success end + it "has no rubocop offenses when using --ext=rust and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version + + bundle "gem #{gem_name} --ext=rust --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no rubocop offenses when using --ext=rust, --test=minitest, and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version + + bundle "gem #{gem_name} --ext=rust --test=minitest --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no rubocop offenses when using --ext=rust, --test=rspec, and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version + + bundle "gem #{gem_name} --ext=rust --test=rspec --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + + it "has no rubocop offenses when using --ext=rust, --test=test-unit, and --linter=rubocop flag", :readline do + skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? + skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version + + bundle "gem #{gem_name} --ext=rust --test=test-unit --linter=rubocop" + bundle_exec_rubocop + expect(last_command).to be_success + end + shared_examples_for "CI config is absent" do it "does not create any CI files" do expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist @@ -1336,12 +1372,15 @@ RSpec.describe "bundle gem" do context "is deprecated", :bundler => "< 3" do it "prints deprecation when used after gem name" do bundle ["gem", "--ext", gem_name].compact.join(" ") - expect(err).to include "[DEPRECATED] Option `--ext` without explicit value is deprecated." + expect(err).to include "[DEPRECATED]" + expect(err).to include "`--ext` with no arguments has been deprecated" expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist end it "prints deprecation when used before gem name" do bundle ["gem", gem_name, "--ext"].compact.join(" ") + expect(err).to include "[DEPRECATED]" + expect(err).to include "`--ext` with no arguments has been deprecated" expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist end end @@ -1364,8 +1403,11 @@ RSpec.describe "bundle gem" do expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist end - it "includes rake-compiler" do + it "includes rake-compiler, but no Rust related changes" do expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"') + + expect(bundled_app("#{gem_name}/Gemfile").read).to_not include('gem "rb_sys"') + expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to_not include('spec.required_rubygems_version = ">= ') end it "depends on compile task for build" do @@ -1387,6 +1429,64 @@ RSpec.describe "bundle gem" do expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile) end end + + context "--ext parameter set with rust and old RubyGems" do + it "fails in friendly way" do + if ::Gem::Version.new("3.3.11") <= ::Gem.rubygems_version + skip "RubyGems compatible with Rust builder" + end + + expect do + bundle ["gem", gem_name, "--ext=rust"].compact.join(" ") + end.to raise_error(RuntimeError, /too old to build Rust extension/) + end + end + + context "--ext parameter set with rust" do + let(:flags) { "--ext=rust" } + + before do + skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version + + bundle ["gem", gem_name, flags].compact.join(" ") + end + + it "is not deprecated" do + expect(err).not_to include "[DEPRECATED] Option `--ext` without explicit value is deprecated." + end + + it "builds ext skeleton" do + expect(bundled_app("#{gem_name}/Cargo.toml")).to exist + expect(bundled_app("#{gem_name}/ext/#{gem_name}/Cargo.toml")).to exist + expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist + expect(bundled_app("#{gem_name}/ext/#{gem_name}/src/lib.rs")).to exist + end + + it "includes rake-compiler, rb_sys gems and required_rubygems_version constraint" do + expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"') + expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rb_sys"') + expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.required_rubygems_version = ">= ') + end + + it "depends on compile task for build" do + rakefile = strip_whitespace <<-RAKEFILE + # frozen_string_literal: true + + require "bundler/gem_tasks" + require "rake/extensiontask" + + task build: :compile + + Rake::ExtensionTask.new("#{gem_name}") do |ext| + ext.lib_dir = "lib/#{gem_name}" + end + + task default: :compile + RAKEFILE + + expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile) + end + end end context "gem naming with dashed", :readline do diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index 583e2aa41b..8c7b9c13c8 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -1310,21 +1310,19 @@ RSpec.describe "bundle update --bundler" do end it "updates the bundler version in the lockfile even if the latest version is not installed", :ruby_repo, :realworld do - skip "ruby-head has a default Bundler version too high for this spec to work" if RUBY_PATCHLEVEL == -1 - pristine_system_gems "bundler-2.3.9" build_repo4 do build_gem "rack", "1.0" end - install_gemfile <<-G + install_gemfile <<-G, :env => { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" } source "#{file_uri_for(gem_repo4)}" gem "rack" G lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9") - bundle :update, :bundler => true, :artifice => "vcr", :verbose => true + bundle :update, :bundler => true, :artifice => "vcr", :verbose => true, :env => { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" } # Only updates properly on modern RubyGems. @@ -1356,15 +1354,13 @@ RSpec.describe "bundle update --bundler" do end it "errors if the explicit target version does not exist", :realworld do - skip "ruby-head has a default Bundler version too high for this spec to work" if RUBY_PATCHLEVEL == -1 - pristine_system_gems "bundler-2.3.9" build_repo4 do build_gem "rack", "1.0" end - install_gemfile <<-G + install_gemfile <<-G, :env => { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" } source "#{file_uri_for(gem_repo4)}" gem "rack" G diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb index 7d263a2fe5..6a9532332c 100644 --- a/spec/bundler/install/gemfile/git_spec.rb +++ b/spec/bundler/install/gemfile/git_spec.rb @@ -235,6 +235,29 @@ RSpec.describe "bundle install with git sources" do G end + it "works when a tag that does not look like a commit hash is used as the value of :ref" do + build_git "foo" + @remote = build_git("bar", :bare => true) + update_git "foo", :remote => file_uri_for(@remote.path) + update_git "foo", :push => "main" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'foo', :git => "#{@remote.path}" + G + + # Create a new tag on the remote that needs fetching + update_git "foo", :tag => "v1.0.0" + update_git "foo", :push => "v1.0.0" + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'foo', :git => "#{@remote.path}", :ref => "v1.0.0" + G + + expect(err).to be_empty + end + it "works when the revision is a non-head ref" do # want to ensure we don't fallback to main update_git "foo", :path => lib_path("foo-1.0") do |s| diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb index 515901064f..9ef1c879f8 100644 --- a/spec/bundler/install/gemfile/path_spec.rb +++ b/spec/bundler/install/gemfile/path_spec.rb @@ -92,14 +92,12 @@ RSpec.describe "bundle install with explicit source paths" do build_lib "demo", :path => lib_path("demo") build_lib "aaa", :path => lib_path("demo/aaa") - gemfile = <<-G + gemfile lib_path("demo/Gemfile"), <<-G source "#{file_uri_for(gem_repo1)}" gemspec gem "aaa", :path => "./aaa" G - File.open(lib_path("demo/Gemfile"), "w") {|f| f.puts gemfile } - lockfile = <<~L PATH remote: . @@ -314,18 +312,67 @@ RSpec.describe "bundle install with explicit source paths" do s.add_dependency "rack", "1.0" end - gemfile = <<-G + gemfile lib_path("foo/Gemfile"), <<-G source "#{file_uri_for(gem_repo1)}" gemspec G - File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts gemfile } - bundle "install", :dir => lib_path("foo") expect(the_bundle).to include_gems "foo 1.0", :dir => lib_path("foo") expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("foo") end + it "does not unlock dependencies of path sources" do + build_repo4 do + build_gem "graphql", "2.0.15" + build_gem "graphql", "2.0.16" + end + + build_lib "foo", "0.1.0", :path => lib_path("foo") do |s| + s.add_dependency "graphql", "~> 2.0" + end + + gemfile_path = lib_path("foo/Gemfile") + + gemfile gemfile_path, <<-G + source "#{file_uri_for(gem_repo4)}" + gemspec + G + + lockfile_path = lib_path("foo/Gemfile.lock") + + original_lockfile = <<~L + PATH + remote: . + specs: + foo (0.1.0) + graphql (~> 2.0) + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + graphql (2.0.15) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + + lockfile lockfile_path, original_lockfile + + build_lib "foo", "0.1.1", :path => lib_path("foo") do |s| + s.add_dependency "graphql", "~> 2.0" + end + + bundle "install", :dir => lib_path("foo") + expect(lockfile_path).to read_as(original_lockfile.gsub("foo (0.1.0)", "foo (0.1.1)")) + end + it "supports gemspec syntax with an alternative path" do build_lib "foo", "1.0", :path => lib_path("foo") do |s| s.add_dependency "rack", "1.0" @@ -791,13 +838,11 @@ 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 build_lib "private_lib", "2.2", :path => lib_path("private_lib") - gemfile = <<-G + gemfile lib_path("private_lib/Gemfile"), <<-G source "http://localgemserver.test" gemspec gem 'rack' G - File.open(lib_path("private_lib/Gemfile"), "w") {|f| f.puts gemfile } - bundle :install, :env => { "DEBUG" => "1" }, :artifice => "endpoint", :dir => lib_path("private_lib") expect(out).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=rack$}) expect(out).not_to match(/^HTTP GET.*private_lib/) diff --git a/spec/bundler/lock/git_spec.rb b/spec/bundler/lock/git_spec.rb index df9d71fdd6..dfcbb645b1 100644 --- a/spec/bundler/lock/git_spec.rb +++ b/spec/bundler/lock/git_spec.rb @@ -52,6 +52,44 @@ RSpec.describe "bundle lock with git gems" do expect(err).to be_empty end + it "properly fetches a git source locked to an unreachable ref" do + # Create a commit and make it unreachable + git "checkout -b foo ", lib_path("foo-1.0") + unreachable_sha = update_git("foo").ref_for("HEAD") + git "checkout main ", lib_path("foo-1.0") + git "branch -D foo ", lib_path("foo-1.0") + + gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem 'foo', :git => "#{lib_path("foo-1.0")}" + G + + lockfile <<-L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{unreachable_sha} + specs: + foo (1.0) + + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install" + + expect(err).to be_empty + end + it "provides correct #full_gem_path" do run <<-RUBY puts Bundler.rubygems.find_name('foo').first.full_gem_path diff --git a/spec/bundler/support/hax.rb b/spec/bundler/support/hax.rb index ad7a6e0de9..c7fe3637cc 100644 --- a/spec/bundler/support/hax.rb +++ b/spec/bundler/support/hax.rb @@ -24,13 +24,30 @@ module Gem end if ENV["BUNDLER_SPEC_PLATFORM"] + previous_platforms = @platforms + previous_local = Platform.local + class Platform @local = new(ENV["BUNDLER_SPEC_PLATFORM"]) end - @platforms = [Gem::Platform::RUBY, Gem::Platform.local] + @platforms = previous_platforms.map {|platform| platform == previous_local ? Platform.local : platform } end if ENV["BUNDLER_SPEC_GEM_SOURCES"] self.sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]] end + + if ENV["BUNDLER_IGNORE_DEFAULT_GEM"] + module RemoveDefaultBundlerStub + def default_stubs(pattern = "*") + super.delete_if {|stub| stub.name == "bundler" } + end + end + + class Specification + class << self + prepend RemoveDefaultBundlerStub + end + end + end end diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb index 8b22e7dbc3..ea7c784683 100644 --- a/spec/bundler/support/matchers.rb +++ b/spec/bundler/support/matchers.rb @@ -162,7 +162,7 @@ module Spec end if exitstatus == 65 actual_platform = out.split("\n").last - next "#{name} was expected to be of platform #{platform} but was #{actual_platform}" + next "#{name} was expected to be of platform #{platform || "ruby"} but was #{actual_platform || "ruby"}" end if exitstatus == 66 actual_source = out.split("\n").last |