diff options
Diffstat (limited to 'spec/bundler/bundler')
54 files changed, 970 insertions, 199 deletions
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb index 268c0d99ac..19e3f0336f 100644 --- a/spec/bundler/bundler/bundler_spec.rb +++ b/spec/bundler/bundler/bundler_spec.rb @@ -1,6 +1,6 @@ # encoding: utf-8 # frozen_string_literal: true -require "spec_helper" + require "bundler" RSpec.describe Bundler do @@ -102,11 +102,29 @@ RSpec.describe Bundler do subject end end + + context "with gemspec containing local variables" do + before do + File.open(app_gemspec_path, "wb") do |f| + f.write strip_whitespace(<<-GEMSPEC) + must_not_leak = true + Gem::Specification.new do |gem| + gem.name = "leak check" + end + GEMSPEC + end + end + + it "should not pollute the TOPLEVEL_BINDING" do + subject + expect(TOPLEVEL_BINDING.eval("local_variables")).to_not include(:must_not_leak) + end + end end describe "#which" do let(:executable) { "executable" } - let(:path) { %w(/a /b c ../d /e) } + let(:path) { %w[/a /b c ../d /e] } let(:expected) { "executable" } before do @@ -145,8 +163,8 @@ RSpec.describe Bundler do context "disable_shared_gems" do it "should unset GEM_PATH with empty string" do env = {} - settings = { :disable_shared_gems => true } - Bundler.send(:configure_gem_path, env, settings) + expect(Bundler).to receive(:use_system_gems?).and_return(false) + Bundler.send(:configure_gem_path, env) expect(env.keys).to include("GEM_PATH") expect(env["GEM_PATH"]).to eq "" end @@ -158,7 +176,7 @@ RSpec.describe Bundler do let(:bundler_ui) { Bundler.ui } it "should raise a friendly error" do allow(File).to receive(:exist?).and_return(true) - allow(FileUtils).to receive(:remove_entry_secure).and_raise(ArgumentError) + allow(bundler_fileutils).to receive(:remove_entry_secure).and_raise(ArgumentError) allow(File).to receive(:world_writable?).and_return(true) message = <<EOF It is a security vulnerability to allow your home directory to be world-writable, and bundler can not continue. diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb index d41e6de4a7..ace4e8a625 100644 --- a/spec/bundler/bundler/cli_spec.rb +++ b/spec/bundler/bundler/cli_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/cli" RSpec.describe "bundle executable" do @@ -27,6 +27,18 @@ RSpec.describe "bundle executable" do expect(out).to eq("Hello, world") end + context "with no arguments" do + it "prints a concise help message", :bundler => "2" do + bundle! "" + expect(last_command.stderr).to be_empty + expect(last_command.stdout).to include("Bundler version #{Bundler::VERSION}"). + and include("\n\nBundler commands:\n\n"). + and include("\n\n Primary commands:\n"). + and include("\n\n Utilities:\n"). + and include("\n\nOptions:\n") + end + end + context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do it "ignores it" do gemfile bundled_app("Gemfile"), <<-G @@ -60,12 +72,17 @@ RSpec.describe "bundle executable" do it "prints the running command" do gemfile "" bundle! "info bundler", :verbose => true - expect(out).to start_with("Running `bundle info bundler --no-color --verbose` with bundler #{Bundler::VERSION}") + expect(last_command.stdout).to start_with("Running `bundle info bundler --no-color --verbose` with bundler #{Bundler::VERSION}") + end + + it "doesn't print defaults" do + install_gemfile! "", :verbose => true + expect(last_command.stdout).to start_with("Running `bundle install --no-color --retry 0 --verbose` with bundler #{Bundler::VERSION}") end it "doesn't print defaults" do install_gemfile! "", :verbose => true - expect(out).to start_with("Running `bundle install --no-color --retry 0 --verbose` with bundler #{Bundler::VERSION}") + expect(last_command.stdout).to start_with("Running `bundle install --no-color --retry 0 --verbose` with bundler #{Bundler::VERSION}") end end @@ -73,13 +90,15 @@ RSpec.describe "bundle executable" do shared_examples_for "no warning" do it "prints no warning" do bundle "fail" - expect(err + out).to eq("Could not find command \"fail\".") + expect(last_command.stdboth).to eq("Could not find command \"fail\".") end end let(:bundler_version) { "1.1" } let(:latest_version) { nil } before do + bundle! "config --global disable_version_check false" + simulate_bundler_version(bundler_version) if latest_version info_path = home(".bundle/cache/compact_index/rubygems.org.443.29b0360b937aa4d161703e6160654e47/info/bundler") @@ -103,13 +122,12 @@ RSpec.describe "bundle executable" do end context "when the latest version is greater than the current version" do - let(:latest_version) { "2.0" } + let(:latest_version) { "222.0" } it "prints the version warning" do bundle "fail" - expect(err + out).to eq(<<-EOS.strip) + expect(last_command.stdout).to start_with(<<-EOS.strip) The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. -To update, run `gem install bundler` -Could not find command "fail". +To install the latest version, run `gem install bundler` EOS end @@ -121,21 +139,20 @@ Could not find command "fail". context "running a parseable command" do it "prints no warning" do bundle! "config --parseable foo" - expect(out).to eq "" + expect(last_command.stdboth).to eq "" bundle "platform --ruby" - expect(out).to eq "Could not locate Gemfile" + expect(last_command.stdboth).to eq "Could not locate Gemfile" end end context "and is a pre-release" do - let(:latest_version) { "2.0.0.pre.4" } + let(:latest_version) { "222.0.0.pre.4" } it "prints the version warning" do bundle "fail" - expect(err + out).to eq(<<-EOS.strip) + expect(last_command.stdout).to start_with(<<-EOS.strip) The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. -To update, run `gem install bundler --pre` -Could not find command "fail". +To install the latest version, run `gem install bundler --pre` EOS end end @@ -144,8 +161,13 @@ Could not find command "fail". end RSpec.describe "bundler executable" do - it "shows the bundler version just as the `bundle` executable does" do + it "shows the bundler version just as the `bundle` executable does", :bundler => "< 2" do bundler "--version" expect(out).to eq("Bundler version #{Bundler::VERSION}") end + + it "shows the bundler version just as the `bundle` executable does", :bundler => "2" do + bundler "--version" + expect(out).to eq(Bundler::VERSION) + end end diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb index c1cae31956..3c4f212b60 100644 --- a/spec/bundler/bundler/compact_index_client/updater_spec.rb +++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "net/http" require "bundler/compact_index_client" require "bundler/compact_index_client/updater" diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb index 73d44a93ab..5abf0d9756 100644 --- a/spec/bundler/bundler/definition_spec.rb +++ b/spec/bundler/bundler/definition_spec.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/definition" RSpec.describe Bundler::Definition do describe "#lock" do before do allow(Bundler).to receive(:settings) { Bundler::Settings.new(".") } - allow(Bundler).to receive(:default_gemfile) { Pathname.new("Gemfile") } + allow(Bundler::SharedHelpers).to receive(:find_gemfile) { Pathname.new("Gemfile") } allow(Bundler).to receive(:ui) { double("UI", :info => "", :debug => "") } end context "when it's not possible to write to the file" do @@ -32,7 +32,7 @@ RSpec.describe Bundler::Definition do end describe "detects changes" do - it "for a path gem with changes" do + it "for a path gem with changes", :bundler => "< 2" do build_lib "foo", "1.0", :path => lib_path("foo") install_gemfile <<-G @@ -70,7 +70,45 @@ RSpec.describe Bundler::Definition do G end - it "for a path gem with deps and no changes" do + it "for a path gem with changes", :bundler => "2" do + build_lib "foo", "1.0", :path => lib_path("foo") + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :path => "#{lib_path("foo")}" + G + + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", "1.0" + end + + bundle :install, :env => { "DEBUG" => 1 } + + expect(out).to match(/re-resolving dependencies/) + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PATH + remote: #{lib_path("foo")} + specs: + foo (1.0) + rack (= 1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + G + end + + it "for a path gem with deps and no changes", :bundler => "< 2" do build_lib "foo", "1.0", :path => lib_path("foo") do |s| s.add_dependency "rack", "1.0" s.add_development_dependency "net-ssh", "1.0" @@ -107,6 +145,43 @@ RSpec.describe Bundler::Definition do G end + it "for a path gem with deps and no changes", :bundler => "2" do + build_lib "foo", "1.0", :path => lib_path("foo") do |s| + s.add_dependency "rack", "1.0" + s.add_development_dependency "net-ssh", "1.0" + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "foo", :path => "#{lib_path("foo")}" + G + + bundle :check, :env => { "DEBUG" => 1 } + + expect(out).to match(/using resolution from the lockfile/) + lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + + PATH + remote: #{lib_path("foo")} + specs: + foo (1.0) + rack (= 1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + G + end + it "for a rubygems gem" do install_gemfile <<-G source "file://#{gem_repo1}" @@ -123,7 +198,7 @@ RSpec.describe Bundler::Definition do foo (1.0) PLATFORMS - ruby + #{lockfile_platforms} DEPENDENCIES foo @@ -160,6 +235,12 @@ RSpec.describe Bundler::Definition do end context "eager unlock" do + let(:source_list) do + Bundler::SourceList.new.tap do |source_list| + source_list.global_rubygems_source = "file://#{gem_repo4}" + end + end + before do gemfile <<-G source "file://#{gem_repo4}" @@ -203,11 +284,11 @@ RSpec.describe Bundler::Definition do definition = Bundler::Definition.new( bundled_app("Gemfile.lock"), updated_deps_in_gemfile, - Bundler::SourceList.new, + source_list, unlock_hash_for_bundle_install ) locked = definition.send(:converge_locked_specs).map(&:name) - expect(locked.include?("shared_dep")).to be_truthy + expect(locked).to include "shared_dep" end it "should not eagerly unlock shared dependency with bundle update conservative updating behavior" do @@ -217,11 +298,11 @@ RSpec.describe Bundler::Definition do definition = Bundler::Definition.new( bundled_app("Gemfile.lock"), updated_deps_in_gemfile, - Bundler::SourceList.new, + source_list, :gems => ["shared_owner_a"], :lock_shared_dependencies => true ) locked = definition.send(:converge_locked_specs).map(&:name) - expect(locked).to eq %w(isolated_dep isolated_owner shared_dep shared_owner_b) + expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b] expect(locked.include?("shared_dep")).to be_truthy end end @@ -242,7 +323,7 @@ RSpec.describe Bundler::Definition do describe "find_indexed_specs" do it "with no platform set in indexed specs" do index = Bundler::Index.new - %w(1.0.0 1.0.1 1.1.0).each {|v| index << build_stub_spec("foo", v) } + %w[1.0.0 1.0.1 1.1.0].each {|v| index << build_stub_spec("foo", v) } dfn = Bundler::Definition.new(nil, [], mock_source_list, true) dfn.instance_variable_set("@index", index) diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb index 4f5eb6dc92..f706e1b9ad 100644 --- a/spec/bundler/bundler/dsl_spec.rb +++ b/spec/bundler/bundler/dsl_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Dsl do before do @@ -26,7 +25,7 @@ RSpec.describe Bundler::Dsl do expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption) end - context "default hosts (git, gist)" do + context "default hosts (git, gist)", :bundler => "< 2" do it "converts :github to :git" do subject.gem("sparks", :github => "indirect/sparks") github_uri = "git://github.com/indirect/sparks.git" @@ -63,11 +62,17 @@ RSpec.describe Bundler::Dsl do expect(subject.dependencies.first.source.uri).to eq(bitbucket_uri) end end + + context "default git sources", :bundler => "2" do + it "has none" do + expect(subject.instance_variable_get(:@git_sources)).to eq({}) + end + end end describe "#method_missing" do it "raises an error for unknown DSL methods" do - expect(Bundler).to receive(:read_file).with("Gemfile"). + expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s). and_return("unknown") error_msg = "There was an error parsing `Gemfile`: Undefined local variable or method `unknown' for Gemfile. Bundler cannot continue." @@ -78,13 +83,13 @@ RSpec.describe Bundler::Dsl do describe "#eval_gemfile" do it "handles syntax errors with a useful message" do - expect(Bundler).to receive(:read_file).with("Gemfile").and_return("}") + expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return("}") expect { subject.eval_gemfile("Gemfile") }. to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: (syntax error, unexpected tSTRING_DEND|(compile error - )?syntax error, unexpected '\}'). Bundler cannot continue./) end it "distinguishes syntax errors from evaluation errors" do - expect(Bundler).to receive(:read_file).with("Gemfile").and_return( + expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return( "ruby '2.1.5', :engine => 'ruby', :engine_version => '1.2.4'" ) expect { subject.eval_gemfile("Gemfile") }. @@ -105,6 +110,11 @@ RSpec.describe Bundler::Dsl do to raise_error(Bundler::GemfileError, /is not a valid platform/) end + it "rejects empty gem name" do + expect { subject.gem("") }. + to raise_error(Bundler::GemfileError, /an empty gem name is not valid/) + end + it "rejects with a leading space in the name" do expect { subject.gem(" foo") }. to raise_error(Bundler::GemfileError, /' foo' is not a valid gem name because it contains whitespace/) @@ -150,13 +160,13 @@ RSpec.describe Bundler::Dsl do to raise_error(Bundler::GemfileError, /The `branch` option for `gem 'foo'` is not allowed. Only gems with a git source can specify a branch/) end - it "allows specifiying a branch on git gems" do + it "allows specifying a branch on git gems" do subject.gem("foo", :branch => "test", :git => "http://mytestrepo") dep = subject.dependencies.last expect(dep.name).to eq "foo" end - it "allows specifiying a branch on git gems with a git_source" do + it "allows specifying a branch on git gems with a git_source" do subject.git_source(:test_source) {|n| "https://github.com/#{n}" } subject.gem("foo", :branch => "test", :test_source => "bundler/bundler") dep = subject.dependencies.last @@ -206,7 +216,7 @@ RSpec.describe Bundler::Dsl do # end describe "#git" do it "from a single repo" do - rails_gems = %w(railties action_pack active_model) + rails_gems = %w[railties action_pack active_model] subject.git "https://github.com/rails/rails.git" do rails_gems.each {|rails_gem| subject.send :gem, rails_gem } end @@ -219,9 +229,9 @@ RSpec.describe Bundler::Dsl do # gem 'spree_api' # gem 'spree_backend' # end - describe "#github" do + describe "#github", :bundler => "< 2" do it "from github" do - spree_gems = %w(spree_core spree_api spree_backend) + spree_gems = %w[spree_core spree_api spree_backend] subject.github "spree" do spree_gems.each {|spree_gem| subject.send :gem, spree_gem } end @@ -231,6 +241,17 @@ RSpec.describe Bundler::Dsl do end end end + + describe "#github", :bundler => "2" do + it "from github" do + expect do + spree_gems = %w[spree_core spree_api spree_backend] + subject.github "spree" do + spree_gems.each {|spree_gem| subject.send :gem, spree_gem } + end + end.to raise_error(Bundler::DeprecatedError, /github method has been removed/) + end + end end describe "syntax errors" do diff --git a/spec/bundler/bundler/endpoint_specification_spec.rb b/spec/bundler/bundler/endpoint_specification_spec.rb index 0b8da840d2..a9371f6617 100644 --- a/spec/bundler/bundler/endpoint_specification_spec.rb +++ b/spec/bundler/bundler/endpoint_specification_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::EndpointSpecification do let(:name) { "foo" } @@ -8,7 +7,7 @@ RSpec.describe Bundler::EndpointSpecification do let(:dependencies) { [] } let(:metadata) { nil } - subject { described_class.new(name, version, platform, dependencies, metadata) } + subject(:spec) { described_class.new(name, version, platform, dependencies, metadata) } describe "#build_dependency" do let(:name) { "foo" } @@ -63,4 +62,10 @@ RSpec.describe Bundler::EndpointSpecification do end end end + + it "supports equality comparison" do + other_spec = described_class.new("bar", version, platform, dependencies, metadata) + expect(spec).to eql(spec) + expect(spec).to_not eql(other_spec) + end end diff --git a/spec/bundler/bundler/env_spec.rb b/spec/bundler/bundler/env_spec.rb index 269c323ac6..83c03e67d5 100644 --- a/spec/bundler/bundler/env_spec.rb +++ b/spec/bundler/bundler/env_spec.rb @@ -1,20 +1,19 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/settings" RSpec.describe Bundler::Env do - let(:env) { described_class.new } let(:git_proxy_stub) { Bundler::Source::Git::GitProxy.new(nil, nil, nil) } describe "#report" do it "prints the environment" do - out = env.report + out = described_class.report expect(out).to include("Environment") expect(out).to include(Bundler::VERSION) expect(out).to include(Gem::VERSION) - expect(out).to include(env.send(:ruby_version)) - expect(out).to include(env.send(:git_version)) + expect(out).to include(described_class.send(:ruby_version)) + expect(out).to include(described_class.send(:git_version)) expect(out).to include(OpenSSL::OPENSSL_VERSION) end @@ -36,7 +35,7 @@ RSpec.describe Bundler::Env do L end - let(:output) { env.report(:print_gemfile => true) } + let(:output) { described_class.report(:print_gemfile => true) } it "prints the Gemfile" do expect(output).to include("Gemfile") @@ -50,7 +49,7 @@ RSpec.describe Bundler::Env do end context "when there no Gemfile and print_gemfile is true" do - let(:output) { env.report(:print_gemfile => true) } + let(:output) { described_class.report(:print_gemfile => true) } it "prints the environment" do expect(output).to start_with("## Environment") @@ -76,20 +75,68 @@ RSpec.describe Bundler::Env do end it "prints the gemspec" do - output = env.report(:print_gemspecs => true) + output = described_class.report(:print_gemspecs => true) expect(output).to include("foo.gemspec") expect(output).to include(gemspec) end end + context "when eval_gemfile is used" do + it "prints all gemfiles" do + create_file "other/Gemfile-other", "gem 'rack'" + create_file "other/Gemfile", "eval_gemfile 'Gemfile-other'" + create_file "Gemfile-alt", <<-G + source "file:#{gem_repo1}" + eval_gemfile "other/Gemfile" + G + gemfile "eval_gemfile #{File.expand_path("Gemfile-alt").dump}" + + output = described_class.report(:print_gemspecs => true) + expect(output).to include(strip_whitespace(<<-ENV)) + ## Gemfile + + ### Gemfile + + ```ruby + eval_gemfile #{File.expand_path("Gemfile-alt").dump} + ``` + + ### Gemfile-alt + + ```ruby + source "file:#{gem_repo1}" + eval_gemfile "other/Gemfile" + ``` + + ### other/Gemfile + + ```ruby + eval_gemfile 'Gemfile-other' + ``` + + ### other/Gemfile-other + + ```ruby + gem 'rack' + ``` + + ### Gemfile.lock + + ``` + <No #{bundled_app("Gemfile.lock")} found> + ``` + ENV + end + end + context "when the git version is OS specific" do it "includes OS specific information with the version number" do expect(git_proxy_stub).to receive(:git).with("--version"). and_return("git version 1.2.3 (Apple Git-BS)") expect(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub) - expect(env.report).to include("Git 1.2.3 (Apple Git-BS)") + expect(described_class.report).to include("Git 1.2.3 (Apple Git-BS)") end end end diff --git a/spec/bundler/bundler/environment_preserver_spec.rb b/spec/bundler/bundler/environment_preserver_spec.rb index 41d2650055..530ca6f835 100644 --- a/spec/bundler/bundler/environment_preserver_spec.rb +++ b/spec/bundler/bundler/environment_preserver_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::EnvironmentPreserver do let(:preserver) { described_class.new(env, ["foo"]) } @@ -22,14 +21,14 @@ RSpec.describe Bundler::EnvironmentPreserver do it "should not affect the original env" do subject - expect(env.keys.sort).to eq(%w(bar foo)) + expect(env.keys.sort).to eq(%w[bar foo]) end context "when a key is empty" do let(:env) { { "foo" => "" } } it "should not create backup entries" do - expect(subject.key?("BUNDLER_ORIG_foo")).to eq(false) + expect(subject).not_to have_key "BUNDLER_ORIG_foo" end end diff --git a/spec/bundler/bundler/fetcher/base_spec.rb b/spec/bundler/bundler/fetcher/base_spec.rb index 38b69429bc..df1245d44d 100644 --- a/spec/bundler/bundler/fetcher/base_spec.rb +++ b/spec/bundler/bundler/fetcher/base_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Fetcher::Base do let(:downloader) { double(:downloader) } diff --git a/spec/bundler/bundler/fetcher/compact_index_spec.rb b/spec/bundler/bundler/fetcher/compact_index_spec.rb index e653c1ea43..e0f58766ea 100644 --- a/spec/bundler/bundler/fetcher/compact_index_spec.rb +++ b/spec/bundler/bundler/fetcher/compact_index_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Fetcher::CompactIndex do let(:downloader) { double(:downloader) } @@ -46,7 +45,17 @@ RSpec.describe Bundler::Fetcher::CompactIndex do end context "when OpenSSL is FIPS-enabled", :ruby => ">= 2.0.0" do - before { stub_const("OpenSSL::OPENSSL_FIPS", true) } + def remove_cached_md5_availability + return unless Bundler::SharedHelpers.instance_variable_defined?(:@md5_available) + Bundler::SharedHelpers.remove_instance_variable(:@md5_available) + end + + before do + remove_cached_md5_availability + stub_const("OpenSSL::OPENSSL_FIPS", true) + end + + after { remove_cached_md5_availability } context "when FIPS-mode is active" do before do diff --git a/spec/bundler/bundler/fetcher/dependency_spec.rb b/spec/bundler/bundler/fetcher/dependency_spec.rb index 134ca1bc57..081fdff34d 100644 --- a/spec/bundler/bundler/fetcher/dependency_spec.rb +++ b/spec/bundler/bundler/fetcher/dependency_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Fetcher::Dependency do let(:downloader) { double(:downloader) } @@ -64,7 +63,7 @@ RSpec.describe Bundler::Fetcher::Dependency do end describe "#specs" do - let(:gem_names) { %w(foo bar) } + let(:gem_names) { %w[foo bar] } let(:full_dependency_list) { ["bar"] } let(:last_spec_list) { [["boulder", gem_version1, "ruby", resque]] } let(:fail_errors) { double(:fail_errors) } @@ -103,7 +102,7 @@ RSpec.describe Bundler::Fetcher::Dependency do context "when all given gem names are in the full dependency list" do let(:gem_names) { ["foo"] } - let(:full_dependency_list) { %w(foo bar) } + let(:full_dependency_list) { %w[foo bar] } let(:last_spec_list) { ["boulder"] } it "should return a hash with the remote_uri and the last spec list" do @@ -190,7 +189,7 @@ RSpec.describe Bundler::Fetcher::Dependency do end describe "#dependency_specs" do - let(:gem_names) { [%w(foo bar), %w(bundler rubocop)] } + let(:gem_names) { [%w[foo bar], %w[bundler rubocop]] } let(:gem_list) { double(:gem_list) } let(:formatted_specs_and_deps) { double(:formatted_specs_and_deps) } @@ -212,7 +211,7 @@ RSpec.describe Bundler::Fetcher::Dependency do end describe "#unmarshalled_dep_gems" do - let(:gem_names) { [%w(foo bar), %w(bundler rubocop)] } + let(:gem_names) { [%w[foo bar], %w[bundler rubocop]] } let(:dep_api_uri) { double(:dep_api_uri) } let(:unmarshalled_gems) { double(:unmarshalled_gems) } let(:fetch_response) { double(:fetch_response, :body => double(:body)) } @@ -220,7 +219,7 @@ RSpec.describe Bundler::Fetcher::Dependency do before { allow(subject).to receive(:dependency_api_uri).with(gem_names).and_return(dep_api_uri) } - it "should fetch dependencies from Rubygems and unmarshal them" do + it "should fetch dependencies from RubyGems and unmarshal them" do expect(gem_names).to receive(:each_slice).with(rubygems_limit).and_call_original expect(downloader).to receive(:fetch).with(dep_api_uri).and_return(fetch_response) expect(Bundler).to receive(:load_marshal).with(fetch_response.body).and_return([unmarshalled_gems]) @@ -254,7 +253,7 @@ RSpec.describe Bundler::Fetcher::Dependency do spec_list, deps_list = subject.get_formatted_specs_and_deps(gem_list) expect(spec_list).to eq([["typhoeus", "1.0.1", "ruby", [["resque", ["req3,req4"]]]], ["grape", "2.0.2", "jruby", [["faraday", ["req1,req2"]]]]]) - expect(deps_list).to eq(%w(resque faraday)) + expect(deps_list).to eq(%w[resque faraday]) end end @@ -262,7 +261,7 @@ RSpec.describe Bundler::Fetcher::Dependency do let(:uri) { URI("http://gem-api.com") } context "with gem names" do - let(:gem_names) { %w(foo bar bundler rubocop) } + let(:gem_names) { %w[foo bar bundler rubocop] } before { allow(subject).to receive(:fetch_uri).and_return(uri) } diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb index 4dcd94b1b2..c9b4fa662a 100644 --- a/spec/bundler/bundler/fetcher/downloader_spec.rb +++ b/spec/bundler/bundler/fetcher/downloader_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Fetcher::Downloader do let(:connection) { double(:connection) } diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb index b17e0d1727..0cf0ae764e 100644 --- a/spec/bundler/bundler/fetcher/index_spec.rb +++ b/spec/bundler/bundler/fetcher/index_spec.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Fetcher::Index do let(:downloader) { nil } let(:remote) { nil } let(:display_uri) { "http://sample_uri.com" } let(:rubygems) { double(:rubygems) } - let(:gem_names) { %w(foo bar) } + let(:gem_names) { %w[foo bar] } subject { described_class.new(downloader, remote, display_uri) } diff --git a/spec/bundler/bundler/fetcher_spec.rb b/spec/bundler/bundler/fetcher_spec.rb index 585768343f..f9e52e09c0 100644 --- a/spec/bundler/bundler/fetcher_spec.rb +++ b/spec/bundler/bundler/fetcher_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/fetcher" RSpec.describe Bundler::Fetcher do @@ -85,11 +85,52 @@ RSpec.describe Bundler::Fetcher do end end end + + context "when no ssl configuration is set" do + it "no cert" do + expect(fetcher.send(:connection).cert).to be_nil + expect(fetcher.send(:connection).key).to be_nil + end + end + + context "when bunder ssl ssl configuration is set" do + before do + allow(Bundler.settings).to receive(:[]).and_return(nil) + allow(Bundler.settings).to receive(:[]).with(:ssl_client_cert).and_return("/cert") + expect(File).to receive(:read).with("/cert").and_return("") + expect(OpenSSL::X509::Certificate).to receive(:new).and_return("cert") + expect(OpenSSL::PKey::RSA).to receive(:new).and_return("key") + end + it "use bundler configuration" do + expect(fetcher.send(:connection).cert).to eq("cert") + expect(fetcher.send(:connection).key).to eq("key") + end + end + + context "when gem ssl configuration is set" do + before do + allow(Bundler.rubygems.configuration).to receive_messages( + :http_proxy => nil, + :ssl_client_cert => "cert", + :ssl_ca_cert => "ca" + ) + expect(File).to receive(:read).and_return("") + expect(OpenSSL::X509::Certificate).to receive(:new).and_return("cert") + expect(OpenSSL::PKey::RSA).to receive(:new).and_return("key") + store = double("ca store") + expect(store).to receive(:add_file) + expect(OpenSSL::X509::Store).to receive(:new).and_return(store) + end + it "use gem configuration" do + expect(fetcher.send(:connection).cert).to eq("cert") + expect(fetcher.send(:connection).key).to eq("key") + end + end end describe "#user_agent" do it "builds user_agent with current ruby version and Bundler settings" do - allow(Bundler.settings).to receive(:all).and_return(%w(foo bar)) + allow(Bundler.settings).to receive(:all).and_return(%w[foo bar]) expect(fetcher.user_agent).to match(%r{bundler/(\d.)}) expect(fetcher.user_agent).to match(%r{rubygems/(\d.)}) expect(fetcher.user_agent).to match(%r{ruby/(\d.)}) diff --git a/spec/bundler/bundler/friendly_errors_spec.rb b/spec/bundler/bundler/friendly_errors_spec.rb index 19799d5495..2a1be491ef 100644 --- a/spec/bundler/bundler/friendly_errors_spec.rb +++ b/spec/bundler/bundler/friendly_errors_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler" require "bundler/friendly_errors" require "cgi" @@ -39,7 +39,7 @@ RSpec.describe Bundler, "friendly errors" do bundle :install, :env => { "DEBUG" => true } - expect(err).to include("Failed to load #{home(".gemrc")}") + expect(last_command.stderr).to include("Failed to load #{home(".gemrc")}") expect(exitstatus).to eq(0) if exitstatus end end diff --git a/spec/bundler/bundler/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb index 498ed89447..c36204c542 100644 --- a/spec/bundler/bundler/gem_helper_spec.rb +++ b/spec/bundler/bundler/gem_helper_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "rake" require "bundler/gem_helper" @@ -105,8 +105,8 @@ RSpec.describe Bundler::GemHelper do context "defines Rake tasks" do let(:task_names) do - %w(build install release release:guard_clean - release:source_control_push release:rubygem_push) + %w[build install release release:guard_clean + release:source_control_push release:rubygem_push] end context "before installation" do @@ -256,5 +256,95 @@ RSpec.describe Bundler::GemHelper do end end end + + describe "release:rubygem_push" do + let!(:rake_application) { Rake.application } + + before(:each) do + Rake.application = Rake::Application.new + subject.install + allow(subject).to receive(:sh) + end + + after(:each) do + Rake.application = rake_application + end + + before do + Dir.chdir(app_path) do + `git init` + `git config user.email "you@example.com"` + `git config user.name "name"` + `git config push.default simple` + end + + # silence messages + allow(Bundler.ui).to receive(:confirm) + allow(Bundler.ui).to receive(:error) + + credentials = double("credentials", "file?" => true) + allow(Bundler.user_home).to receive(:join). + with(".gem/credentials").and_return(credentials) + end + + describe "success messaging" do + context "No allowed_push_host set" do + before do + allow(subject).to receive(:allowed_push_host).and_return(nil) + end + + around do |example| + orig_host = ENV["RUBYGEMS_HOST"] + ENV["RUBYGEMS_HOST"] = rubygems_host_env + + example.run + + ENV["RUBYGEMS_HOST"] = orig_host + end + + context "RUBYGEMS_HOST env var is set" do + let(:rubygems_host_env) { "https://custom.env.gemhost.com" } + + it "should report successful push to the host from the environment" do + mock_confirm_message "Pushed #{app_name} #{app_version} to #{rubygems_host_env}" + + Rake.application["release:rubygem_push"].invoke + end + end + + context "RUBYGEMS_HOST env var is not set" do + let(:rubygems_host_env) { nil } + + it "should report successful push to rubygems.org" do + mock_confirm_message "Pushed #{app_name} #{app_version} to rubygems.org" + + Rake.application["release:rubygem_push"].invoke + end + end + + context "RUBYGEMS_HOST env var is an empty string" do + let(:rubygems_host_env) { "" } + + it "should report successful push to rubygems.org" do + mock_confirm_message "Pushed #{app_name} #{app_version} to rubygems.org" + + Rake.application["release:rubygem_push"].invoke + end + end + end + + context "allowed_push_host set in gemspec" do + before do + allow(subject).to receive(:allowed_push_host).and_return("https://my.gemhost.com") + end + + it "should report successful push to the allowed gem host" do + mock_confirm_message "Pushed #{app_name} #{app_version} to https://my.gemhost.com" + + Rake.application["release:rubygem_push"].invoke + end + end + end + end end end diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb index c7620e2620..01e0232fba 100644 --- a/spec/bundler/bundler/gem_version_promoter_spec.rb +++ b/spec/bundler/bundler/gem_version_promoter_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::GemVersionPromoter do context "conservative resolver" do @@ -27,13 +26,15 @@ RSpec.describe Bundler::GemVersionPromoter do end end - def build_spec_group(name, version) - Bundler::Resolver::SpecGroup.new(build_spec(name, version)) + def build_spec_groups(name, versions) + versions.map do |v| + Bundler::Resolver::SpecGroup.new(build_spec(name, v)) + end end # Rightmost (highest array index) in result is most preferred. # Leftmost (lowest array index) in result is least preferred. - # `build_spec_group` has all version of gem in index. + # `build_spec_groups` has all versions of gem in index. # `build_spec` is the version currently in the .lock file. # # In default (not strict) mode, all versions in the index will @@ -44,28 +45,28 @@ RSpec.describe Bundler::GemVersionPromoter do it "when keeping build_spec, keep current, next release" do keep_locked(:level => :patch) res = @gvp.filter_dep_specs( - build_spec_group("foo", %w(1.7.8 1.7.9 1.8.0)), + build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]), build_spec("foo", "1.7.8").first ) - expect(versions(res)).to eq %w(1.7.9 1.7.8) + expect(versions(res)).to eq %w[1.7.9 1.7.8] end it "when unlocking prefer next release first" do unlocking(:level => :patch) res = @gvp.filter_dep_specs( - build_spec_group("foo", %w(1.7.8 1.7.9 1.8.0)), + build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]), build_spec("foo", "1.7.8").first ) - expect(versions(res)).to eq %w(1.7.8 1.7.9) + expect(versions(res)).to eq %w[1.7.8 1.7.9] end it "when unlocking keep current when already at latest release" do unlocking(:level => :patch) res = @gvp.filter_dep_specs( - build_spec_group("foo", %w(1.7.9 1.8.0 2.0.0)), + build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]), build_spec("foo", "1.7.9").first ) - expect(versions(res)).to eq %w(1.7.9) + expect(versions(res)).to eq %w[1.7.9] end end @@ -73,19 +74,19 @@ RSpec.describe Bundler::GemVersionPromoter do it "when unlocking favor next releases, remove minor and major increases" do unlocking(:level => :minor) res = @gvp.filter_dep_specs( - build_spec_group("foo", %w(0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1)), + build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), build_spec("foo", "0.2.0").first ) - expect(versions(res)).to eq %w(0.2.0 0.3.0 0.3.1 0.9.0) + expect(versions(res)).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0] end it "when keep locked, keep current, then favor next release, remove minor and major increases" do keep_locked(:level => :minor) res = @gvp.filter_dep_specs( - build_spec_group("foo", %w(0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1)), + build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), build_spec("foo", "0.2.0").first ) - expect(versions(res)).to eq %w(0.3.0 0.3.1 0.9.0 0.2.0) + expect(versions(res)).to eq %w[0.3.0 0.3.1 0.9.0 0.2.0] end end @@ -93,37 +94,37 @@ RSpec.describe Bundler::GemVersionPromoter do it "when not unlocking, same order but make sure build_spec version is most preferred to stay put" do keep_locked(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_group("foo", %w(1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1)), + build_spec_groups("foo", %w[1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1]), build_spec("foo", "1.7.7").first ) - expect(versions(res)).to eq %w(1.5.4 1.6.5 1.7.6 2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7) + expect(versions(res)).to eq %w[1.5.4 1.6.5 1.7.6 2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7] end it "when unlocking favor next release, then current over minor increase" do unlocking(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_group("foo", %w(1.7.7 1.7.8 1.7.9 1.8.0)), + build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.8.0]), build_spec("foo", "1.7.8").first ) - expect(versions(res)).to eq %w(1.7.7 1.8.0 1.7.8 1.7.9) + expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9] end it "when unlocking do proper integer comparison, not string" do unlocking(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_group("foo", %w(1.7.7 1.7.8 1.7.9 1.7.15 1.8.0)), + build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0]), build_spec("foo", "1.7.8").first ) - expect(versions(res)).to eq %w(1.7.7 1.8.0 1.7.8 1.7.9 1.7.15) + expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9 1.7.15] end it "leave current when unlocking but already at latest release" do unlocking(:level => :patch) res = @gvp.sort_dep_specs( - build_spec_group("foo", %w(1.7.9 1.8.0 2.0.0)), + build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]), build_spec("foo", "1.7.9").first ) - expect(versions(res)).to eq %w(2.0.0 1.8.0 1.7.9) + expect(versions(res)).to eq %w[2.0.0 1.8.0 1.7.9] end end @@ -131,10 +132,10 @@ RSpec.describe Bundler::GemVersionPromoter do it "when unlocking favor next release, then minor increase over current" do unlocking(:level => :minor) res = @gvp.sort_dep_specs( - build_spec_group("foo", %w(0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1)), + build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), build_spec("foo", "0.2.0").first ) - expect(versions(res)).to eq %w(2.0.0 2.0.1 1.0.0 0.2.0 0.3.0 0.3.1 0.9.0) + expect(versions(res)).to eq %w[2.0.0 2.0.1 1.0.0 0.2.0 0.3.0 0.3.1 0.9.0] end end @@ -159,7 +160,7 @@ RSpec.describe Bundler::GemVersionPromoter do end it "should accept major, minor patch strings" do - %w(major minor patch).each do |value| + %w[major minor patch].each do |value| subject.level = value expect(subject.level).to eq value.to_sym end @@ -170,8 +171,7 @@ RSpec.describe Bundler::GemVersionPromoter do it "should not kerblooie on its own debug output" do gvp = unlocking(:level => :patch) dep = Bundler::DepProxy.new(dep("foo", "1.2.0").first, "ruby") - result = gvp.send(:debug_format_result, dep, [build_spec_group("foo", "1.2.0"), - build_spec_group("foo", "1.3.0")]) + result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0])) expect(result.class).to eq Array end end diff --git a/spec/bundler/bundler/index_spec.rb b/spec/bundler/bundler/index_spec.rb index 09b09e08fa..0f3f6e4944 100644 --- a/spec/bundler/bundler/index_spec.rb +++ b/spec/bundler/bundler/index_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Index do let(:specs) { [] } diff --git a/spec/bundler/bundler/installer/gem_installer_spec.rb b/spec/bundler/bundler/installer/gem_installer_spec.rb index e2f30cdd70..7340a3acc0 100644 --- a/spec/bundler/bundler/installer/gem_installer_spec.rb +++ b/spec/bundler/bundler/installer/gem_installer_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/installer/gem_installer" RSpec.describe Bundler::GemInstaller do @@ -20,6 +20,7 @@ RSpec.describe Bundler::GemInstaller do it "invokes install method with build_args", :rubygems => ">= 2" do allow(Bundler.settings).to receive(:[]).with(:bin) allow(Bundler.settings).to receive(:[]).with(:inline) + allow(Bundler.settings).to receive(:[]).with(:forget_cli_options) allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy") expect(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => ["--with-dummy-config=dummy"]) subject.install_from_spec diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb index 7d2c441399..ace5c1a23a 100644 --- a/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/installer/parallel_installer" RSpec.describe Bundler::ParallelInstaller do diff --git a/spec/bundler/bundler/installer/spec_installation_spec.rb b/spec/bundler/bundler/installer/spec_installation_spec.rb index 1e368ab7c5..a9cf09a372 100644 --- a/spec/bundler/bundler/installer/spec_installation_spec.rb +++ b/spec/bundler/bundler/installer/spec_installation_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/installer/parallel_installer" RSpec.describe Bundler::ParallelInstaller::SpecInstallation do diff --git a/spec/bundler/bundler/lockfile_parser_spec.rb b/spec/bundler/bundler/lockfile_parser_spec.rb index 17bb447194..3a6d61336f 100644 --- a/spec/bundler/bundler/lockfile_parser_spec.rb +++ b/spec/bundler/bundler/lockfile_parser_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/lockfile_parser" RSpec.describe Bundler::LockfileParser do @@ -91,4 +91,63 @@ RSpec.describe Bundler::LockfileParser do end end end + + describe "#initialize" do + before { allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app("gems.rb")) } + subject { described_class.new(lockfile_contents) } + + let(:sources) do + [Bundler::Source::Git.new("uri" => "https://github.com/alloy/peiji-san.git", "revision" => "eca485d8dc95f12aaec1a434b49d295c7e91844b"), + Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"])] + end + let(:dependencies) do + { + "peiji-san" => Bundler::Dependency.new("peiji-san", ">= 0"), + "rake" => Bundler::Dependency.new("rake", ">= 0"), + } + end + let(:specs) do + [ + Bundler::LazySpecification.new("peiji-san", v("1.2.0"), rb), + Bundler::LazySpecification.new("rake", v("10.3.2"), rb), + ] + end + let(:platforms) { [rb] } + let(:bundler_version) { Gem::Version.new("1.12.0.rc.2") } + let(:ruby_version) { "ruby 2.1.3p242" } + + shared_examples_for "parsing" do + it "parses correctly" do + expect(subject.sources).to eq sources + expect(subject.dependencies).to eq dependencies + expect(subject.specs).to eq specs + expect(Hash[subject.specs.map {|s| [s, s.dependencies] }]).to eq Hash[subject.specs.map {|s| [s, s.dependencies] }] + expect(subject.platforms).to eq platforms + expect(subject.bundler_version).to eq bundler_version + expect(subject.ruby_version).to eq ruby_version + end + end + + include_examples "parsing" + + context "when an extra section is at the end" do + let(:lockfile_contents) { super() + "\n\nFOO BAR\n baz\n baa\n qux\n" } + include_examples "parsing" + end + + context "when an extra section is at the start" do + let(:lockfile_contents) { "FOO BAR\n baz\n baa\n qux\n\n" + super() } + include_examples "parsing" + end + + context "when an extra section is in the middle" do + let(:lockfile_contents) { super().split(/(?=GEM)/).insert(1, "FOO BAR\n baz\n baa\n qux\n\n").join } + include_examples "parsing" + end + + context "when a dependency has options" do + let(:lockfile_contents) { super().sub("peiji-san!", "peiji-san!\n foo: bar") } + include_examples "parsing" + end + end end diff --git a/spec/bundler/bundler/mirror_spec.rb b/spec/bundler/bundler/mirror_spec.rb index 9051a80465..0a8b9f8926 100644 --- a/spec/bundler/bundler/mirror_spec.rb +++ b/spec/bundler/bundler/mirror_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/mirror" RSpec.describe Bundler::Settings::Mirror do diff --git a/spec/bundler/bundler/plugin/api/source_spec.rb b/spec/bundler/bundler/plugin/api/source_spec.rb index 4dbb993b89..2c50ff56a4 100644 --- a/spec/bundler/bundler/plugin/api/source_spec.rb +++ b/spec/bundler/bundler/plugin/api/source_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Plugin::API::Source do let(:uri) { "uri://to/test" } @@ -37,7 +36,7 @@ RSpec.describe Bundler::Plugin::API::Source do context "install_path" do let(:uri) { "uri://to/a/repository-name" } - let(:hash) { Digest::SHA1.hexdigest(uri) } + let(:hash) { Digest(:SHA1).hexdigest(uri) } let(:install_path) { Pathname.new "/bundler/install/path" } before do diff --git a/spec/bundler/bundler/plugin/api_spec.rb b/spec/bundler/bundler/plugin/api_spec.rb index e40b9adb0f..58fb908572 100644 --- a/spec/bundler/bundler/plugin/api_spec.rb +++ b/spec/bundler/bundler/plugin/api_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Plugin::API do context "plugin declarations" do @@ -60,15 +59,15 @@ RSpec.describe Bundler::Plugin::API do # A test of delegation it "provides the Bundler's functions" do - expect(Bundler).to receive(:an_unkown_function).once + expect(Bundler).to receive(:an_unknown_function).once - api.an_unkown_function + api.an_unknown_function end it "includes Bundler::SharedHelpers' functions" do - expect(Bundler::SharedHelpers).to receive(:an_unkown_helper).once + expect(Bundler::SharedHelpers).to receive(:an_unknown_helper).once - api.an_unkown_helper + api.an_unknown_helper end context "#tmp" do diff --git a/spec/bundler/bundler/plugin/dsl_spec.rb b/spec/bundler/bundler/plugin/dsl_spec.rb index cd15b6ea9d..be23db3bba 100644 --- a/spec/bundler/bundler/plugin/dsl_spec.rb +++ b/spec/bundler/bundler/plugin/dsl_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Plugin::DSL do DSL = Bundler::Plugin::DSL diff --git a/spec/bundler/bundler/plugin/index_spec.rb b/spec/bundler/bundler/plugin/index_spec.rb index 24b9a408ff..163b563b2a 100644 --- a/spec/bundler/bundler/plugin/index_spec.rb +++ b/spec/bundler/bundler/plugin/index_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Plugin::Index do Index = Bundler::Plugin::Index diff --git a/spec/bundler/bundler/plugin/installer_spec.rb b/spec/bundler/bundler/plugin/installer_spec.rb index e8d5941e33..f8bf8450c9 100644 --- a/spec/bundler/bundler/plugin/installer_spec.rb +++ b/spec/bundler/bundler/plugin/installer_spec.rb @@ -1,12 +1,16 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Plugin::Installer do subject(:installer) { Bundler::Plugin::Installer.new } + before do + # allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(Pathname.new("/Gemfile")) + end + describe "cli install" do it "uses Gem.sources when non of the source is provided" do sources = double(:sources) + Bundler.settings # initialize it before we have to touch rubygems.ext_lock allow(Bundler).to receive_message_chain("rubygems.sources") { sources } allow(installer).to receive(:install_rubygems). diff --git a/spec/bundler/bundler/plugin/source_list_spec.rb b/spec/bundler/bundler/plugin/source_list_spec.rb index 86cc4ac4ed..64a1233dd1 100644 --- a/spec/bundler/bundler/plugin/source_list_spec.rb +++ b/spec/bundler/bundler/plugin/source_list_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Plugin::SourceList do SourceList = Bundler::Plugin::SourceList diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb index 5bbb7384c8..9796b580a3 100644 --- a/spec/bundler/bundler/plugin_spec.rb +++ b/spec/bundler/bundler/plugin_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Plugin do Plugin = Bundler::Plugin diff --git a/spec/bundler/bundler/psyched_yaml_spec.rb b/spec/bundler/bundler/psyched_yaml_spec.rb index 18e40d6b5a..d5d68c5cc3 100644 --- a/spec/bundler/bundler/psyched_yaml_spec.rb +++ b/spec/bundler/bundler/psyched_yaml_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/psyched_yaml" RSpec.describe "Bundler::YamlLibrarySyntaxError" do diff --git a/spec/bundler/bundler/remote_specification_spec.rb b/spec/bundler/bundler/remote_specification_spec.rb index 644814c563..8115e026d8 100644 --- a/spec/bundler/bundler/remote_specification_spec.rb +++ b/spec/bundler/bundler/remote_specification_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::RemoteSpecification do let(:name) { "foo" } diff --git a/spec/bundler/bundler/retry_spec.rb b/spec/bundler/bundler/retry_spec.rb index 525f05d327..b893580d72 100644 --- a/spec/bundler/bundler/retry_spec.rb +++ b/spec/bundler/bundler/retry_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Retry do it "return successful result if no errors" do diff --git a/spec/bundler/bundler/ruby_dsl_spec.rb b/spec/bundler/bundler/ruby_dsl_spec.rb index 3e0ec9d7f0..bc1ca98457 100644 --- a/spec/bundler/bundler/ruby_dsl_spec.rb +++ b/spec/bundler/bundler/ruby_dsl_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/ruby_dsl" RSpec.describe Bundler::RubyDsl do diff --git a/spec/bundler/bundler/ruby_version_spec.rb b/spec/bundler/bundler/ruby_version_spec.rb index f77ec606fc..3f30821b5c 100644 --- a/spec/bundler/bundler/ruby_version_spec.rb +++ b/spec/bundler/bundler/ruby_version_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/ruby_version" RSpec.describe "Bundler::RubyVersion and its subclasses" do diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb index 38ff9dae7e..b1b15d9e5d 100644 --- a/spec/bundler/bundler/rubygems_integration_spec.rb +++ b/spec/bundler/bundler/rubygems_integration_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::RubygemsIntegration do it "uses the same chdir lock as rubygems", :rubygems => "2.1" do @@ -67,7 +66,7 @@ RSpec.describe Bundler::RubygemsIntegration do end let(:fetcher) { double("gem_remote_fetcher") } - it "succesfully downloads gem with retries" do + it "successfully downloads gem with retries" do expect(Bundler.rubygems).to receive(:gem_remote_fetcher).and_return(fetcher) expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "https://foo.bar") expect(Bundler::Retry).to receive(:new).with("download gem from #{uri}/"). @@ -95,7 +94,7 @@ RSpec.describe Bundler::RubygemsIntegration do expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response) expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response) result = Bundler.rubygems.fetch_all_remote_specs(remote_with_mirror) - expect(result).to eq(%w(specs prerelease_specs)) + expect(result).to eq(%w[specs prerelease_specs]) end end @@ -108,7 +107,7 @@ RSpec.describe Bundler::RubygemsIntegration do expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response) expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response) result = Bundler.rubygems.fetch_all_remote_specs(remote_no_mirror) - expect(result).to eq(%w(specs prerelease_specs)) + expect(result).to eq(%w[specs prerelease_specs]) end end end diff --git a/spec/bundler/bundler/settings/validator_spec.rb b/spec/bundler/bundler/settings/validator_spec.rb new file mode 100644 index 0000000000..e4ffd89435 --- /dev/null +++ b/spec/bundler/bundler/settings/validator_spec.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +RSpec.describe Bundler::Settings::Validator do + describe ".validate!" do + def validate!(key, value, settings) + transformed_key = Bundler.settings.key_for(key) + if value.nil? + settings.delete(transformed_key) + else + settings[transformed_key] = value + end + described_class.validate!(key, value, settings) + settings + end + + it "path and path.system are mutually exclusive" do + expect(validate!("path", "bundle", {})).to eq("BUNDLE_PATH" => "bundle") + expect(validate!("path", "bundle", "BUNDLE_PATH__SYSTEM" => false)).to eq("BUNDLE_PATH" => "bundle") + expect(validate!("path", "bundle", "BUNDLE_PATH__SYSTEM" => true)).to eq("BUNDLE_PATH" => "bundle") + expect(validate!("path", nil, "BUNDLE_PATH__SYSTEM" => true)).to eq("BUNDLE_PATH__SYSTEM" => true) + expect(validate!("path", nil, "BUNDLE_PATH__SYSTEM" => false)).to eq("BUNDLE_PATH__SYSTEM" => false) + expect(validate!("path", nil, {})).to eq({}) + + expect(validate!("path.system", true, "BUNDLE_PATH" => "bundle")).to eq("BUNDLE_PATH__SYSTEM" => true) + expect(validate!("path.system", false, "BUNDLE_PATH" => "bundle")).to eq("BUNDLE_PATH" => "bundle", "BUNDLE_PATH__SYSTEM" => false) + expect(validate!("path.system", nil, "BUNDLE_PATH" => "bundle")).to eq("BUNDLE_PATH" => "bundle") + expect(validate!("path.system", true, {})).to eq("BUNDLE_PATH__SYSTEM" => true) + expect(validate!("path.system", false, {})).to eq("BUNDLE_PATH__SYSTEM" => false) + expect(validate!("path.system", nil, {})).to eq({}) + end + + it "a group cannot be in both `with` & `without` simultaneously" do + expect do + validate!("with", "", {}) + validate!("with", nil, {}) + validate!("with", "", "BUNDLE_WITHOUT" => "a") + validate!("with", nil, "BUNDLE_WITHOUT" => "a") + validate!("with", "b:c", "BUNDLE_WITHOUT" => "a") + + validate!("without", "", {}) + validate!("without", nil, {}) + validate!("without", "", "BUNDLE_WITH" => "a") + validate!("without", nil, "BUNDLE_WITH" => "a") + validate!("without", "b:c", "BUNDLE_WITH" => "a") + end.not_to raise_error + + expect { validate!("with", "b:c", "BUNDLE_WITHOUT" => "c:d") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip + Setting `with` to "b:c" failed: + - a group cannot be in both `with` & `without` simultaneously + - `without` is current set to [:c, :d] + - the `c` groups conflict + EOS + + expect { validate!("without", "b:c", "BUNDLE_WITH" => "c:d") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip + Setting `without` to "b:c" failed: + - a group cannot be in both `with` & `without` simultaneously + - `with` is current set to [:c, :d] + - the `c` groups conflict + EOS + end + end + + describe described_class::Rule do + let(:keys) { %w[key] } + let(:description) { "rule description" } + let(:validate) { proc { raise "validate called!" } } + subject(:rule) { described_class.new(keys, description, &validate) } + + describe "#validate!" do + it "calls the block" do + expect { rule.validate!("key", nil, {}) }.to raise_error(RuntimeError, /validate called!/) + end + end + + describe "#fail!" do + it "raises with a helpful message" do + expect { subject.fail!("key", "value", "reason1", "reason2") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip + Setting `key` to "value" failed: + - rule description + - reason1 + - reason2 + EOS + end + end + + describe "#set" do + it "works when the value has not changed" do + allow(Bundler.ui).to receive(:info).never + + subject.set({}, "key", nil) + subject.set({ "BUNDLE_KEY" => "value" }, "key", "value") + end + + it "prints out when the value is changing" do + settings = {} + + expect(Bundler.ui).to receive(:info).with("Setting `key` to \"value\", since rule description, reason1") + subject.set(settings, "key", "value", "reason1") + expect(settings).to eq("BUNDLE_KEY" => "value") + + expect(Bundler.ui).to receive(:info).with("Setting `key` to \"value2\", since rule description, reason2") + subject.set(settings, "key", "value2", "reason2") + expect(settings).to eq("BUNDLE_KEY" => "value2") + + expect(Bundler.ui).to receive(:info).with("Setting `key` to nil, since rule description, reason3") + subject.set(settings, "key", nil, "reason3") + expect(settings).to eq({}) + end + end + end +end diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb index 7302da5421..1a31493e20 100644 --- a/spec/bundler/bundler/settings_spec.rb +++ b/spec/bundler/bundler/settings_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/settings" RSpec.describe Bundler::Settings do @@ -40,7 +40,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow before do hash.each do |key, value| - settings[key] = value + settings.set_local key, value end end @@ -100,12 +100,12 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow context "when is boolean" do it "returns a boolean" do - settings[:frozen] = "true" + settings.set_local :frozen, "true" expect(settings[:frozen]).to be true end context "when specific gem is configured" do it "returns a boolean" do - settings["ignore_messages.foobar"] = "true" + settings.set_local "ignore_messages.foobar", "true" expect(settings["ignore_messages.foobar"]).to be true end end @@ -113,16 +113,16 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow context "when is number" do it "returns a number" do - settings[:ssl_verify_mode] = "1" + settings.set_local :ssl_verify_mode, "1" expect(settings[:ssl_verify_mode]).to be 1 end end context "when it's not possible to write to the file" do it "raises an PermissionError with explanation" do - expect(FileUtils).to receive(:mkdir_p).with(settings.send(:local_config_file).dirname). + expect(bundler_fileutils).to receive(:mkdir_p).with(settings.send(:local_config_file).dirname). and_raise(Errno::EACCES) - expect { settings[:frozen] = "1" }. + expect { settings.set_local :frozen, "1" }. to raise_error(Bundler::PermissionError, /config/) end end @@ -130,7 +130,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow describe "#temporary" do it "reset after used" do - Bundler.settings[:no_install] = true + Bundler.settings.set_local :no_install, true Bundler.settings.temporary(:no_install => false) do expect(Bundler.settings[:no_install]).to eq false @@ -138,12 +138,28 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow expect(Bundler.settings[:no_install]).to eq true end + + it "returns the return value of the block" do + ret = Bundler.settings.temporary({}) { :ret } + expect(ret).to eq :ret + end + + context "when called without a block" do + it "leaves the setting changed" do + Bundler.settings.temporary(:foo => :random) + expect(Bundler.settings[:foo]).to eq "random" + end + + it "returns nil" do + expect(Bundler.settings.temporary(:foo => :bar)).to be_nil + end + end end describe "#set_global" do context "when it's not possible to write to the file" do it "raises an PermissionError with explanation" do - expect(FileUtils).to receive(:mkdir_p).with(settings.send(:global_config_file).dirname). + expect(bundler_fileutils).to receive(:mkdir_p).with(settings.send(:global_config_file).dirname). and_raise(Errno::EACCES) expect { settings.set_global(:frozen, "1") }. to raise_error(Bundler::PermissionError, %r{\.bundle/config}) @@ -154,7 +170,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow describe "#pretty_values_for" do it "prints the converted value rather than the raw string" do bool_key = described_class::BOOL_KEYS.first - settings[bool_key] = false + settings.set_local(bool_key, "false") expect(subject.pretty_values_for(bool_key)).to eq [ "Set for your local app (#{bundled_app("config")}): false", ] @@ -177,7 +193,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow context "with a configured mirror" do let(:mirror_uri) { URI("https://rubygems-mirror.org/") } - before { settings["mirror.https://rubygems.org/"] = mirror_uri.to_s } + before { settings.set_local "mirror.https://rubygems.org/", mirror_uri.to_s } it "returns the mirror URI" do expect(settings.mirror_for(uri)).to eq(mirror_uri) @@ -194,6 +210,22 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow it "is case insensitive" do expect(settings.mirror_for("HTTPS://RUBYGEMS.ORG/")).to eq(mirror_uri) end + + context "with a file URI" do + let(:mirror_uri) { URI("file:/foo/BAR/baz/qUx/") } + + it "returns the mirror URI" do + expect(settings.mirror_for(uri)).to eq(mirror_uri) + end + + it "converts a string parameter to a URI" do + expect(settings.mirror_for("file:/foo/BAR/baz/qUx/")).to eq(mirror_uri) + end + + it "normalizes the URI" do + expect(settings.mirror_for("file:/foo/BAR/baz/qUx")).to eq(mirror_uri) + end + end end end @@ -208,7 +240,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow end context "with credentials configured by URL" do - before { settings["https://gemserver.example.org/"] = credentials } + before { settings.set_local "https://gemserver.example.org/", credentials } it "returns the configured credentials" do expect(settings.credentials_for(uri)).to eq(credentials) @@ -216,7 +248,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow end context "with credentials configured by hostname" do - before { settings["gemserver.example.org"] = credentials } + before { settings.set_local "gemserver.example.org", credentials } it "returns the configured credentials" do expect(settings.credentials_for(uri)).to eq(credentials) @@ -226,41 +258,51 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow describe "URI normalization" do it "normalizes HTTP URIs in credentials configuration" do - settings["http://gemserver.example.org"] = "username:password" + settings.set_local "http://gemserver.example.org", "username:password" expect(settings.all).to include("http://gemserver.example.org/") end it "normalizes HTTPS URIs in credentials configuration" do - settings["https://gemserver.example.org"] = "username:password" + settings.set_local "https://gemserver.example.org", "username:password" expect(settings.all).to include("https://gemserver.example.org/") end it "normalizes HTTP URIs in mirror configuration" do - settings["mirror.http://rubygems.org"] = "http://rubygems-mirror.org" + settings.set_local "mirror.http://rubygems.org", "http://rubygems-mirror.org" expect(settings.all).to include("mirror.http://rubygems.org/") end it "normalizes HTTPS URIs in mirror configuration" do - settings["mirror.https://rubygems.org"] = "http://rubygems-mirror.org" + settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org" expect(settings.all).to include("mirror.https://rubygems.org/") end it "does not normalize other config keys that happen to contain 'http'" do - settings["local.httparty"] = home("httparty") + settings.set_local "local.httparty", home("httparty") expect(settings.all).to include("local.httparty") end it "does not normalize other config keys that happen to contain 'https'" do - settings["local.httpsmarty"] = home("httpsmarty") + settings.set_local "local.httpsmarty", home("httpsmarty") expect(settings.all).to include("local.httpsmarty") end it "reads older keys without trailing slashes" do - settings["mirror.https://rubygems.org"] = "http://rubygems-mirror.org" + settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org" expect(settings.mirror_for("https://rubygems.org/")).to eq( URI("http://rubygems-mirror.org/") ) end + + it "normalizes URIs with a fallback_timeout option" do + settings.set_local "mirror.https://rubygems.org/.fallback_timeout", "true" + expect(settings.all).to include("mirror.https://rubygems.org/.fallback_timeout") + end + + it "normalizes URIs with a fallback_timeout option without a trailing slash" do + settings.set_local "mirror.https://rubygems.org.fallback_timeout", "true" + expect(settings.all).to include("mirror.https://rubygems.org/.fallback_timeout") + end end describe "BUNDLE_ keys format" do diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb index d3b93b56d0..b8f099d5ba 100644 --- a/spec/bundler/bundler/shared_helpers_spec.rb +++ b/spec/bundler/bundler/shared_helpers_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::SharedHelpers do let(:ext_lock_double) { double(:ext_lock) } @@ -31,6 +30,16 @@ RSpec.describe Bundler::SharedHelpers do ) end end + + context "Gemfile is not an absolute path" do + before { ENV["BUNDLE_GEMFILE"] = "Gemfile" } + + let(:expected_gemfile_path) { Pathname.new("Gemfile").expand_path } + + it "returns the Gemfile path" do + expect(subject.default_gemfile).to eq(expected_gemfile_path) + end + end end describe "#default_lockfile" do @@ -102,7 +111,7 @@ RSpec.describe Bundler::SharedHelpers do context "currently in directory with a Gemfile" do before { File.new("Gemfile", "w") } - it "returns path of the bundle gemfile" do + it "returns path of the bundle Gemfile" do expect(subject.in_bundle?).to eq("#{bundled_app}/Gemfile") end end @@ -252,20 +261,53 @@ RSpec.describe Bundler::SharedHelpers do subject.set_bundle_environment end - it "exits if bundle path contains the path seperator" do - stub_const("File::PATH_SEPARATOR", ":".freeze) + it "exits if bundle path contains the unix-like path separator" do + if Gem.respond_to?(:path_separator) + allow(Gem).to receive(:path_separator).and_return(":") + else + stub_const("File::PATH_SEPARATOR", ":".freeze) + end allow(Bundler).to receive(:bundle_path) { Pathname.new("so:me/dir/bin") } expect { subject.send(:validate_bundle_path) }.to raise_error( Bundler::PathError, - "Your bundle path contains a ':', which is the " \ + "Your bundle path contains text matching \":\", which is the " \ "path separator for your system. Bundler cannot " \ "function correctly when the Bundle path contains the " \ "system's PATH separator. Please change your " \ - "bundle path to not include ':'.\nYour current bundle " \ + "bundle path to not match \":\".\nYour current bundle " \ "path is '#{Bundler.bundle_path}'." ) end + context "with a jruby path_separator regex", :ruby => "1.9" do + # In versions of jruby that supported ruby 1.8, the path separator was the standard File::PATH_SEPARATOR + let(:regex) { Regexp.new("(?<!jar:file|jar|file|classpath|uri:classloader|uri|http|https):") } + it "does not exit if bundle path is the standard uri path" do + allow(Bundler.rubygems).to receive(:path_separator).and_return(regex) + allow(Bundler).to receive(:bundle_path) { Pathname.new("uri:classloader:/WEB-INF/gems") } + expect { subject.send(:validate_bundle_path) }.not_to raise_error + end + + it "exits if bundle path contains another directory" do + allow(Bundler.rubygems).to receive(:path_separator).and_return(regex) + allow(Bundler).to receive(:bundle_path) { + Pathname.new("uri:classloader:/WEB-INF/gems:other/dir") + } + + expect { subject.send(:validate_bundle_path) }.to raise_error( + Bundler::PathError, + "Your bundle path contains text matching " \ + "/(?<!jar:file|jar|file|classpath|uri:classloader|uri|http|https):/, which is the " \ + "path separator for your system. Bundler cannot " \ + "function correctly when the Bundle path contains the " \ + "system's PATH separator. Please change your " \ + "bundle path to not match " \ + "/(?<!jar:file|jar|file|classpath|uri:classloader|uri|http|https):/." \ + "\nYour current bundle path is '#{Bundler.bundle_path}'." + ) + end + end + context "ENV['PATH'] does not exist" do before { ENV.delete("PATH") } diff --git a/spec/bundler/bundler/source/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb index 34fe21e9fb..d282a449a5 100644 --- a/spec/bundler/bundler/source/git/git_proxy_spec.rb +++ b/spec/bundler/bundler/source/git/git_proxy_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Source::Git::GitProxy do let(:uri) { "https://github.com/bundler/bundler.git" } @@ -7,25 +6,25 @@ RSpec.describe Bundler::Source::Git::GitProxy do context "with configured credentials" do it "adds username and password to URI" do - Bundler.settings[uri] = "u:p" + Bundler.settings.temporary(uri => "u:p") expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) subject.checkout end it "adds username and password to URI for host" do - Bundler.settings["github.com"] = "u:p" + Bundler.settings.temporary("github.com" => "u:p") expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) subject.checkout end it "does not add username and password to mismatched URI" do - Bundler.settings["https://u:p@github.com/bundler/bundler-mismatch.git"] = "u:p" + Bundler.settings.temporary("https://u:p@github.com/bundler/bundler-mismatch.git" => "u:p") expect(subject).to receive(:git_retry).with(match(uri)) subject.checkout end it "keeps original userinfo" do - Bundler.settings["github.com"] = "u:p" + Bundler.settings.temporary("github.com" => "u:p") original = "https://orig:info@github.com/bundler/bundler.git" subject = described_class.new(Pathname("path"), original, "HEAD") expect(subject).to receive(:git_retry).with(match(original)) diff --git a/spec/bundler/bundler/source/rubygems/remote_spec.rb b/spec/bundler/bundler/source/rubygems/remote_spec.rb index 54394fc0ca..9a7ab42128 100644 --- a/spec/bundler/bundler/source/rubygems/remote_spec.rb +++ b/spec/bundler/bundler/source/rubygems/remote_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/source/rubygems/remote" RSpec.describe Bundler::Source::Rubygems::Remote do @@ -8,7 +8,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do end before do - allow(Digest::MD5).to receive(:hexdigest).with(duck_type(:to_s)) {|string| "MD5HEX(#{string})" } + allow(Digest(:MD5)).to receive(:hexdigest).with(duck_type(:to_s)) {|string| "MD5HEX(#{string})" } end let(:uri_no_auth) { URI("https://gems.example.com") } @@ -22,7 +22,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do end it "applies configured credentials" do - Bundler.settings[uri_no_auth.to_s] = credentials + Bundler.settings.temporary(uri_no_auth.to_s => credentials) expect(remote(uri_no_auth).uri).to eq(uri_with_auth) end end @@ -33,7 +33,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do end it "does not apply given credentials" do - Bundler.settings[uri_no_auth.to_s] = credentials + Bundler.settings.temporary(uri_no_auth.to_s => credentials) expect(remote(uri_no_auth).anonymized_uri).to eq(uri_no_auth) end end @@ -44,7 +44,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do end it "only applies the given user" do - Bundler.settings[uri_no_auth.to_s] = credentials + Bundler.settings.temporary(uri_no_auth.to_s => credentials) expect(remote(uri_no_auth).cache_slug).to eq("gems.example.com.username.443.MD5HEX(gems.example.com.username.443./)") end end @@ -57,7 +57,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do end it "does not apply configured credentials" do - Bundler.settings[uri_no_auth.to_s] = "other:stuff" + Bundler.settings.temporary(uri_no_auth.to_s => "other:stuff") expect(remote(uri_with_auth).uri).to eq(uri_with_auth) end end @@ -68,7 +68,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do end it "does not apply given credentials" do - Bundler.settings[uri_no_auth.to_s] = "other:stuff" + Bundler.settings.temporary(uri_no_auth.to_s => "other:stuff") expect(remote(uri_with_auth).anonymized_uri).to eq(uri_no_auth) end end @@ -79,7 +79,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do end it "does not apply given credentials" do - Bundler.settings[uri_with_auth.to_s] = credentials + Bundler.settings.temporary(uri_with_auth.to_s => credentials) expect(remote(uri_with_auth).cache_slug).to eq("gems.example.com.username.443.MD5HEX(gems.example.com.username.443./)") end end @@ -106,7 +106,7 @@ RSpec.describe Bundler::Source::Rubygems::Remote do let(:mirror_uri_with_auth) { URI("https://username:password@rubygems-mirror.org/") } let(:mirror_uri_no_auth) { URI("https://rubygems-mirror.org/") } - before { Bundler.settings["mirror.https://rubygems.org/"] = mirror_uri_with_auth.to_s } + before { Bundler.settings.set_local("mirror.https://rubygems.org/", mirror_uri_with_auth.to_s) } specify "#uri returns the mirror URI with credentials" do expect(remote(uri).uri).to eq(mirror_uri_with_auth) @@ -131,8 +131,8 @@ RSpec.describe Bundler::Source::Rubygems::Remote do let(:mirror_uri_no_auth) { URI("https://rubygems-mirror.org/") } before do - Bundler.settings["mirror.https://rubygems.org/"] = mirror_uri_no_auth.to_s - Bundler.settings[mirror_uri_no_auth.to_s] = credentials + Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_no_auth.to_s) + Bundler.settings.temporary(mirror_uri_no_auth.to_s => credentials) end specify "#uri returns the mirror URI with credentials" do diff --git a/spec/bundler/bundler/source/rubygems_spec.rb b/spec/bundler/bundler/source/rubygems_spec.rb index b8f9f09c20..7c457a7265 100644 --- a/spec/bundler/bundler/source/rubygems_spec.rb +++ b/spec/bundler/bundler/source/rubygems_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Source::Rubygems do before do diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb index 6a23c8bcbf..ce3353012c 100644 --- a/spec/bundler/bundler/source_list_spec.rb +++ b/spec/bundler/bundler/source_list_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::SourceList do before do @@ -13,6 +12,7 @@ RSpec.describe Bundler::SourceList do subject(:source_list) { Bundler::SourceList.new } let(:rubygems_aggregate) { Bundler::Source::Rubygems.new } + let(:metadata_source) { Bundler::Source::Metadata.new } describe "adding sources" do before do @@ -85,7 +85,7 @@ RSpec.describe Bundler::SourceList do end it "ignores git protocols on request" do - Bundler.settings["git.allow_insecure"] = true + Bundler.settings.temporary(:"git.allow_insecure" => true) expect(Bundler.ui).to_not receive(:warn).with(msg) source_list.add_git_source("uri" => "git://existing-git.org/path.git") end @@ -115,18 +115,19 @@ RSpec.describe Bundler::SourceList do end end - describe "#add_rubygems_remote" do - before do - @returned_source = source_list.add_rubygems_remote("https://rubygems.org/") - end + describe "#add_rubygems_remote", :bundler => "< 2" do + let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") } it "returns the aggregate rubygems source" do - expect(@returned_source).to be_instance_of(Bundler::Source::Rubygems) + expect(returned_source).to be_instance_of(Bundler::Source::Rubygems) end it "adds the provided remote to the beginning of the aggregate source" do source_list.add_rubygems_remote("https://othersource.org") - expect(@returned_source.remotes.first).to eq(URI("https://othersource.org/")) + expect(returned_source.remotes).to eq [ + URI("https://othersource.org/"), + URI("https://rubygems.org/"), + ] end end @@ -204,6 +205,7 @@ RSpec.describe Bundler::SourceList do Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]), Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]), rubygems_aggregate, + metadata_source, ] end end @@ -354,7 +356,7 @@ RSpec.describe Bundler::SourceList do end describe "#lock_sources" do - it "combines the rubygems sources into a single instance, removing duplicate remotes from the end" do + before do source_list.add_git_source("uri" => "git://third-git.org/path.git") source_list.add_rubygems_source("remotes" => ["https://duplicate-rubygems.org"]) source_list.add_plugin_source("new_source", "uri" => "https://third-bar.org/foo") @@ -368,7 +370,9 @@ RSpec.describe Bundler::SourceList do source_list.add_path_source("path" => "/first/path/to/gem") source_list.add_rubygems_source("remotes" => ["https://duplicate-rubygems.org"]) source_list.add_git_source("uri" => "git://first-git.org/path.git") + end + it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 2" do expect(source_list.lock_sources).to eq [ Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), @@ -386,6 +390,24 @@ RSpec.describe Bundler::SourceList do ]), ] end + + it "returns all sources, without combining rubygems sources", :bundler => "2" do + expect(source_list.lock_sources).to eq [ + Bundler::Source::Rubygems.new, + Bundler::Source::Rubygems.new("remotes" => ["https://duplicate-rubygems.org"]), + Bundler::Source::Rubygems.new("remotes" => ["https://first-rubygems.org"]), + Bundler::Source::Rubygems.new("remotes" => ["https://second-rubygems.org"]), + Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]), + Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), + Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), + Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), + Bundler::Source::Path.new("path" => "/first/path/to/gem"), + Bundler::Source::Path.new("path" => "/second/path/to/gem"), + Bundler::Source::Path.new("path" => "/third/path/to/gem"), + ASourcePlugin.new("uri" => "https://second-plugin.org/random"), + ASourcePlugin.new("uri" => "https://third-bar.org/foo"), + ] + end end describe "replace_sources!" do @@ -414,7 +436,7 @@ RSpec.describe Bundler::SourceList do end describe "#cached!" do - let(:rubygems_source) { source_list.add_rubygems_remote("https://rubygems.org") } + let(:rubygems_source) { source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) } let(:git_source) { source_list.add_git_source("uri" => "git://host/path.git") } let(:path_source) { source_list.add_path_source("path" => "/path/to/gem") } @@ -427,7 +449,7 @@ RSpec.describe Bundler::SourceList do end describe "#remote!" do - let(:rubygems_source) { source_list.add_rubygems_remote("https://rubygems.org") } + let(:rubygems_source) { source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) } let(:git_source) { source_list.add_git_source("uri" => "git://host/path.git") } let(:path_source) { source_list.add_path_source("path" => "/path/to/gem") } diff --git a/spec/bundler/bundler/source_spec.rb b/spec/bundler/bundler/source_spec.rb index 08d1698fcd..9ef8e7e50f 100644 --- a/spec/bundler/bundler/source_spec.rb +++ b/spec/bundler/bundler/source_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::Source do class ExampleSource < Bundler::Source diff --git a/spec/bundler/bundler/spec_set_spec.rb b/spec/bundler/bundler/spec_set_spec.rb index 8f7c27f065..6fedd38b50 100644 --- a/spec/bundler/bundler/spec_set_spec.rb +++ b/spec/bundler/bundler/spec_set_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::SpecSet do let(:specs) do @@ -17,6 +16,7 @@ RSpec.describe Bundler::SpecSet do build_spec("e", "1.0.0.pre.1"), ].flatten end + subject { described_class.new(specs) } context "enumerable methods" do @@ -29,15 +29,49 @@ RSpec.describe Bundler::SpecSet do end end + describe "#find_by_name_and_platform" do + let(:platform) { Gem::Platform.new("universal-darwin-64") } + let(:platform_spec) { build_spec("b", "2.0", platform).first } + let(:specs) do + [ + build_spec("a", "1.0"), + platform_spec, + ].flatten + end + + it "finds spec with given name and platform" do + spec = described_class.new(specs).find_by_name_and_platform("b", platform) + expect(spec).to eq platform_spec + end + end + + describe "#merge" do + let(:other_specs) do + [ + build_spec("f", "1.0"), + build_spec("g", "2.0"), + ].flatten + end + + let(:other_spec_set) { described_class.new(other_specs) } + + it "merges the items in each gemspec" do + new_spec_set = subject.merge(other_spec_set) + specs = new_spec_set.to_a.map(&:full_name) + expect(specs).to include("a-1.0") + expect(specs).to include("f-1.0") + end + end + describe "#to_a" do it "returns the specs in order" do - expect(subject.to_a.map(&:full_name)).to eq %w( + expect(subject.to_a.map(&:full_name)).to eq %w[ a-1.0 b-1.0 e-1.0.0.pre.1 c-1.1 d-2.0 - ) + ] end end end diff --git a/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb b/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb index 66853a6815..d1ec08bdc4 100644 --- a/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb +++ b/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/ssl_certs/certificate_manager" RSpec.describe Bundler::SSLCerts::CertificateManager do @@ -78,17 +78,17 @@ RSpec.describe Bundler::SSLCerts::CertificateManager do context "when certificate manager is not up to date" do before do allow(subject).to receive(:up_to_date?).and_return(false) - allow(FileUtils).to receive(:rm) - allow(FileUtils).to receive(:cp) + allow(bundler_fileutils).to receive(:rm) + allow(bundler_fileutils).to receive(:cp) end it "should remove the current bundler certs" do - expect(FileUtils).to receive(:rm).with(subject.bundler_certs) + expect(bundler_fileutils).to receive(:rm).with(subject.bundler_certs) subject.update! end it "should copy the rubygems certs into bundler certs" do - expect(FileUtils).to receive(:cp).with(subject.rubygems_certs, subject.bundler_cert_path) + expect(bundler_fileutils).to receive(:cp).with(subject.rubygems_certs, subject.bundler_cert_path) subject.update! end diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb index f1ddf43bb4..5521d83769 100644 --- a/spec/bundler/bundler/stub_specification_spec.rb +++ b/spec/bundler/bundler/stub_specification_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::StubSpecification do let(:gemspec) do diff --git a/spec/bundler/bundler/ui/shell_spec.rb b/spec/bundler/bundler/ui/shell_spec.rb new file mode 100644 index 0000000000..9a47a3572f --- /dev/null +++ b/spec/bundler/bundler/ui/shell_spec.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +RSpec.describe Bundler::UI::Shell do + subject { described_class.new } + + before { subject.level = "debug" } + + describe "#info" do + before { subject.level = "info" } + it "prints to stdout" do + expect { subject.info("info") }.to output("info\n").to_stdout + end + end + + describe "#confirm" do + before { subject.level = "confirm" } + it "prints to stdout" do + expect { subject.confirm("confirm") }.to output("confirm\n").to_stdout + end + end + + describe "#warn" do + before { subject.level = "warn" } + it "prints to stdout", :bundler => "< 2" do + expect { subject.warn("warning") }.to output("warning\n").to_stdout + end + + it "prints to stderr", :bundler => "2" do + expect { subject.warn("warning") }.to output("warning\n").to_stderr + end + + context "when stderr flag is enabled" do + before { Bundler.settings.temporary(:error_on_stderr => true) } + it "prints to stderr" do + expect { subject.warn("warning!") }.to output("warning!\n").to_stderr + end + end + end + + describe "#debug" do + it "prints to stdout" do + expect { subject.debug("debug") }.to output("debug\n").to_stdout + end + end + + describe "#error" do + before { subject.level = "error" } + + it "prints to stdout", :bundler => "< 2" do + expect { subject.error("error!!!") }.to output("error!!!\n").to_stdout + end + + it "prints to stderr", :bundler => "2" do + expect { subject.error("error!!!") }.to output("error!!!\n").to_stderr + end + + context "when stderr flag is enabled" do + before { Bundler.settings.temporary(:error_on_stderr => true) } + it "prints to stderr" do + expect { subject.error("error!!!") }.to output("error!!!\n").to_stderr + end + end + end +end diff --git a/spec/bundler/bundler/ui_spec.rb b/spec/bundler/bundler/ui_spec.rb index fc76eb1ee7..6ef8729277 100644 --- a/spec/bundler/bundler/ui_spec.rb +++ b/spec/bundler/bundler/ui_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::UI do describe Bundler::UI::Silent do diff --git a/spec/bundler/bundler/uri_credentials_filter_spec.rb b/spec/bundler/bundler/uri_credentials_filter_spec.rb index 1dd01b4be0..fe52d16306 100644 --- a/spec/bundler/bundler/uri_credentials_filter_spec.rb +++ b/spec/bundler/bundler/uri_credentials_filter_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe Bundler::URICredentialsFilter do subject { described_class } diff --git a/spec/bundler/bundler/vendored_persistent_spec.rb b/spec/bundler/bundler/vendored_persistent_spec.rb new file mode 100644 index 0000000000..338431c4a6 --- /dev/null +++ b/spec/bundler/bundler/vendored_persistent_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require "spec_helper" +require "bundler/vendored_persistent" + +RSpec.describe Bundler::PersistentHTTP do + describe "#warn_old_tls_version_rubygems_connection" do + let(:uri) { "https://index.rubygems.org" } + let(:connection) { instance_double(subject.http_class) } + let(:tls_version) { "TLSv1.2" } + let(:socket) { double("Socket") } + let(:socket_io) { double("SocketIO") } + + before do + allow(connection).to receive(:use_ssl?).and_return(!tls_version.nil?) + allow(socket).to receive(:io).and_return(socket_io) + connection.instance_variable_set(:@socket, socket) + + if tls_version + allow(socket_io).to receive(:ssl_version).and_return(tls_version) + end + end + + shared_examples_for "does not warn" do + it "does not warn" do + allow(Bundler.ui).to receive(:warn).never + subject.warn_old_tls_version_rubygems_connection(URI(uri), connection) + end + end + + shared_examples_for "does warn" do |*expected| + it "warns" do + expect(Bundler.ui).to receive(:warn).with(*expected) + subject.warn_old_tls_version_rubygems_connection(URI(uri), connection) + end + end + + context "an HTTPS uri with TLSv1.2" do + include_examples "does not warn" + end + + context "without SSL" do + let(:tls_version) { nil } + + include_examples "does not warn" + end + + context "without a socket" do + let(:socket) { nil } + + include_examples "does not warn" + end + + context "with a different TLD" do + let(:uri) { "https://foo.bar" } + include_examples "does not warn" + + context "and an outdated TLS version" do + let(:tls_version) { "TLSv1" } + include_examples "does not warn" + end + end + + context "with a nonsense TLS version" do + let(:tls_version) { "BlahBlah2.0Blah" } + include_examples "does not warn" + end + + context "with an outdated TLS version" do + let(:tls_version) { "TLSv1" } + include_examples "does warn", + "Warning: Your Ruby version is compiled against a copy of OpenSSL that is very old. " \ + "Starting in January 2018, RubyGems.org will refuse connection requests from these very old versions of OpenSSL. " \ + "If you will need to continue installing gems after January 2018, please follow this guide to upgrade: http://ruby.to/tls-outdated.", + :wrap => true + end + end +end diff --git a/spec/bundler/bundler/version_ranges_spec.rb b/spec/bundler/bundler/version_ranges_spec.rb index f746aa88ad..ccbb9285d5 100644 --- a/spec/bundler/bundler/version_ranges_spec.rb +++ b/spec/bundler/bundler/version_ranges_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/version_ranges" RSpec.describe Bundler::VersionRanges do diff --git a/spec/bundler/bundler/worker_spec.rb b/spec/bundler/bundler/worker_spec.rb index fbfe6ddab3..2e5642709d 100644 --- a/spec/bundler/bundler/worker_spec.rb +++ b/spec/bundler/bundler/worker_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/worker" RSpec.describe Bundler::Worker do diff --git a/spec/bundler/bundler/yaml_serializer_spec.rb b/spec/bundler/bundler/yaml_serializer_spec.rb index c28db59223..1241c74bbf 100644 --- a/spec/bundler/bundler/yaml_serializer_spec.rb +++ b/spec/bundler/bundler/yaml_serializer_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require "spec_helper" + require "bundler/yaml_serializer" RSpec.describe Bundler::YAMLSerializer do @@ -156,6 +156,7 @@ RSpec.describe Bundler::YAMLSerializer do "a_joke" => { "my-stand" => "I can totally keep secrets", "but" => "The people I tell them to can't :P", + "wouldn't it be funny if this string were empty?" => "", }, "more" => { "first" => [ |