mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	[rubygems/rubygems] Support binstubs with --enable-load-relative prolog
				
					
				
			32a5e9057a
			
			
This commit is contained in:
		
							parent
							
								
									044b0ae8e0
								
							
						
					
					
						commit
						7d42b442bb
					
				
					 2 changed files with 208 additions and 66 deletions
				
			
		| 
						 | 
				
			
			@ -220,7 +220,17 @@ class Gem::Installer
 | 
			
		|||
    existing = nil
 | 
			
		||||
 | 
			
		||||
    File.open generated_bin, 'rb' do |io|
 | 
			
		||||
      next unless io.gets =~ /^#!/ # shebang
 | 
			
		||||
      line = io.gets
 | 
			
		||||
      shebang = /^#!.*ruby/
 | 
			
		||||
 | 
			
		||||
      if load_relative_enabled?
 | 
			
		||||
        until line.nil? || line =~ shebang do
 | 
			
		||||
          line = io.gets
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      next unless line =~ shebang
 | 
			
		||||
 | 
			
		||||
      io.gets # blankline
 | 
			
		||||
 | 
			
		||||
      # TODO detect a specially formatted comment instead of trying
 | 
			
		||||
| 
						 | 
				
			
			@ -585,7 +595,6 @@ class Gem::Installer
 | 
			
		|||
  #
 | 
			
		||||
 | 
			
		||||
  def shebang(bin_file_name)
 | 
			
		||||
    ruby_name = ruby_install_name if @env_shebang
 | 
			
		||||
    path = File.join gem_dir, spec.bindir, bin_file_name
 | 
			
		||||
    first_line = File.open(path, "rb") {|file| file.gets } || ""
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -614,14 +623,12 @@ class Gem::Installer
 | 
			
		|||
      end
 | 
			
		||||
 | 
			
		||||
      "#!#{which}"
 | 
			
		||||
    elsif not ruby_name
 | 
			
		||||
      "#!#{Gem.ruby}#{opts}"
 | 
			
		||||
    elsif opts
 | 
			
		||||
      "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
 | 
			
		||||
    else
 | 
			
		||||
    elsif @env_shebang
 | 
			
		||||
      # Create a plain shebang line.
 | 
			
		||||
      @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
 | 
			
		||||
      "#!#{@env_path} #{ruby_name}"
 | 
			
		||||
      "#!#{@env_path} #{ruby_install_name}"
 | 
			
		||||
    else
 | 
			
		||||
      "#{bash_prolog_script}#!#{Gem.ruby}#{opts}"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -980,4 +987,29 @@ TEXT
 | 
			
		|||
  def ruby_install_name
 | 
			
		||||
    rb_config["ruby_install_name"]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def load_relative_enabled?
 | 
			
		||||
    rb_config["LIBRUBY_RELATIVE"] == 'yes'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def bash_prolog_script
 | 
			
		||||
    if load_relative_enabled?
 | 
			
		||||
      script = +<<~EOS
 | 
			
		||||
        bindir="${0%/*}"
 | 
			
		||||
      EOS
 | 
			
		||||
 | 
			
		||||
      script << %Q(exec "$bindir/#{ruby_install_name}" "-x" "$0" "$@"\n)
 | 
			
		||||
 | 
			
		||||
      <<~EOS
 | 
			
		||||
        #!/bin/sh
 | 
			
		||||
        # -*- ruby -*-
 | 
			
		||||
        _=_\\
 | 
			
		||||
        =begin
 | 
			
		||||
        #{script.chomp}
 | 
			
		||||
        =end
 | 
			
		||||
      EOS
 | 
			
		||||
    else
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,11 +18,12 @@ class TestGemInstaller < Gem::InstallerTestCase
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def test_app_script_text
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative "no" do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, ''
 | 
			
		||||
      util_make_exec @spec, ''
 | 
			
		||||
 | 
			
		||||
    expected = <<-EOF
 | 
			
		||||
      expected = <<-EOF
 | 
			
		||||
#!#{Gem.ruby}
 | 
			
		||||
#
 | 
			
		||||
# This file was generated by RubyGems.
 | 
			
		||||
| 
						 | 
				
			
			@ -52,10 +53,11 @@ else
 | 
			
		|||
gem "a", version
 | 
			
		||||
load Gem.bin_path("a", "executable", version)
 | 
			
		||||
end
 | 
			
		||||
    EOF
 | 
			
		||||
      EOF
 | 
			
		||||
 | 
			
		||||
    wrapper = installer.app_script_text 'executable'
 | 
			
		||||
    assert_equal expected, wrapper
 | 
			
		||||
      wrapper = installer.app_script_text 'executable'
 | 
			
		||||
      assert_equal expected, wrapper
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_check_executable_overwrite
 | 
			
		||||
| 
						 | 
				
			
			@ -724,17 +726,19 @@ gem 'other', version
 | 
			
		|||
  def test_generate_bin_uses_default_shebang
 | 
			
		||||
    pend "Symlinks not supported or not enabled" unless symlink_supported?
 | 
			
		||||
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    installer.wrappers = true
 | 
			
		||||
    util_make_exec
 | 
			
		||||
      installer.wrappers = true
 | 
			
		||||
      util_make_exec
 | 
			
		||||
 | 
			
		||||
    installer.generate_bin
 | 
			
		||||
      installer.generate_bin
 | 
			
		||||
 | 
			
		||||
    default_shebang = Gem.ruby
 | 
			
		||||
    shebang_line = File.open("#{@gemhome}/bin/executable") {|f| f.readlines.first }
 | 
			
		||||
    assert_match(/\A#!/, shebang_line)
 | 
			
		||||
    assert_match(/#{default_shebang}/, shebang_line)
 | 
			
		||||
      default_shebang = Gem.ruby
 | 
			
		||||
      shebang_line = File.open("#{@gemhome}/bin/executable") {|f| f.readlines.first }
 | 
			
		||||
      assert_match(/\A#!/, shebang_line)
 | 
			
		||||
      assert_match(/#{default_shebang}/, shebang_line)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_generate_bin_with_dangling_symlink
 | 
			
		||||
| 
						 | 
				
			
			@ -1804,13 +1808,15 @@ gem 'other', version
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative "no" do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/ruby"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/ruby"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_process_options
 | 
			
		||||
| 
						 | 
				
			
			@ -1844,42 +1850,80 @@ gem 'other', version
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_arguments
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/ruby -ws"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/ruby -ws"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_arguments_with_load_relative
 | 
			
		||||
    load_relative 'yes' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/ruby -ws"
 | 
			
		||||
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
      shebang_lines = shebang.split "\n"
 | 
			
		||||
 | 
			
		||||
      assert_equal "#!/bin/sh", shebang_lines.shift
 | 
			
		||||
      assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_empty
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, ''
 | 
			
		||||
      util_make_exec @spec, ''
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
    assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
      assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_env
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/env ruby"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/env ruby"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_env_arguments
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/env ruby -ws"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/env ruby -ws"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_env_arguments_with_load_relative
 | 
			
		||||
    load_relative 'yes' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/env ruby -ws"
 | 
			
		||||
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
      shebang_lines = shebang.split "\n"
 | 
			
		||||
 | 
			
		||||
      assert_equal "#!/bin/sh", shebang_lines.shift
 | 
			
		||||
      assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_env_shebang
 | 
			
		||||
| 
						 | 
				
			
			@ -1897,63 +1941,120 @@ gem 'other', version
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_nested
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/opt/local/ruby/bin/ruby"
 | 
			
		||||
      util_make_exec @spec, "#!/opt/local/ruby/bin/ruby"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_nested_arguments
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws"
 | 
			
		||||
      util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_nested_arguments_with_load_relative
 | 
			
		||||
    load_relative 'yes' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
      util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws"
 | 
			
		||||
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
      shebang_lines = shebang.split "\n"
 | 
			
		||||
 | 
			
		||||
      assert_equal "#!/bin/sh", shebang_lines.shift
 | 
			
		||||
      assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_version
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/ruby18"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/ruby18"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_version_arguments
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/ruby18 -ws"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/ruby18 -ws"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_version_arguments_with_load_relative
 | 
			
		||||
    load_relative 'yes' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/ruby18 -ws"
 | 
			
		||||
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
      shebang_lines = shebang.split "\n"
 | 
			
		||||
 | 
			
		||||
      assert_equal "#!/bin/sh", shebang_lines.shift
 | 
			
		||||
      assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_version_env
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/env ruby18"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/env ruby18"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby}", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_version_env_arguments
 | 
			
		||||
    installer = setup_base_installer
 | 
			
		||||
    load_relative 'no' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
    util_make_exec @spec, "#!/usr/bin/env ruby18 -ws"
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/env ruby18 -ws"
 | 
			
		||||
 | 
			
		||||
    shebang = installer.shebang 'executable'
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
    assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
      assert_equal "#!#{Gem.ruby} -ws", shebang
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_version_env_arguments_with_load_relative
 | 
			
		||||
    load_relative 'yes' do
 | 
			
		||||
      installer = setup_base_installer
 | 
			
		||||
 | 
			
		||||
      util_make_exec @spec, "#!/usr/bin/env ruby18 -ws"
 | 
			
		||||
 | 
			
		||||
      shebang = installer.shebang 'executable'
 | 
			
		||||
 | 
			
		||||
      shebang_lines = shebang.split "\n"
 | 
			
		||||
 | 
			
		||||
      assert_equal "#!/bin/sh", shebang_lines.shift
 | 
			
		||||
      assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_shebang_custom
 | 
			
		||||
| 
						 | 
				
			
			@ -2283,4 +2384,13 @@ gem 'other', version
 | 
			
		|||
  def mask
 | 
			
		||||
    0100755
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def load_relative(value)
 | 
			
		||||
    orig_LIBRUBY_RELATIVE = RbConfig::CONFIG['LIBRUBY_RELATIVE']
 | 
			
		||||
    RbConfig::CONFIG['LIBRUBY_RELATIVE'] = value
 | 
			
		||||
 | 
			
		||||
    yield
 | 
			
		||||
  ensure
 | 
			
		||||
    RbConfig::CONFIG['LIBRUBY_RELATIVE'] = orig_LIBRUBY_RELATIVE
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue