diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 18170230dff1d9..0477b4703538aa 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -675,14 +675,16 @@ def process_options # :nodoc: @build_args = options[:build_args] - @gem_home = @install_dir - @gem_home ||= if options[:user_install] - Gem.user_dir - elsif !ENV.key?("GEM_HOME") && (File.exist?(Gem.dir) && !File.writable?(Gem.dir)) - say "Defaulting to user installation because default installation directory (#{Gem.dir}) is not writable." - Gem.user_dir - else - Gem.dir + @gem_home = @install_dir || Gem.dir + + # `--build-root` overrides `--user-install` and auto-user-install + if @build_root.nil? && @install_dir.nil? + if options[:user_install] + @gem_home = Gem.user_dir + elsif !ENV.key?("GEM_HOME") && (File.exist?(Gem.dir) && !File.writable?(Gem.dir)) + say "Defaulting to user installation because default installation directory (#{Gem.dir}) is not writable." + @gem_home = Gem.user_dir + end end # If the user has asked for the gem to be installed in a directory that is diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index 03903ff9d30950..d0f213fb8d4d05 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -1285,6 +1285,26 @@ def test_install_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