From 9e857ffb52a8b1f75788d7b8ec868215793a44e9 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Sat, 18 May 2019 15:10:18 +0000 Subject: [PATCH] Don't apply `--destdir` twice when running `setup.rb` Prior to this patch, if I ran: ruby setup.rb --destdir /foo Then Bundler files would be written into /foo/foo, because destdir was being prepended, even though `bundler_spec.bin_dir` already included destdir. --- lib/rubygems/commands/setup_command.rb | 13 ++++++++++- .../test_gem_commands_setup_command.rb | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb index 90f17b903745..edc4008cb82b 100644 --- a/lib/rubygems/commands/setup_command.rb +++ b/lib/rubygems/commands/setup_command.rb @@ -385,6 +385,18 @@ def install_default_bundler_gem(bin_dir) bundler_spec = Gem::Specification.load(default_spec_path) + # The base_dir value for a specification is inferred by walking up from the + # folder where the spec was `loaded_from`. In the case of default gems, we + # walk up two levels, because they live at `specifications/default/`, whereas + # in the case of regular gems we walk up just one level because they live at + # `specifications/`. However, in this case, the gem we are installing is + # misdetected as a regular gem, when it's a default gem in reality. This is + # because when there's a `:destdir`, the `loaded_from` path has changed and + # doesn't match `Gem.default_specifications_dir` which is the criteria to + # tag a gem as a default gem. So, in that case, write the correct + # `@base_dir` directly. + bundler_spec.instance_variable_set(:@base_dir, File.dirname(File.dirname(specs_dir))) + # Remove gemspec that was same version of vendored bundler. normal_gemspec = File.join(Gem.default_dir, "specifications", "bundler-#{bundler_spec.version}.gemspec") if File.file? normal_gemspec @@ -399,7 +411,6 @@ def install_default_bundler_gem(bin_dir) end bundler_bin_dir = bundler_spec.bin_dir - bundler_bin_dir = File.join(options[:destdir], bundler_bin_dir) unless Gem.win_platform? mkdir_p bundler_bin_dir, :mode => 0755 bundler_spec.executables.each do |e| cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_bin_dir, e) diff --git a/test/rubygems/test_gem_commands_setup_command.rb b/test/rubygems/test_gem_commands_setup_command.rb index 3aa6bfa2fe56..b66943610dd5 100644 --- a/test/rubygems/test_gem_commands_setup_command.rb +++ b/test/rubygems/test_gem_commands_setup_command.rb @@ -246,6 +246,28 @@ def test_install_default_bundler_gem_with_force_flag end end + def test_install_default_bundler_gem_with_destdir_flag + @cmd.extend FileUtils + + bin_dir = File.join(@gemhome, 'bin') + + bindir(bin_dir) do + destdir = File.join(@tempdir, 'foo') + + @cmd.options[:destdir] = destdir + + @cmd.install_default_bundler_gem bin_dir + + bundler_spec = Gem::Specification.load("bundler/bundler.gemspec") + default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec") + spec = Gem::Specification.load(default_spec_path) + + spec.executables.each do |e| + assert_path_exist File.join destdir, spec.bin_dir.gsub(/^[a-zA-Z]:/, ''), e + end + end + end + def test_remove_old_lib_files lib = File.join @install_dir, 'lib' lib_rubygems = File.join lib, 'rubygems'