Skip to content

Commit

Permalink
Merge pull request #3907 from rubygems/dont_clean_default_gems
Browse files Browse the repository at this point in the history
Make `bundle clean --force` leave default gem executables untouched

(cherry picked from commit b2a2435)
  • Loading branch information
deivid-rodriguez committed Oct 5, 2020
1 parent 55ceffd commit 6d40391
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 12 deletions.
17 changes: 12 additions & 5 deletions bundler/lib/bundler/rubygems_integration.rb
Expand Up @@ -411,6 +411,17 @@ def replace_bin_path(specs_by_name)
# Replace or hook into RubyGems to provide a bundlerized view
# of the world.
def replace_entrypoints(specs)
specs_by_name = add_default_gems_to(specs)

replace_gem(specs, specs_by_name)
stub_rubygems(specs)
replace_bin_path(specs_by_name)

Gem.clear_paths
end

# Add default gems not already present in specs, and return them as a hash.
def add_default_gems_to(specs)
specs_by_name = specs.reduce({}) do |h, s|
h[s.name] = s
h
Expand All @@ -425,11 +436,7 @@ def replace_entrypoints(specs)
specs_by_name[default_spec_name] = default_spec
end

replace_gem(specs, specs_by_name)
stub_rubygems(specs)
replace_bin_path(specs_by_name)

Gem.clear_paths
specs_by_name
end

def undo_replacements
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/runtime.rb
Expand Up @@ -155,7 +155,7 @@ def clean(dry_run = false)
spec_cache_paths = []
spec_gemspec_paths = []
spec_extension_paths = []
specs.each do |spec|
Bundler.rubygems.add_default_gems_to(specs).values.each do |spec|
spec_gem_paths << spec.full_gem_path
# need to check here in case gems are nested like for the rails git repo
md = %r{(.+bundler/gems/.+-[a-f0-9]{7,12})}.match(spec.full_gem_path)
Expand Down
22 changes: 22 additions & 0 deletions bundler/spec/commands/clean_spec.rb
Expand Up @@ -625,6 +625,28 @@ def should_not_have_gems(*gems)
expect(out).to eq("1.0")
end

it "when using --force, it doesn't remove default gem binaries", :rubygems => ">= 3.2.0.rc.1" do
skip "does not work on Windows because it changes the path to look for default gems, and Windows uses the default fiddle gem" if Gem.win_platform?

default_irb_version = ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false
skip "irb isn't a default gem" if default_irb_version.empty?

build_repo2 do
# simulate executable for default gem
build_gem "irb", default_irb_version, :to_system => true, :default => true do |s|
s.executables = "irb"
end
end

install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
G

bundle "clean --force", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }

expect(out).not_to include("Removing irb")
end

it "doesn't blow up on path gems without a .gemspec" do
relative_path = "vendor/private_gems/bar-1.0"
absolute_path = bundled_app(relative_path)
Expand Down
2 changes: 1 addition & 1 deletion bundler/spec/support/builders.rb
Expand Up @@ -758,7 +758,7 @@ def _build(opts)

gem_path = File.expand_path("#{@spec.full_name}.gem", lib_path)
if opts[:to_system]
@context.system_gems gem_path
@context.system_gems gem_path, :default => opts[:default]
elsif opts[:to_bundle]
@context.system_gems gem_path, :path => @context.default_bundle_path
else
Expand Down
2 changes: 2 additions & 0 deletions bundler/spec/support/hax.rb
Expand Up @@ -9,6 +9,8 @@ def self.ruby=(ruby)
Gem.ruby = ENV["RUBY"]
end

@default_dir = ENV["BUNDLER_GEM_DEFAULT_DIR"] if ENV["BUNDLER_GEM_DEFAULT_DIR"]

if ENV["BUNDLER_SPEC_PLATFORM"]
class Platform
@local = new(ENV["BUNDLER_SPEC_PLATFORM"])
Expand Down
14 changes: 9 additions & 5 deletions bundler/spec/support/helpers.rb
Expand Up @@ -290,26 +290,30 @@ def system_gems(*gems)
gems = gems.flatten
options = gems.last.is_a?(Hash) ? gems.pop : {}
path = options.fetch(:path, system_gem_path)
default = options.fetch(:default, false)
with_gem_path_as(path) do
gem_repo = options.fetch(:gem_repo, gem_repo1)
gems.each do |g|
gem_name = g.to_s
if gem_name.start_with?("bundler")
version = gem_name.match(/\Abundler-(?<version>.*)\z/)[:version] if gem_name != "bundler"
with_built_bundler(version) {|gem_path| install_gem(gem_path) }
with_built_bundler(version) {|gem_path| install_gem(gem_path, default) }
elsif gem_name =~ %r{\A(?:[a-zA-Z]:)?/.*\.gem\z}
install_gem(gem_name)
install_gem(gem_name, default)
else
install_gem("#{gem_repo}/gems/#{gem_name}.gem")
install_gem("#{gem_repo}/gems/#{gem_name}.gem", default)
end
end
end
end

def install_gem(path)
def install_gem(path, default = false)
raise "OMG `#{path}` does not exist!" unless File.exist?(path)

gem_command "install --no-document --ignore-dependencies '#{path}'"
args = "--no-document --ignore-dependencies"
args += " --default --install-dir #{system_gem_path}" if default

gem_command "install #{args} '#{path}'"
end

def with_built_bundler(version = nil)
Expand Down

0 comments on commit 6d40391

Please sign in to comment.