summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/bundler/bundler_spec.rb146
-rw-r--r--spec/bundler/plugin/events_spec.rb18
-rw-r--r--spec/bundler/plugin_spec.rb40
-rw-r--r--spec/commands/add_spec.rb108
-rw-r--r--spec/commands/binstubs_spec.rb23
-rw-r--r--spec/commands/exec_spec.rb2
-rw-r--r--spec/commands/install_spec.rb52
-rw-r--r--spec/commands/list_spec.rb53
-rw-r--r--spec/commands/lock_spec.rb6
-rw-r--r--spec/commands/outdated_spec.rb27
-rw-r--r--spec/commands/remove_spec.rb571
-rw-r--r--spec/commands/update_spec.rb17
-rw-r--r--spec/install/failure_spec.rb64
-rw-r--r--spec/install/gemfile/gemspec_spec.rb12
-rw-r--r--spec/install/gemfile/sources_spec.rb8
-rw-r--r--spec/install/gems/mirror_spec.rb6
-rw-r--r--spec/install/gemspecs_spec.rb28
-rw-r--r--spec/install/post_bundle_message_spec.rb2
-rw-r--r--spec/install/process_lock_spec.rb11
-rw-r--r--spec/lock/lockfile_bundler_1_spec.rb2
-rw-r--r--spec/lock/lockfile_spec.rb2
-rw-r--r--spec/plugins/hook_spec.rb114
-rw-r--r--spec/resolver/basic_spec.rb7
-rw-r--r--spec/runtime/setup_spec.rb46
-rw-r--r--spec/spec_helper.rb12
-rw-r--r--spec/support/builders.rb2
-rw-r--r--spec/support/helpers.rb15
-rw-r--r--spec/support/matchers.rb6
-rw-r--r--spec/support/rubygems_ext.rb6
29 files changed, 1351 insertions, 55 deletions
diff --git a/spec/bundler/bundler_spec.rb b/spec/bundler/bundler_spec.rb
index 94d4096cd3..06435b9888 100644
--- a/spec/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler_spec.rb
@@ -2,6 +2,7 @@
# frozen_string_literal: true
require "bundler"
+require "tmpdir"
RSpec.describe Bundler do
describe "#load_gemspec_uncached" do
@@ -189,6 +190,34 @@ EOF
end
end
+ describe "#mkdir_p" do
+ it "creates a folder at the given path" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ Bundler.mkdir_p(bundled_app.join("foo", "bar"))
+ expect(bundled_app.join("foo", "bar")).to exist
+ end
+
+ context "when mkdir_p requires sudo" do
+ it "creates a new folder using sudo" do
+ expect(Bundler).to receive(:requires_sudo?).and_return(true)
+ expect(Bundler).to receive(:sudo).and_return true
+ Bundler.mkdir_p(bundled_app.join("foo"))
+ end
+ end
+
+ context "with :no_sudo option" do
+ it "forces mkdir_p to not use sudo" do
+ expect(Bundler).to receive(:requires_sudo?).and_return(true)
+ expect(Bundler).to_not receive(:sudo)
+ Bundler.mkdir_p(bundled_app.join("foo"), :no_sudo => true)
+ end
+ end
+ end
+
describe "#user_home" do
context "home directory is set" do
it "should return the user home" do
@@ -198,6 +227,57 @@ EOF
allow(File).to receive(:writable?).with(path).and_return true
expect(Bundler.user_home).to eq(Pathname(path))
end
+
+ context "is not a directory" do
+ it "should issue a warning and return a temporary user home" do
+ path = "/home/oggy"
+ allow(Bundler.rubygems).to receive(:user_home).and_return(path)
+ allow(File).to receive(:directory?).with(path).and_return false
+ allow(Etc).to receive(:getlogin).and_return("USER")
+ allow(Dir).to receive(:tmpdir).and_return("/TMP")
+ allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
+ expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
+ message = <<EOF
+`/home/oggy` is not a directory.
+Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
+EOF
+ expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+ end
+ end
+
+ context "is not writable" do
+ let(:path) { "/home/oggy" }
+ let(:dotbundle) { "/home/oggy/.bundle" }
+
+ it "should issue a warning and return a temporary user home" do
+ allow(Bundler.rubygems).to receive(:user_home).and_return(path)
+ allow(File).to receive(:directory?).with(path).and_return true
+ allow(File).to receive(:writable?).with(path).and_return false
+ allow(File).to receive(:directory?).with(dotbundle).and_return false
+ allow(Etc).to receive(:getlogin).and_return("USER")
+ allow(Dir).to receive(:tmpdir).and_return("/TMP")
+ allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
+ expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
+ message = <<EOF
+`/home/oggy` is not writable.
+Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
+EOF
+ expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+ end
+
+ context ".bundle exists and have correct permissions" do
+ it "should return the user home" do
+ allow(Bundler.rubygems).to receive(:user_home).and_return(path)
+ allow(File).to receive(:directory?).with(path).and_return true
+ allow(File).to receive(:writable?).with(path).and_return false
+ allow(File).to receive(:directory?).with(dotbundle).and_return true
+ allow(File).to receive(:writable?).with(dotbundle).and_return true
+ expect(Bundler.user_home).to eq(Pathname(path))
+ end
+ end
+ end
end
context "home directory is not set" do
@@ -228,6 +308,72 @@ EOF
end
end
+ describe "#requires_sudo?" do
+ let!(:tmpdir) { Dir.mktmpdir }
+ let(:bundle_path) { Pathname("#{tmpdir}/bundle") }
+
+ def clear_cached_requires_sudo
+ # Private in ruby 1.8.7
+ return unless Bundler.instance_variable_defined?(:@requires_sudo_ran)
+ Bundler.send(:remove_instance_variable, :@requires_sudo_ran)
+ Bundler.send(:remove_instance_variable, :@requires_sudo)
+ end
+
+ before do
+ clear_cached_requires_sudo
+ allow(Bundler).to receive(:which).with("sudo").and_return("/usr/bin/sudo")
+ allow(Bundler).to receive(:bundle_path).and_return(bundle_path)
+ end
+
+ after do
+ FileUtils.rm_rf(tmpdir)
+ clear_cached_requires_sudo
+ end
+
+ subject { Bundler.requires_sudo? }
+
+ context "bundle_path doesn't exist" do
+ it { should be false }
+
+ context "and parent dir can't be written" do
+ before do
+ FileUtils.chmod(0o500, tmpdir)
+ end
+
+ it { should be true }
+ end
+
+ context "with unwritable files in a parent dir" do
+ # Regression test for https://github.com/bundler/bundler/pull/6316
+ # It doesn't matter if there are other unwritable files so long as
+ # bundle_path can be created
+ before do
+ file = File.join(tmpdir, "unrelated_file")
+ FileUtils.touch(file)
+ FileUtils.chmod(0o400, file)
+ end
+
+ it { should be false }
+ end
+ end
+
+ context "bundle_path exists" do
+ before do
+ FileUtils.mkdir_p(bundle_path)
+ end
+
+ it { should be false }
+
+ context "and is unwritable" do
+ before do
+ FileUtils.chmod(0o500, bundle_path)
+ end
+
+ it { should be true }
+ end
+ end
+ end
+
context "user cache dir" do
let(:home_path) { Pathname.new(ENV["HOME"]) }
diff --git a/spec/bundler/plugin/events_spec.rb b/spec/bundler/plugin/events_spec.rb
new file mode 100644
index 0000000000..b09e915682
--- /dev/null
+++ b/spec/bundler/plugin/events_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::Plugin::Events do
+ context "plugin events" do
+ describe "#define" do
+ it "raises when redefining a constant" do
+ expect do
+ Bundler::Plugin::Events.send(:define, :GEM_BEFORE_INSTALL_ALL, "another-value")
+ end.to raise_error(ArgumentError)
+ end
+
+ it "can define a new constant" do
+ Bundler::Plugin::Events.send(:define, :NEW_CONSTANT, "value")
+ expect(Bundler::Plugin::Events::NEW_CONSTANT).to eq("value")
+ end
+ end
+ end
+end
diff --git a/spec/bundler/plugin_spec.rb b/spec/bundler/plugin_spec.rb
index 68a7e32ad1..eaa0b80905 100644
--- a/spec/bundler/plugin_spec.rb
+++ b/spec/bundler/plugin_spec.rb
@@ -251,6 +251,16 @@ RSpec.describe Bundler::Plugin do
end
end
+ describe "#add_hook" do
+ it "raises an ArgumentError on an unregistered event" do
+ ran = false
+ expect do
+ Plugin.add_hook("unregistered-hook") { ran = true }
+ end.to raise_error(ArgumentError)
+ expect(ran).to be(false)
+ end
+ end
+
describe "#hook" do
before do
path = lib_path("foo-plugin")
@@ -258,7 +268,13 @@ RSpec.describe Bundler::Plugin do
s.write "plugins.rb", code
end
- allow(index).to receive(:hook_plugins).with(event).
+ Bundler::Plugin::Events.send(:reset)
+ Bundler::Plugin::Events.send(:define, :EVENT_1, "event-1")
+ Bundler::Plugin::Events.send(:define, :EVENT_2, "event-2")
+
+ allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_1).
+ and_return(["foo-plugin"])
+ allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_2).
and_return(["foo-plugin"])
allow(index).to receive(:plugin_path).with("foo-plugin").and_return(path)
allow(index).to receive(:load_paths).with("foo-plugin").and_return([])
@@ -268,11 +284,15 @@ RSpec.describe Bundler::Plugin do
Bundler::Plugin::API.hook("event-1") { puts "hook for event 1" }
RUBY
- let(:event) { "event-1" }
+ it "raises an ArgumentError on an unregistered event" do
+ expect do
+ Plugin.hook("unregistered-hook")
+ end.to raise_error(ArgumentError)
+ end
it "executes the hook" do
out = capture(:stdout) do
- Plugin.hook("event-1")
+ Plugin.hook(Bundler::Plugin::Events::EVENT_1)
end.strip
expect(out).to eq("hook for event 1")
@@ -280,17 +300,15 @@ RSpec.describe Bundler::Plugin do
context "single plugin declaring more than one hook" do
let(:code) { <<-RUBY }
- Bundler::Plugin::API.hook("event-1") {}
- Bundler::Plugin::API.hook("event-2") {}
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) {}
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_2) {}
puts "loaded"
RUBY
- let(:event) { /event-1|event-2/ }
-
it "evals plugins.rb once" do
out = capture(:stdout) do
- Plugin.hook("event-1")
- Plugin.hook("event-2")
+ Plugin.hook(Bundler::Plugin::Events::EVENT_1)
+ Plugin.hook(Bundler::Plugin::Events::EVENT_2)
end.strip
expect(out).to eq("loaded")
@@ -299,12 +317,12 @@ RSpec.describe Bundler::Plugin do
context "a block is passed" do
let(:code) { <<-RUBY }
- Bundler::Plugin::API.hook("#{event}") { |&blk| blk.call }
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) { |&blk| blk.call }
RUBY
it "is passed to the hook" do
out = capture(:stdout) do
- Plugin.hook("event-1") { puts "win" }
+ Plugin.hook(Bundler::Plugin::Events::EVENT_1) { puts "win" }
end.strip
expect(out).to eq("win")
diff --git a/spec/commands/add_spec.rb b/spec/commands/add_spec.rb
index d1f2050aa0..2e9ef6b923 100644
--- a/spec/commands/add_spec.rb
+++ b/spec/commands/add_spec.rb
@@ -17,6 +17,14 @@ RSpec.describe "bundle add" do
G
end
+ context "when no gems are specified" do
+ it "shows error" do
+ bundle "add"
+
+ expect(last_command.bundler_err).to include("Please specify gems to add")
+ end
+ end
+
describe "without version specified" do
it "version requirement becomes ~> major.minor.patch when resolved version is < 1.0" do
bundle "add 'bar'"
@@ -75,11 +83,21 @@ RSpec.describe "bundle add" do
describe "with --source" do
it "adds dependency with specified source" do
bundle "add 'foo' --source='file://#{gem_repo2}'"
+
expect(bundled_app("Gemfile").read).to match(%r{gem "foo", "~> 2.0", :source => "file:\/\/#{gem_repo2}"})
expect(the_bundle).to include_gems "foo 2.0"
end
end
+ describe "with --skip-install" do
+ it "adds gem to Gemfile but is not installed" do
+ bundle "add foo --skip-install --version=2.0"
+
+ expect(bundled_app("Gemfile").read).to match(/gem "foo", "= 2.0"/)
+ expect(the_bundle).to_not include_gems "foo 2.0"
+ end
+ end
+
it "using combination of short form options works like long form" do
bundle "add 'foo' -s='file://#{gem_repo2}' -g='development' -v='~>1.0'"
expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 1.0", :group => [:development], :source => "file://#{gem_repo2}")
@@ -106,4 +124,94 @@ RSpec.describe "bundle add" do
bundle "add 'baz' --source='file://does/not/exist'"
expect(out).to include("Could not fetch specs from file://does/not/exist/")
end
+
+ describe "with --optimistic" do
+ it "adds optimistic version" do
+ bundle! "add 'foo' --optimistic"
+ expect(bundled_app("Gemfile").read).to include %(gem "foo", ">= 2.0")
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --strict option" do
+ it "adds strict version" do
+ bundle! "add 'foo' --strict"
+ expect(bundled_app("Gemfile").read).to include %(gem "foo", "= 2.0")
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with no option" do
+ it "adds pessimistic version" do
+ bundle! "add 'foo'"
+ expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 2.0")
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --optimistic and --strict" do
+ it "throws error" do
+ bundle "add 'foo' --strict --optimistic"
+
+ expect(out).to include("You can not specify `--strict` and `--optimistic` at the same time")
+ end
+ end
+
+ context "multiple gems" do
+ it "adds multiple gems to gemfile" do
+ bundle! "add bar baz"
+
+ expect(bundled_app("Gemfile").read).to match(/gem "bar", "~> 0.12.3"/)
+ expect(bundled_app("Gemfile").read).to match(/gem "baz", "~> 1.2"/)
+ end
+
+ it "throws error if any of the specified gems are present in the gemfile with different version" do
+ bundle "add weakling bar"
+
+ expect(out).to include("You cannot specify the same gem twice with different version requirements")
+ expect(out).to include("You specified: weakling (~> 0.0.1) and weakling (>= 0).")
+ end
+ end
+
+ describe "when a gem is added which is already specified in Gemfile with version" do
+ it "shows an error when added with different version requirement" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "rack", "1.0"
+ G
+
+ bundle "add 'rack' --version=1.1"
+
+ expect(out).to include("You cannot specify the same gem twice with different version requirements")
+ expect(out).to include("If you want to update the gem version, run `bundle update rack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
+ end
+
+ it "shows error when added without version requirements" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "rack", "1.0"
+ G
+
+ bundle "add 'rack'"
+
+ expect(out).to include("Gem already added.")
+ expect(out).to include("You cannot specify the same gem twice with different version requirements")
+ expect(out).not_to include("If you want to update the gem version, run `bundle update rack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
+ end
+ end
+
+ describe "when a gem is added which is already specified in Gemfile without version" do
+ it "shows an error when added with different version requirement" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "rack"
+ G
+
+ bundle "add 'rack' --version=1.1"
+
+ expect(out).to include("You cannot specify the same gem twice with different version requirements")
+ expect(out).to include("If you want to update the gem version, run `bundle update rack`.")
+ expect(out).not_to include("You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
+ end
+ end
end
diff --git a/spec/commands/binstubs_spec.rb b/spec/commands/binstubs_spec.rb
index 8157173b42..ad859a21d5 100644
--- a/spec/commands/binstubs_spec.rb
+++ b/spec/commands/binstubs_spec.rb
@@ -39,6 +39,18 @@ RSpec.describe "bundle binstubs <gem>" do
expect(bundled_app("bin/rails")).to exist
end
+ it "allows installing all binstubs" do
+ install_gemfile! <<-G
+ source "file://#{gem_repo1}"
+ gem "rails"
+ G
+
+ bundle! :binstubs, :all => true
+
+ expect(bundled_app("bin/rails")).to exist
+ expect(bundled_app("bin/rake")).to exist
+ end
+
it "displays an error when used without any gem" do
install_gemfile <<-G
source "file://#{gem_repo1}"
@@ -50,6 +62,17 @@ RSpec.describe "bundle binstubs <gem>" do
expect(out).to include("`bundle binstubs` needs at least one gem to run.")
end
+ it "displays an error when used with --all and gems" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ bundle "binstubs rack", :all => true
+ expect(last_command).to be_failure
+ expect(last_command.bundler_err).to include("Cannot specify --all with specific gems")
+ end
+
context "when generating bundle binstub outside bundler" do
it "should abort" do
install_gemfile <<-G
diff --git a/spec/commands/exec_spec.rb b/spec/commands/exec_spec.rb
index 2fe2667363..5ece0bccc3 100644
--- a/spec/commands/exec_spec.rb
+++ b/spec/commands/exec_spec.rb
@@ -789,6 +789,8 @@ __FILE__: #{path.to_s.inspect}
end
it "overrides disable_shared_gems so bundler can be found" do
+ skip "bundler 1.16.x is not support with Ruby 2.6 on Travis CI" if RUBY_VERSION >= "2.6"
+
file = bundled_app("file_that_bundle_execs.rb")
create_file(file, <<-RB)
#!#{Gem.ruby}
diff --git a/spec/commands/install_spec.rb b/spec/commands/install_spec.rb
index b6e89d70da..394f672fef 100644
--- a/spec/commands/install_spec.rb
+++ b/spec/commands/install_spec.rb
@@ -321,6 +321,56 @@ RSpec.describe "bundle install with gem sources" do
expect(File.exist?(bundled_app("Gemfile.lock"))).to eq(true)
end
+ context "throws a warning if a gem is added twice in Gemfile" do
+ it "without version requirements" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "rack"
+ gem "rack"
+ G
+
+ expect(out).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
+ expect(out).to include("Remove any duplicate entries and specify the gem only once (per group).")
+ expect(out).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ end
+
+ it "with same versions" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "rack", "1.0"
+ gem "rack", "1.0"
+ G
+
+ expect(out).to include("Your Gemfile lists the gem rack (= 1.0) more than once.")
+ expect(out).to include("Remove any duplicate entries and specify the gem only once (per group).")
+ expect(out).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ end
+ end
+
+ context "throws an error if a gem is added twice in Gemfile" do
+ it "when version of one dependency is not specified" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "rack"
+ gem "rack", "1.0"
+ G
+
+ expect(out).to include("You cannot specify the same gem twice with different version requirements")
+ expect(out).to include("You specified: rack (>= 0) and rack (= 1.0).")
+ end
+
+ it "when different versions of both dependencies are specified" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "rack", "1.0"
+ gem "rack", "1.1"
+ G
+
+ expect(out).to include("You cannot specify the same gem twice with different version requirements")
+ expect(out).to include("You specified: rack (= 1.0) and rack (= 1.1).")
+ end
+ end
+
it "gracefully handles error when rubygems server is unavailable" do
install_gemfile <<-G, :artifice => nil
source "file://#{gem_repo1}"
@@ -355,7 +405,7 @@ RSpec.describe "bundle install with gem sources" do
expect(last_command.stdboth).not_to match(/Error Report/i)
expect(last_command.bundler_err).to include("An error occurred while installing ajp-rails (0.0.0), and Bundler cannot continue.").
- and include("Make sure that `gem install ajp-rails -v '0.0.0' --source 'file://localhost#{gem_repo2}/'` succeeds before bundling.")
+ and include(normalize_uri_file("Make sure that `gem install ajp-rails -v '0.0.0' --source 'file://localhost#{gem_repo2}/'` succeeds before bundling."))
end
it "doesn't blow up when the local .bundle/config is empty" do
diff --git a/spec/commands/list_spec.rb b/spec/commands/list_spec.rb
index 4ebe934ca7..5305176c65 100644
--- a/spec/commands/list_spec.rb
+++ b/spec/commands/list_spec.rb
@@ -4,21 +4,72 @@ RSpec.describe "bundle list", :bundler => "2" do
before do
install_gemfile <<-G
source "file://#{gem_repo1}"
+
gem "rack"
+ gem "rspec", :group => [:test]
G
end
context "with name-only and paths option" do
it "raises an error" do
bundle "list --name-only --paths"
+
expect(out).to eq "The `--name-only` and `--paths` options cannot be used together"
end
end
+ context "with without-group and only-group option" do
+ it "raises an error" do
+ bundle "list --without-group dev --only-group test"
+
+ expect(out).to eq "The `--only-group` and `--without-group` options cannot be used together"
+ end
+ end
+
+ describe "with without-group option" do
+ context "when group is present" do
+ it "prints the gems not in the specified group" do
+ bundle! "list --without-group test"
+
+ expect(out).to include(" * rack (1.0.0)")
+ expect(out).not_to include(" * rspec (1.2.7)")
+ end
+ end
+
+ context "when group is not found" do
+ it "raises an error" do
+ bundle "list --without-group random"
+
+ expect(out).to eq "`random` group could not be found."
+ end
+ end
+ end
+
+ describe "with only-group option" do
+ context "when group is present" do
+ it "prints the gems in the specified group" do
+ bundle! "list --only-group default"
+
+ expect(out).to include(" * rack (1.0.0)")
+ expect(out).not_to include(" * rspec (1.2.7)")
+ end
+ end
+
+ context "when group is not found" do
+ it "raises an error" do
+ bundle "list --only-group random"
+
+ expect(out).to eq "`random` group could not be found."
+ end
+ end
+ end
+
context "with name-only option" do
it "prints only the name of the gems in the bundle" do
bundle "list --name-only"
- expect(out).to eq "rack"
+
+ expect(out).to include("rack")
+ expect(out).to include("rspec")
end
end
diff --git a/spec/commands/lock_spec.rb b/spec/commands/lock_spec.rb
index 81eba1ceda..f4997b0620 100644
--- a/spec/commands/lock_spec.rb
+++ b/spec/commands/lock_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe "bundle lock" do
gem "foo"
G
- @lockfile = strip_lockfile <<-L
+ @lockfile = strip_lockfile(normalize_uri_file(<<-L))
GEM
remote: file://localhost#{repo}/
specs:
@@ -257,7 +257,7 @@ RSpec.describe "bundle lock" do
simulate_platform(mingw) { bundle! :lock }
- expect(the_bundle.lockfile).to read_as(strip_whitespace(<<-G))
+ expect(the_bundle.lockfile).to read_as(normalize_uri_file(strip_whitespace(<<-G)))
GEM
remote: file://localhost#{gem_repo4}/
specs:
@@ -282,7 +282,7 @@ RSpec.describe "bundle lock" do
simulate_platform(rb) { bundle! :lock }
- expect(the_bundle.lockfile).to read_as(strip_whitespace(<<-G))
+ expect(the_bundle.lockfile).to read_as(normalize_uri_file(strip_whitespace(<<-G)))
GEM
remote: file://localhost#{gem_repo4}/
specs:
diff --git a/spec/commands/outdated_spec.rb b/spec/commands/outdated_spec.rb
index 877e648f5d..394db664d8 100644
--- a/spec/commands/outdated_spec.rb
+++ b/spec/commands/outdated_spec.rb
@@ -764,4 +764,31 @@ RSpec.describe "bundle outdated" do
end
end
end
+
+ describe "with --only-explicit" do
+ it "does not report outdated dependent gems" do
+ build_repo4 do
+ build_gem "weakling", %w[0.2 0.3] do |s|
+ s.add_dependency "bar", "~> 2.1"
+ end
+ build_gem "bar", %w[2.1 2.2]
+ end
+
+ install_gemfile <<-G
+ source "file://#{gem_repo4}"
+ gem 'weakling', '0.2'
+ gem 'bar', '2.1'
+ G
+
+ gemfile <<-G
+ source "file://#{gem_repo4}"
+ gem 'weakling'
+ G
+
+ bundle "outdated --only-explicit"
+
+ expect(out).to include("weakling (newest 0.3")
+ expect(out).not_to include("bar (newest 2.2")
+ end
+ end
end
diff --git a/spec/commands/remove_spec.rb b/spec/commands/remove_spec.rb
new file mode 100644
index 0000000000..37594b1ece
--- /dev/null
+++ b/spec/commands/remove_spec.rb
@@ -0,0 +1,571 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle remove" do
+ context "when no gems are specified" do
+ it "throws error" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ G
+
+ bundle "remove"
+
+ expect(out).to include("Please specify gems to remove.")
+ end
+ end
+
+ context "when --install flag is specified" do
+ it "removes gems from .bundle" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+
+ bundle! "remove rack --install"
+
+ expect(out).to include("rack was removed.")
+ expect(the_bundle).to_not include_gems "rack"
+ 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 "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+
+ bundle! "remove rack"
+
+ expect(out).to include("rack was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ G
+ 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 "file://#{gem_repo1}"
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
+ end
+ end
+ end
+
+ describe "remove mutiple gems from gemfile" do
+ context "when all gems are present in gemfile" do
+ it "shows success fir all removed gems" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ gem "rails"
+ G
+
+ bundle! "remove rack rails"
+
+ expect(out).to include("rack was removed.")
+ expect(out).to include("rails was removed.")
+ gemfile_should_be <<-G
+ source "file://#{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 "file://#{gem_repo1}"
+
+ gem "rails"
+ gem "minitest"
+ gem "rspec"
+ G
+
+ bundle "remove rails rack minitest"
+
+ expect(out).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
+ gemfile_should_be <<-G
+ source "file://#{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 "file://#{gem_repo1}"
+
+ gem "rack", :group => [:dev]
+ G
+
+ bundle! "remove rack"
+
+ expect(out).to include("rack was removed.")
+ gemfile_should_be <<-G
+ source "file://#{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 "file://#{gem_repo1}"
+
+ group :test do
+ gem "rspec"
+ end
+ G
+
+ bundle! "remove rspec"
+
+ expect(out).to include("rspec was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ G
+ end
+ end
+
+ context "when an empty block is also present" do
+ it "removes all empty blocks" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ group :test do
+ gem "rspec"
+ end
+
+ group :dev do
+ end
+ G
+
+ bundle! "remove rspec"
+
+ expect(out).to include("rspec was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ G
+ end
+ end
+
+ context "when the gem belongs to mutiple groups" do
+ it "removes the groups" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ group :test, :serioustest do
+ gem "rspec"
+ end
+ G
+
+ bundle! "remove rspec"
+
+ expect(out).to include("rspec was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ G
+ end
+ end
+
+ context "when the gem is present in mutiple groups" do
+ it "removes all empty blocks" do
+ gemfile <<-G
+ source "file://#{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.")
+ gemfile_should_be <<-G
+ source "file://#{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 "file://#{gem_repo1}"
+
+ group :test do
+ group :serioustest do
+ gem "rspec"
+ end
+ end
+ G
+
+ bundle! "remove rspec"
+
+ expect(out).to include("rspec was removed.")
+ gemfile_should_be <<-G
+ source "file://#{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 "file://#{gem_repo1}"
+
+ group :test do
+ gem "rack-test"
+
+ group :serioustest do
+ gem "rspec"
+ end
+ end
+ G
+
+ bundle! "remove rspec"
+
+ expect(out).to include("rspec was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+
+ group :test do
+ gem "rack-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 "file://#{gem_repo1}"
+
+ group :test do
+ group :serioustest do
+ gem "rspec"
+ gem "rack-test"
+ end
+ end
+ G
+
+ bundle! "remove rspec"
+
+ expect(out).to include("rspec was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+
+ group :test do
+ group :serioustest do
+ gem "rack-test"
+ end
+ end
+ G
+ end
+ end
+ end
+
+ describe "arbitrary gemfile" do
+ context "when mutiple gems are present in same line" do
+ it "shows warning for gems not removed" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"; gem "rails"
+ G
+
+ bundle "remove rails"
+
+ expect(out).to include("Gems could not be removed. rack (>= 0) would also have been removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"; 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
+ source "file://#{gem_repo1}"
+ gem"rack"
+ gem"rspec"
+ gem "rails"
+ gem "minitest"
+ G
+
+ bundle! "remove rails rack rspec minitest"
+
+ expect(out).to include("rails was removed.")
+ expect(out).to include("minitest was removed.")
+ expect(out).to include("rack, rspec could not be removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ gem"rack"
+ gem"rspec"
+ G
+ end
+ end
+ end
+
+ context "with sources" do
+ before do
+ build_repo gem_repo3 do
+ build_gem "rspec"
+ end
+ end
+
+ it "removes gems and empty source blocks" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+
+ source "file://#{gem_repo3}" do
+ gem "rspec"
+ end
+ G
+
+ bundle! "install"
+
+ bundle! "remove rspec"
+
+ expect(out).to include("rspec was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+ end
+ end
+
+ describe "with eval_gemfile" do
+ context "when gems are present in both gemfiles" do
+ it "removes the gems" do
+ create_file "Gemfile-other", <<-G
+ gem "rack"
+ G
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+
+ gem "rack"
+ G
+
+ bundle! "remove rack"
+
+ expect(out).to include("rack was removed.")
+ end
+ end
+
+ context "when gems are present in other gemfile" do
+ it "removes the gems" do
+ create_file "Gemfile-other", <<-G
+ gem "rack"
+ G
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ G
+
+ bundle! "remove rack"
+
+ expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
+ expect(out).to include("rack 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 "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("`rack` 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
+ create_file "Gemfile-other", <<-G
+ gem "rails"
+ G
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ gem "rack"
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("rack was removed.")
+ expect(out).to include("`rack` is not specified in #{bundled_app("Gemfile-other")} so it could not be removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ G
+ end
+ end
+
+ context "when gems can not be removed from other gemfile" do
+ it "shows error" do
+ create_file "Gemfile-other", <<-G
+ gem "rails"; gem "rack"
+ G
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ gem "rack"
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("rack was removed.")
+ expect(out).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ G
+ end
+ end
+
+ context "when gems could not be removed from parent gemfile" do
+ it "shows error" do
+ create_file "Gemfile-other", <<-G
+ gem "rack"
+ G
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ gem "rails"; gem "rack"
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
+ expect(bundled_app("Gemfile-other").read).to include("gem \"rack\"")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ gem "rails"; gem "rack"
+ 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 can not be removed" do
+ create_file "Gemfile-other", <<-G
+ gem "rack"
+ G
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ eval_gemfile "Gemfile-other"
+ gem"rack"
+ G
+
+ bundle! "remove rack"
+
+ expect(out).to include("rack was removed.")
+ expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
+ end
+ end
+ end
+
+ context "with install_if" do
+ it "removes gems inside blocks and empty blocks" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ install_if(lambda { false }) do
+ gem "rack"
+ end
+ G
+
+ bundle! "remove rack"
+
+ expect(out).to include("rack was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ G
+ end
+ end
+
+ context "with env" do
+ it "removes gems inside blocks and empty blocks" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ env "BUNDLER_TEST" do
+ gem "rack"
+ end
+ G
+
+ bundle! "remove rack"
+
+ expect(out).to include("rack was removed.")
+ gemfile_should_be <<-G
+ source "file://#{gem_repo1}"
+ G
+ end
+ end
+
+ context "with gemspec" do
+ it "should not remove the gem" do
+ build_lib("foo", :path => tmp.join("foo")) do |s|
+ s.write("foo.gemspec", "")
+ s.add_dependency "rack"
+ end
+
+ install_gemfile(<<-G)
+ source "file://#{gem_repo1}"
+ gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ G
+
+ bundle! "remove foo"
+
+ expect(out).to include("foo could not be removed.")
+ end
+ end
+end
diff --git a/spec/commands/update_spec.rb b/spec/commands/update_spec.rb
index af09c145c1..b06eaa47e2 100644
--- a/spec/commands/update_spec.rb
+++ b/spec/commands/update_spec.rb
@@ -189,6 +189,23 @@ RSpec.describe "bundle update" do
expect(the_bundle).not_to include_gems "rack 1.2"
end
+ context "when conservatively updating a group with non-group sub-deps" do
+ it "should update only specified group gems" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "activemerchant", :group => :development
+ gem "activesupport"
+ G
+ update_repo2 do
+ build_gem "activemerchant", "2.0"
+ build_gem "activesupport", "3.0"
+ end
+ bundle "update --conservative --group development"
+ expect(the_bundle).to include_gems "activemerchant 2.0"
+ expect(the_bundle).not_to include_gems "activesupport 3.0"
+ end
+ end
+
context "when there is a source with the same name as a gem in a group" do
before :each do
build_git "foo", :path => lib_path("activesupport")
diff --git a/spec/install/failure_spec.rb b/spec/install/failure_spec.rb
index 27abe9fcc3..49e2771dca 100644
--- a/spec/install/failure_spec.rb
+++ b/spec/install/failure_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "bundle install" do
source "file:\/\/localhost#{gem_repo2}"
gem "rails"
G
- expect(last_command.bundler_err).to end_with(<<-M.strip)
+ expect(last_command.bundler_err).to end_with(normalize_uri_file(<<-M.strip))
An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
Make sure that `gem install activesupport -v '2.3.2' --source 'file://localhost#{gem_repo2}/'` succeeds before bundling.
@@ -29,6 +29,66 @@ In Gemfile:
M
end
+ context "when installing a git gem" do
+ it "does not tell the user to run 'gem install'" do
+ build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ abort "make installing activesupport-2.3.2 fail"
+ end
+ RUBY
+ end
+
+ install_gemfile <<-G
+ source "file:\/\/localhost#{gem_repo1}"
+ gem "rails"
+ gem "activesupport", :git => "#{lib_path("activesupport")}"
+ G
+
+ expect(last_command.bundler_err).to end_with(<<-M.strip)
+An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
+
+In Gemfile:
+ rails was resolved to 2.3.2, which depends on
+ actionmailer was resolved to 2.3.2, which depends on
+ activesupport
+ M
+ end
+ end
+
+ context "when installing a gem using a git block" do
+ it "does not tell the user to run 'gem install'" do
+ build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ abort "make installing activesupport-2.3.2 fail"
+ end
+ RUBY
+ end
+
+ install_gemfile <<-G
+ source "file:\/\/localhost#{gem_repo1}"
+ gem "rails"
+
+ git "#{lib_path("activesupport")}" do
+ gem "activesupport"
+ end
+ G
+
+ expect(last_command.bundler_err).to end_with(<<-M.strip)
+An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
+
+
+In Gemfile:
+ rails was resolved to 2.3.2, which depends on
+ actionmailer was resolved to 2.3.2, which depends on
+ activesupport
+ M
+ end
+ end
+
it "prints out the hint for the remote source when available" do
build_repo2 do
build_gem "activesupport", "2.3.2" do |s|
@@ -51,7 +111,7 @@ In Gemfile:
gem "rails"
end
G
- expect(last_command.bundler_err).to end_with(<<-M.strip)
+ expect(last_command.bundler_err).to end_with(normalize_uri_file(<<-M.strip))
An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
Make sure that `gem install activesupport -v '2.3.2' --source 'file://localhost#{gem_repo2}/'` succeeds before bundling.
diff --git a/spec/install/gemfile/gemspec_spec.rb b/spec/install/gemfile/gemspec_spec.rb
index 86cd2d8f3f..7ce037730e 100644
--- a/spec/install/gemfile/gemspec_spec.rb
+++ b/spec/install/gemfile/gemspec_spec.rb
@@ -442,7 +442,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "as a runtime dependency" do
it "keeps java 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)
+ expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
PATH
remote: .
specs:
@@ -473,7 +473,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "keeps java 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)
+ expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
PATH
remote: .
specs:
@@ -505,7 +505,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "keeps java 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)
+ expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
PATH
remote: .
specs:
@@ -543,7 +543,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "as a runtime dependency" do
it "keeps java 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)
+ expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
GEM
remote: file://localhost#{gem_repo2}/
specs:
@@ -574,7 +574,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "keeps java 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)
+ expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
GEM
remote: file://localhost#{gem_repo2}/
specs:
@@ -606,7 +606,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "keeps java 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)
+ expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
GEM
remote: file://localhost#{gem_repo2}/
specs:
diff --git a/spec/install/gemfile/sources_spec.rb b/spec/install/gemfile/sources_spec.rb
index 2cadc61161..384deca7c2 100644
--- a/spec/install/gemfile/sources_spec.rb
+++ b/spec/install/gemfile/sources_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(out).to have_major_deprecation a_string_including("Your Gemfile contains multiple primary sources.")
expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(out).to include("Installed from: file://localhost#{gem_repo1}")
+ expect(out).to include(normalize_uri_file("Installed from: file://localhost#{gem_repo1}"))
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
end
@@ -63,7 +63,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(out).to have_major_deprecation a_string_including("Your Gemfile contains multiple primary sources.")
expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(out).to include("Installed from: file://localhost#{gem_repo1}")
+ expect(out).to include(normalize_uri_file("Installed from: file://localhost#{gem_repo1}"))
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
end
end
@@ -253,7 +253,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
bundle :install
expect(out).to have_major_deprecation a_string_including("Your Gemfile contains multiple primary sources.")
expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(out).to include("Installed from: file://localhost#{gem_repo2}")
+ expect(out).to include(normalize_uri_file("Installed from: file://localhost#{gem_repo2}"))
expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
end
end
@@ -634,7 +634,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
gem "depends_on_rack"
G
expect(last_command).to be_failure
- expect(last_command.stderr).to eq strip_whitespace(<<-EOS).strip
+ expect(last_command.stderr).to eq normalize_uri_file(strip_whitespace(<<-EOS).strip)
The gem 'rack' was found in multiple relevant sources.
* rubygems repository file://localhost#{gem_repo1}/ or installed locally
* rubygems repository file://localhost#{gem_repo4}/ or installed locally
diff --git a/spec/install/gems/mirror_spec.rb b/spec/install/gems/mirror_spec.rb
index 89302615f1..4c35b8f206 100644
--- a/spec/install/gems/mirror_spec.rb
+++ b/spec/install/gems/mirror_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe "bundle install with a mirror configured" do
it "installs from the normal location" do
bundle :install
- expect(out).to include("Fetching source index from file://localhost#{gem_repo1}")
+ expect(out).to include(normalize_uri_file("Fetching source index from file://localhost#{gem_repo1}"))
expect(the_bundle).to include_gems "rack 1.0"
end
end
@@ -31,8 +31,8 @@ RSpec.describe "bundle install with a mirror configured" do
it "installs the gem from the mirror" do
bundle :install
- expect(out).to include("Fetching source index from file://localhost#{gem_repo1}")
- expect(out).not_to include("Fetching source index from file://localhost#{gem_repo2}")
+ expect(out).to include(normalize_uri_file("Fetching source index from file://localhost#{gem_repo1}"))
+ expect(out).not_to include(normalize_uri_file("Fetching source index from file://localhost#{gem_repo2}"))
expect(the_bundle).to include_gems "rack 1.0"
end
end
diff --git a/spec/install/gemspecs_spec.rb b/spec/install/gemspecs_spec.rb
index 5dca6f68c0..35f96367f7 100644
--- a/spec/install/gemspecs_spec.rb
+++ b/spec/install/gemspecs_spec.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
# frozen_string_literal: true
RSpec.describe "bundle install" do
@@ -63,6 +64,33 @@ RSpec.describe "bundle install" do
expect(out).to include("Bundle complete!")
end
+ it "reads gemspecs respecting their encoding" do
+ skip "Unicode is not supported on Ruby 1.x without extra work" if RUBY_VERSION < "2.0"
+
+ create_file "version.rb", <<-RUBY
+ module Persistent💎
+ VERSION = "0.0.1"
+ end
+ RUBY
+
+ create_file "persistent-dmnd.gemspec", <<-G
+ require_relative "version"
+
+ Gem::Specification.new do |gem|
+ gem.name = "persistent-dmnd"
+ gem.version = Persistent💎::VERSION
+ gem.author = "Ivo Anjo"
+ gem.summary = "Unscratchable stuff"
+ end
+ G
+
+ install_gemfile <<-G
+ gemspec
+ G
+
+ expect(out).to include("Bundle complete!")
+ 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|
diff --git a/spec/install/post_bundle_message_spec.rb b/spec/install/post_bundle_message_spec.rb
index 53a93845c2..eadc8a4d85 100644
--- a/spec/install/post_bundle_message_spec.rb
+++ b/spec/install/post_bundle_message_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe "post bundle message" do
gem "rack"
gem "not-a-gem", :group => :development
G
- expect(out).to include <<-EOS.strip
+ expect(out).to include normalize_uri_file(<<-EOS.strip)
Could not find gem 'not-a-gem' in rubygems repository file://localhost#{gem_repo1}/ or installed locally.
The source does not contain any versions of 'not-a-gem'
EOS
diff --git a/spec/install/process_lock_spec.rb b/spec/install/process_lock_spec.rb
index 02217f493b..be8fd04fdd 100644
--- a/spec/install/process_lock_spec.rb
+++ b/spec/install/process_lock_spec.rb
@@ -20,5 +20,16 @@ RSpec.describe "process lock spec" do
thread.join
expect(the_bundle).to include_gems "rack 1.0"
end
+
+ context "when creating a lock raises Errno::ENOTSUP", :ruby => ">= 1.9" do
+ before { allow(File).to receive(:open).and_raise(Errno::ENOTSUP) }
+
+ 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/lock/lockfile_bundler_1_spec.rb b/spec/lock/lockfile_bundler_1_spec.rb
index 233e3f63c4..a8615d4c89 100644
--- a/spec/lock/lockfile_bundler_1_spec.rb
+++ b/spec/lock/lockfile_bundler_1_spec.rb
@@ -1240,7 +1240,7 @@ RSpec.describe "the lockfile format", :bundler => "< 2" do
expect(the_bundle).to include_gems "omg 1.0"
# Confirm that duplicate specs do not appear
- expect(File.read(bundled_app("Gemfile.lock"))).to eq(strip_whitespace(<<-L))
+ lockfile_should_be(<<-L)
GIT
remote: #{lib_path("omg")}
revision: #{revision}
diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb
index 5be77de7ef..53c832445f 100644
--- a/spec/lock/lockfile_spec.rb
+++ b/spec/lock/lockfile_spec.rb
@@ -1279,7 +1279,7 @@ RSpec.describe "the lockfile format", :bundler => "2" do
expect(the_bundle).to include_gems "omg 1.0"
# Confirm that duplicate specs do not appear
- expect(File.read(bundled_app("Gemfile.lock"))).to eq(strip_whitespace(<<-L))
+ lockfile_should_be(<<-L)
GEM
remote: file://localhost#{gem_repo1}/
specs:
diff --git a/spec/plugins/hook_spec.rb b/spec/plugins/hook_spec.rb
index 8bdf61a8ab..53062095e2 100644
--- a/spec/plugins/hook_spec.rb
+++ b/spec/plugins/hook_spec.rb
@@ -1,27 +1,109 @@
# frozen_string_literal: true
RSpec.describe "hook plugins" do
- before do
- build_repo2 do
- build_plugin "before-install-plugin" do |s|
- s.write "plugins.rb", <<-RUBY
- Bundler::Plugin::API.hook "before-install-all" do |deps|
- puts "gems to be installed \#{deps.map(&:name).join(", ")}"
- end
- RUBY
+ context "before-install-all hook" do
+ before do
+ build_repo2 do
+ build_plugin "before-install-all-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_BEFORE_INSTALL_ALL do |deps|
+ puts "gems to be installed \#{deps.map(&:name).join(", ")}"
+ end
+ RUBY
+ end
end
+
+ bundle "plugin install before-install-all-plugin --source file://#{gem_repo2}"
+ end
+
+ it "runs before all rubygems are installed" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rake"
+ gem "rack"
+ G
+
+ expect(out).to include "gems to be installed rake, rack"
+ end
+ end
+
+ context "before-install hook" do
+ before do
+ build_repo2 do
+ build_plugin "before-install-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_BEFORE_INSTALL do |spec_install|
+ puts "installing gem \#{spec_install.name}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install before-install-plugin --source file://#{gem_repo2}"
+ end
+
+ it "runs before each rubygem is installed" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rake"
+ gem "rack"
+ G
+
+ expect(out).to include "installing gem rake"
+ expect(out).to include "installing gem rack"
end
+ end
+
+ context "after-install-all hook" do
+ before do
+ build_repo2 do
+ build_plugin "after-install-all-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_AFTER_INSTALL_ALL do |deps|
+ puts "installed gems \#{deps.map(&:name).join(", ")}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install after-install-all-plugin --source file://#{gem_repo2}"
+ end
+
+ it "runs after each rubygem is installed" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rake"
+ gem "rack"
+ G
- bundle "plugin install before-install-plugin --source file://#{gem_repo2}"
+ expect(out).to include "installed gems rake, rack"
+ end
end
- it "runs after a rubygem is installed" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rake"
- gem "rack"
- G
+ context "after-install hook" do
+ before do
+ build_repo2 do
+ build_plugin "after-install-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_AFTER_INSTALL do |spec_install|
+ puts "installed gem \#{spec_install.name} : \#{spec_install.state}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install after-install-plugin --source file://#{gem_repo2}"
+ end
+
+ it "runs after each rubygem is installed" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rake"
+ gem "rack"
+ G
- expect(out).to include "gems to be installed rake, rack"
+ expect(out).to include "installed gem rake : installed"
+ expect(out).to include "installed gem rack : installed"
+ end
end
end
diff --git a/spec/resolver/basic_spec.rb b/spec/resolver/basic_spec.rb
index c829243a9f..6d2dea2fb3 100644
--- a/spec/resolver/basic_spec.rb
+++ b/spec/resolver/basic_spec.rb
@@ -80,6 +80,13 @@ RSpec.describe "Resolving" do
should_resolve_as %w[need-pre-1.0.0 activesupport-3.0.0.beta1]
end
+ it "selects a pre-release if it's specified in the Gemfile" do
+ dep "activesupport", "= 3.0.0.beta"
+ dep "actionpack"
+
+ should_resolve_as %w[activesupport-3.0.0.beta actionpack-3.0.0.beta rack-1.1 rack-mount-0.6]
+ end
+
it "raises an exception if a child dependency is not resolved" do
@index = a_unresovable_child_index
dep "chef_app_error"
diff --git a/spec/runtime/setup_spec.rb b/spec/runtime/setup_spec.rb
index e84cdaabf5..cd87971238 100644
--- a/spec/runtime/setup_spec.rb
+++ b/spec/runtime/setup_spec.rb
@@ -857,6 +857,50 @@ end
expect(out).to eq("true\ntrue")
end
+ context "with bundler is located in symlinked GEM_HOME" do
+ let(:gem_home) { Dir.mktmpdir }
+ let(:symlinked_gem_home) { Tempfile.new("gem_home") }
+ let(:bundler_dir) { File.expand_path("../../..", __FILE__) }
+ let(:bundler_lib) { File.join(bundler_dir, "lib") }
+
+ before do
+ FileUtils.ln_sf(gem_home, symlinked_gem_home.path)
+ gems_dir = File.join(gem_home, "gems")
+ specifications_dir = File.join(gem_home, "specifications")
+ Dir.mkdir(gems_dir)
+ Dir.mkdir(specifications_dir)
+
+ FileUtils.ln_s(bundler_dir, File.join(gems_dir, "bundler-#{Bundler::VERSION}"))
+
+ gemspec = File.read("#{bundler_dir}/bundler.gemspec").
+ sub("Bundler::VERSION", %("#{Bundler::VERSION}"))
+ gemspec = gemspec.lines.reject {|line| line =~ %r{lib/bundler/version} }.join
+
+ File.open(File.join(specifications_dir, "bundler.gemspec"), "wb") do |f|
+ f.write(gemspec)
+ end
+ end
+
+ it "should succesfully require 'bundler/setup'" do
+ install_gemfile ""
+
+ ENV["GEM_PATH"] = symlinked_gem_home.path
+
+ ruby <<-R
+ if $LOAD_PATH.include?("#{bundler_lib}")
+ # We should use bundler from GEM_PATH for this test, so we should
+ # remove path to the bundler source tree
+ $LOAD_PATH.delete("#{bundler_lib}")
+ else
+ raise "We don't have #{bundler_lib} in $LOAD_PATH"
+ end
+ puts (require 'bundler/setup')
+ R
+
+ expect(out).to eql("true")
+ end
+ end
+
it "stubs out Gem.refresh so it does not reveal system gems" do
system_gems "rack-1.0.0"
@@ -1166,7 +1210,7 @@ end
#{Bundler::VERSION}
L
- lock
+ normalize_uri_file(lock)
end
before do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 228b9e5aa3..56094b72f5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -28,6 +28,18 @@ require "bundler/vendored_fileutils"
require "uri"
require "digest"
+# Delete the default copy of Bundler that RVM installs for us when running in CI
+require "fileutils"
+if ENV.select {|k, _v| k =~ /TRAVIS/ }.any? && Gem::Version.new(Gem::VERSION) > Gem::Version.new("2.0")
+ Dir.glob(File.join(Gem::Specification.default_specifications_dir, "bundler*.gemspec")).each do |file|
+ FileUtils.rm_rf(file)
+ end
+
+ Dir.glob(File.join(RbConfig::CONFIG["sitelibdir"], "bundler*")).each do |file|
+ FileUtils.rm_rf(file)
+ end
+end
+
if File.expand_path(__FILE__) =~ %r{([^\w/\.-])}
abort "The bundler specs cannot be run from a path that contains special characters (particularly #{$1.inspect})"
end
diff --git a/spec/support/builders.rb b/spec/support/builders.rb
index e496df6ecb..fa32b12b65 100644
--- a/spec/support/builders.rb
+++ b/spec/support/builders.rb
@@ -601,7 +601,7 @@ module Spec
@spec.rubygems_version = options[:rubygems_version]
def @spec.mark_version; end
- def @spec.validate; end
+ def @spec.validate(*); end
end
case options[:gemspec]
diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb
index 1b52ed5258..e2b96f5d21 100644
--- a/spec/support/helpers.rb
+++ b/spec/support/helpers.rb
@@ -280,6 +280,15 @@ module Spec
str.gsub(/^#{spaces}/, "")
end
+ def normalize_uri_file(str)
+ # URI::File of Ruby 2.6 normalize localhost variable with file protocol.
+ if defined?(URI::File)
+ str.gsub(%r{file:\/\/localhost}, "file://")
+ else
+ str
+ end
+ end
+
def install_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
@@ -310,7 +319,11 @@ module Spec
raise "OMG `#{path}` does not exist!" unless File.exist?(path)
- gem_command! :install, "--no-rdoc --no-ri --ignore-dependencies '#{path}'"
+ if Gem::VERSION < "2.0.0"
+ gem_command! :install, "--no-rdoc --no-ri --ignore-dependencies '#{path}'"
+ else
+ gem_command! :install, "--no-document --ignore-dependencies '#{path}'"
+ end
bundler_path && bundler_path.rmtree
end
end
diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb
index 782257a222..8e17be3a02 100644
--- a/spec/support/matchers.rb
+++ b/spec/support/matchers.rb
@@ -236,7 +236,11 @@ module Spec
end
def lockfile_should_be(expected)
- expect(bundled_app("Gemfile.lock")).to read_as(strip_whitespace(expected))
+ expect(bundled_app("Gemfile.lock")).to read_as(normalize_uri_file(strip_whitespace(expected)))
+ end
+
+ def gemfile_should_be(expected)
+ expect(bundled_app("Gemfile")).to read_as(strip_whitespace(expected))
end
end
end
diff --git a/spec/support/rubygems_ext.rb b/spec/support/rubygems_ext.rb
index 3627e5a71d..806933fe2f 100644
--- a/spec/support/rubygems_ext.rb
+++ b/spec/support/rubygems_ext.rb
@@ -59,7 +59,11 @@ module Spec
no_reqs.map!(&:first)
reqs.map! {|name, req| "'#{name}:#{req}'" }
deps = reqs.concat(no_reqs).join(" ")
- cmd = "gem install #{deps} --no-rdoc --no-ri --conservative"
+ cmd = if Gem::VERSION < "2.0.0"
+ "gem install #{deps} --no-rdoc --no-ri --conservative"
+ else
+ "gem install #{deps} --no-document --conservative"
+ end
puts cmd
system(cmd) || raise("Installing gems #{deps} for the tests to use failed!")
end