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/runtime/setup_spec.rb
David Rodríguez 5a384e2c08 Fix some bundler specs (#2380)
* These seem to consistenly pass already

* Show actual command when running `make test-bundler`

Current the setup command that installs the necessary gems for testing
bundler was printed, but not the actual command that runs the tests.
That was a bit confusing.

* Borrow trick from setproctitle specs

* A title that long doesn't get set sometimes

No idea why, but the test doesn't need that the title is that long.

* Fix most gem helper spec ruby-core failures

* Fix the rest of the gem helper failures

* Fix version spec by improving the assertion

* Remove unnecessary `BUNDLE_RUBY` environment var

We can use `RUBY` when necessary, and `BUNDLE_RUBY` is not a good name
because bundler considers `BUNDLE_*` variables as settings.

* Rename `BUNDLE_GEM` to `GEM_COMMAND`

This is more descriptive I think, and also friendlier for bundler
because `BUNDLE_` env variables are interpreted by bundler as settings,
and this is not a bundler setting.

This fixes one bundler spec failure in config specs against ruby-core.

* Fix quality spec when run in core

Use the proper path helper.

* Fix dummy lib builder to never load default gems

If a dummy library is named as a default gem, when requiring the library
from its executable, the default gem would be loaded when running from
core, because in core all default gems share path with bundler, and thus
they are always in the $LOAD_PATH. We fix the issue by loading lib
relatively inside dummy lib executables.

* More exact assertions

Sometimes I have the problem that I do some "print debugging" inside
specs, and suddently the spec passes. This happens when the assertion is
too relaxed, and the things I print make it match, specially when they
are simple strings like "1.0" than can be easily be part of gem paths
that I print for debugging.

I fix this by making a more exact assertion.

* Detect the correct shebang when ENV["RUBY"] is set

* Relax assertion

So that the spec passes even if another paths containing "ext" are in
the load path. This works to fix a ruby-core issue, but it's a better
assertion in general. We just want to know that the extension path was
added.

* Use folder structure independent path helper

It should fix this spec for ruby-core.

* Fix the last failing spec on ruby-core

* Skip `bundle open <default_gem>` spec when no default gems
2019-08-20 09:46:31 +09:00

1358 lines
34 KiB
Ruby

# frozen_string_literal: true
require "tmpdir"
require "tempfile"
RSpec.describe "Bundler.setup" do
describe "with no arguments" do
it "makes all groups available" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :group => :test
G
ruby <<-RUBY
require '#{lib}/bundler'
Bundler.setup
require 'rack'
puts RACK
RUBY
expect(err).to be_empty
expect(out).to eq("1.0.0")
end
end
describe "when called with groups" do
before(:each) do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "yard"
gem "rack", :group => :test
G
end
it "doesn't make all groups available" do
ruby <<-RUBY
require '#{lib}/bundler'
Bundler.setup(:default)
begin
require 'rack'
rescue LoadError
puts "WIN"
end
RUBY
expect(err).to be_empty
expect(out).to eq("WIN")
end
it "accepts string for group name" do
ruby <<-RUBY
require '#{lib}/bundler'
Bundler.setup(:default, 'test')
require 'rack'
puts RACK
RUBY
expect(err).to be_empty
expect(out).to eq("1.0.0")
end
it "leaves all groups available if they were already" do
ruby <<-RUBY
require '#{lib}/bundler'
Bundler.setup
Bundler.setup(:default)
require 'rack'
puts RACK
RUBY
expect(err).to be_empty
expect(out).to eq("1.0.0")
end
it "leaves :default available if setup is called twice" do
ruby <<-RUBY
require '#{lib}/bundler'
Bundler.setup(:default)
Bundler.setup(:default, :test)
begin
require 'yard'
puts "WIN"
rescue LoadError
puts "FAIL"
end
RUBY
expect(err).to be_empty
expect(out).to match("WIN")
end
it "handles multiple non-additive invocations" do
ruby <<-RUBY
require '#{lib}/bundler'
Bundler.setup(:default, :test)
Bundler.setup(:default)
require 'rack'
puts "FAIL"
RUBY
expect(err).to match("rack")
expect(err).to match("LoadError")
expect(out).not_to match("FAIL")
end
end
context "load order" do
def clean_load_path(lp)
without_bundler_load_path = ruby!("puts $LOAD_PATH").split("\n")
lp -= without_bundler_load_path
lp.map! {|p| p.sub(/^#{Regexp.union system_gem_path.to_s, default_bundle_path.to_s, lib.to_s}/i, "") }
end
it "puts loaded gems after -I and RUBYLIB", :ruby_repo do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -Idash_i_dir"
ENV["RUBYLIB"] = "rubylib_dir"
ruby <<-RUBY
require '#{lib}/bundler'
Bundler.setup
puts $LOAD_PATH
RUBY
load_path = out.split("\n")
rack_load_order = load_path.index {|path| path.include?("rack") }
expect(err).to eq("")
expect(load_path).to include(a_string_ending_with("dash_i_dir"), "rubylib_dir")
expect(rack_load_order).to be > 0
end
it "orders the load path correctly when there are dependencies" do
system_gems :bundler
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
ruby! <<-RUBY
require '#{lib}/bundler'
Bundler.setup
puts $LOAD_PATH
RUBY
load_path = clean_load_path(out.split("\n"))
expect(load_path).to start_with(
"/gems/rails-2.3.2/lib",
"/gems/bundler-#{Bundler::VERSION}/lib",
"/gems/activeresource-2.3.2/lib",
"/gems/activerecord-2.3.2/lib",
"/gems/actionpack-2.3.2/lib",
"/gems/actionmailer-2.3.2/lib",
"/gems/activesupport-2.3.2/lib",
"/gems/rake-12.3.2/lib"
)
end
it "falls back to order the load path alphabetically for backwards compatibility" do
install_gemfile! <<-G
source "#{file_uri_for(gem_repo1)}"
gem "weakling"
gem "duradura"
gem "terranova"
G
ruby! <<-RUBY
require '#{lib}/bundler/setup'
puts $LOAD_PATH
RUBY
load_path = clean_load_path(out.split("\n"))
expect(load_path).to start_with(
"/gems/weakling-0.0.3/lib",
"/gems/terranova-8/lib",
"/gems/duradura-7.0/lib"
)
end
end
it "raises if the Gemfile was not yet installed" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
ruby <<-R
require '#{lib}/bundler'
begin
Bundler.setup
puts "FAIL"
rescue Bundler::GemNotFound
puts "WIN"
end
R
expect(out).to eq("WIN")
end
it "doesn't create a Gemfile.lock if the setup fails" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
ruby <<-R
require '#{lib}/bundler'
Bundler.setup
R
expect(bundled_app("Gemfile.lock")).not_to exist
end
it "doesn't change the Gemfile.lock if the setup fails" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
lockfile = File.read(bundled_app("Gemfile.lock"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "nosuchgem", "10.0"
G
ruby <<-R
require '#{lib}/bundler'
Bundler.setup
R
expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile)
end
it "makes a Gemfile.lock if setup succeeds" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
File.read(bundled_app("Gemfile.lock"))
FileUtils.rm(bundled_app("Gemfile.lock"))
run "1"
expect(bundled_app("Gemfile.lock")).to exist
end
describe "$BUNDLE_GEMFILE" do
context "user provides an absolute path" do
it "uses BUNDLE_GEMFILE to locate the gemfile if present" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
gemfile bundled_app("4realz"), <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activesupport", "2.3.5"
G
ENV["BUNDLE_GEMFILE"] = bundled_app("4realz").to_s
bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.5"
end
end
context "an absolute path is not provided" do
it "uses BUNDLE_GEMFILE to locate the gemfile if present" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
G
bundle "install"
bundle "install --deployment"
ENV["BUNDLE_GEMFILE"] = "Gemfile"
ruby <<-R
require '#{lib}/bundler'
begin
Bundler.setup
puts "WIN"
rescue ArgumentError => e
puts "FAIL"
end
R
expect(out).to eq("WIN")
end
end
end
it "prioritizes gems in BUNDLE_PATH over gems in GEM_HOME" do
ENV["BUNDLE_PATH"] = bundled_app(".bundle").to_s
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
G
build_gem "rack", "1.0", :to_system => true do |s|
s.write "lib/rack.rb", "RACK = 'FAIL'"
end
expect(the_bundle).to include_gems "rack 1.0.0"
end
describe "integrate with rubygems" do
describe "by replacing #gem" do
before :each do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
G
end
it "replaces #gem but raises when the gem is missing" do
run <<-R
begin
gem "activesupport"
puts "FAIL"
rescue LoadError
puts "WIN"
end
R
expect(out).to eq("WIN")
end
it "version_requirement is now deprecated in rubygems 1.4.0+ when gem is missing" do
run <<-R
begin
gem "activesupport"
puts "FAIL"
rescue LoadError
puts "WIN"
end
R
expect(err).to be_empty
end
it "replaces #gem but raises when the version is wrong" do
run <<-R
begin
gem "rack", "1.0.0"
puts "FAIL"
rescue LoadError
puts "WIN"
end
R
expect(out).to eq("WIN")
end
it "version_requirement is now deprecated in rubygems 1.4.0+ when the version is wrong" do
run <<-R
begin
gem "rack", "1.0.0"
puts "FAIL"
rescue LoadError
puts "WIN"
end
R
expect(err).to be_empty
end
end
describe "by hiding system gems" do
before :each do
system_gems "activesupport-2.3.5"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "yard"
G
end
it "removes system gems from Gem.source_index" do
run "require 'yard'"
expect(out).to eq("bundler-#{Bundler::VERSION}\nyard-1.0")
end
context "when the ruby stdlib is a substring of Gem.path" do
it "does not reject the stdlib from $LOAD_PATH" do
substring = "/" + $LOAD_PATH.find {|p| p =~ /vendor_ruby/ }.split("/")[2]
run "puts 'worked!'", :env => { "GEM_PATH" => substring }
expect(out).to eq("worked!")
end
end
end
end
describe "with paths" do
it "activates the gems in the path source" do
system_gems "rack-1.0.0"
build_lib "rack", "1.0.0" do |s|
s.write "lib/rack.rb", "puts 'WIN'"
end
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
path "#{lib_path("rack-1.0.0")}" do
gem "rack"
end
G
run "require 'rack'"
expect(out).to eq("WIN")
end
end
describe "with git" do
before do
build_git "rack", "1.0.0"
gemfile <<-G
gem "rack", :git => "#{lib_path("rack-1.0.0")}"
G
end
it "provides a useful exception when the git repo is not checked out yet" do
run "1"
expect(err).to match(/the git source #{lib_path('rack-1.0.0')} is not yet checked out. Please run `bundle install`/i)
end
it "does not hit the git binary if the lockfile is available and up to date" do
bundle "install"
break_git!
ruby <<-R
require '#{lib}/bundler'
begin
Bundler.setup
puts "WIN"
rescue Exception => e
puts "FAIL"
end
R
expect(out).to eq("WIN")
end
it "provides a good exception if the lockfile is unavailable" do
bundle "install"
FileUtils.rm(bundled_app("Gemfile.lock"))
break_git!
ruby <<-R
require "#{lib}/bundler"
begin
Bundler.setup
puts "FAIL"
rescue Bundler::GitError => e
puts e.message
end
R
run "puts 'FAIL'"
expect(err).not_to include "This is not the git you are looking for"
end
it "works even when the cache directory has been deleted" do
bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
FileUtils.rm_rf vendored_gems("cache")
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "does not randomly change the path when specifying --path and the bundle directory becomes read only" do
bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
with_read_only("**/*") do
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
it "finds git gem when default bundle path becomes read only" do
bundle "install"
with_read_only("#{Bundler.bundle_path}/**/*") do
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
end
describe "when specifying local override" do
it "explodes if given path does not exist on runtime" do
build_git "rack", "0.8"
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
G
bundle %(config set local.rack #{lib_path("local-rack")})
bundle! :install
FileUtils.rm_rf(lib_path("local-rack"))
run "require 'rack'"
expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/)
end
it "explodes if branch is not given on runtime" do
build_git "rack", "0.8"
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
G
bundle %(config set local.rack #{lib_path("local-rack")})
bundle! :install
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}"
G
run "require 'rack'"
expect(err).to match(/because :branch is not specified in Gemfile/)
end
it "explodes on different branches on runtime" do
build_git "rack", "0.8"
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
G
bundle %(config set local.rack #{lib_path("local-rack")})
bundle! :install
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "changed"
G
run "require 'rack'"
expect(err).to match(/is using branch master but Gemfile specifies changed/)
end
it "explodes on refs with different branches on runtime" do
build_git "rack", "0.8"
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "master", :branch => "master"
G
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "master", :branch => "nonexistant"
G
bundle %(config set local.rack #{lib_path("local-rack")})
run "require 'rack'"
expect(err).to match(/is using branch master but Gemfile specifies nonexistant/)
end
end
describe "when excluding groups" do
it "doesn't change the resolve if --without is used" do
install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
group :rails do
gem "rails", "2.3.2"
end
G
install_gems "activesupport-2.3.5"
expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => :default
end
it "remembers --without and does not bail on bare Bundler.setup" do
install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
group :rails do
gem "rails", "2.3.2"
end
G
install_gems "activesupport-2.3.5"
expect(the_bundle).to include_gems "activesupport 2.3.2"
end
it "remembers --without and does not include groups passed to Bundler.setup" do
install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
group :rack do
gem "rack"
end
group :rails do
gem "rails", "2.3.2"
end
G
expect(the_bundle).not_to include_gems "activesupport 2.3.2", :groups => :rack
expect(the_bundle).to include_gems "rack 1.0.0", :groups => :rack
end
end
# RubyGems returns loaded_from as a string
it "has loaded_from as a string on all specs" do
build_git "foo"
build_git "no-gemspec", :gemspec => false
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "foo", :git => "#{lib_path("foo-1.0")}"
gem "no-gemspec", "1.0", :git => "#{lib_path("no-gemspec-1.0")}"
G
run <<-R
Gem.loaded_specs.each do |n, s|
puts "FAIL" unless s.loaded_from.is_a?(String)
end
R
expect(out).to be_empty
end
it "does not load all gemspecs" do
install_gemfile! <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
run! <<-R
File.open(File.join(Gem.dir, "specifications", "broken.gemspec"), "w") do |f|
f.write <<-RUBY
# -*- encoding: utf-8 -*-
# stub: broken 1.0.0 ruby lib
Gem::Specification.new do |s|
s.name = "broken"
s.version = "1.0.0"
raise "BROKEN GEMSPEC"
end
RUBY
end
R
run! <<-R
puts "WIN"
R
expect(out).to eq("WIN")
end
it "ignores empty gem paths" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
ENV["GEM_HOME"] = ""
bundle %(exec ruby -e "require 'set'")
expect(err).to be_empty
end
describe "$MANPATH" do
before do
build_repo4 do
build_gem "with_man" do |s|
s.write("man/man1/page.1", "MANPAGE")
end
end
end
context "when the user has one set" do
before { ENV["MANPATH"] = "/foo:" }
it "adds the gem's man dir to the MANPATH" do
install_gemfile! <<-G
source "#{file_uri_for(gem_repo4)}"
gem "with_man"
G
run! "puts ENV['MANPATH']"
expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}:/foo")
end
end
context "when the user does not have one set" do
before { ENV.delete("MANPATH") }
it "adds the gem's man dir to the MANPATH" do
install_gemfile! <<-G
source "#{file_uri_for(gem_repo4)}"
gem "with_man"
G
run! "puts ENV['MANPATH']"
expect(out).to eq(default_bundle_path("gems/with_man-1.0/man").to_s)
end
end
end
it "should prepend gemspec require paths to $LOAD_PATH in order" do
update_repo2 do
build_gem("requirepaths") do |s|
s.write("lib/rq.rb", "puts 'yay'")
s.write("src/rq.rb", "puts 'nooo'")
s.require_paths = %w[lib src]
end
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "requirepaths", :require => nil
G
run "require 'rq'"
expect(out).to eq("yay")
end
it "should clean $LOAD_PATH properly", :ruby_repo do
gem_name = "very_simple_binary"
full_gem_name = gem_name + "-1.0"
ext_dir = File.join(tmp("extensions", full_gem_name))
install_gems full_gem_name
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
G
ruby <<-R
if Gem::Specification.method_defined? :extension_dir
s = Gem::Specification.find_by_name '#{gem_name}'
s.extension_dir = '#{ext_dir}'
# Don't build extensions.
s.class.send(:define_method, :build_extensions) { nil }
end
require '#{lib}/bundler'
gem '#{gem_name}'
puts $LOAD_PATH.count {|path| path =~ /#{gem_name}/} >= 2
Bundler.setup
puts $LOAD_PATH.count {|path| path =~ /#{gem_name}/} == 0
R
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").path }
let(:full_name) { "bundler-#{Bundler::VERSION}" }
before do
FileUtils.ln_sf(gem_home, symlinked_gem_home)
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(root, File.join(gems_dir, full_name))
gemspec_content = File.binread(gemspec).
sub("Bundler::VERSION", %("#{Bundler::VERSION}")).
lines.reject {|line| line =~ %r{lib/bundler/version} }.join
File.open(File.join(specifications_dir, "#{full_name}.gemspec"), "wb") do |f|
f.write(gemspec_content)
end
end
it "should not remove itself from the LOAD_PATH and require a different copy of 'bundler/setup'" do
install_gemfile ""
ruby <<-R, :env => { "GEM_PATH" => symlinked_gem_home }, :no_lib => true
TracePoint.trace(:class) do |tp|
if tp.path.include?("bundler") && !tp.path.start_with?("#{root}")
puts "OMG. Defining a class from another bundler at \#{tp.path}:\#{tp.lineno}"
end
end
gem 'bundler', '#{Bundler::VERSION}'
require 'bundler/setup'
R
expect(out).to be_empty
end
end
it "does not reveal system gems even when Gem.refresh is called" do
system_gems "rack-1.0.0"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
G
run <<-R
puts Bundler.rubygems.all_specs.map(&:name)
Gem.refresh
puts Bundler.rubygems.all_specs.map(&:name)
R
expect(out).to eq("activesupport\nbundler\nactivesupport\nbundler")
end
describe "when a vendored gem specification uses the :path option" do
it "should resolve paths relative to the Gemfile" do
path = bundled_app(File.join("vendor", "foo"))
build_lib "foo", :path => path
# If the .gemspec exists, then Bundler handles the path differently.
# See Source::Path.load_spec_files for details.
FileUtils.rm(File.join(path, "foo.gemspec"))
install_gemfile <<-G
gem 'foo', '1.2.3', :path => 'vendor/foo'
G
Dir.chdir(bundled_app.parent) do
run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile") }
require 'foo'
R
end
expect(err).to be_empty
end
it "should make sure the Bundler.root is really included in the path relative to the Gemfile" do
relative_path = File.join("vendor", Dir.pwd[1..-1], "foo")
absolute_path = bundled_app(relative_path)
FileUtils.mkdir_p(absolute_path)
build_lib "foo", :path => absolute_path
# If the .gemspec exists, then Bundler handles the path differently.
# See Source::Path.load_spec_files for details.
FileUtils.rm(File.join(absolute_path, "foo.gemspec"))
gemfile <<-G
gem 'foo', '1.2.3', :path => '#{relative_path}'
G
bundle :install
Dir.chdir(bundled_app.parent) do
run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile") }
require 'foo'
R
end
expect(err).to be_empty
end
end
describe "with git gems that don't have gemspecs" do
before :each do
build_git "no-gemspec", :gemspec => false
install_gemfile <<-G
gem "no-gemspec", "1.0", :git => "#{lib_path("no-gemspec-1.0")}"
G
end
it "loads the library via a virtual spec" do
run <<-R
require 'no-gemspec'
puts NOGEMSPEC
R
expect(out).to eq("1.0")
end
end
describe "with bundled and system gems" do
before :each do
system_gems "rack-1.0.0"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activesupport", "2.3.5"
G
end
it "does not pull in system gems" do
run <<-R
begin;
require 'rack'
rescue LoadError
puts 'WIN'
end
R
expect(out).to eq("WIN")
end
it "provides a gem method" do
run <<-R
gem 'activesupport'
require 'activesupport'
puts ACTIVESUPPORT
R
expect(out).to eq("2.3.5")
end
it "raises an exception if gem is used to invoke a system gem not in the bundle" do
run <<-R
begin
gem 'rack'
rescue LoadError => e
puts e.message
end
R
expect(out).to eq("rack is not part of the bundle. Add it to your Gemfile.")
end
it "sets GEM_HOME appropriately" do
run "puts ENV['GEM_HOME']"
expect(out).to eq(default_bundle_path.to_s)
end
end
describe "with system gems in the bundle" do
before :each do
bundle! "config set path.system true"
system_gems "rack-1.0.0"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
gem "activesupport", "2.3.5"
G
end
it "sets GEM_PATH appropriately" do
run "puts Gem.path"
paths = out.split("\n")
expect(paths).to include(system_gem_path.to_s)
end
end
describe "with a gemspec that requires other files" do
before :each do
build_git "bar", :gemspec => false do |s|
s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
lib = File.expand_path('../lib/', __FILE__)
$:.unshift lib unless $:.include?(lib)
require 'bar/version'
Gem::Specification.new do |s|
s.name = 'bar'
s.version = BAR_VERSION
s.summary = 'Bar'
s.files = Dir["lib/**/*.rb"]
s.author = 'no one'
end
G
end
gemfile <<-G
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
it "evals each gemspec in the context of its parent directory" do
bundle :install
run "require 'bar'; puts BAR"
expect(out).to eq("1.0")
end
it "error intelligently if the gemspec has a LoadError" do
ref = update_git "bar", :gemspec => false do |s|
s.write "bar.gemspec", "require 'foobarbaz'"
end.ref_for("HEAD")
bundle :install
expect(err.lines.map(&:chomp)).to include(
a_string_starting_with("[!] There was an error while loading `bar.gemspec`:"),
a_string_starting_with("Does it try to require a relative path? That's been removed in Ruby 1.9."),
" # from #{default_bundle_path "bundler", "gems", "bar-1.0-#{ref[0, 12]}", "bar.gemspec"}:1",
" > require 'foobarbaz'"
)
end
it "evals each gemspec with a binding from the top level" do
bundle "install"
ruby <<-RUBY
require '#{lib}/bundler'
def Bundler.require(path)
raise "LOSE"
end
Bundler.load
RUBY
expect(err).to be_empty
expect(out).to eq("")
end
end
describe "when Bundler is bundled" do
it "doesn't blow up" do
install_gemfile <<-G
gem "bundler", :path => "#{File.expand_path("..", lib)}"
G
bundle %(exec ruby -e "require 'bundler'; Bundler.setup")
expect(err).to be_empty
end
end
describe "when BUNDLED WITH" do
def lock_with(bundler_version = nil)
lock = <<-L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
rack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
rack
L
if bundler_version
lock += "\n BUNDLED WITH\n #{bundler_version}\n"
end
lock
end
before do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
end
context "is not present" do
it "does not change the lock" do
lockfile lock_with(nil)
ruby "require '#{lib}/bundler/setup'"
lockfile_should_be lock_with(nil)
end
end
context "is newer" do
it "does not change the lock or warn" do
lockfile lock_with(Bundler::VERSION.succ)
ruby "require '#{lib}/bundler/setup'"
expect(out).to eq("")
expect(err).to eq("")
lockfile_should_be lock_with(Bundler::VERSION.succ)
end
end
context "is older" do
it "does not change the lock" do
lockfile lock_with("1.10.1")
ruby "require '#{lib}/bundler/setup'"
lockfile_should_be lock_with("1.10.1")
end
end
end
describe "when RUBY VERSION" do
let(:ruby_version) { nil }
def lock_with(ruby_version = nil)
lock = <<-L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
rack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
rack
L
if ruby_version
lock += "\n RUBY VERSION\n ruby #{ruby_version}\n"
end
lock += <<-L
BUNDLED WITH
#{Bundler::VERSION}
L
lock
end
before do
install_gemfile <<-G
ruby ">= 0"
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
lockfile lock_with(ruby_version)
end
context "is not present" do
it "does not change the lock" do
expect { ruby! "require '#{lib}/bundler/setup'" }.not_to change { lockfile }
end
end
context "is newer" do
let(:ruby_version) { "5.5.5" }
it "does not change the lock or warn" do
expect { ruby! "require '#{lib}/bundler/setup'" }.not_to change { lockfile }
expect(out).to eq("")
expect(err).to eq("")
end
end
context "is older" do
let(:ruby_version) { "1.0.0" }
it "does not change the lock" do
expect { ruby! "require '#{lib}/bundler/setup'" }.not_to change { lockfile }
end
end
end
describe "with gemified standard libraries" do
it "does not load Psych" do
gemfile ""
ruby <<-RUBY
require '#{lib}/bundler/setup'
puts defined?(Psych::VERSION) ? Psych::VERSION : "undefined"
require 'psych'
puts Psych::VERSION
RUBY
pre_bundler, post_bundler = out.split("\n")
expect(pre_bundler).to eq("undefined")
expect(post_bundler).to match(/\d+\.\d+\.\d+/)
end
it "does not load openssl" do
install_gemfile! ""
ruby! <<-RUBY
require "#{lib}/bundler/setup"
puts defined?(OpenSSL) || "undefined"
require "openssl"
puts defined?(OpenSSL) || "undefined"
RUBY
expect(out).to eq("undefined\nconstant")
end
describe "default gem activation" do
let(:exemptions) do
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7")
[]
else
%w[io-console openssl]
end << "bundler"
end
let(:activation_warning_hack) { strip_whitespace(<<-RUBY) }
require #{spec_dir.join("support/hax").to_s.dump}
if Gem::Specification.instance_methods.map(&:to_sym).include?(:activate)
Gem::Specification.send(:alias_method, :bundler_spec_activate, :activate)
Gem::Specification.send(:define_method, :activate) do
unless #{exemptions.inspect}.include?(name)
warn '-' * 80
warn "activating \#{full_name}"
warn *caller
warn '*' * 80
end
bundler_spec_activate
end
end
RUBY
let(:activation_warning_hack_rubyopt) do
create_file("activation_warning_hack.rb", activation_warning_hack)
"-r#{bundled_app("activation_warning_hack.rb")} #{ENV["RUBYOPT"]}"
end
let(:code) { strip_whitespace(<<-RUBY) }
require "pp"
loaded_specs = Gem.loaded_specs.dup
#{exemptions.inspect}.each {|s| loaded_specs.delete(s) }
pp loaded_specs
# not a default gem, but harmful to have loaded
open_uri = $LOADED_FEATURES.grep(/open.uri/)
unless open_uri.empty?
warn "open_uri: \#{open_uri}"
end
RUBY
it "activates no gems with -rbundler/setup" do
install_gemfile! ""
ruby! code, :env => { :RUBYOPT => activation_warning_hack_rubyopt + " -r#{lib}/bundler/setup" }
expect(out).to eq("{}")
end
it "activates no gems with bundle exec" do
install_gemfile! ""
create_file("script.rb", code)
bundle! "exec ruby ./script.rb", :env => { :RUBYOPT => activation_warning_hack_rubyopt }
expect(out).to eq("{}")
end
it "activates no gems with bundle exec that is loaded" do
install_gemfile! ""
create_file("script.rb", "#!/usr/bin/env ruby\n\n#{code}")
FileUtils.chmod(0o777, bundled_app("script.rb"))
bundle! "exec ./script.rb", :artifice => nil, :env => { :RUBYOPT => activation_warning_hack_rubyopt }
expect(out).to eq("{}")
end
let(:default_gems) do
ruby!(<<-RUBY).split("\n")
if Gem::Specification.is_a?(Enumerable)
puts Gem::Specification.select(&:default_gem?).map(&:name)
end
RUBY
end
it "activates newer versions of default gems" do
build_repo4 do
default_gems.each do |g|
build_gem g, "999999"
end
end
default_gems.reject! {|g| exemptions.include?(g) }
install_gemfile! <<-G
source "#{file_uri_for(gem_repo4)}"
#{default_gems}.each do |g|
gem g, "999999"
end
G
expect(the_bundle).to include_gems(*default_gems.map {|g| "#{g} 999999" })
end
it "activates older versions of default gems" do
build_repo4 do
default_gems.each do |g|
build_gem g, "0.0.0.a"
end
end
default_gems.reject! {|g| exemptions.include?(g) }
install_gemfile! <<-G
source "#{file_uri_for(gem_repo4)}"
#{default_gems}.each do |g|
gem g, "0.0.0.a"
end
G
expect(the_bundle).to include_gems(*default_gems.map {|g| "#{g} 0.0.0.a" })
end
end
end
describe "after setup" do
it "allows calling #gem on random objects", :bundler => "< 3" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
ruby! <<-RUBY
require "#{lib}/bundler/setup"
Object.new.gem "rack"
puts Gem.loaded_specs["rack"].full_name
RUBY
expect(out).to eq("rack-1.0.0")
end
it "keeps Kernel#gem private", :bundler => "3" do
install_gemfile! <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
ruby <<-RUBY
require "#{lib}/bundler/setup"
Object.new.gem "rack"
puts "FAIL"
RUBY
expect(last_command.stdboth).not_to include "FAIL"
expect(err).to include "private method `gem'"
end
it "keeps Kernel#require private" do
install_gemfile! <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
ruby <<-RUBY
require "#{lib}/bundler/setup"
Object.new.require "rack"
puts "FAIL"
RUBY
expect(last_command.stdboth).not_to include "FAIL"
expect(err).to include "private method `require'"
end
end
end