diff options
Diffstat (limited to 'lib/bundler/cli/exec.rb')
| -rw-r--r-- | lib/bundler/cli/exec.rb | 54 |
1 files changed, 34 insertions, 20 deletions
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb index 0b0e991ea5..2fdc416286 100644 --- a/lib/bundler/cli/exec.rb +++ b/lib/bundler/cli/exec.rb @@ -12,29 +12,27 @@ module Bundler @options = options @cmd = args.shift @args = args - - if !Bundler.current_ruby.jruby? - @args << { :close_others => !options.keep_file_descriptors? } - elsif options.keep_file_descriptors? - Bundler.ui.warn "Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec." - end + @args << { close_others: !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby? end def run validate_cmd! SharedHelpers.set_bundle_environment if bin_path = Bundler.which(cmd) - if !Bundler.settings[:disable_exec_load] && ruby_shebang?(bin_path) - return kernel_load(bin_path, *args) + if !Bundler.settings[:disable_exec_load] && directly_loadable?(bin_path) + bin_path.delete_suffix!(".bat") if Gem.win_platform? + kernel_load(bin_path, *args) + else + bin_path = "./" + bin_path unless File.absolute_path?(bin_path) + kernel_exec(bin_path, *args) end - kernel_exec(bin_path, *args) else # exec using the given command kernel_exec(cmd, *args) end end - private + private def validate_cmd! return unless cmd.nil? @@ -43,15 +41,11 @@ module Bundler end def kernel_exec(*args) - ui = Bundler.ui - Bundler.ui = nil Kernel.exec(*args) rescue Errno::EACCES, Errno::ENOEXEC - Bundler.ui = ui Bundler.ui.error "bundler: not executable: #{cmd}" exit 126 rescue Errno::ENOENT - Bundler.ui = ui Bundler.ui.error "bundler: command not found: #{cmd}" Bundler.ui.warn "Install missing gem executables with `bundle install`" exit 127 @@ -62,24 +56,44 @@ module Bundler ARGV.replace(args) $0 = file Process.setproctitle(process_title(file, args)) if Process.respond_to?(:setproctitle) - ui = Bundler.ui - Bundler.ui = nil require_relative "../setup" TRAPPED_SIGNALS.each {|s| trap(s, "DEFAULT") } Kernel.load(file) rescue SystemExit, SignalException raise - rescue Exception => e # rubocop:disable Lint/RescueException - Bundler.ui = ui + rescue Exception # rubocop:disable Lint/RescueException Bundler.ui.error "bundler: failed to load command: #{cmd} (#{file})" - backtrace = e.backtrace ? e.backtrace.take_while {|bt| !bt.start_with?(__FILE__) } : [] - abort "#{e.class}: #{e.message}\n #{backtrace.join("\n ")}" + Bundler::FriendlyErrors.disable! + raise end def process_title(file, args) "#{file} #{args.join(" ")}".strip end + def directly_loadable?(file) + if Gem.win_platform? + script_wrapper?(file) + else + ruby_shebang?(file) + end + end + + def script_wrapper?(file) + script_file = file.delete_suffix(".bat") + return false unless File.exist?(script_file) + + if File.zero?(script_file) + Bundler.ui.warn "#{script_file} is empty" + return false + end + + header = File.open(file, "r") {|f| f.read(32) } + ruby_exe = "#{RbConfig::CONFIG["RUBY_INSTALL_NAME"]}#{RbConfig::CONFIG["EXEEXT"]}" + ruby_exe = "ruby.exe" if ruby_exe.empty? + header.include?(ruby_exe) + end + def ruby_shebang?(file) possibilities = [ "#!/usr/bin/env ruby\n", |
