Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make bundle clean --force leave default gem executables untouched #3907

Merged
merged 1 commit into from Sep 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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