summaryrefslogtreecommitdiff
path: root/spec/bundler/cache
diff options
context:
space:
mode:
Diffstat (limited to 'spec/bundler/cache')
-rw-r--r--spec/bundler/cache/gems_spec.rb115
-rw-r--r--spec/bundler/cache/git_spec.rb94
-rw-r--r--spec/bundler/cache/path_spec.rb22
-rw-r--r--spec/bundler/cache/platform_spec.rb2
4 files changed, 186 insertions, 47 deletions
diff --git a/spec/bundler/cache/gems_spec.rb b/spec/bundler/cache/gems_spec.rb
index 161ec64218..abbc2c3cf2 100644
--- a/spec/bundler/cache/gems_spec.rb
+++ b/spec/bundler/cache/gems_spec.rb
@@ -4,10 +4,11 @@ RSpec.describe "bundle cache" do
shared_examples_for "when there are only gemsources" do
before :each do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
G
- system_gems "rack-1.0.0", :path => path
+ system_gems "rack-1.0.0", path: path
bundle :cache
end
@@ -16,7 +17,7 @@ RSpec.describe "bundle cache" do
end
it "uses the cache as a source when installing gems" do
- build_gem "omg", :path => bundled_app("vendor/cache")
+ build_gem "omg", path: bundled_app("vendor/cache")
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -27,18 +28,19 @@ RSpec.describe "bundle cache" do
end
it "uses the cache as a source when installing gems with --local" do
- system_gems [], :path => default_bundle_path
+ system_gems [], path: default_bundle_path
bundle "install --local"
expect(the_bundle).to include_gems("rack 1.0.0")
end
it "does not reinstall gems from the cache if they exist on the system" do
- build_gem "rack", "1.0.0", :path => bundled_app("vendor/cache") do |s|
+ build_gem "rack", "1.0.0", path: bundled_app("vendor/cache") do |s|
s.write "lib/rack.rb", "RACK = 'FAIL'"
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -46,17 +48,18 @@ RSpec.describe "bundle cache" do
end
it "does not reinstall gems from the cache if they exist in the bundle" do
- system_gems "rack-1.0.0", :path => default_bundle_path
+ system_gems "rack-1.0.0", path: default_bundle_path
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- build_gem "rack", "1.0.0", :path => bundled_app("vendor/cache") do |s|
+ build_gem "rack", "1.0.0", path: bundled_app("vendor/cache") do |s|
s.write "lib/rack.rb", "RACK = 'FAIL'"
end
- bundle :install, :local => true
+ bundle :install, local: true
expect(the_bundle).to include_gems("rack 1.0.0")
end
@@ -64,6 +67,7 @@ RSpec.describe "bundle cache" do
cache_gems "rack-1.0.0"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -85,39 +89,49 @@ RSpec.describe "bundle cache" do
it_behaves_like "when there are only gemsources"
end
- describe "when there is a built-in gem" do
+ describe "when there is a built-in gem", :ruby_repo do
+ let(:default_json_version) { ruby "gem 'json'; require 'json'; puts JSON::VERSION" }
+
before :each do
build_repo2 do
- build_gem "builtin_gem", "1.0.2"
+ build_gem "json", default_json_version
end
- build_gem "builtin_gem", "1.0.2", :to_system => true do |s|
- s.summary = "This builtin_gem is bundled with Ruby"
- end
-
- FileUtils.rm("#{system_gem_path}/cache/builtin_gem-1.0.2.gem")
+ build_gem "json", default_json_version, to_system: true, default: true
end
it "uses builtin gems when installing to system gems" do
bundle "config set path.system true"
- install_gemfile %(gem 'builtin_gem', '1.0.2')
- expect(the_bundle).to include_gems("builtin_gem 1.0.2")
+ install_gemfile %(source "#{file_uri_for(gem_repo1)}"; gem 'json', '#{default_json_version}'), verbose: true
+ expect(out).to include("Using json #{default_json_version}")
end
it "caches remote and builtin gems" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
- gem 'builtin_gem', '1.0.2'
+ gem 'json', '#{default_json_version}'
gem 'rack', '1.0.0'
G
bundle :cache
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/builtin_gem-1.0.2.gem")).to exist
+ expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist
+ end
+
+ it "caches builtin gems when cache_all_platforms is set" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "json"
+ G
+
+ bundle "config set cache_all_platforms true"
+
+ bundle :cache
+ expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist
end
it "doesn't make remote request after caching the gem" do
- build_gem "builtin_gem_2", "1.0.2", :path => bundled_app("vendor/cache") do |s|
+ build_gem "builtin_gem_2", "1.0.2", path: bundled_app("vendor/cache") do |s|
s.summary = "This builtin_gem is bundled with Ruby"
end
@@ -134,12 +148,13 @@ RSpec.describe "bundle cache" do
bundle "config set path.system true"
install_gemfile <<-G
- gem 'builtin_gem', '1.0.2'
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'json', '#{default_json_version}'
G
- bundle :cache, :raise_on_error => false
+ bundle :cache, raise_on_error: false
expect(exitstatus).to_not eq(0)
- expect(err).to include("builtin_gem-1.0.2 is built in to Ruby, and can't be cached")
+ expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached")
end
end
@@ -203,7 +218,7 @@ RSpec.describe "bundle cache" do
end
end
- bundle "update", :all => true
+ bundle "update", all: true
expect(cached_gem("rack-1.2")).to exist
expect(cached_gem("rack-1.0.0")).not_to exist
end
@@ -264,10 +279,57 @@ RSpec.describe "bundle cache" do
it "doesn't remove gems with mismatched :rubygems_version or :date" do
cached_gem("rack-1.0.0").rmtree
build_gem "rack", "1.0.0",
- :path => bundled_app("vendor/cache"),
- :rubygems_version => "1.3.2"
+ path: bundled_app("vendor/cache"),
+ rubygems_version: "1.3.2"
+ # This test is only really valid if the checksum isn't saved. It otherwise can't be the same gem. Tested below.
+ bundled_app_lock.write remove_checksums_from_lockfile(bundled_app_lock.read, "rack (1.0.0)")
+ simulate_new_machine
+
+ bundle :install
+ expect(cached_gem("rack-1.0.0")).to exist
+ end
+
+ it "raises an error when the gem is altered and produces a different checksum" do
+ cached_gem("rack-1.0.0").rmtree
+ build_gem "rack", "1.0.0", path: bundled_app("vendor/cache")
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo1, "rack", "1.0.0"
+ end
+
+ simulate_new_machine
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+ #{checksums}
+ L
+
+ bundle :install, raise_on_error: false
+ expect(exitstatus).to eq(37)
+ expect(err).to include("Bundler found mismatched checksums.")
+ expect(err).to include("1. remove the gem at #{cached_gem("rack-1.0.0")}")
+
+ expect(cached_gem("rack-1.0.0")).to exist
+ cached_gem("rack-1.0.0").rmtree
+ bundle :install
+ expect(cached_gem("rack-1.0.0")).to exist
+ end
+
+ it "installs a modified gem with a non-matching checksum when checksums is not opted in" do
+ cached_gem("rack-1.0.0").rmtree
+ build_gem "rack", "1.0.0", path: bundled_app("vendor/cache")
simulate_new_machine
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+ L
+
bundle :install
expect(cached_gem("rack-1.0.0")).to exist
end
@@ -299,9 +361,10 @@ RSpec.describe "bundle cache" do
it "should install gems with the name bundler in them (that aren't bundler)" do
build_gem "foo-bundler", "1.0",
- :path => bundled_app("vendor/cache")
+ path: bundled_app("vendor/cache")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo-bundler"
G
diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb
index 25f12a9e87..4b3cd4d2eb 100644
--- a/spec/bundler/cache/git_spec.rb
+++ b/spec/bundler/cache/git_spec.rb
@@ -15,9 +15,10 @@ end
RSpec.describe "bundle cache with git" do
it "copies repository to vendor cache and uses it" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -33,9 +34,10 @@ RSpec.describe "bundle cache with git" do
it "copies repository to vendor cache and uses it even when configured with `path`" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -55,6 +57,7 @@ RSpec.describe "bundle cache with git" do
build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -69,9 +72,10 @@ RSpec.describe "bundle cache with git" do
it "tracks updates" do
git = build_git "foo"
- old_ref = git.ref_for("master", 11)
+ old_ref = git.ref_for("main", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -82,11 +86,10 @@ RSpec.describe "bundle cache with git" do
s.write "lib/foo.rb", "puts :CACHE"
end
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
expect(ref).not_to eq(old_ref)
- bundle "update", :all => true
- bundle "config set cache_all true"
+ bundle "update", all: true
bundle :cache
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
@@ -99,9 +102,10 @@ RSpec.describe "bundle cache with git" do
it "tracks updates when specifying the gem" do
git = build_git "foo"
- old_ref = git.ref_for("master", 11)
+ old_ref = git.ref_for("main", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -112,7 +116,7 @@ RSpec.describe "bundle cache with git" do
s.write "lib/foo.rb", "puts :CACHE"
end
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
expect(ref).not_to eq(old_ref)
bundle "update foo"
@@ -127,10 +131,11 @@ RSpec.describe "bundle cache with git" do
it "uses the local repository to generate the cache" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :master
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :main
G
bundle %(config set local.foo #{lib_path("foo-1.0")})
@@ -150,22 +155,26 @@ RSpec.describe "bundle cache with git" do
end
it "copies repository to vendor cache, including 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"
git = 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)}"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
G
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
bundle "config set cache_all true"
bundle :cache
@@ -183,12 +192,13 @@ RSpec.describe "bundle cache with git" do
update_git("foo") {|s| s.write "foo.gemspec", spec_lines.join("\n") }
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set cache_all true"
bundle :cache
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
gemspec = bundled_app("vendor/cache/foo-1.0-#{ref}/foo.gemspec").read
expect(gemspec).to_not match("`echo bob`")
end
@@ -197,6 +207,7 @@ RSpec.describe "bundle cache with git" do
build_git "foo"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set cache_all true"
@@ -205,8 +216,61 @@ RSpec.describe "bundle cache with git" do
simulate_new_machine
with_path_as "" do
bundle "config set deployment true"
- bundle :install, :local => true
+ bundle :install, local: true
expect(the_bundle).to include_gem "foo 1.0"
end
end
+
+ it "respects the --no-install flag" do
+ git = build_git "foo", &:add_c_extension
+ ref = git.ref_for("main", 11)
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle "config set cache_all true"
+
+ # The algorithm for the cache location for a git checkout is
+ # in Bundle::Source::Git#cache_path
+ cache_path_name = "foo-1.0-#{Digest(:SHA1).hexdigest(lib_path("foo-1.0").to_s)}"
+
+ # Run this test twice. This is because materially different codepaths
+ # will get hit the second time around.
+ # The first time, Bundler::Sources::Git#install_path is set to the system
+ # wide cache directory bundler/gems; the second time, it's set to the
+ # vendor/cache directory. We don't want the native extension to appear in
+ # either of these places, so run the `bundle cache` command twice.
+ 2.times do
+ bundle :cache, "all-platforms" => true, :install => false
+
+ # it did _NOT_ actually install the gem - neither in $GEM_HOME (bundler 2 mode),
+ # nor in .bundle (bundler 3 mode)
+ expect(Pathname.new(File.join(default_bundle_path, "gems/foo-1.0-#{ref}"))).to_not exist
+ # it _did_ cache the gem in vendor/
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
+ # it did _NOT_ build the gems extensions in the vendor/ dir
+ expect(Dir[bundled_app("vendor/cache/foo-1.0-#{ref}/lib/foo_c*")]).to be_empty
+ # it _did_ cache the git checkout
+ expect(default_cache_path("git", cache_path_name)).to exist
+ # And the checkout is a bare checkout
+ expect(default_cache_path("git", cache_path_name, "HEAD")).to exist
+ end
+
+ # Subsequently installing the gem should compile it.
+ # _currently_, the gem gets compiled in vendor/cache, and vendor/cache is added
+ # to the $LOAD_PATH for git extensions, so it all kind of "works". However, in the
+ # future we would like to stop adding vendor/cache to the $LOAD_PATH for git extensions
+ # and instead treat them identically to normal gems (where the gem install location,
+ # not the cache location, is added to $LOAD_PATH).
+ # Verify that the compilation worked and the result is in $LOAD_PATH by simply attempting
+ # to require it; that should make sure this spec does not break if the load path behaviour
+ # is changed.
+ bundle :install, local: true
+ ruby <<~R, raise_on_error: false
+ require 'bundler/setup'
+ require 'foo_c'
+ R
+ expect(last_command).to_not be_failure
+ end
end
diff --git a/spec/bundler/cache/path_spec.rb b/spec/bundler/cache/path_spec.rb
index c81dda7405..2c8a52617a 100644
--- a/spec/bundler/cache/path_spec.rb
+++ b/spec/bundler/cache/path_spec.rb
@@ -2,9 +2,10 @@
RSpec.describe "bundle cache with path" do
it "is no-op when the path is within the bundle" do
- build_lib "foo", :path => bundled_app("lib/foo")
+ build_lib "foo", path: bundled_app("lib/foo")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{bundled_app("lib/foo")}'
G
@@ -18,6 +19,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -33,9 +35,10 @@ RSpec.describe "bundle cache with path" do
libname = File.basename(bundled_app) + "_gem"
libpath = File.join(File.dirname(bundled_app), libname)
- build_lib libname, :path => libpath
+ build_lib libname, path: libpath
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "#{libname}", :path => '#{libpath}'
G
@@ -51,6 +54,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -73,6 +77,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -84,6 +89,7 @@ RSpec.describe "bundle cache with path" do
build_lib "bar"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "bar", :path => '#{lib_path("bar-1.0")}'
G
@@ -91,10 +97,11 @@ RSpec.describe "bundle cache with path" do
expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
end
- it "does not cache path gems by default", :bundler => "< 3" do
+ it "does not cache path gems by default", bundler: "< 3" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -103,10 +110,11 @@ RSpec.describe "bundle cache with path" do
expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
end
- it "caches path gems by default", :bundler => "3" do
+ it "caches path gems by default", bundler: "3" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -119,6 +127,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -127,6 +136,7 @@ RSpec.describe "bundle cache with path" do
build_lib "bar"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
gem "bar", :path => '#{lib_path("bar-1.0")}'
G
@@ -139,6 +149,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -147,11 +158,12 @@ RSpec.describe "bundle cache with path" do
build_lib "baz"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
gem "baz", :path => '#{lib_path("baz-1.0")}'
G
- bundle "cache --no-all", :raise_on_error => false
+ bundle "cache --no-all", raise_on_error: false
expect(bundled_app("vendor/cache/baz-1.0")).not_to exist
end
end
diff --git a/spec/bundler/cache/platform_spec.rb b/spec/bundler/cache/platform_spec.rb
index 128278956c..36db954c79 100644
--- a/spec/bundler/cache/platform_spec.rb
+++ b/spec/bundler/cache/platform_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe "bundle cache with multiple platforms" do
end
it "ensures that a successful bundle update does not delete gems for other platforms" do
- bundle "update", :all => true
+ bundle "update", all: true
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist