mirror of
https://github.com/ruby/ruby.git
synced 2025-08-24 05:25:34 +02:00

Since now every functionality that changes in Bundler 4 is under a
setting, we can enable that setting to test the new functionality,
without having to run our full CI twice.
This can actually be seen as increasing coverage, because Bundler 4
functionality will now be tested on Windows, MacOS, or any other
environment where previously "Bundler 4 mode" was not running.
1cb3e009fc
751 lines
18 KiB
Ruby
751 lines
18 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe "bundle remove" do
|
|
context "when no gems are specified" do
|
|
it "throws error" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
G
|
|
|
|
bundle "remove", raise_on_error: false
|
|
|
|
expect(err).to include("Please specify gems to remove.")
|
|
end
|
|
end
|
|
|
|
context "after 'bundle install' is run" do
|
|
describe "running 'bundle remove GEM_NAME'" do
|
|
it "removes it from the lockfile" do
|
|
myrack_dep = <<~L
|
|
|
|
DEPENDENCIES
|
|
myrack
|
|
|
|
L
|
|
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "install"
|
|
|
|
expect(lockfile).to include(myrack_dep)
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
expect(lockfile).to_not include(myrack_dep)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when --install flag is specified" do
|
|
it "removes gems from .bundle" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack --install"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(the_bundle).to_not include_gems "myrack"
|
|
end
|
|
end
|
|
|
|
describe "remove single gem from gemfile" do
|
|
context "when gem is present in gemfile" do
|
|
it "shows success for removed gem" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(the_bundle).to_not include_gems "myrack"
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
|
|
context "when gem is specified in multiple lines" do
|
|
it "shows success for removed gem" do
|
|
build_git "myrack"
|
|
|
|
gemfile <<-G
|
|
source 'https://gem.repo1'
|
|
|
|
gem 'git'
|
|
gem 'myrack',
|
|
git: "#{lib_path("myrack-1.0")}",
|
|
branch: 'main'
|
|
gem 'nokogiri'
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source 'https://gem.repo1'
|
|
|
|
gem 'git'
|
|
gem 'nokogiri'
|
|
G
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when gem is not present in gemfile" do
|
|
it "shows warning for gem that could not be removed" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
G
|
|
|
|
bundle "remove myrack", raise_on_error: false
|
|
|
|
expect(err).to include("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "remove multiple gems from gemfile" do
|
|
context "when all gems are present in gemfile" do
|
|
it "shows success fir all removed gems" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
gem "rails"
|
|
G
|
|
|
|
bundle "remove myrack rails"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(out).to include("rails was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when some gems are not present in the gemfile" do
|
|
it "shows warning for those not present and success for those that can be removed" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "rails"
|
|
gem "minitest"
|
|
gem "rspec"
|
|
G
|
|
|
|
bundle "remove rails myrack minitest", raise_on_error: false
|
|
|
|
expect(err).to include("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
gem "rails"
|
|
gem "minitest"
|
|
gem "rspec"
|
|
G
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with inline groups" do
|
|
it "removes the specified gem" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack", :group => [:dev]
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
describe "with group blocks" do
|
|
context "when single group block with gem to be removed is present" do
|
|
it "removes the group block" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
gem "rspec"
|
|
end
|
|
G
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when gem to be removed is outside block" do
|
|
it "does not modify group" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
group :test do
|
|
gem "coffee-script-source"
|
|
end
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
gem "coffee-script-source"
|
|
end
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when an empty block is also present" do
|
|
it "removes all empty blocks" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
gem "rspec"
|
|
end
|
|
|
|
group :dev do
|
|
end
|
|
G
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when the gem belongs to multiple groups" do
|
|
it "removes the groups" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
group :test, :serioustest do
|
|
gem "rspec"
|
|
end
|
|
G
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when the gem is present in multiple groups" do
|
|
it "removes all empty blocks" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
group :one do
|
|
gem "rspec"
|
|
end
|
|
|
|
group :two do
|
|
gem "rspec"
|
|
end
|
|
G
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "nested group blocks" do
|
|
context "when all the groups will be empty after removal" do
|
|
it "removes the empty nested blocks" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
group :serioustest do
|
|
gem "rspec"
|
|
end
|
|
end
|
|
G
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when outer group will not be empty after removal" do
|
|
it "removes only empty blocks" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
gem "myrack-test"
|
|
|
|
group :serioustest do
|
|
gem "rspec"
|
|
end
|
|
end
|
|
G
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
gem "myrack-test"
|
|
|
|
end
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when inner group will not be empty after removal" do
|
|
it "removes only empty blocks" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
group :serioustest do
|
|
gem "rspec"
|
|
gem "myrack-test"
|
|
end
|
|
end
|
|
G
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
group :test do
|
|
group :serioustest do
|
|
gem "myrack-test"
|
|
end
|
|
end
|
|
G
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "arbitrary gemfile" do
|
|
context "when multiple gems are present in same line" do
|
|
it "shows warning for gems not removed" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack"; gem "rails"
|
|
G
|
|
|
|
bundle "remove rails", raise_on_error: false
|
|
|
|
expect(err).to include("Gems could not be removed. myrack (>= 0) would also have been removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
gem "myrack"; gem "rails"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when some gems could not be removed" do
|
|
it "shows warning for gems not removed and success for those removed" do
|
|
install_gemfile <<-G, raise_on_error: false
|
|
source "https://gem.repo1"
|
|
gem"myrack"
|
|
gem"rspec"
|
|
gem "rails"
|
|
gem "minitest"
|
|
G
|
|
|
|
bundle "remove rails myrack rspec minitest"
|
|
|
|
expect(out).to include("rails was removed.")
|
|
expect(out).to include("minitest was removed.")
|
|
expect(out).to include("myrack, rspec could not be removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
gem"myrack"
|
|
gem"rspec"
|
|
G
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with sources" do
|
|
before do
|
|
build_repo3 do
|
|
build_gem "rspec"
|
|
end
|
|
end
|
|
|
|
it "removes gems and empty source blocks" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
|
|
source "https://gem.repo3" do
|
|
gem "rspec"
|
|
end
|
|
G
|
|
|
|
bundle "install"
|
|
|
|
bundle "remove rspec"
|
|
|
|
expect(out).to include("rspec was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
G
|
|
end
|
|
end
|
|
|
|
describe "with eval_gemfile" do
|
|
context "when gems are present in both gemfiles" do
|
|
it "removes the gems" do
|
|
gemfile "Gemfile-other", <<-G
|
|
gem "myrack"
|
|
G
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
end
|
|
end
|
|
|
|
context "when gems are present in other gemfile" do
|
|
it "removes the gems" do
|
|
gemfile "Gemfile-other", <<-G
|
|
gem "myrack"
|
|
G
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(bundled_app("Gemfile-other").read).to_not include("gem \"myrack\"")
|
|
expect(out).to include("myrack was removed.")
|
|
end
|
|
end
|
|
|
|
context "when gems to be removed are not specified in any of the gemfiles" do
|
|
it "throws error for the gems not present" do
|
|
# an empty gemfile
|
|
# indicating the gem is not present in the gemfile
|
|
create_file "Gemfile-other", <<-G
|
|
G
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
G
|
|
|
|
bundle "remove myrack", raise_on_error: false
|
|
|
|
expect(err).to include("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
|
|
end
|
|
end
|
|
|
|
context "when the gem is present in parent file but not in gemfile specified by eval_gemfile" do
|
|
it "removes the gem" do
|
|
gemfile "Gemfile-other", <<-G
|
|
gem "rails"
|
|
G
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack", raise_on_error: false
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(err).to include("`myrack` is not specified in #{bundled_app("Gemfile-other")} so it could not be removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when gems cannot be removed from other gemfile" do
|
|
it "shows error" do
|
|
gemfile "Gemfile-other", <<-G
|
|
gem "rails"; gem "myrack"
|
|
G
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack", raise_on_error: false
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when gems could not be removed from parent gemfile" do
|
|
it "shows error" do
|
|
gemfile "Gemfile-other", <<-G
|
|
gem "myrack"
|
|
G
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
gem "rails"; gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack", raise_on_error: false
|
|
|
|
expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
|
|
expect(bundled_app("Gemfile-other").read).to include("gem \"myrack\"")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
gem "rails"; gem "myrack"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when gem present in gemfiles but could not be removed from one from one of them" do
|
|
it "removes gem which can be removed and shows warning for file from which it cannot be removed" do
|
|
gemfile "Gemfile-other", <<-G
|
|
gem "myrack"
|
|
G
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
eval_gemfile "Gemfile-other"
|
|
gem"myrack"
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(bundled_app("Gemfile-other").read).to_not include("gem \"myrack\"")
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with install_if" do
|
|
it "removes gems inside blocks and empty blocks" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
install_if(lambda { false }) do
|
|
gem "myrack"
|
|
end
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "with env" do
|
|
it "removes gems inside blocks and empty blocks" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
env "BUNDLER_TEST" do
|
|
gem "myrack"
|
|
end
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "with gemspec" do
|
|
it "should not remove the gem" do
|
|
build_lib("foo", path: tmp("foo")) do |s|
|
|
s.write("foo.gemspec", "")
|
|
s.add_dependency "myrack"
|
|
end
|
|
|
|
install_gemfile(<<-G)
|
|
source "https://gem.repo1"
|
|
gemspec :path => '#{tmp("foo")}', :name => 'foo'
|
|
G
|
|
|
|
bundle "remove foo"
|
|
|
|
expect(out).to include("foo could not be removed.")
|
|
end
|
|
end
|
|
|
|
describe "with comments that mention gems" do
|
|
context "when comment is a separate line comment" do
|
|
it "does not remove the line comment" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
# gem "myrack" might be used in the future
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
# gem "myrack" might be used in the future
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when gem specified for removal has an inline comment" do
|
|
it "removes the inline comment" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack" # this can be removed
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when gem specified for removal is mentioned in other gem's comment" do
|
|
it "does not remove other gem" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "puma" # implements interface provided by gem "myrack"
|
|
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to_not include("puma was removed.")
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
gem "puma" # implements interface provided by gem "myrack"
|
|
G
|
|
end
|
|
end
|
|
|
|
context "when gem specified for removal has a comment that mentions other gem" do
|
|
it "does not remove other gem" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "puma" # implements interface provided by gem "myrack"
|
|
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "remove puma"
|
|
|
|
expect(out).to include("puma was removed.")
|
|
expect(out).to_not include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
|
|
gem "myrack"
|
|
G
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when gem definition has parentheses" do
|
|
it "removes the gem" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
|
|
gem("myrack")
|
|
gem("myrack", ">= 0")
|
|
gem("myrack", require: false)
|
|
G
|
|
|
|
bundle "remove myrack"
|
|
|
|
expect(out).to include("myrack was removed.")
|
|
expect(gemfile).to eq <<~G
|
|
source "https://gem.repo1"
|
|
G
|
|
end
|
|
end
|
|
end
|