summaryrefslogtreecommitdiff
path: root/spec/bundler/install
diff options
context:
space:
mode:
Diffstat (limited to 'spec/bundler/install')
-rw-r--r--spec/bundler/install/allow_offline_install_spec.rb23
-rw-r--r--spec/bundler/install/binstubs_spec.rb4
-rw-r--r--spec/bundler/install/bundler_spec.rb101
-rw-r--r--spec/bundler/install/deploy_spec.rb249
-rw-r--r--spec/bundler/install/failure_spec.rb4
-rw-r--r--spec/bundler/install/gemfile/eval_gemfile_spec.rb8
-rw-r--r--spec/bundler/install/gemfile/force_ruby_platform_spec.rb146
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb308
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb282
-rw-r--r--spec/bundler/install/gemfile/groups_spec.rb42
-rw-r--r--spec/bundler/install/gemfile/install_if_spec.rb9
-rw-r--r--spec/bundler/install/gemfile/lockfile_spec.rb5
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb293
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb154
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb50
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb652
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb1233
-rw-r--r--spec/bundler/install/gemfile_spec.rb12
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb410
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb170
-rw-r--r--spec/bundler/install/gems/flex_spec.rb90
-rw-r--r--spec/bundler/install/gems/fund_spec.rb43
-rw-r--r--spec/bundler/install/gems/native_extensions_spec.rb6
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb416
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb169
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb205
-rw-r--r--spec/bundler/install/gemspecs_spec.rb31
-rw-r--r--spec/bundler/install/git_spec.rb147
-rw-r--r--spec/bundler/install/global_cache_spec.rb46
-rw-r--r--spec/bundler/install/path_spec.rb38
-rw-r--r--spec/bundler/install/process_lock_spec.rb22
-rw-r--r--spec/bundler/install/redownload_spec.rb2
-rw-r--r--spec/bundler/install/security_policy_spec.rb12
-rw-r--r--spec/bundler/install/yanked_spec.rb147
34 files changed, 4088 insertions, 1441 deletions
diff --git a/spec/bundler/install/allow_offline_install_spec.rb b/spec/bundler/install/allow_offline_install_spec.rb
index 524363fde5..8da94718e0 100644
--- a/spec/bundler/install/allow_offline_install_spec.rb
+++ b/spec/bundler/install/allow_offline_install_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
context "with no cached data locally" do
it "still installs" do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "http://testgemserver.local"
gem "rack-obama"
G
@@ -15,7 +15,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
end
it "still fails when the network is down" do
- install_gemfile <<-G, :artifice => "fail", :raise_on_error => false
+ install_gemfile <<-G, artifice: "fail", raise_on_error: false
source "http://testgemserver.local"
gem "rack-obama"
G
@@ -26,10 +26,10 @@ RSpec.describe "bundle install with :allow_offline_install" do
context "with cached data locally" do
it "will install from the compact index" do
- system_gems ["rack-1.0.0"], :path => default_bundle_path
+ system_gems ["rack-1.0.0"], path: default_bundle_path
bundle "config set clean false"
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "http://testgemserver.local"
gem "rack-obama"
gem "rack", "< 1.0"
@@ -42,7 +42,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
gem "rack-obama"
G
- bundle :update, :artifice => "fail", :all => true
+ bundle :update, artifice: "fail", all: true
expect(last_command.stdboth).to include "Using the cached data for the new index because of a network error"
expect(the_bundle).to include_gems("rack-obama 1.0", "rack 1.0.0")
@@ -51,9 +51,12 @@ RSpec.describe "bundle install with :allow_offline_install" do
def break_git_remote_ops!
FileUtils.mkdir_p(tmp("broken_path"))
File.open(tmp("broken_path/git"), "w", 0o755) do |f|
- f.puts strip_whitespace(<<-RUBY)
+ f.puts <<~RUBY
#!/usr/bin/env ruby
- if %w(fetch --force --quiet --tags refs/heads/*:refs/heads/*).-(ARGV).empty? || %w(clone --bare --no-hardlinks --quiet).-(ARGV).empty?
+ fetch_args = %w(fetch --force --quiet)
+ clone_args = %w(clone --bare --no-hardlinks --quiet)
+
+ if (fetch_args.-(ARGV).empty? || clone_args.-(ARGV).empty?) && ARGV.any? {|arg| arg.start_with?("file://") }
warn "git remote ops have been disabled"
exit 1
end
@@ -72,14 +75,14 @@ RSpec.describe "bundle install with :allow_offline_install" do
it "will install from a cached git repo" do
skip "doesn't print errors" if Gem.win_platform?
- git = build_git "a", "1.0.0", :path => lib_path("a")
- update_git("a", :path => git.path, :branch => "new_branch")
+ git = build_git "a", "1.0.0", path: lib_path("a")
+ update_git("a", path: git.path, branch: "new_branch")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "a", :git => #{git.path.to_s.dump}
G
- break_git_remote_ops! { bundle :update, :all => true }
+ break_git_remote_ops! { bundle :update, all: true }
expect(err).to include("Using cached git data because of network errors")
expect(the_bundle).to be_locked
diff --git a/spec/bundler/install/binstubs_spec.rb b/spec/bundler/install/binstubs_spec.rb
index 6961171f4f..928ba80b15 100644
--- a/spec/bundler/install/binstubs_spec.rb
+++ b/spec/bundler/install/binstubs_spec.rb
@@ -2,10 +2,8 @@
RSpec.describe "bundle install" do
describe "when system_bindir is set" do
- # On OS X, Gem.bindir defaults to /usr/bin, so system_bindir is useful if
- # you want to avoid sudo installs for system gems with OS X's default ruby
it "overrides Gem.bindir" do
- expect(Pathname.new("/usr/bin")).not_to be_writable unless Process.euid == 0
+ expect(Pathname.new("/usr/bin")).not_to be_writable
gemfile <<-G
def Gem.bindir; "/usr/bin"; end
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb
index 963ce82db8..19911f1154 100644
--- a/spec/bundler/install/bundler_spec.rb
+++ b/spec/bundler/install/bundler_spec.rb
@@ -30,19 +30,18 @@ RSpec.describe "bundle install" do
end
it "causes a conflict if explicitly requesting a different version of bundler" do
- install_gemfile <<-G, :raise_on_error => false
+ 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)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- Current Bundler version:
- bundler (#{Bundler::VERSION})
+ Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.1
+ and Gemfile depends on bundler = 0.9.1,
+ version solving has failed.
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`
@@ -51,19 +50,21 @@ RSpec.describe "bundle install" do
end
it "causes a conflict if explicitly requesting a non matching requirement on bundler" do
- install_gemfile <<-G, :raise_on_error => false
+ 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)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- Current Bundler version:
- bundler (#{Bundler::VERSION})
+ Because rails >= 3.0 depends on bundler >= 0.9.0.pre
+ and the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler >= 0.9.0.pre, < 1.A,
+ rails >= 3.0 requires bundler >= 1.A.
+ So, because Gemfile depends on rails = 3.0
+ and Gemfile depends on bundler ~> 0.8,
+ version solving has failed.
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`
@@ -72,19 +73,18 @@ RSpec.describe "bundle install" do
end
it "causes a conflict if explicitly requesting a version of bundler that doesn't exist" do
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0"
gem "bundler", "0.9.2"
G
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "bundler":
- In Gemfile:
- bundler (= 0.9.2)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- Current Bundler version:
- bundler (#{Bundler::VERSION})
+ Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.2
+ and Gemfile depends on bundler = 0.9.2,
+ version solving has failed.
Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.
E
@@ -143,20 +143,21 @@ RSpec.describe "bundle install" do
end
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo2)}"
gem "activemerchant"
gem "rails_pinned_to_old_activesupport"
G
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "activesupport":
- In Gemfile:
- activemerchant was resolved to 1.0, which depends on
- activesupport (>= 2.0.0)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- rails_pinned_to_old_activesupport was resolved to 1.0, which depends on
- activesupport (= 1.2.3)
+ Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3
+ and every version of activemerchant depends on activesupport >= 2.0.0,
+ every version of rails_pinned_to_old_activesupport is incompatible with activemerchant >= 0.
+ So, because Gemfile depends on activemerchant >= 0
+ and Gemfile depends on rails_pinned_to_old_activesupport >= 0,
+ version solving has failed.
E
expect(err).to include(nice_error)
end
@@ -170,19 +171,20 @@ RSpec.describe "bundle install" do
end
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo2)}"
gem "rails_pinned_to_old_activesupport"
gem "activesupport", "2.3.5"
G
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "activesupport":
- In Gemfile:
- activesupport (= 2.3.5)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- rails_pinned_to_old_activesupport was resolved to 1.0, which depends on
- activesupport (= 1.2.3)
+ Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3
+ and Gemfile depends on rails_pinned_to_old_activesupport >= 0,
+ activesupport = 1.2.3 is required.
+ So, because Gemfile depends on activesupport = 2.3.5,
+ version solving has failed.
E
expect(err).to include(nice_error)
end
@@ -208,6 +210,33 @@ RSpec.describe "bundle install" do
expect(err).to be_empty
end
+ it "prints the previous version when switching to a previously downloaded gem" do
+ build_repo4 do
+ build_gem "rails", "7.0.3"
+ build_gem "rails", "7.0.4"
+ end
+
+ bundle "config set path.system true"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'rails', "7.0.4"
+ G
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'rails', "7.0.3"
+ G
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'rails', "7.0.4"
+ G
+
+ expect(out).to include("Using rails 7.0.4 (was 7.0.3)")
+ expect(err).to be_empty
+ end
+
it "can install dependencies with newer bundler version with system gems" do
bundle "config set path.system true"
diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb
index 3bcb6a703e..d89fdea6f1 100644
--- a/spec/bundler/install/deploy_spec.rb
+++ b/spec/bundler/install/deploy_spec.rb
@@ -8,26 +8,26 @@ RSpec.describe "install in deployment or frozen mode" do
G
end
- context "with CLI flags", :bundler => "< 3" do
+ context "with CLI flags", bundler: "< 3" do
it "fails without a lockfile and says that --deployment requires a lock" do
- bundle "install --deployment", :raise_on_error => false
- expect(err).to include("The --deployment flag requires a Gemfile.lock")
+ bundle "install --deployment", raise_on_error: false
+ expect(err).to include("The --deployment flag requires a lockfile")
end
it "fails without a lockfile and says that --frozen requires a lock" do
- bundle "install --frozen", :raise_on_error => false
- expect(err).to include("The --frozen flag requires a Gemfile.lock")
+ bundle "install --frozen", raise_on_error: false
+ expect(err).to include("The --frozen flag requires a lockfile")
end
it "disallows --deployment --system" do
- bundle "install --deployment --system", :raise_on_error => false
+ bundle "install --deployment --system", raise_on_error: false
expect(err).to include("You have specified both --deployment")
expect(err).to include("Please choose only one option")
expect(exitstatus).to eq(15)
end
it "disallows --deployment --path --system" do
- bundle "install --deployment --path . --system", :raise_on_error => false
+ bundle "install --deployment --path . --system", raise_on_error: false
expect(err).to include("You have specified both --path")
expect(err).to include("as well as --system")
expect(err).to include("Please choose only one option")
@@ -35,10 +35,43 @@ RSpec.describe "install in deployment or frozen mode" do
end
it "doesn't mess up a subsequent `bundle install` after you try to deploy without a lock" do
- bundle "install --deployment", :raise_on_error => false
+ bundle "install --deployment", raise_on_error: false
bundle :install
expect(the_bundle).to include_gems "rack 1.0"
end
+
+ it "installs gems by default to vendor/bundle" do
+ bundle :lock
+ bundle "install --deployment"
+ expect(out).to include("vendor/bundle")
+ end
+
+ it "installs gems to custom path if specified" do
+ bundle :lock
+ bundle "install --path vendor/bundle2 --deployment"
+ expect(out).to include("vendor/bundle2")
+ end
+
+ it "works with the --frozen flag" do
+ bundle :lock
+ bundle "install --frozen"
+ end
+
+ it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do
+ bundle :lock
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ gem "rack-obama"
+ G
+
+ bundle "install --deployment", raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have added to the Gemfile")
+ expect(err).to include("* rack-obama")
+ expect(err).not_to include("You have deleted from the Gemfile")
+ expect(err).not_to include("You have changed in the Gemfile")
+ end
end
it "still works if you are not in the app directory and specify --gemfile" do
@@ -46,7 +79,7 @@ RSpec.describe "install in deployment or frozen mode" do
simulate_new_machine
bundle "config set --local deployment true"
bundle "config set --local path vendor/bundle"
- bundle "install --gemfile #{tmp}/bundled_app/Gemfile", :dir => tmp
+ bundle "install --gemfile #{tmp}/bundled_app/Gemfile", dir: tmp
expect(the_bundle).to include_gems "rack 1.0"
end
@@ -70,12 +103,12 @@ RSpec.describe "install in deployment or frozen mode" do
bundle :install
bundle "config set --local deployment true"
bundle :install
- bundle "exec bundle check", :env => { "PATH" => path }
+ bundle "exec bundle check", env: { "PATH" => path }
end
it "works when using path gems from the same path and the version is specified" do
- build_lib "foo", :path => lib_path("nested/foo")
- build_lib "bar", :path => lib_path("nested/bar")
+ build_lib "foo", path: lib_path("nested/foo")
+ build_lib "bar", path: lib_path("nested/bar")
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo", "1.0", :path => "#{lib_path("nested")}"
@@ -88,7 +121,7 @@ RSpec.describe "install in deployment or frozen mode" do
end
it "works when path gems are specified twice" do
- build_lib "foo", :path => lib_path("nested/foo")
+ build_lib "foo", path: lib_path("nested/foo")
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("nested/foo")}"
@@ -101,14 +134,14 @@ RSpec.describe "install in deployment or frozen mode" do
end
it "works when there are credentials in the source URL" do
- install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
+ install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true)
source "http://user:pass@localgemserver.test/"
gem "rack-obama", ">= 1.0"
G
bundle "config set --local deployment true"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
end
it "works with sources given by a block" do
@@ -141,7 +174,7 @@ RSpec.describe "install in deployment or frozen mode" do
rack (1.0.0)
PLATFORMS
- #{local}
+ #{generic_local_platform}
DEPENDENCIES
rack
@@ -150,50 +183,10 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local deployment true"
end
- it "prevents the replace by default" do
- bundle :install, :raise_on_error => false
-
- expect(err).to match(/The list of sources changed/)
- end
-
- context "when allow_deployment_source_credential_changes is true" do
- before { bundle "config set allow_deployment_source_credential_changes true" }
-
- it "allows the replace" do
- bundle :install
-
- expect(out).to match(/Bundle complete!/)
- end
- end
-
- context "when allow_deployment_source_credential_changes is false" do
- before { bundle "config set allow_deployment_source_credential_changes false" }
-
- it "prevents the replace" do
- bundle :install, :raise_on_error => false
-
- expect(err).to match(/The list of sources changed/)
- end
- end
-
- context "when BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES env var is true" do
- before { ENV["BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES"] = "true" }
-
- it "allows the replace" do
- bundle :install
-
- expect(out).to match(/Bundle complete!/)
- end
- end
-
- context "when BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES env var is false" do
- before { ENV["BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES"] = "false" }
-
- it "prevents the replace" do
- bundle :install, :raise_on_error => false
+ it "allows the replace" do
+ bundle :install
- expect(err).to match(/The list of sources changed/)
- end
+ expect(out).to match(/Bundle complete!/)
end
end
@@ -202,29 +195,41 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "install"
end
- it "installs gems by default to vendor/bundle", :bundler => "< 3" do
- bundle "install --deployment"
+ it "installs gems by default to vendor/bundle" do
+ bundle "config set deployment true"
+ expect do
+ bundle "install"
+ end.not_to change { bundled_app_lock.mtime }
expect(out).to include("vendor/bundle")
end
- it "installs gems to custom path if specified", :bundler => "< 3" do
- bundle "install --path vendor/bundle2 --deployment"
+ it "installs gems to custom path if specified" do
+ bundle "config set path vendor/bundle2"
+ bundle "config set deployment true"
+ bundle "install"
expect(out).to include("vendor/bundle2")
end
- it "works with the --deployment flag if you didn't change anything", :bundler => "< 3" do
- bundle "install --deployment"
+ it "installs gems to custom path if specified, even when configured through ENV" do
+ bundle "config set deployment true"
+ bundle "install", env: { "BUNDLE_PATH" => "vendor/bundle2" }
+ expect(out).to include("vendor/bundle2")
end
- it "works with the --frozen flag if you didn't change anything", :bundler => "< 3" do
- bundle "install --frozen"
+ it "works with the `frozen` setting" do
+ bundle "config set frozen true"
+ expect do
+ bundle "install"
+ end.not_to change { bundled_app_lock.mtime }
end
it "works with BUNDLE_FROZEN if you didn't change anything" do
- bundle :install, :env => { "BUNDLE_FROZEN" => "true" }
+ expect do
+ bundle :install, env: { "BUNDLE_FROZEN" => "true" }
+ end.not_to change { bundled_app_lock.mtime }
end
- it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do
+ it "explodes with the `deployment` setting if you make a change and don't check in the lockfile" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -232,8 +237,8 @@ RSpec.describe "install in deployment or frozen mode" do
G
bundle "config set --local deployment true"
- bundle :install, :raise_on_error => false
- expect(err).to include("deployment mode")
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
@@ -253,22 +258,60 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local path .bundle"
bundle "config set --local without development"
bundle "config set --local deployment true"
- bundle :install, :env => { "DEBUG" => "1" }
+ bundle :install, env: { "DEBUG" => "1" }
run "puts :WIN"
expect(out).to eq("WIN")
end
- it "works if a gem is missing, but it's on a different platform, and the Gemfile has no global source", :bundler => "< 3" do
+ it "works if a gem is missing, but it's on a different platform" do
+ build_repo2
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
source "#{file_uri_for(gem_repo1)}" do
gem "rake", platform: :#{not_local_tag}
end
G
- bundle :install, :env => { "BUNDLE_FROZEN" => "true" }
+ bundle :install, env: { "BUNDLE_FROZEN" => "true" }
expect(last_command).to be_success
end
+ it "shows a good error if a gem is missing from the lockfile" do
+ build_repo4 do
+ build_gem "foo"
+ build_gem "bar"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "foo"
+ gem "bar"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false, artifice: "compact_index"
+ expect(err).to include("Your lock file is missing \"bar\", but the lockfile can't be updated because frozen mode is set")
+ end
+
it "explodes if a path gem is missing" do
build_lib "path_gem"
install_gemfile <<-G
@@ -281,11 +324,11 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local path .bundle"
bundle "config set --local deployment true"
- bundle :install, :raise_on_error => false
+ bundle :install, raise_on_error: false
expect(err).to include("The path `#{lib_path("path_gem-1.0")}` does not exist.")
end
- it "can have --frozen set via an environment variable", :bundler => "< 3" do
+ it "can have --frozen set via an environment variable" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -293,8 +336,8 @@ RSpec.describe "install in deployment or frozen mode" do
G
ENV["BUNDLE_FROZEN"] = "1"
- bundle "install", :raise_on_error => false
- expect(err).to include("deployment mode")
+ bundle "install", raise_on_error: false
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
@@ -309,21 +352,21 @@ RSpec.describe "install in deployment or frozen mode" do
G
ENV["BUNDLE_DEPLOYMENT"] = "true"
- bundle "install", :raise_on_error => false
- expect(err).to include("deployment mode")
+ bundle "install", raise_on_error: false
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have changed in the Gemfile")
end
- it "installs gems by default to vendor/bundle when deployment mode is set via an environment variable", :bundler => "< 3" do
+ it "installs gems by default to vendor/bundle when deployment mode is set via an environment variable" do
ENV["BUNDLE_DEPLOYMENT"] = "true"
bundle "install"
expect(out).to include("vendor/bundle")
end
- it "installs gems to custom path when deployment mode is set via an environment variable ", :bundler => "< 3" do
+ it "installs gems to custom path when deployment mode is set via an environment variable " do
ENV["BUNDLE_DEPLOYMENT"] = "true"
ENV["BUNDLE_PATH"] = "vendor/bundle2"
bundle "install"
@@ -340,7 +383,7 @@ RSpec.describe "install in deployment or frozen mode" do
ENV["BUNDLE_FROZEN"] = "false"
ENV["BUNDLE_DEPLOYMENT"] = "false"
bundle "install"
- expect(out).not_to include("deployment mode")
+ expect(out).not_to include("frozen mode")
expect(out).not_to include("You have added to the Gemfile")
expect(out).not_to include("* rack-obama")
end
@@ -352,8 +395,8 @@ RSpec.describe "install in deployment or frozen mode" do
G
bundle "config set --local deployment true"
- bundle :install, :raise_on_error => false
- expect(err).to include("deployment mode")
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile:\n* activesupport\n\n")
expect(err).to include("You have deleted from the Gemfile:\n* rack")
expect(err).not_to include("You have changed in the Gemfile")
@@ -366,8 +409,8 @@ RSpec.describe "install in deployment or frozen mode" do
G
bundle "config set --local deployment true"
- bundle :install, :raise_on_error => false
- expect(err).to include("deployment mode")
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
expect(err).not_to include("You have added to the Gemfile")
expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `git://hubz.com`")
end
@@ -386,16 +429,16 @@ RSpec.describe "install in deployment or frozen mode" do
G
bundle "config set --local deployment true"
- bundle :install, :raise_on_error => false
- expect(err).to include("deployment mode")
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have added to the Gemfile")
expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack-1.0")}` to `no specified source`")
end
it "explodes if you change a source" do
- build_lib "foo", :path => lib_path("rack/foo")
- build_git "rack", :path => lib_path("rack")
+ build_lib "foo", path: lib_path("rack/foo")
+ build_git "rack", path: lib_path("rack")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -410,8 +453,8 @@ RSpec.describe "install in deployment or frozen mode" do
G
bundle "config set --local deployment true"
- bundle :install, :raise_on_error => false
- expect(err).to include("deployment mode")
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack")}` to `no specified source`")
expect(err).not_to include("You have added to the Gemfile")
expect(err).not_to include("You have deleted from the Gemfile")
@@ -428,23 +471,23 @@ RSpec.describe "install in deployment or frozen mode" do
gem "rack-obama"
G
- run "require 'rack'", :raise_on_error => false
- expect(err).to include strip_whitespace(<<-E).strip
-The dependencies in your gemfile changed
+ run "require 'rack'", raise_on_error: false
+ expect(err).to include <<~E.strip
+ The dependencies in your gemfile changed, but the lockfile can't be updated because frozen mode is set (Bundler::ProductionError)
-You have added to the Gemfile:
-* rack (= 1.0.0)
-* rack-obama
+ You have added to the Gemfile:
+ * rack (= 1.0.0)
+ * rack-obama
-You have deleted from the Gemfile:
-* rack
+ You have deleted from the Gemfile:
+ * rack
E
end
end
context "with path in Gemfile and packed" do
it "works fine after bundle package and bundle install --local" do
- build_lib "foo", :path => lib_path("foo")
+ build_lib "foo", path: lib_path("foo")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo")}"
@@ -463,7 +506,7 @@ You have deleted from the Gemfile:
simulate_new_machine
bundle "config set --local deployment true"
bundle "install --verbose"
- expect(out).not_to include("You are trying to install in deployment mode after changing your Gemfile")
+ expect(out).not_to include("but the lockfile can't be updated because frozen mode is set")
expect(out).not_to include("You have added to the Gemfile")
expect(out).not_to include("You have deleted from the Gemfile")
expect(out).to include("vendor/cache/foo")
diff --git a/spec/bundler/install/failure_spec.rb b/spec/bundler/install/failure_spec.rb
index 4a9c33754f..f972a37bf6 100644
--- a/spec/bundler/install/failure_spec.rb
+++ b/spec/bundler/install/failure_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe "bundle install" do
end
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo2)}"
gem "rails"
G
@@ -39,7 +39,7 @@ In Gemfile:
end
it "removes the downloaded .gem" do
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo4)}"
gem "a"
G
diff --git a/spec/bundler/install/gemfile/eval_gemfile_spec.rb b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
index 02283291b4..cfa66e5986 100644
--- a/spec/bundler/install/gemfile/eval_gemfile_spec.rb
+++ b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
before do
- build_lib("gunks", :path => bundled_app.join("gems/gunks")) do |s|
+ build_lib("gunks", path: bundled_app.join("gems/gunks")) do |s|
s.name = "gunks"
s.version = "0.0.1"
end
@@ -24,7 +24,7 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
expect(out).to include("Resolving dependencies")
expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gem "gunks 0.0.1", :source => "path@#{bundled_app("gems", "gunks")}"
+ expect(the_bundle).to include_gem "gunks 0.0.1", source: "path@#{bundled_app("gems", "gunks")}"
end
end
@@ -64,7 +64,7 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
context "eval-ed Gemfile has relative-path gems" do
before do
- build_lib("a", :path => bundled_app("gems/a"))
+ build_lib("a", path: bundled_app("gems/a"))
create_file bundled_app("nested/Gemfile-nested"), <<-G
source "#{file_uri_for(gem_repo1)}"
gem "a", :path => "../gems/a"
@@ -102,7 +102,7 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
expect(out).to include("Resolving dependencies")
expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gem "gunks 0.0.1", :source => "path@#{bundled_app("gems", "gunks")}"
+ expect(the_bundle).to include_gem "gunks 0.0.1", source: "path@#{bundled_app("gems", "gunks")}"
end
end
diff --git a/spec/bundler/install/gemfile/force_ruby_platform_spec.rb b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
new file mode 100644
index 0000000000..a29b79ad62
--- /dev/null
+++ b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
@@ -0,0 +1,146 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with force_ruby_platform DSL option", :jruby do
+ context "when no transitive deps" do
+ before do
+ build_repo4 do
+ # Build a gem with platform specific versions
+ build_gem("platform_specific") do |s|
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+
+ # Build the exact same gem with a different name to compare using vs not using the option
+ build_gem("platform_specific_forced") do |s|
+ s.write "lib/platform_specific_forced.rb", "PLATFORM_SPECIFIC_FORCED = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific_forced") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific_forced.rb", "PLATFORM_SPECIFIC_FORCED = '1.0.0 #{Bundler.local_platform}'"
+ end
+ end
+ end
+
+ it "pulls the pure ruby variant of the given gem" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "platform_specific_forced", :force_ruby_platform => true
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 #{Bundler.local_platform}"
+ end
+
+ it "still respects a global `force_ruby_platform` config" do
+ install_gemfile <<-G, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "platform_specific_forced", :force_ruby_platform => true
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ end
+ end
+
+ context "when also a transitive dependency" do
+ before do
+ build_repo4 do
+ build_gem("depends_on_platform_specific") {|s| s.add_runtime_dependency "platform_specific" }
+
+ build_gem("platform_specific") do |s|
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+ end
+ end
+
+ it "still pulls the ruby variant" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "depends_on_platform_specific"
+ gem "platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ end
+ end
+
+ context "with transitive dependencies with platform specific versions" do
+ before do
+ build_repo4 do
+ build_gem("depends_on_platform_specific") do |s|
+ s.add_runtime_dependency "platform_specific"
+ s.write "lib/depends_on_platform_specific.rb", "DEPENDS_ON_PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("depends_on_platform_specific") do |s|
+ s.add_runtime_dependency "platform_specific"
+ s.platform = Bundler.local_platform
+ s.write "lib/depends_on_platform_specific.rb", "DEPENDS_ON_PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+ end
+ end
+
+ it "ignores ruby variants for the transitive dependencies" do
+ install_gemfile <<-G, env: { "DEBUG_RESOLVER" => "true" }
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "depends_on_platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "depends_on_platform_specific 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 #{Bundler.local_platform}"
+ end
+
+ it "reinstalls the ruby variant when a platform specific variant is already installed, the lockile has only RUBY platform, and :force_ruby_platform is used in the Gemfile" do
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}
+ specs:
+ platform_specific (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ system_gems "platform_specific-1.0-#{Gem::Platform.local}", path: default_bundle_path
+
+ install_gemfile <<-G, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, artifice: "compact_index"
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ end
+ end
+end
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb
index 6bcfadab7e..63778567cf 100644
--- a/spec/bundler/install/gemfile/gemspec_spec.rb
+++ b/spec/bundler/install/gemfile/gemspec_spec.rb
@@ -8,8 +8,38 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
+ let(:x64_mingw_archs) do
+ if RUBY_PLATFORM == "x64-mingw-ucrt"
+ if Gem.rubygems_version >= Gem::Version.new("3.2.28")
+ ["x64-mingw-ucrt", "x64-mingw32"]
+ else
+ ["x64-mingw32", "x64-unknown"]
+ end
+ else
+ ["x64-mingw32"]
+ end
+ end
+
+ let(:x64_mingw_gems) do
+ x64_mingw_archs.map {|p| "platform_specific (1.0-#{p})" }.join("\n ")
+ end
+
+ let(:x64_mingw_platforms) do
+ x64_mingw_archs.join("\n ")
+ end
+
+ def x64_mingw_checksums(checksums)
+ x64_mingw_archs.each do |arch|
+ if arch == "x64-mingw-ucrt"
+ checksums.no_checksum "platform_specific", "1.0", arch
+ else
+ checksums.checksum gem_repo2, "platform_specific", "1.0", arch
+ end
+ end
+ end
+
it "should install runtime and development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
@@ -20,11 +50,11 @@ RSpec.describe "bundle install from an existing gemspec" do
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development
end
it "that is hidden should install runtime and development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
@@ -37,7 +67,7 @@ RSpec.describe "bundle install from an existing gemspec" do
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development
end
it "should handle a list of requirements" do
@@ -46,7 +76,7 @@ RSpec.describe "bundle install from an existing gemspec" do
build_gem "baz", "1.1"
end
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "baz", ">= 1.0", "< 1.1"
end
@@ -59,29 +89,29 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "should raise if there are no gemspecs available" do
- build_lib("foo", :path => tmp.join("foo"), :gemspec => false)
+ build_lib("foo", path: tmp.join("foo"), gemspec: false)
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo2)}"
gemspec :path => '#{tmp.join("foo")}'
G
- expect(err).to match(/There are no gemspecs at #{tmp.join('foo')}/)
+ expect(err).to match(/There are no gemspecs at #{tmp.join("foo")}/)
end
it "should raise if there are too many gemspecs available" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.write("foo2.gemspec", build_spec("foo", "4.0").first.to_ruby)
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo2)}"
gemspec :path => '#{tmp.join("foo")}'
G
- expect(err).to match(/There are multiple gemspecs at #{tmp.join('foo')}/)
+ expect(err).to match(/There are multiple gemspecs at #{tmp.join("foo")}/)
end
it "should pick a specific gemspec" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.write("foo2.gemspec", "")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
@@ -93,11 +123,11 @@ RSpec.describe "bundle install from an existing gemspec" do
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development
end
it "should use a specific group for development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.write("foo2.gemspec", "")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
@@ -109,32 +139,32 @@ RSpec.describe "bundle install from an existing gemspec" do
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).not_to include_gems "bar-dev 1.0.0", :groups => :development
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :dev
+ expect(the_bundle).not_to include_gems "bar-dev 1.0.0", groups: :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :dev
end
it "should match a lockfile even if the gemspec defines development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.write("Gemfile", "source '#{file_uri_for(gem_repo1)}'\ngemspec")
s.add_dependency "actionpack", "=2.3.2"
- s.add_development_dependency "rake", "=13.0.1"
+ s.add_development_dependency "rake", rake_version
end
- bundle "install", :dir => tmp.join("foo")
+ bundle "install", dir: tmp.join("foo")
# This should really be able to rely on $stderr, but, it's not written
# right, so we can't. In fact, this is a bug negation test, and so it'll
# ghost pass in future, and will only catch a regression if the message
# doesn't change. Exit codes should be used correctly (they can be more
# than just 0 and 1).
bundle "config set --local deployment true"
- output = bundle("install", :dir => tmp.join("foo"))
+ output = bundle("install", dir: tmp.join("foo"))
expect(output).not_to match(/You have added to the Gemfile/)
expect(output).not_to match(/You have deleted from the Gemfile/)
- expect(output).not_to match(/install in deployment mode after changing/)
+ expect(output).not_to match(/the lockfile can't be updated because frozen mode is set/)
end
it "should match a lockfile without needing to re-resolve" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.add_dependency "rack"
end
@@ -143,7 +173,7 @@ RSpec.describe "bundle install from an existing gemspec" do
gemspec :path => '#{tmp.join("foo")}'
G
- bundle "install", :verbose => true
+ bundle "install", verbose: true
message = "Found no changes, using resolution from the lockfile"
expect(out.scan(message).size).to eq(1)
@@ -152,7 +182,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "should match a lockfile without needing to re-resolve with development dependencies" do
simulate_platform java
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.add_dependency "rack"
s.add_development_dependency "thin"
end
@@ -162,34 +192,34 @@ RSpec.describe "bundle install from an existing gemspec" do
gemspec :path => '#{tmp.join("foo")}'
G
- bundle "install", :verbose => true
+ bundle "install", verbose: true
message = "Found no changes, using resolution from the lockfile"
expect(out.scan(message).size).to eq(1)
end
- it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby_only do
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.add_dependency "platform_specific"
end
- system_gems "platform_specific-1.0-java", :path => default_bundle_path
+ system_gems "platform_specific-1.0-java", path: default_bundle_path
install_gemfile <<-G
gemspec :path => '#{tmp.join("foo")}'
G
- bundle "update --bundler", :artifice => "compact_index", :verbose => true
+ bundle "update --bundler", artifice: "compact_index", verbose: true
expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 JAVA"
end
it "should evaluate the gemspec in its directory" do
- build_lib("foo", :path => tmp.join("foo"))
+ build_lib("foo", path: tmp.join("foo"))
File.open(tmp.join("foo/foo.gemspec"), "w") do |s|
s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'"
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
gemspec :path => '#{tmp.join("foo")}'
G
expect(last_command.stdboth).not_to include("ahh")
@@ -203,7 +233,7 @@ RSpec.describe "bundle install from an existing gemspec" do
# so emulate that
system_gems %w[rack-1.0.0 rack-0.9.1 rack-obama-1.0]
- build_lib("foo", :path => bundled_app)
+ build_lib("foo", path: bundled_app)
gemspec = bundled_app("foo.gemspec").read
bundled_app("foo.gemspec").open("w") do |f|
f.write "#{gemspec.strip}.tap { gem 'rack-obama'; require 'rack/obama' }"
@@ -218,14 +248,14 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "allows conflicts" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.version = "1.0.0"
s.add_dependency "bar", "= 1.0.0"
end
- build_gem "deps", :to_bundle => true do |s|
+ build_gem "deps", to_bundle: true do |s|
s.add_dependency "foo", "= 0.0.1"
end
- build_gem "foo", "0.0.1", :to_bundle => true
+ build_gem "foo", "0.0.1", to_bundle: true
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -237,7 +267,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "does not break Gem.finish_resolve with conflicts" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.version = "1.0.0"
s.add_dependency "bar", "= 1.0.0"
end
@@ -261,14 +291,14 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "handles downgrades" do
- build_lib "omg", "2.0", :path => lib_path("omg")
+ build_lib "omg", "2.0", path: lib_path("omg")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec :path => "#{lib_path("omg")}"
G
- build_lib "omg", "1.0", :path => lib_path("omg")
+ build_lib "omg", "1.0", path: lib_path("omg")
bundle :install
@@ -278,7 +308,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "in deployment mode" do
context "when the lockfile was not updated after a change to the gemspec's dependencies" do
it "reports that installation failed" do
- build_lib "cocoapods", :path => bundled_app do |s|
+ build_lib "cocoapods", path: bundled_app do |s|
s.add_dependency "activesupport", ">= 1"
end
@@ -289,12 +319,12 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(the_bundle).to include_gems("cocoapods 1.0", "activesupport 2.3.5")
- build_lib "cocoapods", :path => bundled_app do |s|
+ build_lib "cocoapods", path: bundled_app do |s|
s.add_dependency "activesupport", ">= 1.0.1"
end
bundle "config set --local deployment true"
- bundle :install, :raise_on_error => false
+ bundle :install, raise_on_error: false
expect(err).to include("changed")
end
@@ -304,13 +334,13 @@ RSpec.describe "bundle install from an existing gemspec" do
context "when child gemspecs conflict with a released gemspec" do
before do
# build the "parent" gem that depends on another gem in the same repo
- build_lib "source_conflict", :path => bundled_app do |s|
+ build_lib "source_conflict", path: bundled_app do |s|
s.add_dependency "rack_middleware"
end
# build the "child" gem that is the same version as a released gem, but
# has completely different and conflicting dependency requirements
- build_lib "rack_middleware", "1.0", :path => bundled_app("rack_middleware") do |s|
+ build_lib "rack_middleware", "1.0", path: bundled_app("rack_middleware") do |s|
s.add_dependency "rack", "1.0" # anything other than 0.9.1
end
end
@@ -328,83 +358,69 @@ RSpec.describe "bundle install from an existing gemspec" do
context "with a lockfile and some missing dependencies" do
let(:source_uri) { "http://localgemserver.test" }
- context "previously bundled for Ruby" do
- let(:platform) { "ruby" }
-
- before do
- skip "not installing for some reason" if Gem.win_platform?
-
- build_lib("foo", :path => tmp.join("foo")) do |s|
- s.add_dependency "rack", "=1.0.0"
- end
-
- gemfile <<-G
- source "#{source_uri}"
- gemspec :path => "../foo"
- G
+ before do
+ build_lib("foo", path: tmp.join("foo")) do |s|
+ s.add_dependency "rack", "=1.0.0"
+ end
- lockfile <<-L
- PATH
- remote: ../foo
- specs:
- foo (1.0)
- rack (= 1.0.0)
+ gemfile <<-G
+ source "#{source_uri}"
+ gemspec :path => "../foo"
+ G
- GEM
- remote: #{source_uri}
- specs:
- rack (1.0.0)
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "1.0"
+ end
- PLATFORMS
- #{generic_local_platform}
+ lockfile <<-L
+ PATH
+ remote: ../foo
+ specs:
+ foo (1.0)
+ rack (= 1.0.0)
- DEPENDENCIES
- foo!
+ GEM
+ remote: #{source_uri}
+ specs:
+ rack (1.0.0)
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
+ PLATFORMS
+ #{generic_local_platform}
- context "using JRuby with explicit platform", :jruby do
- before do
- create_file(
- tmp.join("foo", "foo-java.gemspec"),
- build_spec("foo", "1.0", "java") do
- dep "rack", "=1.0.0"
- @spec.authors = "authors"
- @spec.summary = "summary"
- end.first.to_ruby
- )
- end
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
- it "should install" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ context "using JRuby with explicit platform", :jruby_only do
+ before do
+ create_file(
+ tmp.join("foo", "foo-java.gemspec"),
+ build_spec("foo", "1.0", "java") do
+ dep "rack", "=1.0.0"
+ @spec.authors = "authors"
+ @spec.summary = "summary"
+ end.first.to_ruby
+ )
end
- context "using JRuby", :jruby do
- it "should install" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ it "should install" do
+ results = bundle "install", artifice: "endpoint"
+ expect(results).to include("Installing rack 1.0.0")
+ expect(the_bundle).to include_gems "rack 1.0.0"
end
+ end
- context "using Windows" do
- it "should install" do
- simulate_windows do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
- end
+ it "should install", :jruby do
+ results = bundle "install", artifice: "endpoint"
+ expect(results).to include("Installing rack 1.0.0")
+ expect(the_bundle).to include_gems "rack 1.0.0"
end
- context "bundled for ruby and jruby" do
+ context "bundled for multiple platforms" do
let(:platform_specific_type) { :runtime }
let(:dependency) { "platform_specific" }
before do
@@ -414,7 +430,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
- build_lib "foo", :path => bundled_app do |s|
+ build_lib "foo", path: bundled_app do |s|
if platform_specific_type == :runtime
s.add_runtime_dependency dependency
elsif platform_specific_type == :development
@@ -434,6 +450,7 @@ RSpec.describe "bundle install from an existing gemspec" do
simulate_new_machine
simulate_platform("jruby") { bundle "install" }
+ simulate_platform(x64_mingw32) { bundle "install" }
end
context "on ruby" do
@@ -443,9 +460,17 @@ RSpec.describe "bundle install from an existing gemspec" do
end
context "as a runtime dependency" do
- it "keeps java dependencies in the lockfile" do
+ it "keeps all platform dependencies in the lockfile" do
expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq strip_whitespace(<<-L)
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0", "java"
+ x64_mingw_checksums(c)
+ end
+
+ expect(lockfile).to eq <<~L
PATH
remote: .
specs:
@@ -457,14 +482,16 @@ RSpec.describe "bundle install from an existing gemspec" do
specs:
platform_specific (1.0)
platform_specific (1.0-java)
+ #{x64_mingw_gems}
PLATFORMS
java
ruby
+ #{x64_mingw_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -474,9 +501,17 @@ RSpec.describe "bundle install from an existing gemspec" do
context "as a development dependency" do
let(:platform_specific_type) { :development }
- it "keeps java dependencies in the lockfile" do
+ it "keeps all platform dependencies in the lockfile" do
expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq strip_whitespace(<<-L)
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0", "java"
+ x64_mingw_checksums(c)
+ end
+
+ expect(lockfile).to eq <<~L
PATH
remote: .
specs:
@@ -487,15 +522,17 @@ RSpec.describe "bundle install from an existing gemspec" do
specs:
platform_specific (1.0)
platform_specific (1.0-java)
+ #{x64_mingw_gems}
PLATFORMS
java
ruby
+ #{x64_mingw_platforms}
DEPENDENCIES
foo!
platform_specific
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -506,9 +543,18 @@ RSpec.describe "bundle install from an existing gemspec" do
let(:platform_specific_type) { :development }
let(:dependency) { "indirect_platform_specific" }
- it "keeps java dependencies in the lockfile" do
+ it "keeps all platform dependencies in the lockfile" do
expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq strip_whitespace(<<-L)
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo2, "indirect_platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0", "java"
+ x64_mingw_checksums(c)
+ end
+
+ expect(lockfile).to eq <<~L
PATH
remote: .
specs:
@@ -521,15 +567,17 @@ RSpec.describe "bundle install from an existing gemspec" do
platform_specific
platform_specific (1.0)
platform_specific (1.0-java)
+ #{x64_mingw_gems}
PLATFORMS
java
ruby
+ #{x64_mingw_platforms}
DEPENDENCIES
foo!
indirect_platform_specific
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -541,7 +589,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "with multiple platforms" do
before do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp.join("foo")) do |s|
s.version = "1.0.0"
s.add_development_dependency "rack"
s.write "foo-universal-java.gemspec", build_spec("foo", "1.0.0", "universal-java") {|sj| sj.runtime "rack", "1.0.0" }.first.to_ruby
@@ -575,7 +623,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "with multiple platforms and resolving for more specific platforms" do
before do
- build_lib("chef", :path => tmp.join("chef")) do |s|
+ build_lib("chef", path: tmp.join("chef")) do |s|
s.version = "17.1.17"
s.write "chef-universal-mingw32.gemspec", build_spec("chef", "17.1.17", "universal-mingw32") {|sw| sw.runtime "win32-api", "~> 1.5.3" }.first.to_ruby
end
@@ -593,6 +641,12 @@ RSpec.describe "bundle install from an existing gemspec" do
gemspec :path => "../chef"
G
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "chef", "17.1.17"
+ c.no_checksum "chef", "17.1.17", "universal-mingw32"
+ c.checksum gem_repo4, "win32-api", "1.5.3", "universal-mingw32"
+ end
+
initial_lockfile = <<~L
PATH
remote: ../chef
@@ -608,12 +662,12 @@ RSpec.describe "bundle install from an existing gemspec" do
PLATFORMS
ruby
- x64-mingw32
+ #{x64_mingw_platforms}
x86-mingw32
DEPENDENCIES
chef!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -628,7 +682,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "with multiple locked platforms" do
before do
- build_lib("activeadmin", :path => tmp.join("activeadmin")) do |s|
+ build_lib("activeadmin", path: tmp.join("activeadmin")) do |s|
s.version = "2.9.0"
s.add_dependency "railties", ">= 5.2", "< 6.2"
end
@@ -651,6 +705,12 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "does not remove the platform specific specs from the lockfile when re-resolving due to gemspec changes" do
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "activeadmin", "2.9.0"
+ c.no_checksum "jruby-openssl", "0.10.7", "java"
+ c.checksum gem_repo4, "railties", "6.1.4"
+ end
+
expect(lockfile).to eq <<~L
PATH
remote: ../activeadmin
@@ -665,12 +725,12 @@ RSpec.describe "bundle install from an existing gemspec" do
railties (6.1.4)
PLATFORMS
- #{lockfile_platforms_for(["java"] + local_platforms)}
+ #{lockfile_platforms("java")}
DEPENDENCIES
activeadmin!
jruby-openssl
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index 07995d013b..45ee7b44d1 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe "bundle install with git sources" do
- describe "when floating on master" do
+ describe "when floating on main" do
before :each do
build_git "foo" do |s|
s.executables = "foobar"
@@ -26,15 +26,22 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
- it "caches the git repo", :bundler => "< 3" do
- expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes :size => 1
+ it "caches the git repo", bundler: "< 3" do
+ expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes size: 1
+ end
+
+ it "does not write to cache on bundler/setup" do
+ cache_path = default_bundle_path.join("cache")
+ FileUtils.rm_rf(cache_path)
+ ruby "require 'bundler/setup'"
+ expect(cache_path).not_to exist
end
it "caches the git repo globally and properly uses the cached repo on the next invocation" do
simulate_new_machine
bundle "config set global_gem_cache true"
bundle :install
- expect(Dir["#{home}/.bundle/cache/git/foo-1.0-*"]).to have_attributes :size => 1
+ expect(Dir["#{home}/.bundle/cache/git/foo-1.0-*"]).to have_attributes size: 1
bundle "install --verbose"
expect(err).to be_empty
@@ -51,9 +58,10 @@ RSpec.describe "bundle install with git sources" do
bundle "update foo"
- sha = git.ref_for("master", 11)
- spec_file = default_bundle_path.join("bundler/gems/foo-1.0-#{sha}/foo.gemspec").to_s
- ruby_code = Gem::Specification.load(spec_file).to_ruby
+ sha = git.ref_for("main", 11)
+ spec_file = default_bundle_path.join("bundler/gems/foo-1.0-#{sha}/foo.gemspec")
+ expect(spec_file).to exist
+ ruby_code = Gem::Specification.load(spec_file.to_s).to_ruby
file_code = File.read(spec_file)
expect(file_code).to eq(ruby_code)
end
@@ -61,7 +69,7 @@ RSpec.describe "bundle install with git sources" do
it "does not update the git source implicitly" do
update_git "foo"
- install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2
+ install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
@@ -84,7 +92,7 @@ RSpec.describe "bundle install with git sources" do
it "complains if pinned specs don't exist in the git repo" do
build_git "foo"
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem "foo", "1.1", :git => "#{lib_path("foo-1.0")}"
G
@@ -92,12 +100,12 @@ RSpec.describe "bundle install with git sources" do
expect(err).to include("The source contains the following gems matching 'foo':\n * foo-1.0")
end
- it "complains with version and platform if pinned specs don't exist in the git repo", :jruby do
+ it "complains with version and platform if pinned specs don't exist in the git repo", :jruby_only do
build_git "only_java" do |s|
s.platform = "java"
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.0-java")}"
@@ -107,7 +115,7 @@ RSpec.describe "bundle install with git sources" do
expect(err).to include("The source contains the following gems matching 'only_java':\n * only_java-1.0-java")
end
- it "complains with multiple versions and platforms if pinned specs don't exist in the git repo", :jruby do
+ it "complains with multiple versions and platforms if pinned specs don't exist in the git repo", :jruby_only do
build_git "only_java", "1.0" do |s|
s.platform = "java"
end
@@ -117,7 +125,7 @@ RSpec.describe "bundle install with git sources" do
s.write "only_java1-0.gemspec", File.read("#{lib_path("only_java-1.0-java")}/only_java.gemspec")
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.1-java")}"
@@ -133,7 +141,7 @@ RSpec.describe "bundle install with git sources" do
FileUtils.mv bundled_app, tmp("bundled_app.bck")
- expect(the_bundle).to include_gems "foo 1.0", :dir => tmp("bundled_app.bck")
+ expect(the_bundle).to include_gems "foo 1.0", dir: tmp("bundled_app.bck")
end
it "can still install after moving the application directory" do
@@ -142,7 +150,7 @@ RSpec.describe "bundle install with git sources" do
FileUtils.mv bundled_app, tmp("bundled_app.bck")
- update_git "foo", "1.1", :path => lib_path("foo-1.0")
+ update_git "foo", "1.1", path: lib_path("foo-1.0")
gemfile tmp("bundled_app.bck/Gemfile"), <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -153,9 +161,9 @@ RSpec.describe "bundle install with git sources" do
gem "rack", "1.0"
G
- bundle "update foo", :dir => tmp("bundled_app.bck")
+ bundle "update foo", dir: tmp("bundled_app.bck")
- expect(the_bundle).to include_gems "foo 1.1", "rack 1.0", :dir => tmp("bundled_app.bck")
+ expect(the_bundle).to include_gems "foo 1.1", "rack 1.0", dir: tmp("bundled_app.bck")
end
end
@@ -192,6 +200,7 @@ RSpec.describe "bundle install with git sources" do
gem "foo"
end
G
+ expect(err).to be_empty
run <<-RUBY
require 'foo'
@@ -218,16 +227,55 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
+ it "works when an abbreviated revision is added after an initial, potentially shallow clone" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ git "#{lib_path("foo-1.0")}" do
+ gem "foo"
+ end
+ G
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ git "#{lib_path("foo-1.0")}", :ref => #{@revision[0..7].inspect} do
+ gem "foo"
+ end
+ 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 master
- update_git "foo", :path => lib_path("foo-1.0") do |s|
+ # want to ensure we don't fallback to main
+ update_git "foo", path: lib_path("foo-1.0") do |s|
s.write("lib/foo.rb", "raise 'FAIL'")
end
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", dir: lib_path("foo-1.0"))
# want to ensure we don't fallback to HEAD
- update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s|
+ update_git "foo", path: lib_path("foo-1.0"), branch: "rando" do |s|
s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'")
end
@@ -255,15 +303,15 @@ RSpec.describe "bundle install with git sources" do
end
G
- # want to ensure we don't fallback to master
- update_git "foo", :path => lib_path("foo-1.0") do |s|
+ # want to ensure we don't fallback to main
+ update_git "foo", path: lib_path("foo-1.0") do |s|
s.write("lib/foo.rb", "raise 'FAIL'")
end
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", dir: lib_path("foo-1.0"))
# want to ensure we don't fallback to HEAD
- update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s|
+ update_git "foo", path: lib_path("foo-1.0"), branch: "rando" do |s|
s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'")
end
@@ -284,7 +332,7 @@ RSpec.describe "bundle install with git sources" do
end
it "does not download random non-head refs" do
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", dir: lib_path("foo-1.0"))
bundle "config set global_gem_cache true"
@@ -296,9 +344,9 @@ RSpec.describe "bundle install with git sources" do
G
# ensure we also git fetch after cloning
- bundle :update, :all => true
+ bundle :update, all: true
- sys_exec("git ls-remote .", :dir => Dir[home(".bundle/cache/git/foo-*")].first)
+ sys_exec("git ls-remote .", dir: Dir[home(".bundle/cache/git/foo-*")].first)
expect(out).not_to include("refs/bundler/1")
end
@@ -309,7 +357,7 @@ RSpec.describe "bundle install with git sources" do
let(:repo) { build_git("foo").path }
it "works" do
- update_git("foo", :path => repo, :branch => branch)
+ update_git("foo", path: repo, branch: branch)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -326,7 +374,7 @@ RSpec.describe "bundle install with git sources" do
it "works" do
skip "git does not accept this" if Gem.win_platform?
- update_git("foo", :path => repo, :branch => branch)
+ update_git("foo", path: repo, branch: branch)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -344,7 +392,7 @@ RSpec.describe "bundle install with git sources" do
it "works" do
skip "git does not accept this" if Gem.win_platform?
- update_git("foo", :path => repo, :branch => branch)
+ update_git("foo", path: repo, branch: branch)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -363,7 +411,7 @@ RSpec.describe "bundle install with git sources" do
let(:repo) { build_git("foo").path }
it "works" do
- update_git("foo", :path => repo, :tag => tag)
+ update_git("foo", path: repo, tag: tag)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -380,7 +428,7 @@ RSpec.describe "bundle install with git sources" do
it "works" do
skip "git does not accept this" if Gem.win_platform?
- update_git("foo", :path => repo, :tag => tag)
+ update_git("foo", path: repo, tag: tag)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -398,7 +446,7 @@ RSpec.describe "bundle install with git sources" do
it "works" do
skip "git does not accept this" if Gem.win_platform?
- update_git("foo", :path => repo, :tag => tag)
+ update_git("foo", path: repo, tag: tag)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -414,13 +462,13 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying local override" do
it "uses the local repository instead of checking a new one out" do
- build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ build_git "rack", "0.8", path: lib_path("local-rack") do |s|
s.write "lib/rack.rb", "puts :LOCAL"
end
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -435,13 +483,13 @@ RSpec.describe "bundle install with git sources" do
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
- update_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ update_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"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -454,14 +502,14 @@ RSpec.describe "bundle install with git sources" do
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
- update_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ update_git "rack", "0.8", path: lib_path("local-rack") do |s|
s.write "rack.gemspec", build_spec("rack", "0.8") { runtime "rspec", "> 0" }.first.to_ruby
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"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -477,13 +525,13 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
lockfile0 = File.read(bundled_app_lock)
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
- update_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ update_git "rack", "0.8", path: lib_path("local-rack") do |s|
s.add_dependency "nokogiri", "1.4.2"
end
@@ -499,13 +547,13 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
lockfile0 = File.read(bundled_app_lock)
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
- update_git "rack", "0.8", :path => lib_path("local-rack")
+ update_git "rack", "0.8", path: lib_path("local-rack")
bundle %(config set local.rack #{lib_path("local-rack")})
bundle :install
@@ -519,12 +567,12 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install, :raise_on_error => false
- expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/)
+ bundle :install, raise_on_error: false
+ expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path("local-rack").to_s)} does not exist/)
solution = "config unset local.rack"
expect(err).to match(/Run `bundle #{solution}` to remove the local override/)
@@ -545,8 +593,8 @@ RSpec.describe "bundle install with git sources" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install, :raise_on_error => false
- expect(err).to match(/Cannot use local override for rack-0.8 at #{Regexp.escape(lib_path('local-rack').to_s)} because :branch is not specified in Gemfile/)
+ bundle :install, raise_on_error: false
+ expect(err).to match(/Cannot use local override for rack-0.8 at #{Regexp.escape(lib_path("local-rack").to_s)} because :branch is not specified in Gemfile/)
solution = "config unset local.rack"
expect(err).to match(/Specify a branch or run `bundle #{solution}` to remove the local override/)
@@ -577,47 +625,47 @@ RSpec.describe "bundle install with git sources" do
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
- update_git "rack", "0.8", :path => lib_path("local-rack"), :branch => "another" do |s|
+ update_git "rack", "0.8", path: lib_path("local-rack"), branch: "another" 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"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install, :raise_on_error => false
- expect(err).to match(/is using branch another but Gemfile specifies master/)
+ bundle :install, raise_on_error: false
+ expect(err).to match(/is using branch another but Gemfile specifies main/)
end
it "explodes on invalid revision on install" do
build_git "rack", "0.8"
- build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ 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"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install, :raise_on_error => false
+ 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|
+ 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"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -658,11 +706,11 @@ RSpec.describe "bundle install with git sources" do
it "installs dependencies from git even if a newer gem is available elsewhere" do
system_gems "rack-1.0.0"
- build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s|
+ build_lib "rack", "1.0", path: lib_path("nested/bar") do |s|
s.write "lib/rack.rb", "puts 'WIN OVERRIDE'"
end
- build_git "foo", :path => lib_path("nested") do |s|
+ build_git "foo", path: lib_path("nested") do |s|
s.add_dependency "rack", "= 1.0"
end
@@ -681,7 +729,7 @@ RSpec.describe "bundle install with git sources" do
gem "rack", "0.9.1"
G
- build_git "rack", :path => lib_path("rack")
+ build_git "rack", path: lib_path("rack")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -697,7 +745,7 @@ RSpec.describe "bundle install with git sources" do
gem "rack"
G
- build_git "rack", "1.2", :path => lib_path("rack")
+ build_git "rack", "1.2", path: lib_path("rack")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -710,8 +758,8 @@ RSpec.describe "bundle install with git sources" do
describe "block syntax" do
it "pulls all gems from a git block" do
- build_lib "omg", :path => lib_path("hi2u/omg")
- build_lib "hi2u", :path => lib_path("hi2u")
+ build_lib "omg", path: lib_path("hi2u/omg")
+ build_lib "hi2u", path: lib_path("hi2u")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -759,7 +807,7 @@ RSpec.describe "bundle install with git sources" do
end
it "runs the gemspec in the context of its parent directory" do
- build_lib "bar", :path => lib_path("foo/bar"), :gemspec => false do |s|
+ build_lib "bar", path: lib_path("foo/bar"), gemspec: false do |s|
s.write lib_path("foo/bar/lib/version.rb"), %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
$:.unshift Dir.pwd
@@ -774,7 +822,7 @@ RSpec.describe "bundle install with git sources" do
G
end
- build_git "foo", :path => lib_path("foo") do |s|
+ build_git "foo", path: lib_path("foo") do |s|
s.write "bin/foo", ""
end
@@ -789,7 +837,7 @@ RSpec.describe "bundle install with git sources" do
end
it "installs from git even if a rubygems gem is present" do
- build_gem "foo", "1.0", :path => lib_path("fake_foo"), :to_system => true do |s|
+ build_gem "foo", "1.0", path: lib_path("fake_foo"), to_system: true do |s|
s.write "lib/foo.rb", "raise 'FAIL'"
end
@@ -804,7 +852,7 @@ RSpec.describe "bundle install with git sources" do
end
it "fakes the gem out if there is no gemspec" do
- build_git "foo", :gemspec => false
+ build_git "foo", gemspec: false
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -822,7 +870,7 @@ RSpec.describe "bundle install with git sources" do
gem "foo", "1.0", :git => "omgomg"
G
- bundle :install, :raise_on_error => false
+ bundle :install, raise_on_error: false
expect(err).to include("Git error:")
expect(err).to include("fatal")
@@ -830,7 +878,7 @@ RSpec.describe "bundle install with git sources" do
end
it "works when the gem path has spaces in it" do
- build_git "foo", :path => lib_path("foo space-1.0")
+ build_git "foo", path: lib_path("foo space-1.0")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -855,41 +903,47 @@ RSpec.describe "bundle install with git sources" do
s.write "lib/forced.rb", "FORCED = '1.1'"
end
- bundle "update", :all => true
+ bundle "update", all: true
expect(the_bundle).to include_gems "forced 1.1"
- sys_exec("git reset --hard HEAD^", :dir => lib_path("forced-1.0"))
+ sys_exec("git reset --hard HEAD^", dir: lib_path("forced-1.0"))
- bundle "update", :all => true
+ bundle "update", all: true
expect(the_bundle).to include_gems "forced 1.0"
end
it "ignores submodules if :submodule is not passed" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
end
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
- sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", dir: lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", dir: lib_path("has_submodule-1.0")
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
G
- expect(err).to match(/could not find gem 'submodule/i)
+ expect(err).to match(%r{submodule >= 0 could not be found in rubygems repository #{file_uri_for(gem_repo1)}/, cached gems or installed locally})
expect(the_bundle).not_to include_gems "has_submodule 1.0"
end
it "handles repos with submodules" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
end
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
- sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", dir: lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", dir: lib_path("has_submodule-1.0")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -902,11 +956,14 @@ RSpec.describe "bundle install with git sources" do
end
it "does not warn when deiniting submodules" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
build_git "has_submodule", "1.0"
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
- sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", dir: lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", dir: lib_path("has_submodule-1.0")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -980,7 +1037,7 @@ RSpec.describe "bundle install with git sources" do
FileUtils.mkdir_p(default_bundle_path)
FileUtils.touch(default_bundle_path("bundler"))
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -992,11 +1049,11 @@ RSpec.describe "bundle install with git sources" do
end
it "does not duplicate git gem sources" do
- build_lib "foo", :path => lib_path("nested/foo")
- build_lib "bar", :path => lib_path("nested/bar")
+ build_lib "foo", path: lib_path("nested/foo")
+ build_lib "bar", path: lib_path("nested/bar")
- build_git "foo", :path => lib_path("nested")
- build_git "bar", :path => lib_path("nested")
+ build_git "foo", path: lib_path("nested")
+ build_git "bar", path: lib_path("nested")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -1009,11 +1066,11 @@ RSpec.describe "bundle install with git sources" do
describe "switching sources" do
it "doesn't explode when switching Path to Git sources" do
- build_gem "foo", "1.0", :to_system => true do |s|
+ build_gem "foo", "1.0", to_system: true do |s|
s.write "lib/foo.rb", "raise 'fail'"
end
- build_lib "foo", "1.0", :path => lib_path("bar/foo")
- build_git "bar", "1.0", :path => lib_path("bar") do |s|
+ build_lib "foo", "1.0", path: lib_path("bar/foo")
+ build_git "bar", "1.0", path: lib_path("bar") do |s|
s.add_dependency "foo"
end
@@ -1088,17 +1145,28 @@ RSpec.describe "bundle install with git sources" do
G
expect(out).to_not match(/Revision.*does not exist/)
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :ref => "deadbeef"
G
expect(err).to include("Revision deadbeef does not exist in the repository")
end
+
+ it "gives a helpful error message when the remote branch no longer exists" do
+ build_git "foo"
+
+ install_gemfile <<-G, env: { "LANG" => "en" }, raise_on_error: false
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :branch => "deadbeef"
+ G
+
+ expect(err).to include("Revision deadbeef does not exist in the repository")
+ end
end
describe "bundle install with deployment mode configured and git sources" do
it "works" do
- build_git "valim", :path => lib_path("valim")
+ build_git "valim", path: lib_path("valim")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -1129,7 +1197,7 @@ RSpec.describe "bundle install with git sources" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
+ requires: [lib_path("install_hooks.rb")]
expect(err_without_deprecations).to eq("Ran pre-install hook: foo-1.0")
end
@@ -1149,7 +1217,7 @@ RSpec.describe "bundle install with git sources" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
+ requires: [lib_path("install_hooks.rb")]
expect(err_without_deprecations).to eq("Ran post-install hook: foo-1.0")
end
@@ -1168,7 +1236,7 @@ RSpec.describe "bundle install with git sources" do
H
end
- bundle :install, :requires => [lib_path("install_hooks.rb")], :raise_on_error => false
+ bundle :install, requires: [lib_path("install_hooks.rb")], raise_on_error: false
expect(err).to include("failed for foo-1.0")
end
end
@@ -1206,8 +1274,8 @@ RSpec.describe "bundle install with git sources" do
expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
end
- it "does not use old extension after ref changes", :ruby_repo do
- git_reader = build_git "foo", :no_default => true do |s|
+ it "does not use old extension after ref changes" do
+ git_reader = build_git "foo", no_default: true do |s|
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-RUBY
require "mkmf"
@@ -1224,7 +1292,7 @@ RSpec.describe "bundle install with git sources" do
void Init_foo() { rb_define_global_function("foo", &foo, 0); }
C
end
- sys_exec("git commit -m \"commit for iteration #{i}\" ext/foo.c", :dir => git_reader.path)
+ sys_exec("git commit -m \"commit for iteration #{i}\" ext/foo.c", dir: git_reader.path)
git_commit_sha = git_reader.ref_for("HEAD")
@@ -1253,7 +1321,7 @@ RSpec.describe "bundle install with git sources" do
RUBY
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1379,7 +1447,7 @@ In Gemfile:
installed_time = out
- update_git("foo", :branch => "branch2")
+ update_git("foo", branch: "branch2")
expect(installed_time).to match(/\A\d+\.\d+\z/)
@@ -1430,8 +1498,6 @@ In Gemfile:
describe "without git installed" do
it "prints a better error message when installing" do
- build_git "foo"
-
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -1460,7 +1526,7 @@ In Gemfile:
L
with_path_as("") do
- bundle "install", :raise_on_error => false
+ bundle "install", raise_on_error: false
end
expect(err).
to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git")
@@ -1477,7 +1543,7 @@ In Gemfile:
G
with_path_as("") do
- bundle "update", :all => true, :raise_on_error => false
+ bundle "update", all: true, raise_on_error: false
end
expect(err).
to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git")
@@ -1496,7 +1562,7 @@ In Gemfile:
bundle :cache
simulate_new_machine
- bundle "install", :env => { "PATH" => "" }
+ bundle "install", env: { "PATH" => "" }
expect(out).to_not include("You need to install git to be able to use gems from git repositories.")
end
end
@@ -1514,11 +1580,11 @@ In Gemfile:
end
it "installs successfully" do
- build_git "foo", "1.0", :path => lib_path("foo")
+ build_git "foo", "1.0", path: lib_path("foo")
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{lib_path("foo")}", :branch => "master"
+ gem "foo", :git => "#{lib_path("foo")}", :branch => "main"
G
bundle :install
@@ -1532,7 +1598,7 @@ In Gemfile:
let(:credentials) { "user1:password1" }
it "does not display the password" do
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
git "https://#{credentials}@github.com/company/private-repo" do
gem "foo"
@@ -1548,7 +1614,7 @@ In Gemfile:
let(:credentials) { "oauth_token" }
it "displays the oauth scheme but not the oauth token" do
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
git "https://#{credentials}:x-oauth-basic@github.com/company/private-repo" do
gem "foo"
diff --git a/spec/bundler/install/gemfile/groups_spec.rb b/spec/bundler/install/gemfile/groups_spec.rb
index 734e012e84..f7907a9cad 100644
--- a/spec/bundler/install/gemfile/groups_spec.rb
+++ b/spec/bundler/install/gemfile/groups_spec.rb
@@ -88,32 +88,32 @@ RSpec.describe "bundle install with groups" do
it "installs gems in the default group" do
bundle "config set --local without emo"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
+ expect(the_bundle).to include_gems "rack 1.0.0", groups: [:default]
end
it "respects global `without` configuration, but does not save it locally" do
bundle "config set --global without emo"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
+ expect(the_bundle).to include_gems "rack 1.0.0", groups: [:default]
bundle "config list"
expect(out).not_to include("Set for your local app (#{bundled_app(".bundle/config")}): [:emo]")
expect(out).to include("Set for the current user (#{home(".bundle/config")}): [:emo]")
end
- it "allows running application where groups where configured by a different user", :bundler => "< 3" do
+ it "allows running application where groups where configured by a different user", bundler: "< 3" do
bundle "config set without emo"
bundle :install
- bundle "exec ruby -e 'puts 42'", :env => { "BUNDLE_USER_HOME" => tmp("new_home").to_s }
+ bundle "exec ruby -e 'puts 42'", env: { "BUNDLE_USER_HOME" => tmp("new_home").to_s }
expect(out).to include("42")
end
it "does not install gems from the excluded group" do
bundle "config set --local without emo"
bundle :install
- expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default]
+ expect(the_bundle).not_to include_gems "activesupport 2.3.5", groups: [:default]
end
- it "remembers previous exclusion with `--without`", :bundler => "< 3" do
+ it "remembers previous exclusion with `--without`", bundler: "< 3" do
bundle "install --without emo"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
bundle :install
@@ -144,7 +144,7 @@ RSpec.describe "bundle install with groups" do
bundle "config set --local without emo"
bundle :install
- expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => [:default]
+ expect(the_bundle).to include_gems "activesupport 2.3.2", groups: [:default]
end
it "still works when BUNDLE_WITHOUT is set" do
@@ -153,20 +153,20 @@ RSpec.describe "bundle install with groups" do
bundle :install
expect(out).not_to include("activesupport")
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
- expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default]
+ expect(the_bundle).to include_gems "rack 1.0.0", groups: [:default]
+ expect(the_bundle).not_to include_gems "activesupport 2.3.5", groups: [:default]
ENV["BUNDLE_WITHOUT"] = nil
end
- it "clears --without when passed an empty list", :bundler => "< 3" do
+ it "clears --without when passed an empty list", bundler: "< 3" do
bundle "install --without emo"
bundle "install --without ''"
expect(the_bundle).to include_gems "activesupport 2.3.5"
end
- it "doesn't clear without when nothing is passed", :bundler => "< 3" do
+ it "doesn't clear without when nothing is passed", bundler: "< 3" do
bundle "install --without emo"
bundle :install
@@ -184,7 +184,7 @@ RSpec.describe "bundle install with groups" do
expect(the_bundle).to include_gems "thin 1.0"
end
- it "installs gems from the previously requested group", :bundler => "< 3" do
+ it "installs gems from the previously requested group", bundler: "< 3" do
bundle "install --with debugging"
expect(the_bundle).to include_gems "thin 1.0"
bundle :install
@@ -198,26 +198,26 @@ RSpec.describe "bundle install with groups" do
ENV["BUNDLE_WITH"] = nil
end
- it "clears --with when passed an empty list", :bundler => "< 3" do
+ it "clears --with when passed an empty list", bundler: "< 3" do
bundle "install --with debugging"
bundle "install --with ''"
expect(the_bundle).not_to include_gems "thin 1.0"
end
- it "removes groups from without when passed at --with", :bundler => "< 3" do
+ it "removes groups from without when passed at --with", bundler: "< 3" do
bundle "config set --local without emo"
bundle "install --with emo"
expect(the_bundle).to include_gems "activesupport 2.3.5"
end
- it "removes groups from with when passed at --without", :bundler => "< 3" do
+ it "removes groups from with when passed at --without", bundler: "< 3" do
bundle "config set --local with debugging"
- bundle "install --without debugging", :raise_on_error => false
+ bundle "install --without debugging", raise_on_error: false
expect(the_bundle).not_to include_gem "thin 1.0"
end
- it "errors out when passing a group to with and without via CLI flags", :bundler => "< 3" do
- bundle "install --with emo debugging --without emo", :raise_on_error => false
+ it "errors out when passing a group to with and without via CLI flags", bundler: "< 3" do
+ bundle "install --with emo debugging --without emo", raise_on_error: false
expect(last_command).to be_failure
expect(err).to include("The offending groups are: emo")
end
@@ -235,7 +235,7 @@ RSpec.describe "bundle install with groups" do
expect(the_bundle).to include_gem "thin 1.0"
end
- it "can add and remove a group at the same time", :bundler => "< 3" do
+ it "can add and remove a group at the same time", bundler: "< 3" do
bundle "install --with debugging --without emo"
expect(the_bundle).to include_gems "thin 1.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
@@ -349,7 +349,7 @@ RSpec.describe "bundle install with groups" do
G
ruby <<-R
- require "#{entrypoint}"
+ require "bundler"
Bundler.setup :default
Bundler.require :default
puts RACK
@@ -396,7 +396,7 @@ RSpec.describe "bundle install with groups" do
it "does not hit the remote a second time" do
FileUtils.rm_rf gem_repo2
bundle "config set --local without rack"
- bundle :install, :verbose => true
+ bundle :install, verbose: true
expect(last_command.stdboth).not_to match(/fetching/i)
end
end
diff --git a/spec/bundler/install/gemfile/install_if_spec.rb b/spec/bundler/install/gemfile/install_if_spec.rb
index 3d2d15a698..c7640d07e1 100644
--- a/spec/bundler/install/gemfile/install_if_spec.rb
+++ b/spec/bundler/install/gemfile/install_if_spec.rb
@@ -18,6 +18,13 @@ RSpec.describe "bundle install with install_if conditionals" do
expect(the_bundle).not_to include_gems("thin")
expect(the_bundle).not_to include_gems("foo")
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo1, "activesupport", "2.3.5"
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo1, "rack", "1.0.0"
+ c.no_checksum "thin", "1.0"
+ end
+
expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
@@ -36,7 +43,7 @@ RSpec.describe "bundle install with install_if conditionals" do
foo
rack
thin
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
diff --git a/spec/bundler/install/gemfile/lockfile_spec.rb b/spec/bundler/install/gemfile/lockfile_spec.rb
index 313e99d0b8..4601d3e2a8 100644
--- a/spec/bundler/install/gemfile/lockfile_spec.rb
+++ b/spec/bundler/install/gemfile/lockfile_spec.rb
@@ -11,6 +11,11 @@ RSpec.describe "bundle install with a lockfile present" do
install_gemfile(gf)
end
+ it "touches the lockfile on install even when nothing has changed" do
+ subject
+ expect { bundle :install }.to change { bundled_app_lock.mtime }
+ end
+
context "gemfile evaluation" do
let(:gf) { super() + "\n\n File.open('evals', 'a') {|f| f << %(1\n) } unless ENV['BUNDLER_SPEC_NO_APPEND']" }
diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb
index 515901064f..a57b7ee560 100644
--- a/spec/bundler/install/gemfile/path_spec.rb
+++ b/spec/bundler/install/gemfile/path_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe "bundle install with explicit source paths" do
- it "fetches gems with a global path source", :bundler => "< 3" do
+ it "fetches gems with a global path source", bundler: "< 3" do
build_lib "foo"
install_gemfile <<-G
@@ -69,7 +69,7 @@ RSpec.describe "bundle install with explicit source paths" do
username = "some_unexisting_user"
relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new("/home/#{username}").expand_path)
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => "~#{username}/#{relative_path}"
G
@@ -78,27 +78,30 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "expands paths relative to Bundler.root" do
- build_lib "foo", :path => bundled_app("foo-1.0")
+ build_lib "foo", path: bundled_app("foo-1.0")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => "./foo-1.0"
G
- expect(the_bundle).to include_gems("foo 1.0", :dir => bundled_app("subdir").mkpath)
+ expect(the_bundle).to include_gems("foo 1.0", dir: bundled_app("subdir").mkpath)
end
it "sorts paths consistently on install and update when they start with ./" do
- build_lib "demo", :path => lib_path("demo")
- build_lib "aaa", :path => lib_path("demo/aaa")
+ 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 }
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "aaa", "1.0"
+ c.no_checksum "demo", "1.0"
+ end
lockfile = <<~L
PATH
@@ -121,19 +124,19 @@ RSpec.describe "bundle install with explicit source paths" do
DEPENDENCIES
aaa!
demo!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
- bundle :install, :dir => lib_path("demo")
+ bundle :install, dir: lib_path("demo")
expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile)
- bundle :update, :all => true, :dir => lib_path("demo")
+ bundle :update, all: true, dir: lib_path("demo")
expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile)
end
it "expands paths when comparing locked paths to Gemfile paths" do
- build_lib "foo", :path => bundled_app("foo-1.0")
+ build_lib "foo", path: bundled_app("foo-1.0")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -147,11 +150,11 @@ RSpec.describe "bundle install with explicit source paths" do
it "installs dependencies from the path even if a newer gem is available elsewhere" do
system_gems "rack-1.0.0"
- build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s|
+ build_lib "rack", "1.0", path: lib_path("nested/bar") do |s|
s.write "lib/rack.rb", "puts 'WIN OVERRIDE'"
end
- build_lib "foo", :path => lib_path("nested") do |s|
+ build_lib "foo", path: lib_path("nested") do |s|
s.add_dependency "rack", "= 1.0"
end
@@ -165,15 +168,15 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "works" do
- build_gem "foo", "1.0.0", :to_system => true do |s|
+ build_gem "foo", "1.0.0", to_system: true do |s|
s.write "lib/foo.rb", "puts 'FAIL'"
end
- build_lib "omg", "1.0", :path => lib_path("omg") do |s|
+ build_lib "omg", "1.0", path: lib_path("omg") do |s|
s.add_dependency "foo"
end
- build_lib "foo", "1.0.0", :path => lib_path("omg/foo")
+ build_lib "foo", "1.0.0", path: lib_path("omg/foo")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -184,7 +187,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "works when using prereleases of 0.0.0" do
- build_lib "foo", "0.0.0.dev", :path => lib_path("foo")
+ build_lib "foo", "0.0.0.dev", path: lib_path("foo")
gemfile <<~G
source "#{file_uri_for(gem_repo1)}"
@@ -217,7 +220,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "works when using uppercase prereleases of 0.0.0" do
- build_lib "foo", "0.0.0.SNAPSHOT", :path => lib_path("foo")
+ build_lib "foo", "0.0.0.SNAPSHOT", path: lib_path("foo")
gemfile <<~G
source "#{file_uri_for(gem_repo1)}"
@@ -250,14 +253,14 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "handles downgrades" do
- build_lib "omg", "2.0", :path => lib_path("omg")
+ build_lib "omg", "2.0", path: lib_path("omg")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "omg", :path => "#{lib_path("omg")}"
G
- build_lib "omg", "1.0", :path => lib_path("omg")
+ build_lib "omg", "1.0", path: lib_path("omg")
bundle :install
@@ -265,7 +268,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "prefers gemspecs closer to the path root" do
- build_lib "premailer", "1.0.0", :path => lib_path("premailer") do |s|
+ build_lib "premailer", "1.0.0", path: lib_path("premailer") do |s|
s.write "gemfiles/ruby187.gemspec", <<-G
Gem::Specification.new do |s|
s.name = 'premailer'
@@ -298,7 +301,7 @@ RSpec.describe "bundle install with explicit source paths" do
G
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
@@ -310,24 +313,78 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "supports gemspec syntax" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
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")
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "0.1.0"
+ c.checksum gem_repo4, "graphql", "2.0.15"
+ end
+
+ 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}
- 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")
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ 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|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack", "1.0"
end
@@ -341,48 +398,48 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "doesn't automatically unlock dependencies when using the gemspec syntax" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack", ">= 1.0"
end
- install_gemfile lib_path("foo/Gemfile"), <<-G, :dir => lib_path("foo")
+ install_gemfile lib_path("foo/Gemfile"), <<-G, dir: lib_path("foo")
source "#{file_uri_for(gem_repo1)}"
gemspec
G
- build_gem "rack", "1.0.1", :to_system => true
+ build_gem "rack", "1.0.1", to_system: true
- bundle "install", :dir => lib_path("foo")
+ 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")
+ 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 "doesn't automatically unlock dependencies when using the gemspec syntax and the gem has development dependencies" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack", ">= 1.0"
s.add_development_dependency "activesupport"
end
- install_gemfile lib_path("foo/Gemfile"), <<-G, :dir => lib_path("foo")
+ install_gemfile lib_path("foo/Gemfile"), <<-G, dir: lib_path("foo")
source "#{file_uri_for(gem_repo1)}"
gemspec
G
- build_gem "rack", "1.0.1", :to_system => true
+ build_gem "rack", "1.0.1", to_system: true
- bundle "install", :dir => lib_path("foo")
+ 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")
+ 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 "raises if there are multiple gemspecs" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.write "bar.gemspec", build_spec("bar", "1.0").first.to_ruby
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gemspec :path => "#{lib_path("foo")}"
G
@@ -392,7 +449,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "allows :name to be specified to resolve ambiguity" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.write "bar.gemspec"
end
@@ -409,7 +466,7 @@ RSpec.describe "bundle install with explicit source paths" do
s.executables = "foobar"
end
- install_gemfile <<-G, :verbose => true
+ install_gemfile <<-G, verbose: true
source "#{file_uri_for(gem_repo1)}"
path "#{lib_path("foo-1.0")}" do
gem 'foo'
@@ -463,9 +520,9 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "keeps source pinning" do
- build_lib "foo", "1.0", :path => lib_path("foo")
- build_lib "omg", "1.0", :path => lib_path("omg")
- build_lib "foo", "1.0", :path => lib_path("omg/foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo")
+ build_lib "omg", "1.0", path: lib_path("omg")
+ build_lib "foo", "1.0", path: lib_path("omg/foo") do |s|
s.write "lib/foo.rb", "puts 'FAIL'"
end
@@ -479,7 +536,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "works when the path does not have a gemspec" do
- build_lib "foo", :gemspec => false
+ build_lib "foo", gemspec: false
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -517,17 +574,17 @@ RSpec.describe "bundle install with explicit source paths" do
gem 'net-ssh', '1.0'
G
- bundle :check, :env => { "DEBUG" => "1" }
+ bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
expect(the_bundle).to include_gems "rack-obama 1.0", "net-ssh 1.0"
end
it "source path gems w/deps don't re-resolve without changes" do
- build_lib "rack-obama", "1.0", :path => lib_path("omg") do |s|
+ build_lib "rack-obama", "1.0", path: lib_path("omg") do |s|
s.add_dependency "yard"
end
- build_lib "net-ssh", "1.0", :path => lib_path("omg") do |s|
+ build_lib "net-ssh", "1.0", path: lib_path("omg") do |s|
s.add_dependency "yard"
end
@@ -537,7 +594,7 @@ RSpec.describe "bundle install with explicit source paths" do
gem 'net-ssh', :path => "#{lib_path("omg")}"
G
- bundle :check, :env => { "DEBUG" => "1" }
+ bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
expect(the_bundle).to include_gems "rack-obama 1.0", "net-ssh 1.0"
end
@@ -559,10 +616,10 @@ RSpec.describe "bundle install with explicit source paths" do
describe "when the gem version in the path is updated" do
before :each do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "bar"
end
- build_lib "bar", "1.0", :path => lib_path("foo/bar")
+ build_lib "bar", "1.0", path: lib_path("foo/bar")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -571,7 +628,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "unlocks all gems when the top level gem is updated" do
- build_lib "foo", "2.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "2.0", path: lib_path("foo") do |s|
s.add_dependency "bar"
end
@@ -581,7 +638,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "unlocks all gems when a child dependency gem is updated" do
- build_lib "bar", "2.0", :path => lib_path("foo/bar")
+ build_lib "bar", "2.0", path: lib_path("foo/bar")
bundle "install"
@@ -591,7 +648,7 @@ RSpec.describe "bundle install with explicit source paths" do
describe "when dependencies in the path are updated" do
before :each do
- build_lib "foo", "1.0", :path => lib_path("foo")
+ build_lib "foo", "1.0", path: lib_path("foo")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -600,7 +657,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "gets dependencies that are updated in the path" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack"
end
@@ -610,7 +667,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "keeps using the same version if it's compatible" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack", "0.9.1"
end
@@ -618,6 +675,11 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "rack 0.9.1"
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo1, "rack", "0.9.1"
+ end
+
expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
@@ -635,12 +697,12 @@ RSpec.describe "bundle install with explicit source paths" do
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack"
end
@@ -663,7 +725,7 @@ RSpec.describe "bundle install with explicit source paths" do
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
@@ -672,7 +734,7 @@ RSpec.describe "bundle install with explicit source paths" do
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|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack", "0.9.1"
end
@@ -680,6 +742,11 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "rack 0.9.1"
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo1, "rack", "0.9.1"
+ end
+
expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
@@ -697,53 +764,107 @@ RSpec.describe "bundle install with explicit source paths" do
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "rack"
- s.add_dependency "rake", "13.0.1"
+ s.add_dependency "rake", rake_version
end
bundle "install"
+ checksums.checksum gem_repo1, "rake", rake_version
+
expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
specs:
foo (1.0)
rack
- rake (= 13.0.1)
+ rake (= #{rake_version})
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
rack (0.9.1)
- rake (13.0.1)
+ rake (#{rake_version})
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
expect(the_bundle).to include_gems "rack 0.9.1"
end
+
+ it "does not remove existing ruby platform" do
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "rack", "0.9.1"
+ end
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "foo", "1.0"
+ end
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ checksums.no_checksum "rack", "0.9.1"
+
+ expect(lockfile).to eq <<~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("ruby")}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
end
describe "switching sources" do
it "doesn't switch pinned git sources to rubygems when pinning the parent gem to a path source" do
- build_gem "foo", "1.0", :to_system => true do |s|
+ build_gem "foo", "1.0", to_system: true do |s|
s.write "lib/foo.rb", "raise 'fail'"
end
- build_lib "foo", "1.0", :path => lib_path("bar/foo")
- build_git "bar", "1.0", :path => lib_path("bar") do |s|
+ build_lib "foo", "1.0", path: lib_path("bar/foo")
+ build_git "bar", "1.0", path: lib_path("bar") do |s|
s.add_dependency "foo"
end
@@ -761,8 +882,8 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "switches the source when the gem existed in rubygems and the path was already being used for another gem" do
- build_lib "foo", "1.0", :path => lib_path("foo")
- build_gem "bar", "1.0", :to_bundle => true do |s|
+ build_lib "foo", "1.0", path: lib_path("foo")
+ build_gem "bar", "1.0", to_bundle: true do |s|
s.write "lib/bar.rb", "raise 'fail'"
end
@@ -774,7 +895,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
G
- build_lib "bar", "1.0", :path => lib_path("foo/bar")
+ build_lib "bar", "1.0", path: lib_path("foo/bar")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -790,19 +911,17 @@ 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
+ build_lib "private_lib", "2.2", path: lib_path("private_lib")
+ 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")
+ 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/)
- expect(the_bundle).to include_gems "private_lib 2.2", :dir => lib_path("private_lib")
- expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("private_lib")
+ expect(the_bundle).to include_gems "private_lib 2.2", dir: lib_path("private_lib")
+ expect(the_bundle).to include_gems "rack 1.0", dir: lib_path("private_lib")
end
end
@@ -823,7 +942,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
+ requires: [lib_path("install_hooks.rb")]
expect(err_without_deprecations).to eq("Ran pre-install hook: foo-1.0")
end
@@ -843,7 +962,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
+ requires: [lib_path("install_hooks.rb")]
expect(err_without_deprecations).to eq("Ran post-install hook: foo-1.0")
end
@@ -862,7 +981,7 @@ RSpec.describe "bundle install with explicit source paths" do
H
end
- bundle :install, :requires => [lib_path("install_hooks.rb")], :raise_on_error => false
+ bundle :install, requires: [lib_path("install_hooks.rb")], raise_on_error: false
expect(err).to include("failed for foo-1.0")
end
diff --git a/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb
index cf80844b02..d90dacdc02 100644
--- a/spec/bundler/install/gemfile/platform_spec.rb
+++ b/spec/bundler/install/gemfile/platform_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe "bundle install across platforms" do
expect(the_bundle).to include_gems "platform_specific 1.0 JAVA"
end
- it "pulls the pure ruby version on jruby if the java platform is not present in the lockfile and bundler is run in frozen mode", :jruby do
+ it "pulls the pure ruby version on jruby if the java platform is not present in the lockfile and bundler is run in frozen mode", :jruby_only do
lockfile <<-G
GEM
remote: #{file_uri_for(gem_repo1)}
@@ -75,6 +75,81 @@ RSpec.describe "bundle install across platforms" do
expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
end
+ context "on universal Rubies" do
+ before do
+ build_repo4 do
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "ruby"
+ s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 RUBY'"
+ end
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "arm64-darwin"
+ s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 arm64-darwin'"
+ end
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "x86_64-darwin"
+ s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 x86_64-darwin'"
+ end
+ end
+ end
+
+ it "pulls in the correct architecture gem" do
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}
+ specs:
+ darwin_single_arch (1.0)
+ darwin_single_arch (1.0-arm64-darwin)
+ darwin_single_arch (1.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ darwin_single_arch
+ G
+
+ simulate_platform "universal-darwin-21"
+ simulate_ruby_platform "universal.x86_64-darwin21" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "darwin_single_arch"
+ G
+
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 x86_64-darwin"
+ end
+ end
+
+ it "pulls in the correct architecture gem on arm64e macOS Ruby" do
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}
+ specs:
+ darwin_single_arch (1.0)
+ darwin_single_arch (1.0-arm64-darwin)
+ darwin_single_arch (1.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ darwin_single_arch
+ G
+
+ simulate_platform "universal-darwin-21"
+ simulate_ruby_platform "universal.arm64e-darwin21" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "darwin_single_arch"
+ G
+
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 arm64-darwin"
+ end
+ end
+ end
+
it "works with gems that have different dependencies" do
simulate_platform "java"
install_gemfile <<-G
@@ -128,6 +203,15 @@ RSpec.describe "bundle install across platforms" do
gem "pry"
G
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "coderay", "1.1.2"
+ c.checksum gem_repo4, "empyrean", "0.1.0"
+ c.checksum gem_repo4, "ffi", "1.9.23", "java"
+ c.checksum gem_repo4, "method_source", "0.9.0"
+ c.checksum gem_repo4, "pry", "0.11.3", "java"
+ c.checksum gem_repo4, "spoon", "0.0.6"
+ end
+
expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
@@ -149,7 +233,7 @@ RSpec.describe "bundle install across platforms" do
DEPENDENCIES
empyrean (= 0.1.0)
pry
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -181,7 +265,7 @@ RSpec.describe "bundle install across platforms" do
DEPENDENCIES
empyrean (= 0.1.0)
pry
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -214,30 +298,30 @@ RSpec.describe "bundle install across platforms" do
DEPENDENCIES
empyrean (= 0.1.0)
pry
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ 1.16.1
L
aggregate_failures do
lockfile bad_lockfile
- bundle :install
+ bundle :install, env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle :update, :all => true
+ bundle :update, all: true, env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle "update ffi"
+ bundle "update ffi", env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle "update empyrean"
+ bundle "update empyrean", env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle :lock
+ bundle :lock, env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(lockfile).to eq good_lockfile
end
end
@@ -288,6 +372,11 @@ RSpec.describe "bundle install across platforms" do
end
it "keeps existing platforms when installing with force_ruby_platform" do
+ checksums = checksums_section do |c|
+ c.no_checksum "platform_specific", "1.0"
+ c.no_checksum "platform_specific", "1.0", "java"
+ end
+
lockfile <<-G
GEM
remote: #{file_uri_for(gem_repo1)}/
@@ -299,6 +388,7 @@ RSpec.describe "bundle install across platforms" do
DEPENDENCIES
platform_specific
+ #{checksums}
G
bundle "config set --local force_ruby_platform true"
@@ -308,6 +398,8 @@ RSpec.describe "bundle install across platforms" do
gem "platform_specific"
G
+ checksums.checksum gem_repo1, "platform_specific", "1.0"
+
expect(the_bundle).to include_gem "platform_specific 1.0 RUBY"
expect(lockfile).to eq <<~G
@@ -323,7 +415,7 @@ RSpec.describe "bundle install across platforms" do
DEPENDENCIES
platform_specific
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
@@ -332,8 +424,6 @@ end
RSpec.describe "bundle install with platform conditionals" do
it "installs gems tagged w/ the current platforms" do
- skip "platform issues" if Gem.win_platform?
-
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -386,7 +476,7 @@ RSpec.describe "bundle install with platform conditionals" do
tzinfo (2.0.4)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
activesupport
@@ -402,8 +492,6 @@ RSpec.describe "bundle install with platform conditionals" do
end
it "installs gems tagged w/ the current platforms inline" do
- skip "platform issues" if Gem.win_platform?
-
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri", :platforms => :#{local_tag}
@@ -422,8 +510,6 @@ RSpec.describe "bundle install with platform conditionals" do
end
it "installs gems tagged w/ the current platform inline" do
- skip "platform issues" if Gem.win_platform?
-
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri", :platform => :#{local_tag}
@@ -466,11 +552,9 @@ RSpec.describe "bundle install with platform conditionals" do
it "does not attempt to install gems from other rubies when using --local" do
bundle "config set --local force_ruby_platform true"
- other_ruby_version_tag = RUBY_VERSION =~ /^1\.8/ ? :ruby_19 : :ruby_18
-
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "some_gem", platform: :#{other_ruby_version_tag}
+ gem "some_gem", platform: :ruby_22
G
bundle "install --local"
@@ -483,7 +567,7 @@ RSpec.describe "bundle install with platform conditionals" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby]
+ gem "rack", :platform => [:windows, :mswin, :mswin64, :mingw, :x64_mingw, :jruby]
G
bundle "install"
@@ -500,16 +584,36 @@ RSpec.describe "bundle install with platform conditionals" do
DEPENDENCIES
rack
-
+ #{checksums_section_when_existing}
BUNDLED WITH
#{Bundler::VERSION}
L
end
+
+ it "resolves fine when a dependency is unused on a platform different from the current one, but reintroduced transitively" do
+ bundle "config set --local force_ruby_platform true"
+
+ build_repo4 do
+ build_gem "listen", "3.7.1" do |s|
+ s.add_dependency "ffi"
+ end
+
+ build_gem "ffi", "1.15.5"
+ end
+
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "listen"
+ gem "ffi", :platform => :windows
+ G
+ expect(err).to be_empty
+ end
end
RSpec.describe "when a gem has no architecture" do
it "still installs correctly" do
- simulate_platform mswin
+ simulate_platform x86_mswin32
build_repo2 do
# The rcov gem is platform mswin32, but has no arch
@@ -525,7 +629,7 @@ RSpec.describe "when a gem has no architecture" do
gem "rcov"
G
- bundle :install, :artifice => "windows", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle :install, artifice: "windows", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(the_bundle).to include_gems "rcov 1.0.0"
end
end
diff --git a/spec/bundler/install/gemfile/ruby_spec.rb b/spec/bundler/install/gemfile/ruby_spec.rb
index ba250acfdd..b64d633fd3 100644
--- a/spec/bundler/install/gemfile/ruby_spec.rb
+++ b/spec/bundler/install/gemfile/ruby_spec.rb
@@ -11,13 +11,13 @@ RSpec.describe "ruby requirement" do
it "allows adding gems" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "#{RUBY_VERSION}"
+ ruby "#{Gem.ruby_version}"
gem "rack"
G
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "#{RUBY_VERSION}"
+ ruby "#{Gem.ruby_version}"
gem "rack"
gem "rack-obama"
G
@@ -28,7 +28,7 @@ RSpec.describe "ruby requirement" do
it "allows removing the ruby version requirement" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "~> #{RUBY_VERSION}"
+ ruby "~> #{Gem.ruby_version}"
gem "rack"
G
@@ -46,7 +46,7 @@ RSpec.describe "ruby requirement" do
it "allows changing the ruby version requirement to something compatible" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby ">= #{RUBY_VERSION[0..2]}.0"
+ ruby ">= #{current_ruby_minor}"
gem "rack"
G
@@ -55,7 +55,7 @@ RSpec.describe "ruby requirement" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby ">= #{RUBY_VERSION}"
+ ruby ">= #{Gem.ruby_version}"
gem "rack"
G
@@ -93,7 +93,7 @@ RSpec.describe "ruby requirement" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby ">= #{RUBY_VERSION[0..2]}.0"
+ ruby ">= #{current_ruby_minor}"
gem "rack"
G
@@ -104,7 +104,7 @@ RSpec.describe "ruby requirement" do
it "allows requirements with trailing whitespace" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "#{RUBY_VERSION}\\n \t\\n"
+ ruby "#{Gem.ruby_version}\\n \t\\n"
gem "rack"
G
@@ -112,7 +112,7 @@ RSpec.describe "ruby requirement" do
end
it "fails gracefully with malformed requirements" do
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
ruby ">= 0", "-.\\0"
gem "rack"
@@ -120,4 +120,38 @@ RSpec.describe "ruby requirement" do
expect(err).to include("There was an error parsing") # i.e. DSL error, not error template
end
+
+ it "allows picking up ruby version from a file" do
+ create_file ".ruby-version", Gem.ruby_version.to_s
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ ruby file: ".ruby-version"
+ gem "rack"
+ G
+
+ expect(lockfile).to include("RUBY VERSION")
+ end
+
+ it "reads the ruby version file from the right folder when nested Gemfiles are involved" do
+ create_file ".ruby-version", Gem.ruby_version.to_s
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ ruby file: ".ruby-version"
+ gem "rack"
+ G
+
+ nested_dir = bundled_app(".ruby-lsp")
+
+ FileUtils.mkdir nested_dir
+
+ create_file ".ruby-lsp/Gemfile", <<-G
+ eval_gemfile(File.expand_path("../Gemfile", __dir__))
+ G
+
+ bundle "install", dir: nested_dir
+
+ expect(bundled_app(".ruby-lsp/Gemfile.lock").read).to include("RUBY VERSION")
+ end
end
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 62cad6800f..a5ba76f4d9 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -27,18 +27,72 @@ 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 => "< 3" do
- bundle :install, :artifice => "compact_index"
+ it "refuses to install mismatched checksum because one gem has been tampered with", bundler: "< 3" do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo3/
+ remote: https://gem.repo1/
+ specs:
+ rack (1.0.0)
- expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).to include("Installed from: https://gem.repo1")
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ depends_on_rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install, artifice: "compact_index", raise_on_error: false
+
+ expect(exitstatus).to eq(37)
+ expect(err).to eq <<~E.strip
+ [DEPRECATED] Your Gemfile contains multiple global sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source.
+ Bundler found mismatched checksums. This is a potential security risk.
+ #{checksum_to_lock(gem_repo1, "rack", "1.0.0")}
+ from the API at https://gem.repo1/
+ #{checksum_to_lock(gem_repo3, "rack", "1.0.0")}
+ from the API at https://gem.repo3/
+
+ Mismatched checksums each have an authoritative source:
+ 1. the API at https://gem.repo1/
+ 2. the API at https://gem.repo3/
+ You may need to alter your Gemfile sources to resolve this issue.
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
end
- it "fails", :bundler => "3" do
- bundle :instal, :artifice => "compact_index", :raise_on_error => false
- expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4)
+ context "when checksum validation is disabled" do
+ before do
+ bundle "config set --local disable_checksum_validation true"
+ end
+
+ it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", bundler: "< 3" do
+ bundle :install, artifice: "compact_index"
+
+ expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(err).to include("Installed from: https://gem.repo1")
+ expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", source: "remote1")
+ end
+
+ it "does not use the full index unnecessarily", bundler: "< 3" do
+ bundle :install, artifice: "compact_index", verbose: true
+
+ expect(out).to include("https://gem.repo1/versions")
+ expect(out).to include("https://gem.repo3/versions")
+ expect(out).not_to include("https://gem.repo1/quick/Marshal.4.8/")
+ expect(out).not_to include("https://gem.repo3/quick/Marshal.4.8/")
+ end
+
+ it "fails", bundler: "3" do
+ bundle :install, artifice: "compact_index", raise_on_error: false
+ expect(err).to include("Each source after the first must include a block")
+ expect(exitstatus).to eq(4)
+ end
end
end
@@ -54,21 +108,49 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "warns about ambiguous gems, but installs anyway", :bundler => "< 3" do
- bundle :install, :artifice => "compact_index"
+ it "warns about ambiguous gems, but installs anyway", bundler: "< 3" do
+ bundle :install, artifice: "compact_index"
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).to include("Installed from: https://gem.repo1")
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
+ expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", source: "remote1")
end
- it "fails", :bundler => "3" do
- bundle :install, :artifice => "compact_index", :raise_on_error => false
+ it "fails", bundler: "3" do
+ bundle :install, artifice: "compact_index", raise_on_error: false
expect(err).to include("Each source after the first must include a block")
expect(exitstatus).to eq(4)
end
end
end
+ context "without source affinity, and a stdlib gem present in one of the sources", :ruby_repo do
+ let(:default_json_version) { ruby "gem 'json'; require 'json'; puts JSON::VERSION" }
+
+ before do
+ build_repo2 do
+ build_gem "json", default_json_version
+ end
+
+ build_repo4 do
+ build_gem "foo" do |s|
+ s.add_dependency "json", default_json_version
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ source "https://gem.repo4"
+
+ gem "foo"
+ G
+ end
+
+ it "works in standalone mode", bundler: "< 3" do
+ gem_checksum = checksum_digest(gem_repo4, "foo", "1.0")
+ bundle "install --standalone", artifice: "compact_index", env: { "BUNDLER_SPEC_FOO_CHECKSUM" => gem_checksum }
+ end
+ end
+
context "with source affinity" do
context "with sources given by a block" do
before do
@@ -95,20 +177,20 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs the gems without any warning" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
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")
+ expect(the_bundle).to include_gems("rack 1.0.0", source: "remote1")
end
it "can cache and deploy" do
- bundle :cache, :artifice => "compact_index"
+ bundle :cache, artifice: "compact_index"
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/rack-obama-1.0.gem")).to exist
bundle "config set --local deployment true"
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
end
@@ -128,7 +210,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo3"
gem "rack-obama" # should come from repo3!
gem "rack", :source => "https://gem.repo1"
@@ -168,9 +250,9 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs from the same source without any warning" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(err).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", source: "remote3")
end
end
@@ -185,18 +267,18 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs from the same source without any warning" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
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")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", source: "remote3")
# 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, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
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")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", source: "remote3")
end
end
end
@@ -218,7 +300,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "and not in any other sources" do
before do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo2"
source "https://gem.repo3" do
gem "depends_on_rack"
@@ -243,11 +325,63 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do
- bundle :install, :artifice => "compact_index"
+ it "fails when the two sources don't have the same checksum", bundler: "< 3" do
+ bundle :install, artifice: "compact_index", raise_on_error: false
+
+ expect(err).to eq(<<~E.strip)
+ [DEPRECATED] Your Gemfile contains multiple global sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source.
+ Bundler found mismatched checksums. This is a potential security risk.
+ #{checksum_to_lock(gem_repo2, "rack", "1.0.0")}
+ from the API at https://gem.repo2/
+ #{checksum_to_lock(gem_repo1, "rack", "1.0.0")}
+ from the API at https://gem.repo1/
+
+ Mismatched checksums each have an authoritative source:
+ 1. the API at https://gem.repo2/
+ 2. the API at https://gem.repo1/
+ You may need to alter your Gemfile sources to resolve this issue.
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
+ expect(exitstatus).to eq(37)
+ end
+
+ it "fails when the two sources agree, but the local gem calculates a different checksum", bundler: "< 3" do
+ rack_checksum = "c0ffee11" * 8
+ bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_RACK_CHECKSUM" => rack_checksum }, raise_on_error: false
+
+ expect(err).to eq(<<~E.strip)
+ [DEPRECATED] Your Gemfile contains multiple global sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source.
+ Bundler found mismatched checksums. This is a potential security risk.
+ rack (1.0.0) sha256=#{rack_checksum}
+ from the API at https://gem.repo2/
+ and the API at https://gem.repo1/
+ #{checksum_to_lock(gem_repo2, "rack", "1.0.0")}
+ from the gem at #{default_bundle_path("cache", "rack-1.0.0.gem")}
+
+ If you trust the API at https://gem.repo2/, to resolve this issue you can:
+ 1. remove the gem at #{default_bundle_path("cache", "rack-1.0.0.gem")}
+ 2. run `bundle install`
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
+ expect(exitstatus).to eq(37)
+ end
+
+ it "installs from the other source and warns about ambiguous gems when the sources have the same checksum", bundler: "< 3" do
+ gem_checksum = checksum_digest(gem_repo2, "rack", "1.0.0")
+ bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_RACK_CHECKSUM" => gem_checksum, "DEBUG" => "1" }
+
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).to include("Installed from: https://gem.repo2")
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo3, "depends_on_rack", "1.0.1"
+ c.checksum gem_repo2, "rack", "1.0.0"
+ end
+
expect(lockfile).to eq <<~L
GEM
remote: https://gem.repo1/
@@ -262,11 +396,51 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
depends_on_rack!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ previous_lockfile = lockfile
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ expect(lockfile).to eq(previous_lockfile)
+ end
+ it "installs from the other source and warns about ambiguous gems when checksum validation is disabled", bundler: "< 3" do
+ bundle "config set --local disable_checksum_validation true"
+ bundle :install, artifice: "compact_index"
+
+ expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(err).to include("Installed from: https://gem.repo2")
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "depends_on_rack", "1.0.1"
+ c.no_checksum "rack", "1.0.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ remote: https://gem.repo2/
+ specs:
+ rack (1.0.0)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ depends_on_rack (1.0.1)
+ rack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ depends_on_rack!
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -276,8 +450,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(lockfile).to eq(previous_lockfile)
end
- it "fails", :bundler => "3" do
- bundle :install, :artifice => "compact_index", :raise_on_error => false
+ it "fails", bundler: "3" do
+ bundle :install, artifice: "compact_index", raise_on_error: false
expect(err).to include("Each source after the first must include a block")
expect(exitstatus).to eq(4)
end
@@ -301,8 +475,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "installs the dependency from the pinned source without warning", :bundler => "< 3" do
- bundle :install, :artifice => "compact_index"
+ it "installs the dependency from the pinned source without warning", bundler: "< 3" do
+ bundle :install, artifice: "compact_index"
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")
@@ -310,14 +484,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
# In https://github.com/rubygems/bundler/issues/3585 this failed
# when there is already a lock file, and the gems are missing, so try again
system_gems []
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
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
- it "fails", :bundler => "3" do
- bundle :install, :artifice => "compact_index", :raise_on_error => false
+ it "fails", bundler: "3" do
+ bundle :install, artifice: "compact_index", raise_on_error: false
expect(err).to include("Each source after the first must include a block")
expect(exitstatus).to eq(4)
end
@@ -345,12 +519,12 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "fails" do
- bundle :install, :artifice => "compact_index", :raise_on_error => false
- expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository https://gem.repo2/ or installed locally.")
+ bundle :install, artifice: "compact_index", raise_on_error: false
+ expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository https://gem.repo2/, cached gems or installed locally.")
end
end
- context "when an indirect dependency can't be found in the aggregate rubygems source", :bundler => "< 3" do
+ context "when an indirect dependency can't be found in the aggregate rubygems source", bundler: "< 3" do
before do
build_repo2
@@ -370,8 +544,16 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "fails" do
- bundle :install, :artifice => "compact_index", :raise_on_error => false
- expect(err).to include("Could not find gem 'missing', which is required by gem 'depends_on_missing', in any of the sources.")
+ bundle :install, artifice: "compact_index", raise_on_error: false
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of depends_on_missing depends on missing >= 0
+ and missing >= 0 could not be found in any of the sources,
+ depends_on_missing cannot be used.
+ So, because Gemfile depends on depends_on_missing >= 0,
+ version solving has failed.
+ E
end
end
@@ -406,11 +588,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs the dependency from the top-level source without warning" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2")
- expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", source: "remote2")
+ expect(the_bundle).to include_gems("unrelated_gem 1.0.0", source: "remote3")
end
end
@@ -424,10 +606,16 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "does not find the dependency" do
- bundle :install, :artifice => "compact_index", :raise_on_error => false
- expect(err).to include(
- "Could not find gem 'rack', which is required by gem 'depends_on_rack', in rubygems repository https://gem.repo2/ or installed locally."
- )
+ bundle :install, artifice: "compact_index", raise_on_error: false
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of depends_on_rack depends on rack >= 0
+ and rack >= 0 could not be found in rubygems repository https://gem.repo2/, cached gems or installed locally,
+ depends_on_rack cannot be used.
+ So, because Gemfile depends on depends_on_rack >= 0,
+ version solving has failed.
+ E
end
end
@@ -445,12 +633,12 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs the dependency from the top-level source without warning" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(err).not_to include("Warning")
expect(run("require 'rack'; puts RACK")).to eq("1.0.0")
expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2")
- expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", source: "remote2")
+ expect(the_bundle).to include_gems("unrelated_gem 1.0.0", source: "remote3")
end
end
end
@@ -484,10 +672,10 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs the dependency from the top-level source" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0")
- expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote2")
- expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", :source => "remote3")
+ expect(the_bundle).to include_gems("rack 1.0.0", source: "remote2")
+ expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", source: "remote3")
end
end
@@ -501,8 +689,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs the dependency from the pinned source" do
- bundle :install, :artifice => "compact_index"
- expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ bundle :install, artifice: "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", source: "remote3")
end
end
@@ -520,8 +708,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs the dependency from the pinned source without warning" do
- bundle :install, :artifice => "compact_index"
- expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ bundle :install, artifice: "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", source: "remote3")
end
end
end
@@ -595,6 +783,21 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
G
+ @locked_checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo2, "activesupport", "6.0.3.4"
+ c.checksum gem_repo2, "concurrent-ruby", "1.1.8"
+ c.checksum gem_repo2, "connection_pool", "2.2.3"
+ c.checksum gem_repo2, "i18n", "1.8.9"
+ c.checksum gem_repo2, "minitest", "5.14.3"
+ c.checksum gem_repo2, "rack", "2.2.3"
+ c.checksum gem_repo2, "redis", "4.2.5"
+ c.checksum gem_repo2, "sidekiq", "6.1.3"
+ c.checksum gem_repo3, "sidekiq-pro", "5.2.1"
+ c.checksum gem_repo2, "thread_safe", "0.3.6"
+ c.checksum gem_repo2, "tzinfo", "1.2.9"
+ c.checksum gem_repo2, "zeitwerk", "2.4.2"
+ end
+
lockfile <<~L
GEM
remote: https://gem.repo2/
@@ -626,19 +829,19 @@ RSpec.describe "bundle install with gems on multiple sources" do
zeitwerk (2.4.2)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
activesupport
sidekiq-pro!
-
+ #{@locked_checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
end
it "does not install newer versions but updates the lockfile format when running bundle install in non frozen mode, and doesn't warn" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(err).to be_empty
expect(the_bundle).to include_gems("activesupport 6.0.3.4")
@@ -682,22 +885,22 @@ RSpec.describe "bundle install with gems on multiple sources" do
sidekiq (>= 6.1.0)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
activesupport
sidekiq-pro!
-
+ #{@locked_checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
end
- it "does not install newer versions or generate lockfile changes when running bundle install in frozen mode, and warns", :bundler => "< 3" do
+ it "does not install newer versions or generate lockfile changes when running bundle install in frozen mode, and warns", bundler: "< 3" do
initial_lockfile = lockfile
bundle "config set --local frozen true"
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
@@ -711,11 +914,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(lockfile).to eq(initial_lockfile)
end
- it "fails when running bundle install in frozen mode", :bundler => "3" do
+ it "fails when running bundle install in frozen mode", bundler: "3" do
initial_lockfile = lockfile
bundle "config set --local frozen true"
- bundle :install, :artifice => "compact_index", :raise_on_error => false
+ bundle :install, artifice: "compact_index", raise_on_error: false
expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
@@ -723,15 +926,21 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "splits sections and upgrades gems when running bundle update, and doesn't warn" do
- bundle "update --all", :artifice => "compact_index"
+ bundle "update --all", artifice: "compact_index"
expect(err).to be_empty
expect(the_bundle).not_to include_gems("activesupport 6.0.3.4")
expect(the_bundle).to include_gems("activesupport 6.1.2.1")
+ @locked_checksums.checksum gem_repo2, "activesupport", "6.1.2.1"
+
expect(the_bundle).not_to include_gems("tzinfo 1.2.9")
expect(the_bundle).to include_gems("tzinfo 2.0.4")
+ @locked_checksums.checksum gem_repo2, "tzinfo", "2.0.4"
+ @locked_checksums.delete "thread_safe"
+
expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8")
expect(the_bundle).to include_gems("concurrent-ruby 1.1.9")
+ @locked_checksums.checksum gem_repo2, "concurrent-ruby", "1.1.9"
expect(lockfile).to eq <<~L
GEM
@@ -766,19 +975,19 @@ RSpec.describe "bundle install with gems on multiple sources" do
sidekiq (>= 6.1.0)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
activesupport
sidekiq-pro!
-
+ #{@locked_checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
end
it "upgrades the lockfile format and upgrades the requested gem when running bundle update with an argument" do
- bundle "update concurrent-ruby", :artifice => "compact_index"
+ bundle "update concurrent-ruby", artifice: "compact_index"
expect(err).to be_empty
expect(the_bundle).to include_gems("activesupport 6.0.3.4")
@@ -788,6 +997,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(the_bundle).to include_gems("concurrent-ruby 1.1.9")
expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8")
+ @locked_checksums.checksum gem_repo2, "concurrent-ruby", "1.1.9"
+
expect(lockfile).to eq <<~L
GEM
remote: https://gem.repo2/
@@ -822,12 +1033,12 @@ RSpec.describe "bundle install with gems on multiple sources" do
sidekiq (>= 6.1.0)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
activesupport
sidekiq-pro!
-
+ #{@locked_checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -836,8 +1047,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved" 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|
+ 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
@@ -859,11 +1070,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs all gems without warning" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
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")}")
+ 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
@@ -895,6 +1106,12 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs from the default source without any warnings or errors and generates a proper lockfile" do
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo3, "handsoap", "0.2.5.5"
+ c.checksum gem_repo2, "nokogiri", "1.11.1"
+ c.checksum gem_repo2, "racca", "1.5.2"
+ end
+
expected_lockfile = <<~L
GEM
remote: https://gem.repo2/
@@ -910,30 +1127,30 @@ RSpec.describe "bundle install with gems on multiple sources" do
nokogiri (>= 1.2.3)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
handsoap!
nokogiri
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
- bundle "install --verbose", :artifice => "compact_index"
+ bundle "install --verbose", artifice: "compact_index"
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")
+ 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")
expect(lockfile).to eq(expected_lockfile)
# Even if the gems are already installed
FileUtils.rm bundled_app_lock
- bundle "install --verbose", :artifice => "compact_index"
+ bundle "install --verbose", artifice: "compact_index"
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")
+ 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")
expect(lockfile).to eq(expected_lockfile)
end
end
@@ -944,7 +1161,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "not_in_repo1", "1.0.0"
end
- install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index", raise_on_error: false
source "https://gem.repo3"
gem "not_in_repo1", :source => "https://gem.repo1"
G
@@ -957,7 +1174,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "with an existing lockfile" do
before do
- system_gems "rack-0.9.1", "rack-1.0.0", :path => default_bundle_path
+ system_gems "rack-0.9.1", "rack-1.0.0", path: default_bundle_path
lockfile <<-L
GEM
@@ -970,7 +1187,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack (0.9.1)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
rack!
@@ -1000,11 +1217,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack (0.9.1)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
rack!
-
+ #{checksums_section}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -1022,7 +1239,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack (0.9.1)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
rack!
@@ -1047,20 +1264,48 @@ RSpec.describe "bundle install with gems on multiple sources" do
lockfile aggregate_gem_section_lockfile
end
- it "installs the existing lockfile but prints a warning", :bundler => "< 3" do
+ it "installs the existing lockfile but prints a warning when checksum validation is disabled", bundler: "< 3" do
bundle "config set --local deployment true"
+ bundle "config set --local disable_checksum_validation true"
- bundle "install", :artifice => "compact_index"
+ bundle "install", artifice: "compact_index"
expect(lockfile).to eq(aggregate_gem_section_lockfile)
expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
- expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
+ expect(the_bundle).to include_gems("rack 0.9.1", source: "remote3")
+ end
+
+ it "prints a checksum warning when the checksums from both sources do not match", bundler: "< 3" do
+ bundle "config set --local deployment true"
+
+ bundle "install", artifice: "compact_index", raise_on_error: false
+
+ api_checksum1 = checksum_digest(gem_repo1, "rack", "0.9.1")
+ api_checksum3 = checksum_digest(gem_repo3, "rack", "0.9.1")
+
+ expect(exitstatus).to eq(37)
+ expect(err).to eq(<<~E.strip)
+ [DEPRECATED] Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure.
+ Bundler found mismatched checksums. This is a potential security risk.
+ rack (0.9.1) sha256=#{api_checksum3}
+ from the API at https://gem.repo3/
+ rack (0.9.1) sha256=#{api_checksum1}
+ from the API at https://gem.repo1/
+
+ Mismatched checksums each have an authoritative source:
+ 1. the API at https://gem.repo3/
+ 2. the API at https://gem.repo1/
+ You may need to alter your Gemfile sources to resolve this issue.
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
end
- it "refuses to install the existing lockfile and prints an error", :bundler => "3" do
+ it "refuses to install the existing lockfile and prints an error", bundler: "3" do
bundle "config set --local deployment true"
- bundle "install", :artifice => "compact_index", :raise_on_error =>false
+ bundle "install", artifice: "compact_index", raise_on_error: false
expect(lockfile).to eq(aggregate_gem_section_lockfile)
expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
@@ -1080,7 +1325,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "does not unlock the non-path gem after install" do
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
bundle %(exec ruby -e 'puts "OK"')
@@ -1093,7 +1338,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
before do
system_gems "rack-0.9.1"
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
gem "rack" # should come from repo1!
G
@@ -1122,7 +1367,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
bundle "config set --local path ../gems/system"
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
# And then we add some new versions...
update_repo4 do
@@ -1133,7 +1378,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
it "allows them to be unlocked separately" do
# And install this gemfile, updating only foo.
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source 'https://gem.repo1'
gem 'rack'
gem 'foo', '~> 0.2', :source => 'https://gem.repo4'
@@ -1157,7 +1402,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_git "git1"
build_git "git2"
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
gem "rails"
@@ -1173,7 +1418,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "does not re-resolve" do
- bundle :install, :artifice => "compact_index", :verbose => true
+ bundle :install, artifice: "compact_index", verbose: true
expect(out).to include("using resolution from the lockfile")
expect(out).not_to include("re-resolving dependencies")
end
@@ -1182,7 +1427,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "when a gem is installed to system gems" do
before do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
gem "rack"
G
@@ -1196,7 +1441,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
# When this gemfile is installed...
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
source "https://gem.repo4" do
@@ -1218,14 +1463,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
# But we should still be able to find rack 2.0.1.1.forked and install it
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
end
end
end
describe "source changed to one containing a higher version of a dependency" do
before do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
gem "rack"
@@ -1239,11 +1484,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "bar"
end
- build_lib("gemspec_test", :path => tmp.join("gemspec_test")) do |s|
+ build_lib("gemspec_test", path: tmp.join("gemspec_test")) do |s|
s.add_dependency "bar", "=1.0.0"
end
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo2"
gem "rack"
gemspec :path => "#{tmp.join("gemspec_test")}"
@@ -1255,6 +1500,32 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
+ context "when Gemfile overrides a gemspec development dependency to change the default source" do
+ before do
+ build_repo4 do
+ build_gem "bar"
+ end
+
+ build_lib("gemspec_test", path: tmp.join("gemspec_test")) do |s|
+ s.add_development_dependency "bar"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
+
+ source "https://gem.repo4" do
+ gem "bar"
+ end
+
+ gemspec :path => "#{tmp.join("gemspec_test")}"
+ G
+ end
+
+ it "does not print warnings" do
+ expect(err).to be_empty
+ end
+ end
+
it "doesn't update version when a gem uses a source block but a higher version from another source is already installed locally" do
build_repo2 do
build_gem "example", "0.1.0"
@@ -1264,7 +1535,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "example", "1.0.2"
end
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo4"
gem "example", :source => "https://gem.repo2"
@@ -1273,14 +1544,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
bundle "info example"
expect(out).to include("example (0.1.0)")
- system_gems "example-1.0.2", :path => default_bundle_path, :gem_repo => gem_repo4
+ system_gems "example-1.0.2", path: default_bundle_path, gem_repo: gem_repo4
- bundle "update example --verbose", :artifice => "compact_index"
+ bundle "update example --verbose", artifice: "compact_index"
expect(out).not_to include("Using example 1.0.2")
expect(out).to include("Using example 0.1.0")
end
- it "fails inmmediately with a helpful error when a rubygems source does not exist and bundler/setup is required" do
+ it "fails immediately with a helpful error when a rubygems source does not exist and bundler/setup is required" do
gemfile <<-G
source "https://gem.repo1"
@@ -1289,17 +1560,15 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
G
- simulate_bundler_version_when_missing_prerelease_default_gem_activation do
- ruby <<~R, :raise_on_error => false
- require 'bundler/setup'
- R
- end
+ ruby <<~R, raise_on_error: false
+ require 'bundler/setup'
+ R
expect(last_command).to be_failure
expect(err).to include("Could not find gem 'example' in locally installed gems.")
end
- it "fails inmmediately with a helpful error when a non retriable network error happens while resolving sources" do
+ it "fails immediately with a helpful error when a non retriable network error happens while resolving sources" do
gemfile <<-G
source "https://gem.repo1"
@@ -1308,13 +1577,13 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
G
- bundle "install", :artifice => nil, :raise_on_error => false
+ bundle "install", artifice: nil, raise_on_error: false
expect(last_command).to be_failure
expect(err).to include("Could not reach host gem.repo4. Check your network connection and try again.")
end
- context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "< 3" do
+ context "when an indirect dependency is available from multiple ambiguous sources", bundler: "< 3" do
it "succeeds but warns, suggesting a source block" do
build_repo4 do
build_gem "depends_on_rack" do |s|
@@ -1323,7 +1592,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "rack"
end
- install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index", raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
source "https://gem.repo4" do
@@ -1334,7 +1603,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
gem "thin"
end
G
- expect(err).to eq strip_whitespace(<<-EOS).strip
+ expect(err).to eq <<~EOS.strip
Warning: The gem 'rack' was found in multiple relevant sources.
* rubygems repository https://gem.repo1/
* rubygems repository https://gem.repo4/
@@ -1345,7 +1614,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "3" do
+ context "when an indirect dependency is available from multiple ambiguous sources", bundler: "3" do
it "raises, suggesting a source block" do
build_repo4 do
build_gem "depends_on_rack" do |s|
@@ -1354,7 +1623,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "rack"
end
- install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index", raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
source "https://gem.repo4" do
gem "depends_on_rack"
@@ -1364,7 +1633,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
G
expect(last_command).to be_failure
- expect(err).to eq strip_whitespace(<<-EOS).strip
+ expect(err).to eq <<~EOS.strip
The gem 'rack' was found in multiple relevant sources.
* rubygems repository https://gem.repo1/
* rubygems repository https://gem.repo4/
@@ -1408,16 +1677,23 @@ RSpec.describe "bundle install with gems on multiple sources" do
mime-types (3.3.1)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
capybara (~> 2.5.0)
mime-types (~> 3.0)!
+
+ CHECKSUMS
L
end
it "upgrades the lockfile correctly" do
- bundle "lock --update", :artifice => "compact_index"
+ bundle "lock --update", artifice: "compact_index"
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo2, "capybara", "2.5.0"
+ c.checksum gem_repo4, "mime-types", "3.0.0"
+ end
expect(lockfile).to eq <<~L
GEM
@@ -1432,12 +1708,70 @@ RSpec.describe "bundle install with gems on multiple sources" do
mime-types (3.0.0)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
capybara (~> 2.5.0)
mime-types (~> 3.0)!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when default source includes old gems with nil required_ruby_version" do
+ before do
+ build_repo2 do
+ build_gem "ruport", "1.7.0.3" do |s|
+ s.add_dependency "pdf-writer", "1.1.8"
+ end
+ end
+ build_repo gem_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_ruby_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://localgemserver.test"
+
+ gem "ruport", "= 1.7.0.3", :source => "https://localgemserver.test/extra"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "pdf-writer", "1.1.8"
+ c.checksum gem_repo2, "ruport", "1.7.0.3"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ pdf-writer (1.1.8)
+
+ GEM
+ remote: https://localgemserver.test/extra/
+ specs:
+ ruport (1.7.0.3)
+ pdf-writer (= 1.1.8)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ruport (= 1.7.0.3)!
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -1471,7 +1805,12 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "handles that fine" do
- bundle "install", :artifice => "compact_index_extra", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "pdf-writer", "1.1.8"
+ c.checksum gem_repo2, "ruport", "1.7.0.3"
+ end
expect(lockfile).to eq <<~L
GEM
@@ -1486,11 +1825,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
pdf-writer (= 1.1.8)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
ruport (= 1.7.0.3)!
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -1518,7 +1857,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "handles that fine" do
- bundle "install --verbose", :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install --verbose", artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "pdf-writer", "1.1.8"
+ end
expect(lockfile).to eq <<~L
GEM
@@ -1527,14 +1870,53 @@ RSpec.describe "bundle install with gems on multiple sources" do
pdf-writer (1.1.8)
PLATFORMS
- #{specific_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
pdf-writer (= 1.1.8)
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
end
end
+
+ context "when mistakenly adding a top level gem already depended on and cached under the wrong source" do
+ before do
+ build_repo4 do
+ build_gem "some_private_gem", "0.1.0" do |s|
+ s.add_dependency "example", "~> 1.0"
+ end
+ end
+
+ build_repo2 do
+ build_gem "example", "1.0.0"
+ end
+
+ install_gemfile <<~G, artifice: "compact_index"
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "some_private_gem"
+ end
+ G
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "some_private_gem"
+ gem "example" # MISTAKE, example is not available at gem.repo4
+ end
+ G
+ end
+
+ it "shows a proper error message and does not generate a corrupted lockfile" do
+ expect do
+ bundle :install, artifice: "compact_index", raise_on_error: false, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end.not_to change { lockfile }
+
+ expect(err).to include("Could not find gem 'example' in rubygems repository https://gem.repo4/")
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 113a0a1352..5f1b034bfc 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -6,29 +6,29 @@ RSpec.describe "bundle install with specific platforms" do
gem "google-protobuf"
G
- context "when on a darwin machine" do
- before { simulate_platform "x86_64-darwin-15" }
-
- it "locks to the specific darwin platform" do
+ it "locks to the specific darwin platform" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.platforms).to include(pl("x86_64-darwin-15"))
expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
- google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
- ])
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(
+ "google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin"
+ )
end
+ end
- it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
system_gems "bundler-2.1.4"
# Consistent location to install and look for gems
- bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" }
+ bundle "config set --local path vendor/bundle", env: { "BUNDLER_VERSION" => "2.1.4" }
- install_gemfile(google_protobuf, :env => { "BUNDLER_VERSION" => "2.1.4" })
+ install_gemfile(google_protobuf, env: { "BUNDLER_VERSION" => "2.1.4" })
# simulate lockfile created with old bundler, which only locks for ruby platform
lockfile <<-L
@@ -48,22 +48,28 @@ RSpec.describe "bundle install with specific platforms" do
L
# force strict usage of the lock file by setting frozen mode
- bundle "config set --local frozen true", :env => { "BUNDLER_VERSION" => "2.1.4" }
+ bundle "config set --local frozen true", env: { "BUNDLER_VERSION" => "2.1.4" }
# make sure the platform that got actually installed with the old bundler is used
expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
end
+ end
- it "understands that a non-platform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do
+ it "understands that a non-platform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
system_gems "bundler-2.1.4"
# Consistent location to install and look for gems
- bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" }
+ bundle "config set --local path vendor/bundle", env: { "BUNDLER_VERSION" => "2.1.4" }
gemfile google_protobuf
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo2, "google-protobuf", "3.0.0.alpha.4.0"
+ end
+
# simulate lockfile created with old bundler, which only locks for ruby platform
lockfile <<-L
GEM
@@ -76,12 +82,14 @@ RSpec.describe "bundle install with specific platforms" do
DEPENDENCIES
google-protobuf
-
+ #{checksums}
BUNDLED WITH
2.1.4
L
- bundle "update", :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ bundle "update", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+
+ checksums.checksum gem_repo2, "google-protobuf", "3.0.0.alpha.5.0.5.1"
# make sure the platform that the platform specific dependency is used, since we're only locked to ruby
expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
@@ -98,13 +106,61 @@ RSpec.describe "bundle install with specific platforms" do
DEPENDENCIES
google-protobuf
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when running on a legacy lockfile locked only to RUBY" do
+ around do |example|
+ build_repo4 do
+ build_gem "nokogiri", "1.3.10"
+ build_gem "nokogiri", "1.3.10" do |s|
+ s.platform = "arm64-darwin"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.3.10)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
BUNDLED WITH
#{Bundler::VERSION}
L
+
+ simulate_platform "arm64-darwin-22", &example
end
- it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ it "still installs the generic RUBY variant if necessary" do
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(out).to include("Installing nokogiri 1.3.10")
+ end
+
+ it "still installs the generic RUBY variant if necessary, even in frozen mode" do
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s, "BUNDLE_FROZEN" => "true" }
+ expect(out).to include("Installing nokogiri 1.3.10")
+ end
+ end
+
+ it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ simulate_platform "x86_64-darwin-15" do
build_repo2 do
build_gem("libv8", "8.4.255.0")
build_gem("libv8", "8.4.255.0") {|s| s.platform = "universal-darwin" }
@@ -117,7 +173,7 @@ RSpec.describe "bundle install with specific platforms" do
system_gems "bundler-2.1.4"
# Consistent location to install and look for gems
- bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" }
+ bundle "config set --local path vendor/bundle", env: { "BUNDLER_VERSION" => "2.1.4" }
gemfile <<-G
source "https://localgemserver.test"
@@ -141,14 +197,50 @@ RSpec.describe "bundle install with specific platforms" do
2.1.4
L
- bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_VERSION" => "2.1.4", "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_VERSION" => "2.1.4", "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Installing libv8 8.4.255.0 (universal-darwin)")
- bundle "add mini_racer --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle "add mini_racer --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Using libv8 8.4.255.0 (universal-darwin)")
end
+ end
- it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ it "chooses platform specific gems even when resolving upon materialization and the API returns more specific platforms first" do
+ simulate_platform "x86_64-darwin-15" do
+ build_repo4 do
+ build_gem("grpc", "1.50.0")
+ build_gem("grpc", "1.50.0") {|s| s.platform = "universal-darwin" }
+ end
+
+ gemfile <<-G
+ source "https://localgemserver.test"
+ gem "grpc"
+ G
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ grpc (1.50.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ grpc
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose", artifice: "compact_index_precompiled_before", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(out).to include("Installing grpc 1.50.0 (universal-darwin)")
+ end
+ end
+
+ it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
gemfile(google_protobuf)
bundle "cache --all-platforms"
@@ -157,8 +249,10 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose"
expect(err).to be_empty
end
+ end
- it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
gemfile(google_protobuf)
bundle "config set --local cache_all_platforms true"
@@ -168,44 +262,46 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose"
expect(err).to be_empty
end
+ end
- it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do
- git = build_git "pg_array_parser", "1.0"
+ it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do
+ git = build_git "pg_array_parser", "1.0"
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}"
- G
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}"
+ G
- lockfile <<-L
- GIT
- remote: #{lib_path("pg_array_parser-1.0")}
- revision: #{git.ref_for("master")}
- specs:
- pg_array_parser (1.0-java)
- pg_array_parser (1.0)
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("pg_array_parser-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ pg_array_parser (1.0-java)
+ pg_array_parser (1.0)
- GEM
- specs:
+ GEM
+ specs:
- PLATFORMS
- java
- #{lockfile_platforms}
+ PLATFORMS
+ java
+ #{lockfile_platforms}
- DEPENDENCIES
- pg_array_parser!
+ DEPENDENCIES
+ pg_array_parser!
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- bundle "config set --local cache_all true"
- bundle "cache --all-platforms"
+ bundle "config set --local cache_all true"
+ bundle "cache --all-platforms"
- expect(err).to be_empty
- end
+ expect(err).to be_empty
+ end
- it "uses the platform-specific gem with extra dependencies" do
+ it "uses the platform-specific gem with extra dependencies" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem_with_different_dependencies_per_platform
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -213,47 +309,52 @@ RSpec.describe "bundle install with specific platforms" do
G
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.platforms).to include(pl("x86_64-darwin-15"))
expect(the_bundle).to include_gems("facter 2.4.6 universal-darwin", "CFPropertyList 1.0")
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0",
- "facter-2.4.6-universal-darwin"])
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include("CFPropertyList-1.0",
+ "facter-2.4.6-universal-darwin")
end
+ end
- context "when adding a platform via lock --add_platform" do
- before do
- allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- end
+ context "when adding a platform via lock --add_platform" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ end
- it "adds the foreign platform" do
+ it "adds the foreign platform" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
- bundle "lock --add-platform=#{x64_mingw}"
+ bundle "lock --add-platform=#{x64_mingw32}"
- expect(the_bundle.locked_gems.platforms).to eq([x64_mingw, pl("x86_64-darwin-15")])
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
+ expect(the_bundle.locked_gems.platforms).to include(x64_mingw32, pl("x86_64-darwin-15"))
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(*%w[
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32
])
end
+ end
- it "falls back on plain ruby when that version doesnt have a platform-specific gem" do
+ it "falls back on plain ruby when that version doesn't have a platform-specific gem" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
bundle "lock --add-platform=#{java}"
- expect(the_bundle.locked_gems.platforms).to eq([java, pl("x86_64-darwin-15")])
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
- google-protobuf-3.0.0.alpha.5.0.5.1
- google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
- ])
+ expect(the_bundle.locked_gems.platforms).to include(java, pl("x86_64-darwin-15"))
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(
+ "google-protobuf-3.0.0.alpha.5.0.5.1",
+ "google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin"
+ )
end
end
end
- it "installs sorbet-static, which does not provide a pure ruby variant, just fine on truffleruby", :truffleruby do
+ it "installs sorbet-static, which does not provide a pure ruby variant, just fine", :truffleruby do
+ skip "does not apply to Windows" if Gem.win_platform?
+
build_repo2 do
- build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "x86_64-linux" }
- build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "universal-darwin-20" }
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = Bundler.local_platform }
end
gemfile <<~G
@@ -266,8 +367,7 @@ RSpec.describe "bundle install with specific platforms" do
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
- sorbet-static (0.5.6403-universal-darwin-20)
- sorbet-static (0.5.6403-x86_64-linux)
+ sorbet-static (0.5.6403-#{Bundler.local_platform})
PLATFORMS
ruby
@@ -283,54 +383,1001 @@ RSpec.describe "bundle install with specific platforms" do
end
it "does not resolve if the current platform does not match any of available platform specific variants for a top level dependency" do
- build_repo2 do
+ build_repo4 do
build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" }
build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" }
end
gemfile <<~G
- source "#{file_uri_for(gem_repo2)}"
+ source "#{file_uri_for(gem_repo4)}"
gem "sorbet-static", "0.5.6433"
G
- simulate_platform "arm64-darwin-21" do
- bundle "install", :raise_on_error => false
- end
-
- expect(err).to include <<~ERROR.rstrip
- Could not find gem 'sorbet-static (= 0.5.6433) arm64-darwin-21' in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally.
+ error_message = <<~ERROR.strip
+ Could not find gem 'sorbet-static (= 0.5.6433)' with platform 'arm64-darwin-21' in rubygems repository #{file_uri_for(gem_repo4)}/, cached gems or installed locally.
The source contains the following gems matching 'sorbet-static (= 0.5.6433)':
* sorbet-static-0.5.6433-universal-darwin-20
* sorbet-static-0.5.6433-x86_64-linux
ERROR
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
+
+ # Make sure it doesn't print error twice in verbose mode
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock --verbose", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
end
it "does not resolve if the current platform does not match any of available platform specific variants for a transitive dependency" do
- build_repo2 do
+ build_repo4 do
build_gem("sorbet", "0.5.6433") {|s| s.add_dependency "sorbet-static", "= 0.5.6433" }
build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" }
build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" }
end
gemfile <<~G
- source "#{file_uri_for(gem_repo2)}"
+ source "#{file_uri_for(gem_repo4)}"
gem "sorbet", "0.5.6433"
G
- simulate_platform "arm64-darwin-21" do
- bundle "install", :raise_on_error => false
- end
+ error_message = <<~ERROR.strip
+ Could not find compatible versions
- expect(err).to include <<~ERROR.rstrip
- Could not find gem 'sorbet-static (= 0.5.6433) arm64-darwin-21', which is required by gem 'sorbet (= 0.5.6433)', in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally.
+ Because every version of sorbet depends on sorbet-static = 0.5.6433
+ and sorbet-static = 0.5.6433 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/, cached gems or installed locally for any resolution platforms (arm64-darwin-21),
+ sorbet cannot be used.
+ So, because Gemfile depends on sorbet = 0.5.6433,
+ version solving has failed.
The source contains the following gems matching 'sorbet-static (= 0.5.6433)':
* sorbet-static-0.5.6433-universal-darwin-20
* sorbet-static-0.5.6433-x86_64-linux
ERROR
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
+
+ # Make sure it doesn't print error twice in verbose mode
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock --verbose", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
+ end
+
+ it "does not generate a lockfile if RUBY platform is forced and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.9889") {|s| s.platform = Gem::Platform.local }
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static", "0.5.9889"
+ G
+
+ bundle "lock", raise_on_error: false, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
+
+ expect(err).to include <<~ERROR.rstrip
+ Could not find gem 'sorbet-static (= 0.5.9889)' with platform 'ruby' in rubygems repository #{file_uri_for(gem_repo4)}/, cached gems or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.9889)':
+ * sorbet-static-0.5.9889-#{Gem::Platform.local}
+ ERROR
+ end
+
+ it "automatically fixes the lockfile if RUBY platform is locked and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet", "= 0.5.10160"
+ s.add_runtime_dependency "sorbet-runtime", "= 0.5.10160"
+ end
+
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-runtime", "0.5.10160")
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static-and-runtime"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "sorbet", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-runtime", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10160", Gem::Platform.local
+ c.checksum gem_repo4, "sorbet-static-and-runtime", "0.5.10160"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile if both RUBY platform and a more specific platform are locked, and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem "nokogiri", "1.12.0"
+ build_gem "nokogiri", "1.12.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+
+ build_gem "nokogiri", "1.13.0"
+ build_gem "nokogiri", "1.13.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+
+ build_gem("sorbet-static", "0.5.10601") do |s|
+ s.platform = "x86_64-darwin"
+ end
+ end
+
+ simulate_platform "x86_64-darwin-22" do
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+ end
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "nokogiri", "1.13.0", "x86_64-darwin"
+ c.no_checksum "sorbet-static", "0.5.10601", "x86_64-darwin"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.12.0)
+ nokogiri (1.12.0-x86_64-darwin)
+ sorbet-static (0.5.10601-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "update --conservative nokogiri"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.13.0-x86_64-darwin)
+ sorbet-static (0.5.10601-x86_64-darwin)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile if only RUBY platform is locked and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet", "= 0.5.10160"
+ s.add_runtime_dependency "sorbet-runtime", "= 0.5.10160"
+ end
+
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-runtime", "0.5.10160")
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static-and-runtime"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "sorbet", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-runtime", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10160", Gem::Platform.local
+ c.checksum gem_repo4, "sorbet-static-and-runtime", "0.5.10160"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile if multiple platforms locked, but no valid versions of direct dependencies for all of them" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "arm-linux"
+ end
+
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0-arm-linux)
+ nokogiri (1.14.0-x86_64-linux)
+ sorbet-static (0.5.10696-x86_64-linux)
+
+ PLATFORMS
+ aarch64-linux
+ arm-linux
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10696", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0-x86_64-linux)
+ sorbet-static (0.5.10696-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "automatically fixes the lockfile without removing other variants if it's missing platform gems, but they are installed locally" do
+ simulate_platform "x86_64-darwin-21" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-20"
+ end
+
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-21"
+ end
+ end
+
+ # Make sure sorbet-static-0.5.10549-universal-darwin-21 is installed
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static", "= 0.5.10549"
+ G
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "sorbet-static", "0.5.10549", "universal-darwin-20"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10549", "universal-darwin-21"
+ end
+
+ # Make sure the lockfile is missing sorbet-static-0.5.10549-universal-darwin-21
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ checksums.no_checksum "sorbet-static", "0.5.10549", "universal-darwin-21"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+ sorbet-static (0.5.10549-universal-darwin-21)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not remove ruby if gems for other platforms, and not present in the lockfile, exist in the Gemfile" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8"
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+
+ gem "tzinfo", "~> 1.2", platform: :#{not_local_tag}
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.13.8)
+ nokogiri (1.13.8-#{Gem::Platform.local})
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ nokogiri
+ tzinfo (~> 1.2)
+
+ CHECKSUMS
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ bundle "lock --update"
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "nokogiri", "1.13.8"
+ c.no_checksum "nokogiri", "1.13.8", Gem::Platform.local
+ end
+
+ updated_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.13.8)
+ nokogiri (1.13.8-#{Gem::Platform.local})
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ nokogiri
+ tzinfo (~> 1.2)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expect(lockfile).to eq(updated_lockfile)
+ end
+
+ it "does not remove ruby when adding a new gem to the Gemfile" do
+ build_repo4 do
+ build_gem "concurrent-ruby", "1.2.2"
+ build_gem "rack", "3.0.7"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "concurrent-ruby"
+ gem "rack"
+ G
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "concurrent-ruby", "1.2.2"
+ c.no_checksum "rack", "3.0.7"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ concurrent-ruby (1.2.2)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ concurrent-ruby
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ concurrent-ruby (1.2.2)
+ rack (3.0.7)
+
+ PLATFORMS
+ #{lockfile_platforms("ruby", generic_local_platform, defaults: [])}
+
+ DEPENDENCIES
+ concurrent-ruby
+ rack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "can fallback to a source gem when platform gems are incompatible with current ruby version" do
+ setup_multiplatform_gem_with_source_gem
+
+ source = file_uri_for(gem_repo2)
+
+ gemfile <<~G
+ source "#{source}"
+
+ gem "my-precompiled-gem"
+ G
+
+ # simulate lockfile which includes both a precompiled gem with:
+ # - Gem the current platform (with incompatible ruby version)
+ # - A source gem with compatible ruby version
+ lockfile <<-L
+ GEM
+ remote: #{source}/
+ specs:
+ my-precompiled-gem (3.0.0)
+ my-precompiled-gem (3.0.0-#{Bundler.local_platform})
+
+ PLATFORMS
+ ruby
+ #{Bundler.local_platform}
+
+ DEPENDENCIES
+ my-precompiled-gem
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+ end
+
+ it "automatically fixes the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
+ #
+ # Given an existing application using native gems (e.g., nokogiri)
+ # And a lockfile generated with a stable ruby version
+ # When want test the application against ruby-head and `bundle install`
+ # Then bundler should fall back to the generic ruby platform gem
+ #
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0"
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri", "1.14.0"
+ G
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri (= 1.14.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0"
+ end
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri (= 1.14.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "locks specific platforms automatically" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0"
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "arm-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x64-mingw32"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "java"
+ end
+
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "universal-darwin-22"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ G
+
+ bundle "lock"
+
+ checksums = checksums_section_when_existing do |c|
+ c.no_checksum "nokogiri", "1.14.0"
+ c.no_checksum "nokogiri", "1.14.0", "arm-linux"
+ c.no_checksum "nokogiri", "1.14.0", "x86_64-linux"
+ end
+
+ # locks all compatible platforms, excluding Java and Windows
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0)
+ nokogiri (1.14.0-arm-linux)
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ arm-linux
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+
+ FileUtils.rm bundled_app_lock
+
+ bundle "lock"
+
+ checksums.delete "nokogiri", "arm-linux"
+ checksums.no_checksum "sorbet-static", "0.5.10696", "universal-darwin-22"
+ checksums.no_checksum "sorbet-static", "0.5.10696", "x86_64-linux"
+
+ # locks only platforms compatible with all gems in the bundle
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0)
+ nokogiri (1.14.0-x86_64-linux)
+ sorbet-static (0.5.10696-universal-darwin-22)
+ sorbet-static (0.5.10696-x86_64-linux)
+
+ PLATFORMS
+ universal-darwin-22
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution", rubygems: ">= 3.3.21" do
+ build_repo4 do
+ build_gem "nokogiri", "1.15.5"
+
+ build_gem "nokogiri", "1.15.5" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{current_ruby_minor}.dev"
+ end
+
+ build_gem "sass-embedded", "1.69.5"
+
+ build_gem "sass-embedded", "1.69.5" do |s|
+ s.platform = "x86_64-linux-gnu"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ gem "sass-embedded"
+ G
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "nokogiri", "1.15.5"
+ c.no_checksum "sass-embedded", "1.69.5"
+ c.checksum gem_repo4, "sass-embedded", "1.69.5", "x86_64-linux-gnu"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ # locks all compatible platforms, excluding Java and Windows
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.15.5)
+ sass-embedded (1.69.5)
+ sass-embedded (1.69.5-x86_64-linux-gnu)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sass-embedded
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not add ruby platform gem if it brings extra dependencies not resolved originally" do
+ build_repo4 do
+ build_gem "nokogiri", "1.15.5" do |s|
+ s.add_dependency "mini_portile2", "~> 2.8.2"
+ end
+
+ build_gem "nokogiri", "1.15.5" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ G
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo4, "nokogiri", "1.15.5", "x86_64-linux"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.15.5-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ ["x86_64-linux", "x86_64-linux-musl"].each do |host_platform|
+ describe "on host platform #{host_platform}" do
+ it "adds current musl platform" do
+ build_repo4 do
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux-musl"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "rcee_precompiled", "0.5.0"
+ G
+
+ simulate_platform host_platform do
+ bundle "lock", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rcee_precompiled (0.5.0-x86_64-linux)
+ rcee_precompiled (0.5.0-x86_64-linux-musl)
+
+ PLATFORMS
+ x86_64-linux
+ x86_64-linux-musl
+
+ DEPENDENCIES
+ rcee_precompiled (= 0.5.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+ end
+ end
+
+ it "adds current musl platform, when there are also gnu variants", rubygems: ">= 3.3.21" do
+ build_repo4 do
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux-gnu"
+ end
+
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux-musl"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "rcee_precompiled", "0.5.0"
+ G
+
+ simulate_platform "x86_64-linux-musl" do
+ bundle "lock", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rcee_precompiled (0.5.0-x86_64-linux-gnu)
+ rcee_precompiled (0.5.0-x86_64-linux-musl)
+
+ PLATFORMS
+ x86_64-linux-gnu
+ x86_64-linux-musl
+
+ DEPENDENCIES
+ rcee_precompiled (= 0.5.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not add current platform if there's an equivalent less specific platform among the ones resolved" do
+ build_repo4 do
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "universal-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "rcee_precompiled", "0.5.0"
+ G
+
+ simulate_platform "x86_64-darwin-15" do
+ bundle "lock", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rcee_precompiled (0.5.0-universal-darwin)
+
+ PLATFORMS
+ universal-darwin
+
+ DEPENDENCIES
+ rcee_precompiled (= 0.5.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
end
private
@@ -363,4 +1410,16 @@ RSpec.describe "bundle install with specific platforms" do
build_gem("CFPropertyList")
end
end
+
+ def setup_multiplatform_gem_with_source_gem
+ build_repo2 do
+ build_gem("my-precompiled-gem", "3.0.0")
+ build_gem("my-precompiled-gem", "3.0.0") do |s|
+ s.platform = Bundler.local_platform
+
+ # purposely unresolvable
+ s.required_ruby_version = ">= 1000.0.0"
+ end
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile_spec.rb b/spec/bundler/install/gemfile_spec.rb
index 0f8f1ecfa8..158645d3eb 100644
--- a/spec/bundler/install/gemfile_spec.rb
+++ b/spec/bundler/install/gemfile_spec.rb
@@ -3,7 +3,7 @@
RSpec.describe "bundle install" do
context "with duplicated gems" do
it "will display a warning" do
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem 'rails', '~> 4.0.0'
@@ -20,7 +20,7 @@ RSpec.describe "bundle install" do
gem 'rack'
G
- bundle :install, :gemfile => bundled_app("NotGemfile")
+ bundle :install, gemfile: bundled_app("NotGemfile")
# Specify BUNDLE_GEMFILE for `the_bundle`
# to retrieve the proper Gemfile
@@ -46,8 +46,8 @@ RSpec.describe "bundle install" do
end
it "uses the gemfile while in a subdirectory" do
bundled_app("subdir").mkpath
- bundle "install", :dir => bundled_app("subdir")
- bundle "list", :dir => bundled_app("subdir")
+ bundle "install", dir: bundled_app("subdir")
+ bundle "list", dir: bundled_app("subdir")
expect(out).to include("rack (1.0.0)")
end
@@ -61,12 +61,12 @@ RSpec.describe "bundle install" do
gem "rack", :lib => "rack"
G
- bundle :install, :raise_on_error => false
+ bundle :install, raise_on_error: false
expect(err).to match(/You passed :lib as an option for gem 'rack', but it is invalid/)
end
end
- context "with engine specified in symbol", :jruby do
+ context "with engine specified in symbol", :jruby_only do
it "does not raise any error parsing Gemfile" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index 72ad40e24f..50add8743b 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "compact index api" do
gem "rack"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -21,7 +21,7 @@ RSpec.describe "compact index api" do
gem " sinatra"
G
- bundle :install, :artifice => "compact_index", :raise_on_error => false
+ bundle :install, artifice: "compact_index", raise_on_error: false
expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.")
end
@@ -31,7 +31,7 @@ RSpec.describe "compact index api" do
gem "rails"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems(
"rails 2.3.2",
@@ -44,14 +44,14 @@ RSpec.describe "compact index api" do
end
it "should handle case sensitivity conflicts" do
- build_repo4 do
+ build_repo4(build_compact_index: false) do
build_gem "rack", "1.0" do |s|
s.add_runtime_dependency("Rack", "0.1")
end
build_gem "Rack", "0.1"
end
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
gem "rack", "1.0"
gem "Rack", "0.1"
@@ -69,7 +69,7 @@ RSpec.describe "compact index api" do
gem "net-sftp"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems "net-sftp 1.1.1"
end
@@ -78,11 +78,11 @@ RSpec.describe "compact index api" do
source "#{source_uri}"
gem "rack"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
bundle "config set --local deployment true"
bundle "config set --local path vendor/bundle"
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -100,7 +100,7 @@ RSpec.describe "compact index api" do
end
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("rails 2.3.2")
end
@@ -116,10 +116,10 @@ RSpec.describe "compact index api" do
gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
bundle "config set --local deployment true"
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("rails 2.3.2")
end
@@ -131,9 +131,9 @@ RSpec.describe "compact index api" do
gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
G
- bundle "install", :artifice => "compact_index"
+ bundle "install", artifice: "compact_index"
bundle "config set --local deployment true"
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("foo 1.0")
end
@@ -144,7 +144,7 @@ RSpec.describe "compact index api" do
gem "rack"
G
- bundle :install, :verbose => true, :artifice => "compact_index_forbidden"
+ bundle :install, verbose: true, artifice: "compact_index_forbidden"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -155,14 +155,34 @@ RSpec.describe "compact index api" do
gem "rack"
G
- bundle :install, :verbose => true, :artifice => "compact_index_checksum_mismatch"
+ bundle :install, verbose: true, artifice: "compact_index_checksum_mismatch"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(out).to include <<-'WARN'
-The checksum of /versions does not match the checksum provided by the server! Something is wrong (local checksum is "\"d41d8cd98f00b204e9800998ecf8427e\"", was expecting "\"123\"").
- WARN
+ expect(out).to include("The checksum of /versions does not match the checksum provided by the server!")
+ expect(out).to include('Calculated checksums {"sha-256"=>"8KfZiM/fszVkqhP/m5s9lvE6M9xKu4I1bU4Izddp5Ms="} did not match expected {"sha-256"=>"ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="}')
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ it "shows proper path when permission errors happen", :permissions do
+ gemfile <<-G
+ source "#{source_uri}"
+ gem "rack"
+ G
+
+ versions = Pathname.new(Bundler.rubygems.user_home).join(
+ ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
+ )
+ versions.dirname.mkpath
+ versions.write("created_at")
+ FileUtils.chmod("-r", versions)
+
+ bundle :install, artifice: "compact_index", raise_on_error: false
+
+ expect(err).to include(
+ "There was an error while trying to read from `#{versions}`. It is likely that you need to grant read permissions for that path."
+ )
+ end
+
it "falls back when the user's home directory does not exist or is not writable" do
ENV["HOME"] = tmp("missing_home").to_s
@@ -171,7 +191,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -182,11 +202,11 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :artifice => "compact_index_host_redirect"
+ bundle :install, artifice: "compact_index_host_redirect"
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "handles host redirects without Net::HTTP::Persistent" do
+ it "handles host redirects without Gem::Net::HTTP::Persistent" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
@@ -205,7 +225,7 @@ The checksum of /versions does not match the checksum provided by the server! So
H
end
- bundle :install, :artifice => "compact_index_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")]
+ bundle :install, artifice: "compact_index_host_redirect", requires: [lib_path("disable_net_http_persistent.rb")]
expect(out).to_not match(/Too many redirects/)
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -216,7 +236,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :artifice => "compact_index_redirects", :raise_on_error => false
+ bundle :install, artifice: "compact_index_redirects", raise_on_error: false
expect(err).to match(/Too many redirects/)
end
@@ -227,7 +247,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle "install --full-index", :artifice => "compact_index"
+ bundle "install --full-index", artifice: "compact_index"
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -238,7 +258,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle "update --full-index", :artifice => "compact_index", :all => true
+ bundle "update --full-index", artifice: "compact_index", all: true
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -268,14 +288,14 @@ The checksum of /versions does not match the checksum provided by the server! So
end
end
- system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0], :gem_repo => gem_repo2
+ system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0], gem_repo: gem_repo2
bundle "config set --local path.system true"
- ENV["BUNDLER_SPEC_ALL_REQUESTS"] = strip_whitespace(<<-EOS).strip
+ ENV["BUNDLER_SPEC_ALL_REQUESTS"] = <<~EOS.strip
#{source_uri}/versions
#{source_uri}/info/rack
EOS
- install_gemfile <<-G, :artifice => "compact_index", :verbose => true, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ install_gemfile <<-G, artifice: "compact_index", verbose: true, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
source "#{source_uri}"
gem "rack"
G
@@ -283,7 +303,7 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(last_command.stdboth).not_to include "Double checking"
end
- it "fetches again when more dependencies are found in subsequent sources", :bundler => "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources", bundler: "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -297,7 +317,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "back_deps"
G
- bundle :install, :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
end
@@ -309,7 +329,7 @@ The checksum of /versions does not match the checksum provided by the server! So
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- install_gemfile <<-G, :artifice => "compact_index_extra", :verbose => true
+ install_gemfile <<-G, artifice: "compact_index_extra", verbose: true
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -324,7 +344,7 @@ The checksum of /versions does not match the checksum provided by the server! So
source "#{source_uri}"
gem "rack", "1.0.0"
G
- bundle :install, :artifice => "compact_index_extra_api"
+ bundle :install, artifice: "compact_index_extra_api"
expect(the_bundle).to include_gems "rack 1.0.0"
build_repo4 do
@@ -338,11 +358,11 @@ The checksum of /versions does not match the checksum provided by the server! So
source "#{source_uri}/extra"
gem "rack", "1.2"
G
- bundle :install, :artifice => "compact_index_extra_api"
+ bundle :install, artifice: "compact_index_extra_api"
expect(the_bundle).to include_gems "rack 1.2"
end
- it "considers all possible versions of dependencies from all api gem sources", :bundler => "< 3" do
+ it "considers all possible versions of dependencies from all api gem sources", bundler: "< 3" do
# In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
# exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
# of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
@@ -360,7 +380,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'somegem', '1.0.0'
G
- bundle :install, :artifice => "compact_index_extra_api"
+ bundle :install, artifice: "compact_index_extra_api"
expect(the_bundle).to include_gems "somegem 1.0.0"
expect(the_bundle).to include_gems "activesupport 1.2.3"
@@ -381,13 +401,13 @@ The checksum of /versions does not match the checksum provided by the server! So
end
G
- bundle :install, :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
expect(out).to include("Fetching gem metadata from http://localgemserver.test/")
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
end
- it "does not fetch every spec if the index of gems is large when doing back deps" do
+ it "does not fetch every spec when doing back deps" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -397,9 +417,7 @@ The checksum of /versions does not match the checksum provided by the server! So
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- api_request_limit = low_api_request_limit_for(gem_repo2)
-
- install_gemfile <<-G, :artifice => "compact_index_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, artifice: "compact_index_extra_missing"
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -409,7 +427,7 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "does not fetch every spec if the index of gems is large when doing back deps & everything is the compact index" do
+ it "does not fetch every spec when doing back deps & everything is the compact index" do
build_repo4 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -419,9 +437,7 @@ The checksum of /versions does not match the checksum provided by the server! So
FileUtils.rm_rf Dir[gem_repo4("gems/foo-*.gem")]
end
- api_request_limit = low_api_request_limit_for(gem_repo4)
-
- install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, artifice: "compact_index_extra_api_missing"
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -438,11 +454,11 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'foo'
G
- bundle :install, :artifice => "compact_index_api_missing"
+ bundle :install, artifice: "compact_index_api_missing"
expect(the_bundle).to include_gems "foo 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode", bundler: "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -456,9 +472,9 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "back_deps"
G
- bundle :install, :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
bundle "config --set local deployment true"
- bundle :install, :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
@@ -477,9 +493,9 @@ The checksum of /versions does not match the checksum provided by the server! So
end
G
- bundle :install, :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
bundle "config set --local deployment true"
- bundle :install, :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
@@ -496,52 +512,40 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "bundler_dep"
G
- bundle :install, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle :install, :artifice => "compact_index"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
- it "installs the binstubs", :bundler => "< 3" do
+ it "installs the binstubs", bundler: "< 3" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle "install --binstubs", :artifice => "compact_index"
+ bundle "install --binstubs", artifice: "compact_index"
gembin "rackup"
expect(out).to eq("1.0.0")
end
- it "installs the bins when using --path and uses autoclean", :bundler => "< 3" do
+ it "installs the bins when using --path and uses autoclean", bundler: "< 3" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle "install --path vendor/bundle", :artifice => "compact_index"
+ bundle "install --path vendor/bundle", artifice: "compact_index"
expect(vendored_gems("bin/rackup")).to exist
end
- it "installs the bins when using --path and uses bundle clean", :bundler => "< 3" do
+ it "installs the bins when using --path and uses bundle clean", bundler: "< 3" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle "install --path vendor/bundle --no-clean", :artifice => "compact_index"
+ bundle "install --path vendor/bundle --no-clean", artifice: "compact_index"
expect(vendored_gems("bin/rackup")).to exist
end
@@ -552,7 +556,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack-obama'
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Post-install message from rack:")
end
@@ -562,7 +566,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack_middleware'
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Post-install message from rack:")
expect(out).to include("Rack's post install message")
end
@@ -571,7 +575,7 @@ The checksum of /versions does not match the checksum provided by the server! So
let(:user) { "user" }
let(:password) { "pass" }
let(:basic_auth_source_uri) do
- uri = Bundler::URI.parse(source_uri)
+ uri = Gem::URI.parse(source_uri)
uri.user = user
uri.password = password
@@ -584,7 +588,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :artifice => "compact_index_basic_authentication"
+ bundle :install, artifice: "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -595,19 +599,19 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :verbose => true, :artifice => "compact_index_basic_authentication"
+ bundle :install, verbose: true, artifice: "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do
+ it "strips http basic auth creds when warning about ambiguous sources", bundler: "< 3" do
gemfile <<-G
source "#{basic_auth_source_uri}"
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- bundle :install, :artifice => "compact_index_basic_authentication"
+ bundle :install, artifice: "compact_index_basic_authentication"
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -619,7 +623,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :artifice => "compact_index_creds_diff_host"
+ bundle :install, artifice: "compact_index_creds_diff_host"
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -634,7 +638,7 @@ The checksum of /versions does not match the checksum provided by the server! So
it "reads authentication details by host name from bundle config" do
bundle "config set #{source_hostname} #{user}:#{password}"
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -644,7 +648,7 @@ The checksum of /versions does not match the checksum provided by the server! So
# The trailing slash is necessary here; Fetcher canonicalizes the URI.
bundle "config set #{source_uri}/ #{user}:#{password}"
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -652,7 +656,7 @@ The checksum of /versions does not match the checksum provided by the server! So
it "should use the API" do
bundle "config set #{source_hostname} #{user}:#{password}"
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -665,20 +669,29 @@ The checksum of /versions does not match the checksum provided by the server! So
bundle "config set #{source_hostname} otheruser:wrong"
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "shows instructions if auth is not provided for the source" do
- bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false
+ bundle :install, artifice: "compact_index_strict_basic_authentication", raise_on_error: false
expect(err).to include("bundle config set --global #{source_hostname} username:password")
end
it "fails if authentication has already been provided, but failed" do
bundle "config set #{source_hostname} #{user}:wrong"
- bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false
+ bundle :install, artifice: "compact_index_strict_basic_authentication", raise_on_error: false
+ expect(err).to include("Bad username or password")
+ end
+
+ it "does not fallback to old dependency API if bad authentication is provided" do
+ bundle "config set #{source_hostname} #{user}:wrong"
+
+ bundle :install, artifice: "compact_index_strict_basic_authentication", raise_on_error: false, verbose: true
expect(err).to include("Bad username or password")
+ expect(out).to include("HTTP 401 Unauthorized http://user@localgemserver.test/versions")
+ expect(out).not_to include("HTTP 401 Unauthorized http://user@localgemserver.test/api/v1/dependencies")
end
end
@@ -691,7 +704,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :artifice => "compact_index_basic_authentication"
+ bundle :install, artifice: "compact_index_basic_authentication"
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
@@ -716,7 +729,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :env => { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, :raise_on_error => false
+ bundle :install, env: { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, raise_on_error: false
expect(err).to include("OpenSSL")
end
end
@@ -726,7 +739,7 @@ The checksum of /versions does not match the checksum provided by the server! So
# Install a monkeypatch that reproduces the effects of openssl raising
# a certificate validation error when RubyGems tries to connect.
gemfile <<-G
- class Net::HTTP
+ class Gem::Net::HTTP
def start
raise OpenSSL::SSL::SSLError, "certificate verify failed"
end
@@ -736,7 +749,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :raise_on_error => false
+ bundle :install, raise_on_error: false
expect(err).to match(/could not verify the SSL certificate/i)
end
end
@@ -744,7 +757,7 @@ The checksum of /versions does not match the checksum provided by the server! So
context ".gemrc with sources is present" do
it "uses other sources declared in the Gemfile" do
File.open(home(".gemrc"), "w") do |file|
- file.puts({ :sources => ["https://rubygems.org"] }.to_yaml)
+ file.puts({ sources: ["https://rubygems.org"] }.to_yaml)
end
begin
@@ -753,21 +766,30 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack'
G
- bundle :install, :artifice => "compact_index_forbidden"
+ bundle :install, artifice: "compact_index_forbidden"
ensure
home(".gemrc").rmtree
end
end
end
- it "performs partial update with a non-empty range" do
+ it "performs update with etag not-modified" do
+ versions_etag = Pathname.new(Bundler.rubygems.user_home).join(
+ ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions.etag"
+ )
+ expect(versions_etag.file?).to eq(false)
+
gemfile <<-G
source "#{source_uri}"
gem 'rack', '0.9.1'
G
- # Initial install creates the cached versions file
- bundle :install, :artifice => "compact_index"
+ # Initial install creates the cached versions file and etag file
+ bundle :install, artifice: "compact_index"
+
+ expect(versions_etag.file?).to eq(true)
+ previous_content = versions_etag.binread
# Update the Gemfile so we can check subsequent install was successful
gemfile <<-G
@@ -775,8 +797,59 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack', '1.0.0'
G
- # Second install should make only a partial request to /versions
- bundle :install, :artifice => "compact_index_partial_update"
+ # Second install should match etag
+ bundle :install, artifice: "compact_index_etag_match"
+
+ expect(versions_etag.binread).to eq(previous_content)
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+
+ it "performs full update when range is ignored" do
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'rack', '0.9.1'
+ G
+
+ # Initial install creates the cached versions file and etag file
+ bundle :install, artifice: "compact_index"
+
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'rack', '1.0.0'
+ G
+
+ versions = Pathname.new(Bundler.rubygems.user_home).join(
+ ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
+ )
+ # Modify the cached file. The ranged request will be based on this but,
+ # in this test, the range is ignored so this gets overwritten, allowing install.
+ versions.write "ruining this file"
+
+ bundle :install, artifice: "compact_index_range_ignored"
+
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+
+ it "performs partial update with a non-empty range" do
+ build_repo4 do
+ build_gem "rack", "0.9.1"
+ end
+
+ # Initial install creates the cached versions file
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'rack', '0.9.1'
+ G
+
+ update_repo4 do
+ build_gem "rack", "1.0.0"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index_partial_update", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'rack', '1.0.0'
+ G
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -787,24 +860,48 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack'
G
- # Create an empty file to trigger a partial download
- versions = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
- "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions")
- FileUtils.mkdir_p(File.dirname(versions))
- FileUtils.touch(versions)
+ # Create a partial cache versions file
+ versions = Pathname.new(Bundler.rubygems.user_home).join(
+ ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
+ )
+ versions.dirname.mkpath
+ versions.write("created_at")
+
+ bundle :install, artifice: "compact_index_concurrent_download"
+
+ expect(versions.read).to start_with("created_at")
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+
+ it "performs a partial update that fails digest check, then a full update" do
+ build_repo4 do
+ build_gem "rack", "0.9.1"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'rack', '0.9.1'
+ G
+
+ update_repo4 do
+ build_gem "rack", "1.0.0"
+ end
- bundle :install, :artifice => "compact_index_concurrent_download"
+ install_gemfile <<-G, artifice: "compact_index_partial_update_bad_digest", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'rack', '1.0.0'
+ G
- expect(File.read(versions)).to start_with("created_at")
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "performs full update if server endpoints serve partial content responses but don't have incremental content and provide no Etag" do
+ it "performs full update if server endpoints serve partial content responses but don't have incremental content and provide no digest" do
build_repo4 do
build_gem "rack", "0.9.1"
end
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
gem 'rack', '0.9.1'
G
@@ -813,7 +910,7 @@ The checksum of /versions does not match the checksum provided by the server! So
build_gem "rack", "1.0.0"
end
- install_gemfile <<-G, :artifice => "compact_index_partial_update_no_etag_not_incremental", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ install_gemfile <<-G, artifice: "compact_index_partial_update_no_digest_not_incremental", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
gem 'rack', '1.0.0'
G
@@ -827,15 +924,19 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack', '0.9.1'
G
- rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
- "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack")
+ bundle :install, artifice: "compact_index"
- bundle :install, :artifice => "compact_index"
+ # We must remove the etag so that we don't ignore the range and get a 304 Not Modified.
+ rake_info_etag_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info-etags", "rack-11690b09f16021ff06a6857d784a1870")
+ File.unlink(rake_info_etag_path) if File.exist?(rake_info_etag_path)
+ rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack")
expected_rack_info_content = File.read(rake_info_path)
- # Modify the cache files. We expect them to be reset to the normal ones when we re-run :install
- File.open(rake_info_path, "w") {|f| f << (expected_rack_info_content + "this is different") }
+ # Modify the cache files to make the range not satisfiable
+ File.open(rake_info_path, "a") {|f| f << "0.9.2 |checksum:c55b525b421fd833a93171ad3d7f04528ca8e87d99ac273f8933038942a5888c" }
# Update the Gemfile so the next install does its normal things
gemfile <<-G
@@ -845,7 +946,7 @@ The checksum of /versions does not match the checksum provided by the server! So
# The cache files now being longer means the requested range is going to be not satisfiable
# Bundler must end up requesting the whole file to fix things up.
- bundle :install, :artifice => "compact_index_range_not_satisfiable"
+ bundle :install, artifice: "compact_index_range_not_satisfiable"
resulting_rack_info_content = File.read(rake_info_path)
@@ -853,7 +954,7 @@ The checksum of /versions does not match the checksum provided by the server! So
end
it "fails gracefully when the source URI has an invalid scheme" do
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "htps://rubygems.org"
gem "rack"
G
@@ -864,38 +965,76 @@ The checksum of /versions does not match the checksum provided by the server! So
end
describe "checksum validation" do
+ before do
+ lockfile <<-L
+ GEM
+ remote: #{source_uri}
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ #{checksums_section}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "handles checksums from the server in base64" do
+ api_checksum = checksum_digest(gem_repo1, "rack", "1.0.0")
+ rack_checksum = [[api_checksum].pack("H*")].pack("m0")
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_RACK_CHECKSUM" => rack_checksum }
+ source "#{source_uri}"
+ gem "rack"
+ G
+
+ expect(out).to include("Fetching gem metadata from #{source_uri}")
+ expect(the_bundle).to include_gems("rack 1.0.0")
+ end
+
it "raises when the checksum does not match" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum", raise_on_error: false
source "#{source_uri}"
gem "rack"
G
- expect(exitstatus).to eq(19)
- expect(err).
- to include("Bundler cannot continue installing rack (1.0.0).").
- and include("The checksum for the downloaded `rack-1.0.0.gem` does not match the checksum given by the server.").
- and include("This means the contents of the downloaded gem is different from what was uploaded to the server, and could be a potential security issue.").
- and include("To resolve this issue:").
- and include("1. delete the downloaded gem located at: `#{default_bundle_path}/gems/rack-1.0.0/rack-1.0.0.gem`").
- and include("2. run `bundle install`").
- and include("If you wish to continue installing the downloaded gem, and are certain it does not pose a security issue despite the mismatching checksum, do the following:").
- and include("1. run `bundle config set --local disable_checksum_validation true` to turn off checksum verification").
- and include("2. run `bundle install`").
- and match(/\(More info: The expected SHA256 checksum was "#{"ab" * 22}", but the checksum for the downloaded gem was ".+?"\.\)/)
+ gem_path = if Bundler.feature_flag.global_gem_cache?
+ default_cache_path.dirname.join("cache", "gems", "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "rack-1.0.0.gem")
+ else
+ default_cache_path.dirname.join("rack-1.0.0.gem")
+ end
+
+ expect(exitstatus).to eq(37)
+ expect(err).to eq <<~E.strip
+ Bundler found mismatched checksums. This is a potential security risk.
+ rack (1.0.0) sha256=2222222222222222222222222222222222222222222222222222222222222222
+ from the API at http://localgemserver.test/
+ #{checksum_to_lock(gem_repo1, "rack", "1.0.0")}
+ from the gem at #{gem_path}
+
+ If you trust the API at http://localgemserver.test/, to resolve this issue you can:
+ 1. remove the gem at #{gem_path}
+ 2. run `bundle install`
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
end
it "raises when the checksum is the wrong length" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => "checksum!", "DEBUG" => "1" }, :verbose => true, :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum", env: { "BUNDLER_SPEC_RACK_CHECKSUM" => "checksum!", "DEBUG" => "1" }, verbose: true, raise_on_error: false
source "#{source_uri}"
gem "rack"
G
- expect(exitstatus).to eq(5)
- expect(err).to include("The given checksum for rack-1.0.0 (\"checksum!\") is not a valid SHA256 hexdigest nor base64digest")
+ expect(exitstatus).to eq(14)
+ expect(err).to include('Invalid checksum for rack-0.9.1: "checksum!" is not a valid SHA256 hex or base64 digest')
end
it "does not raise when disable_checksum_validation is set" do
bundle "config set disable_checksum_validation true"
- install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum"
+ install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum"
source "#{source_uri}"
gem "rack"
G
@@ -903,7 +1042,7 @@ The checksum of /versions does not match the checksum provided by the server! So
end
it "works when cache dir is world-writable" do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
File.umask(0000)
source "#{source_uri}"
gem "rack"
@@ -911,11 +1050,11 @@ The checksum of /versions does not match the checksum provided by the server! So
end
it "doesn't explode when the API dependencies are wrong" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_dependencies", :env => { "DEBUG" => "true" }, :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index_wrong_dependencies", env: { "DEBUG" => "true" }, raise_on_error: false
source "#{source_uri}"
gem "rails"
G
- deps = [Gem::Dependency.new("rake", "= 13.0.1"),
+ deps = [Gem::Dependency.new("rake", "= #{rake_version}"),
Gem::Dependency.new("actionpack", "= 2.3.2"),
Gem::Dependency.new("activerecord", "= 2.3.2"),
Gem::Dependency.new("actionmailer", "= 2.3.2"),
@@ -923,12 +1062,12 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(out).to include("rails-2.3.2 from rubygems remote at #{source_uri}/ has either corrupted API or lockfile dependencies")
expect(err).to include(<<-E.strip)
Bundler::APIResponseMismatchError: Downloading rails-2.3.2 revealed dependencies not in the API or the lockfile (#{deps.map(&:to_s).join(", ")}).
-Either installing with `--full-index` or running `bundle update rails` should fix the problem.
+Running `bundle update rails` should fix the problem.
E
end
it "does not duplicate specs in the lockfile when updating and a dependency is not installed" do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "#{file_uri_for(gem_repo1)}"
source "#{source_uri}" do
gem "rails"
@@ -936,7 +1075,8 @@ Either installing with `--full-index` or running `bundle update rails` should fi
end
G
gem_command "uninstall activemerchant"
- bundle "update rails", :artifice => "compact_index"
- expect(lockfile.scan(/activemerchant \(/).size).to eq(1)
+ bundle "update rails", artifice: "compact_index"
+ count = lockfile.match?("CHECKSUMS") ? 2 : 1 # Once in the specs, and once in CHECKSUMS
+ expect(lockfile.scan(/activemerchant \(/).size).to eq(count)
end
end
diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb
index 79317a7fad..35468b3a1c 100644
--- a/spec/bundler/install/gems/dependency_api_spec.rb
+++ b/spec/bundler/install/gems/dependency_api_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -21,7 +21,7 @@ RSpec.describe "gemcutter's dependency API" do
gem " sinatra"
G
- bundle :install, :artifice => "endpoint", :raise_on_error => false
+ bundle :install, artifice: "endpoint", raise_on_error: false
expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.")
end
@@ -31,7 +31,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rails"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}/...")
expect(the_bundle).to include_gems(
"rails 2.3.2",
@@ -49,7 +49,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "net-sftp"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems "net-sftp 1.1.1"
end
@@ -58,11 +58,11 @@ RSpec.describe "gemcutter's dependency API" do
source "#{source_uri}"
gem "rack"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
bundle "config set --local deployment true"
bundle "config set --local path vendor/bundle"
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -80,7 +80,7 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems("rails 2.3.2")
end
@@ -96,10 +96,10 @@ RSpec.describe "gemcutter's dependency API" do
gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
bundle "config set --local deployment true"
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems("rails 2.3.2")
end
@@ -111,15 +111,15 @@ RSpec.describe "gemcutter's dependency API" do
gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
G
- bundle "install", :artifice => "endpoint"
+ bundle "install", artifice: "endpoint"
bundle "config set --local deployment true"
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems("foo 1.0")
end
it "falls back when the API errors out" do
- simulate_platform mswin
+ simulate_platform x86_mswin32
build_repo2 do
# The rcov gem is platform mswin32, but has no arch
@@ -134,7 +134,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rcov"
G
- bundle :install, :artifice => "windows", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle :install, artifice: "windows", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rcov 1.0.0"
end
@@ -150,7 +150,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
gem "rails"
G
- bundle :install, :artifice => "endpoint_fallback"
+ bundle :install, artifice: "endpoint_fallback"
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems(
@@ -171,7 +171,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :verbose => true, :artifice => "endpoint_marshal_fail"
+ bundle :install, verbose: true, artifice: "endpoint_marshal_fail"
expect(out).to include("could not fetch from the dependency API, trying the full index")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -182,7 +182,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :verbose => true, :artifice => "endpoint_api_forbidden"
+ bundle :install, verbose: true, artifice: "endpoint_api_forbidden"
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -193,11 +193,11 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_host_redirect"
+ bundle :install, artifice: "endpoint_host_redirect"
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "handles host redirects without Net::HTTP::Persistent" do
+ it "handles host redirects without Gem::Net::HTTP::Persistent" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
@@ -216,7 +216,7 @@ RSpec.describe "gemcutter's dependency API" do
H
end
- bundle :install, :artifice => "endpoint_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")]
+ bundle :install, artifice: "endpoint_host_redirect", requires: [lib_path("disable_net_http_persistent.rb")]
expect(out).to_not match(/Too many redirects/)
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -227,7 +227,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_redirect", :raise_on_error => false
+ bundle :install, artifice: "endpoint_redirect", raise_on_error: false
expect(err).to match(/Too many redirects/)
end
@@ -238,7 +238,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle "install --full-index", :artifice => "endpoint"
+ bundle "install --full-index", artifice: "endpoint"
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -249,13 +249,13 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle "update --full-index", :artifice => "endpoint", :all => true
+ bundle "update --full-index", artifice: "endpoint", all: true
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
- it "fetches again when more dependencies are found in subsequent sources", :bundler => "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources", bundler: "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -269,7 +269,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "back_deps"
G
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
end
@@ -288,7 +288,7 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
end
@@ -297,7 +297,7 @@ RSpec.describe "gemcutter's dependency API" do
source "#{source_uri}"
gem "rack", "1.0.0"
G
- bundle :install, :artifice => "endpoint_extra_api"
+ bundle :install, artifice: "endpoint_extra_api"
build_repo4 do
build_gem "rack", "1.2" do |s|
@@ -310,11 +310,11 @@ RSpec.describe "gemcutter's dependency API" do
source "#{source_uri}/extra"
gem "rack", "1.2"
G
- bundle :install, :artifice => "endpoint_extra_api"
+ bundle :install, artifice: "endpoint_extra_api"
expect(the_bundle).to include_gems "rack 1.2"
end
- it "considers all possible versions of dependencies from all api gem sources", :bundler => "< 3" do
+ it "considers all possible versions of dependencies from all api gem sources", bundler: "< 3" do
# In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
# exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
# of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
@@ -332,7 +332,7 @@ RSpec.describe "gemcutter's dependency API" do
gem 'somegem', '1.0.0'
G
- bundle :install, :artifice => "endpoint_extra_api"
+ bundle :install, artifice: "endpoint_extra_api"
expect(the_bundle).to include_gems "somegem 1.0.0"
expect(the_bundle).to include_gems "activesupport 1.2.3"
@@ -353,13 +353,13 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
expect(out).to include("Fetching gem metadata from http://localgemserver.test/.")
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
end
- it "does not fetch every spec if the index of gems is large when doing back deps", :bundler => "< 3" do
+ it "does not fetch every spec when doing back deps", bundler: "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -369,9 +369,7 @@ RSpec.describe "gemcutter's dependency API" do
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- api_request_limit = low_api_request_limit_for(gem_repo2)
-
- install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, artifice: "endpoint_extra_missing"
source "#{source_uri}"
source "#{source_uri}/extra"
gem "back_deps"
@@ -380,7 +378,7 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "does not fetch every spec if the index of gems is large when doing back deps using blocks" do
+ it "does not fetch every spec when doing back deps using blocks" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -390,9 +388,7 @@ RSpec.describe "gemcutter's dependency API" do
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- api_request_limit = low_api_request_limit_for(gem_repo2)
-
- install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, artifice: "endpoint_extra_missing"
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -402,7 +398,7 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode", bundler: "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -416,9 +412,9 @@ RSpec.describe "gemcutter's dependency API" do
gem "back_deps"
G
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
bundle "config set --local deployment true"
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
@@ -437,12 +433,28 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
bundle "config set --local deployment true"
- bundle "install", :artifice => "endpoint_extra"
+ bundle "install", artifice: "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
+ it "does not fetch all marshaled specs" do
+ build_repo2 do
+ build_gem "foo", "1.0"
+ build_gem "foo", "2.0"
+ end
+
+ install_gemfile <<-G, artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, verbose: true
+ source "#{source_uri}"
+
+ gem "foo"
+ G
+
+ expect(out).to include("foo-2.0.gemspec.rz")
+ expect(out).not_to include("foo-1.0.gemspec.rz")
+ end
+
it "does not refetch if the only unmet dependency is bundler" do
build_repo2 do
build_gem "bundler_dep" do |s|
@@ -456,52 +468,40 @@ RSpec.describe "gemcutter's dependency API" do
gem "bundler_dep"
G
- bundle :install, :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle :install, artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle :install, :artifice => "endpoint"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
- it "installs the binstubs", :bundler => "< 3" do
+ it "installs the binstubs", bundler: "< 3" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle "install --binstubs", :artifice => "endpoint"
+ bundle "install --binstubs", artifice: "endpoint"
gembin "rackup"
expect(out).to eq("1.0.0")
end
- it "installs the bins when using --path and uses autoclean", :bundler => "< 3" do
+ it "installs the bins when using --path and uses autoclean", bundler: "< 3" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle "install --path vendor/bundle", :artifice => "endpoint"
+ bundle "install --path vendor/bundle", artifice: "endpoint"
expect(vendored_gems("bin/rackup")).to exist
end
- it "installs the bins when using --path and uses bundle clean", :bundler => "< 3" do
+ it "installs the bins when using --path and uses bundle clean", bundler: "< 3" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle "install --path vendor/bundle --no-clean", :artifice => "endpoint"
+ bundle "install --path vendor/bundle --no-clean", artifice: "endpoint"
expect(vendored_gems("bin/rackup")).to exist
end
@@ -512,7 +512,7 @@ RSpec.describe "gemcutter's dependency API" do
gem 'rack-obama'
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Post-install message from rack:")
end
@@ -522,7 +522,7 @@ RSpec.describe "gemcutter's dependency API" do
gem 'rack_middleware'
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Post-install message from rack:")
expect(out).to include("Rack's post install message")
end
@@ -531,7 +531,7 @@ RSpec.describe "gemcutter's dependency API" do
let(:user) { "user" }
let(:password) { "pass" }
let(:basic_auth_source_uri) do
- uri = Bundler::URI.parse(source_uri)
+ uri = Gem::URI.parse(source_uri)
uri.user = user
uri.password = password
@@ -544,7 +544,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_basic_authentication"
+ bundle :install, artifice: "endpoint_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -555,7 +555,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :verbose => true, :artifice => "endpoint_basic_authentication"
+ bundle :install, verbose: true, artifice: "endpoint_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -566,7 +566,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_marshal_fail_basic_authentication"
+ bundle :install, artifice: "endpoint_marshal_fail_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -577,18 +577,18 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_500", :raise_on_error => false
+ bundle :install, artifice: "endpoint_500", raise_on_error: false
expect(out).not_to include("#{user}:#{password}")
end
- it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do
+ it "strips http basic auth creds when warning about ambiguous sources", bundler: "< 3" do
gemfile <<-G
source "#{basic_auth_source_uri}"
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- bundle :install, :artifice => "endpoint_basic_authentication"
+ bundle :install, artifice: "endpoint_basic_authentication"
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -600,7 +600,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_creds_diff_host"
+ bundle :install, artifice: "endpoint_creds_diff_host"
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -613,7 +613,7 @@ RSpec.describe "gemcutter's dependency API" do
end
it "reads authentication details from a valid ENV variable" do
- bundle :install, :artifice => "endpoint_strict_basic_authentication", :env => { "BUNDLE_LOCAL___GEMSERVER__TEST" => "#{user}:#{password}" }
+ bundle :install, artifice: "endpoint_strict_basic_authentication", env: { "BUNDLE_LOCAL___GEMSERVER__TEST" => "#{user}:#{password}" }
expect(out).to include("Fetching gem metadata from http://local-gemserver.test")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -631,7 +631,7 @@ RSpec.describe "gemcutter's dependency API" do
it "reads authentication details by host name from bundle config" do
bundle "config set #{source_hostname} #{user}:#{password}"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -641,7 +641,7 @@ RSpec.describe "gemcutter's dependency API" do
# The trailing slash is necessary here; Fetcher canonicalizes the URI.
bundle "config set #{source_uri}/ #{user}:#{password}"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -649,7 +649,7 @@ RSpec.describe "gemcutter's dependency API" do
it "should use the API" do
bundle "config set #{source_hostname} #{user}:#{password}"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -662,19 +662,19 @@ RSpec.describe "gemcutter's dependency API" do
bundle "config set #{source_hostname} otheruser:wrong"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "shows instructions if auth is not provided for the source" do
- bundle :install, :artifice => "endpoint_strict_basic_authentication", :raise_on_error => false
+ bundle :install, artifice: "endpoint_strict_basic_authentication", raise_on_error: false
expect(err).to include("bundle config set --global #{source_hostname} username:password")
end
it "fails if authentication has already been provided, but failed" do
bundle "config set #{source_hostname} #{user}:wrong"
- bundle :install, :artifice => "endpoint_strict_basic_authentication", :raise_on_error => false
+ bundle :install, artifice: "endpoint_strict_basic_authentication", raise_on_error: false
expect(err).to include("Bad username or password")
end
end
@@ -688,7 +688,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_basic_authentication"
+ bundle :install, artifice: "endpoint_basic_authentication"
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
@@ -713,7 +713,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :env => { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, :raise_on_error => false
+ bundle :install, env: { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, raise_on_error: false
expect(err).to include("OpenSSL")
end
end
@@ -723,7 +723,7 @@ RSpec.describe "gemcutter's dependency API" do
# Install a monkeypatch that reproduces the effects of openssl raising
# a certificate validation error when RubyGems tries to connect.
gemfile <<-G
- class Net::HTTP
+ class Gem::Net::HTTP
def start
raise OpenSSL::SSL::SSLError, "certificate verify failed"
end
@@ -733,7 +733,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :raise_on_error => false
+ bundle :install, raise_on_error: false
expect(err).to match(/could not verify the SSL certificate/i)
end
end
@@ -741,7 +741,7 @@ RSpec.describe "gemcutter's dependency API" do
context ".gemrc with sources is present" do
it "uses other sources declared in the Gemfile" do
File.open(home(".gemrc"), "w") do |file|
- file.puts({ :sources => ["https://rubygems.org"] }.to_yaml)
+ file.puts({ sources: ["https://rubygems.org"] }.to_yaml)
end
begin
@@ -750,7 +750,7 @@ RSpec.describe "gemcutter's dependency API" do
gem 'rack'
G
- bundle "install", :artifice => "endpoint_marshal_fail"
+ bundle "install", artifice: "endpoint_marshal_fail"
ensure
home(".gemrc").rmtree
end
diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb
index f9b374cf01..8ef3984975 100644
--- a/spec/bundler/install/gems/flex_spec.rb
+++ b/spec/bundler/install/gems/flex_spec.rb
@@ -156,7 +156,7 @@ RSpec.describe "bundle flex_install" do
end
end
- describe "when Gemfile conflicts with lockfile" do
+ describe "when running bundle install and Gemfile conflicts with lockfile" do
before(:each) do
build_repo2
install_gemfile <<-G
@@ -183,34 +183,70 @@ RSpec.describe "bundle flex_install" do
end
it "does not install gems whose dependencies are not met" do
- bundle :install, :raise_on_error => false
- ruby <<-RUBY, :raise_on_error => false
+ bundle :install, raise_on_error: false
+ ruby <<-RUBY, raise_on_error: false
require 'bundler/setup'
RUBY
expect(err).to match(/could not find gem 'rack-obama/i)
end
- it "suggests bundle update when the Gemfile requires different versions than the lock" do
+ it "discards the locked gems when the Gemfile requires different versions than the lock" do
bundle "config set force_ruby_platform true"
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "rack":
- In snapshot (Gemfile.lock):
- rack (= 0.9.1)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- In Gemfile:
- rack-obama (= 2.0) was resolved to 2.0, which depends on
- rack (= 1.2)
+ Because rack-obama >= 2.0 depends on rack = 1.2
+ and rack = 1.2 could not be found in rubygems repository #{file_uri_for(gem_repo2)}/, cached gems or installed locally,
+ rack-obama >= 2.0 cannot be used.
+ So, because Gemfile depends on rack-obama = 2.0,
+ version solving has failed.
+ E
+
+ bundle :install, retry: 0, raise_on_error: false
+ expect(err).to end_with(nice_error)
+ end
- rack_middleware was resolved to 1.0, which depends on
- rack (= 0.9.1)
+ it "does not include conflicts with a single requirement tree, because that can't possibly be a conflict" do
+ bundle "config set force_ruby_platform true"
- Running `bundle update` will rebuild your snapshot from scratch, using only
- the gems in your Gemfile, which may resolve the conflict.
+ bad_error = <<~E.strip
+ Bundler could not find compatible versions for gem "rack-obama":
+ In Gemfile:
+ rack-obama (= 2.0)
E
- bundle :install, :retry => 0, :raise_on_error => false
- expect(err).to end_with(nice_error)
+ bundle "update rack_middleware", retry: 0, raise_on_error: false
+ expect(err).not_to end_with(bad_error)
+ end
+ end
+
+ describe "when running bundle update and Gemfile conflicts with lockfile" do
+ before(:each) do
+ build_repo4 do
+ build_gem "jekyll-feed", "0.16.0"
+ build_gem "jekyll-feed", "0.15.1"
+
+ build_gem "github-pages", "226" do |s|
+ s.add_dependency "jekyll-feed", "0.15.1"
+ end
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "jekyll-feed", "~> 0.12"
+ G
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "github-pages", "~> 226"
+ gem "jekyll-feed", "~> 0.12"
+ G
+ end
+
+ it "discards the conflicting lockfile information and resolves properly" do
+ bundle :update, raise_on_error: false, all: true
+ expect(err).to be_empty
end
end
@@ -232,6 +268,11 @@ RSpec.describe "bundle flex_install" do
it "should work when you install" do
bundle "install"
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo1, "rack", "0.9.1"
+ c.checksum gem_repo1, "rack-obama", "1.0"
+ end
+
expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
@@ -246,7 +287,7 @@ RSpec.describe "bundle flex_install" do
DEPENDENCIES
rack (= 0.9.1)
rack-obama
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -272,6 +313,10 @@ RSpec.describe "bundle flex_install" do
gem "rack"
G
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo1, "rack", "1.0.0"
+ end
+
expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
@@ -287,7 +332,7 @@ RSpec.describe "bundle flex_install" do
DEPENDENCIES
rack
-
+ #{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
@@ -314,7 +359,7 @@ RSpec.describe "bundle flex_install" do
end
end
- it "prints the correct error message" do
+ it "resolves them" do
# install Rails 3.0.0.rc
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -323,13 +368,12 @@ RSpec.describe "bundle flex_install" do
G
# upgrade Rails to 3.0.0 and then install again
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0.0"
gem "capybara", "0.3.9"
G
-
- expect(err).to include("Gemfile.lock")
+ expect(err).to be_empty
end
end
end
diff --git a/spec/bundler/install/gems/fund_spec.rb b/spec/bundler/install/gems/fund_spec.rb
index f521b0296f..9aadc9ed25 100644
--- a/spec/bundler/install/gems/fund_spec.rb
+++ b/spec/bundler/install/gems/fund_spec.rb
@@ -6,20 +6,20 @@ RSpec.describe "bundle install" do
build_repo2 do
build_gem "has_funding_and_other_metadata" do |s|
s.metadata = {
- "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
- "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
"documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
- "homepage_uri" => "https://bestgemever.example.io",
- "mailing_list_uri" => "https://groups.example.com/bestgemever",
- "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
- "source_code_uri" => "https://example.com/user/bestgemever",
- "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
}
end
build_gem "has_funding", "1.2.3" do |s|
s.metadata = {
- "funding_uri" => "https://example.com/has_funding/funding",
+ "funding_uri" => "https://example.com/has_funding/funding",
}
end
@@ -52,6 +52,33 @@ RSpec.describe "bundle install" do
end
end
+ context "when gems include a fund URI but `ignore_funding_requests` is configured" do
+ before do
+ bundle "config set ignore_funding_requests true"
+ end
+
+ it "does not display the plural fund message after installing" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ gem 'rack-obama'
+ G
+
+ expect(out).not_to include("2 installed gems you directly depend on are looking for funding.")
+ end
+
+ it "does not display the singular fund message after installing" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding'
+ gem 'rack-obama'
+ G
+
+ expect(out).not_to include("1 installed gem you directly depend on is looking for funding.")
+ end
+ end
+
context "when gems do not include fund messages" do
it "does not display any fund messages" do
install_gemfile <<-G
diff --git a/spec/bundler/install/gems/native_extensions_spec.rb b/spec/bundler/install/gems/native_extensions_spec.rb
index d5cafcfc2c..907778a384 100644
--- a/spec/bundler/install/gems/native_extensions_spec.rb
+++ b/spec/bundler/install/gems/native_extensions_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "installing a gem with native extensions", :ruby_repo do
+RSpec.describe "installing a gem with native extensions" do
it "installs" do
build_repo2 do
build_gem "c_extension" do |s|
@@ -91,7 +91,7 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
it "installs correctly from git when multiple gems with extensions share one repository" do
build_repo2 do
["one", "two"].each do |n|
- build_lib "c_extension_#{n}", "1.0", :path => lib_path("gems/c_extension_#{n}") do |s|
+ build_lib "c_extension_#{n}", "1.0", path: lib_path("gems/c_extension_#{n}") do |s|
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-E
require "mkmf"
@@ -119,7 +119,7 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
C
end
end
- build_git "gems", :path => lib_path("gems"), :gemspec => false
+ build_git "gems", path: lib_path("gems"), gemspec: false
end
bundle "config set build.c_extension_one --with-c_extension_one=one"
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index 469ecd412f..c5f9c4a3d3 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -106,7 +106,7 @@ RSpec.describe "bundle install with install-time dependencies" do
path = "#{gem_repo2}/#{Gem::MARSHAL_SPEC_DIR}/actionpack-2.3.2.gemspec.rz"
spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
spec.dependencies.each do |d|
- d.instance_variable_set(:@type, :fail)
+ d.instance_variable_set(:@type, "fail")
end
File.open(path, "wb") do |f|
f.write Gem.deflate(Marshal.dump(spec))
@@ -131,7 +131,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
it "installs plugins depended on by other plugins" do
- install_gemfile <<-G, :env => { "DEBUG" => "1" }
+ install_gemfile <<-G, env: { "DEBUG" => "1" }
source "#{file_uri_for(gem_repo2)}"
gem "net_a"
G
@@ -140,7 +140,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
it "installs multiple levels of dependencies" do
- install_gemfile <<-G, :env => { "DEBUG" => "1" }
+ install_gemfile <<-G, env: { "DEBUG" => "1" }
source "#{file_uri_for(gem_repo2)}"
gem "net_c"
gem "net_e"
@@ -157,9 +157,9 @@ RSpec.describe "bundle install with install-time dependencies" do
gem "net_e"
G
- bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
+ bundle :install, env: { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
- expect(out).to include("BUNDLER: Starting resolution")
+ expect(out).to include("Resolving dependencies...")
end
end
@@ -171,9 +171,9 @@ RSpec.describe "bundle install with install-time dependencies" do
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
+ bundle :install, env: { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
- expect(out).to include("BUNDLER: Starting resolution")
+ expect(out).to include("Resolving dependencies...")
end
end
@@ -185,18 +185,12 @@ RSpec.describe "bundle install with install-time dependencies" do
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" }
-
- 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
+ bundle :install, env: { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" }
expect(out).to include(" net_b").
- and include("BUNDLER: Starting resolution").
- and include("BUNDLER: Finished resolution").
- and include("Attempting to activate [#{activated_groups}]")
+ and include("Resolving dependencies...").
+ and include("Solution found after 1 attempts:").
+ and include("selected net_b 1.0")
end
end
end
@@ -214,13 +208,13 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
- ruby "#{RUBY_VERSION}"
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ ruby "#{Gem.ruby_version}"
source "http://localgemserver.test/"
gem 'rack'
G
- expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
@@ -235,51 +229,304 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- install_gemfile <<-G, :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
- ruby "#{RUBY_VERSION}"
+ install_gemfile <<-G, artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ ruby "#{Gem.ruby_version}"
source "http://localgemserver.test/"
gem 'rack'
G
- expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
- it "gives a meaningful error if there's a lockfile using the newer incompatible version" do
- build_repo2 do
- build_gem "parallel_tests", "3.7.0" do |s|
- s.required_ruby_version = ">= #{current_ruby_minor}"
+ context "when there is a lockfile using the newer incompatible version" do
+ before do
+ build_repo2 do
+ build_gem "parallel_tests", "3.7.0" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+ end
+
+ build_gem "parallel_tests", "3.8.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+ end
end
- build_gem "parallel_tests", "3.8.0" do |s|
- s.required_ruby_version = ">= #{next_ruby_minor}"
+ gemfile <<-G
+ source "http://localgemserver.test/"
+ gem 'parallel_tests'
+ G
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo2, "parallel_tests", "3.8.0"
end
+
+ lockfile <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ parallel_tests (3.8.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
- gemfile <<-G
- source "http://localgemserver.test/"
- gem 'parallel_tests'
- G
+ it "automatically updates lockfile to use the older version" do
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo2, "parallel_tests", "3.7.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ parallel_tests (3.7.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "gives a meaningful error if we're in frozen mode" do
+ expect do
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s, "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ end.not_to change { lockfile }
- lockfile <<~L
- GEM
- remote: http://localgemserver.test/
- specs:
- parallel_tests (3.8.0)
+ expect(err).to include("parallel_tests-3.8.0 requires ruby version >= #{next_ruby_minor}")
+ expect(err).not_to include("That means the author of parallel_tests (3.8.0) has removed it.")
+ end
+ end
+
+ context "with transitive dependencies in a lockfile" do
+ before do
+ build_repo2 do
+ build_gem "rubocop", "1.28.2" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
- PLATFORMS
- #{lockfile_platforms}
+ s.add_dependency "rubocop-ast", ">= 1.17.0", "< 2.0"
+ end
- DEPENDENCIES
- parallel_tests
+ build_gem "rubocop", "1.35.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ s.add_dependency "rubocop-ast", ">= 1.20.1", "< 2.0"
+ end
- bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, :raise_on_error => false
- expect(err).to include("parallel_tests-3.8.0 requires ruby version >= #{next_ruby_minor}")
- expect(err).not_to include("That means the author of parallel_tests (3.8.0) has removed it.")
+ build_gem "rubocop-ast", "1.17.0" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+ end
+
+ build_gem "rubocop-ast", "1.21.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+ end
+ end
+
+ gemfile <<-G
+ source "http://localgemserver.test/"
+ gem 'rubocop'
+ G
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo2, "rubocop", "1.35.0"
+ c.checksum gem_repo2, "rubocop-ast", "1.21.0"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ rubocop (1.35.0)
+ rubocop-ast (>= 1.20.1, < 2.0)
+ rubocop-ast (1.21.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically updates lockfile to use the older compatible versions" do
+ bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+
+ checksums = checksums_section_when_existing do |c|
+ c.checksum gem_repo2, "rubocop", "1.28.2"
+ c.checksum gem_repo2, "rubocop-ast", "1.17.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ rubocop (1.28.2)
+ rubocop-ast (>= 1.17.0, < 2.0)
+ rubocop-ast (1.17.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rubocop
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "with a Gemfile and lock file that don't resolve under the current platform" do
+ before do
+ build_repo4 do
+ build_gem "sorbet", "0.5.10554" do |s|
+ s.add_dependency "sorbet-static", "0.5.10554"
+ end
+
+ build_gem "sorbet-static", "0.5.10554" do |s|
+ s.platform = "universal-darwin-21"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'sorbet', '= 0.5.10554'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10554)
+ sorbet-static (= 0.5.10554)
+ sorbet-static (0.5.10554-universal-darwin-21)
+
+ PLATFORMS
+ arm64-darwin-21
+
+ DEPENDENCIES
+ sorbet (= 0.5.10554)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a proper error" do
+ simulate_platform "aarch64-linux" do
+ bundle "install", raise_on_error: false
+ end
+
+ nice_error = <<~E.strip
+ Could not find gems matching 'sorbet-static (= 0.5.10554)' valid for all resolution platforms (arm64-darwin-21, aarch64-linux) in rubygems repository #{file_uri_for(gem_repo4)}/, cached gems or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.10554)':
+ * sorbet-static-0.5.10554-universal-darwin-21
+ E
+ expect(err).to end_with(nice_error)
+ end
+ end
+
+ context "when adding a new gem that does not resolve under all locked platforms" do
+ before do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "arm-linux"
+ end
+
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0-arm-linux)
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ arm-linux
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+
+ bundle "lock", raise_on_error: false
+ end
+ end
+
+ it "raises a proper error" do
+ nice_error = <<~E.strip
+ Could not find gems matching 'sorbet-static' valid for all resolution platforms (arm-linux, x86_64-linux) in rubygems repository #{file_uri_for(gem_repo4)}/, cached gems or installed locally.
+
+ The source contains the following gems matching 'sorbet-static':
+ * sorbet-static-0.5.10696-x86_64-linux
+ E
+ expect(err).to end_with(nice_error)
+ end
+ end
+
+ it "gives a meaningful error on ruby version mismatches between dependencies" do
+ build_repo4 do
+ build_gem "requires-old-ruby" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ build_lib("foo", path: bundled_app) do |s|
+ s.required_ruby_version = ">= #{Gem.ruby_version}"
+
+ s.add_dependency "requires-old-ruby"
+ end
+
+ install_gemfile <<-G, raise_on_error: false
+ source "#{file_uri_for(gem_repo4)}"
+ gemspec
+ G
+
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of foo depends on requires-old-ruby >= 0
+ and every version of requires-old-ruby depends on Ruby < #{Gem.ruby_version},
+ every version of foo requires Ruby < #{Gem.ruby_version}.
+ So, because Gemfile depends on foo >= 0
+ and current Ruby version is = #{Gem.ruby_version},
+ version solving has failed.
+ E
end
it "installs the older version under rate limiting conditions" do
@@ -291,14 +538,14 @@ RSpec.describe "bundle install with install-time dependencies" do
build_gem "foo1", "1.0"
end
- install_gemfile <<-G, :artifice => "compact_index_rate_limited", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- ruby "#{RUBY_VERSION}"
+ install_gemfile <<-G, artifice: "compact_index_rate_limited", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ ruby "#{Gem.ruby_version}"
source "http://localgemserver.test/"
gem 'rack'
gem 'foo1'
G
- expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
@@ -308,22 +555,22 @@ RSpec.describe "bundle install with install-time dependencies" do
s.required_ruby_version = "> 9000"
end
build_gem "rack", "1.2" do |s|
- s.platform = mingw
+ s.platform = x86_mingw32
s.required_ruby_version = "> 9000"
end
build_gem "rack", "1.2"
end
- simulate_platform mingw do
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- ruby "#{RUBY_VERSION}"
+ simulate_platform x86_mingw32 do
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ ruby "#{Gem.ruby_version}"
source "http://localgemserver.test/"
gem 'rack'
G
end
- expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
- expect(out).to_not include("rack-1.2-#{Bundler.local_platform} requires ruby version > 9000")
+ expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("rack-1.2-#{Bundler.local_platform} requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
end
@@ -337,33 +584,32 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- let(:ruby_requirement) { %("#{RUBY_VERSION}") }
- let(:error_message_requirement) { "= #{RUBY_VERSION}" }
+ let(:ruby_requirement) { %("#{Gem.ruby_version}") }
+ let(:error_message_requirement) { "= #{Gem.ruby_version}" }
it "raises a proper error that mentions the current Ruby version during resolution" do
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, raise_on_error: false
source "http://localgemserver.test/"
gem 'require_ruby'
G
expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000")
- nice_error = strip_whitespace(<<-E).strip
- Bundler found conflicting requirements for the Ruby\0 version:
- In Gemfile:
- require_ruby was resolved to 1.0, which depends on
- Ruby\0 (> 9000)
-
- Current Ruby\0 version:
- Ruby\0 (#{error_message_requirement})
+ nice_error = <<~E.strip
+ Could not find compatible versions
+ Because every version of require_ruby depends on Ruby > 9000
+ and Gemfile depends on require_ruby >= 0,
+ Ruby > 9000 is required.
+ So, because current Ruby version is #{error_message_requirement},
+ version solving has failed.
E
expect(err).to end_with(nice_error)
end
shared_examples_for "ruby version conflicts" do
it "raises an error during resolution" do
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, raise_on_error: false
source "http://localgemserver.test/"
ruby #{ruby_requirement}
gem 'require_ruby'
@@ -371,15 +617,14 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000")
- nice_error = strip_whitespace(<<-E).strip
- Bundler found conflicting requirements for the Ruby\0 version:
- In Gemfile:
- require_ruby was resolved to 1.0, which depends on
- Ruby\0 (> 9000)
-
- Current Ruby\0 version:
- Ruby\0 (#{error_message_requirement})
+ nice_error = <<~E.strip
+ Could not find compatible versions
+ Because every version of require_ruby depends on Ruby > 9000
+ and Gemfile depends on require_ruby >= 0,
+ Ruby > 9000 is required.
+ So, because current Ruby version is #{error_message_requirement},
+ version solving has failed.
E
expect(err).to end_with(nice_error)
end
@@ -410,21 +655,18 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo2)}"
gem 'require_rubygems'
G
expect(err).to_not include("Gem::InstallError: require_rubygems requires RubyGems version > 9000")
- nice_error = strip_whitespace(<<-E).strip
- Bundler found conflicting requirements for the RubyGems\0 version:
- In Gemfile:
- require_rubygems was resolved to 1.0, which depends on
- RubyGems\0 (> 9000)
-
- Current RubyGems\0 version:
- RubyGems\0 (= #{Gem::VERSION})
-
+ nice_error = <<~E.strip
+ Because every version of require_rubygems depends on RubyGems > 9000
+ and Gemfile depends on require_rubygems >= 0,
+ RubyGems > 9000 is required.
+ So, because current RubyGems version is = #{Gem::VERSION},
+ version solving has failed.
E
expect(err).to end_with(nice_error)
end
diff --git a/spec/bundler/install/gems/standalone_spec.rb b/spec/bundler/install/gems/standalone_spec.rb
index 5cbb484c68..46cab2dfeb 100644
--- a/spec/bundler/install/gems/standalone_spec.rb
+++ b/spec/bundler/install/gems/standalone_spec.rb
@@ -32,6 +32,21 @@ RSpec.shared_examples "bundle install --standalone" do
expect(out).to eq(expected_gems.values.join("\n"))
end
+ it "makes the gems available without bundler nor rubygems" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nrequire \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
+ end
+ sys_exec %(#{Gem.ruby} --disable-gems -w -e #{testrb.shellescape})
+
+ 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")
@@ -82,7 +97,23 @@ RSpec.shared_examples "bundle install --standalone" do
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
- ruby testrb, :dir => "#{bundled_app}2"
+ ruby testrb, dir: "#{bundled_app}2"
+
+ expect(out).to eq(expected_gems.values.join("\n"))
+ end
+
+ it "skips activating gems" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ gem "do_not_activate_me"
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nrequire \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
+ end
+ sys_exec %(#{Gem.ruby} -w -e #{testrb.shellescape})
expect(out).to eq(expected_gems.values.join("\n"))
end
@@ -95,7 +126,7 @@ RSpec.shared_examples "bundle install --standalone" do
gem "rails"
G
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => true, :dir => cwd
+ bundle :install, standalone: true, dir: cwd
end
let(:expected_gems) do
@@ -110,26 +141,18 @@ RSpec.shared_examples "bundle install --standalone" do
describe "with default gems and a lockfile", :ruby_repo do
before do
- skip "does not work on rubygems versions where `--install_dir` doesn't respect --default" unless Gem::Installer.for_spec(loaded_gemspec, :install_dir => "/foo").default_spec_file == "/foo/specifications/default/bundler-#{Bundler::VERSION}.gemspec" # Since rubygems 3.2.0.rc.2
- skip "does not work on old rubies because the realworld gems that need to be installed don't support them" if RUBY_VERSION < "2.7.0"
-
- if Gem.win_platform? && RUBY_VERSION < "3.1.0"
- default_fiddle_version = ruby "require 'fiddle'; puts Gem.loaded_specs['fiddle'].version"
- realworld_system_gems "fiddle --version #{default_fiddle_version}"
- end
-
realworld_system_gems "tsort --version 0.1.0"
- necessary_system_gems = ["optparse --version 0.1.1", "psych --version 3.3.2", "logger --version 1.4.3", "etc --version 1.2.0", "stringio --version 3.0.1"]
+ necessary_system_gems = ["optparse --version 0.1.1", "psych --version 3.3.2", "logger --version 1.4.3", "etc --version 1.2.0", "stringio --version 3.1.0"]
necessary_system_gems += ["shellwords --version 0.1.0", "base64 --version 0.1.0", "resolv --version 0.2.1"] if Gem.rubygems_version < Gem::Version.new("3.3.a")
necessary_system_gems += ["yaml --version 0.1.1"] if Gem.rubygems_version < Gem::Version.new("3.4.a")
- realworld_system_gems(*necessary_system_gems, :path => scoped_gem_path(bundled_app("bundle")))
+ realworld_system_gems(*necessary_system_gems, path: scoped_gem_path(bundled_app("bundle")))
- build_gem "foo", "1.0.0", :to_system => true, :default => true do |s|
+ build_gem "foo", "1.0.0", to_system: true, default: true do |s|
s.add_dependency "bar"
end
- build_gem "bar", "1.0.0", :to_system => true, :default => true
+ build_gem "bar", "1.0.0", to_system: true, default: true
build_repo4 do
build_gem "foo", "1.0.0" do |s|
@@ -144,18 +167,25 @@ RSpec.shared_examples "bundle install --standalone" do
gem "foo"
G
- bundle "lock", :dir => cwd, :artifice => "compact_index"
+ bundle "lock", dir: cwd, artifice: "compact_index"
end
- it "works" do
+ it "works and points to the vendored copies, not to the default copies", :realworld do
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => true, :dir => cwd, :artifice => "compact_index", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+ bundle :install, standalone: true, dir: cwd, artifice: "compact_index", env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+
+ load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
+
+ expect(load_path_lines).to eq [
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/bar-1.0.0/lib")',
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/foo-1.0.0/lib")',
+ ]
end
end
- describe "with Gemfiles using path sources and resulting bundle moved to a folder hierarchy with different nesting" do
+ describe "with Gemfiles using absolute path sources and resulting bundle moved to a folder hierarchy with different nesting" do
before do
- build_lib "minitest", "1.0.0", :path => lib_path("minitest")
+ build_lib "minitest", "1.0.0", path: lib_path("minitest")
Dir.mkdir bundled_app("app")
@@ -164,14 +194,14 @@ RSpec.shared_examples "bundle install --standalone" do
gem "minitest", :path => "#{lib_path("minitest")}"
G
- bundle "install", :standalone => true, :dir => bundled_app("app")
+ bundle "install", standalone: true, dir: bundled_app("app")
Dir.mkdir tmp("one_more_level")
FileUtils.mv bundled_app, tmp("one_more_level")
end
it "also works" do
- ruby <<-RUBY, :dir => tmp("one_more_level/bundled_app/app")
+ ruby <<-RUBY, dir: tmp("one_more_level/bundled_app/app")
require "./bundle/bundler/setup"
require "minitest"
@@ -183,10 +213,39 @@ RSpec.shared_examples "bundle install --standalone" do
end
end
- describe "with gems with native extension", :ruby_repo do
+ describe "with Gemfiles using relative path sources and app moved to a different root" do
+ before do
+ FileUtils.mkdir_p bundled_app("app/vendor")
+
+ build_lib "minitest", "1.0.0", path: bundled_app("app/vendor/minitest")
+
+ gemfile bundled_app("app/Gemfile"), <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "minitest", :path => "vendor/minitest"
+ G
+
+ bundle "install", standalone: true, dir: bundled_app("app")
+
+ FileUtils.mv(bundled_app("app"), bundled_app2("app"))
+ end
+
+ it "also works" do
+ ruby <<-RUBY, dir: bundled_app2("app")
+ require "./bundle/bundler/setup"
+
+ require "minitest"
+ puts MINITEST
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+ end
+
+ describe "with gems with native extension" do
before do
bundle "config set --local path #{bundled_app("bundle")}"
- install_gemfile <<-G, :standalone => true, :dir => cwd
+ install_gemfile <<-G, standalone: true, dir: cwd
source "#{file_uri_for(gem_repo1)}"
gem "very_simple_binary"
G
@@ -194,15 +253,19 @@ RSpec.shared_examples "bundle install --standalone" do
it "generates a bundle/bundler/setup.rb with the proper paths" do
expected_path = bundled_app("bundle/bundler/setup.rb")
- extension_line = File.read(expected_path).each_line.find {|line| line.include? "/extensions/" }.strip
- expect(extension_line).to start_with '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}/extensions/'
- expect(extension_line).to end_with '/very_simple_binary-1.0")'
+ script_content = File.read(expected_path)
+ expect(script_content).to include("def self.ruby_api_version")
+ expect(script_content).to include("def self.extension_api_version")
+ extension_line = script_content.each_line.find {|line| line.include? "/extensions/" }.strip
+ platform = Gem::Platform.local
+ expect(extension_line).to start_with '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/'
+ expect(extension_line).to end_with platform.to_s + '/#{Gem.extension_api_version}/very_simple_binary-1.0")'
end
end
describe "with gem that has an invalid gemspec" do
before do
- build_git "bar", :gemspec => false do |s|
+ build_git "bar", gemspec: false do |s|
s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
lib = File.expand_path('lib/', __dir__)
@@ -220,7 +283,7 @@ RSpec.shared_examples "bundle install --standalone" do
G
end
bundle "config set --local path #{bundled_app("bundle")}"
- install_gemfile <<-G, :standalone => true, :dir => cwd, :raise_on_error => false
+ install_gemfile <<-G, standalone: true, dir: cwd, raise_on_error: false
source "#{file_uri_for(gem_repo1)}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
@@ -242,7 +305,7 @@ RSpec.shared_examples "bundle install --standalone" do
gem "devise", :git => "#{lib_path("devise-1.0")}"
G
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => true, :dir => cwd
+ bundle :install, standalone: true, dir: cwd
end
let(:expected_gems) do
@@ -270,7 +333,7 @@ RSpec.shared_examples "bundle install --standalone" do
end
G
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => true, :dir => cwd
+ bundle :install, standalone: true, dir: cwd
end
let(:expected_gems) do
@@ -284,7 +347,7 @@ RSpec.shared_examples "bundle install --standalone" do
it "allows creating a standalone file with limited groups" do
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => "default", :dir => cwd
+ bundle :install, standalone: "default", dir: cwd
load_error_ruby <<-RUBY, "spec"
$:.unshift File.expand_path("bundle")
@@ -302,7 +365,7 @@ RSpec.shared_examples "bundle install --standalone" do
it "allows `without` configuration to limit the groups used in a standalone" do
bundle "config set --local path #{bundled_app("bundle")}"
bundle "config set --local without test"
- bundle :install, :standalone => true, :dir => cwd
+ bundle :install, standalone: true, dir: cwd
load_error_ruby <<-RUBY, "spec"
$:.unshift File.expand_path("bundle")
@@ -319,7 +382,7 @@ RSpec.shared_examples "bundle install --standalone" do
it "allows `path` configuration to change the location of the standalone bundle" do
bundle "config set --local path path/to/bundle"
- bundle "install", :standalone => true, :dir => cwd
+ bundle "install", standalone: true, dir: cwd
ruby <<-RUBY
$:.unshift File.expand_path("path/to/bundle")
@@ -334,9 +397,9 @@ RSpec.shared_examples "bundle install --standalone" do
it "allows `without` to limit the groups used in a standalone" do
bundle "config set --local without test"
- bundle :install, :dir => cwd
+ bundle :install, dir: cwd
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => true, :dir => cwd
+ bundle :install, standalone: true, dir: cwd
load_error_ruby <<-RUBY, "spec"
$:.unshift File.expand_path("bundle")
@@ -362,7 +425,7 @@ RSpec.shared_examples "bundle install --standalone" do
gem "rails"
G
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => true, :artifice => "endpoint", :dir => cwd
+ bundle :install, standalone: true, artifice: "endpoint", dir: cwd
end
let(:expected_gems) do
@@ -376,14 +439,14 @@ RSpec.shared_examples "bundle install --standalone" do
end
end
- describe "with --binstubs", :bundler => "< 3" do
+ describe "with --binstubs", bundler: "< 3" do
before do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, :standalone => true, :binstubs => true, :dir => cwd
+ bundle :install, standalone: true, binstubs: true, dir: cwd
end
let(:expected_gems) do
@@ -401,7 +464,7 @@ RSpec.shared_examples "bundle install --standalone" do
it "creates stubs that can be executed from anywhere" do
require "tmpdir"
- sys_exec(%(#{bundled_app("bin/rails")} -v), :dir => Dir.tmpdir)
+ sys_exec(%(#{bundled_app("bin/rails")} -v), dir: Dir.tmpdir)
expect(out).to eq("2.3.2")
end
@@ -435,3 +498,31 @@ RSpec.describe "bundle install --standalone run in a subdirectory" do
include_examples("bundle install --standalone")
end
+
+RSpec.describe "bundle install --standalone --local" do
+ before do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ system_gems "rack-1.0.0", path: default_bundle_path
+ end
+
+ it "generates script pointing to system gems" do
+ bundle "install --standalone --local --verbose"
+
+ expect(out).to include("Using rack 1.0.0")
+
+ load_error_ruby <<-RUBY, "spec"
+ require "./bundler/setup"
+
+ require "rack"
+ puts RACK
+ require "spec"
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to eq("ZOMG LOAD ERROR")
+ end
+end
diff --git a/spec/bundler/install/gems/sudo_spec.rb b/spec/bundler/install/gems/sudo_spec.rb
deleted file mode 100644
index 41b241da25..0000000000
--- a/spec/bundler/install/gems/sudo_spec.rb
+++ /dev/null
@@ -1,205 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "when using sudo", :sudo => true do
- describe "and BUNDLE_PATH is writable" do
- context "but BUNDLE_PATH/build_info is not writable" do
- let(:subdir) do
- system_gem_path("cache")
- end
-
- before do
- bundle "config set path.system true"
- subdir.mkpath
- sudo "chmod u-w #{subdir}"
- end
-
- after do
- sudo "chmod u+w #{subdir}"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- expect(out).to_not match(/an error occurred/i)
- expect(system_gem_path("cache/rack-1.0.0.gem")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
- end
- end
-
- describe "and GEM_HOME is owned by root" do
- before :each do
- bundle "config set path.system true"
- chown_system_gems_to_root
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- gem "thin"
- G
-
- expect(system_gem_path("gems/rack-1.0.0")).to exist
- expect(system_gem_path("gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs rake and a gem dependent on rake in the same session" do
- build_repo2 do
- build_gem "another_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("lib", __dir__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
- f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
- end
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rake"
- gem "another_implicit_rake_dep"
- G
- bundle "install"
- expect(system_gem_path("gems/another_implicit_rake_dep-1.0")).to exist
- end
-
- it "installs when BUNDLE_PATH is owned by root" do
- bundle_path = tmp("owned_by_root")
- FileUtils.mkdir_p bundle_path
- sudo "chown -R root #{bundle_path}"
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0")).to exist
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs when BUNDLE_PATH does not exist" do
- root_path = tmp("owned_by_root")
- FileUtils.mkdir_p root_path
- sudo "chown -R root #{root_path}"
- bundle_path = root_path.join("does_not_exist")
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0")).to exist
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs extensions/" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "very_simple_binary"
- G
-
- expect(system_gem_path("gems/very_simple_binary-1.0")).to exist
- binary_glob = system_gem_path("extensions/*/*/very_simple_binary-1.0")
- expect(Dir.glob(binary_glob).first).to be
- end
- end
-
- describe "and BUNDLE_PATH is not writable" do
- before do
- bundle "config set --local path .bundle"
- sudo "chmod ugo-w .bundle"
- end
-
- after do
- sudo "chmod ugo+w .bundle"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(local_gem_path("gems/rack-1.0.0")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "cleans up the tmpdirs generated" do
- require "tmpdir"
- Dir.glob("#{Dir.tmpdir}/bundler*").each do |tmpdir|
- FileUtils.remove_entry_secure(tmpdir)
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- tmpdirs = Dir.glob("#{Dir.tmpdir}/bundler*")
-
- expect(tmpdirs).to be_empty
- end
- end
-
- describe "and GEM_HOME is not writable" do
- it "installs" do
- bundle "config set path.system true"
- gem_home = tmp("sudo_gem_home")
- sudo "mkdir -p #{gem_home}"
- sudo "chmod ugo-w #{gem_home}"
-
- system_gems :bundler, :path => gem_home
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- bundle :install, :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
- expect(gem_home.join("bin/rackup")).to exist
- expect(the_bundle).to include_gems "rack 1.0", :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
-
- sudo "rm -rf #{tmp("sudo_gem_home")}"
- end
- end
-
- describe "and root runs install" do
- let(:warning) { "Don't run Bundler as root." }
-
- before do
- gemfile %(source "#{file_uri_for(gem_repo1)}")
- end
-
- it "warns against that" do
- bundle :install, :sudo => :preserve_env
- expect(err).to include(warning)
- end
-
- context "when ENV['BUNDLE_SILENCE_ROOT_WARNING'] is set" do
- it "skips the warning" do
- bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "true" }
- expect(err).to_not include(warning)
- end
- end
-
- context "when silence_root_warning = false" do
- it "warns against that" do
- bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" }
- expect(err).to include(warning)
- end
- end
- end
-end
diff --git a/spec/bundler/install/gemspecs_spec.rb b/spec/bundler/install/gemspecs_spec.rb
index 3684d8749d..51aa0ed14f 100644
--- a/spec/bundler/install/gemspecs_spec.rb
+++ b/spec/bundler/install/gemspecs_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "bundle install" do
describe "when a gem has a YAML gemspec" do
before :each do
build_repo2 do
- build_gem "yaml_spec", :gemspec => :yaml
+ build_gem "yaml_spec", gemspec: :yaml
end
end
@@ -18,7 +18,7 @@ RSpec.describe "bundle install" do
end
it "still installs correctly when using path" do
- build_lib "yaml_spec", :gemspec => :yaml
+ build_lib "yaml_spec", gemspec: :yaml
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -34,7 +34,7 @@ RSpec.describe "bundle install" do
gem 'rack'
G
- system_gems "rack-1.0.0", :path => default_bundle_path
+ system_gems "rack-1.0.0", path: default_bundle_path
FileUtils.mkdir_p "#{default_bundle_path}/specifications"
File.open("#{default_bundle_path}/specifications/rack-1.0.0.gemspec", "w+") do |f|
@@ -45,7 +45,7 @@ RSpec.describe "bundle install" do
end
f.write spec.to_ruby
end
- bundle :install, :artifice => "endpoint_marshal_fail" # force gemspec load
+ bundle :install, artifice: "endpoint_marshal_fail" # force gemspec load
expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.2"
end
@@ -59,7 +59,7 @@ RSpec.describe "bundle install" do
end
G
- install_gemfile <<-G, :env => { "LANG" => "C" }
+ install_gemfile <<-G, env: { "LANG" => "C" }
source "#{file_uri_for(gem_repo1)}"
gemspec
G
@@ -94,8 +94,9 @@ RSpec.describe "bundle install" do
end
context "when ruby version is specified in gemspec and gemfile" do
- it "installs when patch level is not specified and the version matches" do
- build_lib("foo", :path => bundled_app) do |s|
+ it "installs when patch level is not specified and the version matches",
+ if: RUBY_PATCHLEVEL >= 0 do
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = "~> #{RUBY_VERSION}.0"
end
@@ -108,12 +109,12 @@ RSpec.describe "bundle install" do
end
it "installs when patch level is specified and the version still matches the current version",
- :if => RUBY_PATCHLEVEL >= 0 do
- build_lib("foo", :path => bundled_app) do |s|
+ if: RUBY_PATCHLEVEL >= 0 do
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = "#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}"
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{RUBY_PATCHLEVEL}'
source "#{file_uri_for(gem_repo1)}"
gemspec
@@ -122,13 +123,13 @@ RSpec.describe "bundle install" do
end
it "fails and complains about patchlevel on patchlevel mismatch",
- :if => RUBY_PATCHLEVEL >= 0 do
+ if: RUBY_PATCHLEVEL >= 0 do
patchlevel = RUBY_PATCHLEVEL.to_i + 1
- build_lib("foo", :path => bundled_app) do |s|
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = "#{RUBY_VERSION}.#{patchlevel}"
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{patchlevel}'
source "#{file_uri_for(gem_repo1)}"
gemspec
@@ -142,11 +143,11 @@ RSpec.describe "bundle install" do
it "fails and complains about version on version mismatch" do
version = Gem::Requirement.create(RUBY_VERSION).requirements.first.last.bump.version
- build_lib("foo", :path => bundled_app) do |s|
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = version
end
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
ruby '#{version}', :engine_version => '#{version}', :engine => 'ruby'
source "#{file_uri_for(gem_repo1)}"
gemspec
diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb
index d43aacee7e..c8d574baf3 100644
--- a/spec/bundler/install/git_spec.rb
+++ b/spec/bundler/install/git_spec.rb
@@ -3,51 +3,51 @@
RSpec.describe "bundle install" do
context "git sources" do
it "displays the revision hash of the gem repository" do
- build_git "foo", "1.0", :path => lib_path("foo")
+ build_git "foo", "1.0", path: lib_path("foo")
- install_gemfile <<-G, :verbose => true
+ install_gemfile <<-G, verbose: true
source "#{file_uri_for(gem_repo1)}"
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 master@#{revision_for(lib_path("foo"))[0..6]})")
- expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
+ 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 correct default branch", :git => ">= 2.28.0" do
- build_git "foo", "1.0", :path => lib_path("foo"), :default_branch => "main"
+ it "displays the correct default branch", git: ">= 2.28.0" do
+ build_git "foo", "1.0", path: lib_path("foo"), default_branch: "main"
- install_gemfile <<-G, :verbose => true
+ install_gemfile <<-G, verbose: true
source "#{file_uri_for(gem_repo1)}"
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")}"
+ 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")
+ build_git "foo", "1.0", path: lib_path("foo")
rev = revision_for(lib_path("foo"))[0..6]
- update_git "foo", "2.0", :path => lib_path("foo"), :gemspec => true
+ update_git "foo", "2.0", path: lib_path("foo"), gemspec: true
rev2 = revision_for(lib_path("foo"))[0..6]
- update_git "foo", "3.0", :path => lib_path("foo"), :gemspec => true
+ update_git "foo", "3.0", path: lib_path("foo"), gemspec: true
- install_gemfile <<-G, :verbose => true
+ install_gemfile <<-G, verbose: true
source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "master~2"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "main~2"
G
- expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev})")
- expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
+ expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main~2@#{rev})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
- update_git "foo", "4.0", :path => lib_path("foo"), :gemspec => true
+ update_git "foo", "4.0", path: lib_path("foo"), gemspec: 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")}"
+ 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 main~2@#{rev2})")
+ expect(the_bundle).to include_gems "foo 2.0", source: "git@#{lib_path("foo")}"
end
it "should allows git repos that are missing but not being installed" do
@@ -81,9 +81,9 @@ RSpec.describe "bundle install" do
it "allows multiple gems from the same git source" do
build_repo2 do
- build_lib "foo", "1.0", :path => lib_path("gems/foo")
- build_lib "zebra", "2.0", :path => lib_path("gems/zebra")
- build_git "gems", :path => lib_path("gems"), :gemspec => false
+ build_lib "foo", "1.0", path: lib_path("gems/foo")
+ build_lib "zebra", "2.0", path: lib_path("gems/zebra")
+ build_git "gems", path: lib_path("gems"), gemspec: false
end
install_gemfile <<-G
@@ -98,5 +98,108 @@ RSpec.describe "bundle install" do
bundle "info zebra"
expect(out).to include("* zebra (2.0 #{revision_for(lib_path("gems"))[0..6]})")
end
+
+ it "should always sort dependencies in the same order" do
+ # This Gemfile + lockfile had a problem where the first
+ # `bundle install` would change the order, but the second would
+ # change it back.
+
+ # NOTE: both gems MUST have the same path! It has to be two gems in one repo.
+
+ test = build_git "test", "1.0.0", path: lib_path("test-and-other")
+ other = build_git "other", "1.0.0", path: lib_path("test-and-other")
+ test_ref = test.ref_for("HEAD")
+ other_ref = other.ref_for("HEAD")
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "test", git: #{test.path.to_s.inspect}
+ gem "other", ref: #{other_ref.inspect}, git: #{other.path.to_s.inspect}
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{test.path}
+ revision: #{test_ref}
+ specs:
+ test (1.0.0)
+
+ GIT
+ remote: #{other.path}
+ revision: #{other_ref}
+ ref: #{other_ref}
+ specs:
+ other (1.0.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ other!
+ test!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ # If GH#6743 is present, the first `bundle install` will change the
+ # lockfile, by flipping the order (`other` would be moved to the top).
+ #
+ # The second `bundle install` would then change the lockfile back
+ # to the original.
+ #
+ # The fix makes it so it may change it once, but it will not change
+ # it a second time.
+ #
+ # So, we run `bundle install` once, and store the value of the
+ # modified lockfile.
+ bundle :install
+ modified_lockfile = lockfile
+
+ # If GH#6743 is present, the second `bundle install` would change the
+ # lockfile back to what it was originally.
+ #
+ # This `expect` makes sure it doesn't change a second time.
+ bundle :install
+ expect(lockfile).to eq(modified_lockfile)
+
+ expect(out).to include("Bundle complete!")
+ end
+
+ it "allows older revisions of git source when clean true" do
+ build_git "foo", "1.0", path: lib_path("foo")
+ rev = revision_for(lib_path("foo"))
+
+ bundle "config set path vendor/bundle"
+ bundle "config set clean true"
+ install_gemfile <<-G, verbose: true
+ source "#{file_uri_for(gem_repo1)}"
+ 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@#{rev[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ old_lockfile = lockfile
+
+ update_git "foo", "2.0", path: lib_path("foo"), gemspec: true
+ rev2 = revision_for(lib_path("foo"))
+
+ 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 main@#{rev2[0..6]})")
+ expect(out).to include("Removing foo (#{rev[0..11]})")
+ expect(the_bundle).to include_gems "foo 2.0", source: "git@#{lib_path("foo")}"
+
+ lockfile(old_lockfile)
+
+ bundle :install, verbose: true
+ expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main@#{rev[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+ end
end
end
diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb
index afa0ff76c1..0da4de05b2 100644
--- a/spec/bundler/install/global_cache_spec.rb
+++ b/spec/bundler/install/global_cache_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe "global gem caching" do
end
it "caches gems into the global cache on download" do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
gem "rack"
G
@@ -29,7 +29,7 @@ RSpec.describe "global gem caching" do
source_global_cache.mkpath
FileUtils.cp(gem_repo1("gems/rack-1.0.0.gem"), source_global_cache("rack-1.0.0.gem"))
- install_gemfile <<-G, :artifice => "compact_index_no_gem"
+ install_gemfile <<-G, artifice: "compact_index_no_gem"
source "#{source}"
gem "rack"
G
@@ -41,7 +41,7 @@ RSpec.describe "global gem caching" do
source_global_cache.mkpath
FileUtils.touch(source_global_cache("rack-1.0.0.gem"))
- install_gemfile <<-G, :artifice => "compact_index_no_gem", :raise_on_error => false
+ install_gemfile <<-G, artifice: "compact_index_no_gem", raise_on_error: false
source "#{source}"
gem "rack"
G
@@ -51,7 +51,7 @@ RSpec.describe "global gem caching" do
describe "when the same gem from different sources is installed" do
it "should use the appropriate one from the global cache" do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
gem "rack"
G
@@ -61,7 +61,7 @@ RSpec.describe "global gem caching" do
expect(source_global_cache("rack-1.0.0.gem")).to exist
# rack 1.0.0 is not installed and it is in the global cache
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source2}"
gem "rack", "0.9.1"
G
@@ -76,7 +76,7 @@ RSpec.describe "global gem caching" do
gem "rack", "1.0.0"
G
- bundle :install, :artifice => "compact_index_no_gem"
+ bundle :install, artifice: "compact_index_no_gem"
# rack 1.0.0 is installed and rack 0.9.1 is not
expect(the_bundle).to include_gems "rack 1.0.0"
expect(the_bundle).not_to include_gems "rack 0.9.1"
@@ -87,7 +87,7 @@ RSpec.describe "global gem caching" do
gem "rack", "0.9.1"
G
- bundle :install, :artifice => "compact_index_no_gem"
+ bundle :install, artifice: "compact_index_no_gem"
# rack 0.9.1 is installed and rack 1.0.0 is not
expect(the_bundle).to include_gems "rack 0.9.1"
expect(the_bundle).not_to include_gems "rack 1.0.0"
@@ -99,7 +99,7 @@ RSpec.describe "global gem caching" do
gem "rack"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
simulate_new_machine
expect(the_bundle).not_to include_gems "rack 1.0.0"
expect(source_global_cache("rack-1.0.0.gem")).to exist
@@ -110,7 +110,7 @@ RSpec.describe "global gem caching" do
gem "rack", "0.9.1"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
simulate_new_machine
expect(the_bundle).not_to include_gems "rack 0.9.1"
expect(source2_global_cache("rack-0.9.1.gem")).to exist
@@ -123,7 +123,7 @@ RSpec.describe "global gem caching" do
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source2_global_cache("rack-0.9.1.gem")).to exist
- bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false
+ bundle :install, artifice: "compact_index_no_gem", raise_on_error: false
expect(err).to include("Internal Server Error 500")
expect(err).not_to include("ERROR REPORT TEMPLATE")
@@ -138,7 +138,7 @@ RSpec.describe "global gem caching" do
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source2_global_cache("rack-0.9.1.gem")).to exist
- bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false
+ bundle :install, artifice: "compact_index_no_gem", raise_on_error: false
expect(err).to include("Internal Server Error 500")
expect(err).not_to include("ERROR REPORT TEMPLATE")
@@ -150,7 +150,7 @@ RSpec.describe "global gem caching" do
describe "when installing gems from a different directory" do
it "uses the global cache as a source" do
- install_gemfile <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
gem "rack"
gem "activesupport"
@@ -166,7 +166,7 @@ RSpec.describe "global gem caching" do
expect(the_bundle).not_to include_gems "rack 1.0.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- install_gemfile <<-G, :artifice => "compact_index_no_gem"
+ install_gemfile <<-G, artifice: "compact_index_no_gem"
source "#{source}"
gem "rack"
G
@@ -183,20 +183,18 @@ RSpec.describe "global gem caching" do
G
# Neither gem is installed and both are in the global cache
- expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2
- expect(the_bundle).not_to include_gems "activesupport 2.3.5", :dir => bundled_app2
+ expect(the_bundle).not_to include_gems "rack 1.0.0", dir: bundled_app2
+ expect(the_bundle).not_to include_gems "activesupport 2.3.5", dir: bundled_app2
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
# Install using the global cache instead of by downloading the .gem
# from the server
- bundle :install, :artifice => "compact_index_no_gem", :dir => bundled_app2
+ bundle :install, artifice: "compact_index_no_gem", dir: bundled_app2
# activesupport is installed and both are in the global cache
- simulate_bundler_version_when_missing_prerelease_default_gem_activation do
- expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2
- expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2
- end
+ expect(the_bundle).not_to include_gems "rack 1.0.0", dir: bundled_app2
+ expect(the_bundle).to include_gems "activesupport 2.3.5", dir: bundled_app2
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
@@ -205,7 +203,7 @@ RSpec.describe "global gem caching" do
end
describe "extension caching" do
- it "works", :ruby_repo do
+ it "works" do
skip "gets incorrect ref in path" if Gem.win_platform?
build_git "very_simple_git_binary", &:add_c_extension
@@ -220,9 +218,9 @@ RSpec.describe "global gem caching" do
gem "very_simple_path_binary", :path => "#{lib_path("very_simple_path_binary-1.0")}"
G
- gem_binary_cache = home(".bundle", "cache", "extensions", specific_local_platform.to_s, Bundler.ruby_scope,
+ gem_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
Digest(:MD5).hexdigest("#{gem_repo1}/"), "very_simple_binary-1.0")
- git_binary_cache = home(".bundle", "cache", "extensions", specific_local_platform.to_s, Bundler.ruby_scope,
+ git_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
"very_simple_git_binary-1.0-#{revision}", "very_simple_git_binary-1.0")
cached_extensions = Pathname.glob(home(".bundle", "cache", "extensions", "*", "*", "*", "*", "*")).sort
@@ -234,7 +232,7 @@ RSpec.describe "global gem caching" do
R
expect(out).to eq "VERY_SIMPLE_BINARY_IN_C\nVERY_SIMPLE_GIT_BINARY_IN_C"
- FileUtils.rm Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]
+ FileUtils.rm_rf Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]
gem_binary_cache.join("very_simple_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" }
git_binary_cache.join("very_simple_git_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" }
diff --git a/spec/bundler/install/path_spec.rb b/spec/bundler/install/path_spec.rb
index b0392c4ed2..0a30e402b7 100644
--- a/spec/bundler/install/path_spec.rb
+++ b/spec/bundler/install/path_spec.rb
@@ -3,7 +3,7 @@
RSpec.describe "bundle install" do
describe "with path configured" do
before :each do
- build_gem "rack", "1.0.0", :to_system => true do |s|
+ build_gem "rack", "1.0.0", to_system: true do |s|
s.write "lib/rack.rb", "puts 'FAIL'"
end
@@ -23,7 +23,7 @@ RSpec.describe "bundle install" do
bundle "config set --local path.system true"
bundle "config set --global path vendor/bundle"
bundle :install
- run "require 'rack'", :raise_on_error => false
+ run "require 'rack'", raise_on_error: false
expect(out).to include("FAIL")
end
@@ -32,7 +32,7 @@ RSpec.describe "bundle install" do
dir.mkpath
bundle "config set --local path #{dir.join("vendor/bundle")}"
- bundle :install, :dir => dir
+ bundle :install, dir: dir
expect(out).to include("installed into `./vendor/bundle`")
dir.rmtree
@@ -44,13 +44,13 @@ RSpec.describe "bundle install" do
expect(out).to include("gems are installed into `./vendor/bundle`")
end
- it "disallows --path vendor/bundle --system", :bundler => "< 3" do
- bundle "install --path vendor/bundle --system", :raise_on_error => false
+ it "disallows --path vendor/bundle --system", bundler: "< 3" do
+ bundle "install --path vendor/bundle --system", raise_on_error: false
expect(err).to include("Please choose only one option.")
expect(exitstatus).to eq(15)
end
- it "remembers to disable system gems after the first time with bundle --path vendor/bundle", :bundler => "< 3" do
+ it "remembers to disable system gems after the first time with bundle --path vendor/bundle", bundler: "< 3" do
bundle "install --path vendor/bundle"
FileUtils.rm_rf bundled_app("vendor")
bundle "install"
@@ -62,22 +62,22 @@ RSpec.describe "bundle install" do
context "with path_relative_to_cwd set to true" do
before { bundle "config set path_relative_to_cwd true" }
- it "installs the bundle relatively to current working directory", :bundler => "< 3" do
- bundle "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle", :dir => bundled_app.parent
+ it "installs the bundle relatively to current working directory", bundler: "< 3" do
+ bundle "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle", dir: bundled_app.parent
expect(out).to include("installed into `./vendor/bundle`")
expect(bundled_app("../vendor/bundle")).to be_directory
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "installs the standalone bundle relative to the cwd" do
- bundle :install, :gemfile => bundled_app_gemfile, :standalone => true, :dir => bundled_app.parent
+ bundle :install, gemfile: bundled_app_gemfile, standalone: true, dir: bundled_app.parent
expect(out).to include("installed into `./bundled_app/bundle`")
expect(bundled_app("bundle")).to be_directory
expect(bundled_app("bundle/ruby")).to be_directory
bundle "config unset path"
- bundle :install, :gemfile => bundled_app_gemfile, :standalone => true, :dir => bundled_app("subdir").tap(&:mkpath)
+ bundle :install, gemfile: bundled_app_gemfile, standalone: true, dir: bundled_app("subdir").tap(&:mkpath)
expect(out).to include("installed into `../bundle`")
expect(bundled_app("bundle")).to be_directory
expect(bundled_app("bundle/ruby")).to be_directory
@@ -87,7 +87,7 @@ RSpec.describe "bundle install" do
describe "when BUNDLE_PATH or the global path config is set" do
before :each do
- build_lib "rack", "1.0.0", :to_system => true do |s|
+ build_lib "rack", "1.0.0", to_system: true do |s|
s.write "lib/rack.rb", "raise 'FAIL'"
end
@@ -141,7 +141,7 @@ RSpec.describe "bundle install" do
set_bundle_path(type, "vendor")
FileUtils.mkdir_p bundled_app("lol")
- bundle :install, :dir => bundled_app("lol")
+ bundle :install, dir: bundled_app("lol")
expect(bundled_app("vendor", Bundler.ruby_scope, "gems/rack-1.0.0")).to be_directory
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -168,7 +168,7 @@ RSpec.describe "bundle install" do
it "disables system gems when passing a path to install" do
# This is so that vendored gems can be distributed to others
- build_gem "rack", "1.1.0", :to_system => true
+ build_gem "rack", "1.1.0", to_system: true
bundle "config set --local path ./vendor/bundle"
bundle :install
@@ -176,8 +176,8 @@ RSpec.describe "bundle install" do
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "re-installs gems whose extensions have been deleted", :ruby_repo do
- build_lib "very_simple_binary", "1.0.0", :to_system => true do |s|
+ it "re-installs gems whose extensions have been deleted" do
+ build_lib "very_simple_binary", "1.0.0", to_system: true do |s|
s.write "lib/very_simple_binary.rb", "raise 'FAIL'"
end
@@ -191,11 +191,11 @@ RSpec.describe "bundle install" do
expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory
expect(vendored_gems("extensions")).to be_directory
- expect(the_bundle).to include_gems "very_simple_binary 1.0", :source => "remote1"
+ expect(the_bundle).to include_gems "very_simple_binary 1.0", source: "remote1"
vendored_gems("extensions").rmtree
- run "require 'very_simple_binary_c'", :raise_on_error => false
+ run "require 'very_simple_binary_c'", raise_on_error: false
expect(err).to include("Bundler::GemNotFound")
bundle "config set --local path ./vendor/bundle"
@@ -203,7 +203,7 @@ RSpec.describe "bundle install" do
expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory
expect(vendored_gems("extensions")).to be_directory
- expect(the_bundle).to include_gems "very_simple_binary 1.0", :source => "remote1"
+ expect(the_bundle).to include_gems "very_simple_binary 1.0", source: "remote1"
end
end
@@ -219,7 +219,7 @@ RSpec.describe "bundle install" do
G
bundle "config set --local path bundle"
- bundle :install, :raise_on_error => false
+ bundle :install, raise_on_error: false
expect(err).to include("file already exists")
end
end
diff --git a/spec/bundler/install/process_lock_spec.rb b/spec/bundler/install/process_lock_spec.rb
index dac0d34bc4..1f8c62f26e 100644
--- a/spec/bundler/install/process_lock_spec.rb
+++ b/spec/bundler/install/process_lock_spec.rb
@@ -31,5 +31,27 @@ RSpec.describe "process lock spec" do
expect(processed).to eq true
end
end
+
+ context "when creating a lock raises Errno::EPERM" do
+ before { allow(File).to receive(:open).and_raise(Errno::EPERM) }
+
+ it "skips creating the lock file and yields" do
+ processed = false
+ Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
+
+ expect(processed).to eq true
+ end
+ end
+
+ context "when creating a lock raises Errno::EROFS" do
+ before { allow(File).to receive(:open).and_raise(Errno::EROFS) }
+
+ it "skips creating the lock file and yields" do
+ processed = false
+ Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
+
+ expect(processed).to eq true
+ end
+ end
end
end
diff --git a/spec/bundler/install/redownload_spec.rb b/spec/bundler/install/redownload_spec.rb
index a936b2b536..3a72c356d9 100644
--- a/spec/bundler/install/redownload_spec.rb
+++ b/spec/bundler/install/redownload_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe "bundle install" do
end
end
- describe "with --force", :bundler => 2 do
+ describe "with --force", bundler: 2 do
it_behaves_like "an option to force redownloading gems" do
let(:flag) { "force" }
end
diff --git a/spec/bundler/install/security_policy_spec.rb b/spec/bundler/install/security_policy_spec.rb
index 43c3069c4e..befeb81da5 100644
--- a/spec/bundler/install/security_policy_spec.rb
+++ b/spec/bundler/install/security_policy_spec.rb
@@ -16,23 +16,23 @@ RSpec.describe "policies with unsigned gems" do
end
it "will work after you try to deploy without a lock" do
- bundle "install --deployment", :raise_on_error => false
+ bundle "install --deployment", raise_on_error: false
bundle :install
expect(the_bundle).to include_gems "rack 1.0", "signed_gem 1.0"
end
it "will fail when given invalid security policy" do
- bundle "install --trust-policy=InvalidPolicyName", :raise_on_error => false
+ bundle "install --trust-policy=InvalidPolicyName", raise_on_error: false
expect(err).to include("RubyGems doesn't know about trust policy")
end
it "will fail with High Security setting due to presence of unsigned gem" do
- bundle "install --trust-policy=HighSecurity", :raise_on_error => false
+ bundle "install --trust-policy=HighSecurity", raise_on_error: false
expect(err).to include("security policy didn't allow")
end
it "will fail with Medium Security setting due to presence of unsigned gem" do
- bundle "install --trust-policy=MediumSecurity", :raise_on_error => false
+ bundle "install --trust-policy=MediumSecurity", raise_on_error: false
expect(err).to include("security policy didn't allow")
end
@@ -51,12 +51,12 @@ RSpec.describe "policies with signed gems and no CA" do
end
it "will fail with High Security setting, gem is self-signed" do
- bundle "install --trust-policy=HighSecurity", :raise_on_error => false
+ bundle "install --trust-policy=HighSecurity", raise_on_error: false
expect(err).to include("security policy didn't allow")
end
it "will fail with Medium Security setting, gem is self-signed" do
- bundle "install --trust-policy=MediumSecurity", :raise_on_error => false
+ bundle "install --trust-policy=MediumSecurity", raise_on_error: false
expect(err).to include("security policy didn't allow")
end
diff --git a/spec/bundler/install/yanked_spec.rb b/spec/bundler/install/yanked_spec.rb
index b53c15be69..7408c24327 100644
--- a/spec/bundler/install/yanked_spec.rb
+++ b/spec/bundler/install/yanked_spec.rb
@@ -15,14 +15,14 @@ RSpec.context "when installing a bundle that includes yanked gems" do
foo (10.0.0)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
foo (= 10.0.0)
L
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo4)}"
gem "foo", "10.0.0"
G
@@ -30,10 +30,76 @@ RSpec.context "when installing a bundle that includes yanked gems" do
expect(err).to include("Your bundle is locked to foo (10.0.0)")
end
+ context "when a re-resolve is necessary, and a yanked version is considered by the resolver" do
+ before do
+ skip "Materialization on Windows is not yet strict, so the example does not detect the gem has been yanked" if Gem.win_platform?
+
+ build_repo4 do
+ build_gem "foo", "1.0.0", "1.0.1"
+ build_gem "actiontext", "6.1.7" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "actiontext", "6.1.6" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "actiontext", "6.1.7" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "nokogiri", "1.13.8"
+ end
+
+ gemfile <<~G
+ source "#{source_uri}"
+ gem "foo", "1.0.1"
+ gem "actiontext", "6.1.6"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{source_uri}/
+ specs:
+ actiontext (6.1.6)
+ nokogiri (>= 1.8)
+ foo (1.0.0)
+ nokogiri (1.13.8-#{Bundler.local_platform})
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ actiontext (= 6.1.6)
+ foo (= 1.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ context "and the old index is used" do
+ let(:source_uri) { file_uri_for(gem_repo4) }
+
+ it "reports the yanked gem properly" do
+ bundle "install", raise_on_error: false
+
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ end
+ end
+
+ context "and the compact index API is used" do
+ let(:source_uri) { "https://gem.repo4" }
+
+ it "reports the yanked gem properly" do
+ bundle "install", artifice: "compact_index", raise_on_error: false
+
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ end
+ end
+ end
+
it "throws the original error when only the Gemfile specifies a gem version that doesn't exist" do
bundle "config set force_ruby_platform true"
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G, raise_on_error: false
source "#{file_uri_for(gem_repo4)}"
gem "foo", "10.0.0"
G
@@ -43,6 +109,63 @@ RSpec.context "when installing a bundle that includes yanked gems" do
end
end
+RSpec.context "when resolving a bundle that includes yanked gems, but unlocking an unrelated gem" do
+ before(:each) do
+ build_repo4 do
+ build_gem "foo", "10.0.0"
+
+ build_gem "bar", "1.0.0"
+ build_gem "bar", "2.0.0"
+ end
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}
+ specs:
+ foo (9.0.0)
+ bar (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "foo"
+ gem "bar"
+ G
+ end
+
+ it "does not update the yanked gem" do
+ bundle "lock --update bar"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ bar (2.0.0)
+ foo (9.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ bar
+ foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+end
+
RSpec.context "when using gem before installing" do
it "does not suggest the author has yanked the gem" do
gemfile <<-G
@@ -57,18 +180,24 @@ RSpec.context "when using gem before installing" do
rack (0.9.1)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
rack (= 0.9.1)
L
- bundle :list, :raise_on_error => false
+ bundle :list, raise_on_error: false
- expect(err).to include("Could not find rack-0.9.1 in any of the sources")
+ expect(err).to include("Could not find rack-0.9.1 in cached gems or installed locally")
expect(err).to_not include("Your bundle is locked to rack (0.9.1) from")
expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
+
+ # Check error message is still correct when multiple platforms are locked
+ lockfile lockfile.gsub(/PLATFORMS\n #{lockfile_platforms}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
+
+ bundle :list, raise_on_error: false
+ expect(err).to include("Could not find rack-0.9.1 in cached gems or installed locally")
end
it "does not suggest the author has yanked the gem when using more than one gem, but shows all gems that couldn't be found in the source" do
@@ -86,16 +215,16 @@ RSpec.context "when using gem before installing" do
rack_middleware (1.0)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
rack (= 0.9.1)
rack_middleware (1.0)
L
- bundle :list, :raise_on_error => false
+ bundle :list, raise_on_error: false
- expect(err).to include("Could not find rack-0.9.1, rack_middleware-1.0 in any of the sources")
+ expect(err).to include("Could not find rack-0.9.1, rack_middleware-1.0 in cached gems or installed locally")
expect(err).to include("Install missing gems with `bundle install`.")
expect(err).to_not include("Your bundle is locked to rack (0.9.1) from")
expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")