Skip to content

Commit

Permalink
Do not check only unlocked gems for pruning (#7295)
Browse files Browse the repository at this point in the history
We're seeing an issue with bundler updates not correctly pruning all the
old cached dependencies that have been removed that we believe might be
caused by this check.

Co-authored-by: Jurre Stender <jurre@github.com>
  • Loading branch information
deivid-rodriguez and jurre authored Aug 11, 2023
1 parent 3193956 commit 9f53299
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions bundler/helpers/v2/lib/functions/lockfile_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ def generate_lockfile # rubocop:disable Metrics/PerceivedComplexity
end

def cache_vendored_gems(definition)
# Dependencies that have been unlocked for the update (including
# sub-dependencies)
unlocked_gems = definition.instance_variable_get(:@unlock).
fetch(:gems)
resolve = definition.resolve

# Dependencies that have been updated (including sub-dependencies)
updated_gems = resolve.reject do |spec|
lockfile_specs.include?(spec)
end.map(&:name).uniq

bundler_opts = {
cache_all: true,
cache_all_platforms: true,
Expand All @@ -76,24 +79,23 @@ def cache_vendored_gems(definition)
# Fetch and cache gems on all platforms without pruning
Bundler::Runtime.new(nil, definition).cache

# Only prune unlocked gems (the original implementation is in
# Only prune updated gems (the original implementation is in
# Bundler::Runtime)
cache_path = Bundler.app_cache
resolve = definition.resolve
prune_gem_cache(resolve, cache_path, unlocked_gems)
prune_gem_cache(resolve, cache_path, updated_gems)
prune_git_and_path_cache(resolve, cache_path)
end
end

# Copied from Bundler::Runtime: Modified to only prune gems that have
# been unlocked
def prune_gem_cache(resolve, cache_path, unlocked_gems)
# been updated
def prune_gem_cache(resolve, cache_path, updated_gems)
cached_gems = Dir["#{cache_path}/*.gem"]

outdated_gems = cached_gems.reject do |path|
spec = Bundler.rubygems.spec_from_gem path

!unlocked_gems.include?(spec.name) || resolve.any? do |s|
!updated_gems.include?(spec.name) || resolve.any? do |s|
s.name == spec.name && s.version == spec.version &&
!s.source.is_a?(Bundler::Source::Git)
end
Expand Down Expand Up @@ -138,8 +140,7 @@ def unlock_yanked_gem(dependencies_to_unlock, error)
end

def unlock_blocking_subdeps(dependencies_to_unlock, error)
all_deps = Bundler::LockfileParser.new(lockfile).
specs.map(&:name).map(&:to_s)
all_deps = lockfile_specs.map(&:name).map(&:to_s)
top_level = build_definition([]).dependencies.
map(&:name).map(&:to_s)
allowed_new_unlocks = all_deps - top_level - dependencies_to_unlock
Expand Down Expand Up @@ -215,6 +216,10 @@ def git_dependency?(dep)
sources.all? { |s| s&.fetch("type", nil) == "git" }
end

def lockfile_specs
@lockfile_specs ||= Bundler::LockfileParser.new(lockfile).specs
end

def lockfile
@lockfile ||= File.read(lockfile_name)
end
Expand Down

0 comments on commit 9f53299

Please sign in to comment.