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.
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)
|
@unlock[:gems] ||= @dependencies.map(&:name)
|
||||||
else
|
else
|
||||||
eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
|
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
|
end
|
||||||
|
|
||||||
@dependency_changes = converge_dependencies
|
@dependency_changes = converge_dependencies
|
||||||
|
@ -191,14 +191,6 @@ module Bundler
|
||||||
# @return [Bundler::SpecSet]
|
# @return [Bundler::SpecSet]
|
||||||
def specs
|
def specs
|
||||||
@specs ||= materialize(requested_dependencies)
|
@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
|
end
|
||||||
|
|
||||||
def new_specs
|
def new_specs
|
||||||
|
@ -210,9 +202,7 @@ module Bundler
|
||||||
end
|
end
|
||||||
|
|
||||||
def missing_specs
|
def missing_specs
|
||||||
missing = []
|
resolve.materialize(requested_dependencies).missing_specs
|
||||||
resolve.materialize(requested_dependencies, missing)
|
|
||||||
missing
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def missing_specs?
|
def missing_specs?
|
||||||
|
@ -498,6 +488,20 @@ module Bundler
|
||||||
|
|
||||||
def materialize(dependencies)
|
def materialize(dependencies)
|
||||||
specs = resolve.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?
|
unless specs["bundler"].any?
|
||||||
bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
|
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),
|
# if we won't need the source (according to the lockfile),
|
||||||
# don't error if the path/git source isn't available
|
# don't error if the path/git source isn't available
|
||||||
next if @locked_specs.
|
next if @locked_specs.
|
||||||
for(requested_dependencies, false, true, false).
|
for(requested_dependencies, false, true).
|
||||||
none? {|locked_spec| locked_spec.source == s.source }
|
none? {|locked_spec| locked_spec.source == s.source }
|
||||||
|
|
||||||
raise
|
raise
|
||||||
|
@ -755,7 +759,7 @@ module Bundler
|
||||||
|
|
||||||
resolve = SpecSet.new(converged)
|
resolve = SpecSet.new(converged)
|
||||||
@locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
|
@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
|
diff = nil
|
||||||
|
|
||||||
# Now, we unlock any sources that do not have anymore gems pinned to it
|
# Now, we unlock any sources that do not have anymore gems pinned to it
|
||||||
|
@ -859,12 +863,6 @@ module Bundler
|
||||||
current == proposed
|
current == proposed
|
||||||
end
|
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
|
def compute_requires
|
||||||
dependencies.reduce({}) do |requires, dep|
|
dependencies.reduce({}) do |requires, dep|
|
||||||
next requires unless dep.should_include?
|
next requires unless dep.should_include?
|
||||||
|
|
|
@ -11,7 +11,7 @@ module Bundler
|
||||||
@specs = specs
|
@specs = specs
|
||||||
end
|
end
|
||||||
|
|
||||||
def for(dependencies, check = false, match_current_platform = false, raise_on_missing = true)
|
def for(dependencies, check = false, match_current_platform = false)
|
||||||
handled = []
|
handled = []
|
||||||
deps = dependencies.dup
|
deps = dependencies.dup
|
||||||
specs = []
|
specs = []
|
||||||
|
@ -33,11 +33,6 @@ module Bundler
|
||||||
end
|
end
|
||||||
elsif check
|
elsif check
|
||||||
return false
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -71,8 +66,8 @@ module Bundler
|
||||||
lookup.dup
|
lookup.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
def materialize(deps, missing_specs = nil)
|
def materialize(deps)
|
||||||
materialized = self.for(deps, false, true, !missing_specs)
|
materialized = self.for(deps, false, true)
|
||||||
|
|
||||||
materialized.group_by(&:source).each do |source, specs|
|
materialized.group_by(&:source).each do |source, specs|
|
||||||
next unless specs.any?{|s| s.is_a?(LazySpecification) }
|
next unless specs.any?{|s| s.is_a?(LazySpecification) }
|
||||||
|
@ -84,16 +79,9 @@ module Bundler
|
||||||
|
|
||||||
materialized.map! do |s|
|
materialized.map! do |s|
|
||||||
next s unless s.is_a?(LazySpecification)
|
next s unless s.is_a?(LazySpecification)
|
||||||
spec = s.__materialize__
|
s.__materialize__ || s
|
||||||
unless spec
|
|
||||||
unless missing_specs
|
|
||||||
raise GemNotFound, "Could not find #{s.full_name} in any of the sources"
|
|
||||||
end
|
end
|
||||||
missing_specs << s
|
SpecSet.new(materialized)
|
||||||
end
|
|
||||||
spec
|
|
||||||
end
|
|
||||||
SpecSet.new(missing_specs ? materialized.compact : materialized)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Materialize for all the specs in the spec set, regardless of what platform they're for
|
# Materialize for all the specs in the spec set, regardless of what platform they're for
|
||||||
|
@ -117,6 +105,10 @@ module Bundler
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def missing_specs
|
||||||
|
select {|s| s.is_a?(LazySpecification) }
|
||||||
|
end
|
||||||
|
|
||||||
def merge(set)
|
def merge(set)
|
||||||
arr = sorted.dup
|
arr = sorted.dup
|
||||||
set.each do |set_spec|
|
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("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.")
|
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
|
||||||
|
|
||||||
|
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
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue