mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[rubygems/rubygems] Show all missing gems when using a bundle before installing it
Not only the first one that's missing. This also allows us to simplify things. https://github.com/rubygems/rubygems/commit/69718a9509
This commit is contained in:
parent
d298ef40f2
commit
9a25a98c6b
Notes:
git
2021-08-31 19:07:28 +09:00
3 changed files with 57 additions and 37 deletions
|
@ -138,7 +138,7 @@ module Bundler
|
|||
@unlock[:gems] ||= @dependencies.map(&:name)
|
||||
else
|
||||
eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
|
||||
@unlock[:gems] = @locked_specs.for(eager_unlock, false, false, false).map(&:name)
|
||||
@unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name)
|
||||
end
|
||||
|
||||
@dependency_changes = converge_dependencies
|
||||
|
@ -191,14 +191,6 @@ module Bundler
|
|||
# @return [Bundler::SpecSet]
|
||||
def specs
|
||||
@specs ||= materialize(requested_dependencies)
|
||||
rescue GemNotFound => e # Handle yanked gem
|
||||
gem_name, gem_version = extract_gem_info(e)
|
||||
locked_gem = @locked_specs[gem_name].last
|
||||
raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
|
||||
raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
|
||||
"no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
|
||||
"You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
|
||||
"removed in order to install."
|
||||
end
|
||||
|
||||
def new_specs
|
||||
|
@ -210,9 +202,7 @@ module Bundler
|
|||
end
|
||||
|
||||
def missing_specs
|
||||
missing = []
|
||||
resolve.materialize(requested_dependencies, missing)
|
||||
missing
|
||||
resolve.materialize(requested_dependencies).missing_specs
|
||||
end
|
||||
|
||||
def missing_specs?
|
||||
|
@ -498,6 +488,20 @@ module Bundler
|
|||
|
||||
def materialize(dependencies)
|
||||
specs = resolve.materialize(dependencies)
|
||||
missing_specs = specs.missing_specs
|
||||
|
||||
if missing_specs.any?
|
||||
missing_specs.each do |s|
|
||||
locked_gem = @locked_specs[s.name].last
|
||||
next if locked_gem.nil? || locked_gem.version != s.version || !@remote
|
||||
raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
|
||||
"no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
|
||||
"You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
|
||||
"removed in order to install."
|
||||
end
|
||||
|
||||
raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources"
|
||||
end
|
||||
|
||||
unless specs["bundler"].any?
|
||||
bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
|
||||
|
@ -735,7 +739,7 @@ module Bundler
|
|||
# if we won't need the source (according to the lockfile),
|
||||
# don't error if the path/git source isn't available
|
||||
next if @locked_specs.
|
||||
for(requested_dependencies, false, true, false).
|
||||
for(requested_dependencies, false, true).
|
||||
none? {|locked_spec| locked_spec.source == s.source }
|
||||
|
||||
raise
|
||||
|
@ -755,7 +759,7 @@ module Bundler
|
|||
|
||||
resolve = SpecSet.new(converged)
|
||||
@locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
|
||||
resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false, false).reject{|s| @unlock[:gems].include?(s.name) })
|
||||
resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
|
||||
diff = nil
|
||||
|
||||
# Now, we unlock any sources that do not have anymore gems pinned to it
|
||||
|
@ -859,12 +863,6 @@ module Bundler
|
|||
current == proposed
|
||||
end
|
||||
|
||||
def extract_gem_info(error)
|
||||
# This method will extract the error message like "Could not find foo-1.2.3 in any of the sources"
|
||||
# to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
|
||||
error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
|
||||
end
|
||||
|
||||
def compute_requires
|
||||
dependencies.reduce({}) do |requires, dep|
|
||||
next requires unless dep.should_include?
|
||||
|
|
|
@ -11,7 +11,7 @@ module Bundler
|
|||
@specs = specs
|
||||
end
|
||||
|
||||
def for(dependencies, check = false, match_current_platform = false, raise_on_missing = true)
|
||||
def for(dependencies, check = false, match_current_platform = false)
|
||||
handled = []
|
||||
deps = dependencies.dup
|
||||
specs = []
|
||||
|
@ -33,11 +33,6 @@ module Bundler
|
|||
end
|
||||
elsif check
|
||||
return false
|
||||
elsif raise_on_missing
|
||||
others = lookup[dep.name] if match_current_platform
|
||||
message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
|
||||
message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty?
|
||||
raise GemNotFound, message
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -71,8 +66,8 @@ module Bundler
|
|||
lookup.dup
|
||||
end
|
||||
|
||||
def materialize(deps, missing_specs = nil)
|
||||
materialized = self.for(deps, false, true, !missing_specs)
|
||||
def materialize(deps)
|
||||
materialized = self.for(deps, false, true)
|
||||
|
||||
materialized.group_by(&:source).each do |source, specs|
|
||||
next unless specs.any?{|s| s.is_a?(LazySpecification) }
|
||||
|
@ -84,16 +79,9 @@ module Bundler
|
|||
|
||||
materialized.map! do |s|
|
||||
next s unless s.is_a?(LazySpecification)
|
||||
spec = s.__materialize__
|
||||
unless spec
|
||||
unless missing_specs
|
||||
raise GemNotFound, "Could not find #{s.full_name} in any of the sources"
|
||||
s.__materialize__ || s
|
||||
end
|
||||
missing_specs << s
|
||||
end
|
||||
spec
|
||||
end
|
||||
SpecSet.new(missing_specs ? materialized.compact : materialized)
|
||||
SpecSet.new(materialized)
|
||||
end
|
||||
|
||||
# Materialize for all the specs in the spec set, regardless of what platform they're for
|
||||
|
@ -117,6 +105,10 @@ module Bundler
|
|||
end
|
||||
end
|
||||
|
||||
def missing_specs
|
||||
select {|s| s.is_a?(LazySpecification) }
|
||||
end
|
||||
|
||||
def merge(set)
|
||||
arr = sorted.dup
|
||||
set.each do |set_spec|
|
||||
|
|
|
@ -70,4 +70,34 @@ RSpec.context "when using gem before installing" do
|
|||
expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
|
||||
expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
|
||||
end
|
||||
|
||||
it "does not suggest the author has yanked the gem when using more than one gem, but shows all gems that couldn't be found in the source" do
|
||||
gemfile <<-G
|
||||
source "#{file_uri_for(gem_repo1)}"
|
||||
gem "rack", "0.9.1"
|
||||
gem "rack_middleware", "1.0"
|
||||
G
|
||||
|
||||
lockfile <<-L
|
||||
GEM
|
||||
remote: #{file_uri_for(gem_repo1)}
|
||||
specs:
|
||||
rack (0.9.1)
|
||||
rack_middleware (1.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
rack (= 0.9.1)
|
||||
rack_middleware (1.0)
|
||||
L
|
||||
|
||||
bundle :list, :raise_on_error => false
|
||||
|
||||
expect(err).to include("Could not find rack-0.9.1, rack_middleware-1.0 in any of the sources")
|
||||
expect(err).to_not include("Your bundle is locked to rack (0.9.1), but that version could not be found in any of the sources listed in your Gemfile.")
|
||||
expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
|
||||
expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue