From a1a1c9080ff5a948762da54962412c407304f41c Mon Sep 17 00:00:00 2001 From: sodacris Date: Mon, 18 Nov 2024 13:04:31 +0800 Subject: [PATCH] [rubygems/rubygems] add loading support on Windows https://github.com/rubygems/rubygems/commit/04574ba59a --- lib/bundler/cli/exec.rb | 33 ++++++++++++++++++++--- spec/bundler/commands/exec_spec.rb | 42 ++++++------------------------ 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb index 9428e9db3b..2fdc416286 100644 --- a/lib/bundler/cli/exec.rb +++ b/lib/bundler/cli/exec.rb @@ -19,11 +19,13 @@ module Bundler 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 - bin_path = "./" + bin_path unless File.absolute_path?(bin_path) - kernel_exec(bin_path, *args) else # exec using the given command kernel_exec(cmd, *args) @@ -69,6 +71,29 @@ module Bundler "#{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", diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 49465fa07b..af8bfc71f1 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -661,8 +661,6 @@ RSpec.describe "bundle exec" do describe "with gems bundled for deployment" do it "works when calling bundler from another script" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - gemfile <<-G source "https://gem.repo1" @@ -739,8 +737,7 @@ RSpec.describe "bundle exec" do RUBY before do - bundled_app(path).open("w") {|f| f << executable } - bundled_app(path).chmod(0o755) + create_file(bundled_app(path), executable) install_gemfile <<-G source "https://gem.repo1" @@ -765,8 +762,6 @@ RSpec.describe "bundle exec" do subject { bundle "exec #{path} arg1 arg2", raise_on_error: false } it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -778,8 +773,6 @@ RSpec.describe "bundle exec" do context "with exit 0" do it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -791,8 +784,6 @@ RSpec.describe "bundle exec" do let(:exit_code) { 99 } it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -831,7 +822,12 @@ RSpec.describe "bundle exec" do let(:expected) { "" } it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + # it's empty, so `create_file` won't add executable permission and bat scripts on Windows + bundled_app(path).chmod(0o755) + path.sub_ext(".bat").write <<~SCRIPT if Gem.win_platform? + @ECHO OFF + @"ruby.exe" "%~dpn0" %* + SCRIPT subject expect(exitstatus).to eq(exit_code) @@ -844,12 +840,10 @@ RSpec.describe "bundle exec" do let(:executable) { super() << "\nraise 'ERROR'" } let(:exit_code) { 1 } let(:expected_err) do - /\Abundler: failed to load command: #{Regexp.quote(path.to_s)} \(#{Regexp.quote(path.to_s)}\)\n#{Regexp.quote(path.to_s)}:10:in [`']': ERROR \(RuntimeError\)/ + /\Abundler: failed to load command: #{Regexp.quote(path.to_s)} \(#{Regexp.quote(path.to_s)}\)\n#{Regexp.quote(path.to_s)}:[0-9]+:in [`']': ERROR \(RuntimeError\)/ end it "runs like a normally executed executable" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to match(expected_err) @@ -864,8 +858,6 @@ RSpec.describe "bundle exec" do let(:expected) { super() } it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -877,8 +869,6 @@ RSpec.describe "bundle exec" do let(:shebang) { "#!#{Gem.ruby}" } it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -909,8 +899,6 @@ RSpec.describe "bundle exec" do EOS it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -933,8 +921,6 @@ RSpec.describe "bundle exec" do let(:expected) { "" } it "prints proper suggestion" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to include("Run `bundle install --gemfile CustomGemfile` to install missing gems.") @@ -947,8 +933,6 @@ RSpec.describe "bundle exec" do let(:exit_code) { 1 } it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -971,8 +955,6 @@ RSpec.describe "bundle exec" do end it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -995,8 +977,6 @@ RSpec.describe "bundle exec" do EOS it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -1013,8 +993,6 @@ RSpec.describe "bundle exec" do EOS it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -1031,8 +1009,6 @@ RSpec.describe "bundle exec" do EOS it "runs" do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - subject expect(exitstatus).to eq(exit_code) expect(err).to eq(expected_err) @@ -1173,8 +1149,6 @@ RSpec.describe "bundle exec" do context "when gemfile and path are configured", :ruby_repo do before do - skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? - build_repo2 do build_gem "rails", "6.1.0" do |s| s.executables = "rails"