aboutsummaryrefslogtreecommitdiffstats
path: root/spec/bundler/commands/install_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/bundler/commands/install_spec.rb')
-rw-r--r--spec/bundler/commands/install_spec.rb513
1 files changed, 513 insertions, 0 deletions
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb
new file mode 100644
index 0000000000..2d67a39f1e
--- /dev/null
+++ b/spec/bundler/commands/install_spec.rb
@@ -0,0 +1,513 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe "bundle install with gem sources" do
+ describe "the simple case" do
+ it "prints output and returns if no dependencies are specified" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ G
+
+ bundle :install
+ expect(out).to match(/no dependencies/)
+ end
+
+ it "does not make a lockfile if the install fails" do
+ install_gemfile <<-G
+ raise StandardError, "FAIL"
+ G
+
+ expect(err).to lack_errors
+ expect(out).to match(/StandardError, "FAIL"/)
+ expect(bundled_app("Gemfile.lock")).not_to exist
+ end
+
+ it "creates a Gemfile.lock" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ expect(bundled_app("Gemfile.lock")).to exist
+ end
+
+ it "does not create ./.bundle by default" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ bundle :install # can't use install_gemfile since it sets retry
+ expect(bundled_app(".bundle")).not_to exist
+ end
+
+ it "creates lock files based on the Gemfile name" do
+ gemfile bundled_app("OmgFile"), <<-G
+ source "file://#{gem_repo1}"
+ gem "rack", "1.0"
+ G
+
+ bundle "install --gemfile OmgFile"
+
+ expect(bundled_app("OmgFile.lock")).to exist
+ end
+
+ it "doesn't delete the lockfile if one already exists" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack'
+ G
+
+ lockfile = File.read(bundled_app("Gemfile.lock"))
+
+ install_gemfile <<-G
+ raise StandardError, "FAIL"
+ G
+
+ expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile)
+ end
+
+ it "does not touch the lockfile if nothing changed" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ expect { run "1" }.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
+ end
+
+ it "fetches gems" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack'
+ G
+
+ expect(default_bundle_path("gems/rack-1.0.0")).to exist
+ expect(the_bundle).to include_gems("rack 1.0.0")
+ end
+
+ it "fetches gems when multiple versions are specified" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack', "> 0.9", "< 1.0"
+ G
+
+ expect(default_bundle_path("gems/rack-0.9.1")).to exist
+ expect(the_bundle).to include_gems("rack 0.9.1")
+ end
+
+ it "fetches gems when multiple versions are specified take 2" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack', "< 1.0", "> 0.9"
+ G
+
+ expect(default_bundle_path("gems/rack-0.9.1")).to exist
+ expect(the_bundle).to include_gems("rack 0.9.1")
+ end
+
+ it "raises an appropriate error when gems are specified using symbols" do
+ install_gemfile(<<-G)
+ source "file://#{gem_repo1}"
+ gem :rack
+ G
+ expect(exitstatus).to eq(4) if exitstatus
+ end
+
+ it "pulls in dependencies" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rails"
+ G
+
+ expect(the_bundle).to include_gems "actionpack 2.3.2", "rails 2.3.2"
+ end
+
+ it "does the right version" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack", "0.9.1"
+ G
+
+ expect(the_bundle).to include_gems "rack 0.9.1"
+ end
+
+ it "does not install the development dependency" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "with_development_dependency"
+ G
+
+ expect(the_bundle).to include_gems("with_development_dependency 1.0.0").
+ and not_include_gems("activesupport 2.3.5")
+ end
+
+ it "resolves correctly" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "activemerchant"
+ gem "rails"
+ G
+
+ expect(the_bundle).to include_gems "activemerchant 1.0", "activesupport 2.3.2", "actionpack 2.3.2"
+ end
+
+ it "activates gem correctly according to the resolved gems" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "activesupport", "2.3.5"
+ G
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "activemerchant"
+ gem "rails"
+ G
+
+ expect(the_bundle).to include_gems "activemerchant 1.0", "activesupport 2.3.2", "actionpack 2.3.2"
+ end
+
+ it "does not reinstall any gem that is already available locally" do
+ system_gems "activesupport-2.3.2"
+
+ build_repo2 do
+ build_gem "activesupport", "2.3.2" do |s|
+ s.write "lib/activesupport.rb", "ACTIVESUPPORT = 'fail'"
+ end
+ end
+
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+ gem "activerecord", "2.3.2"
+ G
+
+ expect(the_bundle).to include_gems "activesupport 2.3.2"
+ end
+
+ it "works when the gemfile specifies gems that only exist in the system" do
+ build_gem "foo", :to_system => true
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ gem "foo"
+ G
+
+ expect(the_bundle).to include_gems "rack 1.0.0", "foo 1.0.0"
+ end
+
+ it "prioritizes local gems over remote gems" do
+ build_gem "rack", "1.0.0", :to_system => true do |s|
+ s.add_dependency "activesupport", "2.3.5"
+ end
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ end
+
+ describe "with a gem that installs multiple platforms" do
+ it "installs gems for the local platform as first choice" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "platform_specific"
+ G
+
+ run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
+ expect(out).to eq("1.0.0 #{Bundler.local_platform}")
+ end
+
+ it "falls back on plain ruby" do
+ simulate_platform "foo-bar-baz"
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "platform_specific"
+ G
+
+ run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
+ expect(out).to eq("1.0.0 RUBY")
+ end
+
+ it "installs gems for java" do
+ simulate_platform "java"
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "platform_specific"
+ G
+
+ run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
+ expect(out).to eq("1.0.0 JAVA")
+ end
+
+ it "installs gems for windows" do
+ simulate_platform mswin
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "platform_specific"
+ G
+
+ run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
+ expect(out).to eq("1.0.0 MSWIN")
+ end
+ end
+
+ describe "doing bundle install foo" do
+ before do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+ end
+
+ it "works" do
+ bundle "install --path vendor"
+ expect(the_bundle).to include_gems "rack 1.0"
+ end
+
+ it "allows running bundle install --system without deleting foo" do
+ bundle "install --path vendor"
+ bundle "install --system"
+ FileUtils.rm_rf(bundled_app("vendor"))
+ expect(the_bundle).to include_gems "rack 1.0"
+ end
+
+ it "allows running bundle install --system after deleting foo" do
+ bundle "install --path vendor"
+ FileUtils.rm_rf(bundled_app("vendor"))
+ bundle "install --system"
+ expect(the_bundle).to include_gems "rack 1.0"
+ end
+ end
+
+ it "finds gems in multiple sources" do
+ build_repo2
+ update_repo2
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ source "file://#{gem_repo2}"
+
+ gem "activesupport", "1.2.3"
+ gem "rack", "1.2"
+ G
+
+ expect(the_bundle).to include_gems "rack 1.2", "activesupport 1.2.3"
+ end
+
+ it "gives a useful error if no sources are set" do
+ install_gemfile <<-G
+ gem "rack"
+ G
+
+ bundle :install
+ expect(out).to include("Your Gemfile has no gem server sources")
+ end
+
+ it "creates a Gemfile.lock on a blank Gemfile" do
+ install_gemfile <<-G
+ G
+
+ expect(File.exist?(bundled_app("Gemfile.lock"))).to eq(true)
+ end
+
+ it "gracefully handles error when rubygems server is unavailable" do
+ install_gemfile <<-G, :artifice => nil
+ source "file://#{gem_repo1}"
+ source "http://localhost:9384"
+
+ gem 'foo'
+ G
+
+ bundle :install, :artifice => nil
+ expect(out).to include("Could not fetch specs from http://localhost:9384/")
+ expect(out).not_to include("file://")
+ end
+
+ it "fails gracefully when downloading an invalid specification from the full index", :rubygems => "2.5" do
+ build_repo2 do
+ build_gem "ajp-rails", "0.0.0", :gemspec => false, :skip_validation => true do |s|
+ bad_deps = [["ruby-ajp", ">= 0.2.0"], ["rails", ">= 0.14"]]
+ s.
+ instance_variable_get(:@spec).
+ instance_variable_set(:@dependencies, bad_deps)
+
+ raise "failed to set bad deps" unless s.dependencies == bad_deps
+ end
+ build_gem "ruby-ajp", "1.0.0"
+ end
+
+ install_gemfile <<-G, :full_index => true
+ source "file://#{gem_repo2}"
+
+ gem "ajp-rails", "0.0.0"
+ G
+
+ expect(out).not_to match(/Error Report/i)
+ expect(err).not_to match(/Error Report/i)
+ expect(out).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'` succeeds before bundling.")
+ end
+
+ it "doesn't blow up when the local .bundle/config is empty" do
+ FileUtils.mkdir_p(bundled_app(".bundle"))
+ FileUtils.touch(bundled_app(".bundle/config"))
+
+ install_gemfile(<<-G)
+ source "file://#{gem_repo1}"
+
+ gem 'foo'
+ G
+ expect(exitstatus).to eq(0) if exitstatus
+ end
+
+ it "doesn't blow up when the global .bundle/config is empty" do
+ FileUtils.mkdir_p("#{Bundler.rubygems.user_home}/.bundle")
+ FileUtils.touch("#{Bundler.rubygems.user_home}/.bundle/config")
+
+ install_gemfile(<<-G)
+ source "file://#{gem_repo1}"
+
+ gem 'foo'
+ G
+ expect(exitstatus).to eq(0) if exitstatus
+ end
+ end
+
+ describe "Ruby version in Gemfile.lock" do
+ include Bundler::GemHelpers
+
+ context "and using an unsupported Ruby version" do
+ it "prints an error" do
+ install_gemfile <<-G
+ ::RUBY_VERSION = '1.8.7'
+ ruby '~> 2.1'
+ G
+ expect(out).to include("Your Ruby version is 1.8.7, but your Gemfile specified ~> 2.1")
+ end
+ end
+
+ context "and using a supported Ruby version" do
+ before do
+ install_gemfile <<-G
+ ::RUBY_VERSION = '2.1.3'
+ ::RUBY_PATCHLEVEL = 100
+ ruby '~> 2.1.0'
+ G
+ end
+
+ it "writes current Ruby version to Gemfile.lock" do
+ lockfile_should_be <<-L
+ GEM
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ RUBY VERSION
+ ruby 2.1.3p100
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "updates Gemfile.lock with updated incompatible ruby version" do
+ install_gemfile <<-G
+ ::RUBY_VERSION = '2.2.3'
+ ::RUBY_PATCHLEVEL = 100
+ ruby '~> 2.2.0'
+ G
+
+ lockfile_should_be <<-L
+ GEM
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ RUBY VERSION
+ ruby 2.2.3p100
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+ end
+
+ describe "when Bundler root contains regex chars" do
+ before do
+ root_dir = tmp("foo[]bar")
+
+ FileUtils.mkdir_p(root_dir)
+ in_app_root_custom(root_dir)
+ end
+
+ it "doesn't blow up" do
+ build_lib "foo"
+ gemfile = <<-G
+ gem 'foo', :path => "#{lib_path("foo-1.0")}"
+ G
+ File.open("Gemfile", "w") do |file|
+ file.puts gemfile
+ end
+
+ bundle :install
+
+ expect(exitstatus).to eq(0) if exitstatus
+ end
+ end
+
+ describe "when requesting a quiet install via --quiet" do
+ it "should be quiet" do
+ gemfile <<-G
+ gem 'rack'
+ G
+
+ bundle :install, :quiet => true
+ expect(out).to include("Could not find gem 'rack'")
+ expect(out).to_not include("Your Gemfile has no gem server sources")
+ end
+ end
+
+ describe "when bundle path does not have write access" do
+ before do
+ FileUtils.mkdir_p(bundled_app("vendor"))
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod(0o500, bundled_app("vendor"))
+
+ bundle :install, :path => "vendor"
+ expect(out).to include(bundled_app("vendor").to_s)
+ expect(out).to include("grant write permissions")
+ end
+ end
+
+ describe "when bundle install is executed with unencoded authentication" do
+ before do
+ gemfile <<-G
+ source 'https://rubygems.org/'
+ gem 'bundler'
+ G
+ end
+
+ it "should display a helpful messag explaining how to fix it" do
+ bundle :install, :env => { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }
+ expect(exitstatus).to eq(17) if exitstatus
+ expect(out).to eq("Please CGI escape your usernames and passwords before " \
+ "setting them for authentication.")
+ end
+ end
+end