# frozen_string_literal: true require_relative "installer_test_case" class TestGemInstaller < Gem::InstallerTestCase def setup super common_installer_setup @config = Gem.configuration end def teardown common_installer_teardown super Gem.configuration = instance_variable_defined?(:@config) ? @config : nil end def test_app_script_text load_relative "no" do installer = setup_base_installer util_make_exec @spec, "" expected = <<-EOF #!#{Gem.ruby} # # This file was generated by RubyGems. # # The application 'a' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' Gem.use_gemdeps version = \">= 0.a\" str = ARGV.first if str str = str.b[/\\A_(.*)_\\z/, 1] if str and Gem::Version.correct?(str) version = str ARGV.shift end end if Gem.respond_to?(:activate_bin_path) load Gem.activate_bin_path('a', 'executable', version) else gem "a", version load Gem.bin_path("a", "executable", version) end EOF wrapper = installer.app_script_text "executable" assert_equal expected, wrapper end end def test_check_executable_overwrite installer = setup_base_installer installer.generate_bin @spec = Gem::Specification.new do |s| s.files = ["lib/code.rb"] s.name = "a" s.version = "3" s.summary = "summary" s.description = "desc" s.require_path = "lib" end util_make_exec installer.gem_dir = @spec.gem_dir installer.wrappers = true installer.generate_bin installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) end def test_check_executable_overwrite_default_bin_dir installer = setup_base_installer(false) bindir(Gem.bindir) do util_conflict_executable false ui = Gem::MockGemUi.new "n\n" use_ui ui do e = assert_raise Gem::InstallError do installer.generate_bin end conflicted = File.join @gemhome, "bin", "executable" assert_match(/\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z/, e.message) end end end def test_check_executable_overwrite_format_executable installer = setup_base_installer installer.generate_bin @spec = Gem::Specification.new do |s| s.files = ["lib/code.rb"] s.name = "a" s.version = "3" s.summary = "summary" s.description = "desc" s.require_path = "lib" end File.open File.join(util_inst_bindir, "executable"), "w" do |io| io.write <<-EXEC #!/usr/local/bin/ruby # # This file was generated by RubyGems gem 'other', version EXEC end util_make_exec Gem::Installer.exec_format = "foo-%s-bar" installer.gem_dir = @spec.gem_dir installer.wrappers = true installer.format_executable = true installer.generate_bin # should not raise installed_exec = File.join util_inst_bindir, "foo-executable-bar" assert_path_exist installed_exec wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) ensure Gem::Installer.exec_format = nil end def test_check_executable_overwrite_other_gem installer = setup_base_installer(false) util_conflict_executable true ui = Gem::MockGemUi.new "n\n" use_ui ui do e = assert_raise Gem::InstallError do installer.generate_bin end assert_equal '"executable" from a conflicts with installed executable from conflict', e.message end end def test_check_executable_overwrite_other_gem_force installer = setup_base_installer util_conflict_executable true installer.wrappers = true installer.force = true installer.generate_bin installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) end def test_check_executable_overwrite_other_non_gem installer = setup_base_installer util_conflict_executable false installer.wrappers = true installer.generate_bin installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) end unless Gem.win_platform? def test_check_that_user_bin_dir_is_in_path installer = setup_base_installer bin_dir = installer.bin_dir if Gem.win_platform? bin_dir = bin_dir.downcase end orig_path = ENV["PATH"] ENV["PATH"] = [ENV["PATH"], bin_dir].join(File::PATH_SEPARATOR) use_ui @ui do installer.check_that_user_bin_dir_is_in_path end assert_empty @ui.error return unless Gem.win_platform? ENV["PATH"] = [orig_path, bin_dir.tr(File::SEPARATOR, File::ALT_SEPARATOR)].join(File::PATH_SEPARATOR) use_ui @ui do installer.check_that_user_bin_dir_is_in_path end assert_empty @ui.error ensure ENV["PATH"] = orig_path end def test_check_that_user_bin_dir_is_in_path_tilde pend "Tilde is PATH is not supported under MS Windows" if Gem.win_platform? orig_path = ENV["PATH"] ENV["PATH"] = [ENV["PATH"], "~/bin"].join(File::PATH_SEPARATOR) installer = setup_base_installer installer.bin_dir.replace File.join @userhome, "bin" use_ui @ui do installer.check_that_user_bin_dir_is_in_path end assert_empty @ui.error ensure ENV["PATH"] = orig_path unless Gem.win_platform? end def test_check_that_user_bin_dir_is_in_path_not_in_path installer = setup_base_installer use_ui @ui do installer.check_that_user_bin_dir_is_in_path end expected = installer.bin_dir if Gem.win_platform? expected = expected.downcase end assert_match expected, @ui.error end def test_ensure_dependency installer = setup_base_installer util_spec "a" dep = Gem::Dependency.new "a", ">= 2" assert installer.ensure_dependency(@spec, dep) dep = Gem::Dependency.new "b", "> 2" e = assert_raise Gem::InstallError do installer.ensure_dependency @spec, dep end assert_equal "a requires b (> 2)", e.message end def test_ensure_loadable_spec a, a_gem = util_gem "a", 2 do |s| s.add_dependency "garbage ~> 5" end installer = Gem::Installer.at a_gem e = assert_raise Gem::InstallError do installer.ensure_loadable_spec end assert_equal "The specification for #{a.full_name} is corrupt " \ "(SyntaxError)", e.message end def test_ensure_loadable_spec_security_policy pend "openssl is missing" unless Gem::HAVE_OPENSSL _, a_gem = util_gem "a", 2 do |s| s.add_dependency "garbage ~> 5" end policy = Gem::Security::HighSecurity installer = Gem::Installer.at a_gem, security_policy: policy assert_raise Gem::Security::Exception do installer.ensure_loadable_spec end end def test_extract_files installer = setup_base_installer installer.extract_files assert_path_exist File.join @spec.gem_dir, "bin/executable" end def test_generate_bin_bindir installer = setup_base_installer installer.wrappers = true @spec.executables = %w[executable] @spec.bindir = "bin" exec_file = installer.formatted_program_filename "executable" exec_path = File.join @spec.gem_dir, exec_file File.open exec_path, "w" do |f| f.puts "#!/usr/bin/ruby" end installer.gem_dir = @spec.gem_dir installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join(util_inst_bindir, "executable") assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) end def test_generate_bin_bindir_with_user_install_warning bin_dir = if Gem.win_platform? File.expand_path(ENV["WINDIR"]).upcase else "/usr/bin" end old_path = ENV["PATH"] ENV["PATH"] = [ENV["PATH"], bin_dir].compact.join(File::PATH_SEPARATOR) options = { bin_dir: bin_dir, install_dir: "/non/existent", } inst = Gem::Installer.at "", options Gem::Installer.path_warning = false use_ui @ui do inst.check_that_user_bin_dir_is_in_path end assert_equal "", @ui.error ensure ENV["PATH"] = old_path end def test_generate_bin_script installer = setup_base_installer installer.wrappers = true util_make_exec installer.gem_dir = @spec.gem_dir installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) end def test_generate_bin_script_format installer = setup_base_installer installer.format_executable = true installer.wrappers = true util_make_exec installer.gem_dir = @spec.gem_dir Gem::Installer.exec_format = "foo-%s-bar" installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, "foo-executable-bar" assert_path_exist installed_exec ensure Gem::Installer.exec_format = nil end def test_generate_bin_script_format_disabled installer = setup_base_installer installer.wrappers = true util_make_exec installer.gem_dir = @spec.gem_dir Gem::Installer.exec_format = "foo-%s-bar" installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec ensure Gem::Installer.exec_format = nil end def test_generate_bin_script_install_dir installer = setup_base_installer installer.wrappers = true gem_dir = File.join("#{@gemhome}2", "gems", @spec.full_name) gem_bindir = File.join gem_dir, "bin" FileUtils.mkdir_p gem_bindir File.open File.join(gem_bindir, "executable"), "w" do |f| f.puts "#!/bin/ruby" end installer.gem_home = "#{@gemhome}2" installer.gem_dir = gem_dir installer.bin_dir = File.join "#{@gemhome}2", "bin" installer.generate_bin installed_exec = File.join("#{@gemhome}2", "bin", "executable") assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) end def test_generate_bin_script_no_execs installer = setup_base_installer installer = util_execless installer.wrappers = true installer.generate_bin assert_path_not_exist util_inst_bindir, "bin dir was created when not needed" end def test_generate_bin_script_no_perms installer = setup_base_installer installer.wrappers = true util_make_exec Dir.mkdir util_inst_bindir if Gem.win_platform? pend("test_generate_bin_script_no_perms skipped on MS Windows") elsif Process.uid.zero? pend("test_generate_bin_script_no_perms skipped in root privilege") else FileUtils.chmod 0o000, util_inst_bindir assert_raise Gem::FilePermissionError do installer.generate_bin end end ensure FileUtils.chmod 0o755, util_inst_bindir unless $DEBUG || Gem.win_platform? end def test_generate_bin_script_no_shebang installer = setup_base_installer installer.wrappers = true @spec.executables = %w[executable] gem_dir = File.join @gemhome, "gems", @spec.full_name gem_bindir = File.join gem_dir, "bin" FileUtils.mkdir_p gem_bindir File.open File.join(gem_bindir, "executable"), "w" do |f| f.puts "blah blah blah" end installer.generate_bin installed_exec = File.join @gemhome, "bin", "executable" assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) # HACK: some gems don't have #! in their executables, restore 2008/06 # assert_no_match %r|generated by RubyGems|, wrapper end def test_generate_bin_script_wrappers installer = setup_base_installer installer.wrappers = true util_make_exec installer.gem_dir = @spec.gem_dir installed_exec = File.join(util_inst_bindir, "executable") real_exec = File.join @spec.gem_dir, "bin", "executable" # fake --no-wrappers for previous install unless Gem.win_platform? FileUtils.mkdir_p File.dirname(installed_exec) FileUtils.ln_s real_exec, installed_exec end installer.generate_bin assert_directory_exists util_inst_bindir assert_path_exist installed_exec assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? assert_match(/generated by RubyGems/, File.read(installed_exec)) refute_match(/generated by RubyGems/, File.read(real_exec), "real executable overwritten") end def test_generate_bin_symlink pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer installer.wrappers = false util_make_exec installer.gem_dir = @spec.gem_dir installer.generate_bin assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, "executable" assert_equal true, File.symlink?(installed_exec) assert_equal(File.join(@spec.gem_dir, "bin", "executable"), File.readlink(installed_exec)) end def test_generate_bin_symlink_no_execs installer = setup_base_installer installer = util_execless installer.wrappers = false installer.generate_bin assert_path_not_exist util_inst_bindir end def test_generate_bin_symlink_no_perms installer = setup_base_installer installer.wrappers = false util_make_exec installer.gem_dir = @spec.gem_dir Dir.mkdir util_inst_bindir if Gem.win_platform? pend("test_generate_bin_symlink_no_perms skipped on MS Windows") elsif Process.uid.zero? pend("test_user_install_disabled_read_only test skipped in root privilege") else FileUtils.chmod 0o000, util_inst_bindir assert_raise Gem::FilePermissionError do installer.generate_bin end end ensure FileUtils.chmod 0o755, util_inst_bindir unless $DEBUG || Gem.win_platform? end def test_generate_bin_symlink_update_newer pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer installer.wrappers = false util_make_exec installer.gem_dir = @spec.gem_dir installer.generate_bin installed_exec = File.join(util_inst_bindir, "executable") assert_equal(File.join(@spec.gem_dir, "bin", "executable"), File.readlink(installed_exec)) @spec = Gem::Specification.new do |s| s.files = ["lib/code.rb"] s.name = "a" s.version = "3" s.summary = "summary" s.description = "desc" s.require_path = "lib" end util_make_exec installer.gem_dir = @spec.gem_dir installer.generate_bin installed_exec = File.join(util_inst_bindir, "executable") assert_equal(@spec.bin_file("executable"), File.readlink(installed_exec), "Ensure symlink moved to latest version") end def test_generate_bin_symlink_update_older pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer installer.wrappers = false util_make_exec installer.gem_dir = @spec.gem_dir installer.generate_bin installed_exec = File.join(util_inst_bindir, "executable") assert_equal(File.join(@spec.gem_dir, "bin", "executable"), File.readlink(installed_exec)) spec = Gem::Specification.new do |s| s.files = ["lib/code.rb"] s.name = "a" s.version = "1" s.summary = "summary" s.description = "desc" s.require_path = "lib" end util_make_exec one = @spec.dup one.version = 1 installer = Gem::Installer.for_spec spec installer.gem_dir = one.gem_dir installer.generate_bin installed_exec = File.join util_inst_bindir, "executable" expected = File.join @spec.gem_dir, "bin", "executable" assert_equal(expected, File.readlink(installed_exec), "Ensure symlink not moved") end def test_generate_bin_symlink_update_remove_wrapper pend "Symlinks not supported or not enabled" unless symlink_supported? installer = setup_base_installer installer.wrappers = true util_make_exec installer.gem_dir = @spec.gem_dir installer.generate_bin installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec @spec = Gem::Specification.new do |s| s.files = ["lib/code.rb"] s.name = "a" s.version = "3" s.summary = "summary" s.description = "desc" s.require_path = "lib" end util_make_exec util_installer @spec, @gemhome installer.wrappers = false installer.gem_dir = @spec.gem_dir installer.generate_bin installed_exec = File.join util_inst_bindir, "executable" assert_equal(@spec.bin_file("executable"), File.readlink(installed_exec), "Ensure symlink moved to latest version") end def test_generate_bin_symlink_win32 old_win_platform = Gem.win_platform? Gem.win_platform = true old_alt_separator = File::ALT_SEPARATOR File.__send__(:remove_const, :ALT_SEPARATOR) File.const_set(:ALT_SEPARATOR, "\\") installer = setup_base_installer installer.wrappers = false util_make_exec installer.gem_dir = @spec.gem_dir use_ui @ui do installer.generate_bin end assert_directory_exists util_inst_bindir installed_exec = File.join(util_inst_bindir, "executable") assert_path_exist installed_exec if symlink_supported? assert File.symlink?(installed_exec) return end assert_match(/Unable to use symlinks, installing wrapper/i, @ui.error) wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) ensure File.__send__(:remove_const, :ALT_SEPARATOR) File.const_set(:ALT_SEPARATOR, old_alt_separator) Gem.win_platform = old_win_platform end def test_generate_bin_uses_default_shebang pend "Symlinks not supported or not enabled" unless symlink_supported? load_relative "no" do installer = setup_base_installer installer.wrappers = true util_make_exec installer.generate_bin default_shebang = Gem.ruby shebang_line = File.open("#{@gemhome}/bin/executable", &:gets) assert_match(/\A#!/, shebang_line) assert_include(shebang_line, default_shebang) end end def test_generate_bin_with_dangling_symlink gem_with_dangling_symlink = File.expand_path("packages/ascii_binder-0.1.10.1.gem", __dir__) installer = Gem::Installer.at( gem_with_dangling_symlink, user_install: false, force: true ) build_rake_in do use_ui @ui do installer.install end end errors = @ui.error.split("\n") assert_equal "WARNING: ascii_binder-0.1.10.1 ships with a dangling symlink named bin/ascii_binder pointing to missing bin/asciibinder file. Ignoring", errors.shift assert_empty errors assert_empty @ui.output end def test_generate_plugins installer = util_setup_installer do |spec| write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| io.write "# do nothing" end spec.files += %w[lib/rubygems_plugin.rb] end build_rake_in do installer.install end plugin_path = File.join Gem.plugindir, "a_plugin.rb" FileUtils.rm plugin_path installer.generate_plugins assert File.exist?(plugin_path), "plugin not written" end def test_generate_plugins_with_install_dir spec = quick_gem "a" do |s| write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| io.write "puts __FILE__" end s.files += %w[lib/rubygems_plugin.rb] end util_build_gem spec plugin_path = File.join "#{@gemhome}2", "plugins", "a_plugin.rb" installer = util_installer spec, "#{@gemhome}2" assert_equal spec, installer.install assert File.exist?(plugin_path), "plugin not written to install_dir" end def test_generate_plugins_with_user_install spec = quick_gem "a" do |s| write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| io.write "puts __FILE__" end s.files += %w[lib/rubygems_plugin.rb] end util_build_gem spec File.chmod(0o555, Gem.plugindir) system_path = File.join(Gem.plugindir, "a_plugin.rb") user_path = File.join(Gem.plugindir(Gem.user_dir), "a_plugin.rb") installer = Gem::Installer.at spec.cache_file, user_install: true, force: true assert_equal spec, installer.install assert !File.exist?(system_path), "plugin incorrectly written to system plugins_dir" assert File.exist?(user_path), "plugin not written to user plugins_dir" end def test_generate_plugins_with_build_root spec = quick_gem "a" do |s| write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| io.write "puts __FILE__" end s.files += %w[lib/rubygems_plugin.rb] end util_build_gem spec File.chmod(0o555, Gem.plugindir) system_path = File.join(Gem.plugindir, "a_plugin.rb") build_root = File.join(@tempdir, "build_root") build_root_path = File.join(build_root, Gem.plugindir.gsub(/^[a-zA-Z]:/, ""), "a_plugin.rb") installer = Gem::Installer.at spec.cache_file, build_root: build_root assert_equal spec, installer.install assert !File.exist?(system_path), "plugin written incorrect written to system plugins_dir" assert File.exist?(build_root_path), "plugin not written to build_root" refute_includes File.read(build_root_path), build_root end class << self attr_accessor :plugin_loaded attr_accessor :post_install_is_called end def test_use_plugin_immediately self.class.plugin_loaded = false self.class.post_install_is_called = false spec_version = nil plugin_path = nil installer = util_setup_installer do |spec| spec_version = spec.version plugin_path = File.join("lib", "rubygems_plugin.rb") write_file File.join(@tempdir, plugin_path) do |io| io.write <<-PLUGIN #{self.class}.plugin_loaded = true Gem.post_install do #{self.class}.post_install_is_called = true end PLUGIN end spec.files += [plugin_path] plugin_path = File.join(spec.gem_dir, plugin_path) end build_rake_in do installer.install end assert self.class.plugin_loaded, "plugin is not loaded" assert self.class.post_install_is_called, "post install hook registered by plugin is not called" self.class.plugin_loaded = false $LOADED_FEATURES.delete(plugin_path) installer_new = util_setup_installer do |spec_new| spec_new.version = spec_version.version.succ plugin_path = File.join("lib", "rubygems_plugin.rb") write_file File.join(@tempdir, plugin_path) do |io| io.write "#{self.class}.plugin_loaded = true" end spec_new.files += [plugin_path] end build_rake_in do installer_new.install end assert !self.class.plugin_loaded, "plugin is loaded even when old version is already loaded" end def test_keeps_plugins_up_to_date # NOTE: version a-2 is already installed by setup hooks write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| io.write "# do nothing" end build_rake_in do util_setup_installer do |spec| spec.version = "1" spec.files += %w[lib/rubygems_plugin.rb] end.install plugin_path = File.join Gem.plugindir, "a_plugin.rb" refute File.exist?(plugin_path), "old version installed while newer version without plugin also installed, but plugin written" util_setup_installer do |spec| spec.version = "2" spec.files += %w[lib/rubygems_plugin.rb] end.install plugin_path = File.join Gem.plugindir, "a_plugin.rb" assert File.exist?(plugin_path), "latest version reinstalled, but plugin not written" assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), "written plugin has incorrect content" util_setup_installer do |spec| spec.version = "3" spec.files += %w[lib/rubygems_plugin.rb] end.install plugin_path = File.join Gem.plugindir, "a_plugin.rb" assert File.exist?(plugin_path), "latest version installed, but plugin removed" assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), "written plugin has incorrect content" util_setup_installer do |spec| spec.version = "4" end.install refute File.exist?(plugin_path), "new version installed without a plugin while older version with a plugin installed, but plugin not removed" end end def test_generates_plugins_dir_under_install_dir_if_not_there Gem.use_paths "#{@gemhome}2" # Set GEM_HOME to an uninitialized repo @spec = util_spec "a" path = Gem::Package.build @spec installer = Gem::Installer.at path, install_dir: "#{@gemhome}3" assert_equal @spec, installer.install end def test_initialize spec = util_spec "a" do |s| s.platform = Gem::Platform.new "mswin32" end gem = File.join @tempdir, spec.file_name Dir.mkdir util_inst_bindir util_build_gem spec FileUtils.mv spec.cache_file, @tempdir installer = Gem::Installer.at gem assert_equal File.join(@gemhome, "gems", spec.full_name), installer.gem_dir assert_equal File.join(@gemhome, "bin"), installer.bin_dir end def test_initialize_user_install @gem = setup_base_gem installer = Gem::Installer.at @gem, user_install: true assert_equal File.join(Gem.user_dir, "gems", @spec.full_name), installer.gem_dir assert_equal Gem.bindir(Gem.user_dir), installer.bin_dir end def test_initialize_user_install_bin_dir @gem = setup_base_gem installer = Gem::Installer.at @gem, user_install: true, bin_dir: @tempdir assert_equal File.join(Gem.user_dir, "gems", @spec.full_name), installer.gem_dir assert_equal @tempdir, installer.bin_dir end def test_install_dir_takes_precedence_to_user_install gemhome2 = "#{@gemhome}2" @gem = setup_base_gem installer = Gem::Installer.at @gem, install_dir: gemhome2, user_install: true installer.install assert_path_exist File.join(gemhome2, "gems", @spec.full_name) assert_path_not_exist File.join(Gem.user_dir, "gems", @spec.full_name) end def test_install installer = util_setup_installer gemdir = File.join @gemhome, "gems", @spec.full_name cache_file = File.join @gemhome, "cache", @spec.file_name stub_exe = File.join @gemhome, "bin", "executable" rakefile = File.join gemdir, "ext", "a", "Rakefile" spec_file = File.join @gemhome, "specifications", @spec.spec_name Gem.pre_install do assert_path_not_exist cache_file, "cache file must not exist yet" true end Gem.post_build do assert_path_exist gemdir, "gem install dir must exist" assert_path_exist rakefile, "gem executable must exist" assert_path_not_exist stub_exe, "gem executable must not exist" true end Gem.post_install do assert_path_exist cache_file, "cache file must exist" end @newspec = nil build_rake_in do use_ui @ui do @newspec = installer.install end end assert_equal @spec, @newspec assert_path_exist gemdir assert_path_exist stub_exe, "gem executable must exist" exe = File.join gemdir, "bin", "executable" assert_path_exist exe exe_mode = File.stat(exe).mode & 0o111 assert_equal 0o111, exe_mode, format("0%o", exe_mode) unless Gem.win_platform? assert_path_exist File.join gemdir, "lib", "code.rb" assert_path_exist rakefile assert_equal spec_file, @newspec.loaded_from assert_path_exist spec_file assert_same installer, @post_build_hook_arg assert_same installer, @post_install_hook_arg assert_same installer, @pre_install_hook_arg end def test_install_creates_working_binstub installer = util_setup_installer installer.wrappers = true gemdir = File.join @gemhome, "gems", @spec.full_name @newspec = nil build_rake_in do use_ui @ui do @newspec = installer.install end end exe = File.join gemdir, "bin", "executable" e = assert_raise RuntimeError do instance_eval File.read(exe) end assert_match(/ran executable/, e.message) end def test_conflicting_binstubs @gem = setup_base_gem # build old version that has a bin file installer = util_setup_gem do |_spec| File.open File.join("bin", "executable"), "w" do |f| f.puts "require 'code'" end File.open File.join("lib", "code.rb"), "w" do |f| f.puts 'raise "I have an executable"' end end installer.wrappers = true build_rake_in do use_ui @ui do @newspec = installer.install end end old_bin_file = File.join installer.bin_dir, "executable" # build new version that doesn't have a bin file installer = util_setup_gem do |spec| FileUtils.rm File.join("bin", "executable") spec.files.delete File.join("bin", "executable") spec.executables.delete "executable" spec.version = @spec.version.bump File.open File.join("lib", "code.rb"), "w" do |f| f.puts 'raise "I do not have an executable"' end end build_rake_in do use_ui @ui do @newspec = installer.install end end e = assert_raise RuntimeError do instance_eval File.read(old_bin_file) end # We expect the bin stub to activate the version that actually contains # the binstub. assert_match("I have an executable", e.message) end def test_install_creates_binstub_that_understand_version installer = util_setup_installer installer.wrappers = true @newspec = nil build_rake_in do use_ui @ui do @newspec = installer.install end end exe = File.join @gemhome, "bin", "executable" ARGV.unshift "_3.0_" begin Gem::Specification.reset e = assert_raise Gem::GemNotFoundException do instance_eval File.read(exe) end ensure ARGV.shift if ARGV.first == "_3.0_" end assert_includes(e.message, "can't find gem a (= 3.0)") end def test_install_creates_binstub_that_prefers_user_installed_gem_to_default default_spec = new_default_spec("default", "2", nil, "exe/executable") default_spec.executables = "executable" install_default_gems default_spec exe = File.join @gemhome, "bin", "executable" assert_path_exist exe, "default gem's executable not installed" installer = util_setup_installer do |spec| spec.name = "default" spec.version = "2" end util_clear_gems installer.wrappers = true @newspec = nil build_rake_in do use_ui @ui do @newspec = installer.install end end e = assert_raise RuntimeError do instance_eval File.read(exe) end assert_equal(e.message, "ran executable") end def test_install_creates_binstub_that_dont_trust_encoding installer = util_setup_installer installer.wrappers = true @newspec = nil build_rake_in do use_ui @ui do @newspec = installer.install end end exe = File.join @gemhome, "bin", "executable" extra_arg = "\xE4pfel".dup.force_encoding("UTF-8") ARGV.unshift extra_arg begin Gem::Specification.reset e = assert_raise RuntimeError do instance_eval File.read(exe) end ensure ARGV.shift if ARGV.first == extra_arg end assert_match(/ran executable/, e.message) end def test_install_with_no_prior_files installer = util_setup_installer build_rake_in do use_ui @ui do assert_equal @spec, installer.install end end gemdir = File.join(@gemhome, "gems", @spec.full_name) assert_path_exist File.join gemdir, "lib", "code.rb" installer = util_setup_installer # Morph spec to have lib/other.rb instead of code.rb and recreate @spec.files = File.join("lib", "other.rb") Dir.chdir @tempdir do File.open File.join("lib", "other.rb"), "w" do |f| f.puts "1" end use_ui ui do FileUtils.rm @gem Gem::Package.build @spec end end installer = Gem::Installer.at @gem, force: true build_rake_in do use_ui @ui do assert_equal @spec, installer.install end end assert_path_exist File.join gemdir, "lib", "other.rb" assert_path_not_exist File.join gemdir, "lib", "code.rb", "code.rb from prior install of same gem shouldn't remain here" end def test_install_force _, missing_dep_gem = util_gem "missing_dep", "1" do |s| s.add_dependency "doesnt_exist", "1" end use_ui @ui do installer = Gem::Installer.at missing_dep_gem, force: true installer.install end gem_dir = File.join(@gemhome, "gems", "missing_dep-1") assert_path_exist gem_dir end def test_install_build_root build_root = File.join(@tempdir, "build_root") @gem = setup_base_gem installer = Gem::Installer.at @gem, build_root: build_root assert_equal @spec, installer.install end def test_install_build_root_when_gem_home_not_writable_does_not_fallback_to_user_install_inside_build_root build_root = File.join(@tempdir, "build_root") orig_gem_home = ENV.delete("GEM_HOME") @gem = setup_base_gem FileUtils.chmod "-w", @gemhome installer = Gem::Installer.at @gem, build_root: build_root assert_equal @spec, installer.install build_root_path = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, "")) assert File.exist?(build_root_path), "gem not written to build_root" ensure FileUtils.chmod "+w", @gemhome ENV["GEM_HOME"] = orig_gem_home end def test_install_missing_dirs installer = setup_base_installer FileUtils.rm_rf File.join(Gem.dir, "doc") FileUtils.rm_rf File.join(Gem.dir, "specifications") use_ui @ui do installer.install end assert_directory_exists File.join(Gem.dir, "doc") assert_directory_exists File.join(Gem.dir, "specifications") assert_path_exist File.join @gemhome, "cache", @spec.file_name assert_path_exist File.join @gemhome, "specifications", @spec.spec_name end def test_install_post_build_false @spec = util_spec "a" util_build_gem @spec installer = util_installer @spec, @gemhome Gem.post_build do false end use_ui @ui do e = assert_raise Gem::InstallError do installer.install end location = "#{__FILE__}:#{__LINE__ - 9}" assert_equal "post-build hook at #{location} failed for a-2", e.message end spec_file = File.join @gemhome, "specifications", @spec.spec_name assert_path_not_exist spec_file gem_dir = File.join @gemhome, "gems", @spec.full_name assert_path_not_exist gem_dir end def test_install_post_build_nil installer = setup_base_installer Gem.post_build do nil end use_ui @ui do installer.install end spec_file = File.join @gemhome, "specifications", @spec.spec_name assert_path_exist spec_file gem_dir = File.join @gemhome, "gems", @spec.full_name assert_path_exist gem_dir end def test_install_pre_install_false @spec = util_spec "a" util_build_gem @spec installer = util_installer @spec, @gemhome Gem.pre_install do false end use_ui @ui do e = assert_raise Gem::InstallError do installer.install end location = "#{__FILE__}:#{__LINE__ - 9}" assert_equal "pre-install hook at #{location} failed for a-2", e.message end spec_file = File.join @gemhome, "specifications", @spec.spec_name assert_path_not_exist spec_file end def test_install_pre_install_nil installer = setup_base_installer Gem.pre_install do nil end use_ui @ui do installer.install end spec_file = File.join @gemhome, "specifications", @spec.spec_name assert_path_exist spec_file end def test_install_with_message @spec = setup_base_spec @spec.post_install_message = "I am a shiny gem!" use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path installer.install end assert_match(/I am a shiny gem!/, @ui.output) end def test_install_with_skipped_message @spec = setup_base_spec @spec.post_install_message = "I am a shiny gem!" use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path, post_install_message: false installer.install end refute_match(/I am a shiny gem!/, @ui.output) end def test_install_extension_dir gemhome2 = "#{@gemhome}2" @spec = setup_base_spec @spec.extensions << "extconf.rb" write_file File.join(@tempdir, "extconf.rb") do |io| io.write <<-RUBY require "mkmf" create_makefile("#{@spec.name}") RUBY end @spec.files += %w[extconf.rb] use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path, install_dir: gemhome2 installer.install end expected_makefile = File.join gemhome2, "gems", @spec.full_name, "Makefile" assert_path_exist expected_makefile end def test_install_extension_dir_is_removed_on_reinstall @spec = setup_base_spec @spec.extensions << "extconf.rb" write_file File.join(@tempdir, "extconf.rb") do |io| io.write <<-RUBY require "mkmf" create_makefile("#{@spec.name}") RUBY end @spec.files += %w[extconf.rb] path = Gem::Package.build @spec # Install a gem with an extension use_ui @ui do installer = Gem::Installer.at path installer.install end # pretend that a binary file was created as part of the build should_be_removed = File.join(@spec.extension_dir, "#{@spec.name}.so") write_file should_be_removed do |io| io.write "DELETE ME ON REINSTALL" end assert_path_exist should_be_removed # reinstall the gem, this is also the same as pristine use_ui @ui do installer = Gem::Installer.at path, force: true installer.install end assert_path_not_exist should_be_removed end def test_install_user_extension_dir @spec = setup_base_spec @spec.extensions << "extconf.rb" write_file File.join(@tempdir, "extconf.rb") do |io| io.write <<-RUBY require "mkmf" create_makefile("#{@spec.name}") RUBY end @spec.files += %w[extconf.rb] # Create the non-user ext dir expected_extension_dir = @spec.extension_dir.dup FileUtils.mkdir_p expected_extension_dir use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path, user_install: true installer.install end expected_makefile = File.join Gem.user_dir, "gems", @spec.full_name, "Makefile" assert_path_exist expected_makefile assert_path_exist expected_extension_dir assert_path_not_exist File.join expected_extension_dir, "gem_make.out" end def test_find_lib_file_after_install pend "extensions don't quite work on jruby" if Gem.java_platform? @spec = setup_base_spec @spec.extensions << "extconf.rb" write_file File.join(@tempdir, "extconf.rb") do |io| io.write <<-RUBY require "mkmf" CONFIG['CC'] = '$(TOUCH) $@ ||' CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' $ruby = '#{Gem.ruby}' create_makefile("#{@spec.name}") RUBY end write_file File.join(@tempdir, "depend") write_file File.join(@tempdir, "a.c") do |io| io.write <<-C #include void Init_a() { } C end Dir.mkdir File.join(@tempdir, "lib") write_file File.join(@tempdir, "lib", "b.rb") do |io| io.write "# b.rb" end @spec.files += %w[extconf.rb lib/b.rb depend a.c] use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path installer.install end expected = File.join @spec.full_require_paths.find {|path| File.exist? File.join path, "b.rb" }, "b.rb" assert_equal expected, @spec.matches_for_glob("b.rb").first end def test_install_extension_and_script pend "Makefile creation crashes on jruby" if Gem.java_platform? pend "terminates on mswin" if vc_windows? && ruby_repo? @spec = setup_base_spec @spec.extensions << "extconf.rb" write_file File.join(@tempdir, "extconf.rb") do |io| io.write <<-RUBY require "mkmf" create_makefile("#{@spec.name}") RUBY end rb = File.join("lib", "#{@spec.name}.rb") @spec.files += [rb] write_file File.join(@tempdir, rb) do |io| io.write <<-RUBY # #{@spec.name}.rb RUBY end Dir.mkdir(File.join("lib", @spec.name)) rb2 = File.join("lib", @spec.name, "#{@spec.name}.rb") @spec.files << rb2 write_file File.join(@tempdir, rb2) do |io| io.write <<-RUBY # #{@spec.name}/#{@spec.name}.rb RUBY end assert_path_not_exist File.join @spec.gem_dir, rb assert_path_not_exist File.join @spec.gem_dir, rb2 use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path installer.install end assert_path_exist File.join @spec.gem_dir, rb assert_path_exist File.join @spec.gem_dir, rb2 end def test_install_extension_flat pend "extensions don't quite work on jruby" if Gem.java_platform? begin @spec = setup_base_spec @spec.require_paths = ["."] @spec.extensions << "extconf.rb" write_file File.join(@tempdir, "extconf.rb") do |io| io.write <<-RUBY require "mkmf" CONFIG['CC'] = '$(TOUCH) $@ ||' CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' $ruby = '#{Gem.ruby}' create_makefile("#{@spec.name}") RUBY end # empty depend file for no auto dependencies @spec.files += %W[depend #{@spec.name}.c].each do |file| write_file File.join(@tempdir, file) end so = File.join(@spec.extension_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}") assert_path_not_exist so use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path installer.install end assert_path_exist so end end def test_install_extension_clean_intermediate_files pend "extensions don't quite work on jruby" if Gem.java_platform? @spec = setup_base_spec @spec.require_paths = ["."] @spec.extensions << "extconf.rb" File.write File.join(@tempdir, "extconf.rb"), <<-RUBY require "mkmf" CONFIG['CC'] = '$(TOUCH) $@ ||' CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' $ruby = '#{Gem.ruby}' create_makefile("#{@spec.name}") RUBY # empty depend file for no auto dependencies @spec.files += %W[depend #{@spec.name}.c].each do |file| write_file File.join(@tempdir, file) end shared_object = "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}" extension_file = File.join @spec.extension_dir, shared_object intermediate_file = File.join @spec.gem_dir, shared_object assert_path_not_exist extension_file, "no before installing" use_ui @ui do path = Gem::Package.build @spec installer = Gem::Installer.at path installer.install end assert_path_exist extension_file, "installed" assert_path_not_exist intermediate_file end def test_installation_satisfies_dependency_eh installer = setup_base_installer util_spec "a" dep = Gem::Dependency.new "a", ">= 2" assert installer.installation_satisfies_dependency?(dep) dep = Gem::Dependency.new "a", "> 2" refute installer.installation_satisfies_dependency?(dep) end def test_installation_satisfies_dependency_eh_development installer = setup_base_installer installer.options[:development] = true installer.options[:dev_shallow] = true util_spec "a" dep = Gem::Dependency.new "a", :development assert installer.installation_satisfies_dependency?(dep) end def test_pre_install_checks_dependencies installer = setup_base_installer @spec.add_dependency "b", "> 5" installer = util_setup_gem installer.force = false use_ui @ui do assert_raise Gem::InstallError do installer.install end end end def test_pre_install_checks_dependencies_ignore installer = util_setup_installer @spec.add_dependency "b", "> 5" installer.ignore_dependencies = true build_rake_in do use_ui @ui do assert installer.pre_install_checks end end end def test_pre_install_checks_dependencies_install_dir gemhome2 = "#{@gemhome}2" @gem = setup_base_gem @spec.add_dependency "d" quick_gem "d", 2 gem = File.join @gemhome, @spec.file_name FileUtils.mv @gemhome, gemhome2 FileUtils.mkdir @gemhome FileUtils.mv File.join(gemhome2, "cache", @spec.file_name), gem # Don't leak any already activated gems into the installer, require # that it work everything out on it's own. Gem::Specification.reset installer = Gem::Installer.at gem, install_dir: gemhome2 build_rake_in do use_ui @ui do assert installer.pre_install_checks end end end def test_pre_install_checks_malicious_name spec = util_spec "../malicious", "1" def spec.full_name # so the spec is buildable "malicious-1" end def spec.validate(packaging, strict); end util_build_gem spec gem = File.join(@gemhome, "cache", spec.file_name) use_ui @ui do installer = Gem::Installer.at gem e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid name", e.message end end def test_pre_install_checks_malicious_name_before_eval spec = util_spec "malicious\n::Object.const_set(:FROM_EVAL, true)#", "1" def spec.full_name # so the spec is buildable "malicious-1" end def spec.validate(*args); end util_build_gem spec gem = File.join(@gemhome, "cache", spec.file_name) use_ui @ui do installer = Gem::Installer.at gem e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid name", e.message end refute defined?(::Object::FROM_EVAL) end def test_pre_install_checks_malicious_require_paths_before_eval spec = util_spec "malicious", "1" def spec.full_name # so the spec is buildable "malicious-1" end def spec.validate(*args); end spec.require_paths = ["malicious\n``"] util_build_gem spec gem = File.join(@gemhome, "cache", spec.file_name) use_ui @ui do installer = Gem::Installer.at gem e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid require_paths", e.message end end def test_pre_install_checks_malicious_extensions_before_eval pend "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform? spec = util_spec "malicious", "1" def spec.full_name # so the spec is buildable "malicious-1" end def spec.validate(*args); end spec.extensions = ["malicious\n``"] util_build_gem spec gem = File.join(@gemhome, "cache", spec.file_name) use_ui @ui do installer = Gem::Installer.at gem e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid extensions", e.message end end def test_pre_install_checks_malicious_specification_version_before_eval spec = util_spec "malicious", "1" def spec.full_name # so the spec is buildable "malicious-1" end def spec.validate(*args); end spec.specification_version = "malicious\n``" util_build_gem spec gem = File.join(@gemhome, "cache", spec.file_name) use_ui @ui do installer = Gem::Installer.at gem e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid specification_version", e.message end end def test_pre_install_checks_malicious_dependencies_before_eval spec = util_spec "malicious", "1" def spec.full_name # so the spec is buildable "malicious-1" end def spec.validate(*args); end spec.add_dependency "b\nfoo", "> 5" util_build_gem spec gem = File.join(@gemhome, "cache", spec.file_name) use_ui @ui do installer = Gem::Installer.at gem installer.ignore_dependencies = true e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "# has an invalid dependencies", e.message end end def test_pre_install_checks_malicious_platform_before_eval gem_with_ill_formated_platform = File.expand_path("packages/ill-formatted-platform-1.0.0.10.gem", __dir__) installer = Gem::Installer.at( gem_with_ill_formated_platform, install_dir: @gemhome, user_install: false, force: true ) use_ui @ui do e = assert_raise Gem::InstallError do installer.pre_install_checks end assert_equal "x86-mswin32\n system('id > /tmp/nyangawa')# is an invalid platform", e.message assert_empty @ui.output end end def test_shebang load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/ruby" shebang = installer.shebang "executable" assert_equal "#!#{Gem.ruby}", shebang end end def test_process_options installer = setup_base_installer assert_nil installer.build_root assert_equal File.join(@gemhome, "bin"), installer.bin_dir assert_equal @gemhome, installer.gem_home end def test_process_options_build_root build_root = File.join @tempdir, "build_root" bin_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ""), "bin") gem_home = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, "")) plugins_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ""), "plugins") @gem = setup_base_gem installer = use_ui(@ui) { Gem::Installer.at @gem, build_root: build_root } assert_equal build_root, installer.build_root assert_equal bin_dir, installer.bin_dir assert_equal gem_home, installer.gem_home errors = @ui.error.split("\n") assert_equal "WARNING: You build with buildroot.", errors.shift assert_equal " Build root: #{build_root}", errors.shift assert_equal " Bin dir: #{bin_dir}", errors.shift assert_equal " Gem home: #{gem_home}", errors.shift assert_equal " Plugins dir: #{plugins_dir}", errors.shift end def test_process_options_fallback_to_user_install_when_gem_home_not_writable if Process.uid.zero? pend("skipped in root privilege") return end orig_gem_home = ENV.delete("GEM_HOME") @gem = setup_base_gem FileUtils.chmod 0o000, @gemhome installer = use_ui(@ui) { Gem::Installer.at @gem } assert_equal Gem.user_dir, installer.gem_home assert_equal "Defaulting to user installation because default installation directory (#{@gemhome}) is not writable.", @ui.output.strip ensure FileUtils.chmod 0o755, @gemhome ENV["GEM_HOME"] = orig_gem_home end def test_process_options_does_not_fallback_to_user_install_when_gem_home_not_writable_and_no_user_install if Process.uid.zero? pend("skipped in root privilege") return end orig_gem_home = ENV.delete("GEM_HOME") @gem = setup_base_gem FileUtils.chmod 0o000, @gemhome installer = use_ui(@ui) { Gem::Installer.at @gem, user_install: false } assert_equal @gemhome, installer.gem_home assert_empty @ui.output.strip ensure FileUtils.chmod 0o755, @gemhome ENV["GEM_HOME"] = orig_gem_home end def test_shebang_arguments load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/ruby -ws" shebang = installer.shebang "executable" 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 load_relative "no" do installer = setup_base_installer util_make_exec @spec, "" shebang = installer.shebang "executable" assert_equal "#!#{Gem.ruby}", shebang end end def test_shebang_env load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/env ruby" shebang = installer.shebang "executable" assert_equal "#!#{Gem.ruby}", shebang end end def test_shebang_env_arguments load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/env ruby -ws" shebang = installer.shebang "executable" 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 installer = setup_base_installer util_make_exec @spec, "" installer.env_shebang = true shebang = installer.shebang "executable" bin_env = get_bin_env assert_equal("#!#{bin_env} #{RbConfig::CONFIG["ruby_install_name"]}", shebang) end def test_shebang_nested load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/opt/local/ruby/bin/ruby" shebang = installer.shebang "executable" assert_equal "#!#{Gem.ruby}", shebang end end def test_shebang_nested_arguments load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws" shebang = installer.shebang "executable" 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 load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/ruby18" shebang = installer.shebang "executable" assert_equal "#!#{Gem.ruby}", shebang end end def test_shebang_version_arguments load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/ruby18 -ws" shebang = installer.shebang "executable" 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 load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/env ruby18" shebang = installer.shebang "executable" assert_equal "#!#{Gem.ruby}", shebang end end def test_shebang_version_env_arguments load_relative "no" do installer = setup_base_installer util_make_exec @spec, "#!/usr/bin/env ruby18 -ws" shebang = installer.shebang "executable" 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 installer = setup_base_installer conf = Gem::ConfigFile.new [] conf[:custom_shebang] = "test" Gem.configuration = conf util_make_exec @spec, "#!/usr/bin/ruby" shebang = installer.shebang "executable" assert_equal "#!test", shebang end def get_bin_env if Gem.win_platform? "" else %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } end end def test_shebang_custom_with_expands installer = setup_base_installer bin_env = get_bin_env conf = Gem::ConfigFile.new [] conf[:custom_shebang] = "1 $env 2 $ruby 3 $exec 4 $name" Gem.configuration = conf util_make_exec @spec, "#!/usr/bin/ruby" shebang = installer.shebang "executable" assert_equal "#!1 #{bin_env} 2 #{Gem.ruby} 3 executable 4 a", shebang end def test_shebang_custom_with_expands_and_arguments installer = setup_base_installer bin_env = get_bin_env conf = Gem::ConfigFile.new [] conf[:custom_shebang] = "1 $env 2 $ruby 3 $exec" Gem.configuration = conf util_make_exec @spec, "#!/usr/bin/ruby -ws" shebang = installer.shebang "executable" assert_equal "#!1 #{bin_env} 2 #{Gem.ruby} -ws 3 executable", shebang end def test_unpack installer = util_setup_installer dest = File.join @gemhome, "gems", @spec.full_name Gem::Deprecate.skip_during do installer.unpack dest end assert_path_exist File.join dest, "lib", "code.rb" assert_path_exist File.join dest, "bin", "executable" end def test_write_build_info_file installer = setup_base_installer assert_path_not_exist @spec.build_info_file installer.build_args = %w[ --with-libyaml-dir /usr/local/Cellar/libyaml/0.1.4 ] installer.write_build_info_file assert_path_exist @spec.build_info_file expected = "--with-libyaml-dir\n/usr/local/Cellar/libyaml/0.1.4\n" assert_equal expected, File.read(@spec.build_info_file) end def test_write_build_info_file_empty installer = setup_base_installer assert_path_not_exist @spec.build_info_file installer.write_build_info_file assert_path_not_exist @spec.build_info_file end def test_write_build_info_file_install_dir @gem = setup_base_gem installer = Gem::Installer.at @gem, install_dir: "#{@gemhome}2" installer.build_args = %w[ --with-libyaml-dir /usr/local/Cellar/libyaml/0.1.4 ] installer.write_build_info_file assert_path_not_exist @spec.build_info_file assert_path_exist \ File.join("#{@gemhome}2", "build_info", "#{@spec.full_name}.info") end def test_write_cache_file @gem = setup_base_gem cache_file = File.join @gemhome, "cache", @spec.file_name gem = File.join @gemhome, @spec.file_name FileUtils.mv cache_file, gem assert_path_not_exist cache_file installer = Gem::Installer.at gem installer.gem_home = @gemhome installer.write_cache_file assert_path_exist cache_file end def test_write_spec @spec = setup_base_spec FileUtils.rm @spec.spec_file assert_path_not_exist @spec.spec_file installer = Gem::Installer.for_spec @spec installer.gem_home = @gemhome installer.write_spec assert_path_exist @spec.spec_file loaded = Gem::Specification.load @spec.spec_file assert_equal @spec, loaded assert_equal Gem.rubygems_version, @spec.installed_by_version end def test_write_spec_writes_cached_spec @spec = setup_base_spec FileUtils.rm @spec.spec_file assert_path_not_exist @spec.spec_file @spec.files = %w[a.rb b.rb c.rb] installer = Gem::Installer.for_spec @spec installer.gem_home = @gemhome installer.write_spec # cached specs have no file manifest: @spec.files = [] assert_equal @spec, eval(File.read(@spec.spec_file)) end def test_leaves_no_empty_cached_spec_when_no_more_disk_space @spec = setup_base_spec FileUtils.rm @spec.spec_file assert_path_not_exist @spec.spec_file @spec.files = %w[a.rb b.rb c.rb] installer = Gem::Installer.for_spec @spec installer.gem_home = @gemhome File.class_eval do alias_method :original_write, :write def write(data) raise Errno::ENOSPC end end assert_raise Errno::ENOSPC do installer.write_spec end assert_path_not_exist @spec.spec_file ensure File.class_eval do remove_method :write alias_method :write, :original_write remove_method :original_write end end def test_dir installer = setup_base_installer assert_match %r{/gemhome/gems/a-2$}, installer.dir end def test_default_gem_loaded_from spec = util_spec "a" installer = Gem::Installer.for_spec spec, install_as_default: true installer.install assert_predicate spec, :default_gem? end def test_default_gem_without_wrappers installer = setup_base_installer FileUtils.rm_rf File.join(Gem.default_dir, "specifications") installer.wrappers = false installer.options[:install_as_default] = true installer.gem_dir = @spec.gem_dir use_ui @ui do installer.install end assert_directory_exists File.join(@spec.gem_dir, "bin") installed_exec = File.join @spec.gem_dir, "bin", "executable" assert_path_exist installed_exec assert_directory_exists File.join(Gem.default_dir, "specifications") assert_directory_exists File.join(Gem.default_dir, "specifications", "default") default_spec = eval File.read File.join(Gem.default_dir, "specifications", "default", "a-2.gemspec") assert_equal Gem::Version.new("2"), default_spec.version assert_equal ["bin/executable"], default_spec.files assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec wrapper = File.read installed_exec if symlink_supported? refute_match(/generated by RubyGems/, wrapper) else # when symlink not supported, it warns and fallbacks back to installing wrapper assert_match(/Unable to use symlinks, installing wrapper/, @ui.error) assert_match(/generated by RubyGems/, wrapper) end end def test_default_gem_with_wrappers installer = setup_base_installer installer.wrappers = true installer.options[:install_as_default] = true installer.gem_dir = @spec.gem_dir use_ui @ui do installer.install end assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec wrapper = File.read installed_exec assert_match(/generated by RubyGems/, wrapper) end def test_default_gem_with_exe_as_bindir @spec = quick_gem "c" do |spec| util_make_exec spec, "#!/usr/bin/ruby", "exe" end util_build_gem @spec @spec.cache_file installer = util_installer @spec, @gemhome installer.options[:install_as_default] = true installer.gem_dir = @spec.gem_dir use_ui @ui do installer.install end assert_directory_exists File.join(@spec.gem_dir, "exe") installed_exec = File.join @spec.gem_dir, "exe", "executable" assert_path_exist installed_exec assert_directory_exists File.join(Gem.default_dir, "specifications") assert_directory_exists File.join(Gem.default_dir, "specifications", "default") default_spec = eval File.read File.join(Gem.default_dir, "specifications", "default", "c-2.gemspec") assert_equal Gem::Version.new("2"), default_spec.version assert_equal ["exe/executable"], default_spec.files end def test_default_gem_to_specific_install_dir @gem = setup_base_gem installer = util_installer @spec, "#{@gemhome}2" installer.options[:install_as_default] = true use_ui @ui do installer.install end assert_directory_exists File.join("#{@gemhome}2", "specifications") assert_directory_exists File.join("#{@gemhome}2", "specifications", "default") default_spec = eval File.read File.join("#{@gemhome}2", "specifications", "default", "a-2.gemspec") assert_equal Gem::Version.new("2"), default_spec.version assert_equal ["bin/executable"], default_spec.files end def test_package_attribute gem = quick_gem "c" do |spec| util_make_exec spec, "#!/usr/bin/ruby", "exe" end installer = util_installer(gem, @gemhome) assert_respond_to(installer, :package) assert_kind_of(Gem::Package, installer.package) end def test_gem_attribute gem = quick_gem "c" do |spec| util_make_exec spec, "#!/usr/bin/ruby", "exe" end installer = util_installer(gem, @gemhome) assert_respond_to(installer, :gem) assert_kind_of(String, installer.gem) end private def util_execless @spec = util_spec "z" util_build_gem @spec util_installer @spec, @gemhome end def util_conflict_executable(wrappers) conflict = quick_gem "conflict" do |spec| util_make_exec spec end util_build_gem conflict installer = util_installer conflict, @gemhome installer.wrappers = wrappers installer.generate_bin end def mask 0o100755 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