diff options
author | Samuel Giddins <segiddins@segiddins.me> | 2017-07-06 18:07:15 -0400 |
---|---|---|
committer | Samuel Giddins <segiddins@segiddins.me> | 2017-07-06 18:07:15 -0400 |
commit | 357ba9d9012751d74c61228be430c4ea05369028 (patch) | |
tree | dd778f8c551bc86a65a28559600ec1f889154adb | |
parent | 93c48c751bb5c7d5fcb5fb0f4ba586a059008e0f (diff) | |
download | bundler-seg-hot-mess-in-proc-specs.tar.gz |
WIP in-process specsseg-hot-mess-in-proc-specs
-rwxr-xr-x | exe/bundle_ruby | 4 | ||||
-rw-r--r-- | lib/bundler.rb | 23 | ||||
-rw-r--r-- | lib/bundler/cli.rb | 2 | ||||
-rw-r--r-- | lib/bundler/definition.rb | 1 | ||||
-rw-r--r-- | lib/bundler/friendly_errors.rb | 8 | ||||
-rw-r--r-- | lib/bundler/rubygems_integration.rb | 2 | ||||
-rw-r--r-- | spec/bundler/cli_spec.rb | 57 | ||||
-rw-r--r-- | spec/commands/install_spec.rb | 29 | ||||
-rw-r--r-- | spec/lock/git_spec.rb | 12 | ||||
-rw-r--r-- | spec/spec_helper.rb | 1 | ||||
-rw-r--r-- | spec/support/hax.rb | 25 | ||||
-rw-r--r-- | spec/support/helpers.rb | 78 | ||||
-rw-r--r-- | spec/support/matchers.rb | 9 | ||||
-rw-r--r-- | spec/support/path.rb | 4 |
14 files changed, 193 insertions, 62 deletions
diff --git a/exe/bundle_ruby b/exe/bundle_ruby index 847708c3ea..fbbd7f83e5 100755 --- a/exe/bundle_ruby +++ b/exe/bundle_ruby @@ -9,7 +9,7 @@ require "bundler/ruby_dsl" require "bundler/shared_helpers" module Bundler - class Dsl + class BundleRubyDsl include RubyDsl attr_accessor :ruby_version @@ -44,7 +44,7 @@ end Bundler::SharedHelpers.major_deprecation("the bundle_ruby executable has been removed in favor of `bundle platform --ruby`") -dsl = Bundler::Dsl.new +dsl = Bundler::BundleRubyDsl.new begin dsl.eval_gemfile(Bundler::SharedHelpers.default_gemfile) ruby_version = dsl.ruby_version diff --git a/lib/bundler.rb b/lib/bundler.rb index b0f6869423..18443d468d 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -15,9 +15,14 @@ require "bundler/current_ruby" require "bundler/build_metadata" module Bundler - environment_preserver = EnvironmentPreserver.new(ENV, EnvironmentPreserver::BUNDLER_KEYS) - ORIGINAL_ENV = environment_preserver.restore - ENV.replace(environment_preserver.backup) + ORIGINAL_ENV = {} # rubocop:disable Style/MutableConstant + def self.preserve_env! + environment_preserver = EnvironmentPreserver.new(ENV, EnvironmentPreserver::BUNDLER_KEYS) + ORIGINAL_ENV.replace environment_preserver.restore + ENV.replace(environment_preserver.backup) + end + preserve_env! + SUDO_MUTEX = Mutex.new autoload :Definition, "bundler/definition" @@ -38,6 +43,7 @@ module Bundler autoload :Injector, "bundler/injector" autoload :Installer, "bundler/installer" autoload :LazySpecification, "bundler/lazy_specification" + autoload :LockfileGenerator, "bundler/lockfile_generator" autoload :LockfileParser, "bundler/lockfile_parser" autoload :MatchPlatform, "bundler/match_platform" autoload :RemoteSpecification, "bundler/remote_specification" @@ -451,14 +457,14 @@ EOF end def reset_paths! - @root = nil - @settings = nil + @bin_path = nil + @bundle_path = nil @definition = nil - @setup = nil @load = nil @locked_gems = nil - @bundle_path = nil - @bin_path = nil + @root = nil + @settings = nil + @setup = nil @user_home = nil end @@ -466,6 +472,7 @@ EOF return unless defined?(@rubygems) && @rubygems rubygems.undo_replacements rubygems.reset + rubygems.clear_paths @rubygems = nil end diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 786e24b2de..8304b5b89f 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -96,7 +96,7 @@ module Bundler # Ensure `bundle help --no-color` is valid all_commands["help"].disable_class_options = false - def self.handle_no_command_error(command, has_namespace = $thor_runner) + def self.handle_no_command_error(command, has_namespace = false) if Bundler.feature_flag.plugins? && Bundler::Plugin.command?(command) return Bundler::Plugin.exec_command(command, ARGV[1..-1]) end diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index bf0316b8d8..bb173588b6 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -362,7 +362,6 @@ module Bundler end def to_lock - require "bundler/lockfile_generator" LockfileGenerator.generate(self) end diff --git a/lib/bundler/friendly_errors.rb b/lib/bundler/friendly_errors.rb index 9caeeee1a5..a073301b5d 100644 --- a/lib/bundler/friendly_errors.rb +++ b/lib/bundler/friendly_errors.rb @@ -115,12 +115,16 @@ module Bundler "https://github.com/bundler/bundler/search?q=" \ "#{CGI.escape(message)}&type=Issues" end + + def handle_error(error) + log_error(error) + exit exit_status(error) + end end def self.with_friendly_errors yield rescue Exception => e - FriendlyErrors.log_error(e) - exit FriendlyErrors.exit_status(e) + FriendlyErrors.handle_error(e) end end diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index edc931e79f..b70110ffe6 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -505,7 +505,7 @@ module Bundler replace_bin_path(specs, specs_by_name) replace_refresh - Gem.clear_paths + clear_paths end # This backports the correct segment generation code from RubyGems 1.4+ diff --git a/spec/bundler/cli_spec.rb b/spec/bundler/cli_spec.rb index 5df50c94ec..9bf30b30ac 100644 --- a/spec/bundler/cli_spec.rb +++ b/spec/bundler/cli_spec.rb @@ -1,15 +1,18 @@ # frozen_string_literal: true require "bundler/cli" +require "bundler/friendly_errors" RSpec.describe "bundle executable" do it "returns non-zero exit status when passed unrecognized options" do - bundle "--invalid_argument" - expect(exitstatus).to_not be_zero if exitstatus + bundle_command "--invalid_argument" + expect(last_command).to be_failure + expect(last_command.bundler_err).to eq "Unknown switches '--invalid_argument'" end it "returns non-zero exit status when passed unrecognized task" do - bundle "unrecognized-task" - expect(exitstatus).to_not be_zero if exitstatus + bundle_command "unrecognized-task" + expect(last_command).to be_failure + expect(last_command.bundler_err).to eq 'Could not find command "unrecognized-task".' end it "looks for a binary and executes it if it's named bundler-<task>" do @@ -17,51 +20,21 @@ RSpec.describe "bundle executable" do f.puts "#!/usr/bin/env ruby\nputs 'Hello, world'\n" end + expect(Kernel).to receive(:exec).with(tmp("bundler-testtasks").to_s) with_path_added(tmp) do - bundle "testtasks" - end - - expect(exitstatus).to be_zero if exitstatus - expect(out).to eq("Hello, world") - end - - context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do - it "ignores it" do - gemfile bundled_app("Gemfile"), <<-G - source "file://#{gem_repo1}" - gem 'rack' - G - - bundle :install, :env => { "BUNDLE_GEMFILE" => "" } - - expect(the_bundle).to include_gems "rack 1.0.0" - end - end - - context "when ENV['RUBYGEMS_GEMDEPS'] is set" do - it "displays a warning" do - gemfile bundled_app("Gemfile"), <<-G - source "file://#{gem_repo1}" - gem 'rack' - G - - bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "foo" } - expect(out).to include("RUBYGEMS_GEMDEPS") - expect(out).to include("conflict with Bundler") - - bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "" } - expect(out).not_to include("RUBYGEMS_GEMDEPS") + bundle_command! "testtasks" end end context "with --verbose" do it "prints the running command" do - bundle! "config", :verbose => true + bundle_command! :config, :verbose => true expect(last_command.stdout).to start_with("Running `bundle config --verbose` with bundler #{Bundler::VERSION}") end it "doesn't print defaults" do - install_gemfile! "", :verbose => true + gemfile "" + bundle_command! :install, :verbose => true, :retry => 0, :"no-color" => true expect(last_command.stdout).to start_with("Running `bundle install --no-color --retry 0 --verbose` with bundler #{Bundler::VERSION}") end end @@ -69,7 +42,7 @@ RSpec.describe "bundle executable" do describe "printing the outdated warning" do shared_examples_for "no warning" do it "prints no warning" do - bundle "fail" + bundle_command "fail" expect(last_command.stdboth).to eq("Could not find command \"fail\".") end end @@ -102,7 +75,7 @@ RSpec.describe "bundle executable" do context "when the latest version is greater than the current version" do let(:latest_version) { "2.0" } it "prints the version warning" do - bundle "fail" + bundle_command "fail" 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` @@ -130,7 +103,7 @@ end RSpec.describe "bundler executable" do it "shows the bundler version just as the `bundle` executable does" do - bundler "--version" + bundle_command "--version", :exe => bundle_exe("bundler") expect(out).to eq("Bundler version #{Bundler::VERSION}") end end diff --git a/spec/commands/install_spec.rb b/spec/commands/install_spec.rb index a21b735f8e..e1d00dd4df 100644 --- a/spec/commands/install_spec.rb +++ b/spec/commands/install_spec.rb @@ -507,4 +507,33 @@ RSpec.describe "bundle install with gem sources" do "setting them for authentication.") end end + + context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do + it "ignores it" do + gemfile bundled_app("Gemfile"), <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + bundle :install, :env => { "BUNDLE_GEMFILE" => "" } + + expect(the_bundle).to include_gems "rack 1.0.0" + end + end + + context "when ENV['RUBYGEMS_GEMDEPS'] is set" do + it "displays a warning" do + gemfile bundled_app("Gemfile"), <<-G + source "file://#{gem_repo1}" + gem 'rack' + G + + bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "foo" } + expect(out).to include("RUBYGEMS_GEMDEPS") + expect(out).to include("conflict with Bundler") + + bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "" } + expect(out).not_to include("RUBYGEMS_GEMDEPS") + end + end end diff --git a/spec/lock/git_spec.rb b/spec/lock/git_spec.rb index 4179a0218a..b622328fb4 100644 --- a/spec/lock/git_spec.rb +++ b/spec/lock/git_spec.rb @@ -4,20 +4,21 @@ RSpec.describe "bundle lock with git gems" do before :each do build_git "foo" - install_gemfile <<-G + gemfile <<-G gem 'foo', :git => "#{lib_path("foo-1.0")}" G + bundle_command! :install end it "doesn't break right after running lock" do - expect(the_bundle).to include_gems "foo 1.0.0" + expect(the_bundle).to include_gems "foo 1.0.0", :as_if => true end it "locks a git source to the current ref" do update_git "foo" - bundle :install + bundle_command! :install - run <<-RUBY + run_as_if <<-RUBY require 'foo' puts "WIN" unless defined?(FOO_PREV_REF) RUBY @@ -26,9 +27,10 @@ RSpec.describe "bundle lock with git gems" do end it "provides correct #full_gem_path" do - run <<-RUBY + run_as_if <<-RUBY puts Bundler.rubygems.find_name('foo').first.full_gem_path RUBY + expect(out).to eq(bundle("show foo")) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5c7fcbffa5..a5a3eca081 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -23,6 +23,7 @@ if File.expand_path(__FILE__) =~ %r{([^\w/\.])} end require "bundler" +require "bundler/cli" # Require the correct version of popen for the current platform if RbConfig::CONFIG["host_os"] =~ /mingw|mswin/ diff --git a/spec/support/hax.rb b/spec/support/hax.rb index 663d3527c5..8f5fc8aaec 100644 --- a/spec/support/hax.rb +++ b/spec/support/hax.rb @@ -1,6 +1,31 @@ # frozen_string_literal: true require "rubygems" +module BundlerSpecOriginal + UNSET = Module.new + GEM_PLATFORM_LOCAL = Gem::Platform.local + CONSTANTS = Hash[ + %w[Bundler::VERSION Bundler::WINDOWS Object::RUBY_ENGINE Object::RUBY_ENGINE_VERSION].map do |const| + value = const.split("::").reduce(Module) {|ns, c| ns.const_defined?(c) ? ns.const_get(c) : UNSET } + [const, value] + end + ] + + def self.reset! + Gem.module_exec { @platforms = nil } + Gem::Platform.module_exec { @local = BundlerSpecOriginal::GEM_PLATFORM_LOCAL } + + CONSTANTS.each do |name, value| + parts = name.split("::") + sym = parts.pop + namespace = parts.reduce(Module) {|ns, c| ns.const_get(c) } + namespace.send(:remove_const, sym) if namespace.const_defined?(sym) + namespace.const_set(sym, value) unless UNSET == value + end + Object.send :remove_const, :BundlerSpecOriginal + end +end + module Gem class Platform @local = new(ENV["BUNDLER_SPEC_PLATFORM"]) if ENV["BUNDLER_SPEC_PLATFORM"] diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb index 03d9711878..4f49de3cb5 100644 --- a/spec/support/helpers.rb +++ b/spec/support/helpers.rb @@ -12,6 +12,7 @@ module Spec end FileUtils.mkdir_p(home) FileUtils.mkdir_p(tmpdir) + Bundler.rubygems Bundler.reset! Bundler.ui = nil Bundler.ui # force it to initialize @@ -141,6 +142,83 @@ module Spec end bang :bundle + def bundle_command(*args) + options = args.last.is_a?(Hash) ? args.pop : {} + exe = options.delete(:exe) { bundle_exe } + env = options.delete(:env) { {} } + args += options.map do |k, v| + v == true ? ["--#{k}"] : ["--#{k}", v.to_s] if v + end.compact.flatten(1) + args = args.flatten.map(&:to_s) + + as_if_running("#{exe} #{args.join(" ")}") do + ENV.update(env) + + ARGV.replace args.flatten.map(&:to_s) + load exe.to_s + end + end + bang :bundle_command + + def as_if + argv = ARGV.dup + env = ENV.to_h.dup + load_path = $LOAD_PATH.map(&:dup) + loaded_features = $LOADED_FEATURES.map(&:dup) + object_constants = ::Object.constants.to_set + + yield + ensure + ARGV.replace argv + ENV.clear + ENV.update env + $LOAD_PATH.replace load_path + bundler_loaded_features = $LOADED_FEATURES.select {|lf| lf.start_with? bundler_path.to_s } + $LOADED_FEATURES.replace loaded_features.concat(bundler_loaded_features) + ::Object.constants.each do |const| + next if object_constants.include?(const) + ::Object.send(:remove_const, const) + end + end + + def as_if_running(cmd) + as_if do + command_execution = Spec::CommandExecution.new(cmd.to_s, Dir.pwd) + command_execution.stdout = capture(:stdout) do + command_execution.stderr = capture(:stderr) do + begin + load root.join("spec", "support", "hax.rb") + Bundler.preserve_env! + + yield + rescue SystemExit => exception + command_execution.exitstatus = exception.status + rescue + raise + else + command_execution.exitstatus = 0 + ensure + BundlerSpecOriginal.reset! + Bundler.reset! + end + end.strip + end.strip + + (@command_executions ||= []) << command_execution + + command_execution.stdout + end + end + + def run_as_if(cmd, *args) + cmd = strip_whitespace(cmd) + as_if_running("ruby -e #{cmd.inspect}") do + _opts = args.last.is_a?(Hash) ? args.pop : {} + Bundler.setup(*args.map(&:to_s)) + eval(cmd) + end + end + def bundler(cmd, options = {}) options["bundle_bin"] = File.expand_path("../../../exe/bundler", __FILE__) bundle(cmd, options) diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 7316e43684..5748ff7f3b 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -141,6 +141,15 @@ module Spec end define_compound_matcher :include_gems, [be_an_instance_of(Spec::TheBundle)] do |*names| + define_method :run do |*args| + opts = names.last.is_a?(Hash) ? names.pop : {} + if opts.delete(:as_if) { false } + run_as_if!(*args) + else + run!(*args) + end + end + match do opts = names.last.is_a?(Hash) ? names.pop : {} source = opts.delete(:source) diff --git a/spec/support/path.rb b/spec/support/path.rb index 2b929003fb..ceb060ac81 100644 --- a/spec/support/path.rb +++ b/spec/support/path.rb @@ -93,6 +93,10 @@ module Spec tmp "tmpdir", *args end + def bundle_exe(exe = "bundle") + root.join("exe", exe) + end + extend self end end |