1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/spec/bundler/commands/clean_spec.rb
David Rodríguez 9e7249da4e [rubygems/rubygems] This spec can pass now on ruby 3
TSort was released as a library so we can install it, and also other
gems that are loaded by the spec. Also, Ruby on Windows apparently loads
fiddle 1.0.6, so we need to also install that to make that not fail.

https://github.com/rubygems/rubygems/commit/2b8dcab99e
2021-08-31 19:06:14 +09:00

916 lines
22 KiB
Ruby

# frozen_string_literal: true
RSpec.describe "bundle clean" do
def should_have_gems(*gems)
gems.each do |g|
expect(vendored_gems("gems/#{g}")).to exist
expect(vendored_gems("specifications/#{g}.gemspec")).to exist
expect(vendored_gems("cache/#{g}.gem")).to exist
end
end
def should_not_have_gems(*gems)
gems.each do |g|
expect(vendored_gems("gems/#{g}")).not_to exist
expect(vendored_gems("specifications/#{g}.gemspec")).not_to exist
expect(vendored_gems("cache/#{g}.gem")).not_to exist
end
end
it "removes unused gems that are different" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
G
bundle "install"
bundle :clean
expect(out).to include("Removing foo (1.0)")
should_have_gems "thin-1.0", "rack-1.0.0"
should_not_have_gems "foo-1.0"
expect(vendored_gems("bin/rackup")).to exist
end
it "removes old version of gem if unused" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
gem "foo"
G
bundle "install"
bundle :clean
expect(out).to include("Removing rack (0.9.1)")
should_have_gems "foo-1.0", "rack-1.0.0"
should_not_have_gems "rack-0.9.1"
expect(vendored_gems("bin/rackup")).to exist
end
it "removes new version of gem if unused" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
gem "foo"
G
bundle "update rack"
bundle :clean
expect(out).to include("Removing rack (1.0.0)")
should_have_gems "foo-1.0", "rack-0.9.1"
should_not_have_gems "rack-1.0.0"
expect(vendored_gems("bin/rackup")).to exist
end
it "removes gems in bundle without groups" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo"
group :test_group do
gem "rack", "1.0.0"
end
G
bundle "config set path vendor/bundle"
bundle "install"
bundle "config set without test_group"
bundle "install"
bundle :clean
expect(out).to include("Removing rack (1.0.0)")
should_have_gems "foo-1.0"
should_not_have_gems "rack-1.0.0"
expect(vendored_gems("bin/rackup")).to_not exist
end
it "does not remove cached git dir if it's being used" do
build_git "foo"
revision = revision_for(lib_path("foo-1.0"))
git_path = lib_path("foo-1.0")
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
G
bundle "config set path vendor/bundle"
bundle "install"
bundle :clean
digest = Digest(:SHA1).hexdigest(git_path.to_s)
cache_path = Bundler::VERSION.start_with?("2.") ? vendored_gems("cache/bundler/git/foo-1.0-#{digest}") : home(".bundle/cache/git/foo-1.0-#{digest}")
expect(cache_path).to exist
end
it "removes unused git gems" do
build_git "foo", :path => lib_path("foo")
git_path = lib_path("foo")
revision = revision_for(git_path)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
G
bundle "config set path vendor/bundle"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
G
bundle "install"
bundle :clean
expect(out).to include("Removing foo (#{revision[0..11]})")
expect(vendored_gems("gems/rack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).not_to exist
digest = Digest(:SHA1).hexdigest(git_path.to_s)
expect(vendored_gems("cache/bundler/git/foo-#{digest}")).not_to exist
expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist
expect(vendored_gems("bin/rackup")).to exist
end
it "keeps used git gems even if installed to a symlinked location" do
build_git "foo", :path => lib_path("foo")
git_path = lib_path("foo")
revision = revision_for(git_path)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
G
FileUtils.mkdir_p(bundled_app("real-path"))
FileUtils.ln_sf(bundled_app("real-path"), bundled_app("symlink-path"))
bundle "config set path #{bundled_app("symlink-path")}"
bundle "install"
bundle :clean
expect(out).not_to include("Removing foo (#{revision[0..11]})")
expect(bundled_app("symlink-path/#{Bundler.ruby_scope}/bundler/gems/foo-#{revision[0..11]}")).to exist
end
it "removes old git gems" do
build_git "foo-bar", :path => lib_path("foo-bar")
revision = revision_for(lib_path("foo-bar"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
git "#{lib_path("foo-bar")}" do
gem "foo-bar"
end
G
bundle "config set path vendor/bundle"
bundle "install"
update_git "foo", :path => lib_path("foo-bar")
revision2 = revision_for(lib_path("foo-bar"))
bundle "update", :all => true
bundle :clean
expect(out).to include("Removing foo-bar (#{revision[0..11]})")
expect(vendored_gems("gems/rack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-bar-#{revision[0..11]}")).not_to exist
expect(vendored_gems("bundler/gems/foo-bar-#{revision2[0..11]}")).to exist
expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist
expect(vendored_gems("bin/rackup")).to exist
end
it "does not remove nested gems in a git repo" do
build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport")
build_git "rails", "3.0", :path => lib_path("rails") do |s|
s.add_dependency "activesupport", "= 3.0"
end
revision = revision_for(lib_path("rails"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activesupport", :git => "#{lib_path("rails")}", :ref => '#{revision}'
G
bundle "config set path vendor/bundle"
bundle "install"
bundle :clean
expect(out).to include("")
expect(vendored_gems("bundler/gems/rails-#{revision[0..11]}")).to exist
end
it "does not remove git sources that are in without groups" do
build_git "foo", :path => lib_path("foo")
git_path = lib_path("foo")
revision = revision_for(git_path)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
group :test do
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
end
G
bundle "config set path vendor/bundle"
bundle "config set without test"
bundle "install"
bundle :clean
expect(out).to include("")
expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).to exist
digest = Digest(:SHA1).hexdigest(git_path.to_s)
expect(vendored_gems("cache/bundler/git/foo-#{digest}")).to_not exist
end
it "does not blow up when using without groups" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
group :development do
gem "foo"
end
G
bundle "config set path vendor/bundle"
bundle "config set without development"
bundle "install"
bundle :clean
end
it "displays an error when used without --path" do
bundle "config set path.system true"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
G
bundle :clean, :raise_on_error => false
expect(exitstatus).to eq(15)
expect(err).to include("--force")
end
# handling bundle clean upgrade path from the pre's
it "removes .gem/.gemspec file even if there's no corresponding gem dir" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo"
G
bundle "install"
FileUtils.rm(vendored_gems("bin/rackup"))
FileUtils.rm_rf(vendored_gems("gems/thin-1.0"))
FileUtils.rm_rf(vendored_gems("gems/rack-1.0.0"))
bundle :clean
should_not_have_gems "thin-1.0", "rack-1.0"
should_have_gems "foo-1.0"
expect(vendored_gems("bin/rackup")).not_to exist
end
it "does not call clean automatically when using system gems" do
bundle "config set path.system true"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "rack"
G
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
gem_command :list
expect(out).to include("rack (1.0.0)").and include("thin (1.0)")
end
it "--clean should override the bundle setting on install", :bundler => "< 3" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "rack"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install --clean true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
bundle "install"
should_have_gems "rack-1.0.0"
should_not_have_gems "thin-1.0"
end
it "--clean should override the bundle setting on update", :bundler => "< 3" do
build_repo2
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install --clean true"
update_repo2 do
build_gem "foo", "1.0.1"
end
bundle "update", :all => true
should_have_gems "foo-1.0.1"
should_not_have_gems "foo-1.0"
end
it "automatically cleans when path has not been set", :bundler => "3" do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "foo"
G
update_repo2 do
build_gem "foo", "1.0.1"
end
bundle "update", :all => true
files = Pathname.glob(bundled_app(".bundle", Bundler.ruby_scope, "*", "*"))
files.map! {|f| f.to_s.sub(bundled_app(".bundle", Bundler.ruby_scope).to_s, "") }
expect(files.sort).to eq %w[
/cache/foo-1.0.1.gem
/gems/foo-1.0.1
/specifications/foo-1.0.1.gemspec
]
end
it "does not clean automatically on --path" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "rack"
G
bundle "config set path vendor/bundle"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
bundle "install"
should_have_gems "rack-1.0.0", "thin-1.0"
end
it "does not clean on bundle update with --path" do
build_repo2
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "install"
update_repo2 do
build_gem "foo", "1.0.1"
end
bundle :update, :all => true
should_have_gems "foo-1.0", "foo-1.0.1"
end
it "does not clean on bundle update when using --system" do
bundle "config set path.system true"
build_repo2
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "foo"
G
bundle "install"
update_repo2 do
build_gem "foo", "1.0.1"
end
bundle :update, :all => true
gem_command :list
expect(out).to include("foo (1.0.1, 1.0)")
end
it "cleans system gems when --force is used" do
bundle "config set path.system true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo"
gem "rack"
G
bundle :install
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
bundle :install
bundle "clean --force"
expect(out).to include("Removing foo (1.0)")
gem_command :list
expect(out).not_to include("foo (1.0)")
expect(out).to include("rack (1.0.0)")
end
describe "when missing permissions", :permissions do
before { ENV["BUNDLE_PATH__SYSTEM"] = "true" }
let(:system_cache_path) { system_gem_path("cache") }
after do
FileUtils.chmod(0o755, system_cache_path)
end
it "returns a helpful error message" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo"
gem "rack"
G
bundle :install
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
bundle :install
FileUtils.chmod(0o500, system_cache_path)
bundle :clean, :force => true, :raise_on_error => false
expect(err).to include(system_gem_path.to_s)
expect(err).to include("grant write permissions")
gem_command :list
expect(out).to include("foo (1.0)")
expect(out).to include("rack (1.0.0)")
end
end
it "cleans git gems with a 7 length git revision" do
build_git "foo"
revision = revision_for(lib_path("foo-1.0"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
bundle "config set path vendor/bundle"
bundle "install"
# mimic 7 length git revisions in Gemfile.lock
gemfile_lock = File.read(bundled_app_lock).split("\n")
gemfile_lock.each_with_index do |line, index|
gemfile_lock[index] = line[0..(11 + 7)] if line.include?(" revision:")
end
lockfile(bundled_app_lock, gemfile_lock.join("\n"))
bundle "config set path vendor/bundle"
bundle "install"
bundle :clean
expect(out).not_to include("Removing foo (1.0 #{revision[0..6]})")
expect(vendored_gems("bundler/gems/foo-1.0-#{revision[0..6]}")).to exist
end
it "when using --force on system gems, it doesn't remove binaries" do
bundle "config set path.system true"
build_repo2 do
build_gem "bindir" do |s|
s.bindir = "exe"
s.executables = "foo"
end
end
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "bindir"
G
bundle :install
bundle "clean --force"
sys_exec "foo"
expect(out).to eq("1.0")
end
it "when using --force, it doesn't remove default gem binaries" do
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"
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
default_irb_version = ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false
skip "irb isn't a default gem" if default_irb_version.empty?
# simulate executable for default gem
build_gem "irb", default_irb_version, :to_system => true, :default => true do |s|
s.executables = "irb"
end
realworld_system_gems "fiddle --version 1.0.6", "tsort --version 0.1.0", "pathname --version 0.1.0", "set --version 1.0.1"
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
G
bundle "clean --force", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
expect(out).not_to include("Removing irb")
end
it "doesn't blow up on path gems without a .gemspec" do
relative_path = "vendor/private_gems/bar-1.0"
absolute_path = bundled_app(relative_path)
FileUtils.mkdir_p("#{absolute_path}/lib/bar")
File.open("#{absolute_path}/lib/bar/bar.rb", "wb") do |file|
file.puts "module Bar; end"
end
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo"
gem "bar", "1.0", :path => "#{relative_path}"
G
bundle "config set path vendor/bundle"
bundle "install"
bundle :clean
end
it "doesn't remove gems in dry-run mode with path set" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
G
bundle :install
bundle "clean --dry-run"
expect(out).not_to include("Removing foo (1.0)")
expect(out).to include("Would have removed foo (1.0)")
should_have_gems "thin-1.0", "rack-1.0.0", "foo-1.0"
expect(vendored_gems("bin/rackup")).to exist
end
it "doesn't remove gems in dry-run mode with no path set" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
G
bundle :install
bundle "clean --dry-run"
expect(out).not_to include("Removing foo (1.0)")
expect(out).to include("Would have removed foo (1.0)")
should_have_gems "thin-1.0", "rack-1.0.0", "foo-1.0"
expect(vendored_gems("bin/rackup")).to exist
end
it "doesn't store dry run as a config setting" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install"
bundle "config set dry_run false"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
G
bundle :install
bundle "clean"
expect(out).to include("Removing foo (1.0)")
expect(out).not_to include("Would have removed foo (1.0)")
should_have_gems "thin-1.0", "rack-1.0.0"
should_not_have_gems "foo-1.0"
expect(vendored_gems("bin/rackup")).to exist
end
it "performs an automatic bundle install" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "foo"
G
bundle "config set path vendor/bundle"
bundle "config set clean false"
bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "weakling"
G
bundle "config set auto_install 1"
bundle :clean
expect(out).to include("Installing weakling 0.0.3")
should_have_gems "thin-1.0", "rack-1.0.0", "weakling-0.0.3"
should_not_have_gems "foo-1.0"
end
it "doesn't remove extensions artifacts from bundled git gems after clean", :ruby_repo do
build_git "very_simple_git_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
G
bundle "config set path vendor/bundle"
bundle "install"
expect(vendored_gems("bundler/gems/extensions")).to exist
expect(vendored_gems("bundler/gems/very_simple_git_binary-1.0-#{revision[0..11]}")).to exist
bundle :clean
expect(out).to be_empty
expect(vendored_gems("bundler/gems/extensions")).to exist
expect(vendored_gems("bundler/gems/very_simple_git_binary-1.0-#{revision[0..11]}")).to exist
end
it "removes extension directories", :ruby_repo do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "very_simple_binary"
gem "simple_binary"
G
bundle "config set path vendor/bundle"
bundle "install"
very_simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/extensions/*/*/very_simple_binary-1.0").first
simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/extensions/*/*/simple_binary-1.0").first
expect(very_simple_binary_extensions_dir).to exist
expect(simple_binary_extensions_dir).to exist
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "simple_binary"
G
bundle "install"
bundle :clean
expect(out).to eq("Removing very_simple_binary (1.0)")
expect(very_simple_binary_extensions_dir).not_to exist
expect(simple_binary_extensions_dir).to exist
end
it "removes git extension directories", :ruby_repo do
build_git "very_simple_git_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
short_revision = revision[0..11]
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
G
bundle "config set path vendor/bundle"
bundle "install"
very_simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first
expect(very_simple_binary_extensions_dir).to exist
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
G
bundle "install"
bundle :clean
expect(out).to include("Removing thin (1.0)")
expect(very_simple_binary_extensions_dir).to exist
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
G
bundle "install"
bundle :clean
expect(out).to eq("Removing very_simple_git_binary-1.0 (#{short_revision})")
expect(very_simple_binary_extensions_dir).not_to exist
end
it "keeps git extension directories when excluded by group" do
build_git "very_simple_git_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
short_revision = revision[0..11]
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
group :development do
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
end
G
bundle :lock
bundle "config set without development"
bundle "config set path vendor/bundle"
bundle "install"
bundle :clean
very_simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first
expect(very_simple_binary_extensions_dir).to be_nil
end
end